FreeCalypso > hg > fc-tourmaline
diff src/cs/drivers/drv_app/r2d/r2d.c @ 0:4e78acac3d88
src/{condat,cs,gpf,nucleus}: import from Selenite
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Fri, 16 Oct 2020 06:23:26 +0000 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/cs/drivers/drv_app/r2d/r2d.c Fri Oct 16 06:23:26 2020 +0000 @@ -0,0 +1,5365 @@ +/** + + @file r2d.c + + @author Christophe Favergeon + + @version 0.5 + + Function Riviera 2D system implementation + (higher software layer) + +*/ + +/* + Date Modification + ------------------------ + 06/12/2001 Create + 10/18/2001 Version 0.5 for first integration with Riviera database + ************************************************************************** + History + + Apr-06-2005 MMI-SPR-29655 - xreddymn + Added function r2d_flush_region to allow flushing of portions + of framebuffer to the display + +*/ + + +#include "rv/general.h" +#include "rvf/rvf_api.h" +#include "r2d/r2d_config.h" +#include "r2d/r2d.h" +#include "r2d/r2d_i.h" +#include "r2d/r2d_independance_layer.h" +#include "r2d/r2d_convertion_table.h" +#include "r2d/r2d_env.h" +#include "rvm/rvm_use_id_list.h" +#include <string.h> + +#include "r2d_cos.c" + + +#ifdef _WINDOWS + #pragma warning(disable:4761) // integral size mismatch in argument; conversion supplied +#endif + + +/*************************************** + + IMPORTANT INFORMATION + +***************************************/ + +/* + +Clipping is done on original coordinates. +Then those coordinates are modified to take into account a possible +mirror symetry of the LCD. +Then the scanning algorithm is applied on those transformed and clipped +coordinates. It assumes a vertical scanning (column per column). +If it is not the case. The high level coordinates (x,y) are swapped +after clipping and mirroring. The scanning is done on the swapped coordinates +so that coulmns are mapped to lines. + +Subroutine's comment use following rule: +H -> High level user coordinates +L -> LCD coordinates (mirroring or not and local_to_global applied) +S -> Scanning coordinates (vertical or horizontal) +*/ + +/*************************************** + + CONSTANTS + +***************************************/ + +// Used for char drawing algorithm with unicode +typedef enum K_R2D_CHAR_DRAWING_MODE +{ +R2D_COMBINING_CHAR=1 +} T_R2D_CHAR_DRAWING_MODE; + +// Used for internal drawing function +typedef enum K_R2D_TEXT_DRAWING_SETTINGS +{ + R2D_TEXT_DRAW=1 +} T_R2D_TEXT_DRAWING_SETTINGS; + + + + + +/*************************************** + + REFRESH TASK RELATED GLOBALS + +***************************************/ + +extern INT16 r2d_update_ul_x,r2d_update_ul_y,r2d_update_br_x,r2d_update_br_y; + +/*************************************** + + STATIC INTERNAL FUNCTIONS + AND GLOBALS + +***************************************/ + + +#define IND_r2d_write_lcd_line r2d_write_lcd_line +#define IND_r2d_write_lcd_pixel r2d_write_lcd_pixel +#define IND_r2d_blit_lcd_to_lcd r2d_blit_lcd_to_lcd +#define IND_r2d_blit_lcd_to_color r2d_blit_lcd_to_color +#define IND_r2d_blit_color_to_lcd r2d_blit_color_to_lcd +#define IND_r2d_blit_color_to_color r2d_blit_color_to_color +#define IND_r2d_get_color_pixel_value r2d_get_color_pixel_value + +static T_R2D_GC_PTR r2d_new_font_buffer_context(T_RVF_MB_ID bank, + T_R2D_FRAMEBUFFER_KIND kind, + UINT16 max_width, + UINT16 ascent); +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); +static T_R2D_SHAPE_PTR r2d_s_level(T_R2D_GC_PTR gc,T_R2D_SHAPE_PTR self); +static void r2d_mirror_rectangle(T_R2D_GC_PTR gc,T_R2D_SHAPE_PTR rectangle); +static void r2d_mirror_clip_rectangle(T_R2D_GC_PTR gc,T_R2D_SHAPE_PTR rectangle); +static void r2d_diagonal_mirror(T_R2D_SHAPE_PTR rectangle); + +static void r2d_update_region(T_R2D_GC *gc,INT16 ul_x,INT16 ul_y,INT16 br_x,INT16 br_y); + +void r2d_translate_shape(T_R2D_SHAPE_PTR self,INT16 dx,INT16 dy); + +// Used for pen_size != 1. It computes the bounding rect and calls +// fillrectangle +static void r2d_s_fill_point(T_R2D_GC_PTR gc,INT16 x,INT16 y,INT16 pen_size); + +static void r2d_df_rectangle(T_R2D_GC_PTR gc, + INT16 ul_x,INT16 ul_y,INT16 br_x, INT16 br_y,BOOLEAN background); +static void r2d_s_fill_rectangle(T_R2D_GC_PTR gc, + INT16 ul_x,INT16 ul_y,INT16 br_x, INT16 br_y,BOOLEAN background); + + + +#define R2D_SQUARE_P(x) (x*x) +#define R2D_SWAP(x,y) tmp=x; x=y; y=tmp +#define SQRT2 0x16A09 +#define PI 0x3243F + +//////////////////////////////////////// +// +// Utility functions +// + +// L COORDINATES +void r2d_update_region(T_R2D_GC* gc,INT16 ul_x,INT16 ul_y,INT16 br_x,INT16 br_y) +{ + + INT16 tmp; + + rvf_lock_mutex(r2d_g_global_mutex); + + if (ul_x>br_x) + { + tmp=ul_x; + ul_x=br_x; + br_x=tmp; + } + + if (ul_y>br_y) + { + tmp=ul_y; + ul_y=br_y; + br_y=tmp; + } + + if (gc) + { + if (ul_x<((T_R2D_RECT*)(gc->p_clipping_shape))->ul_x-gc->org_x) + ul_x=((T_R2D_RECT*)(gc->p_clipping_shape))->ul_x-gc->org_x; + if (ul_y<((T_R2D_RECT*)(gc->p_clipping_shape))->ul_y-gc->org_y) + ul_y=((T_R2D_RECT*)(gc->p_clipping_shape))->ul_y-gc->org_y; + if (br_x>=((T_R2D_RECT*)(gc->p_clipping_shape))->br_x-1-gc->org_x) + br_x=((T_R2D_RECT*)(gc->p_clipping_shape))->br_x-1-gc->org_x; + if (br_y>=((T_R2D_RECT*)(gc->p_clipping_shape))->br_y-1-gc->org_y) + br_y=((T_R2D_RECT*)(gc->p_clipping_shape))->br_y-1-gc->org_y; + } + + if (ul_x < r2d_update_ul_x) + r2d_update_ul_x=ul_x; + if (ul_y < r2d_update_ul_y) + r2d_update_ul_y=ul_y; + if (br_x > r2d_update_br_x) + r2d_update_br_x=br_x; + if (br_y > r2d_update_br_y) + r2d_update_br_y=br_y; + + + if (r2d_update_ul_x<0) + r2d_update_ul_x=0; + if (r2d_update_ul_y<0) + r2d_update_ul_y=0; + if (r2d_update_br_x>=R2D_WIDTH) + r2d_update_br_x=R2D_WIDTH-1; + if (r2d_update_br_y>=R2D_HEIGHT) + r2d_update_br_y=R2D_HEIGHT-1; + + + rvf_unlock_mutex(r2d_g_global_mutex); +} + + +void r2d_check_and_send_event(T_R2D_GC_PTR gc) +{ + // If routine has drawn into the LCD framebuffer + // then refresh may be required + // If LCD framebuffer ONLY + if (((T_R2D_FRAMEBUFFER*)(((T_R2D_GC*)gc)->p_frame_buffer))->kind==0) + { + if ((r2d_g_event_was_sent==FALSE) && (r2d_g_refresh_disabled==0)) + { + //rvf_send_trace("R2D SEND EVENT",strlen("R2D SEND EVENT"), NULL_PARAM, + //RV_TRACE_LEVEL_DEBUG_HIGH, TRACE_XXX ); + r2d_g_event_was_sent=TRUE; + rvf_send_event( (UINT8)(r2d_addr_id & 0xFF), EVENT_MASK(RVF_APPL_EVT_0) ); + } + } +} + +// WILL HAVE TO BE IMPROVED + +INT32 r2d_fixed_division(INT32 a,INT32 b) +{ + INT16 k; + UINT32 q,nb; + INT16 right_shift=0; + INT16 sign=0; + + // Convert to positive values + if ((b<0) && (a<0)) + { + b=-b; + a=-a; + } + if ((b<0) && (a>=0)) + { + b=-b; + sign=1; + } + if ((a<0) && (b>=0)) + { + a=-a; + sign=1; + } + + + // Normalize b between in [0.5,1[ + + + nb=b; + + if (nb>=0x10000) + { + //printf("%08X/%08X\n",a,nb); + while(((nb>>16)&0x0FFFF)!=0) + { + nb>>=1; + right_shift++; + //printf("%08X\n",nb); + } + } else if (nb<0x8000) + { + while((nb&0x8000)==0) + { + nb<<=1; + right_shift--; + //printf("%08X\n",nb); + } + } + //printf("right_shift=%d\n",right_shift); + if (nb==0x8000) + { + //printf("nb=0x8000, return %08X\n",((a>>right_shift)<<1)); + if (sign) + return (-((a>>right_shift)<<1)); + else + return (((a>>right_shift)<<1)); + } + + + + + // Newton method used to compute 1/nb with + // q=q(2-nb * q) + + // Which first choice for q and which accuracies for intermediate + // computations ? + + + // nb being in ]0.5,1[ one must has q in ]0.5, 3[ + // And one must check that the function is contracting + // Derivative is nul for q*nb = 1. Below, sign of + // derivatuve (relatively to q) is positive if a<1 and + // the derivative is between 2 and 0 + // <1 is got for q>1/(2 nb) and q must be < 1/nb + // One can take q=1 as starting value. It solves + // for the bounds except for nb=1 or nb=0.5 + + // if q in ]1/2nb, 1/nb[ one can check that qnew + // will at most reach 3/2nb at next iteration and then will + // fall back into the intervall + // So, one needs to represents values up to 3 for q + // and 2 bits are required for integer part + + // So, q is 2.16, nb is 0.16 + // q*nb is 2.32 which cannot be represented and one needs + // to shift value by 1 bit + // nb will be 0.15 and q 2.15 sor nb*q is 2.30 + // It must be multiplied by a format 2.16 + // so both intermediate result must be shifted to + // 2.15 (1 for q and 15 for np*q) + + + + q=(1<<16); + //printf("-- q=%08X\n",q); + + + for(k=0;k<5;k++) + { + q=((q>>1) * ((2 << 15) - (((nb>>1) * (q>>1)) >> 15))) >> 14; + //printf("-- q=%08X\n",q); + } + + // a is known to be an integer and q is know to be less than 1 + // so a 64 bits product is not required + + //printf("a=%08X, q=%08X\n",a,q); + + q>>=right_shift; + + q=((a>>16)*q) ; + + + //printf("right_shift=%d, q=%08X\n",right_shift,q); + + if (sign) + return(-((INT32)q)); + else + return(q); + + +} + +//////////////////////////////////////// +// +// Texture +// + +T_R2D_FREE_TEXTURE_PTR r2d_new_free_texture(T_RVF_MB_ID bank,INT16 size,T_R2D_ARGB_COLOR *pattern) +{ + T_R2D_FREE_TEXTURE *t; + + R2D_MALLOC(bank,T_R2D_FREE_TEXTURE,sizeof(T_R2D_FREE_TEXTURE),t); + + if (t) + { + t->refcount=1; + t->size=size; + t->pattern=pattern; + } + + return(t); +} + +T_R2D_FREE_TEXTURE_PTR r2d_new_const_free_texture(T_RVF_MB_ID bank,INT16 size,T_R2D_ARGB_COLOR *pattern) +{ + T_R2D_FREE_TEXTURE *t; + + R2D_MALLOC(bank,T_R2D_FREE_TEXTURE,sizeof(T_R2D_FREE_TEXTURE),t); + + if (t) + { + t->refcount=-1; + t->size=size; + t->pattern=pattern; + } + + return(t); +} + +void r2d_release_free_texture(T_R2D_FREE_TEXTURE_PTR texture) +{ + if (texture) + { + // Remove the array of words if needed + // (refcount must be 1 else the array should not be deleted) + if (R2D_REFCOUNT(texture)==1) + { + if (((T_R2D_FREE_TEXTURE*)texture)->pattern) + R2D_FREE(((T_R2D_FREE_TEXTURE*)texture)->pattern); + } + } + // Autorelease + r2d_release(texture); +} + +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) +{ + + INT16 length; + T_R2D_FREE_TEXTURE *ft; + T_R2D_ANCHORED_TEXTURE *at; + INT16 i,j,x,y,ni,nj,pos; + UINT32 *p; + + T_R2D_ARGB_COLOR b; + + // If a new texture is installed, + // one must recompute p_background + if (texture==NULL) + goto erroranchored; + + + + ft=(T_R2D_FREE_TEXTURE *)texture; + + length=1<<(ft->size); + + R2D_MALLOC(bank,T_R2D_ANCHORED_TEXTURE,sizeof(T_R2D_ANCHORED_TEXTURE),at); + + if (at==NULL) + goto erroranchored; + + at->refcount=1; + + at->size=ft->size; + + R2D_MALLOC(bank,UINT32,sizeof(UINT32)*length*length,at->pattern); + + if (at->pattern==NULL) + { + R2D_FREE(at); + goto erroranchored; + } + + + p=at->pattern; + b=r2d_get_background_color(gc); + + if (((T_R2D_FRAMEBUFFER*)(((T_R2D_GC*)gc)->p_frame_buffer))->kind==R2D_FULL_KIND) + { + x=0; + y=0; + for(i=0;i<length;i++) // Horizontal + for(j=0;j<length;j++) // Vertical + { + r2d_convert_background_color_color(gc,ft->pattern[i*length+j]); + + #if (R2D_REFRESH == R2D_VERTICAL) + #ifdef R2D_MIRRORED_X + ni=(length-1)-i; + #else + ni=i; + #endif + + #ifdef R2D_MIRRORED_Y + nj=(length-1)-j; + #else + nj=j; + #endif + p[ni*length+nj]=((T_R2D_GC*)gc)->background_pixel_value; + #else + #ifdef R2D_MIRRORED_X + nj=(length-1)-j; + #else + nj=j; + #endif + + #ifdef R2D_MIRRORED_Y + ni=(length-1)-i; + #else + ni=i; + #endif + + p[nj*length+ni]=((T_R2D_GC*)gc)->background_pixel_value; + #endif + + } + } + else + { + for(i=0;i<length;i++) + for(j=0;j<length;j++) + { + r2d_convert_background_color(gc,ft->pattern[i*length+j]); + #if (R2D_REFRESH == R2D_VERTICAL) + #ifdef R2D_MIRRORED_X + ni=(length-1)-i; + #else + ni=i; + #endif + + #ifdef R2D_MIRRORED_Y + nj=(length-1)-j; + #else + nj=j; + #endif + pos=ni*length+nj; + #else + #ifdef R2D_MIRRORED_X + nj=(length-1)-j; + #else + nj=j; + #endif + + #ifdef R2D_MIRRORED_Y + ni=(length-1)-i; + #else + ni=i; + #endif + + pos=nj*length+ni; + #endif + #if (R2D_DITHERING == R2D_OFF) + p[pos]=((T_R2D_GC*)gc)->background_pixel_value; + #else + p[pos]=r2d_get_dithering_matrix_entry(((T_R2D_GC*)gc)->p_background_dithered_cache,x,y); + #endif + + #if (R2D_REFRESH == R2D_VERTICAL) + y++; + if (y==length) + { + y=0; + x++; + } + #else + x++; + if (x==length) + { + x=0; + y++; + } + #endif + } + } + // Force change + r2d_set_background_color(gc,b^1); + r2d_set_background_color(gc,b); + + return((T_R2D_ANCHORED_TEXTURE_PTR)at); +erroranchored: return(NULL); +} + +void r2d_release_anchored_texture(T_R2D_ANCHORED_TEXTURE_PTR texture) +{ + if (texture) + { + // Remove the array of words if needed + // (refcount must be 1 else the array should not be deleted) + if (R2D_REFCOUNT(texture)==1) + { + if (((T_R2D_ANCHORED_TEXTURE*)texture)->pattern) + R2D_FREE(((T_R2D_ANCHORED_TEXTURE*)texture)->pattern); + } + } + // Autorelease + r2d_release(texture); +} + + +//////////////////////////////////////// +// +// Framebuffer +// + +UINT32 r2d_get_framebuffer_size(T_R2D_FRAMEBUFFER_KIND the_kind,UINT16 width, UINT16 height) +{ + UINT32 t; + UINT32 length; + + t=0; + + + + + t+=sizeof(T_R2D_FRAMEBUFFER); + + switch(the_kind) + { + case R2D_LCD_KIND: + #if (R2D_REFRESH==R2D_VERTICAL) + // Column is contiguous in memory + length=width*R2D_ALIGNED_MWLENGTH(height); + t+=((length+1)<<R2D_LONGSIZE_FACTOR); + #else + length=height*R2D_ALIGNED_MWLENGTH(width); + t+=((length+1)<<R2D_LONGSIZE_FACTOR); + #endif + break; + default: + length=width*height; + t+=((length+1)<<R2D_LONGSIZE_FACTOR); + break; + } + + t+=sizeof(T_RVF_MUTEX); + + + return(t); +} + +UINT32 r2d_get_gc_size(void) +{ + UINT32 t; + + t=0; + + + t+=sizeof(T_R2D_GC); + t+=sizeof(T_R2D_RECT); // clipping + t+=sizeof(T_R2D_RECT); // s_clipping + t+=sizeof(UINT32)*4; // foreground dithering cache + t+=sizeof(UINT32)*4; // backround dithering cache + + + return(t); +} + + +T_R2D_FRAMEBUFFER_PTR r2d_new_framebuffer(T_RVF_MB_ID bank,T_R2D_FRAMEBUFFER_KIND the_kind,UINT16 width, UINT16 height) +{ + UINT32 length; + T_R2D_FRAMEBUFFER *p; +// UINT32 *elem; + T_RVF_RET err; + + R2D_MALLOC(bank,T_R2D_FRAMEBUFFER,sizeof(T_R2D_FRAMEBUFFER),p); + + if (p) + { + switch(the_kind) + { + case R2D_LCD_KIND: + #if (R2D_REFRESH==R2D_VERTICAL) + // Column is contiguous in memory + length=width*R2D_ALIGNED_MWLENGTH(height); + R2D_MALLOC(bank,UINT32,((length+1)<<R2D_LONGSIZE_FACTOR),p->p_memory_words); + if (!(p->p_memory_words)) + { + R2D_FREE(p); + p=NULL; + return(p); + } + p->refcount=1; + p->kind=R2D_LCD_KIND; + p->p_frame_buffer_end=p->p_memory_words+length; + p->width=width; + p->height=height; + R2D_MALLOC(bank,T_RVF_MUTEX,sizeof(T_RVF_MUTEX),p->mutex); + if (p->mutex!=NULL) + { + err=rvf_initialize_mutex(p->mutex); + if (err!=RVF_OK) + { + R2D_FREE(p->mutex); + R2D_FREE(p->p_memory_words); + R2D_FREE(p); + p=NULL; + return(p); + } + } + else + { + R2D_FREE(p->p_memory_words); + R2D_FREE(p); + p=NULL; + return(p); + } + + #else + // Line is contiguous in memory + length=height*R2D_ALIGNED_MWLENGTH(width); + R2D_MALLOC(bank,UINT32,((length+1)<<R2D_LONGSIZE_FACTOR),p->p_memory_words); + if (!(p->p_memory_words)) + { + R2D_FREE(p); + p=NULL; + return(p); + } + p->refcount=1; + p->kind=R2D_LCD_KIND; + p->p_frame_buffer_end=p->p_memory_words+length; + p->width=width; + p->height=height; + R2D_MALLOC(bank,T_RVF_MUTEX,sizeof(T_RVF_MUTEX),p->mutex); + if (p->mutex!=NULL) + { + err=rvf_initialize_mutex(p->mutex); + if (err!=RVF_OK) + { + R2D_FREE(p->mutex); + R2D_FREE(p->p_memory_words); + R2D_FREE(p); + p=NULL; + return(p); + } + } + else + { + R2D_FREE(p->p_memory_words); + R2D_FREE(p); + p=NULL; + return(p); + } + #endif + break; + default: + length=width*height; + R2D_MALLOC(bank,UINT32,((length+1)<<R2D_LONGSIZE_FACTOR),p->p_memory_words); + if (!(p->p_memory_words)) + { + R2D_FREE(p); + p=NULL; + return(p); + } + p->refcount=1; + p->kind=R2D_FULL_KIND; + p->p_frame_buffer_end=p->p_memory_words+length; + p->width=width; + p->height=height; + R2D_MALLOC(bank,T_RVF_MUTEX,sizeof(T_RVF_MUTEX),p->mutex); + if (p->mutex!=NULL) + { + err=rvf_initialize_mutex(p->mutex); + if (err!=RVF_OK) + { + R2D_FREE(p->mutex); + R2D_FREE(p->p_memory_words); + R2D_FREE(p); + p=NULL; + return(p); + } + } + else + { + R2D_FREE(p->p_memory_words); + R2D_FREE(p); + p=NULL; + return(p); + } + break; + } + } else p=NULL; + + return(p); +} + +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) +{ + UINT32 length; + T_R2D_FONT_CACHE_FRAMEBUFFER *p; +// UINT32 *elem; + T_RVF_RET err; + + R2D_MALLOC(bank,T_R2D_FONT_CACHE_FRAMEBUFFER,sizeof(T_R2D_FONT_CACHE_FRAMEBUFFER),p); + + if (p) + { + switch(the_kind) + { + case R2D_LCD_KIND: + #if (R2D_REFRESH==R2D_VERTICAL) + // Column is contiguous in memory + length=width*R2D_ALIGNED_MWLENGTH(height); + R2D_MALLOC(bank,UINT32,((length+1)<<R2D_LONGSIZE_FACTOR),p->p_memory_words); + if (!(p->p_memory_words)) + { + R2D_FREE(p); + p=NULL; + return(p); + } + p->refcount=1; + p->kind=R2D_LCD_KIND; + p->p_frame_buffer_end=p->p_memory_words+length; + p->width=width; + p->height=height; + R2D_MALLOC(bank,T_RVF_MUTEX,sizeof(T_RVF_MUTEX),p->mutex); + if (p->mutex!=NULL) + { + err=rvf_initialize_mutex(p->mutex); + if (err!=RVF_OK) + { + R2D_FREE(p->mutex); + R2D_FREE(p->p_memory_words); + R2D_FREE(p); + p=NULL; + return(p); + } + } + else + { + R2D_FREE(p->p_memory_words); + R2D_FREE(p); + p=NULL; + return(p); + } + #else + // Line is contiguous in memory + length=height*R2D_ALIGNED_MWLENGTH(width); + R2D_MALLOC(bank,UINT32,((length+1)<<R2D_LONGSIZE_FACTOR),p->p_memory_words); + if (!(p->p_memory_words)) + { + R2D_FREE(p); + p=NULL; + return(p); + } + p->refcount=1; + p->kind=R2D_LCD_KIND; + p->p_frame_buffer_end=p->p_memory_words+length; + p->width=width; + p->height=height; + R2D_MALLOC(bank,T_RVF_MUTEX,sizeof(T_RVF_MUTEX),p->mutex); + if (p->mutex!=NULL) + { + err=rvf_initialize_mutex(p->mutex); + if (err!=RVF_OK) + { + R2D_FREE(p->mutex); + R2D_FREE(p->p_memory_words); + R2D_FREE(p); + p=NULL; + return(p); + } + } + else + { + R2D_FREE(p->p_memory_words); + R2D_FREE(p); + p=NULL; + return(p); + } + #endif + break; + default: + length=width*height; + R2D_MALLOC(bank,UINT32,((length+1)<<R2D_LONGSIZE_FACTOR),p->p_memory_words); + if (!(p->p_memory_words)) + { + R2D_FREE(p); + p=NULL; + return(p); + } + p->refcount=1; + p->kind=R2D_FULL_KIND; + p->p_frame_buffer_end=p->p_memory_words+length; + p->width=width; + p->height=height; + R2D_MALLOC(bank,T_RVF_MUTEX,sizeof(T_RVF_MUTEX),p->mutex); + if (p->mutex!=NULL) + { + err=rvf_initialize_mutex(p->mutex); + if (err!=RVF_OK) + { + R2D_FREE(p->mutex); + R2D_FREE(p->p_memory_words); + R2D_FREE(p); + p=NULL; + return(p); + } + } + else + { + R2D_FREE(p->p_memory_words); + R2D_FREE(p); + p=NULL; + return(p); + } + break; + } + + } else p=NULL; + + return(p); +} + + +// Release a framebuffer +void r2d_release_framebuffer(T_R2D_FRAMEBUFFER_PTR p) +{ + if (p) + { + // Remove the array of words if needed + // (refcount must be 1 else the array should not be deleted) + if (R2D_REFCOUNT(p)==1) + { + R2D_FREE(((T_R2D_FRAMEBUFFER*)p)->p_memory_words); + rvf_delete_mutex(((T_R2D_FRAMEBUFFER*)p)->mutex); + R2D_FREE(((T_R2D_FRAMEBUFFER*)p)->mutex); + } + } + // Autorelease + r2d_release(p); +} + + +//////////////////////////////////////// +// +// Graphic context +// + + +static T_R2D_GC_PTR r2d_new_font_buffer_context(T_RVF_MB_ID bank, + T_R2D_FRAMEBUFFER_KIND kind, + UINT16 max_width, + UINT16 ascent) +{ + T_R2D_FRAMEBUFFER_PTR cache_buffer; + T_R2D_GC_PTR result; + + //printf("width=%d,height=%d\n",the_width,((T_R2D_FRAMEBUFFER*)font_frame_buffer)->height); + + cache_buffer=r2d_new_font_framebuffer(bank,kind, + max_width,ascent); + + + + if (cache_buffer!=NULL) + { + result=r2d_new_context(bank,cache_buffer); + r2d_release_framebuffer(cache_buffer); + + return(result); + } else return(NULL); +} + + +T_R2D_GC_PTR r2d_new_context(T_RVF_MB_ID bank,T_R2D_FRAMEBUFFER_PTR the_frame_buffer) +{ + T_R2D_GC *gc; + + // Allocate a new gc structure + R2D_MALLOC(bank,T_R2D_GC,sizeof(T_R2D_GC),gc); + if (gc) + { + // gc is pointing to the LCD framebuffer + gc->p_frame_buffer=(T_R2D_FRAMEBUFFER*)the_frame_buffer; + r2d_retain(the_frame_buffer); + + // Default initialization for a gc + gc->background_texture=NULL; + gc->foreground_color=r2d_get_standard_argb_color(R2D_BLACK); + gc->background_color=r2d_get_standard_argb_color(R2D_WHITE); + + + #if (R2D_REFRESH == R2D_VERTICAL) + gc->p_s_clipping_shape=r2d_new_rectangle(bank,0,0,((T_R2D_FRAMEBUFFER*)the_frame_buffer)->width, + ((T_R2D_FRAMEBUFFER*)the_frame_buffer)->height); + + #else + 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); + + #endif + + if (gc->p_s_clipping_shape==NULL) + { + r2d_release_framebuffer(the_frame_buffer); + R2D_FREE(gc); + gc=NULL; + return(NULL); + } + + gc->p_clipping_shape=r2d_new_rectangle(bank,0,0,((T_R2D_FRAMEBUFFER*)the_frame_buffer)->width, + ((T_R2D_FRAMEBUFFER*)the_frame_buffer)->height); + + + gc->drawing_mode=R2D_COPY_MODE; + + gc->drawing_op=r2d_get_drawing_op(gc,R2D_COPY_MODE); + + gc->org_x=gc->org_y=0; + gc->s_org_x=gc->s_org_y=0; + + gc->pen_size=1; + gc->dash=0; + gc->text_face=R2D_SYSTEM; + gc->text_style=R2D_PLAIN; + gc->internal_text_style=R2D_PLAIN; + gc->text_size=R2D_SMALL; + gc->script_mode=R2D_LEFT_TO_RIGHT; + gc->font_frame_buffer=r2d_g_default_font_framebuffer; + gc->font_metrics=r2d_g_default_font_metrics; + gc->font_table=r2d_g_default_font_table; + if (gc->p_clipping_shape) + { + r2d_retain(r2d_g_default_font_framebuffer); + + // refcount set to 1 for creation + gc->refcount=1; + R2D_MALLOC(bank,UINT32,sizeof(UINT32)*4,gc->p_foreground_dithered_cache); + if (gc->p_foreground_dithered_cache) + { + R2D_MALLOC(bank,UINT32,sizeof(UINT32)*4,gc->p_background_dithered_cache); + if (gc->p_background_dithered_cache) + { + if (((T_R2D_FRAMEBUFFER*)the_frame_buffer)->kind==R2D_FULL_KIND) + { + r2d_convert_foreground_color_color(gc,gc->foreground_color); + r2d_convert_background_color_color(gc,gc->background_color); + } + else + { + r2d_convert_foreground_color(gc,gc->foreground_color); + r2d_convert_background_color(gc,gc->background_color); + } + } else // cannot create backround dithered matrix + { + r2d_release_shape(gc->p_clipping_shape); + r2d_release_shape(gc->p_s_clipping_shape); + r2d_release_framebuffer(gc->p_frame_buffer); + r2d_release_framebuffer(r2d_g_default_font_framebuffer); + R2D_FREE(((T_R2D_GC *)gc)->p_foreground_dithered_cache); + R2D_FREE(gc); + gc=NULL; + } + } else // Cannot create foreground dithered matrix + { + r2d_release_shape(gc->p_clipping_shape); + r2d_release_shape(gc->p_s_clipping_shape); + r2d_release_framebuffer(gc->p_frame_buffer); + r2d_release_framebuffer(r2d_g_default_font_framebuffer); + R2D_FREE(gc); + gc=NULL; + } + } else // Cannot create clipping shape + { + R2D_FREE(gc); + gc=NULL; + } + } + else + gc=NULL; + return(gc); +} + +T_R2D_GC_PTR r2d_new_lcd_context(T_RVF_MB_ID bank) +{ +// T_R2D_GC *gc; + T_R2D_GC_PTR result; + + result=r2d_new_context(bank,r2d_g_framebuffer); + r2d_release_framebuffer(r2d_g_framebuffer); + return (result); +} + +void r2d_release_context(T_R2D_GC_PTR gc) +{ + if (gc) + { + if (R2D_REFCOUNT(gc)==1) + { + // framebuffer release since it is no more used + r2d_release_framebuffer(((T_R2D_GC *)gc)->font_frame_buffer); + r2d_release_shape(((T_R2D_GC *)gc)->p_clipping_shape); + r2d_release_shape(((T_R2D_GC *)gc)->p_s_clipping_shape); + r2d_release_framebuffer(((T_R2D_GC *)gc)->p_frame_buffer); + R2D_FREE((((T_R2D_GC *)gc)->p_foreground_dithered_cache)); + R2D_FREE((((T_R2D_GC *)gc)->p_background_dithered_cache)); + } + } + + // Autodelete of the gc if required + r2d_release(gc); +} + +T_R2D_GC_PTR r2d_new_picture_context(T_RVF_MB_ID bank,const UINT32 *the_picture,T_R2D_FRAMEBUFFER_KIND kind) +{ + UINT32 h,v,length; + UINT32 *p; + T_R2D_FRAMEBUFFER *buf; + T_R2D_GC_PTR result; + T_RVF_RET err; + + p=((UINT32*)the_picture)+3; + + h=the_picture[0]; + v=the_picture[1]; + length=the_picture[2]; + + rvf_get_buf(bank, sizeof(T_R2D_FRAMEBUFFER), + (T_RVF_BUFFER**)&buf); + + if (buf != NULL) + { + + + + + + + buf->p_memory_words=p; + buf->refcount=-1; // Emulate infinite refcount + buf->kind=kind; + buf->p_frame_buffer_end=p+length; + buf->width=h; + buf->height=v; + + R2D_MALLOC(bank,T_RVF_MUTEX,sizeof(T_RVF_MUTEX),buf->mutex); + if (buf->mutex!=NULL) + { + err=rvf_initialize_mutex(buf->mutex); + if (err!=RVF_OK) + { + R2D_FREE(buf->mutex); + R2D_FREE(buf); + buf=NULL; + return(buf); + } + } + else + { + R2D_FREE(buf); + buf=NULL; + return(buf); + } + + result=r2d_new_context(bank,(T_R2D_FRAMEBUFFER_PTR)buf); + r2d_release_framebuffer(buf); + + return(result); + } else return(NULL); +} + +void r2d_release_picture_context(T_R2D_GC_PTR gc) +{ + T_R2D_FRAMEBUFFER *fb_p; + + if (gc) + { + if (R2D_REFCOUNT(gc) == 1) + { + r2d_release_context(gc); + fb_p = (T_R2D_FRAMEBUFFER *) ((T_R2D_GC *) gc)->p_frame_buffer; + rvf_delete_mutex(fb_p->mutex); + R2D_FREE(fb_p->mutex); + R2D_FREE(fb_p); + } + + r2d_release(gc); + } +} + +UINT16 r2d_get_width(T_R2D_GC_PTR gc) +{ + return(((T_R2D_FRAMEBUFFER*)((T_R2D_GC *)gc)->p_frame_buffer)->width); +} + +UINT16 r2d_get_height(T_R2D_GC_PTR gc) +{ + return(((T_R2D_FRAMEBUFFER*)((T_R2D_GC *)gc)->p_frame_buffer)->height); +} + +void r2d_erase(T_R2D_GC_PTR gc) +{ +// UINT32 *p; + INT16 x,y; + T_R2D_ARGB_COLOR col; + + r2d_get_context_origin(gc,&x,&y); + + col=r2d_get_background_color(gc); + r2d_set_background_color(gc,r2d_get_standard_argb_color(R2D_WHITE)); + + + r2d_fill_rectangle(gc,x-1,y-1,x+r2d_get_width(gc),y+r2d_get_height(gc)); + r2d_set_background_color(gc,col); + + if (((T_R2D_FRAMEBUFFER*)((T_R2D_GC*)gc)->p_frame_buffer)->kind==0) + r2d_update_region((T_R2D_GC*)gc,x,y,x+r2d_get_width(gc)-1,y+r2d_get_height(gc)-1); + r2d_check_and_send_event(gc); +} + +void r2d_erase_with_background(T_R2D_GC_PTR gc, + INT16 a,INT16 b, + INT16 c,INT16 d) +{ + + r2d_fill_rectangle(gc,a-1,b-1,c+1,d+1); +} + +T_R2D_DRAWING_MODE r2d_get_drawing_mode(T_R2D_GC_PTR gc) +{ + return(((T_R2D_GC *)gc)->drawing_mode); +} + +T_R2D_ERROR r2d_set_drawing_mode(T_R2D_GC_PTR gc,T_R2D_DRAWING_MODE the_mode) +{ + if (the_mode!=((T_R2D_GC *)gc)->drawing_mode) + { + // All modes must be supported in ASM mode + + if (r2d_get_drawing_op(gc,the_mode)!=NULL) + + { + ((T_R2D_GC *)gc)->drawing_mode=the_mode; + ((T_R2D_GC *)gc)->drawing_op=r2d_get_drawing_op(gc,the_mode); + + return(R2D_OK); + } + + else + return(R2D_UNKNOWN_OP); + + } + else + return(R2D_OK); + + +} + +UINT16 r2d_get_pen_size(T_R2D_GC_PTR gc) +{ + return(((T_R2D_GC *)gc)->pen_size); +} + +void r2d_set_pen_size(T_R2D_GC_PTR gc,UINT16 the_size) +{ + ((T_R2D_GC *)gc)->pen_size=the_size; +} + +// H COORDINATES +void r2d_set_context_origin(T_R2D_GC_PTR gc,INT16 x,INT16 y) +{ + INT16 dx,dy; + T_R2D_RECTANGLE *ra,*rb; + + dx=x-((T_R2D_GC *)gc)->org_x; + dy=y-((T_R2D_GC *)gc)->org_y; + + ((T_R2D_GC *)gc)->org_x=x; + ((T_R2D_GC *)gc)->org_y=y; + + r2d_translate_shape(((T_R2D_GC *)gc)->p_clipping_shape,dx,dy); + + + ra=r2d_new_rectangle(r2d_mb_id,0,0,0,0); + rb=r2d_s_level(gc,ra); + + if (rb) + { + ((T_R2D_GC *)gc)->s_org_x=rb->ul_x; + ((T_R2D_GC *)gc)->s_org_y=rb->ul_y; + } + + r2d_release_shape(ra); + r2d_release_shape(rb); + + + // No translation of p_s_clipping_shape which is in S coordinates. + // Only H coordinates are impacted by the context origin +} + +// H COORDINATES +void r2d_get_context_origin(T_R2D_GC_PTR gc,INT16 *x,INT16 *y) +{ + *x=((T_R2D_GC *)gc)->org_x; + *y=((T_R2D_GC *)gc)->org_y; +} + +// H COORDINATES +void r2d_local_to_global(T_R2D_GC_PTR gc,INT16 *x,INT16 *y) +{ + *x-=((T_R2D_GC *)gc)->org_x; + *y-=((T_R2D_GC *)gc)->org_y; +} + +// H coordinates +void r2d_get_pen_pos(T_R2D_GC_PTR gc,INT16 *x,INT16 *y) +{ + *x=((T_R2D_GC *)gc)->pen_x; + *y=((T_R2D_GC *)gc)->pen_y; +} + +BOOLEAN r2d_dash_enabled(T_R2D_GC_PTR gc) +{ + return(((T_R2D_GC *)gc)->dash); +} + +void r2d_set_dash_state(T_R2D_GC_PTR gc,BOOLEAN enabled) +{ + ((T_R2D_GC *)gc)->dash=enabled; +} + +static void r2d_change_font(T_R2D_GC_PTR gc,T_R2D_FONT_DESCRIPTION *desc) +{ + r2d_retain(desc->framebuffer); + r2d_release_framebuffer(((T_R2D_GC *)gc)->font_frame_buffer); + ((T_R2D_GC *)gc)->font_frame_buffer=desc->framebuffer; + + ((T_R2D_GC *)gc)->font_metrics=desc->metrics; + ((T_R2D_GC *)gc)->font_table=desc->table; +} + +static T_R2D_FONT_DESCRIPTION *r2d_get_desc(T_R2D_GC_PTR gc) +{ + INT16 f; + INT16 s; + INT16 t; + T_R2D_FONT_DESCRIPTION *p; + INT16 temp; + + p=r2d_g_font_configuration; + + f=r2d_get_text_face(gc)-1; + s=r2d_get_text_size(gc)-1; + t=r2d_get_text_style(gc) & (R2D_BOLD | R2D_ITALIC); + + t=t-(t>>1); + + temp=(f<<2) + (f<<3) + (s<<2) + t; + p=r2d_g_font_configuration+(temp); + + return(p); +} + +void r2d_set_text_face(T_R2D_GC_PTR gc,T_R2D_TEXT_FACE the_face) +{ + ((T_R2D_GC *)gc)->text_face=the_face; + + r2d_change_font(gc,r2d_get_desc(gc)); + +} + +T_R2D_TEXT_FACE r2d_get_text_face(T_R2D_GC_PTR gc) +{ + return(((T_R2D_GC *)gc)->text_face); +} + + +void r2d_set_text_style(T_R2D_GC_PTR gc,T_R2D_TEXT_STYLE the_style) +{ + T_R2D_FONT_DESCRIPTION *desc; + + ((T_R2D_GC *)gc)->text_style=the_style; + + // Clear italic bit; + the_style=the_style & (~R2D_ITALIC); + + // Clear bold bit if desc for Bold is not NULL + desc=r2d_get_desc(gc); + if (!desc->compute_bold) + the_style=the_style & (~R2D_BOLD); + + + ((T_R2D_GC *)gc)->internal_text_style=the_style; + + r2d_change_font(gc,r2d_get_desc(gc)); + +} + +T_R2D_TEXT_STYLE r2d_get_text_style(T_R2D_GC_PTR gc) +{ + return(((T_R2D_GC *)gc)->text_style); +} + + +void r2d_set_text_size(T_R2D_GC_PTR gc,T_R2D_TEXT_SIZE the_size) +{ + ((T_R2D_GC *)gc)->text_size=the_size; + r2d_change_font(gc,r2d_get_desc(gc)); +} + +T_R2D_TEXT_SIZE r2d_get_text_size(T_R2D_GC_PTR gc) +{ + return(((T_R2D_GC *)gc)->text_size); +} + +T_R2D_ERROR r2d_context_lock(T_R2D_GC_PTR gc) +{ + T_RVF_RET err; + err=RVF_OK; + err=rvf_lock_mutex(((T_R2D_FRAMEBUFFER*)((T_R2D_GC*)gc)->p_frame_buffer)->mutex); + if (err!=RVF_OK) + return(R2D_LOCK_ERROR); + else + return(R2D_OK); +} + +T_R2D_ERROR r2d_context_unlock(T_R2D_GC_PTR gc) +{ + T_RVF_RET err; + err=RVF_OK; + err=rvf_unlock_mutex(((T_R2D_FRAMEBUFFER*)((T_R2D_GC*)gc)->p_frame_buffer)->mutex); + if (err!=RVF_OK) + return(R2D_UNLOCK_ERROR); + else + return(R2D_OK); +} + +// Return the a pointer to the memory area containing +// pixels for the graphic context gc +// +UINT32* r2d_get_pixmap(T_R2D_GC_PTR gc) +{ + T_R2D_GC *src; + T_R2D_FRAMEBUFFER *src_f; + UINT32 *ps; + + src=(T_R2D_GC*)gc; + src_f=(T_R2D_FRAMEBUFFER*)(src->p_frame_buffer); + ps=src_f->p_memory_words; + + return(ps); +} + +// Force the flushing of LCD framebuffer to display its +// content +void r2d_flush(void) +{ + r2d_update_region(NULL,0, + 0, + R2D_WIDTH-1, + R2D_HEIGHT-1); + r2d_check_and_send_event(r2d_g_lcd_gc); +} + +// xreddymn Apr-06-2005 MMI-SPR-29655 +// Force the flushing of a portion of LCD framebuffer to display its +// content +void r2d_flush_region(INT16 ul_x,INT16 ul_y,INT16 br_x,INT16 br_y) +{ + r2d_update_region(NULL, ul_x, + ul_y, + br_x, + br_y); + r2d_check_and_send_event(r2d_g_lcd_gc); +} + +void r2d_disable_refresh(void) +{ + rvf_lock_mutex(r2d_g_global_mutex); + r2d_g_refresh_disabled++; + //rvf_send_trace("R2D : disable refresh\n",sizeof("R2D : disable refresh\n"), NULL_PARAM, + // RV_TRACE_LEVEL_ERROR, R2D_USE_ID ); + rvf_unlock_mutex(r2d_g_global_mutex); +} + +void r2d_enable_refresh(void) +{ + //rvf_send_trace("R2D : enable refresh\n",sizeof("R2D : enable refresh\n"), NULL_PARAM, + // RV_TRACE_LEVEL_ERROR, R2D_USE_ID ); + rvf_lock_mutex(r2d_g_global_mutex); + r2d_g_refresh_disabled--; + if (r2d_g_refresh_disabled==0) + { + //rvf_send_trace("R2D : flush\n",sizeof("R2D : flush\n"), NULL_PARAM, + //RV_TRACE_LEVEL_ERROR, R2D_USE_ID ); + //rvf_send_trace("Enable refresh and flush",sizeof("Enable refresh and flush")-1, NULL_PARAM, + // RV_TRACE_LEVEL_DEBUG_HIGH, R2D_USE_ID ); + // The flush will not raise a context commutation to R2D since R2D may + // be sleeping waiting for the current refresh perio. + // So, the event will not be processed at once. While R2D is sleeping, + // another task may call r2d_disable_refresh and thus + // when R2D is awaken, it will not process the event which is waiting. + // So, finally, the display will not be refreshed. + // To avoid this problem which occurs for a quick succession of + // r2d_disable_refresh + // r2d_enable_refresh + // one should try to call them with a rate which is lower than the refresh rate + rvf_unlock_mutex(r2d_g_global_mutex); + //r2d_flush(); + + r2d_check_and_send_event(r2d_g_lcd_gc); + } + else + rvf_unlock_mutex(r2d_g_global_mutex); +} + +//////////////////////////////////////// +// +// Colors +// + + +// Return ARGB foreground color for the gc +T_R2D_ARGB_COLOR r2d_get_foreground_color(T_R2D_GC_PTR gc) +{ + return (((T_R2D_GC*)gc)->foreground_color); +} + +// Set ARGB foreground color for the gc +// (Alpha channel not yet supported) +void r2d_set_foreground_color_with_argb(T_R2D_GC_PTR gc,UINT16 alpha,UINT16 red,UINT16 green,UINT16 blue) +{ + UINT32 color; + color=r2d_new_argb_color(alpha,red,green,blue); + if (color !=((T_R2D_GC*)gc)->foreground_color) + { + ((T_R2D_GC*)gc)->foreground_color=color; + + if (((T_R2D_FRAMEBUFFER*)(((T_R2D_GC*)gc)->p_frame_buffer))->kind==R2D_FULL_KIND) +r2d_convert_foreground_color_color(gc,color); + else + r2d_convert_foreground_color(gc,color); + } +} + +// Set ARGB foreground color for the gc +// (Alpha channel not yet supported) +void r2d_set_foreground_color(T_R2D_GC_PTR gc,T_R2D_ARGB_COLOR color) +{ + if (color !=((T_R2D_GC*)gc)->foreground_color) + { + ((T_R2D_GC*)gc)->foreground_color=color; + if (((T_R2D_FRAMEBUFFER*)(((T_R2D_GC*)gc)->p_frame_buffer))->kind==R2D_FULL_KIND) + r2d_convert_foreground_color_color(gc,color); + else + r2d_convert_foreground_color(gc,color); + } +} + +// Return ARGB foreground color for the gc +T_R2D_ARGB_COLOR r2d_get_background_color(T_R2D_GC_PTR gc) +{ + return (((T_R2D_GC*)gc)->background_color); +} + +// Set ARGB foreground color for the gc +// (Alpha channel not yet supported) +void r2d_set_background_color_with_argb(T_R2D_GC_PTR gc,UINT16 alpha,UINT16 red,UINT16 green,UINT16 blue) +{ + UINT32 color; + color=r2d_new_argb_color(alpha,red,green,blue); + if (color !=((T_R2D_GC*)gc)->background_color) + { + ((T_R2D_GC*)gc)->background_color=color; + if (((T_R2D_FRAMEBUFFER*)(((T_R2D_GC*)gc)->p_frame_buffer))->kind==R2D_FULL_KIND) + r2d_convert_background_color_color(gc,color); + else + r2d_convert_background_color(gc,color); + } +} + +// Set ARGB foreground color for the gc +// (Alpha channel not yet supported) +void r2d_set_background_color(T_R2D_GC_PTR gc,T_R2D_ARGB_COLOR color) +{ + if (color !=((T_R2D_GC*)gc)->background_color) + { + ((T_R2D_GC*)gc)->background_color=color; + if (((T_R2D_FRAMEBUFFER*)(((T_R2D_GC*)gc)->p_frame_buffer))->kind==R2D_FULL_KIND) + r2d_convert_background_color_color(gc,color); + else + r2d_convert_background_color(gc,color); + } +} + +void r2d_set_background_texture(T_R2D_GC_PTR gc,T_R2D_ANCHORED_TEXTURE_PTR texture) +{ + +// INT16 length; +// T_R2D_ANCHORED_TEXTURE *t; + + // If a texture is already in place try to release it + if (((T_R2D_GC*)gc)->background_texture!=NULL) + { + r2d_release_anchored_texture(((T_R2D_GC*)gc)->background_texture); + ((T_R2D_GC*)gc)->background_texture=NULL; + } + + + ((T_R2D_GC*)gc)->background_texture=texture; + + + if (texture!=NULL) + { + r2d_retain(texture); + } + + + + +} + +T_R2D_ANCHORED_TEXTURE_PTR r2d_get_background_texture(T_R2D_GC_PTR gc) +{ + return ((T_R2D_GC*)gc)->background_texture; +} + +T_R2D_ARGB_COLOR r2d_new_argb_color(UINT16 alpha,UINT16 red,UINT16 green,UINT16 blue) +{ + T_R2D_ARGB_COLOR col; + col=0; + + col=col|(alpha&0xFF); + col=col<<8; + col=col|(red&0xFF); + col=col<<8; + col=col|(green&0xFF); + col=col<<8; + col=col|(blue&0xFF); + + return(col); +} + +T_R2D_ARGB_COLOR r2d_get_argb_color_at_point(T_R2D_GC_PTR gc,INT16 x,INT16 y) +{ + UINT32 result; + if (r2d_point_in_shape(((T_R2D_GC*)gc)->p_clipping_shape,x,y)) + { + r2d_local_to_global(gc,&x,&y); + #ifdef R2D_MIRRORED_X + + x=r2d_get_width(gc)-1-x; + #endif + + #ifdef R2D_MIRRORED_Y + y=r2d_get_height(gc)-1-y; + #endif + +#if (R2D_REFRESH == R2D_VERTICAL) + result=IND_r2d_get_color_pixel_value(gc,x,y); +#else + result=IND_r2d_get_color_pixel_value(gc,y,x); +#endif + return(result); + } + else + return(0); +} + +T_R2D_ARGB_COLOR r2d_get_standard_argb_color(T_R2D_COLOR_REF ref) +{ + switch(ref) + { + case R2D_RED: return(r2d_new_argb_color(0,255,0,0)); break; + case R2D_BLUE:return(r2d_new_argb_color(0,0,0,255)); break; + case R2D_GREEN:return(r2d_new_argb_color(0,0,255,0)); break; + case R2D_WHITE:return(r2d_new_argb_color(0,255,255,255)); break; + case R2D_BLACK:return(r2d_new_argb_color(0,0,0,0)); break; + case R2D_GRAY50:return(r2d_new_argb_color(0,127,127,12)); break; + default:return(r2d_new_argb_color(0,0,0,0)); break; + } +} + +// h from 0 to 360 : +// s from 0 to 1 : 1 is 0x800000 +// v from 0 to 1 +// r,g,b from 0 to 1 +// Value in Q8 +void r2d_hsv_to_rgb( INT16 *r, INT16 *g, INT16 *b, INT32 h, INT32 s, INT32 v ) +{ + int i; + INT32 f, p, q, t; + + //s and v in Q8. So 255 is FF is 1 + + if( s == 0 ) { + // achromatic (grey) + *r = *g = *b = (v>>13); + return; + } + h = h * (0x3000000 >> 8) ; // 360/256 / 60 ;Q23 ; sector 0 to 5 + i = h & 0xFF800000; + f = h - i; // factorial part of h + i=i>>15; + f = f >> 15; // Q16 + p = (v * ( 0x100 - s )) >> 8; + q = (v * ( 0x100 - ((s * f) >> 8) )) >> 8; + t = (v * ( 0x100 - ((s * ( 0x100 - f )) >> 8) )) >> 8; + switch( i>>8 ) { + case 0: + *r = v; + *g = t; + *b = p; + break; + case 1: + *r = q; + *g = v; + *b = p; + break; + case 2: + *r = p; + *g = v; + *b = t; + break; + case 3: + *r = p; + *g = q; + *b = v; + break; + case 4: + *r = t; + *g = p; + *b = v; + break; + default: // case 5: + *r = v; + *g = p; + *b = q; + break; + } +} + +//////////////////////////////////////// +// +// Shapes +// + +// H COORDINATES ... +void r2d_draw_shape(T_R2D_SHAPE_PTR self,T_R2D_GC_PTR gc) +{ + + if (self) + { + ((T_R2D_SHAPE*)self)->p_r2d_class->draw(self,gc); + + } +} + +void r2d_fill_shape(T_R2D_SHAPE_PTR self,T_R2D_GC_PTR gc) +{ + if (self) + { + ((T_R2D_SHAPE*)self)->p_r2d_class->fill(self,gc); + + } +} + +void r2d_release_shape(T_R2D_SHAPE_PTR self) +{ + + + if (self) + ((T_R2D_SHAPE*)self)->p_r2d_class->release(self); +} + +T_R2D_SHAPE_PTR r2d_clone_shape(T_RVF_MB_ID bank,T_R2D_SHAPE_PTR self) +{ + if (self) + return (((T_R2D_SHAPE*)self)->p_r2d_class->clone(bank,self)); + else + return(NULL); +} + +void r2d_translate_shape(T_R2D_SHAPE_PTR self,INT16 dx,INT16 dy) +{ + if (self) + ((T_R2D_SHAPE*)self)->p_r2d_class->translate(self,dx,dy); + +} + +BOOLEAN r2d_point_in_shape(T_R2D_SHAPE_PTR self,INT16 x,INT16 y) +{ + + if (self) + return(((T_R2D_SHAPE*)self)->p_r2d_class->point_in_shape(self,x,y)); + else + return(FALSE); + +} + + +BOOLEAN r2d_point_in_rectangle_shape(T_R2D_SHAPE* self,INT16 x,INT16 y) +{ + T_R2D_RECTANGLE *r; + + r=(T_R2D_RECTANGLE*)self; + + return (((x>=r2d_get_xmin(self)) + && (x<r2d_get_xmax(self)) + && (y>=r2d_get_ymin(self)) + && (y<r2d_get_ymax(self)))); +} + +BOOLEAN r2d_point_in_circle_shape(T_R2D_SHAPE* self,INT16 x,INT16 y) +{ + T_R2D_CIRCLE *c; + c=(T_R2D_CIRCLE*)self; + + return((x-c->x)*(x-c->x)+(y-c->y)*(y-c->y)-c->r*c->r<0); +} + +BOOLEAN r2d_point_in_ellipse_shape(T_R2D_SHAPE* self,INT16 x,INT16 y) +{ + T_R2D_ELLIPSE *c; + INT32 a,b,cx,cy,nx,ny; + + c=(T_R2D_ELLIPSE*)self; + // Work on Q1 + + // a is half width so no <<1 is used here + a=(c->br_x-c->ul_x); + b=(c->br_y-c->ul_y); + + nx=x<<1; + ny=y<<1; + + cx=((c->ul_x)<<1)+a; + cy=((c->ul_y)<<1)+b; + + //b^2*x^2+a^2y^2-a^2b^2=0 + + return((b*b*(nx-cx)*(nx-cx)+a*a*(ny-cy)*(ny-cy)-a*a*b*b)<0); + +} + +BOOLEAN r2d_point_in_round_rectangle_shape(T_R2D_SHAPE* self,INT16 x,INT16 y) +{ + T_R2D_ROUND_RECTANGLE *r; + BOOLEAN result; + + result=FALSE; + r=(T_R2D_ROUND_RECTANGLE *)self; + + if ((x>=r->ul_x+r->h+1) && (x<r->br_x-r->h) && (y>=r->ul_y) && (y<r->br_y)) + result=TRUE; + else if ((x>=r->ul_x) && (x<r->br_x) && (y>=r->ul_y+r->v+1) && (y<r->br_y-r->v)) + result=TRUE; + else + { + INT32 a,b,cx,cy,nx,ny; + + if (x>=r->br_x-r->h) + x=x-(r->br_x-r->ul_x)+((r->h)<<1); + + if (y>=r->br_y-r->v) + y=y-(r->br_y-r->ul_y)+((r->v)<<1); + + + a=(r->h<<1); + b=(r->v<<1); + + nx=x<<1; + ny=y<<1; + + cx=((r->ul_x)<<1)+a; + cy=((r->ul_y)<<1)+b; + + //b^2*x^2+a^2y^2-a^2b^2=0 + + result=(b*b*(nx-cx)*(nx-cx)+a*a*(ny-cy)*(ny-cy)-a*a*b*b)<0; + + + } + + return(result); + +} + +BOOLEAN r2d_point_in_not_supported_shape(T_R2D_SHAPE* self,INT16 x,INT16 y) +{ + return FALSE; +} + +void r2d_translate_rectangle_shape(T_R2D_SHAPE* self,INT16 dx,INT16 dy) +{ + T_R2D_RECTANGLE *r; + r=(T_R2D_RECTANGLE *)self; + r->ul_x+=dx; + r->ul_y+=dy; + r->br_x+=dx; + r->br_y+=dy; +} + +void r2d_translate_point_shape(T_R2D_SHAPE* self,INT16 dx,INT16 dy) +{ + T_R2D_CIRCLE *r; + r=(T_R2D_CIRCLE *)self; + r->x+=dx; + r->y+=dy; +} + + +T_R2D_SHAPE_PTR r2d_new_rectangle(T_RVF_MB_ID bank,INT16 ul_x,INT16 ul_y,INT16 br_x,INT16 br_y) +{ + T_R2D_RECTANGLE *r; + T_R2D_ERROR err; + err=R2D_MALLOC(bank,T_R2D_RECTANGLE,sizeof(T_R2D_RECTANGLE),r); + if (r) + { + r->refcount=1; + r->ul_x=ul_x; + r->ul_y=ul_y; + r->br_x=br_x; + r->br_y=br_y; + r->p_r2d_class=&r2d_class_rectangle; + } else r=NULL; + return(r); +} + +void r2d_release_rectangle(T_R2D_SHAPE* self) +{ + T_R2D_RECTANGLE *r; + r=(T_R2D_RECTANGLE *)self; + + r2d_release(r); +} + +T_R2D_SHAPE_PTR r2d_clone_rectangle_shape(T_RVF_MB_ID bank,T_R2D_SHAPE* self) +{ + T_R2D_RECTANGLE *r; + r=(T_R2D_RECTANGLE *)self; + + return(r2d_new_rectangle(bank,r->ul_x,r->ul_y,r->br_x,r->br_y)); +} + +void r2d_draw_rectangle_shape(T_R2D_SHAPE* self,T_R2D_GC_PTR gc) +{ + T_R2D_RECTANGLE *r; + r=(T_R2D_RECTANGLE *)self; + r2d_draw_rectangle(gc,r->ul_x,r->ul_y,r->br_x,r->br_y); +} + +void r2d_fill_rectangle_shape(T_R2D_SHAPE* self,T_R2D_GC_PTR gc) +{ + T_R2D_RECTANGLE *r; + r=(T_R2D_RECTANGLE *)self; + r2d_fill_rectangle(gc,r->ul_x,r->ul_y,r->br_x,r->br_y); +} + + +void r2d_release_circle(T_R2D_SHAPE* self) +{ + T_R2D_CIRCLE *r; + r=(T_R2D_CIRCLE *)self; + + r2d_release(r); + + #if (R2D_DEBUG == R2D_ON) + r=NULL; + #endif +} + +T_R2D_SHAPE_PTR r2d_clone_circle_shape(T_RVF_MB_ID bank,T_R2D_SHAPE* self) +{ + T_R2D_CIRCLE *r; + r=(T_R2D_CIRCLE *)self; + + return(r2d_new_circle(bank,r->x,r->y,r->r)); +} + +void r2d_draw_circle_shape(T_R2D_SHAPE* self,T_R2D_GC_PTR gc) +{ + T_R2D_CIRCLE *r; + r=(T_R2D_CIRCLE *)self; + r2d_draw_circle(gc,r->x,r->y,r->r); +} + +void r2d_fill_circle_shape(T_R2D_SHAPE* self,T_R2D_GC_PTR gc) +{ + T_R2D_CIRCLE *r; + r=(T_R2D_CIRCLE *)self; + r2d_fill_circle(gc,r->x,r->y,r->r); +} + +T_R2D_SHAPE_PTR r2d_new_circle(T_RVF_MB_ID bank,INT16 x,INT16 y,INT16 r) +{ + T_R2D_CIRCLE *c; + R2D_MALLOC(bank,T_R2D_CIRCLE,sizeof(T_R2D_CIRCLE),c); + if (c) + { + c->refcount=1; + c->x=x; + c->y=y; + c->r=r; + c->p_r2d_class=&r2d_class_circle; + } else c=NULL; + return(c); +} + +void r2d_release_ellipse(T_R2D_SHAPE* self) +{ + T_R2D_ELLIPSE *r; + r=(T_R2D_ELLIPSE *)self; + + r2d_release(r); +#if (R2D_DEBUG == R2D_ON) + r=NULL; +#endif +} + +void r2d_draw_ellipse_shape(T_R2D_SHAPE* self,T_R2D_GC_PTR gc) +{ + T_R2D_ELLIPSE *r; + r=(T_R2D_ELLIPSE *)self; + r2d_draw_ellipse(gc,r->ul_x,r->ul_y,r->br_x,r->br_y); +} + +void r2d_fill_ellipse_shape(T_R2D_SHAPE* self,T_R2D_GC_PTR gc) +{ + T_R2D_ELLIPSE *r; + r=(T_R2D_ELLIPSE *)self; + r2d_fill_ellipse(gc,r->ul_x,r->ul_y,r->br_x,r->br_y); +} + +T_R2D_SHAPE_PTR r2d_new_ellipse(T_RVF_MB_ID bank,INT16 ul_x,INT16 ul_y,INT16 br_x,INT16 br_y) +{ + T_R2D_ELLIPSE *r; + R2D_MALLOC(bank,T_R2D_ELLIPSE,sizeof(T_R2D_ELLIPSE),r); + if (r) + { + r->refcount=1; + r->ul_x=ul_x; + r->ul_y=ul_y; + r->br_x=br_x; + r->br_y=br_y; + r->p_r2d_class=&r2d_class_ellipse; + } else r=NULL; + return(r); +} + +void r2d_release_round_rectangle(T_R2D_SHAPE* self) +{ + T_R2D_ROUND_RECTANGLE *r; + r=(T_R2D_ROUND_RECTANGLE *)self; + + r2d_release(r); + #if (R2D_DEBUG == R2D_ON) + r=NULL; +#endif +} + +void r2d_draw_round_rectangle_shape(T_R2D_SHAPE* self,T_R2D_GC_PTR gc) +{ + T_R2D_ROUND_RECTANGLE *r; + r=(T_R2D_ROUND_RECTANGLE *)self; + r2d_draw_round_rectangle(gc,r->ul_x,r->ul_y,r->br_x,r->br_y,r->h,r->v); +} + +void r2d_fill_round_rectangle_shape(T_R2D_SHAPE* self,T_R2D_GC_PTR gc) +{ + T_R2D_ROUND_RECTANGLE *r; + r=(T_R2D_ROUND_RECTANGLE *)self; + r2d_fill_round_rectangle(gc,r->ul_x,r->ul_y,r->br_x,r->br_y,r->h,r->v); +} + +T_R2D_SHAPE_PTR r2d_clone_round_rectangle_shape(T_RVF_MB_ID bank,T_R2D_SHAPE* self) +{ + T_R2D_ROUND_RECTANGLE *r; + r=(T_R2D_ROUND_RECTANGLE *)self; + + return(r2d_new_round_rectangle(bank,r->ul_x,r->ul_y,r->br_x,r->br_y,r->h,r->v)); +} + +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) +{ + T_R2D_ROUND_RECTANGLE *r; + R2D_MALLOC(bank,T_R2D_ROUND_RECTANGLE,sizeof(T_R2D_ROUND_RECTANGLE),r); + if (r) + { + r->refcount=1; + r->ul_x=ul_x; + r->ul_y=ul_y; + r->br_x=br_x; + r->br_y=br_y; + r->h=h; + r->v=v; + r->p_r2d_class=&r2d_class_round_rectangle; + } else r=NULL; + return(r); +} + +T_R2D_SHAPE_PTR r2d_clone_arc_shape(T_RVF_MB_ID bank,T_R2D_SHAPE* self) +{ + T_R2D_ARC *r; + r=(T_R2D_ARC *)self; + + return(r2d_new_arc(bank,r->start_angle,r->stop_angle,r->ul_x,r->ul_y,r->br_x,r->br_y)); +} + +T_R2D_SHAPE_PTR r2d_new_arc(T_RVF_MB_ID bank,INT16 start_angle, INT16 stop_angle,INT16 ul_x,INT16 ul_y, + INT16 br_x,INT16 br_y) +{ + T_R2D_ARC *r; + R2D_MALLOC(bank,T_R2D_ARC,sizeof(T_R2D_ARC),r); + if (r) + { + r->refcount=1; + r->ul_x=ul_x; + r->ul_y=ul_y; + r->br_x=br_x; + r->br_y=br_y; + r->start_angle=start_angle; + r->stop_angle=stop_angle; + r->p_r2d_class=&r2d_class_arc; + } else r=NULL; + return(r); +} + +void r2d_release_arc(T_R2D_SHAPE *self) +{ + T_R2D_ARC *r; + r=(T_R2D_ARC *)self; + + r2d_release(r); +} + +void r2d_draw_arc_shape(T_R2D_SHAPE *self,T_R2D_GC_PTR gc) +{ + T_R2D_ARC *r; + r=(T_R2D_ARC *)self; + + r2d_draw_arc(gc,r->start_angle,r->stop_angle, + r->ul_x,r->ul_y,r->br_x,r->br_y); +} + +void r2d_fill_arc_shape(T_R2D_SHAPE *self,T_R2D_GC_PTR gc) +{ + T_R2D_ARC *r; + r=(T_R2D_ARC *)self; + + r2d_fill_arc(gc,r->start_angle,r->stop_angle, + r->ul_x,r->ul_y,r->br_x,r->br_y); +} + +T_R2D_SHAPE_PTR r2d_new_rectangle_intersection(T_RVF_MB_ID bank,T_R2D_SHAPE_PTR a,T_R2D_SHAPE_PTR b) +{ +if ( a && b && (((T_R2D_SHAPE*)a)->p_r2d_class==&r2d_class_rectangle) +&& (((T_R2D_SHAPE*)b)->p_r2d_class==&r2d_class_rectangle)) +{ + T_R2D_RECT *ra; + T_R2D_RECT *rb; + INT16 xa,ya,xb,yb; + + ra=(T_R2D_RECT *)a; + rb=(T_R2D_RECT *)b; + + if (ra->ul_x>rb->ul_x) + xa=ra->ul_x; + else + xa=rb->ul_x; + + if (ra->ul_y>rb->ul_y) + ya=ra->ul_y; + else + ya=rb->ul_y; + + if (ra->br_x<rb->br_x) + xb=ra->br_x; + else + xb=rb->br_x; + + if (ra->br_y<rb->br_y) + yb=ra->br_y; + else + yb=rb->br_y; + + if ((xa<=xb) && (ya<=yb)) + return(r2d_new_rectangle(bank,xa,ya,xb,yb)); + else + return(R2D_EMPTY_RECT); + +} +else return(NULL); +} + +T_R2D_SHAPE_PTR r2d_new_rectangle_union(T_RVF_MB_ID bank,T_R2D_SHAPE_PTR a,T_R2D_SHAPE_PTR b) +{ + if ( a && b && (((T_R2D_SHAPE*)a)->p_r2d_class==&r2d_class_rectangle) +&& (((T_R2D_SHAPE*)b)->p_r2d_class==&r2d_class_rectangle)) +{ + T_R2D_RECTANGLE *ra; + T_R2D_RECTANGLE *rb; + INT16 xa,ya,xb,yb; + + ra=(T_R2D_RECTANGLE *)a; + rb=(T_R2D_RECTANGLE *)b; + + if (ra->ul_x<rb->ul_x) + xa=ra->ul_x; + else + xa=rb->ul_x; + + if (ra->ul_y<rb->ul_y) + ya=ra->ul_y; + else + ya=rb->ul_y; + + if (ra->br_x>rb->br_x) + xb=ra->br_x; + else + xb=rb->br_x; + + if (ra->br_y>rb->br_y) + yb=ra->br_y; + else + yb=rb->br_y; + + if ((xa<=xb) && (ya<=yb)) + return(r2d_new_rectangle(bank,xa,ya,xb,yb)); + else + return(R2D_EMPTY_RECT); + +} +else if (a) +return(r2d_clone_shape(bank,a)); +else if (b) +return(r2d_clone_shape(bank,b)); +else +return(NULL); +} + +T_R2D_SHAPE_PTR r2d_new_text(T_RVF_MB_ID bank,INT16 x, INT16 y,T_R2D_UTF16 *the_text) +{ + T_R2D_TEXT *r; + R2D_MALLOC(bank,T_R2D_TEXT,sizeof(T_R2D_TEXT),r); + if (r) + { + r->refcount=1; + r->x=x; + r->y=y; + r->p_text=the_text; + r->p_r2d_class=&r2d_class_text; + } else r=NULL; + return(r); +} + +T_R2D_SHAPE_PTR r2d_clone_text_shape(T_RVF_MB_ID bank,T_R2D_SHAPE* self) +{ + T_R2D_TEXT *r; + r=(T_R2D_TEXT *)self; + + return(r2d_new_text(bank,r->x,r->y,NULL)); +} + + +void r2d_release_text(T_R2D_SHAPE *self) +{ + T_R2D_TEXT *r; + r=(T_R2D_TEXT *)self; + + r2d_release(r); +} + +void r2d_draw_text_shape(T_R2D_SHAPE *self,T_R2D_GC_PTR gc) +{ + T_R2D_TEXT *r; + r=(T_R2D_TEXT *)self; + r2d_draw_text(gc,r->x,r->y,r->p_text); +} + +void r2d_fill_text_shape(T_R2D_SHAPE *self,T_R2D_GC_PTR gc) +{ + // A text has no interior and thus cannot be filled. +} + + + + +//////////////////////////////////////// +// +// Clipping functions +// + +// Conversion is done such that line y = ymax and x=xmax MUST NOT +// be drawn. So, they do not belong to the cliiping region +// So, behavior of s_clipping_shape is using drawing convention +// and not the clipping convention +static T_R2D_SHAPE_PTR r2d_s_level(T_R2D_GC_PTR gc,T_R2D_SHAPE_PTR self) +{ + T_R2D_SHAPE_PTR result; + T_R2D_RECTANGLE *r; + + + r=(T_R2D_RECTANGLE*)self; + + if ((r) && (gc)) + { + + result=r2d_clone_shape(r2d_mb_id,self); + r=(T_R2D_RECTANGLE*)result; + + r2d_local_to_global(gc,&(r->ul_x),&(r->ul_y)); + r2d_local_to_global(gc,&(r->br_x),&(r->br_y)); + + //r2d_mirror_clip_rectangle(gc,result); + r2d_mirror_rectangle(gc,result); + r=(T_R2D_RECTANGLE*)result; + +#if (R2D_REFRESH != R2D_VERTICAL) + r2d_diagonal_mirror(result); + r=(T_R2D_RECTANGLE*)result; +#endif + + return(result); + } + else + return(NULL); +} + +void r2d_set_clipping_shape(T_R2D_SHAPE_PTR self,T_R2D_GC_PTR gc) +{ + + if ((self) && (((T_R2D_SHAPE*)self)->p_r2d_class==&r2d_class_rectangle)) + { + T_R2D_RECT *r; + INT16 orgx,orgy; + + r=(T_R2D_RECT *)self; + + r2d_get_context_origin(gc,&orgx,&orgy); + + if (r->ul_x-orgx<0) + r->ul_x=orgx; + + if (r->ul_y-orgy<0) + r->ul_y=orgy; + + if (r->br_x-orgx>=r2d_get_width(gc)) + r->br_x=orgx+r2d_get_width(gc); + + if (r->br_y-orgy>=r2d_get_height(gc)) + r->br_y=orgy+r2d_get_height(gc); + + + { + r2d_release_shape(((T_R2D_GC *)gc)->p_clipping_shape); + ((T_R2D_GC *)gc)->p_clipping_shape=self; + r2d_retain(self); + + r2d_release_shape(((T_R2D_GC *)gc)->p_s_clipping_shape); + ((T_R2D_GC *)gc)->p_s_clipping_shape=r2d_s_level(gc,self); + } + } +} + +T_R2D_SHAPE_PTR r2d_get_clipping_shape(T_R2D_GC_PTR gc) +{ + return(((T_R2D_GC *)gc)->p_clipping_shape); +} + +T_R2D_ERROR r2d_restore_standard_clipping_shape(T_R2D_GC_PTR gc) +{ + INT16 x,y; + T_R2D_SHAPE_PTR s,sb; + r2d_get_context_origin(gc,&x,&y); + s=((T_R2D_GC *)gc)->p_clipping_shape; + sb=((T_R2D_GC *)gc)->p_s_clipping_shape; + + ((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)); + +// No mirroring when shape is the whole LCD +// Force use of global coordinates for s_ frame +#if (R2D_REFRESH == R2D_VERTICAL) + ((T_R2D_GC *)gc)->p_s_clipping_shape= + r2d_new_rectangle(r2d_mb_id,0,0,r2d_get_width(gc),r2d_get_height(gc)); +#else + ((T_R2D_GC *)gc)->p_s_clipping_shape= + r2d_new_rectangle(r2d_mb_id,0,0,r2d_get_height(gc),r2d_get_width(gc)); +#endif + + + if ((((T_R2D_GC *)gc)->p_clipping_shape==NULL) + || (((T_R2D_GC *)gc)->p_s_clipping_shape==NULL)) + { + if (((T_R2D_GC *)gc)->p_clipping_shape!=NULL) + r2d_release_shape(((T_R2D_GC *)gc)->p_clipping_shape); + if (((T_R2D_GC *)gc)->p_s_clipping_shape!=NULL) + r2d_release_shape(((T_R2D_GC *)gc)->p_s_clipping_shape); + ((T_R2D_GC *)gc)->p_clipping_shape=s; + ((T_R2D_GC *)gc)->p_s_clipping_shape=sb; + return(R2D_MEMORY_ERR); + } + else + { + r2d_release_shape(s); + r2d_release_shape(sb); + return(R2D_OK); + } +} + + +//////////////////////////////////////// +// +// Graphical primitives +// + +// S COORDINATES +static void r2d_s_fill_point(T_R2D_GC_PTR gc,INT16 x,INT16 y,INT16 pen_size) +{ + INT16 ul_x,ul_y,br_x,br_y,bs,as; +// UINT32 f,b; + + bs=(pen_size>>1); + as=(pen_size>>1) + (pen_size&1); + + // Squares are not symetrically placed + // since pen_size is not always odd + // Mirroring must take it into account so that the + // asymetry is also mirrored +#ifdef R2D_MIRRORED_X + ul_x=x-bs; + br_x=x+as-1; +#else + ul_x=x-bs+1; + br_x=x+as; + +#endif + +#ifdef R2D_MIRRORED_Y + ul_y=y-bs; + br_y=y+as-1; +#else + ul_y=y-bs+1; + br_y=y+as; +#endif + + //printf("%d %d %d %d\n",ul_x,ul_y,br_x,br_y); + + + r2d_s_fill_rectangle(gc,ul_x-1,ul_y-1,br_x+1,br_y+1,FALSE); + +} + +// Draw point in gc at position (x,y) +// S COORDINATES +static void r2d_s_draw_point(T_R2D_GC_PTR gc,INT16 x,INT16 y,INT32 l) +{ + UINT32 pixel_value; + INT16 pen_size; + BOOLEAN isLCD_format,can_draw; + T_R2D_GC* pgc; + + can_draw=FALSE; + + if (r2d_dash_enabled(gc)) + { + // Q16, 0x0008000 is 8 pixels + if (!(l&0x00080000)) + can_draw=TRUE; + } + else + can_draw=TRUE; + + if (can_draw==TRUE) + { + pgc=(T_R2D_GC*)gc; + + isLCD_format=((T_R2D_FRAMEBUFFER*)(((T_R2D_GC*)gc)->p_frame_buffer))->kind!=R2D_FULL_KIND; + + + pen_size=r2d_get_pen_size(gc); + + + if (r2d_point_in_shape(((T_R2D_GC*)gc)->p_s_clipping_shape,x,y)) + { + + + if (pen_size>1) + r2d_s_fill_point(gc,x,y,pen_size); + + + else + { + // Dithering is relative to global coordinate system + + + // Color is recomputed only when dithering is on + #if (R2D_DITHERING == R2D_ON) + if (isLCD_format) + pixel_value=r2d_get_dithering_matrix_entry(((T_R2D_GC*)gc)->p_foreground_dithered_cache,x,y); + else + pixel_value=((T_R2D_GC*)gc)->foreground_pixel_value; + #else + pixel_value=((T_R2D_GC*)gc)->foreground_pixel_value; + #endif + + // Low level pixel drawing routine with CONVERTED color value + + IND_r2d_write_lcd_pixel(gc,x,y,pixel_value); + + } + } + + r2d_check_and_send_event(gc); + } +} + +// Draw point in gc at position (x,y) +// H COORDINATES +void r2d_draw_point(T_R2D_GC_PTR gc,INT16 x,INT16 y) +{ + if (r2d_point_in_shape(((T_R2D_GC*)gc)->p_clipping_shape,x,y)) + { + r2d_local_to_global(gc,&x,&y); + +#ifdef R2D_MIRRORED_X + x=r2d_get_width(gc)-1-x; +#endif + +#ifdef R2D_MIRRORED_Y + y=r2d_get_height(gc)-1-y; +#endif + + + + + if (((T_R2D_FRAMEBUFFER*)((T_R2D_GC*)gc)->p_frame_buffer)->kind==0) + r2d_update_region((T_R2D_GC*)gc,x,y,x,y); +#if (R2D_REFRESH == R2D_VERTICAL) + r2d_s_draw_point(gc,x,y,0); +#else + r2d_s_draw_point(gc,y,x,0); +#endif + + } +} + +void r2d_erase_point(T_R2D_GC_PTR gc,INT16 x,INT16 y) +{ + + T_R2D_ARGB_COLOR col; + + +if (r2d_point_in_shape(((T_R2D_GC*)gc)->p_clipping_shape,x,y)) +{ + r2d_local_to_global(gc,&x,&y); + col=r2d_get_foreground_color(gc); + r2d_set_foreground_color(gc,r2d_get_background_color(gc)); + +#ifdef R2D_MIRRORED_X + x=r2d_get_width(gc)-1-x; +#endif + +#ifdef R2D_MIRRORED_Y + y=r2d_get_height(gc)-1-y; + +#endif + + + if (((T_R2D_FRAMEBUFFER*)((T_R2D_GC*)gc)->p_frame_buffer)->kind==0) + r2d_update_region((T_R2D_GC*)gc,x,y,x,y); + + #if (R2D_REFRESH == R2D_VERTICAL) + r2d_s_draw_point(gc,x,y,0); +#else + r2d_s_draw_point(gc,y,x,0); +#endif + + r2d_set_foreground_color(gc,col); +} + + +} + +// Move pen to point (x,y) +// H_COORDINATES +void r2d_moveto(T_R2D_GC_PTR gc,INT16 x,INT16 y) +{ + ((T_R2D_GC*)gc)->pen_x=x; + ((T_R2D_GC*)gc)->pen_y=y; +} + + +static BOOLEAN r2d_clipt(INT32 denom,INT32 num,INT32 *tE,INT32 *tL) +{ + INT32 t; + + //printf("clipt %08X %08X\n",denom,num); + if (denom<0) + { + t=r2d_fixed_division(num,denom); + //printf("denom<0 ; t=%08X\n",t); + if (t>*tL) + return FALSE; + else if (t > *tE) + *tE=t; + } + else if (denom>0) + { + t=r2d_fixed_division(num,denom); + //printf("denom>0 ; t=%08X\n",t); + if (t<*tE) + return FALSE; + else if (t < *tL) + *tL=t; + } else if (num<0) + return FALSE; + + //printf("t=%08X tE=%08X tL=%08X\n",t,*tE,*tL); + return TRUE; +} + +static BOOLEAN r2d_clip_line(T_R2D_SHAPE *self,INT32 *x0,INT32 *y0,INT32 *x1, INT32 *y1) +{ + T_R2D_RECTANGLE *r; + BOOLEAN visible=FALSE; + INT32 dx=*x1-*x0; + INT32 dy=*y1-*y0; + + r=(T_R2D_RECTANGLE*)self; + + // Can only clip against reactangular shapes + if (self->p_r2d_class==&r2d_class_rectangle) + { + + if ((dx==0) && (dy==0) && r2d_point_in_shape(self,(*x0>>16) & 0x0FFFF,(*y0>>16) & 0x0FFFF)) + visible=TRUE; + else + { + INT32 tE=0; + INT32 tL=(1<<16); + + + if (r2d_clipt(dx,((r2d_get_xmax(self)-1)<<16)-*x0,&tE,&tL)==TRUE) + if (r2d_clipt(-dx,*x0-(r2d_get_xmin(self)<<16),&tE,&tL)==TRUE) + if (r2d_clipt(-dy,*y0-(r2d_get_ymin(self)<<16),&tE,&tL)==TRUE) + if (r2d_clipt(dy,((r2d_get_ymax(self)-1)<<16) -*y0,&tE,&tL)==TRUE) + { + visible=TRUE; + + //printf("tE=%08X tL=%08X\n",tE,tL); + // 1 with fixed point representation + if (tL < (1<<16)) + { + // dx and dy are integer + // tL and tE should be lower than 1 + // So intermediate values are shifted so that + // the product can be done on 32 bits instead of 64 bits + *x1=*x0 + (tL*(dx>>16)) ; + *y1=*y0 + (tL*(dy>>16)) ; + //printf("x1=%08X y1=%08X\n",*x1,*y1); + } + if (tE > 0) + { + *x0 += (tE*(dx>>16)) ; + *y0 += (tE*(dy>>16)) ; + //printf("x0=%08X y0=%08X\n",*x0,*y0); + + } + } + } + } + return(visible); +} + +// 0.5 is rounded down because in line drawing the bottom +// point is chosen when the line is passing through the middle +// point +#define R2D_Q16INT_VALUE(x) ((x+(0x7FFF)) & 0xFFFF0000) + +#define R2D_FLOOR_VALUE(x) (x & 0xFFFF0000) + +// Positive times signed value +#define R2D_MULT_PN(x,y) ((((x >> 16) & 0x0FFFF)*y) + (((x & 0x0FFFF) * y) >> 16)) + +// draw line from pen position to point (x,y) +void r2d_lineto(T_R2D_GC_PTR gc,INT16 x,INT16 y) +{ + // Clipping + // Now drawing with low level function + + UINT32 pixel_value; + INT32 P0X,P0Y,P1X,P1Y,c,cy,cx; + INT32 current_x,current_y,tmp,tmpx,tmpy; + INT32 dx,dy,dn,dnp,dnn; + INT16 xincrement,yincrement,reverse; + INT32 nx,ny; + INT16 pen_size; + INT32 l; + BOOLEAN isLCD_format; + l=0; + + + + isLCD_format=((T_R2D_FRAMEBUFFER*)(((T_R2D_GC*)gc)->p_frame_buffer))->kind!=R2D_FULL_KIND; + + pixel_value=((T_R2D_GC*)gc)->foreground_pixel_value; + pen_size=r2d_get_pen_size(gc); + + P0X=((T_R2D_GC*)gc)->pen_x << 16; + P0Y=((T_R2D_GC*)gc)->pen_y << 16; + P1X=x << 16; + P1Y=y << 16; + //printf("\n\n(%d,%d) ; (%d,%d)\n",P0X>>16,P0Y>>16,P1X>>16,P1Y>>16); + +// As far as possible, most datas are computed before clipping to get same accuracy +// Update pen position + ((T_R2D_GC*)gc)->pen_x=x; + ((T_R2D_GC*)gc)->pen_y=y; + +if (r2d_clip_line((((T_R2D_GC*)gc)->p_clipping_shape),&P0X,&P0Y,&P1X,&P1Y)) +{ + +// Local to global + + P0X-=((T_R2D_GC*)gc)->org_x << 16; + P0Y-=((T_R2D_GC*)gc)->org_y << 16; + P1X-=((T_R2D_GC*)gc)->org_x << 16; + P1Y-=((T_R2D_GC*)gc)->org_y << 16; + + +#ifdef R2D_MIRRORED_X + P0X=((r2d_get_width(gc)-1)<<16)-P0X; + P1X=((r2d_get_width(gc)-1)<<16)-P1X; +#endif + +#ifdef R2D_MIRRORED_Y + P0Y=((r2d_get_height(gc)-1)<<16)-P0Y; + P1Y=((r2d_get_height(gc)-1)<<16)-P1Y; +#endif + + + /*printf("%d %d %d %d\n",r2d_get_xmin(((T_R2D_GC*)gc)->p_clipping_shape), + r2d_get_xmax(((T_R2D_GC*)gc)->p_clipping_shape), + r2d_get_ymin(((T_R2D_GC*)gc)->p_clipping_shape), + r2d_get_ymax(((T_R2D_GC*)gc)->p_clipping_shape) + );*/ + + //r2d_clip_line(&(((T_R2D_GC*)gc)->clipping_rectangle),&P0X,&P0Y,&P1X,&P1Y); + + //printf("(%d,%d) ; (%d,%d)\n",P0X>>16,P0Y>>16,P1X>>16,P1Y>>16); + //printf("(%08X,%08X) ; (%08X,%08X)\n------------------\n",P0X,P0Y,P1X,P1Y); + + //printf("(%d,%d) ; (%d,%d)\n",P0X>>16,P0Y>>16,P1X>>16,P1Y>>16); + +if (((T_R2D_FRAMEBUFFER*)((T_R2D_GC*)gc)->p_frame_buffer)->kind==0) + r2d_update_region((T_R2D_GC*)gc,P0X>>16,P0Y>>16,P1X>>16,P1Y>>16); + + +#if (R2D_REFRESH==R2D_VERTICAL) + current_x=P0Y; + current_y=P0X; + nx=P1Y; ny=P1X; + + +#else + current_x=P0X; + current_y=P0Y; + nx=P1X; ny=P1Y; +#endif + + dx=nx-current_x; + dy=ny-current_y; + + yincrement=1; + + if (dx>=0) + { + xincrement=1; + } + else + { + xincrement=-1; + dx=-dx; + } + + if (dy>=0) + { + yincrement=1; + } + else + { + yincrement=-1; + dy=-dy; + } + + if (dy<=dx) + reverse=0; + else + { + reverse=1; + tmp=dy; + dy=dx; + dx=tmp; + tmp=current_y; + current_y=current_x; + current_x=tmp; + tmp=ny; + ny=nx; + nx=tmp; + tmp=yincrement; + yincrement=xincrement; + xincrement=tmp; + } + + reverse=1-reverse; + + + //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); + + + // Remember that when one is speaking about a move of 1 horizontally + // one is talking about internal coordinates used by the algorithm + // In the window it may be vertical or horizontal depending on the + // refresh mode and on the line slope (<1 or >1) + + + dn=dy - (dx >> 1) ; // d0 = a-b/2 + dnp=dy-dx ; + dnn=dy; + + // We draw the point which is the closest to the line so we use INT + // instead of FLOOR or CEIL + // But, then, the drawing algorithm assumes that the first drawn point is + // the lowest one + + // If F(P) = 0 is a parametric description of the line + // The, when one is moving from the point of the line on the frontier + // of the clipping rectangle to the closest + // point with x,y integer coordinate then one needs to compute dx*cy and dy*cx + // since it is the variation of F along that path + tmpx=(INT32)R2D_Q16INT_VALUE(current_x); + tmpy=(INT32)R2D_Q16INT_VALUE(current_y); + cx = current_x - tmpx; + cy = current_y - tmpy; + + + c= -R2D_MULT_PN(dx,cy) + R2D_MULT_PN(dy,cx); + + + //printf("cx=%08X, cy=%08X, c=%08X, dx=%08X, dy=%08X \n",cx,cy,c,dx,dy); + + // Then, one can add c to the variation due to a move of 1 horizontally + // an a move of 1/2 vertically. + // One finally get the value of the decision variable at the midpoint + dn+=c; + + //printf("%08X %08X %08X %08X %08X\n",current_x,current_y,nx,ny); + current_x=((INT32)R2D_Q16INT_VALUE(current_x)) >> 16; + current_y=((INT32)R2D_Q16INT_VALUE(current_y)) >> 16; + nx=((INT32)R2D_Q16INT_VALUE(nx)) >> 16; + ny=((INT32)R2D_Q16INT_VALUE(ny)) >> 16; + + + //printf("dx=%08X dy=%08X dn=%08X dnp=%08X dnn=%08X\n",dx,dy,dn,dnp,dnn); + + if (reverse) + { + r2d_s_draw_point(gc,current_y,current_x,l); + + } + else + { + r2d_s_draw_point(gc,current_x,current_y,l); + } + + + + while(current_x != nx) + { + + if (dn>0) + { + dn += dnp; + current_y+=yincrement; + l=l+SQRT2; + } + else if (dn<0) + { + dn += dnn; + l=l+0x10000; + } + else + { + if (xincrement<0) + { + dn += dnp; + current_y+=yincrement; + l=l+SQRT2; + } + else + { + dn += dnn; + l=l+0x10000; + } + } + + current_x+=xincrement; + //printf(" -->%08X %d %d\n",dn,current_x,current_y); + // Color is recomputed only when dithering is on + + + if (reverse) + { + + r2d_s_draw_point(gc,current_y,current_x,l); + } + else + { + r2d_s_draw_point(gc,current_x,current_y,l); + } + } + } // END CLIPPING + + //printf("END LINE\n"); + + + r2d_check_and_send_event(gc); +} + +// Used for filling +// Do clipping and coordinate transforms then call +// low levl line filling algorithm +// No mirroring check since it is a low level routine +// S COORDINATES +static void r2d_s_fill_line(T_R2D_GC_PTR gc,INT16 x,INT16 y,INT16 nb,BOOLEAN background) +{ + T_R2D_SHAPE_PTR clip; + T_R2D_RECTANGLE *r; +// INT16 tmp; + + clip=((T_R2D_GC*)gc)->p_s_clipping_shape; + r=(T_R2D_RECTANGLE*)clip; + + + if ((x>=r2d_get_xmin(clip)) && ( x<r2d_get_xmax(clip))) + { + if (y<r2d_get_ymin(clip)) + { + nb-=r2d_get_ymin(clip)-y; + y=r2d_get_ymin(clip); + } + + if (y+nb-1>=r2d_get_ymax(clip)) + nb=r2d_get_ymax(clip)-y; + + if (nb>0) + + IND_r2d_write_lcd_line(gc,x,y,nb,background); + } + + +} + +// Used for filling +// Do clipping and coordinate transforms then call +// low levl line filling algorithm +// No mirroring check since it is a low level routine +// S COORDINATES +static void r2d_s_arc_fill_line(T_R2D_GC_PTR gc,INT16 x,INT16 y, + INT16 org_x,INT16 org_y,INT16 nb,T_R2D_ARC_REGION *rgn,BOOLEAN background) +{ + T_R2D_SHAPE_PTR clip; + T_R2D_RECTANGLE *r; +// INT16 tmp; + + clip=((T_R2D_GC*)gc)->p_s_clipping_shape; + r=(T_R2D_RECTANGLE*)clip; + + + if ((x>=r2d_get_xmin(clip)) && ( x<r2d_get_xmax(clip))) + { + if (y<r2d_get_ymin(clip)) + { + nb-=r2d_get_ymin(clip)-y; + y=r2d_get_ymin(clip); + } + + if (y+nb-1>=r2d_get_ymax(clip)) + nb=r2d_get_ymax(clip)-y; + + if (nb>0) + + r2d_arc_write_lcd_line(gc,x,y,org_x,org_y,nb,rgn,background); + } + + +} + +// S coordinates +static void r2d_s_fill_rectangle(T_R2D_GC_PTR gc, + INT16 ul_x,INT16 ul_y,INT16 br_x, INT16 br_y,BOOLEAN background) +{ + + INT16 i; + // The ifdef is not passing the coordinates to S frame. + // It just changing the way the square is scanned + // to improve behavior relatively to the scanning mode. + for(i=ul_x+1;i<=br_x-1;i++) + { + r2d_s_fill_line(gc,i,ul_y+1,(br_y-ul_y)+1-2,background); + } + +} + +// Background allows to chose the color for filling +// If TRUE, background color is used +// (required for pen_size different from 1) +// L coordinates +static void r2d_df_rectangle(T_R2D_GC_PTR gc, + INT16 ul_x,INT16 ul_y,INT16 br_x, INT16 br_y,BOOLEAN background) +{ + + INT16 i; + // The ifdef is not passing the coordinates to S frame. + // It just changing the way the square is scanned + // to improve behavior relatively to the scanning mode. + #if (R2D_REFRESH==R2D_VERTICAL) + for(i=ul_x+1;i<=br_x-1;i++) + { + r2d_s_fill_line(gc,i,ul_y+1,(br_y-ul_y)+1-2,background); + } + #else + for(i=ul_y+1;i<=br_y-1;i++) + { + r2d_s_fill_line(gc,i,ul_x+1,(br_x-ul_x)+1-2,background); + } + #endif +} + +void r2d_draw_rectangle(T_R2D_GC_PTR gc, + INT16 ul_x,INT16 ul_y,INT16 br_x, INT16 br_y) +{ + + + r2d_moveto(gc,ul_x,ul_y); + r2d_lineto(gc,br_x,ul_y); + + + r2d_moveto(gc,br_x,ul_y+1); + r2d_lineto(gc,br_x,br_y); + + + r2d_moveto(gc,br_x-1,br_y); + r2d_lineto(gc,ul_x,br_y); + + + r2d_moveto(gc,ul_x,ul_y+1); + r2d_lineto(gc,ul_x,br_y-1); + +} + +void r2d_fill_rectangle(T_R2D_GC_PTR gc, + INT16 ul_x,INT16 ul_y,INT16 br_x, INT16 br_y) +{ +#ifdef R2D_MIRRORED_X + INT16 tmp; +#endif + r2d_local_to_global(gc,&ul_x,&ul_y); + r2d_local_to_global(gc,&br_x,&br_y); + + +#ifdef R2D_MIRRORED_X + ul_x = r2d_get_width(gc)-1-ul_x; + br_x = r2d_get_width(gc)-1-br_x; + R2D_SWAP(ul_x,br_x); +#endif + +#ifdef R2D_MIRRORED_Y + ul_y = r2d_get_height(gc)-1-ul_y; + br_y = r2d_get_height(gc)-1-br_y; + R2D_SWAP(ul_y,br_y); +#endif + r2d_df_rectangle(gc,ul_x,ul_y,br_x,br_y,TRUE); + if (((T_R2D_FRAMEBUFFER*)((T_R2D_GC*)gc)->p_frame_buffer)->kind==0) + r2d_update_region((T_R2D_GC*)gc,ul_x,ul_y,br_x,br_y); + + r2d_check_and_send_event(gc); +} + + + +void r2d_df_circle(T_R2D_GC_PTR gc, + INT16 x,INT16 y,INT16 r,BOOLEAN filling) +{ + INT32 current_x,current_y,my,mx; + INT32 dn,dnp,dnn,org_x,org_y,limit,rs,tmp,D_yx; + INT32 l; + INT32 p; // perimeter divided by 4 + + l=0; + + p=(PI*r)>>1; + + + #if (R2D_REFRESH==R2D_VERTICAL) + current_x=y; + current_y=x+r; + org_x=y; + org_y=x; + + #else + current_x=x; + current_y=y+r; + org_x=x; + org_y=y; + #endif + + D_yx=org_y-org_x; + + dnp=((-r) << 1) + 5; + dnn=3; + dn=-r; + rs=r*r; + limit=-r; + + + + + + tmp=1; + while(limit<=0) + { + + // Some points are their own image with symetries + // and yet they must not be drawn twice for drawing + // modes other than copy hence the tests + + my=(org_y << 1) - current_y; + mx=(org_x << 1) - current_x; + + // PY or PX is reflection relatively to horizontal line or vertical line + // PY = vertical mirroring where bottom becomes top + + // D = diagonal mirroring + + // AB means apply transform A then B + + // I is identity + + // Everything is done relatively to what is displayed on the LCD + // so my may be PX according to the refresh mode + + + if (!filling) + { + if (mx != current_x) + { + r2d_s_draw_point(gc,current_y,current_x,l); // I : 3 + r2d_s_draw_point(gc,mx+D_yx,current_y-D_yx,l); // D PX : 5 + r2d_s_draw_point(gc,my,mx,l); // PX.PY : 7 + r2d_s_draw_point(gc,current_x+D_yx,my-D_yx,l); // D PY : 1 + } + + if (current_x != current_y) + { + r2d_s_draw_point(gc,current_x+D_yx,current_y-D_yx,l+p); // D : 4 + r2d_s_draw_point(gc,current_y,mx,l+p); // PY : 2 + } + + if ((mx != my) || (current_x != current_y)) + r2d_s_draw_point(gc,my,current_x,l+p); // PX : 6 + + + if (mx != my) + r2d_s_draw_point(gc,mx+D_yx,my-D_yx,l+p); // D PX PY : 8 + + } + else + { + //printf("%d\n",current_x); + if (tmp) + { + if (current_x-mx!=0) + { + r2d_s_fill_line(gc,my,mx+1,(current_x-mx)+1-2,TRUE); + r2d_s_fill_line(gc,current_y,mx+1,(current_x-mx)+1-2,TRUE); + } + } + if (mx != my) + { + r2d_s_fill_line(gc,mx+D_yx,my+1-D_yx,(current_y-my)+1-2,TRUE); + if (current_x != mx); + r2d_s_fill_line(gc,current_x+D_yx,my+1-D_yx,(current_y-my)+1-2,TRUE); + } + } + + + if (dn>0) // M outside circle, point below must be drawn + { + dn+=dnp; + dnp+=4; + + current_y--; + l+=SQRT2; + limit+=2; + tmp=1; + } + else + { + dn+=dnn; + dnp+=2; + limit+=1; + tmp=0; + l+=0x10000; + } + + current_x++; + dnn+=2; + + + + + } + //printf("%08X\n",limit); +} + +void r2d_draw_circle(T_R2D_GC_PTR gc, + INT16 x,INT16 y,INT16 r) +{ + + r2d_local_to_global(gc,&x,&y); + + +#ifdef R2D_MIRRORED_X + x = r2d_get_width(gc)-1-x; +#endif + +#ifdef R2D_MIRRORED_Y + y = r2d_get_height(gc)-1-y; +#endif + + + r2d_df_circle(gc,x,y,r,FALSE); + if (((T_R2D_FRAMEBUFFER*)((T_R2D_GC*)gc)->p_frame_buffer)->kind==0) + r2d_update_region((T_R2D_GC*)gc,x-r,y-r,x+r,y+r); + r2d_check_and_send_event(gc); +} + +void r2d_fill_circle(T_R2D_GC_PTR gc, + INT16 x,INT16 y,INT16 r) +{ + r2d_local_to_global(gc,&x,&y); + +#ifdef R2D_MIRRORED_X + x = r2d_get_width(gc)-1-x; +#endif + +#ifdef R2D_MIRRORED_Y + y = r2d_get_height(gc)-1-y; +#endif + + r2d_df_circle(gc,x,y,r,TRUE); + if (((T_R2D_FRAMEBUFFER*)((T_R2D_GC*)gc)->p_frame_buffer)->kind==0) + r2d_update_region((T_R2D_GC*)gc,x-r,y-r,x+r,y+r); + r2d_check_and_send_event(gc); +} + + + +// h and v are used to draw roundrectangle (each piece of the ellipse must be +// separated from other parts) +void r2d_df_ellipse(T_R2D_GC_PTR gc, + INT16 ul_x,INT16 ul_y,INT16 br_x, INT16 br_y, INT16 h,INT16 v,BOOLEAN filling) +{ + INT32 current_x,current_y,limit,newx,newy,org_x,org_y; + INT32 dn,dnp,dnn,as,bs,tmp,a,b,mx,my,lastx,lasty,round; + INT32 l; + l=0; + + if ((h!=0) || (v!=0)) + round=1; + else + round=0; + + + // Width of rectangle is assumed to be even + // and it is forced to even dimension + + + #if (R2D_REFRESH==R2D_VERTICAL) + org_x=(ul_y + br_y)>>1; + org_y=(br_x + ul_x)>>1; + a=(br_y-ul_y)>>1; + as=R2D_SQUARE_P(a); + b=(br_x-ul_x)>>1; + bs=R2D_SQUARE_P(b); + + current_x=org_x ; + current_y=org_y+b; + newx=org_y; + newy=org_x+a; + + #else + org_x=(ul_x + br_x)>>1; + org_y=(br_y + ul_y)>>1; + + b=(br_y-ul_y)>>1; + bs=R2D_SQUARE_P(b); + a=(br_x-ul_x)>>1; + as=R2D_SQUARE_P(a); + + current_x=org_x; + current_y=org_y+b; + newx=org_y; + newy=org_x+a; + R2D_SWAP(h,v); + + #endif + + // Now, shift by 2 to have the accuracy required by division by four + + + //printf("current_x=%d, current_y=%d,as=%08X bs=%08X\n",current_x,current_y,as,bs); + + + // New shift by 2 because one needs to compute quarter of values + bs<<=2; as <<=2;b<<=2;a<<=2; + + limit = - ((as * b) >> 2); // -a^2 * b in Q2 + + tmp=-((as * b) >> 2); + dnp=(bs << 1) + bs + (tmp<<1) + (as << 1); + dnn=(bs << 1) + bs; + dn=bs + tmp + (as >>2); + + + + //printf("dn=%f dnp=%f dnn=%f\n",dn / 8.0,dnp / 8.0,dnn / 8.0); + +/*#if (R2D_REFRESH==R2D_VERTICAL) + r2d_draw_point(gc,current_y,current_x); +#else + r2d_draw_point(gc,current_x,current_y); +#endif*/ + + //printf("as=%08X bs=%08X\n",as,bs); + + tmp=1; + while(limit<=0) + { + my=(org_y << 1) - current_y; + mx=(org_x << 1) - current_x; + + lastx=current_y; + lasty=current_x; + + if (!filling) + { + r2d_s_draw_point(gc,(current_y)+h,(current_x)+v,l); // I : 1 + r2d_s_draw_point(gc,my,mx,l); // PX PY : 2 + + if ((mx != current_x) || (round)) + { + r2d_s_draw_point(gc,(current_y)+h,mx,l); // PY : 3 + r2d_s_draw_point(gc,my,current_x+v,l); // PX : 4 + } + } + else + { + if (tmp) + { + + // Used to remove point on horizontal extremity + if (current_x+v-mx !=0) + { + r2d_s_fill_line(gc,my,mx+1,(current_x+v-mx)+1-2,TRUE); + r2d_s_fill_line(gc,current_y+h,mx+1,(current_x+v-mx)+1-2,TRUE); + } + } + } + + if (dn>=0) // M outside circle, point below must be drawn + { + dn+=dnp; + dnp+=((bs + as) << 1); + current_y--; + limit+=(as + bs); + tmp=1; + l+=SQRT2; + } + else + + { + dn+=dnn; + dnp+=(bs << 1); + limit+=bs; + tmp=0; + l+=0x10000; + + } + current_x++; + dnn+=(bs << 1); + + + //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); + + + } + + current_x=newx; + current_y=newy; + R2D_SWAP(as,bs); + R2D_SWAP(a,b); + + limit = - ((as * b) >> 2); + + tmp=-((as * b) >> 2); + dnp=(bs << 1) + bs + (tmp<<1) + (as << 1); + dnn=(bs << 1) + bs; + dn=bs + tmp + (as >>2); + + //printf("newx=%d, newy=%d,a=%d,b=%d\n",newx,newy,a,b); + //printf("dn=%f dnp=%f dnn=%f\n",dn / 4.0,dnp / 4.0,dnn / 4.0); + + tmp=1; + + /* #if (R2D_REFRESH==R2D_VERTICAL) + r2d_draw_point(gc,current_x,current_y); + #else + r2d_draw_point(gc,current_y,current_x); + #endif*/ + + while(limit<0) + { + + my=(org_x << 1) - current_y; + mx=(org_y << 1) - current_x; + + if (!filling) + { + if ((lastx!=current_x) || (lasty!=current_y)) + { + + r2d_s_draw_point(gc,(current_x)+h,(current_y)+v,l); // D : 5 + + + r2d_s_draw_point(gc,mx,my,l); // D PX PY : 6 + + if ((mx != (current_x+h)) || (round)) + { + r2d_s_draw_point(gc,(current_x)+h,my,l); // D PY : 7 + r2d_s_draw_point(gc,mx,(current_y)+v,l); // D PX : 8 + } + + } + } + else + { + if (current_x != lastx) + { + r2d_s_fill_line(gc,mx,my+1,(current_y+v-my)+1-2,TRUE); + if ((current_x+h) !=mx) + r2d_s_fill_line(gc,current_x+h,my+1,(current_y+v-my)+1-2,TRUE); + } + } + + if (dn>0) // M outside circle, point below must be drawn + { + dn+=dnp; + dnp+=((bs + as) << 1); + current_y--; // Q1 + limit+=(as + bs); + tmp=1; + l+=SQRT2; + } + else + { + dn+=dnn; + dnp+=(bs << 1); + limit+=bs; + tmp=0; + l+=0x10000; + + } + current_x++; // Q1 + dnn+=(bs << 1); + + + + + //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); + + + } +} + +void r2d_draw_ellipse(T_R2D_GC_PTR gc, + INT16 ul_x,INT16 ul_y,INT16 br_x, INT16 br_y) +{ +#ifdef R2D_MIRRORED_X + INT16 tmp; +#endif + r2d_local_to_global(gc,&ul_x,&ul_y); + r2d_local_to_global(gc,&br_x,&br_y); + + +#ifdef R2D_MIRRORED_X + ul_x = r2d_get_width(gc)-1-ul_x; + br_x = r2d_get_width(gc)-1-br_x; + R2D_SWAP(ul_x,br_x); +#endif + +#ifdef R2D_MIRRORED_Y + ul_y = r2d_get_height(gc)-1-ul_y; + br_y = r2d_get_height(gc)-1-br_y; + R2D_SWAP(ul_y,br_y); +#endif + + r2d_df_ellipse(gc,ul_x,ul_y,br_x,br_y,0,0,FALSE); + if (((T_R2D_FRAMEBUFFER*)((T_R2D_GC*)gc)->p_frame_buffer)->kind==0) + r2d_update_region((T_R2D_GC*)gc,ul_x,ul_y,br_x,br_y); + + r2d_check_and_send_event(gc); +} + +void r2d_fill_ellipse(T_R2D_GC_PTR gc, + INT16 ul_x,INT16 ul_y,INT16 br_x, INT16 br_y) +{ +#ifdef R2D_MIRRORED_X + INT16 tmp; +#endif + r2d_local_to_global(gc,&ul_x,&ul_y); + r2d_local_to_global(gc,&br_x,&br_y); + + +#ifdef R2D_MIRRORED_X + ul_x = r2d_get_width(gc)-1-ul_x; + br_x = r2d_get_width(gc)-1-br_x; + R2D_SWAP(ul_x,br_x); +#endif + +#ifdef R2D_MIRRORED_Y + ul_y = r2d_get_height(gc)-1-ul_y; + br_y = r2d_get_height(gc)-1-br_y; + R2D_SWAP(ul_y,br_y); +#endif + + r2d_df_ellipse(gc,ul_x,ul_y,br_x,br_y,0,0,TRUE); + if (((T_R2D_FRAMEBUFFER*)((T_R2D_GC*)gc)->p_frame_buffer)->kind==0) + r2d_update_region((T_R2D_GC*)gc,ul_x,ul_y,br_x,br_y); + + r2d_check_and_send_event(gc); +} + +void r2d_draw_round_rectangle(T_R2D_GC_PTR gc, + INT16 ul_x,INT16 ul_y,INT16 br_x, INT16 br_y,INT16 h,INT16 v) +{ +#ifdef R2D_MIRRORED_X + INT16 tmp; +#endif + r2d_moveto(gc,ul_x+h+1,ul_y); + r2d_lineto(gc,br_x-h-1,ul_y); + + r2d_moveto(gc,ul_x+h+1,br_y); + r2d_lineto(gc,br_x-h-1,br_y); + + r2d_moveto(gc,ul_x,ul_y+v+1); + r2d_lineto(gc,ul_x,br_y-v-1); + + r2d_moveto(gc,br_x,ul_y+v+1); + r2d_lineto(gc,br_x,br_y-v-1); + + r2d_local_to_global(gc,&ul_x,&ul_y); + r2d_local_to_global(gc,&br_x,&br_y); + + +#ifdef R2D_MIRRORED_X + ul_x = r2d_get_width(gc)-1-ul_x; + br_x = r2d_get_width(gc)-1-br_x; + R2D_SWAP(ul_x,br_x); +#endif + +#ifdef R2D_MIRRORED_Y + ul_y = r2d_get_height(gc)-1-ul_y; + br_y = r2d_get_height(gc)-1-br_y; + R2D_SWAP(ul_y,br_y); +#endif + 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); +if (((T_R2D_FRAMEBUFFER*)((T_R2D_GC*)gc)->p_frame_buffer)->kind==0) + r2d_update_region((T_R2D_GC*)gc,ul_x,ul_y,br_x,br_y); + + //printf("%d %d\n",ul_x+h+1,br_x-h-1); + + + r2d_check_and_send_event(gc); +} + +void r2d_fill_round_rectangle(T_R2D_GC_PTR gc, + INT16 ul_x,INT16 ul_y,INT16 br_x, INT16 br_y,INT16 h,INT16 v) +{ +#ifdef R2D_MIRRORED_X + INT16 tmp; +#endif + r2d_local_to_global(gc,&ul_x,&ul_y); + r2d_local_to_global(gc,&br_x,&br_y); + +#ifdef R2D_MIRRORED_X + ul_x = r2d_get_width(gc)-1-ul_x; + br_x = r2d_get_width(gc)-1-br_x; + R2D_SWAP(ul_x,br_x); +#endif + + +#ifdef R2D_MIRRORED_Y + ul_y = r2d_get_height(gc)-1-ul_y; + br_y = r2d_get_height(gc)-1-br_y; + R2D_SWAP(ul_y,br_y); +#endif + + 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); +#if (R2D_REFRESH == R2D_VERTICAL) + r2d_df_rectangle(gc,ul_x+h,ul_y,br_x-h+1,br_y,TRUE); + +#else + + r2d_df_rectangle(gc,ul_x,ul_y+v,br_x,br_y-v+1,TRUE); +#endif + if (((T_R2D_FRAMEBUFFER*)((T_R2D_GC*)gc)->p_frame_buffer)->kind==0) + r2d_update_region((T_R2D_GC*)gc,ul_x,ul_y,br_x,br_y); + //printf("%d %d\n",ul_x+h+1,br_x-h-1); + /*r2d_moveto(gc,ul_x+h+1,ul_y); + r2d_lineto(gc,br_x-h-1,ul_y); + + r2d_moveto(gc,ul_x+h+1,br_y); + r2d_lineto(gc,br_x-h-1,br_y); + + r2d_moveto(gc,ul_x,ul_y+v+1); + r2d_lineto(gc,ul_x,br_y-v-1); + + r2d_moveto(gc,br_x,ul_y+v+1); + r2d_lineto(gc,br_x,br_y-v-1);*/ + r2d_check_and_send_event(gc); +} + +// angle must be between 0 and 359 +static INT32 r2d_cos(INT16 angle) +{ + + + if (angle<=90) + return(r2d_cos_table[angle]); + else if (angle<=180) + return(-r2d_cos_table[180-angle]); + else if (angle<=270) + return(-r2d_cos_table[angle-180]); + else + return(r2d_cos_table[360-angle]); +} + +// angle must be between 0 and 359 +static INT32 r2d_sin(INT16 angle) +{ + angle=angle+90; + if (angle>=360) + angle=angle-360; + + return(-r2d_cos(angle)); +} + +static void r2d_check_angles(INT16 *start,INT16 *stop) +{ +// INT16 tmp; + + + while(*start<0) + *start+=360; + while(*start>=360) + *start-=360; + + while(*stop<0) + *stop+=360; + while(*stop>=360) + *stop-=360; + + //if (*start>*stop) + //{ +// R2D_SWAP((*start),(*stop)); + + //} + +} + + + +void r2d_df_arc(T_R2D_GC_PTR gc, + INT16 ul_x,INT16 ul_y,INT16 br_x, INT16 br_y,T_R2D_ARC_REGION *rgn ,BOOLEAN filling) +{ + INT32 current_x,current_y,limit,newx,newy,org_x,org_y; + INT32 dn,dnp,dnn,as,bs,tmp,a,b,mx,my,lastx,lasty; + INT32 l; + + l=0; + + // Width of rectangle is assumed to be even + // and it is forced to even dimension + + if (rgn->is_null) + goto end_arc; + + #if (R2D_REFRESH==R2D_VERTICAL) + org_x=(ul_y + br_y)>>1; + org_y=(br_x + ul_x)>>1; + a=(br_y-ul_y)>>1; + as=R2D_SQUARE_P(a); + b=(br_x-ul_x)>>1; + bs=R2D_SQUARE_P(b); + + current_x=org_x ; + current_y=org_y+b; + newx=org_y; + newy=org_x+a; + + + + #else + org_x=(ul_x + br_x)>>1; + org_y=(br_y + ul_y)>>1; + + b=(br_y-ul_y)>>1; + bs=R2D_SQUARE_P(b); + a=(br_x-ul_x)>>1; + as=R2D_SQUARE_P(a); + + current_x=org_x; + current_y=org_y+b; + newx=org_y; + newy=org_x+a; + + r2d_arc_region_diagonal_reflect(rgn); + r2d_arc_region_x_reflect(rgn); + r2d_arc_region_y_reflect(rgn); + #endif + + + + // Orthogonal is (eb,-ea) + + //r2d_s_draw_point(gc,org_y,org_x); + //r2d_s_draw_point(gc,((rgn->sa)>>16)+org_y,((rgn->sb)>>16)+org_x); + //r2d_s_draw_point(gc,((rgn->sb)>>16)+org_y,((-rgn->sa)>>16)+org_x); + + //r2d_s_draw_point(gc,((rgn->ea)>>16)+org_y,((rgn->eb)>>16)+org_x); + + //goto end_arc; + + // Now, shift by 2 to have the accuracy required by division by four + + + //printf("current_x=%d, current_y=%d,as=%08X bs=%08X\n",current_x,current_y,as,bs); + + + // New shift by 2 because one needs to compute quarter of values + bs<<=2; as <<=2;b<<=2;a<<=2; + + limit = - ((as * b) >> 2); // -a^2 * b in Q2 + + tmp=-((as * b) >> 2); + dnp=(bs << 1) + bs + (tmp<<1) + (as << 1); + dnn=(bs << 1) + bs; + dn=bs + tmp + (as >>2); + + + + //printf("dn=%f dnp=%f dnn=%f\n",dn / 8.0,dnp / 8.0,dnn / 8.0); + +/*#if (R2D_REFRESH==R2D_VERTICAL) + r2d_draw_point(gc,current_y,current_x); +#else + r2d_draw_point(gc,current_x,current_y); +#endif*/ + + //printf("as=%08X bs=%08X\n",as,bs); + + tmp=1; + while(limit<=0) + { + my=(org_y << 1) - current_y; + mx=(org_x << 1) - current_x; + + lastx=current_y; + lasty=current_x; + + if (!filling) + { + if (r2d_check_is_in_arc_region(current_y-org_y,current_x-org_x,rgn)) + r2d_s_draw_point(gc,(current_y),(current_x),l); // I : 1 + + if (r2d_check_is_in_arc_region(my-org_y,mx-org_x,rgn)) + r2d_s_draw_point(gc,my,mx,l); // PX PY : 2 + + if ((mx != current_x) ) + { + if (r2d_check_is_in_arc_region(current_y-org_y,mx-org_x,rgn)) + r2d_s_draw_point(gc,current_y,mx,l); // PY : 3 + + if (r2d_check_is_in_arc_region(my-org_y,current_x-org_x,rgn)) + r2d_s_draw_point(gc,my,current_x,l); // PX : 4 + } + } + else + { + if (tmp) + { + + // Used to remove point on horizontal extremity + if (current_x-mx !=0) + { + r2d_s_arc_fill_line(gc,my,mx+1,org_y,org_x,(current_x-mx)+1-2 + ,rgn,TRUE); + + r2d_s_arc_fill_line(gc,current_y,mx+1,org_y,org_x,(current_x-mx)+1-2 + ,rgn,TRUE); + } + } + } + + if (dn>=0) // M outside circle, point below must be drawn + { + dn+=dnp; + dnp+=((bs + as) << 1); + current_y--; + limit+=(as + bs); + tmp=1; + l+=SQRT2; + } + else + + { + dn+=dnn; + dnp+=(bs << 1); + limit+=bs; + tmp=0; + l+=0x10000; + } + current_x++; + dnn+=(bs << 1); + + + //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); + + + } + + current_x=newx; + current_y=newy; + R2D_SWAP(as,bs); + R2D_SWAP(a,b); + + limit = - ((as * b) >> 2); + + tmp=-((as * b) >> 2); + dnp=(bs << 1) + bs + (tmp<<1) + (as << 1); + dnn=(bs << 1) + bs; + dn=bs + tmp + (as >>2); + + //printf("newx=%d, newy=%d,a=%d,b=%d\n",newx,newy,a,b); + //printf("dn=%f dnp=%f dnn=%f\n",dn / 4.0,dnp / 4.0,dnn / 4.0); + + tmp=1; + + /* #if (R2D_REFRESH==R2D_VERTICAL) + r2d_draw_point(gc,current_x,current_y); + #else + r2d_draw_point(gc,current_y,current_x); + #endif*/ + + while(limit<0) + { + + my=(org_x << 1) - current_y; + mx=(org_y << 1) - current_x; + + if (!filling) + { + if ((lastx!=current_x) || (lasty!=current_y)) + { + + if (r2d_check_is_in_arc_region(current_x-org_y,current_y-org_x,rgn)) + r2d_s_draw_point(gc,(current_x),(current_y),l); // D : 5 + + + if (r2d_check_is_in_arc_region(mx-org_y,my-org_x,rgn)) + r2d_s_draw_point(gc,mx,my,l); // D PX PY : 6 + + if ((mx != current_x) ) + { + if (r2d_check_is_in_arc_region(current_x-org_y,my-org_x,rgn)) + r2d_s_draw_point(gc,(current_x),my,l); // D PY : 7 + + if (r2d_check_is_in_arc_region(mx-org_y,current_y-org_x,rgn)) + r2d_s_draw_point(gc,mx,(current_y),l); // D PX : 8 + } + + } + } + else + { + if (current_x != lastx) + { + r2d_s_arc_fill_line(gc,mx,my+1,org_y,org_x,(current_y-my)+1-2 + ,rgn,TRUE); + + if (current_x !=mx) + r2d_s_arc_fill_line(gc,current_x,my+1,org_y,org_x,(current_y-my)+1-2 + ,rgn,TRUE); + } + } + + if (dn>0) // M outside circle, point below must be drawn + { + dn+=dnp; + dnp+=((bs + as) << 1); + current_y--; // Q1 + limit+=(as + bs); + tmp=1; + l+=SQRT2; + } + else + { + dn+=dnn; + dnp+=(bs << 1); + limit+=bs; + tmp=0; + l+=0x10000; + + } + current_x++; // Q1 + dnn+=(bs << 1); + + + + + //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); + + + } + + end_arc: current_x=0; +} + +void r2d_draw_arc(T_R2D_GC_PTR gc,INT16 start_angle,INT16 stop_angle, + INT16 ul_x,INT16 ul_y,INT16 br_x, INT16 br_y) +{ +#ifdef R2D_MIRRORED_X + INT16 tmp; +#endif + BOOLEAN large=FALSE; + T_R2D_ARC_REGION rgn; + INT32 sa,sb,ea,eb; + INT32 a,b; + + a=(br_x-ul_x)>>1; + b=(br_y-ul_y)>>1; + + r2d_local_to_global(gc,&ul_x,&ul_y); + r2d_local_to_global(gc,&br_x,&br_y); + + rgn.one_sector=0; + if (stop_angle-start_angle>180) + rgn.one_sector=1; + + if (stop_angle-start_angle==360) + rgn.one_sector=2; + + if (start_angle==stop_angle) + rgn.is_null=TRUE; + else + rgn.is_null=FALSE; + r2d_check_angles(&start_angle,&stop_angle); + + + sa=a * r2d_cos(start_angle); // Q16 + sb= -b* r2d_sin(start_angle); // Q16 + // Orthogonal is (sb,-sa) + + ea= a * r2d_cos(stop_angle); // Q16 + eb= -b* r2d_sin(stop_angle); // Q16 + // Orthogonal is (-sb,sa) + + //r2d_moveto(gc,ul_x+a,ul_y+b); + //r2d_lineto(gc,ul_x+a+(sa>>16),ul_y+b+(sb>>16)); + + // Orthogonal + //r2d_moveto(gc,ul_x+a,ul_y+b); + //r2d_lineto(gc,ul_x+a+(sb>>16),ul_y+b+((-sa)>>16)); + + //r2d_moveto(gc,ul_x+a,ul_y+b); + //r2d_lineto(gc,ul_x+a+(ea>>16),ul_y+b+(eb>>16)); + + rgn.sa=sa; + rgn.sb=sb; + + + rgn.ea=-ea; + rgn.eb=-eb; + + + + + + +#ifdef R2D_MIRRORED_X + ul_x = r2d_get_width(gc)-1-ul_x; + br_x = r2d_get_width(gc)-1-br_x; + R2D_SWAP(ul_x,br_x); + + r2d_arc_region_x_reflect(&rgn); + +#endif + +#ifdef R2D_MIRRORED_Y + ul_y = r2d_get_height(gc)-1-ul_y; + br_y = r2d_get_height(gc)-1-br_y; + R2D_SWAP(ul_y,br_y); + + r2d_arc_region_y_reflect(&rgn); +#endif + + + + r2d_df_arc(gc,ul_x,ul_y,br_x,br_y,&rgn,FALSE); + if (((T_R2D_FRAMEBUFFER*)((T_R2D_GC*)gc)->p_frame_buffer)->kind==0) + r2d_update_region((T_R2D_GC*)gc,ul_x,ul_y,br_x,br_y); + + r2d_check_and_send_event(gc); +} + +void r2d_fill_arc(T_R2D_GC_PTR gc, INT16 start_angle,INT16 stop_angle, + INT16 ul_x,INT16 ul_y,INT16 br_x, INT16 br_y) +{ +#ifdef R2D_MIRRORED_X + INT16 tmp; +#endif + BOOLEAN large=FALSE; + T_R2D_ARC_REGION rgn; + INT32 sa,sb,ea,eb; + INT32 a,b; + + a=(br_x-ul_x)>>1; + b=(br_y-ul_y)>>1; + + r2d_local_to_global(gc,&ul_x,&ul_y); + r2d_local_to_global(gc,&br_x,&br_y); + + + rgn.one_sector=0; + if (stop_angle-start_angle>180) + rgn.one_sector=1; + + if (stop_angle-start_angle==360) + rgn.one_sector=2; + + if (start_angle==stop_angle) + rgn.is_null=TRUE; + else + rgn.is_null=FALSE; + r2d_check_angles(&start_angle,&stop_angle); + + + sa=a * r2d_cos(start_angle); // Q16 + sb= -b* r2d_sin(start_angle); // Q16 + // Orthogonal is (sb,-sa) + + ea= a * r2d_cos(stop_angle); // Q16 + eb= -b* r2d_sin(stop_angle); // Q16 + // Orthogonal is (-sb,sa) + + //r2d_moveto(gc,ul_x+a,ul_y+b); + //r2d_lineto(gc,ul_x+a+(sa>>16),ul_y+b+(sb>>16)); + + // Orthogonal + //r2d_moveto(gc,ul_x+a,ul_y+b); + //r2d_lineto(gc,ul_x+a+(sb>>16),ul_y+b+((-sa)>>16)); + + //r2d_moveto(gc,ul_x+a,ul_y+b); + //r2d_lineto(gc,ul_x+a+(ea>>16),ul_y+b+(eb>>16)); + + rgn.sa=sa; + rgn.sb=sb; + + + rgn.ea=-ea; + rgn.eb=-eb; + + + +#ifdef R2D_MIRRORED_X + ul_x = r2d_get_width(gc)-1-ul_x; + br_x = r2d_get_width(gc)-1-br_x; + R2D_SWAP(ul_x,br_x); + + r2d_arc_region_x_reflect(&rgn); +#endif + +#ifdef R2D_MIRRORED_Y + ul_y = r2d_get_height(gc)-1-ul_y; + br_y = r2d_get_height(gc)-1-br_y; + R2D_SWAP(ul_y,br_y); + + r2d_arc_region_y_reflect(&rgn); +#endif + + + + + + r2d_df_arc(gc,ul_x,ul_y,br_x,br_y,&rgn,TRUE); + if (((T_R2D_FRAMEBUFFER*)((T_R2D_GC*)gc)->p_frame_buffer)->kind==0) + r2d_update_region((T_R2D_GC*)gc,ul_x,ul_y,br_x,br_y); + + r2d_check_and_send_event(gc); +} + +/////////////////////////////////////// +// +// Copy function +// + +static void r2d_diagonal_mirror(T_R2D_SHAPE_PTR rectangle) +{ + T_R2D_RECTANGLE *r; + INT16 tmp; + r=(T_R2D_RECTANGLE *)rectangle; + + tmp=r->ul_x; + r->ul_x=r->ul_y; + r->ul_y=tmp; + + tmp=r->br_x; + r->br_x=r->br_y; + r->br_y=tmp; +} + +// Global coordinates +static void r2d_mirror_rectangle(T_R2D_GC_PTR gc,T_R2D_SHAPE_PTR rectangle) +{ + T_R2D_RECTANGLE *r; + //INT16 org_x,org_y; +#ifdef R2D_MIRRORED_X + INT16 tmp; +#endif + r=(T_R2D_RECTANGLE *)rectangle; + + +#ifdef R2D_MIRRORED_X + r->ul_x = r2d_get_width(gc)-r->ul_x; + r->br_x = r2d_get_width(gc)-r->br_x; + tmp=r->ul_x; + r->ul_x=r->br_x; + r->br_x=tmp; +#endif + +#ifdef R2D_MIRRORED_Y + r->ul_y = r2d_get_height(gc)-r->ul_y; + r->br_y = r2d_get_height(gc)-r->br_y; + + tmp=r->ul_y; + r->ul_y=r->br_y; + r->br_y=tmp; +#endif + + +} + +// Global coordinates +// Here a rectangle with clipping convention is mirrored +// The resulting rectangle (s_clipping) is used with drawing +// convention. So, the boundary must be updated +static void r2d_mirror_clip_rectangle(T_R2D_GC_PTR gc,T_R2D_SHAPE_PTR rectangle) +{ + T_R2D_RECTANGLE *r; +// INT16 org_x,org_y; +#ifdef R2D_MIRRORED_X + INT16 tmp; +#endif + r=(T_R2D_RECTANGLE *)rectangle; + + + //Be careful br_x is NOT a line wich must be drawn +#ifdef R2D_MIRRORED_X + r->ul_x = r2d_get_width(gc)-r->ul_x+1; + r->br_x = r2d_get_width(gc)-(r->br_x-1); + tmp=r->ul_x; + r->ul_x=r->br_x; + r->br_x=tmp; +#endif + +#ifdef R2D_MIRRORED_Y + r->ul_y = r2d_get_height(gc)-r->ul_y+1; + r->br_y = r2d_get_height(gc)-(r->br_y-1); + + tmp=r->ul_y; + r->ul_y=r->br_y; + r->br_y=tmp; +#endif + + +} + +// Compute the intersection of the clipping shape of srcGc with +// the srcRectangle. Report he size reduction onto dstRectangle. +// Compute the intersection between dstRectangle and the clipping rectangle +// of dstGc and report the size reduction to srcRectangle. +// At the end, one get two rectangles of same size. +// The first one is contained in the clipping shape of srcGc +// and the second one in the clipping shape of dstGc. +// If the result is null, false is returned and no copy is done +// The rectangles are modified. +static BOOLEAN r2d_clipped_is_not_null(T_R2D_GC* src_gc,T_R2D_GC *dst_gc, + T_R2D_RECTANGLE* src_rectangle,T_R2D_RECTANGLE* dst_rectangle) +{ + BOOLEAN result=TRUE; + //CC : clipping coordinate , RC : rectangle coordinate + INT16 delta,CC,RC; + +#if (R2D_DEBUG == R2D_ON) +#if (R2D_DEBUG_WARNING == R2D_DEBUG_HIGH) + if (src_gc->p_clipping_shape==NULL) + rvf_send_trace("R2D : clipping shape error",26, NULL_PARAM, + RV_TRACE_LEVEL_ERROR, r2d_use_id ); + if (dst_gc->p_clipping_shape==NULL) + rvf_send_trace("R2D : clipping shape error",26, NULL_PARAM, + RV_TRACE_LEVEL_ERROR, r2d_use_id ); +#endif +#endif + + //T_R2D_RECTANGLE *debug; + + //debug=(T_R2D_RECTANGLE*)src_gc->p_clipping_shape; + + + // Intersections in src context + CC=r2d_get_xmin(src_gc->p_clipping_shape); + RC=r2d_get_xmin(src_rectangle); + if ( CC > RC) + { + delta=CC-RC; + src_rectangle->ul_x=CC; + dst_rectangle->ul_x+=delta; + } + + CC=r2d_get_xmax(src_gc->p_clipping_shape); + RC=r2d_get_xmax(src_rectangle); + if ( RC > CC) + { + delta=RC-CC; + src_rectangle->br_x=CC; + dst_rectangle->br_x-=delta; + } + + CC=r2d_get_ymin(src_gc->p_clipping_shape); + RC=r2d_get_ymin(src_rectangle); + if ( CC > RC) + { + delta=CC-RC; + src_rectangle->ul_y=CC; + dst_rectangle->ul_y+=delta; + } + + CC=r2d_get_ymax(src_gc->p_clipping_shape); + RC=r2d_get_ymax(src_rectangle); + if ( RC > CC) + { + delta=RC-CC; + src_rectangle->br_y=CC; + dst_rectangle->br_y-=delta; + } + + // Intersection in dst context + CC=r2d_get_xmin(dst_gc->p_clipping_shape); + RC=r2d_get_xmin(dst_rectangle); + if ( CC > RC) + { + delta=CC-RC; + dst_rectangle->ul_x=CC; + src_rectangle->ul_x+=delta; + } + + CC=r2d_get_xmax(dst_gc->p_clipping_shape); + RC=r2d_get_xmax(dst_rectangle); + if ( RC > CC) + { + delta=RC-CC; + dst_rectangle->br_x=CC; + src_rectangle->br_x-=delta; + } + + CC=r2d_get_ymin(dst_gc->p_clipping_shape); + RC=r2d_get_ymin(dst_rectangle); + if ( CC > RC) + { + delta=CC-RC; + dst_rectangle->ul_y=CC; + src_rectangle->ul_y+=delta; + } + + CC=r2d_get_ymax(dst_gc->p_clipping_shape); + RC=r2d_get_ymax(dst_rectangle); + if ( RC > CC) + { + delta=RC-CC; + dst_rectangle->br_y=CC; + src_rectangle->br_y-=delta; + } + + if (src_rectangle->ul_x>=src_rectangle->br_x) + result=FALSE; + + + if (src_rectangle->ul_y>=src_rectangle->br_y) + result=FALSE; + + if (result) + { + /*printf("src: (%d,%d) -- (%d,%d)\n",src_rectangle->ul_x,src_rectangle->ul_y + ,src_rectangle->br_x,src_rectangle->br_y); + printf("dst: (%d,%d) -- (%d,%d)\n",dst_rectangle->ul_x,dst_rectangle->ul_y + ,dst_rectangle->br_x,dst_rectangle->br_y);*/ + + // Conversion of clipped rectangles to framebuffer coordinates + r2d_local_to_global(src_gc,&(src_rectangle->ul_x),&(src_rectangle->ul_y)); + r2d_local_to_global(src_gc,&(src_rectangle->br_x),&(src_rectangle->br_y)); + r2d_local_to_global(dst_gc,&(dst_rectangle->ul_x),&(dst_rectangle->ul_y)); + r2d_local_to_global(dst_gc,&(dst_rectangle->br_x),&(dst_rectangle->br_y)); + +#if (R2D_DEBUG == R2D_ON) +#if (R2D_DEBUG_WARNING == R2D_DEBUG_HIGH) + if (src_rectangle->ul_x<0) + rvf_send_trace("R2D : clipping shape error",26, NULL_PARAM, + RV_TRACE_LEVEL_ERROR, R2D_USE_ID ); + + if (src_rectangle->ul_y<0) + rvf_send_trace("R2D : clipping shape error",26, NULL_PARAM, + RV_TRACE_LEVEL_ERROR, R2D_USE_ID ); + + if (dst_rectangle->ul_x<0) + rvf_send_trace("R2D : clipping shape error",26, NULL_PARAM, + RV_TRACE_LEVEL_ERROR, R2D_USE_ID ); + + + if (dst_rectangle->ul_y<0) + rvf_send_trace("R2D : clipping shape error",26, NULL_PARAM, + RV_TRACE_LEVEL_ERROR, R2D_USE_ID ); + + if (src_rectangle->br_x>r2d_get_width(src_gc)) + rvf_send_trace("R2D : clipping shape error",26, NULL_PARAM, + RV_TRACE_LEVEL_ERROR, R2D_USE_ID ); + + if (src_rectangle->br_y>r2d_get_height(src_gc)) + rvf_send_trace("R2D : clipping shape error",26, NULL_PARAM, + RV_TRACE_LEVEL_ERROR, R2D_USE_ID ); + + if (dst_rectangle->br_x>r2d_get_width(dst_gc)) + rvf_send_trace("R2D : clipping shape error",26, NULL_PARAM, + RV_TRACE_LEVEL_ERROR, R2D_USE_ID ); + + if (dst_rectangle->br_y>r2d_get_height(dst_gc)) + rvf_send_trace("R2D : clipping shape error",26, NULL_PARAM, + RV_TRACE_LEVEL_ERROR, R2D_USE_ID ); + +#endif +#endif + /*printf("src: (%d,%d) -- (%d,%d)\n",src_rectangle->ul_x,src_rectangle->ul_y + ,src_rectangle->br_x,src_rectangle->br_y); + printf("dst: (%d,%d) -- (%d,%d)\n",dst_rectangle->ul_x,dst_rectangle->ul_y + ,dst_rectangle->br_x,dst_rectangle->br_y);*/ + } + + return(result); +} + +T_R2D_ERROR r2d_low_level_blit_rect(T_R2D_GC_PTR src_gc,T_R2D_GC_PTR dst_gc, + T_R2D_SHAPE_PTR org_src_rectangle, T_R2D_SHAPE_PTR org_dst_rectangle, + BOOLEAN src_mirrored,BOOLEAN dst_mirrored, + BOOLEAN use_foreground_color) +{ + + INT16 kind_src,kind_dst,org_bx,org_by,org_ux,org_uy; +#if (R2D_ASM == R2D_ON) + T_R2D_DRAWING_MODE mode; +#endif + + T_R2D_SHAPE_PTR src_rectangle,dst_rectangle; + +#if (R2D_DEBUG == R2D_ON) +#if (R2D_DEBUG_WARNING == R2D_DEBUG_HIGH) + if (src_gc==NULL) + { + rvf_send_trace("src_gc NULL",11, NULL_PARAM, + RV_TRACE_LEVEL_ERROR, r2d_use_id ); + rvf_delay(RVF_SECS_TO_TICKS(1)); + } + + if (dst_gc==NULL) + { + rvf_send_trace("dst_gc NULL",11, NULL_PARAM, + RV_TRACE_LEVEL_ERROR, r2d_use_id ); + rvf_delay(RVF_SECS_TO_TICKS(1));\ + } + + if (org_src_rectangle==NULL) + { + rvf_send_trace("org_src NULL",12, NULL_PARAM, + RV_TRACE_LEVEL_ERROR, r2d_use_id ); + rvf_delay(RVF_SECS_TO_TICKS(1));\ + } + + if (org_dst_rectangle==NULL) + { + rvf_send_trace("org_dst NULL",12, NULL_PARAM, + RV_TRACE_LEVEL_ERROR, r2d_use_id ); + rvf_delay(RVF_SECS_TO_TICKS(1));\ + } +#endif +#endif + + + + src_rectangle=r2d_clone_shape(r2d_mb_id,org_src_rectangle); + if (src_rectangle==NULL) + return(R2D_MEMORY_ERR); + + + dst_rectangle=r2d_clone_shape(r2d_mb_id,org_dst_rectangle); + if (dst_rectangle==NULL) + { + r2d_release_shape(src_rectangle); + return(R2D_MEMORY_ERR); + } + + r2d_disable_refresh(); + + org_bx=((T_R2D_RECT*)src_rectangle)->br_x; + org_by=((T_R2D_RECT*)src_rectangle)->br_y; + org_ux=((T_R2D_RECT*)src_rectangle)->ul_x; + org_uy=((T_R2D_RECT*)src_rectangle)->ul_y; + r2d_local_to_global(src_gc,&org_ux,&org_uy); + r2d_local_to_global(src_gc,&org_bx,&org_by); + if (r2d_clipped_is_not_null(src_gc,dst_gc,src_rectangle,dst_rectangle)) + { + // Rects are now clipped and in global coordinates + +if (src_mirrored) + r2d_mirror_rectangle(src_gc,src_rectangle); + +if (dst_mirrored) + r2d_mirror_rectangle(dst_gc,dst_rectangle); + +// In that case we are drawing text. +// If dst rect clipped by the right side, the src must be shifted to +// the start of the char +// and must not remained aligned with the end of the char +// (don't forget that since char is drawn with mirror its start +// is corresponding to the right and bottom side of the bounding +// rectangle) +// There is the dual problem when the dst rect is clipped by the +// left side + +if ((dst_mirrored) && (!src_mirrored)) +{ + INT16 dbx,dby,dux,duy; + dbx=0; + dux=0; + dby=0; + duy=0; + +#ifdef R2D_MIRRORED_X + dbx=org_bx-((T_R2D_RECT*)src_rectangle)->br_x; + dux=org_ux-((T_R2D_RECT*)src_rectangle)->ul_x; +#endif + +#ifdef R2D_MIRRORED_Y + dby=org_by-((T_R2D_RECT*)src_rectangle)->br_y; + duy=org_uy-((T_R2D_RECT*)src_rectangle)->ul_y; +#endif + + r2d_translate_shape(src_rectangle,dbx,dby); + r2d_translate_shape(src_rectangle,dux,duy); +} + + + + // After mirrong one is in L coordinates + + + if (((T_R2D_FRAMEBUFFER*)((T_R2D_GC*)dst_gc)->p_frame_buffer)->kind==0) + r2d_update_region((T_R2D_GC*)dst_gc,r2d_get_xmin(dst_rectangle), + r2d_get_ymin(dst_rectangle), + r2d_get_xmax(dst_rectangle), + r2d_get_ymax(dst_rectangle)); + +#if (R2D_REFRESH != R2D_VERTICAL) + r2d_diagonal_mirror(src_rectangle); + r2d_diagonal_mirror(dst_rectangle); +#endif + + // After swap one is in S coordinates + + kind_src=((T_R2D_FRAMEBUFFER*)(((T_R2D_GC*)src_gc)->p_frame_buffer))->kind; + kind_dst=((T_R2D_FRAMEBUFFER*)(((T_R2D_GC*)dst_gc)->p_frame_buffer))->kind; + + +#if (R2D_ASM == R2D_OFF) + + if ((kind_src!=R2D_FULL_KIND) && (kind_dst!=R2D_FULL_KIND)) + IND_r2d_blit_lcd_to_lcd(src_gc,dst_gc,src_rectangle,dst_rectangle,use_foreground_color); + else + if ((kind_src==R2D_FULL_KIND) && (kind_dst==R2D_FULL_KIND)) + IND_r2d_blit_color_to_color(src_gc,dst_gc,src_rectangle,dst_rectangle,use_foreground_color); + else + if ((kind_src!=R2D_FULL_KIND) && (kind_dst==R2D_FULL_KIND)) + IND_r2d_blit_lcd_to_color(src_gc,dst_gc,src_rectangle,dst_rectangle,use_foreground_color); + else + if ((kind_src==R2D_FULL_KIND) && (kind_dst!=R2D_FULL_KIND)) + IND_r2d_blit_color_to_lcd(src_gc,dst_gc,src_rectangle,dst_rectangle,use_foreground_color); + +#else + mode=(((T_R2D_GC*)dst_gc))->drawing_mode; + rvf_lock_mutex(r2d_g_blit_mutex); + + if ((kind_src!=R2D_FULL_KIND) && (kind_dst!=R2D_FULL_KIND)) + { + r2d_patch_blit(dst_gc,mode, + use_foreground_color,R2D_LCDLCD); + r2d_blit_asm(src_gc,dst_gc,src_rectangle,dst_rectangle, + use_foreground_color,R2D_LCDLCD); + } + else + if ((kind_src==R2D_FULL_KIND) && (kind_dst==R2D_FULL_KIND)) + { + r2d_patch_blit(dst_gc,mode, + use_foreground_color,R2D_COLORCOLOR); + r2d_blit_asm(src_gc,dst_gc,src_rectangle,dst_rectangle, + use_foreground_color,R2D_COLORCOLOR); + } + else + if ((kind_src!=R2D_FULL_KIND) && (kind_dst==R2D_FULL_KIND)) + { + r2d_patch_blit(dst_gc,mode, + use_foreground_color,R2D_LCDCOLOR); + r2d_blit_asm(src_gc,dst_gc,src_rectangle,dst_rectangle, + use_foreground_color,R2D_LCDCOLOR); + } + else + if ((kind_src==R2D_FULL_KIND) && (kind_dst!=R2D_FULL_KIND)) + { + r2d_patch_blit(dst_gc,mode, + use_foreground_color,R2D_COLORLCD); + r2d_blit_asm(src_gc,dst_gc,src_rectangle,dst_rectangle, + use_foreground_color,R2D_COLORLCD); + } + rvf_unlock_mutex(r2d_g_blit_mutex); + +#endif + + + r2d_check_and_send_event(dst_gc); + } + r2d_release_shape(src_rectangle); + r2d_release_shape(dst_rectangle); + r2d_enable_refresh(); + return(R2D_OK); +} + +T_R2D_ERROR r2d_blit_rect(T_R2D_GC_PTR src_gc,T_R2D_GC_PTR dst_gc, + T_R2D_SHAPE_PTR org_src_rectangle, + T_R2D_SHAPE_PTR org_dst_rectangle, + BOOLEAN use_foreground_color) +{ + // Allow reversing if needed + return(r2d_low_level_blit_rect(src_gc,dst_gc,org_src_rectangle,org_dst_rectangle,TRUE,TRUE,use_foreground_color)); +} + + + +/////////////////////////////////////// +// +// Text functions +// + +T_R2D_CHAR_METRIC_PTR r2d_get_char_metrics(T_R2D_GC_PTR gc,UINT32 the_char) +{ + INT32 *p; + INT32 new_char; + + new_char=r2d_ptree_find(((T_R2D_GC*)gc)->font_table,the_char); + + p=((T_R2D_GC*)gc)->font_metrics; + p+=(new_char<<3); + + *p++; + + return((T_R2D_CHAR_METRIC_PTR)p); +} + +T_R2D_ERROR r2d_draw_char(T_R2D_GC_PTR font_cache_gc, + T_R2D_GC_PTR gc, + T_R2D_GC_PTR fontgc, + INT16 x,INT16 y,INT16 org_size,T_R2D_CHAR_METRIC_PTR met) +{ + + T_R2D_SHAPE_PTR src_rectangle,dst_rectangle,tdst_rectangle; + + + INT32 *p; + INT16 underline; +// INT32 new_char; + INT16 style; + INT16 ascent; + T_R2D_ERROR err; + + style=((T_R2D_GC *)gc)->internal_text_style; + ascent=((T_R2D_GC*)gc)->font_metrics[R2D_BUFFER_WIDTH_POS+1]; + + err=R2D_OK; + + + p=((T_R2D_GC*)gc)->font_metrics; + underline=*--p; + + + + { + + + + if (style & R2D_BOLD) + { +// T_R2D_DRAWING_MODE the_mode; +// T_R2D_ARGB_COLOR bg_color; + +#if (R2D_REFRESH == R2D_VERTICAL) + src_rectangle=r2d_new_rectangle(r2d_mb_id,r2d_get_char_x(met),0, + r2d_get_char_x(met)+r2d_get_char_width(met), + r2d_get_char_height(met)); +#else + // In horizontal mode char are organized vertically + src_rectangle=r2d_new_rectangle(r2d_mb_id,0,r2d_get_char_x(met), + r2d_get_char_width(met),r2d_get_char_x(met)+r2d_get_char_height(met)); +#endif + if (src_rectangle==NULL) + { + err=R2D_MEMORY_ERR; + return(err); + } + //dst_rectangle=r2d_new_rectangle(0,0,char_width+1,char_height); + //if (dst_rectangle==NULL) + //{ + // r2d_release_shape(src_rectangle); + // *err=1; + // return(0); + //} + + // erase temporary char if R2D is starting to draw a new char + // (it is not always the case with diacritics chars) + + //r2d_set_background_color_with_argb(font_cache_gc,0,0,255,0); + r2d_fill_rectangle(font_cache_gc,-1,-1,r2d_get_width(font_cache_gc)+1, + r2d_get_height(font_cache_gc)+1); + //r2d_set_background_color_with_argb(font_cache_gc,0,255,255,255); + + //r2d_release_shape(dst_rectangle); + + // Create destination rectangles + dst_rectangle=r2d_new_rectangle(r2d_mb_id,0,0,r2d_get_char_width(met), + r2d_get_char_height(met)); + if (dst_rectangle==NULL) + { + r2d_release_shape(src_rectangle); + err=R2D_MEMORY_ERR; + return(err); + } + + tdst_rectangle=r2d_clone_shape(r2d_mb_id,dst_rectangle); + if (tdst_rectangle==NULL) + { + r2d_release_shape(src_rectangle); + r2d_release_shape(dst_rectangle); + err=R2D_MEMORY_ERR; + return(err); + } + + r2d_translate_shape(tdst_rectangle,1,0); + + + // set mode + r2d_set_drawing_mode(font_cache_gc,R2D_OR_MODE); + + // Build bold char + + if (r2d_low_level_blit_rect(fontgc,font_cache_gc,src_rectangle,dst_rectangle, + FALSE,FALSE,FALSE)!=R2D_OK) + { + r2d_release_shape(src_rectangle); + r2d_release_shape(dst_rectangle); + r2d_release_shape(tdst_rectangle); + err=R2D_MEMORY_ERR; + return(err); + } + + if (r2d_low_level_blit_rect(fontgc,font_cache_gc,src_rectangle,tdst_rectangle, + FALSE,FALSE,FALSE)!=R2D_OK) + { + r2d_release_shape(src_rectangle); + r2d_release_shape(dst_rectangle); + r2d_release_shape(tdst_rectangle); + err=R2D_MEMORY_ERR; + return(err); + } + + if (style & R2D_STRIKETHROUGH) + { + r2d_moveto(font_cache_gc,0,ascent>>1); + r2d_lineto(font_cache_gc,r2d_get_char_width(met),ascent>>1); + } + + // Reset mode + r2d_set_drawing_mode(font_cache_gc,R2D_COPY_MODE); + + r2d_release_shape(tdst_rectangle); + + r2d_release_shape(dst_rectangle); + r2d_release_shape(src_rectangle); + + // Recreate src and dest rectangle + src_rectangle=r2d_new_rectangle(r2d_mb_id,0,0,r2d_get_char_width(met)+1, + r2d_get_char_height(met)); + if (src_rectangle==NULL) + { + err=R2D_MEMORY_ERR; + return(err); + } + + if (org_size != 0) + { + INT16 tmp; + + tmp=(org_size-r2d_get_char_width(met))>>1; + dst_rectangle=r2d_new_rectangle(r2d_mb_id,x+tmp,y-r2d_get_char_height(met), + x+tmp+r2d_get_char_width(met)+1,y); + } + else + dst_rectangle=r2d_new_rectangle(r2d_mb_id,x+r2d_get_char_org_x(met), + y-r2d_get_char_org_y(met), + x+r2d_get_char_width(met)+r2d_get_char_org_x(met)+1, + y+r2d_get_char_height(met)-r2d_get_char_org_y(met)); + + if (dst_rectangle==NULL) + { + r2d_release_shape(src_rectangle); + err=R2D_MEMORY_ERR; + return(err); + } + //printf("free_pos=%d, char_width=%d\n",free_pos,char_width); + if (r2d_low_level_blit_rect(font_cache_gc,gc,src_rectangle,dst_rectangle, + FALSE,TRUE,TRUE)!=R2D_OK) + { + r2d_release_shape(src_rectangle); + r2d_release_shape(dst_rectangle); + err=R2D_MEMORY_ERR; + return(err); + } + + } + else + { + #if (R2D_REFRESH == R2D_VERTICAL) + src_rectangle=r2d_new_rectangle(r2d_mb_id,r2d_get_char_x(met), + 0, + r2d_get_char_x(met)+r2d_get_char_width(met), + r2d_get_char_height(met)); +#else + // In horizontal mode char are organized vertically + src_rectangle=r2d_new_rectangle(r2d_mb_id,0, + r2d_get_char_x(met), + r2d_get_char_width(met), + r2d_get_char_x(met)+r2d_get_char_height(met)); +#endif + if (src_rectangle==NULL) + { + err=R2D_MEMORY_ERR; + return(err); + } + + if (org_size != 0) + { + INT16 tmp; + + tmp=(org_size-r2d_get_char_width(met))>>1; + dst_rectangle=r2d_new_rectangle(r2d_mb_id,x+tmp, + y-r2d_get_char_height(met), + x+tmp+r2d_get_char_width(met),y); + } + else + dst_rectangle=r2d_new_rectangle(r2d_mb_id, + x+r2d_get_char_org_x(met), + y-r2d_get_char_org_y(met), + x+r2d_get_char_width(met)+r2d_get_char_org_x(met), + y+r2d_get_char_height(met)-r2d_get_char_org_y(met)); + + if (dst_rectangle==NULL) + { + r2d_release_shape(src_rectangle); + err=R2D_MEMORY_ERR; + return(err); + } + + if (style & R2D_STRIKETHROUGH) + { + r2d_fill_rectangle(font_cache_gc,-1,-1,r2d_get_width(font_cache_gc)+1, + r2d_get_height(font_cache_gc)+1); + tdst_rectangle=r2d_new_rectangle(r2d_mb_id,0,0,r2d_get_char_width(met), + r2d_get_char_height(met)); + + if (tdst_rectangle==NULL) + { + r2d_release_shape(src_rectangle); + r2d_release_shape(dst_rectangle); + err=R2D_MEMORY_ERR; + return(err); + } + + err=r2d_low_level_blit_rect(fontgc,font_cache_gc,src_rectangle,tdst_rectangle, + FALSE,FALSE,FALSE); + if (err==R2D_OK) + { + r2d_moveto(font_cache_gc,0,ascent>>1); + r2d_lineto(font_cache_gc,r2d_get_char_width(met),ascent>>1); + err=r2d_low_level_blit_rect(font_cache_gc,gc,tdst_rectangle,dst_rectangle, + FALSE,TRUE,TRUE); + } + + r2d_release_shape(tdst_rectangle); + } + else + { + err=r2d_low_level_blit_rect(fontgc,gc,src_rectangle,dst_rectangle, + FALSE,TRUE,TRUE); + } + + if (err!=R2D_OK) + { + r2d_release_shape(src_rectangle); + r2d_release_shape(dst_rectangle); + err=R2D_MEMORY_ERR; + return(err); + } + + + } + + + + if (style & R2D_UNDERLINED) + { + r2d_moveto(gc,x+r2d_get_char_org_x(met),y+underline); + r2d_lineto(gc,x+r2d_get_char_org_x(met)+ + r2d_get_char_dx(met),y+underline); + } + + r2d_release_shape(src_rectangle); + r2d_release_shape(dst_rectangle); + + + } + return(err); +} + + +#define R2D_ENDIAN_SWAP(a) {misc=(a&0x0FF) << 8;a=a>>8;a=a|misc;a=a&0x0FFFF;} + +UINT32 r2d_get_next_char(T_R2D_UTF16 *the_text,INT16 *pos,UINT16 max_chars, + BOOLEAN *swapping) +{ + T_R2D_UTF16 current; + INT16 temp; + INT32 the_char; + BOOLEAN must_display,combining,done; + T_R2D_UTF16 next, misc; +// T_R2D_CHAR_METRIC_PTR p; + // Swapping should be set to FALSE first time this function is called + + + + + // current char consider a WHOLE char + // (when combining char are used, they are considered + // as making ONE char) + done=FALSE; + + // Detection of byte order mark + if (the_text[*pos] == 0xFFFE) + { + *swapping=TRUE; + *pos=*pos+1; + } + while ((!done) && (the_text[*pos]!=0) && (*pos<max_chars)) + { + must_display=FALSE; + combining=FALSE; + + current=the_text[*pos]; + *pos=*pos+1; + if (*swapping) + R2D_ENDIAN_SWAP(current); + + if ((current != 0x0FFFF)) + { + // If High-surrogate + if ((current >= 0xd800) && (current <= 0xdbff)) + { + // Then check that next char if a low-surrogate + next=the_text[*pos]; + if (*swapping) + R2D_ENDIAN_SWAP(next); + + if ((next >= 0xdc00) && (next<=0xdfff)) + { + *pos=*pos+1; + the_char=(current - 0xd800) * 0x400 + (next - 0xdc00) + 0x10000; + must_display=TRUE; + } + else + { + rvf_send_trace("r2d_get_next_char() missing low surrogate char", + strlen("r2d_get_next_char() missing low surrogate char"), NULL_PARAM, + RV_TRACE_LEVEL_ERROR, R2D_USE_ID ); + } + } + else + { + // If not a high-surrogate then check it is not + // a low-surrogate + if ((current < 0xdc00) || (current>0xdfff)) + { + the_char=current; + must_display=TRUE; + } + else + { + rvf_send_trace("R2D : r2d_get_next_char unexpected low surrogate char", + strlen("R2D : r2d_get_next_char unexpected low surrogate char"), NULL_PARAM, + RV_TRACE_LEVEL_ERROR, R2D_USE_ID ); + } + + } + } + + if ((the_char>=0x300) && (the_char <=0x36f)) + combining=TRUE; + + if (must_display) + { + + if (!combining) + { + // Next char + done=TRUE; + + } + } + + + } + if (done) + return(the_char); + else + return(0); +} +// +static T_R2D_ERROR r2d_low_draw_text(T_R2D_GC_PTR gc,INT16 x,INT16 y, + T_R2D_UTF16 *the_text, + T_R2D_TEXT_DRAWING_SETTINGS settings, + UINT16 max_words, + UINT16 *width, + UINT16 *height) +{ + T_R2D_GC_PTR fontgc; + T_R2D_GC_PTR cache_gc; + BOOLEAN draw; + T_R2D_DRAWING_MODE the_mode; + T_R2D_UTF16 *temp; + INT16 err; + INT16 current_word; + INT32 the_char; + BOOLEAN must_display,swapping,combining; + INT16 delta,deltay,misc,current_y,maxx,delta_line,y_org; + T_R2D_UTF16 next,current; + T_R2D_CHAR_METRIC_PTR p; + + + INT16 x_org; + + + + draw=((settings & R2D_TEXT_DRAW)==R2D_TEXT_DRAW); + + if (the_text==NULL) + return(R2D_MEMORY_ERR); + + x_org=x; + y_org=y; + + maxx=0; + + + + current_word=0; // We are at first word in string + // current word consider a word which may be a partial char + // (when combining char are used, they are considered + // as making ONE char) + swapping=FALSE; + + if (draw) + { + // +1 used since blit_rect is using a bounding rect + cache_gc=r2d_new_font_buffer_context(r2d_mb_id,((T_R2D_GC*)gc)->font_frame_buffer->kind, + ((T_R2D_GC*)gc)->font_metrics[R2D_BUFFER_WIDTH_POS]+1,// max width for free area + ((T_R2D_GC*)gc)->font_metrics[R2D_BUFFER_WIDTH_POS+1]+ // ascent + ((T_R2D_GC*)gc)->font_metrics[R2D_BUFFER_WIDTH_POS+2]+ // descent + ((T_R2D_GC*)gc)->font_metrics[R2D_BUFFER_WIDTH_POS+3]); // leading + + delta_line=((T_R2D_GC*)gc)->font_metrics[R2D_BUFFER_WIDTH_POS+1]+ // ascent + ((T_R2D_GC*)gc)->font_metrics[R2D_BUFFER_WIDTH_POS+2]+ // descent + ((T_R2D_GC*)gc)->font_metrics[R2D_BUFFER_WIDTH_POS+3]; + + + if (cache_gc==NULL) + return(R2D_MEMORY_ERR); + + r2d_context_lock(cache_gc); + + fontgc=r2d_new_context(r2d_mb_id,((T_R2D_GC*)gc)->font_frame_buffer); + //r2d_release_framebuffer(((T_R2D_GC*)gc)->font_frame_buffer); + + + if (fontgc==NULL) + { + r2d_context_unlock(cache_gc); + r2d_release_context(cache_gc); + return(R2D_MEMORY_ERR); + } + + r2d_context_lock(fontgc); + + r2d_set_background_color_with_argb(fontgc,0,255,255,255); + r2d_set_foreground_color_with_argb(fontgc,0,0,0,0); + + the_mode=r2d_get_drawing_mode(gc); + } + + err=R2D_OK; + delta=0; + deltay=0; + current_y=y; + // Detection of byte order mark + if (*the_text == 0xFFFE) + { + swapping=TRUE; + the_text++; + current_word++; + } + while((*the_text!=0) && (err==R2D_OK) && (current_word<max_words)) + { + must_display=FALSE; + combining=FALSE; + if (the_char!=0xa) + x+=delta; + + delta = 0; + + current=*the_text++; + current_word++; + + if (swapping) + R2D_ENDIAN_SWAP(current); + + if ((current != 0x0FFFF)) + { + // If High-surrogate + if ((current >= 0xd800) && (current <= 0xdbff)) + { + // Then check that next char if a low-surrogate + next=*the_text; + if (swapping) + R2D_ENDIAN_SWAP(next); + if ((next >= 0xdc00) && (next<=0xdfff)) + { + the_text++; + current_word++; + the_char=(current - 0xd800) * 0x400 + (next - 0xdc00) + 0x10000; + must_display=TRUE; + } + else + { + rvf_send_trace("r2d_low_draw_text() missing low surrogate char", + strlen("r2d_low_draw_text() missing low surrogate char"), NULL_PARAM, + RV_TRACE_LEVEL_ERROR, R2D_USE_ID ); + } + } + else + { + // If not a high-surrogate then check it is not + // a low-surrogate + if ((current < 0xdc00) || (current>0xdfff)) + { + the_char=current; + must_display=TRUE; + } + else + { + rvf_send_trace("r2d_low_draw_text() unexpected low surrogate char", + strlen("r2d_low_draw_text() unexpected low surrogate char"), NULL_PARAM, + RV_TRACE_LEVEL_ERROR, R2D_USE_ID ); + } + } + } + + if ((the_char>=0x300) && (the_char <=0x36f)) + combining=TRUE; + else + current_y=y; + + if (the_char==0xa) + { + if ((x-x_org)>maxx) + maxx=x-x_org; + + if ((x_org-x)>maxx) + maxx=x_org-x; + x=x_org; + y += delta_line; + + } + + if ((must_display) && (the_char!=0xa)) + { + p=r2d_get_char_metrics(gc,the_char); + if (combining) + { + + if (draw) + { + + current_y -= deltay; + x=x-delta; + + if (((T_R2D_GC*)gc)->script_mode==R2D_LEFT_TO_RIGHT) + err=r2d_draw_char(cache_gc,gc,fontgc,x,current_y,delta,p); + else + err=r2d_draw_char(cache_gc,gc,fontgc,x+delta,current_y,delta,p); + deltay=r2d_get_char_height(p); + } + } + else + { + if (draw) + { + + + if (((T_R2D_GC*)gc)->script_mode==R2D_LEFT_TO_RIGHT) + { + delta=r2d_get_char_dx(p); + err=r2d_draw_char(cache_gc,gc,fontgc,x,current_y,0,p); + + } + else + { + delta=-r2d_get_char_dx(p); + err=r2d_draw_char(cache_gc,gc,fontgc,x+delta,current_y,0,p); + } + deltay=r2d_get_char_height(p); + + } + else + { + + if (((T_R2D_GC*)gc)->script_mode==R2D_LEFT_TO_RIGHT) + delta=r2d_get_char_dx(p); + else + delta=-r2d_get_char_dx(p); + } + } + } + + + } + if (the_char!=0xa) + x+=delta; + + if ((x-x_org)>maxx) + maxx=x-x_org; + + if ((x_org-x)>maxx) + maxx=x_org-x; + + /*if (((T_R2D_GC*)gc)->script_mode==R2D_LEFT_TO_RIGHT) + *result=x-x_org; + else + *result=x_org-x;*/ + + *width=maxx; + *height=y-y_org+delta_line; + + if (draw) + { + r2d_set_drawing_mode(gc,the_mode); + + r2d_context_unlock(fontgc); + r2d_context_unlock(cache_gc); + r2d_release_context(fontgc); + r2d_release_context(cache_gc); + + r2d_check_and_send_event(gc); + } + + return(err); + +} + +T_R2D_ERROR r2d_get_text_width(T_R2D_GC_PTR gc,T_R2D_UTF16 *the_text,UINT16 *size) +{ + UINT16 x,y; + T_R2D_ERROR err; + err=R2D_OK; + + + err=r2d_low_draw_text(gc,0,0,the_text,0,-1,&x,&y); + + if (err!=R2D_OK) + *size=1; + else + { + if (x>=0) + *size=x; + else + *size=-x; + } + + return(err); +} + +T_R2D_ERROR r2d_get_width_of_chars(T_R2D_GC_PTR gc,T_R2D_UTF16 *the_text, + UINT16 nb_chars,UINT16 *size) +{ + UINT16 x,y; + T_R2D_ERROR err; + + err=r2d_low_draw_text(gc,0,0,the_text,0,nb_chars,&x,&y); + + + if (err!=R2D_OK) + *size=1; + else + { + if (x>=0) + *size=x; + else + *size=-x; + } + + return(err); +} + + +T_R2D_ERROR r2d_draw_text(T_R2D_GC_PTR gc,INT16 x,INT16 y,T_R2D_UTF16 *the_text) +{ + UINT16 r,h; + return(r2d_low_draw_text(gc,x,y,the_text,R2D_TEXT_DRAW,-1,&r,&h)); +} + + +T_R2D_ERROR r2d_draw_chars(T_R2D_GC_PTR gc,INT16 x,INT16 y, + T_R2D_UTF16 *the_text,UINT16 nb_chars) +{ + UINT16 r,h; + return(r2d_low_draw_text(gc,x,y,the_text,R2D_TEXT_DRAW,nb_chars,&r,&h)); +} + +T_R2D_ERROR r2d_draw_chars_and_get_size(T_R2D_GC_PTR gc,INT16 x,INT16 y,T_R2D_UTF16 *the_text, + UINT16 nb_words16,UINT16 *width,UINT16 *height) +{ + return(r2d_low_draw_text(gc,x,y,the_text,R2D_TEXT_DRAW,nb_words16,width,height)); +} + +T_R2D_UTF16 *r2d_new_unicode_from_cstring(T_RVF_MB_ID bank,unsigned char *the_string) +{ + T_R2D_UTF16 *result,*p; +// INT16 i; + INT16 index; + + R2D_MALLOC(bank,T_R2D_UTF16,sizeof(T_R2D_UTF16)*(strlen((char*)the_string)+1),result); + if (result!=NULL) + { + p=result; + while(*the_string!='\0') + { + index=*the_string++; + *p++ = R2D_WIN_LATIN1_TO_UNICODE[index]; + } + *p++ = 0; + } + return(result); +} + +T_R2D_UTF16 *r2d_new_unicode_from_pstring(T_RVF_MB_ID bank,unsigned char *the_string) +{ + T_R2D_UTF16 *result,*p; + INT16 l,index; +// INT16 i; + + R2D_MALLOC(bank,T_R2D_UTF16,sizeof(T_R2D_UTF16)*(the_string[0]+1),result); + if (result!=NULL) + { + p=result; + l=*the_string++; + + while(l!=0) + { + index=*the_string++; + *p++ = R2D_WIN_LATIN1_TO_UNICODE[index]; + l--; + } + *p++ = 0; + } + return(result); +} + + +void r2d_get_font_info(T_R2D_GC_PTR gc,INT16 *ascent,INT16 *descent,INT16 *leading) +{ + INT32 *p; + + + p=((T_R2D_GC*)gc)->font_metrics; + + *p--; + *leading=*--p; + *descent=*--p; + *ascent=*--p; + +} + +INT16 r2d_str_nb_word16(T_R2D_UTF16 *l) +{ + INT16 res; + T_R2D_UTF16 *p; + + if (l==NULL) + return 0; + + p=l; + res=0; + + while(*p!=0) + { + p++; + res++; + } + return(res); +} + +T_R2D_UTF16 *r2d_duplicate_text(T_RVF_MB_ID bank,T_R2D_UTF16 *l) +{ + T_R2D_UTF16 *ret; + INT16 len; + + if (l==NULL) + return(NULL); + + len=r2d_str_nb_word16(l); + rvf_get_buf(bank,(len+1)*sizeof(T_R2D_UTF16),(void*)&ret); + if (ret) + { + memcpy(ret,l,(len+1)*2); + return(ret); + } + else return(NULL); +} + + + +T_R2D_SCRIPT_MODE r2d_get_script_mode(T_R2D_GC_PTR gc) +{ + return(((T_R2D_GC*)gc)->script_mode); +} + +void r2d_set_script_mode(T_R2D_GC_PTR gc,T_R2D_SCRIPT_MODE mode) +{ + ((T_R2D_GC*)gc)->script_mode=mode; +}