29
29
30
30
#include "config.h"
31
31
32
- #include <time.h>
33
- #include <stdio.h>
34
- #include <stdlib.h>
35
32
#ifdef USE_OPENMP
36
33
#include <omp.h>
37
34
#endif
35
+ #include <time.h>
36
+ #include <stdio.h>
37
+ #include <stdlib.h>
38
+ #include <string.h>
38
39
#include <LCUI_Build.h>
39
40
#include <LCUI/LCUI.h>
40
41
#include <LCUI/input.h>
62
63
#define PARALLEL_RENDERING_THREADS 1
63
64
#endif
64
65
66
+ #define FLASH_DURATION 1000.0
67
+
68
+ typedef struct FlashRectRec_ {
69
+ int64_t paint_time ;
70
+ LCUI_Rect rect ;
71
+ } FlashRectRec , * FlashRect ;
72
+
65
73
typedef struct SurfaceRecordRec_ {
66
- /**< whether new content has been rendered */
74
+ /** whether new content has been rendered */
67
75
LCUI_BOOL rendered ;
68
76
69
77
/** dirty rectangles for rendering */
70
78
LinkedList rects ;
71
79
80
+ /** flashing rect list */
81
+ LinkedList flash_rects ;
82
+
72
83
LCUI_Surface surface ;
73
84
LCUI_Widget widget ;
74
85
} SurfaceRecordRec , * SurfaceRecord ;
@@ -88,29 +99,102 @@ static struct LCUI_DisplayModule {
88
99
#define LCUIDisplay_CleanSurfaces () \
89
100
LinkedList_Clear(&display.surfaces, OnDestroySurfaceRecord)
90
101
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
+
91
108
static void OnDestroySurfaceRecord (void * data )
92
109
{
93
110
SurfaceRecord record = data ;
111
+
94
112
Surface_Close (record -> surface );
95
113
LinkedList_Clear (& record -> rects , free );
114
+ LinkedList_Clear (& record -> flash_rects , free );
96
115
free (record );
97
116
}
98
117
99
- static void DrawBorder (LCUI_PaintContext paint )
118
+ static void DrawBorder (LCUI_Graph * mask )
100
119
{
101
120
LCUI_Pos pos ;
102
121
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 ;
105
124
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 );
111
130
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 );
114
198
}
115
199
116
200
static void SurfaceRecord_DumpRects (SurfaceRecord record , LinkedList * rects )
@@ -227,13 +311,8 @@ static size_t LCUIDisplay_RenderSurface(SurfaceRecord record)
227
311
DEBUG_MSG ("rect: (%d,%d,%d,%d)\n" , paint -> rect .x , paint -> rect .y ,
228
312
paint -> rect .width , paint -> rect .height );
229
313
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
- */
235
314
if (display .show_rect_border ) {
236
- DrawBorder ( paint );
315
+ LCUIDisplay_AppendFlashRects ( record , & paint -> rect );
237
316
}
238
317
if (display .mode != LCUI_DMODE_SEAMLESS ) {
239
318
LCUICursor_Paint (paint );
@@ -242,6 +321,7 @@ static size_t LCUIDisplay_RenderSurface(SurfaceRecord record)
242
321
}
243
322
RectList_Clear (& rects );
244
323
record -> rendered = count > 0 ;
324
+ count += LCUIDisplay_UpdateFlashRects (record );
245
325
return count ;
246
326
}
247
327
@@ -260,7 +340,6 @@ void LCUIDisplay_Update(void)
260
340
if (record -> widget && surface && Surface_IsReady (surface )) {
261
341
Surface_Update (surface );
262
342
}
263
- /* 收集无效区域记录 */
264
343
Widget_GetInvalidArea (record -> widget , & record -> rects );
265
344
}
266
345
if (display .mode == LCUI_DMODE_SEAMLESS || !record ) {
@@ -387,6 +466,7 @@ static void LCUIDisplay_BindSurface(LCUI_Widget widget)
387
466
record -> surface = Surface_New ();
388
467
record -> widget = widget ;
389
468
record -> rendered = FALSE;
469
+ LinkedList_Init (& record -> flash_rects );
390
470
LCUIMetrics_ComputeRectActual (& rect , & widget -> box .canvas );
391
471
if (Widget_CheckStyleValid (widget , key_top ) &&
392
472
Widget_CheckStyleValid (widget , key_left )) {
0 commit comments