diff options
Diffstat (limited to 'engines/sci')
-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; |