2929
3030#include "config.h"
3131
32- #include <time.h>
33- #include <stdio.h>
34- #include <stdlib.h>
3532#ifdef USE_OPENMP
3633#include <omp.h>
3734#endif
35+ #include <time.h>
36+ #include <stdio.h>
37+ #include <stdlib.h>
38+ #include <string.h>
3839#include <LCUI_Build.h>
3940#include <LCUI/LCUI.h>
4041#include <LCUI/input.h>
6263#define PARALLEL_RENDERING_THREADS 1
6364#endif
6465
66+ #define FLASH_DURATION 1000.0
67+
68+ typedef struct FlashRectRec_ {
69+ int64_t paint_time ;
70+ LCUI_Rect rect ;
71+ } FlashRectRec , * FlashRect ;
72+
6573typedef struct SurfaceRecordRec_ {
66- /**< whether new content has been rendered */
74+ /** whether new content has been rendered */
6775 LCUI_BOOL rendered ;
6876
6977 /** dirty rectangles for rendering */
7078 LinkedList rects ;
7179
80+ /** flashing rect list */
81+ LinkedList flash_rects ;
82+
7283 LCUI_Surface surface ;
7384 LCUI_Widget widget ;
7485} SurfaceRecordRec , * SurfaceRecord ;
@@ -88,29 +99,102 @@ static struct LCUI_DisplayModule {
8899#define LCUIDisplay_CleanSurfaces () \
89100 LinkedList_Clear(&display.surfaces, OnDestroySurfaceRecord)
90101
102+ INLINE int is_rect_equals (const LCUI_Rect * a , const LCUI_Rect * b )
103+ {
104+ return a -> x == b -> x && a -> y == b -> y && a -> width == b -> width &&
105+ a -> height == b -> height ;
106+ }
107+
91108static void OnDestroySurfaceRecord (void * data )
92109{
93110 SurfaceRecord record = data ;
111+
94112 Surface_Close (record -> surface );
95113 LinkedList_Clear (& record -> rects , free );
114+ LinkedList_Clear (& record -> flash_rects , free );
96115 free (record );
97116}
98117
99- static void DrawBorder (LCUI_PaintContext paint )
118+ static void DrawBorder (LCUI_Graph * mask )
100119{
101120 LCUI_Pos pos ;
102121 LCUI_Color color ;
103- int end_x = paint -> rect . width - 1 ;
104- int end_y = paint -> rect . height - 1 ;
122+ int end_x = mask -> width - 1 ;
123+ int end_y = mask -> height - 1 ;
105124 pos .x = pos .y = 0 ;
106- color = RGB (255 , 0 , 0 );
107- Graph_DrawHorizLine (& paint -> canvas , color , 1 , pos , end_x );
108- Graph_DrawVertiLine (& paint -> canvas , color , 1 , pos , end_y );
109- pos .x = paint -> rect . width - 1 ;
110- Graph_DrawVertiLine (& paint -> canvas , color , 1 , pos , end_y );
125+ color = RGB (124 , 179 , 5 );
126+ Graph_DrawHorizLine (mask , color , 1 , pos , end_x );
127+ Graph_DrawVertiLine (mask , color , 1 , pos , end_y );
128+ pos .x = mask -> width - 1 ;
129+ Graph_DrawVertiLine (mask , color , 1 , pos , end_y );
111130 pos .x = 0 ;
112- pos .y = paint -> rect .height - 1 ;
113- Graph_DrawHorizLine (& paint -> canvas , color , 1 , pos , end_x );
131+ pos .y = mask -> height - 1 ;
132+ Graph_DrawHorizLine (mask , color , 1 , pos , end_x );
133+ }
134+
135+ static size_t LCUIDisplay_UpdateFlashRects (SurfaceRecord record )
136+ {
137+ int64_t period ;
138+ size_t count = 0 ;
139+ LCUI_Graph mask ;
140+ LCUI_PaintContext paint ;
141+ FlashRect flash_rect ;
142+ LinkedListNode * node , * prev ;
143+
144+ for (LinkedList_Each (node , & record -> flash_rects )) {
145+ flash_rect = node -> data ;
146+ if (flash_rect -> paint_time == 0 ) {
147+ prev = node -> prev ;
148+ free (node -> data );
149+ LinkedList_DeleteNode (& record -> flash_rects , node );
150+ node = prev ;
151+ continue ;
152+ }
153+ period = LCUI_GetTimeDelta (flash_rect -> paint_time );
154+ if (period >= FLASH_DURATION ) {
155+ flash_rect -> paint_time = 0 ;
156+ } else {
157+ Graph_Init (& mask );
158+ mask .color_type = LCUI_COLOR_TYPE_ARGB ;
159+ Graph_Create (& mask , flash_rect -> rect .width ,
160+ flash_rect -> rect .height );
161+ Graph_FillRect (& mask , ARGB (125 , 124 , 179 , 5 ), NULL , TRUE);
162+ mask .opacity =
163+ 0.6 * (FLASH_DURATION - (float )period ) / FLASH_DURATION ;
164+ }
165+ paint = Surface_BeginPaint (record -> surface , & flash_rect -> rect );
166+ if (!paint ) {
167+ continue ;
168+ }
169+ count += Widget_Render (record -> widget , paint );
170+ if (flash_rect -> paint_time != 0 ) {
171+ DrawBorder (& mask );
172+ Graph_Mix (& paint -> canvas , & mask , 0 , 0 , TRUE);
173+ Graph_Free (& mask );
174+ }
175+ Surface_EndPaint (record -> surface , paint );
176+ record -> rendered = TRUE;
177+ }
178+ return count ;
179+ }
180+
181+ static void LCUIDisplay_AppendFlashRects (SurfaceRecord record , LCUI_Rect * rect )
182+ {
183+ LinkedListNode * node ;
184+ FlashRect flash_rect ;
185+
186+ for (LinkedList_Each (node , & record -> flash_rects )) {
187+ flash_rect = node -> data ;
188+ if (is_rect_equals (& flash_rect -> rect , rect )) {
189+ flash_rect -> paint_time = LCUI_GetTime ();
190+ return ;
191+ }
192+ }
193+
194+ flash_rect = NEW (FlashRectRec , 1 );
195+ flash_rect -> rect = * rect ;
196+ flash_rect -> paint_time = LCUI_GetTime ();
197+ LinkedList_Append (& record -> flash_rects , flash_rect );
114198}
115199
116200static void SurfaceRecord_DumpRects (SurfaceRecord record , LinkedList * rects )
@@ -227,13 +311,8 @@ static size_t LCUIDisplay_RenderSurface(SurfaceRecord record)
227311 DEBUG_MSG ("rect: (%d,%d,%d,%d)\n" , paint -> rect .x , paint -> rect .y ,
228312 paint -> rect .width , paint -> rect .height );
229313 count += Widget_Render (record -> widget , paint );
230- /**
231- * FIXME: Improve highlighting of repainted areas
232- * Let the highlighted areas disappear after a short
233- * period of time, just like flashing
234- */
235314 if (display .show_rect_border ) {
236- DrawBorder ( paint );
315+ LCUIDisplay_AppendFlashRects ( record , & paint -> rect );
237316 }
238317 if (display .mode != LCUI_DMODE_SEAMLESS ) {
239318 LCUICursor_Paint (paint );
@@ -242,6 +321,7 @@ static size_t LCUIDisplay_RenderSurface(SurfaceRecord record)
242321 }
243322 RectList_Clear (& rects );
244323 record -> rendered = count > 0 ;
324+ count += LCUIDisplay_UpdateFlashRects (record );
245325 return count ;
246326}
247327
@@ -260,7 +340,6 @@ void LCUIDisplay_Update(void)
260340 if (record -> widget && surface && Surface_IsReady (surface )) {
261341 Surface_Update (surface );
262342 }
263- /* 收集无效区域记录 */
264343 Widget_GetInvalidArea (record -> widget , & record -> rects );
265344 }
266345 if (display .mode == LCUI_DMODE_SEAMLESS || !record ) {
@@ -387,6 +466,7 @@ static void LCUIDisplay_BindSurface(LCUI_Widget widget)
387466 record -> surface = Surface_New ();
388467 record -> widget = widget ;
389468 record -> rendered = FALSE;
469+ LinkedList_Init (& record -> flash_rects );
390470 LCUIMetrics_ComputeRectActual (& rect , & widget -> box .canvas );
391471 if (Widget_CheckStyleValid (widget , key_top ) &&
392472 Widget_CheckStyleValid (widget , key_left )) {
0 commit comments