00001
00002
00003
00004
00005
00006
00007
00008
00009
00012 #include "../stdafx.h"
00013 #include "../zoom_func.h"
00014 #include "../settings_type.h"
00015 #include "../core/math_func.hpp"
00016 #include "32bpp_optimized.hpp"
00017
00019 static FBlitter_32bppOptimized iFBlitter_32bppOptimized;
00020
00028 template <BlitterMode mode>
00029 inline void Blitter_32bppOptimized::Draw(const Blitter::BlitterParams *bp, ZoomLevel zoom)
00030 {
00031 const SpriteData *src = (const SpriteData *)bp->sprite;
00032
00033
00034
00035 const Colour *src_px = (const Colour *)(src->data + src->offset[zoom][0]);
00036
00037
00038
00039 const uint16 *src_n = (const uint16 *)(src->data + src->offset[zoom][1]);
00040
00041
00042 for (uint i = bp->skip_top; i != 0; i--) {
00043 src_px = (const Colour *)((const byte *)src_px + *(const uint32 *)src_px);
00044 src_n = (const uint16 *)((const byte *)src_n + *(const uint32 *)src_n);
00045 }
00046
00047
00048 uint32 *dst = (uint32 *)bp->dst + bp->top * bp->pitch + bp->left;
00049
00050
00051 const byte *remap = bp->remap;
00052
00053 for (int y = 0; y < bp->height; y++) {
00054
00055 uint32 *dst_ln = dst + bp->pitch;
00056
00057
00058 const Colour *src_px_ln = (const Colour *)((const byte *)src_px + *(const uint32 *)src_px);
00059 src_px++;
00060
00061
00062 const uint16 *src_n_ln = (const uint16 *)((const byte *)src_n + *(const uint32 *)src_n);
00063 src_n += 2;
00064
00065
00066 uint32 *dst_end = dst + bp->skip_left;
00067
00068
00069 uint n;
00070
00071 while (dst < dst_end) {
00072 n = *src_n++;
00073
00074 if (src_px->a == 0) {
00075 dst += n;
00076 src_px ++;
00077 src_n++;
00078 } else {
00079 if (dst + n > dst_end) {
00080 uint d = dst_end - dst;
00081 src_px += d;
00082 src_n += d;
00083
00084 dst = dst_end - bp->skip_left;
00085 dst_end = dst + bp->width;
00086
00087 n = min<uint>(n - d, (uint)bp->width);
00088 goto draw;
00089 }
00090 dst += n;
00091 src_px += n;
00092 src_n += n;
00093 }
00094 }
00095
00096 dst -= bp->skip_left;
00097 dst_end -= bp->skip_left;
00098
00099 dst_end += bp->width;
00100
00101 while (dst < dst_end) {
00102 n = min<uint>(*src_n++, (uint)(dst_end - dst));
00103
00104 if (src_px->a == 0) {
00105 dst += n;
00106 src_px++;
00107 src_n++;
00108 continue;
00109 }
00110
00111 draw:;
00112
00113 switch (mode) {
00114 case BM_COLOUR_REMAP:
00115 if (src_px->a == 255) {
00116 do {
00117 uint m = *src_n;
00118
00119 if (m == 0) {
00120 *dst = src_px->data;
00121 } else {
00122 uint r = remap[GB(m, 0, 8)];
00123 if (r != 0) *dst = this->AdjustBrightness(this->LookupColourInPalette(r), GB(m, 8, 8));
00124 }
00125 dst++;
00126 src_px++;
00127 src_n++;
00128 } while (--n != 0);
00129 } else {
00130 do {
00131 uint m = *src_n;
00132 if (m == 0) {
00133 *dst = ComposeColourRGBANoCheck(src_px->r, src_px->g, src_px->b, src_px->a, *dst);
00134 } else {
00135 uint r = remap[GB(m, 0, 8)];
00136 if (r != 0) *dst = ComposeColourPANoCheck(this->AdjustBrightness(this->LookupColourInPalette(r), GB(m, 8, 8)), src_px->a, *dst);
00137 }
00138 dst++;
00139 src_px++;
00140 src_n++;
00141 } while (--n != 0);
00142 }
00143 break;
00144
00145 case BM_TRANSPARENT:
00146
00147
00148
00149
00150
00151 src_n += n;
00152 if (src_px->a == 255) {
00153 src_px += n;
00154 do {
00155 *dst = MakeTransparent(*dst, 3, 4);
00156 dst++;
00157 } while (--n != 0);
00158 } else {
00159 do {
00160 *dst = MakeTransparent(*dst, (256 * 4 - src_px->a), 256 * 4);
00161 dst++;
00162 src_px++;
00163 } while (--n != 0);
00164 }
00165 break;
00166
00167 default:
00168 if (src_px->a == 255) {
00169
00170 src_n += n;
00171 do {
00172 *dst = src_px->data;
00173 dst++;
00174 src_px++;
00175 } while (--n != 0);
00176 } else {
00177 src_n += n;
00178 do {
00179 *dst = ComposeColourRGBANoCheck(src_px->r, src_px->g, src_px->b, src_px->a, *dst);
00180 dst++;
00181 src_px++;
00182 } while (--n != 0);
00183 }
00184 break;
00185 }
00186 }
00187
00188 dst = dst_ln;
00189 src_px = src_px_ln;
00190 src_n = src_n_ln;
00191 }
00192 }
00193
00201 void Blitter_32bppOptimized::Draw(Blitter::BlitterParams *bp, BlitterMode mode, ZoomLevel zoom)
00202 {
00203 switch (mode) {
00204 default: NOT_REACHED();
00205 case BM_NORMAL: Draw<BM_NORMAL> (bp, zoom); return;
00206 case BM_COLOUR_REMAP: Draw<BM_COLOUR_REMAP>(bp, zoom); return;
00207 case BM_TRANSPARENT: Draw<BM_TRANSPARENT> (bp, zoom); return;
00208 }
00209 }
00210
00218 static const SpriteLoader::Sprite *ResizeSprite(const SpriteLoader::Sprite *sprite_src, ZoomLevel zoom)
00219 {
00220 SpriteLoader::Sprite *sprite = MallocT<SpriteLoader::Sprite>(1);
00221
00222 if (zoom == ZOOM_LVL_NORMAL) {
00223 memcpy(sprite, sprite_src, sizeof(*sprite));
00224 uint size = sprite_src->height * sprite_src->width;
00225 sprite->data = MallocT<SpriteLoader::CommonPixel>(size);
00226 memcpy(sprite->data, sprite_src->data, size * sizeof(SpriteLoader::CommonPixel));
00227 return sprite;
00228 }
00229
00230 sprite->height = UnScaleByZoom(sprite_src->height, zoom);
00231 sprite->width = UnScaleByZoom(sprite_src->width, zoom);
00232 sprite->x_offs = UnScaleByZoom(sprite_src->x_offs, zoom);
00233 sprite->y_offs = UnScaleByZoom(sprite_src->y_offs, zoom);
00234
00235 uint size = sprite->height * sprite->width;
00236 SpriteLoader::CommonPixel *dst = sprite->data = CallocT<SpriteLoader::CommonPixel>(size);
00237
00238 const SpriteLoader::CommonPixel *src = (SpriteLoader::CommonPixel *)sprite_src->data;
00239 const SpriteLoader::CommonPixel *src_end = src + sprite_src->height * sprite_src->width;
00240
00241 uint scaled_1 = ScaleByZoom(1, zoom);
00242
00243 for (uint y = 0; y < sprite->height; y++) {
00244 if (src >= src_end) src = src_end - sprite_src->width;
00245
00246 const SpriteLoader::CommonPixel *src_ln = src + sprite_src->width * scaled_1;
00247 for (uint x = 0; x < sprite->width; x++) {
00248 if (src >= src_ln) src = src_ln - 1;
00249 *dst = *src;
00250 dst++;
00251 src += scaled_1;
00252 }
00253
00254 src = src_ln;
00255 }
00256
00257 return sprite;
00258 }
00259
00260 Sprite *Blitter_32bppOptimized::Encode(SpriteLoader::Sprite *sprite, AllocatorProc *allocator)
00261 {
00262
00263
00264
00265 Colour *dst_px_orig[ZOOM_LVL_COUNT];
00266
00267
00268
00269
00270
00271
00272
00273 uint16 *dst_n_orig[ZOOM_LVL_COUNT];
00274
00275
00276 uint32 lengths[ZOOM_LVL_COUNT][2];
00277
00278 ZoomLevel zoom_min;
00279 ZoomLevel zoom_max;
00280
00281 if (sprite->type == ST_FONT) {
00282 zoom_min = ZOOM_LVL_NORMAL;
00283 zoom_max = ZOOM_LVL_NORMAL;
00284 } else {
00285 zoom_min = _settings_client.gui.zoom_min;
00286 zoom_max = _settings_client.gui.zoom_max;
00287 if (zoom_max == zoom_min) zoom_max = ZOOM_LVL_MAX;
00288 }
00289
00290 for (ZoomLevel z = zoom_min; z <= zoom_max; z++) {
00291 const SpriteLoader::Sprite *src_orig = ResizeSprite(sprite, z);
00292
00293 uint size = src_orig->height * src_orig->width;
00294
00295 dst_px_orig[z] = CallocT<Colour>(size + src_orig->height * 2);
00296 dst_n_orig[z] = CallocT<uint16>(size * 2 + src_orig->height * 4 * 2);
00297
00298 uint32 *dst_px_ln = (uint32 *)dst_px_orig[z];
00299 uint32 *dst_n_ln = (uint32 *)dst_n_orig[z];
00300
00301 const SpriteLoader::CommonPixel *src = (const SpriteLoader::CommonPixel *)src_orig->data;
00302
00303 for (uint y = src_orig->height; y > 0; y--) {
00304 Colour *dst_px = (Colour *)(dst_px_ln + 1);
00305 uint16 *dst_n = (uint16 *)(dst_n_ln + 1);
00306
00307 uint16 *dst_len = dst_n++;
00308
00309 uint last = 3;
00310 int len = 0;
00311
00312 for (uint x = src_orig->width; x > 0; x--) {
00313 uint8 a = src->a;
00314 uint t = a > 0 && a < 255 ? 1 : a;
00315
00316 if (last != t || len == 65535) {
00317 if (last != 3) {
00318 *dst_len = len;
00319 dst_len = dst_n++;
00320 }
00321 len = 0;
00322 }
00323
00324 last = t;
00325 len++;
00326
00327 if (a != 0) {
00328 dst_px->a = a;
00329 *dst_n = src->m;
00330 if (src->m != 0) {
00331
00332 uint8 rgb_max = max(src->r, max(src->g, src->b));
00333
00334
00335 if (rgb_max == 0) rgb_max = DEFAULT_BRIGHTNESS;
00336 *dst_n |= rgb_max << 8;
00337
00338
00339 uint32 colour = this->AdjustBrightness(this->LookupColourInPalette(src->m), rgb_max);
00340 dst_px->r = GB(colour, 16, 8);
00341 dst_px->g = GB(colour, 8, 8);
00342 dst_px->b = GB(colour, 0, 8);
00343 } else {
00344 dst_px->r = src->r;
00345 dst_px->g = src->g;
00346 dst_px->b = src->b;
00347 }
00348 dst_px++;
00349 dst_n++;
00350 } else if (len == 1) {
00351 dst_px++;
00352 *dst_n = src->m;
00353 dst_n++;
00354 }
00355
00356 src++;
00357 }
00358
00359 if (last != 3) {
00360 *dst_len = len;
00361 }
00362
00363 dst_px = (Colour *)AlignPtr(dst_px, 4);
00364 dst_n = (uint16 *)AlignPtr(dst_n, 4);
00365
00366 *dst_px_ln = (uint8 *)dst_px - (uint8 *)dst_px_ln;
00367 *dst_n_ln = (uint8 *)dst_n - (uint8 *)dst_n_ln;
00368
00369 dst_px_ln = (uint32 *)dst_px;
00370 dst_n_ln = (uint32 *)dst_n;
00371 }
00372
00373 lengths[z][0] = (byte *)dst_px_ln - (byte *)dst_px_orig[z];
00374 lengths[z][1] = (byte *)dst_n_ln - (byte *)dst_n_orig[z];
00375
00376 free(src_orig->data);
00377 free(src_orig);
00378 }
00379
00380 uint len = 0;
00381 for (ZoomLevel z = zoom_min; z <= zoom_max; z++) {
00382 len += lengths[z][0] + lengths[z][1];
00383 }
00384
00385 Sprite *dest_sprite = (Sprite *)allocator(sizeof(*dest_sprite) + sizeof(SpriteData) + len);
00386
00387 dest_sprite->height = sprite->height;
00388 dest_sprite->width = sprite->width;
00389 dest_sprite->x_offs = sprite->x_offs;
00390 dest_sprite->y_offs = sprite->y_offs;
00391
00392 SpriteData *dst = (SpriteData *)dest_sprite->data;
00393
00394 for (ZoomLevel z = zoom_min; z <= zoom_max; z++) {
00395 dst->offset[z][0] = z == zoom_min ? 0 : lengths[z - 1][1] + dst->offset[z - 1][1];
00396 dst->offset[z][1] = lengths[z][0] + dst->offset[z][0];
00397
00398 memcpy(dst->data + dst->offset[z][0], dst_px_orig[z], lengths[z][0]);
00399 memcpy(dst->data + dst->offset[z][1], dst_n_orig[z], lengths[z][1]);
00400
00401 free(dst_px_orig[z]);
00402 free(dst_n_orig[z]);
00403 }
00404
00405 return dest_sprite;
00406 }