1 | /*␊ |
2 | * egview.c␊ |
3 | * Image View handling functions (extension for libeg)␊ |
4 | *␊ |
5 | * Copyright (c) 2012-2013 Cadet-Petit Armel␊ |
6 | * All rights reserved.␊ |
7 | *␊ |
8 | * Redistribution and use in source and binary forms, with or without␊ |
9 | * modification, are permitted provided that the following conditions are␊ |
10 | * met:␊ |
11 | *␊ |
12 | * * Redistributions of source code must retain the above copyright␊ |
13 | * notice, this list of conditions and the following disclaimer.␊ |
14 | *␊ |
15 | * * Redistributions in binary form must reproduce the above copyright␊ |
16 | * notice, this list of conditions and the following disclaimer in the␊ |
17 | * documentation and/or other materials provided with the␊ |
18 | * distribution.␊ |
19 | *␊ |
20 | * * Neither the name of Cadet-Petit Armel nor the names of the␊ |
21 | * contributors may be used to endorse or promote products derived␊ |
22 | * from this software without specific prior written permission.␊ |
23 | *␊ |
24 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS␊ |
25 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT␊ |
26 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR␊ |
27 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT␊ |
28 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,␊ |
29 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT␊ |
30 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,␊ |
31 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY␊ |
32 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT␊ |
33 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE␊ |
34 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.␊ |
35 | */␊ |
36 | #include <utarray.h>␊ |
37 | #include "libegint.h"␊ |
38 | #include <CException.h>␊ |
39 | #include <sys/time.h>␊ |
40 | ␊ |
41 | STATIC VOID _egViewBufferUpdate(IN OUT EG_VIEW *View)␊ |
42 | {␊ |
43 | EG_IMAGE_VIEW *p = NULL;␊ |
44 | ␊ |
45 | ASSERT(View);␊ |
46 | ASSERT(View->CompImage);␊ |
47 | ASSERT(View->CompImage->PixelData);␊ |
48 | ␊ |
49 | memset(View->CompImage->PixelData,0,View->CompImage->Width*View->CompImage->Height*sizeof(EG_PIXEL));␊ |
50 | ␊ |
51 | if (View->Background) {␊ |
52 | ␊ |
53 | if (View->useBackgroundColor == TRUE)␊ |
54 | {␊ |
55 | ASSERT(View->Background->PixelData);␊ |
56 | egFillImage(View->CompImage,␊ |
57 | ␊ |
58 | (EG_PIXEL*)&View->Background->PixelData[0]);␊ |
59 | }␊ |
60 | else␊ |
61 | egComposeImage(View->CompImage, View->Background, 0, 0);␊ |
62 | ␊ |
63 | }␊ |
64 | ␊ |
65 | if (View->Array) {␊ |
66 | while( (p=(EG_IMAGE_VIEW*)utarray_next(View->Array,p))) {␊ |
67 | if (p->Image)␊ |
68 | {␊ |
69 | if (p->Name)␊ |
70 | {␊ |
71 | egFlipRB(p->Image);␊ |
72 | egComposeImage(View->CompImage, p->Image, p->PosX, p->PosY);␊ |
73 | ␊ |
74 | }␊ |
75 | ␊ |
76 | }␊ |
77 | }␊ |
78 | }␊ |
79 | ␊ |
80 | View->isDirty = FALSE;␊ |
81 | ␊ |
82 | }␊ |
83 | ␊ |
84 | static long long␊ |
85 | timeval_diff(struct timeval *difference,␊ |
86 | struct timeval *end_time,␊ |
87 | struct timeval *start_time␊ |
88 | )␊ |
89 | {␊ |
90 | struct timeval temp_diff;␊ |
91 | ␊ |
92 | if(difference==NULL)␊ |
93 | {␊ |
94 | difference=&temp_diff;␊ |
95 | }␊ |
96 | ␊ |
97 | difference->tv_sec =end_time->tv_sec -start_time->tv_sec ;␊ |
98 | difference->tv_usec=end_time->tv_usec-start_time->tv_usec;␊ |
99 | ␊ |
100 | /* Using while instead of if below makes the code slightly more robust. */␊ |
101 | ␊ |
102 | while(difference->tv_usec<0)␊ |
103 | {␊ |
104 | difference->tv_usec+=1000000;␊ |
105 | difference->tv_sec -=1;␊ |
106 | }␊ |
107 | ␊ |
108 | return 1000000LL*difference->tv_sec+␊ |
109 | difference->tv_usec;␊ |
110 | ␊ |
111 | } ␊ |
112 | ␊ |
113 | VOID egViewBufferUpdate(IN OUT EG_VIEW *View)␊ |
114 | {␊ |
115 | CEXCEPTION_T e = CEXCEPTION_NONE;␊ |
116 | ␊ |
117 | static struct timeval earlier;␊ |
118 | static struct timeval later;␊ |
119 | static BOOLEAN use_earlier = TRUE;␊ |
120 | static BOOLEAN use_later = FALSE;␊ |
121 | static long long diff = 0;␊ |
122 | int h = 16666;␊ |
123 | ␊ |
124 | Try␊ |
125 | {␊ |
126 | ASSERT(View);␊ |
127 | ASSERT(View->CompImage); ␊ |
128 | ␊ |
129 | if (use_earlier == TRUE && use_later == FALSE)␊ |
130 | {␊ |
131 | memset(&earlier,0,sizeof(struct timeval));␊ |
132 | ␊ |
133 | if(gettimeofday(&earlier,NULL) != 0)␊ |
134 | {␊ |
135 | ␊ |
136 | ASSERT(FALSE);␊ |
137 | }␊ |
138 | use_later = TRUE;␊ |
139 | use_earlier = FALSE;␊ |
140 | ␊ |
141 | }␊ |
142 | else if(use_earlier == FALSE && use_later == TRUE)␊ |
143 | {␊ |
144 | ␊ |
145 | memset(&later,0,sizeof(struct timeval));␊ |
146 | ␊ |
147 | if(gettimeofday(&later,NULL) != 0)␊ |
148 | {␊ |
149 | ␊ |
150 | ASSERT(FALSE);␊ |
151 | }␊ |
152 | use_earlier = TRUE; ␊ |
153 | use_later = FALSE;␊ |
154 | }␊ |
155 | else␊ |
156 | {␊ |
157 | memset(&later,0,sizeof(struct timeval));␊ |
158 | memset(&earlier,0,sizeof(struct timeval)); ␊ |
159 | }␊ |
160 | ␊ |
161 | diff = timeval_diff(NULL,&later,&earlier);␊ |
162 | ␊ |
163 | if (diff != 0) {␊ |
164 | ␊ |
165 | ␊ |
166 | if (diff >= h || diff <= 0-h) {␊ |
167 | _egViewBufferUpdate(View);␊ |
168 | }␊ |
169 | else␊ |
170 | {␊ |
171 | if (diff > 0) {␊ |
172 | diff = h - diff ;␊ |
173 | }␊ |
174 | else␊ |
175 | {␊ |
176 | diff = h + diff ;␊ |
177 | }␊ |
178 | delay(diff);␊ |
179 | _egViewBufferUpdate(View);␊ |
180 | ␊ |
181 | } ␊ |
182 | }␊ |
183 | ␊ |
184 | ␊ |
185 | }␊ |
186 | Catch(e)␊ |
187 | {␊ |
188 | } ␊ |
189 | }␊ |
190 | ␊ |
191 | VOID egViewUpdate(IN OUT EG_VIEW *View)␊ |
192 | {␊ |
193 | if (View != NULL) {␊ |
194 | ␊ |
195 | if (View->isDirty == TRUE)␊ |
196 | {␊ |
197 | egViewBufferUpdate(View);␊ |
198 | ␊ |
199 | //if (!egHasGraphicsMode())␊ |
200 | // return;␊ |
201 | ␊ |
202 | ASSERT(View->CompImage);␊ |
203 | ASSERT(View->CompImage->PixelData);␊ |
204 | ␊ |
205 | if (View->isDirty == FALSE)␊ |
206 | egVramWrite ( View->CompImage->PixelData, View->CompImage->Width, View->CompImage->Height, 0 , 0, sizeof(EG_PIXEL) );␊ |
207 | }␊ |
208 | ␊ |
209 | }␊ |
210 | }␊ |
211 | ␊ |
212 | VOID egViewSetUpdateValue(IN OUT EG_VIEW *View, IN BOOLEAN AutoUpdate)␊ |
213 | {␊ |
214 | if (View != NULL) {␊ |
215 | ␊ |
216 | View->AutoUpdate = AutoUpdate;␊ |
217 | }␊ |
218 | }␊ |
219 | ␊ |
220 | BOOLEAN egViewGetUpdateValue(IN OUT EG_VIEW *View)␊ |
221 | {␊ |
222 | if (View != NULL) {␊ |
223 | ␊ |
224 | return View->AutoUpdate;␊ |
225 | ␊ |
226 | } ␊ |
227 | return FALSE; // we return false if the view is null␊ |
228 | ␊ |
229 | }␊ |
230 | ␊ |
231 | VOID egViewSetDirtyValue(IN OUT EG_VIEW *View, IN BOOLEAN Dirty)␊ |
232 | {␊ |
233 | if (View != NULL) {␊ |
234 | ␊ |
235 | View->isDirty = Dirty;␊ |
236 | }␊ |
237 | }␊ |
238 | ␊ |
239 | BOOLEAN egViewGetDirtyValue(IN OUT EG_VIEW *View)␊ |
240 | {␊ |
241 | if (View != NULL) {␊ |
242 | ␊ |
243 | return View->isDirty;␊ |
244 | ␊ |
245 | }␊ |
246 | return FALSE; // we return false if the view is null␊ |
247 | ␊ |
248 | }␊ |
249 | ␊ |
250 | EG_VIEW * egCreateView(IN UINTN Width, IN UINTN Height, IN BOOLEAN HasAlpha)␊ |
251 | {␊ |
252 | EG_VIEW *NewView = NULL;␊ |
253 | ␉CEXCEPTION_T e = CEXCEPTION_NONE;␊ |
254 | ␊ |
255 | NewView = (EG_VIEW *) AllocateZeroPool(sizeof(EG_VIEW));␊ |
256 | if (NewView == NULL)␊ |
257 | return NULL;␊ |
258 | ␊ |
259 | NewView->CompImage = egCreateImage( Width, Height, HasAlpha);␊ |
260 | if (NewView->CompImage == NULL) {␊ |
261 | FreePool(NewView);␊ |
262 | return NULL;␊ |
263 | }␊ |
264 | ␊ |
265 | ␉NewView->Background = egCreateImage( Width, Height, HasAlpha);␊ |
266 | if (NewView->Background == NULL) {␊ |
267 | ␉␉egFreeImage(NewView->CompImage);␊ |
268 | FreePool(NewView);␊ |
269 | return NULL;␊ |
270 | }␊ |
271 | NewView->useBackgroundColor = TRUE;␊ |
272 | ␊ |
273 | ␉␊ |
274 | ␉Try␊ |
275 | {␊ |
276 | utarray_new(NewView->Array, &image_view_t_icd);␊ |
277 | ␊ |
278 | }␊ |
279 | Catch(e)␊ |
280 | {␊ |
281 | ␉␉if (NewView)␊ |
282 | egFreeView(NewView);␊ |
283 | ␊ |
284 | return NULL;␊ |
285 | }␊ |
286 | ␉NewView->isDirty = FALSE;␊ |
287 | NewView->AutoUpdate = FALSE;␊ |
288 | ␊ |
289 | return NewView;␊ |
290 | }␊ |
291 | ␊ |
292 | VOID egFreeView(IN EG_VIEW *View)␊ |
293 | {␊ |
294 | CEXCEPTION_T e = CEXCEPTION_NONE;␊ |
295 | ␊ |
296 | Try␊ |
297 | {␊ |
298 | ASSERT(View);␊ |
299 | ␊ |
300 | if(View->Array) ␊ |
301 | utarray_free(View->Array);␊ |
302 | ␊ |
303 | if (View->CompImage)␊ |
304 | egFreeImage(View->CompImage);␊ |
305 | ␊ |
306 | if (View->Background)␊ |
307 | egFreeImage(View->Background);␊ |
308 | ␊ |
309 | FreePool (View);␊ |
310 | View = NULL;␊ |
311 | }␊ |
312 | Catch(e)␊ |
313 | {␊ |
314 | } ␊ |
315 | }␊ |
316 | ␊ |
317 | VOID egViewSetBackgroundColor(IN OUT EG_VIEW *CompView, IN EG_PIXEL *Color)␊ |
318 | {␊ |
319 | if (CompView)␊ |
320 | {␊ |
321 | if (CompView->Background && Color)␊ |
322 | {␊ |
323 | if (CompView->Background->PixelData)␊ |
324 | {␊ |
325 | EG_PIXEL *BackgroundColor = (EG_PIXEL*)&CompView->Background->PixelData[0];␊ |
326 | ASSERT(BackgroundColor);␊ |
327 | BackgroundColor->r = Color->r;␊ |
328 | BackgroundColor->g = Color->g;␊ |
329 | BackgroundColor->b = Color->b;␊ |
330 | BackgroundColor->a = Color->a;␊ |
331 | CompView->useBackgroundColor = TRUE;␊ |
332 | CompView->isDirty = TRUE;␊ |
333 | if (CompView->AutoUpdate) {␊ |
334 | egViewUpdate(CompView);␊ |
335 | }␊ |
336 | }␊ |
337 | ␊ |
338 | }␊ |
339 | }␊ |
340 | }␊ |
341 | ␊ |
342 | VOID egUseBackgroundColor(IN OUT EG_VIEW *CompView, IN BOOLEAN Use)␊ |
343 | {␊ |
344 | if (CompView)␊ |
345 | { ␊ |
346 | ␊ |
347 | CompView->useBackgroundColor = Use;␊ |
348 | ␊ |
349 | }␊ |
350 | }␊ |
351 | ␊ |
352 | EG_PIXEL * egViewGetBackgroundColor(IN OUT EG_VIEW *CompView)␊ |
353 | {␊ |
354 | EG_PIXEL * Color = NULL ;␊ |
355 | ␊ |
356 | ␊ |
357 | if (CompView->useBackgroundColor == TRUE)␊ |
358 | { ␊ |
359 | if (CompView)␊ |
360 | {␊ |
361 | if (CompView->Background)␊ |
362 | {␊ |
363 | if (CompView->Background->PixelData) {␊ |
364 | Color = (EG_PIXEL*)AllocateZeroPool(sizeof(EG_PIXEL)) ;␊ |
365 | ASSERT(Color);␊ |
366 | ␊ |
367 | Color->r = CompView->Background->PixelData[0].r ;␊ |
368 | Color->g = CompView->Background->PixelData[0].g ;␊ |
369 | Color->b = CompView->Background->PixelData[0].b ;␊ |
370 | Color->a = CompView->Background->PixelData[0].a ;␊ |
371 | }␊ |
372 | }␊ |
373 | }␊ |
374 | }␊ |
375 | ␊ |
376 | ␊ |
377 | return Color;␊ |
378 | }␊ |
379 | ␊ |
380 | VOID egViewSetBackground(IN OUT EG_VIEW *CompView, IN EG_IMAGE *Background)␊ |
381 | {␊ |
382 | if (CompView)␊ |
383 | {␊ |
384 | if (CompView->Background && Background)␊ |
385 | {␊ |
386 | egCopyImage(CompView->Background, Background);␊ |
387 | CompView->isDirty = TRUE;␊ |
388 | CompView->useBackgroundColor = FALSE;␊ |
389 | ␊ |
390 | if (CompView->AutoUpdate) {␊ |
391 | egViewUpdate(CompView);␊ |
392 | }␊ |
393 | }␊ |
394 | }␊ |
395 | }␊ |
396 | ␊ |
397 | EG_IMAGE_VIEW *egViewAddImageView(IN OUT EG_VIEW *CompView, IN EG_IMAGE_VIEW *TopView)␊ |
398 | {␊ |
399 | CEXCEPTION_T e = CEXCEPTION_NONE;␊ |
400 | EG_IMAGE_VIEW *NewImageView = NULL;␊ |
401 | Try␊ |
402 | {␊ |
403 | ASSERT(CompView);␊ |
404 | ASSERT(CompView->Array);␊ |
405 | ASSERT(TopView);␊ |
406 | ␊ |
407 | utarray_push_back(CompView->Array, TopView);␊ |
408 | NewImageView = (EG_IMAGE_VIEW *)utarray_back(CompView->Array);␊ |
409 | ASSERT(NewImageView);␊ |
410 | ␊ |
411 | CompView->isDirty = TRUE;␊ |
412 | if (CompView->AutoUpdate) {␊ |
413 | egViewUpdate(CompView);␊ |
414 | }␊ |
415 | ␊ |
416 | }␊ |
417 | Catch(e)␊ |
418 | {␊ |
419 | }␊ |
420 | ␊ |
421 | return NewImageView;␊ |
422 | ␊ |
423 | }␊ |
424 | ␊ |
425 | VOID egViewRemoveImageView(IN OUT EG_VIEW *CompView, IN EG_IMAGE_VIEW *ImageView)␊ |
426 | {␊ |
427 | CEXCEPTION_T e = CEXCEPTION_NONE;␊ |
428 | Try␊ |
429 | {␊ |
430 | ASSERT(CompView);␊ |
431 | ASSERT(CompView->Array);␊ |
432 | ASSERT(ImageView);␊ |
433 | ␊ |
434 | UINTN Index = utarray_eltidx(CompView->Array,ImageView);␊ |
435 | utarray_erase(CompView->Array,Index,1);␊ |
436 | CompView->isDirty = TRUE;␊ |
437 | ␊ |
438 | if (CompView->AutoUpdate) {␊ |
439 | egViewUpdate(CompView);␊ |
440 | }␊ |
441 | ␊ |
442 | }␊ |
443 | Catch(e)␊ |
444 | {␊ |
445 | }␊ |
446 | }␊ |
447 | ␊ |
448 | VOID egViewRemoveImageViewByName(IN OUT EG_VIEW *CompView, IN CHAR16 *Name, IN UINTN NameSize)␊ |
449 | {␊ |
450 | CEXCEPTION_T e = CEXCEPTION_NONE;␊ |
451 | ␉EG_IMAGE_VIEW *p = NULL;␊ |
452 | Try␊ |
453 | {␊ |
454 | ASSERT(CompView);␊ |
455 | ASSERT(CompView->Array);␊ |
456 | ASSERT(Name);␊ |
457 | ASSERT((NameSize > 0));␊ |
458 | ␊ |
459 | while( (p=(EG_IMAGE_VIEW*)utarray_next(CompView->Array,p))) {␊ |
460 | if (p->Image)␊ |
461 | {␊ |
462 | if (p->Name)␊ |
463 | {␊ |
464 | if (StrnCmp(p->Name, Name, NameSize) == 0)␊ |
465 | {␊ |
466 | UINTN Index = utarray_eltidx(CompView->Array,p);␊ |
467 | utarray_erase(CompView->Array,Index,1);␊ |
468 | CompView->isDirty = TRUE;␊ |
469 | break;␊ |
470 | ␊ |
471 | }␊ |
472 | }␊ |
473 | ␊ |
474 | }␊ |
475 | }␊ |
476 | ␊ |
477 | if (CompView->AutoUpdate) {␊ |
478 | egViewUpdate(CompView);␊ |
479 | }␊ |
480 | ␊ |
481 | }␊ |
482 | Catch(e)␊ |
483 | {␊ |
484 | } ␊ |
485 | }␊ |
486 | |