From 67c6e92efba2ffcde33a3e9b8e9ebaf7389e05ae Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Sun, 11 Oct 2009 12:00:56 +0000 Subject: Add support for 8x16 chars in the FM-Towns font ROM code. svn-id: r44910 --- graphics/sjis.cpp | 237 ++++++++++++++++++++++++++++-------------------------- graphics/sjis.h | 45 +++++------ 2 files changed, 145 insertions(+), 137 deletions(-) (limited to 'graphics') diff --git a/graphics/sjis.cpp b/graphics/sjis.cpp index 8db3a6ede4..950546b0d5 100644 --- a/graphics/sjis.cpp +++ b/graphics/sjis.cpp @@ -53,7 +53,7 @@ FontSJIS *FontSJIS::createFont(const Common::Platform platform) { } template -void FontSJIS16x16::drawCharInternOutline(const uint16 *glyph, uint8 *dst, int pitch, Color c1, Color c2) const { +void FontSJISBase::drawCharInternOutline(const uint16 *glyph, uint8 *dst, int pitch, Color c1, Color c2) const { uint32 outlineGlyph[18]; memset(outlineGlyph, 0, sizeof(outlineGlyph)); @@ -88,7 +88,7 @@ void FontSJIS16x16::drawCharInternOutline(const uint16 *glyph, uint8 *dst, int p } template -void FontSJIS16x16::drawCharIntern(const uint16 *glyph, uint8 *dst, int pitch, Color c1) const { +void FontSJISBase::drawCharIntern(const uint16 *glyph, uint8 *dst, int pitch, Color c1) const { for (int y = 0; y < 16; ++y) { Color *lineBuf = (Color *)dst; uint16 line = *glyph++; @@ -104,28 +104,118 @@ void FontSJIS16x16::drawCharIntern(const uint16 *glyph, uint8 *dst, int pitch, C } } -void FontSJIS16x16::drawChar(void *dst, uint16 ch, int pitch, int bpp, uint32 c1, uint32 c2) const { - const uint16 *glyphSource = getCharData(ch); - if (!glyphSource) { - warning("FontSJIS16x16::drawChar: Font does not offer data for %02X %02X", ch & 0xFF, ch >> 8); - return; +template +void FontSJISBase::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; } - if (bpp == 1) { - if (!_outlineEnabled) - drawCharIntern(glyphSource, (uint8 *)dst, pitch, c1); - else - drawCharInternOutline(glyphSource, (uint8 *)dst, pitch, c1, c2); - } else if (bpp == 2) { - if (!_outlineEnabled) - drawCharIntern(glyphSource, (uint8 *)dst, pitch, c1); - else - drawCharInternOutline(glyphSource, (uint8 *)dst, pitch, c1, c2); + // draw the original char + drawCharIntern(glyph, dst + pitch + 1, pitch, c1); +} + +template +void FontSJISBase::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; + } +} + +void FontSJISBase::drawChar(void *dst, uint16 ch, int pitch, int bpp, uint32 c1, uint32 c2) const { + if (is8x16(ch)) { + const uint8 *glyphSource = getCharData8x16(ch); + if (!glyphSource) { + warning("FontSJISBase::drawChar: Font does not offer data for %02X %02X", ch & 0xFF, ch >> 8); + return; + } + + if (bpp == 1) { + if (!_outlineEnabled) + drawCharIntern(glyphSource, (uint8 *)dst, pitch, c1); + else + drawCharInternOutline(glyphSource, (uint8 *)dst, pitch, c1, c2); + } else if (bpp == 2) { + if (!_outlineEnabled) + drawCharIntern(glyphSource, (uint8 *)dst, pitch, c1); + else + drawCharInternOutline(glyphSource, (uint8 *)dst, pitch, c1, c2); + } else { + error("FontSJISBase::drawChar: unsupported bpp: %d", bpp); + } } else { - error("FontSJIS16x16::drawChar: unsupported bpp: %d", bpp); + const uint16 *glyphSource = getCharData(ch); + if (!glyphSource) { + warning("FontSJISBase::drawChar: Font does not offer data for %02X %02X", ch & 0xFF, ch >> 8); + return; + } + + if (bpp == 1) { + if (!_outlineEnabled) + drawCharIntern(glyphSource, (uint8 *)dst, pitch, c1); + else + drawCharInternOutline(glyphSource, (uint8 *)dst, pitch, c1, c2); + } else if (bpp == 2) { + if (!_outlineEnabled) + drawCharIntern(glyphSource, (uint8 *)dst, pitch, c1); + else + drawCharInternOutline(glyphSource, (uint8 *)dst, pitch, c1, c2); + } else { + error("FontSJISBase::drawChar: unsupported bpp: %d", bpp); + } } } +uint FontSJISBase::getCharWidth(uint16 ch) const { + if (is8x16(ch)) + return _outlineEnabled ? 10 : 8; + else + return getMaxFontWidth(); +} + +bool FontSJISBase::is8x16(uint16 ch) const { + if (ch >= 0xFF) + return false; + else if (ch <= 0x7F || (ch >= 0xA1 && ch <= 0xDF)) + return true; + else + return false; +} + // FM-TOWNS ROM font bool FontTowns::loadData() { @@ -133,8 +223,11 @@ bool FontTowns::loadData() { if (!data) return false; - for (uint i = 0; i < (kFontRomSize / 2); ++i) - _fontData[i] = data->readUint16BE(); + for (uint i = 0; i < kFont16x16Chars * 16; ++i) + _fontData16x16[i] = data->readUint16BE(); + + data->seek(251904, SEEK_SET); + data->read(_fontData8x16, kFont8x16Chars * 16); bool retValue = !data->err(); delete data; @@ -226,7 +319,17 @@ const uint16 *FontTowns::getCharData(uint16 ch) const { } debug(6, "Kanji: %c%c f 0x%x s 0x%x base 0x%x c %d p %d chunk %d cr %d index %d", f, s, f, s, base, c, p, chunk, cr, ((chunk_f + chunk) * 32 + (s - base)) + cr); - return _fontData + (((chunk_f + chunk) * 32 + (s - base)) + cr) * 16; + const int chunkNum = (((chunk_f + chunk) * 32 + (s - base)) + cr); + if (chunkNum < 0 || chunkNum >= kFont16x16Chars) + return 0; + else + return _fontData16x16 + chunkNum * 16; +} + +const uint8 *FontTowns::getCharData8x16(uint16 c) const { + if (c >= kFont8x16Chars) + return 0; + return _fontData8x16 + c * 16; } // ScummVM SJIS font @@ -270,98 +373,6 @@ bool FontSjisSVM::loadData() { 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(glyphSource, (uint8 *)dst, pitch, c1); - else - drawCharInternOutline(glyphSource, (uint8 *)dst, pitch, c1, c2); - } else if (bpp == 2) { - if (!_outlineEnabled) - drawCharIntern(glyphSource, (uint8 *)dst, pitch, c1); - else - drawCharInternOutline(glyphSource, (uint8 *)dst, pitch, c1, c2); - } else { - error("FontSjisSVM::drawChar: unsupported bpp: %d", bpp); - } -} - -// TODO: Consider merging these with FontSjis16x16 -template -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(glyph, dst + pitch + 1, pitch, c1); -} - -template -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; const uint8 sB = c >> 8; diff --git a/graphics/sjis.h b/graphics/sjis.h index 14a5187914..d53cb46818 100644 --- a/graphics/sjis.h +++ b/graphics/sjis.h @@ -91,7 +91,7 @@ public: /** * Returns the width of a specific character. */ - virtual uint getCharWidth(uint16 ch) const { return getMaxFontWidth(); } + virtual uint getCharWidth(uint16 ch) const = 0; /** * Draws a SJIS encoded character on the given surface. @@ -118,19 +118,20 @@ public: }; /** - * A base class to render 16x16 monochrome SJIS fonts. + * A base class to render 16x16 (2 byte chars), 8x16 (1 byte chars) monochrome SJIS fonts. */ -class FontSJIS16x16 : public FontSJIS { +class FontSJISBase : public FontSJIS { public: - FontSJIS16x16() : _outlineEnabled(false) {} + FontSJISBase() : _outlineEnabled(false) {} void enableOutline(bool enable) { _outlineEnabled = enable; } uint getFontHeight() const { return _outlineEnabled ? 18 : 16; } uint getMaxFontWidth() const { return _outlineEnabled ? 18 : 16; } - virtual void drawChar(void *dst, uint16 ch, int pitch, int bpp, uint32 c1, uint32 c2) const; + uint getCharWidth(uint16 ch) const; + void drawChar(void *dst, uint16 ch, int pitch, int bpp, uint32 c1, uint32 c2) const; private: template void drawCharInternOutline(const uint16 *glyph, uint8 *dst, int pitch, Color c1, Color c2) const; @@ -138,40 +139,48 @@ private: template void drawCharIntern(const uint16 *glyph, uint8 *dst, int pitch, Color c1) const; + template + void drawCharInternOutline(const uint8 *glyph, uint8 *dst, int pitch, Color c1, Color c2) const; + + template + void drawCharIntern(const uint8 *glyph, uint8 *dst, int pitch, Color c1) const; protected: bool _outlineEnabled; + bool is8x16(uint16 ch) const; + virtual const uint16 *getCharData(uint16 c) const = 0; + virtual const uint8 *getCharData8x16(uint16 c) const = 0; }; /** * 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 { +class FontTowns : public FontSJISBase { public: /** * Loads the ROM data from "FMT_FNT.ROM". */ bool loadData(); - private: enum { - kFontRomSize = 262144 + kFont16x16Chars = 7808, + kFont8x16Chars = 256 }; - uint16 _fontData[kFontRomSize / 2]; + uint16 _fontData16x16[kFont16x16Chars * 16]; + uint8 _fontData8x16[kFont8x16Chars * 16]; const uint16 *getCharData(uint16 c) const; + const uint8 *getCharData8x16(uint16 c) const; }; /** * Our custom SJIS FNT. */ -class FontSjisSVM : public FontSJIS16x16 { +class FontSjisSVM : public FontSJISBase { public: FontSjisSVM() : _fontData16x16(0), _fontData16x16Size(0), _fontData8x16(0), _fontData8x16Size(0) {} ~FontSjisSVM() { delete[] _fontData16x16; delete[] _fontData8x16; } @@ -180,10 +189,6 @@ public: * 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; @@ -191,16 +196,8 @@ private: uint8 *_fontData8x16; uint _fontData8x16Size; - bool is8x16(uint16 ch) const; - const uint16 *getCharData(uint16 c) const; const uint8 *getCharData8x16(uint16 c) const; - - template - void drawCharInternOutline(const uint8 *glyph, uint8 *dst, int pitch, Color c1, Color c2) const; - - template - void drawCharIntern(const uint8 *glyph, uint8 *dst, int pitch, Color c1) const; }; // TODO: Consider adding support for PC98 ROM -- cgit v1.2.3