From: Andrew R. <ar...@us...> - 2004-05-30 05:00:17
|
Update of /cvsroot/plplot/plplot/src In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv13946/src Modified Files: plfreetype.c Log Message: Changes to the freetype routines to add text buffering support. While adding freetype support to the wingcc driver I discovered that "plRemakePlot()" caches line drawing commands, and things line changes to the pen, but it does not cache text commands (well, it does... sort of... as line drawing primitives). That meant that every time a "plRemakePlot(pls);" was issued, the text would disappear. To QUICKLY compensate for this limitation without major changes to the API, these changes add a text cache to freetype. These changes are really for interactive terminals that may get a "redraw" command, and use plRemakePlot to refresh the display. There is one new "public" function, one function-like macro, a private function, and some changes to the FT structure to accommodate the new cache. The new cache is "activated" if "pls->plbuf_write" is set to one before the freetype engine is initialised. Then, there are only three more things the user has to do: 1) to the "plD_bop_[...]" function, add a call to "pl_FreeTypeBOP();", which resets the text cache for the new page; 2) Add a "pl_RemakeFreeType_text_from_buffer(pls);" command after your "plRemakePlot(pls)" command; and, 3) If there is a "resize" command, update a couple of freetype internals so they know of the new size, i.e. if (FT) { FT->scale=dev->scale; FT->ymax=dev->height; } To have a look at it "working" examine wingcc.c ---------------------------------------------------------------------- Index: plfreetype.c =================================================================== RCS file: /cvsroot/plplot/plplot/src/plfreetype.c,v retrieving revision 1.18 retrieving revision 1.19 diff -u -d -r1.18 -r1.19 --- plfreetype.c 19 May 2004 03:43:24 -0000 1.18 +++ plfreetype.c 30 May 2004 05:00:07 -0000 1.19 @@ -87,6 +87,10 @@ #define NTEXT_ALLOC 1024 +/* Default size of the text cache used with buffering */ + +#define FT_TEXT_CACHESZ 65536 + /* FUNCTION PROTOTYPES */ /* Public prototypes, generally available to the API */ @@ -95,6 +99,7 @@ void plD_render_freetype_text (PLStream *pls, EscText *args); void plD_FreeType_Destroy(PLStream *pls); void pl_set_extended_cmap0(PLStream *pls, int ncol0_width, int ncol0_org); +void pl_RemakeFreeType_text_from_buffer (PLStream *pls); /* Private prototypes for use in this file only */ @@ -103,6 +108,8 @@ static void FT_PlotChar(PLStream *pls,FT_Data *FT, FT_GlyphSlot slot, int x, int y, short colour ); static void FT_SetFace( PLStream *pls, int fnt ); static PLFLT CalculateIncrement( int bg, int fg, int levels); +static void pl_save_FreeType_text_to_buffer (PLStream *pls, EscText *args); + /*----------------------------------------------------------------------*\ * FT_StrX_Y() @@ -482,6 +489,13 @@ if ((FT->textbuf=calloc(NTEXT_ALLOC, 1))==NULL) plexit("Could not allocate memory for Freetype text buffer"); + if (pls->plbuf_write==1) + { + if((FT->text_cache=calloc(1, (size_t) FT_TEXT_CACHESZ))==NULL) + plexit("Could not allocate memory for Freetype text cache"); + FT->mem_allocated=FT_TEXT_CACHESZ; + } + if ( FT_Init_FreeType( &FT->library ) ) plexit("Could not initialise Freetype library"); @@ -637,6 +651,13 @@ PLFLT Sin_A,Cos_A; FT_Vector adjust; +/* + * First of all we will see if we are buffering the output. If we are, + * then we will take this opportunity to save the text to out local + * cached buffer here. + */ + if ((pls->plbuf_write==1)&&(FT->redraw==0)) + pl_save_FreeType_text_to_buffer (pls, args); if (FT->cfont!=pls->cfont) FT_SetFace(pls,pls->cfont); @@ -816,6 +837,12 @@ if (FT) { if (FT->smooth_text==1) plscmap0n(FT->ncol0_org); + if (pls->plbuf_write==1) + { + if (FT->text_cache!=NULL) + free(FT->text_cache); + } + FT_Done_Library(FT->library); free(FT->textbuf); free(pls->FT); @@ -888,6 +915,158 @@ } } +/*--------------------------------------------------------------------------*\ + * void pl_save_FreeType_text_to_buffer (PLStream *pls, EscText *args) + * + * Function to save the text calls to freetype to a local cache which we + * will later use to replay the commands, and therefore plot the text + * (since the plReplot function doesn't cache text as "text" but rather as + * vectors.) We need to save the EscText structure, naturally, as well as + * the string pointed to in that structure, the colour of text from pls, + * and also the size of text from pls. +\*--------------------------------------------------------------------------*/ + +static void pl_save_FreeType_text_to_buffer (PLStream *pls, EscText *args) +{ + FT_Data *FT=(FT_Data *)pls->FT; + unsigned short len=strlen(args->string); + unsigned short total_mem; + int i; + +/* + * Calcualte how much memory this piece of text will take up + * We have to add in the text structure, text colour, the transform matrix, + * the font size, and the text itself + */ + + total_mem=len+sizeof(unsigned short)+sizeof(PLINT)+sizeof(EscText)+(4*sizeof(PLFLT))+1; + + i=FT->mem_pointer; + + /* + * Next we check to see if the cache has enough memory in it for the text + * it was just asked to draw - if it doesn't we will try to realloc some + * more memory to it. Assuming we get this extra memory, we will keep it + * until the program terminates. + */ + + while ((FT->mem_pointer+total_mem)>FT->mem_allocated) + { + if ((FT->text_cache=(realloc(FT->text_cache,(size_t) (FT_TEXT_CACHESZ+FT->mem_allocated)))==NULL)) + { + plexit("Could not allocate extra memory to Freetype text cache"); + } + FT->mem_allocated+=FT_TEXT_CACHESZ; + } + + /* + * Now we will start copying the stuff we want to keep to our cache + * This isn't the most efficient way of doing stuff in terms of speed, + * for example, if we really wanted this to be fast we would keep things + * on 32 bit boundaries, but it's good enough for our purposes. + * We basically have a pair system of a memcpy command to copy the stuff + * to the cache, then advance the pointer for the next write. + */ + + memcpy(&FT->text_cache[i],&len,sizeof(unsigned short)); /* Length of the text string we are printing */ + i+=sizeof(unsigned short); + + memcpy(&FT->text_cache[i],&pls->icol0,sizeof(PLINT)); /* Text colour */ + i+=sizeof(PLINT); + + memcpy(&FT->text_cache[i],&pls->chrht,sizeof(PLFLT)); /* Text size */ + i+=sizeof(PLFLT); + + memcpy(&FT->text_cache[i],&FT->scale,sizeof(PLFLT)); /* scale */ + i+=sizeof(PLFLT); + + memcpy(&FT->text_cache[i],args,sizeof(EscText)); + i+=sizeof(EscText); + + memcpy(&FT->text_cache[i],args->xform,(4*sizeof(PLFLT))); + i+=(4*sizeof(PLFLT)); + + memcpy(&FT->text_cache[i],args->string,len+1); /* Add the "len+1" at the end to get the terminating NULL */ + i+=(len+1); + + FT->mem_pointer=i; /* Advance the memory pointer */ + FT->num_strings++; +} + + +/*--------------------------------------------------------------------------*\ + * void pl_RemakeFreeType_text_from_buffer (PLStream *pls) + * + * The function replays the contents of our "local" plot text buffer to the + * freetype engine, therefore replaying the text drawing commands. +\*--------------------------------------------------------------------------*/ + +void pl_RemakeFreeType_text_from_buffer (PLStream *pls) +{ + FT_Data *FT=(FT_Data *)pls->FT; + unsigned short len; + PLINT colour, last_colour; + PLFLT chrht, last_chrht,scale; + int i,j; + EscText text; + + if ((pls->plbuf_write==1)&&(pls->dev_text==1)&&(FT->num_strings>0)) + { + + /* + * Save the current colours and font size so we can restore stuff later. Should not + * be needed since this function should ONLY be getting called at the END of pages, + * when all plotting is done, and since the BOP functions should be setting these + * up anyway before the start of each page... BUT best done just in case. + */ + + last_colour=pls->icol0; + last_chrht=pls->chrht; + + for (i=j=0;j<FT->num_strings;j++) + { + memcpy(&len,&FT->text_cache[i],sizeof(unsigned short)); /* Length of the text string we are printing */ + i+=sizeof(unsigned short); + + memcpy(&colour,&FT->text_cache[i],sizeof(PLINT)); /* Text writing colour */ + i+=sizeof(PLINT); + pls->icol0=colour; + + memcpy(&chrht,&FT->text_cache[i],sizeof(PLFLT)); /* Text size */ + i+=sizeof(PLFLT); + + memcpy(&scale,&FT->text_cache[i],sizeof(PLFLT)); /* driver scale */ + i+=sizeof(PLFLT); + + memcpy(&text,&FT->text_cache[i],sizeof(EscText)); + i+=sizeof(EscText); + + text.xform=(PLFLT *)&FT->text_cache[i]; /* We just point back to our buffer :-) */ + i+=(4*sizeof(PLFLT)); + + text.string=&FT->text_cache[i]; /* Again, we just point to the copy in our buffer */ + i+=(len+1); + + pls->chrht=chrht*scale/FT->scale; + + /* + * Since we are calling plD_render_freetype_text here, we need + * to set a special "redraw" flag to make sure we don't get + * recursion, since "plD_render_freetype_text" also ADDs text + * to the text buffer. + */ + + FT->redraw=1; + plD_render_freetype_text(pls, &text); + FT->redraw=0; + } + pls->icol0=last_colour; /* Reset the colour */ + pls->chrht=last_chrht; /* reset the font size */ + + } +} + + #else int plfreetype() |