SCUMM: COMI: Fix string wrapping when wrap flag is active

This commit is contained in:
Andrea Boscarino 2021-08-17 02:01:00 +02:00 committed by athrxx
parent 378cf3a953
commit 359a9718e7
3 changed files with 85 additions and 1 deletions

View file

@ -532,6 +532,33 @@ int CharsetRenderer::getStringWidth(int arg, const byte *text, uint strLenMax) {
return width; return width;
} }
int CharsetRenderer::getStringHeight(const char *str, uint numBytesMax) {
assert(str);
int totalHeight = 0;
int lineHeight = 0;
if (!numBytesMax)
return 0;
while (*str && numBytesMax) {
// No treatment of the ^ commands here, since they're handled/removed in handleTextResource().
if (*str == '\n') {
totalHeight += (lineHeight ? lineHeight : getFontHeight()) + 1;
lineHeight = 0;
} else if (*str != '\r' && *str != _vm->_newLineCharacter) {
lineHeight = MAX<int>(lineHeight, getCharHeight(*str));
if (is2ByteCharacter(_vm->_language, *str)) {
++str;
--numBytesMax;
}
}
++str;
--numBytesMax;
}
return totalHeight + (lineHeight ? lineHeight : getFontHeight()) + 1;
}
void CharsetRenderer::addLinebreaks(int a, byte *str, int pos, int maxwidth) { void CharsetRenderer::addLinebreaks(int a, byte *str, int pos, int maxwidth) {
int lastKoreanLineBreak = -1; int lastKoreanLineBreak = -1;
int origPos = pos; int origPos = pos;

View file

@ -96,7 +96,8 @@ public:
virtual void printChar(int chr, bool ignoreCharsetMask) = 0; virtual void printChar(int chr, bool ignoreCharsetMask) = 0;
virtual void drawChar(int chr, Graphics::Surface &s, int x, int y) {} virtual void drawChar(int chr, Graphics::Surface &s, int x, int y) {}
virtual int getStringWidth(int arg, const byte *text, uint strLenMax = 100000); virtual int getStringWidth(int arg, const byte *text uint strLenMax = 100000);
int getStringHeight(const char *str, uint strLenMax = 100000);
void addLinebreaks(int a, byte *str, int pos, int maxwidth); void addLinebreaks(int a, byte *str, int pos, int maxwidth);
void translateColor(); void translateColor();

View file

@ -179,6 +179,62 @@ void ScummEngine_v6::enqueueText(const byte *text, int x, int y, byte color, byt
clipHeight = clipHeight + clipHeight / 2; clipHeight = clipHeight + clipHeight / 2;
y = MIN<int>(y, 470 - clipHeight); y = MIN<int>(y, 470 - clipHeight);
// HACK: Wrap the text when it's too long.
// The original does this by drawing word by word and adjusting x and y for each step of the pipeline.
// This, instead, is a mixture of code from SmushFont::drawStringWrap() and CHARSET_1(), which is just
// enough to split the full line into more smaller lines, which are treated as different blastText in
// the queue. Anyway this shouldn't generate more than 2 lines total but it's generalized just in case.
_charset->addLinebreaks(0, (byte *) bt.text, 0, _screenWidth - 20);
int16 substrPos[200];
memset(substrPos, 0, sizeof(substrPos));
int16 substrLen[200];
memset(substrLen, 0, sizeof(substrLen));
int len = (int) strlen((char *) bt.text);
int curPos = -1;
int numLines = 1;
// Save splitting information (position of the substring and its length)
while (curPos <= len) {
if (bt.text[curPos] == '\r') {
substrPos[numLines] = curPos + 1;
substrLen[numLines - 1] -= 1;
numLines++;
} else {
substrLen[numLines - 1] += 1;
}
curPos++;
}
// If we have found more than one line, then we split the lines and
// draw them from top to bottom
if (numLines > 1) {
int lastLineY = 0;
for (int i = 1; i < numLines; i++) {
BlastText &bt_secondary = _blastTextQueue[_blastTextQueuePos++];
strncpy((char*)bt_secondary.text, (char*)(bt.text + substrPos[i]), substrLen[i]);
bt_secondary.xpos = x;
bt_secondary.ypos = lastLineY = y + (numLines - i) * _charset->getStringHeight((char*)bt_secondary.text);
bt_secondary.color = color;
bt_secondary.charset = charset;
bt_secondary.center = center;
}
// Truncate the first substring accordingly
bt.text[substrLen[0]] = '\0';
// Now correct the vertical placement for the last line, and compensate bottom-up
int diffY = lastLineY - MIN<int>(lastLineY, 470 - clipHeight);
for (int i = 1; i < numLines; i++) {
BlastText &bt_compensation = _blastTextQueue[_blastTextQueuePos - i];
bt_compensation.ypos -= diffY;
}
// Also adjust the first line
y -= diffY;
}
} }
bt.xpos = x; bt.xpos = x;