cleanup; got rid of the split function and rather work in place (so instead of allocating dozens of small goblets of memory, we only need to duplicate the string once); fixed some text positioning bugs (but again, to get a real accurate implementation, I'll need to study screen shots of the Dig/FT/COMI videos and compare them to our results)

svn-id: r8388
This commit is contained in:
Max Horn
2003-06-08 00:39:08 +00:00
parent f273c4195b
commit faadbcafa7
3 changed files with 131 additions and 186 deletions
+123 -178
View File
@@ -33,6 +33,7 @@ SmushFont::SmushFont(bool use_original_colors, bool new_colors) :
}
int SmushFont::getStringWidth(const char *str) {
assert(str);
if (!_loaded) {
warning("SmushFont::getStringWidth() Font is not loaded");
return 0;
@@ -46,6 +47,7 @@ int SmushFont::getStringWidth(const char *str) {
}
int SmushFont::getStringHeight(const char *str) {
assert(str);
if (!_loaded) {
warning("SmushFont::getStringHeight() Font is not loaded");
return 0;
@@ -134,30 +136,6 @@ int SmushFont::draw2byte(byte *buffer, int dst_width, int x, int y, int idx) {
return w + 1;
}
static char **split(const 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);
}
int len = strlen(i);
ret[n] = new char[len + 1];
memcpy(ret[n], i, len);
ret[n++][len] = 0;
ret[n] = 0;
return ret;
}
void SmushFont::drawSubstring(const char *str, byte *buffer, int dst_width, int x, int y) {
for (int i = 0; str[i] != 0; i++) {
if ((byte)str[i] >= 0x80 && _vm->_CJKMode) {
@@ -168,6 +146,9 @@ void SmushFont::drawSubstring(const char *str, byte *buffer, int dst_width, int
}
}
#define MAX_WORDS 60
void SmushFont::drawStringAbsolute(const char *str, byte *buffer, int dst_width, int x, int y) {
debug(9, "SmushFont::drawStringAbsolute(%s, %d, %d)", str, x, y);
@@ -187,137 +168,115 @@ void SmushFont::drawStringAbsolute(const char *str, byte *buffer, int dst_width,
}
}
void SmushFont::drawStringCentered(const 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);
void SmushFont::drawStringCentered(const char *str, byte *buffer, int dst_width, int dst_height, int x, int y, int left, int right) {
debug(9, "SmushFont::drawStringCentered(%s, %d, %d, %d, %d)", str, x, y, left, right);
char *z = strchr(str, '\n');
if (z != 0) {
// FIXME: this is actually evil, because it silently modifes the
// string 'str' passed to us, despite it being declared const.
warning("drawStringCentered: got input string containing \\n");
*z = 0;
}
char **words = split(str, ' ');
const int width = right - left;
char *s = strdup(str);
char *words[MAX_WORDS];
int word_count = 0;
while (words[word_count])
word_count++;
char *tmp = s;
while (tmp) {
assert(word_count < MAX_WORDS);
words[word_count++] = tmp;
tmp = strpbrk(tmp, " \t\r\n");
if (tmp == 0)
break;
*tmp++ = 0;
}
int i = 0, max_width = 0, height = 0, line_count = 0;
char **substrings = new char *[word_count];
int *substr_widths = new int[word_count];
int space_width = getCharWidth(' ');
char *substrings[MAX_WORDS];
int substr_widths[MAX_WORDS];
const int space_width = getCharWidth(' ');
i = 0;
while (i < word_count) {
int substr_width = getStringWidth(words[i]);
char *substr = new char[1000];
strcpy(substr, words[i]);
int j = i + 1;
char *substr = words[i++];
int substr_width = getStringWidth(substr);
while (j < word_count) {
int word_width = getStringWidth(words[j]);
while (i < word_count) {
int word_width = getStringWidth(words[i]);
if ((substr_width + space_width + word_width) >= width)
break;
substr_width += word_width + space_width;
j++;
}
for (int k = i + 1; k < j; k++) {
strcat(substr, " ");
strcat(substr, words[k]);
}
substrings[line_count] = substr;
substr_widths[line_count++] = substr_width;
if (substr_width > max_width)
max_width = substr_width;
i = j;
height += getStringHeight(substr);
}
for (i = 0; i < word_count; i++) {
delete[] words[i];
}
delete[] words;
if (y > dst_height - height) {
y = dst_height - height;
}
max_width = (max_width + 1) >> 1;
int x = xmin + width / 2 + offset - dst_width / 2;
if (x < max_width)
x = max_width;
if (x > dst_width - max_width)
x = dst_width - max_width;
for (i = 0; i < line_count; i++) {
drawSubstring(substrings[i], buffer, dst_width, x - substr_widths[i] / 2, y);
y += getStringHeight(substrings[i]);
delete[] substrings[i];
}
delete[] substr_widths;
delete[] substrings;
}
void SmushFont::drawStringWrap(const 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);
char *z = strchr(str, '\n');
if (z != 0) {
// FIXME: this is actually evil, because it silently modifes the
// string 'str' passed to us, despite it being declared const.
warning("drawStringWrap: got input string containing \\n");
*z = 0;
}
char **words = split(str, ' ');
int word_count = 0;
while (words[word_count])
word_count++;
int i = 0, max_width = 0, height = 0, line_count = 0;
char **substrings = new char *[word_count];
int *substr_widths = new int[word_count];
int space_width = getCharWidth(' ');
i = 0;
while (i < word_count) {
int substr_width = getStringWidth(words[i]);
char *substr = new char[1000];
strcpy(substr, words[i]);
int j = i + 1;
while (j < word_count) {
int word_width = getStringWidth(words[j]);
if ((substr_width + space_width + word_width) >= width)
break;
substr_width += word_width + space_width;
j++;
}
for (int k = i + 1; k < j; k++) {
strcat(substr, " ");
strcat(substr, words[k]);
*(words[i]-1) = ' '; // Convert 0 byte back to space
i++;
}
substrings[line_count] = substr;
substr_widths[line_count++] = substr_width;
if (max_width < substr_width)
max_width = substr_width;
i = j;
height += getStringHeight(substr);
}
for (i = 0; i < word_count; i++) {
delete[] words[i];
if (y > dst_height - height) {
y = dst_height - height;
}
max_width = (max_width + 1) >> 1;
x = left + width / 2;
if (x < left + max_width)
x = left + max_width;
if (x > right - max_width)
x = right - max_width;
for (i = 0; i < line_count; i++) {
drawSubstring(substrings[i], buffer, dst_width, x - substr_widths[i] / 2, y);
y += getStringHeight(substrings[i]);
}
free(s);
}
void SmushFont::drawStringWrap(const char *str, byte *buffer, int dst_width, int dst_height, int x, int y, int left, int right) {
debug(9, "SmushFont::drawStringWrap(%s, %d, %d, %d, %d)", str, x, y, left, right);
const int width = right - left;
char *s = strdup(str);
char *words[MAX_WORDS];
int word_count = 0;
char *tmp = s;
while (tmp) {
assert(word_count < MAX_WORDS);
words[word_count++] = tmp;
tmp = strpbrk(tmp, " \t\r\n");
if (tmp == 0)
break;
*tmp++ = 0;
}
int i = 0, max_width = 0, height = 0, line_count = 0;
char *substrings[MAX_WORDS];
int substr_widths[MAX_WORDS];
const int space_width = getCharWidth(' ');
i = 0;
while (i < word_count) {
char *substr = words[i++];
int substr_width = getStringWidth(substr);
while (i < word_count) {
int word_width = getStringWidth(words[i]);
if ((substr_width + space_width + word_width) >= width)
break;
substr_width += word_width + space_width;
*(words[i]-1) = ' '; // Convert 0 byte back to space
i++;
}
substrings[line_count] = substr;
substr_widths[line_count++] = substr_width;
if (max_width < substr_width)
max_width = substr_width;
height += getStringHeight(substr);
}
delete[] words;
if (y > dst_height - height) {
y = dst_height - height;
@@ -329,86 +288,72 @@ void SmushFont::drawStringWrap(const char *str, byte *buffer, int dst_width, int
for (i = 0; i < line_count; i++) {
drawSubstring(substrings[i], buffer, dst_width, x, y);
y += getStringHeight(substrings[i]);
delete[] substrings[i];
}
delete[] substr_widths;
delete[] substrings;
free(s);
}
void SmushFont::drawStringWrapCentered(const char *str, byte *buffer, int dst_width, int dst_height, int x, int y, int width) {
debug(9, "SmushFont::drawStringWrapCentered(%s, %d, %d)", str, x, y);
void SmushFont::drawStringWrapCentered(const char *str, byte *buffer, int dst_width, int dst_height, int x, int y, int left, int right) {
debug(9, "SmushFont::drawStringWrapCentered(%s, %d, %d, %d, %d)", str, x, y, left, right);
char *z = strchr(str, '\n');
if (z != 0) {
// FIXME: this is actually evil, because it silently modifes the
// string 'str' passed to us, despite it being declared const.
warning("drawStringWrapCentered: got input string containing \\n");
*z = 0;
}
char **words = split(str, ' ');
const int width = right - left;
char *s = strdup(str);
char *words[MAX_WORDS];
int word_count = 0;
while (words[word_count])
word_count++;
char *tmp = s;
while (tmp) {
assert(word_count < MAX_WORDS);
words[word_count++] = tmp;
tmp = strpbrk(tmp, " \t\r\n");
if (tmp == 0)
break;
*tmp++ = 0;
}
int i = 0, max_width = 0, height = 0, line_count = 0;
char **substrings = new char *[word_count];
int *substr_widths = new int[word_count];
int space_width = getCharWidth(' ');
char *substrings[MAX_WORDS];
int substr_widths[MAX_WORDS];
const int space_width = getCharWidth(' ');
i = 0;
width = MIN(width, dst_width);
while (i < word_count) {
int substr_width = getStringWidth(words[i]);
char *substr = new char[1000];
strcpy(substr, words[i]);
int j = i + 1;
char *substr = words[i++];
int substr_width = getStringWidth(substr);
while (j < word_count) {
int word_width = getStringWidth(words[j]);
while (i < word_count) {
int word_width = getStringWidth(words[i]);
if ((substr_width + space_width + word_width) >= width)
break;
substr_width += word_width + space_width;
j++;
}
for (int k = i + 1; k < j; k++) {
strcat(substr, " ");
strcat(substr, words[k]);
*(words[i]-1) = ' '; // Convert 0 byte back to space
i++;
}
substrings[line_count] = substr;
substr_widths[line_count++] = substr_width;
if (max_width < substr_width)
max_width = substr_width;
i = j;
height += getStringHeight(substr);
}
for (i = 0; i < word_count; i++) {
delete[] words[i];
}
delete[] words;
if (y > dst_height - height) {
y = dst_height - height;
}
max_width = (max_width + 1) >> 1;
x = left + width / 2;
if (x < max_width)
x = max_width;
if (x > dst_width - max_width)
x = dst_width - max_width;
if (x < left + max_width)
x = left + max_width;
if (x > right - max_width)
x = right - max_width;
for (i = 0; i < line_count; i++) {
drawSubstring(substrings[i], buffer, dst_width, x - substr_widths[i] / 2, y);
y += getStringHeight(substrings[i]);
delete[] substrings[i];
}
delete[] substr_widths;
delete[] substrings;
free(s);
}
+4 -4
View File
@@ -43,10 +43,10 @@ public:
SmushFont(bool use_original_colors, bool new_colors);
void setColor(byte c) { _color = c; }
void drawStringCentered(const char *str, byte *buffer, int dst_width, int dst_height, int y, int xmin, int width, int offset);
void drawStringWrap(const char *str, byte *buffer, int dst_width, int dst_height, int x, int y, int width);
void drawStringWrapCentered(const char *str, byte *buffer, int dst_width, int dst_height, int x, int y, int width);
void drawStringAbsolute(const char *str, byte *buffer, int dst_width, int x, int y);
void drawStringAbsolute (const char *str, byte *buffer, int dst_width, int x, int y);
void drawStringCentered (const char *str, byte *buffer, int dst_width, int dst_height, int x, int y, int left, int right);
void drawStringWrap (const char *str, byte *buffer, int dst_width, int dst_height, int x, int y, int left, int right);
void drawStringWrapCentered(const char *str, byte *buffer, int dst_width, int dst_height, int x, int y, int left, int right);
};
#endif
+4 -4
View File
@@ -484,7 +484,7 @@ void SmushPlayer::handleTextResource(Chunk &b) {
int flags = b.getShort();
int left = b.getShort();
int top = b.getShort();
int width = b.getShort();
int right = b.getShort();
/*int32 height =*/ b.getShort();
/*int32 unk2 =*/ b.getWord();
@@ -561,13 +561,13 @@ void SmushPlayer::handleTextResource(Chunk &b) {
sf->drawStringAbsolute(str, _data, _width, pos_x, pos_y);
break;
case 1:
sf->drawStringCentered(str, _data, _width, _height, MAX(pos_y, top), left, width, pos_x);
sf->drawStringCentered(str, _data, _width, _height, pos_x, MAX(pos_y, top), left, right);
break;
case 8:
sf->drawStringWrap(str, _data, _width, _height, pos_x, MAX(pos_y, top), width);
sf->drawStringWrap(str, _data, _width, _height, pos_x, MAX(pos_y, top), left, right);
break;
case 9:
sf->drawStringWrapCentered(str, _data, _width, _height, pos_x, MAX(pos_y, top), width);
sf->drawStringWrapCentered(str, _data, _width, _height, pos_x, MAX(pos_y, top), left, right);
break;
default:
warning("SmushPlayer::handleTextResource. Not handled flags: %d", flags);