aboutsummaryrefslogtreecommitdiff
path: root/scumm/smush/smush_font.cpp
diff options
context:
space:
mode:
authorPaweł Kołodziejski2003-03-17 12:28:50 +0000
committerPaweł Kołodziejski2003-03-17 12:28:50 +0000
commit06ef80fa6170bec33f9ac117400fa86f965c4aa7 (patch)
tree70c978c3f0f8bda24e5f2aae221ac88ac4d2fc2d /scumm/smush/smush_font.cpp
parentee26752d2e83ba3ae0a51a170f39894d8a78a14b (diff)
downloadscummvm-rg350-06ef80fa6170bec33f9ac117400fa86f965c4aa7.tar.gz
scummvm-rg350-06ef80fa6170bec33f9ac117400fa86f965c4aa7.tar.bz2
scummvm-rg350-06ef80fa6170bec33f9ac117400fa86f965c4aa7.zip
reorg/clenup, changed main loop in smush code
svn-id: r6817
Diffstat (limited to 'scumm/smush/smush_font.cpp')
-rw-r--r--scumm/smush/smush_font.cpp489
1 files changed, 489 insertions, 0 deletions
diff --git a/scumm/smush/smush_font.cpp b/scumm/smush/smush_font.cpp
new file mode 100644
index 0000000000..2e1207be38
--- /dev/null
+++ b/scumm/smush/smush_font.cpp
@@ -0,0 +1,489 @@
+/* ScummVM - Scumm Interpreter
+ * Copyright (C) 2002-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 "common/util.h"
+#include "common/engine.h"
+#include "common/file.h"
+#include "scumm/scumm.h"
+
+#include "smush_font.h"
+
+SmushFont::SmushFont(bool use_original_colors, bool new_colors) :
+ _nbChars(0),
+ _color(-1),
+ _new_colors(new_colors),
+ _original(use_original_colors) {
+ for(int i = 0; i < 256; i++)
+ _chars[i].chr = NULL;
+}
+
+SmushFont::~SmushFont() {
+ for(int i = 0; i < _nbChars; i++) {
+ if(_chars[i].chr)
+ delete []_chars[i].chr;
+ }
+}
+
+bool SmushFont::loadFont(const char *filename, const char *directory) {
+ debug(2, "SmushFont::loadFont() called");
+
+ File file;
+ file.open(filename, directory);
+ if (file.isOpen() == false) {
+ warning("SmushFont::loadFont() Can't open font file: %s/%s", directory, filename);
+ return false;
+ }
+
+ uint32 tag = file.readUint32BE();
+ if (tag != 'ANIM') {
+ debug(2, "SmushFont::loadFont() there is no ANIM chunk in font header");
+ return false;
+ }
+
+ if (_dataSrc != NULL) {
+ free(_dataSrc);
+ _dataSrc = NULL;
+ }
+
+ uint32 length = file.readUint32BE();
+ _dataSrc = (byte *)malloc(length);
+ file.read(_dataSrc, length);
+ file.close();
+
+ if (READ_BE_UINT32(_dataSrc) != 'AHDR') {
+ debug(2, "SmushFont::loadFont() there is no AHDR chunk in font header");
+ free(_dataSrc);
+ _dataSrc = NULL;
+ return false;
+ }
+
+ _nbChars = READ_LE_UINT16(_dataSrc + 10);
+ int32 offset = READ_BE_UINT32(_dataSrc + 4) + 8;
+ for (int l = 0; l < _nbChars; l++) {
+ if (READ_BE_UINT32(_dataSrc + offset) == 'FRME') {
+ offset += 8;
+ if (READ_BE_UINT32(_dataSrc + offset) == 'FOBJ') {
+ _chars[l].width = READ_LE_UINT16(_dataSrc + offset + 14);
+ _chars[l].height = READ_LE_UINT16(_dataSrc + offset + 16);
+ _chars[l].chr = new byte[_chars[l].width * _chars[l].height + 1000];
+ decodeCodec(_chars[l].chr, _dataSrc + offset + 22, READ_BE_UINT32(_dataSrc + offset + 4) - 14);
+ offset += READ_BE_UINT32(_dataSrc + offset + 4) + 8;
+ } else {
+ debug(2, "SmushFont::loadFont(%s, %s) there is no FOBJ chunk in FRME chunk %d (offset %x)", filename, directory, l, offset);
+ break;
+ }
+ } else {
+ debug(2, "SmushFont::loadFont(%s, %s) there is no FRME chunk %d (offset %x)", filename, directory, l, offset);
+ break;
+ }
+ }
+
+ free(_dataSrc);
+ _dataSrc = NULL;
+ return true;
+}
+
+int SmushFont::getCharWidth(byte v) {
+ if(v >= _nbChars)
+ error("invalid character in SmushFont::charWidth : %d (%d)", v, _nbChars);
+
+ return _chars[v].width;
+}
+
+int SmushFont::getCharHeight(byte v) {
+ if(v >= _nbChars)
+ error("invalid character in SmushFont::charHeight : %d (%d)", v, _nbChars);
+
+ return _chars[v].height;
+}
+
+int SmushFont::getStringWidth(char *str) {
+ int ret = 0;
+
+ while(*str) {
+ ret += getCharWidth(*str++);
+ }
+
+ return ret;
+}
+
+int SmushFont::getStringHeight(char *str) {
+ int ret = 0;
+
+ for(int i = 0; str[i] != 0; i++) {
+ int h = getCharHeight(str[i]);
+ ret = MAX(ret, h);
+ }
+
+ return ret;
+}
+
+void SmushFont::decodeCodec(byte *dst, byte *src, int length) {
+ int size_line, num;
+ byte *src2 = src;
+ byte *dst2 = dst;
+ byte val;
+
+ do {
+ size_line = READ_LE_UINT16(src2);
+ src2 += 2;
+ length -= 2;
+
+ while (size_line != 0) {
+ num = *src2++;
+ val = *src2++;
+ memset(dst2, val, num);
+ dst2 += num;
+ length -= 2;
+ size_line -= 2;
+ if (size_line != 0) {
+ num = READ_LE_UINT16(src2) + 1;
+ src2 += 2;
+ memcpy(dst2, src2, num);
+ dst2 += num;
+ src2 += num;
+ length -= num + 2;
+ size_line -= num + 2;
+ }
+ }
+ dst2--;
+
+ } while (length > 1);
+}
+
+int SmushFont::drawChar(byte *buffer, int dst_width, int x, int y, byte chr) {
+ int w = _chars[chr].width;
+ int h = _chars[chr].height;
+ byte *src = _chars[chr].chr;
+ byte *dst = buffer + dst_width * y + x;
+
+ if(_original) {
+ for(int32 j = 0; j < h; j++) {
+ for(int32 i = 0; i < w; i++) {
+ char value = *src++;
+ if(value) dst[i] = value;
+ }
+ dst += dst_width;
+ }
+ } else {
+ char color = (_color != -1) ? _color : 1;
+ if (_new_colors == true) {
+ for(int j = 0; j < h; j++) {
+ for(int i = 0; i < w; i++) {
+ char value = *src++;
+ if(value == -color) {
+ dst[i] = 0xFF;
+ } else if(value == -31) {
+ dst[i] = 0;
+ } else if(value) {
+ dst[i] = value;
+ }
+ }
+ dst += dst_width;
+ }
+ } else {
+ for(int j = 0; j < h; j++) {
+ for(int i = 0; i < w; i++) {
+ char value = *src++;
+ if(value == 1) {
+ dst[i] = color;
+ } else if(value) {
+ dst[i] = 0;
+ }
+ }
+ dst += dst_width;
+ }
+ }
+ }
+ return w;
+}
+
+static char **split(char *str, char sep) {
+ char **ret = new char *[62];
+ int n = 0;
+ const char *i = str;
+ char *j = strchr(i, sep);
+
+ while(j != NULL) {
+ assert(n < 60);
+ ret[n] = new char[j - i + 1];
+ memcpy(ret[n], i, j - i);
+ ret[n++][j - i] = 0;
+ i = j + 1;
+ j = strchr(i, sep);
+ }
+
+ ret[n] = new char[strlen(i) + 1];
+ memcpy(ret[n], i, strlen(i));
+ ret[n++][strlen(i)] = 0;
+ ret[n] = 0;
+
+ return ret;
+}
+
+void SmushFont::drawSubstring(char *str, byte *buffer, int dst_width, int x, int y) {
+ for(int i = 0; str[i] != 0; i++)
+ x += drawChar(buffer, dst_width, x, y, str[i]);
+}
+
+void SmushFont::drawStringAbsolute(char *str, byte *buffer, int dst_width, int x, int y) {
+ debug(9, "SmushFont::drawStringAbsolute(%s, %d, %d)", str, x, y);
+
+ while(str) {
+ char line[256];
+ char *pos = strchr(str, '\n');
+ if(pos) {
+ memcpy(line, str, pos - str - 1);
+ line[pos - str - 1] = 0;
+ str = pos + 1;
+ } else {
+ strcpy(line, str);
+ str = 0;
+ }
+ drawSubstring(line, buffer, dst_width, x, y);
+ y += getStringHeight(line);
+ }
+}
+
+void SmushFont::drawStringCentered(char *str, byte *buffer, int dst_width, int dst_height, int y, int xmin, int width, int offset) {
+ debug(9, "SmushFont::drawStringCentered(%s, %d, %d)", str, xmin, y);
+
+ if ((strchr(str, '\n') != 0)) {
+ char *z = strchr(str, '\n');
+ *z = 0;
+ }
+ char **words = split(str, ' ');
+ int nb_sub = 0;
+
+ while(words[nb_sub])
+ nb_sub++;
+
+ int *sizes = new int[nb_sub];
+ int i = 0, max_width = 0, height = 0, nb_subs = 0;
+
+ for(i = 0; i < nb_sub; i++)
+ sizes[i] = getStringWidth(words[i]);
+
+ char **substrings = new char *[nb_sub];
+ int *substr_widths = new int[nb_sub];
+ int space_width = getCharWidth(' ');
+
+ i = 0;
+ while(i < nb_sub) {
+ int substr_width = sizes[i];
+ char *substr = new char[1000];
+ strcpy(substr, words[i]);
+ int j = i + 1;
+
+ while(j < nb_sub && (substr_width + space_width + sizes[j]) < width) {
+ substr_width += sizes[j++] + space_width;
+ }
+
+ for(int k = i + 1; k < j; k++) {
+ strcat(substr, " ");
+ strcat(substr, words[k]);
+ }
+
+ substrings[nb_subs] = substr;
+ substr_widths[nb_subs++] = substr_width;
+ if(substr_width > max_width)
+ max_width = substr_width;
+ i = j;
+ height += getStringHeight(substr);
+ }
+
+ delete []sizes;
+ for(i = 0; i < nb_sub; i++) {
+ delete []words[i];
+ }
+ delete []words;
+
+ max_width = (max_width + 1) >> 1;
+ int x = xmin + width / 2;
+ x += offset - dst_width / 2;
+
+ if(x < max_width) x = max_width;
+ if(x + max_width > dst_width) {
+ x = dst_width - max_width;
+ }
+
+ if(y + height > dst_height) {
+ y = dst_height - height;
+ }
+
+ for(i = 0; i < nb_subs; i++) {
+ int substr_width = substr_widths[i];
+ drawSubstring(substrings[i], buffer, dst_width, x - substr_width / 2, y);
+ y += getStringHeight(substrings[i]);
+ delete []substrings[i];
+ }
+
+ delete []substr_widths;
+ delete []substrings;
+}
+
+void SmushFont::drawStringWrap(char *str, byte *buffer, int dst_width, int dst_height, int x, int y, int width) {
+ debug(9, "SmushFont::drawStringWrap(%s, %d, %d)", str, x, y);
+
+ if ((strchr(str, '\n') != 0)) {
+ char *z = strchr(str, '\n');
+ *z = 0;
+ }
+ char ** words = split(str, ' ');
+ int nb_sub = 0;
+
+ while(words[nb_sub])
+ nb_sub++;
+
+ int *sizes = new int[nb_sub];
+ int i = 0, max_width = 0, height = 0, nb_subs = 0, left_x;
+
+ for(i = 0; i < nb_sub; i++)
+ sizes[i] = getStringWidth(words[i]);
+
+ char **substrings = new char *[nb_sub];
+ int *substr_widths = new int[nb_sub];
+ int space_width = getCharWidth(' ');
+
+ i = 0;
+ while(i < nb_sub) {
+ int substr_width = sizes[i];
+ char *substr = new char[1000];
+ strcpy(substr, words[i]);
+ int j = i + 1;
+
+ while(j < nb_sub && (substr_width + space_width + sizes[j]) < width) {
+ substr_width += sizes[j++] + space_width;
+ }
+
+ for(int k = i + 1; k < j; k++) {
+ strcat(substr, " ");
+ strcat(substr, words[k]);
+ }
+
+ substrings[nb_subs] = substr;
+ substr_widths[nb_subs++] = substr_width;
+ i = j;
+ height += getStringHeight(substr);
+ }
+
+ delete []sizes;
+ for(i = 0; i < nb_sub; i++) {
+ delete []words[i];
+ }
+ delete []words;
+
+ if(y + height > dst_height) {
+ y = dst_height - height;
+ }
+
+ for(i = 0; i < nb_subs; i++)
+ max_width = MAX(max_width, substr_widths[i]);
+
+ if(max_width + x > dst_width)
+ left_x = dst_width - max_width + getCharWidth(' ');
+ else
+ left_x = x;
+
+ if(max_width + left_x > dst_height)
+ left_x = dst_width - max_width;
+
+ for(i = 0; i < nb_subs; i++) {
+ drawSubstring(substrings[i], buffer, dst_width, left_x, y);
+ y += getStringHeight(substrings[i]);
+ delete []substrings[i];
+ }
+
+ delete []substr_widths;
+ delete []substrings;
+}
+
+void SmushFont::drawStringWrapCentered(char *str, byte *buffer, int dst_width, int dst_height, int x, int32 y, int width) {
+ debug(9, "SmushFont::drawStringWrapCentered(%s, %d, %d)", str, x, y);
+
+ int max_substr_width = 0;
+ if ((strchr(str, '\n') != 0)) {
+ char *z = strchr(str, '\n');
+ *z = 0;
+ }
+ char **words = split(str, ' ');
+ int nb_sub = 0;
+
+ while(words[nb_sub])
+ nb_sub++;
+
+ int *sizes = new int[nb_sub];
+ int i = 0, height = 0, nb_subs = 0;
+
+ for(i = 0; i < nb_sub; i++)
+ sizes[i] = getStringWidth(words[i]);
+
+ char **substrings = new char *[nb_sub];
+ int *substr_widths = new int[nb_sub];
+ int space_width = getCharWidth(' ');
+
+ i = 0;
+ width = MIN(width, dst_width);
+ while(i < nb_sub) {
+ int substr_width = sizes[i];
+ char *substr = new char[1000];
+ strcpy(substr, words[i]);
+ int j = i + 1;
+
+ while(j < nb_sub && (substr_width + space_width + sizes[j]) < width) {
+ substr_width += sizes[j++] + space_width;
+ }
+
+ for(int k = i + 1; k < j; k++) {
+ strcat(substr, " ");
+ strcat(substr, words[k]);
+ }
+
+ substrings[nb_subs] = substr;
+ substr_widths[nb_subs++] = substr_width;
+ max_substr_width = MAX(substr_width, max_substr_width);
+ i = j;
+ height += getStringHeight(substr);
+ }
+
+ delete []sizes;
+ for(i = 0; i < nb_sub; i++) {
+ delete []words[i];
+ }
+ delete []words;
+
+ if(y + height > dst_height) {
+ y = dst_height - height;
+ }
+
+ x = (dst_width - max_substr_width) / 2;
+
+ for(i = 0; i < nb_subs; i++) {
+ int substr_width = substr_widths[i];
+ drawSubstring(substrings[i], buffer, dst_width, x + (max_substr_width - substr_width) / 2, y);
+ y += getStringHeight(substrings[i]);
+ delete []substrings[i];
+ }
+
+ delete []substr_widths;
+ delete []substrings;
+}