[Scummvm-cvs-logs] scummvm branch-1-8 -> 27c65ed2f89239114f00aea7af59cd450d9548da

criezy criezy at scummvm.org
Fri Apr 8 03:16:59 CEST 2016


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

Summary:
fdf80bf9b9 DRASCULA: Improve text centering and spacing between lines
98b0e5f09d DRASCULA: Fix text alignment to be faithful to the original
27c65ed2f8 NEWS: Add Drascula text alignment fix


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

Commit Message:
DRASCULA: Improve text centering and spacing between lines

This in particular fixes bug #7111: Incorrect position in texts, not as the
original. However this codes centers the text better than what we see in
DosBox, so the result is not identical.

This change is based on the code before the commit 7cf7f4b
"Rewrote the very confusing centerText() function into something that
makes more sense". The changes in that commit do not all make
sense to me so I reverted the line spacing (to add back 2 pixels between
text lines) and part of the logic to center text. The result looks a lot
closer to the original engine in DosBox, but not identical.

Changed paths:
    engines/drascula/graphics.cpp



diff --git a/engines/drascula/graphics.cpp b/engines/drascula/graphics.cpp
index 077047a..5e37d2c 100644
--- a/engines/drascula/graphics.cpp
+++ b/engines/drascula/graphics.cpp
@@ -319,9 +319,12 @@ int DrasculaEngine::print_abc_opc(const char *said, int screenY, int game) {
 }
 
 bool DrasculaEngine::textFitsCentered(char *text, int x) {
-	int len = strlen(text);
-	int tmp = CLIP<int>(x - len * CHAR_WIDTH / 2, 60, 255);
-	return (tmp + len * CHAR_WIDTH) <= 320;
+	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);
 }
 
 void DrasculaEngine::centerText(const char *message, int textX, int textY) {
@@ -340,7 +343,7 @@ void DrasculaEngine::centerText(const char *message, int textX, int textY) {
 
 	// If the message fits on screen as-is, just print it here
 	if (textFitsCentered(msg, textX)) {
-		x = CLIP<int>(textX - strlen(msg) * CHAR_WIDTH / 2, 60, 255);
+		x = CLIP<int>(textX, 60, 259) - strlen(msg) * CHAR_WIDTH / 2;
 		print_abc(msg, x, y);
 		return;
 	}
@@ -351,7 +354,7 @@ 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, 0, 319 - len * CHAR_WIDTH);
+		x = CLIP<int>(textX - len * CHAR_WIDTH / 2, 2, 317 - len * CHAR_WIDTH);
 		print_abc(msg, x, y);
 		return;
 	}
@@ -372,8 +375,8 @@ void DrasculaEngine::centerText(const char *message, int textX, int textY) {
 			// 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 - strlen(messageLine) * CHAR_WIDTH / 2, 60, 255);
-			print_abc(messageLine, x, y + curLine * CHAR_HEIGHT);
+			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++;
@@ -383,8 +386,8 @@ void DrasculaEngine::centerText(const char *message, int textX, int textY) {
 		curWord = strtok(NULL, " ");
 
 		if (curWord == NULL) {
-			x = CLIP<int>(textX - strlen(messageLine) * CHAR_WIDTH / 2, 60, 255);
-			print_abc(messageLine, x, y + curLine * CHAR_HEIGHT);
+			x = CLIP<int>(textX, 60, 259) - strlen(messageLine) * CHAR_WIDTH / 2;
+			print_abc(messageLine, x, y + curLine * (CHAR_HEIGHT + 2));
 		}
 	}
 }


Commit: 98b0e5f09d34dad0a530d1cd6d255f1f5e969dcf
    https://github.com/scummvm/scummvm/commit/98b0e5f09d34dad0a530d1cd6d255f1f5e969dcf
Author: Thierry Crozat (criezy at scummvm.org)
Date: 2016-04-08T02:15:22+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() {


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

Commit Message:
NEWS: Add Drascula text alignment fix

Changed paths:
    NEWS



diff --git a/NEWS b/NEWS
index ecf05d3..cc5a4b7 100644
--- a/NEWS
+++ b/NEWS
@@ -12,6 +12,9 @@ For a more comprehensive changelog of the latest experimental code, see:
  CinE:
    - Fixed sound effect loading.
 
+ Drascula:
+   - Fixed text alignment to be faithful to the original.
+
  Gob:
    - Fixed lock up for some games during sound initialization.
 






More information about the Scummvm-git-logs mailing list