aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--engines/drascula/graphics.cpp102
1 files changed, 66 insertions, 36 deletions
diff --git a/engines/drascula/graphics.cpp b/engines/drascula/graphics.cpp
index 5e37d2c3b0..4ed949cc99 100644
--- a/engines/drascula/graphics.cpp
+++ b/engines/drascula/graphics.cpp
@@ -319,31 +319,42 @@ int DrasculaEngine::print_abc_opc(const char *said, int screenY, int game) {
}
bool DrasculaEngine::textFitsCentered(char *text, int x) {
- int half_len = strlen(text) * CHAR_WIDTH / 2;
- // Clip center between 60 and 255
- x = CLIP<int>(x, 60, 259);
- // We want a text centered on x thats fits on screen
- // CHAR_WIDTH is even so x - length / 2 + length is always equal to x + length / 2
- return (x - half_len >= 2 && x + half_len <= 317);
+ int halfLen = (strlen(text) / 2) * CHAR_WIDTH;
+
+ // See comment in centerText()
+ if (x > 160)
+ x = 315 - x;
+ return (halfLen <= x);
}
void DrasculaEngine::centerText(const char *message, int textX, int textY) {
char msg[200];
- char messageLine[200];
- char tmpMessageLine[200];
- *messageLine = 0;
- *tmpMessageLine = 0;
- char *curWord;
- int curLine = 0;
- int x = 0;
- // original starts printing 4 lines above textY
- int y = CLIP<int>(textY - (4 * CHAR_HEIGHT), 0, 320);
-
Common::strlcpy(msg, message, 200);
+
+ // We make sure to have a width of at least 120 pixels by clipping the center.
+ // In theory since the screen width is 320 I would expect something like this:
+ // x = CLIP<int>(x, 60, 260);
+ // return (x - halfLen >= 0 && x + halfLen <= 319);
+
+ // The engines does things differently though. It tries to clips text at 315 instead of 319.
+ // And instead of testing the upper bound if x is greater than 160 it takes the complement to 315
+ // and test only the lower bounds. However since 160 is not the middle of 315, we end up having
+ // text that can go beyond 315 (up to 320) if x is in [159, 160].
+ // Also note that if the numbers of characters is odd, there is one more character to the right
+ // than to the left as it computes the half length with an integer division by two BEFORE multiplying
+ // by CHAR_WIDTH. Thus in theory we may end up with one character out of the screen!
+ // Be faithfull to the original and do the same though.
+
+ textX = CLIP<int>(textX, 60, 255);
// If the message fits on screen as-is, just print it here
if (textFitsCentered(msg, textX)) {
- x = CLIP<int>(textX, 60, 259) - strlen(msg) * CHAR_WIDTH / 2;
+ int x = textX - (strlen(msg) / 2) * CHAR_WIDTH - 1;
+ // The original starts to draw (nbLines + 2) lines above textY, except if there is a single line
+ // in which case it starts drawing at (nbLines + 3) above textY.
+ // Also clip to the screen height although the original does not do it.
+ int y = textY - 4 * CHAR_HEIGHT;
+ y = CLIP<int>(y, 0, 200 - CHAR_HEIGHT);
print_abc(msg, x, y);
return;
}
@@ -354,42 +365,61 @@ void DrasculaEngine::centerText(const char *message, int textX, int textY) {
// with the German translation.
if (!strchr(msg, ' ')) {
int len = strlen(msg);
- x = CLIP<int>(textX - len * CHAR_WIDTH / 2, 2, 317 - len * CHAR_WIDTH);
+ int x = CLIP<int>(textX - (len / 2) * CHAR_WIDTH - 1, 0, 319 - len * CHAR_WIDTH);
+ int y = textY - 4 * CHAR_HEIGHT;
+ y = CLIP<int>(y, 0, 200 - CHAR_HEIGHT);
print_abc(msg, x, y);
return;
}
// Message doesn't fit on screen, split it
-
+ char messageLines[15][41]; // screenWidth/charWidth = 320/8 = 40. Thus lines can have up to 41 characters with the null terminator (despite the original allocating only 40 characters here).
+ int curLine = 0;
+ char messageCurLine[50];
+ char tmpMessageCurLine[50];
+ *messageCurLine = 0;
+ *tmpMessageCurLine = 0;
// Get a word from the message
- curWord = strtok(msg, " ");
+ char* curWord = strtok(msg, " ");
while (curWord != NULL) {
// Check if the word and the current line fit on screen
- if (tmpMessageLine[0] != '\0')
- Common::strlcat(tmpMessageLine, " ", 200);
- Common::strlcat(tmpMessageLine, curWord, 200);
- if (textFitsCentered(tmpMessageLine, textX)) {
+ if (tmpMessageCurLine[0] != '\0')
+ Common::strlcat(tmpMessageCurLine, " ", 50);
+ Common::strlcat(tmpMessageCurLine, curWord, 50);
+ if (textFitsCentered(tmpMessageCurLine, textX)) {
// Line fits, so add the word to the current message line
- strcpy(messageLine, tmpMessageLine);
+ strcpy(messageCurLine, tmpMessageCurLine);
} else {
- // Line doesn't fit, so show the current line on screen and
- // create a new one
- // If it goes off screen, print_abc will adjust it
- x = CLIP<int>(textX, 60, 259) - strlen(messageLine) * CHAR_WIDTH / 2;
- print_abc(messageLine, x, y + curLine * (CHAR_HEIGHT + 2));
- Common::strlcpy(messageLine, curWord, 200);
- Common::strlcpy(tmpMessageLine, curWord, 200);
- curLine++;
+ // Line does't fit. Store the current line and start a new line.
+ Common::strlcpy(messageLines[curLine++], messageCurLine, 41);
+ Common::strlcpy(messageCurLine, curWord, 50);
+ Common::strlcpy(tmpMessageCurLine, curWord, 50);
}
// Get next word
curWord = strtok(NULL, " ");
-
if (curWord == NULL) {
- x = CLIP<int>(textX, 60, 259) - strlen(messageLine) * CHAR_WIDTH / 2;
- print_abc(messageLine, x, y + curLine * (CHAR_HEIGHT + 2));
+ // The original has an interesting bug that if we split the text on several lines
+ // a space is added at the end (which impacts the alignment, and may even cause the line
+ // to become too long).
+ Common::strlcat(messageCurLine, " ", 50);
+ if (!textFitsCentered(messageCurLine, textX)) {
+ messageCurLine[strlen(messageCurLine) - 1] = '\0';
+ Common::strlcpy(messageLines[curLine++], messageCurLine, 41);
+ strcpy(messageLines[curLine++], " ");
+ } else
+ Common::strlcpy(messageLines[curLine++], messageCurLine, 41);
}
}
+
+ // The original starts to draw (nbLines + 2) lines above textY.
+ // Also clip to the screen height although the original does not do it.
+ int y = textY - (curLine + 2) * CHAR_HEIGHT;
+ y = CLIP<int>(y, 0, 200 - curLine * (CHAR_HEIGHT + 2) + 2);
+ for (int line = 0 ; line < curLine ; ++line, y += CHAR_HEIGHT + 2) {
+ int textHalfLen = (strlen(messageLines[line]) / 2) * CHAR_WIDTH;
+ print_abc(messageLines[line], textX - textHalfLen - 1, y);
+ }
}
void DrasculaEngine::screenSaver() {