11#define RETROHTR_TREE_FLAG_GUI_ACTIVE 1
13#define RETROHTR_NODE_FLAG_DIRTY 2
15#ifndef RETROHTR_RENDER_NODES_INIT_SZ
16# define RETROHTR_RENDER_NODES_INIT_SZ 10
19#ifndef RETROHTR_TRACE_LVL
20# define RETROHTR_TRACE_LVL 0
23#define RETROHTR_EDGE_UNKNOWN 0
24#define RETROHTR_EDGE_LEFT 1
25#define RETROHTR_EDGE_TOP 2
26#define RETROHTR_EDGE_INSIDE 4
44#ifdef RETROGXC_PRESENT
73#define retrohtr_node( tree, idx ) \
74 (0 <= (ssize_t)idx ? &((tree)->nodes[idx]) : NULL)
76#define retrohtr_node_parent( tree, idx ) \
77 (0 <= idx && 0 <= (tree)->nodes[idx].parent ? \
78 &((tree)->nodes[(tree)->nodes[idx].parent]) : NULL)
80#define retrohtr_tree_lock( tree ) \
81 if( NULL == (tree)->nodes ) { \
82 maug_mlock( (tree)->nodes_h, (tree)->nodes ); \
83 maug_cleanup_if_null_alloc( struct RETROHTR_RENDER_NODE*, (tree)->nodes ); \
86#define retrohtr_tree_unlock( tree ) \
87 if( NULL != (tree)->nodes ) { \
88 maug_munlock( (tree)->nodes_h, (tree)->nodes ); \
91#define retrohtr_tree_is_locked( tree ) (NULL != (tree)->nodes)
95#define retrohtr_node_screen_x( tree, node_idx ) \
96 ((tree)->nodes[node_idx].x)
98#define retrohtr_node_screen_y( tree, node_idx ) \
99 ((tree)->nodes[node_idx].y)
103 size_t x,
size_t y,
size_t w,
size_t h,
104 ssize_t tag_idx, ssize_t node_idx,
size_t d );
119 struct MCSS_STYLE* parent_style,
struct MCSS_STYLE* effect_style,
124 struct MCSS_STYLE* prev_sibling_style,
125 struct MCSS_STYLE* parent_style, ssize_t node_idx,
size_t d );
129 struct MCSS_STYLE* prev_sibling_style,
130 struct MCSS_STYLE* parent_style, ssize_t node_idx,
size_t d );
134 ssize_t node_idx,
size_t d );
138 RETROFLAT_IN_KEY* input,
143 ssize_t iter,
size_t d );
152 uint8_t auto_unlocked = 0;
154 MAUG_MHANDLE new_nodes_h = (MAUG_MHANDLE)NULL;
156 if( NULL != tree->
nodes ) {
157 debug_printf( RETROHTR_TRACE_LVL,
"auto-unlocking nodes..." );
158 maug_munlock( tree->nodes_h, tree->
nodes );
163 assert( NULL == tree->
nodes );
164 assert( (MAUG_MHANDLE)NULL != tree->nodes_h );
170 if( (MAUG_MHANDLE)NULL == new_nodes_h ) {
172 "unable to reallocate " SIZE_T_FMT
" nodes!",
176 tree->nodes_h = new_nodes_h;
181 assert( NULL == tree->
nodes );
182 maug_mlock( tree->nodes_h, tree->
nodes );
183 if( NULL == tree->
nodes ) {
184 error_printf(
"unable to lock nodes!" );
189 debug_printf( RETROHTR_TRACE_LVL,
190 "zeroing node " SIZE_T_FMT
" (of " SIZE_T_FMT
")...",
198 maug_munlock( tree->nodes_h, tree->
nodes );
202 if( auto_unlocked ) {
203 debug_printf( RETROHTR_TRACE_LVL,
"auto-locking nodes..." );
204 maug_mlock( tree->nodes_h, tree->
nodes );
210ssize_t retrohtr_add_node_child(
213 ssize_t node_new_idx = -1,
214 node_sibling_idx = -1;
216 node_new_idx = retrohtr_get_next_free_node( tree );
217 if( 0 > node_new_idx ) {
221#ifdef RETROGXC_PRESENT
222 retrohtr_node( tree, node_new_idx )->font_idx = -1;
224 retrohtr_node( tree, node_new_idx )->parent = node_parent_idx;
225 retrohtr_node( tree, node_new_idx )->first_child = -1;
226 retrohtr_node( tree, node_new_idx )->next_sibling = -1;
228 if( 0 > node_parent_idx ) {
230 1,
"adding root node under " SSIZE_T_FMT
"...", node_parent_idx );
234 1,
"adding node " SSIZE_T_FMT
" under " SSIZE_T_FMT,
235 node_new_idx, node_parent_idx );
239 if( 0 > retrohtr_node( tree, node_parent_idx )->first_child ) {
240 debug_printf( RETROHTR_TRACE_LVL,
"adding first child..." );
241 assert( -1 == retrohtr_node( tree, node_parent_idx )->first_child );
242 retrohtr_node( tree, node_parent_idx )->first_child = node_new_idx;
244 assert( NULL != retrohtr_node( tree, node_parent_idx ) );
245 node_sibling_idx = retrohtr_node( tree, node_parent_idx )->first_child;
246 assert( NULL != retrohtr_node( tree, node_sibling_idx ) );
247 while( 0 <= retrohtr_node( tree, node_sibling_idx )->next_sibling ) {
249 retrohtr_node( tree, node_sibling_idx )->next_sibling;
251 retrohtr_node( tree, node_sibling_idx )->next_sibling = node_new_idx;
261 size_t x,
size_t y,
size_t w,
size_t h,
262 ssize_t tag_idx, ssize_t node_idx,
size_t d
264 ssize_t node_new_idx = -1;
265 ssize_t tag_iter_idx = -1;
268 ssize_t tag_next_idx = 0;
270 debug_printf( RETROHTR_TRACE_LVL,
271 "creating render node for tag: " SSIZE_T_FMT, tag_idx );
273 mdata_vector_lock( &(parser->tags) );
278 p_tag_iter = mdata_vector_get( &(parser->tags), tag_idx,
union MHTML_TAG );
279 if( NULL == p_tag_iter ) {
285 assert( MHTML_TAG_TYPE_BODY == p_tag_iter->base.type );
287 node_new_idx = retrohtr_add_node_child( tree, node_idx );
288 if( 0 > node_new_idx ) {
291 debug_printf( RETROHTR_TRACE_LVL,
292 "created initial root node: " SIZE_T_FMT, node_new_idx );
294 node_idx = node_new_idx;
297 retrohtr_node( tree, node_idx )->tag = tag_idx;
299 retrohtr_node( tree, node_idx )->x = x;
300 retrohtr_node( tree, node_idx )->y = y;
301 retrohtr_node( tree, node_idx )->w = w;
302 retrohtr_node( tree, node_idx )->h = h;
305 tag_iter_idx = p_tag_iter->base.first_child;
306 while( 0 <= tag_iter_idx ) {
307 node_new_idx = retrohtr_add_node_child( tree, node_idx );
308 p_tag_iter = mdata_vector_get(
309 &(parser->tags), tag_iter_idx,
union MHTML_TAG );
310 assert( NULL != p_tag_iter );
311 if( 0 > node_new_idx ) {
315 retrohtr_node( tree, node_new_idx )->tag = tag_iter_idx;
317 debug_printf( RETROHTR_TRACE_LVL,
318 "rendering node " SSIZE_T_FMT
" (%s) under node " SSIZE_T_FMT,
320 gc_mhtml_tag_names[p_tag_iter->base.type],
324 if( MHTML_TAG_TYPE_IMG == p_tag_iter->base.type ) {
328 &(retrohtr_node( tree, node_new_idx )->bitmap),
330 if( MERROR_OK == retval ) {
331 debug_printf( RETROHTR_TRACE_LVL,
"loaded img: %s",
332 p_tag_iter->IMG.src );
334 error_printf(
"could not load img: %s", p_tag_iter->IMG.src );
338 tag_next_idx = p_tag_iter->base.next_sibling;
340 mdata_vector_unlock( &(parser->tags) );
342 retval = retrohtr_tree_create( parser, tree, x, y, w, h,
343 tag_iter_idx, node_new_idx, d + 1 );
344 maug_cleanup_if_not_ok();
346 mdata_vector_lock( &(parser->tags) );
348 tag_iter_idx = tag_next_idx;
353 if( mdata_vector_is_locked( &(parser->tags) ) ) {
354 mdata_vector_unlock( &(parser->tags) );
362 struct MCSS_STYLE* parent_style,
struct MCSS_STYLE* effect_style,
366 ssize_t tag_style_idx = -1;
369 struct MCSS_STYLE* style = NULL;
372 debug_printf( RETROHTR_TRACE_LVL,
373 "applying styles for tag: " SSIZE_T_FMT, tag_idx );
375 assert( !mdata_vector_is_locked( &(parser->tags) ) );
376 mdata_vector_lock( &(parser->styler.styles) );
377 mdata_vector_lock( &(parser->tags) );
379 maug_mzero( effect_style,
sizeof(
struct MCSS_STYLE ) );
384 p_tag_iter = mdata_vector_get( &(parser->tags), tag_idx,
union MHTML_TAG );
385 if( NULL == p_tag_iter ) {
389 tag_type = p_tag_iter->base.type;
392 if( 0 < p_tag_iter->base.classes_sz ) {
393 for( i = 0 ; mdata_vector_ct( &(parser->styler.styles) ) > i ; i++ ) {
394 style = mdata_vector_get(
395 &(parser->styler.styles), i,
struct MCSS_STYLE );
400 p_tag_iter->base.classes,
402 p_tag_iter->base.classes_sz
405 debug_printf( RETROHTR_TRACE_LVL,
"found style for tag class: %s",
408 mcssmerge_styles( effect_style, parent_style, style, tag_type );
414 if( 0 < p_tag_iter->base.id_sz ) {
415 for( i = 0 ; mdata_vector_ct( &(parser->styler.styles) ) > i ; i++ ) {
416 style = mdata_vector_get(
417 &(parser->styler.styles), i,
struct MCSS_STYLE );
424 p_tag_iter->base.id_sz
427 debug_printf( RETROHTR_TRACE_LVL,
"found style for tag ID: %s",
430 mcssmerge_styles( effect_style, parent_style, style, tag_type );
436 tag_style_idx = p_tag_iter->base.style;
443 style = mdata_vector_get(
444 &(parser->styler.styles), tag_style_idx,
struct MCSS_STYLE );
447 mcssmerge_styles( effect_style, parent_style, style, tag_type );
449 mdata_vector_unlock( &(parser->tags) );
450 mdata_vector_unlock( &(parser->styler.styles) );
456 struct MCSS_PARSER* styler,
457#ifdef RETROGXC_PRESENT
460 MAUG_MHANDLE* font_h_p,
462 struct MCSS_STYLE* effect_style
465 char* strpool = NULL;
467#ifdef RETROGXC_PRESENT
468 if( 0 <= *font_idx_p ) {
469 error_printf(
"tried to load font but font already loaded, idx: "
470 SSIZE_T_FMT, *font_idx_p );
472 if( (MAUG_MHANDLE)NULL != *font_h_p ) {
473 error_printf(
"tried to load font but font already loaded, p: %p",
479 mdata_strpool_lock( &(styler->strpool), strpool );
481 debug_printf( RETROHTR_TRACE_LVL,
482 "loading font: %s (" SSIZE_T_FMT
")",
483 &(strpool[effect_style->FONT_FAMILY]), effect_style->FONT_FAMILY );
485 if( 0 >= effect_style->FONT_FAMILY ) {
486 error_printf(
"style has no font associated!" );
493#ifdef RETROGXC_PRESENT
495 retrogxc_load_font( &(strpool[effect_style->FONT_FAMILY]), 0, 33, 93 );
497 retval = retrofont_load(
498 &(strpool[effect_style->FONT_FAMILY]), font_h_p, 0, 33, 93 );
503 mdata_strpool_unlock( &(styler->strpool), strpool );
510 struct MCSS_STYLE* effect_style
516 RETROHTR_TREE_FLAG_GUI_ACTIVE ==
517 (RETROHTR_TREE_FLAG_GUI_ACTIVE & tree->flags)
519 debug_printf( RETROHTR_TRACE_LVL,
"tree GUI already active!" );
526 retval = retrogui_init( &(tree->gui) );
527 maug_cleanup_if_not_ok();
529 retval = retrohtr_load_font(
531#ifdef RETROGXC_PRESENT
532 &(tree->gui.font_idx),
537 maug_cleanup_if_not_ok();
539 tree->flags |= RETROHTR_TREE_FLAG_GUI_ACTIVE;
541 debug_printf( RETROHTR_TRACE_LVL,
"tree GUI initialized!" );
549 struct MCSS_STYLE* prev_sibling_style,
550 struct MCSS_STYLE* parent_style, ssize_t node_idx,
size_t d
552 struct MCSS_STYLE effect_style;
553 struct MCSS_STYLE child_prev_sibling_style;
554 struct MCSS_STYLE child_style;
555 char* strpool = NULL;
556 ssize_t child_iter_idx = -1;
557 ssize_t tag_idx = -1;
558 ssize_t node_iter_idx = -1;
559 size_t this_line_w = 0;
560 size_t this_line_h = 0;
566 if( NULL == retrohtr_node( tree, node_idx ) ) {
570 tag_idx = retrohtr_node( tree, node_idx )->tag;
573 parser, tree, parent_style, &effect_style, tag_idx );
574 maug_cleanup_if_not_ok();
576 assert( !mdata_vector_is_locked( &(parser->tags) ) );
577 mdata_vector_lock( &(parser->tags) );
579 p_tag_iter = mdata_vector_get( &(parser->tags), tag_idx,
union MHTML_TAG );
580 assert( NULL != p_tag_iter );
584 if( mcss_prop_is_active( effect_style.POSITION ) ) {
585 debug_printf( RETROHTR_TRACE_LVL,
586 "node " SSIZE_T_FMT
": applying %s positioning",
587 node_idx, gc_mcss_position_names[effect_style.POSITION] );
595 retrohtr_node( tree, node_idx )->pos = effect_style.POSITION;
596 retrohtr_node( tree, node_idx )->pos_flags = effect_style.POSITION_flags;
604 if( mcss_prop_is_active_NOT_flag( effect_style.WIDTH, AUTO ) ) {
605 retrohtr_node( tree, node_idx )->w = effect_style.WIDTH;
608 if( mcss_prop_is_active_NOT_flag( effect_style.HEIGHT, AUTO ) ) {
609 retrohtr_node( tree, node_idx )->h = effect_style.HEIGHT;
615 retval = retrohtr_load_font(
617#ifdef RETROGXC_PRESENT
618 &(retrohtr_node( tree, node_idx )->font_idx),
620 &(retrohtr_node( tree, node_idx )->font_h),
623 maug_cleanup_if_not_ok();
625 if( 0 <= tag_idx && MHTML_TAG_TYPE_TEXT == p_tag_iter->base.type ) {
628 mdata_strpool_lock( &(parser->strpool), strpool );
630#ifdef RETROGXC_PRESENT
635 NULL, &(strpool[p_tag_iter->TEXT.content_idx]),
636 p_tag_iter->TEXT.content_sz,
637#ifdef RETROGXC_PRESENT
638 retrohtr_node( tree, node_idx )->font_idx,
640 retrohtr_node( tree, node_idx )->font_h,
643 retrohtr_node_parent( tree, node_idx )->w,
644 retrohtr_node_parent( tree, node_idx )->h,
645 &(retrohtr_node( tree, node_idx )->w),
646 &(retrohtr_node( tree, node_idx )->h), 0 );
648 debug_printf( RETROHTR_TRACE_LVL,
"TEXT w: " SIZE_T_FMT,
649 retrohtr_node( tree, node_idx )->w );
651 mdata_strpool_unlock( &(parser->strpool), strpool );
655 MHTML_TAG_TYPE_INPUT == p_tag_iter->base.type
659 retval = retrohtr_tree_gui( tree, &(parser->styler), &effect_style );
661 retrogui_lock( &(tree->gui) );
665 MERROR_OK != retrogui_init_ctl(
666 &ctl, RETROGUI_CTL_TYPE_BUTTON, node_idx )
668 error_printf(
"could not initialize control!" );
669 retrogui_unlock( &(tree->gui) );
673 p_tag_node = mdata_vector_get(
675 retrohtr_node( tree, node_idx )->tag,
union MHTML_TAG );
677 ctl.base.x = retrohtr_node( tree, node_idx )->x;
678 ctl.base.y = retrohtr_node( tree, node_idx )->y;
681 ctl.BUTTON.label = p_tag_node->INPUT.value;
684 retrohtr_node( tree, node_idx )->w = ctl.base.w;
685 retrohtr_node( tree, node_idx )->h = ctl.base.h;
687 debug_printf( RETROHTR_TRACE_LVL,
"initialized control for INPUT..." );
689 retrogui_push_ctl( &(tree->gui), &ctl );
691 retrogui_unlock( &(tree->gui) );
693 }
else if( 0 <= tag_idx && MHTML_TAG_TYPE_IMG == p_tag_iter->base.type ) {
696 retrohtr_node( tree, node_idx )->w =
697 retroflat_bitmap_w( &(retrohtr_node( tree, node_idx )->bitmap) );
698 retrohtr_node( tree, node_idx )->h =
699 retroflat_bitmap_h( &(retrohtr_node( tree, node_idx )->bitmap) );
702 debug_printf( RETROHTR_TRACE_LVL,
"TEXT w: " SIZE_T_FMT,
703 retrohtr_node( tree, node_idx )->w );
708 maug_mzero( &child_prev_sibling_style,
sizeof(
struct MCSS_STYLE ) );
709 node_iter_idx = retrohtr_node( tree, node_idx )->first_child;
710 mdata_vector_unlock( &(parser->tags) );
711 while( 0 <= node_iter_idx ) {
713 parser, tree, &child_prev_sibling_style, &effect_style,
714 node_iter_idx, d + 1 );
716 node_iter_idx = retrohtr_node( tree, node_iter_idx )->next_sibling;
720 if( mdata_vector_is_locked( &(parser->tags) ) ) {
721 mdata_vector_unlock( &(parser->tags) );
725 if( 0 == retrohtr_node( tree, node_idx )->w ) {
727 MCSS_DISPLAY_BLOCK == effect_style.DISPLAY &&
728 0 <= retrohtr_node( tree, node_idx )->parent
732 retrohtr_node( tree, node_idx )->w =
733 retrohtr_node_parent( tree, node_idx )->w;
737 child_iter_idx = retrohtr_node( tree, node_idx )->first_child;
738 while( 0 <= child_iter_idx ) {
739 assert( !mdata_vector_is_locked( &(parser->tags) ) );
741 parser, tree, &effect_style, &child_style,
742 retrohtr_node( tree, child_iter_idx )->tag );
743 maug_cleanup_if_not_ok();
746 if( MCSS_POSITION_ABSOLUTE == child_style.POSITION ) {
748 retrohtr_node( tree, child_iter_idx )->next_sibling;
752 if( MCSS_DISPLAY_BLOCK == child_style.DISPLAY ) {
757 retrohtr_node( tree, child_iter_idx )->w >
758 retrohtr_node( tree, node_idx )->w
761 retrohtr_node( tree, node_idx )->w =
762 retrohtr_node( tree, child_iter_idx )->w;
766 this_line_w += retrohtr_node( tree, child_iter_idx )->w;
768 if( this_line_w > retrohtr_node( tree, node_idx )->w ) {
770 retrohtr_node( tree, node_idx )->w = this_line_w;
773 child_iter_idx = retrohtr_node( tree, child_iter_idx )->next_sibling;
778 if( 0 == retrohtr_node( tree, node_idx )->h ) {
780 child_iter_idx = retrohtr_node( tree, node_idx )->first_child;
781 while( 0 <= child_iter_idx ) {
782 assert( !mdata_vector_is_locked( &(parser->tags) ) );
784 parser, tree, &effect_style, &child_style,
785 retrohtr_node( tree, child_iter_idx )->tag );
788 if( MCSS_POSITION_ABSOLUTE == child_style.POSITION ) {
789 child_iter_idx = retrohtr_node( tree, child_iter_idx )->next_sibling;
793 if( MCSS_DISPLAY_BLOCK == child_style.DISPLAY ) {
795 retrohtr_node( tree, node_idx )->h += this_line_h;
798 this_line_h = retrohtr_node( tree, child_iter_idx )->h;
801 if( this_line_h < retrohtr_node( tree, child_iter_idx )->h ) {
802 this_line_h = retrohtr_node( tree, child_iter_idx )->h;
806 child_iter_idx = retrohtr_node( tree, child_iter_idx )->next_sibling;
810 retrohtr_node( tree, node_idx )->h += this_line_h;
819 if( mcss_prop_is_active_NOT_flag( effect_style.PADDING_LEFT, AUTO ) ) {
820 retrohtr_node( tree, node_idx )->w += effect_style.PADDING_LEFT;
821 }
else if( mcss_prop_is_active_NOT_flag( effect_style.PADDING, AUTO ) ) {
822 retrohtr_node( tree, node_idx )->w += effect_style.PADDING;
826 if( mcss_prop_is_active_NOT_flag( effect_style.PADDING_RIGHT, AUTO ) ) {
827 retrohtr_node( tree, node_idx )->w += effect_style.PADDING_RIGHT;
828 }
else if( mcss_prop_is_active_NOT_flag( effect_style.PADDING, AUTO ) ) {
829 retrohtr_node( tree, node_idx )->w += effect_style.PADDING;
833 if( mcss_prop_is_active_NOT_flag( effect_style.PADDING_TOP, AUTO ) ) {
834 retrohtr_node( tree, node_idx )->h += effect_style.PADDING_TOP;
835 }
else if( mcss_prop_is_active_NOT_flag( effect_style.PADDING, AUTO ) ) {
836 retrohtr_node( tree, node_idx )->h += effect_style.PADDING;
840 if( mcss_prop_is_active_NOT_flag( effect_style.PADDING_BOTTOM, AUTO ) ) {
841 retrohtr_node( tree, node_idx )->h += effect_style.PADDING_BOTTOM;
842 }
else if( mcss_prop_is_active_NOT_flag( effect_style.PADDING, AUTO ) ) {
843 retrohtr_node( tree, node_idx )->h += effect_style.PADDING;
846 debug_printf( RETROHTR_TRACE_LVL,
847 "setting node " SIZE_T_FMT
" dirty...", node_idx );
848 retrohtr_node( tree, node_idx )->flags |= RETROHTR_NODE_FLAG_DIRTY;
852 if( mdata_vector_is_locked( &(parser->tags) ) ) {
853 mdata_vector_unlock( &(parser->tags) );
859 if( NULL != prev_sibling_style ) {
861 prev_sibling_style, &effect_style,
862 sizeof(
struct MCSS_STYLE ) );
870#define retrohtr_break_on_active_pos( iter_idx ) \
871 if( mcss_prop_is_active( retrohtr_node( tree, iter_idx )->pos ) ) { \
875static ssize_t retrohtr_find_prev_sibling_in_box_model(
879 ssize_t sibling_iter_idx = -1;
880 ssize_t sibling_found_idx = -1;
882 if( 0 > retrohtr_node( tree, node_idx )->parent ) {
887 sibling_iter_idx = retrohtr_node_parent( tree, node_idx )->first_child;
889 if( sibling_iter_idx == node_idx ) {
894 while( 0 <= sibling_iter_idx && node_idx != sibling_iter_idx ) {
897 MCSS_POSITION_ABSOLUTE != retrohtr_node( tree, sibling_iter_idx )->pos
899 sibling_found_idx = sibling_iter_idx;
904 sibling_iter_idx = retrohtr_node( tree, sibling_iter_idx )->next_sibling;
908 return sibling_found_idx;
913 ssize_t node_parent_idx
915 ssize_t node_sibling_idx = -1;
917 struct MCSS_STYLE effect_style;
922 node_sibling_idx = retrohtr_node( tree, node_parent_idx )->first_child;
923 while( 0 <= node_sibling_idx ) {
924 maug_mzero( &effect_style,
sizeof(
struct MCSS_STYLE ) );
926 parser, tree, NULL, &effect_style,
927 retrohtr_node( tree, node_sibling_idx )->tag );
929 if( MCSS_POSITION_ABSOLUTE == effect_style.POSITION ) {
931 retrohtr_node( tree, node_sibling_idx )->edge |= RETROHTR_EDGE_INSIDE;
933 }
else if( MCSS_DISPLAY_INLINE == effect_style.DISPLAY ) {
936 retrohtr_node( tree, node_sibling_idx )->edge |= RETROHTR_EDGE_LEFT;
939 retrohtr_node( tree, node_sibling_idx )->edge |= RETROHTR_EDGE_TOP;
941 if( 0 < row_idx && 0 < col_idx ) {
942 retrohtr_node( tree, node_sibling_idx )->edge |= RETROHTR_EDGE_INSIDE;
955 retrohtr_node( tree, node_sibling_idx )->edge |= RETROHTR_EDGE_TOP;
959 retrohtr_node( tree, node_sibling_idx )->edge |= RETROHTR_EDGE_LEFT;
962 assert( !mdata_vector_is_locked( &(parser->tags) ) );
963 mdata_vector_lock( &(parser->tags) );
965 p_tag_iter = mdata_vector_get( &(parser->tags),
966 retrohtr_node( tree, node_sibling_idx )->tag,
968 assert( NULL != p_tag_iter );
970 debug_printf( 1,
"marking node " SIZE_T_FMT
" (%s) edge: %u",
972 gc_mhtml_tag_names[p_tag_iter->base.type],
973 retrohtr_node( tree, node_sibling_idx )->edge );
975 mdata_vector_unlock( &(parser->tags) );
978 retrohtr_node( tree, node_sibling_idx )->next_sibling;
983 if( mdata_vector_is_locked( &(parser->tags) ) ) {
984 mdata_vector_unlock( &(parser->tags) );
992 struct MCSS_STYLE* prev_sibling_style,
993 struct MCSS_STYLE* parent_style, ssize_t node_idx,
size_t d
995 struct MCSS_STYLE child_prev_sibling_style;
996 struct MCSS_STYLE effect_style;
997 ssize_t child_iter_idx = -1;
998 ssize_t tag_idx = -1;
999 ssize_t node_iter_idx = -1;
1000 ssize_t prev_sibling_idx = -1;
1004 if( NULL == retrohtr_node( tree, node_idx ) ) {
1008 tag_idx = retrohtr_node( tree, node_idx )->tag;
1011 parser, tree, parent_style, &effect_style, tag_idx );
1014 retrohtr_find_prev_sibling_in_box_model( tree, node_idx );
1018 if( MCSS_POSITION_ABSOLUTE == effect_style.POSITION ) {
1021 if( mcss_prop_is_active_NOT_flag( effect_style.LEFT, AUTO ) ) {
1023 child_iter_idx = retrohtr_node( tree, node_idx )->parent;
1024 while( 0 <= retrohtr_node( tree, child_iter_idx )->parent ) {
1025 retrohtr_break_on_active_pos( child_iter_idx );
1026 child_iter_idx = retrohtr_node( tree, child_iter_idx )->parent;
1030 retrohtr_node( tree, node_idx )->x =
1031 retrohtr_node( tree, child_iter_idx )->x + effect_style.LEFT;
1033 if( mcss_prop_is_active_NOT_flag( effect_style.RIGHT, AUTO ) ) {
1035 child_iter_idx = retrohtr_node( tree, node_idx )->parent;
1036 while( 0 <= retrohtr_node( tree, child_iter_idx )->parent ) {
1037 retrohtr_break_on_active_pos( child_iter_idx );
1038 child_iter_idx = retrohtr_node( tree, child_iter_idx )->parent;
1042 retrohtr_node( tree, node_idx )->x =
1043 retrohtr_node( tree, child_iter_idx )->w -
1044 retrohtr_node( tree, node_idx )->w -
1049 MCSS_DISPLAY_INLINE == effect_style.DISPLAY &&
1050 MCSS_DISPLAY_INLINE == prev_sibling_style->DISPLAY &&
1051 0 <= prev_sibling_idx
1054 retrohtr_node( tree, node_idx )->x =
1055 retrohtr_node( tree, prev_sibling_idx )->x +
1056 retrohtr_node( tree, prev_sibling_idx )->w;
1058 }
else if( 0 <= retrohtr_node( tree, node_idx )->parent ) {
1059 retrohtr_node( tree, node_idx )->x = retrohtr_node_parent( tree, node_idx )->x;
1066 if( MCSS_POSITION_ABSOLUTE == effect_style.POSITION ) {
1069 if( mcss_prop_is_active_NOT_flag( effect_style.TOP, AUTO ) ) {
1071 child_iter_idx = retrohtr_node( tree, node_idx )->parent;
1072 while( 0 <= retrohtr_node( tree, child_iter_idx )->parent ) {
1073 retrohtr_break_on_active_pos( child_iter_idx );
1074 child_iter_idx = retrohtr_node( tree, child_iter_idx )->parent;
1078 retrohtr_node( tree, node_idx )->y =
1079 retrohtr_node( tree, child_iter_idx )->y + effect_style.TOP;
1081 if( mcss_prop_is_active_NOT_flag( effect_style.BOTTOM, AUTO ) ) {
1083 child_iter_idx = retrohtr_node( tree, node_idx )->parent;
1084 while( 0 <= retrohtr_node( tree, child_iter_idx )->parent ) {
1085 retrohtr_break_on_active_pos( child_iter_idx );
1086 child_iter_idx = retrohtr_node( tree, child_iter_idx )->parent;
1090 retrohtr_node( tree, node_idx )->y =
1091 retrohtr_node( tree, child_iter_idx )->h -
1092 retrohtr_node( tree, node_idx )->h -
1093 effect_style.BOTTOM;
1097 MCSS_DISPLAY_INLINE == effect_style.DISPLAY &&
1098 MCSS_DISPLAY_INLINE == prev_sibling_style->DISPLAY &&
1099 0 <= prev_sibling_idx
1102 retrohtr_node( tree, node_idx )->y = retrohtr_node( tree, prev_sibling_idx )->y;
1104 }
else if( 0 <= prev_sibling_idx ) {
1111 retrohtr_node( tree, node_idx )->y =
1112 retrohtr_node( tree, prev_sibling_idx )->y +
1113 retrohtr_node( tree, prev_sibling_idx )->h;
1115 }
else if( 0 <= retrohtr_node( tree, node_idx )->parent ) {
1118 retrohtr_node( tree, node_idx )->y = retrohtr_node_parent( tree, node_idx )->y;
1124 MCSS_POSITION_ABSOLUTE != retrohtr_node( tree, node_idx )->pos &&
1125 0 <= retrohtr_node( tree, node_idx )->parent &&
1126 mcss_prop_is_active_flag( effect_style.MARGIN_LEFT, AUTO ) &&
1127 mcss_prop_is_active_flag( effect_style.MARGIN_RIGHT, AUTO )
1130 retrohtr_node( tree, node_idx )->x =
1131 retrohtr_node_parent( tree, node_idx )->x +
1132 (retrohtr_node_parent( tree, node_idx )->w >> 1) -
1133 (retrohtr_node( tree, node_idx )->w >> 1);
1136 0 <= retrohtr_node( tree, node_idx )->parent &&
1137 mcss_prop_is_active_flag( effect_style.MARGIN_LEFT, AUTO ) &&
1138 mcss_prop_is_active_NOT_flag( effect_style.MARGIN_RIGHT, AUTO )
1142 retrohtr_node( tree, node_idx )->x =
1143 retrohtr_node_parent( tree, node_idx )->w -
1144 retrohtr_node( tree, node_idx )->w;
1146 }
else if( mcss_prop_is_active( effect_style.MARGIN_LEFT ) ) {
1148 retrohtr_node( tree, node_idx )->x += effect_style.MARGIN_LEFT;
1157 debug_printf( 1,
"(d: " SIZE_T_FMT
") node " SIZE_T_FMT
" is on edge: %u",
1158 d, node_idx, retrohtr_node( tree, node_idx )->edge );
1162 RETROHTR_EDGE_UNKNOWN != retrohtr_node( tree, node_idx )->edge );
1165 RETROHTR_EDGE_LEFT ==
1166 (RETROHTR_EDGE_LEFT & retrohtr_node( tree, node_idx )->edge)
1169 if( mcss_prop_is_active_NOT_flag( parent_style->PADDING_LEFT, AUTO ) ) {
1170 retrohtr_node( tree, node_idx )->x += parent_style->PADDING_LEFT;
1171 }
else if( mcss_prop_is_active_NOT_flag( parent_style->PADDING, AUTO ) ) {
1172 retrohtr_node( tree, node_idx )->x += parent_style->PADDING;
1177 RETROHTR_EDGE_TOP ==
1178 (RETROHTR_EDGE_TOP & retrohtr_node( tree, node_idx )->edge) &&
1180 RETROHTR_EDGE_LEFT ==
1181 (RETROHTR_EDGE_LEFT & retrohtr_node( tree, node_idx )->edge)
1184 if( mcss_prop_is_active_NOT_flag( parent_style->PADDING_TOP, AUTO ) ) {
1185 retrohtr_node( tree, node_idx )->y += parent_style->PADDING_TOP;
1186 }
else if( mcss_prop_is_active_NOT_flag( parent_style->PADDING, AUTO ) ) {
1187 retrohtr_node( tree, node_idx )->y += parent_style->PADDING;
1193 if( mcss_prop_is_active( effect_style.COLOR ) ) {
1194 retrohtr_node( tree, node_idx )->fg = effect_style.COLOR;
1197 if( mcss_prop_is_active( effect_style.BACKGROUND_COLOR ) ) {
1198 retrohtr_node( tree, node_idx )->bg = effect_style.BACKGROUND_COLOR;
1203 retrohtr_mark_edge_child_nodes( parser, tree, node_idx );
1205 maug_mzero( &child_prev_sibling_style,
sizeof(
struct MCSS_STYLE ) );
1206 node_iter_idx = retrohtr_node( tree, node_idx )->first_child;
1207 while( 0 <= node_iter_idx ) {
1212 parser, tree, &child_prev_sibling_style, &effect_style,
1213 node_iter_idx, d + 1 );
1215 node_iter_idx = retrohtr_node( tree, node_iter_idx )->next_sibling;
1218 assert( !mdata_vector_is_locked( &(parser->tags) ) );
1219 mdata_vector_lock( &(parser->tags) );
1220 p_tag_iter = mdata_vector_get( &(parser->tags), tag_idx,
union MHTML_TAG );
1221 assert( NULL != p_tag_iter );
1223 if( MHTML_TAG_TYPE_INPUT == p_tag_iter->base.type ) {
1225 retval = retrogui_pos_ctl( &(tree->gui), node_idx,
1226 retrohtr_node_screen_x( tree, node_idx ),
1227 retrohtr_node_screen_y( tree, node_idx ),
1228 retrohtr_node( tree, node_idx )->w,
1229 retrohtr_node( tree, node_idx )->h );
1230 maug_cleanup_if_not_ok();
1233 debug_printf( RETROHTR_TRACE_LVL,
1234 "setting node " SIZE_T_FMT
" dirty...", node_idx );
1235 retrohtr_node( tree, node_idx )->flags |= RETROHTR_NODE_FLAG_DIRTY;
1239 if( mdata_vector_is_locked( &(parser->tags) ) ) {
1240 mdata_vector_unlock( &(parser->tags) );
1246 if( NULL != prev_sibling_style ) {
1248 prev_sibling_style, &effect_style,
1249 sizeof(
struct MCSS_STYLE ) );
1257 ssize_t node_idx,
size_t d
1259 char* strpool = NULL;
1264 node = retrohtr_node( tree, node_idx );
1266 if( NULL == node ) {
1272 if( 0 > node->tag ) {
1276 if( RETROHTR_NODE_FLAG_DIRTY != (RETROHTR_NODE_FLAG_DIRTY & node->flags) ) {
1280 assert( !mdata_vector_is_locked( &(parser->tags) ) );
1281 mdata_vector_lock( &(parser->tags) );
1283 p_tag = mdata_vector_get( &(parser->tags), node->tag,
union MHTML_TAG );
1284 if( NULL == p_tag ) {
1289 if( MHTML_TAG_TYPE_TEXT == p_tag->base.type ) {
1292 0 > p_tag->TEXT.content_idx ||
1293#ifdef RETROGXC_PRESENT
1296 NULL == node->font_h
1302 mdata_strpool_lock( &(parser->strpool), strpool );
1304#ifdef RETROGXC_PRESENT
1310 &(strpool[p_tag->TEXT.content_idx]), p_tag->TEXT.content_sz,
1311#ifdef RETROGXC_PRESENT
1316 retrohtr_node_screen_x( tree, node_idx ),
1317 retrohtr_node_screen_y( tree, node_idx ),
1318 node->w, node->h, 0 );
1320 mdata_strpool_unlock( &(parser->strpool), strpool );
1322 }
else if( MHTML_TAG_TYPE_BODY == p_tag->base.type ) {
1325 RETROHTR_TRACE_LVL,
"drawing BODY node " SIZE_T_FMT
"...", node_idx );
1328 if( RETROFLAT_COLOR_NULL != node->bg ) {
1331 retrohtr_node_screen_x( tree, node_idx ),
1332 retrohtr_node_screen_y( tree, node_idx ),
1333 retrohtr_node( tree, node_idx )->w,
1334 retrohtr_node( tree, node_idx )->h,
1335 RETROFLAT_FLAGS_FILL );
1338 }
else if( MHTML_TAG_TYPE_IMG == p_tag->base.type ) {
1346 RETROHTR_TRACE_LVL,
"drawing IMG node " SIZE_T_FMT
"...", node_idx );
1349 NULL, &(retrohtr_node( tree, node_idx )->bitmap),
1351 retrohtr_node_screen_x( tree, node_idx ),
1352 retrohtr_node_screen_y( tree, node_idx ),
1353 retroflat_bitmap_w( &(retrohtr_node( tree, node_idx )->bitmap) ),
1354 retroflat_bitmap_h( &(retrohtr_node( tree, node_idx )->bitmap) ),
1359 }
else if( MHTML_TAG_TYPE_INPUT == p_tag->base.type ) {
1362 RETROHTR_TRACE_LVL,
"setting tree GUI dirty..." );
1367 if( RETROFLAT_COLOR_NULL == node->bg ) {
1372 RETROHTR_TRACE_LVL,
"drawing xs node " SIZE_T_FMT
"...",
1379 retrohtr_node_screen_x( tree, node_idx ),
1380 retrohtr_node_screen_y( tree, node_idx ),
1385 node->flags &= ~RETROHTR_NODE_FLAG_DIRTY;
1389 if( retrogui_is_locked( &(tree->gui) ) ) {
1390 retrogui_unlock( &(tree->gui) );
1393 if( mdata_vector_is_locked( &(parser->tags) ) ) {
1394 mdata_vector_unlock( &(parser->tags) );
1397 if( MERROR_OK != retval ) {
1398 error_printf(
"failed drawing node: " SIZE_T_FMT, node_idx );
1403 retrohtr_tree_draw( parser, tree, node->
first_child, d + 1 );
1405 retrohtr_tree_draw( parser, tree, node->
next_sibling, d );
1410 RETROHTR_TREE_FLAG_GUI_ACTIVE ==
1411 (tree->flags & RETROHTR_TREE_FLAG_GUI_ACTIVE)
1413 retrogui_lock( &(tree->gui) );
1414 retrogui_redraw_ctls( &(tree->gui) );
1415 retrogui_unlock( &(tree->gui) );
1423 RETROFLAT_IN_KEY* input,
1429 assert( retrohtr_tree_is_locked( tree ) );
1432 RETROHTR_TREE_FLAG_GUI_ACTIVE !=
1433 (RETROHTR_TREE_FLAG_GUI_ACTIVE & tree->flags)
1443 RETROHTR_TRACE_LVL,
"setting node " SIZE_T_FMT
" dirty...", idc );
1444 retrohtr_node( tree, idc )->flags |= RETROHTR_NODE_FLAG_DIRTY;
1447 if( MERROR_OK != retval ) {
1456 ssize_t node_idx,
size_t d
1463 if( 0 > node_idx ) {
1467 assert( !mdata_vector_is_locked( &(parser->tags) ) );
1468 mdata_vector_lock( &(parser->tags) );
1470 p_tag_iter = mdata_vector_get(
1472 if( NULL == p_tag_iter ) {
1478 for( i = 0 ; d > i ; i++ ) {
1479 if( maug_strlen( indents ) >= 30 ) {
1482 strcat( indents,
" " );
1488 "%s" SSIZE_T_FMT
" (tag %s): x: " SSIZE_T_FMT
", y: " SSIZE_T_FMT
1489 " (" SSIZE_T_FMT
" x " SSIZE_T_FMT
") f: "
1490#ifdef RETROGXC_PRESENT
1496 0 <= tree->
nodes[node_idx].tag ?
1497 gc_mhtml_tag_names[p_tag_iter->base.type] :
"ROOT",
1498 tree->
nodes[node_idx].x, tree->
nodes[node_idx].y,
1499 tree->
nodes[node_idx].w, tree->
nodes[node_idx].h,
1500#ifdef RETROGXC_PRESENT
1501 tree->
nodes[node_idx].font_idx
1503 tree->
nodes[node_idx].font_h
1507 mdata_vector_unlock( &(parser->tags) );
1509 retval = retrohtr_tree_dump(
1511 maug_cleanup_if_not_ok();
1513 retval = retrohtr_tree_dump(
1515 maug_cleanup_if_not_ok();
1524 debug_printf( RETROHTR_TRACE_LVL,
"freeing render nodes..." );
1532 RETROHTR_TREE_FLAG_GUI_ACTIVE ==
1533 (tree->flags & RETROHTR_TREE_FLAG_GUI_ACTIVE)
1535 retrogui_free( &(tree->gui) );
1539 retrohtr_tree_unlock( tree );
1541 if( NULL != tree->nodes_h ) {
1542 maug_mfree( tree->nodes_h );
1553 debug_printf( RETROHTR_TRACE_LVL,
1554 "allocating " SIZE_T_FMT
" nodes...", tree->
nodes_sz_max );
1555 tree->nodes_h = maug_malloc(
int MERROR_RETVAL
Return type indicating function returns a value from this list.
Definition merror.h:19
#define maug_mzero(ptr, sz)
Zero the block of memory pointed to by ptr.
Definition mmem.h:62
#define maug_mrealloc(handle, nmemb, sz)
Definition mmem.h:54
MERROR_RETVAL retroflat_blit_bitmap(struct RETROFLAT_BITMAP *target, struct RETROFLAT_BITMAP *src, size_t s_x, size_t s_y, int16_t d_x, int16_t d_y, size_t w, size_t h, int16_t instance)
Blit the contents of a RETROFLAT_BITMAP onto another RETROFLAT_BITMAP.
MERROR_RETVAL retroflat_load_bitmap(const char *filename, struct RETROFLAT_BITMAP *bmp_out, uint8_t flags)
Load a bitmap into the given RETROFLAT_BITMAP structure if it is available. Bitmaps are subject to th...
#define RETROFLAT_INSTANCE_NULL
Pass to retroflat_blit_bitmap() instance arg if this is not a sprite (i.e. if it is a background tile...
Definition retroflt.h:567
#define retroflat_bitmap_ok(bitmap)
Check to see if a bitmap is loaded.
Definition retpltd.h:30
int8_t RETROFLAT_COLOR
Defines an index in the platform-specific color-table.
Definition retroflt.h:307
#define RETROFLAT_FLAGS_LITERAL_PATH
Flag for retroflat_load_bitmap() to not use assets path.
Definition retroflt.h:374
void retroflat_rect(struct RETROFLAT_BITMAP *target, const RETROFLAT_COLOR color, int16_t x, int16_t y, int16_t w, int16_t h, uint8_t flags)
Draw a rectangle onto the target RETROFLAT_BITMAP.
#define RETROFLAT_FLAGS_FILL
Flag for retroflat_rect() or retroflat_ellipse(), indicating drawn shape should be filled.
Definition retroflt.h:355
#define RETROGUI_FLAGS_DIRTY
RETROGUI::flags indicating controls should be redrawn.
Definition retrogui.h:16
retrogui_idc_t retrogui_poll_ctls(struct RETROGUI *gui, RETROFLAT_IN_KEY *p_input, struct RETROFLAT_INPUT *input_evt)
Poll for the last clicked control and maintain listboxes and menus.
size_t retrogui_idc_t
Unique identifying constant number for controls.
Definition retrogui.h:89
size_t nodes_sz_max
Current alloc'd number of nodes in RETROHTR_RENDER_NODE::nodes_h.
Definition retrohtr.h:67
ssize_t parent
Index of container's render node in RETROHTR_RENDER_TREE.
Definition retrohtr.h:51
ssize_t first_child
Index of first child's render node in RETROHTR_RENDER_TREE.
Definition retrohtr.h:53
MERROR_RETVAL retrohtr_apply_styles(struct MHTML_PARSER *parser, struct RETROHTR_RENDER_TREE *tree, struct MCSS_STYLE *parent_style, struct MCSS_STYLE *effect_style, ssize_t tag_idx)
Create a style node that is a composite of a parent style and the styles applicable to the classes/ID...
ssize_t next_sibling
Index of next sibling's render node in RETROHTR_RENDER_TREE.
Definition retrohtr.h:55
size_t nodes_sz
Current active number of nodes in RETROHTR_RENDER_NODE::nodes_h.
Definition retrohtr.h:65
struct RETROHTR_RENDER_NODE * nodes
Locked pointer to nodes when locked with retrohtr_tree_lock().
Definition retrohtr.h:63
Platform-specific bitmap structure. retroflat_bitmap_ok() can be used on a pointer to it to determine...
Definition retpltd.h:21
Definition retrogui.h:167
Definition retrogui.h:158