diff options
Diffstat (limited to 'graphics')
35 files changed, 699 insertions, 186 deletions
diff --git a/graphics/VectorRenderer.cpp b/graphics/VectorRenderer.cpp index 0237712f13..e3ca0bf588 100644 --- a/graphics/VectorRenderer.cpp +++ b/graphics/VectorRenderer.cpp @@ -23,14 +23,9 @@ * */ +#include "common/textconsole.h" #include "common/util.h" -#include "common/system.h" -#include "common/events.h" -#include "graphics/surface.h" -#include "graphics/colormasks.h" - -#include "gui/ThemeEngine.h" #include "graphics/VectorRenderer.h" #define VECTOR_RENDERER_FAST_TRIANGLES diff --git a/graphics/VectorRenderer.h b/graphics/VectorRenderer.h index 0a783a077d..9285fa21c5 100644 --- a/graphics/VectorRenderer.h +++ b/graphics/VectorRenderer.h @@ -26,16 +26,19 @@ #ifndef VECTOR_RENDERER_H #define VECTOR_RENDERER_H +#include "common/rect.h" #include "common/scummsys.h" -#include "common/system.h" +#include "common/str.h" #include "graphics/surface.h" -#include "graphics/pixelformat.h" #include "gui/ThemeEngine.h" +class OSystem; + namespace Graphics { class VectorRenderer; +struct DrawStep; typedef void (VectorRenderer::*DrawingFunctionCallback)(const Common::Rect &, const Graphics::DrawStep &); diff --git a/graphics/VectorRendererSpec.cpp b/graphics/VectorRendererSpec.cpp index 0ee13033af..3eb8b1345f 100644 --- a/graphics/VectorRendererSpec.cpp +++ b/graphics/VectorRendererSpec.cpp @@ -25,7 +25,6 @@ #include "common/util.h" #include "common/system.h" -#include "common/events.h" #include "common/frac.h" #include "graphics/surface.h" @@ -277,7 +276,7 @@ copyFrame(OSystem *sys, const Common::Rect &r) { sys->copyRectToOverlay( (const OverlayColor *)_activeSurface->getBasePtr(r.left, r.top), - _activeSurface->pitch / _activeSurface->bytesPerPixel, + _activeSurface->pitch / _activeSurface->format.bytesPerPixel, r.left, r.top, r.width(), r.height() ); } @@ -337,8 +336,8 @@ blitAlphaBitmap(const Graphics::Surface *source, const Common::Rect &r) { PixelType *dst_ptr = (PixelType *)_activeSurface->getBasePtr(x, y); const PixelType *src_ptr = (const PixelType *)source->getBasePtr(0, 0); - int dst_pitch = _activeSurface->pitch / _activeSurface->bytesPerPixel; - int src_pitch = source->pitch / source->bytesPerPixel; + int dst_pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel; + int src_pitch = source->pitch / source->format.bytesPerPixel; int w, h = source->h; @@ -485,7 +484,7 @@ drawLine(int x1, int y1, int x2, int y2) { return; PixelType *ptr = (PixelType *)_activeSurface->getBasePtr(x1, y1); - int pitch = _activeSurface->pitch / _activeSurface->bytesPerPixel; + int pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel; int st = Base::_strokeWidth >> 1; if (dy == 0) { // horizontal lines @@ -733,7 +732,7 @@ void VectorRendererSpec<PixelType>:: drawTabAlg(int x1, int y1, int w, int h, int r, PixelType color, VectorRenderer::FillMode fill_m, int baseLeft, int baseRight) { int f, ddF_x, ddF_y; int x, y, px, py; - int pitch = _activeSurface->pitch / _activeSurface->bytesPerPixel; + int pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel; int sw = 0, sp = 0, hp = 0; PixelType *ptr_tl = (PixelType *)Base::_activeSurface->getBasePtr(x1 + r, y1 + r); @@ -831,7 +830,7 @@ drawTabAlg(int x1, int y1, int w, int h, int r, PixelType color, VectorRenderer: template<typename PixelType> void VectorRendererSpec<PixelType>:: drawBevelTabAlg(int x, int y, int w, int h, int bevel, PixelType top_color, PixelType bottom_color, int baseLeft, int baseRight) { - int pitch = _activeSurface->pitch / _activeSurface->bytesPerPixel; + int pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel; int i, j; PixelType *ptr_left = (PixelType *)_activeSurface->getBasePtr(x, y); @@ -876,7 +875,7 @@ template<typename PixelType> void VectorRendererSpec<PixelType>:: drawSquareAlg(int x, int y, int w, int h, PixelType color, VectorRenderer::FillMode fill_m) { PixelType *ptr = (PixelType *)_activeSurface->getBasePtr(x, y); - int pitch = _activeSurface->pitch / _activeSurface->bytesPerPixel; + int pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel; int max_h = h; if (fill_m != kFillDisabled) { @@ -908,7 +907,7 @@ drawSquareAlg(int x, int y, int w, int h, PixelType color, VectorRenderer::FillM template<typename PixelType> void VectorRendererSpec<PixelType>:: drawBevelSquareAlg(int x, int y, int w, int h, int bevel, PixelType top_color, PixelType bottom_color, bool fill) { - int pitch = _activeSurface->pitch / _activeSurface->bytesPerPixel; + int pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel; int height = h; PixelType *ptr_fill = (PixelType *)_activeSurface->getBasePtr(x, y); @@ -965,7 +964,7 @@ template<typename PixelType> void VectorRendererSpec<PixelType>:: drawLineAlg(int x1, int y1, int x2, int y2, int dx, int dy, PixelType color) { PixelType *ptr = (PixelType *)_activeSurface->getBasePtr(x1, y1); - int pitch = _activeSurface->pitch / _activeSurface->bytesPerPixel; + int pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel; int xdir = (x2 > x1) ? 1 : -1; *ptr = (PixelType)color; @@ -1013,7 +1012,7 @@ template<typename PixelType> void VectorRendererSpec<PixelType>:: drawTriangleVertAlg(int x1, int y1, int w, int h, bool inverted, PixelType color, VectorRenderer::FillMode fill_m) { int dx = w >> 1, dy = h, gradient_h = 0; - int pitch = _activeSurface->pitch / _activeSurface->bytesPerPixel; + int pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel; PixelType *ptr_right = 0, *ptr_left = 0; if (inverted) { @@ -1094,7 +1093,7 @@ drawTriangleVertAlg(int x1, int y1, int w, int h, bool inverted, PixelType color template<typename PixelType> void VectorRendererSpec<PixelType>:: drawTriangleFast(int x1, int y1, int size, bool inverted, PixelType color, VectorRenderer::FillMode fill_m) { - int pitch = _activeSurface->pitch / _activeSurface->bytesPerPixel; + int pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel; int hstep = 0, dy = size; bool grad = (fill_m == kFillGradient); @@ -1143,7 +1142,7 @@ void VectorRendererSpec<PixelType>:: drawRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, VectorRenderer::FillMode fill_m) { int f, ddF_x, ddF_y; int x, y, px, py; - int pitch = _activeSurface->pitch / _activeSurface->bytesPerPixel; + int pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel; int sw = 0, sp = 0, hp = h * pitch; PixelType *ptr_tl = (PixelType *)Base::_activeSurface->getBasePtr(x1 + r, y1 + r); @@ -1234,7 +1233,7 @@ void VectorRendererSpec<PixelType>:: drawCircleAlg(int x1, int y1, int r, PixelType color, VectorRenderer::FillMode fill_m) { int f, ddF_x, ddF_y; int x, y, px, py, sw = 0; - int pitch = _activeSurface->pitch / _activeSurface->bytesPerPixel; + int pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel; PixelType *ptr = (PixelType *)Base::_activeSurface->getBasePtr(x1, y1); if (fill_m == kFillDisabled) { @@ -1284,7 +1283,7 @@ template<typename PixelType> void VectorRendererSpec<PixelType>:: drawSquareShadow(int x, int y, int w, int h, int blur) { PixelType *ptr = (PixelType *)_activeSurface->getBasePtr(x + w - 1, y + blur); - int pitch = _activeSurface->pitch / _activeSurface->bytesPerPixel; + int pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel; int i, j; i = h - blur; @@ -1321,7 +1320,7 @@ void VectorRendererSpec<PixelType>:: drawRoundedSquareShadow(int x1, int y1, int r, int w, int h, int blur) { int f, ddF_x, ddF_y; int x, y, px, py; - int pitch = _activeSurface->pitch / _activeSurface->bytesPerPixel; + int pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel; int alpha = 102; x1 += blur; @@ -1368,7 +1367,7 @@ template<typename PixelType> void VectorRendererSpec<PixelType>:: drawRoundedSquareFakeBevel(int x1, int y1, int r, int w, int h, int amount) { int x, y; - const int pitch = _activeSurface->pitch / _activeSurface->bytesPerPixel; + const int pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel; int px, py; int sw = 0, sp = 0; @@ -1438,7 +1437,7 @@ void VectorRendererAA<PixelType>:: drawLineAlg(int x1, int y1, int x2, int y2, int dx, int dy, PixelType color) { PixelType *ptr = (PixelType *)Base::_activeSurface->getBasePtr(x1, y1); - int pitch = Base::_activeSurface->pitch / Base::_activeSurface->bytesPerPixel; + int pitch = Base::_activeSurface->pitch / Base::_activeSurface->format.bytesPerPixel; int xdir = (x2 > x1) ? 1 : -1; uint16 error_tmp, error_acc, gradient; uint8 alpha; @@ -1489,7 +1488,7 @@ template<typename PixelType> void VectorRendererAA<PixelType>:: drawRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, VectorRenderer::FillMode fill_m) { int x, y; - const int pitch = Base::_activeSurface->pitch / Base::_activeSurface->bytesPerPixel; + const int pitch = Base::_activeSurface->pitch / Base::_activeSurface->format.bytesPerPixel; int px, py; int sw = 0, sp = 0, hp = h * pitch; @@ -1566,7 +1565,7 @@ template<typename PixelType> void VectorRendererAA<PixelType>:: drawCircleAlg(int x1, int y1, int r, PixelType color, VectorRenderer::FillMode fill_m) { int x, y, sw = 0; - const int pitch = Base::_activeSurface->pitch / Base::_activeSurface->bytesPerPixel; + const int pitch = Base::_activeSurface->pitch / Base::_activeSurface->format.bytesPerPixel; int px, py; uint32 rsq = r*r; diff --git a/graphics/conversion.cpp b/graphics/conversion.cpp index fee4b05f66..c9679432fa 100644 --- a/graphics/conversion.cpp +++ b/graphics/conversion.cpp @@ -23,6 +23,7 @@ */ #include "graphics/conversion.h" +#include "graphics/pixelformat.h" namespace Graphics { diff --git a/graphics/conversion.h b/graphics/conversion.h index b6d230612e..2759f3bb5e 100644 --- a/graphics/conversion.h +++ b/graphics/conversion.h @@ -27,10 +27,11 @@ #define GRAPHICS_CONVERSION_H #include "common/util.h" -#include "graphics/pixelformat.h" namespace Graphics { +struct PixelFormat; + /** Converting a color from YUV to RGB colorspace. */ inline static void YUV2RGB(byte y, byte u, byte v, byte &r, byte &g, byte &b) { r = CLIP<int>(y + ((1357 * (v - 128)) >> 10), 0, 255); diff --git a/graphics/dither.cpp b/graphics/dither.cpp index 6a37679b0a..5f423d1c7a 100644 --- a/graphics/dither.cpp +++ b/graphics/dither.cpp @@ -174,7 +174,7 @@ bool PaletteLUT::save(Common::WriteStream &stream) { while (_got < _dim1) buildNext(); - stream.writeUint32BE(MKID_BE('PLUT')); // Magic + stream.writeUint32BE(MKTAG('P','L','U','T')); // Magic stream.writeUint32BE(kVersion); stream.writeByte(_depth1); if (stream.write(_realPal, 768) != 768) @@ -200,7 +200,7 @@ bool PaletteLUT::load(Common::SeekableReadStream &stream) { return false; // Magic - if (stream.readUint32BE() != MKID_BE('PLUT')) + if (stream.readUint32BE() != MKTAG('P','L','U','T')) return false; if (stream.readUint32BE() != kVersion) diff --git a/graphics/font.cpp b/graphics/font.cpp index 359374436c..7fa39d07db 100644 --- a/graphics/font.cpp +++ b/graphics/font.cpp @@ -25,7 +25,11 @@ #include "common/stream.h" #include "common/file.h" #include "common/endian.h" +#include "common/array.h" +#include "common/textconsole.h" +#include "common/util.h" #include "graphics/font.h" +#include "graphics/surface.h" namespace Graphics { @@ -74,7 +78,7 @@ void NewFont::drawChar(Surface *dst, byte chr, const int tx, const int ty, const assert(dst != 0); assert(desc.bits != 0 && desc.maxwidth <= 16); - assert(dst->bytesPerPixel == 1 || dst->bytesPerPixel == 2); + assert(dst->format.bytesPerPixel == 1 || dst->format.bytesPerPixel == 2); // If this character is not included in the font, use the default char. if (chr < desc.firstchar || chr >= desc.firstchar + desc.size) { @@ -106,9 +110,9 @@ void NewFont::drawChar(Surface *dst, byte chr, const int tx, const int ty, const tmp += bbh - y; y -= MAX(0, ty + desc.ascent - bby - dst->h); - if (dst->bytesPerPixel == 1) + if (dst->format.bytesPerPixel == 1) drawCharIntern<byte>(ptr, dst->pitch, tmp, y, MAX(0, -(tx + bbx)), MIN(bbw, dst->w - tx - bbx), color); - else if (dst->bytesPerPixel == 2) + else if (dst->format.bytesPerPixel == 2) drawCharIntern<uint16>(ptr, dst->pitch, tmp, y, MAX(0, -(tx + bbx)), MIN(bbw, dst->w - tx - bbx), color); } diff --git a/graphics/font.h b/graphics/font.h index b1a4735249..9e6e180ec3 100644 --- a/graphics/font.h +++ b/graphics/font.h @@ -26,15 +26,16 @@ #define GRAPHICS_FONT_H #include "common/str.h" -#include "common/array.h" -#include "graphics/surface.h" namespace Common { class SeekableReadStream; +template<class T> class Array; } namespace Graphics { +struct Surface; + /** Text alignment modes */ enum TextAlign { kTextAlignInvalid, diff --git a/graphics/fontman.cpp b/graphics/fontman.cpp index 35ea14b199..bbd75bfca2 100644 --- a/graphics/fontman.cpp +++ b/graphics/fontman.cpp @@ -22,6 +22,7 @@ * $Id$ */ +#include "graphics/font.h" #include "graphics/fontman.h" DECLARE_SINGLETON(Graphics::FontManager); diff --git a/graphics/fontman.h b/graphics/fontman.h index 7871f32ba9..34b457ae83 100644 --- a/graphics/fontman.h +++ b/graphics/fontman.h @@ -30,11 +30,12 @@ #include "common/str.h" #include "common/hashmap.h" #include "common/hash-str.h" -#include "graphics/font.h" namespace Graphics { +class Font; + class FontManager : public Common::Singleton<FontManager> { public: enum FontUsage { diff --git a/graphics/fonts/scummfont.cpp b/graphics/fonts/scummfont.cpp index 87078e1475..3331b72c47 100644 --- a/graphics/fonts/scummfont.cpp +++ b/graphics/fonts/scummfont.cpp @@ -23,6 +23,7 @@ */ #include "graphics/font.h" +#include "graphics/surface.h" namespace Graphics { @@ -302,9 +303,9 @@ void ScummFont::drawChar(Surface *dst, byte chr, int tx, int ty, uint32 color) c } c = ((buffer & mask) != 0); if (c) { - if (dst->bytesPerPixel == 1) + if (dst->format.bytesPerPixel == 1) ptr[x] = color; - else if (dst->bytesPerPixel == 2) + else if (dst->format.bytesPerPixel == 2) ((uint16 *)ptr)[x] = color; } } diff --git a/graphics/fonts/winfont.cpp b/graphics/fonts/winfont.cpp index fb37c8ddef..7db9a233f6 100644 --- a/graphics/fonts/winfont.cpp +++ b/graphics/fonts/winfont.cpp @@ -23,8 +23,12 @@ */ #include "common/file.h" -#include "common/ne_exe.h" #include "common/str.h" +#include "common/stream.h" +#include "common/textconsole.h" +#include "common/winexe_ne.h" +#include "common/winexe_pe.h" +#include "graphics/surface.h" #include "graphics/fonts/winfont.h" namespace Graphics { @@ -75,8 +79,15 @@ static WinFontDirEntry readDirEntry(Common::SeekableReadStream &stream) { } bool WinFont::loadFromFON(const Common::String &fileName, const WinFontDirEntry &dirEntry) { - // TODO: PE libraries (If it's used anywhere by a ScummVM game) + // First try loading via the NE code + if (loadFromNE(fileName, dirEntry)) + return true; + // Then try loading via the PE code + return loadFromPE(fileName, dirEntry); +} + +bool WinFont::loadFromNE(const Common::String &fileName, const WinFontDirEntry &dirEntry) { Common::NEResources exe; if (!exe.loadFromEXE(fileName)) @@ -89,44 +100,53 @@ bool WinFont::loadFromFON(const Common::String &fileName, const WinFontDirEntry return false; } - uint16 numFonts = fontDirectory->readUint16LE(); + uint32 fontId = getFontIndex(*fontDirectory, dirEntry); + + delete fontDirectory; - // Probably not possible, so this is really a sanity check - if (numFonts == 0) { - warning("No fonts in '%s'", fileName.c_str()); + // Couldn't match the face name + if (fontId == 0xffffffff) { + warning("Could not find face '%s' in '%s'", dirEntry.faceName.c_str(), fileName.c_str()); return false; } - // Scour the directory for our matching name - int fontId = -1; - for (uint16 i = 0; i < numFonts; i++) { - uint16 id = fontDirectory->readUint16LE(); + // Actually go get our font now... + Common::SeekableReadStream *fontStream = exe.getResource(Common::kNEFont, fontId); + if (!fontStream) { + warning("Could not find font %d in %s", fontId, fileName.c_str()); + return false; + } - if (dirEntry.faceName.empty()) { - // Use the first name when empty - fontId = id; - break; - } + bool ok = loadFromFNT(*fontStream); + delete fontStream; + return ok; +} - WinFontDirEntry entry = readDirEntry(*fontDirectory); +bool WinFont::loadFromPE(const Common::String &fileName, const WinFontDirEntry &dirEntry) { + Common::PEResources exe; - if (dirEntry.faceName.equalsIgnoreCase(entry.faceName) && dirEntry.points == entry.points) { - // Match! - fontId = id; - break; - } + if (!exe.loadFromEXE(fileName)) + return false; + + // Let's pull out the font directory + Common::SeekableReadStream *fontDirectory = exe.getResource(Common::kPEFontDir, Common::String("FONTDIR")); + if (!fontDirectory) { + warning("No font directory in '%s'", fileName.c_str()); + return false; } + uint32 fontId = getFontIndex(*fontDirectory, dirEntry); + delete fontDirectory; // Couldn't match the face name - if (fontId < 0) { + if (fontId == 0xffffffff) { warning("Could not find face '%s' in '%s'", dirEntry.faceName.c_str(), fileName.c_str()); return false; } // Actually go get our font now... - Common::SeekableReadStream *fontStream = exe.getResource(Common::kNEFont, fontId); + Common::SeekableReadStream *fontStream = exe.getResource(Common::kPEFont, fontId); if (!fontStream) { warning("Could not find font %d in %s", fontId, fileName.c_str()); return false; @@ -137,6 +157,32 @@ bool WinFont::loadFromFON(const Common::String &fileName, const WinFontDirEntry return ok; } +uint32 WinFont::getFontIndex(Common::SeekableReadStream &stream, const WinFontDirEntry &dirEntry) { + uint16 numFonts = stream.readUint16LE(); + + // Probably not possible, so this is really a sanity check + if (numFonts == 0) { + warning("No fonts in exe"); + return 0xffffffff; + } + + // Scour the directory for our matching name + for (uint16 i = 0; i < numFonts; i++) { + uint16 id = stream.readUint16LE(); + + // Use the first name when empty + if (dirEntry.faceName.empty()) + return id; + + WinFontDirEntry entry = readDirEntry(stream); + + if (dirEntry.faceName.equalsIgnoreCase(entry.faceName) && dirEntry.points == entry.points) // Match! + return id; + } + + return 0xffffffff; +} + bool WinFont::loadFromFNT(const Common::String &fileName) { Common::File file; @@ -277,7 +323,7 @@ bool WinFont::loadFromFNT(Common::SeekableReadStream &stream) { void WinFont::drawChar(Surface *dst, byte chr, int x, int y, uint32 color) const { assert(dst); - assert(dst->bytesPerPixel == 1 || dst->bytesPerPixel == 2 || dst->bytesPerPixel == 4); + assert(dst->format.bytesPerPixel == 1 || dst->format.bytesPerPixel == 2 || dst->format.bytesPerPixel == 4); assert(_glyphs); GlyphEntry &glyph = _glyphs[characterToIndex(chr)]; @@ -285,11 +331,11 @@ void WinFont::drawChar(Surface *dst, byte chr, int x, int y, uint32 color) const for (uint16 i = 0; i < _pixHeight; i++) { for (uint16 j = 0; j < glyph.charWidth; j++) { if (glyph.bitmap[j + i * glyph.charWidth]) { - if (dst->bytesPerPixel == 1) + if (dst->format.bytesPerPixel == 1) *((byte *)dst->getBasePtr(x + j, y + i)) = color; - else if (dst->bytesPerPixel == 2) + else if (dst->format.bytesPerPixel == 2) *((uint16 *)dst->getBasePtr(x + j, y + i)) = color; - else if (dst->bytesPerPixel == 4) + else if (dst->format.bytesPerPixel == 4) *((uint32 *)dst->getBasePtr(x + j, y + i)) = color; } } diff --git a/graphics/fonts/winfont.h b/graphics/fonts/winfont.h index b23455e2d5..c31d45e2ce 100644 --- a/graphics/fonts/winfont.h +++ b/graphics/fonts/winfont.h @@ -25,11 +25,11 @@ #ifndef GRAPHICS_WINFONT_H #define GRAPHICS_WINFONT_H +#include "common/str.h" #include "graphics/font.h" namespace Common { - class SeekableReadStream; - class String; +class SeekableReadStream; } namespace Graphics { @@ -69,6 +69,10 @@ public: void drawChar(Surface *dst, byte chr, int x, int y, uint32 color) const; private: + bool loadFromPE(const Common::String &fileName, const WinFontDirEntry &dirEntry); + bool loadFromNE(const Common::String &fileName, const WinFontDirEntry &dirEntry); + + uint32 getFontIndex(Common::SeekableReadStream &stream, const WinFontDirEntry &dirEntry); bool loadFromFNT(Common::SeekableReadStream &stream); char indexToCharacter(uint16 index) const; uint16 characterToIndex(byte character) const; diff --git a/graphics/iff.cpp b/graphics/iff.cpp index 2174291112..fee71de485 100644 --- a/graphics/iff.cpp +++ b/graphics/iff.cpp @@ -25,6 +25,10 @@ #include "graphics/iff.h" #include "graphics/surface.h" +#include "common/endian.h" +#include "common/func.h" +#include "common/iff_container.h" +#include "common/textconsole.h" #include "common/util.h" namespace Graphics { @@ -204,7 +208,7 @@ struct PBMLoader { case ID_BODY: if (_surface) { - _surface->create(_decoder._header.width, _decoder._header.height, 1); + _surface->create(_decoder._header.width, _decoder._header.height, PixelFormat::createFormatCLUT8()); _decoder.loadBitmap((byte*)_surface->pixels, chunk._stream); } return true; // stop the parser diff --git a/graphics/iff.h b/graphics/iff.h index 0aab0e09cb..fc837a3ea2 100644 --- a/graphics/iff.h +++ b/graphics/iff.h @@ -31,7 +31,7 @@ #ifndef GRAPHICS_IFF_H #define GRAPHICS_IFF_H -#include "common/iff_container.h" +#include "common/stream.h" namespace Graphics { diff --git a/graphics/imagedec.cpp b/graphics/imagedec.cpp index a4d2fbc1cf..f45f0ce5ef 100644 --- a/graphics/imagedec.cpp +++ b/graphics/imagedec.cpp @@ -23,6 +23,7 @@ */ #include "graphics/imagedec.h" +#include "graphics/pixelformat.h" #include "graphics/surface.h" #include "common/file.h" @@ -117,7 +118,7 @@ Surface *BMPDecoder::decodeImage(Common::SeekableReadStream &stream, const Pixel uint8 r = 0, g = 0, b = 0; Surface *newSurf = new Surface; assert(newSurf); - newSurf->create(info.width, info.height, sizeof(OverlayColor)); + newSurf->create(info.width, info.height, format); assert(newSurf->pixels); OverlayColor *curPixel = (OverlayColor*)newSurf->pixels + (newSurf->h-1) * newSurf->w; int pitchAdd = info.width % 4; diff --git a/graphics/imagedec.h b/graphics/imagedec.h index 13aa63a153..7ea987b1e4 100644 --- a/graphics/imagedec.h +++ b/graphics/imagedec.h @@ -28,14 +28,13 @@ #include "common/scummsys.h" #include "common/str.h" -#include "graphics/pixelformat.h" - namespace Common{ class SeekableReadStream; } namespace Graphics { +struct PixelFormat; struct Surface; class ImageDecoder { diff --git a/graphics/jpeg.cpp b/graphics/jpeg.cpp index aa4b876680..70ffb06f6b 100644 --- a/graphics/jpeg.cpp +++ b/graphics/jpeg.cpp @@ -27,9 +27,10 @@ #include "graphics/jpeg.h" #include "graphics/pixelformat.h" +#include "common/debug.h" #include "common/endian.h" -#include "common/util.h" #include "common/stream.h" +#include "common/textconsole.h" namespace Graphics { @@ -46,7 +47,7 @@ static const uint8 _zigZagOrder[64] = { }; // IDCT table built with : -// _idct8x8[x][y] = cos(((2 * x + 1) * y) * (PI / 16.0)) * 0.5; +// _idct8x8[x][y] = cos(((2 * x + 1) * y) * (M_PI / 16.0)) * 0.5; // _idct8x8[x][y] /= sqrt(2.0) if y == 0 static const double _idct8x8[8][8] = { { 0.353553390593274, 0.490392640201615, 0.461939766255643, 0.415734806151273, 0.353553390593274, 0.277785116509801, 0.191341716182545, 0.097545161008064 }, @@ -95,7 +96,7 @@ Surface *JPEG::getSurface(const PixelFormat &format) { Graphics::Surface *vComponent = getComponent(3); Graphics::Surface *output = new Graphics::Surface(); - output->create(yComponent->w, yComponent->h, format.bytesPerPixel); + output->create(yComponent->w, yComponent->h, format); for (uint16 i = 0; i < output->h; i++) { for (uint16 j = 0; j < output->w; j++) { @@ -226,7 +227,7 @@ bool JPEG::read(Common::SeekableReadStream *stream) { bool JPEG::readJFIF() { uint16 length = _stream->readUint16BE(); uint32 tag = _stream->readUint32BE(); - if (tag != MKID_BE('JFIF')) { + if (tag != MKTAG('J','F','I','F')) { warning("JPEG::readJFIF() tag mismatch"); return false; } @@ -443,7 +444,7 @@ bool JPEG::readSOS() { // Initialize the scan surfaces for (uint16 c = 0; c < _numScanComp; c++) { - _scanComp[c]->surface.create(xMCU * _maxFactorH * 8, yMCU * _maxFactorV * 8, 1); + _scanComp[c]->surface.create(xMCU * _maxFactorH * 8, yMCU * _maxFactorV * 8, PixelFormat::createFormatCLUT8()); } bool ok = true; @@ -710,9 +711,9 @@ uint8 JPEG::readBit() { if (byte2 == 0xDC) { // DNL marker: Define Number of Lines // TODO: terminate scan - printf("DNL marker detected: terminate scan\n"); + warning("DNL marker detected: terminate scan"); } else { - printf("Error: marker 0x%02X read in entropy data\n", byte2); + warning("Error: marker 0x%02X read in entropy data", byte2); } } } diff --git a/graphics/module.mk b/graphics/module.mk index c962f0617d..cb3a07e691 100644 --- a/graphics/module.mk +++ b/graphics/module.mk @@ -23,7 +23,8 @@ MODULE_OBJS := \ surface.o \ thumbnail.o \ VectorRenderer.o \ - VectorRendererSpec.o + VectorRendererSpec.o \ + wincursor.o ifdef USE_SCALERS MODULE_OBJS += \ diff --git a/graphics/palette.h b/graphics/palette.h index 8d7fdbd99a..14e433f153 100644 --- a/graphics/palette.h +++ b/graphics/palette.h @@ -26,6 +26,7 @@ #ifndef GRAPHICS_PALETTE_H #define GRAPHICS_PALETTE_H +#include "common/scummsys.h" #include "common/noncopyable.h" /** diff --git a/graphics/pict.cpp b/graphics/pict.cpp index ca4aac751d..acade48515 100644 --- a/graphics/pict.cpp +++ b/graphics/pict.cpp @@ -23,9 +23,12 @@ * */ +#include "common/debug.h" +#include "common/endian.h" +#include "common/stream.h" #include "common/substream.h" +#include "common/textconsole.h" -#include "graphics/conversion.h" #include "graphics/jpeg.h" #include "graphics/pict.h" #include "graphics/surface.h" @@ -209,7 +212,7 @@ void PictDecoder::decodeDirectBitsRect(Common::SeekableReadStream *stream, bool bytesPerPixel = directBitsData.pixMap.pixelSize / 8; _outputSurface = new Graphics::Surface(); - _outputSurface->create(width, height, (bytesPerPixel == 1) ? 1 : _pixelFormat.bytesPerPixel); + _outputSurface->create(width, height, (bytesPerPixel == 1) ? PixelFormat::createFormatCLUT8() : _pixelFormat); byte *buffer = new byte[width * height * bytesPerPixel]; // Read in amount of data per row diff --git a/graphics/pict.h b/graphics/pict.h index a683a23bf6..22f36aafe7 100644 --- a/graphics/pict.h +++ b/graphics/pict.h @@ -32,7 +32,7 @@ #include "graphics/pixelformat.h" namespace Common { - class SeekableReadStream; +class SeekableReadStream; } namespace Graphics { diff --git a/graphics/png.cpp b/graphics/png.cpp index 5292ea0100..3cdb9f7cca 100644 --- a/graphics/png.cpp +++ b/graphics/png.cpp @@ -23,13 +23,14 @@ * */ -#include "graphics/conversion.h" #include "graphics/png.h" #include "graphics/pixelformat.h" +#include "graphics/surface.h" #include "common/endian.h" #include "common/memstream.h" #include "common/stream.h" +#include "common/types.h" #include "common/util.h" #include "common/zlib.h" @@ -67,12 +68,12 @@ namespace Graphics { enum PNGChunks { // == Critical chunks ===================================================== - kChunkIHDR = MKID_BE('IHDR'), // Image header - kChunkIDAT = MKID_BE('IDAT'), // Image data - kChunkPLTE = MKID_BE('PLTE'), // Palette - kChunkIEND = MKID_BE('IEND'), // Image trailer + kChunkIHDR = MKTAG('I','H','D','R'), // Image header + kChunkIDAT = MKTAG('I','D','A','T'), // Image data + kChunkPLTE = MKTAG('P','L','T','E'), // Palette + kChunkIEND = MKTAG('I','E','N','D'), // Image trailer // == Ancillary chunks ==================================================== - kChunktRNS = MKID_BE('tRNS') // Transparency + kChunktRNS = MKTAG('t','R','N','S') // Transparency // All of the other ancillary chunks are ignored. They're added here for // reference only. // cHRM - Primary chromacities and white point @@ -99,8 +100,6 @@ enum PNGFilters { kFilterPaeth = 4 }; -#define PNG_HEADER(a, b, c, d) CONSTANT_LE_32(d | (c << 8) | (b << 16) | (a << 24)) - PNG::PNG() : _compressedBuffer(0), _compressedBufferSize(0), _unfilteredSurface(0), _transparentColorSpecified(false) { } @@ -114,60 +113,62 @@ PNG::~PNG() { Graphics::Surface *PNG::getSurface(const PixelFormat &format) { Graphics::Surface *output = new Graphics::Surface(); - output->create(_unfilteredSurface->w, _unfilteredSurface->h, format.bytesPerPixel); + output->create(_unfilteredSurface->w, _unfilteredSurface->h, format); byte *src = (byte *)_unfilteredSurface->pixels; byte a = 0xFF; if (_header.colorType != kIndexed) { if (_header.colorType == kTrueColor || _header.colorType == kTrueColorWithAlpha) { - if (_unfilteredSurface->bytesPerPixel != 3 && _unfilteredSurface->bytesPerPixel != 4) + if (_unfilteredSurface->format.bytesPerPixel != 3 && _unfilteredSurface->format.bytesPerPixel != 4) error("Unsupported truecolor PNG format"); } else if (_header.colorType == kGrayScale || _header.colorType == kGrayScaleWithAlpha) { - if (_unfilteredSurface->bytesPerPixel != 1 && _unfilteredSurface->bytesPerPixel != 2) + if (_unfilteredSurface->format.bytesPerPixel != 1 && _unfilteredSurface->format.bytesPerPixel != 2) error("Unsupported grayscale PNG format"); } for (uint16 i = 0; i < output->h; i++) { for (uint16 j = 0; j < output->w; j++) { - if (format.bytesPerPixel == 2) { - if (_unfilteredSurface->bytesPerPixel == 1) { // Grayscale + if (format.bytesPerPixel == 2) { // 2bpp + uint16 *dest = ((uint16 *)output->getBasePtr(j, i)); + if (_unfilteredSurface->format.bytesPerPixel == 1) { // Grayscale if (_transparentColorSpecified) a = (src[0] == _transparentColor[0]) ? 0 : 0xFF; - *((uint16 *)output->getBasePtr(j, i)) = format.ARGBToColor( a, src[0], src[0], src[0]); - } else if (_unfilteredSurface->bytesPerPixel == 2) { // Grayscale + alpha - *((uint16 *)output->getBasePtr(j, i)) = format.ARGBToColor(src[1], src[0], src[0], src[0]); - } else if (_unfilteredSurface->bytesPerPixel == 3) { // RGB + *dest = format.ARGBToColor( a, src[0], src[0], src[0]); + } else if (_unfilteredSurface->format.bytesPerPixel == 2) { // Grayscale + alpha + *dest = format.ARGBToColor(src[1], src[0], src[0], src[0]); + } else if (_unfilteredSurface->format.bytesPerPixel == 3) { // RGB if (_transparentColorSpecified) { bool isTransparentColor = (src[0] == _transparentColor[0] && src[1] == _transparentColor[1] && src[2] == _transparentColor[2]); a = isTransparentColor ? 0 : 0xFF; } - *((uint16 *)output->getBasePtr(j, i)) = format.ARGBToColor( a, src[0], src[1], src[2]); - } else if (_unfilteredSurface->bytesPerPixel == 4) { // RGBA - *((uint16 *)output->getBasePtr(j, i)) = format.ARGBToColor(src[3], src[0], src[1], src[2]); + *dest = format.ARGBToColor( a, src[0], src[1], src[2]); + } else if (_unfilteredSurface->format.bytesPerPixel == 4) { // RGBA + *dest = format.ARGBToColor(src[3], src[0], src[1], src[2]); } - } else { - if (_unfilteredSurface->bytesPerPixel == 1) { // Grayscale + } else { // 4bpp + uint32 *dest = ((uint32 *)output->getBasePtr(j, i)); + if (_unfilteredSurface->format.bytesPerPixel == 1) { // Grayscale if (_transparentColorSpecified) a = (src[0] == _transparentColor[0]) ? 0 : 0xFF; - *((uint32 *)output->getBasePtr(j, i)) = format.ARGBToColor( a, src[0], src[0], src[0]); - } else if (_unfilteredSurface->bytesPerPixel == 2) { // Grayscale + alpha - *((uint32 *)output->getBasePtr(j, i)) = format.ARGBToColor(src[1], src[0], src[0], src[0]); - } else if (_unfilteredSurface->bytesPerPixel == 3) { // RGB + *dest = format.ARGBToColor( a, src[0], src[0], src[0]); + } else if (_unfilteredSurface->format.bytesPerPixel == 2) { // Grayscale + alpha + *dest = format.ARGBToColor(src[1], src[0], src[0], src[0]); + } else if (_unfilteredSurface->format.bytesPerPixel == 3) { // RGB if (_transparentColorSpecified) { bool isTransparentColor = (src[0] == _transparentColor[0] && src[1] == _transparentColor[1] && src[2] == _transparentColor[2]); a = isTransparentColor ? 0 : 0xFF; } - *((uint32 *)output->getBasePtr(j, i)) = format.ARGBToColor( a, src[0], src[1], src[2]); - } else if (_unfilteredSurface->bytesPerPixel == 4) { // RGBA - *((uint32 *)output->getBasePtr(j, i)) = format.ARGBToColor(src[3], src[0], src[1], src[2]); + *dest = format.ARGBToColor( a, src[0], src[1], src[2]); + } else if (_unfilteredSurface->format.bytesPerPixel == 4) { // RGBA + *dest = format.ARGBToColor(src[3], src[0], src[1], src[2]); } } - src += _unfilteredSurface->bytesPerPixel; + src += _unfilteredSurface->format.bytesPerPixel; } } } else { @@ -175,8 +176,16 @@ Graphics::Surface *PNG::getSurface(const PixelFormat &format) { // Convert the indexed surface to the target pixel format for (uint16 i = 0; i < output->h; i++) { + bool otherPixel = false; + for (uint16 j = 0; j < output->w; j++) { - index = *src; + if (_header.bitDepth != 4) + index = *src; + else if (!otherPixel) + index = (*src) >> 4; + else + index = (*src) & 0xf; + r = _palette[index * 4 + 0]; g = _palette[index * 4 + 1]; b = _palette[index * 4 + 2]; @@ -187,8 +196,13 @@ Graphics::Surface *PNG::getSurface(const PixelFormat &format) { else *((uint32 *)output->getBasePtr(j, i)) = format.ARGBToColor(a, r, g, b); - src++; + if (_header.bitDepth != 4 || otherPixel) + src++; + otherPixel = !otherPixel; } + // The surface is a whole scanline wide, skip the rest of it. + if (_header.bitDepth == 4) + src += output->w / 2; } } @@ -200,11 +214,11 @@ bool PNG::read(Common::SeekableReadStream *str) { _stream = str; // First, check the PNG signature - if (_stream->readUint32BE() != PNG_HEADER(0x89, 0x50, 0x4e, 0x47)) { + if (_stream->readUint32BE() != MKTAG(0x89, 0x50, 0x4e, 0x47)) { delete _stream; return false; } - if (_stream->readUint32BE() != PNG_HEADER(0x0d, 0x0a, 0x1a, 0x0a)) { + if (_stream->readUint32BE() != MKTAG(0x0d, 0x0a, 0x1a, 0x0a)) { delete _stream; return false; } @@ -377,7 +391,8 @@ void PNG::constructImage() { delete _unfilteredSurface; } _unfilteredSurface = new Graphics::Surface(); - _unfilteredSurface->create(_header.width, _header.height, (getNumColorChannels() * _header.bitDepth + 7) / 8); + // TODO/FIXME: It seems we can not properly determine the format here. But maybe there is a way... + _unfilteredSurface->create(_header.width, _header.height, PixelFormat((getNumColorChannels() * _header.bitDepth + 7) / 8, 0, 0, 0, 0, 0, 0, 0, 0)); scanLine = new byte[_unfilteredSurface->pitch]; dest = (byte *)_unfilteredSurface->getBasePtr(0, 0); @@ -386,7 +401,7 @@ void PNG::constructImage() { for (uint16 y = 0; y < _unfilteredSurface->h; y++) { filterType = _imageData->readByte(); _imageData->read(scanLine, scanLineWidth); - unfilterScanLine(dest, scanLine, prevLine, _unfilteredSurface->bytesPerPixel, filterType, scanLineWidth); + unfilterScanLine(dest, scanLine, prevLine, _unfilteredSurface->format.bytesPerPixel, filterType, scanLineWidth); prevLine = dest; dest += _unfilteredSurface->pitch; } diff --git a/graphics/png.h b/graphics/png.h index 70f2e4ba27..21e0f35be1 100644 --- a/graphics/png.h +++ b/graphics/png.h @@ -31,8 +31,6 @@ #ifndef GRAPHICS_PNG_H #define GRAPHICS_PNG_H -#include "graphics/surface.h" - // PNG decoder, based on the W3C specs: // http://www.w3.org/TR/PNG/ // Parts of the code have been adapted from LodePNG, by Lode Vandevenne: @@ -54,12 +52,17 @@ // is a bit unclear. For now, these won't be supported, until a suitable sample // is found. +#include "common/scummsys.h" +#include "common/textconsole.h" + namespace Common { class SeekableReadStream; } namespace Graphics { +struct Surface; + enum PNGColorType { kGrayScale = 0, // bit depths: 1, 2, 4, 8, 16 kTrueColor = 2, // bit depths: 8, 16 @@ -117,14 +120,18 @@ public: } /** - * Returns the palette of the specified PNG8 image. - * - * Note that the palette's format is RGBA. + * Returns the palette of the specified PNG8 image, given a pointer to + * an RGBA palette array (4 x 256). */ void getPalette(byte *palette, uint16 &entries) { if (_header.colorType != kIndexed) error("Palette requested for a non-indexed PNG"); - palette = _palette; + for (int i = 0; i < 256; i++) { + palette[0 + i * 4] = _palette[0 + i * 4]; // R + palette[1 + i * 4] = _palette[1 + i * 4]; // G + palette[2 + i * 4] = _palette[2 + i * 4]; // B + palette[3 + i * 4] = _palette[3 + i * 4]; // A + } entries = _paletteEntries; } diff --git a/graphics/scaler/2xsai.cpp b/graphics/scaler/2xsai.cpp index 936ed19124..43a5b2fd1d 100644 --- a/graphics/scaler/2xsai.cpp +++ b/graphics/scaler/2xsai.cpp @@ -287,7 +287,7 @@ void _2xSaITemplate(const uint8 *srcPtr, uint32 srcPitch, uint8 *dstPtr, uint32 register unsigned colorA, colorB; unsigned colorC, colorD, - colorE, colorF, colorG, colorH, colorI, colorJ, colorK, colorL, colorM, colorN, colorO, colorP; + colorE, colorF, colorG, colorH, colorI, colorJ, colorK, colorL, colorM, colorN, colorO; unsigned product, product1, product2; //--------------------------------------- @@ -313,7 +313,6 @@ void _2xSaITemplate(const uint8 *srcPtr, uint32 srcPitch, uint8 *dstPtr, uint32 colorM = *(bP + 2 * nextlineSrc - 1); colorN = *(bP + 2 * nextlineSrc); colorO = *(bP + 2 * nextlineSrc + 1); - colorP = *(bP + 2 * nextlineSrc + 2); if ((colorA == colorD) && (colorB != colorC)) { if (((colorA == colorE) && (colorB == colorL)) || diff --git a/graphics/scaler/scale2x.cpp b/graphics/scaler/scale2x.cpp index deae44c1c7..ec2aa2086e 100644 --- a/graphics/scaler/scale2x.cpp +++ b/graphics/scaler/scale2x.cpp @@ -34,7 +34,6 @@ #include "common/scummsys.h" -#include "graphics/scaler/intern.h" #include "graphics/scaler/scale2x.h" /***************************************************************************/ diff --git a/graphics/scaler/scale3x.cpp b/graphics/scaler/scale3x.cpp index 4e78796ee7..788c8694c5 100644 --- a/graphics/scaler/scale3x.cpp +++ b/graphics/scaler/scale3x.cpp @@ -34,7 +34,6 @@ #include "common/scummsys.h" -#include "graphics/scaler/intern.h" #include "graphics/scaler/scale3x.h" /***************************************************************************/ diff --git a/graphics/scaler/scalebit.cpp b/graphics/scaler/scalebit.cpp index 706fea8f05..c6d2a0d752 100644 --- a/graphics/scaler/scalebit.cpp +++ b/graphics/scaler/scalebit.cpp @@ -35,7 +35,6 @@ #include "common/scummsys.h" -#include "graphics/scaler/intern.h" #include "graphics/scaler/scale2x.h" #include "graphics/scaler/scale3x.h" diff --git a/graphics/scaler/thumbnail_intern.cpp b/graphics/scaler/thumbnail_intern.cpp index 5cee1c7a72..d78648c325 100644 --- a/graphics/scaler/thumbnail_intern.cpp +++ b/graphics/scaler/thumbnail_intern.cpp @@ -30,6 +30,7 @@ #include "graphics/colormasks.h" #include "graphics/scaler.h" #include "graphics/scaler/intern.h" +#include "graphics/palette.h" template<int bitFormat> uint16 quadBlockInterpolate(const uint8 *src, uint32 srcPitch) { @@ -99,12 +100,12 @@ static bool grabScreen565(Graphics::Surface *surf) { if (!screen) return false; - assert(screen->bytesPerPixel == 1 || screen->bytesPerPixel == 2); + assert(screen->format.bytesPerPixel == 1 || screen->format.bytesPerPixel == 2); assert(screen->pixels != 0); Graphics::PixelFormat screenFormat = g_system->getScreenFormat(); - surf->create(screen->w, screen->h, 2); + surf->create(screen->w, screen->h, Graphics::PixelFormat(2, 5, 6, 5, 0, 11, 5, 0, 0)); byte *palette = 0; if (screenFormat.bytesPerPixel == 1) { @@ -146,7 +147,7 @@ static bool createThumbnail(Graphics::Surface &out, Graphics::Surface &in) { // center MM NES screen Graphics::Surface newscreen; - newscreen.create(width, in.h, in.bytesPerPixel); + newscreen.create(width, in.h, in.format); uint8 *dst = (uint8 *)newscreen.getBasePtr((320 - in.w) / 2, 0); const uint8 *src = (const uint8 *)in.getBasePtr(0, 0); @@ -171,13 +172,13 @@ static bool createThumbnail(Graphics::Surface &out, Graphics::Surface &in) { // cut off menu and so on.. Graphics::Surface newscreen; - newscreen.create(width, 400, in.bytesPerPixel); + newscreen.create(width, 400, in.format); uint8 *dst = (uint8 *)newscreen.getBasePtr(0, (400 - 240) / 2); const uint8 *src = (const uint8 *)in.getBasePtr(41, 28); for (int y = 0; y < 240; ++y) { - memcpy(dst, src, 640 * in.bytesPerPixel); + memcpy(dst, src, 640 * in.format.bytesPerPixel); dst += newscreen.pitch; src += in.pitch; } @@ -190,9 +191,9 @@ static bool createThumbnail(Graphics::Surface &out, Graphics::Surface &in) { inHeight = 480; Graphics::Surface newscreen; - newscreen.create(width, 480, in.bytesPerPixel); + newscreen.create(width, 480, in.format); - memcpy(newscreen.getBasePtr(0, 0), in.getBasePtr(0, 0), width * 440 * in.bytesPerPixel); + memcpy(newscreen.getBasePtr(0, 0), in.getBasePtr(0, 0), width * 440 * in.format.bytesPerPixel); in.free(); in = newscreen; @@ -200,7 +201,7 @@ static bool createThumbnail(Graphics::Surface &out, Graphics::Surface &in) { uint16 newHeight = !(inHeight % 240) ? kThumbnailHeight2 : kThumbnailHeight1; - out.create(kThumbnailWidth, newHeight, sizeof(uint16)); + out.create(kThumbnailWidth, newHeight, Graphics::PixelFormat(2, 5, 6, 5, 0, 11, 5, 0, 0)); createThumbnail((const uint8 *)in.pixels, width * sizeof(uint16), (uint8 *)out.pixels, out.pitch, width, inHeight); in.free(); @@ -223,7 +224,7 @@ bool createThumbnail(Graphics::Surface *surf, const uint8 *pixels, int w, int h, assert(surf); Graphics::Surface screen; - screen.create(w, h, 2); + screen.create(w, h, Graphics::PixelFormat(2, 5, 6, 5, 0, 11, 5, 0, 0)); for (uint y = 0; y < screen.h; ++y) { for (uint x = 0; x < screen.w; ++x) { diff --git a/graphics/sjis.cpp b/graphics/sjis.cpp index bb9f33aa26..caa53a4f63 100644 --- a/graphics/sjis.cpp +++ b/graphics/sjis.cpp @@ -31,6 +31,7 @@ #include "common/archive.h" #include "common/endian.h" #include "common/stream.h" +#include "common/textconsole.h" #include "graphics/surface.h" @@ -57,7 +58,7 @@ FontSJIS *FontSJIS::createFont(const Common::Platform platform) { } void FontSJIS::drawChar(Graphics::Surface &dst, uint16 ch, int x, int y, uint32 c1, uint32 c2) const { - drawChar(dst.getBasePtr(x, y), ch, dst.pitch, dst.bytesPerPixel, c1, c2, dst.w - x, dst.h - y); + drawChar(dst.getBasePtr(x, y), ch, dst.pitch, dst.format.bytesPerPixel, c1, c2, dst.w - x, dst.h - y); } template<typename Color> @@ -362,7 +363,7 @@ bool FontSjisSVM::loadData() { uint32 magic1 = data->readUint32BE(); uint32 magic2 = data->readUint32BE(); - if (magic1 != MKID_BE('SCVM') || magic2 != MKID_BE('SJIS')) { + if (magic1 != MKTAG('S','C','V','M') || magic2 != MKTAG('S','J','I','S')) { delete data; return false; } diff --git a/graphics/surface.cpp b/graphics/surface.cpp index f06c24c2cd..88bdcfc822 100644 --- a/graphics/surface.cpp +++ b/graphics/surface.cpp @@ -24,7 +24,8 @@ #include "common/algorithm.h" #include "common/util.h" -#include "common/endian.h" +#include "common/rect.h" +#include "common/textconsole.h" #include "graphics/primitives.h" #include "graphics/surface.h" @@ -40,23 +41,23 @@ static void plotPoint(int x, int y, int color, void *data) { } void Surface::drawLine(int x0, int y0, int x1, int y1, uint32 color) { - if (bytesPerPixel == 1) + if (format.bytesPerPixel == 1) Graphics::drawLine(x0, y0, x1, y1, color, plotPoint<byte>, this); - else if (bytesPerPixel == 2) + else if (format.bytesPerPixel == 2) Graphics::drawLine(x0, y0, x1, y1, color, plotPoint<uint16>, this); else error("Surface::drawLine: bytesPerPixel must be 1 or 2"); } -void Surface::create(uint16 width, uint16 height, uint8 bytesPP) { +void Surface::create(uint16 width, uint16 height, const PixelFormat &f) { free(); w = width; h = height; - bytesPerPixel = bytesPP; - pitch = w * bytesPP; + format = f; + pitch = w * format.bytesPerPixel; - pixels = calloc(width * height, bytesPP); + pixels = calloc(width * height, format.bytesPerPixel); assert(pixels); } @@ -64,11 +65,11 @@ void Surface::free() { ::free(pixels); pixels = 0; w = h = pitch = 0; - bytesPerPixel = 0; + format = PixelFormat(); } void Surface::copyFrom(const Surface &surf) { - create(surf.w, surf.h, surf.bytesPerPixel); + create(surf.w, surf.h, surf.format); memcpy(pixels, surf.pixels, h * pitch); } @@ -88,10 +89,10 @@ void Surface::hLine(int x, int y, int x2, uint32 color) { if (x2 < x) return; - if (bytesPerPixel == 1) { + if (format.bytesPerPixel == 1) { byte *ptr = (byte *)getBasePtr(x, y); memset(ptr, (byte)color, x2-x+1); - } else if (bytesPerPixel == 2) { + } else if (format.bytesPerPixel == 2) { uint16 *ptr = (uint16 *)getBasePtr(x, y); Common::set_to(ptr, ptr + (x2-x+1), (uint16)color); } else { @@ -112,13 +113,13 @@ void Surface::vLine(int x, int y, int y2, uint32 color) { if (y2 >= h) y2 = h - 1; - if (bytesPerPixel == 1) { + if (format.bytesPerPixel == 1) { byte *ptr = (byte *)getBasePtr(x, y); while (y++ <= y2) { *ptr = (byte)color; ptr += pitch; } - } else if (bytesPerPixel == 2) { + } else if (format.bytesPerPixel == 2) { uint16 *ptr = (uint16 *)getBasePtr(x, y); while (y++ <= y2) { *ptr = (uint16)color; @@ -140,13 +141,13 @@ void Surface::fillRect(Common::Rect r, uint32 color) { int height = r.height(); bool useMemset = true; - if (bytesPerPixel == 2) { + if (format.bytesPerPixel == 2) { lineLen *= 2; if ((uint16)color != ((color & 0xff) | (color & 0xff) << 8)) useMemset = false; - } else if (bytesPerPixel == 4) { + } else if (format.bytesPerPixel == 4) { useMemset = false; - } else if (bytesPerPixel != 1) { + } else if (format.bytesPerPixel != 1) { error("Surface::fillRect: bytesPerPixel must be 1, 2 or 4"); } @@ -157,7 +158,7 @@ void Surface::fillRect(Common::Rect r, uint32 color) { ptr += pitch; } } else { - if (bytesPerPixel == 2) { + if (format.bytesPerPixel == 2) { uint16 *ptr = (uint16 *)getBasePtr(r.left, r.top); while (height--) { Common::set_to(ptr, ptr + width, (uint16)color); @@ -185,7 +186,7 @@ void Surface::move(int dx, int dy, int height) { if ((dx == 0 && dy == 0) || height <= 0) return; - if (bytesPerPixel != 1 && bytesPerPixel != 2) + if (format.bytesPerPixel != 1 && format.bytesPerPixel != 2) error("Surface::move: bytesPerPixel must be 1 or 2"); byte *src, *dst; @@ -215,37 +216,37 @@ void Surface::move(int dx, int dy, int height) { // horizontal movement if (dx > 0) { // move right - copy from right to left - dst = (byte *)pixels + (pitch - bytesPerPixel); - src = dst - (dx * bytesPerPixel); + dst = (byte *)pixels + (pitch - format.bytesPerPixel); + src = dst - (dx * format.bytesPerPixel); for (y = 0; y < height; y++) { for (x = dx; x < w; x++) { - if (bytesPerPixel == 1) { + if (format.bytesPerPixel == 1) { *dst-- = *src--; - } else if (bytesPerPixel == 2) { + } else if (format.bytesPerPixel == 2) { *(uint16 *)dst = *(const uint16 *)src; src -= 2; dst -= 2; } } - src += pitch + (pitch - dx * bytesPerPixel); - dst += pitch + (pitch - dx * bytesPerPixel); + src += pitch + (pitch - dx * format.bytesPerPixel); + dst += pitch + (pitch - dx * format.bytesPerPixel); } } else if (dx < 0) { // move left - copy from left to right dst = (byte *)pixels; - src = dst - (dx * bytesPerPixel); + src = dst - (dx * format.bytesPerPixel); for (y = 0; y < height; y++) { for (x = -dx; x < w; x++) { - if (bytesPerPixel == 1) { + if (format.bytesPerPixel == 1) { *dst++ = *src++; - } else if (bytesPerPixel == 2) { + } else if (format.bytesPerPixel == 2) { *(uint16 *)dst = *(const uint16 *)src; src += 2; dst += 2; } } - src += pitch - (pitch + dx * bytesPerPixel); - dst += pitch - (pitch + dx * bytesPerPixel); + src += pitch - (pitch + dx * format.bytesPerPixel); + dst += pitch - (pitch + dx * format.bytesPerPixel); } } } diff --git a/graphics/surface.h b/graphics/surface.h index f9cb6cc474..1b54690aa9 100644 --- a/graphics/surface.h +++ b/graphics/surface.h @@ -26,7 +26,12 @@ #define GRAPHICS_SURFACE_H #include "common/scummsys.h" -#include "common/rect.h" + +namespace Common { +struct Rect; +} + +#include "graphics/pixelformat.h" namespace Graphics { @@ -65,14 +70,14 @@ struct Surface { void *pixels; /** - * How many bytes a single pixel occupies. + * The pixel format of the surface. */ - uint8 bytesPerPixel; + PixelFormat format; /** * Construct a simple Surface object. */ - Surface() : w(0), h(0), pitch(0), pixels(0), bytesPerPixel(0) { + Surface() : w(0), h(0), pitch(0), pixels(0), format() { } /** @@ -83,7 +88,7 @@ struct Surface { * @return Pointer to the pixel. */ inline const void *getBasePtr(int x, int y) const { - return (const byte *)(pixels) + y * pitch + x * bytesPerPixel; + return (const byte *)(pixels) + y * pitch + x * format.bytesPerPixel; } /** @@ -94,7 +99,7 @@ struct Surface { * @return Pointer to the pixel. */ inline void *getBasePtr(int x, int y) { - return static_cast<byte *>(pixels) + y * pitch + x * bytesPerPixel; + return static_cast<byte *>(pixels) + y * pitch + x * format.bytesPerPixel; } /** @@ -105,9 +110,9 @@ struct Surface { * * @param width Width of the surface object. * @param height Height of the surface object. - * @param bytePP The number of bytes a single pixel uses. + * @param format The pixel format the surface should use. */ - void create(uint16 width, uint16 height, uint8 bytesPP); + void create(uint16 width, uint16 height, const PixelFormat &format); /** * Release the memory used by the pixels memory of this surface. This is the diff --git a/graphics/thumbnail.cpp b/graphics/thumbnail.cpp index b245cfc5fa..32ab04ed24 100644 --- a/graphics/thumbnail.cpp +++ b/graphics/thumbnail.cpp @@ -28,6 +28,7 @@ #include "common/endian.h" #include "common/system.h" #include "common/stream.h" +#include "common/textconsole.h" namespace Graphics { @@ -49,7 +50,7 @@ bool loadHeader(Common::SeekableReadStream &in, ThumbnailHeader &header, bool ou // We also accept the bad 'BMHT' header here, for the sake of compatibility // with some older savegames which were written incorrectly due to a bug in // ScummVM which wrote the thumb header type incorrectly on LE systems. - if (header.type != MKID_BE('THMB') && header.type != MKID_BE('BMHT')) { + if (header.type != MKTAG('T','H','M','B') && header.type != MKTAG('B','M','H','T')) { if (outputWarnings) warning("couldn't find thumbnail header type"); return false; @@ -107,10 +108,10 @@ bool loadThumbnail(Common::SeekableReadStream &in, Graphics::Surface &to) { return false; } - to.create(header.width, header.height, sizeof(OverlayColor)); + Graphics::PixelFormat format = g_system->getOverlayFormat(); + to.create(header.width, header.height, format); OverlayColor *pixels = (OverlayColor *)to.pixels; - Graphics::PixelFormat format = g_system->getOverlayFormat(); for (int y = 0; y < to.h; ++y) { for (int x = 0; x < to.w; ++x) { uint8 r, g, b; @@ -139,18 +140,18 @@ bool saveThumbnail(Common::WriteStream &out) { } bool saveThumbnail(Common::WriteStream &out, const Graphics::Surface &thumb) { - if (thumb.bytesPerPixel != 2) { + if (thumb.format.bytesPerPixel != 2) { warning("trying to save thumbnail with bpp different than 2"); return false; } ThumbnailHeader header; - header.type = MKID_BE('THMB'); - header.size = ThumbnailHeaderSize + thumb.w*thumb.h*thumb.bytesPerPixel; + header.type = MKTAG('T','H','M','B'); + header.size = ThumbnailHeaderSize + thumb.w*thumb.h*thumb.format.bytesPerPixel; header.version = THMB_VERSION; header.width = thumb.w; header.height = thumb.h; - header.bpp = thumb.bytesPerPixel; + header.bpp = thumb.format.bytesPerPixel; out.writeUint32BE(header.type); out.writeUint32BE(header.size); diff --git a/graphics/wincursor.cpp b/graphics/wincursor.cpp new file mode 100644 index 0000000000..bae64f9303 --- /dev/null +++ b/graphics/wincursor.cpp @@ -0,0 +1,314 @@ +/* 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. + * + * $URL$ + * $Id$ + * + */ + +#include "common/ptr.h" +#include "common/stream.h" +#include "common/textconsole.h" +#include "common/winexe_ne.h" +#include "common/winexe_pe.h" + +#include "graphics/wincursor.h" + +namespace Graphics { + +WinCursor::WinCursor() { + _width = 0; + _height = 0; + _hotspotX = 0; + _hotspotY = 0; + _surface = 0; + _keyColor = 0; + memset(_palette, 0, 256 * 3); +} + +WinCursor::~WinCursor() { + clear(); +} + +uint16 WinCursor::getWidth() const { + return _width; +} + +uint16 WinCursor::getHeight() const { + return _height; +} + +uint16 WinCursor::getHotspotX() const { + return _hotspotX; +} + +uint16 WinCursor::getHotspotY() const { + return _hotspotY; +} + +byte WinCursor::getKeyColor() const { + return _keyColor; +} + +bool WinCursor::readFromStream(Common::SeekableReadStream &stream) { + clear(); + + _hotspotX = stream.readUint16LE(); + _hotspotY = stream.readUint16LE(); + + // Check header size + if (stream.readUint32LE() != 40) + return false; + + // Check dimensions + _width = stream.readUint32LE(); + _height = stream.readUint32LE() / 2; + + if (_width & 3) { + // Cursors should always be a power of 2 + // Of course, it wouldn't be hard to handle but if we have no examples... + warning("Non-divisible-by-4 width cursor found"); + return false; + } + + // Color planes + if (stream.readUint16LE() != 1) + return false; + + // Only 1bpp and 8bpp supported + uint16 bitsPerPixel = stream.readUint16LE(); + if (bitsPerPixel != 1 && bitsPerPixel != 8) + return false; + + // Compression + if (stream.readUint32LE() != 0) + return false; + + // Image size + X resolution + Y resolution + stream.skip(12); + + uint32 numColors = stream.readUint32LE(); + + // If the color count is 0, then it uses up the maximum amount + if (numColors == 0) + numColors = 1 << bitsPerPixel; + + // Reading the palette + stream.seek(40 + 4); + for (uint32 i = 0 ; i < numColors; i++) { + _palette[i * 3 + 2] = stream.readByte(); + _palette[i * 3 + 1] = stream.readByte(); + _palette[i * 3 ] = stream.readByte(); + stream.readByte(); + } + + // Reading the bitmap data + uint32 dataSize = stream.size() - stream.pos(); + byte *initialSource = new byte[dataSize]; + stream.read(initialSource, dataSize); + + // Parse the XOR map + const byte *src = initialSource; + _surface = new byte[_width * _height]; + byte *dest = _surface + _width * (_height - 1); + uint32 imagePitch = _width * bitsPerPixel / 8; + + for (uint32 i = 0; i < _height; i++) { + byte *rowDest = dest; + + if (bitsPerPixel == 1) { + // 1bpp + for (uint16 j = 0; j < (_width / 8); j++) { + byte p = src[j]; + + for (int k = 0; k < 8; k++, rowDest++, p <<= 1) { + if ((p & 0x80) == 0x80) + *rowDest = 1; + else + *rowDest = 0; + } + } + } else { + // 8bpp + memcpy(rowDest, src, _width); + } + + dest -= _width; + src += imagePitch; + } + + // Calculate our key color + if (numColors < 256) { + // If we're not using the maximum colors in a byte, we can fit it in + _keyColor = numColors; + } else { + // HACK: Try to find a color that's not being used so it can become + // our keycolor. It's quite impossible to fit 257 entries into 256... + for (uint32 i = 0; i < 256; i++) { + for (int j = 0; j < _width * _height; j++) { + // TODO: Also check to see if the space is transparent + + if (_surface[j] == i) + break; + + if (j == _width * _height - 1) { + _keyColor = i; + i = 256; + break; + } + } + } + } + + // Now go through and apply the AND map to get the transparency + uint32 andWidth = (_width + 7) / 8; + src += andWidth * (_height - 1); + + for (uint32 y = 0; y < _height; y++) { + for (uint32 x = 0; x < _width; x++) + if (src[x / 8] & (1 << (7 - x % 8))) + _surface[y * _width + x] = _keyColor; + + src -= andWidth; + } + + delete[] initialSource; + return true; +} + +void WinCursor::clear() { + delete[] _surface; _surface = 0; +} + +WinCursorGroup::WinCursorGroup() { +} + +WinCursorGroup::~WinCursorGroup() { + for (uint32 i = 0; i < cursors.size(); i++) + delete cursors[i].cursor; +} + +WinCursorGroup *WinCursorGroup::createCursorGroup(Common::NEResources &exe, const Common::WinResourceID &id) { + Common::ScopedPtr<Common::SeekableReadStream> stream(exe.getResource(Common::kNEGroupCursor, id)); + + if (!stream || stream->size() <= 6) + return 0; + + stream->skip(4); + uint32 cursorCount = stream->readUint16LE(); + if ((uint32)stream->size() < (6 + cursorCount * 16)) + return 0; + + WinCursorGroup *group = new WinCursorGroup(); + group->cursors.reserve(cursorCount); + + for (uint32 i = 0; i < cursorCount; i++) { + stream->readUint16LE(); // width + stream->readUint16LE(); // height + + // Plane count + if (stream->readUint16LE() != 1) { + delete group; + return 0; + } + + // Bits per pixel + // NE cursors can only be 1bpp + if (stream->readUint16LE() != 1) { + delete group; + return 0; + } + + stream->readUint32LE(); // data size + uint32 cursorId = stream->readUint32LE(); + + Common::ScopedPtr<Common::SeekableReadStream> cursorStream(exe.getResource(Common::kNECursor, cursorId)); + if (!cursorStream) { + delete group; + return 0; + } + + WinCursor *cursor = new WinCursor(); + if (!cursor->readFromStream(*cursorStream)) { + delete cursor; + delete group; + return 0; + } + + CursorItem item; + item.id = cursorId; + item.cursor = cursor; + group->cursors.push_back(item); + } + + return group; +} + +WinCursorGroup *WinCursorGroup::createCursorGroup(Common::PEResources &exe, const Common::WinResourceID &id) { + Common::ScopedPtr<Common::SeekableReadStream> stream(exe.getResource(Common::kPEGroupCursor, id)); + + if (!stream || stream->size() <= 6) + return 0; + + stream->skip(4); + uint32 cursorCount = stream->readUint16LE(); + if ((uint32)stream->size() < (6 + cursorCount * 14)) + return 0; + + WinCursorGroup *group = new WinCursorGroup(); + group->cursors.reserve(cursorCount); + + for (uint32 i = 0; i < cursorCount; i++) { + stream->readUint16LE(); // width + stream->readUint16LE(); // height + + // Plane count + if (stream->readUint16LE() != 1) { + delete group; + return 0; + } + + stream->readUint16LE(); // bits per pixel + stream->readUint32LE(); // data size + uint32 cursorId = stream->readUint16LE(); + + Common::ScopedPtr<Common::SeekableReadStream> cursorStream(exe.getResource(Common::kPECursor, cursorId)); + if (!cursorStream) { + delete group; + return 0; + } + + WinCursor *cursor = new WinCursor(); + if (!cursor->readFromStream(*cursorStream)) { + delete cursor; + delete group; + return 0; + } + + CursorItem item; + item.id = cursorId; + item.cursor = cursor; + group->cursors.push_back(item); + } + + return group; +} + +} // End of namespace Graphics diff --git a/graphics/wincursor.h b/graphics/wincursor.h new file mode 100644 index 0000000000..717a1be588 --- /dev/null +++ b/graphics/wincursor.h @@ -0,0 +1,105 @@ +/* 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. + * + * $URL$ + * $Id$ + * + */ + +#ifndef GRAPHICS_WINCURSOR_H +#define GRAPHICS_WINCURSOR_H + +#include "common/array.h" +#include "common/winexe.h" + +namespace Common { +class NEResources; +class PEResources; +class SeekableReadStream; +} + +namespace Graphics { + +/** A Windows cursor. */ +class WinCursor { +public: + WinCursor(); + ~WinCursor(); + + /** Return the cursor's width. */ + uint16 getWidth() const; + /** Return the cursor's height. */ + uint16 getHeight() const; + /** Return the cursor's hotspot's x coordinate. */ + uint16 getHotspotX() const; + /** Return the cursor's hotspot's y coordinate. */ + uint16 getHotspotY() const; + /** Return the cursor's transparent key. */ + byte getKeyColor() const; + + const byte *getSurface() const { return _surface; } + const byte *getPalette() const { return _palette; } + + /** Read the cursor's data out of a stream. */ + bool readFromStream(Common::SeekableReadStream &stream); + +private: + byte *_surface; + byte _palette[256 * 3]; + + uint16 _width; ///< The cursor's width. + uint16 _height; ///< The cursor's height. + uint16 _hotspotX; ///< The cursor's hotspot's x coordinate. + uint16 _hotspotY; ///< The cursor's hotspot's y coordinate. + byte _keyColor; ///< The cursor's transparent key + + /** Clear the cursor. */ + void clear(); +}; + +/** + * A structure holding an array of cursors from a single Windows Executable cursor group. + * + * Windows lumps different versions of the same cursors/icons together and decides which one + * to use based on the screen's color depth and resolution. For instance, one cursor group + * could hold a 1bpp 16x16 cursorand a 8bpp 16x16 cursor. This will hold all cursors in the + * group. This class should be used to actually parse the cursors, whereas WinCursor is just + * the representation used by this struct to store the cursors. + */ +struct WinCursorGroup { + WinCursorGroup(); + ~WinCursorGroup(); + + struct CursorItem { + Common::WinResourceID id; + WinCursor *cursor; + }; + + Common::Array<CursorItem> cursors; + + /** Create a cursor group from an NE EXE, returns 0 on failure */ + static WinCursorGroup *createCursorGroup(Common::NEResources &exe, const Common::WinResourceID &id); + /** Create a cursor group from an PE EXE, returns 0 on failure */ + static WinCursorGroup *createCursorGroup(Common::PEResources &exe, const Common::WinResourceID &id); +}; + +} // End of namespace Graphics + +#endif |