diff options
| -rw-r--r-- | engines/sci/engine/kgraphics.cpp | 8 | ||||
| -rw-r--r-- | engines/sci/graphics/frameout.cpp | 10 | ||||
| -rw-r--r-- | engines/sci/graphics/text32.cpp | 94 | ||||
| -rw-r--r-- | engines/sci/graphics/text32.h | 7 | 
4 files changed, 100 insertions, 19 deletions
diff --git a/engines/sci/engine/kgraphics.cpp b/engines/sci/engine/kgraphics.cpp index 2bf3f25930..83eb94195b 100644 --- a/engines/sci/engine/kgraphics.cpp +++ b/engines/sci/engine/kgraphics.cpp @@ -354,11 +354,9 @@ reg_t kTextSize(EngineState *s, int argc, reg_t *argv) {  	textWidth = dest[3].toUint16(); textHeight = dest[2].toUint16();  #ifdef ENABLE_SCI32 -	if (!g_sci->_gfxText16) { -		// TODO: Implement this -		textWidth = 0; textHeight = 0; -		warning("TODO: implement kTextSize for SCI32"); -	} else +	if (g_sci->_gfxText32) +		g_sci->_gfxText32->kernelTextSize(g_sci->strSplit(text.c_str(), sep).c_str(), font_nr, maxwidth, &textWidth, &textHeight); +	else  #endif  		g_sci->_gfxText16->kernelTextSize(g_sci->strSplit(text.c_str(), sep).c_str(), font_nr, maxwidth, &textWidth, &textHeight); diff --git a/engines/sci/graphics/frameout.cpp b/engines/sci/graphics/frameout.cpp index fcd22de7e1..e4d921a129 100644 --- a/engines/sci/graphics/frameout.cpp +++ b/engines/sci/graphics/frameout.cpp @@ -554,21 +554,13 @@ void GfxFrameout::kernelFrameout() {  					TextEntry *textEntry = g_sci->_gfxText32->getTextEntry(itemEntry->object);  					uint16 startX = ((textEntry->x * _screen->getWidth()) / scriptsRunningWidth) + it->planeRect.left;  					uint16 startY = ((textEntry->y * _screen->getHeight()) / scriptsRunningHeight) + it->planeRect.top; -					// HACK. The plane sometimes doesn't contain the correct width. This -					// hack breaks the dialog options when speaking with Grace, but it's -					// the best we got up to now. This happens because of the unimplemented -					// kTextWidth function in SCI32. -					// TODO: Remove this once kTextWidth has been implemented. -					uint16 w = it->planeRect.width() >= 20 ? it->planeRect.width() : _screen->getWidth() - 10; -  					// Upscale the coordinates/width if the fonts are already upscaled  					if (_screen->fontIsUpscaled()) {  						startX = startX * _screen->getDisplayWidth() / _screen->getWidth();  						startY = startY * _screen->getDisplayHeight() / _screen->getHeight(); -						w  = w * _screen->getDisplayWidth() / _screen->getWidth();  					} -					g_sci->_gfxText32->drawTextBitmap(itemEntry->object, startX, startY, w); +					g_sci->_gfxText32->drawTextBitmap(itemEntry->object, startX, startY, it->planeRect.width());  				}  			}  		} diff --git a/engines/sci/graphics/text32.cpp b/engines/sci/graphics/text32.cpp index 21372f1502..f13a56fa17 100644 --- a/engines/sci/graphics/text32.cpp +++ b/engines/sci/graphics/text32.cpp @@ -74,7 +74,7 @@ void GfxText32::createTextBitmap(reg_t textObject) {  }  // TODO: Finish this! -void GfxText32::drawTextBitmap(reg_t textObject, uint16 textX, uint16 textY, uint16 w) { +void GfxText32::drawTextBitmap(reg_t textObject, uint16 textX, uint16 textY, uint16 planeWidth) {  	uint32 textId = (textObject.segment << 16) | textObject.offset;  	if (!_textCache.contains(textId)) @@ -90,11 +90,19 @@ void GfxText32::drawTextBitmap(reg_t textObject, uint16 textX, uint16 textY, uin  	const char *txt = entry->text.c_str();  	int16 charCount; +	uint16 maxWidth = (planeWidth > 0) ? planeWidth : _screen->getWidth() - textX;  	while (*txt) { -		charCount = GetLongest(txt, w, font); -		if (charCount == 0) -			break; +		charCount = GetLongest(txt, maxWidth, font); +		if (charCount == 0) { +			// If the text does not fit inside the given plane, use the +			// whole screen. +			// TODO/FIXME: Is this really needed? Perhaps some other +			// functionality is missing instead? +			charCount = GetLongest(txt, _screen->getWidth() - textX, font); +			if (charCount == 0) +				break; +		}  		uint16 curX = textX; @@ -235,4 +243,82 @@ int16 GfxText32::GetLongest(const char *text, int16 maxWidth, GfxFont *font) {  	return maxChars;  } +void GfxText32::kernelTextSize(const char *text, int16 font, int16 maxWidth, int16 *textWidth, int16 *textHeight) { +	Common::Rect rect(0, 0, 0, 0); +	Size(rect, text, font, maxWidth); +	*textWidth = rect.width(); +	*textHeight = rect.height(); + +	// TODO: Setting textWidth properly changes the subtitle plane top to 0. +	// I have no idea why, so we currently hack in the old behavior here. +	*textWidth = 0; +	*textHeight = 0; +} + +void GfxText32::StringWidth(const char *str, GuiResourceId fontId, int16 &textWidth, int16 &textHeight) { +	Width(str, 0, (int16)strlen(str), fontId, textWidth, textHeight, true); +} + +void GfxText32::Width(const char *text, int16 from, int16 len, GuiResourceId fontId, int16 &textWidth, int16 &textHeight, bool restoreFont) { +	uint16 curChar; +	textWidth = 0; textHeight = 0; + +	GfxFont *font = _cache->getFont(fontId); + +	if (font) { +		text += from; +		while (len--) { +			curChar = (*(const byte *)text++); +			switch (curChar) { +			case 0x0A: +			case 0x0D: +			case 0x9781: // this one is used by SQ4/japanese as line break as well +				textHeight = MAX<int16> (textHeight, font->getHeight()); +				break; +			case 0x7C: +				warning("Code processing isn't implemented in SCI32"); +				break; +			default: +				textHeight = MAX<int16> (textHeight, font->getHeight()); +				textWidth += font->getCharWidth(curChar); +				break; +			} +		} +	} +} + +int16 GfxText32::Size(Common::Rect &rect, const char *text, GuiResourceId fontId, int16 maxWidth) { +	int16 charCount; +	int16 maxTextWidth = 0, textWidth; +	int16 totalHeight = 0, textHeight; + +	rect.top = rect.left = 0; +	GfxFont *font = _cache->getFont(fontId); + +	if (maxWidth < 0) { // force output as single line +		StringWidth(text, fontId, textWidth, textHeight); +		rect.bottom = textHeight; +		rect.right = textWidth; +	} else { +		// rect.right=found widest line with RTextWidth and GetLongest +		// rect.bottom=num. lines * GetPointSize +		rect.right = (maxWidth ? maxWidth : 192); +		const char *curPos = text; +		while (*curPos) { +			charCount = GetLongest(curPos, rect.right, font); +			if (charCount == 0) +				break; +			Width(curPos, 0, charCount, fontId, textWidth, textHeight, false); +			maxTextWidth = MAX(textWidth, maxTextWidth); +			totalHeight += textHeight; +			curPos += charCount; +			while (*curPos == ' ') +				curPos++; // skip over breaking spaces +		} +		rect.bottom = totalHeight; +		rect.right = maxWidth ? maxWidth : MIN(rect.right, maxTextWidth); +	} +	return rect.right; +} +  } // End of namespace Sci diff --git a/engines/sci/graphics/text32.h b/engines/sci/graphics/text32.h index 39fe710a86..7f70afc880 100644 --- a/engines/sci/graphics/text32.h +++ b/engines/sci/graphics/text32.h @@ -52,12 +52,17 @@ public:  	GfxText32(SegManager *segMan, GfxCache *fonts, GfxScreen *screen);  	~GfxText32();  	void createTextBitmap(reg_t textObject); -	void drawTextBitmap(reg_t textObject, uint16 textX, uint16 textY, uint16 w); +	void drawTextBitmap(reg_t textObject, uint16 textX, uint16 textY, uint16 planeWidth);  	int16 GetLongest(const char *text, int16 maxWidth, GfxFont *font);  	TextEntry *getTextEntry(reg_t textObject); +	void kernelTextSize(const char *text, int16 font, int16 maxWidth, int16 *textWidth, int16 *textHeight); +  private:  	TextEntry *createTextEntry(reg_t textObject); +	int16 Size(Common::Rect &rect, const char *text, GuiResourceId fontId, int16 maxWidth); +	void Width(const char *text, int16 from, int16 len, GuiResourceId orgFontId, int16 &textWidth, int16 &textHeight, bool restoreFont); +	void StringWidth(const char *str, GuiResourceId orgFontId, int16 &textWidth, int16 &textHeight);  	void purgeCache();  	SegManager *_segMan;  | 
