void Blitter_16bppAnim::Draw(const Blitter::BlitterParams *bp, ZoomLevel zoom) { const Pixel *src, *src_line; Colour16 *dst, *dst_line; Anim *anim, *anim_line; /* Find where to start reading in the source sprite */ src_line = (const Pixel *)bp->sprite + (bp->skip_top * bp->sprite_width + bp->skip_left) * ScaleByZoom(1, zoom); dst_line = (Colour16 *)bp->dst + bp->top * bp->pitch + bp->left; anim_line = this->anim_buf + ((Colour16 *)bp->dst - (Colour16 *)_screen.dst_ptr) + bp->top * this->anim_buf_width + bp->left; for (int y = 0; y < bp->height; y++) { dst = dst_line; dst_line += bp->pitch; src = src_line; src_line += bp->sprite_width * ScaleByZoom(1, zoom); anim = anim_line; anim_line += this->anim_buf_width; for (int x = 0; x < bp->width; x++) { switch (mode) { case BM_COLOUR_REMAP: /* In case the m-channel is zero, do not remap this pixel in any way */ anim->m = 0; anim->v = 0; if (src->m == 0) { if (src->a != 0) *dst = ComposeColourPA(src->c, src->a, *dst); } else { uint8 r = bp->remap[src->m]; if (r != 0) { *dst = ComposeColourPA(AdjustBrightness(LookupColourInPalette(r), src->v), src->a, *dst); if (src->a == 15 && r >= PALETTE_ANIM_START) { anim->m = r - PALETTE_ANIM_START + 1; anim->v = src->v >> 1; } } } break; case BM_TRANSPARENT: /* TODO -- We make an assumption here that the remap in fact is transparency, not some colour. * This is never a problem with the code we produce, but newgrfs can make it fail... or at least: * we produce a result the newgrf maker didn't expect ;) */ /* Make the current colour a bit more black, so it looks like this image is transparent */ if (src->a != 0) *dst = MakeTransparent(*dst, 192); anim->m = 0; anim->v = 0; break; default: if (src->a == 15 && src->m >= PALETTE_ANIM_START) { *dst = AdjustBrightness(LookupColourInPalette(src->m), src->v); anim->m = src->m - PALETTE_ANIM_START + 1; anim->v = src->v >> 1; } else { if (src->a != 0) {
void Blitter_32bppAnim::DrawRect(void *video, int width, int height, uint8 colour) { if (_screen_disable_anim) { /* This means our output is not to the screen, so we can't be doing any animation stuff, so use our parent DrawRect() */ Blitter_32bppOptimized::DrawRect(video, width, height, colour); return; } Colour colour32 = LookupColourInPalette(colour); uint16 *anim_line; anim_line = ((uint32 *)video - (uint32 *)_screen.dst_ptr) + this->anim_buf; do { Colour *dst = (Colour *)video; uint16 *anim = anim_line; for (int i = width; i > 0; i--) { *dst = colour32; /* Set the colour in the anim-buffer too */ *anim = colour | (DEFAULT_BRIGHTNESS << 8); dst++; anim++; } video = (uint32 *)video + _screen.pitch; anim_line += this->anim_buf_width; } while (--height); }
void Blitter_32bppAnim::PaletteAnimate(const Palette &palette) { assert(!_screen_disable_anim); this->palette = palette; /* If first_dirty is 0, it is for 8bpp indication to send the new * palette. However, only the animation colours might possibly change. * Especially when going between toyland and non-toyland. */ assert(this->palette.first_dirty == PALETTE_ANIM_START || this->palette.first_dirty == 0); const uint16 *anim = this->anim_buf; Colour *dst = (Colour *)_screen.dst_ptr; /* Let's walk the anim buffer and try to find the pixels */ for (int y = this->anim_buf_height; y != 0 ; y--) { for (int x = this->anim_buf_width; x != 0 ; x--) { uint colour = GB(*anim, 0, 8); if (colour >= PALETTE_ANIM_START) { /* Update this pixel */ *dst = this->AdjustBrightness(LookupColourInPalette(colour), GB(*anim, 8, 8)); } dst++; anim++; } dst += _screen.pitch - this->anim_buf_width; } /* Make sure the backend redraws the whole screen */ _video_driver->MakeDirty(0, 0, _screen.width, _screen.height); }
void Blitter_32bppAnim::PaletteAnimate(uint start, uint count) { assert(!_screen_disable_anim); /* Never repaint the transparency pixel */ if (start == 0) { start++; count--; } const uint8 *anim = this->anim_buf; uint32 *dst = (uint32 *)_screen.dst_ptr; /* Let's walk the anim buffer and try to find the pixels */ for (int y = this->anim_buf_height; y != 0 ; y--) { for (int x = this->anim_buf_width; x != 0 ; x--) { uint colour = *anim; if (IsInsideBS(colour, start, count)) { /* Update this pixel */ *dst = LookupColourInPalette(colour); } dst++; anim++; } dst += _screen.pitch - this->anim_buf_width; } /* Make sure the backend redraws the whole screen */ _video_driver->MakeDirty(0, 0, _screen.width, _screen.height); }
void Blitter_32bppAnim::SetPixel(void *video, int x, int y, uint8 colour) { *((Colour *)video + x + y * _screen.pitch) = LookupColourInPalette(colour); /* Set the colour in the anim-buffer too, if we are rendering to the screen */ if (_screen_disable_anim) return; this->anim_buf[((uint32 *)video - (uint32 *)_screen.dst_ptr) + x + y * this->anim_buf_width] = colour | (DEFAULT_BRIGHTNESS << 8); }
void Blitter_32bppAnim::SetPixel(void *video, int x, int y, uint8 colour) { *((Colour *)video + x + y * _screen.pitch) = LookupColourInPalette(colour); /* Set the colour in the anim-buffer too, if we are rendering to the screen */ if (_screen_disable_anim) return; assert(_screen.pitch == this->anim_buf_pitch); // precondition for translating 'video' into an 'anim_buf' offset below. this->anim_buf[((uint32 *)video - (uint32 *)_screen.dst_ptr) + x + y * this->anim_buf_pitch] = colour | (DEFAULT_BRIGHTNESS << 8); }
void Blitter_32bppBase::DrawRect(void *video, int width, int height, uint8 colour) { Colour colour32 = LookupColourInPalette(colour); do { Colour *dst = (Colour *)video; for (int i = width; i > 0; i--) { *dst = colour32; dst++; } video = (uint32 *)video + _screen.pitch; } while (--height); }
Sprite *Blitter_16bppSimple::Encode(const SpriteLoader::Sprite *sprite, AllocatorProc *allocator) { Pixel *dst; Sprite *dest_sprite = (Sprite *)allocator(sizeof(*dest_sprite) + (size_t)sprite->height * (size_t)sprite->width * sizeof(Pixel)); dest_sprite->height = sprite->height; dest_sprite->width = sprite->width; dest_sprite->x_offs = sprite->x_offs; dest_sprite->y_offs = sprite->y_offs; dst = (Pixel *)dest_sprite->data; SpriteLoader::CommonPixel *src = (SpriteLoader::CommonPixel *)sprite->data; for (int i = 0; i < sprite->height * sprite->width; i++) { if (src->m == 0) { dst[i].c = To16(src->r, src->g, src->b); dst[i].a = src->a / 16; dst[i].m = 0; dst[i].v = 0; } else { /* Get brightest value */ uint8 rgb_max = max(src->r, max(src->g, src->b)); #if 0 /* Pre-convert the mapping channel to a RGB value, use 32bpp AdjustBrightness() variant for better colors, because this function is not called each frame */ if (rgb_max == 0) rgb_max = Blitter_32bppBase::DEFAULT_BRIGHTNESS; dst[i].c = To16(Blitter_32bppBase::AdjustBrightness(LookupColourInPalette32(src->m), rgb_max)); dst[i].v = rgb_max / 16; #endif rgb_max /= 16; /* Black pixel (8bpp or old 32bpp image), so use default value */ if (rgb_max == 0) rgb_max = DEFAULT_BRIGHTNESS; /* Pre-convert the mapping channel to a RGB value, use 32bpp AdjustBrightness() variant for better colors, because this function is not called each frame */ dst[i].c = AdjustBrightness(LookupColourInPalette(src->m), rgb_max); dst[i].v = rgb_max; dst[i].a = src->a / 16; dst[i].m = src->m; } src++; } return dest_sprite; }
void Blitter_32bppAnim::CopyFromBuffer(void *video, const void *src, int width, int height) { assert(!_screen_disable_anim); assert(video >= _screen.dst_ptr && video <= (uint32 *)_screen.dst_ptr + _screen.width + _screen.height * _screen.pitch); uint32 *dst = (uint32 *)video; uint32 *usrc = (uint32 *)src; uint8 *anim_line = ((uint32 *)video - (uint32 *)_screen.dst_ptr) + this->anim_buf; int count = (_use_palette == PAL_DOS) ? PALETTE_ANIM_SIZE_DOS : PALETTE_ANIM_SIZE_WIN; for (; height > 0; height--) { /* We need to keep those for palette animation. */ uint32 *dst_pal = dst; uint8 *anim_pal = anim_line; memcpy(dst, usrc, width * sizeof(uint32)); usrc += width; dst += _screen.pitch; /* Copy back the anim-buffer */ memcpy(anim_line, usrc, width * sizeof(uint8)); usrc = (uint32 *)((uint8 *)usrc + width); anim_line += this->anim_buf_width; /* Okay, it is *very* likely that the image we stored is using * the wrong palette animated colours. There are two things we * can do to fix this. The first is simply reviewing the whole * screen after we copied the buffer, i.e. run PaletteAnimate, * however that forces a full screen redraw which is expensive * for just the cursor. This just copies the implementation of * palette animation, much cheaper though slightly nastier. */ for (int i = 0; i < width; i++) { uint colour = *anim_pal; if (IsInsideBS(colour, PALETTE_ANIM_SIZE_START, count)) { /* Update this pixel */ *dst_pal = LookupColourInPalette(colour); } dst_pal++; anim_pal++; } } }
void Blitter_32bppAnim::CopyFromBuffer(void *video, const void *src, int width, int height) { assert(!_screen_disable_anim); assert(video >= _screen.dst_ptr && video <= (uint32 *)_screen.dst_ptr + _screen.width + _screen.height * _screen.pitch); Colour *dst = (Colour *)video; const uint32 *usrc = (const uint32 *)src; assert(_screen.pitch == this->anim_buf_pitch); // precondition for translating 'video' into an 'anim_buf' offset below. uint16 *anim_line = ((uint32 *)video - (uint32 *)_screen.dst_ptr) + this->anim_buf; for (; height > 0; height--) { /* We need to keep those for palette animation. */ Colour *dst_pal = dst; uint16 *anim_pal = anim_line; memcpy(dst, usrc, width * sizeof(uint32)); usrc += width; dst += _screen.pitch; /* Copy back the anim-buffer */ memcpy(anim_line, usrc, width * sizeof(uint16)); usrc = (const uint32 *)((const uint16 *)usrc + width); anim_line += this->anim_buf_pitch; /* Okay, it is *very* likely that the image we stored is using * the wrong palette animated colours. There are two things we * can do to fix this. The first is simply reviewing the whole * screen after we copied the buffer, i.e. run PaletteAnimate, * however that forces a full screen redraw which is expensive * for just the cursor. This just copies the implementation of * palette animation, much cheaper though slightly nastier. */ for (int i = 0; i < width; i++) { uint colour = GB(*anim_pal, 0, 8); if (colour >= PALETTE_ANIM_START) { /* Update this pixel */ *dst_pal = this->AdjustBrightness(LookupColourInPalette(colour), GB(*anim_pal, 8, 8)); } dst_pal++; anim_pal++; } } }
/* Make the current colour a bit more black, so it looks like this image is transparent */ if (src->a != 0) *dst = MakeTransparent(*dst, 192); anim->m = 0; anim->v = 0; break; default: if (src->a == 15 && src->m >= PALETTE_ANIM_START) { *dst = AdjustBrightness(LookupColourInPalette(src->m), src->v); anim->m = src->m - PALETTE_ANIM_START + 1; anim->v = src->v >> 1; } else { if (src->a != 0) { if (src->m >= PALETTE_ANIM_START) { *dst = ComposeColourPANoCheck(AdjustBrightness(LookupColourInPalette(src->m), src->v), src->a, *dst); } else { *dst = ComposeColourPA(src->c, src->a, *dst); } } anim->m = 0; anim->v = 0; } break; } dst++; src += ScaleByZoom(1, zoom); } } }
void Blitter_32bppBase::SetPixel(void *video, int x, int y, uint8 colour) { *((Colour *)video + x + y * _screen.pitch) = LookupColourInPalette(colour); }
void Blitter_16bppSimple::Draw(const Blitter::BlitterParams *bp, ZoomLevel zoom) { const Pixel *src, *src_line; Colour16 *dst, *dst_line; /* Find where to start reading in the source sprite */ src_line = (const Pixel *)bp->sprite + (bp->skip_top * bp->sprite_width + bp->skip_left) * ScaleByZoom(1, zoom); dst_line = (Colour16 *)bp->dst + bp->top * bp->pitch + bp->left; for (int y = 0; y < bp->height; y++) { dst = dst_line; dst_line += bp->pitch; src = src_line; src_line += bp->sprite_width * ScaleByZoom(1, zoom); for (int x = 0; x < bp->width; x++) { switch (mode) { case BM_COLOUR_REMAP: /* In case the m-channel is zero, do not remap this pixel in any way */ if (src->m == 0) { if (src->a != 0) *dst = ComposeColourPA(src->c, src->a, *dst); } else { if (bp->remap[src->m] != 0) *dst = ComposeColourPA(AdjustBrightness(LookupColourInPalette(bp->remap[src->m]), src->v), src->a, *dst); } break; case BM_CRASH_REMAP: if (src->m == 0) { if (src->a != 0) { uint8 g = MakeDark(src->c); *dst = ComposeColourRGBA(g, g, g, src->a, *dst); } } else { if (bp->remap[src->m] != 0) *dst = ComposeColourPA(AdjustBrightness(LookupColourInPalette(bp->remap[src->m]), src->v), src->a, *dst); } break; case BM_TRANSPARENT: /* TODO -- We make an assumption here that the remap in fact is transparency, not some colour. * This is never a problem with the code we produce, but newgrfs can make it fail... or at least: * we produce a result the newgrf maker didn't expect ;) */ /* Make the current colour a bit more black, so it looks like this image is transparent */ if (src->a != 0) *dst = MakeTransparent(*dst, 192); break; case BM_BLACK_REMAP: if (src->a != 0) { *dst = Colour16(0, 0, 0); } break; default: if (src->a != 0) *dst = ComposeColourPA(src->c, src->a, *dst); break; } dst++; src += ScaleByZoom(1, zoom); } } }