00001
00008 #ifndef OPCTOOL_H
00009 #include "opctool.h"
00010 #endif
00011
00012 #ifndef PIXEL
00013 #error 'PIXEL' must be defined. It specifies the pixel format (i.e. uint8, uint16, uint32).
00014 #endif
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00035 void OPC_NAMING(ShrinkBound)( OPC* dst, const OPC* src, OPC_NAMING(Pixel) transparent )
00036 {
00037 if( dst != src )
00038 *dst = *src;
00039
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
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
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
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 }
00108
00109
00117 size_t OPC_NAMING(Shape_Calc)( const OPC* src, OPC_NAMING(Pixel) transparent, bool bMask )
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 }
00154
00155
00188 OPCShape* OPC_NAMING(Shape_Create)( const OPC* src, OPC_NAMING(Pixel) transparent, void* buffer, bool bMask )
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
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
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++ )
00229 if( !bMask )
00230 {
00231
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 )
00239 {
00240
00241 if( dump )
00242 {
00243 *pCode++ = DUMP_CODE(dump);
00244 dump = 0;
00245 }
00246
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
00259 if( *(pCode-1) < 0 && *(pCode-1) != -128 && pCode > (int8*)(shape+1) )
00260 *--pCode = -128;
00261 *pCode++ = -128;
00262 }
00263
00264 while( *(pCode-1) < 0 && pCode > (int8*)(shape+1) )
00265 --pCode;
00266 *pCode++ = 0;
00267
00268 while( (size_t)pCode & 3 )
00269 *pCode++ = 0;
00270 if( bMask )
00271 {
00272 shape->data = 0;
00273 }
00274 else
00275 {
00276
00277 #ifdef OPC_POINTERS
00278 shape->data = pCode;
00279 #else
00280 shape->data = pCode-(int8*)shape;
00281 #endif
00282 {
00283
00284
00285
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
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
00333
00334 }
00335 return shape;
00336 }
00337
00341 size_t OPC_NAMING(Shape_Pack_Needs)( OPCShape* shape )
00342 {
00343
00344
00345
00346 return OPC_NAMING(Shape_DataSize)( shape );
00347 }
00348
00373 size_t OPC_NAMING(Shape_Pack)( OPCShape* shape, void* buffer )
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
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
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
00429
00430
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
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
00453 if( bestLen == code )
00454 break;
00455 }
00456 }
00457 if( bestLen > 0 )
00458 {
00459 *pIndexes++ = best;
00460 if( bestLen < code )
00461 {
00462
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
00473 {
00474
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
00487
00488
00489 size_t packsize = (size_t)pixCurr - (size_t)buffer;
00490
00491
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
00507 }
00508 }
00509
00510
00511
00512 return OPC_NAMING(Shape_TotalSize)( shape );
00513 }
00514
00521 void OPC_NAMING(ExportH)( const OPC* opc, FILE* fp, const char* szname )
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 }
00528
00538 void OPC_NAMING(ExportC)( const OPC* opc, FILE* fp, const char* modifier, const char* szname, const char* szComment, ... )
00539 {
00540 if( szComment )
00541 {
00542 va_list args;
00543 va_start( args, szComment );
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 }
00557
00558
00559
00560
00561
00562
00563
00564
00572 void OPC_NAMING(ExportCData)( const OPC* opc, FILE* fp, const char* szname )
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 }
00631
00639 void OPC_NAMING(Shape_ExportH)( const OPCShape* shape, FILE* fp, const char* szname, bool bMask )
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 }
00646
00657 void OPC_NAMING(Shape_ExportC)( const OPCShape* shape, FILE* fp, const char* modifier, const char* szname, bool bMask, const char* szComment, ... )
00658 {
00659 if( szComment )
00660 {
00661 va_list args;
00662 va_start( args, szComment );
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 }
00691
00700 void OPC_NAMING(Shape_ExportCData)( const OPCShape* shape, FILE* fp, const char* szname, bool bMask )
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
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
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
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
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 }
00797