From cd4812dfd9444a7c9df1955c940523186922de42 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Fri, 16 Apr 2010 18:23:50 +0000 Subject: SCI: support for kanji (sjis), minor centering issue left svn-id: r48674 --- engines/sci/graphics/cache.cpp | 10 ++++- engines/sci/graphics/font.cpp | 16 ++++---- engines/sci/graphics/font.h | 29 ++++++++++---- engines/sci/graphics/fontsjis.cpp | 80 +++++++++++++++++++++++++++++++++++++++ engines/sci/graphics/fontsjis.h | 62 ++++++++++++++++++++++++++++++ engines/sci/graphics/frameout.cpp | 2 +- engines/sci/graphics/screen.cpp | 7 ++++ engines/sci/graphics/screen.h | 3 ++ engines/sci/graphics/text16.cpp | 37 ++++++++++-------- engines/sci/module.mk | 1 + 10 files changed, 213 insertions(+), 34 deletions(-) create mode 100644 engines/sci/graphics/fontsjis.cpp create mode 100644 engines/sci/graphics/fontsjis.h diff --git a/engines/sci/graphics/cache.cpp b/engines/sci/graphics/cache.cpp index ef8538349f..81bdab80ea 100644 --- a/engines/sci/graphics/cache.cpp +++ b/engines/sci/graphics/cache.cpp @@ -32,6 +32,7 @@ #include "sci/engine/selector.h" #include "sci/graphics/cache.h" #include "sci/graphics/font.h" +#include "sci/graphics/fontsjis.h" #include "sci/graphics/view.h" namespace Sci { @@ -67,8 +68,13 @@ GfxFont *GfxCache::getFont(GuiResourceId fontId) { if (_cachedFonts.size() >= MAX_CACHED_FONTS) purgeFontCache(); - if (!_cachedFonts.contains(fontId)) - _cachedFonts[fontId] = new GfxFont(_resMan, _screen, fontId); + if (!_cachedFonts.contains(fontId)) { + // Create special SJIS font in japanese games, when font 900 is selected + if ((fontId == 900) && (g_sci->getLanguage() == Common::JA_JPN)) + _cachedFonts[fontId] = new GfxFontSjis(_screen, fontId); + else + _cachedFonts[fontId] = new GfxFontFromResource(_resMan, _screen, fontId); + } return _cachedFonts[fontId]; } diff --git a/engines/sci/graphics/font.cpp b/engines/sci/graphics/font.cpp index 4bfe8f87dd..91cf01c912 100644 --- a/engines/sci/graphics/font.cpp +++ b/engines/sci/graphics/font.cpp @@ -30,7 +30,7 @@ namespace Sci { -GfxFont::GfxFont(ResourceManager *resMan, GfxScreen *screen, GuiResourceId resourceId) +GfxFontFromResource::GfxFontFromResource(ResourceManager *resMan, GfxScreen *screen, GuiResourceId resourceId) : _resourceId(resourceId), _screen(screen), _resMan(resMan) { assert(resourceId != -1); @@ -56,29 +56,29 @@ GfxFont::GfxFont(ResourceManager *resMan, GfxScreen *screen, GuiResourceId resou } } -GfxFont::~GfxFont() { +GfxFontFromResource::~GfxFontFromResource() { delete []_chars; _resMan->unlockResource(_resource); } -GuiResourceId GfxFont::getResourceId() { +GuiResourceId GfxFontFromResource::getResourceId() { return _resourceId; } -byte GfxFont::getHeight() { +byte GfxFontFromResource::getHeight() { return _fontHeight; } -byte GfxFont::getCharWidth(byte chr) { +byte GfxFontFromResource::getCharWidth(uint16 chr) { return chr < _numChars ? _chars[chr].w : 0; } -byte GfxFont::getCharHeight(byte chr) { +byte GfxFontFromResource::getCharHeight(uint16 chr) { return chr < _numChars ? _chars[chr].h : 0; } -byte *GfxFont::getCharData(byte chr) { +byte *GfxFontFromResource::getCharData(uint16 chr) { return chr < _numChars ? _resourceData + _chars[chr].offset + 2 : 0; } -void GfxFont::draw(int16 chr, int16 top, int16 left, byte color, bool greyedOutput) { +void GfxFontFromResource::draw(uint16 chr, int16 top, int16 left, byte color, bool greyedOutput) { int charWidth = MIN(getCharWidth(chr), _screen->getWidth() - left); int charHeight = MIN(getCharHeight(chr), _screen->getHeight() - top); byte b = 0, mask = 0xFF; diff --git a/engines/sci/graphics/font.h b/engines/sci/graphics/font.h index 975b7e712a..c405f5a0a0 100644 --- a/engines/sci/graphics/font.h +++ b/engines/sci/graphics/font.h @@ -30,23 +30,38 @@ namespace Sci { +class GfxFont { +public: + GfxFont() {}; + virtual ~GfxFont() {}; + + virtual GuiResourceId getResourceId() { return 0; }; + virtual byte getHeight() { return 0; }; + virtual bool isDoubleByte(uint16 chr) { return false; }; + virtual byte getCharWidth(uint16 chr) { return 0; }; + virtual byte getCharHeight(uint16 chr) { return 0; }; + virtual void draw(uint16 chr, int16 top, int16 left, byte color, bool greyedOutput) {}; +}; + + /** * Font class, handles loading of font resources and drawing characters to screen * every font resource has its own instance of this class */ -class GfxFont { +class GfxFontFromResource : public GfxFont { public: - GfxFont(ResourceManager *resMan, GfxScreen *screen, GuiResourceId resourceId); - ~GfxFont(); + GfxFontFromResource(ResourceManager *resMan, GfxScreen *screen, GuiResourceId resourceId); + ~GfxFontFromResource(); GuiResourceId getResourceId(); byte getHeight(); - byte getCharWidth(byte chr); - byte getCharHeight(byte chr); - byte *getCharData(byte chr); - void draw(int16 chr, int16 top, int16 left, byte color, bool greyedOutput); + byte getCharWidth(uint16 chr); + byte getCharHeight(uint16 chr); + void draw(uint16 chr, int16 top, int16 left, byte color, bool greyedOutput); private: + byte *getCharData(uint16 chr); + ResourceManager *_resMan; GfxScreen *_screen; diff --git a/engines/sci/graphics/fontsjis.cpp b/engines/sci/graphics/fontsjis.cpp new file mode 100644 index 0000000000..3e2d5217f7 --- /dev/null +++ b/engines/sci/graphics/fontsjis.cpp @@ -0,0 +1,80 @@ +/* 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 "sci/sci.h" +#include "sci/engine/state.h" +#include "sci/graphics/screen.h" +#include "sci/graphics/font.h" +#include "sci/graphics/fontsjis.h" + +namespace Sci { + +GfxFontSjis::GfxFontSjis(GfxScreen *screen, GuiResourceId resourceId) + : _resourceId(resourceId), _screen(screen) { + assert(resourceId != -1); + + if (!_screen->getUpscaledHires()) + error("I don't want to initialize, when not being in upscaled hires mode"); + + _commonFont = Graphics::FontSJIS::createFont(Common::kPlatformPC98); + + if (!_commonFont) + error("Could not load ScummVM's 'SJIS.FNT'"); +} + +GfxFontSjis::~GfxFontSjis() { +} + +GuiResourceId GfxFontSjis::getResourceId() { + return _resourceId; +} + +// Returns true for first byte of double byte characters +bool GfxFontSjis::isDoubleByte(uint16 chr) { + if ((chr == 0x5C) || (chr == 0x7E) || ((chr >= 0x81) && (chr <= 0x9F)) || ((chr >= 0xE0) && (chr <= 0xEF))) + return true; + return false; +} + +// We can do >>1, because returned char width/height is 8 or 16 exclusively. Font returns hires size, we need lowres +byte GfxFontSjis::getHeight() { + return _commonFont->getFontHeight() >> 1; +} + +byte GfxFontSjis::getCharWidth(uint16 chr) { + return _commonFont->getCharWidth(chr) >> 1; + +} +byte GfxFontSjis::getCharHeight(uint16 chr) { + return _commonFont->getFontHeight() >> 1; +} + +void GfxFontSjis::draw(uint16 chr, int16 top, int16 left, byte color, bool greyedOutput) { + // TODO: Check, if character fits on screen - if it doesn't we need to skip it + // Normally SCI cuts the character and draws the part that fits, but the common SJIS doesn't support that + _screen->putKanjiChar(_commonFont, left, top, chr, color); +} + +} // End of namespace Sci diff --git a/engines/sci/graphics/fontsjis.h b/engines/sci/graphics/fontsjis.h new file mode 100644 index 0000000000..4330342331 --- /dev/null +++ b/engines/sci/graphics/fontsjis.h @@ -0,0 +1,62 @@ +/* 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 SCI_GRAPHICS_FONTSJIS_H +#define SCI_GRAPHICS_FONTSJIS_H + +#include "graphics/sjis.h" + +#include "sci/graphics/helpers.h" + +namespace Sci { + +/** + * Special Font class, handles SJIS inside sci games, uses ScummVM SJIS support + */ +class GfxFontSjis : public GfxFont { +public: + GfxFontSjis(GfxScreen *screen, GuiResourceId resourceId); + ~GfxFontSjis(); + + GuiResourceId getResourceId(); + byte getHeight(); + bool isDoubleByte(uint16 chr); + byte getCharWidth(uint16 chr); + byte getCharHeight(uint16 chr); + void draw(uint16 chr, int16 top, int16 left, byte color, bool greyedOutput); + +private: + GfxScreen *_screen; + GuiResourceId _resourceId; + + Graphics::FontSJIS *_commonFont; + + byte _lastForDoubleByteWidth; + byte _lastForDoubleByteDraw; +}; + +} // End of namespace Sci + +#endif diff --git a/engines/sci/graphics/frameout.cpp b/engines/sci/graphics/frameout.cpp index 79cbc6c669..e401798233 100644 --- a/engines/sci/graphics/frameout.cpp +++ b/engines/sci/graphics/frameout.cpp @@ -243,7 +243,7 @@ void GfxFrameout::kernelFrameout() { if (lookup_selector(_segMan, itemEntry->object, kernel->_selectorCache.text, NULL, NULL) == kSelectorVariable) { Common::String text = _segMan->getString(GET_SEL32(_segMan, itemEntry->object, SELECTOR(text))); int16 fontRes = GET_SEL32V(_segMan, itemEntry->object, SELECTOR(font)); - GfxFont *font = new GfxFont(_resMan, _screen, fontRes); + GfxFont *font = new GfxFontFromResource(_resMan, _screen, fontRes); bool dimmed = GET_SEL32V(_segMan, itemEntry->object, SELECTOR(dimmed)); uint16 foreColor = GET_SEL32V(_segMan, itemEntry->object, SELECTOR(fore)); uint16 curX = itemEntry->x; diff --git a/engines/sci/graphics/screen.cpp b/engines/sci/graphics/screen.cpp index 4d39ca45e3..21f9b0afdd 100644 --- a/engines/sci/graphics/screen.cpp +++ b/engines/sci/graphics/screen.cpp @@ -234,6 +234,13 @@ void GfxScreen::drawLine(Common::Point startPoint, Common::Point endPoint, byte } } +// We put hires kanji chars onto upscaled background, so we need to adjust coordinates. Caller gives use low-res ones +void GfxScreen::putKanjiChar(Graphics::FontSJIS *commonFont, int16 x, int16 y, uint16 chr, byte color) { + byte *displayPtr = _displayScreen + y * _displayWidth * 2 + x * 2; + // we don't use outline, so color 0 is actually not used + commonFont->drawChar(displayPtr, chr, _displayWidth, 1, color, 0); +} + byte GfxScreen::getVisual(int x, int y) { return _visualScreen[y * _width + x]; } diff --git a/engines/sci/graphics/screen.h b/engines/sci/graphics/screen.h index 6d8b6f7c9a..3316b53c69 100644 --- a/engines/sci/graphics/screen.h +++ b/engines/sci/graphics/screen.h @@ -29,6 +29,8 @@ #include "sci/sci.h" #include "sci/graphics/helpers.h" +#include "graphics/sjis.h" + namespace Sci { #define SCI_SCREEN_MAXHEIGHT 400 @@ -75,6 +77,7 @@ public: bool getUpscaledHires() { return _upscaledHires; } + void putKanjiChar(Graphics::FontSJIS *commonFont, int16 x, int16 y, uint16 chr, byte color); byte getVisual(int x, int y); byte getPriority(int x, int y); byte getControl(int x, int y); diff --git a/engines/sci/graphics/text16.cpp b/engines/sci/graphics/text16.cpp index 9f39725692..efbfbde666 100644 --- a/engines/sci/graphics/text16.cpp +++ b/engines/sci/graphics/text16.cpp @@ -153,7 +153,7 @@ int16 GfxText16::CodeProcessing(const char *&text, GuiResourceId orgFontId, int1 // return max # of chars to fit maxwidth with full words int16 GfxText16::GetLongest(const char *text, int16 maxWidth, GuiResourceId orgFontId) { - char curChar; + uint16 curChar; int16 maxChars = 0, curCharCount = 0; uint16 width = 0; GuiResourceId oldFontId = GetFontId(); @@ -164,7 +164,11 @@ int16 GfxText16::GetLongest(const char *text, int16 maxWidth, GuiResourceId orgF return 0; while (width <= maxWidth) { - curChar = *text++; + curChar = (*(unsigned char *)text++); + if (_font->isDoubleByte(curChar)) { + curChar |= (*(unsigned char *)text++) << 8; + curCharCount++; + } switch (curChar) { case 0x7C: if (getSciVersion() >= SCI_VERSION_1_1) { @@ -193,8 +197,9 @@ int16 GfxText16::GetLongest(const char *text, int16 maxWidth, GuiResourceId orgF curCharCount++; } if (maxChars == 0) { - // Is Kanji - maxChars = curCharCount - 1; + // Text w/o space, supposingly kanji - we don't adjust back to last char here strangely. If we do, we don't + // get the same text cutting like in sierra sci + maxChars = curCharCount; } SetFont(oldFontId); _ports->penColor(oldPenColor); @@ -202,7 +207,7 @@ int16 GfxText16::GetLongest(const char *text, int16 maxWidth, GuiResourceId orgF } void GfxText16::Width(const char *text, int16 from, int16 len, GuiResourceId orgFontId, int16 &textWidth, int16 &textHeight) { - unsigned char curChar; + uint16 curChar; GuiResourceId oldFontId = GetFontId(); int16 oldPenColor = _ports->_curPort->penClr; @@ -212,7 +217,11 @@ void GfxText16::Width(const char *text, int16 from, int16 len, GuiResourceId org if (_font) { text += from; while (len--) { - curChar = *text++; + curChar = (*(unsigned char *)text++); + if (_font->isDoubleByte(curChar)) { + curChar |= (*(unsigned char *)text++) << 8; + len--; + } switch (curChar) { case 0x0A: case 0x0D: @@ -266,10 +275,6 @@ int16 GfxText16::Size(Common::Rect &rect, const char *str, GuiResourceId fontId, rect.right = (maxWidth ? maxWidth : 192); const char*p = str; while (*p) { - //if (*p == 0xD || *p == 0xA) { - // p++; - // continue; - //} charCount = GetLongest(p, rect.right, oldFontId); if (charCount == 0) break; @@ -288,7 +293,7 @@ int16 GfxText16::Size(Common::Rect &rect, const char *str, GuiResourceId fontId, // returns maximum font height used void GfxText16::Draw(const char *text, int16 from, int16 len, GuiResourceId orgFontId, int16 orgPenColor) { - int16 curChar, charWidth; + uint16 curChar, charWidth; Common::Rect rect; GetFont(); @@ -299,7 +304,11 @@ void GfxText16::Draw(const char *text, int16 from, int16 len, GuiResourceId orgF rect.bottom = rect.top + _ports->_curPort->fontHeight; text += from; while (len--) { - curChar = (*text++); + curChar = (*(unsigned char *)text++); + if (_font->isDoubleByte(curChar)) { + curChar |= (*(unsigned char *)text++) << 8; + len--; + } switch (curChar) { case 0x0A: case 0x0D: @@ -349,10 +358,6 @@ void GfxText16::Box(const char *text, int16 bshow, const Common::Rect &rect, Tex SetFont(fontId); while (*text) { -// if (*text == 0xD || *text == 0xA) { -// text++; -// continue; -// } charCount = GetLongest(text, rect.width(), orgFontId); if (charCount == 0) break; diff --git a/engines/sci/module.mk b/engines/sci/module.mk index 0a110f2aa1..852f97b225 100644 --- a/engines/sci/module.mk +++ b/engines/sci/module.mk @@ -41,6 +41,7 @@ MODULE_OBJS := \ graphics/coordadjuster.o \ graphics/cursor.o \ graphics/font.o \ + graphics/fontsjis.o \ graphics/gui.o \ graphics/menu.o \ graphics/paint.o \ -- cgit v1.2.3