00001 #include "RLEBitmap.h"
00002 #include "Image.h"
00003 #include "Asset.h"
00004 #include "Bitmap.h"
00005 #include "AlphaBitmap.h"
00006
00007 #define max(a,b) (((a) > (b)) ? (a) : (b))
00008 #define min(a,b) (((a) < (b)) ? (a) : (b))
00009
00010 const char* Pixie_Rle_Header="PIXIE_RLE";
00011
00012
00013
00014 RLEBitmap::RLEBitmap():
00015 usesMask_(0),
00016 xOffset_(0),
00017 yOffset_(0),
00018 activeWidth_(0),
00019 activeHeight_(0),
00020 width_(0),
00021 height_(0),
00022 opaqueSize_(0),
00023 opaqueData_(0),
00024 alphaSize_(0),
00025 alphaData_(0),
00026 colorCount_(0),
00027 palette_(0),
00028 modulatedPalette_(0),
00029 currentPalette_(0)
00030 {
00031 }
00032
00033
00034
00035
00036 RLEBitmap::RLEBitmap(const Image& image):
00037 usesMask_(0),
00038 xOffset_(0),
00039 yOffset_(0),
00040 activeWidth_(0),
00041 activeHeight_(0),
00042 width_(0),
00043 height_(0),
00044 opaqueSize_(0),
00045 opaqueData_(0),
00046 alphaSize_(0),
00047 alphaData_(0),
00048 colorCount_(0),
00049 palette_(0),
00050 modulatedPalette_(0),
00051 currentPalette_(0)
00052 {
00053 CreateFromImage(&image);
00054 }
00055
00056
00057
00058
00059 RLEBitmap::RLEBitmap(const Asset& asset):
00060 usesMask_(0),
00061 xOffset_(0),
00062 yOffset_(0),
00063 activeWidth_(0),
00064 activeHeight_(0),
00065 width_(0),
00066 height_(0),
00067 opaqueSize_(0),
00068 opaqueData_(0),
00069 alphaSize_(0),
00070 alphaData_(0),
00071 colorCount_(0),
00072 palette_(0),
00073 modulatedPalette_(0),
00074 currentPalette_(0)
00075 {
00076 Load(asset);
00077 }
00078
00079
00080
00081
00082 RLEBitmap::~RLEBitmap()
00083 {
00084 if (opaqueData_)
00085 {
00086 Free(opaqueData_);
00087 }
00088
00089 if (alphaData_)
00090 {
00091 Free(alphaData_);
00092 }
00093
00094 if (palette_)
00095 {
00096 Free(palette_);
00097 }
00098
00099 if (modulatedPalette_)
00100 {
00101 Free(modulatedPalette_);
00102 }
00103 }
00104
00105
00106
00107
00108 void RLEBitmap::ReadFromAsset(const Asset* asset)
00109 {
00110 asset->Read(&width_);
00111 asset->Read(&height_);
00112 asset->Read(&activeWidth_);
00113 asset->Read(&activeHeight_);
00114 asset->Read(&colorCount_);
00115 palette_=(unsigned short*)Malloc(sizeof(unsigned short)*colorCount_);
00116 asset->Read(palette_,colorCount_);
00117 asset->Read(&usesMask_);
00118 asset->Read(&opaqueSize_);
00119 if (opaqueSize_>0)
00120 {
00121 opaqueData_=(unsigned char*)Malloc(opaqueSize_);
00122 asset->Read(opaqueData_,opaqueSize_);
00123 }
00124 asset->Read(&alphaSize_);
00125 if (alphaSize_>0)
00126 {
00127 alphaData_=(unsigned char*)Malloc(alphaSize_);
00128 asset->Read(alphaData_,alphaSize_);
00129 }
00130 asset->Read(&xOffset_,1);
00131 asset->Read(&yOffset_,1);
00132 }
00133
00134
00135
00136
00137 void RLEBitmap::WriteToAsset(Asset* asset)
00138 {
00139 asset->Write(&width_);
00140 asset->Write(&height_);
00141 asset->Write(&activeWidth_);
00142 asset->Write(&activeHeight_);
00143 asset->Write(&colorCount_);
00144 asset->Write(palette_,colorCount_);
00145 asset->Write(&usesMask_);
00146 asset->Write(&opaqueSize_);
00147 if (opaqueSize_>0 && opaqueData_)
00148 {
00149 asset->Write(opaqueData_,opaqueSize_);
00150 }
00151 asset->Write(&alphaSize_);
00152 if (alphaSize_>0 && alphaData_)
00153 {
00154 asset->Write(alphaData_,alphaSize_);
00155 }
00156 asset->Write(&xOffset_);
00157 asset->Write(&yOffset_);
00158 }
00159
00160
00161
00162
00163 int calculateDiff(unsigned short a, unsigned short b)
00164 {
00165 unsigned char ar=(unsigned char)((a & 0xf800)>>11);
00166 unsigned char ag=(unsigned char)((a & 0x7e0)>>5);
00167 unsigned char ab=(unsigned char)((a & 0x1f));
00168 unsigned char br=(unsigned char)((b & 0xf800)>>11);
00169 unsigned char bg=(unsigned char)((b & 0x7e0)>>5);
00170 unsigned char bb=(unsigned char)((b & 0x1f));
00171
00172
00173 int dr=Abs(ar-br);
00174 int dg=Abs(ab-bb);
00175 int db=Abs(ag-bg);
00176
00177 return dr+dg+db;
00178 }
00179
00180
00181
00182
00183 void RLEBitmap::FindGetRidOfDiff(unsigned short* palette, int usedPaletteEntries,int& diff, int& a, int& b)
00184 {
00185
00186 int bestPairA=0;
00187 int bestPairB=1;
00188 int bestDiff=calculateDiff(palette[bestPairA],palette[bestPairB]);
00189 for (int i=0; i<usedPaletteEntries-1; i++)
00190 {
00191 for (int j=i+1; j<usedPaletteEntries; j++)
00192 {
00193 int diff=calculateDiff(palette[i],palette[j]);
00194 if (diff<bestDiff)
00195 {
00196 bestDiff=diff;
00197 bestPairA=i;
00198 bestPairB=j;
00199 }
00200 }
00201 }
00202 a=bestPairA;
00203 b=bestPairB;
00204 diff=bestDiff;
00205 }
00206
00207
00208
00209
00210 void RLEBitmap::GetRidOfColor(unsigned char* data, int size, unsigned short* palette, int& usedPaletteEntries,unsigned int* timesUsed, int bestDiff, int bestPairA, int bestPairB)
00211 {
00212
00213 if (timesUsed[bestPairB]>timesUsed[bestPairA])
00214 {
00215 int temp=bestPairB;
00216 bestPairB=bestPairA;
00217 bestPairA=temp;
00218 }
00219 timesUsed[bestPairA]+=timesUsed[bestPairB];
00220 for (int i=0; i<size; i++)
00221 {
00222 if (data[i]==bestPairB)
00223 {
00224 data[i]=(unsigned char)bestPairA;
00225 }
00226 }
00227
00228
00229 palette[bestPairB]=palette[usedPaletteEntries-1];
00230 for (int i=0; i<size; i++)
00231 {
00232 if (data[i]==(usedPaletteEntries-1))
00233 data[i]=(unsigned char)bestPairB;
00234 }
00235
00236
00237 usedPaletteEntries--;
00238 }
00239
00240
00241
00242
00243 unsigned char RLEBitmap::FindBestColor(unsigned char* data, int size, unsigned short* palette, int& usedPaletteEntries,unsigned int* timesUsed, unsigned char r, unsigned char g, unsigned char b)
00244 {
00245 unsigned short color=(r<<11)|(g<<5)|(b);
00246 for (int i=0; i<usedPaletteEntries; i++)
00247 {
00248 if (palette[i]==color)
00249 {
00250 timesUsed[i]++;
00251 return (unsigned char)i;
00252 }
00253 }
00254 if (usedPaletteEntries==254)
00255 {
00256
00257 int bestMatch=0;
00258 int bestDiff=calculateDiff(color,palette[bestMatch]);
00259 for (int i=1; i<usedPaletteEntries; i++)
00260 {
00261 int diff=calculateDiff(color,palette[i]);
00262 if (diff<bestDiff)
00263 {
00264 bestDiff=diff;
00265 bestMatch=i;
00266 }
00267 }
00268
00269 int ridPairA=0;
00270 int ridPairB=0;
00271 int ridDiff=0;
00272 FindGetRidOfDiff(palette,usedPaletteEntries,ridDiff,ridPairA,ridPairB);
00273 if (bestDiff<=ridDiff)
00274 {
00275 timesUsed[bestMatch]++;
00276 return (unsigned char)bestMatch;
00277 }
00278 GetRidOfColor(data,size,palette,usedPaletteEntries,timesUsed,ridDiff,ridPairA,ridPairB);
00279 }
00280
00281 Assert(usedPaletteEntries<254,"Palette full!");
00282
00283 palette[usedPaletteEntries]=color;
00284 timesUsed[usedPaletteEntries]=0;
00285 usedPaletteEntries++;
00286 return (unsigned char)(usedPaletteEntries-1);
00287 }
00288
00289
00290
00291
00292 void RLEBitmap::CreateFromImage(const Image* image)
00293 {
00294 width_=(unsigned short)image->GetWidth();
00295 height_=(unsigned short)image->GetHeight();
00296 int minX=0;
00297 int minY=0;
00298 int maxX=0;
00299 int maxY=0;
00300
00301
00302 Crop(image,&minX,&minY,&maxX,&maxY);
00303 if (maxX<minX || maxY<minY)
00304 {
00305 return;
00306 }
00307
00308 activeWidth_=(unsigned short)(maxX-minX+1);
00309 activeHeight_=(unsigned short)(maxY-minY+1);
00310
00311 xOffset_=(unsigned short)minX;
00312 yOffset_=(unsigned short)minY;
00313
00314
00315 unsigned char* data=0;
00316 unsigned char* mask=0;
00317 Palettize(image,&data,&mask,&palette_,&colorCount_);
00318
00319 if (mask)
00320 usesMask_=1;
00321 else
00322 usesMask_=0;
00323
00324
00325 opaqueSize_=GetRLESize(data,mask);
00326 if (opaqueSize_>0)
00327 {
00328 opaqueData_=(unsigned char*)Malloc(opaqueSize_);
00329 CreateRLE(data,mask,opaqueData_);
00330 }
00331
00332
00333 if (mask)
00334 {
00335 alphaSize_=GetRLESize_Alpha(data,mask);
00336 if (alphaSize_>0)
00337 {
00338 alphaData_=(unsigned char*)Malloc(alphaSize_);
00339 CreateRLE_Alpha(data,mask,alphaData_);
00340 }
00341 }
00342
00343
00344
00345 if (data)
00346 {
00347 Free(data);
00348 }
00349 if (mask)
00350 {
00351 Free(mask);
00352 }
00353 }
00354
00355
00356
00357
00358 int RLEBitmap::GetRunLength(unsigned char* data, unsigned char* mask,int size)
00359 {
00360 int length=0;
00361 int currCol=*data;
00362 if (mask && *mask<255)
00363 {
00364 currCol=255;
00365 }
00366 int c=currCol;
00367 while ((currCol==c) && size>0)
00368 {
00369 length++;
00370 data++;
00371 if (mask)
00372 {
00373 mask++;
00374 }
00375 size--;
00376 currCol=*data;
00377 if (mask && *mask<255)
00378 {
00379 currCol=255;
00380 }
00381 }
00382 return length;
00383 }
00384
00385
00386
00387
00388 int RLEBitmap::GetUniquesLength(unsigned char* data, unsigned char* mask,int size)
00389 {
00390 int length=0;
00391 while (GetRunLength(data,mask,size)<=2 && size>0)
00392 {
00393 length++;
00394 data++;
00395 if (mask)
00396 {
00397 mask++;
00398 }
00399 size--;
00400 }
00401 return length;
00402 }
00403
00404
00405
00406
00407 int RLEBitmap::GetRLESize(unsigned char* data,unsigned char* mask)
00408 {
00409 return CreateRLE(data,mask,0);
00410 }
00411
00412
00413
00414
00415 int RLEBitmap::CreateRLE(unsigned char* source, unsigned char* mask, unsigned char* destination)
00416 {
00417 int size=activeWidth_*activeHeight_;
00418 int result=0;
00419 int xleft=activeWidth_;
00420 while (size>0)
00421 {
00422 unsigned char len=(unsigned char)GetRunLength(source,mask,min(127,min(size,xleft)));
00423 if (len<=2)
00424 {
00425 unsigned char len=(unsigned char)GetUniquesLength(source,mask,min(127,min(size,xleft)));
00426
00427 result++;
00428 if (destination)
00429 {
00430 *destination=(len | 0x80);
00431 destination++;
00432 }
00433
00434 result+=len;
00435 if (destination)
00436 {
00437 unsigned char* colorsource=source;
00438 unsigned char* maskvalue=mask;
00439 for (int i=0; i<len; i++)
00440 {
00441 if (mask && *maskvalue<255)
00442 *destination=255;
00443 else
00444 *destination=*colorsource;
00445 destination++;
00446 colorsource++;
00447 if (mask)
00448 maskvalue++;
00449 }
00450 }
00451
00452 if (mask)
00453 mask+=len;
00454 source+=len;
00455 xleft-=len;
00456 Assert(xleft>=0,"Inavlid run length");
00457 if (xleft==0)
00458 xleft=activeWidth_;
00459 size-=len;
00460 }
00461 else
00462 {
00463 result++;
00464 if (destination)
00465 {
00466 *destination=len;
00467 destination++;
00468 }
00469
00470 result++;
00471 if (destination)
00472 {
00473 if (mask && *mask<255)
00474 *destination=255;
00475 else
00476 *destination=*source;
00477 destination++;
00478 }
00479
00480 source+=len;
00481 xleft-=len;
00482 Assert(xleft>=0,"Inavlid run length");
00483 if (xleft==0)
00484 xleft=activeWidth_;
00485 if (mask)
00486 mask+=len;
00487 size-=len;
00488 }
00489 }
00490
00491 return result;
00492 }
00493
00494
00495
00496
00497
00498 int RLEBitmap::GetRunLength_Alpha(unsigned char* data, unsigned char* mask,int size)
00499 {
00500 int length=0;
00501 int currCol=*data;
00502 int currMask=*mask;
00503 if (currMask==0 || currMask==255)
00504 {
00505 currMask=0;
00506 currCol=255;
00507 }
00508 int c=currCol;
00509 int m=currMask;
00510 while ((currCol==c) && (currMask==m) && size>0)
00511 {
00512 length++;
00513 data++;
00514 mask++;
00515 size--;
00516 currCol=*data;
00517 currMask=*mask;
00518 if (currMask==0 || currMask==255)
00519 {
00520 currMask=0;
00521 currCol=255;
00522 }
00523 }
00524 return length;
00525 }
00526
00527
00528
00529
00530 int RLEBitmap::GetUniquesLength_Alpha(unsigned char* data, unsigned char* mask,int size)
00531 {
00532 int length=0;
00533 while (GetRunLength_Alpha(data,mask,size)<=2 && size>0)
00534 {
00535 length++;
00536 data++;
00537 mask++;
00538 size--;
00539 }
00540 return length;
00541 }
00542
00543
00544
00545
00546 int RLEBitmap::GetRLESize_Alpha(unsigned char* data,unsigned char* mask)
00547 {
00548 return CreateRLE_Alpha(data,mask,0);
00549 }
00550
00551
00552
00553
00554 int RLEBitmap::CreateRLE_Alpha(unsigned char* source, unsigned char* mask, unsigned char* destination)
00555 {
00556 int size=activeWidth_*activeHeight_;
00557 int result=0;
00558 int xleft=activeWidth_;
00559 while (size>0)
00560 {
00561 unsigned char len=(unsigned char)GetRunLength_Alpha(source,mask,min(127,min(size,xleft)));
00562 if (len<=2)
00563 {
00564 unsigned char len=(unsigned char)GetUniquesLength_Alpha(source,mask,min(127,min(size,xleft)));
00565
00566 result++;
00567 if (destination)
00568 {
00569 *destination=(len | 0x80);
00570 destination++;
00571 }
00572
00573
00574 unsigned char* colorsource=source;
00575 unsigned char* maskvalue=mask;
00576 for (int i=0; i<len; i++)
00577 {
00578 if (*maskvalue==0 || *maskvalue==255)
00579 {
00580 if (destination)
00581 {
00582 *destination=0;
00583 destination++;
00584 *destination=0;
00585 destination++;
00586 }
00587 result+=2;
00588 }
00589 else
00590 {
00591 if (destination)
00592 {
00593 *destination=*maskvalue;
00594 destination++;
00595 *destination=*colorsource;
00596 destination++;
00597 }
00598 result+=2;
00599 }
00600 colorsource++;
00601 maskvalue++;
00602 }
00603
00604 mask+=len;
00605 source+=len;
00606 xleft-=len;
00607 Assert(xleft>=0,"Invalid run length");
00608 if (xleft==0)
00609 xleft=activeWidth_;
00610 size-=len;
00611 }
00612 else
00613 {
00614 result++;
00615 if (destination)
00616 {
00617 *destination=len;
00618 destination++;
00619 }
00620
00621
00622
00623 if (*mask==0 || *mask==255)
00624 {
00625 if (destination)
00626 {
00627 *destination=0;
00628 destination++;
00629 *destination=0;
00630 destination++;
00631 }
00632 result+=2;
00633 }
00634 else
00635 {
00636 if (destination)
00637 {
00638 *destination=*mask;
00639 destination++;
00640 *destination=*source;
00641 destination++;
00642 }
00643 result+=2;
00644 }
00645
00646 source+=len;
00647 xleft-=len;
00648 Assert(xleft>=0,"Invalid run length");
00649 if (xleft==0)
00650 xleft=activeWidth_;
00651 mask+=len;
00652 size-=len;
00653 }
00654 }
00655
00656 return result;
00657 }
00658
00659
00660
00661
00662 void RLEBitmap::Palettize(const Image* image,unsigned char** data, unsigned char** mask, unsigned short** palette, unsigned char* colorCount)
00663 {
00664 static unsigned short pal[256];
00665 static unsigned int timesUsed[256];
00666 int usedPaletteEntries=0;
00667 *data=(unsigned char*)Malloc(sizeof(unsigned char)*activeWidth_*activeHeight_);
00668 *mask=(unsigned char*)Malloc(sizeof(unsigned char)*activeWidth_*activeHeight_);
00669 unsigned char* img=*data;
00670 unsigned char* maskimg=*mask;
00671 bool maskUsed=false;
00672 bool maskUsedTrans=false;
00673
00674 for (int y=0; y<activeHeight_; y++)
00675 {
00676 for (int x=0; x<activeWidth_; x++)
00677 {
00678 unsigned int color=image->GetPixel(xOffset_+x,yOffset_+y);
00679 unsigned short color16=RGB32TO16(color);
00680 unsigned char a=((unsigned char)((color&0xff000000)>>24));
00681 unsigned char r=((unsigned char)((color16 & 0xf800)>>11));
00682 unsigned char g=((unsigned char)((color16 & 0x07e0)>>5));
00683 unsigned char b=((unsigned char)((color16 & 0x1f)));
00684
00685 *img=FindBestColor(*data,(int)(img-*data),pal,usedPaletteEntries,timesUsed,r,g,b);
00686 img++;
00687 *maskimg=a;
00688 maskimg++;
00689 if (a<255)
00690 {
00691 maskUsed=true;
00692 if (a>0)
00693 {
00694 maskUsedTrans=true;
00695 }
00696 }
00697 }
00698 }
00699
00700 if (!maskUsed)
00701 {
00702 Free(*mask);
00703 *mask=0;
00704 }
00705
00706 *palette=(unsigned short*)Malloc(sizeof(unsigned short)*usedPaletteEntries);
00707 MemCpy(*palette,pal,sizeof(unsigned short)*usedPaletteEntries);
00708 *colorCount=(unsigned char)usedPaletteEntries;
00709 }
00710
00711
00712
00713
00714 void RLEBitmap::Crop(const Image* image, int* minX, int* minY, int* maxX, int* maxY)
00715 {
00716 *minX=image->GetWidth();
00717 *minY=image->GetHeight();
00718 *maxX=0;
00719 *maxY=0;
00720 for (int y=0; y<image->GetHeight(); y++)
00721 {
00722 for (int x=0; x<image->GetWidth(); x++)
00723 {
00724 unsigned int color=image->GetPixel(x,y);
00725 if (color>>24)
00726 {
00727 if (y<*minY)
00728 *minY=y;
00729 if (x<*minX)
00730 *minX=x;
00731 if (y>*maxY)
00732 *maxY=y;
00733 if (x>*maxX)
00734 *maxX=x;
00735 }
00736 }
00737 }
00738 }
00739
00740
00741
00742
00743 void RLEBitmap::Blit(Bitmap* target,int x, int y,unsigned short modulate, unsigned char alpha) const
00744 {
00745 Blit(0,0,activeWidth_-1,activeHeight_-1,target,x,y,modulate,alpha);
00746 }
00747
00748
00749
00750
00751 void RLEBitmap::Blit(int x1, int y1, int x2, int y2, Bitmap* target,int x, int y, unsigned short modulate, unsigned char alpha) const
00752 {
00753
00754 if (!opaqueData_ && !alphaData_)
00755 {
00756 return;
00757 }
00758
00759 if (alpha==0)
00760 {
00761 return;
00762 }
00763
00764
00765 int clipX1=x+xOffset_;
00766 int clipY1=y+yOffset_;
00767 int clipX2=x+xOffset_+(x2-x1);
00768 int clipY2=y+yOffset_+(y2-y1);
00769
00770 x-=x1;
00771 y-=y1;
00772
00773 if (clipX1<0)
00774 clipX1=0;
00775 if (clipY1<0)
00776 clipY1=0;
00777 if (clipX2>=target->GetWidth())
00778 clipX2=target->GetWidth()-1;
00779 if (clipY2>=target->GetHeight())
00780 clipY2=target->GetHeight()-1;
00781
00782
00783 currentPalette_=palette_;
00784 if (modulate!=0xffff)
00785 {
00786 if (!modulatedPalette_)
00787 {
00788 modulatedPalette_=(unsigned short*)Malloc(sizeof(unsigned short)*colorCount_);
00789 }
00790 for (int i=0; i<colorCount_; i++)
00791 {
00792 int c=palette_[i];
00793 unsigned int r=(c & 0xf800)>>11;
00794 unsigned int g=(c & 0x7e0)>>5;
00795 unsigned int b=(c & 0x1f);
00796 unsigned int mr=(modulate & 0xf800)>>11;
00797 unsigned int mg=(modulate & 0x7e0)>>5;
00798 unsigned int mb=(modulate & 0x1f);
00799 r*=mr;
00800 g*=mg;
00801 b*=mb;
00802 r>>=5;
00803 g>>=6;
00804 b>>=5;
00805 modulatedPalette_[i]=(unsigned short)((r<<11)|(g<<5)|(b));
00806 }
00807 currentPalette_=modulatedPalette_;
00808 }
00809 int targetDelta=target->GetWidth()-activeWidth_;
00810 int tx1=x+xOffset_;
00811 int ty1=y+yOffset_;
00812 int tx2=tx1+activeWidth_-1;
00813 int ty2=ty1+activeHeight_-1;
00814 unsigned short* data=&(target->GetData())[tx1+ty1*target->GetWidth()];
00815
00816
00817 if (tx1>=clipX1 && ty1>=clipY1 && tx2<=clipX2 && ty2<=clipY2)
00818 {
00819
00820 if (opaqueData_)
00821 {
00822 if (usesMask_)
00823 {
00824 if (alpha==255)
00825 {
00826 Blit_Opaque_Unclipped_Masked(data,targetDelta,tx1,ty1);
00827 }
00828 else
00829 {
00830 Blit_Opaque_Unclipped_Masked_Transparent(data,targetDelta,tx1,ty1,alpha);
00831 }
00832 }
00833 else
00834 {
00835 if (alpha==255)
00836 {
00837 Blit_Opaque_Unclipped_Unmasked(data,targetDelta,tx1,ty1);
00838 }
00839 else
00840 {
00841 Blit_Opaque_Unclipped_Unmasked_Transparent(data,targetDelta,tx1,ty1,alpha);
00842 }
00843 }
00844 }
00845
00846
00847 if (alphaData_)
00848 {
00849 if (alpha==255)
00850 {
00851 Blit_Alpha_Unclipped(data,targetDelta,tx1,ty1);
00852 }
00853 else
00854 {
00855 Blit_Alpha_Unclipped_Transparent(data,targetDelta,tx1,ty1,alpha);
00856 }
00857 }
00858 }
00859 else
00860 {
00861
00862 if (tx2<clipX1 || ty2<clipY1 || tx1>clipX2 || ty1>clipY2)
00863 return;
00864
00865
00866 int xStart=0;
00867 int yStart=0;
00868 int xEnd=0;
00869 int yEnd=0;
00870
00871 if (tx1<clipX1)
00872 {
00873 xStart=clipX1-tx1;
00874 }
00875 if (ty1<clipY1)
00876 {
00877 yStart=clipY1-ty1;
00878 }
00879 if (tx2>clipX2)
00880 {
00881 xEnd=tx2-clipX2+1;
00882 }
00883 if (ty2>clipY2)
00884 {
00885 yEnd=ty2-clipY2+1;
00886 }
00887
00888
00889 if (opaqueData_)
00890 {
00891 if (usesMask_)
00892 {
00893 if (alpha==255)
00894 {
00895 Blit_Opaque_Clipped_Masked(data,targetDelta,tx1,ty1,xStart,yStart,xEnd,yEnd);
00896 }
00897 else
00898 {
00899 Blit_Opaque_Clipped_Masked_Transparent(data,targetDelta,tx1,ty1,xStart,yStart,xEnd,yEnd,alpha);
00900 }
00901 }
00902 else
00903 {
00904 if (alpha==255)
00905 {
00906 Blit_Opaque_Clipped_Unmasked(data,targetDelta,tx1,ty1,xStart,yStart,xEnd,yEnd);
00907 }
00908 else
00909 {
00910 Blit_Opaque_Clipped_Unmasked_Transparent(data,targetDelta,tx1,ty1,xStart,yStart,xEnd,yEnd,alpha);
00911 }
00912 }
00913 }
00914
00915
00916 if (alphaData_)
00917 {
00918 Blit_Alpha_Clipped(data,targetDelta,tx1,ty1,xStart,yStart,xEnd,yEnd);
00919 }
00920 }
00921 }
00922
00923
00924
00925
00926 void RLEBitmap::Blit(AlphaBitmap* target,int x, int y) const
00927 {
00928 Blit(0,0,activeWidth_-1,activeHeight_-1,target,x,y);
00929 }
00930
00931
00932
00933
00934 void RLEBitmap::Blit(int x1, int y1, int x2, int y2, AlphaBitmap* target, int x, int y) const
00935 {
00936
00937 if (!opaqueData_ && !alphaData_)
00938 {
00939 return;
00940 }
00941
00942 x-=x1;
00943 y-=y1;
00944
00945
00946 int clipX1=x+xOffset_;
00947 int clipY1=y+yOffset_;
00948 int clipX2=x+xOffset_+(x2-x1);
00949 int clipY2=y+yOffset_+(y2-y1);
00950
00951
00952 if (clipX1<0)
00953 clipX1=0;
00954 if (clipY1<0)
00955 clipY1=0;
00956 if (clipX2>=target->GetWidth())
00957 clipX2=target->GetWidth()-1;
00958 if (clipY2>=target->GetHeight())
00959 clipY2=target->GetHeight()-1;
00960
00961 currentPalette_=palette_;
00962
00963 int targetDelta=target->GetWidth()-activeWidth_;
00964 int tx1=x+xOffset_;
00965 int ty1=y+yOffset_;
00966 int tx2=tx1+activeWidth_-1;
00967 int ty2=ty1+activeHeight_-1;
00968 unsigned short* colorData=&(target->GetColorData())[tx1+ty1*target->GetWidth()];
00969 unsigned char* alphaData=&(target->GetAlphaData())[tx1+ty1*target->GetWidth()];
00970
00971
00972 if (tx1>=clipX1 && ty1>=clipY1 && tx2<=clipX2 && ty2<=clipY2)
00973 {
00974
00975 if (opaqueData_)
00976 {
00977 if (usesMask_)
00978 {
00979 PreserveAlpha_Blit_Opaque_Unclipped_Masked(colorData, alphaData, targetDelta, tx1, ty1);
00980 }
00981 else
00982 {
00983 PreserveAlpha_Blit_Opaque_Unclipped_Unmasked(colorData, alphaData, targetDelta, tx1, ty1);
00984 }
00985 }
00986
00987
00988 if (alphaData_)
00989 {
00990 PreserveAlpha_Blit_Alpha_Unclipped(colorData, alphaData, targetDelta, tx1, ty1);
00991 }
00992 }
00993 else
00994 {
00995
00996 if (tx2<clipX1 || ty2<clipY1 || tx1>clipX2 || ty1>clipY2)
00997 return;
00998
00999
01000 int xStart=0;
01001 int yStart=0;
01002 int xEnd=0;
01003 int yEnd=0;
01004
01005 if (tx1<clipX1)
01006 {
01007 xStart=clipX1-tx1;
01008 }
01009 if (ty1<clipY1)
01010 {
01011 yStart=clipY1-ty1;
01012 }
01013 if (tx2>clipX2)
01014 {
01015 xEnd=tx2-clipX2+1;
01016 }
01017 if (ty2>clipY2)
01018 {
01019 yEnd=ty2-clipY2+1;
01020 }
01021
01022
01023 if (opaqueData_)
01024 {
01025 if (usesMask_)
01026 {
01027 PreserveAlpha_Blit_Opaque_Clipped_Masked(colorData, alphaData, targetDelta, tx1, ty1, xStart, yStart, xEnd, yEnd);
01028 }
01029 else
01030 {
01031 PreserveAlpha_Blit_Opaque_Clipped_Unmasked(colorData, alphaData, targetDelta, tx1, ty1, xStart, yStart, xEnd, yEnd);
01032 }
01033 }
01034
01035
01036 if (alphaData_)
01037 {
01038 PreserveAlpha_Blit_Alpha_Clipped(colorData, alphaData, targetDelta, tx1, ty1, xStart, yStart, xEnd, yEnd);
01039 }
01040 }
01041 }
01042
01043
01044
01045
01046 __forceinline void Fill(unsigned short* data, unsigned short color, int len)
01047 {
01048 for (int i=0; i<len; ++i)
01049 {
01050 *data=color;
01051 data++;
01052 }
01053 }
01054
01055
01056
01057
01058 __forceinline void Blend(unsigned short* destination, unsigned int color, unsigned int alpha)
01059 {
01060 if (alpha==255)
01061 {
01062 *destination=(unsigned short)color;
01063 }
01064 else
01065 {
01066 unsigned int inva=255-alpha;
01067 unsigned int s=*destination;
01068 unsigned int sr=(s & 0xf800)>>11;
01069 unsigned int sg=(s & 0x7e0)>>5;
01070 unsigned int sb=(s & 0x1f);
01071 unsigned int dr=(color & 0xf800)>>11;
01072 unsigned int dg=(color & 0x7e0)>>5;
01073 unsigned int db=(color & 0x1f);
01074 unsigned int r=((sr*inva)+dr*alpha)>>8;
01075 unsigned int g=((sg*inva)+dg*alpha)>>8;
01076 unsigned int b=((sb*inva)+db*alpha)>>8;
01077 unsigned int c=(r<<11)|(g<<5)|b;
01078 *destination=(unsigned short)c;
01079 }
01080 }
01081
01082
01083
01084
01085 __forceinline void FillTransparent(unsigned short* data, unsigned short color, int len, unsigned char alpha)
01086 {
01087 for (int i=0; i<len; ++i)
01088 {
01089 Blend(data,color,alpha);
01090 data++;
01091 }
01092 }
01093
01094
01095
01096
01097
01098 __forceinline void BurstFill(unsigned short* data, unsigned short color, int len)
01099 {
01100 int len2=len;
01101
01102
01103 #pragma warning (push)
01104 #pragma warning( disable: 4311)
01105 #ifdef _WIN32
01106 if (((int)data)!=(((int)data)&(0xfffffffc)))
01107 #else
01108 if (((long long)data)!=(((long long)data)&(0xfffffffffffffffc)))
01109 #endif
01110 #pragma warning (pop)
01111 {
01112 *data=color;
01113 ++data;
01114 --len2;
01115 if (len2==1)
01116 {
01117 *data=color;
01118 ++data;
01119 --len2;
01120 }
01121 }
01122 if (len2)
01123 {
01124 unsigned int color32=color | (color<<16);
01125 int halflen=len2/2;
01126 unsigned int* data32=(unsigned int*)data;
01127 for (int i=0; i<halflen; ++i)
01128 {
01129 *data32=color32;
01130 ++data32;
01131 }
01132 data=(unsigned short*)data32;
01133 if (len2-halflen*2)
01134 {
01135 *data=color;
01136 ++data;
01137 }
01138 }
01139 }
01140
01141
01142
01143
01144 __forceinline void DoOpaqueUnclippedUnmasked(int len,unsigned short* data, unsigned char** source, unsigned short* palette)
01145 {
01146 unsigned char* dataRLE=*source;
01147 if (len&0x80)
01148 {
01149 len&=0x7f;
01150
01151 for (int i=0; i<len; ++i)
01152 {
01153 *data=palette[*dataRLE];
01154 ++data;
01155 ++(dataRLE);
01156 }
01157 }
01158 else
01159 {
01160
01161 #ifdef _DEBUG
01162 Fill(data,palette[*dataRLE],len);
01163 #else
01164 BurstFill(data,palette[*dataRLE],len);
01165 #endif
01166 ++(dataRLE);
01167 }
01168 *source=dataRLE;
01169 }
01170
01171
01172
01173
01174 __forceinline void DoOpaqueUnclippedUnmaskedTransparent(int len,unsigned short* data, unsigned char** source, unsigned short* palette, unsigned char alpha)
01175 {
01176 unsigned char* dataRLE=*source;
01177 if (len&0x80)
01178 {
01179 len&=0x7f;
01180
01181 for (int i=0; i<len; ++i)
01182 {
01183 Blend(data,palette[*dataRLE],alpha);
01184 ++data;
01185 ++(dataRLE);
01186 }
01187 }
01188 else
01189 {
01190
01191 FillTransparent(data,palette[*dataRLE],len,alpha);
01192 ++(dataRLE);
01193 }
01194 *source=dataRLE;
01195 }
01196
01197
01198
01199
01200 __forceinline void DoOpaqueClippedMasked(int len,unsigned short* data, unsigned char** source, unsigned short* palette, int clipStart, int clipEnd)
01201 {
01202 unsigned char* dataRLE=*source;
01203 int x=0;
01204 if (len&0x80)
01205 {
01206 len&=0x7f;
01207
01208 for (int i=0; i<len; ++i)
01209 {
01210 if ((*dataRLE)<255 && x>=clipStart && x<=clipEnd)
01211 *data=palette[*dataRLE];
01212 ++x;
01213 ++data;
01214 ++(dataRLE);
01215 }
01216 }
01217 else
01218 {
01219
01220 int colorIndex=*dataRLE;
01221 if(colorIndex<255)
01222 {
01223 unsigned short color=palette[colorIndex];
01224 for (int i=0; i<len; ++i)
01225 {
01226 if (colorIndex<255 && x>=clipStart && x<=clipEnd)
01227 {
01228 *data=color;
01229 }
01230 ++x;
01231 ++data;
01232 }
01233 }
01234 else
01235 {
01236 x+=len;
01237 data+=len;
01238 }
01239
01240 ++(dataRLE);
01241 }
01242 *source=dataRLE;
01243 }
01244
01245
01246
01247
01248 __forceinline void DoOpaqueClippedMaskedTransparent(int len,unsigned short* data, unsigned char** source, unsigned short* palette, int clipStart, int clipEnd, unsigned char alpha)
01249 {
01250 unsigned char* dataRLE=*source;
01251 int x=0;
01252 if (len&0x80)
01253 {
01254 len&=0x7f;
01255
01256 for (int i=0; i<len; ++i)
01257 {
01258 if ((*dataRLE)<255 && x>=clipStart && x<=clipEnd)
01259 {
01260 Blend(data,palette[*dataRLE],alpha);
01261 }
01262 ++x;
01263 ++data;
01264 ++(dataRLE);
01265 }
01266 }
01267 else
01268 {
01269
01270 int colorIndex=*dataRLE;
01271 if(colorIndex<255)
01272 {
01273 unsigned short color=palette[colorIndex];
01274 for (int i=0; i<len; ++i)
01275 {
01276 if (colorIndex<255 && x>=clipStart && x<=clipEnd)
01277 {
01278 Blend(data,color,alpha);
01279 }
01280 ++x;
01281 ++data;
01282 }
01283 }
01284 else
01285 {
01286 x+=len;
01287 data+=len;
01288 }
01289
01290 ++(dataRLE);
01291 }
01292 *source=dataRLE;
01293 }
01294
01295
01296
01297 __forceinline void DoOpaqueUnclippedMasked(int len,unsigned short* data, unsigned char** source, unsigned short* palette)
01298 {
01299 unsigned char* dataRLE=*source;
01300 if (len&0x80)
01301 {
01302 len&=0x7f;
01303
01304 for (int i=0; i<len; ++i)
01305 {
01306 if ((*dataRLE)<255)
01307 {
01308 *data=palette[*dataRLE];
01309 }
01310 ++data;
01311 ++(dataRLE);
01312 }
01313 }
01314 else
01315 {
01316
01317 if ((*dataRLE)<255)
01318 {
01319 #ifdef _DEBUG
01320 Fill(data,palette[*dataRLE],len);
01321 #else
01322 BurstFill(data,palette[*dataRLE],len);
01323 #endif
01324 }
01325 ++(dataRLE);
01326 }
01327 *source=dataRLE;
01328 }
01329
01330
01331
01332
01333 __forceinline void DoOpaqueUnclippedMaskedTransparent(int len,unsigned short* data, unsigned char** source, unsigned short* palette, unsigned char alpha)
01334 {
01335 unsigned char* dataRLE=*source;
01336 if (len&0x80)
01337 {
01338 len&=0x7f;
01339
01340 for (int i=0; i<len; ++i)
01341 {
01342 if ((*dataRLE)<255)
01343 {
01344 Blend(data,palette[*dataRLE],alpha);
01345 }
01346 ++data;
01347 ++(dataRLE);
01348 }
01349 }
01350 else
01351 {
01352
01353 if ((*dataRLE)<255)
01354 {
01355 FillTransparent(data,palette[*dataRLE],len,alpha);
01356 }
01357 ++(dataRLE);
01358 }
01359 *source=dataRLE;
01360 }
01361
01362
01363
01364
01365 __forceinline void IgnoreOpaque(int len, unsigned char** source)
01366 {
01367 unsigned char* dataRLE=*source;
01368 if (len&0x80)
01369 {
01370 len&=0x7f;
01371 dataRLE+=len;
01372 }
01373 else
01374 {
01375 ++dataRLE;
01376 }
01377 *source=dataRLE;
01378 }
01379
01380
01381
01382
01383 __forceinline void IgnoreAlpha(int len, unsigned char** source)
01384 {
01385 unsigned char* dataRLE=*source;
01386 if (len&0x80)
01387 {
01388 len&=0x7f;
01389 dataRLE+=len*2;
01390 }
01391 else
01392 {
01393 dataRLE+=2;
01394 }
01395 *source=dataRLE;
01396 }
01397
01398
01399
01400
01401 void RLEBitmap::Blit_Opaque_Unclipped_Unmasked(unsigned short* data, int backBufferDelta,int x, int y) const
01402 {
01403 unsigned char* dataRLE=opaqueData_;
01404 for (int yi=0; yi<activeHeight_; ++yi)
01405 {
01406 int xi=0;
01407 while (xi<activeWidth_)
01408 {
01409
01410 int len=*dataRLE;
01411 ++dataRLE;
01412
01413 DoOpaqueUnclippedUnmasked(len,data,&dataRLE,currentPalette_);
01414 len&=0x7f;
01415 data+=len;
01416
01417 xi+=len;
01418 }
01419
01420 data+=backBufferDelta;
01421 }
01422 }
01423
01424
01425
01426
01427 void RLEBitmap::Blit_Opaque_Unclipped_Unmasked_Transparent(unsigned short* data, int backBufferDelta,int x, int y, unsigned char alpha) const
01428 {
01429 unsigned char* dataRLE=opaqueData_;
01430 for (int yi=0; yi<activeHeight_; ++yi)
01431 {
01432 int xi=0;
01433 while (xi<activeWidth_)
01434 {
01435
01436 int len=*dataRLE;
01437 ++dataRLE;
01438
01439 DoOpaqueUnclippedUnmaskedTransparent(len,data,&dataRLE,currentPalette_,alpha);
01440 len&=0x7f;
01441 data+=len;
01442
01443 xi+=len;
01444 }
01445
01446 data+=backBufferDelta;
01447 }
01448 }
01449
01450
01451
01452
01453 void RLEBitmap::Blit_Opaque_Unclipped_Masked(unsigned short* data, int backBufferDelta,int x, int y) const
01454 {
01455 unsigned char* dataRLE=opaqueData_;
01456 for (int yi=0; yi<activeHeight_; ++yi)
01457 {
01458 int xi=0;
01459 while (xi<activeWidth_)
01460 {
01461
01462 int len=*dataRLE;
01463 ++dataRLE;
01464
01465 DoOpaqueUnclippedMasked(len,data,&dataRLE,currentPalette_);
01466 len&=0x7f;
01467 data+=len;
01468
01469 xi+=len;
01470 }
01471 data+=backBufferDelta;
01472 }
01473 }
01474
01475
01476
01477
01478 void RLEBitmap::Blit_Opaque_Unclipped_Masked_Transparent(unsigned short* data, int backBufferDelta,int x, int y, unsigned char alpha) const
01479 {
01480 unsigned char* dataRLE=opaqueData_;
01481 for (int yi=0; yi<activeHeight_; ++yi)
01482 {
01483 int xi=0;
01484 while (xi<activeWidth_)
01485 {
01486
01487 int len=*dataRLE;
01488 ++dataRLE;
01489
01490 DoOpaqueUnclippedMaskedTransparent(len,data,&dataRLE,currentPalette_,alpha);
01491 len&=0x7f;
01492 data+=len;
01493
01494 xi+=len;
01495 }
01496 data+=backBufferDelta;
01497 }
01498 }
01499
01500
01501
01502
01503 void RLEBitmap::Blit_Opaque_Clipped_Masked(unsigned short* data, int backBufferDelta,int x, int y, int xStart, int yStart, int xEnd, int yEnd) const
01504 {
01505 if (yStart>activeHeight_-yEnd)
01506 return;
01507 if (xStart>activeWidth_-xEnd)
01508 return;
01509 unsigned char* dataRLE=opaqueData_;
01510
01511
01512 for (int i=0; i<yStart; i++)
01513 {
01514 int xi=0;
01515 while (xi<activeWidth_)
01516 {
01517
01518 int len=*dataRLE;
01519 ++dataRLE;
01520
01521 IgnoreOpaque(len,&dataRLE);
01522 len&=0x7f;
01523
01524 xi+=len;
01525 }
01526 }
01527
01528 data+=yStart*(backBufferDelta+activeWidth_);
01529
01530 for (int yi=yStart; yi<(activeHeight_-yEnd); ++yi)
01531 {
01532 int xi=0;
01533 while (xi<activeWidth_)
01534 {
01535
01536 int len=*dataRLE;
01537 ++dataRLE;
01538
01539
01540 int runLength=(len&0x7f);
01541 if (xi<xStart || (xi+runLength)>(activeWidth_-xEnd))
01542 {
01543
01544 if ((xi+runLength)<xStart || xi>(activeWidth_-xEnd))
01545 {
01546
01547 IgnoreOpaque(len,&dataRLE);
01548 }
01549 else
01550 {
01551
01552 int clipStart=xStart-xi;
01553 int clipEnd=(activeWidth_-xEnd)-xi;
01554
01555 DoOpaqueClippedMasked(len,data,&dataRLE,currentPalette_,clipStart,clipEnd);
01556 }
01557 }
01558 else
01559 {
01560 DoOpaqueUnclippedMasked(len,data,&dataRLE,currentPalette_);
01561 }
01562
01563 len&=0x7f;
01564 data+=len;
01565
01566 xi+=len;
01567 }
01568 data+=backBufferDelta;
01569 }
01570 }
01571
01572
01573
01574
01575 void RLEBitmap::Blit_Opaque_Clipped_Masked_Transparent(unsigned short* data, int backBufferDelta,int x, int y, int xStart, int yStart, int xEnd, int yEnd, unsigned char alpha) const
01576 {
01577 if (yStart>activeHeight_-yEnd)
01578 return;
01579 if (xStart>activeWidth_-xEnd)
01580 return;
01581 unsigned char* dataRLE