opctool.temp.h File Reference

Tool related OPC function generator Generates things purely useful for tooling up code to make OPC/OPCShape data. More...

#include "opctool.h"

Include dependency graph for opctool.temp.h:

Go to the source code of this file.

Functions

void OPC_NAMING() ShrinkBound (OPC *dst, const OPC *src, OPC_NAMING(Pixel) transparent)
 Find the non-transparent edges of a shape Copies src to dst, then moves clipping bounds of dst down until they all hit something non-transparent.
size_t OPC_NAMING() Shape_Calc (const OPC *src, OPC_NAMING(Pixel) transparent, bool bMask)
 Calculate how big a buffer would be required to define a new shape This will usually calculate a little bigger, because it doesn't bother working out how to eliminate excess skips.
OPCShape *OPC_NAMING() Shape_Create (const OPC *src, OPC_NAMING(Pixel) transparent, void *buffer, bool bMask)
 Define a new transparent shape Not super optimized, more a tool library or initialization function Origin is set to clipping box's origin, so make an OPC_Window, then find the edges, then pass that in.
size_t OPC_NAMING() Shape_Pack_Needs (OPCShape *shape)
 Do something like LZ+RLE on non-transparent parts of a shape.
size_t OPC_NAMING() Shape_Pack (OPCShape *shape, void *buffer)
 Do something like LZ on non-transparent, non-RUN parts of a shape.
void OPC_NAMING() ExportH (const OPC *opc, FILE *fp, const char *szname)
 Export a header definition for OPC data.
void OPC_NAMING() ExportC (const OPC *opc, FILE *fp, const char *modifier, const char *szname, const char *szComment,...)
 Export the OPC structure portion of OPC data.
void OPC_NAMING() ExportCData (const OPC *opc, FILE *fp, const char *szname)
 Export the OPCShape pixel image data.
void OPC_NAMING() Shape_ExportH (const OPCShape *shape, FILE *fp, const char *szname, bool bMask)
 Export a header definition for OPCShape data.
void OPC_NAMING() Shape_ExportC (const OPCShape *shape, FILE *fp, const char *modifier, const char *szname, bool bMask, const char *szComment,...)
 Export the OPCShape structure portion of OPC data.
void OPC_NAMING() Shape_ExportCData (const OPCShape *shape, FILE *fp, const char *szname, bool bMask)
 Export the OPCShape pixel image data.


Detailed Description

Tool related OPC function generator Generates things purely useful for tooling up code to make OPC/OPCShape data.

Author:
David Mace

Definition in file opctool.temp.h.


Function Documentation

void OPC_NAMING() ExportC ( const OPC opc,
FILE *  fp,
const char *  modifier,
const char *  szname,
const char *  szComment,
  ... 
)

Export the OPC structure portion of OPC data.

Parameters:
opc Solid buffer we're weiting
fp FILE* open to write to a header file
modifier Definition modifier (such as 'static' or __declspec(dllexport)), or just ""
szname What to call this particular export
szComment An optional comment for the export, or NULL if you don't want it Writes OPC with forward references to static data

Definition at line 538 of file opctool.temp.h.

00539 {
00540     if( szComment )
00541     {
00542         va_list args;
00543         va_start( args, szComment );     /* Initialize variable arguments. */
00544         fputs( "\n/*\n * ", fp );
00545         vfprintf( fp, szComment, args );
00546         fputs( "\n */\n", fp );
00547     }
00548     fprintf( fp, "static const OPC_NAMING(Pixel) data_%s[];\n", szname );
00549     if( modifier && *modifier )
00550         fprintf( fp, "%s ", modifier );
00551     fprintf( fp, "const OPC %s = /* Stamp */\n{\n", szname );
00552     fprintf( fp, "\t(uint8*)data_%s,\t/* origin */\n", szname );
00553     fprintf( fp, "\t%d,\t/* pitch */\n", abs(opc->pitch) );
00554     fprintf( fp, "\t{%d,%d,%d,%d}\t/* clip */\n", opc->clip.left, opc->clip.top, opc->clip.right, opc->clip.bottom );
00555     fputs( "};\n", fp );
00556 }

void OPC_NAMING() ExportCData ( const OPC opc,
FILE *  fp,
const char *  szname 
)

Export the OPCShape pixel image data.

Parameters:
opc Solid buffer we're weiting
fp FILE* open to write to a header file
szname What to call this particular export Writes the static data, tries to write it same shape as opc, but gives up past a certain point.

Definition at line 572 of file opctool.temp.h.

References RectHigh, RectWide, throwassert, and wrap.

00573 {
00574 #ifndef GIVEUP_AFTER
00575 #define GIVEUP_AFTER    15
00576 #endif
00577     size_t curr;
00578     const OPC_NAMING(Pixel)* pData = (const OPC_NAMING(Pixel)*)opc->origin;
00579     size_t size = OPC_NAMING(Needs)( RectWide(opc->clip), RectHigh(opc->clip) );
00580     unsigned wrap = min( RectWide(opc->clip), GIVEUP_AFTER );
00581     fprintf( fp, "static const OPC_NAMING(Pixel) data_%s[%d] = \n{\n\t", szname, size );
00582 #ifdef PIXEL_OUTPUT
00583     for( curr = 0; curr < size; ++curr )
00584     {
00585         PIXEL_OUTPUT( fp, *pData++ );
00586         if( (curr % wrap) == wrap - 1 )
00587             fputs( "\n\t", fp );
00588     }
00589 #else
00590     switch(sizeof(OPC_NAMING(Pixel)))
00591     {
00592     case 1:
00593         for( curr = 0; curr < size; ++curr )
00594         {
00595             fprintf( fp, "%3d,", (unsigned)*pData++ );
00596             if( (curr % wrap) == wrap - 1 )
00597                 fputs( "\n\t", fp );
00598         }
00599         break;
00600     case 2:
00601         for( curr = 0; curr < size; ++curr )
00602         {
00603             fprintf( fp, "0x%04x,", (unsigned)*pData++ );
00604             if( (curr % wrap) == wrap - 1 )
00605                 fputs( "\n\t", fp );
00606         }
00607         break;
00608     case 4:
00609         for( curr = 0; curr < size; ++curr )
00610         {
00611             fprintf( fp, "0x%08x,", (unsigned)*pData++ );
00612             if( (curr % wrap) == wrap - 1 )
00613                 fputs( "\n\t", fp );
00614         }
00615         break;
00616     case 8:
00617         for( curr = 0; curr < size; ++curr )
00618         {
00619             fprintf( fp, "0x%" LLX(char) ",", (uint64)*pData++ );
00620             if( (curr % wrap) == wrap - 1 )
00621                 fputs( "\n\t", fp );
00622         }
00623         break;
00624     default:
00625         throwassert( "Invalid pixel size." );
00626         break;
00627     }
00628     fputs( "\n};\n", fp );
00629 #endif
00630 }

void OPC_NAMING() ExportH ( const OPC opc,
FILE *  fp,
const char *  szname 
)

Export a header definition for OPC data.

Parameters:
opc Solid buffer we're weiting
fp FILE* open to write to a header file
szname What to call this particular export

Definition at line 521 of file opctool.temp.h.

References RectHigh, and RectWide.

00522 {
00523     fprintf( fp, "#define %s_BOUND(x,y)\t{(x),(y),(x)+%d,(y)+%d}\n", szname, RectWide(opc->clip), RectHigh(opc->clip) );
00524     fprintf( fp, "#define %s_WIDE\t%d\n", szname, RectWide(opc->clip) );
00525     fprintf( fp, "#define %s_HIGh\t%d\n", szname, RectHigh(opc->clip) );
00526     fprintf( fp, "extern const OPC %s; /* Stamp */\n", szname );
00527 }

size_t OPC_NAMING() Shape_Calc ( const OPC src,
OPC_NAMING(Pixel)  transparent,
bool  bMask 
)

Calculate how big a buffer would be required to define a new shape This will usually calculate a little bigger, because it doesn't bother working out how to eliminate excess skips.

Parameters:
src OPC containing shape to be defined
transparent Color to consider 'invisible'
bMask True if we're making a mask, rather than a textured shape

Definition at line 117 of file opctool.temp.h.

References Rect::bottom, Rect::left, Rect::right, and Rect::top.

00118 {
00119     size_t dataLen = 0;
00120     size_t codeLen = 0;
00121     int x, y;
00122     for( y = src->clip.top; y < src->clip.bottom; ++y )
00123     {
00124         for( x = src->clip.left; x < src->clip.right; )
00125         {
00126             {
00127                 const OPC_NAMING(Pixel)* line = OPC_PTR( src, x,y );
00128                 int skip = 0;
00129                 for( ; x < src->clip.right && skip < MAX_SKIP && *line++ == transparent; x++ )
00130                     skip++;
00131                 if( skip )
00132                 {
00133                     codeLen++;
00134                 }
00135             }
00136             {
00137                 const OPC_NAMING(Pixel)* line = OPC_PTR( src, x,y );
00138                 int run = 0;
00139                 for( ; x < src->clip.right && run < MAX_DUMP && *line++ != transparent; x++ )
00140                     run++;
00141                 if( run )
00142                 {
00143                     codeLen++;
00144                     if( !bMask )
00145                         dataLen+=run;
00146                 }
00147             }
00148         }
00149         codeLen++;
00150     }
00151     codeLen++;
00152     return sizeof(OPCShape) + (codeLen+sizeof(int)) + (dataLen * sizeof(OPC_NAMING(Pixel)));
00153 }

OPCShape* OPC_NAMING() Shape_Create ( const OPC src,
OPC_NAMING(Pixel)  transparent,
void *  buffer,
bool  bMask 
)

Define a new transparent shape Not super optimized, more a tool library or initialization function Origin is set to clipping box's origin, so make an OPC_Window, then find the edges, then pass that in.

Parameters:
src OPC containing shape to be defined
transparent Color to consider 'invisible'
buffer A buffer of at least OPC_CalcShape(src,transparent) bytes to convert into
bMask True if we're making a mask, rather than a textured shape
Returns:
The new shape (pointer is equal to buffer)
OPC Data is basically an 8-bit skip compressed mask which references templated pixel data.

Codes (signed char code array): -1~-127 Skip -128: End line 0: End shape 1~MAX_DUMP: Copy MAX_DUMP~127: Fill If 'code' is not NULL, and first 'code' is 0, data is packed somehow

The pixel data can be either just dumped, or further compressed.

The compression to apply has a LOT to do with the target format and speed of target system. For instance, a PC will handle full-blown LZH compression, but many embedded CPUs will not. RLE might do very nicely on data with lots of solid runs, and a target with little or no horsepower to use on decompressing data. Data alignment also figures into the problem since data on 32 bit boundaries will consume 32 bits for a code, even if the code is 8-bits.

Definition at line 188 of file opctool.temp.h.

References Rect::bottom, OPC::clip, OPCShape::code, OPCShape::data, OPCShape::high, Rect::left, OPCShape::pack, OPC::pitch, RectHigh, RectWide, Rect::right, ShrinkBound(), Rect::top, OPCShape::wide, OPCShape::xOff, and OPCShape::yOff.

00189 {
00190     OPC bound;
00191     OPCShape* shape = (OPCShape*)buffer;
00192     int8* pCode = (int8*)(shape+1);
00193     int x, y;
00194     OPC_NAMING(ShrinkBound)( &bound, src, transparent );
00195 #ifdef OPC_POINTERS
00196     shape->code = pCode;
00197     shape->data = NULL;
00198     shape->pack = NULL;
00199 #else
00200     shape->code = pCode-(int8*)shape;
00201     shape->data = 0;
00202     shape->pack = 0;
00203 #endif
00204     shape->wide = (uint16)RectWide(bound.clip);
00205     shape->high = (uint16)RectHigh(bound.clip);
00206     shape->xOff = (int16)bound.clip.left;
00207     shape->yOff = (int16)bound.clip.top;
00208     for( y = bound.clip.top; y < bound.clip.bottom; ++y )
00209     {
00210         for( x = bound.clip.left; x < bound.clip.right; )
00211         {
00212             {
00213                 /* Skip transparent */
00214                 const OPC_NAMING(Pixel)* line = OPC_PTR( src, x,y );
00215                 int skip = 0;
00216                 for( x = x; x < bound.clip.right && skip < MAX_SKIP && *line == transparent; x++, skip++, line++ )
00217                     ;
00218                 if( skip )
00219                 {
00220                     *pCode++ = SKIP_CODE(skip);
00221                     continue;
00222                 }
00223             }
00224             {
00225                 /* Now do RLE on non-transparent pixels */
00226                 const OPC_NAMING(Pixel)* line = OPC_PTR( src, x,y );
00227                 int dump = 0;
00228                 for( x = x; x < bound.clip.right && dump < MAX_DUMP && *line != transparent; x++, dump++, line++ ) /* Small optimization for 8/16 bit data on large, solid shapes */
00229                 if( !bMask ) /* If we're building a mask, we don't need to break lines down */
00230                 {
00231                     /* Look for runs of color in dump */
00232                     PIXEL prun = *line;
00233                     const PIXEL* scanLine = line+1;
00234                     int run = 1;
00235                     int tmpx;
00236                     for( tmpx = x+1; tmpx < bound.clip.right && run < MAX_RUN && *scanLine == prun && *scanLine != transparent; tmpx++, run++, scanLine++ )
00237                         ;
00238                     if( run >= MIN_RUN ) /* We want more than mere crumbs of run */
00239                     {
00240                         /* Output dump code */
00241                         if( dump )
00242                         {
00243                             *pCode++ = DUMP_CODE(dump);
00244                             dump = 0;
00245                         }
00246                         /* Output run length */
00247                         *pCode++ = RUN_CODE(run);
00248                         x = tmpx;
00249                         break;
00250                     }
00251                 }
00252                 if( dump )
00253                 {
00254                     *pCode++ = DUMP_CODE(dump);
00255                 }
00256             }
00257         }
00258         /* Consume any trailing skips (a wide shape might contain two or more skips on the trailing edge of the line) */
00259         if( *(pCode-1) < 0 && *(pCode-1) != -128 && pCode > (int8*)(shape+1) )
00260             *--pCode = -128;
00261         *pCode++ = -128;
00262     }
00263     /* Terminate, removing all trailing skips */
00264     while( *(pCode-1) < 0 && pCode > (int8*)(shape+1) )
00265         --pCode;
00266     *pCode++ = 0;
00267     /* Clear extra bytes & align 'pointer' */
00268     while( (size_t)pCode & 3 )
00269         *pCode++ = 0;
00270     if( bMask )
00271     {
00272         shape->data = 0;
00273     }
00274     else
00275     {
00276     /* Get pixel data onto integer boundary */
00277 #ifdef OPC_POINTERS
00278         shape->data = pCode;
00279 #else
00280         shape->data = pCode-(int8*)shape;
00281 #endif
00282         {
00283             /*
00284              * Now that we know how big the code is, we can copy the data onto the 
00285              * end of it. Use the rle code we generated to determine what to copy
00286              */
00287 #ifdef OPC_POINTERS
00288             const int8* pCode = shape->code;
00289             OPC_NAMING(Pixel)* pData = (OPC_NAMING(Pixel)*)shape->data;
00290 #else
00291             const int8* pCode = (int8*)shape + shape->code;
00292             OPC_NAMING(Pixel)* pData = (OPC_NAMING(Pixel)*)((uint8*)shape + shape->data);
00293 #endif
00294             const OPC_NAMING(Pixel)* pSrc = OPC_PTR( src, bound.clip.left,bound.clip.top );
00295             const OPC_NAMING(Pixel)* pSpan = pSrc;
00296             size_t wrote = 0;
00297             for( ; ; )
00298             {
00299                 int curr = *pCode++;
00300                 if( IS_SKIP(curr) )
00301                 {
00302                     if( IS_EOL(curr) )
00303                         pSpan = pSrc = (OPC_NAMING(Pixel)*)((uint8*)pSrc + bound.pitch);
00304                     else
00305                         pSpan += SKIP_LEN(curr);
00306                 }
00307                 else if( IS_RUNDUMP(curr) )
00308                 {
00309                     if( IS_RUN(curr) )
00310                     {
00311                         OPC_HCOPY(pData,pSpan,1);
00312                         pSpan += RUN_LEN(curr);
00313                         pData += 1;
00314                         wrote += sizeof(OPC_NAMING(Pixel));
00315                     }
00316                     else /* if( IS_DUMP(curr) ) */
00317                     {
00318                         OPC_HCOPY(pData,pSpan,curr);
00319                         pSpan += DUMP_LEN(curr);
00320                         pData += DUMP_LEN(curr);
00321                         wrote += DUMP_LEN(curr) * sizeof(OPC_NAMING(Pixel));
00322                     }
00323                 }
00324                 else
00325                 {
00326                     break;
00327                 }
00328             }
00329             if( !wrote )
00330                 shape->data = 0;
00331         }
00332         /* Now we know how big the whole thing is. */
00333         /*shape->size = (uint8*)pData - (uint8*)shape;*/
00334     }
00335     return shape;
00336 }

Here is the call graph for this function:

void OPC_NAMING() Shape_ExportC ( const OPCShape shape,
FILE *  fp,
const char *  modifier,
const char *  szname,
bool  bMask,
const char *  szComment,
  ... 
)

Export the OPCShape structure portion of OPC data.

Parameters:
opc Solid buffer we're weiting
fp FILE* open to write to a header file
modifier Definition modifier (such as 'static' or __declspec(dllexport)), or just ""
szname What to call this particular export
bMask If true, PIXEL data is exclued; just the OPCShape and runs
szComment An optional comment for the export, or NULL if you don't want it Writes OPCShape structure with forward references to static data

Definition at line 657 of file opctool.temp.h.

00658 {
00659     if( szComment )
00660     {
00661         va_list args;
00662         va_start( args, szComment );     /* Initialize variable arguments. */
00663         fputs( "\n/*\n * ", fp );
00664         vfprintf( fp, szComment, args );
00665         fputs( "\n */\n", fp );
00666     }
00667     fprintf( fp, "static const int8 code_%s[%u];\n", szname, OPC_NAMING(Shape_CodeSize)( shape ) );
00668     if( !bMask && shape->data )
00669         fprintf( fp, "static const OPC_NAMING(Pixel) data_%s[%u];\n", szname, OPC_NAMING(Shape_DataSize)( shape ) );
00670     if( !bMask && shape->pack )
00671         fprintf( fp, "static const opc_pack_type pack_%s[%u];\n", szname, OPC_NAMING(Shape_PackLutSize)( shape ) );
00672     if( modifier && *modifier )
00673         fprintf( fp, "%s ", modifier );
00674     fprintf( fp, "const OPCShape %s =\n", szname );
00675     fputs( "{\n", fp );
00676     fprintf( fp, "\t%3d,\t/* xOff */\n", shape->xOff );
00677     fprintf( fp, "\t%3d,\t/* yOff */\n", shape->yOff );
00678     fprintf( fp, "\t%3u,\t/* wide */\n", shape->wide );
00679     fprintf( fp, "\t%3u,\t/* high */\n", shape->high );
00680     fprintf( fp, "\tcode_%s,\t/* code */\n", szname );
00681     if( bMask || !shape->data )
00682         fprintf( fp, "\tNULL,\t/* no data */\n" );
00683     else
00684         fprintf( fp, "\tdata_%s,\t/* data */\n", szname );
00685     if( bMask || !shape->pack )
00686         fprintf( fp, "\tNULL,\t/* no pack */\n" );
00687     else
00688         fprintf( fp, "\tpack_%s,\t/* packed */\n", szname );
00689     fputs( "};\n", fp );
00690 }

void OPC_NAMING() Shape_ExportCData ( const OPCShape shape,
FILE *  fp,
const char *  szname,
bool  bMask 
)

Export the OPCShape pixel image data.

Parameters:
opc Solid buffer we're weiting
fp FILE* open to write to a header file
szname What to call this particular export Writes the static data, tries to write it same shape as opc
bMask If true, PIXEL data is exclued; just the OPCShape and runs

Definition at line 700 of file opctool.temp.h.

References throwassert.

00701 {
00702     size_t cCode = OPC_NAMING(Shape_CodeSize)( shape );
00703     size_t curr;
00704 #ifdef OPC_POINTERS
00705     const int8* pCode = shape->code;
00706 #else
00707     const int8* pCode = (int8*)shape + shape->code;
00708 #endif
00709     /* Lay out codes intelligibly */
00710     fprintf( fp, "static const int8 code_%s[%u] = \n{\n\t", szname, cCode );
00711     for( curr = 0; curr < cCode; ++curr )
00712     {
00713         int code = *pCode++;
00714         if( code == -128 )
00715         {
00716             fputs( "-128,\n\t", fp );
00717         }
00718         else
00719         {
00720             fprintf( fp, "%d, ", code );
00721         }
00722     }
00723     fputs( "\n};\n", fp );
00724     if( !bMask && shape->pack )
00725     {
00726         size_t cData = OPC_NAMING(Shape_PackLutSize)( shape );
00727         size_t cols = 0;
00728 #ifdef OPC_POINTERS
00729         const uint8* plut = (const opc_pack_type*)shape->pack;
00730 #else
00731         const uint8* plut = (const opc_pack_type*)shape + shape->pack;
00732 #endif
00733         /* Align data so a few more 32 bit DMA's can happen on 8/16 bit art */
00734         fprintf( fp, "static const OPC_NAMING(Pixel) pack_%s[%u] __attribute__((aligned)) = \n{\n\t", szname, cData );
00735         while( cData-- )
00736         {
00737             fprintf( fp, "%d,", (unsigned)*plut++ );
00738             ++cols;
00739             if( 0 == (cols & 0xf) )
00740             {
00741                 fputs( "\n\t", fp );
00742                 cols = 0;
00743             }
00744         }
00745         fputs( "\n};\n", fp );
00746     }
00747     if( !bMask && shape->data )
00748     {
00749         /* Draw shapes recognizably */
00750         size_t cData = OPC_NAMING(Shape_DataSize)( shape );
00751         size_t cols = 0;
00752 #ifdef OPC_POINTERS
00753         const uint8* pData = (const uint8*)shape->data;
00754 #else
00755         const uint8* pData = (const uint8*)shape + shape->data;
00756 #endif
00757         /* Align data so a few more 32 bit DMA's can happen on 8/16 bit art */
00758         fprintf( fp, "static const OPC_NAMING(Pixel) data_%s[%u] __attribute__((aligned)) = \n{\n\t", szname, cData );
00759         while( cData-- )
00760         {
00761 #ifdef PIXEL_OUTPUT
00762             PIXEL_OUTPUT( fp, *pData++ );
00763 #else
00764             switch(sizeof(OPC_NAMING(Pixel)))
00765             {
00766             case 1:
00767                 fprintf( fp, "0x%02x,", (unsigned)*pData++ );
00768                 break;
00769             case 2:
00770                 fprintf( fp, "0x%04x,", (unsigned)*pData++ );
00771                 break;
00772             case 4:
00773                 fprintf( fp, "0x%08x,", (unsigned)*pData++ );
00774                 break;
00775             case 8:
00776                 fprintf( fp, "0x%" LLX(char) ",", (uint64)*pData++ );
00777                 break;
00778             default:
00779                 throwassert( "Invalid pixel size." );
00780                 break;
00781             }
00782 #endif
00783             ++cols;
00784             if( 0 == (cols & 0xf) )
00785             {
00786                 fputs( "\n\t", fp );
00787                 cols = 0;
00788             }
00789             else if( 0 == (cols & 7) )
00790             {
00791                 fputs( " ", fp );
00792             }
00793         }
00794         fputs( "\n};\n", fp );
00795     }
00796 }

void OPC_NAMING() Shape_ExportH ( const OPCShape shape,
FILE *  fp,
const char *  szname,
bool  bMask 
)

Export a header definition for OPCShape data.

Parameters:
opc Solid buffer we're weiting
fp FILE* open to write to a header file
szname What to call this particular export
bMask If true, PIXEL data is exclued; just the OPCShape and runs

Definition at line 639 of file opctool.temp.h.

00640 {
00641     fprintf( fp, "#define %s_BOUND(x,y)\t{ (x)+%d, (y)+%d, (x)+%d+%d, (y)+%d+%d }\n", szname, shape->xOff, shape->yOff, shape->xOff, shape->xOff+shape->wide, shape->yOff, shape->yOff + shape->high );
00642     fprintf( fp, "#define %s_WIDE\t%d\n", szname, shape->wide );
00643     fprintf( fp, "#define %s_HIGH\t%d\n", szname, shape->high );
00644     fprintf( fp, "extern const OPCShape %s;\n", szname );
00645 }

size_t OPC_NAMING() Shape_Pack ( OPCShape shape,
void *  buffer 
)

Do something like LZ on non-transparent, non-RUN parts of a shape.

Parameters:
shape Shape to attempt compression on
buffer Scratch buffer, needs at least 'OPC_NAMING(Shape_Pack_Needs)(shape)' bytes
Returns:
Size of data; may be same as original (no savings), should be less in many cases
A compressed shape is identified by having the first skip code '0', which is normally the shape terminator. If it is '0', then we look for a compression header at the start of data, and parse from there.

All in all, this doesn't try very hard to find runs. It only searches for matches the same size as the RLE dumps that are passed in. Otherwise, clipping could get really ugly and time-consuming. The idea here is to have some compression, but not make it really cost us anything substantial in runtime cycles, possibly saving some runtime cycles on cache hits. It's also important to me to keep the RLE compression seperate from this packing, so 'better' and more time- consuming packing can be added for faster target platforms without melting down the whole skip compressed format.

TODO: I need to rethink this kludged format a bit; the source code output is endian-dependant; tool and code must match for source to work. It's that uint16 LUT.

Definition at line 373 of file opctool.temp.h.

References assert.

00374 {
00375 #ifdef OPC_POINTERS
00376     int8* pCode = shape->code;
00377     OPC_NAMING(Pixel)* pData = (OPC_NAMING(Pixel)*)shape->data;
00378 #else
00379     int8* pCode = (int8*)shape + shape->code;
00380     OPC_NAMING(Pixel)* pData = (OPC_NAMING(Pixel)*)((uint8*)shape + shape->data);
00381 #endif
00382     if( pData && !shape->pack )
00383     {
00384         /*
00385          * Go through the shape run-by-run, and see if any runs can be 
00386          * made from earlier data, or if runs are just a solid fill-color.
00387          *
00388          * Unsigned 16 bit window
00389          * >0: Lookup pixels from earlier spans (length from 'pCode')
00390          * 0: Start from current position
00391          *
00392          * Special case: a run may be added to from '-code' that is 
00393          * shorter than 'span', if the additional bytes are added after 
00394          * it.  For instance, a previous span ended '...21234', and the 
00395          * current one is '23456...,' the '234' can be used for the 
00396          * current span, only adding '56...' on the end.  This will help 
00397          * with some pattern fills that might not have compressed at all.
00398          *
00399          */
00400         opc_pack_type* pIndexBegin = (opc_pack_type*)(buffer);
00401         opc_pack_type* pIndexEnd = pIndexBegin;
00402         opc_pack_type* pIndexes = pIndexBegin;
00403         const int8* pCodeEnd, *pCodeBegin;
00404         int indexCount = 0;
00405         OPC_NAMING(Pixel)* pixBegin, *pixCurr;
00406         OPC_NAMING(Pixel)* pixEnd = (uint8*)buffer + OPC_NAMING(Shape_DataSize)( shape );
00407         {
00408             pCodeBegin = pCodeEnd = pCode;
00409             while( *pCodeEnd )
00410             {
00411                 int code = *pCodeEnd++;
00412                 if( IS_DUMP(code) )
00413                     indexCount++;
00414             }
00415             pIndexEnd = pIndexBegin + indexCount;
00416             while( (size_t)pIndexEnd & 3 )
00417             {
00418                 pIndexEnd++;
00419             }
00420             pixBegin = pixCurr = (OPC_NAMING(Pixel)*)pIndexEnd;
00421         }
00422         while( pixCurr < pixEnd )
00423         {
00424             int code = *pCode++;
00425             if( IS_RUN(code) )
00426             {
00427                 /*
00428                  * Runs of color are transferred without an index lookup
00429                  */
00430                 /* Don't smash RAM */
00431                 if( pixCurr + 1 > pixEnd )
00432                     break;
00433                 *pixCurr++ = *pData++;
00434             }
00435             else if( IS_DUMP(code) )
00436             {
00437                 assert( pCode <= pCodeEnd );
00438                 assert( pIndexes < (opc_pack_type*)pixBegin );
00439                 /* See if some of new run can be re-used from previous run */
00440                 {
00441                     int best = 0;
00442                     int bestLen = 0;
00443                     int index = 0;
00444                     const OPC_NAMING(Pixel)* scan = pixCurr;
00445                     while( scan-- > pixBegin && ++index < opc_pack_max )
00446                     {
00447                         size_t scanLen = min(pixCurr-scan,code);
00448                         if( !memcmp(scan,pData,sizeof(OPC_NAMING(Pixel))*scanLen) )
00449                         {
00450                             best = index;
00451                             bestLen = scanLen;
00452                             /* If we found a match equal to full code size, mission accomplished */
00453                             if( bestLen == code )
00454                                 break;
00455                         }
00456                     }
00457                     if( bestLen > 0 )
00458                     {
00459                         *pIndexes++ = best;
00460                         if( bestLen < code )
00461                         {
00462                             /* Don't smash RAM */
00463                             if( pixCurr + (code-bestLen) > pixEnd )
00464                                 break;
00465                             memcpy( pixCurr, pData+best, sizeof(OPC_NAMING(Pixel))*(code-bestLen) );
00466                             pixCurr += (code-bestLen);
00467                         }
00468                         pData += code;
00469                         continue;
00470                     }
00471                 }
00472                 /* Just dump new run on end and hope future runs are better */
00473                 {
00474                     /* Don't smash RAM */
00475                     if( pixCurr + code > pixEnd )
00476                         break;
00477                     *pIndexes++ = 0;
00478                     memcpy( pixCurr, pData, sizeof(OPC_NAMING(Pixel))*code );
00479                     pixCurr += code;
00480                     pData += code;
00481                 }
00482             }
00483             else if( code == 0 )
00484             {
00485                 /* 
00486                  * We hit the end and didn't run out? SUCCESS!
00487                  * Update OPCShape, copy new data, etc.
00488                  */
00489                 size_t packsize = (size_t)pixCurr - (size_t)buffer;
00490 
00491                 /* Clear extra bytes & align pointer */
00492                 while( (size_t)pCode & 3 )
00493                     *pCode++ = 0;
00494                 memcpy( pCode, buffer, packsize );
00495                 
00496 #ifdef OPC_POINTERS
00497                 shape->pack = pCode;
00498                 shape->data = pCode + (pIndexEnd-pIndexBegin);
00499 #else
00500                 shape->pack = (size_t)pCode - (size_t)shape;
00501                 shape->data = shape->pack + (pIndexEnd-pIndexBegin);
00502 #endif
00503 
00504                 return OPC_NAMING(Shape_TotalSize)( shape );
00505             }
00506             /* else if( code < 0 ), we ignore it. */
00507         }
00508     }
00509     /*
00510      * Just return input shape's size
00511      */
00512     return OPC_NAMING(Shape_TotalSize)( shape );
00513 }

void OPC_NAMING() ShrinkBound ( OPC dst,
const OPC src,
OPC_NAMING(Pixel)  transparent 
)

Find the non-transparent edges of a shape Copies src to dst, then moves clipping bounds of dst down until they all hit something non-transparent.

Parameters:
dst OPC we're constructing from src.
src OPC we're making a shrunken version of
transparent Pixel value to treat as transparent

Definition at line 35 of file opctool.temp.h.

References Rect::bottom, and Rect::right.

Referenced by Shape_Create().

00036 {
00037     if( dst != src )
00038         *dst = *src;
00039     /* Move down top edge until it hits something */
00040     while( dst->clip.top < dst->clip.bottom )
00041     {
00042         OPC_NAMING(Pixel) pixel = transparent;
00043         const OPC_NAMING(Pixel)* curr = OPC_PTR( dst, dst->clip.left,dst->clip.top );
00044         int x;
00045         for( x = dst->clip.left; x < dst->clip.right; ++x )
00046         {
00047             pixel = *curr++;
00048             if( pixel != transparent )
00049                 break;
00050         }
00051         if( pixel != transparent )
00052             break;
00053         dst->clip.top++;
00054     }
00055     /* Move up bottom edge until it hits something */
00056     while( dst->clip.top < dst->clip.bottom )
00057     {
00058         OPC_NAMING(Pixel) pixel = transparent;
00059         const OPC_NAMING(Pixel)* curr = OPC_PTR( dst, dst->clip.left,dst->clip.bottom-1 );
00060         int x;
00061         for( x = dst->clip.left; x < dst->clip.right; ++x )
00062         {
00063             pixel = *curr++;
00064             if( pixel != transparent )
00065                 break;
00066         }
00067         if( pixel != transparent )
00068             break;
00069         dst->clip.bottom--;
00070     }
00071     /* Move left edge right until it hits something */
00072     while( dst->clip.left < dst->clip.right )
00073     {
00074         OPC_NAMING(Pixel) pixel = transparent;
00075         const OPC_NAMING(Pixel)* curr = OPC_PTR( dst, dst->clip.left,dst->clip.top );
00076         int pitch = dst->pitch;
00077         int y;
00078         for( y = dst->clip.top; y < dst->clip.bottom; ++y )
00079         {
00080             pixel = *curr;
00081             curr = (OPC_NAMING(Pixel)*)((uint8*)curr + pitch);
00082             if( pixel != transparent )
00083                 break;
00084         }
00085         if( pixel != transparent )
00086             break;
00087         dst->clip.left++;
00088     }
00089     /* Move right edge left until it hits something */
00090     while( dst->clip.left < dst->clip.right )
00091     {
00092         OPC_NAMING(Pixel) pixel = transparent;
00093         const OPC_NAMING(Pixel)* curr = OPC_PTR( dst, dst->clip.right-1,dst->clip.top );
00094         int pitch = dst->pitch;
00095         int y;
00096         for( y = dst->clip.top; y < dst->clip.bottom; ++y )
00097         {
00098             pixel = *curr;
00099             curr = (OPC_NAMING(Pixel)*)((uint8*)curr + pitch);
00100             if( pixel != transparent )
00101                 break;
00102         }
00103         if( pixel != transparent )
00104             break;
00105         dst->clip.right--;
00106     }
00107 }


Generated on Fri Jan 2 15:28:35 2009 for Squat by  doxygen 1.5.6