From 215f5f9a495c5072b398307bce12c940094b1d28 Mon Sep 17 00:00:00 2001 From: Eugene Sandulenko Date: Mon, 2 Jun 2014 18:41:21 +0300 Subject: WINTERMUTE: Speeding up blitting routines for TransparentSurface --- .../wintermute/graphics/transparent_surface.cpp | 457 ++++++++------------- engines/wintermute/graphics/transparent_surface.h | 23 -- 2 files changed, 179 insertions(+), 301 deletions(-) diff --git a/engines/wintermute/graphics/transparent_surface.cpp b/engines/wintermute/graphics/transparent_surface.cpp index 5fe0d13766..b16ba0ffdc 100644 --- a/engines/wintermute/graphics/transparent_surface.cpp +++ b/engines/wintermute/graphics/transparent_surface.cpp @@ -41,252 +41,31 @@ namespace Wintermute { -void doBlitOpaqueFast(byte *ino, byte *outo, uint32 width, uint32 height, uint32 pitch, int32 inStep, int32 inoStep); -void doBlitBinaryFast(byte *ino, byte *outo, uint32 width, uint32 height, uint32 pitch, int32 inStep, int32 inoStep); - -// These gather together various blendPixel functions for use with templates. - -class BlenderAdditive { -public: - inline void blendPixel(byte ina, byte inr, byte ing, byte inb, byte *outa, byte *outr, byte *outg, byte *outb); - inline void blendPixel(byte ina, byte inr, byte ing, byte inb, byte *outa, byte *outr, byte *outg, byte *outb, byte *ca, byte *cr, byte *cg, byte *cb); - inline void blendPixel(byte *in, byte *out); - inline void blendPixel(byte *in, byte *out, int colorMod); -}; - -class BlenderSubtractive { -public: - inline void blendPixel(byte ina, byte inr, byte ing, byte inb, byte *outa, byte *outr, byte *outg, byte *outb); - inline void blendPixel(byte ina, byte inr, byte ing, byte inb, byte *outa, byte *outr, byte *outg, byte *outb, byte *ca, byte *cr, byte *cg, byte *cb); - inline void blendPixel(byte *in, byte *out); - inline void blendPixel(byte *in, byte *out, int colorMod); -}; - -class BlenderNormal { -public: - inline void blendPixel(byte ina, byte inr, byte ing, byte inb, byte *outa, byte *outr, byte *outg, byte *outb); - inline void blendPixel(byte ina, byte inr, byte ing, byte inb, byte *outa, byte *outr, byte *outg, byte *outb, byte *ca, byte *cr, byte *cg, byte *cb); - inline void blendPixel(byte *in, byte *out); - inline void blendPixel(byte *in, byte *out, int colorMod); -}; - -/** - * Perform additive blending of a pixel, applying beforehand a given colormod. - * @param ina, inr, ing, inb: the input pixel, split into its components. - * @param *outa, *outr, *outg, *outb pointer to the output pixel. - * @param *outa, *outr, *outg, *outb pointer to the colormod components. - */ -void BlenderAdditive::blendPixel(byte ina, byte inr, byte ing, byte inb, byte *outa, byte *outr, byte *outg, byte *outb, byte *ca, byte *cr, byte *cg, byte *cb) { - if (*ca != 255) { - ina = (ina) * (*ca) >> 8; - } - - if (ina == 0) { - return; - } else { - if (*cb != 255) { - *outb = MIN(*outb + ((inb * (*cb) * ina) >> 16), 255); - } else { - *outb = MIN(*outb + (inb * ina >> 8), 255); - } - - if (*cg != 255) { - *outg = MIN(*outg + ((ing * (*cg) * ina) >> 16), 255); - } else { - *outg = MIN(*outg + (ing * ina >> 8), 255); - } - - if (*cr != 255) { - *outr = MIN(*outr + ((inr * (*cr) * ina) >> 16), 255); - } else { - *outr = MIN(*outr + (inr * ina >> 8), 255); - } - } -} - -/** - * Perform subtractive blending of a pixel, applying beforehand a given colormod. - * @param ina, inr, ing, inb: the input pixel, split into its components. - * @param *outa, *outr, *outg, *outb pointer to the output pixel. - * @param *outa, *outr, *outg, *outb pointer to the colormod components. - */ -void BlenderSubtractive::blendPixel(byte ina, byte inr, byte ing, byte inb, byte *outa, byte *outr, byte *outg, byte *outb, byte *ca, byte *cr, byte *cg, byte *cb) { - //if (*ca != 255) { - // ina = ina * (*ca) >> 8; - // } - - // As weird as it is, evidence suggests that alphamod is ignored when doing - // subtractive... +static const int kAShift = 0;//img->format.aShift; - // TODO if ina == 255 fast version +static const int kBModShift = 0;//img->format.bShift; +static const int kGModShift = 8;//img->format.gShift; +static const int kRModShift = 16;//img->format.rShift; +static const int kAModShift = 24;//img->format.aShift; - if (ina == 0) { - return; - } else { - if (*cb != 255) { - *outb = MAX(*outb - ((inb * (*cb) * (*outb) * ina) >> 24), 0); - } else { - *outb = MAX(*outb - (inb * (*outb) * ina >> 16), 0); - } - - if (*cg != 255) { - *outg = MAX(*outg - ((ing * (*cg) * (*outg) * ina) >> 24), 0); - } else { - *outg = MAX(*outg - (ing * (*outg) * ina >> 16), 0); - } +#ifdef SCUMM_LITTLE_ENDIAN +static const int kAIndex = 0; +static const int kBIndex = 1; +static const int kGIndex = 2; +static const int kRIndex = 3; - if (*cr != 255) { - *outr = MAX(*outr - ((inr * (*cr) * (*outr) * ina) >> 24), 0); - } else { - *outr = MAX(*outr - (inr * (*outr) * ina >> 16), 0); - } - } -} - -/** - * Perform "regular" alphablending of a pixel, applying beforehand a given colormod. - * @param ina, inr, ing, inb: the input pixel, split into its components. - * @param *outa, *outr, *outg, *outb pointer to the output pixel. - * @param *outa, *outr, *outg, *outb pointer to the colormod components. - */ - -void BlenderNormal::blendPixel(byte ina, byte inr, byte ing, byte inb, byte *outa, byte *outr, byte *outg, byte *outb, byte *ca, byte *cr, byte *cg, byte *cb) { - if (*ca != 255) { - ina = ina * (*ca) >> 8; - } - - if (ina == 0) { - return; - } else if (ina == 255) { - if (*cb != 255) { - *outb = (inb * (*cb)) >> 8; - } else { - *outb = inb; - } - - if (*cr != 255) { - *outr = (inr * (*cr)) >> 8; - } else { - *outr = inr; - } - - if (*cg != 255) { - *outg = (ing * (*cg)) >> 8; - } else { - *outg = ing; - } - - *outa = ina; - - return; - - } else { - - *outa = 255; - *outb = (*outb * (255 - ina) >> 8); - *outr = (*outr * (255 - ina) >> 8); - *outg = (*outg * (255 - ina) >> 8); - - if (*cb == 0) { - *outb = *outb; - } else if (*cb != 255) { - *outb = *outb + (inb * ina * (*cb) >> 16); - } else { - *outb = *outb + (inb * ina >> 8); - } - - if (*cr == 0) { - *outr = *outr; - } else if (*cr != 255) { - *outr = *outr + (inr * ina * (*cr) >> 16); - } else { - *outr = *outr + (inr * ina >> 8); - } - - if (*cg == 0) { - *outg = *outg; - } else if (*cg != 255) { - *outg = *outg + (ing * ina * (*cg) >> 16); - } else { - *outg = *outg + (ing * ina >> 8); - } - - return; - } -} - -/** - * Perform "regular" alphablending of a pixel. - * @param ina, inr, ing, inb: the input pixel, split into its components. - * @param *outa, *outr, *outg, *outb pointer to the output pixel. - */ - -void BlenderNormal::blendPixel(byte ina, byte inr, byte ing, byte inb, byte *outa, byte *outr, byte *outg, byte *outb) { - - if (ina == 0) { - return; - } else if (ina == 255) { - *outb = inb; - *outg = ing; - *outr = inr; - *outa = ina; - return; - } else { - *outa = 255; - *outb = ((inb * ina) + *outb * (255 - ina)) >> 8; - *outg = ((ing * ina) + *outg * (255 - ina)) >> 8; - *outr = ((inr * ina) + *outr * (255 - ina)) >> 8; - } -} - -/** - * Perform subtractive blending of a pixel. - * @param ina, inr, ing, inb: the input pixel, split into its components. - * @param *outa, *outr, *outg, *outb pointer to the output pixel. - */ -void BlenderSubtractive::blendPixel(byte ina, byte inr, byte ing, byte inb, byte *outa, byte *outr, byte *outg, byte *outb) { - - if (ina == 0) { - return; - } else if (ina == 255) { - *outa = *outa; - *outr = *outr - (inr * (*outr) >> 8); - *outg = *outg - (ing * (*outg) >> 8); - *outb = *outb - (inb * (*outb) >> 8); - return; - } else { - *outa = *outa; - *outb = MAX(*outb - ((inb * (*outb)) * ina >> 16), 0); - *outg = MAX(*outg - ((ing * (*outg)) * ina >> 16), 0); - *outr = MAX(*outr - ((inr * (*outr)) * ina >> 16), 0); - return; - } -} - -/** - * Perform additive blending of a pixel. - * @param ina, inr, ing, inb: the input pixel, split into its components. - * @param *outa, *outr, *outg, *outb pointer to the output pixel. - */ -void BlenderAdditive::blendPixel(byte ina, byte inr, byte ing, byte inb, byte *outa, byte *outr, byte *outg, byte *outb) { - - if (ina == 0) { - return; - } else if (ina == 255) { - *outa = *outa; - *outr = MIN(*outr + inr, 255); - *outg = MIN(*outg + ing, 255); - *outb = MIN(*outb + inb, 255); - return; - } else { - *outa = *outa; - *outb = MIN((inb * ina >> 8) + *outb, 255); - *outg = MIN((ing * ina >> 8) + *outg, 255); - *outr = MIN((inr * ina >> 8) + *outr, 255); - return; - } -} +#else +static const int kAIndex = 3; +static const int kBIndex = 2; +static const int kGIndex = 1; +static const int kRIndex = 0; +#endif +void doBlitOpaqueFast(byte *ino, byte *outo, uint32 width, uint32 height, uint32 pitch, int32 inStep, int32 inoStep); +void doBlitBinaryFast(byte *ino, byte *outo, uint32 width, uint32 height, uint32 pitch, int32 inStep, int32 inoStep); +void doBlitAlphaBlend(byte *ino, byte *outo, uint32 width, uint32 height, uint32 pitch, int32 inStep, int32 inoStep, uint32 color); +void doBlitAdditiveBlend(byte *ino, byte *outo, uint32 width, uint32 height, uint32 pitch, int32 inStep, int32 inoStep, uint32 color); +void doBlitSubtractiveBlend(byte *ino, byte *outo, uint32 width, uint32 height, uint32 pitch, int32 inStep, int32 inoStep, uint32 color); TransparentSurface::TransparentSurface() : Surface(), _alphaMode(ALPHA_FULL) {} @@ -318,7 +97,7 @@ void doBlitOpaqueFast(byte *ino, byte *outo, uint32 width, uint32 height, uint32 in = ino; memcpy(out, in, width * 4); for (uint32 j = 0; j < width; j++) { - out[TransparentSurface::kAIndex] = 0xFF; + out[kAIndex] = 0xFF; out += 4; } outo += pitch; @@ -339,12 +118,11 @@ void doBlitBinaryFast(byte *ino, byte *outo, uint32 width, uint32 height, uint32 in = ino; for (uint32 j = 0; j < width; j++) { uint32 pix = *(uint32 *)in; - int a = (pix >> TransparentSurface::kAShift) & 0xff; + int a = (pix >> kAShift) & 0xff; - if (a == 0) { // Full transparency - } else { // Full opacity (Any value not exactly 0 is Opaque here) + if (a != 0) { // Full opacity (Any value not exactly 0 is Opaque here) *(uint32 *)out = pix; - out[TransparentSurface::kAIndex] = 0xFF; + out[kAIndex] = 0xFF; } out += 4; in += inStep; @@ -355,9 +133,7 @@ void doBlitBinaryFast(byte *ino, byte *outo, uint32 width, uint32 height, uint32 } /** - * What we have here is a template method that calls blendPixel() from a different - * class - the one we call it with - thus performing a different type of blending. - * + * Optimized version of doBlit to be used with alpha blended blitting * @param ino a pointer to the input surface * @param outo a pointer to the output surface * @param width width of the input surface @@ -367,10 +143,65 @@ void doBlitBinaryFast(byte *ino, byte *outo, uint32 width, uint32 height, uint32 * @inoStep width in bytes of every row on the *input* surface / kind of like pitch * @color colormod in 0xAARRGGBB format - 0xFFFFFFFF for no colormod */ +void doBlitAlphaBlend(byte *ino, byte *outo, uint32 width, uint32 height, uint32 pitch, int32 inStep, int32 inoStep, uint32 color) { + byte *in; + byte *out; -template -void doBlit(byte *ino, byte *outo, uint32 width, uint32 height, uint32 pitch, int32 inStep, int32 inoStep, uint32 color) { - Blender b; + if (color == 0xffffffff) { + + for (uint32 i = 0; i < height; i++) { + out = outo; + in = ino; + for (uint32 j = 0; j < width; j++) { + + if (in[kAIndex] != 0) { + out[kAIndex] = 255; + out[kRIndex] = ((in[kRIndex] * in[kAIndex]) + out[kRIndex] * (255 - in[kAIndex])) >> 8; + out[kGIndex] = ((in[kGIndex] * in[kAIndex]) + out[kGIndex] * (255 - in[kAIndex])) >> 8; + out[kBIndex] = ((in[kBIndex] * in[kAIndex]) + out[kBIndex] * (255 - in[kAIndex])) >> 8; + } + + in += inStep; + out += 4; + } + outo += pitch; + ino += inoStep; + } + } else { + + byte ca = (color >> kAModShift) & 0xFF; + byte cr = (color >> kRModShift) & 0xFF; + byte cg = (color >> kGModShift) & 0xFF; + byte cb = (color >> kBModShift) & 0xFF; + + for (uint32 i = 0; i < height; i++) { + out = outo; + in = ino; + for (uint32 j = 0; j < width; j++) { + + uint32 ina = in[kAIndex] * ca >> 8; + out[kAIndex] = 255; + out[kBIndex] = (out[kBIndex] * (255 - ina) >> 8); + out[kGIndex] = (out[kGIndex] * (255 - ina) >> 8); + out[kRIndex] = (out[kRIndex] * (255 - ina) >> 8); + + out[kBIndex] = out[kBIndex] + (in[kBIndex] * ina * cb >> 16); + out[kGIndex] = out[kGIndex] + (in[kGIndex] * ina * cg >> 16); + out[kRIndex] = out[kRIndex] + (in[kRIndex] * ina * cr >> 16); + + in += inStep; + out += 4; + } + outo += pitch; + ino += inoStep; + } + } +} + +/** + * Optimized version of doBlit to be used with additive blended blitting + */ +void doBlitAdditiveBlend(byte *ino, byte *outo, uint32 width, uint32 height, uint32 pitch, int32 inStep, int32 inoStep, uint32 color) { byte *in; byte *out; @@ -381,16 +212,78 @@ void doBlit(byte *ino, byte *outo, uint32 width, uint32 height, uint32 pitch, in in = ino; for (uint32 j = 0; j < width; j++) { - byte *outa = &out[TransparentSurface::kAIndex]; - byte *outr = &out[TransparentSurface::kRIndex]; - byte *outg = &out[TransparentSurface::kGIndex]; - byte *outb = &out[TransparentSurface::kBIndex]; + if (in[kAIndex] != 0) { + out[kRIndex] = MIN((in[kRIndex] * in[kAIndex] >> 8) + out[kRIndex], 255); + out[kGIndex] = MIN((in[kGIndex] * in[kAIndex] >> 8) + out[kGIndex], 255); + out[kBIndex] = MIN((in[kBIndex] * in[kAIndex] >> 8) + out[kBIndex], 255); + } - b.blendPixel(in[TransparentSurface::kAIndex], - in[TransparentSurface::kRIndex], - in[TransparentSurface::kGIndex], - in[TransparentSurface::kBIndex], - outa, outr, outg, outb); + in += inStep; + out += 4; + } + outo += pitch; + ino += inoStep; + } + } else { + + byte ca = (color >> kAModShift) & 0xFF; + byte cr = (color >> kRModShift) & 0xFF; + byte cg = (color >> kGModShift) & 0xFF; + byte cb = (color >> kBModShift) & 0xFF; + + for (uint32 i = 0; i < height; i++) { + out = outo; + in = ino; + for (uint32 j = 0; j < width; j++) { + + uint32 ina = in[kAIndex] * ca >> 8; + + if (cb != 255) { + out[kBIndex] = MIN(out[kBIndex] + ((in[kBIndex] * cb * ina) >> 16), 255u); + } else { + out[kBIndex] = MIN(out[kBIndex] + (in[kBIndex] * ina >> 8), 255u); + } + + if (cg != 255) { + out[kGIndex] = MIN(out[kGIndex] + ((in[kGIndex] * cg * ina) >> 16), 255u); + } else { + out[kGIndex] = MIN(out[kGIndex] + (in[kGIndex] * ina >> 8), 255u); + } + + if (cr != 255) { + out[kRIndex] = MIN(out[kRIndex] + ((in[kRIndex] * cr * ina) >> 16), 255u); + } else { + out[kRIndex] = MIN(out[kRIndex] + (in[kRIndex] * ina >> 8), 255u); + } + + in += inStep; + out += 4; + } + outo += pitch; + ino += inoStep; + } + } +} + +/** + * Optimized version of doBlit to be used with subtractive blended blitting + */ +void doBlitSubtractiveBlend(byte *ino, byte *outo, uint32 width, uint32 height, uint32 pitch, int32 inStep, int32 inoStep, uint32 color) { + byte *in; + byte *out; + + if (color == 0xffffffff) { + + for (uint32 i = 0; i < height; i++) { + out = outo; + in = ino; + for (uint32 j = 0; j < width; j++) { + + if (in[kAIndex] != 0) { + out[kRIndex] = MAX(out[kRIndex] - ((in[kRIndex] * out[kRIndex]) * in[kAIndex] >> 16), 0); + out[kGIndex] = MAX(out[kGIndex] - ((in[kGIndex] * out[kGIndex]) * in[kAIndex] >> 16), 0); + out[kBIndex] = MAX(out[kBIndex] - ((in[kBIndex] * out[kBIndex]) * in[kAIndex] >> 16), 0); + } in += inStep; out += 4; @@ -400,26 +293,34 @@ void doBlit(byte *ino, byte *outo, uint32 width, uint32 height, uint32 pitch, in } } else { - byte ca = (color >> TransparentSurface::kAModShift) & 0xFF; - byte cr = (color >> TransparentSurface::kRModShift) & 0xFF; - byte cg = (color >> TransparentSurface::kGModShift) & 0xFF; - byte cb = (color >> TransparentSurface::kBModShift) & 0xFF; + byte cr = (color >> kRModShift) & 0xFF; + byte cg = (color >> kGModShift) & 0xFF; + byte cb = (color >> kBModShift) & 0xFF; for (uint32 i = 0; i < height; i++) { out = outo; in = ino; for (uint32 j = 0; j < width; j++) { - byte *outa = &out[TransparentSurface::kAIndex]; - byte *outr = &out[TransparentSurface::kRIndex]; - byte *outg = &out[TransparentSurface::kGIndex]; - byte *outb = &out[TransparentSurface::kBIndex]; + out[kAIndex] = 255; + if (cb != 255) { + out[kBIndex] = MAX(out[kBIndex] - ((in[kBIndex] * cb * (out[kBIndex]) * in[kAIndex]) >> 24), 0); + } else { + out[kBIndex] = MAX(out[kBIndex] - (in[kBIndex] * (out[kBIndex]) * in[kAIndex] >> 16), 0); + } + + if (cg != 255) { + out[kGIndex] = MAX(out[kGIndex] - ((in[kGIndex] * cg * (out[kGIndex]) * in[kAIndex]) >> 24), 0); + } else { + out[kGIndex] = MAX(out[kGIndex] - (in[kGIndex] * (out[kGIndex]) * in[kAIndex] >> 16), 0); + } + + if (cr != 255) { + out[kRIndex] = MAX(out[kRIndex] - ((in[kRIndex] * cr * (out[kRIndex]) * in[kAIndex]) >> 24), 0); + } else { + out[kRIndex] = MAX(out[kRIndex] - (in[kRIndex] * (out[kRIndex]) * in[kAIndex] >> 16), 0); + } - b.blendPixel(in[TransparentSurface::kAIndex], - in[TransparentSurface::kRIndex], - in[TransparentSurface::kGIndex], - in[TransparentSurface::kBIndex], - outa, outr, outg, outb, &ca, &cr, &cg, &cb); in += inStep; out += 4; } @@ -540,12 +441,12 @@ Common::Rect TransparentSurface::blit(Graphics::Surface &target, int posX, int p doBlitBinaryFast(ino, outo, img->w, img->h, target.pitch, inStep, inoStep); } else { if (blendMode == BLEND_ADDITIVE) { - doBlit(ino, outo, img->w, img->h, target.pitch, inStep, inoStep, color); + doBlitAdditiveBlend(ino, outo, img->w, img->h, target.pitch, inStep, inoStep, color); } else if (blendMode == BLEND_SUBTRACTIVE) { - doBlit(ino, outo, img->w, img->h, target.pitch, inStep, inoStep, color); + doBlitSubtractiveBlend(ino, outo, img->w, img->h, target.pitch, inStep, inoStep, color); } else { assert(blendMode == BLEND_NORMAL); - doBlit(ino, outo, img->w, img->h, target.pitch, inStep, inoStep, color); + doBlitAlphaBlend(ino, outo, img->w, img->h, target.pitch, inStep, inoStep, color); } } diff --git a/engines/wintermute/graphics/transparent_surface.h b/engines/wintermute/graphics/transparent_surface.h index 4ad9bf07eb..e5049a5f3f 100644 --- a/engines/wintermute/graphics/transparent_surface.h +++ b/engines/wintermute/graphics/transparent_surface.h @@ -74,29 +74,6 @@ struct TransparentSurface : public Graphics::Surface { ALPHA_FULL = 2 }; -#ifdef SCUMM_LITTLE_ENDIAN - static const int kAIndex = 0; - static const int kBIndex = 1; - static const int kGIndex = 2; - static const int kRIndex = 3; -#else - static const int kAIndex = 3; - static const int kBIndex = 2; - static const int kGIndex = 1; - static const int kRIndex = 0; -#endif - - static const int kBShift = 8;//img->format.bShift; - static const int kGShift = 16;//img->format.gShift; - static const int kRShift = 24;//img->format.rShift; - static const int kAShift = 0;//img->format.aShift; - - - static const int kBModShift = 0;//img->format.bShift; - static const int kGModShift = 8;//img->format.gShift; - static const int kRModShift = 16;//img->format.rShift; - static const int kAModShift = 24;//img->format.aShift; - /** @brief renders the surface to another surface -- cgit v1.2.3 From 7322d905b37c222983e48219853aae105670e374 Mon Sep 17 00:00:00 2001 From: Eugene Sandulenko Date: Tue, 3 Jun 2014 17:25:18 +0300 Subject: COMMON: Copy TransparentSurface from Wintermute engine to common code --- graphics/module.mk | 3 + graphics/transform_struct.cpp | 120 ++++++ graphics/transform_struct.h | 97 +++++ graphics/transform_tools.cpp | 87 ++++ graphics/transform_tools.h | 77 ++++ graphics/transparent_surface.cpp | 851 +++++++++++++++++++++++++++++++++++++++ graphics/transparent_surface.h | 152 +++++++ 7 files changed, 1387 insertions(+) create mode 100644 graphics/transform_struct.cpp create mode 100644 graphics/transform_struct.h create mode 100644 graphics/transform_tools.cpp create mode 100644 graphics/transform_tools.h create mode 100644 graphics/transparent_surface.cpp create mode 100644 graphics/transparent_surface.h diff --git a/graphics/module.mk b/graphics/module.mk index 5918775240..2705322c79 100644 --- a/graphics/module.mk +++ b/graphics/module.mk @@ -17,6 +17,9 @@ MODULE_OBJS := \ scaler/thumbnail_intern.o \ sjis.o \ surface.o \ + transform_struct.o \ + transform_tools.o \ + transparent_surface.o \ thumbnail.o \ VectorRenderer.o \ VectorRendererSpec.o \ diff --git a/graphics/transform_struct.cpp b/graphics/transform_struct.cpp new file mode 100644 index 0000000000..a6beada17f --- /dev/null +++ b/graphics/transform_struct.cpp @@ -0,0 +1,120 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program 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; either version 2 + * of the License, or (at your option) any later version. + * + * This program 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. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "graphics/transform_struct.h" +#include "graphics/transparent_surface.h" + +namespace Graphics { + +void TransformStruct::init(Common::Point zoom, uint32 angle, Common::Point hotspot, bool alphaDisable, TSpriteBlendMode blendMode, uint32 rgbaMod, bool mirrorX, bool mirrorY, Common::Point offset) { + _zoom = zoom; + _angle = angle; + _hotspot = hotspot; + _blendMode = blendMode; + _rgbaMod = rgbaMod; + _alphaDisable = alphaDisable; + _flip = 0; + _flip += FLIP_H * mirrorX; + _flip += FLIP_V * mirrorY; + _offset = offset; + _numTimesX = 1; + _numTimesY = 1; +} + +TransformStruct::TransformStruct(int32 zoomX, int32 zoomY, uint32 angle, int32 hotspotX, int32 hotspotY, TSpriteBlendMode blendMode, uint32 rgbaMod, bool mirrorX, bool mirrorY, int32 offsetX, int32 offsetY) { + init(Common::Point(zoomX, zoomY), + angle, + Common::Point(hotspotX, hotspotY), + false, + blendMode, + rgbaMod, + mirrorX, mirrorY, + Common::Point(offsetX, offsetY)); +} + +TransformStruct::TransformStruct(float zoomX, float zoomY, uint32 angle, int32 hotspotX, int32 hotspotY, TSpriteBlendMode blendMode, uint32 rgbaMod, bool mirrorX, bool mirrorY, int32 offsetX, int32 offsetY) { + init(Common::Point((int)(zoomX / 100.0 * kDefaultZoomX), + (int)(zoomY / 100.0 * kDefaultZoomY)), + angle, + Common::Point(hotspotX, hotspotY), + false, + blendMode, + rgbaMod, + mirrorX, mirrorY, + Common::Point(offsetX, offsetY)); +} + +TransformStruct::TransformStruct(int32 zoomX, int32 zoomY, TSpriteBlendMode blendMode, uint32 rgbaMod, bool mirrorX, bool mirrorY) { + init(Common::Point(zoomX, zoomY), + kDefaultAngle, + Common::Point(kDefaultHotspotX, kDefaultHotspotY), + false, + blendMode, + rgbaMod, + mirrorX, + mirrorY, + Common::Point(kDefaultOffsetX, kDefaultOffsetY)); +} + +TransformStruct::TransformStruct(int32 zoomX, int32 zoomY, uint32 angle, int32 hotspotX, int32 hotspotY) { + init(Common::Point(zoomX, zoomY), + angle, + Common::Point(hotspotX, hotspotY), + true, + BLEND_NORMAL, + kDefaultRgbaMod, + false, false, + Common::Point(kDefaultOffsetX, kDefaultOffsetY)); +} + +TransformStruct::TransformStruct(int32 numTimesX, int32 numTimesY) { + init(Common::Point(kDefaultZoomX, kDefaultZoomY), + kDefaultAngle, + Common::Point(kDefaultHotspotX, kDefaultHotspotY), + false, + BLEND_NORMAL, + kDefaultRgbaMod, + false, false, + Common::Point(kDefaultOffsetX, kDefaultOffsetY)); + _numTimesX = numTimesX; + _numTimesY = numTimesY; +} + +TransformStruct::TransformStruct() { + init(Common::Point(kDefaultZoomX, kDefaultZoomY), + kDefaultAngle, + Common::Point(kDefaultHotspotX, kDefaultHotspotY), + true, + BLEND_NORMAL, + kDefaultRgbaMod, + false, false, + Common::Point(kDefaultOffsetX, kDefaultOffsetY)); +} + +bool TransformStruct::getMirrorX() const { + return (bool)(_flip & FLIP_H); +} + +bool TransformStruct::getMirrorY() const { + return (bool)(_flip & FLIP_V); +} +} // End of namespace Graphics diff --git a/graphics/transform_struct.h b/graphics/transform_struct.h new file mode 100644 index 0000000000..640daf9f4c --- /dev/null +++ b/graphics/transform_struct.h @@ -0,0 +1,97 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program 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; either version 2 + * of the License, or (at your option) any later version. + * + * This program 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. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef GRAPHICS_TRANSFORM_STRUCT_H +#define GRAPHICS_TRANSFORM_STRUCT_H + +#include "common/rect.h" + +namespace Graphics { + +enum TSpriteBlendMode { + BLEND_UNKNOWN = -1, + BLEND_NORMAL = 0, + BLEND_ADDITIVE = 1, + BLEND_SUBTRACTIVE = 2, + NUM_BLEND_MODES +}; + +/** + * Contains all the required information that define a transform. + * Same source sprite + same TransformStruct = Same resulting sprite. + * Has a number of overloaded constructors to accomodate various argument lists. + */ + +const int32 kDefaultZoomX = 100; +const int32 kDefaultZoomY = 100; +const uint32 kDefaultRgbaMod = 0xFFFFFFFF; +const int32 kDefaultHotspotX = 0; +const int32 kDefaultHotspotY = 0; +const int32 kDefaultOffsetX = 0; +const int32 kDefaultOffsetY = 0; +const int32 kDefaultAngle = 0; + +struct TransformStruct { +private: + void init(Common::Point zoom, uint32 angle, Common::Point hotspot, bool alphaDisable, TSpriteBlendMode blendMode, uint32 alpha, bool mirrorX, bool mirrorY, Common::Point offset); + +public: + TransformStruct(int32 zoomX, int32 zoomY, uint32 angle, int32 hotspotX, int32 hotspotY, TSpriteBlendMode blendMode, uint32 alpha, bool mirrorX = false, bool mirrorY = false, int32 offsetX = 0, int32 offsetY = 0); + TransformStruct(float zoomX, float zoomY, uint32 angle, int32 hotspotX, int32 hotspotY, TSpriteBlendMode blendMode, uint32 alpha, bool mirrorX = false, bool mirrorY = false, int32 offsetX = 0, int32 offsetY = 0); + TransformStruct(int32 zoomX, int32 zoomY, TSpriteBlendMode blendMode, uint32 alpha, bool mirrorX = false, bool mirrorY = false); + TransformStruct(int32 zoomX, int32 zoomY, uint32 angle, int32 hotspotX = 0, int32 hotspotY = 0); + TransformStruct(int32 numTimesX, int32 numTimesY); + TransformStruct(); + + Common::Point _zoom; ///< Zoom; 100 = no zoom + Common::Point _hotspot; ///< Position of the hotspot + int32 _angle; ///< Rotation angle, in degrees + byte _flip; ///< Bitflag: see TransparentSurface::FLIP_XXX + bool _alphaDisable; + TSpriteBlendMode _blendMode; + uint32 _rgbaMod; ///< RGBa + Common::Point _offset; + int32 _numTimesX; + int32 _numTimesY; + + bool getMirrorX() const; + bool getMirrorY() const; + + bool operator==(const TransformStruct &compare) const { + return (compare._angle == _angle && + compare._flip == _flip && + compare._zoom == _zoom && + compare._offset == _offset && + compare._alphaDisable == _alphaDisable && + compare._rgbaMod == _rgbaMod && + compare._blendMode == _blendMode && + compare._numTimesX == _numTimesX && + compare._numTimesY == _numTimesY + ); + } + + bool operator!=(const TransformStruct &compare) const { + return !(compare == *this); + } +}; +} // End of namespace Graphics +#endif diff --git a/graphics/transform_tools.cpp b/graphics/transform_tools.cpp new file mode 100644 index 0000000000..6e87b6321a --- /dev/null +++ b/graphics/transform_tools.cpp @@ -0,0 +1,87 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program 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; either version 2 + * of the License, or (at your option) any later version. + * + * This program 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. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + + +#include "graphics/transform_tools.h" +#include + +namespace Graphics { + +FloatPoint TransformTools::transformPoint(FloatPoint point, const float rotate, const Common::Point &zoom, const bool mirrorX, const bool mirrorY) { + float rotateRad = rotate * M_PI / 180.0f; + float x = point.x; + float y = point.y; + x = (x * zoom.x) / kDefaultZoomX; + y = (y * zoom.y) / kDefaultZoomY; +#if 0 + // TODO: Mirroring should be done before rotation, but the blitting + // code does the inverse, so we match that for now. + if (mirrorX) + x *= -1; + if (mirrorY) + y *= -1; +#endif + FloatPoint newPoint; + newPoint.x = x * cos(rotateRad) - y * sin(rotateRad); + newPoint.y = x * sin(rotateRad) + y * cos(rotateRad); + if (mirrorX) { + newPoint.x *= -1; + } + if (mirrorY) { + newPoint.y *= -1; + } + return newPoint; +} + +Common::Rect TransformTools::newRect(const Common::Rect &oldRect, const TransformStruct &transform, Common::Point *newHotspot) { + Common::Point nw(oldRect.left, oldRect.top); + Common::Point ne(oldRect.right, oldRect.top); + Common::Point sw(oldRect.left, oldRect.bottom); + Common::Point se(oldRect.right, oldRect.bottom); + + FloatPoint nw1, ne1, sw1, se1; + + nw1 = transformPoint(nw - transform._hotspot, transform._angle, transform._zoom); + ne1 = transformPoint(ne - transform._hotspot, transform._angle, transform._zoom); + sw1 = transformPoint(sw - transform._hotspot, transform._angle, transform._zoom); + se1 = transformPoint(se - transform._hotspot, transform._angle, transform._zoom); + + float top = MIN(nw1.y, MIN(ne1.y, MIN(sw1.y, se1.y))); + float bottom = MAX(nw1.y, MAX(ne1.y, MAX(sw1.y, se1.y))); + float left = MIN(nw1.x, MIN(ne1.x, MIN(sw1.x, se1.x))); + float right = MAX(nw1.x, MAX(ne1.x, MAX(sw1.x, se1.x))); + + if (newHotspot) { + newHotspot->y = (uint32)(-floor(top)); + newHotspot->x = (uint32)(-floor(left)); + } + + Common::Rect res; + res.top = (int32)(floor(top)) + transform._hotspot.y; + res.bottom = (int32)(ceil(bottom)) + transform._hotspot.y; + res.left = (int32)(floor(left)) + transform._hotspot.x; + res.right = (int32)(ceil(right)) + transform._hotspot.x; + + return res; +} + +} // End of namespace Graphics diff --git a/graphics/transform_tools.h b/graphics/transform_tools.h new file mode 100644 index 0000000000..c618f7c35a --- /dev/null +++ b/graphics/transform_tools.h @@ -0,0 +1,77 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program 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; either version 2 + * of the License, or (at your option) any later version. + * + * This program 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. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef GRAPHICS_TRANSFORM_TOOLS_H +#define GRAPHICS_TRANSFORM_TOOLS_H + +#include "common/rect.h" +#include "graphics/transform_struct.h" + +namespace Graphics { + + static const float kEpsilon = 0.00001; // arbitrarily taken number + + struct FloatPoint { + float x; + float y; + FloatPoint() : x(0), y(0) {} + FloatPoint(float x1, float y1) : x(x1), y(y1) {} + FloatPoint(const Common::Point p) : x(p.x), y(p.y) {} + bool operator==(const FloatPoint &p) const { return fabs(x - p.x) < kEpsilon && fabs(y - p.y) < kEpsilon; } + bool operator!=(const FloatPoint &p) const { return fabs(x - p.x) > kEpsilon || fabs(y - p.y) > kEpsilon; } + FloatPoint operator+(const FloatPoint &delta) const { return FloatPoint (x + delta.x, y + delta.y); } + FloatPoint operator-(const FloatPoint &delta) const { return FloatPoint (x - delta.x, y - delta.y); } + + FloatPoint& operator+=(const FloatPoint &delta) { + x += delta.x; + y += delta.y; + return *this; + } + FloatPoint& operator-=(const FloatPoint &delta) { + x -= delta.x; + y -= delta.y; + return *this; + } + }; + +class TransformTools { +public: + /** + * Basic transform (scale + rotate) for a single point + */ + static FloatPoint transformPoint(FloatPoint point, const float rotate, const Common::Point &zoom, const bool mirrorX = false, const bool mirrorY = false); + + /** + * @param &point the point on which the transform is to be applied + * @param rotate the angle in degrees + * @param &zoom zoom x,y in percent + * @param mirrorX flip along the vertical axis? + * @param mirrorY flip along the horizontal axis? + * @return the smallest rect that can contain the transformed sprite + * and, as a side-effect, "newHotspot" will tell you where the hotspot will + * have ended up in the new rect, for centering. + */ + static Common::Rect newRect(const Common::Rect &oldRect, const TransformStruct &transform, Common::Point *newHotspot); +}; + +} // End of namespace Wintermute +#endif diff --git a/graphics/transparent_surface.cpp b/graphics/transparent_surface.cpp new file mode 100644 index 0000000000..c2d334e731 --- /dev/null +++ b/graphics/transparent_surface.cpp @@ -0,0 +1,851 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program 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; either version 2 + * of the License, or (at your option) any later version. + * + * This program 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. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * + * The bottom part of this is file is adapted from SDL_rotozoom.c. The + * relevant copyright notice for those specific functions can be found at the + * top of that section. + * + */ + + + +#include "common/algorithm.h" +#include "common/endian.h" +#include "common/util.h" +#include "common/rect.h" +#include "common/math.h" +#include "common/textconsole.h" +#include "graphics/primitives.h" +#include "graphics/transparent_surface.h" +#include "graphics/transform_tools.h" + +//#define ENABLE_BILINEAR + +namespace Graphics { + +static const int kAShift = 0;//img->format.aShift; + +static const int kBModShift = 0;//img->format.bShift; +static const int kGModShift = 8;//img->format.gShift; +static const int kRModShift = 16;//img->format.rShift; +static const int kAModShift = 24;//img->format.aShift; + +#ifdef SCUMM_LITTLE_ENDIAN +static const int kAIndex = 0; +static const int kBIndex = 1; +static const int kGIndex = 2; +static const int kRIndex = 3; + +#else +static const int kAIndex = 3; +static const int kBIndex = 2; +static const int kGIndex = 1; +static const int kRIndex = 0; +#endif + +void doBlitOpaqueFast(byte *ino, byte *outo, uint32 width, uint32 height, uint32 pitch, int32 inStep, int32 inoStep); +void doBlitBinaryFast(byte *ino, byte *outo, uint32 width, uint32 height, uint32 pitch, int32 inStep, int32 inoStep); +void doBlitAlphaBlend(byte *ino, byte *outo, uint32 width, uint32 height, uint32 pitch, int32 inStep, int32 inoStep, uint32 color); +void doBlitAdditiveBlend(byte *ino, byte *outo, uint32 width, uint32 height, uint32 pitch, int32 inStep, int32 inoStep, uint32 color); +void doBlitSubtractiveBlend(byte *ino, byte *outo, uint32 width, uint32 height, uint32 pitch, int32 inStep, int32 inoStep, uint32 color); + +TransparentSurface::TransparentSurface() : Surface(), _alphaMode(ALPHA_FULL) {} + +TransparentSurface::TransparentSurface(const Surface &surf, bool copyData) : Surface(), _alphaMode(ALPHA_FULL) { + if (copyData) { + copyFrom(surf); + } else { + w = surf.w; + h = surf.h; + pitch = surf.pitch; + format = surf.format; + // We need to cast the const qualifier away here because 'pixels' + // always needs to be writable. 'surf' however is a constant Surface, + // thus getPixels will always return const pixel data. + pixels = const_cast(surf.getPixels()); + } +} + +/** + * Optimized version of doBlit to be used w/opaque blitting (no alpha). + */ +void doBlitOpaqueFast(byte *ino, byte *outo, uint32 width, uint32 height, uint32 pitch, int32 inStep, int32 inoStep) { + + byte *in; + byte *out; + + for (uint32 i = 0; i < height; i++) { + out = outo; + in = ino; + memcpy(out, in, width * 4); + for (uint32 j = 0; j < width; j++) { + out[kAIndex] = 0xFF; + out += 4; + } + outo += pitch; + ino += inoStep; + } +} + +/** + * Optimized version of doBlit to be used w/binary blitting (blit or no-blit, no blending). + */ +void doBlitBinaryFast(byte *ino, byte *outo, uint32 width, uint32 height, uint32 pitch, int32 inStep, int32 inoStep) { + + byte *in; + byte *out; + + for (uint32 i = 0; i < height; i++) { + out = outo; + in = ino; + for (uint32 j = 0; j < width; j++) { + uint32 pix = *(uint32 *)in; + int a = (pix >> kAShift) & 0xff; + + if (a != 0) { // Full opacity (Any value not exactly 0 is Opaque here) + *(uint32 *)out = pix; + out[kAIndex] = 0xFF; + } + out += 4; + in += inStep; + } + outo += pitch; + ino += inoStep; + } +} + +/** + * Optimized version of doBlit to be used with alpha blended blitting + * @param ino a pointer to the input surface + * @param outo a pointer to the output surface + * @param width width of the input surface + * @param height height of the input surface + * @param pitch pitch of the output surface - that is, width in bytes of every row, usually bpp * width of the TARGET surface (the area we are blitting to might be smaller, do the math) + * @inStep size in bytes to skip to address each pixel, usually bpp of the source surface + * @inoStep width in bytes of every row on the *input* surface / kind of like pitch + * @color colormod in 0xAARRGGBB format - 0xFFFFFFFF for no colormod + */ +void doBlitAlphaBlend(byte *ino, byte *outo, uint32 width, uint32 height, uint32 pitch, int32 inStep, int32 inoStep, uint32 color) { + byte *in; + byte *out; + + if (color == 0xffffffff) { + + for (uint32 i = 0; i < height; i++) { + out = outo; + in = ino; + for (uint32 j = 0; j < width; j++) { + + if (in[kAIndex] != 0) { + out[kAIndex] = 255; + out[kRIndex] = ((in[kRIndex] * in[kAIndex]) + out[kRIndex] * (255 - in[kAIndex])) >> 8; + out[kGIndex] = ((in[kGIndex] * in[kAIndex]) + out[kGIndex] * (255 - in[kAIndex])) >> 8; + out[kBIndex] = ((in[kBIndex] * in[kAIndex]) + out[kBIndex] * (255 - in[kAIndex])) >> 8; + } + + in += inStep; + out += 4; + } + outo += pitch; + ino += inoStep; + } + } else { + + byte ca = (color >> kAModShift) & 0xFF; + byte cr = (color >> kRModShift) & 0xFF; + byte cg = (color >> kGModShift) & 0xFF; + byte cb = (color >> kBModShift) & 0xFF; + + for (uint32 i = 0; i < height; i++) { + out = outo; + in = ino; + for (uint32 j = 0; j < width; j++) { + + uint32 ina = in[kAIndex] * ca >> 8; + out[kAIndex] = 255; + out[kBIndex] = (out[kBIndex] * (255 - ina) >> 8); + out[kGIndex] = (out[kGIndex] * (255 - ina) >> 8); + out[kRIndex] = (out[kRIndex] * (255 - ina) >> 8); + + out[kBIndex] = out[kBIndex] + (in[kBIndex] * ina * cb >> 16); + out[kGIndex] = out[kGIndex] + (in[kGIndex] * ina * cg >> 16); + out[kRIndex] = out[kRIndex] + (in[kRIndex] * ina * cr >> 16); + + in += inStep; + out += 4; + } + outo += pitch; + ino += inoStep; + } + } +} + +/** + * Optimized version of doBlit to be used with additive blended blitting + */ +void doBlitAdditiveBlend(byte *ino, byte *outo, uint32 width, uint32 height, uint32 pitch, int32 inStep, int32 inoStep, uint32 color) { + byte *in; + byte *out; + + if (color == 0xffffffff) { + + for (uint32 i = 0; i < height; i++) { + out = outo; + in = ino; + for (uint32 j = 0; j < width; j++) { + + if (in[kAIndex] != 0) { + out[kRIndex] = MIN((in[kRIndex] * in[kAIndex] >> 8) + out[kRIndex], 255); + out[kGIndex] = MIN((in[kGIndex] * in[kAIndex] >> 8) + out[kGIndex], 255); + out[kBIndex] = MIN((in[kBIndex] * in[kAIndex] >> 8) + out[kBIndex], 255); + } + + in += inStep; + out += 4; + } + outo += pitch; + ino += inoStep; + } + } else { + + byte ca = (color >> kAModShift) & 0xFF; + byte cr = (color >> kRModShift) & 0xFF; + byte cg = (color >> kGModShift) & 0xFF; + byte cb = (color >> kBModShift) & 0xFF; + + for (uint32 i = 0; i < height; i++) { + out = outo; + in = ino; + for (uint32 j = 0; j < width; j++) { + + uint32 ina = in[kAIndex] * ca >> 8; + + if (cb != 255) { + out[kBIndex] = MIN(out[kBIndex] + ((in[kBIndex] * cb * ina) >> 16), 255u); + } else { + out[kBIndex] = MIN(out[kBIndex] + (in[kBIndex] * ina >> 8), 255u); + } + + if (cg != 255) { + out[kGIndex] = MIN(out[kGIndex] + ((in[kGIndex] * cg * ina) >> 16), 255u); + } else { + out[kGIndex] = MIN(out[kGIndex] + (in[kGIndex] * ina >> 8), 255u); + } + + if (cr != 255) { + out[kRIndex] = MIN(out[kRIndex] + ((in[kRIndex] * cr * ina) >> 16), 255u); + } else { + out[kRIndex] = MIN(out[kRIndex] + (in[kRIndex] * ina >> 8), 255u); + } + + in += inStep; + out += 4; + } + outo += pitch; + ino += inoStep; + } + } +} + +/** + * Optimized version of doBlit to be used with subtractive blended blitting + */ +void doBlitSubtractiveBlend(byte *ino, byte *outo, uint32 width, uint32 height, uint32 pitch, int32 inStep, int32 inoStep, uint32 color) { + byte *in; + byte *out; + + if (color == 0xffffffff) { + + for (uint32 i = 0; i < height; i++) { + out = outo; + in = ino; + for (uint32 j = 0; j < width; j++) { + + if (in[kAIndex] != 0) { + out[kRIndex] = MAX(out[kRIndex] - ((in[kRIndex] * out[kRIndex]) * in[kAIndex] >> 16), 0); + out[kGIndex] = MAX(out[kGIndex] - ((in[kGIndex] * out[kGIndex]) * in[kAIndex] >> 16), 0); + out[kBIndex] = MAX(out[kBIndex] - ((in[kBIndex] * out[kBIndex]) * in[kAIndex] >> 16), 0); + } + + in += inStep; + out += 4; + } + outo += pitch; + ino += inoStep; + } + } else { + + byte cr = (color >> kRModShift) & 0xFF; + byte cg = (color >> kGModShift) & 0xFF; + byte cb = (color >> kBModShift) & 0xFF; + + for (uint32 i = 0; i < height; i++) { + out = outo; + in = ino; + for (uint32 j = 0; j < width; j++) { + + out[kAIndex] = 255; + if (cb != 255) { + out[kBIndex] = MAX(out[kBIndex] - ((in[kBIndex] * cb * (out[kBIndex]) * in[kAIndex]) >> 24), 0); + } else { + out[kBIndex] = MAX(out[kBIndex] - (in[kBIndex] * (out[kBIndex]) * in[kAIndex] >> 16), 0); + } + + if (cg != 255) { + out[kGIndex] = MAX(out[kGIndex] - ((in[kGIndex] * cg * (out[kGIndex]) * in[kAIndex]) >> 24), 0); + } else { + out[kGIndex] = MAX(out[kGIndex] - (in[kGIndex] * (out[kGIndex]) * in[kAIndex] >> 16), 0); + } + + if (cr != 255) { + out[kRIndex] = MAX(out[kRIndex] - ((in[kRIndex] * cr * (out[kRIndex]) * in[kAIndex]) >> 24), 0); + } else { + out[kRIndex] = MAX(out[kRIndex] - (in[kRIndex] * (out[kRIndex]) * in[kAIndex] >> 16), 0); + } + + in += inStep; + out += 4; + } + outo += pitch; + ino += inoStep; + } + } +} + +Common::Rect TransparentSurface::blit(Graphics::Surface &target, int posX, int posY, int flipping, Common::Rect *pPartRect, uint color, int width, int height, TSpriteBlendMode blendMode) { + + Common::Rect retSize; + retSize.top = 0; + retSize.left = 0; + retSize.setWidth(0); + retSize.setHeight(0); + // Check if we need to draw anything at all + int ca = (color >> 24) & 0xff; + + if (ca == 0) { + return retSize; + } + + // Create an encapsulating surface for the data + TransparentSurface srcImage(*this, false); + // TODO: Is the data really in the screen format? + if (format.bytesPerPixel != 4) { + warning("TransparentSurface can only blit 32bpp images, but got %d", format.bytesPerPixel * 8); + return retSize; + } + + if (pPartRect) { + + int xOffset = pPartRect->left; + int yOffset = pPartRect->top; + + if (flipping & FLIP_V) { + yOffset = srcImage.h - pPartRect->bottom; + } + + if (flipping & FLIP_H) { + xOffset = srcImage.w - pPartRect->right; + } + + srcImage.pixels = getBasePtr(xOffset, yOffset); + srcImage.w = pPartRect->width(); + srcImage.h = pPartRect->height(); + + debug(6, "Blit(%d, %d, %d, [%d, %d, %d, %d], %08x, %d, %d)", posX, posY, flipping, + pPartRect->left, pPartRect->top, pPartRect->width(), pPartRect->height(), color, width, height); + } else { + + debug(6, "Blit(%d, %d, %d, [%d, %d, %d, %d], %08x, %d, %d)", posX, posY, flipping, 0, 0, + srcImage.w, srcImage.h, color, width, height); + } + + if (width == -1) { + width = srcImage.w; + } + if (height == -1) { + height = srcImage.h; + } + +#ifdef SCALING_TESTING + // Hardcode scaling to 66% to test scaling + width = width * 2 / 3; + height = height * 2 / 3; +#endif + + Graphics::Surface *img = nullptr; + Graphics::Surface *imgScaled = nullptr; + byte *savedPixels = nullptr; + if ((width != srcImage.w) || (height != srcImage.h)) { + // Scale the image + img = imgScaled = srcImage.scale(width, height); + savedPixels = (byte *)img->getPixels(); + } else { + img = &srcImage; + } + + // Handle off-screen clipping + if (posY < 0) { + img->h = MAX(0, (int)img->h - -posY); + img->setPixels((byte *)img->getBasePtr(0, -posY)); + posY = 0; + } + + if (posX < 0) { + img->w = MAX(0, (int)img->w - -posX); + img->setPixels((byte *)img->getBasePtr(-posX, 0)); + posX = 0; + } + + img->w = CLIP((int)img->w, 0, (int)MAX((int)target.w - posX, 0)); + img->h = CLIP((int)img->h, 0, (int)MAX((int)target.h - posY, 0)); + + if ((img->w > 0) && (img->h > 0)) { + int xp = 0, yp = 0; + + int inStep = 4; + int inoStep = img->pitch; + if (flipping & FLIP_H) { + inStep = -inStep; + xp = img->w - 1; + } + + if (flipping & FLIP_V) { + inoStep = -inoStep; + yp = img->h - 1; + } + + byte *ino = (byte *)img->getBasePtr(xp, yp); + byte *outo = (byte *)target.getBasePtr(posX, posY); + + if (color == 0xFFFFFFFF && blendMode == BLEND_NORMAL && _alphaMode == ALPHA_OPAQUE) { + doBlitOpaqueFast(ino, outo, img->w, img->h, target.pitch, inStep, inoStep); + } else if (color == 0xFFFFFFFF && blendMode == BLEND_NORMAL && _alphaMode == ALPHA_BINARY) { + doBlitBinaryFast(ino, outo, img->w, img->h, target.pitch, inStep, inoStep); + } else { + if (blendMode == BLEND_ADDITIVE) { + doBlitAdditiveBlend(ino, outo, img->w, img->h, target.pitch, inStep, inoStep, color); + } else if (blendMode == BLEND_SUBTRACTIVE) { + doBlitSubtractiveBlend(ino, outo, img->w, img->h, target.pitch, inStep, inoStep, color); + } else { + assert(blendMode == BLEND_NORMAL); + doBlitAlphaBlend(ino, outo, img->w, img->h, target.pitch, inStep, inoStep, color); + } + } + + } + + retSize.setWidth(img->w); + retSize.setHeight(img->h); + + if (imgScaled) { + imgScaled->setPixels(savedPixels); + imgScaled->free(); + delete imgScaled; + } + + return retSize; +} + +/** + * Writes a color key to the alpha channel of the surface + * @param rKey the red component of the color key + * @param gKey the green component of the color key + * @param bKey the blue component of the color key + * @param overwriteAlpha if true, all other alpha will be set fully opaque + */ +void TransparentSurface::applyColorKey(uint8 rKey, uint8 gKey, uint8 bKey, bool overwriteAlpha) { + assert(format.bytesPerPixel == 4); + for (int i = 0; i < h; i++) { + for (int j = 0; j < w; j++) { + uint32 pix = ((uint32 *)pixels)[i * w + j]; + uint8 r, g, b, a; + format.colorToARGB(pix, a, r, g, b); + if (r == rKey && g == gKey && b == bKey) { + a = 0; + ((uint32 *)pixels)[i * w + j] = format.ARGBToColor(a, r, g, b); + } else if (overwriteAlpha) { + a = 255; + ((uint32 *)pixels)[i * w + j] = format.ARGBToColor(a, r, g, b); + } + } + } +} + +AlphaType TransparentSurface::getAlphaMode() const { + return _alphaMode; +} + +void TransparentSurface::setAlphaMode(AlphaType mode) { + _alphaMode = mode; +} + + + + + + +/* + +The below two functions are adapted from SDL_rotozoom.c, +taken from SDL_gfx-2.0.18. + +Its copyright notice: + +============================================================================= +SDL_rotozoom.c: rotozoomer, zoomer and shrinker for 32bit or 8bit surfaces + +Copyright (C) 2001-2012 Andreas Schiffler + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any damages +arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not +claim that you wrote the original software. If you use this software +in a product, an acknowledgment in the product documentation would be +appreciated but is not required. + +2. Altered source versions must be plainly marked as such, and must not be +misrepresented as being the original software. + +3. This notice may not be removed or altered from any source +distribution. + +Andreas Schiffler -- aschiffler at ferzkopp dot net +============================================================================= + + +The functions have been adapted for different structures and coordinate +systems. + +*/ + + + + + +TransparentSurface *TransparentSurface::rotoscale(const TransformStruct &transform) const { + + assert(transform._angle != 0); // This would not be ideal; rotoscale() should never be called in conditional branches where angle = 0 anyway. + + Common::Point newHotspot; + Common::Rect srcRect(0, 0, (int16)w, (int16)h); + Common::Rect rect = TransformTools::newRect(Common::Rect(srcRect), transform, &newHotspot); + Common::Rect dstRect(0, 0, (int16)(rect.right - rect.left), (int16)(rect.bottom - rect.top)); + + TransparentSurface *target = new TransparentSurface(); + assert(format.bytesPerPixel == 4); + + int srcW = w; + int srcH = h; + int dstW = dstRect.width(); + int dstH = dstRect.height(); + + target->create((uint16)dstW, (uint16)dstH, this->format); + + if (transform._zoom.x == 0 || transform._zoom.y == 0) { + return target; + } + + uint32 invAngle = 360 - (transform._angle % 360); + float invCos = cos(invAngle * M_PI / 180.0); + float invSin = sin(invAngle * M_PI / 180.0); + + struct tColorRGBA { byte r; byte g; byte b; byte a; }; + int icosx = (int)(invCos * (65536.0f * kDefaultZoomX / transform._zoom.x)); + int isinx = (int)(invSin * (65536.0f * kDefaultZoomX / transform._zoom.x)); + int icosy = (int)(invCos * (65536.0f * kDefaultZoomY / transform._zoom.y)); + int isiny = (int)(invSin * (65536.0f * kDefaultZoomY / transform._zoom.y)); + + + bool flipx = false, flipy = false; // TODO: See mirroring comment in RenderTicket ctor + + int xd = (srcRect.left + transform._hotspot.x) << 16; + int yd = (srcRect.top + transform._hotspot.y) << 16; + int cx = newHotspot.x; + int cy = newHotspot.y; + + int ax = -icosx * cx; + int ay = -isiny * cx; + int sw = srcW - 1; + int sh = srcH - 1; + + tColorRGBA *pc = (tColorRGBA*)target->getBasePtr(0, 0); + + for (int y = 0; y < dstH; y++) { + int t = cy - y; + int sdx = ax + (isinx * t) + xd; + int sdy = ay - (icosy * t) + yd; + for (int x = 0; x < dstW; x++) { + int dx = (sdx >> 16); + int dy = (sdy >> 16); + if (flipx) { + dx = sw - dx; + } + if (flipy) { + dy = sh - dy; + } + +#ifdef ENABLE_BILINEAR + if ((dx > -1) && (dy > -1) && (dx < sw) && (dy < sh)) { + const tColorRGBA *sp = (const tColorRGBA *)getBasePtr(dx, dy); + tColorRGBA c00, c01, c10, c11, cswap; + c00 = *sp; + sp += 1; + c01 = *sp; + sp += (this->pitch / 4); + c11 = *sp; + sp -= 1; + c10 = *sp; + if (flipx) { + cswap = c00; c00=c01; c01=cswap; + cswap = c10; c10=c11; c11=cswap; + } + if (flipy) { + cswap = c00; c00=c10; c10=cswap; + cswap = c01; c01=c11; c11=cswap; + } + /* + * Interpolate colors + */ + int ex = (sdx & 0xffff); + int ey = (sdy & 0xffff); + int t1, t2; + t1 = ((((c01.r - c00.r) * ex) >> 16) + c00.r) & 0xff; + t2 = ((((c11.r - c10.r) * ex) >> 16) + c10.r) & 0xff; + pc->r = (((t2 - t1) * ey) >> 16) + t1; + t1 = ((((c01.g - c00.g) * ex) >> 16) + c00.g) & 0xff; + t2 = ((((c11.g - c10.g) * ex) >> 16) + c10.g) & 0xff; + pc->g = (((t2 - t1) * ey) >> 16) + t1; + t1 = ((((c01.b - c00.b) * ex) >> 16) + c00.b) & 0xff; + t2 = ((((c11.b - c10.b) * ex) >> 16) + c10.b) & 0xff; + pc->b = (((t2 - t1) * ey) >> 16) + t1; + t1 = ((((c01.a - c00.a) * ex) >> 16) + c00.a) & 0xff; + t2 = ((((c11.a - c10.a) * ex) >> 16) + c10.a) & 0xff; + pc->a = (((t2 - t1) * ey) >> 16) + t1; + } +#else + if ((dx >= 0) && (dy >= 0) && (dx < srcW) && (dy < srcH)) { + const tColorRGBA *sp = (const tColorRGBA *)getBasePtr(dx, dy); + *pc = *sp; + } +#endif + sdx += icosx; + sdy += isiny; + pc++; + } + } + return target; +} + +TransparentSurface *TransparentSurface::scale(uint16 newWidth, uint16 newHeight) const { + + Common::Rect srcRect(0, 0, (int16)w, (int16)h); + Common::Rect dstRect(0, 0, (int16)newWidth, (int16)newHeight); + + TransparentSurface *target = new TransparentSurface(); + + assert(format.bytesPerPixel == 4); + + int srcW = srcRect.width(); + int srcH = srcRect.height(); + int dstW = dstRect.width(); + int dstH = dstRect.height(); + + target->create((uint16)dstW, (uint16)dstH, this->format); + +#ifdef ENABLE_BILINEAR + + // NB: The actual order of these bytes may not be correct, but + // since all values are treated equal, that does not matter. + struct tColorRGBA { byte r; byte g; byte b; byte a; }; + + bool flipx = false, flipy = false; // TODO: See mirroring comment in RenderTicket ctor + + + int *sax = new int[dstW + 1]; + int *say = new int[dstH + 1]; + assert(sax && say); + + /* + * Precalculate row increments + */ + int spixelw = (srcW - 1); + int spixelh = (srcH - 1); + int sx = (int) (65536.0f * (float) spixelw / (float) (dstW - 1)); + int sy = (int) (65536.0f * (float) spixelh / (float) (dstH - 1)); + + /* Maximum scaled source size */ + int ssx = (srcW << 16) - 1; + int ssy = (srcH << 16) - 1; + + /* Precalculate horizontal row increments */ + int csx = 0; + int *csax = sax; + for (int x = 0; x <= dstW; x++) { + *csax = csx; + csax++; + csx += sx; + + /* Guard from overflows */ + if (csx > ssx) { + csx = ssx; + } + } + + /* Precalculate vertical row increments */ + int csy = 0; + int *csay = say; + for (int y = 0; y <= dstH; y++) { + *csay = csy; + csay++; + csy += sy; + + /* Guard from overflows */ + if (csy > ssy) { + csy = ssy; + } + } + + const tColorRGBA *sp = (const tColorRGBA *) getBasePtr(0, 0); + tColorRGBA *dp = (tColorRGBA *) target->getBasePtr(0, 0); + int spixelgap = srcW; + + if (flipx) { + sp += spixelw; + } + if (flipy) { + sp += spixelgap * spixelh; + } + + csay = say; + for (int y = 0; y < dstH; y++) { + const tColorRGBA *csp = sp; + csax = sax; + for (int x = 0; x < dstW; x++) { + /* + * Setup color source pointers + */ + int ex = (*csax & 0xffff); + int ey = (*csay & 0xffff); + int cx = (*csax >> 16); + int cy = (*csay >> 16); + + const tColorRGBA *c00, *c01, *c10, *c11; + c00 = sp; + c01 = sp; + c10 = sp; + if (cy < spixelh) { + if (flipy) { + c10 -= spixelgap; + } else { + c10 += spixelgap; + } + } + c11 = c10; + if (cx < spixelw) { + if (flipx) { + c01--; + c11--; + } else { + c01++; + c11++; + } + } + + /* + * Draw and interpolate colors + */ + int t1, t2; + t1 = ((((c01->r - c00->r) * ex) >> 16) + c00->r) & 0xff; + t2 = ((((c11->r - c10->r) * ex) >> 16) + c10->r) & 0xff; + dp->r = (((t2 - t1) * ey) >> 16) + t1; + t1 = ((((c01->g - c00->g) * ex) >> 16) + c00->g) & 0xff; + t2 = ((((c11->g - c10->g) * ex) >> 16) + c10->g) & 0xff; + dp->g = (((t2 - t1) * ey) >> 16) + t1; + t1 = ((((c01->b - c00->b) * ex) >> 16) + c00->b) & 0xff; + t2 = ((((c11->b - c10->b) * ex) >> 16) + c10->b) & 0xff; + dp->b = (((t2 - t1) * ey) >> 16) + t1; + t1 = ((((c01->a - c00->a) * ex) >> 16) + c00->a) & 0xff; + t2 = ((((c11->a - c10->a) * ex) >> 16) + c10->a) & 0xff; + dp->a = (((t2 - t1) * ey) >> 16) + t1; + + /* + * Advance source pointer x + */ + int *salastx = csax; + csax++; + int sstepx = (*csax >> 16) - (*salastx >> 16); + if (flipx) { + sp -= sstepx; + } else { + sp += sstepx; + } + + /* + * Advance destination pointer x + */ + dp++; + } + /* + * Advance source pointer y + */ + int *salasty = csay; + csay++; + int sstepy = (*csay >> 16) - (*salasty >> 16); + sstepy *= spixelgap; + if (flipy) { + sp = csp - sstepy; + } else { + sp = csp + sstepy; + } + } + + delete[] sax; + delete[] say; + +#else + + int *scaleCacheX = new int[dstW]; + for (int x = 0; x < dstW; x++) { + scaleCacheX[x] = (x * srcW) / dstW; + } + + for (int y = 0; y < dstH; y++) { + uint32 *destP = (uint32 *)target->getBasePtr(0, y); + const uint32 *srcP = (const uint32 *)getBasePtr(0, (y * srcH) / dstH); + for (int x = 0; x < dstW; x++) { + *destP++ = srcP[scaleCacheX[x]]; + } + } + delete[] scaleCacheX; + +#endif + + return target; + +} + +} // End of namespace Graphics diff --git a/graphics/transparent_surface.h b/graphics/transparent_surface.h new file mode 100644 index 0000000000..cc35f8e6a0 --- /dev/null +++ b/graphics/transparent_surface.h @@ -0,0 +1,152 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program 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; either version 2 + * of the License, or (at your option) any later version. + * + * This program 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. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef GRAPHICS_TRANSPARENTSURFACE_H +#define GRAPHICS_TRANSPARENTSURFACE_H + +#include "graphics/surface.h" +#include "graphics/transform_struct.h" + +/* + * This code is based on Broken Sword 2.5 engine + * + * Copyright (c) Malte Thiesen, Daniel Queteschiner and Michael Elsdoerfer + * + * Licensed under GNU GPL v2 + * + */ + +// TODO: Find a better solution for this. +#define BS_RGB(R,G,B) (0xFF000000 | ((R) << 16) | ((G) << 8) | (B)) +#define BS_ARGB(A,R,G,B) (((A) << 24) | ((R) << 16) | ((G) << 8) | (B)) + +namespace Graphics { + +// Enums +/** + @brief The possible flipping parameters for the blit method. + */ +enum FLIP_FLAGS { + /// The image will not be flipped. + FLIP_NONE = 0, + /// The image will be flipped at the horizontal axis. + FLIP_H = 1, + /// The image will be flipped at the vertical axis. + FLIP_V = 2, + /// The image will be flipped at the horizontal and vertical axis. + FLIP_HV = FLIP_H | FLIP_V, + /// The image will be flipped at the horizontal and vertical axis. + FLIP_VH = FLIP_H | FLIP_V +}; + +enum AlphaType { + ALPHA_OPAQUE = 0, + ALPHA_BINARY = 1, + ALPHA_FULL = 2 +}; + +/** + * A transparent graphics surface, which implements alpha blitting. + */ +struct TransparentSurface : public Graphics::Surface { + TransparentSurface(); + TransparentSurface(const Graphics::Surface &surf, bool copyData = false); + + void setColorKey(char r, char g, char b); + void disableColorKey(); + + /** + @brief renders the surface to another surface + @param target a pointer to the target surface. In most cases this is the framebuffer. + @param posX the position on the X-axis in the target image in pixels where the image is supposed to be rendered.
+ The default value is 0. + @param posY the position on the Y-axis in the target image in pixels where the image is supposed to be rendered.
+ The default value is 0. + @param flipping how the the image should be flipped.
+ The default value is BS_Image::FLIP_NONE (no flipping) + @param pPartRect Pointer on Common::Rect which specifies the section to be rendered. If the whole image has to be rendered the Pointer is NULL.
+ This referes to the unflipped and unscaled image.
+ The default value is NULL. + @param color an ARGB color value, which determines the parameters for the color modulation und alpha blending.
+ The alpha component of the color determines the alpha blending parameter (0 = no covering, 255 = full covering).
+ The color components determines the color for color modulation.
+ The default value is BS_ARGB(255, 255, 255, 255) (full covering, no color modulation). + The macros BS_RGB and BS_ARGB can be used for the creation of the color value. + @param width the output width of the screen section. + The images will be scaled if the output width of the screen section differs from the image section.
+ The value -1 determines that the image should not be scaled.
+ The default value is -1. + @param height the output height of the screen section. + The images will be scaled if the output width of the screen section differs from the image section.
+ The value -1 determines that the image should not be scaled.
+ The default value is -1. + @return returns false if the rendering failed. + */ + Common::Rect blit(Graphics::Surface &target, int posX = 0, int posY = 0, + int flipping = FLIP_NONE, + Common::Rect *pPartRect = nullptr, + uint color = BS_ARGB(255, 255, 255, 255), + int width = -1, int height = -1, + TSpriteBlendMode blend = BLEND_NORMAL); + void applyColorKey(uint8 r, uint8 g, uint8 b, bool overwriteAlpha = false); + + /** + * @brief Scale function; this returns a transformed version of this surface after rotation and + * scaling. Please do not use this if angle != 0, use rotoscale. + * + * @param newWidth the resulting width. + * @param newHeight the resulting height. + * @see TransformStruct + */ + TransparentSurface *scale(uint16 newWidth, uint16 newHeight) const; + + /** + * @brief Rotoscale function; this returns a transformed version of this surface after rotation and + * scaling. Please do not use this if angle == 0, use plain old scaling function. + * + * @param transform a TransformStruct wrapping the required info. @see TransformStruct + * + */ + TransparentSurface *rotoscale(const TransformStruct &transform) const; + AlphaType getAlphaMode() const; + void setAlphaMode(AlphaType); +private: + AlphaType _alphaMode; + +}; + +/** + * A deleter for Surface objects which can be used with SharedPtr. + * + * This deleter assures Surface::free is called on deletion. + */ +/*struct SharedPtrTransparentSurfaceDeleter { + void operator()(TransparentSurface *ptr) { + ptr->free(); + delete ptr; + } +};*/ + +} // End of namespace Graphics + + +#endif -- cgit v1.2.3 From 385f8358ab2ea138a39eb6fc76d246b3c5f48e45 Mon Sep 17 00:00:00 2001 From: Eugene Sandulenko Date: Tue, 3 Jun 2014 18:19:59 +0300 Subject: WINTERMUTE: Switch to use of moved to OSystem TransparentSurface --- engines/wintermute/base/base_frame.cpp | 2 +- engines/wintermute/base/base_frame.h | 3 +- engines/wintermute/base/base_object.cpp | 8 +- engines/wintermute/base/base_object.h | 3 +- .../wintermute/base/base_persistence_manager.cpp | 4 +- engines/wintermute/base/base_sprite.cpp | 2 +- engines/wintermute/base/base_sprite.h | 10 +- engines/wintermute/base/base_sub_frame.cpp | 36 +- engines/wintermute/base/base_sub_frame.h | 3 +- .../wintermute/base/font/base_font_truetype.cpp | 2 +- engines/wintermute/base/gfx/base_image.cpp | 6 +- engines/wintermute/base/gfx/base_surface.cpp | 2 +- engines/wintermute/base/gfx/base_surface.h | 14 +- .../base/gfx/osystem/base_render_osystem.cpp | 6 +- .../base/gfx/osystem/base_render_osystem.h | 4 +- .../base/gfx/osystem/base_surface_osystem.cpp | 58 +- .../base/gfx/osystem/base_surface_osystem.h | 20 +- .../wintermute/base/gfx/osystem/render_ticket.cpp | 18 +- .../wintermute/base/gfx/osystem/render_ticket.h | 8 +- engines/wintermute/dctypes.h | 8 - engines/wintermute/graphics/transform_struct.cpp | 119 --- engines/wintermute/graphics/transform_struct.h | 89 --- engines/wintermute/graphics/transform_tools.cpp | 87 --- engines/wintermute/graphics/transform_tools.h | 53 -- .../wintermute/graphics/transparent_surface.cpp | 851 --------------------- engines/wintermute/graphics/transparent_surface.h | 153 ---- engines/wintermute/module.mk | 3 - 27 files changed, 107 insertions(+), 1465 deletions(-) delete mode 100644 engines/wintermute/graphics/transform_struct.cpp delete mode 100644 engines/wintermute/graphics/transform_struct.h delete mode 100644 engines/wintermute/graphics/transform_tools.cpp delete mode 100644 engines/wintermute/graphics/transform_tools.h delete mode 100644 engines/wintermute/graphics/transparent_surface.cpp delete mode 100644 engines/wintermute/graphics/transparent_surface.h diff --git a/engines/wintermute/base/base_frame.cpp b/engines/wintermute/base/base_frame.cpp index f2c24b8f6a..471185f2d2 100644 --- a/engines/wintermute/base/base_frame.cpp +++ b/engines/wintermute/base/base_frame.cpp @@ -76,7 +76,7 @@ BaseFrame::~BaseFrame() { ////////////////////////////////////////////////////////////////////// -bool BaseFrame::draw(int x, int y, BaseObject *registerOwner, float zoomX, float zoomY, bool precise, uint32 alpha, bool allFrames, float rotate, TSpriteBlendMode blendMode) { +bool BaseFrame::draw(int x, int y, BaseObject *registerOwner, float zoomX, float zoomY, bool precise, uint32 alpha, bool allFrames, float rotate, Graphics::TSpriteBlendMode blendMode) { bool res; for (uint32 i = 0; i < _subframes.size(); i++) { diff --git a/engines/wintermute/base/base_frame.h b/engines/wintermute/base/base_frame.h index 49a56592bb..ff9e67a166 100644 --- a/engines/wintermute/base/base_frame.h +++ b/engines/wintermute/base/base_frame.h @@ -31,6 +31,7 @@ #include "engines/wintermute/base/base_scriptable.h" #include "engines/wintermute/coll_templ.h" +#include "graphics/transform_struct.h" namespace Wintermute { class BaseSound; @@ -51,7 +52,7 @@ public: int32 _moveX; uint32 _delay; BaseArray _subframes; - bool draw(int x, int y, BaseObject *registerOwner = nullptr, float zoomX = 100, float zoomY = 100, bool precise = true, uint32 alpha = 0xFFFFFFFF, bool allFrames = false, float rotate = 0.0f, TSpriteBlendMode blendMode = BLEND_NORMAL); + bool draw(int x, int y, BaseObject *registerOwner = nullptr, float zoomX = 100, float zoomY = 100, bool precise = true, uint32 alpha = 0xFFFFFFFF, bool allFrames = false, float rotate = 0.0f, Graphics::TSpriteBlendMode blendMode = Graphics::BLEND_NORMAL); bool loadBuffer(char *buffer, int lifeTime, bool keepLoaded); BaseFrame(BaseGame *inGame); diff --git a/engines/wintermute/base/base_object.cpp b/engines/wintermute/base/base_object.cpp index 708df8def1..cce3561f67 100644 --- a/engines/wintermute/base/base_object.cpp +++ b/engines/wintermute/base/base_object.cpp @@ -95,7 +95,7 @@ BaseObject::BaseObject(BaseGame *inGame) : BaseScriptHolder(inGame) { _sFXType = SFX_NONE; _sFXParam1 = _sFXParam2 = _sFXParam3 = _sFXParam4 = 0; - _blendMode = BLEND_NORMAL; + _blendMode = Graphics::BLEND_NORMAL; } @@ -807,10 +807,10 @@ bool BaseObject::scSetProperty(const char *name, ScValue *value) { ////////////////////////////////////////////////////////////////////////// else if (strcmp(name, "BlendMode") == 0) { int i = value->getInt(); - if (i < BLEND_NORMAL || i >= NUM_BLEND_MODES) { - i = BLEND_NORMAL; + if (i < Graphics::BLEND_NORMAL || i >= Graphics::NUM_BLEND_MODES) { + i = Graphics::BLEND_NORMAL; } - _blendMode = (TSpriteBlendMode)i; + _blendMode = (Graphics::TSpriteBlendMode)i; return STATUS_OK; } diff --git a/engines/wintermute/base/base_object.h b/engines/wintermute/base/base_object.h index f5036f4ec4..8ca8ffc246 100644 --- a/engines/wintermute/base/base_object.h +++ b/engines/wintermute/base/base_object.h @@ -33,6 +33,7 @@ #include "engines/wintermute/base/base_script_holder.h" #include "engines/wintermute/persistent.h" #include "common/events.h" +#include "graphics/transform_struct.h" namespace Wintermute { @@ -75,7 +76,7 @@ protected: int32 _iD; char *_soundEvent; public: - TSpriteBlendMode _blendMode; + Graphics::TSpriteBlendMode _blendMode; virtual bool afterMove(); float _scale; uint32 _alphaColor; diff --git a/engines/wintermute/base/base_persistence_manager.cpp b/engines/wintermute/base/base_persistence_manager.cpp index bea55fb857..bb5e0c4091 100644 --- a/engines/wintermute/base/base_persistence_manager.cpp +++ b/engines/wintermute/base/base_persistence_manager.cpp @@ -36,7 +36,7 @@ #include "engines/wintermute/base/gfx/base_image.h" #include "engines/wintermute/base/save_thumb_helper.h" #include "engines/wintermute/base/sound/base_sound.h" -#include "engines/wintermute/graphics/transparent_surface.h" +#include "graphics/transparent_surface.h" #include "engines/wintermute/wintermute.h" #include "graphics/scaler.h" #include "image/bmp.h" @@ -173,7 +173,7 @@ void BasePersistenceManager::getSaveStateDesc(int slot, SaveStateDescriptor &des Image::BitmapDecoder bmpDecoder; if (bmpDecoder.loadStream(thumbStream)) { const Graphics::Surface *bmpSurface = bmpDecoder.getSurface(); - TransparentSurface *scaleableSurface = new TransparentSurface(*bmpSurface, false); + Graphics::TransparentSurface *scaleableSurface = new Graphics::TransparentSurface(*bmpSurface, false); Graphics::Surface *scaled = scaleableSurface->scale(kThumbnailWidth, kThumbnailHeight2); Graphics::Surface *thumb = scaled->convertTo(g_system->getOverlayFormat()); desc.setThumbnail(thumb); diff --git a/engines/wintermute/base/base_sprite.cpp b/engines/wintermute/base/base_sprite.cpp index 2e00998037..04060bff32 100644 --- a/engines/wintermute/base/base_sprite.cpp +++ b/engines/wintermute/base/base_sprite.cpp @@ -418,7 +418,7 @@ bool BaseSprite::getCurrentFrame(float zoomX, float zoomY) { ////////////////////////////////////////////////////////////////////// -bool BaseSprite::display(int x, int y, BaseObject *registerVal, float zoomX, float zoomY, uint32 alpha, float rotate, TSpriteBlendMode blendMode) { +bool BaseSprite::display(int x, int y, BaseObject *registerVal, float zoomX, float zoomY, uint32 alpha, float rotate, Graphics::TSpriteBlendMode blendMode) { if (_currentFrame < 0 || _currentFrame >= (int32)_frames.size()) { return STATUS_OK; } diff --git a/engines/wintermute/base/base_sprite.h b/engines/wintermute/base/base_sprite.h index 92287995d9..ec71512ec9 100644 --- a/engines/wintermute/base/base_sprite.h +++ b/engines/wintermute/base/base_sprite.h @@ -32,7 +32,7 @@ #include "engines/wintermute/coll_templ.h" #include "engines/wintermute/base/base_script_holder.h" -#include "engines/wintermute/graphics/transform_tools.h" +#include "graphics/transform_tools.h" namespace Wintermute { class BaseFrame; @@ -45,17 +45,17 @@ public: void setDefaults(); DECLARE_PERSISTENT(BaseSprite, BaseScriptHolder) - bool getBoundingRect(Rect32 *rect, int x, int y, float scaleX = kDefaultZoomX, float scaleY = kDefaultZoomY); + bool getBoundingRect(Rect32 *rect, int x, int y, float scaleX = Graphics::kDefaultZoomX, float scaleY = Graphics::kDefaultZoomY); int32 _moveY; int32 _moveX; - bool display(int x, int y, BaseObject *registerOwner = nullptr, float zoomX = kDefaultZoomX, float zoomY = kDefaultZoomY, uint32 alpha = kDefaultRgbaMod, float rotate = kDefaultAngle, TSpriteBlendMode blendMode = BLEND_NORMAL); - bool getCurrentFrame(float zoomX = kDefaultZoomX, float zoomY = kDefaultZoomY); + bool display(int x, int y, BaseObject *registerOwner = nullptr, float zoomX = Graphics::kDefaultZoomX, float zoomY = Graphics::kDefaultZoomY, uint32 alpha = Graphics::kDefaultRgbaMod, float rotate = Graphics::kDefaultAngle, Graphics::TSpriteBlendMode blendMode = Graphics::BLEND_NORMAL); + bool getCurrentFrame(float zoomX = Graphics::kDefaultZoomX, float zoomY = Graphics::kDefaultZoomY); void reset(); bool isChanged(); bool isFinished(); bool loadBuffer(char *buffer, bool compete = true, int lifeTime = -1, TSpriteCacheType cacheType = CACHE_ALL); bool loadFile(const Common::String &filename, int lifeTime = -1, TSpriteCacheType cacheType = CACHE_ALL); - bool draw(int x, int y, BaseObject *Register = nullptr, float zoomX = kDefaultZoomX, float zoomY = kDefaultZoomY, uint32 alpha = kDefaultRgbaMod); + bool draw(int x, int y, BaseObject *Register = nullptr, float zoomX = Graphics::kDefaultZoomX, float zoomY = Graphics::kDefaultZoomY, uint32 alpha = Graphics::kDefaultRgbaMod); bool _looping; int32 _currentFrame; bool addFrame(const char *filename, uint32 delay = 0, int hotspotX = 0, int hotspotY = 0, Rect32 *rect = nullptr); diff --git a/engines/wintermute/base/base_sub_frame.cpp b/engines/wintermute/base/base_sub_frame.cpp index 3a6e28b1f2..4388942064 100644 --- a/engines/wintermute/base/base_sub_frame.cpp +++ b/engines/wintermute/base/base_sub_frame.cpp @@ -37,8 +37,8 @@ #include "engines/wintermute/base/gfx/base_renderer.h" #include "engines/wintermute/base/scriptables/script_value.h" #include "engines/wintermute/base/scriptables/script_stack.h" -#include "engines/wintermute/graphics/transform_tools.h" -#include "engines/wintermute/graphics/transform_struct.h" +#include "graphics/transform_tools.h" +#include "graphics/transform_struct.h" namespace Wintermute { @@ -47,9 +47,9 @@ IMPLEMENT_PERSISTENT(BaseSubFrame, false) ////////////////////////////////////////////////////////////////////////// BaseSubFrame::BaseSubFrame(BaseGame *inGame) : BaseScriptable(inGame, true) { _surface = nullptr; - _hotspotX = kDefaultHotspotX; - _hotspotY = kDefaultHotspotY; - _alpha = kDefaultRgbaMod; + _hotspotX = Graphics::kDefaultHotspotX; + _hotspotY = Graphics::kDefaultHotspotY; + _alpha = Graphics::kDefaultRgbaMod; _transparent = 0xFFFF00FF; _wantsDefaultRect = false; @@ -234,7 +234,7 @@ const char* BaseSubFrame::getSurfaceFilename() { } ////////////////////////////////////////////////////////////////////// -bool BaseSubFrame::draw(int x, int y, BaseObject *registerOwner, float zoomX, float zoomY, bool precise, uint32 alpha, float rotate, TSpriteBlendMode blendMode) { +bool BaseSubFrame::draw(int x, int y, BaseObject *registerOwner, float zoomX, float zoomY, bool precise, uint32 alpha, float rotate, Graphics::TSpriteBlendMode blendMode) { rotate = fmod(rotate, 360.0f); if (rotate < 0) { @@ -246,7 +246,7 @@ bool BaseSubFrame::draw(int x, int y, BaseObject *registerOwner, float zoomX, fl } if (registerOwner != nullptr && !_decoration) { - if (zoomX == kDefaultZoomX && zoomY == kDefaultZoomY) { + if (zoomX == Graphics::kDefaultZoomX && zoomY == Graphics::kDefaultZoomY) { BaseEngine::getRenderer()->addRectToList(new BaseActiveRect(_gameRef, registerOwner, this, x - _hotspotX + getRect().left, y - _hotspotY + getRect().top, getRect().right - getRect().left, getRect().bottom - getRect().top, zoomX, zoomY, precise)); } else { BaseEngine::getRenderer()->addRectToList(new BaseActiveRect(_gameRef, registerOwner, this, (int)(x - (_hotspotX + getRect().left) * (zoomX / 100)), (int)(y - (_hotspotY + getRect().top) * (zoomY / 100)), (int)((getRect().right - getRect().left) * (zoomX / 100)), (int)((getRect().bottom - getRect().top) * (zoomY / 100)), zoomX, zoomY, precise)); @@ -259,24 +259,26 @@ bool BaseSubFrame::draw(int x, int y, BaseObject *registerOwner, float zoomX, fl bool res; //if (Alpha==0xFFFFFFFF) Alpha = _alpha; // TODO: better (combine owner's and self alpha) - if (_alpha != kDefaultRgbaMod) { + if (_alpha != Graphics::kDefaultRgbaMod) { alpha = _alpha; } - if (rotate != kDefaultAngle) { - Point32 boxOffset, rotatedHotspot, hotspotOffset, newOrigin; - Point32 origin(x, y); - Rect32 oldRect = getRect(); - Point32 newHotspot; - TransformStruct transform = TransformStruct(zoomX, zoomY, (uint32)rotate, _hotspotX, _hotspotY, blendMode, alpha, _mirrorX, _mirrorY, 0, 0); - Rect32 newRect = TransformTools::newRect (oldRect, transform, &newHotspot); + if (rotate != Graphics::kDefaultAngle) { + Point32 boxOffset, rotatedHotspot, hotspotOffset; + Common::Point origin(x, y); + Common::Point newOrigin; + Rect32 oldRect1 = getRect(); + Common::Rect oldRect(oldRect1.top, oldRect1.left, oldRect1.bottom, oldRect1.right); + Common::Point newHotspot; + Graphics::TransformStruct transform = Graphics::TransformStruct(zoomX, zoomY, (uint32)rotate, _hotspotX, _hotspotY, blendMode, alpha, _mirrorX, _mirrorY, 0, 0); + Rect32 newRect = Graphics::TransformTools::newRect(oldRect, transform, &newHotspot); newOrigin = origin - newHotspot; res = _surface->displayTransform(newOrigin.x, newOrigin.y, oldRect, newRect, transform); } else { - if (zoomX == kDefaultZoomX && zoomY == kDefaultZoomY) { + if (zoomX == Graphics::kDefaultZoomX && zoomY == Graphics::kDefaultZoomY) { res = _surface->displayTrans(x - _hotspotX, y - _hotspotY, getRect(), alpha, blendMode, _mirrorX, _mirrorY); } else { - res = _surface->displayTransZoom((int)(x - _hotspotX * (zoomX / kDefaultZoomX)), (int)(y - _hotspotY * (zoomY / kDefaultZoomY)), getRect(), zoomX, zoomY, alpha, blendMode, _mirrorX, _mirrorY); + res = _surface->displayTransZoom((int)(x - _hotspotX * (zoomX / Graphics::kDefaultZoomX)), (int)(y - _hotspotY * (zoomY / Graphics::kDefaultZoomY)), getRect(), zoomX, zoomY, alpha, blendMode, _mirrorX, _mirrorY); } } diff --git a/engines/wintermute/base/base_sub_frame.h b/engines/wintermute/base/base_sub_frame.h index b2859fa3f3..f156c332d6 100644 --- a/engines/wintermute/base/base_sub_frame.h +++ b/engines/wintermute/base/base_sub_frame.h @@ -32,6 +32,7 @@ #include "engines/wintermute/base/base.h" #include "engines/wintermute/base/base_scriptable.h" +#include "graphics/transform_struct.h" namespace Wintermute { class BaseObject; @@ -52,7 +53,7 @@ public: BaseSubFrame(BaseGame *inGame); virtual ~BaseSubFrame(); bool loadBuffer(char *buffer, int lifeTime, bool keepLoaded); - bool draw(int x, int y, BaseObject *registerOwner = nullptr, float zoomX = 100, float zoomY = 100, bool precise = true, uint32 alpha = 0xFFFFFFFF, float rotate = 0.0f, TSpriteBlendMode blendMode = BLEND_NORMAL); + bool draw(int x, int y, BaseObject *registerOwner = nullptr, float zoomX = 100, float zoomY = 100, bool precise = true, uint32 alpha = 0xFFFFFFFF, float rotate = 0.0f, Graphics::TSpriteBlendMode blendMode = Graphics::BLEND_NORMAL); bool getBoundingRect(Rect32 *rect, int x, int y, float scaleX = 100, float scaleY = 100); const char* getSurfaceFilename(); diff --git a/engines/wintermute/base/font/base_font_truetype.cpp b/engines/wintermute/base/font/base_font_truetype.cpp index df9a8648db..f27b565a7f 100644 --- a/engines/wintermute/base/font/base_font_truetype.cpp +++ b/engines/wintermute/base/font/base_font_truetype.cpp @@ -234,7 +234,7 @@ void BaseFontTT::drawText(const byte *text, int x, int y, int width, TTextAlign color = BYTETORGBA(RGBCOLGetR(color), RGBCOLGetG(color), RGBCOLGetB(color), RGBCOLGetA(renderer->_forceAlphaColor)); renderer->_forceAlphaColor = 0; } - surface->displayTransOffset(x, y - textOffset, rc, color, BLEND_NORMAL, false, false, _layers[i]->_offsetX, _layers[i]->_offsetY); + surface->displayTransOffset(x, y - textOffset, rc, color, Graphics::BLEND_NORMAL, false, false, _layers[i]->_offsetX, _layers[i]->_offsetY); renderer->_forceAlphaColor = origForceAlpha; } diff --git a/engines/wintermute/base/gfx/base_image.cpp b/engines/wintermute/base/gfx/base_image.cpp index e676fafdbf..a1548b83ea 100644 --- a/engines/wintermute/base/gfx/base_image.cpp +++ b/engines/wintermute/base/gfx/base_image.cpp @@ -28,7 +28,7 @@ #include "engines/wintermute/base/gfx/base_image.h" #include "engines/wintermute/base/base_file_manager.h" -#include "engines/wintermute/graphics/transparent_surface.h" +#include "graphics/transparent_surface.h" #include "graphics/surface.h" #include "image/png.h" #include "image/jpeg.h" @@ -112,7 +112,7 @@ bool BaseImage::saveBMPFile(const Common::String &filename) const { ////////////////////////////////////////////////////////////////////////// bool BaseImage::resize(int newWidth, int newHeight) { // WME Lite used FILTER_BILINEAR with FreeImage_Rescale here. - TransparentSurface temp(*_surface, true); + Graphics::TransparentSurface temp(*_surface, true); if (_deletableSurface) { _deletableSurface->free(); delete _deletableSurface; @@ -216,7 +216,7 @@ bool BaseImage::writeBMPToStream(Common::WriteStream *stream) const { bool BaseImage::copyFrom(BaseImage *origImage, int newWidth, int newHeight) { // WME Lite used FILTER_BILINEAR with FreeImage_Rescale here. - TransparentSurface temp(*origImage->_surface, false); + Graphics::TransparentSurface temp(*origImage->_surface, false); if (_deletableSurface) { _deletableSurface->free(); delete _deletableSurface; diff --git a/engines/wintermute/base/gfx/base_surface.cpp b/engines/wintermute/base/gfx/base_surface.cpp index ec42a63c77..f8b96b5baf 100644 --- a/engines/wintermute/base/gfx/base_surface.cpp +++ b/engines/wintermute/base/gfx/base_surface.cpp @@ -75,7 +75,7 @@ bool BaseSurface::displayHalfTrans(int x, int y, Rect32 rect) { } ////////////////////////////////////////////////////////////////////////// -bool BaseSurface::displayTransform(int x, int y, Rect32 rect, Rect32 newRect, const TransformStruct &transform) { +bool BaseSurface::displayTransform(int x, int y, Rect32 rect, Rect32 newRect, const Graphics::TransformStruct &transform) { return displayTransform(x, y, rect, newRect, transform); } diff --git a/engines/wintermute/base/gfx/base_surface.h b/engines/wintermute/base/gfx/base_surface.h index 7bd9bcbaea..ea743bdaf2 100644 --- a/engines/wintermute/base/gfx/base_surface.h +++ b/engines/wintermute/base/gfx/base_surface.h @@ -32,7 +32,7 @@ #include "engines/wintermute/base/base.h" #include "engines/wintermute/math/rect32.h" #include "graphics/surface.h" -#include "engines/wintermute/graphics/transform_struct.h" +#include "graphics/transform_struct.h" namespace Wintermute { @@ -50,12 +50,12 @@ public: virtual bool displayHalfTrans(int x, int y, Rect32 rect); virtual bool isTransparentAt(int x, int y); - virtual bool displayTransZoom(int x, int y, Rect32 rect, float zoomX, float zoomY, uint32 alpha = 0xFFFFFFFF, TSpriteBlendMode blendMode = BLEND_NORMAL, bool mirrorX = false, bool mirrorY = false) = 0; - virtual bool displayTrans(int x, int y, Rect32 rect, uint32 alpha = 0xFFFFFFFF, TSpriteBlendMode blendMode = BLEND_NORMAL, bool mirrorX = false, bool mirrorY = false) = 0; - virtual bool displayTransOffset(int x, int y, Rect32 rect, uint32 alpha = 0xFFFFFFFF, TSpriteBlendMode blendMode = BLEND_NORMAL, bool mirrorX = false, bool mirrorY = false, int offsetX = 0, int offsetY = 0) = 0; - virtual bool display(int x, int y, Rect32 rect, TSpriteBlendMode blendMode = BLEND_NORMAL, bool mirrorX = false, bool mirrorY = false) = 0; - virtual bool displayTransform(int x, int y, Rect32 rect, Rect32 newRect, const TransformStruct &transform) = 0; - virtual bool displayZoom(int x, int y, Rect32 rect, float zoomX, float zoomY, uint32 alpha = 0xFFFFFFFF, bool transparent = false, TSpriteBlendMode blendMode = BLEND_NORMAL, bool mirrorX = false, bool mirrorY = false) = 0; + virtual bool displayTransZoom(int x, int y, Rect32 rect, float zoomX, float zoomY, uint32 alpha = 0xFFFFFFFF, Graphics::TSpriteBlendMode blendMode = Graphics::BLEND_NORMAL, bool mirrorX = false, bool mirrorY = false) = 0; + virtual bool displayTrans(int x, int y, Rect32 rect, uint32 alpha = 0xFFFFFFFF, Graphics::TSpriteBlendMode blendMode = Graphics::BLEND_NORMAL, bool mirrorX = false, bool mirrorY = false) = 0; + virtual bool displayTransOffset(int x, int y, Rect32 rect, uint32 alpha = 0xFFFFFFFF, Graphics::TSpriteBlendMode blendMode = Graphics::BLEND_NORMAL, bool mirrorX = false, bool mirrorY = false, int offsetX = 0, int offsetY = 0) = 0; + virtual bool display(int x, int y, Rect32 rect, Graphics::TSpriteBlendMode blendMode = Graphics::BLEND_NORMAL, bool mirrorX = false, bool mirrorY = false) = 0; + virtual bool displayTransform(int x, int y, Rect32 rect, Rect32 newRect, const Graphics::TransformStruct &transform) = 0; + virtual bool displayZoom(int x, int y, Rect32 rect, float zoomX, float zoomY, uint32 alpha = 0xFFFFFFFF, bool transparent = false, Graphics::TSpriteBlendMode blendMode = Graphics::BLEND_NORMAL, bool mirrorX = false, bool mirrorY = false) = 0; virtual bool displayTiled(int x, int y, Rect32 rect, int numTimesX, int numTimesY) = 0; virtual bool restore(); virtual bool create(const Common::String &filename, bool defaultCK, byte ckRed, byte ckGreen, byte ckBlue, int lifeTime = -1, bool keepLoaded = false) = 0; diff --git a/engines/wintermute/base/gfx/osystem/base_render_osystem.cpp b/engines/wintermute/base/gfx/osystem/base_render_osystem.cpp index 601fcc0ffa..0f6a184cb3 100644 --- a/engines/wintermute/base/gfx/osystem/base_render_osystem.cpp +++ b/engines/wintermute/base/gfx/osystem/base_render_osystem.cpp @@ -35,7 +35,7 @@ #include "engines/wintermute/base/base_game.h" #include "engines/wintermute/base/base_sprite.h" #include "common/system.h" -#include "engines/wintermute/graphics/transparent_surface.h" +#include "graphics/transparent_surface.h" #include "common/queue.h" #include "common/config-manager.h" @@ -254,7 +254,7 @@ void BaseRenderOSystem::fadeToColor(byte r, byte g, byte b, byte a) { Common::Rect sizeRect(fillRect); sizeRect.translate(-fillRect.top, -fillRect.left); surf.fillRect(fillRect, col); - TransformStruct temp = TransformStruct(); + Graphics::TransformStruct temp = Graphics::TransformStruct(); temp._alphaDisable = false; drawSurface(nullptr, &surf, &sizeRect, &fillRect, temp); surf.free(); @@ -268,7 +268,7 @@ Graphics::PixelFormat BaseRenderOSystem::getPixelFormat() const { return _renderSurface->format; } -void BaseRenderOSystem::drawSurface(BaseSurfaceOSystem *owner, const Graphics::Surface *surf, Common::Rect *srcRect, Common::Rect *dstRect, TransformStruct &transform) { +void BaseRenderOSystem::drawSurface(BaseSurfaceOSystem *owner, const Graphics::Surface *surf, Common::Rect *srcRect, Common::Rect *dstRect, Graphics::TransformStruct &transform) { if (_disableDirtyRects) { RenderTicket *ticket = new RenderTicket(owner, surf, srcRect, dstRect, transform); diff --git a/engines/wintermute/base/gfx/osystem/base_render_osystem.h b/engines/wintermute/base/gfx/osystem/base_render_osystem.h index c9b8a52282..bc267fd656 100644 --- a/engines/wintermute/base/gfx/osystem/base_render_osystem.h +++ b/engines/wintermute/base/gfx/osystem/base_render_osystem.h @@ -33,7 +33,7 @@ #include "common/rect.h" #include "graphics/surface.h" #include "common/list.h" -#include "engines/wintermute/graphics/transform_struct.h" +#include "graphics/transform_struct.h" namespace Wintermute { class BaseSurfaceOSystem; @@ -110,7 +110,7 @@ public: virtual bool startSpriteBatch() override; virtual bool endSpriteBatch() override; void endSaveLoad(); - void drawSurface(BaseSurfaceOSystem *owner, const Graphics::Surface *surf, Common::Rect *srcRect, Common::Rect *dstRect, TransformStruct &transform); + void drawSurface(BaseSurfaceOSystem *owner, const Graphics::Surface *surf, Common::Rect *srcRect, Common::Rect *dstRect, Graphics::TransformStruct &transform); BaseSurface *createSurface() override; private: /** diff --git a/engines/wintermute/base/gfx/osystem/base_surface_osystem.cpp b/engines/wintermute/base/gfx/osystem/base_surface_osystem.cpp index 983f9c1296..a2a0032e26 100644 --- a/engines/wintermute/base/gfx/osystem/base_surface_osystem.cpp +++ b/engines/wintermute/base/gfx/osystem/base_surface_osystem.cpp @@ -32,8 +32,8 @@ #include "engines/wintermute/base/gfx/osystem/base_render_osystem.h" #include "engines/wintermute/base/gfx/base_image.h" #include "engines/wintermute/platform_osystem.h" -#include "engines/wintermute/graphics/transparent_surface.h" -#include "engines/wintermute/graphics/transform_tools.h" +#include "graphics/transparent_surface.h" +#include "graphics/transform_tools.h" #include "graphics/pixelformat.h" #include "graphics/surface.h" #include "common/stream.h" @@ -45,7 +45,7 @@ namespace Wintermute { BaseSurfaceOSystem::BaseSurfaceOSystem(BaseGame *inGame) : BaseSurface(inGame) { _surface = new Graphics::Surface(); _alphaMask = nullptr; - _alphaType = TransparentSurface::ALPHA_FULL; + _alphaType = Graphics::ALPHA_FULL; _lockPixels = nullptr; _lockPitch = 0; _loaded = false; @@ -68,10 +68,10 @@ BaseSurfaceOSystem::~BaseSurfaceOSystem() { renderer->invalidateTicketsFromSurface(this); } -TransparentSurface::AlphaType hasTransparencyType(const Graphics::Surface *surf) { +Graphics::AlphaType hasTransparencyType(const Graphics::Surface *surf) { if (surf->format.bytesPerPixel != 4) { warning("hasTransparencyType:: non 32 bpp surface passed as argument"); - return TransparentSurface::ALPHA_OPAQUE; + return Graphics::ALPHA_OPAQUE; } uint8 r, g, b, a; bool seenAlpha = false; @@ -93,11 +93,11 @@ TransparentSurface::AlphaType hasTransparencyType(const Graphics::Surface *surf) } } if (seenFullAlpha) { - return TransparentSurface::ALPHA_FULL; + return Graphics::ALPHA_FULL; } else if (seenAlpha) { - return TransparentSurface::ALPHA_BINARY; + return Graphics::ALPHA_BINARY; } else { - return TransparentSurface::ALPHA_OPAQUE; + return Graphics::ALPHA_OPAQUE; } } @@ -175,7 +175,7 @@ bool BaseSurfaceOSystem::finishLoad() { } if (needsColorKey) { - TransparentSurface trans(*_surface); + Graphics::TransparentSurface trans(*_surface); trans.applyColorKey(_ckRed, _ckGreen, _ckBlue, replaceAlpha); } @@ -328,46 +328,46 @@ bool BaseSurfaceOSystem::endPixelOp() { ////////////////////////////////////////////////////////////////////////// -bool BaseSurfaceOSystem::display(int x, int y, Rect32 rect, TSpriteBlendMode blendMode, bool mirrorX, bool mirrorY) { +bool BaseSurfaceOSystem::display(int x, int y, Rect32 rect, Graphics::TSpriteBlendMode blendMode, bool mirrorX, bool mirrorY) { _rotation = 0; - return drawSprite(x, y, &rect, nullptr, TransformStruct(kDefaultZoomX, kDefaultZoomY, mirrorX, mirrorY)); + return drawSprite(x, y, &rect, nullptr, Graphics::TransformStruct(Graphics::kDefaultZoomX, Graphics::kDefaultZoomY, mirrorX, mirrorY)); } ////////////////////////////////////////////////////////////////////////// -bool BaseSurfaceOSystem::displayTrans(int x, int y, Rect32 rect, uint32 alpha, TSpriteBlendMode blendMode, bool mirrorX, bool mirrorY) { +bool BaseSurfaceOSystem::displayTrans(int x, int y, Rect32 rect, uint32 alpha, Graphics::TSpriteBlendMode blendMode, bool mirrorX, bool mirrorY) { _rotation = 0; - return drawSprite(x, y, &rect, nullptr, TransformStruct(kDefaultZoomX, kDefaultZoomY, blendMode, alpha, mirrorX, mirrorY)); + return drawSprite(x, y, &rect, nullptr, Graphics::TransformStruct(Graphics::kDefaultZoomX, Graphics::kDefaultZoomY, blendMode, alpha, mirrorX, mirrorY)); } ////////////////////////////////////////////////////////////////////////// -bool BaseSurfaceOSystem::displayTransOffset(int x, int y, Rect32 rect, uint32 alpha, TSpriteBlendMode blendMode, bool mirrorX, bool mirrorY, int offsetX, int offsetY) { +bool BaseSurfaceOSystem::displayTransOffset(int x, int y, Rect32 rect, uint32 alpha, Graphics::TSpriteBlendMode blendMode, bool mirrorX, bool mirrorY, int offsetX, int offsetY) { _rotation = 0; - return drawSprite(x, y, &rect, nullptr, TransformStruct(kDefaultZoomX, kDefaultZoomY, kDefaultAngle, kDefaultHotspotX, kDefaultHotspotY, blendMode, alpha, mirrorX, mirrorY, offsetX, offsetY)); + return drawSprite(x, y, &rect, nullptr, Graphics::TransformStruct(Graphics::kDefaultZoomX, Graphics::kDefaultZoomY, Graphics::kDefaultAngle, Graphics::kDefaultHotspotX, Graphics::kDefaultHotspotY, blendMode, alpha, mirrorX, mirrorY, offsetX, offsetY)); } ////////////////////////////////////////////////////////////////////////// -bool BaseSurfaceOSystem::displayTransZoom(int x, int y, Rect32 rect, float zoomX, float zoomY, uint32 alpha, TSpriteBlendMode blendMode, bool mirrorX, bool mirrorY) { +bool BaseSurfaceOSystem::displayTransZoom(int x, int y, Rect32 rect, float zoomX, float zoomY, uint32 alpha, Graphics::TSpriteBlendMode blendMode, bool mirrorX, bool mirrorY) { _rotation = 0; - return drawSprite(x, y, &rect, nullptr, TransformStruct((int32)zoomX, (int32)zoomY, blendMode, alpha, mirrorX, mirrorY)); + return drawSprite(x, y, &rect, nullptr, Graphics::TransformStruct((int32)zoomX, (int32)zoomY, blendMode, alpha, mirrorX, mirrorY)); } ////////////////////////////////////////////////////////////////////////// -bool BaseSurfaceOSystem::displayZoom(int x, int y, Rect32 rect, float zoomX, float zoomY, uint32 alpha, bool transparent, TSpriteBlendMode blendMode, bool mirrorX, bool mirrorY) { +bool BaseSurfaceOSystem::displayZoom(int x, int y, Rect32 rect, float zoomX, float zoomY, uint32 alpha, bool transparent, Graphics::TSpriteBlendMode blendMode, bool mirrorX, bool mirrorY) { _rotation = 0; - TransformStruct transform; + Graphics::TransformStruct transform; if (transparent) { - transform = TransformStruct((int32)zoomX, (int32)zoomY, kDefaultAngle, kDefaultHotspotX, kDefaultHotspotY, blendMode, alpha, mirrorX, mirrorY); + transform = Graphics::TransformStruct((int32)zoomX, (int32)zoomY, Graphics::kDefaultAngle, Graphics::kDefaultHotspotX, Graphics::kDefaultHotspotY, blendMode, alpha, mirrorX, mirrorY); } else { - transform = TransformStruct((int32)zoomX, (int32)zoomY, mirrorX, mirrorY); + transform = Graphics::TransformStruct((int32)zoomX, (int32)zoomY, mirrorX, mirrorY); } return drawSprite(x, y, &rect, nullptr, transform); } ////////////////////////////////////////////////////////////////////////// -bool BaseSurfaceOSystem::displayTransform(int x, int y, Rect32 rect, Rect32 newRect, const TransformStruct &transform) { +bool BaseSurfaceOSystem::displayTransform(int x, int y, Rect32 rect, Rect32 newRect, const Graphics::TransformStruct &transform) { _rotation = (uint32)transform._angle; if (transform._angle < 0.0f) { warning("Negative rotation: %d %d", transform._angle, _rotation); @@ -380,13 +380,13 @@ bool BaseSurfaceOSystem::displayTransform(int x, int y, Rect32 rect, Rect32 newR ////////////////////////////////////////////////////////////////////////// bool BaseSurfaceOSystem::displayTiled(int x, int y, Rect32 rect, int numTimesX, int numTimesY) { assert(numTimesX > 0 && numTimesY > 0); - TransformStruct transform(numTimesX, numTimesY); + Graphics::TransformStruct transform(numTimesX, numTimesY); return drawSprite(x, y, &rect, nullptr, transform); } ////////////////////////////////////////////////////////////////////////// -bool BaseSurfaceOSystem::drawSprite(int x, int y, Rect32 *rect, Rect32 *newRect, TransformStruct transform) { +bool BaseSurfaceOSystem::drawSprite(int x, int y, Rect32 *rect, Rect32 *newRect, Graphics::TransformStruct transform) { BaseRenderOSystem *renderer = static_cast(_gameRef->_renderer); if (!_loaded) { @@ -414,13 +414,13 @@ bool BaseSurfaceOSystem::drawSprite(int x, int y, Rect32 *rect, Rect32 *newRect, position.setHeight(newRect->height()); } else { - Rect32 r; + Common::Rect r; r.top = 0; r.left = 0; r.setWidth(rect->width()); r.setHeight(rect->height()); - r = TransformTools::newRect(r, transform, 0); + r = Graphics::TransformTools::newRect(r, transform, 0); position.top = r.top + y + transform._offset.y; position.left = r.left + x + transform._offset.x; @@ -433,7 +433,7 @@ bool BaseSurfaceOSystem::drawSprite(int x, int y, Rect32 *rect, Rect32 *newRect, // But no checking is in place for that yet. // Optimize by not doing alpha-blits if we lack alpha - if (_alphaType == TransparentSurface::ALPHA_OPAQUE && !transform._alphaDisable) { + if (_alphaType == Graphics::ALPHA_OPAQUE && !transform._alphaDisable) { transform._alphaDisable = true; } @@ -452,9 +452,9 @@ bool BaseSurfaceOSystem::putSurface(const Graphics::Surface &surface, bool hasAl _surface->copyFrom(surface); } if (hasAlpha) { - _alphaType = TransparentSurface::ALPHA_FULL; + _alphaType = Graphics::ALPHA_FULL; } else { - _alphaType = TransparentSurface::ALPHA_OPAQUE; + _alphaType = Graphics::ALPHA_OPAQUE; } BaseRenderOSystem *renderer = static_cast(_gameRef->_renderer); renderer->invalidateTicketsFromSurface(this); diff --git a/engines/wintermute/base/gfx/osystem/base_surface_osystem.h b/engines/wintermute/base/gfx/osystem/base_surface_osystem.h index 4a05b2c66c..9fbbe1d498 100644 --- a/engines/wintermute/base/gfx/osystem/base_surface_osystem.h +++ b/engines/wintermute/base/gfx/osystem/base_surface_osystem.h @@ -30,7 +30,7 @@ #define WINTERMUTE_BASE_SURFACESDL_H #include "graphics/surface.h" -#include "engines/wintermute/graphics/transparent_surface.h" +#include "graphics/transparent_surface.h" #include "engines/wintermute/base/gfx/base_surface.h" #include "common/list.h" @@ -52,12 +52,12 @@ public: bool endPixelOp() override; - bool displayTransZoom(int x, int y, Rect32 rect, float zoomX, float zoomY, uint32 alpha = kDefaultRgbaMod, TSpriteBlendMode blendMode = BLEND_NORMAL, bool mirrorX = false, bool mirrorY = false) override; - bool displayTrans(int x, int y, Rect32 rect, uint32 alpha = kDefaultRgbaMod, TSpriteBlendMode blendMode = BLEND_NORMAL, bool mirrorX = false, bool mirrorY = false) override; - bool displayTransOffset(int x, int y, Rect32 rect, uint32 alpha = kDefaultRgbaMod, TSpriteBlendMode blendMode = BLEND_NORMAL, bool mirrorX = false, bool mirrorY = false, int offsetX = 0, int offsetY = 0) override; - bool display(int x, int y, Rect32 rect, TSpriteBlendMode blendMode = BLEND_NORMAL, bool mirrorX = false, bool mirrorY = false) override; - bool displayZoom(int x, int y, Rect32 rect, float zoomX, float zoomY, uint32 alpha = kDefaultRgbaMod, bool transparent = false, TSpriteBlendMode blendMode = BLEND_NORMAL, bool mirrorX = false, bool mirrorY = false) override; - bool displayTransform(int x, int y, Rect32 rect, Rect32 newRect, const TransformStruct &transform) override; + bool displayTransZoom(int x, int y, Rect32 rect, float zoomX, float zoomY, uint32 alpha = Graphics::kDefaultRgbaMod, Graphics::TSpriteBlendMode blendMode = Graphics::BLEND_NORMAL, bool mirrorX = false, bool mirrorY = false) override; + bool displayTrans(int x, int y, Rect32 rect, uint32 alpha = Graphics::kDefaultRgbaMod, Graphics::TSpriteBlendMode blendMode = Graphics::BLEND_NORMAL, bool mirrorX = false, bool mirrorY = false) override; + bool displayTransOffset(int x, int y, Rect32 rect, uint32 alpha = Graphics::kDefaultRgbaMod, Graphics::TSpriteBlendMode blendMode = Graphics::BLEND_NORMAL, bool mirrorX = false, bool mirrorY = false, int offsetX = 0, int offsetY = 0) override; + bool display(int x, int y, Rect32 rect, Graphics::TSpriteBlendMode blendMode = Graphics::BLEND_NORMAL, bool mirrorX = false, bool mirrorY = false) override; + bool displayZoom(int x, int y, Rect32 rect, float zoomX, float zoomY, uint32 alpha = Graphics::kDefaultRgbaMod, bool transparent = false, Graphics::TSpriteBlendMode blendMode = Graphics::BLEND_NORMAL, bool mirrorX = false, bool mirrorY = false) override; + bool displayTransform(int x, int y, Rect32 rect, Rect32 newRect, const Graphics::TransformStruct &transform) override; virtual bool displayTiled(int x, int y, Rect32 rect, int numTimesX, int numTimesY); virtual bool putSurface(const Graphics::Surface &surface, bool hasAlpha = false) override; /* static unsigned DLL_CALLCONV ReadProc(void *buffer, unsigned size, unsigned count, fi_handle handle); @@ -82,17 +82,17 @@ public: return _height; } - TransparentSurface::AlphaType getAlphaType() const { return _alphaType; } + Graphics::AlphaType getAlphaType() const { return _alphaType; } private: Graphics::Surface *_surface; bool _loaded; bool finishLoad(); - bool drawSprite(int x, int y, Rect32 *rect, Rect32 *newRect, TransformStruct transformStruct); + bool drawSprite(int x, int y, Rect32 *rect, Rect32 *newRect, Graphics::TransformStruct transformStruct); void genAlphaMask(Graphics::Surface *surface); uint32 getPixelAt(Graphics::Surface *surface, int x, int y); uint32 _rotation; - TransparentSurface::AlphaType _alphaType; + Graphics::AlphaType _alphaType; void *_lockPixels; int _lockPitch; byte *_alphaMask; diff --git a/engines/wintermute/base/gfx/osystem/render_ticket.cpp b/engines/wintermute/base/gfx/osystem/render_ticket.cpp index f8579dfd41..afe884300a 100644 --- a/engines/wintermute/base/gfx/osystem/render_ticket.cpp +++ b/engines/wintermute/base/gfx/osystem/render_ticket.cpp @@ -29,12 +29,12 @@ #include "engines/wintermute/base/gfx/osystem/render_ticket.h" #include "engines/wintermute/base/gfx/osystem/base_surface_osystem.h" -#include "engines/wintermute/graphics/transform_tools.h" +#include "graphics/transform_tools.h" #include "common/textconsole.h" namespace Wintermute { -RenderTicket::RenderTicket(BaseSurfaceOSystem *owner, const Graphics::Surface *surf, Common::Rect *srcRect, Common::Rect *dstRect, TransformStruct transform) : +RenderTicket::RenderTicket(BaseSurfaceOSystem *owner, const Graphics::Surface *surf, Common::Rect *srcRect, Common::Rect *dstRect, Graphics::TransformStruct transform) : _owner(owner), _srcRect(*srcRect), _dstRect(*dstRect), @@ -57,8 +57,8 @@ RenderTicket::RenderTicket(BaseSurfaceOSystem *owner, const Graphics::Surface *s // NB: Mirroring and rotation are probably done in the wrong order. // (Mirroring should most likely be done before rotation. See also // TransformTools.) - if (_transform._angle != kDefaultAngle) { - TransparentSurface src(*_surface, false); + if (_transform._angle != Graphics::kDefaultAngle) { + Graphics::TransparentSurface src(*_surface, false); Graphics::Surface *temp = src.rotoscale(transform); _surface->free(); delete _surface; @@ -66,7 +66,7 @@ RenderTicket::RenderTicket(BaseSurfaceOSystem *owner, const Graphics::Surface *s } else if ((dstRect->width() != srcRect->width() || dstRect->height() != srcRect->height()) && _transform._numTimesX * _transform._numTimesY == 1) { - TransparentSurface src(*_surface, false); + Graphics::TransparentSurface src(*_surface, false); Graphics::Surface *temp = src.scale(dstRect->width(), dstRect->height()); _surface->free(); delete _surface; @@ -97,7 +97,7 @@ bool RenderTicket::operator==(const RenderTicket &t) const { // Replacement for SDL2's SDL_RenderCopy void RenderTicket::drawToSurface(Graphics::Surface *_targetSurface) const { - TransparentSurface src(*getSurface(), false); + Graphics::TransparentSurface src(*getSurface(), false); Common::Rect clipRect; clipRect.setWidth(getSurface()->w); @@ -105,7 +105,7 @@ void RenderTicket::drawToSurface(Graphics::Surface *_targetSurface) const { if (_owner) { if (_transform._alphaDisable) { - src.setAlphaMode(TransparentSurface::ALPHA_OPAQUE); + src.setAlphaMode(Graphics::ALPHA_OPAQUE); } else { src.setAlphaMode(_owner->getAlphaType()); } @@ -126,7 +126,7 @@ void RenderTicket::drawToSurface(Graphics::Surface *_targetSurface) const { } void RenderTicket::drawToSurface(Graphics::Surface *_targetSurface, Common::Rect *dstRect, Common::Rect *clipRect) const { - TransparentSurface src(*getSurface(), false); + Graphics::TransparentSurface src(*getSurface(), false); bool doDelete = false; if (!clipRect) { doDelete = true; @@ -137,7 +137,7 @@ void RenderTicket::drawToSurface(Graphics::Surface *_targetSurface, Common::Rect if (_owner) { if (_transform._alphaDisable) { - src.setAlphaMode(TransparentSurface::ALPHA_OPAQUE); + src.setAlphaMode(Graphics::ALPHA_OPAQUE); } else { src.setAlphaMode(_owner->getAlphaType()); } diff --git a/engines/wintermute/base/gfx/osystem/render_ticket.h b/engines/wintermute/base/gfx/osystem/render_ticket.h index de95273021..3d3bd2e844 100644 --- a/engines/wintermute/base/gfx/osystem/render_ticket.h +++ b/engines/wintermute/base/gfx/osystem/render_ticket.h @@ -29,7 +29,7 @@ #ifndef WINTERMUTE_RENDER_TICKET_H #define WINTERMUTE_RENDER_TICKET_H -#include "engines/wintermute/graphics/transparent_surface.h" +#include "graphics/transparent_surface.h" #include "graphics/surface.h" #include "common/rect.h" @@ -51,8 +51,8 @@ class BaseSurfaceOSystem; */ class RenderTicket { public: - RenderTicket(BaseSurfaceOSystem *owner, const Graphics::Surface *surf, Common::Rect *srcRect, Common::Rect *dstRest, TransformStruct transform); - RenderTicket() : _isValid(true), _wantsDraw(false), _transform(TransformStruct()) {} + RenderTicket(BaseSurfaceOSystem *owner, const Graphics::Surface *surf, Common::Rect *srcRect, Common::Rect *dstRest, Graphics::TransformStruct transform); + RenderTicket() : _isValid(true), _wantsDraw(false), _transform(Graphics::TransformStruct()) {} ~RenderTicket(); const Graphics::Surface *getSurface() const { return _surface; } // Non-dirty-rects: @@ -65,7 +65,7 @@ public: bool _isValid; bool _wantsDraw; - TransformStruct _transform; + Graphics::TransformStruct _transform; BaseSurfaceOSystem *_owner; bool operator==(const RenderTicket &a) const; diff --git a/engines/wintermute/dctypes.h b/engines/wintermute/dctypes.h index 33e1cc4018..90340f437d 100644 --- a/engines/wintermute/dctypes.h +++ b/engines/wintermute/dctypes.h @@ -200,14 +200,6 @@ enum TTextEncoding { NUM_TEXT_ENCODINGS }; -enum TSpriteBlendMode { - BLEND_UNKNOWN = -1, - BLEND_NORMAL = 0, - BLEND_ADDITIVE = 1, - BLEND_SUBTRACTIVE = 2, - NUM_BLEND_MODES -}; - enum TTTSType { TTS_CAPTION = 0, TTS_TALK, diff --git a/engines/wintermute/graphics/transform_struct.cpp b/engines/wintermute/graphics/transform_struct.cpp deleted file mode 100644 index 9483975d94..0000000000 --- a/engines/wintermute/graphics/transform_struct.cpp +++ /dev/null @@ -1,119 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program 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; either version 2 - * of the License, or (at your option) any later version. - * - * This program 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. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -#include "engines/wintermute/graphics/transform_struct.h" -#include "engines/wintermute/graphics/transparent_surface.h" - -namespace Wintermute { -void TransformStruct::init(Point32 zoom, uint32 angle, Point32 hotspot, bool alphaDisable, TSpriteBlendMode blendMode, uint32 rgbaMod, bool mirrorX, bool mirrorY, Point32 offset) { - _zoom = zoom; - _angle = angle; - _hotspot = hotspot; - _blendMode = blendMode; - _rgbaMod = rgbaMod; - _alphaDisable = alphaDisable; - _flip = 0; - _flip += TransparentSurface::FLIP_H * mirrorX; - _flip += TransparentSurface::FLIP_V * mirrorY; - _offset = offset; - _numTimesX = 1; - _numTimesY = 1; -} - -TransformStruct::TransformStruct(int32 zoomX, int32 zoomY, uint32 angle, int32 hotspotX, int32 hotspotY, TSpriteBlendMode blendMode, uint32 rgbaMod, bool mirrorX, bool mirrorY, int32 offsetX, int32 offsetY) { - init(Point32(zoomX, zoomY), - angle, - Point32(hotspotX, hotspotY), - false, - blendMode, - rgbaMod, - mirrorX, mirrorY, - Point32(offsetX, offsetY)); -} - -TransformStruct::TransformStruct(float zoomX, float zoomY, uint32 angle, int32 hotspotX, int32 hotspotY, TSpriteBlendMode blendMode, uint32 rgbaMod, bool mirrorX, bool mirrorY, int32 offsetX, int32 offsetY) { - init(Point32((int32)(zoomX / 100.0 * kDefaultZoomX), - (int32)(zoomY / 100.0 * kDefaultZoomY)), - angle, - Point32(hotspotX, hotspotY), - false, - blendMode, - rgbaMod, - mirrorX, mirrorY, - Point32(offsetX, offsetY)); -} - -TransformStruct::TransformStruct(int32 zoomX, int32 zoomY, TSpriteBlendMode blendMode, uint32 rgbaMod, bool mirrorX, bool mirrorY) { - init(Point32(zoomX, zoomY), - kDefaultAngle, - Point32(kDefaultHotspotX, kDefaultHotspotY), - false, - blendMode, - rgbaMod, - mirrorX, - mirrorY, - Point32(kDefaultOffsetX, kDefaultOffsetY)); -} - -TransformStruct::TransformStruct(int32 zoomX, int32 zoomY, uint32 angle, int32 hotspotX, int32 hotspotY) { - init(Point32(zoomX, zoomY), - angle, - Point32(hotspotX, hotspotY), - true, - BLEND_NORMAL, - kDefaultRgbaMod, - false, false, - Point32(kDefaultOffsetX, kDefaultOffsetY)); -} - -TransformStruct::TransformStruct(int32 numTimesX, int32 numTimesY) { - init(Point32(kDefaultZoomX, kDefaultZoomY), - kDefaultAngle, - Point32(kDefaultHotspotX, kDefaultHotspotY), - false, - BLEND_NORMAL, - kDefaultRgbaMod, - false, false, - Point32(kDefaultOffsetX, kDefaultOffsetY)); - _numTimesX = numTimesX; - _numTimesY = numTimesY; -} - -TransformStruct::TransformStruct() { - init(Point32(kDefaultZoomX, kDefaultZoomY), - kDefaultAngle, - Point32(kDefaultHotspotX, kDefaultHotspotY), - true, - BLEND_NORMAL, - kDefaultRgbaMod, - false, false, - Point32(kDefaultOffsetX, kDefaultOffsetY)); -} - -bool TransformStruct::getMirrorX() const { - return (bool)(_flip & TransparentSurface::FLIP_H); -} - -bool TransformStruct::getMirrorY() const { - return (bool)(_flip & TransparentSurface::FLIP_V); -} -} // End of namespace Wintermute diff --git a/engines/wintermute/graphics/transform_struct.h b/engines/wintermute/graphics/transform_struct.h deleted file mode 100644 index f80b0967cb..0000000000 --- a/engines/wintermute/graphics/transform_struct.h +++ /dev/null @@ -1,89 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program 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; either version 2 - * of the License, or (at your option) any later version. - * - * This program 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. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -#ifndef WINTERMUTE_TRANSFORM_STRUCT_H -#define WINTERMUTE_TRANSFORM_STRUCT_H - -#include "engines/wintermute/math/rect32.h" -#include "engines/wintermute/dctypes.h" - -namespace Wintermute { -/** - * Contains all the required information that define a transform. - * Same source sprite + same TransformStruct = Same resulting sprite. - * Has a number of overloaded constructors to accomodate various argument lists. - */ - -const int32 kDefaultZoomX = 100; -const int32 kDefaultZoomY = 100; -const uint32 kDefaultRgbaMod = 0xFFFFFFFF; -const int32 kDefaultHotspotX = 0; -const int32 kDefaultHotspotY = 0; -const int32 kDefaultOffsetX = 0; -const int32 kDefaultOffsetY = 0; -const int32 kDefaultAngle = 0; - -struct TransformStruct { -private: - void init(Point32 zoom, uint32 angle, Point32 hotspot, bool alphaDisable, TSpriteBlendMode blendMode, uint32 alpha, bool mirrorX, bool mirrorY, Point32 offset); - -public: - TransformStruct(int32 zoomX, int32 zoomY, uint32 angle, int32 hotspotX, int32 hotspotY, TSpriteBlendMode blendMode, uint32 alpha, bool mirrorX = false, bool mirrorY = false, int32 offsetX = 0, int32 offsetY = 0); - TransformStruct(float zoomX, float zoomY, uint32 angle, int32 hotspotX, int32 hotspotY, TSpriteBlendMode blendMode, uint32 alpha, bool mirrorX = false, bool mirrorY = false, int32 offsetX = 0, int32 offsetY = 0); - TransformStruct(int32 zoomX, int32 zoomY, TSpriteBlendMode blendMode, uint32 alpha, bool mirrorX = false, bool mirrorY = false); - TransformStruct(int32 zoomX, int32 zoomY, uint32 angle, int32 hotspotX = 0, int32 hotspotY = 0); - TransformStruct(int32 numTimesX, int32 numTimesY); - TransformStruct(); - - Point32 _zoom; ///< Zoom; 100 = no zoom - Point32 _hotspot; ///< Position of the hotspot - int32 _angle; ///< Rotation angle, in degrees - byte _flip; ///< Bitflag: see TransparentSurface::FLIP_XXX - bool _alphaDisable; - TSpriteBlendMode _blendMode; - uint32 _rgbaMod; ///< RGBa - Point32 _offset; - int32 _numTimesX; - int32 _numTimesY; - - bool getMirrorX() const; - bool getMirrorY() const; - - bool operator==(const TransformStruct &compare) const { - return (compare._angle == _angle && - compare._flip == _flip && - compare._zoom == _zoom && - compare._offset == _offset && - compare._alphaDisable == _alphaDisable && - compare._rgbaMod == _rgbaMod && - compare._blendMode == _blendMode && - compare._numTimesX == _numTimesX && - compare._numTimesY == _numTimesY - ); - } - - bool operator!=(const TransformStruct &compare) const { - return !(compare == *this); - } -}; -} // End of namespace Wintermute -#endif diff --git a/engines/wintermute/graphics/transform_tools.cpp b/engines/wintermute/graphics/transform_tools.cpp deleted file mode 100644 index 7a009c26fa..0000000000 --- a/engines/wintermute/graphics/transform_tools.cpp +++ /dev/null @@ -1,87 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program 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; either version 2 - * of the License, or (at your option) any later version. - * - * This program 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. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - - -#include "engines/wintermute/graphics/transform_tools.h" -#include - -namespace Wintermute { - -FloatPoint TransformTools::transformPoint(FloatPoint point, const float rotate, const Point32 &zoom, const bool mirrorX, const bool mirrorY) { - float rotateRad = rotate * M_PI / 180.0f; - float x = point.x; - float y = point.y; - x = (x * zoom.x) / kDefaultZoomX; - y = (y * zoom.y) / kDefaultZoomY; -#if 0 - // TODO: Mirroring should be done before rotation, but the blitting - // code does the inverse, so we match that for now. - if (mirrorX) - x *= -1; - if (mirrorY) - y *= -1; -#endif - FloatPoint newPoint; - newPoint.x = x * cos(rotateRad) - y * sin(rotateRad); - newPoint.y = x * sin(rotateRad) + y * cos(rotateRad); - if (mirrorX) { - newPoint.x *= -1; - } - if (mirrorY) { - newPoint.y *= -1; - } - return newPoint; -} - -Rect32 TransformTools::newRect(const Rect32 &oldRect, const TransformStruct &transform, Point32 *newHotspot) { - Point32 nw(oldRect.left, oldRect.top); - Point32 ne(oldRect.right, oldRect.top); - Point32 sw(oldRect.left, oldRect.bottom); - Point32 se(oldRect.right, oldRect.bottom); - - FloatPoint nw1, ne1, sw1, se1; - - nw1 = transformPoint(nw - transform._hotspot, transform._angle, transform._zoom); - ne1 = transformPoint(ne - transform._hotspot, transform._angle, transform._zoom); - sw1 = transformPoint(sw - transform._hotspot, transform._angle, transform._zoom); - se1 = transformPoint(se - transform._hotspot, transform._angle, transform._zoom); - - float top = MIN(nw1.y, MIN(ne1.y, MIN(sw1.y, se1.y))); - float bottom = MAX(nw1.y, MAX(ne1.y, MAX(sw1.y, se1.y))); - float left = MIN(nw1.x, MIN(ne1.x, MIN(sw1.x, se1.x))); - float right = MAX(nw1.x, MAX(ne1.x, MAX(sw1.x, se1.x))); - - if (newHotspot) { - newHotspot->y = (uint32)(-floor(top)); - newHotspot->x = (uint32)(-floor(left)); - } - - Rect32 res; - res.top = (int32)(floor(top)) + transform._hotspot.y; - res.bottom = (int32)(ceil(bottom)) + transform._hotspot.y; - res.left = (int32)(floor(left)) + transform._hotspot.x; - res.right = (int32)(ceil(right)) + transform._hotspot.x; - - return res; -} - -} // End of namespace Wintermute diff --git a/engines/wintermute/graphics/transform_tools.h b/engines/wintermute/graphics/transform_tools.h deleted file mode 100644 index e259db04e5..0000000000 --- a/engines/wintermute/graphics/transform_tools.h +++ /dev/null @@ -1,53 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program 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; either version 2 - * of the License, or (at your option) any later version. - * - * This program 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. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -#ifndef WINTERMUTE_TRANSFORM_TOOLS_H -#define WINTERMUTE_TRANSFORM_TOOLS_H - -#include "engines/wintermute/math/rect32.h" -#include "engines/wintermute/math/floatpoint.h" -#include "engines/wintermute/graphics/transform_struct.h" - -namespace Wintermute { - -class TransformTools { -public: - /** - * Basic transform (scale + rotate) for a single point - */ - static FloatPoint transformPoint(FloatPoint point, const float rotate, const Point32 &zoom, const bool mirrorX = false, const bool mirrorY = false); - - /** - * @param &point the point on which the transform is to be applied - * @param rotate the angle in degrees - * @param &zoom zoom x,y in percent - * @param mirrorX flip along the vertical axis? - * @param mirrorY flip along the horizontal axis? - * @return the smallest rect that can contain the transformed sprite - * and, as a side-effect, "newHotspot" will tell you where the hotspot will - * have ended up in the new rect, for centering. - */ - static Rect32 newRect(const Rect32 &oldRect, const TransformStruct &transform, Point32 *newHotspot); -}; - -} // End of namespace Wintermute -#endif diff --git a/engines/wintermute/graphics/transparent_surface.cpp b/engines/wintermute/graphics/transparent_surface.cpp deleted file mode 100644 index b16ba0ffdc..0000000000 --- a/engines/wintermute/graphics/transparent_surface.cpp +++ /dev/null @@ -1,851 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program 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; either version 2 - * of the License, or (at your option) any later version. - * - * This program 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. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * - * The bottom part of this is file is adapted from SDL_rotozoom.c. The - * relevant copyright notice for those specific functions can be found at the - * top of that section. - * - */ - - - -#include "common/algorithm.h" -#include "common/endian.h" -#include "common/util.h" -#include "common/rect.h" -#include "common/math.h" -#include "common/textconsole.h" -#include "graphics/primitives.h" -#include "engines/wintermute/graphics/transparent_surface.h" -#include "engines/wintermute/graphics/transform_tools.h" - -//#define ENABLE_BILINEAR - -namespace Wintermute { - -static const int kAShift = 0;//img->format.aShift; - -static const int kBModShift = 0;//img->format.bShift; -static const int kGModShift = 8;//img->format.gShift; -static const int kRModShift = 16;//img->format.rShift; -static const int kAModShift = 24;//img->format.aShift; - -#ifdef SCUMM_LITTLE_ENDIAN -static const int kAIndex = 0; -static const int kBIndex = 1; -static const int kGIndex = 2; -static const int kRIndex = 3; - -#else -static const int kAIndex = 3; -static const int kBIndex = 2; -static const int kGIndex = 1; -static const int kRIndex = 0; -#endif - -void doBlitOpaqueFast(byte *ino, byte *outo, uint32 width, uint32 height, uint32 pitch, int32 inStep, int32 inoStep); -void doBlitBinaryFast(byte *ino, byte *outo, uint32 width, uint32 height, uint32 pitch, int32 inStep, int32 inoStep); -void doBlitAlphaBlend(byte *ino, byte *outo, uint32 width, uint32 height, uint32 pitch, int32 inStep, int32 inoStep, uint32 color); -void doBlitAdditiveBlend(byte *ino, byte *outo, uint32 width, uint32 height, uint32 pitch, int32 inStep, int32 inoStep, uint32 color); -void doBlitSubtractiveBlend(byte *ino, byte *outo, uint32 width, uint32 height, uint32 pitch, int32 inStep, int32 inoStep, uint32 color); - -TransparentSurface::TransparentSurface() : Surface(), _alphaMode(ALPHA_FULL) {} - -TransparentSurface::TransparentSurface(const Surface &surf, bool copyData) : Surface(), _alphaMode(ALPHA_FULL) { - if (copyData) { - copyFrom(surf); - } else { - w = surf.w; - h = surf.h; - pitch = surf.pitch; - format = surf.format; - // We need to cast the const qualifier away here because 'pixels' - // always needs to be writable. 'surf' however is a constant Surface, - // thus getPixels will always return const pixel data. - pixels = const_cast(surf.getPixels()); - } -} - -/** - * Optimized version of doBlit to be used w/opaque blitting (no alpha). - */ -void doBlitOpaqueFast(byte *ino, byte *outo, uint32 width, uint32 height, uint32 pitch, int32 inStep, int32 inoStep) { - - byte *in; - byte *out; - - for (uint32 i = 0; i < height; i++) { - out = outo; - in = ino; - memcpy(out, in, width * 4); - for (uint32 j = 0; j < width; j++) { - out[kAIndex] = 0xFF; - out += 4; - } - outo += pitch; - ino += inoStep; - } -} - -/** - * Optimized version of doBlit to be used w/binary blitting (blit or no-blit, no blending). - */ -void doBlitBinaryFast(byte *ino, byte *outo, uint32 width, uint32 height, uint32 pitch, int32 inStep, int32 inoStep) { - - byte *in; - byte *out; - - for (uint32 i = 0; i < height; i++) { - out = outo; - in = ino; - for (uint32 j = 0; j < width; j++) { - uint32 pix = *(uint32 *)in; - int a = (pix >> kAShift) & 0xff; - - if (a != 0) { // Full opacity (Any value not exactly 0 is Opaque here) - *(uint32 *)out = pix; - out[kAIndex] = 0xFF; - } - out += 4; - in += inStep; - } - outo += pitch; - ino += inoStep; - } -} - -/** - * Optimized version of doBlit to be used with alpha blended blitting - * @param ino a pointer to the input surface - * @param outo a pointer to the output surface - * @param width width of the input surface - * @param height height of the input surface - * @param pitch pitch of the output surface - that is, width in bytes of every row, usually bpp * width of the TARGET surface (the area we are blitting to might be smaller, do the math) - * @inStep size in bytes to skip to address each pixel, usually bpp of the source surface - * @inoStep width in bytes of every row on the *input* surface / kind of like pitch - * @color colormod in 0xAARRGGBB format - 0xFFFFFFFF for no colormod - */ -void doBlitAlphaBlend(byte *ino, byte *outo, uint32 width, uint32 height, uint32 pitch, int32 inStep, int32 inoStep, uint32 color) { - byte *in; - byte *out; - - if (color == 0xffffffff) { - - for (uint32 i = 0; i < height; i++) { - out = outo; - in = ino; - for (uint32 j = 0; j < width; j++) { - - if (in[kAIndex] != 0) { - out[kAIndex] = 255; - out[kRIndex] = ((in[kRIndex] * in[kAIndex]) + out[kRIndex] * (255 - in[kAIndex])) >> 8; - out[kGIndex] = ((in[kGIndex] * in[kAIndex]) + out[kGIndex] * (255 - in[kAIndex])) >> 8; - out[kBIndex] = ((in[kBIndex] * in[kAIndex]) + out[kBIndex] * (255 - in[kAIndex])) >> 8; - } - - in += inStep; - out += 4; - } - outo += pitch; - ino += inoStep; - } - } else { - - byte ca = (color >> kAModShift) & 0xFF; - byte cr = (color >> kRModShift) & 0xFF; - byte cg = (color >> kGModShift) & 0xFF; - byte cb = (color >> kBModShift) & 0xFF; - - for (uint32 i = 0; i < height; i++) { - out = outo; - in = ino; - for (uint32 j = 0; j < width; j++) { - - uint32 ina = in[kAIndex] * ca >> 8; - out[kAIndex] = 255; - out[kBIndex] = (out[kBIndex] * (255 - ina) >> 8); - out[kGIndex] = (out[kGIndex] * (255 - ina) >> 8); - out[kRIndex] = (out[kRIndex] * (255 - ina) >> 8); - - out[kBIndex] = out[kBIndex] + (in[kBIndex] * ina * cb >> 16); - out[kGIndex] = out[kGIndex] + (in[kGIndex] * ina * cg >> 16); - out[kRIndex] = out[kRIndex] + (in[kRIndex] * ina * cr >> 16); - - in += inStep; - out += 4; - } - outo += pitch; - ino += inoStep; - } - } -} - -/** - * Optimized version of doBlit to be used with additive blended blitting - */ -void doBlitAdditiveBlend(byte *ino, byte *outo, uint32 width, uint32 height, uint32 pitch, int32 inStep, int32 inoStep, uint32 color) { - byte *in; - byte *out; - - if (color == 0xffffffff) { - - for (uint32 i = 0; i < height; i++) { - out = outo; - in = ino; - for (uint32 j = 0; j < width; j++) { - - if (in[kAIndex] != 0) { - out[kRIndex] = MIN((in[kRIndex] * in[kAIndex] >> 8) + out[kRIndex], 255); - out[kGIndex] = MIN((in[kGIndex] * in[kAIndex] >> 8) + out[kGIndex], 255); - out[kBIndex] = MIN((in[kBIndex] * in[kAIndex] >> 8) + out[kBIndex], 255); - } - - in += inStep; - out += 4; - } - outo += pitch; - ino += inoStep; - } - } else { - - byte ca = (color >> kAModShift) & 0xFF; - byte cr = (color >> kRModShift) & 0xFF; - byte cg = (color >> kGModShift) & 0xFF; - byte cb = (color >> kBModShift) & 0xFF; - - for (uint32 i = 0; i < height; i++) { - out = outo; - in = ino; - for (uint32 j = 0; j < width; j++) { - - uint32 ina = in[kAIndex] * ca >> 8; - - if (cb != 255) { - out[kBIndex] = MIN(out[kBIndex] + ((in[kBIndex] * cb * ina) >> 16), 255u); - } else { - out[kBIndex] = MIN(out[kBIndex] + (in[kBIndex] * ina >> 8), 255u); - } - - if (cg != 255) { - out[kGIndex] = MIN(out[kGIndex] + ((in[kGIndex] * cg * ina) >> 16), 255u); - } else { - out[kGIndex] = MIN(out[kGIndex] + (in[kGIndex] * ina >> 8), 255u); - } - - if (cr != 255) { - out[kRIndex] = MIN(out[kRIndex] + ((in[kRIndex] * cr * ina) >> 16), 255u); - } else { - out[kRIndex] = MIN(out[kRIndex] + (in[kRIndex] * ina >> 8), 255u); - } - - in += inStep; - out += 4; - } - outo += pitch; - ino += inoStep; - } - } -} - -/** - * Optimized version of doBlit to be used with subtractive blended blitting - */ -void doBlitSubtractiveBlend(byte *ino, byte *outo, uint32 width, uint32 height, uint32 pitch, int32 inStep, int32 inoStep, uint32 color) { - byte *in; - byte *out; - - if (color == 0xffffffff) { - - for (uint32 i = 0; i < height; i++) { - out = outo; - in = ino; - for (uint32 j = 0; j < width; j++) { - - if (in[kAIndex] != 0) { - out[kRIndex] = MAX(out[kRIndex] - ((in[kRIndex] * out[kRIndex]) * in[kAIndex] >> 16), 0); - out[kGIndex] = MAX(out[kGIndex] - ((in[kGIndex] * out[kGIndex]) * in[kAIndex] >> 16), 0); - out[kBIndex] = MAX(out[kBIndex] - ((in[kBIndex] * out[kBIndex]) * in[kAIndex] >> 16), 0); - } - - in += inStep; - out += 4; - } - outo += pitch; - ino += inoStep; - } - } else { - - byte cr = (color >> kRModShift) & 0xFF; - byte cg = (color >> kGModShift) & 0xFF; - byte cb = (color >> kBModShift) & 0xFF; - - for (uint32 i = 0; i < height; i++) { - out = outo; - in = ino; - for (uint32 j = 0; j < width; j++) { - - out[kAIndex] = 255; - if (cb != 255) { - out[kBIndex] = MAX(out[kBIndex] - ((in[kBIndex] * cb * (out[kBIndex]) * in[kAIndex]) >> 24), 0); - } else { - out[kBIndex] = MAX(out[kBIndex] - (in[kBIndex] * (out[kBIndex]) * in[kAIndex] >> 16), 0); - } - - if (cg != 255) { - out[kGIndex] = MAX(out[kGIndex] - ((in[kGIndex] * cg * (out[kGIndex]) * in[kAIndex]) >> 24), 0); - } else { - out[kGIndex] = MAX(out[kGIndex] - (in[kGIndex] * (out[kGIndex]) * in[kAIndex] >> 16), 0); - } - - if (cr != 255) { - out[kRIndex] = MAX(out[kRIndex] - ((in[kRIndex] * cr * (out[kRIndex]) * in[kAIndex]) >> 24), 0); - } else { - out[kRIndex] = MAX(out[kRIndex] - (in[kRIndex] * (out[kRIndex]) * in[kAIndex] >> 16), 0); - } - - in += inStep; - out += 4; - } - outo += pitch; - ino += inoStep; - } - } -} - -Common::Rect TransparentSurface::blit(Graphics::Surface &target, int posX, int posY, int flipping, Common::Rect *pPartRect, uint color, int width, int height, TSpriteBlendMode blendMode) { - - Common::Rect retSize; - retSize.top = 0; - retSize.left = 0; - retSize.setWidth(0); - retSize.setHeight(0); - // Check if we need to draw anything at all - int ca = (color >> 24) & 0xff; - - if (ca == 0) { - return retSize; - } - - // Create an encapsulating surface for the data - TransparentSurface srcImage(*this, false); - // TODO: Is the data really in the screen format? - if (format.bytesPerPixel != 4) { - warning("TransparentSurface can only blit 32 bpp images"); - return retSize; - } - - if (pPartRect) { - - int xOffset = pPartRect->left; - int yOffset = pPartRect->top; - - if (flipping & FLIP_V) { - yOffset = srcImage.h - pPartRect->bottom; - } - - if (flipping & FLIP_H) { - xOffset = srcImage.w - pPartRect->right; - } - - srcImage.pixels = getBasePtr(xOffset, yOffset); - srcImage.w = pPartRect->width(); - srcImage.h = pPartRect->height(); - - debug(6, "Blit(%d, %d, %d, [%d, %d, %d, %d], %08x, %d, %d)", posX, posY, flipping, - pPartRect->left, pPartRect->top, pPartRect->width(), pPartRect->height(), color, width, height); - } else { - - debug(6, "Blit(%d, %d, %d, [%d, %d, %d, %d], %08x, %d, %d)", posX, posY, flipping, 0, 0, - srcImage.w, srcImage.h, color, width, height); - } - - if (width == -1) { - width = srcImage.w; - } - if (height == -1) { - height = srcImage.h; - } - -#ifdef SCALING_TESTING - // Hardcode scaling to 66% to test scaling - width = width * 2 / 3; - height = height * 2 / 3; -#endif - - Graphics::Surface *img = nullptr; - Graphics::Surface *imgScaled = nullptr; - byte *savedPixels = nullptr; - if ((width != srcImage.w) || (height != srcImage.h)) { - // Scale the image - img = imgScaled = srcImage.scale(width, height); - savedPixels = (byte *)img->getPixels(); - } else { - img = &srcImage; - } - - // Handle off-screen clipping - if (posY < 0) { - img->h = MAX(0, (int)img->h - -posY); - img->setPixels((byte *)img->getBasePtr(0, -posY)); - posY = 0; - } - - if (posX < 0) { - img->w = MAX(0, (int)img->w - -posX); - img->setPixels((byte *)img->getBasePtr(-posX, 0)); - posX = 0; - } - - img->w = CLIP((int)img->w, 0, (int)MAX((int)target.w - posX, 0)); - img->h = CLIP((int)img->h, 0, (int)MAX((int)target.h - posY, 0)); - - if ((img->w > 0) && (img->h > 0)) { - int xp = 0, yp = 0; - - int inStep = 4; - int inoStep = img->pitch; - if (flipping & TransparentSurface::FLIP_H) { - inStep = -inStep; - xp = img->w - 1; - } - - if (flipping & TransparentSurface::FLIP_V) { - inoStep = -inoStep; - yp = img->h - 1; - } - - byte *ino = (byte *)img->getBasePtr(xp, yp); - byte *outo = (byte *)target.getBasePtr(posX, posY); - - if (color == 0xFFFFFFFF && blendMode == BLEND_NORMAL && _alphaMode == ALPHA_OPAQUE) { - doBlitOpaqueFast(ino, outo, img->w, img->h, target.pitch, inStep, inoStep); - } else if (color == 0xFFFFFFFF && blendMode == BLEND_NORMAL && _alphaMode == ALPHA_BINARY) { - doBlitBinaryFast(ino, outo, img->w, img->h, target.pitch, inStep, inoStep); - } else { - if (blendMode == BLEND_ADDITIVE) { - doBlitAdditiveBlend(ino, outo, img->w, img->h, target.pitch, inStep, inoStep, color); - } else if (blendMode == BLEND_SUBTRACTIVE) { - doBlitSubtractiveBlend(ino, outo, img->w, img->h, target.pitch, inStep, inoStep, color); - } else { - assert(blendMode == BLEND_NORMAL); - doBlitAlphaBlend(ino, outo, img->w, img->h, target.pitch, inStep, inoStep, color); - } - } - - } - - retSize.setWidth(img->w); - retSize.setHeight(img->h); - - if (imgScaled) { - imgScaled->setPixels(savedPixels); - imgScaled->free(); - delete imgScaled; - } - - return retSize; -} - -/** - * Writes a color key to the alpha channel of the surface - * @param rKey the red component of the color key - * @param gKey the green component of the color key - * @param bKey the blue component of the color key - * @param overwriteAlpha if true, all other alpha will be set fully opaque - */ -void TransparentSurface::applyColorKey(uint8 rKey, uint8 gKey, uint8 bKey, bool overwriteAlpha) { - assert(format.bytesPerPixel == 4); - for (int i = 0; i < h; i++) { - for (int j = 0; j < w; j++) { - uint32 pix = ((uint32 *)pixels)[i * w + j]; - uint8 r, g, b, a; - format.colorToARGB(pix, a, r, g, b); - if (r == rKey && g == gKey && b == bKey) { - a = 0; - ((uint32 *)pixels)[i * w + j] = format.ARGBToColor(a, r, g, b); - } else if (overwriteAlpha) { - a = 255; - ((uint32 *)pixels)[i * w + j] = format.ARGBToColor(a, r, g, b); - } - } - } -} - -TransparentSurface::AlphaType TransparentSurface::getAlphaMode() const { - return _alphaMode; -} - -void TransparentSurface::setAlphaMode(TransparentSurface::AlphaType mode) { - _alphaMode = mode; -} - - - - - - -/* - -The below two functions are adapted from SDL_rotozoom.c, -taken from SDL_gfx-2.0.18. - -Its copyright notice: - -============================================================================= -SDL_rotozoom.c: rotozoomer, zoomer and shrinker for 32bit or 8bit surfaces - -Copyright (C) 2001-2012 Andreas Schiffler - -This software is provided 'as-is', without any express or implied -warranty. In no event will the authors be held liable for any damages -arising from the use of this software. - -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it -freely, subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not -claim that you wrote the original software. If you use this software -in a product, an acknowledgment in the product documentation would be -appreciated but is not required. - -2. Altered source versions must be plainly marked as such, and must not be -misrepresented as being the original software. - -3. This notice may not be removed or altered from any source -distribution. - -Andreas Schiffler -- aschiffler at ferzkopp dot net -============================================================================= - - -The functions have been adapted for different structures and coordinate -systems. - -*/ - - - - - -TransparentSurface *TransparentSurface::rotoscale(const TransformStruct &transform) const { - - assert(transform._angle != 0); // This would not be ideal; rotoscale() should never be called in conditional branches where angle = 0 anyway. - - Point32 newHotspot; - Common::Rect srcRect(0, 0, (int16)w, (int16)h); - Rect32 rect = TransformTools::newRect(Rect32(srcRect), transform, &newHotspot); - Common::Rect dstRect(0, 0, (int16)(rect.right - rect.left), (int16)(rect.bottom - rect.top)); - - TransparentSurface *target = new TransparentSurface(); - assert(format.bytesPerPixel == 4); - - int srcW = w; - int srcH = h; - int dstW = dstRect.width(); - int dstH = dstRect.height(); - - target->create((uint16)dstW, (uint16)dstH, this->format); - - if (transform._zoom.x == 0 || transform._zoom.y == 0) { - return target; - } - - uint32 invAngle = 360 - (transform._angle % 360); - float invCos = cos(invAngle * M_PI / 180.0); - float invSin = sin(invAngle * M_PI / 180.0); - - struct tColorRGBA { byte r; byte g; byte b; byte a; }; - int icosx = (int)(invCos * (65536.0f * kDefaultZoomX / transform._zoom.x)); - int isinx = (int)(invSin * (65536.0f * kDefaultZoomX / transform._zoom.x)); - int icosy = (int)(invCos * (65536.0f * kDefaultZoomY / transform._zoom.y)); - int isiny = (int)(invSin * (65536.0f * kDefaultZoomY / transform._zoom.y)); - - - bool flipx = false, flipy = false; // TODO: See mirroring comment in RenderTicket ctor - - int xd = (srcRect.left + transform._hotspot.x) << 16; - int yd = (srcRect.top + transform._hotspot.y) << 16; - int cx = newHotspot.x; - int cy = newHotspot.y; - - int ax = -icosx * cx; - int ay = -isiny * cx; - int sw = srcW - 1; - int sh = srcH - 1; - - tColorRGBA *pc = (tColorRGBA*)target->getBasePtr(0, 0); - - for (int y = 0; y < dstH; y++) { - int t = cy - y; - int sdx = ax + (isinx * t) + xd; - int sdy = ay - (icosy * t) + yd; - for (int x = 0; x < dstW; x++) { - int dx = (sdx >> 16); - int dy = (sdy >> 16); - if (flipx) { - dx = sw - dx; - } - if (flipy) { - dy = sh - dy; - } - -#ifdef ENABLE_BILINEAR - if ((dx > -1) && (dy > -1) && (dx < sw) && (dy < sh)) { - const tColorRGBA *sp = (const tColorRGBA *)getBasePtr(dx, dy); - tColorRGBA c00, c01, c10, c11, cswap; - c00 = *sp; - sp += 1; - c01 = *sp; - sp += (this->pitch / 4); - c11 = *sp; - sp -= 1; - c10 = *sp; - if (flipx) { - cswap = c00; c00=c01; c01=cswap; - cswap = c10; c10=c11; c11=cswap; - } - if (flipy) { - cswap = c00; c00=c10; c10=cswap; - cswap = c01; c01=c11; c11=cswap; - } - /* - * Interpolate colors - */ - int ex = (sdx & 0xffff); - int ey = (sdy & 0xffff); - int t1, t2; - t1 = ((((c01.r - c00.r) * ex) >> 16) + c00.r) & 0xff; - t2 = ((((c11.r - c10.r) * ex) >> 16) + c10.r) & 0xff; - pc->r = (((t2 - t1) * ey) >> 16) + t1; - t1 = ((((c01.g - c00.g) * ex) >> 16) + c00.g) & 0xff; - t2 = ((((c11.g - c10.g) * ex) >> 16) + c10.g) & 0xff; - pc->g = (((t2 - t1) * ey) >> 16) + t1; - t1 = ((((c01.b - c00.b) * ex) >> 16) + c00.b) & 0xff; - t2 = ((((c11.b - c10.b) * ex) >> 16) + c10.b) & 0xff; - pc->b = (((t2 - t1) * ey) >> 16) + t1; - t1 = ((((c01.a - c00.a) * ex) >> 16) + c00.a) & 0xff; - t2 = ((((c11.a - c10.a) * ex) >> 16) + c10.a) & 0xff; - pc->a = (((t2 - t1) * ey) >> 16) + t1; - } -#else - if ((dx >= 0) && (dy >= 0) && (dx < srcW) && (dy < srcH)) { - const tColorRGBA *sp = (const tColorRGBA *)getBasePtr(dx, dy); - *pc = *sp; - } -#endif - sdx += icosx; - sdy += isiny; - pc++; - } - } - return target; -} - -TransparentSurface *TransparentSurface::scale(uint16 newWidth, uint16 newHeight) const { - - Common::Rect srcRect(0, 0, (int16)w, (int16)h); - Common::Rect dstRect(0, 0, (int16)newWidth, (int16)newHeight); - - TransparentSurface *target = new TransparentSurface(); - - assert(format.bytesPerPixel == 4); - - int srcW = srcRect.width(); - int srcH = srcRect.height(); - int dstW = dstRect.width(); - int dstH = dstRect.height(); - - target->create((uint16)dstW, (uint16)dstH, this->format); - -#ifdef ENABLE_BILINEAR - - // NB: The actual order of these bytes may not be correct, but - // since all values are treated equal, that does not matter. - struct tColorRGBA { byte r; byte g; byte b; byte a; }; - - bool flipx = false, flipy = false; // TODO: See mirroring comment in RenderTicket ctor - - - int *sax = new int[dstW + 1]; - int *say = new int[dstH + 1]; - assert(sax && say); - - /* - * Precalculate row increments - */ - int spixelw = (srcW - 1); - int spixelh = (srcH - 1); - int sx = (int) (65536.0f * (float) spixelw / (float) (dstW - 1)); - int sy = (int) (65536.0f * (float) spixelh / (float) (dstH - 1)); - - /* Maximum scaled source size */ - int ssx = (srcW << 16) - 1; - int ssy = (srcH << 16) - 1; - - /* Precalculate horizontal row increments */ - int csx = 0; - int *csax = sax; - for (int x = 0; x <= dstW; x++) { - *csax = csx; - csax++; - csx += sx; - - /* Guard from overflows */ - if (csx > ssx) { - csx = ssx; - } - } - - /* Precalculate vertical row increments */ - int csy = 0; - int *csay = say; - for (int y = 0; y <= dstH; y++) { - *csay = csy; - csay++; - csy += sy; - - /* Guard from overflows */ - if (csy > ssy) { - csy = ssy; - } - } - - const tColorRGBA *sp = (const tColorRGBA *) getBasePtr(0, 0); - tColorRGBA *dp = (tColorRGBA *) target->getBasePtr(0, 0); - int spixelgap = srcW; - - if (flipx) { - sp += spixelw; - } - if (flipy) { - sp += spixelgap * spixelh; - } - - csay = say; - for (int y = 0; y < dstH; y++) { - const tColorRGBA *csp = sp; - csax = sax; - for (int x = 0; x < dstW; x++) { - /* - * Setup color source pointers - */ - int ex = (*csax & 0xffff); - int ey = (*csay & 0xffff); - int cx = (*csax >> 16); - int cy = (*csay >> 16); - - const tColorRGBA *c00, *c01, *c10, *c11; - c00 = sp; - c01 = sp; - c10 = sp; - if (cy < spixelh) { - if (flipy) { - c10 -= spixelgap; - } else { - c10 += spixelgap; - } - } - c11 = c10; - if (cx < spixelw) { - if (flipx) { - c01--; - c11--; - } else { - c01++; - c11++; - } - } - - /* - * Draw and interpolate colors - */ - int t1, t2; - t1 = ((((c01->r - c00->r) * ex) >> 16) + c00->r) & 0xff; - t2 = ((((c11->r - c10->r) * ex) >> 16) + c10->r) & 0xff; - dp->r = (((t2 - t1) * ey) >> 16) + t1; - t1 = ((((c01->g - c00->g) * ex) >> 16) + c00->g) & 0xff; - t2 = ((((c11->g - c10->g) * ex) >> 16) + c10->g) & 0xff; - dp->g = (((t2 - t1) * ey) >> 16) + t1; - t1 = ((((c01->b - c00->b) * ex) >> 16) + c00->b) & 0xff; - t2 = ((((c11->b - c10->b) * ex) >> 16) + c10->b) & 0xff; - dp->b = (((t2 - t1) * ey) >> 16) + t1; - t1 = ((((c01->a - c00->a) * ex) >> 16) + c00->a) & 0xff; - t2 = ((((c11->a - c10->a) * ex) >> 16) + c10->a) & 0xff; - dp->a = (((t2 - t1) * ey) >> 16) + t1; - - /* - * Advance source pointer x - */ - int *salastx = csax; - csax++; - int sstepx = (*csax >> 16) - (*salastx >> 16); - if (flipx) { - sp -= sstepx; - } else { - sp += sstepx; - } - - /* - * Advance destination pointer x - */ - dp++; - } - /* - * Advance source pointer y - */ - int *salasty = csay; - csay++; - int sstepy = (*csay >> 16) - (*salasty >> 16); - sstepy *= spixelgap; - if (flipy) { - sp = csp - sstepy; - } else { - sp = csp + sstepy; - } - } - - delete[] sax; - delete[] say; - -#else - - int *scaleCacheX = new int[dstW]; - for (int x = 0; x < dstW; x++) { - scaleCacheX[x] = (x * srcW) / dstW; - } - - for (int y = 0; y < dstH; y++) { - uint32 *destP = (uint32 *)target->getBasePtr(0, y); - const uint32 *srcP = (const uint32 *)getBasePtr(0, (y * srcH) / dstH); - for (int x = 0; x < dstW; x++) { - *destP++ = srcP[scaleCacheX[x]]; - } - } - delete[] scaleCacheX; - -#endif - - return target; - -} - -} // End of namespace Wintermute diff --git a/engines/wintermute/graphics/transparent_surface.h b/engines/wintermute/graphics/transparent_surface.h deleted file mode 100644 index e5049a5f3f..0000000000 --- a/engines/wintermute/graphics/transparent_surface.h +++ /dev/null @@ -1,153 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program 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; either version 2 - * of the License, or (at your option) any later version. - * - * This program 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. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -#ifndef GRAPHICS_TRANSPARENTSURFACE_H -#define GRAPHICS_TRANSPARENTSURFACE_H - -#include "graphics/surface.h" -#include "engines/wintermute/graphics/transform_struct.h" - -/* - * This code is based on Broken Sword 2.5 engine - * - * Copyright (c) Malte Thiesen, Daniel Queteschiner and Michael Elsdoerfer - * - * Licensed under GNU GPL v2 - * - */ - -// TODO: Find a better solution for this. -#define BS_RGB(R,G,B) (0xFF000000 | ((R) << 16) | ((G) << 8) | (B)) -#define BS_ARGB(A,R,G,B) (((A) << 24) | ((R) << 16) | ((G) << 8) | (B)) - -namespace Wintermute { - -/** - * A transparent graphics surface, which implements alpha blitting. - */ -struct TransparentSurface : public Graphics::Surface { - TransparentSurface(); - TransparentSurface(const Graphics::Surface &surf, bool copyData = false); - - void setColorKey(char r, char g, char b); - void disableColorKey(); - - // Enums - /** - @brief The possible flipping parameters for the blit methode. - */ - enum FLIP_FLAGS { - /// The image will not be flipped. - FLIP_NONE = 0, - /// The image will be flipped at the horizontal axis. - FLIP_H = 1, - /// The image will be flipped at the vertical axis. - FLIP_V = 2, - /// The image will be flipped at the horizontal and vertical axis. - FLIP_HV = FLIP_H | FLIP_V, - /// The image will be flipped at the horizontal and vertical axis. - FLIP_VH = FLIP_H | FLIP_V - }; - - enum AlphaType { - ALPHA_OPAQUE = 0, - ALPHA_BINARY = 1, - ALPHA_FULL = 2 - }; - - - /** - @brief renders the surface to another surface - @param target a pointer to the target surface. In most cases this is the framebuffer. - @param posX the position on the X-axis in the target image in pixels where the image is supposed to be rendered.
- The default value is 0. - @param posY the position on the Y-axis in the target image in pixels where the image is supposed to be rendered.
- The default value is 0. - @param flipping how the the image should be flipped.
- The default value is BS_Image::FLIP_NONE (no flipping) - @param pPartRect Pointer on Common::Rect which specifies the section to be rendered. If the whole image has to be rendered the Pointer is NULL.
- This referes to the unflipped and unscaled image.
- The default value is NULL. - @param color an ARGB color value, which determines the parameters for the color modulation und alpha blending.
- The alpha component of the color determines the alpha blending parameter (0 = no covering, 255 = full covering).
- The color components determines the color for color modulation.
- The default value is BS_ARGB(255, 255, 255, 255) (full covering, no color modulation). - The macros BS_RGB and BS_ARGB can be used for the creation of the color value. - @param width the output width of the screen section. - The images will be scaled if the output width of the screen section differs from the image section.
- The value -1 determines that the image should not be scaled.
- The default value is -1. - @param height the output height of the screen section. - The images will be scaled if the output width of the screen section differs from the image section.
- The value -1 determines that the image should not be scaled.
- The default value is -1. - @return returns false if the rendering failed. - */ - Common::Rect blit(Graphics::Surface &target, int posX = 0, int posY = 0, - int flipping = FLIP_NONE, - Common::Rect *pPartRect = nullptr, - uint color = BS_ARGB(255, 255, 255, 255), - int width = -1, int height = -1, - TSpriteBlendMode blend = BLEND_NORMAL); - void applyColorKey(uint8 r, uint8 g, uint8 b, bool overwriteAlpha = false); - - /** - * @brief Scale function; this returns a transformed version of this surface after rotation and - * scaling. Please do not use this if angle != 0, use rotoscale. - * - * @param newWidth the resulting width. - * @param newHeight the resulting height. - * @see TransformStruct - */ - TransparentSurface *scale(uint16 newWidth, uint16 newHeight) const; - - /** - * @brief Rotoscale function; this returns a transformed version of this surface after rotation and - * scaling. Please do not use this if angle == 0, use plain old scaling function. - * - * @param transform a TransformStruct wrapping the required info. @see TransformStruct - * - */ - TransparentSurface *rotoscale(const TransformStruct &transform) const; - AlphaType getAlphaMode() const; - void setAlphaMode(AlphaType); -private: - AlphaType _alphaMode; - -}; - -/** - * A deleter for Surface objects which can be used with SharedPtr. - * - * This deleter assures Surface::free is called on deletion. - */ -/*struct SharedPtrTransparentSurfaceDeleter { - void operator()(TransparentSurface *ptr) { - ptr->free(); - delete ptr; - } -};*/ - -} // End of namespace Wintermute - - -#endif diff --git a/engines/wintermute/module.mk b/engines/wintermute/module.mk index 19fb3d6717..1b6c52e0b7 100644 --- a/engines/wintermute/module.mk +++ b/engines/wintermute/module.mk @@ -89,9 +89,6 @@ MODULE_OBJS := \ base/save_thumb_helper.o \ base/timer.o \ detection.o \ - graphics/transform_struct.o \ - graphics/transform_tools.o \ - graphics/transparent_surface.o \ math/math_util.o \ math/matrix4.o \ math/vector2.o \ -- cgit v1.2.3 From 5c706dde274753b62c9fc72d5d33b4f42100c11a Mon Sep 17 00:00:00 2001 From: Eugene Sandulenko Date: Tue, 3 Jun 2014 19:00:47 +0300 Subject: SWORD25: Switch to common TransparentSurface --- engines/sword25/gfx/animation.cpp | 8 +- engines/sword25/gfx/bitmapresource.h | 18 +- engines/sword25/gfx/dynamicbitmap.cpp | 8 +- engines/sword25/gfx/graphicengine.cpp | 10 +- engines/sword25/gfx/image/image.h | 22 +- engines/sword25/gfx/image/imgloader.cpp | 4 +- engines/sword25/gfx/image/renderedimage.cpp | 292 +++------------------- engines/sword25/gfx/image/renderedimage.h | 11 +- engines/sword25/gfx/image/swimage.h | 2 +- engines/sword25/gfx/image/vectorimage.h | 2 +- engines/sword25/gfx/image/vectorimagerenderer.cpp | 10 +- engines/sword25/gfx/staticbitmap.cpp | 8 +- engines/sword25/gfx/text.cpp | 6 +- engines/sword25/sword25.cpp | 2 +- 14 files changed, 74 insertions(+), 329 deletions(-) diff --git a/engines/sword25/gfx/animation.cpp b/engines/sword25/gfx/animation.cpp index eeb78857ea..e2662fb2b3 100644 --- a/engines/sword25/gfx/animation.cpp +++ b/engines/sword25/gfx/animation.cpp @@ -189,14 +189,14 @@ bool Animation::doRender(RectangleList *updateRects) { bool result; if (isScalingAllowed() && (_width != pBitmapResource->getWidth() || _height != pBitmapResource->getHeight())) { result = pBitmapResource->blit(_absoluteX, _absoluteY, - (animationDescriptionPtr->getFrame(_currentFrame).flipV ? BitmapResource::FLIP_V : 0) | - (animationDescriptionPtr->getFrame(_currentFrame).flipH ? BitmapResource::FLIP_H : 0), + (animationDescriptionPtr->getFrame(_currentFrame).flipV ? Graphics::FLIP_V : 0) | + (animationDescriptionPtr->getFrame(_currentFrame).flipH ? Graphics::FLIP_H : 0), 0, _modulationColor, _width, _height, updateRects); } else { result = pBitmapResource->blit(_absoluteX, _absoluteY, - (animationDescriptionPtr->getFrame(_currentFrame).flipV ? BitmapResource::FLIP_V : 0) | - (animationDescriptionPtr->getFrame(_currentFrame).flipH ? BitmapResource::FLIP_H : 0), + (animationDescriptionPtr->getFrame(_currentFrame).flipV ? Graphics::FLIP_V : 0) | + (animationDescriptionPtr->getFrame(_currentFrame).flipH ? Graphics::FLIP_H : 0), 0, _modulationColor, -1, -1, updateRects); } diff --git a/engines/sword25/gfx/bitmapresource.h b/engines/sword25/gfx/bitmapresource.h index 7a4daedd84..2ae891f5cd 100644 --- a/engines/sword25/gfx/bitmapresource.h +++ b/engines/sword25/gfx/bitmapresource.h @@ -40,22 +40,6 @@ namespace Sword25 { class BitmapResource : public Resource { public: - /** - @brief Die möglichen Flippingparameter für die Blit-Methode. - */ - enum FLIP_FLAGS { - /// Das Bild wird nicht gespiegelt. - FLIP_NONE = 0, - /// Das Bild wird an der horizontalen Achse gespiegelt. - FLIP_H = 1, - /// Das Bild wird an der vertikalen Achse gespiegelt. - FLIP_V = 2, - /// Das Bild wird an der horizontalen und vertikalen Achse gespiegelt. - FLIP_HV = FLIP_H | FLIP_V, - /// Das Bild wird an der horizontalen und vertikalen Achse gespiegelt. - FLIP_VH = FLIP_H | FLIP_V - }; - BitmapResource(const Common::String &filename, Image *pImage) : _pImage(pImage), Resource(filename, Resource::TYPE_BITMAP) {} virtual ~BitmapResource() { delete _pImage; } @@ -120,7 +104,7 @@ public: - IsColorModulationAllowed() */ bool blit(int posX = 0, int posY = 0, - int flipping = FLIP_NONE, + int flipping = Graphics::FLIP_NONE, Common::Rect *pSrcPartRect = NULL, uint color = BS_ARGB(255, 255, 255, 255), int width = -1, int height = -1, diff --git a/engines/sword25/gfx/dynamicbitmap.cpp b/engines/sword25/gfx/dynamicbitmap.cpp index ce9c056d08..a335f87fa5 100644 --- a/engines/sword25/gfx/dynamicbitmap.cpp +++ b/engines/sword25/gfx/dynamicbitmap.cpp @@ -86,8 +86,8 @@ bool DynamicBitmap::doRender(RectangleList *updateRects) { // a bit slow when drawing videos, but it's not the main // bottleneck. result = _image->blit(_absoluteX, _absoluteY, - (_flipV ? BitmapResource::FLIP_V : 0) | - (_flipH ? BitmapResource::FLIP_H : 0), + (_flipV ? Graphics::FLIP_V : 0) | + (_flipH ? Graphics::FLIP_H : 0), 0, _modulationColor, -1, -1, updateRects); #else @@ -105,8 +105,8 @@ bool DynamicBitmap::doRender(RectangleList *updateRects) { return true; } else { result = _image->blit(_absoluteX, _absoluteY, - (_flipV ? BitmapResource::FLIP_V : 0) | - (_flipH ? BitmapResource::FLIP_H : 0), + (_flipV ? Graphics::FLIP_V : 0) | + (_flipH ? Graphics::FLIP_H : 0), 0, _modulationColor, _width, _height, updateRects); } diff --git a/engines/sword25/gfx/graphicengine.cpp b/engines/sword25/gfx/graphicengine.cpp index 2a870c021d..f887c3cd51 100644 --- a/engines/sword25/gfx/graphicengine.cpp +++ b/engines/sword25/gfx/graphicengine.cpp @@ -183,7 +183,7 @@ bool GraphicEngine::fill(const Common::Rect *fillRectPtr, uint color) { if (rect.width() > 0 && rect.height() > 0) { if (ca == 0xff) { - _backSurface.fillRect(rect, color); + _backSurface.fillRect(rect, BS_ARGB(cr, cg, cb, ca)); } else { byte *outo = (byte *)_backSurface.getBasePtr(rect.left, rect.top); byte *out; @@ -192,23 +192,23 @@ bool GraphicEngine::fill(const Common::Rect *fillRectPtr, uint color) { out = outo; for (int j = rect.left; j < rect.right; j++) { #if defined(SCUMM_LITTLE_ENDIAN) + *out = 255; + out++; *out += (byte)(((cb - *out) * ca) >> 8); out++; *out += (byte)(((cg - *out) * ca) >> 8); out++; *out += (byte)(((cr - *out) * ca) >> 8); out++; - *out = 255; - out++; #else - *out = 255; - out++; *out += (byte)(((cr - *out) * ca) >> 8); out++; *out += (byte)(((cg - *out) * ca) >> 8); out++; *out += (byte)(((cb - *out) * ca) >> 8); out++; + *out = 255; + out++; #endif } diff --git a/engines/sword25/gfx/image/image.h b/engines/sword25/gfx/image/image.h index 8fbf802501..f8cb0dfec0 100644 --- a/engines/sword25/gfx/image/image.h +++ b/engines/sword25/gfx/image/image.h @@ -43,6 +43,7 @@ #include "sword25/kernel/common.h" #include "common/rect.h" #include "sword25/gfx/graphicengine.h" +#include "graphics/transparent_surface.h" namespace Sword25 { @@ -52,23 +53,6 @@ class Image { public: virtual ~Image() {} - // Enums - /** - @brief The possible flipping parameters for the blit methode. - */ - enum FLIP_FLAGS { - /// The image will not be flipped. - FLIP_NONE = 0, - /// The image will be flipped at the horizontal axis. - FLIP_H = 1, - /// The image will be flipped at the vertical axis. - FLIP_V = 2, - /// The image will be flipped at the horizontal and vertical axis. - FLIP_HV = FLIP_H | FLIP_V, - /// The image will be flipped at the horizontal and vertical axis. - FLIP_VH = FLIP_H | FLIP_V - }; - //@{ /** @name Accessor methods */ @@ -100,7 +84,7 @@ public: @param PosY the position on the Y-axis in the target image in pixels where the image is supposed to be rendered.
The default value is 0. @param Flipping how the the image should be flipped.
- The default value is BS_Image::FLIP_NONE (no flipping) + The default value is Graphics::FLIP_NONE (no flipping) @param pSrcPartRect Pointer on Common::Rect which specifies the section to be rendered. If the whole image has to be rendered the Pointer is NULL.
This referes to the unflipped and unscaled image.
The default value is NULL. @@ -128,7 +112,7 @@ public: - IsSetContentAllowed() */ virtual bool blit(int posX = 0, int posY = 0, - int flipping = FLIP_NONE, + int flipping = Graphics::FLIP_NONE, Common::Rect *pPartRect = NULL, uint color = BS_ARGB(255, 255, 255, 255), int width = -1, int height = -1, diff --git a/engines/sword25/gfx/image/imgloader.cpp b/engines/sword25/gfx/image/imgloader.cpp index b4b3030de8..f299cee9d1 100644 --- a/engines/sword25/gfx/image/imgloader.cpp +++ b/engines/sword25/gfx/image/imgloader.cpp @@ -45,7 +45,7 @@ bool ImgLoader::decodePNGImage(const byte *fileDataPtr, uint fileSize, byte *&un error("Error while reading PNG image"); const Graphics::Surface *sourceSurface = png.getSurface(); - Graphics::Surface *pngSurface = sourceSurface->convertTo(Graphics::PixelFormat(4, 8, 8, 8, 8, 16, 8, 0, 24), png.getPalette()); + Graphics::Surface *pngSurface = sourceSurface->convertTo(Graphics::PixelFormat(4, 8, 8, 8, 8, 24, 16, 8, 0), png.getPalette()); width = pngSurface->w; height = pngSurface->h; @@ -70,7 +70,7 @@ bool ImgLoader::decodeThumbnailImage(const byte *pFileData, uint fileSize, byte uint32 totalSize = pitch * height; pUncompressedData = new byte[totalSize]; uint32 *dst = (uint32 *)pUncompressedData; // treat as uint32, for pixelformat output - const Graphics::PixelFormat format = Graphics::PixelFormat(4, 8, 8, 8, 8, 16, 8, 0, 24); + const Graphics::PixelFormat format = Graphics::PixelFormat(4, 8, 8, 8, 8, 24, 16, 8, 0); byte r, g, b; for (uint32 i = 0; i < totalSize / 4; i++) { diff --git a/engines/sword25/gfx/image/renderedimage.cpp b/engines/sword25/gfx/image/renderedimage.cpp index 107b4cd402..de79630376 100644 --- a/engines/sword25/gfx/image/renderedimage.cpp +++ b/engines/sword25/gfx/image/renderedimage.cpp @@ -100,9 +100,6 @@ static byte *readSavegameThumbnail(const Common::String &filename, uint &fileSiz } RenderedImage::RenderedImage(const Common::String &filename, bool &result) : - _data(0), - _width(0), - _height(0), _isTransparent(true) { result = false; @@ -130,10 +127,18 @@ RenderedImage::RenderedImage(const Common::String &filename, bool &result) : // Uncompress the image int pitch; + byte *dst; + int w, h; if (isPNG) - result = ImgLoader::decodePNGImage(pFileData, fileSize, _data, _width, _height, pitch); + result = ImgLoader::decodePNGImage(pFileData, fileSize, dst, w, h, pitch); else - result = ImgLoader::decodeThumbnailImage(pFileData, fileSize, _data, _width, _height, pitch); + result = ImgLoader::decodeThumbnailImage(pFileData, fileSize, dst, w, h, pitch); + + _surface.w = w; + _surface.h = h; + _surface.pitch = w * 4; + _surface.setPixels(dst); + _surface.format = Graphics::PixelFormat(4, 8, 8, 8, 8, 24, 16, 8, 0); if (!result) { error("Could not decode image."); @@ -157,12 +162,9 @@ RenderedImage::RenderedImage(const Common::String &filename, bool &result) : // ----------------------------------------------------------------------------- RenderedImage::RenderedImage(uint width, uint height, bool &result) : - _width(width), - _height(height), _isTransparent(true) { - _data = new byte[width * height * 4]; - Common::fill(_data, &_data[width * height * 4], 0); + _surface.create(width, height, Graphics::PixelFormat(4, 8, 8, 8, 8, 24, 16, 8, 0)); _backSurface = Kernel::getInstance()->getGfx()->getSurface(); @@ -172,9 +174,11 @@ RenderedImage::RenderedImage(uint width, uint height, bool &result) : return; } -RenderedImage::RenderedImage() : _width(0), _height(0), _data(0), _isTransparent(true) { +RenderedImage::RenderedImage() : _isTransparent(true) { _backSurface = Kernel::getInstance()->getGfx()->getSurface(); + _surface.format = Graphics::PixelFormat(4, 8, 8, 8, 8, 24, 16, 8, 0); + _doCleanup = false; return; @@ -183,8 +187,6 @@ RenderedImage::RenderedImage() : _width(0), _height(0), _data(0), _isTransparent // ----------------------------------------------------------------------------- RenderedImage::~RenderedImage() { - if (_doCleanup) - delete[] _data; } // ----------------------------------------------------------------------------- @@ -198,17 +200,17 @@ bool RenderedImage::fill(const Common::Rect *pFillRect, uint color) { bool RenderedImage::setContent(const byte *pixeldata, uint size, uint offset, uint stride) { // Check if PixelData contains enough pixel to create an image with image size equals width * height - if (size < static_cast(_width * _height * 4)) { - error("PixelData vector is too small to define a 32 bit %dx%d image.", _width, _height); + if (size < static_cast(_surface.w * _surface.h * 4)) { + error("PixelData vector is too small to define a 32 bit %dx%d image.", _surface.w, _surface.h); return false; } const byte *in = &pixeldata[offset]; - byte *out = _data; + byte *out = (byte *)_surface.getPixels(); - for (int i = 0; i < _height; i++) { - memcpy(out, in, _width * 4); - out += _width * 4; + for (int i = 0; i < _surface.h; i++) { + memcpy(out, in, _surface.w * 4); + out += _surface.w * 4; in += stride; } @@ -216,9 +218,10 @@ bool RenderedImage::setContent(const byte *pixeldata, uint size, uint offset, ui } void RenderedImage::replaceContent(byte *pixeldata, int width, int height) { - _width = width; - _height = height; - _data = pixeldata; + _surface.w = width; + _surface.h = height; + _surface.pitch = width * 4; + _surface.setPixels(pixeldata); } // ----------------------------------------------------------------------------- @@ -230,251 +233,26 @@ uint RenderedImage::getPixel(int x, int y) { // ----------------------------------------------------------------------------- bool RenderedImage::blit(int posX, int posY, int flipping, Common::Rect *pPartRect, uint color, int width, int height, RectangleList *updateRects) { - int ca = (color >> 24) & 0xff; - - // Check if we need to draw anything at all - if (ca == 0) - return true; - - int cr = (color >> 16) & 0xff; - int cg = (color >> 8) & 0xff; - int cb = (color >> 0) & 0xff; - - // Create an encapsulating surface for the data - Graphics::Surface srcImage; - // TODO: Is the data really in the screen format? - srcImage.init(_width, _height, _width * 4, _data, g_system->getScreenFormat()); - - if (pPartRect) { - srcImage.setPixels(&_data[pPartRect->top * srcImage.pitch + pPartRect->left * 4]); - srcImage.w = pPartRect->right - pPartRect->left; - srcImage.h = pPartRect->bottom - pPartRect->top; - - debug(6, "Blit(%d, %d, %d, [%d, %d, %d, %d], %08x, %d, %d)", posX, posY, flipping, - pPartRect->left, pPartRect->top, pPartRect->width(), pPartRect->height(), color, width, height); - } else { - - debug(6, "Blit(%d, %d, %d, [%d, %d, %d, %d], %08x, %d, %d)", posX, posY, flipping, 0, 0, - srcImage.w, srcImage.h, color, width, height); - } - - if (width == -1) - width = srcImage.w; - if (height == -1) - height = srcImage.h; - -#ifdef SCALING_TESTING - // Hardcode scaling to 66% to test scaling - width = width * 2 / 3; - height = height * 2 / 3; -#endif - - Graphics::Surface *img; - Graphics::Surface *imgScaled = NULL; - byte *savedPixels = NULL; - if ((width != srcImage.w) || (height != srcImage.h)) { - // Scale the image - img = imgScaled = scale(srcImage, width, height); - savedPixels = (byte *)img->getPixels(); - } else { - img = &srcImage; - } - - for (RectangleList::iterator it = updateRects->begin(); it != updateRects->end(); ++it) { - const Common::Rect &clipRect = *it; - - int skipLeft = 0, skipTop = 0; - int drawX = posX, drawY = posY; - int drawWidth = img->w; - int drawHeight = img->h; - - // Handle clipping - if (drawX < clipRect.left) { - skipLeft = clipRect.left - drawX; - drawWidth -= skipLeft; - drawX = clipRect.left; - } - - if (drawY < clipRect.top) { - skipTop = clipRect.top - drawY; - drawHeight -= skipTop; - drawY = clipRect.top; - } - - if (drawX + drawWidth >= clipRect.right) - drawWidth = clipRect.right - drawX; - - if (drawY + drawHeight >= clipRect.bottom) - drawHeight = clipRect.bottom - drawY; - - if ((drawWidth > 0) && (drawHeight > 0)) { - int xp = 0, yp = 0; - - int inStep = 4; - int inoStep = img->pitch; - if (flipping & Image::FLIP_V) { - inStep = -inStep; - xp = img->w - 1 - skipLeft; - } else { - xp = skipLeft; - } - - if (flipping & Image::FLIP_H) { - inoStep = -inoStep; - yp = img->h - 1 - skipTop; - } else { - yp = skipTop; - } - - byte *ino = (byte *)img->getBasePtr(xp, yp); - byte *outo = (byte *)_backSurface->getBasePtr(drawX, drawY); - -#if defined(SCUMM_LITTLE_ENDIAN) - // Simple memcpy if the source bitmap doesn't have transparent pixels and the drawing transparency is 255 - // NOTE Only possible with LE-machines at the moment, maybe it would be feasible to convert the bitmap pixels at loading time? - if (!_isTransparent && ca == 255) { - for (int i = 0; i < drawHeight; i++) { - memcpy(outo, ino, drawWidth * 4); - outo += _backSurface->pitch; - ino += inoStep; - } - } else -#endif - { - byte *in, *out; - for (int i = 0; i < drawHeight; i++) { - out = outo; - in = ino; - for (int j = 0; j < drawWidth; j++) { - uint32 pix = *(uint32 *)in; - int a = (pix >> 24) & 0xff; - in += inStep; - - if (ca != 255) { - a = a * ca >> 8; - } - - if (a == 0) { - // Full transparency - out += 4; - continue; - } - - int b = (pix >> 0) & 0xff; - int g = (pix >> 8) & 0xff; - int r = (pix >> 16) & 0xff; - - if (a == 255) { -#if defined(SCUMM_LITTLE_ENDIAN) - if (cb != 255) - b = (b * cb) >> 8; - if (cg != 255) - g = (g * cg) >> 8; - if (cr != 255) - r = (r * cr) >> 8; - *(uint32 *)out = (255 << 24) | (r << 16) | (g << 8) | b; - out += 4; -#else - *out++ = a; - if (cr != 255) - *out++ = (r * cr) >> 8; - else - *out++ = r; - if (cg != 255) - *out++ = (g * cg) >> 8; - else - *out++ = g; - if (cb != 255) - *out++ = (b * cb) >> 8; - else - *out++ = b; -#endif - } else { -#if defined(SCUMM_LITTLE_ENDIAN) - pix = *(uint32 *)out; - int outb = ((pix >> 0) & 0xff) * (255 - a); - int outg = ((pix >> 8) & 0xff) * (255 - a); - int outr = ((pix >> 16) & 0xff) * (255 - a); - if (cb == 0) - outb = outb >> 8; - else if (cb != 255) - outb = ((outb << 8) + b * a * cb) >> 16; - else - outb = (outb + b * a) >> 8; - if (cg == 0) - outg = outg >> 8; - else if (cg != 255) - outg = ((outg << 8) + g * a * cg) >> 16; - else - outg = (outg + g * a) >> 8; - if (cr == 0) - outr = outr >> 8; - else if (cr != 255) - outr = ((outr << 8) + r * a * cr) >> 16; - else - outr = (outr + r * a) >> 8; - *(uint32 *)out = (255 << 24) | (outr << 16) | (outg << 8) | outb; - out += 4; -#else - *out = 255; - out++; - if (cr == 0) - *out = (*out * (255-a)) >> 8; - else if (cr != 255) - *out = (((*out * (255-a)) << 8) + r * a * cr) >> 16; - else - *out = ((*out * (255-a)) + r * a) >> 8; - out++; - if (cg == 0) - *out = (*out * (255-a)) >> 8; - else if (cg != 255) - *out = (((*out * (255-a)) << 8) + g * a * cg) >> 16; - else - *out = ((*out * (255-a)) + g * a) >> 8; - out++; - if (cb == 0) - *out = (*out * (255-a)) >> 8; - else if (cb != 255) - *out = (((*out * (255-a)) << 8) + b * a * cb) >> 16; - else - *out = ((*out * (255-a)) + b * a) >> 8; - out++; -#endif - } - } - outo += _backSurface->pitch; - ino += inoStep; - } - } - - } - - } - - if (imgScaled) { - imgScaled->setPixels(savedPixels); - imgScaled->free(); - delete imgScaled; - } + _surface.blit(*_backSurface, posX, posY, flipping, pPartRect, color, width, height); return true; } void RenderedImage::copyDirectly(int posX, int posY) { - byte *data = _data; - int w = _width; - int h = _height; + byte *data = (byte *)_surface.getPixels(); + int w = _surface.w; + int h = _surface.h; // Handle off-screen clipping if (posY < 0) { - h = MAX(0, (int)_height - -posY); - data = (byte *)_data + _width * -posY; + h = MAX(0, (int)_surface.h - -posY); + data = (byte *)_surface.getPixels() + _surface.w * -posY; posY = 0; } if (posX < 0) { - w = MAX(0, (int)_width - -posX); - data = (byte *)_data + (-posX * 4); + w = MAX(0, (int)_surface.h - -posX); + data = (byte *)_surface.getPixels() + (-posX * 4); posX = 0; } @@ -487,9 +265,9 @@ void RenderedImage::copyDirectly(int posX, int posY) { void RenderedImage::checkForTransparency() { // Check if the source bitmap has any transparent pixels at all _isTransparent = false; - byte *data = _data; - for (int i = 0; i < _height; i++) { - for (int j = 0; j < _width; j++) { + byte *data = (byte *)_surface.getPixels(); + for (int i = 0; i < _surface.h; i++) { + for (int j = 0; j < _surface.w; j++) { _isTransparent = data[3] != 0xff; if (_isTransparent) return; diff --git a/engines/sword25/gfx/image/renderedimage.h b/engines/sword25/gfx/image/renderedimage.h index 3cc9725b12..5b65a27355 100644 --- a/engines/sword25/gfx/image/renderedimage.h +++ b/engines/sword25/gfx/image/renderedimage.h @@ -39,6 +39,7 @@ #include "sword25/kernel/common.h" #include "sword25/gfx/image/image.h" #include "sword25/gfx/graphicengine.h" +#include "graphics/transparent_surface.h" namespace Sword25 { @@ -60,10 +61,10 @@ public: virtual ~RenderedImage(); virtual int getWidth() const { - return _width; + return _surface.w; } virtual int getHeight() const { - return _height; + return _surface.h; } virtual GraphicEngine::COLOR_FORMATS getColorFormat() const { return GraphicEngine::CF_ARGB32; @@ -72,7 +73,7 @@ public: void copyDirectly(int posX, int posY); virtual bool blit(int posX = 0, int posY = 0, - int flipping = Image::FLIP_NONE, + int flipping = Graphics::FLIP_NONE, Common::Rect *pPartRect = NULL, uint color = BS_ARGB(255, 255, 255, 255), int width = -1, int height = -1, @@ -108,9 +109,7 @@ public: virtual bool isSolid() const { return !_isTransparent; } private: - byte *_data; - int _width; - int _height; + Graphics::TransparentSurface _surface; bool _doCleanup; bool _isTransparent; diff --git a/engines/sword25/gfx/image/swimage.h b/engines/sword25/gfx/image/swimage.h index b31c2318ec..60978eb6cc 100644 --- a/engines/sword25/gfx/image/swimage.h +++ b/engines/sword25/gfx/image/swimage.h @@ -55,7 +55,7 @@ public: } virtual bool blit(int posX = 0, int posY = 0, - int flipping = Image::FLIP_NONE, + int flipping = Graphics::FLIP_NONE, Common::Rect *pPartRect = NULL, uint color = BS_ARGB(255, 255, 255, 255), int width = -1, int height = -1, diff --git a/engines/sword25/gfx/image/vectorimage.h b/engines/sword25/gfx/image/vectorimage.h index a99d532e75..057064fc6a 100644 --- a/engines/sword25/gfx/image/vectorimage.h +++ b/engines/sword25/gfx/image/vectorimage.h @@ -209,7 +209,7 @@ public: } virtual bool setContent(const byte *pixeldata, uint size, uint offset, uint stride); virtual bool blit(int posX = 0, int posY = 0, - int flipping = FLIP_NONE, + int flipping = Graphics::FLIP_NONE, Common::Rect *pPartRect = NULL, uint color = BS_ARGB(255, 255, 255, 255), int width = -1, int height = -1, diff --git a/engines/sword25/gfx/image/vectorimagerenderer.cpp b/engines/sword25/gfx/image/vectorimagerenderer.cpp index c7a79fd3c4..c69cb497c1 100644 --- a/engines/sword25/gfx/image/vectorimagerenderer.cpp +++ b/engines/sword25/gfx/image/vectorimagerenderer.cpp @@ -52,7 +52,7 @@ void art_rgb_fill_run1(byte *buf, byte r, byte g, byte b, int n) { memset(buf, g, n + n + n + n); } else { uint32 *alt = (uint32 *)buf; - uint32 color = Graphics::ARGBToColor >(0xff, r, g, b); + uint32 color = Graphics::ARGBToColor >(r, g, b, 0xff); for (i = 0; i < n; i++) *alt++ = color; @@ -65,23 +65,23 @@ void art_rgb_run_alpha1(byte *buf, byte r, byte g, byte b, int alpha, int n) { for (i = 0; i < n; i++) { #if defined(SCUMM_LITTLE_ENDIAN) + v = *buf; + *buf++ = MIN(v + alpha, 0xff); v = *buf; *buf++ = v + (((b - v) * alpha + 0x80) >> 8); v = *buf; *buf++ = v + (((g - v) * alpha + 0x80) >> 8); v = *buf; *buf++ = v + (((r - v) * alpha + 0x80) >> 8); - v = *buf; - *buf++ = MIN(v + alpha, 0xff); #else - v = *buf; - *buf++ = MIN(v + alpha, 0xff); v = *buf; *buf++ = v + (((r - v) * alpha + 0x80) >> 8); v = *buf; *buf++ = v + (((g - v) * alpha + 0x80) >> 8); v = *buf; *buf++ = v + (((b - v) * alpha + 0x80) >> 8); + v = *buf; + *buf++ = MIN(v + alpha, 0xff); #endif } } diff --git a/engines/sword25/gfx/staticbitmap.cpp b/engines/sword25/gfx/staticbitmap.cpp index 14e2012d80..1a6c812508 100644 --- a/engines/sword25/gfx/staticbitmap.cpp +++ b/engines/sword25/gfx/staticbitmap.cpp @@ -98,14 +98,14 @@ bool StaticBitmap::doRender(RectangleList *updateRects) { bool result; if (_scaleFactorX == 1.0f && _scaleFactorY == 1.0f) { result = bitmapResourcePtr->blit(_absoluteX, _absoluteY, - (_flipV ? BitmapResource::FLIP_V : 0) | - (_flipH ? BitmapResource::FLIP_H : 0), + (_flipV ? Graphics::FLIP_V : 0) | + (_flipH ? Graphics::FLIP_H : 0), 0, _modulationColor, -1, -1, updateRects); } else { result = bitmapResourcePtr->blit(_absoluteX, _absoluteY, - (_flipV ? BitmapResource::FLIP_V : 0) | - (_flipH ? BitmapResource::FLIP_H : 0), + (_flipV ? Graphics::FLIP_V : 0) | + (_flipH ? Graphics::FLIP_H : 0), 0, _modulationColor, _width, _height, updateRects); } diff --git a/engines/sword25/gfx/text.cpp b/engines/sword25/gfx/text.cpp index b0a9e4ed3f..904435fcb0 100644 --- a/engines/sword25/gfx/text.cpp +++ b/engines/sword25/gfx/text.cpp @@ -99,7 +99,7 @@ void Text::setText(const Common::String &text) { } void Text::setColor(uint32 modulationColor) { - uint32 newModulationColor = (modulationColor & 0x00ffffff) | (_modulationColor & 0xff000000); + uint32 newModulationColor = (modulationColor & 0xffffff00) | (_modulationColor & 0x000000ff); if (newModulationColor != _modulationColor) { _modulationColor = newModulationColor; forceRefresh(); @@ -108,7 +108,7 @@ void Text::setColor(uint32 modulationColor) { void Text::setAlpha(int alpha) { assert(alpha >= 0 && alpha < 256); - uint32 newModulationColor = (_modulationColor & 0x00ffffff) | alpha << 24; + uint32 newModulationColor = (_modulationColor & 0xffffff00) | alpha; if (newModulationColor != _modulationColor) { _modulationColor = newModulationColor; forceRefresh(); @@ -173,7 +173,7 @@ bool Text::doRender(RectangleList *updateRects) { Common::Rect renderRect(curX, curY, curX + curRect.width(), curY + curRect.height()); renderRect.translate(curRect.left - curX, curRect.top - curY); - result = charMapPtr->blit(curX, curY, Image::FLIP_NONE, &renderRect, _modulationColor, -1, -1, updateRects); + result = charMapPtr->blit(curX, curY, Graphics::FLIP_NONE, &renderRect, _modulationColor, -1, -1, updateRects); if (!result) break; diff --git a/engines/sword25/sword25.cpp b/engines/sword25/sword25.cpp index 259deb2ea8..bb0aab3ad4 100644 --- a/engines/sword25/sword25.cpp +++ b/engines/sword25/sword25.cpp @@ -97,7 +97,7 @@ Common::Error Sword25Engine::run() { Common::Error Sword25Engine::appStart() { // Initialize the graphics mode to ARGB8888 - Graphics::PixelFormat format = Graphics::PixelFormat(4, 8, 8, 8, 8, 16, 8, 0, 24); + Graphics::PixelFormat format = Graphics::PixelFormat(4, 8, 8, 8, 8, 24, 16, 8, 0); initGraphics(800, 600, true, &format); if (format != g_system->getScreenFormat()) return Common::kUnsupportedColorMode; -- cgit v1.2.3