32bpp_optimized.cpp

Go to the documentation of this file.
00001 /* $Id$ */
00002 
00003 /*
00004  * This file is part of OpenTTD.
00005  * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
00006  * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00007  * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
00008  */
00009 
00012 #include "../stdafx.h"
00013 #include "../core/alloc_func.hpp"
00014 #include "../zoom_func.h"
00015 #include "../core/math_func.hpp"
00016 #include "32bpp_optimized.hpp"
00017 
00018 static const int MAX_PALETTE_TABLES = 50;
00019 
00020 struct RecolourTable {
00021   SpriteID   id;
00022   Colour     tables[256];
00023 } _rgb_palettes[MAX_PALETTE_TABLES] = {{0,{{0}}}};
00024 
00025 Colour _rgb_stringremap[3] = {{0}};
00026 
00027 static FBlitter_32bppOptimized iFBlitter_32bppOptimized;
00028 
00036 template <BlitterMode mode>
00037 inline void Blitter_32bppOptimized::Draw(const Blitter::BlitterParams *bp, ZoomLevel zoom)
00038 {
00039   const SpriteData *src = (const SpriteData *)bp->sprite;
00040 
00041   /* src_px : each line begins with uint32 n = 'number of bytes in this line',
00042    *          then n times is the Colour struct for this line */
00043   zoom = ZOOM_LVL_BEGIN;
00044   const Colour *src_px = (const Colour *)(src->data + src->offset[zoom][0]);
00045   /* src_n  : each line begins with uint32 n = 'number of bytes in this line',
00046    *          then interleaved stream of 'm' and 'n' channels. 'm' is remap,
00047    *          'n' is number of bytes with the same alpha channel class */
00048   const uint8  *src_n  = (const uint8  *)(src->data + src->offset[zoom][1]);
00049 
00050   /* skip upper lines in src_px and src_n */
00051   for (uint i = bp->skip_top; i != 0; i--) {
00052     src_px = (const Colour *)((const byte *)src_px + *(const uint32 *)src_px);
00053     src_n += *(uint32 *)src_n;
00054   }
00055 
00056   /* skip lines in dst */
00057   uint32 *dst = (uint32 *)bp->dst + bp->top * bp->pitch + bp->left;
00058 
00059   /* store so we don't have to access it via bp everytime (compiler assumes pointer aliasing) */
00060   const Colour *remap = (const Colour *)bp->remap;
00061   for (int y = 0; y < bp->height; y++) {
00062     /* next dst line begins here */
00063     uint32 *dst_ln = dst + bp->pitch;
00064 
00065     /* next src line begins here */
00066     const Colour *src_px_ln = (const Colour *)((const byte *)src_px + *(const uint32 *)src_px);
00067     src_px++;
00068 
00069     /* next src_n line begins here */
00070     const uint8 *src_n_ln = src_n + *(uint32 *)src_n;
00071     src_n += 4;
00072 
00073     /* we will end this line when we reach this point */
00074     uint32 *dst_end = dst + bp->skip_left;
00075 
00076     /* number of pixels with the same aplha channel class */
00077     uint n;
00078 
00079     while (dst < dst_end) {
00080       n = *src_n++;
00081 
00082       if (src_px->a == 0) {
00083         dst += n;
00084         src_px ++;
00085         src_n++;
00086       } else {
00087         if (dst + n > dst_end) {
00088           uint d = dst_end - dst;
00089           src_px += d;
00090           src_n += d;
00091 
00092           dst = dst_end - bp->skip_left;
00093           dst_end = dst + bp->width;
00094 
00095           n = min<uint>(n - d, (uint)bp->width);
00096           goto draw;
00097         }
00098         dst += n;
00099         src_px += n;
00100         src_n += n;
00101       }
00102     }
00103 
00104     dst -= bp->skip_left;
00105     dst_end -= bp->skip_left;
00106 
00107     dst_end += bp->width;
00108 
00109     while (dst < dst_end) {
00110       n = min<uint>(*src_n++, (uint)(dst_end - dst));
00111 
00112       if (src_px->a == 0) {
00113         dst += n;
00114         src_px++;
00115         src_n++;
00116         continue;
00117       }
00118 
00119       draw:;
00120 
00121       switch (mode) {
00122         case BM_COLOUR_REMAP:
00123           do {
00124             uint m = *src_n;
00125             /* In case the m-channel is zero, do not remap this pixel in any way */
00126             if (m == 0) {
00127               if (src_px->a == 255) {
00128                 *dst = src_px->data;
00129               } else {
00130                 *dst = ComposeColourRGBANoCheck(src_px->r, src_px->g, src_px->b, src_px->a, *dst);
00131               }
00132             } else {
00133               Colour r = remap[m];
00134               if (r.a != 0) {
00135                 uint src_col = ComposeColour(src_px->a, src_px->r, src_px->g, src_px->b);
00136                 uint comp_col = ComposeColourBlend(r.data, src_col);
00137                 *dst = ComposeColourPA(comp_col, src_px->a, *dst);
00138               }
00139             }
00140             dst++;
00141             src_px++;
00142             src_n++;
00143           } while (--n != 0);
00144           break;
00145         case BM_COLOUR_OPAQUE:
00146           do {
00147             uint m = *src_n;
00148             /* In case the m-channel is zero, do not remap this pixel in any way */
00149             if (m == 0) {
00150               *dst = ComposeColourRGBA(src_px->r, src_px->g, src_px->b, src_px->a, *dst);
00151             } else {
00152               Colour r = remap[m];
00153               if (r.a != 0) {
00154                 *dst = ComposeColourPA(r.data, src_px->a, *dst);
00155               }
00156             }
00157             dst++;
00158             src_px++;
00159             src_n++;
00160           } while (--n != 0);
00161           break;
00162         case BM_TRANSPARENT:
00163           do {
00164             uint m = *src_n;
00165             if (m == 0) {
00166               *dst = ComposeColourRGBA(src_px->r, src_px->g, src_px->b, src_px->a / 2, *dst);
00167             } else {
00168               if (remap){
00169                 Colour r = remap[m];
00170                 if (r.a != 0) *dst = ComposeColourPA(r.data, src_px->a / 2, *dst);
00171               }
00172               else {
00173                 *dst = ComposeColourRGBA(src_px->r, src_px->g, src_px->b, src_px->a / 2, *dst);
00174               }
00175             }
00176 
00177             dst++;
00178             src_px++;
00179             src_n++;
00180           /* TODO -- We make an assumption here that the remap in fact is transparency, not some colour.
00181            *  This is never a problem with the code we produce, but newgrfs can make it fail... or at least:
00182            *  we produce a result the newgrf maker didn't expect ;) */
00183           } while (--n != 0);
00184           break;
00185         case BM_SHADOW:
00186           /* Make the current colour a bit more black */
00187           src_n += n;
00188           if (src_px->a == 255) {
00189             src_px += n;
00190             do {
00191               *dst = MakeTransparent(*dst, 3, 4);
00192               dst++;
00193             } while (--n != 0);
00194           } else {
00195             do {
00196               *dst = MakeTransparent(*dst, (256 * 4 - src_px->a), 256 * 4);
00197               dst++;
00198               src_px++;
00199             } while (--n != 0);
00200           }
00201 
00202           break;
00203         default:
00204           if (src_px->a == 255) {
00205             /* faster than memcpy(), n is usually low */
00206             src_n += n;
00207             do {
00208               *dst = src_px->data;
00209               dst++;
00210               src_px++;
00211             } while (--n != 0);
00212           } else {
00213             src_n += n;
00214             do {
00215               *dst = ComposeColourRGBANoCheck(src_px->r, src_px->g, src_px->b, src_px->a, *dst);
00216               dst++;
00217               src_px++;
00218             } while (--n != 0);
00219           }
00220           break;
00221       }
00222     }
00223     dst = dst_ln;
00224     src_px = src_px_ln;
00225     src_n  = src_n_ln;
00226   }
00227 }
00228 
00236 void Blitter_32bppOptimized::Draw(Blitter::BlitterParams *bp, BlitterMode mode, ZoomLevel zoom)
00237 {
00238     switch (mode) {
00239     default: NOT_REACHED();
00240     case BM_NORMAL:        Draw<BM_NORMAL>       (bp, zoom); return;
00241     case BM_COLOUR_REMAP:  Draw<BM_COLOUR_REMAP> (bp, zoom); return;
00242     case BM_COLOUR_OPAQUE: Draw<BM_COLOUR_OPAQUE>(bp, zoom); return;
00243     case BM_TRANSPARENT:   Draw<BM_TRANSPARENT>  (bp, zoom); return;
00244     case BM_SHADOW:        Draw<BM_SHADOW>       (bp, zoom); return;
00245   }
00246 }
00247 
00255 static const SpriteLoader::Sprite *ResizeSprite(const SpriteLoader::Sprite *sprite_src, ZoomLevel zoom)
00256 {
00257   return sprite_src;
00258 }
00259 
00260 Sprite *Blitter_32bppOptimized::Encode(SpriteLoader::Sprite *sprite, AllocatorProc *allocator)
00261 {
00262   /* streams of pixels (a, r, g, b channels)
00263    *
00264    * stored in separated stream so data are always aligned on 4B boundary */
00265   Colour *dst_px_orig[ZOOM_LVL_COUNT];
00266 
00267   /* interleaved stream of 'm' channel and 'n' channel
00268    * 'n' is number if following pixels with the same alpha channel class
00269    * there are 3 classes: 0, 255, others
00270    *
00271    * it has to be stored in one stream so fewer registers are used -
00272    * x86 has problems with register allocation even with this solution */
00273   uint8  *dst_n_orig[ZOOM_LVL_COUNT];
00274 
00275   /* lengths of streams */
00276   uint32 lengths[ZOOM_LVL_COUNT][2];
00277 
00278   for (ZoomLevel z = ZOOM_LVL_BEGIN; z <= ZOOM_LVL_BEGIN; z++) {
00279     const SpriteLoader::Sprite *src_orig = ResizeSprite(sprite, z);
00280 
00281     uint size = src_orig->height * src_orig->width;
00282 
00283     dst_px_orig[z] = CallocT<Colour>(size + src_orig->height * 2);
00284     dst_n_orig[z]  = CallocT<uint8>(size * 2 + src_orig->height * 4 * 2);
00285 
00286     uint32 *dst_px_ln = (uint32 *)dst_px_orig[z];
00287     uint32 *dst_n_ln  = (uint32 *)dst_n_orig[z];
00288 
00289     const SpriteLoader::CommonPixel *src = (const SpriteLoader::CommonPixel *)src_orig->data;
00290 
00291     for (uint y = src_orig->height; y > 0; y--) {
00292       Colour *dst_px = (Colour *)(dst_px_ln + 1);
00293       uint8 *dst_n = (uint8 *)(dst_n_ln + 1);
00294 
00295       uint8 *dst_len = dst_n++;
00296 
00297       uint last = 3;
00298       int len = 0;
00299 
00300       for (uint x = src_orig->width; x > 0; x--) {
00301         uint8 a = src->a;
00302         uint t = a > 0 && a < 255 ? 1 : a;
00303 
00304         if (last != t || len == 255) {
00305           if (last != 3) {
00306             *dst_len = len;
00307             dst_len = dst_n++;
00308           }
00309           len = 0;
00310         }
00311 
00312         last = t;
00313         len++;
00314 
00315         if (a != 0) {
00316           dst_px->a = a;
00317           *dst_n = src->m;
00318 
00319           dst_px->r = src->r;
00320           dst_px->g = src->g;
00321           dst_px->b = src->b;
00322 
00323           dst_px++;
00324           dst_n++;
00325         } else if (len == 1) {
00326           dst_px++;
00327           *dst_n = src->m;
00328           dst_n++;
00329         }
00330 
00331         src++;
00332       }
00333 
00334       if (last != 3) {
00335         *dst_len = len;
00336       }
00337 
00338       dst_px = (Colour *)AlignPtr(dst_px, 4);
00339       dst_n  = (uint8 *)AlignPtr(dst_n, 4);
00340 
00341       *dst_px_ln = (uint8 *)dst_px - (uint8 *)dst_px_ln;
00342       *dst_n_ln  = (uint8 *)dst_n  - (uint8 *)dst_n_ln;
00343 
00344       dst_px_ln = (uint32 *)dst_px;
00345       dst_n_ln =  (uint32 *)dst_n;
00346     }
00347 
00348     lengths[z][0] = (byte *)dst_px_ln - (byte *)dst_px_orig[z]; // all are aligned to 4B boundary
00349     lengths[z][1] = (byte *)dst_n_ln  - (byte *)dst_n_orig[z];
00350 
00351   }
00352 
00353   uint len = 0; // total length of data
00354   for (ZoomLevel z = ZOOM_LVL_BEGIN; z <= ZOOM_LVL_BEGIN; z++) {
00355     len += lengths[z][0] + lengths[z][1];
00356   }
00357 
00358   Sprite *dest_sprite = (Sprite *)allocator(sizeof(*dest_sprite) + sizeof(SpriteData) + len);
00359 
00360   dest_sprite->height = sprite->height;
00361   dest_sprite->width  = sprite->width;
00362   dest_sprite->x_offs = sprite->x_offs;
00363   dest_sprite->y_offs = sprite->y_offs;
00364 
00365   SpriteData *dst = (SpriteData *)dest_sprite->data;
00366 
00367   ZoomLevel z = ZOOM_LVL_BEGIN;
00368   dst->offset[z][0] = 0;
00369   dst->offset[z][1] = lengths[z][0] + dst->offset[z][0];
00370 
00371   memcpy(dst->data + dst->offset[z][0], dst_px_orig[z], lengths[z][0]);
00372   memcpy(dst->data + dst->offset[z][1], dst_n_orig[z],  lengths[z][1]);
00373 
00374   free(dst_px_orig[z]);
00375   free(dst_n_orig[z]);
00376 
00377   return dest_sprite;
00378 }
00379 
00380 void Blitter_32bppOptimized::RescaleSpriteHalfSize(const SpriteLoader::Sprite *src_sprite,
00381                                       SpriteLoader::Sprite *dest_sprite,
00382                                       bool                 prevent_alpha_bleeding)
00383 {
00384   SpriteLoader::CommonPixel *dst;
00385   SpriteLoader::CommonPixel *src;
00386   int width, height;
00387   int x, y;
00388   bool  extra_px_x = false;
00389   bool  extra_px_y = false;
00390 
00391   SpriteLoader::CommonPixel clr;
00392 
00393   width = (src_sprite->width + 1) / 2;
00394   height = (src_sprite->height + 1) / 2;
00395 
00396   /* src sprite width is odd, just copy last pixel iso taking average */
00397   if (src_sprite->width & 1) {
00398     extra_px_x = true;
00399   }
00400   /* src sprite height is odd, just copy last pixel iso taking average */
00401   if (src_sprite->height & 1) {
00402     extra_px_y = true;
00403   }
00404 
00405 
00406   dest_sprite->data = CallocT<SpriteLoader::CommonPixel>(height * width);
00407   dst = (SpriteLoader::CommonPixel *)dest_sprite->data;
00408   src = (SpriteLoader::CommonPixel *)src_sprite->data;
00409 
00410   dest_sprite->width = width ;
00411   dest_sprite->height = height;
00412 
00413   dest_sprite->x_offs = src_sprite->x_offs / 2;
00414   dest_sprite->y_offs = src_sprite->y_offs / 2;
00415 
00416   for (y = 0; y < height + (extra_px_y ? -1 : 0); y++) {
00417     for (x = 0; x < width + (extra_px_x ? -1 : 0); x++) {
00418         uint ma = 0;
00419         uint a = 0;
00420         uint r = 0;
00421         uint g = 0;
00422         uint b = 0;
00423         uint i;
00424         uint j;
00425 
00426         for (i = 0; i < 2; i++) {
00427           for (j = 0; j < 2; j++) {
00428             uint ca;
00429             uint cr;
00430             uint cg;
00431             uint cb;
00432 
00433             clr = src[((2 * y + i ) * src_sprite->width) + (2 * x + j )];
00434             ca = clr.a;
00435             cr = clr.r;
00436             cg = clr.g;
00437             cb = clr.b;
00438 
00439             a += ca;
00440             r += ca * cr;
00441             g += ca * cg;
00442             b += ca * cb;
00443             if (prevent_alpha_bleeding) {
00444               if (ca > ma) ma = ca;
00445             } else {
00446               ma += ca;
00447             }
00448           }
00449         }
00450 
00451         if (a == 0) {
00452           dst[y * width + x].r = 0;
00453           dst[y * width + x].g = 0;
00454           dst[y * width + x].b = 0;
00455           dst[y * width + x].a = 0;
00456           dst[y * width + x].m = 0;
00457         } else {
00458           r /= a;
00459           g /= a;
00460           b /= a;
00461           if (prevent_alpha_bleeding) {
00462             a = ma;
00463           } else {
00464             a /= 4;
00465           }
00466           dst[y * width + x].r = r;
00467           dst[y * width + x].g = g;
00468           dst[y * width + x].b = b;
00469           dst[y * width + x].a = a;
00470           dst[y * width + x].m = clr.m;
00471         }
00472     }
00473     if (extra_px_x) {
00474       clr = src[((2 * y ) * src_sprite->width) + (2 * x)];
00475       dst[y * width + x] = clr;
00476     }
00477   }
00478 
00479 }
00480 /*
00481 void Blitter_32bppOptimized::RescaleSpriteDoubleSizePrev(const SpriteLoader::Sprite *src_sprite,
00482                                         SpriteLoader::Sprite *dest_sprite)
00483 {
00484   int width, height;
00485   SpriteLoader::CommonPixel *dst;
00486   SpriteLoader::CommonPixel *src;
00487 
00488   width = src_sprite->width * 2;
00489   height = src_sprite->height * 2;
00490 
00491   dest_sprite->data = CallocT<SpriteLoader::CommonPixel>(height * width);
00492   dst = (SpriteLoader::CommonPixel *)dest_sprite->data;
00493   src = (SpriteLoader::CommonPixel *)src_sprite->data;
00494 
00495   dest_sprite->width = width;
00496   dest_sprite->height = height;
00497   dest_sprite->x_offs = src_sprite->x_offs * 2;
00498   dest_sprite->y_offs = src_sprite->y_offs * 2;
00499 
00500   uint dst_y = 0;
00501   uint src_y_idx = 0;
00502   for (int y = 0; y < src_sprite->height - 1; y++) {
00503      int x;
00504 
00505     uint dst_x = 0;
00506     for (x = 0; x < src_sprite->width - 1; x++) {
00507       dst[dst_y + dst_x] = src[src_y_idx + x];
00508       dst_x++;
00509       dst[dst_y + dst_x].r = (src[src_y_idx + x + 1].r + src[src_y_idx + x].r) / 2;
00510       dst[dst_y + dst_x].g = (src[src_y_idx + x + 1].g + src[src_y_idx + x].g) / 2;
00511       dst[dst_y + dst_x].b = (src[src_y_idx + x + 1].b + src[src_y_idx + x].b) / 2;
00512       dst[dst_y + dst_x].a = (src[src_y_idx + x + 1].a + src[src_y_idx + x].a) / 2;
00513       dst[dst_y + dst_x].m =  src[src_y_idx + x].m;
00514       dst_x--;
00515       dst_y += width;
00516       dst[dst_y + dst_x].r = (src[src_y_idx + x].r + src[src_y_idx + src_sprite->width + x].r) / 2;
00517       dst[dst_y + dst_x].g = (src[src_y_idx + x].g + src[src_y_idx + src_sprite->width + x].g) / 2;
00518       dst[dst_y + dst_x].b = (src[src_y_idx + x].b + src[src_y_idx + src_sprite->width + x].b) / 2;
00519       dst[dst_y + dst_x].a = (src[src_y_idx + x].a + src[src_y_idx + src_sprite->width + x].a) / 2;
00520       dst[dst_y + dst_x].m =  src[src_y_idx + x].m;
00521       dst_x++;
00522       dst[dst_y + dst_x].r = (src[src_y_idx + x].r + src[src_y_idx + src_sprite->width + x].r +
00523                               src[src_y_idx + x + 1].r + src[src_y_idx + src_sprite->width + x + 1].r ) / 4;
00524       dst[dst_y + dst_x].g = (src[src_y_idx + x].g + src[src_y_idx + src_sprite->width + x].g +
00525                               src[src_y_idx + x + 1].g + src[src_y_idx + src_sprite->width + x + 1].g ) / 4;
00526       dst[dst_y + dst_x].b = (src[src_y_idx + x].b + src[src_y_idx + src_sprite->width + x].b +
00527                               src[src_y_idx + x + 1].b + src[src_y_idx + src_sprite->width + x + 1].b ) / 4;
00528       dst[dst_y + dst_x].a = (src[src_y_idx + x].a + src[src_y_idx + src_sprite->width + x].a +
00529                               src[src_y_idx + x + 1].a + src[src_y_idx + src_sprite->width + x + 1].a ) / 4;
00530       dst[dst_y + dst_x].m =  src[src_y_idx + x].m;
00531       dst_y -= width;
00532       dst_x++;
00533     }
00534 
00535      last pixels in row cannot be interpolated */
00536 /*     dst[dst_y + dst_x] = src[src_y_idx + x];
00537     dst_x++;
00538     dst[dst_y + dst_x] = src[src_y_idx + x];
00539     dst_x--;
00540     dst_y += width;
00541     dst[dst_y + dst_x].r = (src[src_y_idx + x].r + src[src_y_idx + src_sprite->width + x].r) / 2;
00542     dst[dst_y + dst_x].g = (src[src_y_idx + x].g + src[src_y_idx + src_sprite->width + x].g) / 2;
00543     dst[dst_y + dst_x].b = (src[src_y_idx + x].b + src[src_y_idx + src_sprite->width + x].b) / 2;
00544     dst[dst_y + dst_x].a = (src[src_y_idx + x].a + src[src_y_idx + src_sprite->width + x].a) / 2;
00545     dst[dst_y + dst_x].m =  src[src_y_idx + x].m;
00546     dst_x++;
00547     dst[dst_y + dst_x].r = (src[src_y_idx + x].r + src[src_y_idx + src_sprite->width + x].r) / 2;
00548     dst[dst_y + dst_x].g = (src[src_y_idx + x].g + src[src_y_idx + src_sprite->width + x].g) / 2;
00549     dst[dst_y + dst_x].b = (src[src_y_idx + x].b + src[src_y_idx + src_sprite->width + x].b) / 2;
00550     dst[dst_y + dst_x].a = (src[src_y_idx + x].a + src[src_y_idx + src_sprite->width + x].a) / 2;
00551     dst[dst_y + dst_x].m =  src[src_y_idx + x].m;
00552 
00553     dst_y += width;
00554     src_y_idx += src_sprite->width;
00555   }
00556    last row can not be interpolated */
00557 /* uint dst_x = 0;
00558   for (int x = 0; x < src_sprite->width - 1; x++) {
00559     dst[dst_y + dst_x] = src[src_y_idx + x];
00560     dst_x++;
00561     dst[dst_y + dst_x].r = (src[src_y_idx + x + 1].r + src[src_y_idx + x].r) / 2;
00562     dst[dst_y + dst_x].g = (src[src_y_idx + x + 1].g + src[src_y_idx + x].g) / 2;
00563     dst[dst_y + dst_x].b = (src[src_y_idx + x + 1].b + src[src_y_idx + x].b) / 2;
00564     dst[dst_y + dst_x].a = (src[src_y_idx + x + 1].a + src[src_y_idx + x].a) / 2;
00565     dst[dst_y + dst_x].m =  src[src_y_idx + x].m;
00566     dst_x--;
00567     dst_y += width;
00568     dst[dst_y + dst_x] = src[src_y_idx + x];
00569     dst_x++;
00570     dst[dst_y + dst_x].r = (src[src_y_idx + x + 1].r + src[src_y_idx + x].r) / 2;
00571     dst[dst_y + dst_x].g = (src[src_y_idx + x + 1].g + src[src_y_idx + x].g) / 2;
00572     dst[dst_y + dst_x].b = (src[src_y_idx + x + 1].b + src[src_y_idx + x].b) / 2;
00573     dst[dst_y + dst_x].a = (src[src_y_idx + x + 1].a + src[src_y_idx + x].a) / 2;
00574     dst[dst_y + dst_x].m =  src[src_y_idx + x].m;
00575     dst_y -= width;
00576     dst_x++;
00577   }
00578 }
00579 
00580 */
00581 
00582 void Blitter_32bppOptimized::RescaleSpriteDoubleSize(const SpriteLoader::Sprite *src_sprite,
00583                                         SpriteLoader::Sprite *dest_sprite)
00584 {
00585   int width, height;
00586   SpriteLoader::CommonPixel *dst;
00587   SpriteLoader::CommonPixel *src;
00588 
00589   width = src_sprite->width * 2;
00590   height = src_sprite->height * 2;
00591 
00592   dest_sprite->data = CallocT<SpriteLoader::CommonPixel>(height * width);
00593   dst = (SpriteLoader::CommonPixel *)dest_sprite->data;
00594   src = (SpriteLoader::CommonPixel *)src_sprite->data;
00595 
00596   dest_sprite->width = width;
00597   dest_sprite->height = height;
00598   dest_sprite->x_offs = src_sprite->x_offs * 2;
00599   dest_sprite->y_offs = src_sprite->y_offs * 2;
00600   SpriteLoader::CommonPixel B, D, E, H, F;
00601   SpriteLoader::CommonPixel E0, E1, E2, E3;
00602   uint dst_y = 0;
00603   uint src_y_idx = 0;
00604   for (int y = 0; y < src_sprite->height ; y++) {
00605     int x;
00606 
00607     uint dst_x = 0;
00608     for (x = 0; x < src_sprite->width - 1; x++) {
00609       E = src[src_y_idx + x];
00610       if (src_y_idx) {
00611         B = src[src_y_idx + x - src_sprite->width];
00612       } else {
00613         B = src[src_y_idx + x];
00614       }
00615       if (x) {
00616         D = src[src_y_idx + x - 1];
00617       } else {
00618         D = src[src_y_idx + x ];
00619       }
00620       if (x < src_sprite->width - 1){
00621         F = src[src_y_idx + x + 1];
00622       } else {
00623         F = src[src_y_idx + x ];
00624       }
00625       if (y < src_sprite->height - 1){
00626         H = src[src_y_idx + x + src_sprite->width];
00627       } else {
00628         H = src[src_y_idx + x];
00629       }
00630       if ((B.r != H.r && D.r != F.r) ||
00631         (B.g != H.g && D.g != F.g) ||
00632         (B.b != H.b && D.b != F.b) ||
00633         (B.a != H.a && D.a != F.a))
00634        {
00635         if ((D.r == B.r) &&
00636           (D.g == B.g) &&
00637           (D.b == B.b) &&
00638           (D.a == B.a)) {
00639           E0 = D;
00640         } else {
00641           E0 = E;
00642         }
00643         if ((B.r == F.r) &&
00644           (B.g == F.g) &&
00645           (B.b == F.b) &&
00646           (B.a == F.a)) {
00647           E1 = F;
00648         } else {
00649           E1 = E;
00650         }
00651         if ((D.r == H.r) &&
00652           (D.g == H.g) &&
00653           (D.b == H.b) &&
00654           (D.a == H.a)) {
00655           E2 = D;
00656         } else {
00657           E2 = E;
00658         }
00659         if ((H.r == F.r) &&
00660           (H.g == F.g) &&
00661           (H.b == F.b) &&
00662           (H.a == F.a)) {
00663           E3 = F;
00664         } else {
00665           E3 = E;
00666         }
00667       } else {
00668         E0 = E;
00669         E1 = E;
00670         E2 = E;
00671         E3 = E;
00672       }
00673       dst[dst_y + dst_x] = E0;
00674       dst_x++;
00675       dst[dst_y + dst_x] = E1;
00676       dst_x--;
00677       dst_y += width;
00678       dst[dst_y + dst_x] = E2;
00679       dst_x++;
00680       dst[dst_y + dst_x] = E3;
00681       dst_y -= width;
00682       dst_x++;
00683     }
00684 
00685     dst_y += width;
00686 dst_y += width;
00687     src_y_idx += src_sprite->width;
00688   }
00689 }
00690 
00691 void Blitter_32bppOptimized::FillRGBFromPalette(SpriteLoader::Sprite *sprite)
00692 {
00693   SpriteLoader::CommonPixel *spr = sprite->data;
00694 
00695   for (uint y = 0; y < sprite->height; y++) {
00696     uint y_idx  = y * sprite->width;
00697     for (uint x = 0; x < sprite->width; x++) {
00698       if (spr[y_idx + x].a == 0) {
00699         spr[y_idx + x].r = 0;
00700         spr[y_idx + x].g = 0;
00701         spr[y_idx + x].b = 0;
00702         spr[y_idx + x].m = 0;
00703       } else {
00704         if (spr[y_idx + x].m != 0) {
00705           /* Pre-convert the mapping channel to a RGB value */
00706           uint color = this->LookupColourInPalette(spr[y_idx + x].m);
00707           spr[y_idx + x].r = GB(color, 16, 8);
00708           spr[y_idx + x].g = GB(color, 8,  8);
00709           spr[y_idx + x].b = GB(color, 0,  8);
00710         }
00711       }
00712     }
00713   }
00714 }
00715 
00716 byte *Blitter_32bppOptimized::FillRGBPalette(SpriteID id, byte *remap_data)
00717 {
00718   for (int idx = 0; (idx < MAX_PALETTE_TABLES); idx++) {
00719     if ((id == _rgb_palettes[idx].id) || (_rgb_palettes[idx].id == 0)) { 
00720       _rgb_palettes[idx].id = id;
00721       for (int col_idx = 0; col_idx < 256; col_idx++) { 
00722         _rgb_palettes[idx].tables[col_idx].data = this->LookupColourInPalette(remap_data[col_idx + 1]);
00723       }
00724       return (byte *)&(_rgb_palettes[idx].tables[0]);
00725     }
00726   }
00727   error("No more rgb palette tables available");
00728   return NULL;
00729 }
00730 

Generated on Sun Jan 23 01:49:00 2011 for OpenTTD by  doxygen 1.6.1