aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEugene Sandulenko2014-08-09 15:26:20 +0200
committerEugene Sandulenko2014-08-09 15:26:20 +0200
commit908b4113c11686de5e8bcc3014917c92ff8961b6 (patch)
tree8e82ad1ef4cd6c2a10fbbd64837d8f9475209162
parente11fe13620be4b500c91b6141337786948c13694 (diff)
parentc23ac81e36904d41852069477aae8cc1b672ebf0 (diff)
downloadscummvm-rg350-908b4113c11686de5e8bcc3014917c92ff8961b6.tar.gz
scummvm-rg350-908b4113c11686de5e8bcc3014917c92ff8961b6.tar.bz2
scummvm-rg350-908b4113c11686de5e8bcc3014917c92ff8961b6.zip
Merge pull request #484 from wonst719/korean-work
SCUMM: Improve non-Towns CJK text rendering
-rw-r--r--engines/scumm/charset.cpp95
-rw-r--r--engines/scumm/charset.h29
-rw-r--r--engines/scumm/nut_renderer.cpp55
-rw-r--r--engines/scumm/smush/smush_font.cpp66
4 files changed, 190 insertions, 55 deletions
diff --git a/engines/scumm/charset.cpp b/engines/scumm/charset.cpp
index 185ebbce6e..e546c805b5 100644
--- a/engines/scumm/charset.cpp
+++ b/engines/scumm/charset.cpp
@@ -253,7 +253,7 @@ CharsetRenderer::~CharsetRenderer() {
CharsetRendererCommon::CharsetRendererCommon(ScummEngine *vm)
: CharsetRenderer(vm), _bytesPerPixel(0), _fontHeight(0), _numChars(0) {
- _shadowMode = false;
+ _enableShadow = false;
_shadowColor = 0;
}
@@ -392,6 +392,10 @@ int CharsetRenderer::getStringWidth(int arg, const byte *text) {
} else if (chr & 0x80) {
pos++;
width += _vm->_2byteWidth;
+ // Original keeps glyph width and character dimensions separately
+ if (_vm->_language == Common::KO_KOR || _vm->_language == Common::ZH_TWN) {
+ width++;
+ }
continue;
}
}
@@ -478,6 +482,12 @@ void CharsetRenderer::addLinebreaks(int a, byte *str, int pos, int maxwidth) {
} else if (chr & 0x80) {
pos++;
curw += _vm->_2byteWidth;
+ // Original keeps glyph width and character dimensions separately
+ if (_vm->_language == Common::KO_KOR || _vm->_language == Common::ZH_TWN) {
+ curw++;
+ }
+ } else {
+ curw += getCharWidth(chr);
}
} else {
curw += getCharWidth(chr);
@@ -507,12 +517,17 @@ int CharsetRendererV3::getCharWidth(uint16 chr) {
return spacing;
}
-void CharsetRendererV3::enableShadow(bool enable) {
+void CharsetRendererPC::enableShadow(bool enable) {
_shadowColor = 0;
- _shadowMode = enable;
+ _enableShadow = enable;
+
+ if (_vm->_game.version >= 7 && _vm->_language == Common::KO_KOR)
+ _shadowType = kHorizontalShadowType;
+ else
+ _shadowType = kNormalShadowType;
}
-void CharsetRendererV3::drawBits1(Graphics::Surface &dest, int x, int y, const byte *src, int drawTop, int width, int height) {
+void CharsetRendererPC::drawBits1(Graphics::Surface &dest, int x, int y, const byte *src, int drawTop, int width, int height) {
byte *dst = (byte *)dest.getBasePtr(x, y);
byte bits = 0;
@@ -525,8 +540,12 @@ void CharsetRendererV3::drawBits1(Graphics::Surface &dest, int x, int y, const b
if ((x % 8) == 0)
bits = *src++;
if ((bits & revBitMask(x % 8)) && y + drawTop >= 0) {
- if (_shadowMode)
- dst[1] = dst2[0] = dst2[1] = _shadowColor;
+ if (_enableShadow) {
+ if (_shadowType == kNormalShadowType)
+ dst[1] = dst2[0] = dst2[1] = _shadowColor;
+ else if (_shadowType == kHorizontalShadowType)
+ dst[1] = _shadowColor;
+ }
dst[0] = col;
}
dst += dest.format.bytesPerPixel;
@@ -615,7 +634,7 @@ void CharsetRendererV3::printChar(int chr, bool ignoreCharsetMask) {
if (_left + origWidth > _right + 1)
return;
- if (_shadowMode) {
+ if (_enableShadow) {
width++;
height++;
}
@@ -658,7 +677,7 @@ void CharsetRendererV3::printChar(int chr, bool ignoreCharsetMask) {
if (_str.right < _left) {
_str.right = _left;
- if (_shadowMode)
+ if (_enableShadow)
_str.right++;
}
@@ -776,11 +795,15 @@ void CharsetRendererClassic::printChar(int chr, bool ignoreCharsetMask) {
printCharIntern(is2byte, _charPtr, _origWidth, _origHeight, _width, _height, vs, ignoreCharsetMask);
+ // Original keeps glyph width and character dimensions separately
+ if ((_vm->_language == Common::ZH_TWN || _vm->_language == Common::KO_KOR) && is2byte)
+ _origWidth++;
+
_left += _origWidth;
if (_str.right < _left) {
_str.right = _left;
- if (_vm->_game.platform != Common::kPlatformFMTowns && _shadowMode)
+ if (_vm->_game.platform != Common::kPlatformFMTowns && _enableShadow)
_str.right++;
}
@@ -844,7 +867,10 @@ void CharsetRendererClassic::printCharIntern(bool is2byte, const byte *charPtr,
drawTop = _top - _vm->_screenTop;
}
- drawBitsN(dstSurface, dstPtr, charPtr, *_fontPtr, drawTop, origWidth, origHeight);
+ if (is2byte && _vm->_game.platform != Common::kPlatformFMTowns)
+ drawBits1(dstSurface, _left, drawTop, charPtr, drawTop, origWidth, origHeight);
+ else
+ drawBitsN(dstSurface, dstPtr, charPtr, *_fontPtr, drawTop, origWidth, origHeight);
if (_blitAlso && vs->hasTwoBuffers) {
// FIXME: Revisiting this code, I think the _blitAlso mode is likely broken
@@ -884,6 +910,24 @@ void CharsetRendererClassic::printCharIntern(bool is2byte, const byte *charPtr,
}
bool CharsetRendererClassic::prepareDraw(uint16 chr) {
+ bool is2byte = (chr >= 256 && _vm->_useCJKMode);
+ if (is2byte) {
+ if (_vm->_language == Common::KO_KOR)
+ enableShadow(true);
+
+ _charPtr = _vm->get2byteCharPtr(chr);
+ _width = _origWidth = _vm->_2byteWidth;
+ _height = _origHeight = _vm->_2byteHeight;
+ _offsX = _offsY = 0;
+
+ if (_enableShadow) {
+ _width++;
+ _height++;
+ }
+
+ return true;
+ }
+
uint32 charOffs = READ_LE_UINT32(_fontPtr + chr * 4 + 4);
assert(charOffs < 0x14000);
if (!charOffs)
@@ -908,8 +952,14 @@ bool CharsetRendererClassic::prepareDraw(uint16 chr) {
void CharsetRendererClassic::drawChar(int chr, Graphics::Surface &s, int x, int y) {
if (!prepareDraw(chr))
return;
+
byte *dst = (byte *)s.getBasePtr(x, y);
- drawBitsN(s, dst, _charPtr, *_fontPtr, y, _width, _height);
+
+ bool is2byte = (_vm->_useCJKMode && chr >= 256);
+ if (is2byte)
+ drawBits1(s, x, y, _charPtr, y, _width, _height);
+ else
+ drawBitsN(s, dst, _charPtr, *_fontPtr, y, _width, _height);
}
void CharsetRendererClassic::drawBitsN(const Graphics::Surface &s, byte *dst, const byte *src, byte bpp, int drawTop, int width, int height) {
@@ -982,7 +1032,7 @@ int CharsetRendererTownsV3::getFontHeight() {
void CharsetRendererTownsV3::enableShadow(bool enable) {
_shadowColor = 8;
- _shadowMode = enable;
+ _enableShadow = enable;
#ifndef DISABLE_TOWNS_DUAL_LAYER_MODE
_shadowColor = 0x88;
@@ -1027,13 +1077,13 @@ void CharsetRendererTownsV3::drawBits1(Graphics::Surface &dest, int x, int y, co
bits = *src++;
if ((bits & revBitMask(x % 8)) && y + drawTop >= 0) {
if (dest.format.bytesPerPixel == 2) {
- if (_shadowMode) {
+ if (_enableShadow) {
WRITE_UINT16(dst + 2, _vm->_16BitPalette[_shadowColor]);
WRITE_UINT16(dst + dest.pitch, _vm->_16BitPalette[_shadowColor]);
}
WRITE_UINT16(dst, _vm->_16BitPalette[_color]);
} else {
- if (_shadowMode) {
+ if (_enableShadow) {
#ifndef DISABLE_TOWNS_DUAL_LAYER_MODE
if (scale2x) {
dst[2] = dst[3] = dst2[2] = dst2[3] = _shadowColor;
@@ -1124,11 +1174,11 @@ void CharsetRendererPCE::drawBits1(Graphics::Surface &dest, int x, int y, const
bits = *src++;
if ((bits & revBitMask(bitCount % 8)) && y + drawTop >= 0) {
if (dest.format.bytesPerPixel == 2) {
- if (_shadowMode)
+ if (_enableShadow)
WRITE_UINT16(dst + dest.pitch + 2, _vm->_16BitPalette[_shadowColor]);
WRITE_UINT16(dst, _vm->_16BitPalette[_color]);
} else {
- if (_shadowMode)
+ if (_enableShadow)
*(dst + dest.pitch + 1) = _shadowColor;
*dst = _color;
}
@@ -1227,7 +1277,8 @@ void CharsetRendererNut::printChar(int chr, bool ignoreCharsetMask) {
int width = _current->getCharWidth(chr);
int height = _current->getCharHeight(chr);
- if (chr >= 256 && _vm->_useCJKMode)
+ bool is2byte = chr >= 256 && _vm->_useCJKMode;
+ if (is2byte)
width = _vm->_2byteWidth;
shadow.right = _left + width;
@@ -1259,8 +1310,8 @@ void CharsetRendererNut::printChar(int chr, bool ignoreCharsetMask) {
_str.left = _left;
// Original keeps glyph width and character dimensions separately
- if (_vm->_language == Common::ZH_TWN && width == 16)
- width = 17;
+ if ((_vm->_language == Common::ZH_TWN || _vm->_language == Common::KO_KOR) && is2byte)
+ width++;
_left += width;
@@ -1327,7 +1378,7 @@ void CharsetRendererNES::printChar(int chr, bool ignoreCharsetMask) {
if (_str.right < _left) {
_str.right = _left;
- if (_shadowMode)
+ if (_enableShadow)
_str.right++;
}
@@ -1483,7 +1534,7 @@ bool CharsetRendererTownsClassic::prepareDraw(uint16 chr) {
_origHeight = _height = _vm->_2byteHeight;
_charPtr = _vm->get2byteCharPtr(chr);
_offsX = _offsY = 0;
- if (_shadowMode) {
+ if (_enableShadow) {
_width++;
_height++;
}
@@ -1495,7 +1546,7 @@ bool CharsetRendererTownsClassic::prepareDraw(uint16 chr) {
}
void CharsetRendererTownsClassic::setupShadowMode() {
- _shadowMode = true;
+ _enableShadow = true;
_shadowColor = _vm->_townsCharsetColorMap[0];
assert(_vm->_cjkFont);
diff --git a/engines/scumm/charset.h b/engines/scumm/charset.h
index 5a9977b7d6..b4b3d88ccd 100644
--- a/engines/scumm/charset.h
+++ b/engines/scumm/charset.h
@@ -100,7 +100,7 @@ protected:
int _numChars;
byte _shadowColor;
- bool _shadowMode;
+ bool _enableShadow;
public:
CharsetRendererCommon(ScummEngine *vm);
@@ -110,7 +110,24 @@ public:
virtual int getFontHeight();
};
-class CharsetRendererClassic : public CharsetRendererCommon {
+class CharsetRendererPC : public CharsetRendererCommon {
+ enum ShadowType {
+ kNoShadowType,
+ kNormalShadowType,
+ kHorizontalShadowType
+ };
+
+ ShadowType _shadowType;
+
+protected:
+ virtual void enableShadow(bool enable);
+ virtual void drawBits1(Graphics::Surface &dest, int x, int y, const byte *src, int drawTop, int width, int height);
+
+public:
+ CharsetRendererPC(ScummEngine *vm) : CharsetRendererCommon(vm), _shadowType(kNoShadowType) { }
+};
+
+class CharsetRendererClassic : public CharsetRendererPC {
protected:
virtual void drawBitsN(const Graphics::Surface &s, byte *dst, const byte *src, byte bpp, int drawTop, int width, int height);
void printCharIntern(bool is2byte, const byte *charPtr, int origWidth, int origHeight, int width, int height, VirtScreen *vs, bool ignoreCharsetMask);
@@ -124,7 +141,7 @@ protected:
VirtScreenNumber _drawScreen;
public:
- CharsetRendererClassic(ScummEngine *vm) : CharsetRendererCommon(vm) {}
+ CharsetRendererClassic(ScummEngine *vm) : CharsetRendererPC(vm) {}
void printChar(int chr, bool ignoreCharsetMask);
void drawChar(int chr, Graphics::Surface &s, int x, int y);
@@ -170,10 +187,8 @@ public:
int getCharWidth(uint16 chr) { return 8; }
};
-class CharsetRendererV3 : public CharsetRendererCommon {
+class CharsetRendererV3 : public CharsetRendererPC {
protected:
- virtual void enableShadow(bool enable);
- virtual void drawBits1(Graphics::Surface &dest, int x, int y, const byte *src, int drawTop, int width, int height);
virtual int getDrawWidthIntern(uint16 chr);
virtual int getDrawHeightIntern(uint16 chr);
virtual void setDrawCharIntern(uint16 chr) {}
@@ -181,7 +196,7 @@ protected:
const byte *_widthTable;
public:
- CharsetRendererV3(ScummEngine *vm) : CharsetRendererCommon(vm) {}
+ CharsetRendererV3(ScummEngine *vm) : CharsetRendererPC(vm) {}
void printChar(int chr, bool ignoreCharsetMask);
void drawChar(int chr, Graphics::Surface &s, int x, int y);
diff --git a/engines/scumm/nut_renderer.cpp b/engines/scumm/nut_renderer.cpp
index 1d5761ef48..d8672c473c 100644
--- a/engines/scumm/nut_renderer.cpp
+++ b/engines/scumm/nut_renderer.cpp
@@ -395,10 +395,6 @@ void NutRenderer::drawChar(const Graphics::Surface &s, byte c, int x, int y, byt
}
void NutRenderer::draw2byte(const Graphics::Surface &s, int c, int x, int y, byte color) {
- // FIXME: This gets passed a const destination Surface. Intuitively this
- // should never get written to. But sadly it does... For now we simply
- // cast the const qualifier away.
- byte *dst = (byte *)const_cast<void *>(s.getBasePtr(x, y));
const int width = _vm->_2byteWidth;
const int height = MIN(_vm->_2byteHeight, s.h - y);
const byte *src = _vm->get2byteCharPtr(c);
@@ -408,17 +404,50 @@ void NutRenderer::draw2byte(const Graphics::Surface &s, int c, int x, int y, byt
return;
}
- for (int ty = 0; ty < height; ty++) {
- for (int tx = 0; tx < width; tx++) {
- if ((tx & 7) == 0)
- bits = *src++;
- if (x + tx < 0 || x + tx >= s.w || y + ty < 0)
- continue;
- if (bits & revBitMask(tx % 8)) {
- dst[tx] = color;
+ enum ShadowMode {
+ kNone,
+ kKoreanV8ShadowMode
+ };
+
+ ShadowMode shadowMode = kNone;
+
+ if (_vm->_language == Common::KO_KOR && _vm->_game.version == 8) {
+ shadowMode = kKoreanV8ShadowMode;
+ }
+
+ int shadowOffsetXTable[4] = {-1, 0, 1, 0};
+ int shadowOffsetYTable[4] = {0, 1, 0, 0};
+ int shadowOffsetColorTable[4] = {0, 0, 0, color};
+
+ int shadowIdx = 3;
+ if (shadowMode == kKoreanV8ShadowMode)
+ shadowIdx = 0;
+
+ const byte *origSrc = src;
+
+ for (; shadowIdx < 4; shadowIdx++) {
+ int offX = x + shadowOffsetXTable[shadowIdx];
+ int offY = y + shadowOffsetYTable[shadowIdx];
+ byte drawColor = shadowOffsetColorTable[shadowIdx];
+
+ // FIXME: This gets passed a const destination Surface. Intuitively this
+ // should never get written to. But sadly it does... For now we simply
+ // cast the const qualifier away.
+ byte *dst = (byte *)const_cast<void *>(s.getBasePtr(offX, offY));
+ src = origSrc;
+
+ for (int ty = 0; ty < height; ty++) {
+ for (int tx = 0; tx < width; tx++) {
+ if ((tx & 7) == 0)
+ bits = *src++;
+ if (offX + tx < 0 || offX + tx >= s.w || offY + ty < 0)
+ continue;
+ if (bits & revBitMask(tx % 8)) {
+ dst[tx] = drawColor;
+ }
}
+ dst += s.pitch;
}
- dst += s.pitch;
}
}
diff --git a/engines/scumm/smush/smush_font.cpp b/engines/scumm/smush/smush_font.cpp
index 4c04901b42..e2f75a6862 100644
--- a/engines/scumm/smush/smush_font.cpp
+++ b/engines/scumm/smush/smush_font.cpp
@@ -115,9 +115,7 @@ int SmushFont::drawChar(byte *buffer, int dst_width, int x, int y, byte chr) {
int SmushFont::draw2byte(byte *buffer, int dst_width, int x, int y, int idx) {
int w = _vm->_2byteWidth;
int h = _vm->_2byteHeight;
-
- byte *src = _vm->get2byteCharPtr(idx);
- byte *dst = buffer + dst_width * (y + (_vm->_game.id == GID_CMI ? 7 : (_vm->_game.id == GID_DIG ? 2 : 0))) + x;
+ const byte *src = _vm->get2byteCharPtr(idx);
byte bits = 0;
char color = (_color != -1) ? _color : 1;
@@ -128,18 +126,60 @@ int SmushFont::draw2byte(byte *buffer, int dst_width, int x, int y, int idx) {
if (_vm->_game.id == GID_FT)
color = 1;
- for (int j = 0; j < h; j++) {
- for (int i = 0; i < w; i++) {
- if ((i % 8) == 0)
- bits = *src++;
- if (bits & revBitMask(i % 8)) {
- dst[i + 1] = 0;
- dst[dst_width + i] = 0;
- dst[dst_width + i + 1] = 0;
- dst[i] = color;
+ enum ShadowMode {
+ kNone,
+ kNormalShadowMode,
+ kKoreanV7ShadowMode,
+ kKoreanV8ShadowMode
+ };
+
+ ShadowMode shadowMode = kNone;
+
+ if (_vm->_language == Common::KO_KOR) {
+ if (_vm->_game.version == 8)
+ shadowMode = kKoreanV8ShadowMode;
+ else
+ shadowMode = kKoreanV7ShadowMode;
+ }
+
+ int shadowOffsetXTable[4] = {-1, 0, 1, 0};
+ int shadowOffsetYTable[4] = {0, 1, 0, 0};
+ int shadowOffsetColorTable[4] = {0, 0, 0, color};
+
+ int shadowIdx = 3;
+ if (shadowMode == kKoreanV8ShadowMode)
+ shadowIdx = 0;
+ else if (shadowMode == kKoreanV7ShadowMode)
+ shadowIdx = 2;
+
+ const byte *origSrc = src;
+
+ for (; shadowIdx < 4; shadowIdx++) {
+ int offX = x + shadowOffsetXTable[shadowIdx];
+ int offY = y + shadowOffsetYTable[shadowIdx];
+ byte drawColor = shadowOffsetColorTable[shadowIdx];
+
+ src = origSrc;
+
+ byte *dst = buffer + dst_width * (offY + (_vm->_game.id == GID_CMI ? 7 : (_vm->_game.id == GID_DIG ? 2 : 0))) + offX;
+
+ for (int j = 0; j < h; j++) {
+ for (int i = 0; i < w; i++) {
+ if (offX + i < 0)
+ continue;
+ if ((i % 8) == 0)
+ bits = *src++;
+ if (bits & revBitMask(i % 8)) {
+ if (shadowMode == kNormalShadowMode) {
+ dst[i + 1] = 0;
+ dst[dst_width + i] = 0;
+ dst[dst_width + i + 1] = 0;
+ }
+ dst[i] = drawColor;
+ }
}
+ dst += dst_width;
}
- dst += dst_width;
}
return w + 1;
}