[Scummvm-git-logs] scummvm master -> 2df444cecbb509d2a37c53ec6decf8c31dd02fe8

sluicebox 22204938+sluicebox at users.noreply.github.com
Sun Jan 26 02:17:37 UTC 2020


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:
2df444cecb SCI32: Implement kInputText for PHANT2 easter eggs


Commit: 2df444cecbb509d2a37c53ec6decf8c31dd02fe8
    https://github.com/scummvm/scummvm/commit/2df444cecbb509d2a37c53ec6decf8c31dd02fe8
Author: sluicebox (22204938+sluicebox at users.noreply.github.com)
Date: 2020-01-25T18:11:57-08:00

Commit Message:
SCI32: Implement kInputText for PHANT2 easter eggs

Implements kInputText, which displays a black and white utility dialog
with a title and a text box in a fixed position using the system font.
The only known game that uses this is Phantasmagoria 2 for several
easter eggs, which now work. This was probably used by internal scripts
during game development.

kEditText and kInputText share a function in Sierra's interpreter for
processing events, so that code has been factored out and placed in
GfxControls32::processEditEvent().

GfxText32 can now measure text pixel height as SSCI did by identifying
the tallest character height in the current text, which the newly added
titled font bitmap code requires.

Fixes bug #10570

Changed paths:
    engines/sci/engine/kernel.h
    engines/sci/engine/kernel_tables.h
    engines/sci/engine/kgraphics32.cpp
    engines/sci/graphics/controls32.cpp
    engines/sci/graphics/controls32.h
    engines/sci/graphics/font.h
    engines/sci/graphics/text32.cpp
    engines/sci/graphics/text32.h


diff --git a/engines/sci/engine/kernel.h b/engines/sci/engine/kernel.h
index f784e7e..d762ee8 100644
--- a/engines/sci/engine/kernel.h
+++ b/engines/sci/engine/kernel.h
@@ -585,6 +585,7 @@ reg_t kListAllTrue(EngineState *s, int argc, reg_t *argv);
 reg_t kListSort(EngineState *s, int argc, reg_t *argv);
 
 reg_t kEditText(EngineState *s, int argc, reg_t *argv);
+reg_t kInputText(EngineState *s, int argc, reg_t *argv);
 reg_t kSetScroll(EngineState *s, int argc, reg_t *argv);
 
 reg_t kPaletteSetFromResource32(EngineState *s, int argc, reg_t *argv);
diff --git a/engines/sci/engine/kernel_tables.h b/engines/sci/engine/kernel_tables.h
index 8275a36..21263d0 100644
--- a/engines/sci/engine/kernel_tables.h
+++ b/engines/sci/engine/kernel_tables.h
@@ -954,7 +954,7 @@ static SciKernelMapEntry s_kernelMap[] = {
 	{ MAP_DUMMY(GetHighItemPri),   SIG_EVERYWHERE,           "(.*)",                  NULL,            NULL },
 	{ MAP_DUMMY(ShowStylePercent), SIG_EVERYWHERE,           "(.*)",                  NULL,            NULL },
 	{ MAP_DUMMY(InvertRect),       SIG_THRU_SCI21EARLY, SIGFOR_ALL, "(.*)",           NULL,            NULL },
-	{ MAP_DUMMY(InputText),        SIG_EVERYWHERE,           "(.*)",                  NULL,            NULL },
+	{ MAP_CALL(InputText),         SIG_EVERYWHERE,           "rri",                   NULL,            NULL },
 	{ MAP_CALL(TextWidth),         SIG_THRU_SCI21EARLY, SIGFOR_ALL, "ri",             NULL,            NULL },
 	{ MAP_CALL(PointSize),         SIG_THRU_SCI21EARLY, SIGFOR_ALL, "i",              NULL,            NULL },
 
@@ -1243,7 +1243,7 @@ static const char *const sci2_default_knames[] = {
 	/*0x29*/ "Dummy",
 	/*0x2a*/ "SetQuitStr",
 	/*0x2b*/ "EditText",
-	/*0x2c*/ "InputText",			// unused function
+	/*0x2c*/ "InputText",
 	/*0x2d*/ "CreateTextBitmap",
 	/*0x2e*/ "DisposeTextBitmap",	// Priority in early SCI2.1 games with a SCI2 kernel table
 	/*0x2f*/ "GetEvent",
@@ -1438,7 +1438,7 @@ static const char *const sci21_default_knames[] = {
 	/*0x48*/ "Message",
 	/*0x49*/ "Font",
 	/*0x4a*/ "EditText",
-	/*0x4b*/ "InputText",		// unused function
+	/*0x4b*/ "InputText",
 	/*0x4c*/ "ScrollWindow",	// Dummy in SCI3
 	/*0x4d*/ "Dummy",
 	/*0x4e*/ "Dummy",
diff --git a/engines/sci/engine/kgraphics32.cpp b/engines/sci/engine/kgraphics32.cpp
index c28f0cd..6c60cff 100644
--- a/engines/sci/engine/kgraphics32.cpp
+++ b/engines/sci/engine/kgraphics32.cpp
@@ -810,6 +810,10 @@ reg_t kEditText(EngineState *s, int argc, reg_t *argv) {
 	return g_sci->_gfxControls32->kernelEditText(argv[0]);
 }
 
+reg_t kInputText(EngineState *s, int argc, reg_t *argv) {
+	return g_sci->_gfxControls32->kernelInputText(argv[0], argv[1], argv[2].toSint16());
+}
+
 reg_t kAddLine(EngineState *s, int argc, reg_t *argv) {
 	const reg_t plane = argv[0];
 	const Common::Point startPoint(argv[1].toSint16(), argv[2].toSint16());
diff --git a/engines/sci/graphics/controls32.cpp b/engines/sci/graphics/controls32.cpp
index 9f0223b..298006c 100644
--- a/engines/sci/graphics/controls32.cpp
+++ b/engines/sci/graphics/controls32.cpp
@@ -57,8 +57,6 @@ GfxControls32::~GfxControls32() {
 #pragma mark Text input control
 
 reg_t GfxControls32::kernelEditText(const reg_t controlObject) {
-	SegManager *segMan = _segMan;
-
 	TextEditor editor;
 	reg_t textObject = readSelector(_segMan, controlObject, SELECTOR(text));
 	editor.text = _segMan->getString(textObject);
@@ -186,136 +184,243 @@ reg_t GfxControls32::kernelEditText(const reg_t controlObject) {
 		if (event.type != kSciEventNone)
 			eventManager->getSciEvent(kSciEventAny);
 
-		// In SSCI, the font and bitmap were reset here on each iteration
-		// through the loop, but this is not necessary since control is not
-		// yielded back to the VM until input is received, which means there is
-		// nothing that could modify the GfxText32's state with a different font
-		// in the meantime
+		if (processEditTextEvent(event, editor, screenItem, clearTextOnInput)) {
+			textChanged = true;
+		}
+	}
 
-		bool shouldDeleteChar = false;
-		bool shouldRedrawText = false;
-		uint16 lastCursorPosition = editor.cursorCharPosition;
-		if (event.type == kSciEventKeyDown) {
+	g_sci->_gfxFrameout->deletePlane(*plane);
+	if (readSelectorValue(_segMan, controlObject, SELECTOR(frameOut))) {
+		g_sci->_gfxFrameout->frameOut(true);
+	}
+
+	_segMan->freeBitmap(editor.bitmap);
+
+	if (textChanged) {
+		editor.text.trim();
+		SciArray &string = *_segMan->lookupArray(textObject);
+		string.fromString(editor.text);
+	}
+
+	return make_reg(0, textChanged);
+}
+
+reg_t GfxControls32::kernelInputText(const reg_t textObject, const reg_t titleObject, const int16 maxTextLength) {
+	// kInputText is only known to be used by Phantasmagoria 2 easter eggs
+
+	TextEditor editor;
+	editor.text = _segMan->getString(textObject);
+	editor.foreColor = 0;
+	editor.backColor = 255;
+	editor.skipColor = 250;
+	editor.fontId = -1;
+	editor.maxLength = maxTextLength;
+	editor.cursorCharPosition = 0;
+	editor.cursorIsDrawn = false;
+	editor.borderColor = 0;
+
+	Common::String title = _segMan->getString(titleObject);
+	_gfxText32->setFont(editor.fontId);
+	GfxFont *systemFont = _gfxCache->getFont(editor.fontId);
+	int16 textWidth = _gfxText32->getCharWidth('M', true) * maxTextLength;
+	int16 titleWidth = _gfxText32->getStringWidth(title);
+	int16 textHeight = _gfxText32->scaleUpHeight(systemFont->getHeight());
+	int16 width = MAX(textWidth, titleWidth) + 4;
+	int16 height = (textHeight * 2) + 7;
+
+	// SSCI doesn't scale the position when centering, so the dialog is
+	//  centered on the left side of the screen in Phantasmagoria 2.
+	Common::Rect editorPlaneRect(width, height);
+	editorPlaneRect.translate((320 - width) / 2, (200 - height) / 2);
+	editor.textRect = Common::Rect(1, (height / 2) + 1, width - 1, height - 1);
+	editor.width = width;
+
+	editor.bitmap = _gfxText32->createTitledFontBitmap(width, height, editor.textRect, editor.text,
+						editor.foreColor, editor.backColor, editor.skipColor, editor.fontId,
+						kTextAlignLeft, editor.borderColor, title,
+						editor.backColor, editor.foreColor, // title colors are inverse
+						editor.fontId, true, true);
+
+	drawCursor(editor);
+
+	Plane *plane = new Plane(editorPlaneRect, kPlanePicTransparent);
+	plane->changePic();
+	g_sci->_gfxFrameout->addPlane(plane);
+
+	CelInfo32 celInfo;
+	celInfo.type = kCelTypeMem;
+	celInfo.bitmap = editor.bitmap;
+
+	ScreenItem *screenItem = new ScreenItem(plane->_object, celInfo, Common::Point(), ScaleInfo());
+	plane->_screenItemList.add(screenItem);
+
+	g_sci->_gfxFrameout->frameOut(true);
+
+	EventManager *eventManager = g_sci->getEventManager();
+	bool wasEnterPressed = false;
+	bool clearTextOnInput = true;
+	for (;;) {
+		const SciEvent event = eventManager->getSciEvent(kSciEventAny | kSciEventPeek);
+
+		bool exitEventLoop = false;
+		// SSCI did not have a QUIT event, but we do, so we have to handle it
+		if (event.type == kSciEventQuit) {
+			exitEventLoop = true;
+		} else if (event.type == kSciEventKeyDown) {
 			switch (event.character) {
-			case kSciKeyLeft:
-				clearTextOnInput = false;
-				if (editor.cursorCharPosition > 0) {
-					--editor.cursorCharPosition;
-				}
+			case kSciKeyEsc:
+				exitEventLoop = true;
 				break;
-
-			case kSciKeyRight:
-				clearTextOnInput = false;
-				if (editor.cursorCharPosition < editor.text.size()) {
-					++editor.cursorCharPosition;
-				}
+			case kSciKeyEnter:
+				wasEnterPressed = true;
+				exitEventLoop = true;
 				break;
-
-			case kSciKeyHome:
-				clearTextOnInput = false;
-				editor.cursorCharPosition = 0;
+			default:
 				break;
+			}
+		}
 
-			case kSciKeyEnd:
-				clearTextOnInput = false;
-				editor.cursorCharPosition = editor.text.size();
-				break;
+		// consume all events except QUIT so that the engine quits
+		if (event.type != kSciEventNone && event.type != kSciEventQuit) {
+			eventManager->getSciEvent(kSciEventAny);
+		}
 
-			case kSciKeyInsert:
-				clearTextOnInput = false;
-				// Redrawing also changes the cursor rect to reflect the new
-				// insertion mode
-				shouldRedrawText = true;
-				_overwriteMode = !_overwriteMode;
-				break;
+		if (exitEventLoop) {
+			break;
+		}
 
-			case kSciKeyDelete:
-				clearTextOnInput = false;
-				if (editor.cursorCharPosition < editor.text.size()) {
-					shouldDeleteChar = true;
-				}
-				break;
+		processEditTextEvent(event, editor, screenItem, clearTextOnInput);
+	}
 
-			case kSciKeyBackspace:
-				clearTextOnInput = false;
-				shouldDeleteChar = true;
-				if (editor.cursorCharPosition > 0) {
-					--editor.cursorCharPosition;
-				}
-				break;
+	g_sci->_gfxFrameout->deletePlane(*plane);
+	g_sci->_gfxFrameout->frameOut(true);
+	_segMan->freeBitmap(editor.bitmap);
 
-			case kSciKeyEtx:
-				editor.text.clear();
-				editor.cursorCharPosition = 0;
-				shouldRedrawText = true;
-				break;
+	editor.text.trim();
+	SciArray &string = *_segMan->lookupArray(textObject);
+	string.fromString(editor.text);
 
-			default: {
-				if (event.character >= 20 && event.character < 257) {
-					if (clearTextOnInput) {
-						clearTextOnInput = false;
-						editor.text.clear();
-					}
+	return make_reg(0, wasEnterPressed);
+}
 
-					if (
-						(_overwriteMode && editor.cursorCharPosition < editor.maxLength) ||
-						(editor.text.size() < editor.maxLength && _gfxText32->getCharWidth(event.character, true) + _gfxText32->getStringWidth(editor.text) < editor.textRect.width())
-					) {
-						if (_overwriteMode && editor.cursorCharPosition < editor.text.size()) {
-							editor.text.setChar(event.character, editor.cursorCharPosition);
-						} else {
-							editor.text.insertChar(event.character, editor.cursorCharPosition);
-						}
-
-						++editor.cursorCharPosition;
-						shouldRedrawText = true;
-					}
-				}
+bool GfxControls32::processEditTextEvent(const SciEvent &event, TextEditor &editor, ScreenItem *screenItem, bool &clearTextOnInput) {
+	// In SSCI, the font and bitmap were reset here on each iteration
+	// through the loop, but this is not necessary since control is not
+	// yielded back to the VM until input is received, which means there is
+	// nothing that could modify the GfxText32's state with a different font
+	// in the meantime
+
+	bool textChanged = false;
+	bool shouldDeleteChar = false;
+	bool shouldRedrawText = false;
+	uint16 lastCursorPosition = editor.cursorCharPosition;
+	if (event.type == kSciEventKeyDown) {
+		switch (event.character) {
+		case kSciKeyLeft:
+			clearTextOnInput = false;
+			if (editor.cursorCharPosition > 0) {
+				--editor.cursorCharPosition;
 			}
+			break;
+
+		case kSciKeyRight:
+			clearTextOnInput = false;
+			if (editor.cursorCharPosition < editor.text.size()) {
+				++editor.cursorCharPosition;
 			}
-		}
+			break;
 
-		if (shouldDeleteChar) {
+		case kSciKeyHome:
+			clearTextOnInput = false;
+			editor.cursorCharPosition = 0;
+			break;
+
+		case kSciKeyEnd:
+			clearTextOnInput = false;
+			editor.cursorCharPosition = editor.text.size();
+			break;
+
+		case kSciKeyInsert:
+			clearTextOnInput = false;
+			// Redrawing also changes the cursor rect to reflect the new
+			// insertion mode
 			shouldRedrawText = true;
+			_overwriteMode = !_overwriteMode;
+			break;
+
+		case kSciKeyDelete:
+			clearTextOnInput = false;
 			if (editor.cursorCharPosition < editor.text.size()) {
-				editor.text.deleteChar(editor.cursorCharPosition);
+				shouldDeleteChar = true;
 			}
-		}
+			break;
 
-		if (shouldRedrawText) {
-			eraseCursor(editor);
-			_gfxText32->erase(editor.textRect, true);
-			_gfxText32->drawTextBox(editor.text);
-			drawCursor(editor);
-			textChanged = true;
-			screenItem->_updated = g_sci->_gfxFrameout->getScreenCount();
-		} else if (editor.cursorCharPosition != lastCursorPosition) {
-			eraseCursor(editor);
-			drawCursor(editor);
-			screenItem->_updated = g_sci->_gfxFrameout->getScreenCount();
-		} else {
-			flashCursor(editor);
-			screenItem->_updated = g_sci->_gfxFrameout->getScreenCount();
-		}
+		case kSciKeyBackspace:
+			clearTextOnInput = false;
+			shouldDeleteChar = true;
+			if (editor.cursorCharPosition > 0) {
+				--editor.cursorCharPosition;
+			}
+			break;
 
-		g_sci->_gfxFrameout->frameOut(true);
-		g_sci->_gfxFrameout->throttle();
-	}
+		case kSciKeyEtx:
+			editor.text.clear();
+			editor.cursorCharPosition = 0;
+			shouldRedrawText = true;
+			break;
 
-	g_sci->_gfxFrameout->deletePlane(*plane);
-	if (readSelectorValue(segMan, controlObject, SELECTOR(frameOut))) {
-		g_sci->_gfxFrameout->frameOut(true);
+		default: {
+			if (event.character >= 20 && event.character < 257) {
+				if (clearTextOnInput) {
+					clearTextOnInput = false;
+					editor.text.clear();
+				}
+
+				if (
+					(_overwriteMode && editor.cursorCharPosition < editor.maxLength) ||
+					(editor.text.size() < editor.maxLength && _gfxText32->getCharWidth(event.character, true) + _gfxText32->getStringWidth(editor.text) < editor.textRect.width())
+				) {
+					if (_overwriteMode && editor.cursorCharPosition < editor.text.size()) {
+						editor.text.setChar(event.character, editor.cursorCharPosition);
+					} else {
+						editor.text.insertChar(event.character, editor.cursorCharPosition);
+					}
+
+					++editor.cursorCharPosition;
+					shouldRedrawText = true;
+				}
+			}
+		}
+		}
 	}
 
-	_segMan->freeBitmap(editor.bitmap);
+	if (shouldDeleteChar) {
+		shouldRedrawText = true;
+		if (editor.cursorCharPosition < editor.text.size()) {
+			editor.text.deleteChar(editor.cursorCharPosition);
+		}
+	}
 
-	if (textChanged) {
-		editor.text.trim();
-		SciArray &string = *_segMan->lookupArray(textObject);
-		string.fromString(editor.text);
+	if (shouldRedrawText) {
+		eraseCursor(editor);
+		_gfxText32->erase(editor.textRect, true);
+		_gfxText32->drawTextBox(editor.text);
+		drawCursor(editor);
+		textChanged = true;
+		screenItem->_updated = g_sci->_gfxFrameout->getScreenCount();
+	} else if (editor.cursorCharPosition != lastCursorPosition) {
+		eraseCursor(editor);
+		drawCursor(editor);
+		screenItem->_updated = g_sci->_gfxFrameout->getScreenCount();
+	} else {
+		flashCursor(editor);
+		screenItem->_updated = g_sci->_gfxFrameout->getScreenCount();
 	}
 
-	return make_reg(0, textChanged);
+	g_sci->_gfxFrameout->frameOut(true);
+	g_sci->_gfxFrameout->throttle();
+
+	return textChanged;
 }
 
 void GfxControls32::drawCursor(TextEditor &editor) {
diff --git a/engines/sci/graphics/controls32.h b/engines/sci/graphics/controls32.h
index de292da..3f74319 100644
--- a/engines/sci/graphics/controls32.h
+++ b/engines/sci/graphics/controls32.h
@@ -401,6 +401,7 @@ private:
 #pragma mark Text input control
 public:
 	reg_t kernelEditText(const reg_t controlObject);
+	reg_t kernelInputText(const reg_t textObject, const reg_t titleTextObject, const int16 maxTextLength);
 
 private:
 	/**
@@ -430,6 +431,12 @@ private:
 	 */
 	void flashCursor(TextEditor &editor);
 
+	/**
+	* Processes an edit text event during a text box event loop. Returns true if
+	* the event changed the text.
+	*/
+	bool processEditTextEvent(const SciEvent &event, TextEditor &editor, ScreenItem *screenItem, bool &clearTextOnInput);
+
 #pragma mark -
 #pragma mark Scrollable window control
 public:
diff --git a/engines/sci/graphics/font.h b/engines/sci/graphics/font.h
index 05008de..8be0a2d 100644
--- a/engines/sci/graphics/font.h
+++ b/engines/sci/graphics/font.h
@@ -43,6 +43,7 @@ public:
 	virtual byte getHeight() { return 0; }
 	virtual bool isDoubleByte(uint16 chr) { return false; }
 	virtual byte getCharWidth(uint16 chr) { return 0; }
+	virtual byte getCharHeight(uint16 chr) { return 0; }
 	virtual void draw(uint16 chr, int16 top, int16 left, byte color, bool greyedOutput) {}
 	virtual void drawToBuffer(uint16 chr, int16 top, int16 left, byte color, bool greyedOutput, byte *buffer, int16 width, int16 height) {}
 };
diff --git a/engines/sci/graphics/text32.cpp b/engines/sci/graphics/text32.cpp
index 6ebbcc0..3a5ed42 100644
--- a/engines/sci/graphics/text32.cpp
+++ b/engines/sci/graphics/text32.cpp
@@ -163,6 +163,91 @@ reg_t GfxText32::createFontBitmap(const CelInfo32 &celInfo, const Common::Rect &
 	return _bitmap;
 }
 
+reg_t GfxText32::createTitledFontBitmap(int16 width, int16 height, const Common::Rect &textRect, const Common::String &text, const uint8 foreColor, const uint8 backColor, const uint8 skipColor, const GuiResourceId fontId, const TextAlign alignment, const int16 borderColor, const Common::String &title, const uint8 titleForeColor, const uint8 titleBackColor, const GuiResourceId titleFontId, const bool doScaling, const bool gc) {
+
+	_borderColor = borderColor;
+	_width = width;
+	_height = height;
+	_skipColor = skipColor;
+
+	setFont(titleFontId);
+
+	int16 scriptWidth = g_sci->_gfxFrameout->getScriptWidth();
+	int16 scriptHeight = g_sci->_gfxFrameout->getScriptHeight();
+	Ratio scaleX(_xResolution, scriptWidth);
+	Ratio scaleY(_yResolution, scriptHeight);
+
+	if (doScaling) {
+		_width = (_width * scaleX).toInt();
+		_height = (_height * scaleY).toInt();
+	}
+
+	_text = title;
+	int16 titleWidth;
+	int16 titleHeight;
+	getTextDimensions(0, 10000, titleWidth, titleHeight);
+	if (getSciVersion() < SCI_VERSION_3) {
+		GfxFont *titleFont = _cache->getFont(titleFontId);
+		titleHeight = titleFont->getHeight();
+	}
+	titleWidth += 2;
+	titleHeight += 1;
+	if (borderColor != -1) {
+		titleWidth += 2;
+		titleHeight += 2;
+	}
+
+	// allocate memory for the bitmap
+	_segMan->allocateBitmap(&_bitmap, _width, _height, _skipColor, 0, 0, _xResolution, _yResolution, 0, false, gc);
+
+	// draw background
+	_backColor = backColor;
+	_textRect = Common::Rect(0, 0, width, height);
+	erase(_textRect, false);
+
+	// draw title background
+	_foreColor = titleForeColor;
+	_backColor = titleBackColor;
+	_alignment = kTextAlignCenter;
+	_dimmed = false;
+	_textRect.setHeight(titleHeight);
+	erase(_textRect, false);
+
+	// draw title border
+	if (borderColor != -1) {
+		drawFrame(_textRect, 1, borderColor, false);
+		_textRect.grow(-2);
+	}
+
+	// draw title text
+	drawTextBox();
+
+	setFont(fontId);
+	_text = text;
+	_foreColor = foreColor;
+	_backColor = backColor;
+	_alignment = alignment;
+	_textRect = textRect;
+	if (doScaling) {
+		mulinc(_textRect, scaleX, scaleY);
+	}
+
+	// draw text border
+	Common::Rect textBorderRect(0, titleHeight - 1, _width, _height);
+	_textRect.clip(textBorderRect);
+	if (borderColor != -1) {
+		drawFrame(textBorderRect, 1, borderColor, false);
+	}
+
+	// draw text
+	GfxFont *font = _cache->getFont(fontId);
+	if (_textRect.height() >= font->getHeight()) {
+		drawTextBox();
+	}
+
+	return _bitmap;
+}
+
 void GfxText32::setFont(const GuiResourceId fontId) {
 	// In SSCI, this calls FontMgr::BuildFontTable, and then a font table is
 	// built on the FontMgr directly; instead, because we already have GfxFont
@@ -495,7 +580,15 @@ uint GfxText32::getLongest(uint *charIndex, const int16 width) {
 }
 
 int16 GfxText32::getTextWidth(const uint index, uint length) const {
-	int16 width = 0;
+	int16 width;
+	int16 height;
+	getTextDimensions(index, length, width, height);
+	return width;
+}
+
+void GfxText32::getTextDimensions(const uint index, uint length, int16 &width, int16& height) const {
+	width = 0;
+	height = 0;
 
 	const char *text = _text.c_str() + index;
 
@@ -540,6 +633,10 @@ int16 GfxText32::getTextWidth(const uint index, uint length) const {
 			}
 		} else {
 			width += font->getCharWidth((unsigned char)currentChar);
+			byte charHeight = font->getCharHeight((unsigned char)currentChar);
+			if (height < charHeight) {
+				height = charHeight;
+			}
 		}
 
 		if (length > 0) {
@@ -547,8 +644,6 @@ int16 GfxText32::getTextWidth(const uint index, uint length) const {
 			--length;
 		}
 	}
-
-	return width;
 }
 
 int16 GfxText32::getTextWidth(const Common::String &text, const uint index, const uint length) {
diff --git a/engines/sci/graphics/text32.h b/engines/sci/graphics/text32.h
index f9de3ad..3e0d7dc 100644
--- a/engines/sci/graphics/text32.h
+++ b/engines/sci/graphics/text32.h
@@ -137,6 +137,12 @@ private:
 	 */
 	int16 getTextWidth(const uint index, uint length) const;
 
+	/**
+	* Gets the pixel dimensions of a substring of the currently loaded text,
+	* without scaling.
+	*/
+	void getTextDimensions(const uint index, uint length, int16 &width, int16& height) const;
+
 	inline Common::Rect scaleRect(const Common::Rect &rect) {
 		Common::Rect scaledRect(rect);
 		const int16 scriptWidth = g_sci->_gfxFrameout->getScriptWidth();
@@ -190,6 +196,11 @@ public:
 	 */
 	reg_t createFontBitmap(const CelInfo32 &celInfo, const Common::Rect &rect, const Common::String &text, const int16 foreColor, const int16 backColor, const GuiResourceId fontId, const int16 skipColor, const int16 borderColor, const bool dimmed, const bool gc);
 
+	/**
+	 * Creates a titled font bitmap with a flat color background.
+	 */
+	reg_t createTitledFontBitmap(int16 width, int16 height, const Common::Rect &textRect, const Common::String &text, const uint8 foreColor, const uint8 backColor, const uint8 skipColor, const GuiResourceId fontId, const TextAlign alignment, const int16 borderColor, const Common::String &title, const uint8 titleForeColor, const uint8 titleBackColor, const GuiResourceId titleFontId, const bool doScaling, const bool gc);
+
 	inline int scaleUpWidth(int value) const {
 		const int scriptWidth = g_sci->_gfxFrameout->getScriptWidth();
 		return (value * scriptWidth + _xResolution - 1) / _xResolution;




More information about the Scummvm-git-logs mailing list