aboutsummaryrefslogtreecommitdiff
path: root/engines
diff options
context:
space:
mode:
Diffstat (limited to 'engines')
-rw-r--r--engines/bladerunner/subtitles.cpp110
1 files changed, 66 insertions, 44 deletions
diff --git a/engines/bladerunner/subtitles.cpp b/engines/bladerunner/subtitles.cpp
index b61f54947d..7b0738774d 100644
--- a/engines/bladerunner/subtitles.cpp
+++ b/engines/bladerunner/subtitles.cpp
@@ -396,29 +396,50 @@ void Subtitles::draw(Graphics::Surface &s) {
/**
* Calculate the position (X axis - horizontal) where the current active subtitle text should be displayed/drawn
* This also determines if more than one lines should be drawn and what text goes into each line; splitting into multiple lines is done here
+*
+* The code first prioritizes splitting on the "new line" character.
+* That is, if the string contains at least one new line character, then line splitting occurs on new line characters exclusively.
+* The idea is that new line characters are put in the string explicitly by someone who wants specific control over line splitting
+* and thus they assume the responsibility for the resulting line segment widths (the code won't bother with them in this case).
+*
+* If there are NO "new line" characters, then the code will split lines on a space character (auto-split case).
+* For this case we only split if the full original line width exceeds a preset width threshold.
+* If the threshold is exceeded, then we parse the line and calculate how many lines we can split it into (starting from 2 lines)
+* to get segments smaller than the width threshold and also while maintaining (close to) even width across the resulting line segments.
+* What's happening here is that we loop dividing the original quote's character total by an increasing target number of line segments,
+* in order to get an "ideal" length for each segment (for evenness). Then we seek for split points (space character)
+* past the characters of the "ideal" length points.
+*
+* For the second case (auto-split), we don't account for the special case of a single word larger than max line length
+* (no spaces), as practically this won't ever happen.
+*
+* TODO; simplify this code
+* TODO: maybe calculate auto-split points based on quote pixel width and not character count
+* TODO: somehow merge with graphics/font.cpp -> wordWrapTextImpl ?
*/
void Subtitles::calculatePosition() {
- // wOrig is in pixels, origQuoteLength is num of chars in string
+ // wOrig is in pixels, origQuoteNumOfChars is num of chars in string
int wOrig = _subsFont->getTextWidth(_currentSubtitleTextFull) + 2; // +2 to account for left/ right shadow pixels (or for good measure)
- int origQuoteLength = _currentSubtitleTextFull.size();
+ int origQuoteNumOfChars = _currentSubtitleTextFull.size();
int tmpCharIndex = 0;
bool drawSingleLineQuote = false;
const uint8 *textCharacters = (const uint8 *)_currentSubtitleTextFull.c_str();
int tmpLineWidth[kMaxNumOfSubtitlesLines];
+ // initialization of aux variables
_currentSubtitleLines = 1;
- for (int i = 0; i < kMaxNumOfSubtitlesLines; ++i) {
- _subtitleLineSplitAtCharIndex[i] = 0;
- _subtitleLineQuote[i] = "";
- _subtitleLineScreenX[i] = 0;
- tmpLineWidth[i] = 0;
+ for (int j = 0; j < kMaxNumOfSubtitlesLines; ++j) {
+ _subtitleLineSplitAtCharIndex[j] = 0;
+ _subtitleLineQuote[j] = "";
+ _subtitleLineScreenX[j] = 0;
+ tmpLineWidth[j] = 0;
}
while (*textCharacters != 0) {
- // check for new line explicit split
- if (_currentSubtitleLines < kMaxNumOfSubtitlesLines && *textCharacters == 0x0A && tmpCharIndex != 0 && _subtitleLineSplitAtCharIndex[_currentSubtitleLines - 1] == 0) {
+ // check for new line explicit split case
+ if (_currentSubtitleLines < kMaxNumOfSubtitlesLines && *textCharacters == '\n' && tmpCharIndex != 0 && _subtitleLineSplitAtCharIndex[_currentSubtitleLines - 1] == 0) {
_subtitleLineSplitAtCharIndex[_currentSubtitleLines - 1] = tmpCharIndex;
_currentSubtitleLines += 1;
}
@@ -426,26 +447,25 @@ void Subtitles::calculatePosition() {
textCharacters += 1;
}
_subtitleLineSplitAtCharIndex[_currentSubtitleLines - 1] = tmpCharIndex;
- if (_currentSubtitleLines > 1) {
- // if we can split at new line characters:
+ if (_currentSubtitleLines > 1) { // This means that split on new line characters is possible
//
- int j = 0;
- textCharacters = (const uint8 *)_currentSubtitleTextFull.c_str(); // reset pointer to the start of subtitle quote
- for (int i = 0; i < origQuoteLength ; ++i) {
+ int j = 0; // j iterates over subtitle lines.
+ textCharacters = (const uint8 *)_currentSubtitleTextFull.c_str(); // reset pointer to the start of subtitle quote
+ for (int i = 0; i < origQuoteNumOfChars ; ++i) { // i iterates over line characters
if (j < _currentSubtitleLines && i < _subtitleLineSplitAtCharIndex[j]) {
_subtitleLineQuote[j] += textCharacters[i];
- } else { // i is at split point
+ } else { // i is at split point
_subtitleLineQuote[j] += '\0';
- j += 1;
+ j += 1; // start next line
}
}
- _subtitleLineQuote[j] += '\0'; // the last line should also be NULL terminated
+ _subtitleLineQuote[j] += '\0'; // the last line should also be NULL terminated
//
- // Check widths
- for (int i = 0; i < _currentSubtitleLines; ++i) {
- tmpLineWidth[i] = _subsFont->getTextWidth(_subtitleLineQuote[i]) + 2;
- _subtitleLineScreenX[i] = (639 - tmpLineWidth[i]) / 2;
- _subtitleLineScreenX[i] = CLIP(_subtitleLineScreenX[i], 0, 639 - tmpLineWidth[i]);
+ // Check widths and set starting X positions per line
+ for (int k = 0; k < _currentSubtitleLines; ++k) {
+ tmpLineWidth[k] = _subsFont->getTextWidth(_subtitleLineQuote[k]) + 2;
+ _subtitleLineScreenX[k] = (639 - tmpLineWidth[k]) / 2;
+ _subtitleLineScreenX[k] = CLIP(_subtitleLineScreenX[k], 0, 639 - tmpLineWidth[k]);
}
} else {
// Here we initially have _currentSubtitleLines == 1
@@ -454,19 +474,19 @@ void Subtitles::calculatePosition() {
if (wOrig > kMaxWidthPerLineToAutoSplitThresholdPx) { // kMaxWidthPerLineToAutoSplitThresholdPx is a practical chosen threshold for width for auto-splitting quotes purposes
// Start by splitting in two lines. If the new parts are still too lengthy, re-try by splitting in three lines, etc.
for (int linesToSplitInto = 2; linesToSplitInto <= kMaxNumOfSubtitlesLines; ++linesToSplitInto) {
- // find the first blank space after the middle
+ // find the first space after the middle
_subtitleLineQuote[0] = "";
_currentSubtitleLines = 1;
- textCharacters = (const uint8 *)_currentSubtitleTextFull.c_str(); // reset pointer to the start of subtitle quote
- textCharacters += (origQuoteLength / linesToSplitInto);
- _subtitleLineSplitAtCharIndex[0] = (origQuoteLength / linesToSplitInto);
- while (*textCharacters != 0 && *textCharacters != 0x20) { // seek for a blank space character
+ textCharacters = (const uint8 *)_currentSubtitleTextFull.c_str(); // reset pointer to the start of subtitle quote
+ textCharacters += (origQuoteNumOfChars / linesToSplitInto);
+ _subtitleLineSplitAtCharIndex[0] = (origQuoteNumOfChars / linesToSplitInto);
+ while (*textCharacters != 0 && !Common::isSpace(*textCharacters)) { // seek for a space character
_subtitleLineSplitAtCharIndex[0] += 1;
textCharacters += 1;
}
-// debug("space blank at: %d", _subtitleLineSplitAtCharIndex[0]);
- if (*textCharacters == 0x20) { // if we found a blank space
+// debug("space character at: %d", _subtitleLineSplitAtCharIndex[0]);
+ if (Common::isSpace(*textCharacters)) { // if we found a space, we store the segment up to this point in the first _subtitleLineQuote entry
textCharacters = (const uint8 *)_currentSubtitleTextFull.c_str();
for (int i = 0; i < _subtitleLineSplitAtCharIndex[0] ; ++i) {
_subtitleLineQuote[0] += textCharacters[i];
@@ -475,19 +495,19 @@ void Subtitles::calculatePosition() {
// debug(" Line 0 quote %s", _subtitleLineQuote[0].c_str());
tmpLineWidth[0] = _subsFont->getTextWidth(_subtitleLineQuote[0]) + 2; // check the width of the first segment of the quote
if (tmpLineWidth[0] > kMaxWidthPerLineToAutoSplitThresholdPx && linesToSplitInto < kMaxNumOfSubtitlesLines) {
- // reset process by trying to split into more lines
- continue; // try the for loop with increased linesToSplitInto by 1
+ // we exceed max width so we reset process by trying to split into more lines
+ continue; // re-try the For-loop with increased linesToSplitInto by 1
} else {
// keep current split, proceed with splitting the quote for the rest of the subtitle lines (linesToSplitInto)
for (int j = 2; j <= linesToSplitInto; ++j) {
- textCharacters = (const uint8 *)_currentSubtitleTextFull.c_str(); // reset pointer to the start of subtitle quote
- textCharacters += ((j * origQuoteLength) / linesToSplitInto);
- _subtitleLineSplitAtCharIndex[_currentSubtitleLines] = ((j * origQuoteLength) / linesToSplitInto);
- while (*textCharacters != 0 && *textCharacters != 0x20) {
+ textCharacters = (const uint8 *)_currentSubtitleTextFull.c_str(); // reset pointer to the start of subtitle quote
+ textCharacters += ((j * origQuoteNumOfChars) / linesToSplitInto); // move pointer to start of split-seek point for this line segment
+ _subtitleLineSplitAtCharIndex[_currentSubtitleLines] = ((j * origQuoteNumOfChars) / linesToSplitInto);
+ while (*textCharacters != 0 && !Common::isSpace(*textCharacters)) {
_subtitleLineSplitAtCharIndex[_currentSubtitleLines] += 1;
textCharacters += 1;
}
- textCharacters = (const uint8 *)_currentSubtitleTextFull.c_str(); // reset pointer to the start of subtitle quote
+ textCharacters = (const uint8 *)_currentSubtitleTextFull.c_str(); // reset pointer to the start of subtitle quote
for (int i = _subtitleLineSplitAtCharIndex[_currentSubtitleLines - 1] + 1; i < _subtitleLineSplitAtCharIndex[_currentSubtitleLines]; ++i) {
_subtitleLineQuote[_currentSubtitleLines] += textCharacters[i];
}
@@ -496,20 +516,22 @@ void Subtitles::calculatePosition() {
_currentSubtitleLines += 1;
}
//
- // Check widths
- for (int i = 0; i < _currentSubtitleLines; ++i) {
- tmpLineWidth[i] = _subsFont->getTextWidth(_subtitleLineQuote[i]) + 2;
- _subtitleLineScreenX[i] = (639 - tmpLineWidth[i]) / 2;
- _subtitleLineScreenX[i] = CLIP(_subtitleLineScreenX[i], 0, 639 - tmpLineWidth[i]);
+ // Check widths and set starting X positions per line
+ for (int j = 0; j < _currentSubtitleLines; ++j) {
+ tmpLineWidth[j] = _subsFont->getTextWidth(_subtitleLineQuote[j]) + 2;
+ _subtitleLineScreenX[j] = (639 - tmpLineWidth[j]) / 2;
+ _subtitleLineScreenX[j] = CLIP(_subtitleLineScreenX[j], 0, 639 - tmpLineWidth[j]);
}
- break; // from for loop about linesToSplitInto
+ break; // end the for-loop on linesToSplitInto
}
} else {
+ // the line exceeds max width but has no space characters
+ // we treat it as single line quote (it will appear clipped). This won't happen practically though.
drawSingleLineQuote = true;
- break; // from for loop about linesToSplitInto
+ break; // end the for-loop on linesToSplitInto
}
}
- } else {
+ } else { // the width of the line is smaller than the max width
drawSingleLineQuote = true;
}
if (drawSingleLineQuote) {