aboutsummaryrefslogtreecommitdiff
path: root/engines/sci
diff options
context:
space:
mode:
Diffstat (limited to 'engines/sci')
-rw-r--r--engines/sci/engine/kgraphics.cpp8
-rw-r--r--engines/sci/graphics/frameout.cpp10
-rw-r--r--engines/sci/graphics/text32.cpp94
-rw-r--r--engines/sci/graphics/text32.h7
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;