scummvm/graphics/big5.cpp
2023-04-29 13:37:45 +02:00

135 lines
4.4 KiB
C++

/* 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 3 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, see <http://www.gnu.org/licenses/>.
*
*/
#include "graphics/big5.h"
namespace Graphics {
Big5Font::Big5Font() : _chineseTraditionalHeight(0) {
}
Big5Font::~Big5Font() {
_chineseTraditionalFont.clear();
_chineseTraditionalIndex.clear();
}
void Big5Font::ChineseTraditionalGlyph::makeOutline(int height) {
outline[0][0] = 0;
outline[0][1] = 0;
// OR into outline the original bitmap moved by 1 pixel
// 1 pixel down
for (int y = 0; y < height - 1; y++) {
outline[y+1][0] = bitmap[y][0];
outline[y+1][1] = bitmap[y][1];
}
// 1 pixel up
for (int y = 0; y < height - 1; y++) {
outline[y][0] |= bitmap[y+1][0];
outline[y][1] |= bitmap[y+1][1];
}
for (int y = 0; y < height; y++) {
// 1 pixel right
outline[y][0] |= bitmap[y][0] >> 1;
outline[y][1] |= bitmap[y][0] << 7;
outline[y][1] |= bitmap[y][1] >> 1;
// 1 pixel left
outline[y][0] |= bitmap[y][0] << 1;
outline[y][0] |= bitmap[y][1] >> 7;
outline[y][1] |= bitmap[y][1] << 1;
}
// Then AND-out the original bitmap
for (int y = 0; y < height; y++) {
outline[y][0] &= ~bitmap[y][0];
outline[y][1] &= ~bitmap[y][1];
}
}
void Big5Font::loadPrefixedRaw(Common::ReadStream &input, int height) {
_chineseTraditionalHeight = height;
_chineseTraditionalFont.clear();
_chineseTraditionalIndex = Common::move(Common::Array<int>(0x8000, -1));
// So far the smallest version had 1981 glyphs. Optimize a little bit for this number
// but don't rely on it in any way
_chineseTraditionalFont.reserve(1981);
while(!input.eos()) {
// Big-endian because it's not really a u16 but a big5 sequence.
uint16 ch = input.readUint16BE();
ChineseTraditionalGlyph glyph;
if (input.eos())
break;
if (ch == 0xffff)
break;
if (!(ch & 0x8000))
continue;
memset(&glyph.bitmap, 0, sizeof(glyph.bitmap));
memset(&glyph.outline, 0, sizeof(glyph.outline));
input.read(&glyph.bitmap, (kChineseTraditionalWidth / 8) * _chineseTraditionalHeight);
glyph.makeOutline(height);
_chineseTraditionalIndex[ch & 0x7fff] = _chineseTraditionalFont.size();
_chineseTraditionalFont.push_back(glyph);
}
}
template <class T> bool Big5Font::drawReal(byte *dest, uint16 textChar, int maxX, int maxY, uint32 destPitch, byte color, byte outlineColor, bool outline) const {
int glyphIdx = _chineseTraditionalIndex[textChar & 0x7fff];
if (glyphIdx < 0) {
return false;
}
const ChineseTraditionalGlyph& glyph = _chineseTraditionalFont[glyphIdx];
for (int y = 0; y < _chineseTraditionalHeight && y < maxY; y++) {
T *cur = (T*) (dest + y * destPitch);
T *curMax = cur + maxX;
for (int byte = 0; byte < 2; byte++)
for (int bit = 0; bit < 8 && cur < curMax; bit++, cur++)
if ((glyph.bitmap[y][byte] << bit) & 0x80)
*cur = color;
else if (outline && (((glyph.outline[y][byte] << bit) & 0x80)))
*cur = outlineColor;
}
return true;
}
bool Big5Font::drawBig5Char(byte *dest, uint16 ch, int maxX, int maxY, uint32 destPitch, byte color, byte outlineColor, bool outline, int bpp) const {
switch(bpp) {
case 4:
return drawReal<uint32>(dest, ch, maxX, maxY, destPitch, color, outlineColor, outline);
case 2:
return drawReal<uint16>(dest, ch, maxX, maxY, destPitch, color, outlineColor, outline);
case 1:
return drawReal<uint8>(dest, ch, maxX, maxY, destPitch, color, outlineColor, outline);
default:
error("Big5 font for bpp=%d is not supported", bpp);
}
}
bool Big5Font::drawBig5Char(Graphics::Surface *surf, uint16 ch, const Common::Point &pt, uint32 color, byte outlineColor, bool outline) const {
return drawBig5Char((byte*)surf->getBasePtr(pt.x, pt.y), ch, surf->w - pt.x, surf->h - pt.y, surf->pitch, color, outlineColor, outline, surf->format.bytesPerPixel);
}
}