diff options
-rw-r--r-- | engines/kyra/screen.cpp | 4 | ||||
-rw-r--r-- | graphics/sjis.cpp | 124 | ||||
-rw-r--r-- | graphics/sjis.h | 52 |
3 files changed, 158 insertions, 22 deletions
diff --git a/engines/kyra/screen.cpp b/engines/kyra/screen.cpp index f2221d0c3c..5a7bbc4f9a 100644 --- a/engines/kyra/screen.cpp +++ b/engines/kyra/screen.cpp @@ -1136,7 +1136,7 @@ int Screen::getFontWidth() const { int Screen::getCharWidth(uint16 c) const { if ((c & 0xFF00) && _sjisFont) - return _sjisFont->getFontWidth() >> 1; + return _sjisFont->getMaxFontWidth() >> 1; return _fonts[_currentFont]->getCharWidth(c) + _charWidth; } @@ -3092,7 +3092,7 @@ void Screen::drawCharSJIS(uint16 c, int x, int y) { } if (_curPage == 0 || _curPage == 1) - addDirtyRect(x, y, _sjisFont->getFontWidth() >> 1, _sjisFont->getFontHeight() >> 1); + addDirtyRect(x, y, _sjisFont->getMaxFontWidth() >> 1, _sjisFont->getFontHeight() >> 1); x <<= 1; y <<= 1; diff --git a/graphics/sjis.cpp b/graphics/sjis.cpp index e6ad08e14c..a3460d04e5 100644 --- a/graphics/sjis.cpp +++ b/graphics/sjis.cpp @@ -122,7 +122,7 @@ void FontSJIS16x16::drawChar(void *dst, uint16 ch, int pitch, int bpp, uint32 c1 else drawCharInternOutline<uint16>(glyphSource, (uint8 *)dst, pitch, c1, c2); } else { - error("FontTowns::drawChar: unsupported bpp: %d", bpp); + error("FontSJIS16x16::drawChar: unsupported bpp: %d", bpp); } } @@ -250,19 +250,117 @@ bool FontSjisSVM::loadData() { return false; } uint numChars16x16 = data->readUint16BE(); - /*uint numChars8x16 = */data->readUint16BE(); + uint numChars8x16 = data->readUint16BE(); - _fontData16x16 = new uint16[numChars16x16 * 16]; - assert(_fontData16x16); _fontData16x16Size = numChars16x16 * 16; + _fontData16x16 = new uint16[_fontData16x16Size]; + assert(_fontData16x16); for (uint i = 0; i < _fontData16x16Size; ++i) _fontData16x16[i] = data->readUint16BE(); + _fontData8x16Size = numChars8x16 * 16; + _fontData8x16 = new uint8[numChars8x16 * 16]; + assert(_fontData8x16); + + data->read(_fontData8x16, _fontData8x16Size); + bool retValue = !data->err(); delete data; return retValue; } + +void FontSjisSVM::drawChar(void *dst, uint16 ch, int pitch, int bpp, uint32 c1, uint32 c2) const { + if (!is8x16(ch)) + return FontSJIS16x16::drawChar(dst, ch, pitch, bpp, c1, c2); + + const uint8 *glyphSource = getCharData8x16(ch); + if (!glyphSource) + return; + + if (bpp == 1) { + if (!_outlineEnabled) + drawCharIntern<uint8>(glyphSource, (uint8 *)dst, pitch, c1); + else + drawCharInternOutline<uint8>(glyphSource, (uint8 *)dst, pitch, c1, c2); + } else if (bpp == 2) { + if (!_outlineEnabled) + drawCharIntern<uint16>(glyphSource, (uint8 *)dst, pitch, c1); + else + drawCharInternOutline<uint16>(glyphSource, (uint8 *)dst, pitch, c1, c2); + } else { + error("FontSjisSVM::drawChar: unsupported bpp: %d", bpp); + } +} + +// TODO: Consider merging these with FontSjis16x16 +template<typename Color> +void FontSjisSVM::drawCharInternOutline(const uint8 *glyph, uint8 *dst, int pitch, Color c1, Color c2) const { + uint16 outlineGlyph[18]; + memset(outlineGlyph, 0, sizeof(outlineGlyph)); + + // Create an outline map including the original character + const uint8 *src = glyph; + for (int i = 0; i < 16; ++i) { + uint16 line = *src++; + line = (line << 2) | (line << 1) | (line << 0); + + outlineGlyph[i + 0] |= line; + outlineGlyph[i + 1] |= line; + outlineGlyph[i + 2] |= line; + } + + uint8 *dstLine = dst; + for (int y = 0; y < 18; ++y) { + Color *lineBuf = (Color *)dstLine; + uint16 line = outlineGlyph[y]; + + for (int x = 0; x < 10; ++x) { + if (line & 0x200) + *lineBuf = c2; + line <<= 1; + ++lineBuf; + } + + dstLine += pitch; + } + + // draw the original char + drawCharIntern<Color>(glyph, dst + pitch + 1, pitch, c1); +} + +template<typename Color> +void FontSjisSVM::drawCharIntern(const uint8 *glyph, uint8 *dst, int pitch, Color c1) const { + for (int y = 0; y < 16; ++y) { + Color *lineBuf = (Color *)dst; + uint8 line = *glyph++; + + for (int x = 0; x < 8; ++x) { + if (line & 0x80) + *lineBuf = c1; + line <<= 1; + ++lineBuf; + } + + dst += pitch; + } +} + +uint FontSjisSVM::getCharWidth(uint16 ch) const { + if (is8x16(ch)) + return _outlineEnabled ? 10 : 8; + else + return FontSJIS16x16::getMaxFontWidth(); +} + +bool FontSjisSVM::is8x16(uint16 ch) const { + if (ch >= 0xFF) + return false; + else if (ch <= 0x7F || (ch >= 0xA1 && ch <= 0xDF)) + return true; + else + return false; +} const uint16 *FontSjisSVM::getCharData(uint16 c) const { const uint8 fB = c & 0xFF; @@ -292,6 +390,24 @@ const uint16 *FontSjisSVM::getCharData(uint16 c) const { return _fontData16x16 + offset; } +const uint8 *FontSjisSVM::getCharData8x16(uint16 c) const { + const uint8 fB = c & 0xFF; + const uint8 sB = c >> 8; + + if (!is8x16(c) || sB) + return 0; + + int index = fB; + + // half-width katakana + if (fB >= 0xA1 && fB <= 0xDF) + index -= 0x21; + + const uint offset = index * 16; + assert(offset <= _fontData8x16Size); + return _fontData8x16 + offset; +} + } // end of namespace Graphics #endif // defined(GRAPHICS_SJIS_H) diff --git a/graphics/sjis.h b/graphics/sjis.h index 6e975b5afd..b819cffba3 100644 --- a/graphics/sjis.h +++ b/graphics/sjis.h @@ -47,8 +47,6 @@ namespace Graphics { /** * A font that is able to draw SJIS encoded characters. - * - * The font is always monospaced. */ class FontSJIS { public: @@ -75,7 +73,7 @@ public: /** * Enable outline drawing. * - * After changing outline state, getFontHeight and getFontWidth might return + * After changing outline state, getFontHeight and getMaxFontWidth / getCharWidth might return * different values! */ virtual void enableOutline(bool enable) {} @@ -86,9 +84,14 @@ public: virtual uint getFontHeight() const = 0; /** - * Returns the width of the font. + * Returns the max. width of the font. + */ + virtual uint getMaxFontWidth() const = 0; + + /** + * Returns the width of a specific character. */ - virtual uint getFontWidth() const = 0; + virtual uint getCharWidth(uint16 ch) const { return getMaxFontWidth(); } /** * Draws a SJIS encoded character on the given surface. @@ -104,12 +107,12 @@ public: /** * Draws a SJIS char on the given raw buffer. * - * @param dst pointer to the destination - * @param ch character to draw (in little endian) - * @param pitch pitch of the destination buffer (size in *bytes*) - * @param bpp bytes per pixel of the destination buffer - * @param c1 forground color - * @param c2 outline color + * @param dst pointer to the destination + * @param ch character to draw (in little endian) + * @param pitch pitch of the destination buffer (size in *bytes*) + * @param bpp bytes per pixel of the destination buffer + * @param c1 forground color + * @param c2 outline color */ virtual void drawChar(void *dst, uint16 ch, int pitch, int bpp, uint32 c1, uint32 c2) const = 0; }; @@ -124,9 +127,9 @@ public: void enableOutline(bool enable) { _outlineEnabled = enable; } uint getFontHeight() const { return _outlineEnabled ? 18 : 16; } - uint getFontWidth() const { return _outlineEnabled ? 18 : 16; } + uint getMaxFontWidth() const { return _outlineEnabled ? 18 : 16; } - void drawChar(void *dst, uint16 ch, int pitch, int bpp, uint32 c1, uint32 c2) const; + virtual void drawChar(void *dst, uint16 ch, int pitch, int bpp, uint32 c1, uint32 c2) const; private: template<typename Color> @@ -135,8 +138,8 @@ private: template<typename Color> void drawCharIntern(const uint16 *glyph, uint8 *dst, int pitch, Color c1) const; - bool _outlineEnabled; protected: + bool _outlineEnabled; virtual const uint16 *getCharData(uint16 c) const = 0; }; @@ -145,6 +148,8 @@ protected: * FM-TOWNS ROM based SJIS compatible font. * * This is used in KYRA and SCI. + * + * TODO: This implementation does not support any 8x16 ASCII or half-width katakana chars. */ class FontTowns : public FontSJIS16x16 { public: @@ -168,19 +173,34 @@ private: */ class FontSjisSVM : public FontSJIS16x16 { public: - FontSjisSVM() : _fontData16x16(0), _fontData16x16Size(0) {} - ~FontSjisSVM() { delete[] _fontData16x16; } + FontSjisSVM() : _fontData16x16(0), _fontData16x16Size(0), _fontData8x16(0), _fontData8x16Size(0) {} + ~FontSjisSVM() { delete[] _fontData16x16; delete[] _fontData8x16; } /** * Load the font data from "SJIS.FNT". */ bool loadData(); + void drawChar(void *dst, uint16 ch, int pitch, int bpp, uint32 c1, uint32 c2) const; + + uint getCharWidth(uint16 ch) const; private: uint16 *_fontData16x16; uint _fontData16x16Size; + uint8 *_fontData8x16; + uint _fontData8x16Size; + + bool is8x16(uint16 ch) const; + const uint16 *getCharData(uint16 c) const; + const uint8 *getCharData8x16(uint16 c) const; + + template<typename Color> + void drawCharInternOutline(const uint8 *glyph, uint8 *dst, int pitch, Color c1, Color c2) const; + + template<typename Color> + void drawCharIntern(const uint8 *glyph, uint8 *dst, int pitch, Color c1) const; }; // TODO: Consider adding support for PC98 ROM |