diff options
author | Paul Gilbert | 2016-08-27 13:59:08 -0400 |
---|---|---|
committer | Paul Gilbert | 2016-08-27 13:59:08 -0400 |
commit | f5ab3d1cd9eb3a884b0ab5d0b154a4f9cccc74b7 (patch) | |
tree | 771a8d2b3fddf96c17a1d81d42cb08dfba09d110 /engines/titanic/support/font.cpp | |
parent | 873d555add9aaf5eb0d021518f5134142e2c2ff6 (diff) | |
parent | 5ea32efbb0ecb3e6b8336ad3c2edd3905ea5b89a (diff) | |
download | scummvm-rg350-f5ab3d1cd9eb3a884b0ab5d0b154a4f9cccc74b7.tar.gz scummvm-rg350-f5ab3d1cd9eb3a884b0ab5d0b154a4f9cccc74b7.tar.bz2 scummvm-rg350-f5ab3d1cd9eb3a884b0ab5d0b154a4f9cccc74b7.zip |
Merge branch 'master' into xeen
Diffstat (limited to 'engines/titanic/support/font.cpp')
-rw-r--r-- | engines/titanic/support/font.cpp | 281 |
1 files changed, 281 insertions, 0 deletions
diff --git a/engines/titanic/support/font.cpp b/engines/titanic/support/font.cpp new file mode 100644 index 0000000000..69c0efe504 --- /dev/null +++ b/engines/titanic/support/font.cpp @@ -0,0 +1,281 @@ +/* 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 "common/textconsole.h" +#include "titanic/support/font.h" +#include "titanic/support/files_manager.h" +#include "titanic/titanic.h" + +namespace Titanic { + +STFont::STFont() { + _dataPtr = nullptr; + _dataSize = 0; + _fontHeight = 0; + _dataWidth = 0; + _fontR = _fontG = _fontB = 0; +} + +STFont::~STFont() { + delete[] _dataPtr; +} + +void STFont::load(int fontNumber) { + assert(!_dataPtr); + Common::SeekableReadStream *stream = g_vm->_filesManager->getResource( + CString::format("STFONT/%d", fontNumber)); + if (!stream) + error("Could not locate the specified font"); + + _fontHeight = stream->readUint32LE(); + _dataWidth = stream->readUint32LE(); + for (uint idx = 0; idx < 256; ++idx) + _chars[idx]._width = stream->readUint32LE(); + for (uint idx = 0; idx < 256; ++idx) + _chars[idx]._offset = stream->readUint32LE(); + + _dataSize = stream->readUint32LE(); + _dataPtr = new byte[_dataSize]; + stream->read(_dataPtr, _dataSize); + + delete stream; +} + +void STFont::setColor(byte r, byte g, byte b) { + _fontR = r; + _fontG = g; + _fontB = b; +} + +uint16 STFont::getColor() const { + return g_system->getScreenFormat().RGBToColor(_fontR, _fontG, _fontB); +} + +int STFont::getTextBounds(const CString &str, int maxWidth, Point *sizeOut) const { + Point textSize; + + // Reset output dimensions if provided + if (sizeOut) + *sizeOut = Point(0, 0); + + if (_fontHeight == 0 || !_dataPtr) + // No font, so return immediately + return 0; + + // Loop through the characters of the string + if (!str.empty()) { + for (const char *strP = str.c_str(); *strP; ++strP) { + if (*strP == TEXTCMD_NPC) { + strP += 3; + } else if (*strP == TEXTCMD_SET_COLOR) { + strP += 4; + } else { + if (*strP == ' ') { + // Check fo rline wrapping + checkLineWrap(textSize, maxWidth, strP); + } + + extendBounds(textSize, *strP, maxWidth); + } + } + } + + if (sizeOut) + *sizeOut = textSize; + + return textSize.y + _fontHeight; +} + +int STFont::stringWidth(const CString &text) const { + if (text.empty()) + return 0; + + const char *srcP = text.c_str(); + int total = 0; + char c; + while ((c = *srcP++)) { + if (c == 26) { + // Skip over command parameter bytes + srcP += 3; + } else if (c == TEXTCMD_SET_COLOR) { + // Skip over command parameter bytes + srcP += 4; + } else if (c != '\n') { + total += _chars[(byte)c]._width; + } + } + + return total; +} + +int STFont::writeString(CVideoSurface *surface, const Rect &rect1, const Rect &destRect, + int yOffset, const CString &str, CTextCursor *textCursor) { + if (!_fontHeight || !_dataPtr) + return -1; + + Point textSize(0, -yOffset); + Rect destBounds = destRect; + destBounds.constrain(rect1); + if (destBounds.isEmpty()) + return -1; + + const char *endP = nullptr; + const char *strEndP = str.c_str() + str.size() - 1; + for (const char *srcP = str.c_str(); *srcP; ++srcP) { + if (*srcP == TEXTCMD_NPC) { + srcP += 3; + } else if (*srcP == TEXTCMD_SET_COLOR) { + // Change the color used for characters + byte r = *++srcP; + byte g = *++srcP; + byte b = *++srcP; + ++srcP; + setColor(r, g, b); + } else { + if (*srcP == ' ') { + // Check fo rline wrapping + checkLineWrap(textSize, rect1.width(), srcP); + if (!*srcP) + return endP - str.c_str(); + } + + if (*srcP != '\n') { + WriteCharacterResult result = writeChar(surface, *srcP, textSize, rect1, &destBounds); + if (result == WC_OUTSIDE_BOTTOM) + return endP - str.c_str(); + else if (result == WC_IN_BOUNDS) + endP = srcP; + } + + if (srcP < strEndP) + extendBounds(textSize, *srcP, rect1.width()); + } + } + + if (textCursor && textCursor->getMode() == -2) { + Point cursorPos(rect1.left + textSize.x, rect1.top + textSize.y); + textCursor->setPos(cursorPos); + } + + return endP ? endP - str.c_str() : 0; +} + +WriteCharacterResult STFont::writeChar(CVideoSurface *surface, unsigned char c, const Point &pt, + const Rect &destRect, const Rect *srcRect) { + if (c == 233) + c = '$'; + + Rect tempRect; + tempRect.left = _chars[c]._offset; + tempRect.right = _chars[c]._offset + _chars[c]._width; + tempRect.top = 0; + tempRect.bottom = _fontHeight; + Point destPos(pt.x + destRect.left, pt.y + destRect.top); + + if (srcRect->isEmpty()) + srcRect = &destRect; + if (destPos.y > srcRect->bottom) + return WC_OUTSIDE_BOTTOM; + + if ((destPos.y + tempRect.height()) > srcRect->bottom) { + tempRect.bottom += tempRect.top - destPos.y; + } + + if (destPos.y < srcRect->top) { + if ((tempRect.height() + destPos.y) < srcRect->top) + return WC_OUTSIDE_TOP; + + tempRect.top += srcRect->top - destPos.y; + destPos.y = srcRect->top; + } + + if (destPos.x < srcRect->left) { + if ((tempRect.width() + destPos.x) < srcRect->left) + return WC_OUTSIDE_LEFT; + + tempRect.left += srcRect->left - destPos.x; + destPos.x = srcRect->left; + } else { + if ((tempRect.width() + destPos.x) > srcRect->right) { + if (destPos.x > srcRect->right) + return WC_OUTSIDE_RIGHT; + + tempRect.right += srcRect->left - destPos.x; + } + } + + copyRect(surface, destPos, tempRect); + return WC_IN_BOUNDS; +} + +void STFont::copyRect(CVideoSurface *surface, const Point &pt, Rect &rect) { + if (surface->lock()) { + uint16 *lineP = surface->getBasePtr(pt.x, pt.y); + uint16 color = getColor(); + + for (int yp = rect.top; yp < rect.bottom; ++yp, lineP += surface->getWidth()) { + uint16 *destP = lineP; + for (int xp = rect.left; xp < rect.right; ++xp, ++destP) { + const byte *srcP = _dataPtr + yp * _dataWidth + xp; + surface->changePixel(destP, &color, *srcP >> 3, true); + } + } + + surface->unlock(); + } +} + +void STFont::extendBounds(Point &textSize, byte c, int maxWidth) const { + textSize.x += _chars[c]._width; + + if (c == '\n' || textSize.x > maxWidth) { + textSize.x = 0; + textSize.y += _fontHeight; + } +} + +void STFont::checkLineWrap(Point &textSize, int maxWidth, const char *&str) const { + bool flag = false; + int totalWidth = 0; + for (const char *srcPtr = str; *srcPtr && *srcPtr != ' '; ++srcPtr) { + if (*srcPtr == ' ' && flag) + break; + + if (*srcPtr == TEXTCMD_NPC) { + srcPtr += 3; + } else if (*srcPtr == TEXTCMD_SET_COLOR) { + srcPtr += 4; + } else { + totalWidth += _chars[(byte)*srcPtr]._width; + flag = true; + } + } + + if ((textSize.x + totalWidth) >= maxWidth && totalWidth < maxWidth) { + // Word wrap + textSize.x = 0; + textSize.y += _fontHeight; + ++str; + } +} + +} // End of namespace Titanic |