aboutsummaryrefslogtreecommitdiff
path: root/graphics
diff options
context:
space:
mode:
Diffstat (limited to 'graphics')
-rw-r--r--graphics/VectorRenderer.cpp7
-rw-r--r--graphics/VectorRenderer.h7
-rw-r--r--graphics/VectorRendererSpec.cpp39
-rw-r--r--graphics/conversion.cpp1
-rw-r--r--graphics/conversion.h3
-rw-r--r--graphics/dither.cpp4
-rw-r--r--graphics/font.cpp10
-rw-r--r--graphics/font.h5
-rw-r--r--graphics/fontman.cpp1
-rw-r--r--graphics/fontman.h3
-rw-r--r--graphics/fonts/scummfont.cpp5
-rw-r--r--graphics/fonts/winfont.cpp100
-rw-r--r--graphics/fonts/winfont.h8
-rw-r--r--graphics/iff.cpp6
-rw-r--r--graphics/iff.h2
-rw-r--r--graphics/imagedec.cpp3
-rw-r--r--graphics/imagedec.h3
-rw-r--r--graphics/jpeg.cpp15
-rw-r--r--graphics/module.mk3
-rw-r--r--graphics/palette.h1
-rw-r--r--graphics/pict.cpp7
-rw-r--r--graphics/pict.h2
-rw-r--r--graphics/png.cpp87
-rw-r--r--graphics/png.h19
-rw-r--r--graphics/scaler/2xsai.cpp3
-rw-r--r--graphics/scaler/scale2x.cpp1
-rw-r--r--graphics/scaler/scale3x.cpp1
-rw-r--r--graphics/scaler/scalebit.cpp1
-rw-r--r--graphics/scaler/thumbnail_intern.cpp19
-rw-r--r--graphics/sjis.cpp5
-rw-r--r--graphics/surface.cpp59
-rw-r--r--graphics/surface.h21
-rw-r--r--graphics/thumbnail.cpp15
-rw-r--r--graphics/wincursor.cpp314
-rw-r--r--graphics/wincursor.h105
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