scummvm/scumm/charset.cpp

673 lines
18 KiB
C++

/* ScummVM - Scumm Interpreter
* Copyright (C) 2001-2003 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"
#include "nut_renderer.h"
void CharsetRendererCommon::setCurID(byte id) {
_vm->checkRange(_vm->_maxCharsets - 1, 0, _curId, "Printing with bad charset %d");
_curId = id;
_fontPtr = _vm->getResourceAddress(rtCharset, id);
if (_fontPtr == 0)
error("CharsetRendererCommon::setCurID: charset %d not found!\n", id);
if (_vm->_features & GF_AFTER_V4)
_fontPtr += 17;
else
_fontPtr += 29;
}
void CharsetRendererV3::setCurID(byte id) {
_vm->checkRange(_vm->_maxCharsets - 1, 0, _curId, "Printing with bad charset %d");
_curId = id;
_fontPtr = _vm->getResourceAddress(rtCharset, id);
if (_fontPtr == 0)
error("CharsetRendererCommon::setCurID: charset %d not found!\n", id);
_nbChars = _fontPtr[4];
_fontPtr += 6;
_widthTable = _fontPtr;
_fontPtr += _nbChars;
}
// do spacing for variable width old-style font
int CharsetRendererClassic::getCharWidth(byte chr) {
int spacing = 0;
int offs = READ_LE_UINT32(_fontPtr + chr * 4 + 4);
if (offs) {
spacing = _fontPtr[offs];
if (_fontPtr[offs + 2] >= 0x80) {
spacing += _fontPtr[offs + 2] - 0x100;
} else {
spacing += _fontPtr[offs + 2];
}
}
return spacing;
}
int CharsetRenderer::getStringWidth(int arg, byte *text) {
int pos = 0;
int width = 1;
byte chr;
int oldID = getCurID();
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;
setCurID(set);
continue;
}
}
width += getCharWidth(chr);
}
setCurID(oldID);
return width;
}
void CharsetRenderer::addLinebreaks(int a, byte *str, int pos, int maxwidth) {
int lastspace = -1;
int curw = 1;
byte chr;
int oldID = getCurID();
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;
setCurID(set);
continue;
}
}
if (chr == ' ')
lastspace = pos - 1;
curw += getCharWidth(chr);
if (lastspace == -1)
continue;
if (curw > maxwidth) {
str[lastspace] = 0xD;
curw = 1;
pos = lastspace + 1;
lastspace = -1;
}
}
setCurID(oldID);
}
// German Zak font (should work for US version too).
// See patch #732072
static byte charsetDataV2[] = {
0x89, 0x04, 0x00, 0x00, 0x63, 0x01, 0x80, 0x08,
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
0x07, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
0x04, 0x04, 0x07, 0x08, 0x07, 0x07, 0x08, 0x04,
0x05, 0x05, 0x03, 0x08, 0x04, 0x06, 0x04, 0x08,
0x07, 0x04, 0x07, 0x07, 0x08, 0x07, 0x07, 0x07,
0x07, 0x07, 0x04, 0x04, 0x08, 0x08, 0x08, 0x07,
0x06, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
0x07, 0x03, 0x06, 0x07, 0x07, 0x08, 0x07, 0x07,
0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x08,
0x07, 0x07, 0x07, 0x07, 0x07, 0x08, 0x02, 0x08,
0x08, 0x07, 0x07, 0x06, 0x07, 0x07, 0x06, 0x07,
0x07, 0x03, 0x05, 0x07, 0x04, 0x08, 0x07, 0x07, // h i j k l m n o / 104 - 111
0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x08,
0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x08,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xc0, 0x80,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7e, 0x7c,
0x7c, 0x7e, 0x7f, 0x7e, 0x7e, 0x7e, 0x7e, 0x00,
0x00, 0xfe, 0xfe, 0xfe, 0xfc, 0xfe, 0x7e, 0x3e,
0x3e, 0x7e, 0xfe, 0x7e, 0x7e, 0x7e, 0x7e, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x1c, 0x20, 0x20, 0x20, 0x1c, 0x00,
0x04, 0x04, 0x3c, 0x44, 0x44, 0x44, 0x3c, 0x00,
0x00, 0x00, 0x38, 0x44, 0x78, 0x40, 0x3c, 0x00,
0x0c, 0x10, 0x38, 0x10, 0x10, 0x10, 0x10, 0x00,
0x00, 0x00, 0x38, 0x44, 0x44, 0x3c, 0x04, 0x38,
0x00, 0x00, 0x38, 0x04, 0x3c, 0x44, 0x3c, 0x00,
0x40, 0x40, 0x78, 0x44, 0x44, 0x44, 0x78, 0x00,
0x02, 0x02, 0x38, 0x40, 0x40, 0x40, 0x38, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xfc,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x60, 0x60, 0x60, 0x60, 0x00, 0x00, 0x60, 0x00,
0xcc, 0xcc, 0xcc, 0x00, 0x00, 0x00, 0x00, 0x00,
0x66, 0x66, 0xff, 0x66, 0xff, 0x66, 0x66, 0x00,
0x30, 0x7c, 0xc0, 0x78, 0x0c, 0xf8, 0x30, 0x00,
0xc4, 0xcc, 0x18, 0x30, 0x60, 0xcc, 0x8c, 0x00,
0x78, 0xcc, 0x78, 0x70, 0xce, 0xcc, 0x7e, 0x00,
0x60, 0x60, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00,
0x30, 0x60, 0xc0, 0xc0, 0xc0, 0x60, 0x30, 0x00,
0xc0, 0x60, 0x30, 0x30, 0x30, 0x60, 0xc0, 0x00,
0x00, 0x80, 0xc0, 0xc0, 0xc0, 0xc0, 0x80, 0x00,
0x66, 0xcc, 0xcc, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x60, 0xc0,
0x00, 0x00, 0x00, 0xf8, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x60, 0x00,
0x66, 0x66, 0xcc, 0x00, 0x00, 0x00, 0x00, 0x00,
0x78, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00,
0x60, 0xe0, 0x60, 0x60, 0x60, 0x60, 0x60, 0x00,
0x78, 0xcc, 0x0c, 0x18, 0x60, 0xc0, 0xfc, 0x00,
0x78, 0xcc, 0x0c, 0x38, 0x0c, 0xcc, 0x78, 0x00,
0x0c, 0x1c, 0x2c, 0x4c, 0xfe, 0x0c, 0x0c, 0x00,
0xfc, 0xc0, 0xf8, 0x0c, 0x0c, 0xcc, 0x78, 0x00,
0x78, 0xcc, 0xc0, 0xf8, 0xcc, 0xcc, 0x78, 0x00,
0xfc, 0xcc, 0x18, 0x30, 0x30, 0x30, 0x30, 0x00,
0x78, 0xcc, 0xcc, 0x78, 0xcc, 0xcc, 0x78, 0x00,
0x78, 0xcc, 0xcc, 0x7c, 0x0c, 0xcc, 0x78, 0x00,
0x00, 0x00, 0x60, 0x60, 0x00, 0x60, 0x60, 0x00,
0x00, 0x00, 0x60, 0x60, 0x00, 0x60, 0x60, 0xc0,
0x7c, 0xfe, 0xfc, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x3f, 0x61, 0xcc, 0xd0, 0xd0, 0xcc, 0x61, 0x3f,
0x78, 0xcc, 0x0c, 0x18, 0x30, 0x00, 0x30, 0x00,
0x00, 0x00, 0x00, 0xf8, 0xf8, 0x00, 0x00, 0x00,
0x30, 0x78, 0xcc, 0xfc, 0xcc, 0xcc, 0xcc, 0x00,
0xf8, 0xcc, 0xcc, 0xf8, 0xcc, 0xcc, 0xf8, 0x00,
0x78, 0xcc, 0xc0, 0xc0, 0xc0, 0xcc, 0x78, 0x00,
0xf0, 0xd8, 0xcc, 0xcc, 0xcc, 0xd8, 0xf0, 0x00,
0xfc, 0xc0, 0xc0, 0xf8, 0xc0, 0xc0, 0xfc, 0x00,
0xfc, 0xc0, 0xc0, 0xf8, 0xc0, 0xc0, 0xc0, 0x00,
0x78, 0xcc, 0xc0, 0xdc, 0xcc, 0xcc, 0x78, 0x00,
0xcc, 0xcc, 0xcc, 0xfc, 0xcc, 0xcc, 0xcc, 0x00,
0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x00,
0x18, 0x18, 0x18, 0x18, 0x18, 0xd8, 0x70, 0x00,
0xcc, 0xd8, 0xf0, 0xe0, 0xf0, 0xd8, 0xcc, 0x00,
0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xfc, 0x00,
0xc6, 0xee, 0xfe, 0xd6, 0xc6, 0xc6, 0xc6, 0x00,
0xcc, 0xec, 0xfc, 0xfc, 0xdc, 0xcc, 0xcc, 0x00,
0x78, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00,
0xf8, 0xcc, 0xcc, 0xf8, 0xc0, 0xc0, 0xc0, 0x00,
0x78, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x0c,
0xf8, 0xcc, 0xcc, 0xf8, 0xf0, 0xd8, 0xcc, 0x00,
0x78, 0xcc, 0xc0, 0x78, 0x0c, 0xcc, 0x78, 0x00,
0xfc, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x00,
0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00,
0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x30, 0x00,
0xc6, 0xc6, 0xc6, 0xd6, 0xfe, 0xee, 0xc6, 0x00,
0xcc, 0xcc, 0x78, 0x30, 0x78, 0xcc, 0xcc, 0x00,
0xcc, 0xcc, 0xcc, 0x78, 0x30, 0x30, 0x30, 0x00,
0xfc, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0xfc, 0x00,
0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0x7c, 0x00,
0xcc, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0x7c, 0x00,
0xe8, 0x4d, 0x4a, 0x48, 0x00, 0x00, 0x00, 0x00,
0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00,
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0xfe,
0xfe, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0x7c, 0x00,
0xc0, 0xc0, 0xf8, 0xcc, 0xcc, 0xcc, 0xf8, 0x00,
0x00, 0x00, 0x78, 0xc0, 0xc0, 0xc0, 0x78, 0x00,
0x0c, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x7c, 0x00,
0x00, 0x00, 0x78, 0xcc, 0xfc, 0xc0, 0x78, 0x00,
0x38, 0x60, 0xf8, 0x60, 0x60, 0x60, 0x60, 0x00,
0x00, 0x00, 0x78, 0xcc, 0xcc, 0x7c, 0x0c, 0x78,
0xc0, 0xc0, 0xf8, 0xcc, 0xcc, 0xcc, 0xcc, 0x00,
0xc0, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x00,
0x30, 0x00, 0x30, 0x30, 0x30, 0x30, 0x30, 0xe0,
0xc0, 0xc0, 0xcc, 0xd8, 0xf0, 0xd8, 0xcc, 0x00,
0xe0, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x00,
0x00, 0x00, 0xcc, 0xfe, 0xfe, 0xd6, 0xc6, 0x00,
0x00, 0x00, 0xf8, 0xcc, 0xcc, 0xcc, 0xcc, 0x00,
0x00, 0x00, 0x78, 0xcc, 0xcc, 0xcc, 0x78, 0x00,
0x00, 0x00, 0xf8, 0xcc, 0xcc, 0xf8, 0xc0, 0xc0,
0x00, 0x00, 0x7c, 0xcc, 0xcc, 0x7c, 0x0c, 0x0c,
0x00, 0x00, 0xf8, 0xcc, 0xc0, 0xc0, 0xc0, 0x00,
0x00, 0x00, 0x7c, 0xc0, 0x78, 0x0c, 0xf8, 0x00,
0x30, 0x30, 0xfc, 0x30, 0x30, 0x30, 0x1c, 0x00,
0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0x7c, 0x00,
0x00, 0x00, 0xcc, 0xcc, 0xcc, 0x78, 0x30, 0x00,
0x00, 0x00, 0xc6, 0xd6, 0xfe, 0x7c, 0x6c, 0x00,
0x00, 0x00, 0xcc, 0x78, 0x30, 0x78, 0xcc, 0x00,
0x00, 0x00, 0xcc, 0xcc, 0xcc, 0x7c, 0x18, 0x70,
0x00, 0x00, 0xfc, 0x18, 0x30, 0x60, 0xfc, 0x00,
0xcc, 0x00, 0x78, 0xcc, 0xcc, 0xcc, 0x78, 0x00,
0xcc, 0x30, 0x78, 0xcc, 0xfc, 0xcc, 0xcc, 0x00,
0x84, 0x78, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00,
0x38, 0x6c, 0x6c, 0xf8, 0xcc, 0xcc, 0xf8, 0x80,
0x08, 0x0c, 0x0e, 0xff, 0xff, 0x0e, 0x0c, 0x08,
0x0e
};
void CharsetRendererV2::setCurID(byte id) {
_nbChars = charsetDataV2[6];
_widthTable = charsetDataV2 + 8;
_fontPtr = charsetDataV2 + 8 + _nbChars;
}
int CharsetRendererV3::getCharWidth(byte chr) {
int spacing = 0;
spacing = *(_widthTable + chr);
return spacing;
}
void CharsetRendererV3::setColor(byte color)
{
_color = color;
if (_vm->_features & GF_16COLOR) {
_dropShadow = ((_color & 0xF0) != 0);
_color &= 0x0f;
} else
_dropShadow = false;
}
void CharsetRendererV3::printChar(int chr) {
// Indy3 / Zak256 / Loom
VirtScreen *vs;
byte *char_ptr, *dest_ptr, *mask_ptr;
unsigned int buffer = 0, bit = 0, x = 0, y = 0;
bool useMask;
int w, h;
if (!_dropShadow) {
w = h = 8;
} else {
w = h = 9;
}
_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 + chr * 8;
dest_ptr = vs->screenPtr + vs->xstart + (_top - vs->topline) * _vm->_realWidth + _left;
mask_ptr = _vm->getResourceAddress(rtBuffer, 9) + _vm->_screenStartStrip + (_top - vs->topline) * _vm->gdi._numStrips + _left / 8;
useMask = (vs->number == 0 && !_ignoreCharsetMask);
_vm->updateDirtyRect(vs->number, _left, _left + w, _top - vs->topline, _top - vs->topline + h, 0);
if (vs->number == 0)
_hasMask = true;
for (y = 0; y < 8; y++) {
byte maskmask = revBitMask[_left & 7];
int maskpos = 0;
for (x = 0; x < 8; x++) {
if ((bit >>= 1) == 0) {
buffer = *char_ptr++;
bit = 0x80;
}
if (buffer & bit) {
if (_dropShadow) {
*(dest_ptr + x + 1) = 0;
*(dest_ptr + x + _vm->_realWidth) = 0;
*(dest_ptr + x + _vm->_realWidth + 1) = 0;
}
*(dest_ptr + x) = _color;
if (useMask) {
mask_ptr[maskpos] |= maskmask;
if (_dropShadow) {
mask_ptr[maskpos + _vm->gdi._numStrips] |= maskmask;
if (maskmask == 1) {
mask_ptr[maskpos + 1] |= 0x80;
mask_ptr[maskpos + _vm->gdi._numStrips + 1] |= 0x80;
} else {
mask_ptr[maskpos] |= (maskmask >> 1);
mask_ptr[maskpos + _vm->gdi._numStrips] |= (maskmask >> 1);
}
}
}
}
maskmask >>= 1;
if (maskmask == 0) {
maskmask = 0x80;
maskpos++;
}
}
dest_ptr += _vm->_realWidth;
mask_ptr += _vm->gdi._numStrips;
}
if (_strLeft > _left)
_strLeft = _left;
_left += getCharWidth(chr);
if (_strRight < _left) {
_strRight = _left;
if (_dropShadow)
_strRight++;
}
if (_strBottom < _top + h)
_strBottom = _top + h;
}
void CharsetRendererClassic::printChar(int chr) {
int width, height;
int offsX, offsY;
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;
_vm->_charsetColorMap[1] = _color;
uint32 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 CharsetRendererClassic::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 = _vm->_charsetColorMap[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;
}
}
CharsetRendererNut::CharsetRendererNut(Scumm *vm)
: CharsetRenderer(vm) {
_current = 0;
for (int i = 0; i < 5; i++) {
char fontname[256];
sprintf(fontname, "font%d.nut", i);
_fr[i] = new NutRenderer(_vm);
if (!(_fr[i]->loadFont(fontname, _vm->getGameDataPath()))) {
delete _fr[i];
_fr[i] = NULL;
}
}
}
CharsetRendererNut::~CharsetRendererNut() {
for (int i = 0; i < 5; i++)
delete _fr[i];
}
void CharsetRendererNut::setCurID(byte id) {
assert(id < 5);
_curId = id;
_current = _fr[id];
assert(_current);
}
int CharsetRendererNut::getCharWidth(byte chr) {
assert(_current);
return _current->getCharWidth(chr);
}
int CharsetRendererNut::getFontHeight() {
// FIXME / TODO: how to implement this properly???
assert(_current);
return _current->getCharHeight('|');
}
void CharsetRendererNut::printChar(int chr) {
assert(_current);
if (chr == '@')
return;
if (_firstChar) {
_strLeft = _left;
_strTop = _top;
_strRight = _left;
_strBottom = _top;
_firstChar = false;
}
int width = _current->getCharWidth(chr);
int height = _current->getCharHeight(chr);
_hasMask = true;
_current->drawChar((char)chr, _left, _top, _color, !_ignoreCharsetMask);
_vm->updateDirtyRect(0, _left, _left + width, _top, _top + height, 0);
_left += width;
if (_left > _strRight)
_strRight = _left;
if (_top + height > _strBottom)
_strBottom = _top + height;
}