Skip to content

Commit 2a923a6

Browse files
committed
fix(renderer): widget content overflow (#144)
1 parent bfd9461 commit 2a923a6

1 file changed

Lines changed: 80 additions & 40 deletions

File tree

src/gui/widget_paint.c

Lines changed: 80 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -35,26 +35,29 @@
3535
#include <LCUI/gui/widget.h>
3636
#include <LCUI/display.h>
3737

38+
//#define DEBUG_FRAME_RENDER
3839
#define ComputeActualPX(VAL) LCUIMetrics_ComputeActual( VAL, SVT_PX )
3940

41+
#ifdef DEBUG_FRAME_RENDER
42+
#include <LCUI/image.h>
43+
#endif
44+
4045
typedef struct LCUI_RectGroupRec_ {
4146
LCUI_Widget widget;
4247
LinkedList rects;
4348
}LCUI_RectGroupRec, *LCUI_RectGroup;
4449

45-
/** 部件渲染器 */
4650
typedef struct LCUI_WidgetRendererRec_ {
47-
float x, y; /**< 目标部件的位置,相对于根级部件 */
48-
float content_top; /**< 内容区的上边距 */
49-
float content_left; /**< 内容区的左边距 */
50-
LCUI_Widget target; /**< 绘制目标 */
51-
LCUI_PaintContext paint; /**< 绘制上下文 */
52-
LCUI_PaintContext root_paint; /**< 根级绘制上下文 */
53-
LCUI_Graph content_graph; /**< 部件的内容区图形缓存 */
54-
LCUI_Graph self_graph; /**< 部件的图形缓存 */
55-
LCUI_Graph layer_graph; /**< 部件的图层缓存,用于承载自身和内容区的图形 */
56-
LCUI_Rect content_rect; /**< 内容区,相对于根级部件 */
57-
LCUI_Rect content_paint_rect; /**< 内容区中需要绘制的区域 */
51+
float x, y; /**< target widget position, it relative to root canvas */
52+
float content_top; /**< content area top spacing, it relative to widget canvas */
53+
float content_left; /**< content area left spacing, it relative to widget canvas */
54+
LCUI_Widget target; /**< target widget */
55+
LCUI_PaintContext paint; /**< current target widget paint context */
56+
LCUI_PaintContext root_paint; /**< root paint context */
57+
LCUI_Graph content_graph; /**< content canvas */
58+
LCUI_Graph self_graph; /**< target widget canvas */
59+
LCUI_Graph layer_graph; /**< layer canvas, used to mix content and self canvas with widget opacity */
60+
LCUI_Rect content_rect; /**< actual paint rectangle in widget content rectangle, it relative to root canvas */
5861
LCUI_BOOL has_content_graph;
5962
LCUI_BOOL has_self_graph;
6063
LCUI_BOOL has_layer_graph;
@@ -283,6 +286,7 @@ static LCUI_WidgetRenderer WidgetRenderer( LCUI_Widget w,
283286
LCUI_WidgetRenderer parent )
284287
{
285288
LCUI_RectF rect;
289+
LCUI_Rect paint_rect;
286290
ASSIGN( that, LCUI_WidgetRenderer );
287291

288292
that->target = w;
@@ -299,13 +303,12 @@ static LCUI_WidgetRenderer WidgetRenderer( LCUI_Widget w,
299303
that->x = that->y = 0;
300304
that->root_paint = that->paint;
301305
}
302-
/* 若部件本身是透明的 */
303306
if( w->computed_style.opacity < 1.0 ) {
304307
that->has_self_graph = TRUE;
305308
that->has_content_graph = TRUE;
306309
that->has_layer_graph = TRUE;
307310
} else {
308-
/* 若使用了圆角边框,则判断当前脏矩形区域是否在圆角边框内
311+
/* if target has rounded corners border...
309312
...
310313
if( ... ) {
311314
that->has_content_graph = TRUE;
@@ -324,35 +327,44 @@ static LCUI_WidgetRenderer WidgetRenderer( LCUI_Widget w,
324327
that->paint->rect.width,
325328
that->paint->rect.height );
326329
}
327-
/* 获取内容框相对于图层的间距 */
330+
/* get content rectangle left spacing and top */
328331
that->content_left = w->box.padding.x - w->box.canvas.x;
329332
that->content_top = w->box.padding.y - w->box.canvas.y;
330-
/* 获取内容区域,相对于根级部件 */
333+
/* get content rectangle, it relative to root canvas */
331334
rect.x = that->x + that->content_left;
332335
rect.y = that->y + that->content_top;
333336
rect.width = w->box.padding.width;
334337
rect.height = w->box.padding.height;
335-
/* 栅格化内容区域 */
336338
LCUIMetrics_ComputeRectActual( &that->content_rect, &rect );
337-
rect.x -= that->x;
338-
rect.y -= that->y;
339-
LCUIMetrics_ComputeRectActual( &that->content_paint_rect, &rect );
340-
/* 获取内容区域中实际需要绘制的区域 */
339+
/* convert position of paint rectangle to root canvas relative */
340+
rect.x = that->x;
341+
rect.y = that->y;
342+
LCUIMetrics_ComputeRectActual( &paint_rect, &rect );
343+
paint_rect.x += that->paint->rect.x;
344+
paint_rect.y += that->paint->rect.y;
345+
paint_rect.width = that->paint->rect.width;
346+
paint_rect.height = that->paint->rect.height;
347+
/* get actual paint rectangle in widget content rectangle */
341348
that->can_render_centent = LCUIRect_GetOverlayRect(
342-
&that->content_paint_rect, &that->paint->rect,
343-
&that->content_paint_rect
349+
&that->content_rect, &paint_rect, &that->content_rect
344350
);
345-
/* 转换坐标为相对于绘制区域 */
346-
that->content_paint_rect.x -= that->paint->rect.x;
347-
that->content_paint_rect.y -= that->paint->rect.y;
351+
DEBUG_MSG( "[%s][%d/%d] content_rect: (%d,%d,%d,%d), "
352+
"canvas_rect: (%d,%d,%d,%d)\n",
353+
w->id, w->index,
354+
w->parent ? w->parent->children_show.length : 1,
355+
that->content_rect.x, that->content_rect.y,
356+
that->content_rect.width, that->content_rect.height,
357+
that->paint->canvas.quote.left,
358+
that->paint->canvas.quote.top,
359+
that->paint->canvas.width,
360+
that->paint->canvas.height );
348361
if( !that->can_render_centent ) {
349362
return that;
350363
}
351-
/* 若需要部件内容区的位图缓存 */
352364
if( that->has_content_graph ) {
353365
that->content_graph.color_type = COLOR_TYPE_ARGB;
354-
Graph_Create( &that->content_graph, that->content_paint_rect.width,
355-
that->content_paint_rect.height );
366+
Graph_Create( &that->content_graph, that->content_rect.width,
367+
that->content_rect.height );
356368
}
357369
return that;
358370
}
@@ -395,11 +407,6 @@ static size_t WidgetRenderer_RenderChildren( LCUI_WidgetRenderer that )
395407
&paint_rect ) ) {
396408
continue;
397409
}
398-
if( !LCUIRect_GetOverlayRect( &that->root_paint->rect,
399-
&paint_rect,
400-
&paint_rect ) ) {
401-
continue;
402-
}
403410
if( that->has_content_graph ) {
404411
paint.with_alpha = TRUE;
405412
} else {
@@ -426,16 +433,35 @@ static size_t WidgetRenderer_Render( LCUI_WidgetRenderer renderer )
426433
size_t count = 0;
427434
LCUI_PaintContextRec self_paint;
428435
LCUI_WidgetRenderer that = renderer;
436+
#ifdef DEBUG_FRAME_RENDER
437+
char filename[256];
438+
static size_t frame = 0;
439+
#endif
429440
/* 如果部件有需要绘制的内容 */
430441
if( that->can_render_self ) {
431442
count += 1;
432443
self_paint = *that->paint;
433444
self_paint.canvas = that->self_graph;
434445
Widget_OnPaint( that->target, &self_paint );
446+
#ifdef DEBUG_FRAME_RENDER
447+
sprintf( filename,
448+
"frame-%lu-%s-self-paint-(%d,%d,%d,%d).png",
449+
frame++, renderer->target->id,
450+
self_paint.rect.x, self_paint.rect.y,
451+
self_paint.rect.width,
452+
self_paint.rect.height );
453+
LCUI_WritePNGFile( filename, &self_paint.canvas );
454+
#endif
435455
/* 若不需要缓存自身位图则直接绘制到画布上 */
436456
if( !that->has_self_graph ) {
437457
Graph_Mix( &that->paint->canvas, &that->self_graph,
438458
0, 0, that->paint->with_alpha );
459+
#ifdef DEBUG_FRAME_RENDER
460+
sprintf( filename, "frame-%lu-%s-canvas.png",
461+
frame++, renderer->target->id );
462+
LCUI_WritePNGFile( filename,
463+
&that->root_paint->canvas );
464+
#endif
439465
}
440466
}
441467
if( that->can_render_centent ) {
@@ -448,9 +474,15 @@ static size_t WidgetRenderer_Render( LCUI_WidgetRenderer renderer )
448474
if( !that->has_layer_graph ) {
449475
if( that->has_content_graph ) {
450476
Graph_Mix( &that->paint->canvas, &that->content_graph,
451-
that->content_paint_rect.x,
452-
that->content_paint_rect.y, TRUE );
477+
that->content_rect.x,
478+
that->content_rect.y, TRUE );
453479
}
480+
#ifdef DEBUG_FRAME_RENDER
481+
sprintf( filename, "frame-%lu-%s-canvas.png",
482+
frame++, renderer->target->id );
483+
LCUI_WritePNGFile( filename,
484+
&that->root_paint->canvas );
485+
#endif
454486
return count;
455487
}
456488
/* 若需要绘制的是当前部件图层,则先混合部件自身位图和内容位图,得出当
@@ -459,18 +491,26 @@ static size_t WidgetRenderer_Render( LCUI_WidgetRenderer renderer )
459491
if( that->can_render_self ) {
460492
Graph_Copy( &that->layer_graph, &that->self_graph );
461493
Graph_Mix( &that->layer_graph, &that->content_graph,
462-
that->content_paint_rect.x,
463-
that->content_paint_rect.y, TRUE );
494+
that->content_rect.x,
495+
that->content_rect.y, TRUE );
464496
} else {
465497
Graph_Create( &that->layer_graph, that->paint->rect.width,
466498
that->paint->rect.height );
467499
Graph_Replace( &that->layer_graph, &that->content_graph,
468-
that->content_paint_rect.x,
469-
that->content_paint_rect.y );
500+
that->content_rect.x,
501+
that->content_rect.y );
470502
}
471503
that->layer_graph.opacity = that->target->computed_style.opacity;
472504
Graph_Mix( &that->paint->canvas, &that->layer_graph,
473505
0, 0, that->paint->with_alpha );
506+
#ifdef DEBUG_FRAME_RENDER
507+
sprintf( filename, "frame-%lu-%s-layer.png",
508+
frame++, renderer->target->id );
509+
LCUI_WritePNGFile( filename, &that->layer_graph );
510+
sprintf( filename, "frame-%lu-%s-canvas.png",
511+
frame++, renderer->target->id );
512+
LCUI_WritePNGFile( filename, &that->root_paint->canvas );
513+
#endif
474514
return count;
475515
}
476516

0 commit comments

Comments
 (0)