comparison src/cs/drivers/drv_app/r2d/r2d.c @ 0:b6a5e36de839

src/cs: initial import from Magnetite
author Mychaela Falconia <falcon@freecalypso.org>
date Sun, 15 Jul 2018 04:39:26 +0000
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:b6a5e36de839
1 /**
2
3 @file r2d.c
4
5 @author Christophe Favergeon
6
7 @version 0.5
8
9 Function Riviera 2D system implementation
10 (higher software layer)
11
12 */
13
14 /*
15 Date Modification
16 ------------------------
17 06/12/2001 Create
18 10/18/2001 Version 0.5 for first integration with Riviera database
19 **************************************************************************
20 History
21
22 Apr-06-2005 MMI-SPR-29655 - xreddymn
23 Added function r2d_flush_region to allow flushing of portions
24 of framebuffer to the display
25
26 */
27
28
29 #include "rv/general.h"
30 #include "rvf/rvf_api.h"
31 #include "r2d/r2d_config.h"
32 #include "r2d/r2d.h"
33 #include "r2d/r2d_i.h"
34 #include "r2d/r2d_independance_layer.h"
35 #include "r2d/r2d_convertion_table.h"
36 #include "r2d/r2d_env.h"
37 #include "rvm/rvm_use_id_list.h"
38 #include <string.h>
39
40 #include "r2d_cos.c"
41
42
43 #ifdef _WINDOWS
44 #pragma warning(disable:4761) // integral size mismatch in argument; conversion supplied
45 #endif
46
47
48 /***************************************
49
50 IMPORTANT INFORMATION
51
52 ***************************************/
53
54 /*
55
56 Clipping is done on original coordinates.
57 Then those coordinates are modified to take into account a possible
58 mirror symetry of the LCD.
59 Then the scanning algorithm is applied on those transformed and clipped
60 coordinates. It assumes a vertical scanning (column per column).
61 If it is not the case. The high level coordinates (x,y) are swapped
62 after clipping and mirroring. The scanning is done on the swapped coordinates
63 so that coulmns are mapped to lines.
64
65 Subroutine's comment use following rule:
66 H -> High level user coordinates
67 L -> LCD coordinates (mirroring or not and local_to_global applied)
68 S -> Scanning coordinates (vertical or horizontal)
69 */
70
71 /***************************************
72
73 CONSTANTS
74
75 ***************************************/
76
77 // Used for char drawing algorithm with unicode
78 typedef enum K_R2D_CHAR_DRAWING_MODE
79 {
80 R2D_COMBINING_CHAR=1
81 } T_R2D_CHAR_DRAWING_MODE;
82
83 // Used for internal drawing function
84 typedef enum K_R2D_TEXT_DRAWING_SETTINGS
85 {
86 R2D_TEXT_DRAW=1
87 } T_R2D_TEXT_DRAWING_SETTINGS;
88
89
90
91
92
93 /***************************************
94
95 REFRESH TASK RELATED GLOBALS
96
97 ***************************************/
98
99 extern INT16 r2d_update_ul_x,r2d_update_ul_y,r2d_update_br_x,r2d_update_br_y;
100
101 /***************************************
102
103 STATIC INTERNAL FUNCTIONS
104 AND GLOBALS
105
106 ***************************************/
107
108
109 #define IND_r2d_write_lcd_line r2d_write_lcd_line
110 #define IND_r2d_write_lcd_pixel r2d_write_lcd_pixel
111 #define IND_r2d_blit_lcd_to_lcd r2d_blit_lcd_to_lcd
112 #define IND_r2d_blit_lcd_to_color r2d_blit_lcd_to_color
113 #define IND_r2d_blit_color_to_lcd r2d_blit_color_to_lcd
114 #define IND_r2d_blit_color_to_color r2d_blit_color_to_color
115 #define IND_r2d_get_color_pixel_value r2d_get_color_pixel_value
116
117 static T_R2D_GC_PTR r2d_new_font_buffer_context(T_RVF_MB_ID bank,
118 T_R2D_FRAMEBUFFER_KIND kind,
119 UINT16 max_width,
120 UINT16 ascent);
121 static T_R2D_FONT_CACHE_FRAMEBUFFER* r2d_new_font_framebuffer(T_RVF_MB_ID bank,
122 T_R2D_FRAMEBUFFER_KIND the_kind,UINT16 width, UINT16 height);
123 static T_R2D_SHAPE_PTR r2d_s_level(T_R2D_GC_PTR gc,T_R2D_SHAPE_PTR self);
124 static void r2d_mirror_rectangle(T_R2D_GC_PTR gc,T_R2D_SHAPE_PTR rectangle);
125 static void r2d_mirror_clip_rectangle(T_R2D_GC_PTR gc,T_R2D_SHAPE_PTR rectangle);
126 static void r2d_diagonal_mirror(T_R2D_SHAPE_PTR rectangle);
127
128 static void r2d_update_region(T_R2D_GC *gc,INT16 ul_x,INT16 ul_y,INT16 br_x,INT16 br_y);
129
130 void r2d_translate_shape(T_R2D_SHAPE_PTR self,INT16 dx,INT16 dy);
131
132 // Used for pen_size != 1. It computes the bounding rect and calls
133 // fillrectangle
134 static void r2d_s_fill_point(T_R2D_GC_PTR gc,INT16 x,INT16 y,INT16 pen_size);
135
136 static void r2d_df_rectangle(T_R2D_GC_PTR gc,
137 INT16 ul_x,INT16 ul_y,INT16 br_x, INT16 br_y,BOOLEAN background);
138 static void r2d_s_fill_rectangle(T_R2D_GC_PTR gc,
139 INT16 ul_x,INT16 ul_y,INT16 br_x, INT16 br_y,BOOLEAN background);
140
141
142
143 #define R2D_SQUARE_P(x) (x*x)
144 #define R2D_SWAP(x,y) tmp=x; x=y; y=tmp
145 #define SQRT2 0x16A09
146 #define PI 0x3243F
147
148 ////////////////////////////////////////
149 //
150 // Utility functions
151 //
152
153 // L COORDINATES
154 void r2d_update_region(T_R2D_GC* gc,INT16 ul_x,INT16 ul_y,INT16 br_x,INT16 br_y)
155 {
156
157 INT16 tmp;
158
159 rvf_lock_mutex(r2d_g_global_mutex);
160
161 if (ul_x>br_x)
162 {
163 tmp=ul_x;
164 ul_x=br_x;
165 br_x=tmp;
166 }
167
168 if (ul_y>br_y)
169 {
170 tmp=ul_y;
171 ul_y=br_y;
172 br_y=tmp;
173 }
174
175 if (gc)
176 {
177 if (ul_x<((T_R2D_RECT*)(gc->p_clipping_shape))->ul_x-gc->org_x)
178 ul_x=((T_R2D_RECT*)(gc->p_clipping_shape))->ul_x-gc->org_x;
179 if (ul_y<((T_R2D_RECT*)(gc->p_clipping_shape))->ul_y-gc->org_y)
180 ul_y=((T_R2D_RECT*)(gc->p_clipping_shape))->ul_y-gc->org_y;
181 if (br_x>=((T_R2D_RECT*)(gc->p_clipping_shape))->br_x-1-gc->org_x)
182 br_x=((T_R2D_RECT*)(gc->p_clipping_shape))->br_x-1-gc->org_x;
183 if (br_y>=((T_R2D_RECT*)(gc->p_clipping_shape))->br_y-1-gc->org_y)
184 br_y=((T_R2D_RECT*)(gc->p_clipping_shape))->br_y-1-gc->org_y;
185 }
186
187 if (ul_x < r2d_update_ul_x)
188 r2d_update_ul_x=ul_x;
189 if (ul_y < r2d_update_ul_y)
190 r2d_update_ul_y=ul_y;
191 if (br_x > r2d_update_br_x)
192 r2d_update_br_x=br_x;
193 if (br_y > r2d_update_br_y)
194 r2d_update_br_y=br_y;
195
196
197 if (r2d_update_ul_x<0)
198 r2d_update_ul_x=0;
199 if (r2d_update_ul_y<0)
200 r2d_update_ul_y=0;
201 if (r2d_update_br_x>=R2D_WIDTH)
202 r2d_update_br_x=R2D_WIDTH-1;
203 if (r2d_update_br_y>=R2D_HEIGHT)
204 r2d_update_br_y=R2D_HEIGHT-1;
205
206
207 rvf_unlock_mutex(r2d_g_global_mutex);
208 }
209
210
211 void r2d_check_and_send_event(T_R2D_GC_PTR gc)
212 {
213 // If routine has drawn into the LCD framebuffer
214 // then refresh may be required
215 // If LCD framebuffer ONLY
216 if (((T_R2D_FRAMEBUFFER*)(((T_R2D_GC*)gc)->p_frame_buffer))->kind==0)
217 {
218 if ((r2d_g_event_was_sent==FALSE) && (r2d_g_refresh_disabled==0))
219 {
220 //rvf_send_trace("R2D SEND EVENT",strlen("R2D SEND EVENT"), NULL_PARAM,
221 //RV_TRACE_LEVEL_DEBUG_HIGH, TRACE_XXX );
222 r2d_g_event_was_sent=TRUE;
223 rvf_send_event( (UINT8)(r2d_addr_id & 0xFF), EVENT_MASK(RVF_APPL_EVT_0) );
224 }
225 }
226 }
227
228 // WILL HAVE TO BE IMPROVED
229
230 INT32 r2d_fixed_division(INT32 a,INT32 b)
231 {
232 INT16 k;
233 UINT32 q,nb;
234 INT16 right_shift=0;
235 INT16 sign=0;
236
237 // Convert to positive values
238 if ((b<0) && (a<0))
239 {
240 b=-b;
241 a=-a;
242 }
243 if ((b<0) && (a>=0))
244 {
245 b=-b;
246 sign=1;
247 }
248 if ((a<0) && (b>=0))
249 {
250 a=-a;
251 sign=1;
252 }
253
254
255 // Normalize b between in [0.5,1[
256
257
258 nb=b;
259
260 if (nb>=0x10000)
261 {
262 //printf("%08X/%08X\n",a,nb);
263 while(((nb>>16)&0x0FFFF)!=0)
264 {
265 nb>>=1;
266 right_shift++;
267 //printf("%08X\n",nb);
268 }
269 } else if (nb<0x8000)
270 {
271 while((nb&0x8000)==0)
272 {
273 nb<<=1;
274 right_shift--;
275 //printf("%08X\n",nb);
276 }
277 }
278 //printf("right_shift=%d\n",right_shift);
279 if (nb==0x8000)
280 {
281 //printf("nb=0x8000, return %08X\n",((a>>right_shift)<<1));
282 if (sign)
283 return (-((a>>right_shift)<<1));
284 else
285 return (((a>>right_shift)<<1));
286 }
287
288
289
290
291 // Newton method used to compute 1/nb with
292 // q=q(2-nb * q)
293
294 // Which first choice for q and which accuracies for intermediate
295 // computations ?
296
297
298 // nb being in ]0.5,1[ one must has q in ]0.5, 3[
299 // And one must check that the function is contracting
300 // Derivative is nul for q*nb = 1. Below, sign of
301 // derivatuve (relatively to q) is positive if a<1 and
302 // the derivative is between 2 and 0
303 // <1 is got for q>1/(2 nb) and q must be < 1/nb
304 // One can take q=1 as starting value. It solves
305 // for the bounds except for nb=1 or nb=0.5
306
307 // if q in ]1/2nb, 1/nb[ one can check that qnew
308 // will at most reach 3/2nb at next iteration and then will
309 // fall back into the intervall
310 // So, one needs to represents values up to 3 for q
311 // and 2 bits are required for integer part
312
313 // So, q is 2.16, nb is 0.16
314 // q*nb is 2.32 which cannot be represented and one needs
315 // to shift value by 1 bit
316 // nb will be 0.15 and q 2.15 sor nb*q is 2.30
317 // It must be multiplied by a format 2.16
318 // so both intermediate result must be shifted to
319 // 2.15 (1 for q and 15 for np*q)
320
321
322
323 q=(1<<16);
324 //printf("-- q=%08X\n",q);
325
326
327 for(k=0;k<5;k++)
328 {
329 q=((q>>1) * ((2 << 15) - (((nb>>1) * (q>>1)) >> 15))) >> 14;
330 //printf("-- q=%08X\n",q);
331 }
332
333 // a is known to be an integer and q is know to be less than 1
334 // so a 64 bits product is not required
335
336 //printf("a=%08X, q=%08X\n",a,q);
337
338 q>>=right_shift;
339
340 q=((a>>16)*q) ;
341
342
343 //printf("right_shift=%d, q=%08X\n",right_shift,q);
344
345 if (sign)
346 return(-((INT32)q));
347 else
348 return(q);
349
350
351 }
352
353 ////////////////////////////////////////
354 //
355 // Texture
356 //
357
358 T_R2D_FREE_TEXTURE_PTR r2d_new_free_texture(T_RVF_MB_ID bank,INT16 size,T_R2D_ARGB_COLOR *pattern)
359 {
360 T_R2D_FREE_TEXTURE *t;
361
362 R2D_MALLOC(bank,T_R2D_FREE_TEXTURE,sizeof(T_R2D_FREE_TEXTURE),t);
363
364 if (t)
365 {
366 t->refcount=1;
367 t->size=size;
368 t->pattern=pattern;
369 }
370
371 return(t);
372 }
373
374 T_R2D_FREE_TEXTURE_PTR r2d_new_const_free_texture(T_RVF_MB_ID bank,INT16 size,T_R2D_ARGB_COLOR *pattern)
375 {
376 T_R2D_FREE_TEXTURE *t;
377
378 R2D_MALLOC(bank,T_R2D_FREE_TEXTURE,sizeof(T_R2D_FREE_TEXTURE),t);
379
380 if (t)
381 {
382 t->refcount=-1;
383 t->size=size;
384 t->pattern=pattern;
385 }
386
387 return(t);
388 }
389
390 void r2d_release_free_texture(T_R2D_FREE_TEXTURE_PTR texture)
391 {
392 if (texture)
393 {
394 // Remove the array of words if needed
395 // (refcount must be 1 else the array should not be deleted)
396 if (R2D_REFCOUNT(texture)==1)
397 {
398 if (((T_R2D_FREE_TEXTURE*)texture)->pattern)
399 R2D_FREE(((T_R2D_FREE_TEXTURE*)texture)->pattern);
400 }
401 }
402 // Autorelease
403 r2d_release(texture);
404 }
405
406 T_R2D_ANCHORED_TEXTURE_PTR r2d_new_anchored_texture(T_RVF_MB_ID bank,T_R2D_GC_PTR gc,T_R2D_FREE_TEXTURE_PTR texture)
407 {
408
409 INT16 length;
410 T_R2D_FREE_TEXTURE *ft;
411 T_R2D_ANCHORED_TEXTURE *at;
412 INT16 i,j,x,y,ni,nj,pos;
413 UINT32 *p;
414
415 T_R2D_ARGB_COLOR b;
416
417 // If a new texture is installed,
418 // one must recompute p_background
419 if (texture==NULL)
420 goto erroranchored;
421
422
423
424 ft=(T_R2D_FREE_TEXTURE *)texture;
425
426 length=1<<(ft->size);
427
428 R2D_MALLOC(bank,T_R2D_ANCHORED_TEXTURE,sizeof(T_R2D_ANCHORED_TEXTURE),at);
429
430 if (at==NULL)
431 goto erroranchored;
432
433 at->refcount=1;
434
435 at->size=ft->size;
436
437 R2D_MALLOC(bank,UINT32,sizeof(UINT32)*length*length,at->pattern);
438
439 if (at->pattern==NULL)
440 {
441 R2D_FREE(at);
442 goto erroranchored;
443 }
444
445
446 p=at->pattern;
447 b=r2d_get_background_color(gc);
448
449 if (((T_R2D_FRAMEBUFFER*)(((T_R2D_GC*)gc)->p_frame_buffer))->kind==R2D_FULL_KIND)
450 {
451 x=0;
452 y=0;
453 for(i=0;i<length;i++) // Horizontal
454 for(j=0;j<length;j++) // Vertical
455 {
456 r2d_convert_background_color_color(gc,ft->pattern[i*length+j]);
457
458 #if (R2D_REFRESH == R2D_VERTICAL)
459 #ifdef R2D_MIRRORED_X
460 ni=(length-1)-i;
461 #else
462 ni=i;
463 #endif
464
465 #ifdef R2D_MIRRORED_Y
466 nj=(length-1)-j;
467 #else
468 nj=j;
469 #endif
470 p[ni*length+nj]=((T_R2D_GC*)gc)->background_pixel_value;
471 #else
472 #ifdef R2D_MIRRORED_X
473 nj=(length-1)-j;
474 #else
475 nj=j;
476 #endif
477
478 #ifdef R2D_MIRRORED_Y
479 ni=(length-1)-i;
480 #else
481 ni=i;
482 #endif
483
484 p[nj*length+ni]=((T_R2D_GC*)gc)->background_pixel_value;
485 #endif
486
487 }
488 }
489 else
490 {
491 for(i=0;i<length;i++)
492 for(j=0;j<length;j++)
493 {
494 r2d_convert_background_color(gc,ft->pattern[i*length+j]);
495 #if (R2D_REFRESH == R2D_VERTICAL)
496 #ifdef R2D_MIRRORED_X
497 ni=(length-1)-i;
498 #else
499 ni=i;
500 #endif
501
502 #ifdef R2D_MIRRORED_Y
503 nj=(length-1)-j;
504 #else
505 nj=j;
506 #endif
507 pos=ni*length+nj;
508 #else
509 #ifdef R2D_MIRRORED_X
510 nj=(length-1)-j;
511 #else
512 nj=j;
513 #endif
514
515 #ifdef R2D_MIRRORED_Y
516 ni=(length-1)-i;
517 #else
518 ni=i;
519 #endif
520
521 pos=nj*length+ni;
522 #endif
523 #if (R2D_DITHERING == R2D_OFF)
524 p[pos]=((T_R2D_GC*)gc)->background_pixel_value;
525 #else
526 p[pos]=r2d_get_dithering_matrix_entry(((T_R2D_GC*)gc)->p_background_dithered_cache,x,y);
527 #endif
528
529 #if (R2D_REFRESH == R2D_VERTICAL)
530 y++;
531 if (y==length)
532 {
533 y=0;
534 x++;
535 }
536 #else
537 x++;
538 if (x==length)
539 {
540 x=0;
541 y++;
542 }
543 #endif
544 }
545 }
546 // Force change
547 r2d_set_background_color(gc,b^1);
548 r2d_set_background_color(gc,b);
549
550 return((T_R2D_ANCHORED_TEXTURE_PTR)at);
551 erroranchored: return(NULL);
552 }
553
554 void r2d_release_anchored_texture(T_R2D_ANCHORED_TEXTURE_PTR texture)
555 {
556 if (texture)
557 {
558 // Remove the array of words if needed
559 // (refcount must be 1 else the array should not be deleted)
560 if (R2D_REFCOUNT(texture)==1)
561 {
562 if (((T_R2D_ANCHORED_TEXTURE*)texture)->pattern)
563 R2D_FREE(((T_R2D_ANCHORED_TEXTURE*)texture)->pattern);
564 }
565 }
566 // Autorelease
567 r2d_release(texture);
568 }
569
570
571 ////////////////////////////////////////
572 //
573 // Framebuffer
574 //
575
576 UINT32 r2d_get_framebuffer_size(T_R2D_FRAMEBUFFER_KIND the_kind,UINT16 width, UINT16 height)
577 {
578 UINT32 t;
579 UINT32 length;
580
581 t=0;
582
583
584
585
586 t+=sizeof(T_R2D_FRAMEBUFFER);
587
588 switch(the_kind)
589 {
590 case R2D_LCD_KIND:
591 #if (R2D_REFRESH==R2D_VERTICAL)
592 // Column is contiguous in memory
593 length=width*R2D_ALIGNED_MWLENGTH(height);
594 t+=((length+1)<<R2D_LONGSIZE_FACTOR);
595 #else
596 length=height*R2D_ALIGNED_MWLENGTH(width);
597 t+=((length+1)<<R2D_LONGSIZE_FACTOR);
598 #endif
599 break;
600 default:
601 length=width*height;
602 t+=((length+1)<<R2D_LONGSIZE_FACTOR);
603 break;
604 }
605
606 t+=sizeof(T_RVF_MUTEX);
607
608
609 return(t);
610 }
611
612 UINT32 r2d_get_gc_size(void)
613 {
614 UINT32 t;
615
616 t=0;
617
618
619 t+=sizeof(T_R2D_GC);
620 t+=sizeof(T_R2D_RECT); // clipping
621 t+=sizeof(T_R2D_RECT); // s_clipping
622 t+=sizeof(UINT32)*4; // foreground dithering cache
623 t+=sizeof(UINT32)*4; // backround dithering cache
624
625
626 return(t);
627 }
628
629
630 T_R2D_FRAMEBUFFER_PTR r2d_new_framebuffer(T_RVF_MB_ID bank,T_R2D_FRAMEBUFFER_KIND the_kind,UINT16 width, UINT16 height)
631 {
632 UINT32 length;
633 T_R2D_FRAMEBUFFER *p;
634 // UINT32 *elem;
635 T_RVF_RET err;
636
637 R2D_MALLOC(bank,T_R2D_FRAMEBUFFER,sizeof(T_R2D_FRAMEBUFFER),p);
638
639 if (p)
640 {
641 switch(the_kind)
642 {
643 case R2D_LCD_KIND:
644 #if (R2D_REFRESH==R2D_VERTICAL)
645 // Column is contiguous in memory
646 length=width*R2D_ALIGNED_MWLENGTH(height);
647 R2D_MALLOC(bank,UINT32,((length+1)<<R2D_LONGSIZE_FACTOR),p->p_memory_words);
648 if (!(p->p_memory_words))
649 {
650 R2D_FREE(p);
651 p=NULL;
652 return(p);
653 }
654 p->refcount=1;
655 p->kind=R2D_LCD_KIND;
656 p->p_frame_buffer_end=p->p_memory_words+length;
657 p->width=width;
658 p->height=height;
659 R2D_MALLOC(bank,T_RVF_MUTEX,sizeof(T_RVF_MUTEX),p->mutex);
660 if (p->mutex!=NULL)
661 {
662 err=rvf_initialize_mutex(p->mutex);
663 if (err!=RVF_OK)
664 {
665 R2D_FREE(p->mutex);
666 R2D_FREE(p->p_memory_words);
667 R2D_FREE(p);
668 p=NULL;
669 return(p);
670 }
671 }
672 else
673 {
674 R2D_FREE(p->p_memory_words);
675 R2D_FREE(p);
676 p=NULL;
677 return(p);
678 }
679
680 #else
681 // Line is contiguous in memory
682 length=height*R2D_ALIGNED_MWLENGTH(width);
683 R2D_MALLOC(bank,UINT32,((length+1)<<R2D_LONGSIZE_FACTOR),p->p_memory_words);
684 if (!(p->p_memory_words))
685 {
686 R2D_FREE(p);
687 p=NULL;
688 return(p);
689 }
690 p->refcount=1;
691 p->kind=R2D_LCD_KIND;
692 p->p_frame_buffer_end=p->p_memory_words+length;
693 p->width=width;
694 p->height=height;
695 R2D_MALLOC(bank,T_RVF_MUTEX,sizeof(T_RVF_MUTEX),p->mutex);
696 if (p->mutex!=NULL)
697 {
698 err=rvf_initialize_mutex(p->mutex);
699 if (err!=RVF_OK)
700 {
701 R2D_FREE(p->mutex);
702 R2D_FREE(p->p_memory_words);
703 R2D_FREE(p);
704 p=NULL;
705 return(p);
706 }
707 }
708 else
709 {
710 R2D_FREE(p->p_memory_words);
711 R2D_FREE(p);
712 p=NULL;
713 return(p);
714 }
715 #endif
716 break;
717 default:
718 length=width*height;
719 R2D_MALLOC(bank,UINT32,((length+1)<<R2D_LONGSIZE_FACTOR),p->p_memory_words);
720 if (!(p->p_memory_words))
721 {
722 R2D_FREE(p);
723 p=NULL;
724 return(p);
725 }
726 p->refcount=1;
727 p->kind=R2D_FULL_KIND;
728 p->p_frame_buffer_end=p->p_memory_words+length;
729 p->width=width;
730 p->height=height;
731 R2D_MALLOC(bank,T_RVF_MUTEX,sizeof(T_RVF_MUTEX),p->mutex);
732 if (p->mutex!=NULL)
733 {
734 err=rvf_initialize_mutex(p->mutex);
735 if (err!=RVF_OK)
736 {
737 R2D_FREE(p->mutex);
738 R2D_FREE(p->p_memory_words);
739 R2D_FREE(p);
740 p=NULL;
741 return(p);
742 }
743 }
744 else
745 {
746 R2D_FREE(p->p_memory_words);
747 R2D_FREE(p);
748 p=NULL;
749 return(p);
750 }
751 break;
752 }
753 } else p=NULL;
754
755 return(p);
756 }
757
758 static T_R2D_FONT_CACHE_FRAMEBUFFER* r2d_new_font_framebuffer(T_RVF_MB_ID bank,T_R2D_FRAMEBUFFER_KIND the_kind,UINT16 width, UINT16 height)
759 {
760 UINT32 length;
761 T_R2D_FONT_CACHE_FRAMEBUFFER *p;
762 // UINT32 *elem;
763 T_RVF_RET err;
764
765 R2D_MALLOC(bank,T_R2D_FONT_CACHE_FRAMEBUFFER,sizeof(T_R2D_FONT_CACHE_FRAMEBUFFER),p);
766
767 if (p)
768 {
769 switch(the_kind)
770 {
771 case R2D_LCD_KIND:
772 #if (R2D_REFRESH==R2D_VERTICAL)
773 // Column is contiguous in memory
774 length=width*R2D_ALIGNED_MWLENGTH(height);
775 R2D_MALLOC(bank,UINT32,((length+1)<<R2D_LONGSIZE_FACTOR),p->p_memory_words);
776 if (!(p->p_memory_words))
777 {
778 R2D_FREE(p);
779 p=NULL;
780 return(p);
781 }
782 p->refcount=1;
783 p->kind=R2D_LCD_KIND;
784 p->p_frame_buffer_end=p->p_memory_words+length;
785 p->width=width;
786 p->height=height;
787 R2D_MALLOC(bank,T_RVF_MUTEX,sizeof(T_RVF_MUTEX),p->mutex);
788 if (p->mutex!=NULL)
789 {
790 err=rvf_initialize_mutex(p->mutex);
791 if (err!=RVF_OK)
792 {
793 R2D_FREE(p->mutex);
794 R2D_FREE(p->p_memory_words);
795 R2D_FREE(p);
796 p=NULL;
797 return(p);
798 }
799 }
800 else
801 {
802 R2D_FREE(p->p_memory_words);
803 R2D_FREE(p);
804 p=NULL;
805 return(p);
806 }
807 #else
808 // Line is contiguous in memory
809 length=height*R2D_ALIGNED_MWLENGTH(width);
810 R2D_MALLOC(bank,UINT32,((length+1)<<R2D_LONGSIZE_FACTOR),p->p_memory_words);
811 if (!(p->p_memory_words))
812 {
813 R2D_FREE(p);
814 p=NULL;
815 return(p);
816 }
817 p->refcount=1;
818 p->kind=R2D_LCD_KIND;
819 p->p_frame_buffer_end=p->p_memory_words+length;
820 p->width=width;
821 p->height=height;
822 R2D_MALLOC(bank,T_RVF_MUTEX,sizeof(T_RVF_MUTEX),p->mutex);
823 if (p->mutex!=NULL)
824 {
825 err=rvf_initialize_mutex(p->mutex);
826 if (err!=RVF_OK)
827 {
828 R2D_FREE(p->mutex);
829 R2D_FREE(p->p_memory_words);
830 R2D_FREE(p);
831 p=NULL;
832 return(p);
833 }
834 }
835 else
836 {
837 R2D_FREE(p->p_memory_words);
838 R2D_FREE(p);
839 p=NULL;
840 return(p);
841 }
842 #endif
843 break;
844 default:
845 length=width*height;
846 R2D_MALLOC(bank,UINT32,((length+1)<<R2D_LONGSIZE_FACTOR),p->p_memory_words);
847 if (!(p->p_memory_words))
848 {
849 R2D_FREE(p);
850 p=NULL;
851 return(p);
852 }
853 p->refcount=1;
854 p->kind=R2D_FULL_KIND;
855 p->p_frame_buffer_end=p->p_memory_words+length;
856 p->width=width;
857 p->height=height;
858 R2D_MALLOC(bank,T_RVF_MUTEX,sizeof(T_RVF_MUTEX),p->mutex);
859 if (p->mutex!=NULL)
860 {
861 err=rvf_initialize_mutex(p->mutex);
862 if (err!=RVF_OK)
863 {
864 R2D_FREE(p->mutex);
865 R2D_FREE(p->p_memory_words);
866 R2D_FREE(p);
867 p=NULL;
868 return(p);
869 }
870 }
871 else
872 {
873 R2D_FREE(p->p_memory_words);
874 R2D_FREE(p);
875 p=NULL;
876 return(p);
877 }
878 break;
879 }
880
881 } else p=NULL;
882
883 return(p);
884 }
885
886
887 // Release a framebuffer
888 void r2d_release_framebuffer(T_R2D_FRAMEBUFFER_PTR p)
889 {
890 if (p)
891 {
892 // Remove the array of words if needed
893 // (refcount must be 1 else the array should not be deleted)
894 if (R2D_REFCOUNT(p)==1)
895 {
896 R2D_FREE(((T_R2D_FRAMEBUFFER*)p)->p_memory_words);
897 rvf_delete_mutex(((T_R2D_FRAMEBUFFER*)p)->mutex);
898 R2D_FREE(((T_R2D_FRAMEBUFFER*)p)->mutex);
899 }
900 }
901 // Autorelease
902 r2d_release(p);
903 }
904
905
906 ////////////////////////////////////////
907 //
908 // Graphic context
909 //
910
911
912 static T_R2D_GC_PTR r2d_new_font_buffer_context(T_RVF_MB_ID bank,
913 T_R2D_FRAMEBUFFER_KIND kind,
914 UINT16 max_width,
915 UINT16 ascent)
916 {
917 T_R2D_FRAMEBUFFER_PTR cache_buffer;
918 T_R2D_GC_PTR result;
919
920 //printf("width=%d,height=%d\n",the_width,((T_R2D_FRAMEBUFFER*)font_frame_buffer)->height);
921
922 cache_buffer=r2d_new_font_framebuffer(bank,kind,
923 max_width,ascent);
924
925
926
927 if (cache_buffer!=NULL)
928 {
929 result=r2d_new_context(bank,cache_buffer);
930 r2d_release_framebuffer(cache_buffer);
931
932 return(result);
933 } else return(NULL);
934 }
935
936
937 T_R2D_GC_PTR r2d_new_context(T_RVF_MB_ID bank,T_R2D_FRAMEBUFFER_PTR the_frame_buffer)
938 {
939 T_R2D_GC *gc;
940
941 // Allocate a new gc structure
942 R2D_MALLOC(bank,T_R2D_GC,sizeof(T_R2D_GC),gc);
943 if (gc)
944 {
945 // gc is pointing to the LCD framebuffer
946 gc->p_frame_buffer=(T_R2D_FRAMEBUFFER*)the_frame_buffer;
947 r2d_retain(the_frame_buffer);
948
949 // Default initialization for a gc
950 gc->background_texture=NULL;
951 gc->foreground_color=r2d_get_standard_argb_color(R2D_BLACK);
952 gc->background_color=r2d_get_standard_argb_color(R2D_WHITE);
953
954
955 #if (R2D_REFRESH == R2D_VERTICAL)
956 gc->p_s_clipping_shape=r2d_new_rectangle(bank,0,0,((T_R2D_FRAMEBUFFER*)the_frame_buffer)->width,
957 ((T_R2D_FRAMEBUFFER*)the_frame_buffer)->height);
958
959 #else
960 gc->p_s_clipping_shape=r2d_new_rectangle(bank,0,0,((T_R2D_FRAMEBUFFER*)the_frame_buffer)->height,((T_R2D_FRAMEBUFFER*)the_frame_buffer)->width);
961
962 #endif
963
964 if (gc->p_s_clipping_shape==NULL)
965 {
966 r2d_release_framebuffer(the_frame_buffer);
967 R2D_FREE(gc);
968 gc=NULL;
969 return(NULL);
970 }
971
972 gc->p_clipping_shape=r2d_new_rectangle(bank,0,0,((T_R2D_FRAMEBUFFER*)the_frame_buffer)->width,
973 ((T_R2D_FRAMEBUFFER*)the_frame_buffer)->height);
974
975
976 gc->drawing_mode=R2D_COPY_MODE;
977
978 gc->drawing_op=r2d_get_drawing_op(gc,R2D_COPY_MODE);
979
980 gc->org_x=gc->org_y=0;
981 gc->s_org_x=gc->s_org_y=0;
982
983 gc->pen_size=1;
984 gc->dash=0;
985 gc->text_face=R2D_SYSTEM;
986 gc->text_style=R2D_PLAIN;
987 gc->internal_text_style=R2D_PLAIN;
988 gc->text_size=R2D_SMALL;
989 gc->script_mode=R2D_LEFT_TO_RIGHT;
990 gc->font_frame_buffer=r2d_g_default_font_framebuffer;
991 gc->font_metrics=r2d_g_default_font_metrics;
992 gc->font_table=r2d_g_default_font_table;
993 if (gc->p_clipping_shape)
994 {
995 r2d_retain(r2d_g_default_font_framebuffer);
996
997 // refcount set to 1 for creation
998 gc->refcount=1;
999 R2D_MALLOC(bank,UINT32,sizeof(UINT32)*4,gc->p_foreground_dithered_cache);
1000 if (gc->p_foreground_dithered_cache)
1001 {
1002 R2D_MALLOC(bank,UINT32,sizeof(UINT32)*4,gc->p_background_dithered_cache);
1003 if (gc->p_background_dithered_cache)
1004 {
1005 if (((T_R2D_FRAMEBUFFER*)the_frame_buffer)->kind==R2D_FULL_KIND)
1006 {
1007 r2d_convert_foreground_color_color(gc,gc->foreground_color);
1008 r2d_convert_background_color_color(gc,gc->background_color);
1009 }
1010 else
1011 {
1012 r2d_convert_foreground_color(gc,gc->foreground_color);
1013 r2d_convert_background_color(gc,gc->background_color);
1014 }
1015 } else // cannot create backround dithered matrix
1016 {
1017 r2d_release_shape(gc->p_clipping_shape);
1018 r2d_release_shape(gc->p_s_clipping_shape);
1019 r2d_release_framebuffer(gc->p_frame_buffer);
1020 r2d_release_framebuffer(r2d_g_default_font_framebuffer);
1021 R2D_FREE(((T_R2D_GC *)gc)->p_foreground_dithered_cache);
1022 R2D_FREE(gc);
1023 gc=NULL;
1024 }
1025 } else // Cannot create foreground dithered matrix
1026 {
1027 r2d_release_shape(gc->p_clipping_shape);
1028 r2d_release_shape(gc->p_s_clipping_shape);
1029 r2d_release_framebuffer(gc->p_frame_buffer);
1030 r2d_release_framebuffer(r2d_g_default_font_framebuffer);
1031 R2D_FREE(gc);
1032 gc=NULL;
1033 }
1034 } else // Cannot create clipping shape
1035 {
1036 R2D_FREE(gc);
1037 gc=NULL;
1038 }
1039 }
1040 else
1041 gc=NULL;
1042 return(gc);
1043 }
1044
1045 T_R2D_GC_PTR r2d_new_lcd_context(T_RVF_MB_ID bank)
1046 {
1047 // T_R2D_GC *gc;
1048 T_R2D_GC_PTR result;
1049
1050 result=r2d_new_context(bank,r2d_g_framebuffer);
1051 r2d_release_framebuffer(r2d_g_framebuffer);
1052 return (result);
1053 }
1054
1055 void r2d_release_context(T_R2D_GC_PTR gc)
1056 {
1057 if (gc)
1058 {
1059 if (R2D_REFCOUNT(gc)==1)
1060 {
1061 // framebuffer release since it is no more used
1062 r2d_release_framebuffer(((T_R2D_GC *)gc)->font_frame_buffer);
1063 r2d_release_shape(((T_R2D_GC *)gc)->p_clipping_shape);
1064 r2d_release_shape(((T_R2D_GC *)gc)->p_s_clipping_shape);
1065 r2d_release_framebuffer(((T_R2D_GC *)gc)->p_frame_buffer);
1066 R2D_FREE((((T_R2D_GC *)gc)->p_foreground_dithered_cache));
1067 R2D_FREE((((T_R2D_GC *)gc)->p_background_dithered_cache));
1068 }
1069 }
1070
1071 // Autodelete of the gc if required
1072 r2d_release(gc);
1073 }
1074
1075 T_R2D_GC_PTR r2d_new_picture_context(T_RVF_MB_ID bank,const UINT32 *the_picture,T_R2D_FRAMEBUFFER_KIND kind)
1076 {
1077 UINT32 h,v,length;
1078 UINT32 *p;
1079 T_R2D_FRAMEBUFFER *buf;
1080 T_R2D_GC_PTR result;
1081 T_RVF_RET err;
1082
1083 p=((UINT32*)the_picture)+3;
1084
1085 h=the_picture[0];
1086 v=the_picture[1];
1087 length=the_picture[2];
1088
1089 rvf_get_buf(bank, sizeof(T_R2D_FRAMEBUFFER),
1090 (T_RVF_BUFFER**)&buf);
1091
1092 if (buf != NULL)
1093 {
1094
1095
1096
1097
1098
1099
1100 buf->p_memory_words=p;
1101 buf->refcount=-1; // Emulate infinite refcount
1102 buf->kind=kind;
1103 buf->p_frame_buffer_end=p+length;
1104 buf->width=h;
1105 buf->height=v;
1106
1107 R2D_MALLOC(bank,T_RVF_MUTEX,sizeof(T_RVF_MUTEX),buf->mutex);
1108 if (buf->mutex!=NULL)
1109 {
1110 err=rvf_initialize_mutex(buf->mutex);
1111 if (err!=RVF_OK)
1112 {
1113 R2D_FREE(buf->mutex);
1114 R2D_FREE(buf);
1115 buf=NULL;
1116 return(buf);
1117 }
1118 }
1119 else
1120 {
1121 R2D_FREE(buf);
1122 buf=NULL;
1123 return(buf);
1124 }
1125
1126 result=r2d_new_context(bank,(T_R2D_FRAMEBUFFER_PTR)buf);
1127 r2d_release_framebuffer(buf);
1128
1129 return(result);
1130 } else return(NULL);
1131 }
1132
1133 void r2d_release_picture_context(T_R2D_GC_PTR gc)
1134 {
1135 T_R2D_FRAMEBUFFER *fb_p;
1136
1137 if (gc)
1138 {
1139 if (R2D_REFCOUNT(gc) == 1)
1140 {
1141 r2d_release_context(gc);
1142 fb_p = (T_R2D_FRAMEBUFFER *) ((T_R2D_GC *) gc)->p_frame_buffer;
1143 rvf_delete_mutex(fb_p->mutex);
1144 R2D_FREE(fb_p->mutex);
1145 R2D_FREE(fb_p);
1146 }
1147
1148 r2d_release(gc);
1149 }
1150 }
1151
1152 UINT16 r2d_get_width(T_R2D_GC_PTR gc)
1153 {
1154 return(((T_R2D_FRAMEBUFFER*)((T_R2D_GC *)gc)->p_frame_buffer)->width);
1155 }
1156
1157 UINT16 r2d_get_height(T_R2D_GC_PTR gc)
1158 {
1159 return(((T_R2D_FRAMEBUFFER*)((T_R2D_GC *)gc)->p_frame_buffer)->height);
1160 }
1161
1162 void r2d_erase(T_R2D_GC_PTR gc)
1163 {
1164 // UINT32 *p;
1165 INT16 x,y;
1166 T_R2D_ARGB_COLOR col;
1167
1168 r2d_get_context_origin(gc,&x,&y);
1169
1170 col=r2d_get_background_color(gc);
1171 r2d_set_background_color(gc,r2d_get_standard_argb_color(R2D_WHITE));
1172
1173
1174 r2d_fill_rectangle(gc,x-1,y-1,x+r2d_get_width(gc),y+r2d_get_height(gc));
1175 r2d_set_background_color(gc,col);
1176
1177 if (((T_R2D_FRAMEBUFFER*)((T_R2D_GC*)gc)->p_frame_buffer)->kind==0)
1178 r2d_update_region((T_R2D_GC*)gc,x,y,x+r2d_get_width(gc)-1,y+r2d_get_height(gc)-1);
1179 r2d_check_and_send_event(gc);
1180 }
1181
1182 void r2d_erase_with_background(T_R2D_GC_PTR gc,
1183 INT16 a,INT16 b,
1184 INT16 c,INT16 d)
1185 {
1186
1187 r2d_fill_rectangle(gc,a-1,b-1,c+1,d+1);
1188 }
1189
1190 T_R2D_DRAWING_MODE r2d_get_drawing_mode(T_R2D_GC_PTR gc)
1191 {
1192 return(((T_R2D_GC *)gc)->drawing_mode);
1193 }
1194
1195 T_R2D_ERROR r2d_set_drawing_mode(T_R2D_GC_PTR gc,T_R2D_DRAWING_MODE the_mode)
1196 {
1197 if (the_mode!=((T_R2D_GC *)gc)->drawing_mode)
1198 {
1199 // All modes must be supported in ASM mode
1200
1201 if (r2d_get_drawing_op(gc,the_mode)!=NULL)
1202
1203 {
1204 ((T_R2D_GC *)gc)->drawing_mode=the_mode;
1205 ((T_R2D_GC *)gc)->drawing_op=r2d_get_drawing_op(gc,the_mode);
1206
1207 return(R2D_OK);
1208 }
1209
1210 else
1211 return(R2D_UNKNOWN_OP);
1212
1213 }
1214 else
1215 return(R2D_OK);
1216
1217
1218 }
1219
1220 UINT16 r2d_get_pen_size(T_R2D_GC_PTR gc)
1221 {
1222 return(((T_R2D_GC *)gc)->pen_size);
1223 }
1224
1225 void r2d_set_pen_size(T_R2D_GC_PTR gc,UINT16 the_size)
1226 {
1227 ((T_R2D_GC *)gc)->pen_size=the_size;
1228 }
1229
1230 // H COORDINATES
1231 void r2d_set_context_origin(T_R2D_GC_PTR gc,INT16 x,INT16 y)
1232 {
1233 INT16 dx,dy;
1234 T_R2D_RECTANGLE *ra,*rb;
1235
1236 dx=x-((T_R2D_GC *)gc)->org_x;
1237 dy=y-((T_R2D_GC *)gc)->org_y;
1238
1239 ((T_R2D_GC *)gc)->org_x=x;
1240 ((T_R2D_GC *)gc)->org_y=y;
1241
1242 r2d_translate_shape(((T_R2D_GC *)gc)->p_clipping_shape,dx,dy);
1243
1244
1245 ra=r2d_new_rectangle(r2d_mb_id,0,0,0,0);
1246 rb=r2d_s_level(gc,ra);
1247
1248 if (rb)
1249 {
1250 ((T_R2D_GC *)gc)->s_org_x=rb->ul_x;
1251 ((T_R2D_GC *)gc)->s_org_y=rb->ul_y;
1252 }
1253
1254 r2d_release_shape(ra);
1255 r2d_release_shape(rb);
1256
1257
1258 // No translation of p_s_clipping_shape which is in S coordinates.
1259 // Only H coordinates are impacted by the context origin
1260 }
1261
1262 // H COORDINATES
1263 void r2d_get_context_origin(T_R2D_GC_PTR gc,INT16 *x,INT16 *y)
1264 {
1265 *x=((T_R2D_GC *)gc)->org_x;
1266 *y=((T_R2D_GC *)gc)->org_y;
1267 }
1268
1269 // H COORDINATES
1270 void r2d_local_to_global(T_R2D_GC_PTR gc,INT16 *x,INT16 *y)
1271 {
1272 *x-=((T_R2D_GC *)gc)->org_x;
1273 *y-=((T_R2D_GC *)gc)->org_y;
1274 }
1275
1276 // H coordinates
1277 void r2d_get_pen_pos(T_R2D_GC_PTR gc,INT16 *x,INT16 *y)
1278 {
1279 *x=((T_R2D_GC *)gc)->pen_x;
1280 *y=((T_R2D_GC *)gc)->pen_y;
1281 }
1282
1283 BOOLEAN r2d_dash_enabled(T_R2D_GC_PTR gc)
1284 {
1285 return(((T_R2D_GC *)gc)->dash);
1286 }
1287
1288 void r2d_set_dash_state(T_R2D_GC_PTR gc,BOOLEAN enabled)
1289 {
1290 ((T_R2D_GC *)gc)->dash=enabled;
1291 }
1292
1293 static void r2d_change_font(T_R2D_GC_PTR gc,T_R2D_FONT_DESCRIPTION *desc)
1294 {
1295 r2d_retain(desc->framebuffer);
1296 r2d_release_framebuffer(((T_R2D_GC *)gc)->font_frame_buffer);
1297 ((T_R2D_GC *)gc)->font_frame_buffer=desc->framebuffer;
1298
1299 ((T_R2D_GC *)gc)->font_metrics=desc->metrics;
1300 ((T_R2D_GC *)gc)->font_table=desc->table;
1301 }
1302
1303 static T_R2D_FONT_DESCRIPTION *r2d_get_desc(T_R2D_GC_PTR gc)
1304 {
1305 INT16 f;
1306 INT16 s;
1307 INT16 t;
1308 T_R2D_FONT_DESCRIPTION *p;
1309 INT16 temp;
1310
1311 p=r2d_g_font_configuration;
1312
1313 f=r2d_get_text_face(gc)-1;
1314 s=r2d_get_text_size(gc)-1;
1315 t=r2d_get_text_style(gc) & (R2D_BOLD | R2D_ITALIC);
1316
1317 t=t-(t>>1);
1318
1319 temp=(f<<2) + (f<<3) + (s<<2) + t;
1320 p=r2d_g_font_configuration+(temp);
1321
1322 return(p);
1323 }
1324
1325 void r2d_set_text_face(T_R2D_GC_PTR gc,T_R2D_TEXT_FACE the_face)
1326 {
1327 ((T_R2D_GC *)gc)->text_face=the_face;
1328
1329 r2d_change_font(gc,r2d_get_desc(gc));
1330
1331 }
1332
1333 T_R2D_TEXT_FACE r2d_get_text_face(T_R2D_GC_PTR gc)
1334 {
1335 return(((T_R2D_GC *)gc)->text_face);
1336 }
1337
1338
1339 void r2d_set_text_style(T_R2D_GC_PTR gc,T_R2D_TEXT_STYLE the_style)
1340 {
1341 T_R2D_FONT_DESCRIPTION *desc;
1342
1343 ((T_R2D_GC *)gc)->text_style=the_style;
1344
1345 // Clear italic bit;
1346 the_style=the_style & (~R2D_ITALIC);
1347
1348 // Clear bold bit if desc for Bold is not NULL
1349 desc=r2d_get_desc(gc);
1350 if (!desc->compute_bold)
1351 the_style=the_style & (~R2D_BOLD);
1352
1353
1354 ((T_R2D_GC *)gc)->internal_text_style=the_style;
1355
1356 r2d_change_font(gc,r2d_get_desc(gc));
1357
1358 }
1359
1360 T_R2D_TEXT_STYLE r2d_get_text_style(T_R2D_GC_PTR gc)
1361 {
1362 return(((T_R2D_GC *)gc)->text_style);
1363 }
1364
1365
1366 void r2d_set_text_size(T_R2D_GC_PTR gc,T_R2D_TEXT_SIZE the_size)
1367 {
1368 ((T_R2D_GC *)gc)->text_size=the_size;
1369 r2d_change_font(gc,r2d_get_desc(gc));
1370 }
1371
1372 T_R2D_TEXT_SIZE r2d_get_text_size(T_R2D_GC_PTR gc)
1373 {
1374 return(((T_R2D_GC *)gc)->text_size);
1375 }
1376
1377 T_R2D_ERROR r2d_context_lock(T_R2D_GC_PTR gc)
1378 {
1379 T_RVF_RET err;
1380 err=RVF_OK;
1381 err=rvf_lock_mutex(((T_R2D_FRAMEBUFFER*)((T_R2D_GC*)gc)->p_frame_buffer)->mutex);
1382 if (err!=RVF_OK)
1383 return(R2D_LOCK_ERROR);
1384 else
1385 return(R2D_OK);
1386 }
1387
1388 T_R2D_ERROR r2d_context_unlock(T_R2D_GC_PTR gc)
1389 {
1390 T_RVF_RET err;
1391 err=RVF_OK;
1392 err=rvf_unlock_mutex(((T_R2D_FRAMEBUFFER*)((T_R2D_GC*)gc)->p_frame_buffer)->mutex);
1393 if (err!=RVF_OK)
1394 return(R2D_UNLOCK_ERROR);
1395 else
1396 return(R2D_OK);
1397 }
1398
1399 // Return the a pointer to the memory area containing
1400 // pixels for the graphic context gc
1401 //
1402 UINT32* r2d_get_pixmap(T_R2D_GC_PTR gc)
1403 {
1404 T_R2D_GC *src;
1405 T_R2D_FRAMEBUFFER *src_f;
1406 UINT32 *ps;
1407
1408 src=(T_R2D_GC*)gc;
1409 src_f=(T_R2D_FRAMEBUFFER*)(src->p_frame_buffer);
1410 ps=src_f->p_memory_words;
1411
1412 return(ps);
1413 }
1414
1415 // Force the flushing of LCD framebuffer to display its
1416 // content
1417 void r2d_flush(void)
1418 {
1419 r2d_update_region(NULL,0,
1420 0,
1421 R2D_WIDTH-1,
1422 R2D_HEIGHT-1);
1423 r2d_check_and_send_event(r2d_g_lcd_gc);
1424 }
1425
1426 // xreddymn Apr-06-2005 MMI-SPR-29655
1427 // Force the flushing of a portion of LCD framebuffer to display its
1428 // content
1429 void r2d_flush_region(INT16 ul_x,INT16 ul_y,INT16 br_x,INT16 br_y)
1430 {
1431 r2d_update_region(NULL, ul_x,
1432 ul_y,
1433 br_x,
1434 br_y);
1435 r2d_check_and_send_event(r2d_g_lcd_gc);
1436 }
1437
1438 void r2d_disable_refresh(void)
1439 {
1440 rvf_lock_mutex(r2d_g_global_mutex);
1441 r2d_g_refresh_disabled++;
1442 //rvf_send_trace("R2D : disable refresh\n",sizeof("R2D : disable refresh\n"), NULL_PARAM,
1443 // RV_TRACE_LEVEL_ERROR, R2D_USE_ID );
1444 rvf_unlock_mutex(r2d_g_global_mutex);
1445 }
1446
1447 void r2d_enable_refresh(void)
1448 {
1449 //rvf_send_trace("R2D : enable refresh\n",sizeof("R2D : enable refresh\n"), NULL_PARAM,
1450 // RV_TRACE_LEVEL_ERROR, R2D_USE_ID );
1451 rvf_lock_mutex(r2d_g_global_mutex);
1452 r2d_g_refresh_disabled--;
1453 if (r2d_g_refresh_disabled==0)
1454 {
1455 //rvf_send_trace("R2D : flush\n",sizeof("R2D : flush\n"), NULL_PARAM,
1456 //RV_TRACE_LEVEL_ERROR, R2D_USE_ID );
1457 //rvf_send_trace("Enable refresh and flush",sizeof("Enable refresh and flush")-1, NULL_PARAM,
1458 // RV_TRACE_LEVEL_DEBUG_HIGH, R2D_USE_ID );
1459 // The flush will not raise a context commutation to R2D since R2D may
1460 // be sleeping waiting for the current refresh perio.
1461 // So, the event will not be processed at once. While R2D is sleeping,
1462 // another task may call r2d_disable_refresh and thus
1463 // when R2D is awaken, it will not process the event which is waiting.
1464 // So, finally, the display will not be refreshed.
1465 // To avoid this problem which occurs for a quick succession of
1466 // r2d_disable_refresh
1467 // r2d_enable_refresh
1468 // one should try to call them with a rate which is lower than the refresh rate
1469 rvf_unlock_mutex(r2d_g_global_mutex);
1470 //r2d_flush();
1471
1472 r2d_check_and_send_event(r2d_g_lcd_gc);
1473 }
1474 else
1475 rvf_unlock_mutex(r2d_g_global_mutex);
1476 }
1477
1478 ////////////////////////////////////////
1479 //
1480 // Colors
1481 //
1482
1483
1484 // Return ARGB foreground color for the gc
1485 T_R2D_ARGB_COLOR r2d_get_foreground_color(T_R2D_GC_PTR gc)
1486 {
1487 return (((T_R2D_GC*)gc)->foreground_color);
1488 }
1489
1490 // Set ARGB foreground color for the gc
1491 // (Alpha channel not yet supported)
1492 void r2d_set_foreground_color_with_argb(T_R2D_GC_PTR gc,UINT16 alpha,UINT16 red,UINT16 green,UINT16 blue)
1493 {
1494 UINT32 color;
1495 color=r2d_new_argb_color(alpha,red,green,blue);
1496 if (color !=((T_R2D_GC*)gc)->foreground_color)
1497 {
1498 ((T_R2D_GC*)gc)->foreground_color=color;
1499
1500 if (((T_R2D_FRAMEBUFFER*)(((T_R2D_GC*)gc)->p_frame_buffer))->kind==R2D_FULL_KIND)
1501 r2d_convert_foreground_color_color(gc,color);
1502 else
1503 r2d_convert_foreground_color(gc,color);
1504 }
1505 }
1506
1507 // Set ARGB foreground color for the gc
1508 // (Alpha channel not yet supported)
1509 void r2d_set_foreground_color(T_R2D_GC_PTR gc,T_R2D_ARGB_COLOR color)
1510 {
1511 if (color !=((T_R2D_GC*)gc)->foreground_color)
1512 {
1513 ((T_R2D_GC*)gc)->foreground_color=color;
1514 if (((T_R2D_FRAMEBUFFER*)(((T_R2D_GC*)gc)->p_frame_buffer))->kind==R2D_FULL_KIND)
1515 r2d_convert_foreground_color_color(gc,color);
1516 else
1517 r2d_convert_foreground_color(gc,color);
1518 }
1519 }
1520
1521 // Return ARGB foreground color for the gc
1522 T_R2D_ARGB_COLOR r2d_get_background_color(T_R2D_GC_PTR gc)
1523 {
1524 return (((T_R2D_GC*)gc)->background_color);
1525 }
1526
1527 // Set ARGB foreground color for the gc
1528 // (Alpha channel not yet supported)
1529 void r2d_set_background_color_with_argb(T_R2D_GC_PTR gc,UINT16 alpha,UINT16 red,UINT16 green,UINT16 blue)
1530 {
1531 UINT32 color;
1532 color=r2d_new_argb_color(alpha,red,green,blue);
1533 if (color !=((T_R2D_GC*)gc)->background_color)
1534 {
1535 ((T_R2D_GC*)gc)->background_color=color;
1536 if (((T_R2D_FRAMEBUFFER*)(((T_R2D_GC*)gc)->p_frame_buffer))->kind==R2D_FULL_KIND)
1537 r2d_convert_background_color_color(gc,color);
1538 else
1539 r2d_convert_background_color(gc,color);
1540 }
1541 }
1542
1543 // Set ARGB foreground color for the gc
1544 // (Alpha channel not yet supported)
1545 void r2d_set_background_color(T_R2D_GC_PTR gc,T_R2D_ARGB_COLOR color)
1546 {
1547 if (color !=((T_R2D_GC*)gc)->background_color)
1548 {
1549 ((T_R2D_GC*)gc)->background_color=color;
1550 if (((T_R2D_FRAMEBUFFER*)(((T_R2D_GC*)gc)->p_frame_buffer))->kind==R2D_FULL_KIND)
1551 r2d_convert_background_color_color(gc,color);
1552 else
1553 r2d_convert_background_color(gc,color);
1554 }
1555 }
1556
1557 void r2d_set_background_texture(T_R2D_GC_PTR gc,T_R2D_ANCHORED_TEXTURE_PTR texture)
1558 {
1559
1560 // INT16 length;
1561 // T_R2D_ANCHORED_TEXTURE *t;
1562
1563 // If a texture is already in place try to release it
1564 if (((T_R2D_GC*)gc)->background_texture!=NULL)
1565 {
1566 r2d_release_anchored_texture(((T_R2D_GC*)gc)->background_texture);
1567 ((T_R2D_GC*)gc)->background_texture=NULL;
1568 }
1569
1570
1571 ((T_R2D_GC*)gc)->background_texture=texture;
1572
1573
1574 if (texture!=NULL)
1575 {
1576 r2d_retain(texture);
1577 }
1578
1579
1580
1581
1582 }
1583
1584 T_R2D_ANCHORED_TEXTURE_PTR r2d_get_background_texture(T_R2D_GC_PTR gc)
1585 {
1586 return ((T_R2D_GC*)gc)->background_texture;
1587 }
1588
1589 T_R2D_ARGB_COLOR r2d_new_argb_color(UINT16 alpha,UINT16 red,UINT16 green,UINT16 blue)
1590 {
1591 T_R2D_ARGB_COLOR col;
1592 col=0;
1593
1594 col=col|(alpha&0xFF);
1595 col=col<<8;
1596 col=col|(red&0xFF);
1597 col=col<<8;
1598 col=col|(green&0xFF);
1599 col=col<<8;
1600 col=col|(blue&0xFF);
1601
1602 return(col);
1603 }
1604
1605 T_R2D_ARGB_COLOR r2d_get_argb_color_at_point(T_R2D_GC_PTR gc,INT16 x,INT16 y)
1606 {
1607 UINT32 result;
1608 if (r2d_point_in_shape(((T_R2D_GC*)gc)->p_clipping_shape,x,y))
1609 {
1610 r2d_local_to_global(gc,&x,&y);
1611 #ifdef R2D_MIRRORED_X
1612
1613 x=r2d_get_width(gc)-1-x;
1614 #endif
1615
1616 #ifdef R2D_MIRRORED_Y
1617 y=r2d_get_height(gc)-1-y;
1618 #endif
1619
1620 #if (R2D_REFRESH == R2D_VERTICAL)
1621 result=IND_r2d_get_color_pixel_value(gc,x,y);
1622 #else
1623 result=IND_r2d_get_color_pixel_value(gc,y,x);
1624 #endif
1625 return(result);
1626 }
1627 else
1628 return(0);
1629 }
1630
1631 T_R2D_ARGB_COLOR r2d_get_standard_argb_color(T_R2D_COLOR_REF ref)
1632 {
1633 switch(ref)
1634 {
1635 case R2D_RED: return(r2d_new_argb_color(0,255,0,0)); break;
1636 case R2D_BLUE:return(r2d_new_argb_color(0,0,0,255)); break;
1637 case R2D_GREEN:return(r2d_new_argb_color(0,0,255,0)); break;
1638 case R2D_WHITE:return(r2d_new_argb_color(0,255,255,255)); break;
1639 case R2D_BLACK:return(r2d_new_argb_color(0,0,0,0)); break;
1640 case R2D_GRAY50:return(r2d_new_argb_color(0,127,127,12)); break;
1641 default:return(r2d_new_argb_color(0,0,0,0)); break;
1642 }
1643 }
1644
1645 // h from 0 to 360 :
1646 // s from 0 to 1 : 1 is 0x800000
1647 // v from 0 to 1
1648 // r,g,b from 0 to 1
1649 // Value in Q8
1650 void r2d_hsv_to_rgb( INT16 *r, INT16 *g, INT16 *b, INT32 h, INT32 s, INT32 v )
1651 {
1652 int i;
1653 INT32 f, p, q, t;
1654
1655 //s and v in Q8. So 255 is FF is 1
1656
1657 if( s == 0 ) {
1658 // achromatic (grey)
1659 *r = *g = *b = (v>>13);
1660 return;
1661 }
1662 h = h * (0x3000000 >> 8) ; // 360/256 / 60 ;Q23 ; sector 0 to 5
1663 i = h & 0xFF800000;
1664 f = h - i; // factorial part of h
1665 i=i>>15;
1666 f = f >> 15; // Q16
1667 p = (v * ( 0x100 - s )) >> 8;
1668 q = (v * ( 0x100 - ((s * f) >> 8) )) >> 8;
1669 t = (v * ( 0x100 - ((s * ( 0x100 - f )) >> 8) )) >> 8;
1670 switch( i>>8 ) {
1671 case 0:
1672 *r = v;
1673 *g = t;
1674 *b = p;
1675 break;
1676 case 1:
1677 *r = q;
1678 *g = v;
1679 *b = p;
1680 break;
1681 case 2:
1682 *r = p;
1683 *g = v;
1684 *b = t;
1685 break;
1686 case 3:
1687 *r = p;
1688 *g = q;
1689 *b = v;
1690 break;
1691 case 4:
1692 *r = t;
1693 *g = p;
1694 *b = v;
1695 break;
1696 default: // case 5:
1697 *r = v;
1698 *g = p;
1699 *b = q;
1700 break;
1701 }
1702 }
1703
1704 ////////////////////////////////////////
1705 //
1706 // Shapes
1707 //
1708
1709 // H COORDINATES ...
1710 void r2d_draw_shape(T_R2D_SHAPE_PTR self,T_R2D_GC_PTR gc)
1711 {
1712
1713 if (self)
1714 {
1715 ((T_R2D_SHAPE*)self)->p_r2d_class->draw(self,gc);
1716
1717 }
1718 }
1719
1720 void r2d_fill_shape(T_R2D_SHAPE_PTR self,T_R2D_GC_PTR gc)
1721 {
1722 if (self)
1723 {
1724 ((T_R2D_SHAPE*)self)->p_r2d_class->fill(self,gc);
1725
1726 }
1727 }
1728
1729 void r2d_release_shape(T_R2D_SHAPE_PTR self)
1730 {
1731
1732
1733 if (self)
1734 ((T_R2D_SHAPE*)self)->p_r2d_class->release(self);
1735 }
1736
1737 T_R2D_SHAPE_PTR r2d_clone_shape(T_RVF_MB_ID bank,T_R2D_SHAPE_PTR self)
1738 {
1739 if (self)
1740 return (((T_R2D_SHAPE*)self)->p_r2d_class->clone(bank,self));
1741 else
1742 return(NULL);
1743 }
1744
1745 void r2d_translate_shape(T_R2D_SHAPE_PTR self,INT16 dx,INT16 dy)
1746 {
1747 if (self)
1748 ((T_R2D_SHAPE*)self)->p_r2d_class->translate(self,dx,dy);
1749
1750 }
1751
1752 BOOLEAN r2d_point_in_shape(T_R2D_SHAPE_PTR self,INT16 x,INT16 y)
1753 {
1754
1755 if (self)
1756 return(((T_R2D_SHAPE*)self)->p_r2d_class->point_in_shape(self,x,y));
1757 else
1758 return(FALSE);
1759
1760 }
1761
1762
1763 BOOLEAN r2d_point_in_rectangle_shape(T_R2D_SHAPE* self,INT16 x,INT16 y)
1764 {
1765 T_R2D_RECTANGLE *r;
1766
1767 r=(T_R2D_RECTANGLE*)self;
1768
1769 return (((x>=r2d_get_xmin(self))
1770 && (x<r2d_get_xmax(self))
1771 && (y>=r2d_get_ymin(self))
1772 && (y<r2d_get_ymax(self))));
1773 }
1774
1775 BOOLEAN r2d_point_in_circle_shape(T_R2D_SHAPE* self,INT16 x,INT16 y)
1776 {
1777 T_R2D_CIRCLE *c;
1778 c=(T_R2D_CIRCLE*)self;
1779
1780 return((x-c->x)*(x-c->x)+(y-c->y)*(y-c->y)-c->r*c->r<0);
1781 }
1782
1783 BOOLEAN r2d_point_in_ellipse_shape(T_R2D_SHAPE* self,INT16 x,INT16 y)
1784 {
1785 T_R2D_ELLIPSE *c;
1786 INT32 a,b,cx,cy,nx,ny;
1787
1788 c=(T_R2D_ELLIPSE*)self;
1789 // Work on Q1
1790
1791 // a is half width so no <<1 is used here
1792 a=(c->br_x-c->ul_x);
1793 b=(c->br_y-c->ul_y);
1794
1795 nx=x<<1;
1796 ny=y<<1;
1797
1798 cx=((c->ul_x)<<1)+a;
1799 cy=((c->ul_y)<<1)+b;
1800
1801 //b^2*x^2+a^2y^2-a^2b^2=0
1802
1803 return((b*b*(nx-cx)*(nx-cx)+a*a*(ny-cy)*(ny-cy)-a*a*b*b)<0);
1804
1805 }
1806
1807 BOOLEAN r2d_point_in_round_rectangle_shape(T_R2D_SHAPE* self,INT16 x,INT16 y)
1808 {
1809 T_R2D_ROUND_RECTANGLE *r;
1810 BOOLEAN result;
1811
1812 result=FALSE;
1813 r=(T_R2D_ROUND_RECTANGLE *)self;
1814
1815 if ((x>=r->ul_x+r->h+1) && (x<r->br_x-r->h) && (y>=r->ul_y) && (y<r->br_y))
1816 result=TRUE;
1817 else if ((x>=r->ul_x) && (x<r->br_x) && (y>=r->ul_y+r->v+1) && (y<r->br_y-r->v))
1818 result=TRUE;
1819 else
1820 {
1821 INT32 a,b,cx,cy,nx,ny;
1822
1823 if (x>=r->br_x-r->h)
1824 x=x-(r->br_x-r->ul_x)+((r->h)<<1);
1825
1826 if (y>=r->br_y-r->v)
1827 y=y-(r->br_y-r->ul_y)+((r->v)<<1);
1828
1829
1830 a=(r->h<<1);
1831 b=(r->v<<1);
1832
1833 nx=x<<1;
1834 ny=y<<1;
1835
1836 cx=((r->ul_x)<<1)+a;
1837 cy=((r->ul_y)<<1)+b;
1838
1839 //b^2*x^2+a^2y^2-a^2b^2=0
1840
1841 result=(b*b*(nx-cx)*(nx-cx)+a*a*(ny-cy)*(ny-cy)-a*a*b*b)<0;
1842
1843
1844 }
1845
1846 return(result);
1847
1848 }
1849
1850 BOOLEAN r2d_point_in_not_supported_shape(T_R2D_SHAPE* self,INT16 x,INT16 y)
1851 {
1852 return FALSE;
1853 }
1854
1855 void r2d_translate_rectangle_shape(T_R2D_SHAPE* self,INT16 dx,INT16 dy)
1856 {
1857 T_R2D_RECTANGLE *r;
1858 r=(T_R2D_RECTANGLE *)self;
1859 r->ul_x+=dx;
1860 r->ul_y+=dy;
1861 r->br_x+=dx;
1862 r->br_y+=dy;
1863 }
1864
1865 void r2d_translate_point_shape(T_R2D_SHAPE* self,INT16 dx,INT16 dy)
1866 {
1867 T_R2D_CIRCLE *r;
1868 r=(T_R2D_CIRCLE *)self;
1869 r->x+=dx;
1870 r->y+=dy;
1871 }
1872
1873
1874 T_R2D_SHAPE_PTR r2d_new_rectangle(T_RVF_MB_ID bank,INT16 ul_x,INT16 ul_y,INT16 br_x,INT16 br_y)
1875 {
1876 T_R2D_RECTANGLE *r;
1877 T_R2D_ERROR err;
1878 err=R2D_MALLOC(bank,T_R2D_RECTANGLE,sizeof(T_R2D_RECTANGLE),r);
1879 if (r)
1880 {
1881 r->refcount=1;
1882 r->ul_x=ul_x;
1883 r->ul_y=ul_y;
1884 r->br_x=br_x;
1885 r->br_y=br_y;
1886 r->p_r2d_class=&r2d_class_rectangle;
1887 } else r=NULL;
1888 return(r);
1889 }
1890
1891 void r2d_release_rectangle(T_R2D_SHAPE* self)
1892 {
1893 T_R2D_RECTANGLE *r;
1894 r=(T_R2D_RECTANGLE *)self;
1895
1896 r2d_release(r);
1897 }
1898
1899 T_R2D_SHAPE_PTR r2d_clone_rectangle_shape(T_RVF_MB_ID bank,T_R2D_SHAPE* self)
1900 {
1901 T_R2D_RECTANGLE *r;
1902 r=(T_R2D_RECTANGLE *)self;
1903
1904 return(r2d_new_rectangle(bank,r->ul_x,r->ul_y,r->br_x,r->br_y));
1905 }
1906
1907 void r2d_draw_rectangle_shape(T_R2D_SHAPE* self,T_R2D_GC_PTR gc)
1908 {
1909 T_R2D_RECTANGLE *r;
1910 r=(T_R2D_RECTANGLE *)self;
1911 r2d_draw_rectangle(gc,r->ul_x,r->ul_y,r->br_x,r->br_y);
1912 }
1913
1914 void r2d_fill_rectangle_shape(T_R2D_SHAPE* self,T_R2D_GC_PTR gc)
1915 {
1916 T_R2D_RECTANGLE *r;
1917 r=(T_R2D_RECTANGLE *)self;
1918 r2d_fill_rectangle(gc,r->ul_x,r->ul_y,r->br_x,r->br_y);
1919 }
1920
1921
1922 void r2d_release_circle(T_R2D_SHAPE* self)
1923 {
1924 T_R2D_CIRCLE *r;
1925 r=(T_R2D_CIRCLE *)self;
1926
1927 r2d_release(r);
1928
1929 #if (R2D_DEBUG == R2D_ON)
1930 r=NULL;
1931 #endif
1932 }
1933
1934 T_R2D_SHAPE_PTR r2d_clone_circle_shape(T_RVF_MB_ID bank,T_R2D_SHAPE* self)
1935 {
1936 T_R2D_CIRCLE *r;
1937 r=(T_R2D_CIRCLE *)self;
1938
1939 return(r2d_new_circle(bank,r->x,r->y,r->r));
1940 }
1941
1942 void r2d_draw_circle_shape(T_R2D_SHAPE* self,T_R2D_GC_PTR gc)
1943 {
1944 T_R2D_CIRCLE *r;
1945 r=(T_R2D_CIRCLE *)self;
1946 r2d_draw_circle(gc,r->x,r->y,r->r);
1947 }
1948
1949 void r2d_fill_circle_shape(T_R2D_SHAPE* self,T_R2D_GC_PTR gc)
1950 {
1951 T_R2D_CIRCLE *r;
1952 r=(T_R2D_CIRCLE *)self;
1953 r2d_fill_circle(gc,r->x,r->y,r->r);
1954 }
1955
1956 T_R2D_SHAPE_PTR r2d_new_circle(T_RVF_MB_ID bank,INT16 x,INT16 y,INT16 r)
1957 {
1958 T_R2D_CIRCLE *c;
1959 R2D_MALLOC(bank,T_R2D_CIRCLE,sizeof(T_R2D_CIRCLE),c);
1960 if (c)
1961 {
1962 c->refcount=1;
1963 c->x=x;
1964 c->y=y;
1965 c->r=r;
1966 c->p_r2d_class=&r2d_class_circle;
1967 } else c=NULL;
1968 return(c);
1969 }
1970
1971 void r2d_release_ellipse(T_R2D_SHAPE* self)
1972 {
1973 T_R2D_ELLIPSE *r;
1974 r=(T_R2D_ELLIPSE *)self;
1975
1976 r2d_release(r);
1977 #if (R2D_DEBUG == R2D_ON)
1978 r=NULL;
1979 #endif
1980 }
1981
1982 void r2d_draw_ellipse_shape(T_R2D_SHAPE* self,T_R2D_GC_PTR gc)
1983 {
1984 T_R2D_ELLIPSE *r;
1985 r=(T_R2D_ELLIPSE *)self;
1986 r2d_draw_ellipse(gc,r->ul_x,r->ul_y,r->br_x,r->br_y);
1987 }
1988
1989 void r2d_fill_ellipse_shape(T_R2D_SHAPE* self,T_R2D_GC_PTR gc)
1990 {
1991 T_R2D_ELLIPSE *r;
1992 r=(T_R2D_ELLIPSE *)self;
1993 r2d_fill_ellipse(gc,r->ul_x,r->ul_y,r->br_x,r->br_y);
1994 }
1995
1996 T_R2D_SHAPE_PTR r2d_new_ellipse(T_RVF_MB_ID bank,INT16 ul_x,INT16 ul_y,INT16 br_x,INT16 br_y)
1997 {
1998 T_R2D_ELLIPSE *r;
1999 R2D_MALLOC(bank,T_R2D_ELLIPSE,sizeof(T_R2D_ELLIPSE),r);
2000 if (r)
2001 {
2002 r->refcount=1;
2003 r->ul_x=ul_x;
2004 r->ul_y=ul_y;
2005 r->br_x=br_x;
2006 r->br_y=br_y;
2007 r->p_r2d_class=&r2d_class_ellipse;
2008 } else r=NULL;
2009 return(r);
2010 }
2011
2012 void r2d_release_round_rectangle(T_R2D_SHAPE* self)
2013 {
2014 T_R2D_ROUND_RECTANGLE *r;
2015 r=(T_R2D_ROUND_RECTANGLE *)self;
2016
2017 r2d_release(r);
2018 #if (R2D_DEBUG == R2D_ON)
2019 r=NULL;
2020 #endif
2021 }
2022
2023 void r2d_draw_round_rectangle_shape(T_R2D_SHAPE* self,T_R2D_GC_PTR gc)
2024 {
2025 T_R2D_ROUND_RECTANGLE *r;
2026 r=(T_R2D_ROUND_RECTANGLE *)self;
2027 r2d_draw_round_rectangle(gc,r->ul_x,r->ul_y,r->br_x,r->br_y,r->h,r->v);
2028 }
2029
2030 void r2d_fill_round_rectangle_shape(T_R2D_SHAPE* self,T_R2D_GC_PTR gc)
2031 {
2032 T_R2D_ROUND_RECTANGLE *r;
2033 r=(T_R2D_ROUND_RECTANGLE *)self;
2034 r2d_fill_round_rectangle(gc,r->ul_x,r->ul_y,r->br_x,r->br_y,r->h,r->v);
2035 }
2036
2037 T_R2D_SHAPE_PTR r2d_clone_round_rectangle_shape(T_RVF_MB_ID bank,T_R2D_SHAPE* self)
2038 {
2039 T_R2D_ROUND_RECTANGLE *r;
2040 r=(T_R2D_ROUND_RECTANGLE *)self;
2041
2042 return(r2d_new_round_rectangle(bank,r->ul_x,r->ul_y,r->br_x,r->br_y,r->h,r->v));
2043 }
2044
2045 T_R2D_SHAPE_PTR r2d_new_round_rectangle(T_RVF_MB_ID bank,INT16 ul_x,INT16 ul_y,INT16 br_x,INT16 br_y,INT16 h,INT16 v)
2046 {
2047 T_R2D_ROUND_RECTANGLE *r;
2048 R2D_MALLOC(bank,T_R2D_ROUND_RECTANGLE,sizeof(T_R2D_ROUND_RECTANGLE),r);
2049 if (r)
2050 {
2051 r->refcount=1;
2052 r->ul_x=ul_x;
2053 r->ul_y=ul_y;
2054 r->br_x=br_x;
2055 r->br_y=br_y;
2056 r->h=h;
2057 r->v=v;
2058 r->p_r2d_class=&r2d_class_round_rectangle;
2059 } else r=NULL;
2060 return(r);
2061 }
2062
2063 T_R2D_SHAPE_PTR r2d_clone_arc_shape(T_RVF_MB_ID bank,T_R2D_SHAPE* self)
2064 {
2065 T_R2D_ARC *r;
2066 r=(T_R2D_ARC *)self;
2067
2068 return(r2d_new_arc(bank,r->start_angle,r->stop_angle,r->ul_x,r->ul_y,r->br_x,r->br_y));
2069 }
2070
2071 T_R2D_SHAPE_PTR r2d_new_arc(T_RVF_MB_ID bank,INT16 start_angle, INT16 stop_angle,INT16 ul_x,INT16 ul_y,
2072 INT16 br_x,INT16 br_y)
2073 {
2074 T_R2D_ARC *r;
2075 R2D_MALLOC(bank,T_R2D_ARC,sizeof(T_R2D_ARC),r);
2076 if (r)
2077 {
2078 r->refcount=1;
2079 r->ul_x=ul_x;
2080 r->ul_y=ul_y;
2081 r->br_x=br_x;
2082 r->br_y=br_y;
2083 r->start_angle=start_angle;
2084 r->stop_angle=stop_angle;
2085 r->p_r2d_class=&r2d_class_arc;
2086 } else r=NULL;
2087 return(r);
2088 }
2089
2090 void r2d_release_arc(T_R2D_SHAPE *self)
2091 {
2092 T_R2D_ARC *r;
2093 r=(T_R2D_ARC *)self;
2094
2095 r2d_release(r);
2096 }
2097
2098 void r2d_draw_arc_shape(T_R2D_SHAPE *self,T_R2D_GC_PTR gc)
2099 {
2100 T_R2D_ARC *r;
2101 r=(T_R2D_ARC *)self;
2102
2103 r2d_draw_arc(gc,r->start_angle,r->stop_angle,
2104 r->ul_x,r->ul_y,r->br_x,r->br_y);
2105 }
2106
2107 void r2d_fill_arc_shape(T_R2D_SHAPE *self,T_R2D_GC_PTR gc)
2108 {
2109 T_R2D_ARC *r;
2110 r=(T_R2D_ARC *)self;
2111
2112 r2d_fill_arc(gc,r->start_angle,r->stop_angle,
2113 r->ul_x,r->ul_y,r->br_x,r->br_y);
2114 }
2115
2116 T_R2D_SHAPE_PTR r2d_new_rectangle_intersection(T_RVF_MB_ID bank,T_R2D_SHAPE_PTR a,T_R2D_SHAPE_PTR b)
2117 {
2118 if ( a && b && (((T_R2D_SHAPE*)a)->p_r2d_class==&r2d_class_rectangle)
2119 && (((T_R2D_SHAPE*)b)->p_r2d_class==&r2d_class_rectangle))
2120 {
2121 T_R2D_RECT *ra;
2122 T_R2D_RECT *rb;
2123 INT16 xa,ya,xb,yb;
2124
2125 ra=(T_R2D_RECT *)a;
2126 rb=(T_R2D_RECT *)b;
2127
2128 if (ra->ul_x>rb->ul_x)
2129 xa=ra->ul_x;
2130 else
2131 xa=rb->ul_x;
2132
2133 if (ra->ul_y>rb->ul_y)
2134 ya=ra->ul_y;
2135 else
2136 ya=rb->ul_y;
2137
2138 if (ra->br_x<rb->br_x)
2139 xb=ra->br_x;
2140 else
2141 xb=rb->br_x;
2142
2143 if (ra->br_y<rb->br_y)
2144 yb=ra->br_y;
2145 else
2146 yb=rb->br_y;
2147
2148 if ((xa<=xb) && (ya<=yb))
2149 return(r2d_new_rectangle(bank,xa,ya,xb,yb));
2150 else
2151 return(R2D_EMPTY_RECT);
2152
2153 }
2154 else return(NULL);
2155 }
2156
2157 T_R2D_SHAPE_PTR r2d_new_rectangle_union(T_RVF_MB_ID bank,T_R2D_SHAPE_PTR a,T_R2D_SHAPE_PTR b)
2158 {
2159 if ( a && b && (((T_R2D_SHAPE*)a)->p_r2d_class==&r2d_class_rectangle)
2160 && (((T_R2D_SHAPE*)b)->p_r2d_class==&r2d_class_rectangle))
2161 {
2162 T_R2D_RECTANGLE *ra;
2163 T_R2D_RECTANGLE *rb;
2164 INT16 xa,ya,xb,yb;
2165
2166 ra=(T_R2D_RECTANGLE *)a;
2167 rb=(T_R2D_RECTANGLE *)b;
2168
2169 if (ra->ul_x<rb->ul_x)
2170 xa=ra->ul_x;
2171 else
2172 xa=rb->ul_x;
2173
2174 if (ra->ul_y<rb->ul_y)
2175 ya=ra->ul_y;
2176 else
2177 ya=rb->ul_y;
2178
2179 if (ra->br_x>rb->br_x)
2180 xb=ra->br_x;
2181 else
2182 xb=rb->br_x;
2183
2184 if (ra->br_y>rb->br_y)
2185 yb=ra->br_y;
2186 else
2187 yb=rb->br_y;
2188
2189 if ((xa<=xb) && (ya<=yb))
2190 return(r2d_new_rectangle(bank,xa,ya,xb,yb));
2191 else
2192 return(R2D_EMPTY_RECT);
2193
2194 }
2195 else if (a)
2196 return(r2d_clone_shape(bank,a));
2197 else if (b)
2198 return(r2d_clone_shape(bank,b));
2199 else
2200 return(NULL);
2201 }
2202
2203 T_R2D_SHAPE_PTR r2d_new_text(T_RVF_MB_ID bank,INT16 x, INT16 y,T_R2D_UTF16 *the_text)
2204 {
2205 T_R2D_TEXT *r;
2206 R2D_MALLOC(bank,T_R2D_TEXT,sizeof(T_R2D_TEXT),r);
2207 if (r)
2208 {
2209 r->refcount=1;
2210 r->x=x;
2211 r->y=y;
2212 r->p_text=the_text;
2213 r->p_r2d_class=&r2d_class_text;
2214 } else r=NULL;
2215 return(r);
2216 }
2217
2218 T_R2D_SHAPE_PTR r2d_clone_text_shape(T_RVF_MB_ID bank,T_R2D_SHAPE* self)
2219 {
2220 T_R2D_TEXT *r;
2221 r=(T_R2D_TEXT *)self;
2222
2223 return(r2d_new_text(bank,r->x,r->y,NULL));
2224 }
2225
2226
2227 void r2d_release_text(T_R2D_SHAPE *self)
2228 {
2229 T_R2D_TEXT *r;
2230 r=(T_R2D_TEXT *)self;
2231
2232 r2d_release(r);
2233 }
2234
2235 void r2d_draw_text_shape(T_R2D_SHAPE *self,T_R2D_GC_PTR gc)
2236 {
2237 T_R2D_TEXT *r;
2238 r=(T_R2D_TEXT *)self;
2239 r2d_draw_text(gc,r->x,r->y,r->p_text);
2240 }
2241
2242 void r2d_fill_text_shape(T_R2D_SHAPE *self,T_R2D_GC_PTR gc)
2243 {
2244 // A text has no interior and thus cannot be filled.
2245 }
2246
2247
2248
2249
2250 ////////////////////////////////////////
2251 //
2252 // Clipping functions
2253 //
2254
2255 // Conversion is done such that line y = ymax and x=xmax MUST NOT
2256 // be drawn. So, they do not belong to the cliiping region
2257 // So, behavior of s_clipping_shape is using drawing convention
2258 // and not the clipping convention
2259 static T_R2D_SHAPE_PTR r2d_s_level(T_R2D_GC_PTR gc,T_R2D_SHAPE_PTR self)
2260 {
2261 T_R2D_SHAPE_PTR result;
2262 T_R2D_RECTANGLE *r;
2263
2264
2265 r=(T_R2D_RECTANGLE*)self;
2266
2267 if ((r) && (gc))
2268 {
2269
2270 result=r2d_clone_shape(r2d_mb_id,self);
2271 r=(T_R2D_RECTANGLE*)result;
2272
2273 r2d_local_to_global(gc,&(r->ul_x),&(r->ul_y));
2274 r2d_local_to_global(gc,&(r->br_x),&(r->br_y));
2275
2276 //r2d_mirror_clip_rectangle(gc,result);
2277 r2d_mirror_rectangle(gc,result);
2278 r=(T_R2D_RECTANGLE*)result;
2279
2280 #if (R2D_REFRESH != R2D_VERTICAL)
2281 r2d_diagonal_mirror(result);
2282 r=(T_R2D_RECTANGLE*)result;
2283 #endif
2284
2285 return(result);
2286 }
2287 else
2288 return(NULL);
2289 }
2290
2291 void r2d_set_clipping_shape(T_R2D_SHAPE_PTR self,T_R2D_GC_PTR gc)
2292 {
2293
2294 if ((self) && (((T_R2D_SHAPE*)self)->p_r2d_class==&r2d_class_rectangle))
2295 {
2296 T_R2D_RECT *r;
2297 INT16 orgx,orgy;
2298
2299 r=(T_R2D_RECT *)self;
2300
2301 r2d_get_context_origin(gc,&orgx,&orgy);
2302
2303 if (r->ul_x-orgx<0)
2304 r->ul_x=orgx;
2305
2306 if (r->ul_y-orgy<0)
2307 r->ul_y=orgy;
2308
2309 if (r->br_x-orgx>=r2d_get_width(gc))
2310 r->br_x=orgx+r2d_get_width(gc);
2311
2312 if (r->br_y-orgy>=r2d_get_height(gc))
2313 r->br_y=orgy+r2d_get_height(gc);
2314
2315
2316 {
2317 r2d_release_shape(((T_R2D_GC *)gc)->p_clipping_shape);
2318 ((T_R2D_GC *)gc)->p_clipping_shape=self;
2319 r2d_retain(self);
2320
2321 r2d_release_shape(((T_R2D_GC *)gc)->p_s_clipping_shape);
2322 ((T_R2D_GC *)gc)->p_s_clipping_shape=r2d_s_level(gc,self);
2323 }
2324 }
2325 }
2326
2327 T_R2D_SHAPE_PTR r2d_get_clipping_shape(T_R2D_GC_PTR gc)
2328 {
2329 return(((T_R2D_GC *)gc)->p_clipping_shape);
2330 }
2331
2332 T_R2D_ERROR r2d_restore_standard_clipping_shape(T_R2D_GC_PTR gc)
2333 {
2334 INT16 x,y;
2335 T_R2D_SHAPE_PTR s,sb;
2336 r2d_get_context_origin(gc,&x,&y);
2337 s=((T_R2D_GC *)gc)->p_clipping_shape;
2338 sb=((T_R2D_GC *)gc)->p_s_clipping_shape;
2339
2340 ((T_R2D_GC *)gc)->p_clipping_shape=r2d_new_rectangle(r2d_mb_id,x,y,x+r2d_get_width(gc),y+r2d_get_height(gc));
2341
2342 // No mirroring when shape is the whole LCD
2343 // Force use of global coordinates for s_ frame
2344 #if (R2D_REFRESH == R2D_VERTICAL)
2345 ((T_R2D_GC *)gc)->p_s_clipping_shape=
2346 r2d_new_rectangle(r2d_mb_id,0,0,r2d_get_width(gc),r2d_get_height(gc));
2347 #else
2348 ((T_R2D_GC *)gc)->p_s_clipping_shape=
2349 r2d_new_rectangle(r2d_mb_id,0,0,r2d_get_height(gc),r2d_get_width(gc));
2350 #endif
2351
2352
2353 if ((((T_R2D_GC *)gc)->p_clipping_shape==NULL)
2354 || (((T_R2D_GC *)gc)->p_s_clipping_shape==NULL))
2355 {
2356 if (((T_R2D_GC *)gc)->p_clipping_shape!=NULL)
2357 r2d_release_shape(((T_R2D_GC *)gc)->p_clipping_shape);
2358 if (((T_R2D_GC *)gc)->p_s_clipping_shape!=NULL)
2359 r2d_release_shape(((T_R2D_GC *)gc)->p_s_clipping_shape);
2360 ((T_R2D_GC *)gc)->p_clipping_shape=s;
2361 ((T_R2D_GC *)gc)->p_s_clipping_shape=sb;
2362 return(R2D_MEMORY_ERR);
2363 }
2364 else
2365 {
2366 r2d_release_shape(s);
2367 r2d_release_shape(sb);
2368 return(R2D_OK);
2369 }
2370 }
2371
2372
2373 ////////////////////////////////////////
2374 //
2375 // Graphical primitives
2376 //
2377
2378 // S COORDINATES
2379 static void r2d_s_fill_point(T_R2D_GC_PTR gc,INT16 x,INT16 y,INT16 pen_size)
2380 {
2381 INT16 ul_x,ul_y,br_x,br_y,bs,as;
2382 // UINT32 f,b;
2383
2384 bs=(pen_size>>1);
2385 as=(pen_size>>1) + (pen_size&1);
2386
2387 // Squares are not symetrically placed
2388 // since pen_size is not always odd
2389 // Mirroring must take it into account so that the
2390 // asymetry is also mirrored
2391 #ifdef R2D_MIRRORED_X
2392 ul_x=x-bs;
2393 br_x=x+as-1;
2394 #else
2395 ul_x=x-bs+1;
2396 br_x=x+as;
2397
2398 #endif
2399
2400 #ifdef R2D_MIRRORED_Y
2401 ul_y=y-bs;
2402 br_y=y+as-1;
2403 #else
2404 ul_y=y-bs+1;
2405 br_y=y+as;
2406 #endif
2407
2408 //printf("%d %d %d %d\n",ul_x,ul_y,br_x,br_y);
2409
2410
2411 r2d_s_fill_rectangle(gc,ul_x-1,ul_y-1,br_x+1,br_y+1,FALSE);
2412
2413 }
2414
2415 // Draw point in gc at position (x,y)
2416 // S COORDINATES
2417 static void r2d_s_draw_point(T_R2D_GC_PTR gc,INT16 x,INT16 y,INT32 l)
2418 {
2419 UINT32 pixel_value;
2420 INT16 pen_size;
2421 BOOLEAN isLCD_format,can_draw;
2422 T_R2D_GC* pgc;
2423
2424 can_draw=FALSE;
2425
2426 if (r2d_dash_enabled(gc))
2427 {
2428 // Q16, 0x0008000 is 8 pixels
2429 if (!(l&0x00080000))
2430 can_draw=TRUE;
2431 }
2432 else
2433 can_draw=TRUE;
2434
2435 if (can_draw==TRUE)
2436 {
2437 pgc=(T_R2D_GC*)gc;
2438
2439 isLCD_format=((T_R2D_FRAMEBUFFER*)(((T_R2D_GC*)gc)->p_frame_buffer))->kind!=R2D_FULL_KIND;
2440
2441
2442 pen_size=r2d_get_pen_size(gc);
2443
2444
2445 if (r2d_point_in_shape(((T_R2D_GC*)gc)->p_s_clipping_shape,x,y))
2446 {
2447
2448
2449 if (pen_size>1)
2450 r2d_s_fill_point(gc,x,y,pen_size);
2451
2452
2453 else
2454 {
2455 // Dithering is relative to global coordinate system
2456
2457
2458 // Color is recomputed only when dithering is on
2459 #if (R2D_DITHERING == R2D_ON)
2460 if (isLCD_format)
2461 pixel_value=r2d_get_dithering_matrix_entry(((T_R2D_GC*)gc)->p_foreground_dithered_cache,x,y);
2462 else
2463 pixel_value=((T_R2D_GC*)gc)->foreground_pixel_value;
2464 #else
2465 pixel_value=((T_R2D_GC*)gc)->foreground_pixel_value;
2466 #endif
2467
2468 // Low level pixel drawing routine with CONVERTED color value
2469
2470 IND_r2d_write_lcd_pixel(gc,x,y,pixel_value);
2471
2472 }
2473 }
2474
2475 r2d_check_and_send_event(gc);
2476 }
2477 }
2478
2479 // Draw point in gc at position (x,y)
2480 // H COORDINATES
2481 void r2d_draw_point(T_R2D_GC_PTR gc,INT16 x,INT16 y)
2482 {
2483 if (r2d_point_in_shape(((T_R2D_GC*)gc)->p_clipping_shape,x,y))
2484 {
2485 r2d_local_to_global(gc,&x,&y);
2486
2487 #ifdef R2D_MIRRORED_X
2488 x=r2d_get_width(gc)-1-x;
2489 #endif
2490
2491 #ifdef R2D_MIRRORED_Y
2492 y=r2d_get_height(gc)-1-y;
2493 #endif
2494
2495
2496
2497
2498 if (((T_R2D_FRAMEBUFFER*)((T_R2D_GC*)gc)->p_frame_buffer)->kind==0)
2499 r2d_update_region((T_R2D_GC*)gc,x,y,x,y);
2500 #if (R2D_REFRESH == R2D_VERTICAL)
2501 r2d_s_draw_point(gc,x,y,0);
2502 #else
2503 r2d_s_draw_point(gc,y,x,0);
2504 #endif
2505
2506 }
2507 }
2508
2509 void r2d_erase_point(T_R2D_GC_PTR gc,INT16 x,INT16 y)
2510 {
2511
2512 T_R2D_ARGB_COLOR col;
2513
2514
2515 if (r2d_point_in_shape(((T_R2D_GC*)gc)->p_clipping_shape,x,y))
2516 {
2517 r2d_local_to_global(gc,&x,&y);
2518 col=r2d_get_foreground_color(gc);
2519 r2d_set_foreground_color(gc,r2d_get_background_color(gc));
2520
2521 #ifdef R2D_MIRRORED_X
2522 x=r2d_get_width(gc)-1-x;
2523 #endif
2524
2525 #ifdef R2D_MIRRORED_Y
2526 y=r2d_get_height(gc)-1-y;
2527
2528 #endif
2529
2530
2531 if (((T_R2D_FRAMEBUFFER*)((T_R2D_GC*)gc)->p_frame_buffer)->kind==0)
2532 r2d_update_region((T_R2D_GC*)gc,x,y,x,y);
2533
2534 #if (R2D_REFRESH == R2D_VERTICAL)
2535 r2d_s_draw_point(gc,x,y,0);
2536 #else
2537 r2d_s_draw_point(gc,y,x,0);
2538 #endif
2539
2540 r2d_set_foreground_color(gc,col);
2541 }
2542
2543
2544 }
2545
2546 // Move pen to point (x,y)
2547 // H_COORDINATES
2548 void r2d_moveto(T_R2D_GC_PTR gc,INT16 x,INT16 y)
2549 {
2550 ((T_R2D_GC*)gc)->pen_x=x;
2551 ((T_R2D_GC*)gc)->pen_y=y;
2552 }
2553
2554
2555 static BOOLEAN r2d_clipt(INT32 denom,INT32 num,INT32 *tE,INT32 *tL)
2556 {
2557 INT32 t;
2558
2559 //printf("clipt %08X %08X\n",denom,num);
2560 if (denom<0)
2561 {
2562 t=r2d_fixed_division(num,denom);
2563 //printf("denom<0 ; t=%08X\n",t);
2564 if (t>*tL)
2565 return FALSE;
2566 else if (t > *tE)
2567 *tE=t;
2568 }
2569 else if (denom>0)
2570 {
2571 t=r2d_fixed_division(num,denom);
2572 //printf("denom>0 ; t=%08X\n",t);
2573 if (t<*tE)
2574 return FALSE;
2575 else if (t < *tL)
2576 *tL=t;
2577 } else if (num<0)
2578 return FALSE;
2579
2580 //printf("t=%08X tE=%08X tL=%08X\n",t,*tE,*tL);
2581 return TRUE;
2582 }
2583
2584 static BOOLEAN r2d_clip_line(T_R2D_SHAPE *self,INT32 *x0,INT32 *y0,INT32 *x1, INT32 *y1)
2585 {
2586 T_R2D_RECTANGLE *r;
2587 BOOLEAN visible=FALSE;
2588 INT32 dx=*x1-*x0;
2589 INT32 dy=*y1-*y0;
2590
2591 r=(T_R2D_RECTANGLE*)self;
2592
2593 // Can only clip against reactangular shapes
2594 if (self->p_r2d_class==&r2d_class_rectangle)
2595 {
2596
2597 if ((dx==0) && (dy==0) && r2d_point_in_shape(self,(*x0>>16) & 0x0FFFF,(*y0>>16) & 0x0FFFF))
2598 visible=TRUE;
2599 else
2600 {
2601 INT32 tE=0;
2602 INT32 tL=(1<<16);
2603
2604
2605 if (r2d_clipt(dx,((r2d_get_xmax(self)-1)<<16)-*x0,&tE,&tL)==TRUE)
2606 if (r2d_clipt(-dx,*x0-(r2d_get_xmin(self)<<16),&tE,&tL)==TRUE)
2607 if (r2d_clipt(-dy,*y0-(r2d_get_ymin(self)<<16),&tE,&tL)==TRUE)
2608 if (r2d_clipt(dy,((r2d_get_ymax(self)-1)<<16) -*y0,&tE,&tL)==TRUE)
2609 {
2610 visible=TRUE;
2611
2612 //printf("tE=%08X tL=%08X\n",tE,tL);
2613 // 1 with fixed point representation
2614 if (tL < (1<<16))
2615 {
2616 // dx and dy are integer
2617 // tL and tE should be lower than 1
2618 // So intermediate values are shifted so that
2619 // the product can be done on 32 bits instead of 64 bits
2620 *x1=*x0 + (tL*(dx>>16)) ;
2621 *y1=*y0 + (tL*(dy>>16)) ;
2622 //printf("x1=%08X y1=%08X\n",*x1,*y1);
2623 }
2624 if (tE > 0)
2625 {
2626 *x0 += (tE*(dx>>16)) ;
2627 *y0 += (tE*(dy>>16)) ;
2628 //printf("x0=%08X y0=%08X\n",*x0,*y0);
2629
2630 }
2631 }
2632 }
2633 }
2634 return(visible);
2635 }
2636
2637 // 0.5 is rounded down because in line drawing the bottom
2638 // point is chosen when the line is passing through the middle
2639 // point
2640 #define R2D_Q16INT_VALUE(x) ((x+(0x7FFF)) & 0xFFFF0000)
2641
2642 #define R2D_FLOOR_VALUE(x) (x & 0xFFFF0000)
2643
2644 // Positive times signed value
2645 #define R2D_MULT_PN(x,y) ((((x >> 16) & 0x0FFFF)*y) + (((x & 0x0FFFF) * y) >> 16))
2646
2647 // draw line from pen position to point (x,y)
2648 void r2d_lineto(T_R2D_GC_PTR gc,INT16 x,INT16 y)
2649 {
2650 // Clipping
2651 // Now drawing with low level function
2652
2653 UINT32 pixel_value;
2654 INT32 P0X,P0Y,P1X,P1Y,c,cy,cx;
2655 INT32 current_x,current_y,tmp,tmpx,tmpy;
2656 INT32 dx,dy,dn,dnp,dnn;
2657 INT16 xincrement,yincrement,reverse;
2658 INT32 nx,ny;
2659 INT16 pen_size;
2660 INT32 l;
2661 BOOLEAN isLCD_format;
2662 l=0;
2663
2664
2665
2666 isLCD_format=((T_R2D_FRAMEBUFFER*)(((T_R2D_GC*)gc)->p_frame_buffer))->kind!=R2D_FULL_KIND;
2667
2668 pixel_value=((T_R2D_GC*)gc)->foreground_pixel_value;
2669 pen_size=r2d_get_pen_size(gc);
2670
2671 P0X=((T_R2D_GC*)gc)->pen_x << 16;
2672 P0Y=((T_R2D_GC*)gc)->pen_y << 16;
2673 P1X=x << 16;
2674 P1Y=y << 16;
2675 //printf("\n\n(%d,%d) ; (%d,%d)\n",P0X>>16,P0Y>>16,P1X>>16,P1Y>>16);
2676
2677 // As far as possible, most datas are computed before clipping to get same accuracy
2678 // Update pen position
2679 ((T_R2D_GC*)gc)->pen_x=x;
2680 ((T_R2D_GC*)gc)->pen_y=y;
2681
2682 if (r2d_clip_line((((T_R2D_GC*)gc)->p_clipping_shape),&P0X,&P0Y,&P1X,&P1Y))
2683 {
2684
2685 // Local to global
2686
2687 P0X-=((T_R2D_GC*)gc)->org_x << 16;
2688 P0Y-=((T_R2D_GC*)gc)->org_y << 16;
2689 P1X-=((T_R2D_GC*)gc)->org_x << 16;
2690 P1Y-=((T_R2D_GC*)gc)->org_y << 16;
2691
2692
2693 #ifdef R2D_MIRRORED_X
2694 P0X=((r2d_get_width(gc)-1)<<16)-P0X;
2695 P1X=((r2d_get_width(gc)-1)<<16)-P1X;
2696 #endif
2697
2698 #ifdef R2D_MIRRORED_Y
2699 P0Y=((r2d_get_height(gc)-1)<<16)-P0Y;
2700 P1Y=((r2d_get_height(gc)-1)<<16)-P1Y;
2701 #endif
2702
2703
2704 /*printf("%d %d %d %d\n",r2d_get_xmin(((T_R2D_GC*)gc)->p_clipping_shape),
2705 r2d_get_xmax(((T_R2D_GC*)gc)->p_clipping_shape),
2706 r2d_get_ymin(((T_R2D_GC*)gc)->p_clipping_shape),
2707 r2d_get_ymax(((T_R2D_GC*)gc)->p_clipping_shape)
2708 );*/
2709
2710 //r2d_clip_line(&(((T_R2D_GC*)gc)->clipping_rectangle),&P0X,&P0Y,&P1X,&P1Y);
2711
2712 //printf("(%d,%d) ; (%d,%d)\n",P0X>>16,P0Y>>16,P1X>>16,P1Y>>16);
2713 //printf("(%08X,%08X) ; (%08X,%08X)\n------------------\n",P0X,P0Y,P1X,P1Y);
2714
2715 //printf("(%d,%d) ; (%d,%d)\n",P0X>>16,P0Y>>16,P1X>>16,P1Y>>16);
2716
2717 if (((T_R2D_FRAMEBUFFER*)((T_R2D_GC*)gc)->p_frame_buffer)->kind==0)
2718 r2d_update_region((T_R2D_GC*)gc,P0X>>16,P0Y>>16,P1X>>16,P1Y>>16);
2719
2720
2721 #if (R2D_REFRESH==R2D_VERTICAL)
2722 current_x=P0Y;
2723 current_y=P0X;
2724 nx=P1Y; ny=P1X;
2725
2726
2727 #else
2728 current_x=P0X;
2729 current_y=P0Y;
2730 nx=P1X; ny=P1Y;
2731 #endif
2732
2733 dx=nx-current_x;
2734 dy=ny-current_y;
2735
2736 yincrement=1;
2737
2738 if (dx>=0)
2739 {
2740 xincrement=1;
2741 }
2742 else
2743 {
2744 xincrement=-1;
2745 dx=-dx;
2746 }
2747
2748 if (dy>=0)
2749 {
2750 yincrement=1;
2751 }
2752 else
2753 {
2754 yincrement=-1;
2755 dy=-dy;
2756 }
2757
2758 if (dy<=dx)
2759 reverse=0;
2760 else
2761 {
2762 reverse=1;
2763 tmp=dy;
2764 dy=dx;
2765 dx=tmp;
2766 tmp=current_y;
2767 current_y=current_x;
2768 current_x=tmp;
2769 tmp=ny;
2770 ny=nx;
2771 nx=tmp;
2772 tmp=yincrement;
2773 yincrement=xincrement;
2774 xincrement=tmp;
2775 }
2776
2777 reverse=1-reverse;
2778
2779
2780 //printf("dx,dy,current_x,current_y,nx,ny\n%08X %08X %08X %08X %08X %08X\n",dx,dy,current_x,current_y,nx,ny);
2781
2782
2783 // Remember that when one is speaking about a move of 1 horizontally
2784 // one is talking about internal coordinates used by the algorithm
2785 // In the window it may be vertical or horizontal depending on the
2786 // refresh mode and on the line slope (<1 or >1)
2787
2788
2789 dn=dy - (dx >> 1) ; // d0 = a-b/2
2790 dnp=dy-dx ;
2791 dnn=dy;
2792
2793 // We draw the point which is the closest to the line so we use INT
2794 // instead of FLOOR or CEIL
2795 // But, then, the drawing algorithm assumes that the first drawn point is
2796 // the lowest one
2797
2798 // If F(P) = 0 is a parametric description of the line
2799 // The, when one is moving from the point of the line on the frontier
2800 // of the clipping rectangle to the closest
2801 // point with x,y integer coordinate then one needs to compute dx*cy and dy*cx
2802 // since it is the variation of F along that path
2803 tmpx=(INT32)R2D_Q16INT_VALUE(current_x);
2804 tmpy=(INT32)R2D_Q16INT_VALUE(current_y);
2805 cx = current_x - tmpx;
2806 cy = current_y - tmpy;
2807
2808
2809 c= -R2D_MULT_PN(dx,cy) + R2D_MULT_PN(dy,cx);
2810
2811
2812 //printf("cx=%08X, cy=%08X, c=%08X, dx=%08X, dy=%08X \n",cx,cy,c,dx,dy);
2813
2814 // Then, one can add c to the variation due to a move of 1 horizontally
2815 // an a move of 1/2 vertically.
2816 // One finally get the value of the decision variable at the midpoint
2817 dn+=c;
2818
2819 //printf("%08X %08X %08X %08X %08X\n",current_x,current_y,nx,ny);
2820 current_x=((INT32)R2D_Q16INT_VALUE(current_x)) >> 16;
2821 current_y=((INT32)R2D_Q16INT_VALUE(current_y)) >> 16;
2822 nx=((INT32)R2D_Q16INT_VALUE(nx)) >> 16;
2823 ny=((INT32)R2D_Q16INT_VALUE(ny)) >> 16;
2824
2825
2826 //printf("dx=%08X dy=%08X dn=%08X dnp=%08X dnn=%08X\n",dx,dy,dn,dnp,dnn);
2827
2828 if (reverse)
2829 {
2830 r2d_s_draw_point(gc,current_y,current_x,l);
2831
2832 }
2833 else
2834 {
2835 r2d_s_draw_point(gc,current_x,current_y,l);
2836 }
2837
2838
2839
2840 while(current_x != nx)
2841 {
2842
2843 if (dn>0)
2844 {
2845 dn += dnp;
2846 current_y+=yincrement;
2847 l=l+SQRT2;
2848 }
2849 else if (dn<0)
2850 {
2851 dn += dnn;
2852 l=l+0x10000;
2853 }
2854 else
2855 {
2856 if (xincrement<0)
2857 {
2858 dn += dnp;
2859 current_y+=yincrement;
2860 l=l+SQRT2;
2861 }
2862 else
2863 {
2864 dn += dnn;
2865 l=l+0x10000;
2866 }
2867 }
2868
2869 current_x+=xincrement;
2870 //printf(" -->%08X %d %d\n",dn,current_x,current_y);
2871 // Color is recomputed only when dithering is on
2872
2873
2874 if (reverse)
2875 {
2876
2877 r2d_s_draw_point(gc,current_y,current_x,l);
2878 }
2879 else
2880 {
2881 r2d_s_draw_point(gc,current_x,current_y,l);
2882 }
2883 }
2884 } // END CLIPPING
2885
2886 //printf("END LINE\n");
2887
2888
2889 r2d_check_and_send_event(gc);
2890 }
2891
2892 // Used for filling
2893 // Do clipping and coordinate transforms then call
2894 // low levl line filling algorithm
2895 // No mirroring check since it is a low level routine
2896 // S COORDINATES
2897 static void r2d_s_fill_line(T_R2D_GC_PTR gc,INT16 x,INT16 y,INT16 nb,BOOLEAN background)
2898 {
2899 T_R2D_SHAPE_PTR clip;
2900 T_R2D_RECTANGLE *r;
2901 // INT16 tmp;
2902
2903 clip=((T_R2D_GC*)gc)->p_s_clipping_shape;
2904 r=(T_R2D_RECTANGLE*)clip;
2905
2906
2907 if ((x>=r2d_get_xmin(clip)) && ( x<r2d_get_xmax(clip)))
2908 {
2909 if (y<r2d_get_ymin(clip))
2910 {
2911 nb-=r2d_get_ymin(clip)-y;
2912 y=r2d_get_ymin(clip);
2913 }
2914
2915 if (y+nb-1>=r2d_get_ymax(clip))
2916 nb=r2d_get_ymax(clip)-y;
2917
2918 if (nb>0)
2919
2920 IND_r2d_write_lcd_line(gc,x,y,nb,background);
2921 }
2922
2923
2924 }
2925
2926 // Used for filling
2927 // Do clipping and coordinate transforms then call
2928 // low levl line filling algorithm
2929 // No mirroring check since it is a low level routine
2930 // S COORDINATES
2931 static void r2d_s_arc_fill_line(T_R2D_GC_PTR gc,INT16 x,INT16 y,
2932 INT16 org_x,INT16 org_y,INT16 nb,T_R2D_ARC_REGION *rgn,BOOLEAN background)
2933 {
2934 T_R2D_SHAPE_PTR clip;
2935 T_R2D_RECTANGLE *r;
2936 // INT16 tmp;
2937
2938 clip=((T_R2D_GC*)gc)->p_s_clipping_shape;
2939 r=(T_R2D_RECTANGLE*)clip;
2940
2941
2942 if ((x>=r2d_get_xmin(clip)) && ( x<r2d_get_xmax(clip)))
2943 {
2944 if (y<r2d_get_ymin(clip))
2945 {
2946 nb-=r2d_get_ymin(clip)-y;
2947 y=r2d_get_ymin(clip);
2948 }
2949
2950 if (y+nb-1>=r2d_get_ymax(clip))
2951 nb=r2d_get_ymax(clip)-y;
2952
2953 if (nb>0)
2954
2955 r2d_arc_write_lcd_line(gc,x,y,org_x,org_y,nb,rgn,background);
2956 }
2957
2958
2959 }
2960
2961 // S coordinates
2962 static void r2d_s_fill_rectangle(T_R2D_GC_PTR gc,
2963 INT16 ul_x,INT16 ul_y,INT16 br_x, INT16 br_y,BOOLEAN background)
2964 {
2965
2966 INT16 i;
2967 // The ifdef is not passing the coordinates to S frame.
2968 // It just changing the way the square is scanned
2969 // to improve behavior relatively to the scanning mode.
2970 for(i=ul_x+1;i<=br_x-1;i++)
2971 {
2972 r2d_s_fill_line(gc,i,ul_y+1,(br_y-ul_y)+1-2,background);
2973 }
2974
2975 }
2976
2977 // Background allows to chose the color for filling
2978 // If TRUE, background color is used
2979 // (required for pen_size different from 1)
2980 // L coordinates
2981 static void r2d_df_rectangle(T_R2D_GC_PTR gc,
2982 INT16 ul_x,INT16 ul_y,INT16 br_x, INT16 br_y,BOOLEAN background)
2983 {
2984
2985 INT16 i;
2986 // The ifdef is not passing the coordinates to S frame.
2987 // It just changing the way the square is scanned
2988 // to improve behavior relatively to the scanning mode.
2989 #if (R2D_REFRESH==R2D_VERTICAL)
2990 for(i=ul_x+1;i<=br_x-1;i++)
2991 {
2992 r2d_s_fill_line(gc,i,ul_y+1,(br_y-ul_y)+1-2,background);
2993 }
2994 #else
2995 for(i=ul_y+1;i<=br_y-1;i++)
2996 {
2997 r2d_s_fill_line(gc,i,ul_x+1,(br_x-ul_x)+1-2,background);
2998 }
2999 #endif
3000 }
3001
3002 void r2d_draw_rectangle(T_R2D_GC_PTR gc,
3003 INT16 ul_x,INT16 ul_y,INT16 br_x, INT16 br_y)
3004 {
3005
3006
3007 r2d_moveto(gc,ul_x,ul_y);
3008 r2d_lineto(gc,br_x,ul_y);
3009
3010
3011 r2d_moveto(gc,br_x,ul_y+1);
3012 r2d_lineto(gc,br_x,br_y);
3013
3014
3015 r2d_moveto(gc,br_x-1,br_y);
3016 r2d_lineto(gc,ul_x,br_y);
3017
3018
3019 r2d_moveto(gc,ul_x,ul_y+1);
3020 r2d_lineto(gc,ul_x,br_y-1);
3021
3022 }
3023
3024 void r2d_fill_rectangle(T_R2D_GC_PTR gc,
3025 INT16 ul_x,INT16 ul_y,INT16 br_x, INT16 br_y)
3026 {
3027 #ifdef R2D_MIRRORED_X
3028 INT16 tmp;
3029 #endif
3030 r2d_local_to_global(gc,&ul_x,&ul_y);
3031 r2d_local_to_global(gc,&br_x,&br_y);
3032
3033
3034 #ifdef R2D_MIRRORED_X
3035 ul_x = r2d_get_width(gc)-1-ul_x;
3036 br_x = r2d_get_width(gc)-1-br_x;
3037 R2D_SWAP(ul_x,br_x);
3038 #endif
3039
3040 #ifdef R2D_MIRRORED_Y
3041 ul_y = r2d_get_height(gc)-1-ul_y;
3042 br_y = r2d_get_height(gc)-1-br_y;
3043 R2D_SWAP(ul_y,br_y);
3044 #endif
3045 r2d_df_rectangle(gc,ul_x,ul_y,br_x,br_y,TRUE);
3046 if (((T_R2D_FRAMEBUFFER*)((T_R2D_GC*)gc)->p_frame_buffer)->kind==0)
3047 r2d_update_region((T_R2D_GC*)gc,ul_x,ul_y,br_x,br_y);
3048
3049 r2d_check_and_send_event(gc);
3050 }
3051
3052
3053
3054 void r2d_df_circle(T_R2D_GC_PTR gc,
3055 INT16 x,INT16 y,INT16 r,BOOLEAN filling)
3056 {
3057 INT32 current_x,current_y,my,mx;
3058 INT32 dn,dnp,dnn,org_x,org_y,limit,rs,tmp,D_yx;
3059 INT32 l;
3060 INT32 p; // perimeter divided by 4
3061
3062 l=0;
3063
3064 p=(PI*r)>>1;
3065
3066
3067 #if (R2D_REFRESH==R2D_VERTICAL)
3068 current_x=y;
3069 current_y=x+r;
3070 org_x=y;
3071 org_y=x;
3072
3073 #else
3074 current_x=x;
3075 current_y=y+r;
3076 org_x=x;
3077 org_y=y;
3078 #endif
3079
3080 D_yx=org_y-org_x;
3081
3082 dnp=((-r) << 1) + 5;
3083 dnn=3;
3084 dn=-r;
3085 rs=r*r;
3086 limit=-r;
3087
3088
3089
3090
3091
3092 tmp=1;
3093 while(limit<=0)
3094 {
3095
3096 // Some points are their own image with symetries
3097 // and yet they must not be drawn twice for drawing
3098 // modes other than copy hence the tests
3099
3100 my=(org_y << 1) - current_y;
3101 mx=(org_x << 1) - current_x;
3102
3103 // PY or PX is reflection relatively to horizontal line or vertical line
3104 // PY = vertical mirroring where bottom becomes top
3105
3106 // D = diagonal mirroring
3107
3108 // AB means apply transform A then B
3109
3110 // I is identity
3111
3112 // Everything is done relatively to what is displayed on the LCD
3113 // so my may be PX according to the refresh mode
3114
3115
3116 if (!filling)
3117 {
3118 if (mx != current_x)
3119 {
3120 r2d_s_draw_point(gc,current_y,current_x,l); // I : 3
3121 r2d_s_draw_point(gc,mx+D_yx,current_y-D_yx,l); // D PX : 5
3122 r2d_s_draw_point(gc,my,mx,l); // PX.PY : 7
3123 r2d_s_draw_point(gc,current_x+D_yx,my-D_yx,l); // D PY : 1
3124 }
3125
3126 if (current_x != current_y)
3127 {
3128 r2d_s_draw_point(gc,current_x+D_yx,current_y-D_yx,l+p); // D : 4
3129 r2d_s_draw_point(gc,current_y,mx,l+p); // PY : 2
3130 }
3131
3132 if ((mx != my) || (current_x != current_y))
3133 r2d_s_draw_point(gc,my,current_x,l+p); // PX : 6
3134
3135
3136 if (mx != my)
3137 r2d_s_draw_point(gc,mx+D_yx,my-D_yx,l+p); // D PX PY : 8
3138
3139 }
3140 else
3141 {
3142 //printf("%d\n",current_x);
3143 if (tmp)
3144 {
3145 if (current_x-mx!=0)
3146 {
3147 r2d_s_fill_line(gc,my,mx+1,(current_x-mx)+1-2,TRUE);
3148 r2d_s_fill_line(gc,current_y,mx+1,(current_x-mx)+1-2,TRUE);
3149 }
3150 }
3151 if (mx != my)
3152 {
3153 r2d_s_fill_line(gc,mx+D_yx,my+1-D_yx,(current_y-my)+1-2,TRUE);
3154 if (current_x != mx);
3155 r2d_s_fill_line(gc,current_x+D_yx,my+1-D_yx,(current_y-my)+1-2,TRUE);
3156 }
3157 }
3158
3159
3160 if (dn>0) // M outside circle, point below must be drawn
3161 {
3162 dn+=dnp;
3163 dnp+=4;
3164
3165 current_y--;
3166 l+=SQRT2;
3167 limit+=2;
3168 tmp=1;
3169 }
3170 else
3171 {
3172 dn+=dnn;
3173 dnp+=2;
3174 limit+=1;
3175 tmp=0;
3176 l+=0x10000;
3177 }
3178
3179 current_x++;
3180 dnn+=2;
3181
3182
3183
3184
3185 }
3186 //printf("%08X\n",limit);
3187 }
3188
3189 void r2d_draw_circle(T_R2D_GC_PTR gc,
3190 INT16 x,INT16 y,INT16 r)
3191 {
3192
3193 r2d_local_to_global(gc,&x,&y);
3194
3195
3196 #ifdef R2D_MIRRORED_X
3197 x = r2d_get_width(gc)-1-x;
3198 #endif
3199
3200 #ifdef R2D_MIRRORED_Y
3201 y = r2d_get_height(gc)-1-y;
3202 #endif
3203
3204
3205 r2d_df_circle(gc,x,y,r,FALSE);
3206 if (((T_R2D_FRAMEBUFFER*)((T_R2D_GC*)gc)->p_frame_buffer)->kind==0)
3207 r2d_update_region((T_R2D_GC*)gc,x-r,y-r,x+r,y+r);
3208 r2d_check_and_send_event(gc);
3209 }
3210
3211 void r2d_fill_circle(T_R2D_GC_PTR gc,
3212 INT16 x,INT16 y,INT16 r)
3213 {
3214 r2d_local_to_global(gc,&x,&y);
3215
3216 #ifdef R2D_MIRRORED_X
3217 x = r2d_get_width(gc)-1-x;
3218 #endif
3219
3220 #ifdef R2D_MIRRORED_Y
3221 y = r2d_get_height(gc)-1-y;
3222 #endif
3223
3224 r2d_df_circle(gc,x,y,r,TRUE);
3225 if (((T_R2D_FRAMEBUFFER*)((T_R2D_GC*)gc)->p_frame_buffer)->kind==0)
3226 r2d_update_region((T_R2D_GC*)gc,x-r,y-r,x+r,y+r);
3227 r2d_check_and_send_event(gc);
3228 }
3229
3230
3231
3232 // h and v are used to draw roundrectangle (each piece of the ellipse must be
3233 // separated from other parts)
3234 void r2d_df_ellipse(T_R2D_GC_PTR gc,
3235 INT16 ul_x,INT16 ul_y,INT16 br_x, INT16 br_y, INT16 h,INT16 v,BOOLEAN filling)
3236 {
3237 INT32 current_x,current_y,limit,newx,newy,org_x,org_y;
3238 INT32 dn,dnp,dnn,as,bs,tmp,a,b,mx,my,lastx,lasty,round;
3239 INT32 l;
3240 l=0;
3241
3242 if ((h!=0) || (v!=0))
3243 round=1;
3244 else
3245 round=0;
3246
3247
3248 // Width of rectangle is assumed to be even
3249 // and it is forced to even dimension
3250
3251
3252 #if (R2D_REFRESH==R2D_VERTICAL)
3253 org_x=(ul_y + br_y)>>1;
3254 org_y=(br_x + ul_x)>>1;
3255 a=(br_y-ul_y)>>1;
3256 as=R2D_SQUARE_P(a);
3257 b=(br_x-ul_x)>>1;
3258 bs=R2D_SQUARE_P(b);
3259
3260 current_x=org_x ;
3261 current_y=org_y+b;
3262 newx=org_y;
3263 newy=org_x+a;
3264
3265 #else
3266 org_x=(ul_x + br_x)>>1;
3267 org_y=(br_y + ul_y)>>1;
3268
3269 b=(br_y-ul_y)>>1;
3270 bs=R2D_SQUARE_P(b);
3271 a=(br_x-ul_x)>>1;
3272 as=R2D_SQUARE_P(a);
3273
3274 current_x=org_x;
3275 current_y=org_y+b;
3276 newx=org_y;
3277 newy=org_x+a;
3278 R2D_SWAP(h,v);
3279
3280 #endif
3281
3282 // Now, shift by 2 to have the accuracy required by division by four
3283
3284
3285 //printf("current_x=%d, current_y=%d,as=%08X bs=%08X\n",current_x,current_y,as,bs);
3286
3287
3288 // New shift by 2 because one needs to compute quarter of values
3289 bs<<=2; as <<=2;b<<=2;a<<=2;
3290
3291 limit = - ((as * b) >> 2); // -a^2 * b in Q2
3292
3293 tmp=-((as * b) >> 2);
3294 dnp=(bs << 1) + bs + (tmp<<1) + (as << 1);
3295 dnn=(bs << 1) + bs;
3296 dn=bs + tmp + (as >>2);
3297
3298
3299
3300 //printf("dn=%f dnp=%f dnn=%f\n",dn / 8.0,dnp / 8.0,dnn / 8.0);
3301
3302 /*#if (R2D_REFRESH==R2D_VERTICAL)
3303 r2d_draw_point(gc,current_y,current_x);
3304 #else
3305 r2d_draw_point(gc,current_x,current_y);
3306 #endif*/
3307
3308 //printf("as=%08X bs=%08X\n",as,bs);
3309
3310 tmp=1;
3311 while(limit<=0)
3312 {
3313 my=(org_y << 1) - current_y;
3314 mx=(org_x << 1) - current_x;
3315
3316 lastx=current_y;
3317 lasty=current_x;
3318
3319 if (!filling)
3320 {
3321 r2d_s_draw_point(gc,(current_y)+h,(current_x)+v,l); // I : 1
3322 r2d_s_draw_point(gc,my,mx,l); // PX PY : 2
3323
3324 if ((mx != current_x) || (round))
3325 {
3326 r2d_s_draw_point(gc,(current_y)+h,mx,l); // PY : 3
3327 r2d_s_draw_point(gc,my,current_x+v,l); // PX : 4
3328 }
3329 }
3330 else
3331 {
3332 if (tmp)
3333 {
3334
3335 // Used to remove point on horizontal extremity
3336 if (current_x+v-mx !=0)
3337 {
3338 r2d_s_fill_line(gc,my,mx+1,(current_x+v-mx)+1-2,TRUE);
3339 r2d_s_fill_line(gc,current_y+h,mx+1,(current_x+v-mx)+1-2,TRUE);
3340 }
3341 }
3342 }
3343
3344 if (dn>=0) // M outside circle, point below must be drawn
3345 {
3346 dn+=dnp;
3347 dnp+=((bs + as) << 1);
3348 current_y--;
3349 limit+=(as + bs);
3350 tmp=1;
3351 l+=SQRT2;
3352 }
3353 else
3354
3355 {
3356 dn+=dnn;
3357 dnp+=(bs << 1);
3358 limit+=bs;
3359 tmp=0;
3360 l+=0x10000;
3361
3362 }
3363 current_x++;
3364 dnn+=(bs << 1);
3365
3366
3367 //printf("limit=%f, dn=%f,dnn=%f,dnp=%f, pos= %d %d\n",limit / 4.0,dn / 4.0,dnn / 4.0,dnp /
3368 //4.0,current_y,current_x);
3369
3370
3371 }
3372
3373 current_x=newx;
3374 current_y=newy;
3375 R2D_SWAP(as,bs);
3376 R2D_SWAP(a,b);
3377
3378 limit = - ((as * b) >> 2);
3379
3380 tmp=-((as * b) >> 2);
3381 dnp=(bs << 1) + bs + (tmp<<1) + (as << 1);
3382 dnn=(bs << 1) + bs;
3383 dn=bs + tmp + (as >>2);
3384
3385 //printf("newx=%d, newy=%d,a=%d,b=%d\n",newx,newy,a,b);
3386 //printf("dn=%f dnp=%f dnn=%f\n",dn / 4.0,dnp / 4.0,dnn / 4.0);
3387
3388 tmp=1;
3389
3390 /* #if (R2D_REFRESH==R2D_VERTICAL)
3391 r2d_draw_point(gc,current_x,current_y);
3392 #else
3393 r2d_draw_point(gc,current_y,current_x);
3394 #endif*/
3395
3396 while(limit<0)
3397 {
3398
3399 my=(org_x << 1) - current_y;
3400 mx=(org_y << 1) - current_x;
3401
3402 if (!filling)
3403 {
3404 if ((lastx!=current_x) || (lasty!=current_y))
3405 {
3406
3407 r2d_s_draw_point(gc,(current_x)+h,(current_y)+v,l); // D : 5
3408
3409
3410 r2d_s_draw_point(gc,mx,my,l); // D PX PY : 6
3411
3412 if ((mx != (current_x+h)) || (round))
3413 {
3414 r2d_s_draw_point(gc,(current_x)+h,my,l); // D PY : 7
3415 r2d_s_draw_point(gc,mx,(current_y)+v,l); // D PX : 8
3416 }
3417
3418 }
3419 }
3420 else
3421 {
3422 if (current_x != lastx)
3423 {
3424 r2d_s_fill_line(gc,mx,my+1,(current_y+v-my)+1-2,TRUE);
3425 if ((current_x+h) !=mx)
3426 r2d_s_fill_line(gc,current_x+h,my+1,(current_y+v-my)+1-2,TRUE);
3427 }
3428 }
3429
3430 if (dn>0) // M outside circle, point below must be drawn
3431 {
3432 dn+=dnp;
3433 dnp+=((bs + as) << 1);
3434 current_y--; // Q1
3435 limit+=(as + bs);
3436 tmp=1;
3437 l+=SQRT2;
3438 }
3439 else
3440 {
3441 dn+=dnn;
3442 dnp+=(bs << 1);
3443 limit+=bs;
3444 tmp=0;
3445 l+=0x10000;
3446
3447 }
3448 current_x++; // Q1
3449 dnn+=(bs << 1);
3450
3451
3452
3453
3454 //printf("limit=%f, dn=%f,dnn=%f,dnp=%f, pos= %d %d\n",limit / 4.0,dn / 4.0,dnn / 4.0,dnp / 4.0,current_y,current_x);
3455
3456
3457 }
3458 }
3459
3460 void r2d_draw_ellipse(T_R2D_GC_PTR gc,
3461 INT16 ul_x,INT16 ul_y,INT16 br_x, INT16 br_y)
3462 {
3463 #ifdef R2D_MIRRORED_X
3464 INT16 tmp;
3465 #endif
3466 r2d_local_to_global(gc,&ul_x,&ul_y);
3467 r2d_local_to_global(gc,&br_x,&br_y);
3468
3469
3470 #ifdef R2D_MIRRORED_X
3471 ul_x = r2d_get_width(gc)-1-ul_x;
3472 br_x = r2d_get_width(gc)-1-br_x;
3473 R2D_SWAP(ul_x,br_x);
3474 #endif
3475
3476 #ifdef R2D_MIRRORED_Y
3477 ul_y = r2d_get_height(gc)-1-ul_y;
3478 br_y = r2d_get_height(gc)-1-br_y;
3479 R2D_SWAP(ul_y,br_y);
3480 #endif
3481
3482 r2d_df_ellipse(gc,ul_x,ul_y,br_x,br_y,0,0,FALSE);
3483 if (((T_R2D_FRAMEBUFFER*)((T_R2D_GC*)gc)->p_frame_buffer)->kind==0)
3484 r2d_update_region((T_R2D_GC*)gc,ul_x,ul_y,br_x,br_y);
3485
3486 r2d_check_and_send_event(gc);
3487 }
3488
3489 void r2d_fill_ellipse(T_R2D_GC_PTR gc,
3490 INT16 ul_x,INT16 ul_y,INT16 br_x, INT16 br_y)
3491 {
3492 #ifdef R2D_MIRRORED_X
3493 INT16 tmp;
3494 #endif
3495 r2d_local_to_global(gc,&ul_x,&ul_y);
3496 r2d_local_to_global(gc,&br_x,&br_y);
3497
3498
3499 #ifdef R2D_MIRRORED_X
3500 ul_x = r2d_get_width(gc)-1-ul_x;
3501 br_x = r2d_get_width(gc)-1-br_x;
3502 R2D_SWAP(ul_x,br_x);
3503 #endif
3504
3505 #ifdef R2D_MIRRORED_Y
3506 ul_y = r2d_get_height(gc)-1-ul_y;
3507 br_y = r2d_get_height(gc)-1-br_y;
3508 R2D_SWAP(ul_y,br_y);
3509 #endif
3510
3511 r2d_df_ellipse(gc,ul_x,ul_y,br_x,br_y,0,0,TRUE);
3512 if (((T_R2D_FRAMEBUFFER*)((T_R2D_GC*)gc)->p_frame_buffer)->kind==0)
3513 r2d_update_region((T_R2D_GC*)gc,ul_x,ul_y,br_x,br_y);
3514
3515 r2d_check_and_send_event(gc);
3516 }
3517
3518 void r2d_draw_round_rectangle(T_R2D_GC_PTR gc,
3519 INT16 ul_x,INT16 ul_y,INT16 br_x, INT16 br_y,INT16 h,INT16 v)
3520 {
3521 #ifdef R2D_MIRRORED_X
3522 INT16 tmp;
3523 #endif
3524 r2d_moveto(gc,ul_x+h+1,ul_y);
3525 r2d_lineto(gc,br_x-h-1,ul_y);
3526
3527 r2d_moveto(gc,ul_x+h+1,br_y);
3528 r2d_lineto(gc,br_x-h-1,br_y);
3529
3530 r2d_moveto(gc,ul_x,ul_y+v+1);
3531 r2d_lineto(gc,ul_x,br_y-v-1);
3532
3533 r2d_moveto(gc,br_x,ul_y+v+1);
3534 r2d_lineto(gc,br_x,br_y-v-1);
3535
3536 r2d_local_to_global(gc,&ul_x,&ul_y);
3537 r2d_local_to_global(gc,&br_x,&br_y);
3538
3539
3540 #ifdef R2D_MIRRORED_X
3541 ul_x = r2d_get_width(gc)-1-ul_x;
3542 br_x = r2d_get_width(gc)-1-br_x;
3543 R2D_SWAP(ul_x,br_x);
3544 #endif
3545
3546 #ifdef R2D_MIRRORED_Y
3547 ul_y = r2d_get_height(gc)-1-ul_y;
3548 br_y = r2d_get_height(gc)-1-br_y;
3549 R2D_SWAP(ul_y,br_y);
3550 #endif
3551 r2d_df_ellipse(gc,ul_x,ul_y,ul_x+(h<<1),ul_y+(v<<1),(br_x - ul_x) - (h<<1),(br_y - ul_y) - (v<<1),FALSE);
3552 if (((T_R2D_FRAMEBUFFER*)((T_R2D_GC*)gc)->p_frame_buffer)->kind==0)
3553 r2d_update_region((T_R2D_GC*)gc,ul_x,ul_y,br_x,br_y);
3554
3555 //printf("%d %d\n",ul_x+h+1,br_x-h-1);
3556
3557
3558 r2d_check_and_send_event(gc);
3559 }
3560
3561 void r2d_fill_round_rectangle(T_R2D_GC_PTR gc,
3562 INT16 ul_x,INT16 ul_y,INT16 br_x, INT16 br_y,INT16 h,INT16 v)
3563 {
3564 #ifdef R2D_MIRRORED_X
3565 INT16 tmp;
3566 #endif
3567 r2d_local_to_global(gc,&ul_x,&ul_y);
3568 r2d_local_to_global(gc,&br_x,&br_y);
3569
3570 #ifdef R2D_MIRRORED_X
3571 ul_x = r2d_get_width(gc)-1-ul_x;
3572 br_x = r2d_get_width(gc)-1-br_x;
3573 R2D_SWAP(ul_x,br_x);
3574 #endif
3575
3576
3577 #ifdef R2D_MIRRORED_Y
3578 ul_y = r2d_get_height(gc)-1-ul_y;
3579 br_y = r2d_get_height(gc)-1-br_y;
3580 R2D_SWAP(ul_y,br_y);
3581 #endif
3582
3583 r2d_df_ellipse(gc,ul_x,ul_y,ul_x+(h<<1),ul_y+(v<<1),(br_x - ul_x) - (h<<1),(br_y - ul_y) - (v<<1),TRUE);
3584 #if (R2D_REFRESH == R2D_VERTICAL)
3585 r2d_df_rectangle(gc,ul_x+h,ul_y,br_x-h+1,br_y,TRUE);
3586
3587 #else
3588
3589 r2d_df_rectangle(gc,ul_x,ul_y+v,br_x,br_y-v+1,TRUE);
3590 #endif
3591 if (((T_R2D_FRAMEBUFFER*)((T_R2D_GC*)gc)->p_frame_buffer)->kind==0)
3592 r2d_update_region((T_R2D_GC*)gc,ul_x,ul_y,br_x,br_y);
3593 //printf("%d %d\n",ul_x+h+1,br_x-h-1);
3594 /*r2d_moveto(gc,ul_x+h+1,ul_y);
3595 r2d_lineto(gc,br_x-h-1,ul_y);
3596
3597 r2d_moveto(gc,ul_x+h+1,br_y);
3598 r2d_lineto(gc,br_x-h-1,br_y);
3599
3600 r2d_moveto(gc,ul_x,ul_y+v+1);
3601 r2d_lineto(gc,ul_x,br_y-v-1);
3602
3603 r2d_moveto(gc,br_x,ul_y+v+1);
3604 r2d_lineto(gc,br_x,br_y-v-1);*/
3605 r2d_check_and_send_event(gc);
3606 }
3607
3608 // angle must be between 0 and 359
3609 static INT32 r2d_cos(INT16 angle)
3610 {
3611
3612
3613 if (angle<=90)
3614 return(r2d_cos_table[angle]);
3615 else if (angle<=180)
3616 return(-r2d_cos_table[180-angle]);
3617 else if (angle<=270)
3618 return(-r2d_cos_table[angle-180]);
3619 else
3620 return(r2d_cos_table[360-angle]);
3621 }
3622
3623 // angle must be between 0 and 359
3624 static INT32 r2d_sin(INT16 angle)
3625 {
3626 angle=angle+90;
3627 if (angle>=360)
3628 angle=angle-360;
3629
3630 return(-r2d_cos(angle));
3631 }
3632
3633 static void r2d_check_angles(INT16 *start,INT16 *stop)
3634 {
3635 // INT16 tmp;
3636
3637
3638 while(*start<0)
3639 *start+=360;
3640 while(*start>=360)
3641 *start-=360;
3642
3643 while(*stop<0)
3644 *stop+=360;
3645 while(*stop>=360)
3646 *stop-=360;
3647
3648 //if (*start>*stop)
3649 //{
3650 // R2D_SWAP((*start),(*stop));
3651
3652 //}
3653
3654 }
3655
3656
3657
3658 void r2d_df_arc(T_R2D_GC_PTR gc,
3659 INT16 ul_x,INT16 ul_y,INT16 br_x, INT16 br_y,T_R2D_ARC_REGION *rgn ,BOOLEAN filling)
3660 {
3661 INT32 current_x,current_y,limit,newx,newy,org_x,org_y;
3662 INT32 dn,dnp,dnn,as,bs,tmp,a,b,mx,my,lastx,lasty;
3663 INT32 l;
3664
3665 l=0;
3666
3667 // Width of rectangle is assumed to be even
3668 // and it is forced to even dimension
3669
3670 if (rgn->is_null)
3671 goto end_arc;
3672
3673 #if (R2D_REFRESH==R2D_VERTICAL)
3674 org_x=(ul_y + br_y)>>1;
3675 org_y=(br_x + ul_x)>>1;
3676 a=(br_y-ul_y)>>1;
3677 as=R2D_SQUARE_P(a);
3678 b=(br_x-ul_x)>>1;
3679 bs=R2D_SQUARE_P(b);
3680
3681 current_x=org_x ;
3682 current_y=org_y+b;
3683 newx=org_y;
3684 newy=org_x+a;
3685
3686
3687
3688 #else
3689 org_x=(ul_x + br_x)>>1;
3690 org_y=(br_y + ul_y)>>1;
3691
3692 b=(br_y-ul_y)>>1;
3693 bs=R2D_SQUARE_P(b);
3694 a=(br_x-ul_x)>>1;
3695 as=R2D_SQUARE_P(a);
3696
3697 current_x=org_x;
3698 current_y=org_y+b;
3699 newx=org_y;
3700 newy=org_x+a;
3701
3702 r2d_arc_region_diagonal_reflect(rgn);
3703 r2d_arc_region_x_reflect(rgn);
3704 r2d_arc_region_y_reflect(rgn);
3705 #endif
3706
3707
3708
3709 // Orthogonal is (eb,-ea)
3710
3711 //r2d_s_draw_point(gc,org_y,org_x);
3712 //r2d_s_draw_point(gc,((rgn->sa)>>16)+org_y,((rgn->sb)>>16)+org_x);
3713 //r2d_s_draw_point(gc,((rgn->sb)>>16)+org_y,((-rgn->sa)>>16)+org_x);
3714
3715 //r2d_s_draw_point(gc,((rgn->ea)>>16)+org_y,((rgn->eb)>>16)+org_x);
3716
3717 //goto end_arc;
3718
3719 // Now, shift by 2 to have the accuracy required by division by four
3720
3721
3722 //printf("current_x=%d, current_y=%d,as=%08X bs=%08X\n",current_x,current_y,as,bs);
3723
3724
3725 // New shift by 2 because one needs to compute quarter of values
3726 bs<<=2; as <<=2;b<<=2;a<<=2;
3727
3728 limit = - ((as * b) >> 2); // -a^2 * b in Q2
3729
3730 tmp=-((as * b) >> 2);
3731 dnp=(bs << 1) + bs + (tmp<<1) + (as << 1);
3732 dnn=(bs << 1) + bs;
3733 dn=bs + tmp + (as >>2);
3734
3735
3736
3737 //printf("dn=%f dnp=%f dnn=%f\n",dn / 8.0,dnp / 8.0,dnn / 8.0);
3738
3739 /*#if (R2D_REFRESH==R2D_VERTICAL)
3740 r2d_draw_point(gc,current_y,current_x);
3741 #else
3742 r2d_draw_point(gc,current_x,current_y);
3743 #endif*/
3744
3745 //printf("as=%08X bs=%08X\n",as,bs);
3746
3747 tmp=1;
3748 while(limit<=0)
3749 {
3750 my=(org_y << 1) - current_y;
3751 mx=(org_x << 1) - current_x;
3752
3753 lastx=current_y;
3754 lasty=current_x;
3755
3756 if (!filling)
3757 {
3758 if (r2d_check_is_in_arc_region(current_y-org_y,current_x-org_x,rgn))
3759 r2d_s_draw_point(gc,(current_y),(current_x),l); // I : 1
3760
3761 if (r2d_check_is_in_arc_region(my-org_y,mx-org_x,rgn))
3762 r2d_s_draw_point(gc,my,mx,l); // PX PY : 2
3763
3764 if ((mx != current_x) )
3765 {
3766 if (r2d_check_is_in_arc_region(current_y-org_y,mx-org_x,rgn))
3767 r2d_s_draw_point(gc,current_y,mx,l); // PY : 3
3768
3769 if (r2d_check_is_in_arc_region(my-org_y,current_x-org_x,rgn))
3770 r2d_s_draw_point(gc,my,current_x,l); // PX : 4
3771 }
3772 }
3773 else
3774 {
3775 if (tmp)
3776 {
3777
3778 // Used to remove point on horizontal extremity
3779 if (current_x-mx !=0)
3780 {
3781 r2d_s_arc_fill_line(gc,my,mx+1,org_y,org_x,(current_x-mx)+1-2
3782 ,rgn,TRUE);
3783
3784 r2d_s_arc_fill_line(gc,current_y,mx+1,org_y,org_x,(current_x-mx)+1-2
3785 ,rgn,TRUE);
3786 }
3787 }
3788 }
3789
3790 if (dn>=0) // M outside circle, point below must be drawn
3791 {
3792 dn+=dnp;
3793 dnp+=((bs + as) << 1);
3794 current_y--;
3795 limit+=(as + bs);
3796 tmp=1;
3797 l+=SQRT2;
3798 }
3799 else
3800
3801 {
3802 dn+=dnn;
3803 dnp+=(bs << 1);
3804 limit+=bs;
3805 tmp=0;
3806 l+=0x10000;
3807 }
3808 current_x++;
3809 dnn+=(bs << 1);
3810
3811
3812 //printf("limit=%f, dn=%f,dnn=%f,dnp=%f, pos= %d %d\n",limit / 4.0,dn / 4.0,dnn / 4.0,dnp /
3813 //4.0,current_y,current_x);
3814
3815
3816 }
3817
3818 current_x=newx;
3819 current_y=newy;
3820 R2D_SWAP(as,bs);
3821 R2D_SWAP(a,b);
3822
3823 limit = - ((as * b) >> 2);
3824
3825 tmp=-((as * b) >> 2);
3826 dnp=(bs << 1) + bs + (tmp<<1) + (as << 1);
3827 dnn=(bs << 1) + bs;
3828 dn=bs + tmp + (as >>2);
3829
3830 //printf("newx=%d, newy=%d,a=%d,b=%d\n",newx,newy,a,b);
3831 //printf("dn=%f dnp=%f dnn=%f\n",dn / 4.0,dnp / 4.0,dnn / 4.0);
3832
3833 tmp=1;
3834
3835 /* #if (R2D_REFRESH==R2D_VERTICAL)
3836 r2d_draw_point(gc,current_x,current_y);
3837 #else
3838 r2d_draw_point(gc,current_y,current_x);
3839 #endif*/
3840
3841 while(limit<0)
3842 {
3843
3844 my=(org_x << 1) - current_y;
3845 mx=(org_y << 1) - current_x;
3846
3847 if (!filling)
3848 {
3849 if ((lastx!=current_x) || (lasty!=current_y))
3850 {
3851
3852 if (r2d_check_is_in_arc_region(current_x-org_y,current_y-org_x,rgn))
3853 r2d_s_draw_point(gc,(current_x),(current_y),l); // D : 5
3854
3855
3856 if (r2d_check_is_in_arc_region(mx-org_y,my-org_x,rgn))
3857 r2d_s_draw_point(gc,mx,my,l); // D PX PY : 6
3858
3859 if ((mx != current_x) )
3860 {
3861 if (r2d_check_is_in_arc_region(current_x-org_y,my-org_x,rgn))
3862 r2d_s_draw_point(gc,(current_x),my,l); // D PY : 7
3863
3864 if (r2d_check_is_in_arc_region(mx-org_y,current_y-org_x,rgn))
3865 r2d_s_draw_point(gc,mx,(current_y),l); // D PX : 8
3866 }
3867
3868 }
3869 }
3870 else
3871 {
3872 if (current_x != lastx)
3873 {
3874 r2d_s_arc_fill_line(gc,mx,my+1,org_y,org_x,(current_y-my)+1-2
3875 ,rgn,TRUE);
3876
3877 if (current_x !=mx)
3878 r2d_s_arc_fill_line(gc,current_x,my+1,org_y,org_x,(current_y-my)+1-2
3879 ,rgn,TRUE);
3880 }
3881 }
3882
3883 if (dn>0) // M outside circle, point below must be drawn
3884 {
3885 dn+=dnp;
3886 dnp+=((bs + as) << 1);
3887 current_y--; // Q1
3888 limit+=(as + bs);
3889 tmp=1;
3890 l+=SQRT2;
3891 }
3892 else
3893 {
3894 dn+=dnn;
3895 dnp+=(bs << 1);
3896 limit+=bs;
3897 tmp=0;
3898 l+=0x10000;
3899
3900 }
3901 current_x++; // Q1
3902 dnn+=(bs << 1);
3903
3904
3905
3906
3907 //printf("limit=%f, dn=%f,dnn=%f,dnp=%f, pos= %d %d\n",limit / 4.0,dn / 4.0,dnn / 4.0,dnp / 4.0,current_y,current_x);
3908
3909
3910 }
3911
3912 end_arc: current_x=0;
3913 }
3914
3915 void r2d_draw_arc(T_R2D_GC_PTR gc,INT16 start_angle,INT16 stop_angle,
3916 INT16 ul_x,INT16 ul_y,INT16 br_x, INT16 br_y)
3917 {
3918 #ifdef R2D_MIRRORED_X
3919 INT16 tmp;
3920 #endif
3921 BOOLEAN large=FALSE;
3922 T_R2D_ARC_REGION rgn;
3923 INT32 sa,sb,ea,eb;
3924 INT32 a,b;
3925
3926 a=(br_x-ul_x)>>1;
3927 b=(br_y-ul_y)>>1;
3928
3929 r2d_local_to_global(gc,&ul_x,&ul_y);
3930 r2d_local_to_global(gc,&br_x,&br_y);
3931
3932 rgn.one_sector=0;
3933 if (stop_angle-start_angle>180)
3934 rgn.one_sector=1;
3935
3936 if (stop_angle-start_angle==360)
3937 rgn.one_sector=2;
3938
3939 if (start_angle==stop_angle)
3940 rgn.is_null=TRUE;
3941 else
3942 rgn.is_null=FALSE;
3943 r2d_check_angles(&start_angle,&stop_angle);
3944
3945
3946 sa=a * r2d_cos(start_angle); // Q16
3947 sb= -b* r2d_sin(start_angle); // Q16
3948 // Orthogonal is (sb,-sa)
3949
3950 ea= a * r2d_cos(stop_angle); // Q16
3951 eb= -b* r2d_sin(stop_angle); // Q16
3952 // Orthogonal is (-sb,sa)
3953
3954 //r2d_moveto(gc,ul_x+a,ul_y+b);
3955 //r2d_lineto(gc,ul_x+a+(sa>>16),ul_y+b+(sb>>16));
3956
3957 // Orthogonal
3958 //r2d_moveto(gc,ul_x+a,ul_y+b);
3959 //r2d_lineto(gc,ul_x+a+(sb>>16),ul_y+b+((-sa)>>16));
3960
3961 //r2d_moveto(gc,ul_x+a,ul_y+b);
3962 //r2d_lineto(gc,ul_x+a+(ea>>16),ul_y+b+(eb>>16));
3963
3964 rgn.sa=sa;
3965 rgn.sb=sb;
3966
3967
3968 rgn.ea=-ea;
3969 rgn.eb=-eb;
3970
3971
3972
3973
3974
3975
3976 #ifdef R2D_MIRRORED_X
3977 ul_x = r2d_get_width(gc)-1-ul_x;
3978 br_x = r2d_get_width(gc)-1-br_x;
3979 R2D_SWAP(ul_x,br_x);
3980
3981 r2d_arc_region_x_reflect(&rgn);
3982
3983 #endif
3984
3985 #ifdef R2D_MIRRORED_Y
3986 ul_y = r2d_get_height(gc)-1-ul_y;
3987 br_y = r2d_get_height(gc)-1-br_y;
3988 R2D_SWAP(ul_y,br_y);
3989
3990 r2d_arc_region_y_reflect(&rgn);
3991 #endif
3992
3993
3994
3995 r2d_df_arc(gc,ul_x,ul_y,br_x,br_y,&rgn,FALSE);
3996 if (((T_R2D_FRAMEBUFFER*)((T_R2D_GC*)gc)->p_frame_buffer)->kind==0)
3997 r2d_update_region((T_R2D_GC*)gc,ul_x,ul_y,br_x,br_y);
3998
3999 r2d_check_and_send_event(gc);
4000 }
4001
4002 void r2d_fill_arc(T_R2D_GC_PTR gc, INT16 start_angle,INT16 stop_angle,
4003 INT16 ul_x,INT16 ul_y,INT16 br_x, INT16 br_y)
4004 {
4005 #ifdef R2D_MIRRORED_X
4006 INT16 tmp;
4007 #endif
4008 BOOLEAN large=FALSE;
4009 T_R2D_ARC_REGION rgn;
4010 INT32 sa,sb,ea,eb;
4011 INT32 a,b;
4012
4013 a=(br_x-ul_x)>>1;
4014 b=(br_y-ul_y)>>1;
4015
4016 r2d_local_to_global(gc,&ul_x,&ul_y);
4017 r2d_local_to_global(gc,&br_x,&br_y);
4018
4019
4020 rgn.one_sector=0;
4021 if (stop_angle-start_angle>180)
4022 rgn.one_sector=1;
4023
4024 if (stop_angle-start_angle==360)
4025 rgn.one_sector=2;
4026
4027 if (start_angle==stop_angle)
4028 rgn.is_null=TRUE;
4029 else
4030 rgn.is_null=FALSE;
4031 r2d_check_angles(&start_angle,&stop_angle);
4032
4033
4034 sa=a * r2d_cos(start_angle); // Q16
4035 sb= -b* r2d_sin(start_angle); // Q16
4036 // Orthogonal is (sb,-sa)
4037
4038 ea= a * r2d_cos(stop_angle); // Q16
4039 eb= -b* r2d_sin(stop_angle); // Q16
4040 // Orthogonal is (-sb,sa)
4041
4042 //r2d_moveto(gc,ul_x+a,ul_y+b);
4043 //r2d_lineto(gc,ul_x+a+(sa>>16),ul_y+b+(sb>>16));
4044
4045 // Orthogonal
4046 //r2d_moveto(gc,ul_x+a,ul_y+b);
4047 //r2d_lineto(gc,ul_x+a+(sb>>16),ul_y+b+((-sa)>>16));
4048
4049 //r2d_moveto(gc,ul_x+a,ul_y+b);
4050 //r2d_lineto(gc,ul_x+a+(ea>>16),ul_y+b+(eb>>16));
4051
4052 rgn.sa=sa;
4053 rgn.sb=sb;
4054
4055
4056 rgn.ea=-ea;
4057 rgn.eb=-eb;
4058
4059
4060
4061 #ifdef R2D_MIRRORED_X
4062 ul_x = r2d_get_width(gc)-1-ul_x;
4063 br_x = r2d_get_width(gc)-1-br_x;
4064 R2D_SWAP(ul_x,br_x);
4065
4066 r2d_arc_region_x_reflect(&rgn);
4067 #endif
4068
4069 #ifdef R2D_MIRRORED_Y
4070 ul_y = r2d_get_height(gc)-1-ul_y;
4071 br_y = r2d_get_height(gc)-1-br_y;
4072 R2D_SWAP(ul_y,br_y);
4073
4074 r2d_arc_region_y_reflect(&rgn);
4075 #endif
4076
4077
4078
4079
4080
4081 r2d_df_arc(gc,ul_x,ul_y,br_x,br_y,&rgn,TRUE);
4082 if (((T_R2D_FRAMEBUFFER*)((T_R2D_GC*)gc)->p_frame_buffer)->kind==0)
4083 r2d_update_region((T_R2D_GC*)gc,ul_x,ul_y,br_x,br_y);
4084
4085 r2d_check_and_send_event(gc);
4086 }
4087
4088 ///////////////////////////////////////
4089 //
4090 // Copy function
4091 //
4092
4093 static void r2d_diagonal_mirror(T_R2D_SHAPE_PTR rectangle)
4094 {
4095 T_R2D_RECTANGLE *r;
4096 INT16 tmp;
4097 r=(T_R2D_RECTANGLE *)rectangle;
4098
4099 tmp=r->ul_x;
4100 r->ul_x=r->ul_y;
4101 r->ul_y=tmp;
4102
4103 tmp=r->br_x;
4104 r->br_x=r->br_y;
4105 r->br_y=tmp;
4106 }
4107
4108 // Global coordinates
4109 static void r2d_mirror_rectangle(T_R2D_GC_PTR gc,T_R2D_SHAPE_PTR rectangle)
4110 {
4111 T_R2D_RECTANGLE *r;
4112 //INT16 org_x,org_y;
4113 #ifdef R2D_MIRRORED_X
4114 INT16 tmp;
4115 #endif
4116 r=(T_R2D_RECTANGLE *)rectangle;
4117
4118
4119 #ifdef R2D_MIRRORED_X
4120 r->ul_x = r2d_get_width(gc)-r->ul_x;
4121 r->br_x = r2d_get_width(gc)-r->br_x;
4122 tmp=r->ul_x;
4123 r->ul_x=r->br_x;
4124 r->br_x=tmp;
4125 #endif
4126
4127 #ifdef R2D_MIRRORED_Y
4128 r->ul_y = r2d_get_height(gc)-r->ul_y;
4129 r->br_y = r2d_get_height(gc)-r->br_y;
4130
4131 tmp=r->ul_y;
4132 r->ul_y=r->br_y;
4133 r->br_y=tmp;
4134 #endif
4135
4136
4137 }
4138
4139 // Global coordinates
4140 // Here a rectangle with clipping convention is mirrored
4141 // The resulting rectangle (s_clipping) is used with drawing
4142 // convention. So, the boundary must be updated
4143 static void r2d_mirror_clip_rectangle(T_R2D_GC_PTR gc,T_R2D_SHAPE_PTR rectangle)
4144 {
4145 T_R2D_RECTANGLE *r;
4146 // INT16 org_x,org_y;
4147 #ifdef R2D_MIRRORED_X
4148 INT16 tmp;
4149 #endif
4150 r=(T_R2D_RECTANGLE *)rectangle;
4151
4152
4153 //Be careful br_x is NOT a line wich must be drawn
4154 #ifdef R2D_MIRRORED_X
4155 r->ul_x = r2d_get_width(gc)-r->ul_x+1;
4156 r->br_x = r2d_get_width(gc)-(r->br_x-1);
4157 tmp=r->ul_x;
4158 r->ul_x=r->br_x;
4159 r->br_x=tmp;
4160 #endif
4161
4162 #ifdef R2D_MIRRORED_Y
4163 r->ul_y = r2d_get_height(gc)-r->ul_y+1;
4164 r->br_y = r2d_get_height(gc)-(r->br_y-1);
4165
4166 tmp=r->ul_y;
4167 r->ul_y=r->br_y;
4168 r->br_y=tmp;
4169 #endif
4170
4171
4172 }
4173
4174 // Compute the intersection of the clipping shape of srcGc with
4175 // the srcRectangle. Report he size reduction onto dstRectangle.
4176 // Compute the intersection between dstRectangle and the clipping rectangle
4177 // of dstGc and report the size reduction to srcRectangle.
4178 // At the end, one get two rectangles of same size.
4179 // The first one is contained in the clipping shape of srcGc
4180 // and the second one in the clipping shape of dstGc.
4181 // If the result is null, false is returned and no copy is done
4182 // The rectangles are modified.
4183 static BOOLEAN r2d_clipped_is_not_null(T_R2D_GC* src_gc,T_R2D_GC *dst_gc,
4184 T_R2D_RECTANGLE* src_rectangle,T_R2D_RECTANGLE* dst_rectangle)
4185 {
4186 BOOLEAN result=TRUE;
4187 //CC : clipping coordinate , RC : rectangle coordinate
4188 INT16 delta,CC,RC;
4189
4190 #if (R2D_DEBUG == R2D_ON)
4191 #if (R2D_DEBUG_WARNING == R2D_DEBUG_HIGH)
4192 if (src_gc->p_clipping_shape==NULL)
4193 rvf_send_trace("R2D : clipping shape error",26, NULL_PARAM,
4194 RV_TRACE_LEVEL_ERROR, r2d_use_id );
4195 if (dst_gc->p_clipping_shape==NULL)
4196 rvf_send_trace("R2D : clipping shape error",26, NULL_PARAM,
4197 RV_TRACE_LEVEL_ERROR, r2d_use_id );
4198 #endif
4199 #endif
4200
4201 //T_R2D_RECTANGLE *debug;
4202
4203 //debug=(T_R2D_RECTANGLE*)src_gc->p_clipping_shape;
4204
4205
4206 // Intersections in src context
4207 CC=r2d_get_xmin(src_gc->p_clipping_shape);
4208 RC=r2d_get_xmin(src_rectangle);
4209 if ( CC > RC)
4210 {
4211 delta=CC-RC;
4212 src_rectangle->ul_x=CC;
4213 dst_rectangle->ul_x+=delta;
4214 }
4215
4216 CC=r2d_get_xmax(src_gc->p_clipping_shape);
4217 RC=r2d_get_xmax(src_rectangle);
4218 if ( RC > CC)
4219 {
4220 delta=RC-CC;
4221 src_rectangle->br_x=CC;
4222 dst_rectangle->br_x-=delta;
4223 }
4224
4225 CC=r2d_get_ymin(src_gc->p_clipping_shape);
4226 RC=r2d_get_ymin(src_rectangle);
4227 if ( CC > RC)
4228 {
4229 delta=CC-RC;
4230 src_rectangle->ul_y=CC;
4231 dst_rectangle->ul_y+=delta;
4232 }
4233
4234 CC=r2d_get_ymax(src_gc->p_clipping_shape);
4235 RC=r2d_get_ymax(src_rectangle);
4236 if ( RC > CC)
4237 {
4238 delta=RC-CC;
4239 src_rectangle->br_y=CC;
4240 dst_rectangle->br_y-=delta;
4241 }
4242
4243 // Intersection in dst context
4244 CC=r2d_get_xmin(dst_gc->p_clipping_shape);
4245 RC=r2d_get_xmin(dst_rectangle);
4246 if ( CC > RC)
4247 {
4248 delta=CC-RC;
4249 dst_rectangle->ul_x=CC;
4250 src_rectangle->ul_x+=delta;
4251 }
4252
4253 CC=r2d_get_xmax(dst_gc->p_clipping_shape);
4254 RC=r2d_get_xmax(dst_rectangle);
4255 if ( RC > CC)
4256 {
4257 delta=RC-CC;
4258 dst_rectangle->br_x=CC;
4259 src_rectangle->br_x-=delta;
4260 }
4261
4262 CC=r2d_get_ymin(dst_gc->p_clipping_shape);
4263 RC=r2d_get_ymin(dst_rectangle);
4264 if ( CC > RC)
4265 {
4266 delta=CC-RC;
4267 dst_rectangle->ul_y=CC;
4268 src_rectangle->ul_y+=delta;
4269 }
4270
4271 CC=r2d_get_ymax(dst_gc->p_clipping_shape);
4272 RC=r2d_get_ymax(dst_rectangle);
4273 if ( RC > CC)
4274 {
4275 delta=RC-CC;
4276 dst_rectangle->br_y=CC;
4277 src_rectangle->br_y-=delta;
4278 }
4279
4280 if (src_rectangle->ul_x>=src_rectangle->br_x)
4281 result=FALSE;
4282
4283
4284 if (src_rectangle->ul_y>=src_rectangle->br_y)
4285 result=FALSE;
4286
4287 if (result)
4288 {
4289 /*printf("src: (%d,%d) -- (%d,%d)\n",src_rectangle->ul_x,src_rectangle->ul_y
4290 ,src_rectangle->br_x,src_rectangle->br_y);
4291 printf("dst: (%d,%d) -- (%d,%d)\n",dst_rectangle->ul_x,dst_rectangle->ul_y
4292 ,dst_rectangle->br_x,dst_rectangle->br_y);*/
4293
4294 // Conversion of clipped rectangles to framebuffer coordinates
4295 r2d_local_to_global(src_gc,&(src_rectangle->ul_x),&(src_rectangle->ul_y));
4296 r2d_local_to_global(src_gc,&(src_rectangle->br_x),&(src_rectangle->br_y));
4297 r2d_local_to_global(dst_gc,&(dst_rectangle->ul_x),&(dst_rectangle->ul_y));
4298 r2d_local_to_global(dst_gc,&(dst_rectangle->br_x),&(dst_rectangle->br_y));
4299
4300 #if (R2D_DEBUG == R2D_ON)
4301 #if (R2D_DEBUG_WARNING == R2D_DEBUG_HIGH)
4302 if (src_rectangle->ul_x<0)
4303 rvf_send_trace("R2D : clipping shape error",26, NULL_PARAM,
4304 RV_TRACE_LEVEL_ERROR, R2D_USE_ID );
4305
4306 if (src_rectangle->ul_y<0)
4307 rvf_send_trace("R2D : clipping shape error",26, NULL_PARAM,
4308 RV_TRACE_LEVEL_ERROR, R2D_USE_ID );
4309
4310 if (dst_rectangle->ul_x<0)
4311 rvf_send_trace("R2D : clipping shape error",26, NULL_PARAM,
4312 RV_TRACE_LEVEL_ERROR, R2D_USE_ID );
4313
4314
4315 if (dst_rectangle->ul_y<0)
4316 rvf_send_trace("R2D : clipping shape error",26, NULL_PARAM,
4317 RV_TRACE_LEVEL_ERROR, R2D_USE_ID );
4318
4319 if (src_rectangle->br_x>r2d_get_width(src_gc))
4320 rvf_send_trace("R2D : clipping shape error",26, NULL_PARAM,
4321 RV_TRACE_LEVEL_ERROR, R2D_USE_ID );
4322
4323 if (src_rectangle->br_y>r2d_get_height(src_gc))
4324 rvf_send_trace("R2D : clipping shape error",26, NULL_PARAM,
4325 RV_TRACE_LEVEL_ERROR, R2D_USE_ID );
4326
4327 if (dst_rectangle->br_x>r2d_get_width(dst_gc))
4328 rvf_send_trace("R2D : clipping shape error",26, NULL_PARAM,
4329 RV_TRACE_LEVEL_ERROR, R2D_USE_ID );
4330
4331 if (dst_rectangle->br_y>r2d_get_height(dst_gc))
4332 rvf_send_trace("R2D : clipping shape error",26, NULL_PARAM,
4333 RV_TRACE_LEVEL_ERROR, R2D_USE_ID );
4334
4335 #endif
4336 #endif
4337 /*printf("src: (%d,%d) -- (%d,%d)\n",src_rectangle->ul_x,src_rectangle->ul_y
4338 ,src_rectangle->br_x,src_rectangle->br_y);
4339 printf("dst: (%d,%d) -- (%d,%d)\n",dst_rectangle->ul_x,dst_rectangle->ul_y
4340 ,dst_rectangle->br_x,dst_rectangle->br_y);*/
4341 }
4342
4343 return(result);
4344 }
4345
4346 T_R2D_ERROR r2d_low_level_blit_rect(T_R2D_GC_PTR src_gc,T_R2D_GC_PTR dst_gc,
4347 T_R2D_SHAPE_PTR org_src_rectangle, T_R2D_SHAPE_PTR org_dst_rectangle,
4348 BOOLEAN src_mirrored,BOOLEAN dst_mirrored,
4349 BOOLEAN use_foreground_color)
4350 {
4351
4352 INT16 kind_src,kind_dst,org_bx,org_by,org_ux,org_uy;
4353 #if (R2D_ASM == R2D_ON)
4354 T_R2D_DRAWING_MODE mode;
4355 #endif
4356
4357 T_R2D_SHAPE_PTR src_rectangle,dst_rectangle;
4358
4359 #if (R2D_DEBUG == R2D_ON)
4360 #if (R2D_DEBUG_WARNING == R2D_DEBUG_HIGH)
4361 if (src_gc==NULL)
4362 {
4363 rvf_send_trace("src_gc NULL",11, NULL_PARAM,
4364 RV_TRACE_LEVEL_ERROR, r2d_use_id );
4365 rvf_delay(RVF_SECS_TO_TICKS(1));
4366 }
4367
4368 if (dst_gc==NULL)
4369 {
4370 rvf_send_trace("dst_gc NULL",11, NULL_PARAM,
4371 RV_TRACE_LEVEL_ERROR, r2d_use_id );
4372 rvf_delay(RVF_SECS_TO_TICKS(1));\
4373 }
4374
4375 if (org_src_rectangle==NULL)
4376 {
4377 rvf_send_trace("org_src NULL",12, NULL_PARAM,
4378 RV_TRACE_LEVEL_ERROR, r2d_use_id );
4379 rvf_delay(RVF_SECS_TO_TICKS(1));\
4380 }
4381
4382 if (org_dst_rectangle==NULL)
4383 {
4384 rvf_send_trace("org_dst NULL",12, NULL_PARAM,
4385 RV_TRACE_LEVEL_ERROR, r2d_use_id );
4386 rvf_delay(RVF_SECS_TO_TICKS(1));\
4387 }
4388 #endif
4389 #endif
4390
4391
4392
4393 src_rectangle=r2d_clone_shape(r2d_mb_id,org_src_rectangle);
4394 if (src_rectangle==NULL)
4395 return(R2D_MEMORY_ERR);
4396
4397
4398 dst_rectangle=r2d_clone_shape(r2d_mb_id,org_dst_rectangle);
4399 if (dst_rectangle==NULL)
4400 {
4401 r2d_release_shape(src_rectangle);
4402 return(R2D_MEMORY_ERR);
4403 }
4404
4405 r2d_disable_refresh();
4406
4407 org_bx=((T_R2D_RECT*)src_rectangle)->br_x;
4408 org_by=((T_R2D_RECT*)src_rectangle)->br_y;
4409 org_ux=((T_R2D_RECT*)src_rectangle)->ul_x;
4410 org_uy=((T_R2D_RECT*)src_rectangle)->ul_y;
4411 r2d_local_to_global(src_gc,&org_ux,&org_uy);
4412 r2d_local_to_global(src_gc,&org_bx,&org_by);
4413 if (r2d_clipped_is_not_null(src_gc,dst_gc,src_rectangle,dst_rectangle))
4414 {
4415 // Rects are now clipped and in global coordinates
4416
4417 if (src_mirrored)
4418 r2d_mirror_rectangle(src_gc,src_rectangle);
4419
4420 if (dst_mirrored)
4421 r2d_mirror_rectangle(dst_gc,dst_rectangle);
4422
4423 // In that case we are drawing text.
4424 // If dst rect clipped by the right side, the src must be shifted to
4425 // the start of the char
4426 // and must not remained aligned with the end of the char
4427 // (don't forget that since char is drawn with mirror its start
4428 // is corresponding to the right and bottom side of the bounding
4429 // rectangle)
4430 // There is the dual problem when the dst rect is clipped by the
4431 // left side
4432
4433 if ((dst_mirrored) && (!src_mirrored))
4434 {
4435 INT16 dbx,dby,dux,duy;
4436 dbx=0;
4437 dux=0;
4438 dby=0;
4439 duy=0;
4440
4441 #ifdef R2D_MIRRORED_X
4442 dbx=org_bx-((T_R2D_RECT*)src_rectangle)->br_x;
4443 dux=org_ux-((T_R2D_RECT*)src_rectangle)->ul_x;
4444 #endif
4445
4446 #ifdef R2D_MIRRORED_Y
4447 dby=org_by-((T_R2D_RECT*)src_rectangle)->br_y;
4448 duy=org_uy-((T_R2D_RECT*)src_rectangle)->ul_y;
4449 #endif
4450
4451 r2d_translate_shape(src_rectangle,dbx,dby);
4452 r2d_translate_shape(src_rectangle,dux,duy);
4453 }
4454
4455
4456
4457 // After mirrong one is in L coordinates
4458
4459
4460 if (((T_R2D_FRAMEBUFFER*)((T_R2D_GC*)dst_gc)->p_frame_buffer)->kind==0)
4461 r2d_update_region((T_R2D_GC*)dst_gc,r2d_get_xmin(dst_rectangle),
4462 r2d_get_ymin(dst_rectangle),
4463 r2d_get_xmax(dst_rectangle),
4464 r2d_get_ymax(dst_rectangle));
4465
4466 #if (R2D_REFRESH != R2D_VERTICAL)
4467 r2d_diagonal_mirror(src_rectangle);
4468 r2d_diagonal_mirror(dst_rectangle);
4469 #endif
4470
4471 // After swap one is in S coordinates
4472
4473 kind_src=((T_R2D_FRAMEBUFFER*)(((T_R2D_GC*)src_gc)->p_frame_buffer))->kind;
4474 kind_dst=((T_R2D_FRAMEBUFFER*)(((T_R2D_GC*)dst_gc)->p_frame_buffer))->kind;
4475
4476
4477 #if (R2D_ASM == R2D_OFF)
4478
4479 if ((kind_src!=R2D_FULL_KIND) && (kind_dst!=R2D_FULL_KIND))
4480 IND_r2d_blit_lcd_to_lcd(src_gc,dst_gc,src_rectangle,dst_rectangle,use_foreground_color);
4481 else
4482 if ((kind_src==R2D_FULL_KIND) && (kind_dst==R2D_FULL_KIND))
4483 IND_r2d_blit_color_to_color(src_gc,dst_gc,src_rectangle,dst_rectangle,use_foreground_color);
4484 else
4485 if ((kind_src!=R2D_FULL_KIND) && (kind_dst==R2D_FULL_KIND))
4486 IND_r2d_blit_lcd_to_color(src_gc,dst_gc,src_rectangle,dst_rectangle,use_foreground_color);
4487 else
4488 if ((kind_src==R2D_FULL_KIND) && (kind_dst!=R2D_FULL_KIND))
4489 IND_r2d_blit_color_to_lcd(src_gc,dst_gc,src_rectangle,dst_rectangle,use_foreground_color);
4490
4491 #else
4492 mode=(((T_R2D_GC*)dst_gc))->drawing_mode;
4493 rvf_lock_mutex(r2d_g_blit_mutex);
4494
4495 if ((kind_src!=R2D_FULL_KIND) && (kind_dst!=R2D_FULL_KIND))
4496 {
4497 r2d_patch_blit(dst_gc,mode,
4498 use_foreground_color,R2D_LCDLCD);
4499 r2d_blit_asm(src_gc,dst_gc,src_rectangle,dst_rectangle,
4500 use_foreground_color,R2D_LCDLCD);
4501 }
4502 else
4503 if ((kind_src==R2D_FULL_KIND) && (kind_dst==R2D_FULL_KIND))
4504 {
4505 r2d_patch_blit(dst_gc,mode,
4506 use_foreground_color,R2D_COLORCOLOR);
4507 r2d_blit_asm(src_gc,dst_gc,src_rectangle,dst_rectangle,
4508 use_foreground_color,R2D_COLORCOLOR);
4509 }
4510 else
4511 if ((kind_src!=R2D_FULL_KIND) && (kind_dst==R2D_FULL_KIND))
4512 {
4513 r2d_patch_blit(dst_gc,mode,
4514 use_foreground_color,R2D_LCDCOLOR);
4515 r2d_blit_asm(src_gc,dst_gc,src_rectangle,dst_rectangle,
4516 use_foreground_color,R2D_LCDCOLOR);
4517 }
4518 else
4519 if ((kind_src==R2D_FULL_KIND) && (kind_dst!=R2D_FULL_KIND))
4520 {
4521 r2d_patch_blit(dst_gc,mode,
4522 use_foreground_color,R2D_COLORLCD);
4523 r2d_blit_asm(src_gc,dst_gc,src_rectangle,dst_rectangle,
4524 use_foreground_color,R2D_COLORLCD);
4525 }
4526 rvf_unlock_mutex(r2d_g_blit_mutex);
4527
4528 #endif
4529
4530
4531 r2d_check_and_send_event(dst_gc);
4532 }
4533 r2d_release_shape(src_rectangle);
4534 r2d_release_shape(dst_rectangle);
4535 r2d_enable_refresh();
4536 return(R2D_OK);
4537 }
4538
4539 T_R2D_ERROR r2d_blit_rect(T_R2D_GC_PTR src_gc,T_R2D_GC_PTR dst_gc,
4540 T_R2D_SHAPE_PTR org_src_rectangle,
4541 T_R2D_SHAPE_PTR org_dst_rectangle,
4542 BOOLEAN use_foreground_color)
4543 {
4544 // Allow reversing if needed
4545 return(r2d_low_level_blit_rect(src_gc,dst_gc,org_src_rectangle,org_dst_rectangle,TRUE,TRUE,use_foreground_color));
4546 }
4547
4548
4549
4550 ///////////////////////////////////////
4551 //
4552 // Text functions
4553 //
4554
4555 T_R2D_CHAR_METRIC_PTR r2d_get_char_metrics(T_R2D_GC_PTR gc,UINT32 the_char)
4556 {
4557 INT32 *p;
4558 INT32 new_char;
4559
4560 new_char=r2d_ptree_find(((T_R2D_GC*)gc)->font_table,the_char);
4561
4562 p=((T_R2D_GC*)gc)->font_metrics;
4563 p+=(new_char<<3);
4564
4565 *p++;
4566
4567 return((T_R2D_CHAR_METRIC_PTR)p);
4568 }
4569
4570 T_R2D_ERROR r2d_draw_char(T_R2D_GC_PTR font_cache_gc,
4571 T_R2D_GC_PTR gc,
4572 T_R2D_GC_PTR fontgc,
4573 INT16 x,INT16 y,INT16 org_size,T_R2D_CHAR_METRIC_PTR met)
4574 {
4575
4576 T_R2D_SHAPE_PTR src_rectangle,dst_rectangle,tdst_rectangle;
4577
4578
4579 INT32 *p;
4580 INT16 underline;
4581 // INT32 new_char;
4582 INT16 style;
4583 INT16 ascent;
4584 T_R2D_ERROR err;
4585
4586 style=((T_R2D_GC *)gc)->internal_text_style;
4587 ascent=((T_R2D_GC*)gc)->font_metrics[R2D_BUFFER_WIDTH_POS+1];
4588
4589 err=R2D_OK;
4590
4591
4592 p=((T_R2D_GC*)gc)->font_metrics;
4593 underline=*--p;
4594
4595
4596
4597 {
4598
4599
4600
4601 if (style & R2D_BOLD)
4602 {
4603 // T_R2D_DRAWING_MODE the_mode;
4604 // T_R2D_ARGB_COLOR bg_color;
4605
4606 #if (R2D_REFRESH == R2D_VERTICAL)
4607 src_rectangle=r2d_new_rectangle(r2d_mb_id,r2d_get_char_x(met),0,
4608 r2d_get_char_x(met)+r2d_get_char_width(met),
4609 r2d_get_char_height(met));
4610 #else
4611 // In horizontal mode char are organized vertically
4612 src_rectangle=r2d_new_rectangle(r2d_mb_id,0,r2d_get_char_x(met),
4613 r2d_get_char_width(met),r2d_get_char_x(met)+r2d_get_char_height(met));
4614 #endif
4615 if (src_rectangle==NULL)
4616 {
4617 err=R2D_MEMORY_ERR;
4618 return(err);
4619 }
4620 //dst_rectangle=r2d_new_rectangle(0,0,char_width+1,char_height);
4621 //if (dst_rectangle==NULL)
4622 //{
4623 // r2d_release_shape(src_rectangle);
4624 // *err=1;
4625 // return(0);
4626 //}
4627
4628 // erase temporary char if R2D is starting to draw a new char
4629 // (it is not always the case with diacritics chars)
4630
4631 //r2d_set_background_color_with_argb(font_cache_gc,0,0,255,0);
4632 r2d_fill_rectangle(font_cache_gc,-1,-1,r2d_get_width(font_cache_gc)+1,
4633 r2d_get_height(font_cache_gc)+1);
4634 //r2d_set_background_color_with_argb(font_cache_gc,0,255,255,255);
4635
4636 //r2d_release_shape(dst_rectangle);
4637
4638 // Create destination rectangles
4639 dst_rectangle=r2d_new_rectangle(r2d_mb_id,0,0,r2d_get_char_width(met),
4640 r2d_get_char_height(met));
4641 if (dst_rectangle==NULL)
4642 {
4643 r2d_release_shape(src_rectangle);
4644 err=R2D_MEMORY_ERR;
4645 return(err);
4646 }
4647
4648 tdst_rectangle=r2d_clone_shape(r2d_mb_id,dst_rectangle);
4649 if (tdst_rectangle==NULL)
4650 {
4651 r2d_release_shape(src_rectangle);
4652 r2d_release_shape(dst_rectangle);
4653 err=R2D_MEMORY_ERR;
4654 return(err);
4655 }
4656
4657 r2d_translate_shape(tdst_rectangle,1,0);
4658
4659
4660 // set mode
4661 r2d_set_drawing_mode(font_cache_gc,R2D_OR_MODE);
4662
4663 // Build bold char
4664
4665 if (r2d_low_level_blit_rect(fontgc,font_cache_gc,src_rectangle,dst_rectangle,
4666 FALSE,FALSE,FALSE)!=R2D_OK)
4667 {
4668 r2d_release_shape(src_rectangle);
4669 r2d_release_shape(dst_rectangle);
4670 r2d_release_shape(tdst_rectangle);
4671 err=R2D_MEMORY_ERR;
4672 return(err);
4673 }
4674
4675 if (r2d_low_level_blit_rect(fontgc,font_cache_gc,src_rectangle,tdst_rectangle,
4676 FALSE,FALSE,FALSE)!=R2D_OK)
4677 {
4678 r2d_release_shape(src_rectangle);
4679 r2d_release_shape(dst_rectangle);
4680 r2d_release_shape(tdst_rectangle);
4681 err=R2D_MEMORY_ERR;
4682 return(err);
4683 }
4684
4685 if (style & R2D_STRIKETHROUGH)
4686 {
4687 r2d_moveto(font_cache_gc,0,ascent>>1);
4688 r2d_lineto(font_cache_gc,r2d_get_char_width(met),ascent>>1);
4689 }
4690
4691 // Reset mode
4692 r2d_set_drawing_mode(font_cache_gc,R2D_COPY_MODE);
4693
4694 r2d_release_shape(tdst_rectangle);
4695
4696 r2d_release_shape(dst_rectangle);
4697 r2d_release_shape(src_rectangle);
4698
4699 // Recreate src and dest rectangle
4700 src_rectangle=r2d_new_rectangle(r2d_mb_id,0,0,r2d_get_char_width(met)+1,
4701 r2d_get_char_height(met));
4702 if (src_rectangle==NULL)
4703 {
4704 err=R2D_MEMORY_ERR;
4705 return(err);
4706 }
4707
4708 if (org_size != 0)
4709 {
4710 INT16 tmp;
4711
4712 tmp=(org_size-r2d_get_char_width(met))>>1;
4713 dst_rectangle=r2d_new_rectangle(r2d_mb_id,x+tmp,y-r2d_get_char_height(met),
4714 x+tmp+r2d_get_char_width(met)+1,y);
4715 }
4716 else
4717 dst_rectangle=r2d_new_rectangle(r2d_mb_id,x+r2d_get_char_org_x(met),
4718 y-r2d_get_char_org_y(met),
4719 x+r2d_get_char_width(met)+r2d_get_char_org_x(met)+1,
4720 y+r2d_get_char_height(met)-r2d_get_char_org_y(met));
4721
4722 if (dst_rectangle==NULL)
4723 {
4724 r2d_release_shape(src_rectangle);
4725 err=R2D_MEMORY_ERR;
4726 return(err);
4727 }
4728 //printf("free_pos=%d, char_width=%d\n",free_pos,char_width);
4729 if (r2d_low_level_blit_rect(font_cache_gc,gc,src_rectangle,dst_rectangle,
4730 FALSE,TRUE,TRUE)!=R2D_OK)
4731 {
4732 r2d_release_shape(src_rectangle);
4733 r2d_release_shape(dst_rectangle);
4734 err=R2D_MEMORY_ERR;
4735 return(err);
4736 }
4737
4738 }
4739 else
4740 {
4741 #if (R2D_REFRESH == R2D_VERTICAL)
4742 src_rectangle=r2d_new_rectangle(r2d_mb_id,r2d_get_char_x(met),
4743 0,
4744 r2d_get_char_x(met)+r2d_get_char_width(met),
4745 r2d_get_char_height(met));
4746 #else
4747 // In horizontal mode char are organized vertically
4748 src_rectangle=r2d_new_rectangle(r2d_mb_id,0,
4749 r2d_get_char_x(met),
4750 r2d_get_char_width(met),
4751 r2d_get_char_x(met)+r2d_get_char_height(met));
4752 #endif
4753 if (src_rectangle==NULL)
4754 {
4755 err=R2D_MEMORY_ERR;
4756 return(err);
4757 }
4758
4759 if (org_size != 0)
4760 {
4761 INT16 tmp;
4762
4763 tmp=(org_size-r2d_get_char_width(met))>>1;
4764 dst_rectangle=r2d_new_rectangle(r2d_mb_id,x+tmp,
4765 y-r2d_get_char_height(met),
4766 x+tmp+r2d_get_char_width(met),y);
4767 }
4768 else
4769 dst_rectangle=r2d_new_rectangle(r2d_mb_id,
4770 x+r2d_get_char_org_x(met),
4771 y-r2d_get_char_org_y(met),
4772 x+r2d_get_char_width(met)+r2d_get_char_org_x(met),
4773 y+r2d_get_char_height(met)-r2d_get_char_org_y(met));
4774
4775 if (dst_rectangle==NULL)
4776 {
4777 r2d_release_shape(src_rectangle);
4778 err=R2D_MEMORY_ERR;
4779 return(err);
4780 }
4781
4782 if (style & R2D_STRIKETHROUGH)
4783 {
4784 r2d_fill_rectangle(font_cache_gc,-1,-1,r2d_get_width(font_cache_gc)+1,
4785 r2d_get_height(font_cache_gc)+1);
4786 tdst_rectangle=r2d_new_rectangle(r2d_mb_id,0,0,r2d_get_char_width(met),
4787 r2d_get_char_height(met));
4788
4789 if (tdst_rectangle==NULL)
4790 {
4791 r2d_release_shape(src_rectangle);
4792 r2d_release_shape(dst_rectangle);
4793 err=R2D_MEMORY_ERR;
4794 return(err);
4795 }
4796
4797 err=r2d_low_level_blit_rect(fontgc,font_cache_gc,src_rectangle,tdst_rectangle,
4798 FALSE,FALSE,FALSE);
4799 if (err==R2D_OK)
4800 {
4801 r2d_moveto(font_cache_gc,0,ascent>>1);
4802 r2d_lineto(font_cache_gc,r2d_get_char_width(met),ascent>>1);
4803 err=r2d_low_level_blit_rect(font_cache_gc,gc,tdst_rectangle,dst_rectangle,
4804 FALSE,TRUE,TRUE);
4805 }
4806
4807 r2d_release_shape(tdst_rectangle);
4808 }
4809 else
4810 {
4811 err=r2d_low_level_blit_rect(fontgc,gc,src_rectangle,dst_rectangle,
4812 FALSE,TRUE,TRUE);
4813 }
4814
4815 if (err!=R2D_OK)
4816 {
4817 r2d_release_shape(src_rectangle);
4818 r2d_release_shape(dst_rectangle);
4819 err=R2D_MEMORY_ERR;
4820 return(err);
4821 }
4822
4823
4824 }
4825
4826
4827
4828 if (style & R2D_UNDERLINED)
4829 {
4830 r2d_moveto(gc,x+r2d_get_char_org_x(met),y+underline);
4831 r2d_lineto(gc,x+r2d_get_char_org_x(met)+
4832 r2d_get_char_dx(met),y+underline);
4833 }
4834
4835 r2d_release_shape(src_rectangle);
4836 r2d_release_shape(dst_rectangle);
4837
4838
4839 }
4840 return(err);
4841 }
4842
4843
4844 #define R2D_ENDIAN_SWAP(a) {misc=(a&0x0FF) << 8;a=a>>8;a=a|misc;a=a&0x0FFFF;}
4845
4846 UINT32 r2d_get_next_char(T_R2D_UTF16 *the_text,INT16 *pos,UINT16 max_chars,
4847 BOOLEAN *swapping)
4848 {
4849 T_R2D_UTF16 current;
4850 INT16 temp;
4851 INT32 the_char;
4852 BOOLEAN must_display,combining,done;
4853 T_R2D_UTF16 next, misc;
4854 // T_R2D_CHAR_METRIC_PTR p;
4855 // Swapping should be set to FALSE first time this function is called
4856
4857
4858
4859
4860 // current char consider a WHOLE char
4861 // (when combining char are used, they are considered
4862 // as making ONE char)
4863 done=FALSE;
4864
4865 // Detection of byte order mark
4866 if (the_text[*pos] == 0xFFFE)
4867 {
4868 *swapping=TRUE;
4869 *pos=*pos+1;
4870 }
4871 while ((!done) && (the_text[*pos]!=0) && (*pos<max_chars))
4872 {
4873 must_display=FALSE;
4874 combining=FALSE;
4875
4876 current=the_text[*pos];
4877 *pos=*pos+1;
4878 if (*swapping)
4879 R2D_ENDIAN_SWAP(current);
4880
4881 if ((current != 0x0FFFF))
4882 {
4883 // If High-surrogate
4884 if ((current >= 0xd800) && (current <= 0xdbff))
4885 {
4886 // Then check that next char if a low-surrogate
4887 next=the_text[*pos];
4888 if (*swapping)
4889 R2D_ENDIAN_SWAP(next);
4890
4891 if ((next >= 0xdc00) && (next<=0xdfff))
4892 {
4893 *pos=*pos+1;
4894 the_char=(current - 0xd800) * 0x400 + (next - 0xdc00) + 0x10000;
4895 must_display=TRUE;
4896 }
4897 else
4898 {
4899 rvf_send_trace("r2d_get_next_char() missing low surrogate char",
4900 strlen("r2d_get_next_char() missing low surrogate char"), NULL_PARAM,
4901 RV_TRACE_LEVEL_ERROR, R2D_USE_ID );
4902 }
4903 }
4904 else
4905 {
4906 // If not a high-surrogate then check it is not
4907 // a low-surrogate
4908 if ((current < 0xdc00) || (current>0xdfff))
4909 {
4910 the_char=current;
4911 must_display=TRUE;
4912 }
4913 else
4914 {
4915 rvf_send_trace("R2D : r2d_get_next_char unexpected low surrogate char",
4916 strlen("R2D : r2d_get_next_char unexpected low surrogate char"), NULL_PARAM,
4917 RV_TRACE_LEVEL_ERROR, R2D_USE_ID );
4918 }
4919
4920 }
4921 }
4922
4923 if ((the_char>=0x300) && (the_char <=0x36f))
4924 combining=TRUE;
4925
4926 if (must_display)
4927 {
4928
4929 if (!combining)
4930 {
4931 // Next char
4932 done=TRUE;
4933
4934 }
4935 }
4936
4937
4938 }
4939 if (done)
4940 return(the_char);
4941 else
4942 return(0);
4943 }
4944 //
4945 static T_R2D_ERROR r2d_low_draw_text(T_R2D_GC_PTR gc,INT16 x,INT16 y,
4946 T_R2D_UTF16 *the_text,
4947 T_R2D_TEXT_DRAWING_SETTINGS settings,
4948 UINT16 max_words,
4949 UINT16 *width,
4950 UINT16 *height)
4951 {
4952 T_R2D_GC_PTR fontgc;
4953 T_R2D_GC_PTR cache_gc;
4954 BOOLEAN draw;
4955 T_R2D_DRAWING_MODE the_mode;
4956 T_R2D_UTF16 *temp;
4957 INT16 err;
4958 INT16 current_word;
4959 INT32 the_char;
4960 BOOLEAN must_display,swapping,combining;
4961 INT16 delta,deltay,misc,current_y,maxx,delta_line,y_org;
4962 T_R2D_UTF16 next,current;
4963 T_R2D_CHAR_METRIC_PTR p;
4964
4965
4966 INT16 x_org;
4967
4968
4969
4970 draw=((settings & R2D_TEXT_DRAW)==R2D_TEXT_DRAW);
4971
4972 if (the_text==NULL)
4973 return(R2D_MEMORY_ERR);
4974
4975 x_org=x;
4976 y_org=y;
4977
4978 maxx=0;
4979
4980
4981
4982 current_word=0; // We are at first word in string
4983 // current word consider a word which may be a partial char
4984 // (when combining char are used, they are considered
4985 // as making ONE char)
4986 swapping=FALSE;
4987
4988 if (draw)
4989 {
4990 // +1 used since blit_rect is using a bounding rect
4991 cache_gc=r2d_new_font_buffer_context(r2d_mb_id,((T_R2D_GC*)gc)->font_frame_buffer->kind,
4992 ((T_R2D_GC*)gc)->font_metrics[R2D_BUFFER_WIDTH_POS]+1,// max width for free area
4993 ((T_R2D_GC*)gc)->font_metrics[R2D_BUFFER_WIDTH_POS+1]+ // ascent
4994 ((T_R2D_GC*)gc)->font_metrics[R2D_BUFFER_WIDTH_POS+2]+ // descent
4995 ((T_R2D_GC*)gc)->font_metrics[R2D_BUFFER_WIDTH_POS+3]); // leading
4996
4997 delta_line=((T_R2D_GC*)gc)->font_metrics[R2D_BUFFER_WIDTH_POS+1]+ // ascent
4998 ((T_R2D_GC*)gc)->font_metrics[R2D_BUFFER_WIDTH_POS+2]+ // descent
4999 ((T_R2D_GC*)gc)->font_metrics[R2D_BUFFER_WIDTH_POS+3];
5000
5001
5002 if (cache_gc==NULL)
5003 return(R2D_MEMORY_ERR);
5004
5005 r2d_context_lock(cache_gc);
5006
5007 fontgc=r2d_new_context(r2d_mb_id,((T_R2D_GC*)gc)->font_frame_buffer);
5008 //r2d_release_framebuffer(((T_R2D_GC*)gc)->font_frame_buffer);
5009
5010
5011 if (fontgc==NULL)
5012 {
5013 r2d_context_unlock(cache_gc);
5014 r2d_release_context(cache_gc);
5015 return(R2D_MEMORY_ERR);
5016 }
5017
5018 r2d_context_lock(fontgc);
5019
5020 r2d_set_background_color_with_argb(fontgc,0,255,255,255);
5021 r2d_set_foreground_color_with_argb(fontgc,0,0,0,0);
5022
5023 the_mode=r2d_get_drawing_mode(gc);
5024 }
5025
5026 err=R2D_OK;
5027 delta=0;
5028 deltay=0;
5029 current_y=y;
5030 // Detection of byte order mark
5031 if (*the_text == 0xFFFE)
5032 {
5033 swapping=TRUE;
5034 the_text++;
5035 current_word++;
5036 }
5037 while((*the_text!=0) && (err==R2D_OK) && (current_word<max_words))
5038 {
5039 must_display=FALSE;
5040 combining=FALSE;
5041 if (the_char!=0xa)
5042 x+=delta;
5043
5044 delta = 0;
5045
5046 current=*the_text++;
5047 current_word++;
5048
5049 if (swapping)
5050 R2D_ENDIAN_SWAP(current);
5051
5052 if ((current != 0x0FFFF))
5053 {
5054 // If High-surrogate
5055 if ((current >= 0xd800) && (current <= 0xdbff))
5056 {
5057 // Then check that next char if a low-surrogate
5058 next=*the_text;
5059 if (swapping)
5060 R2D_ENDIAN_SWAP(next);
5061 if ((next >= 0xdc00) && (next<=0xdfff))
5062 {
5063 the_text++;
5064 current_word++;
5065 the_char=(current - 0xd800) * 0x400 + (next - 0xdc00) + 0x10000;
5066 must_display=TRUE;
5067 }
5068 else
5069 {
5070 rvf_send_trace("r2d_low_draw_text() missing low surrogate char",
5071 strlen("r2d_low_draw_text() missing low surrogate char"), NULL_PARAM,
5072 RV_TRACE_LEVEL_ERROR, R2D_USE_ID );
5073 }
5074 }
5075 else
5076 {
5077 // If not a high-surrogate then check it is not
5078 // a low-surrogate
5079 if ((current < 0xdc00) || (current>0xdfff))
5080 {
5081 the_char=current;
5082 must_display=TRUE;
5083 }
5084 else
5085 {
5086 rvf_send_trace("r2d_low_draw_text() unexpected low surrogate char",
5087 strlen("r2d_low_draw_text() unexpected low surrogate char"), NULL_PARAM,
5088 RV_TRACE_LEVEL_ERROR, R2D_USE_ID );
5089 }
5090 }
5091 }
5092
5093 if ((the_char>=0x300) && (the_char <=0x36f))
5094 combining=TRUE;
5095 else
5096 current_y=y;
5097
5098 if (the_char==0xa)
5099 {
5100 if ((x-x_org)>maxx)
5101 maxx=x-x_org;
5102
5103 if ((x_org-x)>maxx)
5104 maxx=x_org-x;
5105 x=x_org;
5106 y += delta_line;
5107
5108 }
5109
5110 if ((must_display) && (the_char!=0xa))
5111 {
5112 p=r2d_get_char_metrics(gc,the_char);
5113 if (combining)
5114 {
5115
5116 if (draw)
5117 {
5118
5119 current_y -= deltay;
5120 x=x-delta;
5121
5122 if (((T_R2D_GC*)gc)->script_mode==R2D_LEFT_TO_RIGHT)
5123 err=r2d_draw_char(cache_gc,gc,fontgc,x,current_y,delta,p);
5124 else
5125 err=r2d_draw_char(cache_gc,gc,fontgc,x+delta,current_y,delta,p);
5126 deltay=r2d_get_char_height(p);
5127 }
5128 }
5129 else
5130 {
5131 if (draw)
5132 {
5133
5134
5135 if (((T_R2D_GC*)gc)->script_mode==R2D_LEFT_TO_RIGHT)
5136 {
5137 delta=r2d_get_char_dx(p);
5138 err=r2d_draw_char(cache_gc,gc,fontgc,x,current_y,0,p);
5139
5140 }
5141 else
5142 {
5143 delta=-r2d_get_char_dx(p);
5144 err=r2d_draw_char(cache_gc,gc,fontgc,x+delta,current_y,0,p);
5145 }
5146 deltay=r2d_get_char_height(p);
5147
5148 }
5149 else
5150 {
5151
5152 if (((T_R2D_GC*)gc)->script_mode==R2D_LEFT_TO_RIGHT)
5153 delta=r2d_get_char_dx(p);
5154 else
5155 delta=-r2d_get_char_dx(p);
5156 }
5157 }
5158 }
5159
5160
5161 }
5162 if (the_char!=0xa)
5163 x+=delta;
5164
5165 if ((x-x_org)>maxx)
5166 maxx=x-x_org;
5167
5168 if ((x_org-x)>maxx)
5169 maxx=x_org-x;
5170
5171 /*if (((T_R2D_GC*)gc)->script_mode==R2D_LEFT_TO_RIGHT)
5172 *result=x-x_org;
5173 else
5174 *result=x_org-x;*/
5175
5176 *width=maxx;
5177 *height=y-y_org+delta_line;
5178
5179 if (draw)
5180 {
5181 r2d_set_drawing_mode(gc,the_mode);
5182
5183 r2d_context_unlock(fontgc);
5184 r2d_context_unlock(cache_gc);
5185 r2d_release_context(fontgc);
5186 r2d_release_context(cache_gc);
5187
5188 r2d_check_and_send_event(gc);
5189 }
5190
5191 return(err);
5192
5193 }
5194
5195 T_R2D_ERROR r2d_get_text_width(T_R2D_GC_PTR gc,T_R2D_UTF16 *the_text,UINT16 *size)
5196 {
5197 UINT16 x,y;
5198 T_R2D_ERROR err;
5199 err=R2D_OK;
5200
5201
5202 err=r2d_low_draw_text(gc,0,0,the_text,0,-1,&x,&y);
5203
5204 if (err!=R2D_OK)
5205 *size=1;
5206 else
5207 {
5208 if (x>=0)
5209 *size=x;
5210 else
5211 *size=-x;
5212 }
5213
5214 return(err);
5215 }
5216
5217 T_R2D_ERROR r2d_get_width_of_chars(T_R2D_GC_PTR gc,T_R2D_UTF16 *the_text,
5218 UINT16 nb_chars,UINT16 *size)
5219 {
5220 UINT16 x,y;
5221 T_R2D_ERROR err;
5222
5223 err=r2d_low_draw_text(gc,0,0,the_text,0,nb_chars,&x,&y);
5224
5225
5226 if (err!=R2D_OK)
5227 *size=1;
5228 else
5229 {
5230 if (x>=0)
5231 *size=x;
5232 else
5233 *size=-x;
5234 }
5235
5236 return(err);
5237 }
5238
5239
5240 T_R2D_ERROR r2d_draw_text(T_R2D_GC_PTR gc,INT16 x,INT16 y,T_R2D_UTF16 *the_text)
5241 {
5242 UINT16 r,h;
5243 return(r2d_low_draw_text(gc,x,y,the_text,R2D_TEXT_DRAW,-1,&r,&h));
5244 }
5245
5246
5247 T_R2D_ERROR r2d_draw_chars(T_R2D_GC_PTR gc,INT16 x,INT16 y,
5248 T_R2D_UTF16 *the_text,UINT16 nb_chars)
5249 {
5250 UINT16 r,h;
5251 return(r2d_low_draw_text(gc,x,y,the_text,R2D_TEXT_DRAW,nb_chars,&r,&h));
5252 }
5253
5254 T_R2D_ERROR r2d_draw_chars_and_get_size(T_R2D_GC_PTR gc,INT16 x,INT16 y,T_R2D_UTF16 *the_text,
5255 UINT16 nb_words16,UINT16 *width,UINT16 *height)
5256 {
5257 return(r2d_low_draw_text(gc,x,y,the_text,R2D_TEXT_DRAW,nb_words16,width,height));
5258 }
5259
5260 T_R2D_UTF16 *r2d_new_unicode_from_cstring(T_RVF_MB_ID bank,unsigned char *the_string)
5261 {
5262 T_R2D_UTF16 *result,*p;
5263 // INT16 i;
5264 INT16 index;
5265
5266 R2D_MALLOC(bank,T_R2D_UTF16,sizeof(T_R2D_UTF16)*(strlen((char*)the_string)+1),result);
5267 if (result!=NULL)
5268 {
5269 p=result;
5270 while(*the_string!='\0')
5271 {
5272 index=*the_string++;
5273 *p++ = R2D_WIN_LATIN1_TO_UNICODE[index];
5274 }
5275 *p++ = 0;
5276 }
5277 return(result);
5278 }
5279
5280 T_R2D_UTF16 *r2d_new_unicode_from_pstring(T_RVF_MB_ID bank,unsigned char *the_string)
5281 {
5282 T_R2D_UTF16 *result,*p;
5283 INT16 l,index;
5284 // INT16 i;
5285
5286 R2D_MALLOC(bank,T_R2D_UTF16,sizeof(T_R2D_UTF16)*(the_string[0]+1),result);
5287 if (result!=NULL)
5288 {
5289 p=result;
5290 l=*the_string++;
5291
5292 while(l!=0)
5293 {
5294 index=*the_string++;
5295 *p++ = R2D_WIN_LATIN1_TO_UNICODE[index];
5296 l--;
5297 }
5298 *p++ = 0;
5299 }
5300 return(result);
5301 }
5302
5303
5304 void r2d_get_font_info(T_R2D_GC_PTR gc,INT16 *ascent,INT16 *descent,INT16 *leading)
5305 {
5306 INT32 *p;
5307
5308
5309 p=((T_R2D_GC*)gc)->font_metrics;
5310
5311 *p--;
5312 *leading=*--p;
5313 *descent=*--p;
5314 *ascent=*--p;
5315
5316 }
5317
5318 INT16 r2d_str_nb_word16(T_R2D_UTF16 *l)
5319 {
5320 INT16 res;
5321 T_R2D_UTF16 *p;
5322
5323 if (l==NULL)
5324 return 0;
5325
5326 p=l;
5327 res=0;
5328
5329 while(*p!=0)
5330 {
5331 p++;
5332 res++;
5333 }
5334 return(res);
5335 }
5336
5337 T_R2D_UTF16 *r2d_duplicate_text(T_RVF_MB_ID bank,T_R2D_UTF16 *l)
5338 {
5339 T_R2D_UTF16 *ret;
5340 INT16 len;
5341
5342 if (l==NULL)
5343 return(NULL);
5344
5345 len=r2d_str_nb_word16(l);
5346 rvf_get_buf(bank,(len+1)*sizeof(T_R2D_UTF16),(void*)&ret);
5347 if (ret)
5348 {
5349 memcpy(ret,l,(len+1)*2);
5350 return(ret);
5351 }
5352 else return(NULL);
5353 }
5354
5355
5356
5357 T_R2D_SCRIPT_MODE r2d_get_script_mode(T_R2D_GC_PTR gc)
5358 {
5359 return(((T_R2D_GC*)gc)->script_mode);
5360 }
5361
5362 void r2d_set_script_mode(T_R2D_GC_PTR gc,T_R2D_SCRIPT_MODE mode)
5363 {
5364 ((T_R2D_GC*)gc)->script_mode=mode;
5365 }