Skip to content

Commit e9ea262

Browse files
committed
perf(gui): improve invalid area collection
1 parent 37c6749 commit e9ea262

File tree

2 files changed

+149
-99
lines changed

2 files changed

+149
-99
lines changed

src/gui/widget_paint.c

+91-44
Original file line numberDiff line numberDiff line change
@@ -182,69 +182,116 @@ void RectToInvalidArea(const LCUI_Rect *rect, LCUI_Rect *area)
182182
LCUIMetrics_ComputeRectActual(area, &rectf);
183183
}
184184

185-
LCUI_BOOL Widget_InvalidateArea(LCUI_Widget widget, LCUI_RectF *in_rect,
185+
LCUI_BOOL Widget_InvalidateArea(LCUI_Widget w, LCUI_RectF *in_rect,
186186
int box_type)
187187
{
188-
int mode;
189188
LCUI_RectF rect;
190-
LCUI_Rect *actual_rect;
191-
LCUI_Widget w = widget;
192-
LCUI_Widget root = LCUIWidget_GetRoot();
193-
LCUI_RectGroup group;
194189

195190
if (!w) {
196-
w = root;
191+
w = LCUIWidget_GetRoot();
192+
}
193+
if (!w->computed_style.visible ||
194+
w->invalid_area_type > LCUI_INVALID_AREA_TYPE_CUSTOM) {
195+
return FALSE;
197196
}
198-
mode = LCUIDisplay_GetMode();
199197
Widget_AdjustArea(w, in_rect, &rect, box_type);
200198
rect.x += w->box.canvas.x;
201199
rect.y += w->box.canvas.y;
202-
while (w && w->parent) {
203-
LCUIRectF_ValidateArea(&rect, w->parent->box.padding.width,
204-
w->parent->box.padding.height);
205-
if (rect.width <= 0 || rect.height <= 0) {
206-
return FALSE;
207-
}
208-
if (mode != LCUI_DMODE_SEAMLESS && w->parent == root) {
209-
break;
210-
}
211-
w = w->parent;
212-
rect.x += w->box.padding.x;
213-
rect.y += w->box.padding.y;
200+
if (w->invalid_area_type == LCUI_INVALID_AREA_TYPE_CUSTOM) {
201+
LCUIRectF_MergeRect(&w->invalid_area, &rect, &w->invalid_area);
202+
} else {
203+
w->invalid_area = rect;
214204
}
215-
LCUIRectF_ValidateArea(&rect, MAX_VISIBLE_WIDTH, MAX_VISIBLE_HEIGHT);
216-
if (rect.width <= 0 || rect.height <= 0) {
217-
return FALSE;
205+
w->invalid_area_type = LCUI_INVALID_AREA_TYPE_CUSTOM;
206+
while (w->parent) {
207+
w->parent->has_child_invalid_area = TRUE;
208+
w = w->parent;
218209
}
219-
actual_rect = malloc(sizeof(LCUI_Rect));
220-
RectFToInvalidArea(&rect, actual_rect);
221-
if (mode != LCUI_DMODE_SEAMLESS) {
222-
LinkedList_Append(&self.rects, actual_rect);
223-
return TRUE;
210+
return TRUE;
211+
}
212+
213+
#define AddInvalidArea() \
214+
do { \
215+
rect.x += x; \
216+
rect.y += y; \
217+
LCUIRectF_GetOverlayRect(&rect, &visible_area, &rect); \
218+
if (rect.width > 0 && rect.height > 0) { \
219+
actual_rect = malloc(sizeof(LCUI_Rect)); \
220+
RectFToInvalidArea(&rect, actual_rect); \
221+
LinkedList_Append(rects, actual_rect); \
222+
} \
223+
} while (0)
224+
225+
static void Widget_CollectInvalidArea(LCUI_Widget w, LinkedList *rects, float x,
226+
float y, LCUI_RectF visible_area)
227+
{
228+
LCUI_RectF rect;
229+
LCUI_Rect *actual_rect;
230+
LinkedListNode *node;
231+
232+
if (w->parent && w->parent->invalid_area_type >=
233+
LCUI_INVALID_AREA_TYPE_PADDING_BOX) {
234+
w->invalid_area_type = LCUI_INVALID_AREA_TYPE_CANVAS_BOX;
235+
} else if (w->invalid_area_type >= LCUI_INVALID_AREA_TYPE_PADDING_BOX) {
236+
switch (w->invalid_area_type) {
237+
case LCUI_INVALID_AREA_TYPE_PADDING_BOX:
238+
rect = w->box.padding;
239+
break;
240+
case LCUI_INVALID_AREA_TYPE_BORDER_BOX:
241+
rect = w->box.border;
242+
break;
243+
default:
244+
rect = w->box.canvas;
245+
break;
246+
}
247+
if (!LCUIRectF_IsCoverRect(&rect, &w->invalid_area)) {
248+
AddInvalidArea();
249+
rect = w->invalid_area;
250+
AddInvalidArea();
251+
} else {
252+
LCUIRectF_MergeRect(&rect, &rect, &w->invalid_area);
253+
AddInvalidArea();
254+
}
255+
} else if (w->invalid_area_type == LCUI_INVALID_AREA_TYPE_CUSTOM) {
256+
rect = w->invalid_area;
257+
AddInvalidArea();
224258
}
225-
group = RBTree_CustomGetData(&self.groups, w);
226-
if (!group) {
227-
group = NEW(LCUI_RectGroupRec, 1);
228-
group->widget = w;
229-
LinkedList_Init(&group->rects);
230-
RBTree_CustomInsert(&self.groups, w, group);
259+
if (w->has_child_invalid_area) {
260+
visible_area.x -= x;
261+
visible_area.y -= y;
262+
LCUIRectF_GetOverlayRect(&visible_area, &w->box.padding,
263+
&visible_area);
264+
visible_area.x += x;
265+
visible_area.y += y;
266+
for (LinkedList_Each(node, &w->children_show)) {
267+
Widget_CollectInvalidArea(
268+
node->data, rects, x + w->box.padding.x,
269+
y + w->box.padding.y, visible_area);
270+
}
231271
}
232-
return LinkedList_Append(&group->rects, actual_rect) == 0;
272+
w->invalid_area_type = LCUI_INVALID_AREA_TYPE_NONE;
273+
w->has_child_invalid_area = FALSE;
233274
}
234275

235276
size_t Widget_GetInvalidArea(LCUI_Widget w, LinkedList *rects)
236277
{
237-
LCUI_RectGroup group;
278+
LCUI_Rect *rect;
279+
LinkedListNode *node;
238280

239-
if (!w || w == LCUIWidget_GetRoot()) {
240-
LinkedList_Concat(rects, &self.rects);
241-
return (size_t)rects->length;
242-
}
243-
group = RBTree_CustomGetData(&self.groups, w);
244-
if (group) {
245-
LinkedList_Concat(rects, &group->rects);
281+
float scale = LCUIMetrics_GetScale();
282+
int x = iround(w->box.padding.x * scale);
283+
int y = iround(w->box.padding.y * scale);
284+
285+
Widget_CollectInvalidArea(w, rects, 0, 0, w->box.padding);
286+
DEBUG_MSG("rects: %lu\n", rects->length);
287+
for (LinkedList_Each(node, rects)) {
288+
rect = node->data;
289+
rect->x -= x;
290+
rect->y -= y;
291+
_DEBUG_MSG("(%d, %d, %d, %d)\n", rect->x, rect->y, rect->width,
292+
rect->height);
246293
}
247-
return (size_t)rects->length;
294+
return rects->length;
248295
}
249296

250297
static int OnCompareGroup(void *data, const void *keydata)

0 commit comments

Comments
 (0)