Initial commit
This commit is contained in:
643
engines/sword25/gfx/image/vectorimage.cpp
Normal file
643
engines/sword25/gfx/image/vectorimage.cpp
Normal file
@@ -0,0 +1,643 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* This code is based on Broken Sword 2.5 engine
|
||||
*
|
||||
* Copyright (c) Malte Thiesen, Daniel Queteschiner and Michael Elsdoerfer
|
||||
*
|
||||
* Licensed under GNU GPL v2
|
||||
*
|
||||
*/
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Includes
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
#include "sword25/gfx/image/art.h"
|
||||
#include "sword25/gfx/image/vectorimage.h"
|
||||
#include "sword25/gfx/image/renderedimage.h"
|
||||
|
||||
namespace Sword25 {
|
||||
|
||||
#define BEZSMOOTHNESS 0.5
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// SWF datatype
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Bitstream helper class
|
||||
// -----------------------------------------------------------------------------
|
||||
// The parsing of SWF files requires both bitwise readout and on Byte boundaries
|
||||
// oriented reading.
|
||||
// This class is specially equipped for this.
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
class VectorImage::SWFBitStream {
|
||||
public:
|
||||
SWFBitStream(const byte *pData, uint dataSize) :
|
||||
m_Pos(pData), m_End(pData + dataSize), m_WordMask(0)
|
||||
{}
|
||||
|
||||
inline uint32 getBits(uint bitCount) {
|
||||
if (bitCount == 0 || bitCount > 32) {
|
||||
error("SWFBitStream::GetBits() must read at least 1 and at most 32 bits at a time");
|
||||
}
|
||||
|
||||
uint32 value = 0;
|
||||
while (bitCount) {
|
||||
if (m_WordMask == 0)
|
||||
flushByte();
|
||||
|
||||
value <<= 1;
|
||||
value |= ((m_Word & m_WordMask) != 0) ? 1 : 0;
|
||||
m_WordMask >>= 1;
|
||||
|
||||
--bitCount;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
inline int32 getSignedBits(uint bitCount) {
|
||||
// readout bits
|
||||
uint32 temp = getBits(bitCount);
|
||||
|
||||
// If the sign-bit is set, fill the rest of the return value with 1-bit (sign extension)
|
||||
if (temp & 1 << (bitCount - 1))
|
||||
return (0xffffffff << bitCount) | temp;
|
||||
else
|
||||
return temp;
|
||||
}
|
||||
|
||||
inline uint32 getUInt32() {
|
||||
uint32 byte1 = getByte();
|
||||
uint32 byte2 = getByte();
|
||||
uint32 byte3 = getByte();
|
||||
uint32 byte4 = getByte();
|
||||
|
||||
return byte1 | (byte2 << 8) | (byte3 << 16) | (byte4 << 24);
|
||||
}
|
||||
|
||||
inline uint16 getUInt16() {
|
||||
uint32 byte1 = getByte();
|
||||
uint32 byte2 = getByte();
|
||||
|
||||
return byte1 | (byte2 << 8);
|
||||
}
|
||||
|
||||
inline byte getByte() {
|
||||
flushByte();
|
||||
byte value = m_Word;
|
||||
m_WordMask = 0;
|
||||
flushByte();
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
inline void flushByte() {
|
||||
if (m_WordMask != 128) {
|
||||
if (m_Pos >= m_End) {
|
||||
error("Attempted to read past end of file");
|
||||
} else {
|
||||
m_Word = *m_Pos++;
|
||||
m_WordMask = 128;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline void skipBytes(uint skipLength) {
|
||||
flushByte();
|
||||
if (m_Pos + skipLength >= m_End) {
|
||||
error("Attempted to read past end of file");
|
||||
} else {
|
||||
m_Pos += skipLength;
|
||||
m_Word = *(m_Pos - 1);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
const byte *m_Pos;
|
||||
const byte *m_End;
|
||||
|
||||
byte m_Word;
|
||||
uint m_WordMask;
|
||||
};
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Constants and utility functions
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
namespace {
|
||||
// -----------------------------------------------------------------------------
|
||||
// Constants
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
const uint32 MAX_ACCEPTED_FLASH_VERSION = 3; // The maximum flash file version that is accepted by the loader
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Converts SWF rectangle data in a bit stream in Common::Rect objects
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
Common::Rect flashRectToBSRect(VectorImage::SWFBitStream &bs) {
|
||||
bs.flushByte();
|
||||
|
||||
// Determines how many bits of the single components are encoded
|
||||
uint32 bitsPerValue = bs.getBits(5);
|
||||
|
||||
// Readout the single components
|
||||
int32 xMin = bs.getSignedBits(bitsPerValue);
|
||||
int32 xMax = bs.getSignedBits(bitsPerValue);
|
||||
int32 yMin = bs.getSignedBits(bitsPerValue);
|
||||
int32 yMax = bs.getSignedBits(bitsPerValue);
|
||||
|
||||
return Common::Rect(xMin, yMin, xMax + 1, yMax + 1);
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Calculate the bounding box of a BS_VectorImageElement
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
Common::Rect CalculateBoundingBox(const VectorImageElement &vectorImageElement) {
|
||||
double x0 = 0.0, y0 = 0.0, x1 = 0.0, y1 = 0.0;
|
||||
|
||||
for (int j = vectorImageElement.getPathCount() - 1; j >= 0; j--) {
|
||||
ArtBpath *bez = vectorImageElement.getPathInfo(j).getVec();
|
||||
ArtVpath *vec = art_bez_path_to_vec(bez, 0.5);
|
||||
|
||||
if (vec[0].code == ART_END) {
|
||||
free(vec);
|
||||
continue;
|
||||
} else {
|
||||
x0 = x1 = vec[0].x;
|
||||
y0 = y1 = vec[0].y;
|
||||
for (int i = 1; vec[i].code != ART_END; i++) {
|
||||
if (vec[i].x < x0) x0 = vec[i].x;
|
||||
if (vec[i].x > x1) x1 = vec[i].x;
|
||||
if (vec[i].y < y0) y0 = vec[i].y;
|
||||
if (vec[i].y > y1) y1 = vec[i].y;
|
||||
}
|
||||
}
|
||||
free(vec);
|
||||
}
|
||||
|
||||
return Common::Rect(static_cast<int>(x0), static_cast<int>(y0), static_cast<int>(x1) + 1, static_cast<int>(y1) + 1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Construction
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
VectorImage::VectorImage(const byte *pFileData, uint fileSize, bool &success, const Common::String &fname) : _pixelData(0), _fname(fname) {
|
||||
success = false;
|
||||
_bgColor = 0;
|
||||
|
||||
// Create bitstream object
|
||||
// In the following the file data will be readout of the bitstream object.
|
||||
SWFBitStream bs(pFileData, fileSize);
|
||||
|
||||
// Check SWF signature
|
||||
uint32 signature[3];
|
||||
signature[0] = bs.getByte();
|
||||
signature[1] = bs.getByte();
|
||||
signature[2] = bs.getByte();
|
||||
if (signature[0] != 'F' ||
|
||||
signature[1] != 'W' ||
|
||||
signature[2] != 'S') {
|
||||
error("File is not a valid SWF-file");
|
||||
return;
|
||||
}
|
||||
|
||||
// Check the version
|
||||
uint32 version = bs.getByte();
|
||||
if (version > MAX_ACCEPTED_FLASH_VERSION) {
|
||||
error("File is of version %d. Highest accepted version is %d.", version, MAX_ACCEPTED_FLASH_VERSION);
|
||||
return;
|
||||
}
|
||||
|
||||
// Readout filesize and compare with the actual size
|
||||
uint32 storedFileSize = bs.getUInt32();
|
||||
if (storedFileSize != fileSize) {
|
||||
error("File is not a valid SWF-file");
|
||||
return;
|
||||
}
|
||||
|
||||
// readout SWF size
|
||||
flashRectToBSRect(bs);
|
||||
|
||||
// Get frame rate and frame count
|
||||
/* uint32 frameRate = */
|
||||
bs.getUInt16();
|
||||
/* uint32 frameCount = */
|
||||
bs.getUInt16();
|
||||
|
||||
// Parse tags
|
||||
// Because we are only interested in the first DifneShape-Tag...
|
||||
bool keepParsing = true;
|
||||
while (keepParsing) {
|
||||
// Tags always begin on byte boundaries
|
||||
bs.flushByte();
|
||||
|
||||
// Readout tag type and length
|
||||
uint16 tagTypeAndLength = bs.getUInt16();
|
||||
uint32 tagType = tagTypeAndLength >> 6;
|
||||
uint32 tagLength = tagTypeAndLength & 0x3f;
|
||||
if (tagLength == 0x3f)
|
||||
tagLength = bs.getUInt32();
|
||||
|
||||
switch (tagType) {
|
||||
case 2:
|
||||
// DefineShape
|
||||
success = parseDefineShape(2, bs);
|
||||
return;
|
||||
case 22:
|
||||
// DefineShape2
|
||||
success = parseDefineShape(2, bs);
|
||||
return;
|
||||
case 32:
|
||||
success = parseDefineShape(3, bs);
|
||||
return;
|
||||
case 9:
|
||||
// SetBackgroundColor
|
||||
{
|
||||
byte r, g, b;
|
||||
r = bs.getByte();
|
||||
g = bs.getByte();
|
||||
b = bs.getByte();
|
||||
_bgColor = BS_RGB(r, g, b);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
warning("Ignoring tag: %d, %d bytes", tagType, tagLength);
|
||||
// Ignore unknown tags
|
||||
bs.skipBytes(tagLength);
|
||||
}
|
||||
}
|
||||
|
||||
// The execution must not arrive at this point: Either a shape is found, then the function will be leaved before, or it is found none, then
|
||||
// an exception occurs as soon as it is read beyond of the end of file.
|
||||
assert(false);
|
||||
}
|
||||
|
||||
VectorImage::~VectorImage() {
|
||||
for (int j = _elements.size() - 1; j >= 0; j--)
|
||||
for (int i = _elements[j].getPathCount() - 1; i >= 0; i--)
|
||||
if (_elements[j].getPathInfo(i).getVec())
|
||||
free(_elements[j].getPathInfo(i).getVec());
|
||||
|
||||
free(_pixelData);
|
||||
}
|
||||
|
||||
|
||||
ArtBpath *ensureBezStorage(ArtBpath *bez, int nodes, int *allocated) {
|
||||
if (*allocated <= nodes) {
|
||||
(*allocated) += 20;
|
||||
|
||||
return art_renew(bez, ArtBpath, *allocated);
|
||||
}
|
||||
|
||||
return bez;
|
||||
}
|
||||
|
||||
ArtBpath *VectorImage::storeBez(ArtBpath *bez, int lineStyle, int fillStyle0, int fillStyle1, int *bezNodes, int *bezAllocated) {
|
||||
(*bezNodes)++;
|
||||
|
||||
bez = ensureBezStorage(bez, *bezNodes, bezAllocated);
|
||||
bez[*bezNodes].code = ART_END;
|
||||
|
||||
ArtBpath *bez1 = art_new(ArtBpath, *bezNodes + 1);
|
||||
if (!bez1)
|
||||
error("[VectorImage::storeBez] Cannot allocate memory");
|
||||
|
||||
for (int i = 0; i <= *bezNodes; i++)
|
||||
bez1[i] = bez[i];
|
||||
|
||||
_elements.back()._pathInfos.push_back(VectorPathInfo(bez1, *bezNodes, lineStyle, fillStyle0, fillStyle1));
|
||||
|
||||
return bez;
|
||||
}
|
||||
|
||||
bool VectorImage::parseDefineShape(uint shapeType, SWFBitStream &bs) {
|
||||
/*uint32 shapeID = */bs.getUInt16();
|
||||
|
||||
// readout bounding box
|
||||
_boundingBox = flashRectToBSRect(bs);
|
||||
|
||||
// create first image element
|
||||
_elements.resize(1);
|
||||
|
||||
// read styles
|
||||
uint numFillBits;
|
||||
uint numLineBits;
|
||||
if (!parseStyles(shapeType, bs, numFillBits, numLineBits))
|
||||
return false;
|
||||
|
||||
uint lineStyle = 0;
|
||||
uint fillStyle0 = 0;
|
||||
uint fillStyle1 = 0;
|
||||
|
||||
// parse shaperecord
|
||||
// ------------------
|
||||
|
||||
double curX = 0;
|
||||
double curY = 0;
|
||||
int bezNodes = 0;
|
||||
int bezAllocated = 10;
|
||||
ArtBpath *bez = art_new(ArtBpath, bezAllocated);
|
||||
|
||||
bool endOfShapeDiscovered = false;
|
||||
while (!endOfShapeDiscovered) {
|
||||
uint32 typeFlag = bs.getBits(1);
|
||||
|
||||
// Non-Edge Record
|
||||
if (typeFlag == 0) {
|
||||
// Determines which parameters are set
|
||||
uint32 stateNewStyles = bs.getBits(1);
|
||||
uint32 stateLineStyle = bs.getBits(1);
|
||||
uint32 stateFillStyle1 = bs.getBits(1);
|
||||
uint32 stateFillStyle0 = bs.getBits(1);
|
||||
uint32 stateMoveTo = bs.getBits(1);
|
||||
|
||||
uint prevLineStyle = lineStyle;
|
||||
uint prevFillStyle0 = fillStyle0;
|
||||
uint prevFillStyle1 = fillStyle1;
|
||||
|
||||
// End of the shape definition is reached?
|
||||
if (!stateNewStyles && !stateLineStyle && !stateFillStyle0 && !stateFillStyle1 && !stateMoveTo) {
|
||||
endOfShapeDiscovered = true;
|
||||
// Decode parameters
|
||||
} else {
|
||||
if (stateMoveTo) {
|
||||
uint32 moveToBits = bs.getBits(5);
|
||||
curX = bs.getSignedBits(moveToBits);
|
||||
curY = bs.getSignedBits(moveToBits);
|
||||
}
|
||||
|
||||
if (stateFillStyle0) {
|
||||
if (numFillBits > 0)
|
||||
fillStyle0 = bs.getBits(numFillBits);
|
||||
else
|
||||
fillStyle0 = 0;
|
||||
}
|
||||
|
||||
if (stateFillStyle1) {
|
||||
if (numFillBits > 0)
|
||||
fillStyle1 = bs.getBits(numFillBits);
|
||||
else
|
||||
fillStyle1 = 0;
|
||||
}
|
||||
|
||||
if (stateLineStyle) {
|
||||
if (numLineBits)
|
||||
lineStyle = bs.getBits(numLineBits);
|
||||
else
|
||||
numLineBits = 0;
|
||||
}
|
||||
|
||||
// Create a new path, unless there were only defined new styles
|
||||
if (stateLineStyle || stateFillStyle0 || stateFillStyle1 || stateMoveTo) {
|
||||
// Store previous curve if any
|
||||
if (bezNodes) {
|
||||
bez = storeBez(bez, prevLineStyle, prevFillStyle0, prevFillStyle1, &bezNodes, &bezAllocated);
|
||||
}
|
||||
|
||||
// Start new curve
|
||||
bez = ensureBezStorage(bez, 1, &bezAllocated);
|
||||
bez[0].code = ART_MOVETO_OPEN;
|
||||
bez[0].x3 = curX;
|
||||
bez[0].y3 = curY;
|
||||
bezNodes = 0;
|
||||
}
|
||||
|
||||
if (stateNewStyles) {
|
||||
// The old style definitions will be discarded and overwritten with the new at this point in Flash.
|
||||
// A new element will be started with a new element.
|
||||
_elements.resize(_elements.size() + 1);
|
||||
if (!parseStyles(shapeType, bs, numFillBits, numLineBits))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Edge record
|
||||
uint32 edgeFlag = bs.getBits(1);
|
||||
uint32 numBits = bs.getBits(4) + 2;
|
||||
|
||||
// Curved edge
|
||||
if (edgeFlag == 0) {
|
||||
double controlDeltaX = bs.getSignedBits(numBits);
|
||||
double controlDeltaY = bs.getSignedBits(numBits);
|
||||
double anchorDeltaX = bs.getSignedBits(numBits);
|
||||
double anchorDeltaY = bs.getSignedBits(numBits);
|
||||
|
||||
double controlX = curX + controlDeltaX;
|
||||
double controlY = curY + controlDeltaY;
|
||||
double newX = controlX + anchorDeltaX;
|
||||
double newY = controlY + anchorDeltaY;
|
||||
|
||||
#define WEIGHT (2.0/3.0)
|
||||
|
||||
bezNodes++;
|
||||
bez = ensureBezStorage(bez, bezNodes, &bezAllocated);
|
||||
bez[bezNodes].code = ART_CURVETO;
|
||||
bez[bezNodes].x1 = WEIGHT * controlX + (1 - WEIGHT) * curX;
|
||||
bez[bezNodes].y1 = WEIGHT * controlY + (1 - WEIGHT) * curY;
|
||||
bez[bezNodes].x2 = WEIGHT * controlX + (1 - WEIGHT) * newX;
|
||||
bez[bezNodes].y2 = WEIGHT * controlY + (1 - WEIGHT) * newY;
|
||||
bez[bezNodes].x3 = newX;
|
||||
bez[bezNodes].y3 = newY;
|
||||
|
||||
curX = newX;
|
||||
curY = newY;
|
||||
} else {
|
||||
// Staight edge
|
||||
int32 deltaX = 0;
|
||||
int32 deltaY = 0;
|
||||
|
||||
uint32 generalLineFlag = bs.getBits(1);
|
||||
if (generalLineFlag) {
|
||||
deltaX = bs.getSignedBits(numBits);
|
||||
deltaY = bs.getSignedBits(numBits);
|
||||
} else {
|
||||
uint32 vertLineFlag = bs.getBits(1);
|
||||
if (vertLineFlag)
|
||||
deltaY = bs.getSignedBits(numBits);
|
||||
else
|
||||
deltaX = bs.getSignedBits(numBits);
|
||||
}
|
||||
|
||||
curX += deltaX;
|
||||
curY += deltaY;
|
||||
|
||||
bezNodes++;
|
||||
bez = ensureBezStorage(bez, bezNodes, &bezAllocated);
|
||||
bez[bezNodes].code = ART_LINETO;
|
||||
bez[bezNodes].x3 = curX;
|
||||
bez[bezNodes].y3 = curY;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Store last curve
|
||||
if (bezNodes)
|
||||
bez = storeBez(bez, lineStyle, fillStyle0, fillStyle1, &bezNodes, &bezAllocated);
|
||||
|
||||
free(bez);
|
||||
|
||||
// Calculate the bounding boxes of each element
|
||||
Common::Array<VectorImageElement>::iterator it = _elements.begin();
|
||||
for (; it != _elements.end(); ++it)
|
||||
it->_boundingBox = CalculateBoundingBox(*it);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
bool VectorImage::parseStyles(uint shapeType, SWFBitStream &bs, uint &numFillBits, uint &numLineBits) {
|
||||
bs.flushByte();
|
||||
|
||||
// Parse fill styles
|
||||
// -----------------
|
||||
|
||||
// Determine number of fill styles
|
||||
uint fillStyleCount = bs.getByte();
|
||||
if (fillStyleCount == 0xff)
|
||||
fillStyleCount = bs.getUInt16();
|
||||
|
||||
// Readout all fill styles. If a fill style with Typ != 0 is found, the parsing is aborted.
|
||||
// Only "solid fill" (Typ 0) is supported.
|
||||
_elements.back()._fillStyles.reserve(fillStyleCount);
|
||||
for (uint i = 0; i < fillStyleCount; ++i) {
|
||||
byte type = bs.getByte();
|
||||
uint32 color;
|
||||
byte r = bs.getByte();
|
||||
byte g = bs.getByte();
|
||||
byte b = bs.getByte();
|
||||
byte a = 0xff;
|
||||
|
||||
if (shapeType == 3)
|
||||
a = bs.getByte();
|
||||
|
||||
color = BS_ARGB(a, r, g, b);
|
||||
|
||||
if (type != 0)
|
||||
return false;
|
||||
|
||||
_elements.back()._fillStyles.push_back(color);
|
||||
}
|
||||
|
||||
// Line styles parsen
|
||||
// -----------------
|
||||
|
||||
// Determine number of line styles
|
||||
uint lineStyleCount = bs.getByte();
|
||||
if (lineStyleCount == 0xff)
|
||||
lineStyleCount = bs.getUInt16();
|
||||
|
||||
// Readout all line styles
|
||||
_elements.back()._lineStyles.reserve(lineStyleCount);
|
||||
for (uint i = 0; i < lineStyleCount; ++i) {
|
||||
double width = bs.getUInt16();
|
||||
uint32 color;
|
||||
byte r = bs.getByte();
|
||||
byte g = bs.getByte();
|
||||
byte b = bs.getByte();
|
||||
byte a = 0xff;
|
||||
|
||||
if (shapeType == 3)
|
||||
a = bs.getByte();
|
||||
|
||||
color = BS_ARGB(a, r, g, b);
|
||||
|
||||
_elements.back()._lineStyles.push_back(VectorImageElement::LineStyleType(width, color));
|
||||
}
|
||||
|
||||
// Readout the bit width for the following style indices
|
||||
numFillBits = bs.getBits(4);
|
||||
numLineBits = bs.getBits(4);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
bool VectorImage::fill(const Common::Rect *pFillRect, uint color) {
|
||||
error("Fill() is not supported.");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
uint VectorImage::getPixel(int x, int y) {
|
||||
error("GetPixel() is not supported. Returning black.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
bool VectorImage::setContent(const byte *pixeldata, uint size, uint offset, uint stride) {
|
||||
error("SetContent() is not supported.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool VectorImage::blit(int posX, int posY,
|
||||
int flipping,
|
||||
Common::Rect *pPartRect,
|
||||
uint color,
|
||||
int width, int height,
|
||||
RectangleList *updateRects) {
|
||||
static VectorImage *oldThis = 0;
|
||||
static int oldWidth = -2;
|
||||
static int oldHeight = -2;
|
||||
|
||||
// If width or height to 0, nothing needs to be shown.
|
||||
if (width == 0 || height == 0)
|
||||
return true;
|
||||
|
||||
// Determine if the old image in the cache can not be reused and must be recalculated
|
||||
if (!(oldThis == this && oldWidth == width && oldHeight == height)) {
|
||||
render(width, height);
|
||||
|
||||
oldThis = this;
|
||||
oldHeight = height;
|
||||
oldWidth = width;
|
||||
}
|
||||
|
||||
RenderedImage *rend = new RenderedImage();
|
||||
|
||||
rend->replaceContent(_pixelData, width, height);
|
||||
rend->blit(posX, posY, flipping, pPartRect, color, width, height, updateRects);
|
||||
|
||||
delete rend;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // End of namespace Sword25
|
||||
Reference in New Issue
Block a user