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 union RETROGXC_CACHABLE font;
52 struct RETROFLAT_BITMAP bitmap;
69#define retrohtr_node( tree, idx ) \
70 (0 <= (ssize_t)idx ? &((tree)->nodes[idx]) : NULL)
72#define retrohtr_node_parent( tree, idx ) \
73 (0 <= idx && 0 <= (tree)->nodes[idx].parent ? \
74 &((tree)->nodes[(tree)->nodes[idx].parent]) : NULL)
76#define retrohtr_tree_lock( tree ) \
77 if( NULL == (tree)->nodes ) { \
78 maug_mlock( (tree)->nodes_h, (tree)->nodes ); \
79 maug_cleanup_if_null_alloc( struct RETROHTR_RENDER_NODE*, (tree)->nodes ); \
82#define retrohtr_tree_unlock( tree ) \
83 if( NULL != (tree)->nodes ) { \
84 maug_munlock( (tree)->nodes_h, (tree)->nodes ); \
87#define retrohtr_tree_is_locked( tree ) (NULL != (tree)->nodes)
91#define retrohtr_node_screen_x( tree, node_idx ) \
92 ((tree)->nodes[node_idx].x)
94#define retrohtr_node_screen_y( tree, node_idx ) \
95 ((tree)->nodes[node_idx].y)
97void retrohtr_merge_prop(
99 const char* prop_name,
102 void* parent_prop, uint8_t* parent_prop_flags,
103 void* effect_prop, uint8_t* effect_prop_flags,
104 void* tag_prop, uint8_t* tag_prop_flags );
106void retrohtr_merge_styles(
107 struct MCSS_STYLE* effect_style,
108 struct MCSS_STYLE* parent_style,
109 struct MCSS_STYLE* tag_style,
116 ssize_t tag_idx, ssize_t node_idx,
size_t d );
131 struct MCSS_STYLE* parent_style,
struct MCSS_STYLE* effect_style,
136 struct MCSS_STYLE* prev_sibling_style,
137 struct MCSS_STYLE* parent_style, ssize_t node_idx,
size_t d );
141 struct MCSS_STYLE* prev_sibling_style,
142 struct MCSS_STYLE* parent_style, ssize_t node_idx,
size_t d );
146 ssize_t node_idx,
size_t d );
150 RETROFLAT_IN_KEY* input,
155 ssize_t iter,
size_t d );
163void retrohtr_merge_prop(
165 const char* prop_name,
168 void* parent_prop, uint8_t* parent_prop_flags,
169 void* effect_prop, uint8_t* effect_prop_flags,
170 void* tag_prop, uint8_t* tag_prop_flags
176 mcss_prop_is_heritable( p_id )
177 ) && (NULL != parent_prop && (
181 mcss_prop_is_active_flag( *parent_prop, IMPORTANT ) &&
183 !mcss_prop_is_important( *tag_prop ) &&
184 !mcss_prop_is_important( *effect_prop )
188 !mcss_prop_is_active( *tag_prop ) &&
189 !mcss_prop_is_active( *effect_prop )
193 !mcss_prop_is_active( *effect_prop )
198 if( MCSS_PROP_BACKGROUND_COLOR == p_id ) {
199#if RETROHTR_TRACE_LVL > 0
200 debug_printf( RETROHTR_TRACE_LVL,
"background color was %s",
204 }
else if( MCSS_PROP_COLOR == p_id ) {
205#if RETROHTR_TRACE_LVL > 0
206 debug_printf( RETROHTR_TRACE_LVL,
"color was %s",
211#if RETROHTR_TRACE_LVL > 0
212 debug_printf( RETROHTR_TRACE_LVL,
213 "%s using parent %s: " SSIZE_T_FMT,
214 gc_mhtml_tag_names[tag_type], prop_name, *(ssize_t*)parent_prop );
216 memcpy( effect_prop, parent_prop, prop_sz );
217 *effect_prop_flags = *parent_prop_flags;
218 if( MCSS_PROP_BACKGROUND_COLOR == p_id ) {
219#if RETROHTR_TRACE_LVL > 0
220 debug_printf( RETROHTR_TRACE_LVL,
"background color %s",
224 }
else if( MCSS_PROP_COLOR == p_id ) {
225#if RETROHTR_TRACE_LVL > 0
226 debug_printf( RETROHTR_TRACE_LVL,
"color %s",
233 mcss_prop_is_active( *tag_prop )
236#if RETROHTR_TRACE_LVL > 0
237 debug_printf( RETROHTR_TRACE_LVL,
"%s using style %s: " SSIZE_T_FMT,
238 gc_mhtml_tag_names[tag_type], prop_name,
239 *(ssize_t*)tag_prop );
240 if( MCSS_PROP_COLOR == p_id ) {
241 debug_printf( RETROHTR_TRACE_LVL,
"color %s",
246 memcpy( effect_prop, tag_prop, prop_sz );
247 *effect_prop_flags = *tag_prop_flags;
253void retrohtr_merge_styles(
254 struct MCSS_STYLE* effect_style,
255 struct MCSS_STYLE* parent_style,
256 struct MCSS_STYLE* tag_style,
264 MCSS_STYLE_FLAG_ACTIVE !=
265 (MCSS_STYLE_FLAG_ACTIVE & effect_style->flags)
267 mcss_style_init( effect_style );
272 #define MCSS_PROP_TABLE_MERGE( p_id, prop_n, prop_t, prop_p, def ) \
273 retrohtr_merge_prop( p_id, \
277 NULL != parent_style ? &(parent_style->prop_n) : NULL, \
278 NULL != parent_style ? &(parent_style->prop_n ## _flags) : 0, \
279 NULL != effect_style ? &(effect_style->prop_n) : NULL, \
280 NULL != effect_style ? &(effect_style->prop_n ## _flags) : 0, \
281 NULL != tag_style ? &(tag_style->prop_n) : NULL, \
282 NULL != tag_style ? &(tag_style->prop_n ## _flags) : 0 );
284 MCSS_PROP_TABLE( MCSS_PROP_TABLE_MERGE )
289 MCSS_PROP_FLAG_ACTIVE !=
290 (MCSS_PROP_FLAG_ACTIVE & effect_style->DISPLAY_flags)
294 #define MHTML_TAG_TABLE_DISP( tag_id, tag_name, fields, disp ) \
295 } else if( tag_id == tag_type ) { \
296 effect_style->DISPLAY = MCSS_DISPLAY_ ## disp; \
297 debug_printf( RETROHTR_TRACE_LVL, "%s defaulting to %s DISPLAY", \
298 gc_mhtml_tag_names[tag_type], \
299 gc_mcss_display_names[effect_style->DISPLAY] );
302 MHTML_TAG_TABLE( MHTML_TAG_TABLE_DISP )
314 uint8_t auto_unlocked = 0;
316 MAUG_MHANDLE new_nodes_h = (MAUG_MHANDLE)NULL;
318 if( NULL != tree->
nodes ) {
319#if RETROHTR_TRACE_LVL > 0
320 debug_printf( RETROHTR_TRACE_LVL,
"auto-unlocking nodes..." );
322 maug_munlock( tree->nodes_h, tree->
nodes );
327 assert( NULL == tree->
nodes );
328 assert( (MAUG_MHANDLE)NULL != tree->nodes_h );
331 maug_mrealloc_test( new_nodes_h, tree->nodes_h, tree->
nodes_sz_max * 2,
337 assert( NULL == tree->
nodes );
338 maug_mlock( tree->nodes_h, tree->
nodes );
339 if( NULL == tree->
nodes ) {
340 error_printf(
"unable to lock nodes!" );
345#if RETROHTR_TRACE_LVL > 0
346 debug_printf( RETROHTR_TRACE_LVL,
347 "zeroing node " SIZE_T_FMT
" (of " SIZE_T_FMT
")...",
356 maug_munlock( tree->nodes_h, tree->
nodes );
360 if( auto_unlocked ) {
361#if RETROHTR_TRACE_LVL > 0
362 debug_printf( RETROHTR_TRACE_LVL,
"auto-locking nodes..." );
364 maug_mlock( tree->nodes_h, tree->
nodes );
367 if( MERROR_OK != retval ) {
368 retidx = merror_retval_to_sz( retval );
376ssize_t retrohtr_add_node_child(
379 ssize_t node_new_idx = -1,
380 node_sibling_idx = -1;
382 node_new_idx = retrohtr_get_next_free_node( tree );
383 if( 0 > node_new_idx ) {
387#ifdef RETROGXC_PRESENT
388 retrohtr_node( tree, node_new_idx )->font.cache_idx = -1;
390 retrohtr_node( tree, node_new_idx )->parent = node_parent_idx;
391 retrohtr_node( tree, node_new_idx )->first_child = -1;
392 retrohtr_node( tree, node_new_idx )->next_sibling = -1;
394 if( 0 > node_parent_idx ) {
396 1,
"adding root node under " SSIZE_T_FMT
"...", node_parent_idx );
400 1,
"adding node " SSIZE_T_FMT
" under " SSIZE_T_FMT,
401 node_new_idx, node_parent_idx );
405 if( 0 > retrohtr_node( tree, node_parent_idx )->first_child ) {
406#if RETROHTR_TRACE_LVL > 0
407 debug_printf( RETROHTR_TRACE_LVL,
"adding first child..." );
409 assert( -1 == retrohtr_node( tree, node_parent_idx )->first_child );
410 retrohtr_node( tree, node_parent_idx )->first_child = node_new_idx;
412 assert( NULL != retrohtr_node( tree, node_parent_idx ) );
413 node_sibling_idx = retrohtr_node( tree, node_parent_idx )->first_child;
414 assert( NULL != retrohtr_node( tree, node_sibling_idx ) );
415 while( 0 <= retrohtr_node( tree, node_sibling_idx )->next_sibling ) {
417 retrohtr_node( tree, node_sibling_idx )->next_sibling;
419 retrohtr_node( tree, node_sibling_idx )->next_sibling = node_new_idx;
433 ssize_t tag_idx, ssize_t node_idx,
size_t d
435 ssize_t node_new_idx = -1;
436 ssize_t tag_iter_idx = -1;
439 ssize_t tag_next_idx = 0;
441#if RETROHTR_TRACE_LVL > 0
442 debug_printf( RETROHTR_TRACE_LVL,
443 "creating render node for tag: " SSIZE_T_FMT, tag_idx );
451 p_tag_iter = mdata_vector_get( &(parser->tags), tag_idx,
union MHTML_TAG );
452 if( NULL == p_tag_iter ) {
458 assert( MHTML_TAG_TYPE_BODY == p_tag_iter->base.type );
460 node_new_idx = retrohtr_add_node_child( tree, node_idx );
461 if( 0 > node_new_idx ) {
464#if RETROHTR_TRACE_LVL > 0
465 debug_printf( RETROHTR_TRACE_LVL,
466 "created initial root node: " SIZE_T_FMT, node_new_idx );
469 node_idx = node_new_idx;
472 retrohtr_node( tree, node_idx )->tag = tag_idx;
474 retrohtr_node( tree, node_idx )->x = x;
475 retrohtr_node( tree, node_idx )->y = y;
476 retrohtr_node( tree, node_idx )->w = w;
477 retrohtr_node( tree, node_idx )->h = h;
480 tag_iter_idx = p_tag_iter->base.first_child;
481 while( 0 <= tag_iter_idx ) {
482 node_new_idx = retrohtr_add_node_child( tree, node_idx );
483 p_tag_iter = mdata_vector_get(
484 &(parser->tags), tag_iter_idx,
union MHTML_TAG );
485 assert( NULL != p_tag_iter );
486 if( 0 > node_new_idx ) {
490 retrohtr_node( tree, node_new_idx )->tag = tag_iter_idx;
492#if RETROHTR_TRACE_LVL > 0
493 debug_printf( RETROHTR_TRACE_LVL,
494 "rendering node " SSIZE_T_FMT
" (%s) under node " SSIZE_T_FMT,
496 gc_mhtml_tag_names[p_tag_iter->base.type],
501 if( MHTML_TAG_TYPE_IMG == p_tag_iter->base.type ) {
505 &(retrohtr_node( tree, node_new_idx )->bitmap),
507 if( MERROR_OK == retval ) {
508#if RETROHTR_TRACE_LVL > 0
509 debug_printf( RETROHTR_TRACE_LVL,
"loaded img: %s",
510 p_tag_iter->IMG.src );
513 error_printf(
"could not load img: %s", p_tag_iter->IMG.src );
517 tag_next_idx = p_tag_iter->base.next_sibling;
521 retval = retrohtr_tree_create( parser, tree, x, y, w, h,
522 tag_iter_idx, node_new_idx, d + 1 );
523 maug_cleanup_if_not_ok();
527 tag_iter_idx = tag_next_idx;
532 if( mdata_vector_is_locked( &(parser->tags) ) ) {
543 struct MCSS_STYLE* parent_style,
struct MCSS_STYLE* effect_style,
547 ssize_t tag_style_idx = -1;
550 struct MCSS_STYLE* style = NULL;
553#if RETROHTR_TRACE_LVL > 0
554 debug_printf( RETROHTR_TRACE_LVL,
555 "applying styles for tag: " SSIZE_T_FMT, tag_idx );
558 assert( !mdata_vector_is_locked( &(parser->tags) ) );
562 maug_mzero( effect_style,
sizeof(
struct MCSS_STYLE ) );
567 p_tag_iter = mdata_vector_get( &(parser->tags), tag_idx,
union MHTML_TAG );
568 if( NULL == p_tag_iter ) {
572 tag_type = p_tag_iter->base.type;
575 if( 0 < p_tag_iter->base.classes_sz ) {
577 style = mdata_vector_get(
578 &(parser->styler.styles), i,
struct MCSS_STYLE );
583 p_tag_iter->base.classes,
585 p_tag_iter->base.classes_sz
588#if RETROHTR_TRACE_LVL > 0
589 debug_printf( RETROHTR_TRACE_LVL,
"found style for tag class: %s",
593 retrohtr_merge_styles(
594 effect_style, parent_style, style, tag_type );
600 if( 0 < p_tag_iter->base.id_sz ) {
602 style = mdata_vector_get(
603 &(parser->styler.styles), i,
struct MCSS_STYLE );
610 p_tag_iter->base.id_sz
613#if RETROHTR_TRACE_LVL > 0
614 debug_printf( RETROHTR_TRACE_LVL,
"found style for tag ID: %s",
618 retrohtr_merge_styles(
619 effect_style, parent_style, style, tag_type );
625 tag_style_idx = p_tag_iter->base.style;
632 style = mdata_vector_get(
633 &(parser->styler.styles), tag_style_idx,
struct MCSS_STYLE );
636 retrohtr_merge_styles( effect_style, parent_style, style, tag_type );
647 struct MCSS_PARSER* styler,
648 union RETROGXC_CACHABLE* font,
649 struct MCSS_STYLE* effect_style
653 if( retrogxc_cachable_is_loaded( font ) ) {
654 error_printf(
"tried to load font but font already loaded, idx: "
655 SSIZE_T_FMT, font->cache_idx );
659 mdata_strpool_lock( &(styler->strpool) );
661#if RETROHTR_TRACE_LVL > 0
662 debug_printf( RETROHTR_TRACE_LVL,
663 "loading font: %s (" SSIZE_T_FMT
")",
665 effect_style->FONT_FAMILY );
668 if( MDATA_STRPOOL_IDX_ERROR == effect_style->FONT_FAMILY ) {
669 error_printf(
"style has no font associated!" );
676#ifdef RETROGXC_PRESENT
689 &(font->handle), 0, 33, 93 );
690#ifdef RETROGXC_PRESENT
696 mdata_strpool_unlock( &(styler->strpool) );
705 struct MCSS_STYLE* effect_style
711 RETROHTR_TREE_FLAG_GUI_ACTIVE ==
712 (RETROHTR_TREE_FLAG_GUI_ACTIVE & tree->flags)
714#if RETROHTR_TRACE_LVL > 0
715 debug_printf( RETROHTR_TRACE_LVL,
"tree GUI already active!" );
724 maug_cleanup_if_not_ok();
726 retval = retrohtr_load_font(
730 maug_cleanup_if_not_ok();
732 tree->flags |= RETROHTR_TREE_FLAG_GUI_ACTIVE;
734#if RETROHTR_TRACE_LVL > 0
735 debug_printf( RETROHTR_TRACE_LVL,
"tree GUI initialized!" );
746 struct MCSS_STYLE* prev_sibling_style,
747 struct MCSS_STYLE* parent_style, ssize_t node_idx,
size_t d
749 struct MCSS_STYLE effect_style;
750 struct MCSS_STYLE child_prev_sibling_style;
751 struct MCSS_STYLE child_style;
752 ssize_t child_iter_idx = -1;
753 ssize_t tag_idx = -1;
754 ssize_t node_iter_idx = -1;
755 size_t this_line_w = 0;
756 size_t this_line_h = 0;
761 MAUG_MHANDLE font_h = (MAUG_MHANDLE)NULL;
763 if( NULL == retrohtr_node( tree, node_idx ) ) {
767 tag_idx = retrohtr_node( tree, node_idx )->tag;
770 parser, tree, parent_style, &effect_style, tag_idx );
771 maug_cleanup_if_not_ok();
773 assert( !mdata_vector_is_locked( &(parser->tags) ) );
776 p_tag_iter = mdata_vector_get( &(parser->tags), tag_idx,
union MHTML_TAG );
777 assert( NULL != p_tag_iter );
781 if( mcss_prop_is_active( effect_style.POSITION ) ) {
782#if RETROHTR_TRACE_LVL > 0
783 debug_printf( RETROHTR_TRACE_LVL,
784 "node " SSIZE_T_FMT
": applying %s positioning",
785 node_idx, gc_mcss_position_names[effect_style.POSITION] );
794 retrohtr_node( tree, node_idx )->pos = effect_style.POSITION;
795 retrohtr_node( tree, node_idx )->pos_flags = effect_style.POSITION_flags;
803 if( mcss_prop_is_active_NOT_flag( effect_style.WIDTH, AUTO ) ) {
804 retrohtr_node( tree, node_idx )->w = effect_style.WIDTH;
807 if( mcss_prop_is_active_NOT_flag( effect_style.HEIGHT, AUTO ) ) {
808 retrohtr_node( tree, node_idx )->h = effect_style.HEIGHT;
814 retval = retrohtr_load_font(
816 &(retrohtr_node( tree, node_idx )->font),
818 maug_cleanup_if_not_ok();
820 if( 0 <= tag_idx && MHTML_TAG_TYPE_TEXT == p_tag_iter->base.type ) {
823#ifdef RETROGXC_PRESENT
825 retrohtr_node( tree, node_idx )->font.cache_idx,
826 RETROGXC_ASSET_TYPE_FONT );
827 maug_cleanup_if_null_alloc( MAUG_MHANDLE, font_h );
829 font_h = retrohtr_node( tree, node_idx )->font.handle;
832 mdata_strpool_lock( &(parser->strpool) );
837 p_tag_iter->TEXT.content_sz, font_h,
839 retrohtr_node_parent( tree, node_idx )->w,
840 retrohtr_node_parent( tree, node_idx )->h,
841 &(retrohtr_node( tree, node_idx )->w),
842 &(retrohtr_node( tree, node_idx )->h), 0 );
844#if RETROHTR_TRACE_LVL > 0
845 debug_printf( RETROHTR_TRACE_LVL,
"TEXT w: " SIZE_T_FMT,
846 retrohtr_node( tree, node_idx )->w );
849 mdata_strpool_unlock( &(parser->strpool) );
853 MHTML_TAG_TYPE_INPUT == p_tag_iter->base.type
857 retval = retrohtr_tree_gui( tree, &(parser->styler), &effect_style );
861 MERROR_OK != retrogui_init_ctl(
862 &ctl, RETROGUI_CTL_TYPE_BUTTON, node_idx )
864 error_printf(
"could not initialize control!" );
868 p_tag_node = mdata_vector_get(
870 retrohtr_node( tree, node_idx )->tag,
union MHTML_TAG );
872 ctl.base.x = retrohtr_node( tree, node_idx )->x;
873 ctl.base.y = retrohtr_node( tree, node_idx )->y;
876 ctl.BUTTON.label = p_tag_node->INPUT.value;
879 retrohtr_node( tree, node_idx )->w = ctl.base.w;
880 retrohtr_node( tree, node_idx )->h = ctl.base.h;
882#if RETROHTR_TRACE_LVL > 0
883 debug_printf( RETROHTR_TRACE_LVL,
"initialized control for INPUT..." );
886 retrogui_push_ctl( &(tree->gui), &ctl );
888 }
else if( 0 <= tag_idx && MHTML_TAG_TYPE_IMG == p_tag_iter->base.type ) {
890 if( retroflat_bitmap_ok( &(retrohtr_node( tree, node_idx )->bitmap) ) ) {
891 retrohtr_node( tree, node_idx )->w =
892 retroflat_bitmap_w( &(retrohtr_node( tree, node_idx )->bitmap) );
893 retrohtr_node( tree, node_idx )->h =
894 retroflat_bitmap_h( &(retrohtr_node( tree, node_idx )->bitmap) );
897#if RETROHTR_TRACE_LVL > 0
898 debug_printf( RETROHTR_TRACE_LVL,
"TEXT w: " SIZE_T_FMT,
899 retrohtr_node( tree, node_idx )->w );
905 maug_mzero( &child_prev_sibling_style,
sizeof(
struct MCSS_STYLE ) );
906 node_iter_idx = retrohtr_node( tree, node_idx )->first_child;
908 while( 0 <= node_iter_idx ) {
910 parser, tree, &child_prev_sibling_style, &effect_style,
911 node_iter_idx, d + 1 );
913 node_iter_idx = retrohtr_node( tree, node_iter_idx )->next_sibling;
917 if( mdata_vector_is_locked( &(parser->tags) ) ) {
922 if( 0 == retrohtr_node( tree, node_idx )->w ) {
924 MCSS_DISPLAY_BLOCK == effect_style.DISPLAY &&
925 0 <= retrohtr_node( tree, node_idx )->parent
929 retrohtr_node( tree, node_idx )->w =
930 retrohtr_node_parent( tree, node_idx )->w;
934 child_iter_idx = retrohtr_node( tree, node_idx )->first_child;
935 while( 0 <= child_iter_idx ) {
936 assert( !mdata_vector_is_locked( &(parser->tags) ) );
938 parser, tree, &effect_style, &child_style,
939 retrohtr_node( tree, child_iter_idx )->tag );
940 maug_cleanup_if_not_ok();
943 if( MCSS_POSITION_ABSOLUTE == child_style.POSITION ) {
945 retrohtr_node( tree, child_iter_idx )->next_sibling;
949 if( MCSS_DISPLAY_BLOCK == child_style.DISPLAY ) {
954 retrohtr_node( tree, child_iter_idx )->w >
955 retrohtr_node( tree, node_idx )->w
958 retrohtr_node( tree, node_idx )->w =
959 retrohtr_node( tree, child_iter_idx )->w;
963 this_line_w += retrohtr_node( tree, child_iter_idx )->w;
965 if( this_line_w > retrohtr_node( tree, node_idx )->w ) {
967 retrohtr_node( tree, node_idx )->w = this_line_w;
970 child_iter_idx = retrohtr_node( tree, child_iter_idx )->next_sibling;
975 if( 0 == retrohtr_node( tree, node_idx )->h ) {
977 child_iter_idx = retrohtr_node( tree, node_idx )->first_child;
978 while( 0 <= child_iter_idx ) {
979 assert( !mdata_vector_is_locked( &(parser->tags) ) );
981 parser, tree, &effect_style, &child_style,
982 retrohtr_node( tree, child_iter_idx )->tag );
985 if( MCSS_POSITION_ABSOLUTE == child_style.POSITION ) {
986 child_iter_idx = retrohtr_node( tree, child_iter_idx )->next_sibling;
990 if( MCSS_DISPLAY_BLOCK == child_style.DISPLAY ) {
992 retrohtr_node( tree, node_idx )->h += this_line_h;
995 this_line_h = retrohtr_node( tree, child_iter_idx )->h;
998 if( this_line_h < retrohtr_node( tree, child_iter_idx )->h ) {
999 this_line_h = retrohtr_node( tree, child_iter_idx )->h;
1003 child_iter_idx = retrohtr_node( tree, child_iter_idx )->next_sibling;
1007 retrohtr_node( tree, node_idx )->h += this_line_h;
1016 if( mcss_prop_is_active_NOT_flag( effect_style.PADDING_LEFT, AUTO ) ) {
1017 retrohtr_node( tree, node_idx )->w += effect_style.PADDING_LEFT;
1018 }
else if( mcss_prop_is_active_NOT_flag( effect_style.PADDING, AUTO ) ) {
1019 retrohtr_node( tree, node_idx )->w += effect_style.PADDING;
1023 if( mcss_prop_is_active_NOT_flag( effect_style.PADDING_RIGHT, AUTO ) ) {
1024 retrohtr_node( tree, node_idx )->w += effect_style.PADDING_RIGHT;
1025 }
else if( mcss_prop_is_active_NOT_flag( effect_style.PADDING, AUTO ) ) {
1026 retrohtr_node( tree, node_idx )->w += effect_style.PADDING;
1030 if( mcss_prop_is_active_NOT_flag( effect_style.PADDING_TOP, AUTO ) ) {
1031 retrohtr_node( tree, node_idx )->h += effect_style.PADDING_TOP;
1032 }
else if( mcss_prop_is_active_NOT_flag( effect_style.PADDING, AUTO ) ) {
1033 retrohtr_node( tree, node_idx )->h += effect_style.PADDING;
1037 if( mcss_prop_is_active_NOT_flag( effect_style.PADDING_BOTTOM, AUTO ) ) {
1038 retrohtr_node( tree, node_idx )->h += effect_style.PADDING_BOTTOM;
1039 }
else if( mcss_prop_is_active_NOT_flag( effect_style.PADDING, AUTO ) ) {
1040 retrohtr_node( tree, node_idx )->h += effect_style.PADDING;
1043#if RETROHTR_TRACE_LVL > 0
1044 debug_printf( RETROHTR_TRACE_LVL,
1045 "setting node " SIZE_T_FMT
" dirty...", node_idx );
1047 retrohtr_node( tree, node_idx )->flags |= RETROHTR_NODE_FLAG_DIRTY;
1051 if( mdata_vector_is_locked( &(parser->tags) ) ) {
1058 if( NULL != prev_sibling_style ) {
1060 prev_sibling_style, &effect_style,
1061 sizeof(
struct MCSS_STYLE ) );
1069#define retrohtr_break_on_active_pos( iter_idx ) \
1070 if( mcss_prop_is_active( retrohtr_node( tree, iter_idx )->pos ) ) { \
1074static ssize_t retrohtr_find_prev_sibling_in_box_model(
1078 ssize_t sibling_iter_idx = -1;
1079 ssize_t sibling_found_idx = -1;
1081 if( 0 > retrohtr_node( tree, node_idx )->parent ) {
1086 sibling_iter_idx = retrohtr_node_parent( tree, node_idx )->first_child;
1088 if( sibling_iter_idx == node_idx ) {
1093 while( 0 <= sibling_iter_idx && node_idx != sibling_iter_idx ) {
1096 MCSS_POSITION_ABSOLUTE != retrohtr_node( tree, sibling_iter_idx )->pos
1098 sibling_found_idx = sibling_iter_idx;
1103 sibling_iter_idx = retrohtr_node( tree, sibling_iter_idx )->next_sibling;
1107 return sibling_found_idx;
1114 ssize_t node_parent_idx
1116 ssize_t node_sibling_idx = -1;
1118 struct MCSS_STYLE effect_style;
1123 node_sibling_idx = retrohtr_node( tree, node_parent_idx )->first_child;
1124 while( 0 <= node_sibling_idx ) {
1125 maug_mzero( &effect_style,
sizeof(
struct MCSS_STYLE ) );
1127 parser, tree, NULL, &effect_style,
1128 retrohtr_node( tree, node_sibling_idx )->tag );
1130 if( MCSS_POSITION_ABSOLUTE == effect_style.POSITION ) {
1132 retrohtr_node( tree, node_sibling_idx )->edge |= RETROHTR_EDGE_INSIDE;
1134 }
else if( MCSS_DISPLAY_INLINE == effect_style.DISPLAY ) {
1136 if( 0 == col_idx ) {
1137 retrohtr_node( tree, node_sibling_idx )->edge |= RETROHTR_EDGE_LEFT;
1139 if( 0 == row_idx ) {
1140 retrohtr_node( tree, node_sibling_idx )->edge |= RETROHTR_EDGE_TOP;
1142 if( 0 < row_idx && 0 < col_idx ) {
1143 retrohtr_node( tree, node_sibling_idx )->edge |= RETROHTR_EDGE_INSIDE;
1155 if( 0 == row_idx ) {
1156 retrohtr_node( tree, node_sibling_idx )->edge |= RETROHTR_EDGE_TOP;
1160 retrohtr_node( tree, node_sibling_idx )->edge |= RETROHTR_EDGE_LEFT;
1163 assert( !mdata_vector_is_locked( &(parser->tags) ) );
1166 p_tag_iter = mdata_vector_get( &(parser->tags),
1167 retrohtr_node( tree, node_sibling_idx )->tag,
1169 assert( NULL != p_tag_iter );
1171 debug_printf( 1,
"marking node " SIZE_T_FMT
" (%s) edge: %u",
1173 gc_mhtml_tag_names[p_tag_iter->base.type],
1174 retrohtr_node( tree, node_sibling_idx )->edge );
1179 retrohtr_node( tree, node_sibling_idx )->next_sibling;
1184 if( mdata_vector_is_locked( &(parser->tags) ) ) {
1195 struct MCSS_STYLE* prev_sibling_style,
1196 struct MCSS_STYLE* parent_style, ssize_t node_idx,
size_t d
1198 struct MCSS_STYLE child_prev_sibling_style;
1199 struct MCSS_STYLE effect_style;
1200 ssize_t child_iter_idx = -1;
1201 ssize_t tag_idx = -1;
1202 ssize_t node_iter_idx = -1;
1203 ssize_t prev_sibling_idx = -1;
1207 if( NULL == retrohtr_node( tree, node_idx ) ) {
1211 tag_idx = retrohtr_node( tree, node_idx )->tag;
1214 parser, tree, parent_style, &effect_style, tag_idx );
1217 retrohtr_find_prev_sibling_in_box_model( tree, node_idx );
1221 if( MCSS_POSITION_ABSOLUTE == effect_style.POSITION ) {
1224 if( mcss_prop_is_active_NOT_flag( effect_style.LEFT, AUTO ) ) {
1226 child_iter_idx = retrohtr_node( tree, node_idx )->parent;
1227 while( 0 <= retrohtr_node( tree, child_iter_idx )->parent ) {
1228 retrohtr_break_on_active_pos( child_iter_idx );
1229 child_iter_idx = retrohtr_node( tree, child_iter_idx )->parent;
1233 retrohtr_node( tree, node_idx )->x =
1234 retrohtr_node( tree, child_iter_idx )->x + effect_style.LEFT;
1236 if( mcss_prop_is_active_NOT_flag( effect_style.RIGHT, AUTO ) ) {
1238 child_iter_idx = retrohtr_node( tree, node_idx )->parent;
1239 while( 0 <= retrohtr_node( tree, child_iter_idx )->parent ) {
1240 retrohtr_break_on_active_pos( child_iter_idx );
1241 child_iter_idx = retrohtr_node( tree, child_iter_idx )->parent;
1245 retrohtr_node( tree, node_idx )->x =
1246 retrohtr_node( tree, child_iter_idx )->w -
1247 retrohtr_node( tree, node_idx )->w -
1252 MCSS_DISPLAY_INLINE == effect_style.DISPLAY &&
1253 MCSS_DISPLAY_INLINE == prev_sibling_style->DISPLAY &&
1254 0 <= prev_sibling_idx
1257 retrohtr_node( tree, node_idx )->x =
1258 retrohtr_node( tree, prev_sibling_idx )->x +
1259 retrohtr_node( tree, prev_sibling_idx )->w;
1261 }
else if( 0 <= retrohtr_node( tree, node_idx )->parent ) {
1262 retrohtr_node( tree, node_idx )->x = retrohtr_node_parent( tree, node_idx )->x;
1269 if( MCSS_POSITION_ABSOLUTE == effect_style.POSITION ) {
1272 if( mcss_prop_is_active_NOT_flag( effect_style.TOP, AUTO ) ) {
1274 child_iter_idx = retrohtr_node( tree, node_idx )->parent;
1275 while( 0 <= retrohtr_node( tree, child_iter_idx )->parent ) {
1276 retrohtr_break_on_active_pos( child_iter_idx );
1277 child_iter_idx = retrohtr_node( tree, child_iter_idx )->parent;
1281 retrohtr_node( tree, node_idx )->y =
1282 retrohtr_node( tree, child_iter_idx )->y + effect_style.TOP;
1284 if( mcss_prop_is_active_NOT_flag( effect_style.BOTTOM, AUTO ) ) {
1286 child_iter_idx = retrohtr_node( tree, node_idx )->parent;
1287 while( 0 <= retrohtr_node( tree, child_iter_idx )->parent ) {
1288 retrohtr_break_on_active_pos( child_iter_idx );
1289 child_iter_idx = retrohtr_node( tree, child_iter_idx )->parent;
1293 retrohtr_node( tree, node_idx )->y =
1294 retrohtr_node( tree, child_iter_idx )->h -
1295 retrohtr_node( tree, node_idx )->h -
1296 effect_style.BOTTOM;
1300 MCSS_DISPLAY_INLINE == effect_style.DISPLAY &&
1301 MCSS_DISPLAY_INLINE == prev_sibling_style->DISPLAY &&
1302 0 <= prev_sibling_idx
1305 retrohtr_node( tree, node_idx )->y = retrohtr_node( tree, prev_sibling_idx )->y;
1307 }
else if( 0 <= prev_sibling_idx ) {
1314 retrohtr_node( tree, node_idx )->y =
1315 retrohtr_node( tree, prev_sibling_idx )->y +
1316 retrohtr_node( tree, prev_sibling_idx )->h;
1318 }
else if( 0 <= retrohtr_node( tree, node_idx )->parent ) {
1321 retrohtr_node( tree, node_idx )->y = retrohtr_node_parent( tree, node_idx )->y;
1327 MCSS_POSITION_ABSOLUTE != retrohtr_node( tree, node_idx )->pos &&
1328 0 <= retrohtr_node( tree, node_idx )->parent &&
1329 mcss_prop_is_active_flag( effect_style.MARGIN_LEFT, AUTO ) &&
1330 mcss_prop_is_active_flag( effect_style.MARGIN_RIGHT, AUTO )
1333 retrohtr_node( tree, node_idx )->x =
1334 retrohtr_node_parent( tree, node_idx )->x +
1335 (retrohtr_node_parent( tree, node_idx )->w >> 1) -
1336 (retrohtr_node( tree, node_idx )->w >> 1);
1339 0 <= retrohtr_node( tree, node_idx )->parent &&
1340 mcss_prop_is_active_flag( effect_style.MARGIN_LEFT, AUTO ) &&
1341 mcss_prop_is_active_NOT_flag( effect_style.MARGIN_RIGHT, AUTO )
1345 retrohtr_node( tree, node_idx )->x =
1346 retrohtr_node_parent( tree, node_idx )->w -
1347 retrohtr_node( tree, node_idx )->w;
1349 }
else if( mcss_prop_is_active( effect_style.MARGIN_LEFT ) ) {
1351 retrohtr_node( tree, node_idx )->x += effect_style.MARGIN_LEFT;
1360 debug_printf( 1,
"(d: " SIZE_T_FMT
") node " SIZE_T_FMT
" is on edge: %u",
1361 d, node_idx, retrohtr_node( tree, node_idx )->edge );
1365 RETROHTR_EDGE_UNKNOWN != retrohtr_node( tree, node_idx )->edge );
1368 RETROHTR_EDGE_LEFT ==
1369 (RETROHTR_EDGE_LEFT & retrohtr_node( tree, node_idx )->edge)
1372 if( mcss_prop_is_active_NOT_flag( parent_style->PADDING_LEFT, AUTO ) ) {
1373 retrohtr_node( tree, node_idx )->x += parent_style->PADDING_LEFT;
1374 }
else if( mcss_prop_is_active_NOT_flag( parent_style->PADDING, AUTO ) ) {
1375 retrohtr_node( tree, node_idx )->x += parent_style->PADDING;
1380 RETROHTR_EDGE_TOP ==
1381 (RETROHTR_EDGE_TOP & retrohtr_node( tree, node_idx )->edge) &&
1383 RETROHTR_EDGE_LEFT ==
1384 (RETROHTR_EDGE_LEFT & retrohtr_node( tree, node_idx )->edge)
1387 if( mcss_prop_is_active_NOT_flag( parent_style->PADDING_TOP, AUTO ) ) {
1388 retrohtr_node( tree, node_idx )->y += parent_style->PADDING_TOP;
1389 }
else if( mcss_prop_is_active_NOT_flag( parent_style->PADDING, AUTO ) ) {
1390 retrohtr_node( tree, node_idx )->y += parent_style->PADDING;
1396 if( mcss_prop_is_active( effect_style.COLOR ) ) {
1397 retrohtr_node( tree, node_idx )->fg = effect_style.COLOR;
1400 if( mcss_prop_is_active( effect_style.BACKGROUND_COLOR ) ) {
1401 retrohtr_node( tree, node_idx )->bg = effect_style.BACKGROUND_COLOR;
1406 retrohtr_mark_edge_child_nodes( parser, tree, node_idx );
1408 maug_mzero( &child_prev_sibling_style,
sizeof(
struct MCSS_STYLE ) );
1409 node_iter_idx = retrohtr_node( tree, node_idx )->first_child;
1410 while( 0 <= node_iter_idx ) {
1415 parser, tree, &child_prev_sibling_style, &effect_style,
1416 node_iter_idx, d + 1 );
1418 node_iter_idx = retrohtr_node( tree, node_iter_idx )->next_sibling;
1421 assert( !mdata_vector_is_locked( &(parser->tags) ) );
1423 p_tag_iter = mdata_vector_get( &(parser->tags), tag_idx,
union MHTML_TAG );
1424 assert( NULL != p_tag_iter );
1426 if( MHTML_TAG_TYPE_INPUT == p_tag_iter->base.type ) {
1428 retval = retrogui_pos_ctl( &(tree->gui), node_idx,
1429 retrohtr_node_screen_x( tree, node_idx ),
1430 retrohtr_node_screen_y( tree, node_idx ),
1431 retrohtr_node( tree, node_idx )->w,
1432 retrohtr_node( tree, node_idx )->h );
1433 maug_cleanup_if_not_ok();
1436#if RETROHTR_TRACE_LVL > 0
1437 debug_printf( RETROHTR_TRACE_LVL,
1438 "setting node " SIZE_T_FMT
" dirty...", node_idx );
1440 retrohtr_node( tree, node_idx )->flags |= RETROHTR_NODE_FLAG_DIRTY;
1444 if( mdata_vector_is_locked( &(parser->tags) ) ) {
1451 if( NULL != prev_sibling_style ) {
1453 prev_sibling_style, &effect_style,
1454 sizeof(
struct MCSS_STYLE ) );
1464 ssize_t node_idx,
size_t d
1469 MAUG_MHANDLE font_h = (MAUG_MHANDLE)NULL;
1471 node = retrohtr_node( tree, node_idx );
1473 if( NULL == node ) {
1479 if( 0 > node->tag ) {
1483 if( RETROHTR_NODE_FLAG_DIRTY != (RETROHTR_NODE_FLAG_DIRTY & node->flags) ) {
1487 assert( !mdata_vector_is_locked( &(parser->tags) ) );
1490 p_tag = mdata_vector_get( &(parser->tags), node->tag,
union MHTML_TAG );
1491 if( NULL == p_tag ) {
1496 if( MHTML_TAG_TYPE_TEXT == p_tag->base.type ) {
1499 MDATA_STRPOOL_IDX_ERROR == p_tag->TEXT.content_idx ||
1500 !retrogxc_cachable_is_loaded( &(node->font) )
1505#ifdef RETROGXC_PRESENT
1507 node->font.cache_idx, RETROGXC_ASSET_TYPE_FONT );
1508 maug_cleanup_if_null_alloc( MAUG_MHANDLE, font_h );
1510 font_h = node->font.handle;
1513 mdata_strpool_lock( &(parser->strpool) );
1518 p_tag->TEXT.content_sz, font_h,
1519 retrohtr_node_screen_x( tree, node_idx ),
1520 retrohtr_node_screen_y( tree, node_idx ),
1521 node->w, node->h, 0 );
1523 mdata_strpool_unlock( &(parser->strpool) );
1525 }
else if( MHTML_TAG_TYPE_BODY == p_tag->base.type ) {
1527#if RETROHTR_TRACE_LVL > 0
1529 RETROHTR_TRACE_LVL,
"drawing BODY node " SIZE_T_FMT
"...", node_idx );
1533 if( RETROFLAT_COLOR_NULL != node->bg ) {
1536 retrohtr_node_screen_x( tree, node_idx ),
1537 retrohtr_node_screen_y( tree, node_idx ),
1538 retrohtr_node( tree, node_idx )->w,
1539 retrohtr_node( tree, node_idx )->h,
1543 }
else if( MHTML_TAG_TYPE_IMG == p_tag->base.type ) {
1546 if( !retroflat_bitmap_ok( &(retrohtr_node( tree, node_idx )->bitmap) ) ) {
1550#if RETROHTR_TRACE_LVL > 0
1552 RETROHTR_TRACE_LVL,
"drawing IMG node " SIZE_T_FMT
"...", node_idx );
1556 NULL, &(retrohtr_node( tree, node_idx )->bitmap),
1558 retrohtr_node_screen_x( tree, node_idx ),
1559 retrohtr_node_screen_y( tree, node_idx ),
1560 retroflat_bitmap_w( &(retrohtr_node( tree, node_idx )->bitmap) ),
1561 retroflat_bitmap_h( &(retrohtr_node( tree, node_idx )->bitmap) ),
1566 }
else if( MHTML_TAG_TYPE_INPUT == p_tag->base.type ) {
1568#if RETROHTR_TRACE_LVL > 0
1569 debug_printf( RETROHTR_TRACE_LVL,
"setting tree GUI dirty..." );
1575 if( RETROFLAT_COLOR_NULL == node->bg ) {
1579#if RETROHTR_TRACE_LVL > 0
1581 RETROHTR_TRACE_LVL,
"drawing xs node " SIZE_T_FMT
"...",
1589 retrohtr_node_screen_x( tree, node_idx ),
1590 retrohtr_node_screen_y( tree, node_idx ),
1595 node->flags &= ~RETROHTR_NODE_FLAG_DIRTY;
1599 if( mdata_vector_is_locked( &(parser->tags) ) ) {
1603 if( MERROR_OK != retval ) {
1604 error_printf(
"failed drawing node: " SIZE_T_FMT, node_idx );
1609 retrohtr_tree_draw( parser, tree, node->
first_child, d + 1 );
1611 retrohtr_tree_draw( parser, tree, node->
next_sibling, d );
1616 RETROHTR_TREE_FLAG_GUI_ACTIVE ==
1617 (tree->flags & RETROHTR_TREE_FLAG_GUI_ACTIVE)
1619 retrogui_redraw_ctls( &(tree->gui) );
1629 RETROFLAT_IN_KEY* input,
1635 assert( retrohtr_tree_is_locked( tree ) );
1638 RETROHTR_TREE_FLAG_GUI_ACTIVE !=
1639 (RETROHTR_TREE_FLAG_GUI_ACTIVE & tree->flags)
1648#if RETROHTR_TRACE_LVL > 0
1650 RETROHTR_TRACE_LVL,
"setting node " SIZE_T_FMT
" dirty...", idc );
1652 retrohtr_node( tree, idc )->flags |= RETROHTR_NODE_FLAG_DIRTY;
1655 if( MERROR_OK != retval ) {
1666 ssize_t node_idx,
size_t d
1673 if( 0 > node_idx ) {
1677 assert( !mdata_vector_is_locked( &(parser->tags) ) );
1680 p_tag_iter = mdata_vector_get(
1682 if( NULL == p_tag_iter ) {
1687 maug_mzero( indents, 30 );
1688 for( i = 0 ; d > i ; i++ ) {
1689 if( maug_strlen( indents ) >= 30 ) {
1692 strcat( indents,
" " );
1695#if RETROHTR_TRACE_LVL > 0
1699 "%s" SSIZE_T_FMT
" (tag %s): x: " SSIZE_T_FMT
", y: " SSIZE_T_FMT
1700 " (" SSIZE_T_FMT
" x " SSIZE_T_FMT
")",
1702 0 <= tree->
nodes[node_idx].tag ?
1703 gc_mhtml_tag_names[p_tag_iter->base.type] :
"ROOT",
1704 tree->
nodes[node_idx].x, tree->
nodes[node_idx].y,
1705 tree->
nodes[node_idx].w, tree->
nodes[node_idx].h
1711 retval = retrohtr_tree_dump(
1713 maug_cleanup_if_not_ok();
1715 retval = retrohtr_tree_dump(
1717 maug_cleanup_if_not_ok();
1728#if RETROHTR_TRACE_LVL > 0
1729 debug_printf( RETROHTR_TRACE_LVL,
"freeing render nodes..." );
1738 RETROHTR_TREE_FLAG_GUI_ACTIVE ==
1739 (tree->flags & RETROHTR_TREE_FLAG_GUI_ACTIVE)
1745 retrohtr_tree_unlock( tree );
1747 if( (MAUG_MHANDLE)NULL != tree->nodes_h ) {
1748 maug_mfree( tree->nodes_h );
1761#if RETROHTR_TRACE_LVL > 0
1762 debug_printf( RETROHTR_TRACE_LVL,
1763 "allocating " SIZE_T_FMT
" nodes...", tree->
nodes_sz_max );
uint16_t MERROR_RETVAL
Return type indicating function returns a value from this list.
Definition: merror.h:28
#define RETROFLAT_BITMAP_FLAG_LITERAL_PATH
Flag for retroflat_load_bitmap() to not use assets path.
Definition: retroflt.h:580
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 ...
#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:610
MERROR_RETVAL retroflat_blit_bitmap(struct RETROFLAT_BITMAP *target, struct RETROFLAT_BITMAP *src, retroflat_pxxy_t s_x, retroflat_pxxy_t s_y, retroflat_pxxy_t d_x, retroflat_pxxy_t d_y, retroflat_pxxy_t w, retroflat_pxxy_t h, int16_t instance)
Blit the contents of a ::RETROFLAT_BITMAP onto another ::RETROFLAT_BITMAP.
int8_t RETROFLAT_COLOR
Defines an index in the platform-specific color-table.
Definition: retroflt.h:328
#define RETROFLAT_DRAW_FLAG_FILL
Flag for retroflat_rect() or retroflat_ellipse(), indicating drawn shape should be filled.
Definition: retroflt.h:376
void retroflat_rect(struct RETROFLAT_BITMAP *target, const RETROFLAT_COLOR color, retroflat_pxxy_t x, retroflat_pxxy_t y, retroflat_pxxy_t w, retroflat_pxxy_t h, uint8_t flags)
Draw a rectangle onto the target ::RETROFLAT_BITMAP.
int16_t retroflat_pxxy_t
Type used for surface pixel coordinates.
Definition: retroflt.h:925
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.
MERROR_RETVAL retrogui_destroy(struct RETROGUI *gui)
Free memory held by a RETROGUI controller internally and clean up any subordinate controls.
MERROR_RETVAL retrogui_init(struct RETROGUI *gui)
Prepare a RETROGUI controller for use.
int16_t retrogui_idc_t
Unique identifying constant number for controls.
Definition: retrogui.h:330
MAUG_MHANDLE retrogxc_get_asset(size_t asset_idx, retrogxc_asset_type_t asset_type)
Retrive an asset for which we have a prior cached index.
#define mdata_strpool_get(sp, idx)
Get a string by the index of its first character in the strpool.
Definition: mdata.h:334
MERROR_RETVAL retrofont_load(const char *font_name, MAUG_MHANDLE *p_font_h, uint8_t glyph_h, uint16_t first_glyph, uint16_t glyphs_count)
Load a font for drawing.
void retrofont_string(retroflat_blit_t *target, RETROFLAT_COLOR color, const char *str, size_t str_sz, MAUG_MHANDLE font_h, retroflat_pxxy_t x, retroflat_pxxy_t y, retroflat_pxxy_t max_w, retroflat_pxxy_t max_h, uint8_t flags)
Draw a string with the given font.
size_t nodes_sz_max
Current alloc'd number of nodes in RETROHTR_RENDER_NODE::nodes_h.
Definition: retrohtr.h:63
ssize_t parent
Index of container's render node in RETROHTR_RENDER_TREE.
Definition: retrohtr.h:47
ssize_t first_child
Index of first child's render node in RETROHTR_RENDER_TREE.
Definition: retrohtr.h:49
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:51
size_t nodes_sz
Current active number of nodes in RETROHTR_RENDER_NODE::nodes_h.
Definition: retrohtr.h:61
struct RETROHTR_RENDER_NODE * nodes
Locked pointer to nodes when locked with retrohtr_tree_lock().
Definition: retrohtr.h:59
#define mdata_vector_lock(v)
Lock the vector. This should be done when items from the vector are actively being referenced,...
Definition: mdata.h:372
#define mdata_vector_unlock(v)
Unlock the vector so items may be added and removed.
Definition: mdata.h:405
#define mdata_vector_ct(v)
Number of items of MDATA_VECTOR::item_sz bytes actively stored in this vector.
Definition: mdata.h:448
uint8_t retroflat_flags
maug_retroflt_flags indicating current system status.
Definition: retroflt.h:1140
#define RETROFLAT_STATE_FLAG_USE_GXC
Assume all ::RETROGXC_CACHABLE are cache indexes and not handles.
Definition: retroflt.h:432
Definition: retrogui.h:468
#define RETROGUI_FLAGS_DIRTY
RETROGUI::flags indicating controls should be redrawn.
Definition: retrogui.h:263
union RETROGXC_CACHABLE font
Font used to draw any attached RETROGUI_CTL.
Definition: retrogui.h:489
Definition: retrohtr.h:28
Definition: retrohtr.h:55
Definition: retrogui.h:450