aboutsummaryrefslogtreecommitdiff
path: root/scumm/charset.cpp
diff options
context:
space:
mode:
authorMax Horn2002-12-25 21:04:47 +0000
committerMax Horn2002-12-25 21:04:47 +0000
commitfca9ec09e7709ff4400d2a9a7fd76f4f21781006 (patch)
tree2c9dd18841983469c4780c75d90762f8a167c048 /scumm/charset.cpp
parentf1808d20ac90f4212fd14aeaf544a8aaac6a3fbc (diff)
downloadscummvm-rg350-fca9ec09e7709ff4400d2a9a7fd76f4f21781006.tar.gz
scummvm-rg350-fca9ec09e7709ff4400d2a9a7fd76f4f21781006.tar.bz2
scummvm-rg350-fca9ec09e7709ff4400d2a9a7fd76f4f21781006.zip
moved CharsetRendere into its own header/source file; changed Scumm::_charset into a pointer, to make it possible to use different implementations of it
svn-id: r6147
Diffstat (limited to 'scumm/charset.cpp')
-rw-r--r--scumm/charset.cpp386
1 files changed, 386 insertions, 0 deletions
diff --git a/scumm/charset.cpp b/scumm/charset.cpp
new file mode 100644
index 0000000000..0ae52733a4
--- /dev/null
+++ b/scumm/charset.cpp
@@ -0,0 +1,386 @@
+/* ScummVM - Scumm Interpreter
+ * Copyright (C) 2001/2002 The ScummVM project
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * $Header$
+ */
+
+#include "stdafx.h"
+#include "charset.h"
+#include "scumm.h"
+
+void CharsetRenderer::setCurID(byte id) {
+ _curId = id;
+ _fontPtr = getFontPtr(id);
+}
+
+byte *CharsetRenderer::getFontPtr(byte id)
+{
+ byte *ptr = _vm->getResourceAddress(rtCharset, id);
+ assert(ptr);
+ if (_vm->_features & GF_SMALL_HEADER)
+ ptr += 17;
+ else
+ ptr += 29;
+ return ptr;
+}
+
+// do spacing for variable width old-style font
+int CharsetRenderer::getSpacing(byte chr, byte *charset)
+{
+ int spacing = 0;
+
+ if (_vm->_features & GF_OLD256) {
+ spacing = *(charset - 11 + chr);
+ } else {
+ int offs = READ_LE_UINT32(charset + chr * 4 + 4);
+ if (offs) {
+ spacing = charset[offs];
+ if (charset[offs + 2] >= 0x80) {
+ spacing += charset[offs + 2] - 0x100;
+ } else {
+ spacing += charset[offs + 2];
+ }
+ }
+ }
+
+ // FIXME - this fixes the inventory icons in Zak256/Indy3
+ // see bug #613109.
+ // chars 1,2: up arrow chars 3,4: down arrow
+ if ((_vm->_gameId == GID_ZAK256 || _vm->_gameId == GID_INDY3_256)
+ && (chr >= 1 && chr <= 4))
+ spacing = 6;
+
+ return spacing;
+}
+
+int CharsetRenderer::getStringWidth(int arg, byte *text, int pos)
+{
+ byte *ptr;
+ int width;
+ byte chr;
+
+ width = 1;
+ ptr = _fontPtr;
+
+ while ((chr = text[pos++]) != 0) {
+ if (chr == 0xD)
+ break;
+ if (chr == '@')
+ continue;
+ if (chr == 254 || chr == 255) {
+ chr = text[pos++];
+ if (chr == 3) // 'WAIT'
+ break;
+ if (chr == 8) { // 'Verb on next line'
+ if (arg == 1)
+ break;
+ while (text[pos] == ' ')
+ text[pos++] = '@';
+ continue;
+ }
+ if (chr == 10 || chr == 21 || chr == 12 || chr == 13) {
+ pos += 2;
+ continue;
+ }
+ if (chr == 9 || chr == 1 || chr == 2) // 'Newline'
+ break;
+ if (chr == 14) {
+ int set = text[pos] | (text[pos + 1] << 8);
+ pos += 2;
+ ptr = getFontPtr(set);
+ continue;
+ }
+ }
+ width += getSpacing(chr, ptr);
+ }
+
+ return width;
+}
+
+void CharsetRenderer::addLinebreaks(int a, byte *str, int pos, int maxwidth)
+{
+ int lastspace = -1;
+ int curw = 1;
+ byte *ptr;
+ byte chr;
+
+ ptr = _fontPtr;
+
+ while ((chr = str[pos++]) != 0) {
+ if (chr == '@')
+ continue;
+ if (chr == 254)
+ chr = 255;
+ if (chr == 255) {
+ chr = str[pos++];
+ if (chr == 3) // 'Wait'
+ break;
+ if (chr == 8) { // 'Verb on next line'
+ if (a == 1) {
+ curw = 1;
+ } else {
+ while (str[pos] == ' ')
+ str[pos++] = '@';
+ }
+ continue;
+ }
+ if (chr == 10 || chr == 21 || chr == 12 || chr == 13) {
+ pos += 2;
+ continue;
+ }
+ if (chr == 1) { // 'Newline'
+ curw = 1;
+ continue;
+ }
+ if (chr == 2) // 'Don't terminate with \n'
+ break;
+ if (chr == 14) {
+ int set = str[pos] | (str[pos + 1] << 8);
+ pos += 2;
+ ptr = getFontPtr(set);
+ continue;
+ }
+ }
+
+ if (chr == ' ')
+ lastspace = pos - 1;
+
+ curw += getSpacing(chr, ptr);
+ if (lastspace == -1)
+ continue;
+ if (curw > maxwidth) {
+ str[lastspace] = 0xD;
+ curw = 1;
+ pos = lastspace + 1;
+ lastspace = -1;
+ }
+ }
+}
+
+
+void CharsetRenderer::printCharOld(int chr)
+{ // Indy3 / Zak256
+ VirtScreen *vs;
+ byte *char_ptr, *dest_ptr;
+ unsigned int buffer = 0, mask = 0, x = 0, y = 0;
+ unsigned char color;
+
+ _vm->checkRange(_vm->_maxCharsets - 1, 0, _curId, "Printing with bad charset %d");
+
+ if ((vs = _vm->findVirtScreen(_top)) == NULL)
+ return;
+
+ if (chr == '@')
+ return;
+
+ if (_firstChar) {
+ _strLeft = _left;
+ _strTop = _top;
+ _strRight = _left;
+ _strBottom = _top;
+ _firstChar = false;
+ }
+ char_ptr = _fontPtr + 207 + (chr + 1) * 8;
+ dest_ptr = vs->screenPtr + vs->xstart + (_top - vs->topline) * _vm->_realWidth + _left;
+ _vm->updateDirtyRect(vs->number, _left, _left + 8, _top - vs->topline, _top - vs->topline + 8, 0);
+
+ for (y = 0; y < 8; y++) {
+ for (x = 0; x < 8; x++) {
+ if ((mask >>= 1) == 0) {
+ buffer = *char_ptr++;
+ mask = 0x80;
+ }
+ color = ((buffer & mask) != 0);
+ if (color)
+ *(dest_ptr + y * _vm->_realWidth + x) = _color;
+ }
+ }
+
+ // FIXME
+ _left += getSpacing(chr, _fontPtr);
+
+ if (_left > _strRight)
+ _strRight = _left;
+
+ if (_top + 8 > _strBottom)
+ _strBottom = _top + 8;
+
+}
+
+
+void CharsetRenderer::printChar(int chr)
+{
+ int width, height;
+ int d;
+ VirtScreen *vs;
+
+ _vm->checkRange(_vm->_maxCharsets - 1, 1, _curId, "Printing with bad charset %d");
+
+ if ((vs = _vm->findVirtScreen(_top)) == NULL)
+ return;
+
+ if (chr == '@')
+ return;
+
+ _bpp = *_fontPtr;
+ _colorMap[1] = _color;
+
+ _charOffs = READ_LE_UINT32(_fontPtr + chr * 4 + 4);
+
+ if (!_charOffs)
+ return;
+
+ assert(_charOffs < 0x10000);
+
+ _charPtr = _fontPtr + _charOffs;
+
+ width = _charPtr[0];
+ height = _charPtr[1];
+ if (_firstChar) {
+ _strLeft = 0;
+ _strTop = 0;
+ _strRight = 0;
+ _strBottom = 0;
+ }
+
+ if (_disableOffsX) {
+ _offsX = 0;
+ } else {
+ d = _charPtr[2];
+ if (d >= 0x80)
+ d -= 0x100;
+ _offsX = d;
+ }
+
+ d = _charPtr[3];
+ if (d >= 0x80)
+ d -= 0x100;
+ _offsY = d;
+
+ _top += _offsY;
+ _left += _offsX;
+
+ if (_left + width > _right + 1 || _left < 0) {
+ _left += width;
+ _top -= _offsY;
+ return;
+ }
+
+ _disableOffsX = false;
+
+ if (_firstChar) {
+ _strLeft = _left;
+ _strTop = _top;
+ _strRight = _left;
+ _strBottom = _top;
+ _firstChar = false;
+ }
+
+ if (_left < _strLeft)
+ _strLeft = _left;
+
+ if (_top < _strTop)
+ _strTop = _top;
+
+ int drawTop = _top - vs->topline;
+ if (drawTop < 0)
+ drawTop = 0;
+ int bottom = drawTop + height + _offsY;
+
+ _vm->updateDirtyRect(vs->number, _left, _left + width, drawTop, bottom, 0);
+
+ if (vs->number != 0)
+ _blitAlso = false;
+ if (vs->number == 0 && !_blitAlso)
+ _hasMask = true;
+
+ _charPtr += 4;
+
+ byte *mask = _vm->getResourceAddress(rtBuffer, 9)
+ + drawTop * _vm->gdi._numStrips + _left / 8 + _vm->_screenStartStrip;
+
+ byte *dst = vs->screenPtr + vs->xstart + drawTop * _vm->_realWidth + _left;
+
+ if (_blitAlso) {
+ byte *back = dst;
+ dst = _vm->getResourceAddress(rtBuffer, vs->number + 5)
+ + vs->xstart + drawTop * _vm->_realWidth + _left;
+
+ drawBits(vs, dst, mask, drawTop, width, height);
+
+ _vm->blit(back, dst, width, height);
+ } else {
+ drawBits(vs, dst, mask, drawTop, width, height);
+ }
+
+ _left += width;
+ if (_left > _strRight)
+ _strRight = _left;
+
+ if (_top + height > _strBottom)
+ _strBottom = _top + height;
+
+ _top -= _offsY;
+}
+
+void CharsetRenderer::drawBits(VirtScreen *vs, byte *dst, byte *mask, int drawTop, int width, int height)
+{
+ byte maskmask;
+ int y, x;
+ int maskpos;
+ int color;
+ byte numbits, bits;
+ bool useMask = (vs->number == 0 && !_ignoreCharsetMask);
+
+ bits = *_charPtr++;
+ numbits = 8;
+
+ y = 0;
+
+ for (y = 0; y < height && y + drawTop < vs->height; y++) {
+ maskmask = revBitMask[_left & 7];
+ maskpos = 0;
+
+ for (x = 0; x < width; x++) {
+ int myMask = (0xFF << (8 - _bpp)) & 0xFF;
+ int myColor = (bits & myMask) >> (8 - _bpp);
+ color = (bits >> (8 - _bpp)) & 0xFF;
+ assert(color == myColor);
+
+ if (color) {
+ if (useMask) {
+ mask[maskpos] |= maskmask;
+ }
+ *dst = _colorMap[color];
+ }
+ dst++;
+ bits <<= _bpp;
+ numbits -= _bpp;
+ if (numbits == 0) {
+ bits = *_charPtr++;
+ numbits = 8;
+ }
+ maskmask >>= 1;
+ if (maskmask == 0) {
+ maskmask = 0x80;
+ maskpos++;
+ }
+ }
+ dst += _vm->_realWidth - width;
+ mask += _vm->gdi._numStrips;
+ }
+}