/* 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. * */ #include "lastexpress/data/font.h" #include "common/rect.h" #include "common/stream.h" #include "common/system.h" #include "common/textconsole.h" namespace LastExpress { Font::Font() : _numGlyphs(0), _glyphs(NULL), _glyphWidths(0) { memset(&_palette, 0, sizeof(_palette)); memset(&_charMap, 0, sizeof(_charMap)); } Font::~Font() { reset(); } void Font::reset() { delete[] _glyphs; delete[] _glyphWidths; } bool Font::load(Common::SeekableReadStream *stream) { if (!stream) return false; // Reset data reset(); // Read the palette for (uint i = 0; i < _paletteSize; i++) { _palette[i] = stream->readUint16LE(); } // Read the character map stream->read(_charMap, _charMapSize); // Read the glyphs _numGlyphs = stream->readUint16LE(); _glyphs = new byte[_numGlyphs * 18 * 8]; stream->read(_glyphs, _numGlyphs * 18 * 8); // TODO: Read something else? //uint16 unknown = fontFile->readByte(); //warning("unknown = %d", unknown); //warning("pos = %d", fontFile->pos()); //warning("left = %d", fontFile->size() - fontFile->pos()); //while (!fontFile->eos()) { //unknown = fontFile->readByte(); //warning("val = %d", unknown); //} // Precalculate glyph widths _glyphWidths = new byte[_numGlyphs]; for (uint16 i = 0; i < _numGlyphs; i++) { _glyphWidths[i] = getGlyphWidth(i); } delete stream; return true; } uint16 Font::getCharGlyph(uint16 c) const { //warning("%c", c); if (c >= 0x200) error("[Font::getCharGlyph] Invalid character %d", c); return _charMap[c]; } byte *Font::getGlyphImg(uint16 g) { if (!_glyphs) error("[Font::getGlyphImg] Invalid glyphs"); if (g >= _numGlyphs) error("[Font::getGlyphImg] Invalid glyph %d (%d available)", g, _numGlyphs); return _glyphs + g * 18 * 8; } uint8 Font::getGlyphWidth(uint16 g) { byte *p = getGlyphImg(g); uint8 maxLineWidth = 0; for (int j = 0; j < 18; j++) { uint8 currentLineWidth = 0; for (uint8 i = 0; i < 16; i++) { byte index; if (i % 2) index = *p & 0xf; else index = *p >> 4; uint16 color = _palette[index]; if (color != 0x1f) currentLineWidth = i; if (i % 2) p++; } if (currentLineWidth > maxLineWidth) maxLineWidth = currentLineWidth; } return maxLineWidth; } byte *Font::getCharImg(uint16 c) { return getGlyphImg(getCharGlyph(c)); } uint8 Font::getCharWidth(uint16 c) const{ if (c == 0x20) { // Space is a special case // TODO: this is an arbitrary value return 10; } else { if (!_glyphWidths) error("[Font::getCharWidth] Invalid glyphs widths"); return _glyphWidths[getCharGlyph(c)]; } } uint16 Font::getStringWidth(Common::String str) const { uint16 width = 0; for (uint i = 0; i < str.size(); i++) width += getCharWidth((unsigned char)str[i]); return width; } uint16 Font::getStringWidth(const uint16 *str, uint16 length) const { uint16 width = 0; for (uint i = 0; i < length; i++) width += getCharWidth(str[i]); return width; } void Font::drawChar(Graphics::Surface *surface, int16 x, int16 y, uint16 c) { byte *p = getCharImg(c); for (int16 j = 0; j < 18; j++) { for (int16 i = 0; i < 16; i++) { byte index; if (i % 2) index = *p & 0xf; else index = *p >> 4; uint16 color = _palette[index]; if (color != 0x1f) { surface->fillRect(Common::Rect(x+i, y+j, x+i+1, y+j+1), color); } if (i % 2) p++; } } } Common::Rect Font::drawString(Graphics::Surface *surface, int16 x, int16 y, Common::String str) { int16 currentX = x; for (uint i = 0; i < str.size(); i++) { drawChar(surface, currentX, y, (unsigned char)str[i]); currentX += getCharWidth((unsigned char)str[i]); } return Common::Rect(x, y, x + currentX, y + (int16)_charHeight); } Common::Rect Font::drawString(Graphics::Surface *surface, int16 x, int16 y, const uint16 *str, uint16 length) { int16 currentX = x; for (uint i = 0; i < length; i++) { drawChar(surface, currentX, y, str[i]); currentX += getCharWidth(str[i]); } return Common::Rect(x, y, x + currentX, y + (int16)_charHeight); } } // End of namespace LastExpress