FreeCalypso > hg > fc-tourmaline
view src/cs/drivers/drv_app/r2d/r2d.c @ 6:b55b47f49638
FC Tourmaline R2D_EMBEDDED_LCD config change
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Fri, 16 Oct 2020 06:49:33 +0000 |
parents | 4e78acac3d88 |
children |
line wrap: on
line source
/** @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; }