diff options
Diffstat (limited to 'graphics')
-rw-r--r-- | graphics/VectorRenderer.h | 11 | ||||
-rw-r--r-- | graphics/cursorman.cpp | 6 | ||||
-rw-r--r-- | graphics/cursorman.h | 27 | ||||
-rw-r--r-- | graphics/iff.cpp | 258 | ||||
-rw-r--r-- | graphics/iff.h | 101 |
5 files changed, 222 insertions, 181 deletions
diff --git a/graphics/VectorRenderer.h b/graphics/VectorRenderer.h index acc2f77357..136a8d55b3 100644 --- a/graphics/VectorRenderer.h +++ b/graphics/VectorRenderer.h @@ -37,6 +37,10 @@ namespace Graphics { class VectorRenderer; + +typedef void (VectorRenderer::*DrawingFunctionCallback)(const Common::Rect &, const Graphics::DrawStep &); + + struct DrawStep { struct Color { uint8 r, g, b; @@ -59,7 +63,10 @@ struct DrawStep { kVectorAlignBottom, kVectorAlignTop, kVectorAlignCenter - } xAlign, yAlign; + }; + + VectorAlignment xAlign; + VectorAlignment yAlign; uint8 shadow, stroke, factor, radius, bevel; /**< Misc options... */ @@ -68,7 +75,7 @@ struct DrawStep { uint32 scale; /**< scale of all the coordinates in FIXED POINT with 16 bits mantissa */ - void (VectorRenderer::*drawingCall)(const Common::Rect &, const DrawStep &); /** Pointer to drawing function */ + DrawingFunctionCallback drawingCall; /**< Pointer to drawing function */ Graphics::Surface *blitSrc; }; diff --git a/graphics/cursorman.cpp b/graphics/cursorman.cpp index fe5f653b94..2e71b548bc 100644 --- a/graphics/cursorman.cpp +++ b/graphics/cursorman.cpp @@ -129,6 +129,10 @@ void CursorManager::replaceCursor(const byte *buf, uint w, uint h, int hotspotX, g_system->setMouseCursor(cur->_data, w, h, hotspotX, hotspotY, keycolor, targetScale); } +bool CursorManager::supportsCursorPalettes() { + return g_system->hasFeature(OSystem::kFeatureCursorHasPalette); +} + void CursorManager::disableCursorPalette(bool disable) { if (!g_system->hasFeature(OSystem::kFeatureCursorHasPalette)) return; @@ -139,7 +143,7 @@ void CursorManager::disableCursorPalette(bool disable) { Palette *pal = _cursorPaletteStack.top(); pal->_disabled = disable; - g_system->disableCursorPalette(true); + g_system->disableCursorPalette(disable); } void CursorManager::pushCursorPalette(const byte *colors, uint start, uint num) { diff --git a/graphics/cursorman.h b/graphics/cursorman.h index bc38466eda..f019e37b04 100644 --- a/graphics/cursorman.h +++ b/graphics/cursorman.h @@ -36,7 +36,21 @@ public: /** Query whether the mouse cursor is visible. */ bool isVisible(); - /** Show or hide the mouse cursor. */ + /** + * Show or hide the mouse cursor. + * + * This function does not call OSystem::updateScreen, when visible is true. + * This fact might result in a non visible mouse cursor if the caller does + * not call OSystem::updateScreen itself after a showMouse(true) call. + * + * TODO: We might want to reconsider this behavior, it might be confusing + * for the user to call OSystem::updateScreen separately, on the other + * hand OSystem::updateScreen might as well display unwanted changes on + * the screen. Another alternative would be to let the backend worry + * about this on OSystem::showMouse call. + * + * @see OSystem::showMouse. + */ bool showMouse(bool visible); /** @@ -88,6 +102,17 @@ public: void popAllCursors(); /** + * Test whether cursor palettes are supported. + * + * This is just an convenience wrapper for checking for + * OSystem::kFeatureCursorHasPalette to be supported by OSystem. + * + * @see OSystem::kFeatureCursorHasPalette + * @see OSystem::hasFeature + */ + bool supportsCursorPalettes(); + + /** * Enable/Disable the current cursor palette. * * @param disable diff --git a/graphics/iff.cpp b/graphics/iff.cpp index ea6447ac01..902f97499a 100644 --- a/graphics/iff.cpp +++ b/graphics/iff.cpp @@ -48,194 +48,179 @@ char *ID2string(Common::IFF_ID id) { namespace Graphics { - -void fillBMHD(BMHD &bitmapHeader, Common::ReadStream &stream) { - - bitmapHeader.width = stream.readUint16BE(); - bitmapHeader.height = stream.readUint16BE(); - bitmapHeader.x = stream.readUint16BE(); - bitmapHeader.y = stream.readUint16BE(); - bitmapHeader.depth = stream.readByte(); - bitmapHeader.masking = stream.readByte(); - bitmapHeader.pack = stream.readByte(); - bitmapHeader.flags = stream.readByte(); - bitmapHeader.transparentColor = stream.readUint16BE(); - bitmapHeader.xAspect = stream.readByte(); - bitmapHeader.yAspect = stream.readByte(); - bitmapHeader.pageWidth = stream.readUint16BE(); - bitmapHeader.pageHeight = stream.readUint16BE(); - +void BMHD::load(Common::ReadStream *stream) { + assert(stream); + stream->read(this, sizeof(BMHD)); + width = FROM_BE_16(width); + height = FROM_BE_16(height); + x = FROM_BE_16(x); + y = FROM_BE_16(y); + transparentColor = FROM_BE_16(transparentColor); + pageWidth = FROM_BE_16(pageWidth); + pageHeight = FROM_BE_16(pageHeight); } -ILBMDecoder::ILBMDecoder(Common::ReadStream &input, Surface &surface, byte *&colors) : IFFParser(input), _surface(&surface), _colors(&colors) { - if (_typeId != ID_ILBM) - error("unsupported IFF subtype '%s'", Common::ID2string(_typeId)); +void ILBMDecoder::loadHeader(Common::ReadStream *stream) { + _header.load(stream); } -void ILBMDecoder::decode() { - - Common::IFFChunk *chunk; - while ((chunk = nextChunk()) != 0) { - switch (chunk->id) { - case ID_BMHD: - readBMHD(*chunk); - break; +void ILBMDecoder::loadBitmap(uint32 mode, byte *buffer, Common::ReadStream *stream) { + assert(stream); + uint32 numPlanes = MIN(mode & ILBM_UNPACK_PLANES, (uint32)_header.depth); + assert(numPlanes == 1 || numPlanes == 2 || numPlanes == 3 || numPlanes == 4 || numPlanes == 5 || numPlanes == 8); - case ID_CMAP: - readCMAP(*chunk); - break; - - case ID_BODY: - readBODY(*chunk); - break; - } + bool packPixels = (mode & ILBM_PACK_PLANES) != 0; + if (numPlanes != 1 && numPlanes != 2 && numPlanes != 4) { + packPixels = false; } - return; -} + uint32 outPitch = _header.width; + if (packPixels) { + outPitch /= (8 / numPlanes); + } + byte *out = buffer; -void ILBMDecoder::readBMHD(Common::IFFChunk &chunk) { + switch (_header.pack) { + case 1: { // PackBits compressed bitmap + Graphics::PackBitsReadStream packStream(*stream); - fillBMHD(_bitmapHeader, chunk); + // setup a buffer to hold enough data to build a line in the output + uint32 scanlineWidth = ((_header.width + 15)/16) << 1; + byte *scanline = new byte[scanlineWidth * _header.depth]; - _colorCount = 1 << _bitmapHeader.depth; - *_colors = (byte*)malloc(sizeof(**_colors) * _colorCount * 3); - _surface->create(_bitmapHeader.width, _bitmapHeader.height, 1); + for (uint i = 0; i < _header.height; ++i) { + byte *s = scanline; + for (uint32 j = 0; j < _header.depth; ++j) { + packStream.read(s, scanlineWidth); + s += scanlineWidth; + } -} + planarToChunky(out, outPitch, scanline, scanlineWidth, numPlanes, packPixels); + out += outPitch; + } -void ILBMDecoder::readCMAP(Common::IFFChunk &chunk) { - if (*_colors == NULL) { - error("wrong input chunk sequence"); + delete []scanline; + break; } - for (uint32 i = 0; i < _colorCount; i++) { - (*_colors)[i * 3 + 0] = chunk.readByte(); - (*_colors)[i * 3 + 1] = chunk.readByte(); - (*_colors)[i * 3 + 2] = chunk.readByte(); + + default: + // implement other compression types here! + error("only RLE compressed ILBM files are supported"); + break; } } -void ILBMDecoder::readBODY(Common::IFFChunk& chunk) { +void ILBMDecoder::planarToChunky(byte *out, uint32 outPitch, byte *in, uint32 inWidth, uint32 nPlanes, bool packPlanes) { + byte pix, ofs, bit; + byte *s; - switch (_bitmapHeader.pack) { - case 0: - error("unpacked ILBM files are not supported"); - break; + uint32 pixels = outPitch; + if (packPlanes) { + pixels *= (8 / nPlanes); + } - case 1: { - uint32 scanWidth = (_bitmapHeader.width + 7) >> 3; - byte *scan = (byte*)malloc(scanWidth); - byte *out = (byte*)_surface->pixels; + for (uint32 x = 0; x < pixels; ++x) { - PackBitsReadStream stream(chunk); + pix = 0; + ofs = x >> 3; + bit = 0x80 >> (x & 7); - for (uint32 i = 0; i < _bitmapHeader.height; i++) { - for (uint32 j = 0; j < _bitmapHeader.depth; j++) { - stream.read(scan, scanWidth); - fillPlane(out, scan, scanWidth, j); + // first build a pixel by scanning all the usable planes in the input + s = in; + for (uint32 plane = 0; plane < nPlanes; ++plane) { + if (s[ofs] & bit) { + pix |= (1 << plane); } - - out += _bitmapHeader.width; + s += inWidth; } - free(scan); - break; - } - - } -} -void ILBMDecoder::fillPlane(byte *out, byte* buf, uint32 width, uint32 plane) { - byte src, idx, set; - byte mask = 1 << plane; - - for (uint32 j = 0; j < _bitmapHeader.width; j++) { - src = buf[j >> 3]; - idx = 7 - (j & 7); - set = src & (1 << idx); - - if (set) - out[j] |= mask; + // then output the pixel according to the requested packing + if (!packPlanes) { + out[x] = pix; + } else + if (nPlanes == 1) { + out[x/8] |= (pix << (x & 7)); + } else + if (nPlanes == 2) { + out[x/4] |= (pix << ((x & 3) << 1)); + } else + if (nPlanes == 4) { + out[x/2] |= (pix << ((x & 1) << 2)); + } } } - - -PBMDecoder::PBMDecoder(Common::ReadStream &input, Surface &surface, byte *&colors) : IFFParser(input), _surface(&surface), _colors(&colors) { - if (_typeId != ID_PBM) - error("unsupported IFF subtype '%s'", Common::ID2string(_typeId)); +void PBMDecoder::loadHeader(Common::ReadStream *stream) { + _header.load(stream); } -void PBMDecoder::decode() { - Common::IFFChunk *chunk; - while ((chunk = nextChunk()) != 0) { - switch (chunk->id) { - case ID_BMHD: - readBMHD(*chunk); - break; +void PBMDecoder::loadBitmap(byte *buffer, Common::ReadStream *stream) { + uint32 outSize = _header.width * _header.height; - case ID_CMAP: - readCMAP(*chunk); - break; + switch (_header.pack) { + case 0: + stream->read(buffer, outSize); + break; - case ID_BODY: - readBODY(*chunk); - break; + case 1: { + PackBitsReadStream packStream(*stream); + packStream.read(buffer, outSize); + break; } } - - return; } -void PBMDecoder::readBMHD(Common::IFFChunk &chunk) { - fillBMHD(_bitmapHeader, chunk); +struct PBMLoader { + PBMDecoder _decoder; + Surface *_surface; + byte *_colors; - _colorCount = 1 << _bitmapHeader.depth; - *_colors = (byte*)malloc(sizeof(**_colors) * _colorCount * 3); - _surface->create(_bitmapHeader.width, _bitmapHeader.height, 1); - -} - -void PBMDecoder::readCMAP(Common::IFFChunk &chunk) { - if (*_colors == NULL) { - error("wrong input chunk sequence"); - } - for (uint32 i = 0; i < _colorCount; i++) { - (*_colors)[i * 3 + 0] = chunk.readByte(); - (*_colors)[i * 3 + 1] = chunk.readByte(); - (*_colors)[i * 3 + 2] = chunk.readByte(); + void load(Common::ReadStream &input, Surface &surface, byte *&colors) { + _surface = &surface; + _colors = colors; + Common::IFFParser parser(&input); + Common::Functor1Mem< Common::IFFChunk&, bool, PBMLoader > c(this, &PBMLoader::callback); + parser.parse(c); } -} -void PBMDecoder::readBODY(Common::IFFChunk& chunk) { + bool callback(Common::IFFChunk &chunk) { + switch (chunk._type) { + case ID_BMHD: + _decoder.loadHeader(chunk._stream); + break; - uint si = 0; + case ID_CMAP: + if (_colors) { + chunk._stream->read(_colors, chunk._size); + } + break; - switch (_bitmapHeader.pack) { - case 0: - while (!chunk.hasReadAll()) { - ((byte*)_surface->pixels)[si++] = chunk.readByte(); + case ID_BODY: + if (_surface) { + _surface->create(_decoder._header.width, _decoder._header.height, 1); + _decoder.loadBitmap((byte*)_surface->pixels, chunk._stream); + } + return true; // stop the parser } - break; - case 1: { - PackBitsReadStream stream(chunk); - stream.read((byte*)_surface->pixels, _surface->w * _surface->h); - break; + return false; } +}; - } +void decodePBM(Common::ReadStream &input, Surface &surface, byte *colors) { + PBMLoader loader; + loader.load(input, surface, colors); } - PackBitsReadStream::PackBitsReadStream(Common::ReadStream &input) : _input(&input) { } @@ -282,9 +267,4 @@ uint32 PackBitsReadStream::read(void *dataPtr, uint32 dataSize) { } -void decodePBM(Common::ReadStream &input, Surface &surface, byte *&colors) { - PBMDecoder decoder(input, surface, colors); - decoder.decode(); -} - } diff --git a/graphics/iff.h b/graphics/iff.h index 13b82a673c..fc1b6ceefa 100644 --- a/graphics/iff.h +++ b/graphics/iff.h @@ -52,55 +52,80 @@ struct BMHD { BMHD() { memset(this, 0, sizeof(*this)); } -}; - -// handles ILBM subtype of IFF FORM files -// -class ILBMDecoder : public Common::IFFParser { + void load(Common::ReadStream *stream); +}; -protected: - void readBMHD(Common::IFFChunk &chunk); - void readCMAP(Common::IFFChunk &chunk); - void readBODY(Common::IFFChunk &chunk); - BMHD _bitmapHeader; - uint32 _colorCount; +struct ILBMDecoder { + /** + * ILBM header data, necessary for loadBitmap() + */ + Graphics::BMHD _header; + + /** + * Available decoding modes for loadBitmap(). + */ + enum { + ILBM_UNPACK_PLANES = 0xFF, //!< Decode all bitplanes, and map 1 pixel to 1 byte. + ILBM_PACK_PLANES = 0x100, //!< Request unpacking, used as a mask with below options. + + ILBM_1_PLANES = 1, //!< Decode only the first bitplane, don't pack. + ILBM_1_PACK_PLANES = ILBM_1_PLANES | ILBM_PACK_PLANES, //!< Decode only the first bitplane, pack 8 pixels in 1 byte. + ILBM_2_PLANES = 2, //!< Decode first 2 bitplanes, don't pack. + ILBM_2_PACK_PLANES = ILBM_2_PLANES | ILBM_PACK_PLANES, //!< Decode first 2 bitplanes, pack 4 pixels in 1 byte. + ILBM_3_PLANES = 3, //!< Decode first 3 bitplanes, don't pack. + ILBM_4_PLANES = 4, //!< Decode first 4 bitplanes, don't pack. + ILBM_4_PACK_PLANES = ILBM_4_PLANES | ILBM_PACK_PLANES, //!< Decode first 4 bitplanes, pack 2 pixels in 1 byte. + ILBM_5_PLANES = 5, //!< Decode first 5 bitplanes, don't pack. + ILBM_8_PLANES = 8 //!< Decode all 8 bitplanes. + }; + + /** + * Fills the _header member from the given stream. + */ + void loadHeader(Common::ReadStream *stream); + + /** + * Loads and unpacks the ILBM bitmap data from the stream into the buffer. + * The functions assumes the buffer is large enough to contain all data. + * The caller controls how data should be packed by choosing mode from + * the enum above. + */ + void loadBitmap(uint32 mode, byte *buffer, Common::ReadStream *stream); + + /** + * Converts from bitplanar to chunky representation. Intended for internal + * usage, but you can be (ab)use it from client code if you know what you + * are doing. + */ + void planarToChunky(byte *out, uint32 width, byte *in, uint32 planeWidth, uint32 nPlanes, bool packPlanes); +}; - Surface *_surface; - byte **_colors; - void fillPlane(byte *out, byte* buf, uint32 width, uint32 plane); - -public: - ILBMDecoder(Common::ReadStream &input, Surface &surface, byte *&colors); - virtual ~ILBMDecoder() { } - void decode(); -}; // handles PBM subtype of IFF FORM files // -class PBMDecoder : public Common::IFFParser { - -protected: - void readBMHD(Common::IFFChunk &chunk); - void readCMAP(Common::IFFChunk &chunk); - void readBODY(Common::IFFChunk &chunk); - - BMHD _bitmapHeader; - uint32 _colorCount; - - Surface *_surface; - byte **_colors; - -public: - PBMDecoder(Common::ReadStream &input, Surface &surface, byte *&colors); - virtual ~PBMDecoder() { } - void decode(); +struct PBMDecoder { + /** + * PBM header data, necessary for loadBitmap() + */ + Graphics::BMHD _header; + + /** + * Fills the _header member from the given stream. + */ + void loadHeader(Common::ReadStream *stream); + + /** + * Loads and unpacks the PBM bitmap data from the stream into the buffer. + * The functions assumes the buffer is large enough to contain all data. + */ + void loadBitmap(byte *buffer, Common::ReadStream *stream); }; -void decodePBM(Common::ReadStream &input, Surface &surface, byte *&colors); +void decodePBM(Common::ReadStream &input, Surface &surface, byte *colors); /* |