[Scummvm-cvs-logs] scummvm master -> d256f18952623f7d7a720ed52327fe2a1f5a8004

criezy criezy at scummvm.org
Fri Apr 8 03:05:27 CEST 2016


This automated email contains information about 1 new commit which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .

Summary:
d256f18952 DRASCULA: Fix text alignment to be faithful to the original


Commit: d256f18952623f7d7a720ed52327fe2a1f5a8004
    https://github.com/scummvm/scummvm/commit/d256f18952623f7d7a720ed52327fe2a1f5a8004
Author: Thierry Crozat (criezy at scummvm.org)
Date: 2016-04-08T02:04:28+01:00

Commit Message:
DRASCULA: Fix text alignment to be faithful to the original

The changes in this commit should provide an identical text
placement to the original. In addition to using the original source
code as reference I have checked that is the case by comparing
with DosBox for the intro of the Spanish and English versions as
well as  for parts of the game with the English version. I added
comments for the obscure parts (such as the original adding a
space at the end of the last line of text when splitting a string
into several lines, thus impacting how that last line is aligned).

Changed paths:
    engines/drascula/graphics.cpp



diff --git a/engines/drascula/graphics.cpp b/engines/drascula/graphics.cpp
index 5e37d2c..4ed949c 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() {






More information about the Scummvm-git-logs mailing list