aboutsummaryrefslogtreecommitdiff
path: root/engines
diff options
context:
space:
mode:
authorColin Snover2016-02-14 12:07:30 -0600
committerColin Snover2016-02-18 13:18:02 -0600
commit20ccad80bfb689822be9f70512901557cbf244bf (patch)
tree40a0a63028a9355a1c58c3090c6c043af189e26c /engines
parent3bddd869abbd6ba6dd88b0911f80aa305c8d464e (diff)
downloadscummvm-rg350-20ccad80bfb689822be9f70512901557cbf244bf.tar.gz
scummvm-rg350-20ccad80bfb689822be9f70512901557cbf244bf.tar.bz2
scummvm-rg350-20ccad80bfb689822be9f70512901557cbf244bf.zip
SCI: WIP GfxText32 code
This at least prevents SQ6 from crashing when going into the introduction
Diffstat (limited to 'engines')
-rw-r--r--engines/sci/engine/kernel_tables.h2
-rw-r--r--engines/sci/engine/kgraphics32.cpp118
-rw-r--r--engines/sci/engine/selector.cpp5
-rw-r--r--engines/sci/engine/selector.h2
-rw-r--r--engines/sci/graphics/helpers.h11
-rw-r--r--engines/sci/graphics/text32.cpp248
-rw-r--r--engines/sci/graphics/text32.h137
-rw-r--r--engines/sci/sci.cpp4
-rw-r--r--engines/sci/util.cpp9
-rw-r--r--engines/sci/util.h3
10 files changed, 460 insertions, 79 deletions
diff --git a/engines/sci/engine/kernel_tables.h b/engines/sci/engine/kernel_tables.h
index ad0b86b8b1..b4a092a25c 100644
--- a/engines/sci/engine/kernel_tables.h
+++ b/engines/sci/engine/kernel_tables.h
@@ -670,7 +670,7 @@ static SciKernelMapEntry s_kernelMap[] = {
{ MAP_CALL(CelInfo), SIG_EVERYWHERE, "iiiiii", NULL, NULL },
{ MAP_CALL(SetLanguage), SIG_EVERYWHERE, "r", NULL, NULL },
{ MAP_CALL(ScrollWindow), SIG_EVERYWHERE, "i(.*)", kScrollWindow_subops, NULL },
- { MAP_CALL(SetFontRes), SIG_EVERYWHERE, "ii", NULL, NULL },
+ { MAP_DUMMY(SetFontRes), SIG_EVERYWHERE, "(.*)", NULL, NULL },
{ MAP_CALL(Font), SIG_EVERYWHERE, "i(.*)", NULL, NULL },
{ MAP_CALL(Bitmap), SIG_EVERYWHERE, "(.*)", NULL, NULL },
{ MAP_CALL(AddLine), SIG_EVERYWHERE, "oiiiiiiiii", NULL, NULL },
diff --git a/engines/sci/engine/kgraphics32.cpp b/engines/sci/engine/kgraphics32.cpp
index 64ef7ca610..a83836b033 100644
--- a/engines/sci/engine/kgraphics32.cpp
+++ b/engines/sci/engine/kgraphics32.cpp
@@ -174,41 +174,53 @@ reg_t kIsOnMe(EngineState *s, int argc, reg_t *argv) {
}
reg_t kCreateTextBitmap(EngineState *s, int argc, reg_t *argv) {
- switch (argv[0].toUint16()) {
- case 0: {
- if (argc != 4) {
- warning("kCreateTextBitmap(0): expected 4 arguments, got %i", argc);
- return NULL_REG;
- }
- reg_t object = argv[3];
- Common::String text = s->_segMan->getString(readSelector(s->_segMan, object, SELECTOR(text)));
- debugC(kDebugLevelStrings, "kCreateTextBitmap case 0 (%04x:%04x, %04x:%04x, %04x:%04x)",
- PRINT_REG(argv[1]), PRINT_REG(argv[2]), PRINT_REG(argv[3]));
- debugC(kDebugLevelStrings, "%s", text.c_str());
- int16 maxWidth = argv[1].toUint16();
- int16 maxHeight = argv[2].toUint16();
- g_sci->_gfxCoordAdjuster->fromScriptToDisplay(maxHeight, maxWidth);
- // These values can be larger than the screen in the SQ6 demo, room 100
- // TODO: Find out why. For now, don't show any text in that room.
- if (g_sci->getGameId() == GID_SQ6 && g_sci->isDemo() && s->currentRoomNumber() == 100)
- return NULL_REG;
- return g_sci->_gfxText32->createTextBitmap(object, maxWidth, maxHeight);
- }
- case 1: {
- if (argc != 2) {
- warning("kCreateTextBitmap(1): expected 2 arguments, got %i", argc);
- return NULL_REG;
- }
- reg_t object = argv[1];
- Common::String text = s->_segMan->getString(readSelector(s->_segMan, object, SELECTOR(text)));
- debugC(kDebugLevelStrings, "kCreateTextBitmap case 1 (%04x:%04x)", PRINT_REG(argv[1]));
- debugC(kDebugLevelStrings, "%s", text.c_str());
- return g_sci->_gfxText32->createTextBitmap(object);
- }
- default:
- warning("CreateTextBitmap(%d)", argv[0].toUint16());
+ SegManager *segMan = s->_segMan;
+
+ int16 subop = argv[0].toUint16();
+
+ int16 width;
+ int16 height;
+ reg_t object;
+
+ if (subop == 0) {
+ width = argv[1].toUint16();
+ height = argv[2].toUint16();
+ object = argv[3];
+ } else if (subop == 1) {
+ object = argv[1];
+ } else {
+ warning("Invalid kCreateTextBitmap subop %d", subop);
return NULL_REG;
}
+
+ Common::String text = segMan->getString(readSelector(segMan, object, SELECTOR(text)));
+ int16 foreColor = readSelectorValue(segMan, object, SELECTOR(fore));
+ int16 backColor = readSelectorValue(segMan, object, SELECTOR(back));
+ int16 skipColor = readSelectorValue(segMan, object, SELECTOR(skip));
+ GuiResourceId fontId = (GuiResourceId)readSelectorValue(segMan, object, SELECTOR(font));
+ int16 borderColor = readSelectorValue(segMan, object, SELECTOR(borderColor));
+ int16 dimmed = readSelectorValue(segMan, object, SELECTOR(dimmed));
+
+ Common::Rect rect(
+ readSelectorValue(segMan, object, SELECTOR(textLeft)),
+ readSelectorValue(segMan, object, SELECTOR(textTop)),
+ readSelectorValue(segMan, object, SELECTOR(textRight)),
+ readSelectorValue(segMan, object, SELECTOR(textBottom))
+ );
+
+ if (subop == 0) {
+ TextAlign alignment = (TextAlign)readSelectorValue(segMan, object, SELECTOR(mode));
+ reg_t out;
+ return g_sci->_gfxText32->createFontBitmap(width, height, rect, text, foreColor, backColor, skipColor, fontId, alignment, borderColor, dimmed, 1, &out);
+ } else {
+ CelInfo32 celInfo;
+ celInfo.type = kCelTypeView;
+ celInfo.resourceId = readSelectorValue(segMan, object, SELECTOR(view));
+ celInfo.loopNo = readSelectorValue(segMan, object, SELECTOR(loop));
+ celInfo.celNo = readSelectorValue(segMan, object, SELECTOR(cel));
+ reg_t out;
+ return g_sci->_gfxText32->createTitledFontBitmap(celInfo, rect, text, foreColor, backColor, fontId, skipColor, borderColor, dimmed, &out);
+ }
}
reg_t kDisposeTextBitmap(EngineState *s, int argc, reg_t *argv) {
@@ -455,34 +467,26 @@ reg_t kScrollWindow(EngineState *s, int argc, reg_t *argv) {
}
#endif
-reg_t kSetFontRes(EngineState *s, int argc, reg_t *argv) {
- // TODO: This defines the resolution that the fonts are supposed to be displayed
- // in. Currently, this is only used for showing high-res fonts in GK1 Mac, but
- // should be extended to handle other font resolutions such as those
-
- int xResolution = argv[0].toUint16();
- //int yResolution = argv[1].toUint16();
-
- g_sci->_gfxScreen->setFontIsUpscaled(xResolution == 640 &&
- g_sci->_gfxScreen->getUpscaledHires() != GFX_SCREEN_UPSCALED_DISABLED);
-
- return s->r_acc;
-}
-
reg_t kFont(EngineState *s, int argc, reg_t *argv) {
- // Handle font settings for SCI2.1
+ // TODO: Handle font settings for SCI2.1
switch (argv[0].toUint16()) {
case 1:
- // Set font resolution
- return kSetFontRes(s, argc - 1, argv + 1);
+ g_sci->_gfxText32->_scaledWidth = argv[1].toUint16();
+ g_sci->_gfxText32->_scaledHeight = argv[2].toUint16();
+ return NULL_REG;
default:
- warning("kFont: unknown subop %d", argv[0].toUint16());
+ error("kFont: unknown subop %d", argv[0].toUint16());
}
return s->r_acc;
}
+// TODO: Is this actually a thing??
+reg_t kSetFontRes(EngineState *s, int argc, reg_t *argv) {
+ return kStub(s, argc, argv);
+}
+
// TODO: Eventually, all of the kBitmap operations should be put
// in a separate class
@@ -516,8 +520,16 @@ reg_t kBitmap(EngineState *s, int argc, reg_t *argv) {
memset(memoryPtr + BITMAP_HEADER_SIZE, back, width * height);
// Save totalWidth, totalHeight
// TODO: Save the whole bitmap header, like SSCI does
- WRITE_LE_UINT16(memoryPtr, width);
- WRITE_LE_UINT16(memoryPtr + 2, height);
+ WRITE_SCI11ENDIAN_UINT16(memoryPtr, width);
+ WRITE_SCI11ENDIAN_UINT16(memoryPtr + 2, height);
+ WRITE_SCI11ENDIAN_UINT16(memoryPtr + 4, 0);
+ WRITE_SCI11ENDIAN_UINT16(memoryPtr + 6, 0);
+ memoryPtr[8] = 0;
+ WRITE_SCI11ENDIAN_UINT16(memoryPtr + 10, 0);
+ WRITE_SCI11ENDIAN_UINT16(memoryPtr + 20, BITMAP_HEADER_SIZE);
+ WRITE_SCI11ENDIAN_UINT32(memoryPtr + 28, 46);
+ WRITE_SCI11ENDIAN_UINT16(memoryPtr + 36, width);
+ WRITE_SCI11ENDIAN_UINT16(memoryPtr + 38, width);
return memoryId;
}
break;
diff --git a/engines/sci/engine/selector.cpp b/engines/sci/engine/selector.cpp
index 05a9e6c980..b86e0ffd68 100644
--- a/engines/sci/engine/selector.cpp
+++ b/engines/sci/engine/selector.cpp
@@ -179,6 +179,7 @@ void Kernel::mapSelectors() {
FIND_SELECTOR(fore);
FIND_SELECTOR(back);
FIND_SELECTOR(skip);
+ FIND_SELECTOR(borderColor);
FIND_SELECTOR(fixPriority);
FIND_SELECTOR(mirrored);
FIND_SELECTOR(visible);
@@ -187,6 +188,10 @@ void Kernel::mapSelectors() {
FIND_SELECTOR(inLeft);
FIND_SELECTOR(inBottom);
FIND_SELECTOR(inRight);
+ FIND_SELECTOR(textTop);
+ FIND_SELECTOR(textLeft);
+ FIND_SELECTOR(textBottom);
+ FIND_SELECTOR(textRight);
FIND_SELECTOR(magnifier);
#endif
}
diff --git a/engines/sci/engine/selector.h b/engines/sci/engine/selector.h
index a8b195f245..6b724ed271 100644
--- a/engines/sci/engine/selector.h
+++ b/engines/sci/engine/selector.h
@@ -146,6 +146,7 @@ struct SelectorCache {
Selector back;
Selector skip;
Selector dimmed;
+ Selector borderColor;
Selector fixPriority;
Selector mirrored;
@@ -153,6 +154,7 @@ struct SelectorCache {
Selector useInsetRect;
Selector inTop, inLeft, inBottom, inRight;
+ Selector textTop, textLeft, textBottom, textRight;
Selector magnifier;
#endif
diff --git a/engines/sci/graphics/helpers.h b/engines/sci/graphics/helpers.h
index e2fdedb27a..c238e2c87b 100644
--- a/engines/sci/graphics/helpers.h
+++ b/engines/sci/graphics/helpers.h
@@ -128,6 +128,17 @@ struct Window : public Port, public Common::Serializable {
#ifdef ENABLE_SCI32
/**
+ * Multiplies a rectangle by two ratios with default
+ * rounding. Modifies the rect directly.
+ */
+inline void mul(Common::Rect &rect, const Common::Rational &ratioX, const Common::Rational &ratioY) {
+ rect.left = (rect.left * ratioX).toInt();
+ rect.top = (rect.top * ratioY).toInt();
+ rect.right = (rect.right * ratioX).toInt();
+ rect.bottom = (rect.bottom * ratioY).toInt();
+}
+
+/**
* Multiplies a number by a rational number, rounding up to
* the nearest whole number.
*/
diff --git a/engines/sci/graphics/text32.cpp b/engines/sci/graphics/text32.cpp
index 56ce73e8fa..e0fb56b74b 100644
--- a/engines/sci/graphics/text32.cpp
+++ b/engines/sci/graphics/text32.cpp
@@ -31,6 +31,7 @@
#include "sci/graphics/cache.h"
#include "sci/graphics/compare.h"
#include "sci/graphics/font.h"
+#include "sci/graphics/frameout.h"
#include "sci/graphics/screen.h"
#include "sci/graphics/text32.h"
@@ -38,20 +39,220 @@ namespace Sci {
#define BITMAP_HEADER_SIZE 46
-#define SCI_TEXT32_ALIGNMENT_RIGHT -1
-#define SCI_TEXT32_ALIGNMENT_CENTER 1
-#define SCI_TEXT32_ALIGNMENT_LEFT 0
+GfxText32::GfxText32(SegManager *segMan, GfxCache *fonts, GfxScreen *screen) :
+ _segMan(segMan),
+ _cache(fonts),
+ _screen(screen),
+ _scaledWidth(g_sci->_gfxFrameout->getCurrentBuffer().scriptWidth),
+ _scaledHeight(g_sci->_gfxFrameout->getCurrentBuffer().scriptHeight),
+ _bitmap(NULL_REG) {}
+
+void GfxText32::buildBitmapHeader(byte *bitmap, const int16 width, const int16 height, const uint8 skipColor, const int16 displaceX, const int16 displaceY, const int16 scaledWidth, const int16 scaledHeight, const uint32 hunkPaletteOffset, const bool useRemap) const {
+
+ WRITE_SCI11ENDIAN_UINT16(bitmap + 0, width);
+ WRITE_SCI11ENDIAN_UINT16(bitmap + 2, height);
+ WRITE_SCI11ENDIAN_UINT16(bitmap + 4, (uint16)displaceX);
+ WRITE_SCI11ENDIAN_UINT16(bitmap + 6, (uint16)displaceY);
+ bitmap[8] = skipColor;
+ bitmap[9] = 0;
+ WRITE_SCI11ENDIAN_UINT16(bitmap + 10, 0);
+
+ if (useRemap) {
+ bitmap[10] |= 2;
+ }
+
+ WRITE_SCI11ENDIAN_UINT32(bitmap + 12, width * height);
+ WRITE_SCI11ENDIAN_UINT32(bitmap + 16, 0);
+
+ if (hunkPaletteOffset) {
+ WRITE_SCI11ENDIAN_UINT32(bitmap + 20, hunkPaletteOffset + BITMAP_HEADER_SIZE);
+ } else {
+ WRITE_SCI11ENDIAN_UINT32(bitmap + 20, 0);
+ }
+
+ WRITE_SCI11ENDIAN_UINT32(bitmap + 24, BITMAP_HEADER_SIZE);
+ WRITE_SCI11ENDIAN_UINT32(bitmap + 28, BITMAP_HEADER_SIZE);
+ WRITE_SCI11ENDIAN_UINT32(bitmap + 32, 0);
+ WRITE_SCI11ENDIAN_UINT16(bitmap + 36, scaledWidth);
+ WRITE_SCI11ENDIAN_UINT16(bitmap + 38, scaledHeight);
+}
+
+int16 GfxText32::_defaultFontId = 0;
+
+reg_t GfxText32::createFontBitmap(int16 width, int16 height, const Common::Rect &rect, const Common::String &text, const uint8 foreColor, const uint8 backColor, const uint8 skipColor, const GuiResourceId fontId, const TextAlign alignment, const int16 borderColor, const bool dimmed, const bool doScaling, reg_t *outBitmapObject) {
+
+ _field_22 = 0;
+ _borderColor = borderColor;
+ _text = text;
+ _textRect = rect;
+ _width = width;
+ _height = height;
+ _foreColor = foreColor;
+ _backColor = backColor;
+ _skipColor = skipColor;
+ _alignment = alignment;
+ _dimmed = dimmed;
+
+ if (fontId != _fontId) {
+ _fontId = fontId == -1 ? _defaultFontId : fontId;
+ _font = _cache->getFont(_fontId);
+ }
+
+ if (doScaling) {
+ int16 scriptWidth = g_sci->_gfxFrameout->getCurrentBuffer().scriptWidth;
+ int16 scriptHeight = g_sci->_gfxFrameout->getCurrentBuffer().scriptHeight;
+
+ Ratio scaleX(_scaledWidth, scriptWidth);
+ Ratio scaleY(_scaledHeight, scriptHeight);
+
+ _width = (_width * scaleX).toInt();
+ _height = (_height * scaleY).toInt();
+ mul(_textRect, scaleX, scaleY);
+ }
+
+ // _textRect represents where text is drawn inside the
+ // bitmap; clipRect is the entire bitmap
+ Common::Rect bitmapRect(_width, _height);
+
+ if (_textRect.intersects(bitmapRect)) {
+ _textRect.clip(bitmapRect);
+ } else {
+ _textRect = Common::Rect();
+ }
+
+ _bitmap = _segMan->allocateHunkEntry("FontBitmap()", _width * _height + BITMAP_HEADER_SIZE);
+
+ byte *bitmap = _segMan->getHunkPointer(_bitmap);
+ buildBitmapHeader(bitmap, _width, _height, _skipColor, 0, 0, _scaledWidth, _scaledHeight, 0, false);
+
+ erase(bitmapRect, false);
+
+ if (_borderColor > -1) {
+ drawFrame(bitmapRect, 1, _borderColor, false);
+ }
+
+ drawTextBox();
+
+ debug("Drawing a bitmap %dx%d, scaled %dx%d, border %d, font %d", width, height, _width, _height, _borderColor, _fontId);
-GfxText32::GfxText32(SegManager *segMan, GfxCache *fonts, GfxScreen *screen)
- : _segMan(segMan), _cache(fonts), _screen(screen) {
+ *outBitmapObject = _bitmap;
+ return _bitmap;
}
-GfxText32::~GfxText32() {
+reg_t GfxText32::createTitledFontBitmap(CelInfo32 &celInfo, Common::Rect &rect, Common::String &text, int16 foreColor, int16 backColor, int font, int16 skipColor, int16 borderColor, bool dimmed, void *unknown1) {
+ warning("TODO: createTitledFontBitmap");
+ return NULL_REG;
+}
+
+void GfxText32::drawFrame(const Common::Rect &rect, const int size, const uint8 color, const bool doScaling) {
+ Common::Rect targetRect = doScaling ? scaleRect(rect) : rect;
+
+ byte *bitmap = _segMan->getHunkPointer(_bitmap);
+ byte *pixels = bitmap + READ_SCI11ENDIAN_UINT32(bitmap + 28);
+
+ // NOTE: Not fully disassembled, but this should be right
+ // TODO: Implement variable frame size
+ assert(size == 1);
+ Buffer buffer(_width, _height, pixels);
+ buffer.frameRect(targetRect, color);
+}
+
+// TODO: This is not disassembled
+void GfxText32::drawTextBox() {
+ int16 charCount = 0;
+ uint16 curX = 0, curY = 0;
+ const char *txt = _text.c_str();
+ int16 textWidth, textHeight, totalHeight = 0, offsetX = 0, offsetY = 0;
+ uint16 start = 0;
+
+ // Calculate total text height
+ while (*txt) {
+ charCount = GetLongest(txt, _textRect.width(), _font);
+ if (charCount == 0)
+ break;
+
+ Width(txt, 0, (int16)strlen(txt), _fontId, textWidth, textHeight, true);
+
+ totalHeight += textHeight;
+ txt += charCount;
+ while (*txt == ' ') {
+ txt++; // skip over breaking spaces
+ }
+ }
+
+ txt = _text.c_str();
+
+ byte *pixels = _segMan->getHunkPointer(_bitmap);
+ pixels = pixels + READ_SCI11ENDIAN_UINT32(pixels + 28) + _width * _textRect.top + _textRect.left;
+
+ // Draw text in buffer
+ while (*txt) {
+ charCount = GetLongest(txt, _textRect.width(), _font);
+ if (charCount == 0)
+ break;
+ Width(txt, start, charCount, _fontId, textWidth, textHeight, true);
+
+ switch (_alignment) {
+ case kTextAlignRight:
+ offsetX = _textRect.width() - textWidth;
+ break;
+ case kTextAlignCenter:
+ // Center text both horizontally and vertically
+ offsetX = (_textRect.width() - textWidth) / 2;
+ offsetY = (_textRect.height() - totalHeight) / 2;
+ break;
+ case kTextAlignLeft:
+ offsetX = 0;
+ break;
+
+ default:
+ warning("Invalid alignment %d used in TextBox()", _alignment);
+ }
+
+ byte curChar;
+
+ for (int i = 0; i < charCount; i++) {
+ curChar = txt[i];
+
+ switch (curChar) {
+ case 0x0A:
+ case 0x0D:
+ case 0:
+ break;
+ case 0x7C:
+ warning("Code processing isn't implemented in SCI32");
+ break;
+ default:
+ _font->drawToBuffer(curChar, curY + offsetY, curX + offsetX, _foreColor, _dimmed, pixels, _width, _height);
+ curX += _font->getCharWidth(curChar);
+ break;
+ }
+ }
+
+ curX = 0;
+ curY += _font->getHeight();
+ txt += charCount;
+ while (*txt == ' ') {
+ txt++; // skip over breaking spaces
+ }
+ }
+}
+
+void GfxText32::erase(const Common::Rect &rect, const bool doScaling) {
+ Common::Rect targetRect = doScaling ? rect : scaleRect(rect);
+
+ byte *bitmap = _segMan->getHunkPointer(_bitmap);
+ byte *pixels = bitmap + READ_SCI11ENDIAN_UINT32(bitmap + 28);
+
+ // NOTE: There is an extra optimisation within the SCI code to
+ // do a single memset if the scaledRect is the same size as
+ // the bitmap, not implemented here.
+ Buffer buffer(_width, _height, pixels);
+ buffer.fillRect(targetRect, _backColor);
}
reg_t GfxText32::createScrollTextBitmap(Common::String text, reg_t textObject, uint16 maxWidth, uint16 maxHeight, reg_t prevHunk) {
return createTextBitmapInternal(text, textObject, maxWidth, maxHeight, prevHunk);
-
}
reg_t GfxText32::createTextBitmap(reg_t textObject, uint16 maxWidth, uint16 maxHeight, reg_t prevHunk) {
reg_t stringObject = readSelector(_segMan, textObject, SELECTOR(text));
@@ -116,8 +317,16 @@ reg_t GfxText32::createTextBitmapInternal(Common::String &text, reg_t textObject
memset(bitmap, backColor, width * height);
// Save totalWidth, totalHeight
- WRITE_LE_UINT16(memoryPtr, width);
- WRITE_LE_UINT16(memoryPtr + 2, height);
+ WRITE_SCI11ENDIAN_UINT16(memoryPtr, width);
+ WRITE_SCI11ENDIAN_UINT16(memoryPtr + 2, height);
+ WRITE_SCI11ENDIAN_UINT16(memoryPtr + 4, 0);
+ WRITE_SCI11ENDIAN_UINT16(memoryPtr + 6, 0);
+ memoryPtr[8] = 0;
+ WRITE_SCI11ENDIAN_UINT16(memoryPtr + 10, 0);
+ WRITE_SCI11ENDIAN_UINT16(memoryPtr + 20, BITMAP_HEADER_SIZE);
+ WRITE_SCI11ENDIAN_UINT32(memoryPtr + 28, 46);
+ WRITE_SCI11ENDIAN_UINT16(memoryPtr + 36, width);
+ WRITE_SCI11ENDIAN_UINT16(memoryPtr + 38, height);
int16 charCount = 0;
uint16 curX = 0, curY = 0;
@@ -149,15 +358,15 @@ reg_t GfxText32::createTextBitmapInternal(Common::String &text, reg_t textObject
Width(txt, start, charCount, fontId, textWidth, textHeight, true);
switch (alignment) {
- case SCI_TEXT32_ALIGNMENT_RIGHT:
+ case kTextAlignRight:
offsetX = width - textWidth;
break;
- case SCI_TEXT32_ALIGNMENT_CENTER:
+ case kTextAlignCenter:
// Center text both horizontally and vertically
offsetX = (width - textWidth) / 2;
offsetY = (height - totalHeight) / 2;
break;
- case SCI_TEXT32_ALIGNMENT_LEFT:
+ case kTextAlignLeft:
offsetX = 0;
break;
@@ -347,9 +556,10 @@ int16 GfxText32::Size(Common::Rect &rect, const char *text, GuiResourceId fontId
int16 maxTextWidth = 0, textWidth;
int16 totalHeight = 0, textHeight;
- // Adjust maxWidth if we're using an upscaled font
- if (_screen->fontIsUpscaled())
- maxWidth = maxWidth * _screen->getDisplayWidth() / _screen->getWidth();
+ int16 scriptWidth = g_sci->_gfxFrameout->getCurrentBuffer().scriptWidth;
+ int16 scriptHeight = g_sci->_gfxFrameout->getCurrentBuffer().scriptHeight;
+
+ maxWidth = maxWidth * _scaledWidth / scriptWidth;
rect.top = rect.left = 0;
GfxFont *font = _cache->getFont(fontId);
@@ -378,12 +588,8 @@ int16 GfxText32::Size(Common::Rect &rect, const char *text, GuiResourceId fontId
rect.right = maxWidth ? maxWidth : MIN(rect.right, maxTextWidth);
}
- // Adjust the width/height if we're using an upscaled font
- // for the scripts
- if (_screen->fontIsUpscaled()) {
- rect.right = rect.right * _screen->getWidth() / _screen->getDisplayWidth();
- rect.bottom = rect.bottom * _screen->getHeight() / _screen->getDisplayHeight();
- }
+ rect.right = rect.right * scriptWidth / _scaledWidth;
+ rect.bottom = rect.bottom * scriptHeight / _scaledHeight;
return rect.right;
}
diff --git a/engines/sci/graphics/text32.h b/engines/sci/graphics/text32.h
index 7ba7df50e4..42804f5670 100644
--- a/engines/sci/graphics/text32.h
+++ b/engines/sci/graphics/text32.h
@@ -23,15 +23,148 @@
#ifndef SCI_GRAPHICS_TEXT32_H
#define SCI_GRAPHICS_TEXT32_H
+#include "sci/graphics/celobj32.h"
+#include "sci/graphics/frameout.h"
+
namespace Sci {
+enum TextAlign {
+ kTextAlignLeft = 0,
+ kTextAlignCenter = 1,
+ kTextAlignRight = -1
+};
+
/**
- * Text32 class, handles text calculation and displaying of text for SCI2, SCI21 and SCI3 games
+ * This class handles text calculation and rendering for
+ * SCI32 games. The text calculation system in SCI32 is
+ * nearly the same as SCI16, which means this class behaves
+ * similarly. Notably, GfxText32 maintains drawing
+ * parameters across multiple calls.
*/
class GfxText32 {
+private:
+ /**
+ * The resource ID of the default font used by the game.
+ *
+ * @todo Check all SCI32 games to learn what their
+ * default font is.
+ */
+ static int16 _defaultFontId;
+
+ /**
+ * The width and height of the currently active text
+ * bitmap, in text-system coordinates.
+ */
+ int16 _width, _height;
+
+ /**
+ * The colour used to draw text.
+ */
+ uint8 _foreColor;
+
+ /**
+ * The background colour of the text box.
+ */
+ uint8 _backColor;
+
+ /**
+ * The transparent colour of the text box. Used when
+ * compositing the bitmap onto the screen.
+ */
+ uint8 _skipColor;
+
+ /**
+ * The rect where the text is drawn within the bitmap.
+ * This rect is clipped to the dimensions of the bitmap.
+ */
+ Common::Rect _textRect;
+
+ /**
+ * The text being drawn to the currently active text
+ * bitmap.
+ */
+ Common::String _text;
+
+ /**
+ * The font being used to draw the text.
+ */
+ GuiResourceId _fontId;
+
+ /**
+ * The colour of the text box border.
+ */
+ int16 _borderColor;
+
+ /**
+ * TODO: Document
+ */
+ bool _dimmed;
+
+ /**
+ * The text alignment for the drawn text.
+ */
+ TextAlign _alignment;
+
+ /**
+ * The memory handle of the currently active bitmap.
+ */
+ reg_t _bitmap;
+
+ /**
+ * TODO: Document
+ */
+ int _field_22;
+
+ /**
+ * The currently active font resource used to write text
+ * into the bitmap.
+ *
+ * @note SCI engine builds the font table directly
+ * inside of FontMgr; we use GfxFont instead.
+ */
+ GfxFont *_font;
+
+ // TODO: This is general for all CelObjMem and should be
+ // put in a single location, like maybe as a static
+ // method of CelObjMem?!
+ void buildBitmapHeader(byte *bitmap, const int16 width, const int16 height, const uint8 skipColor, const int16 displaceX, const int16 displaceY, const int16 scaledWidth, const int16 scaledHeight, const uint32 hunkPaletteOffset, const bool useRemap) const;
+
+ void drawFrame(const Common::Rect &rect, const int size, const uint8 color, const bool doScaling);
+ void drawTextBox();
+ void erase(const Common::Rect &rect, const bool doScaling);
+
+ inline Common::Rect scaleRect(const Common::Rect &rect) {
+ Common::Rect scaledRect(rect);
+ int16 scriptWidth = g_sci->_gfxFrameout->getCurrentBuffer().scriptWidth;
+ int16 scriptHeight = g_sci->_gfxFrameout->getCurrentBuffer().scriptHeight;
+ Ratio scaleX(_scaledWidth, scriptWidth);
+ Ratio scaleY(_scaledHeight, scriptHeight);
+ mul(scaledRect, scaleX, scaleY);
+ return scaledRect;
+ }
+
public:
GfxText32(SegManager *segMan, GfxCache *fonts, GfxScreen *screen);
- ~GfxText32();
+
+ /**
+ * The size of the x-dimension of the coordinate system
+ * used by the text renderer.
+ */
+ int16 _scaledWidth;
+
+ /**
+ * The size of the y-dimension of the coordinate system
+ * used by the text renderer.
+ */
+ int16 _scaledHeight;
+
+ reg_t createFontBitmap(int16 width, int16 height, const Common::Rect &rect, const Common::String &text, const uint8 foreColor, const uint8 backColor, const uint8 skipColor, const GuiResourceId fontId, TextAlign alignment, const int16 borderColor, bool dimmed, const bool doScaling, reg_t *outBitmapObject);
+
+ reg_t createTitledFontBitmap(CelInfo32 &celInfo, Common::Rect &rect, Common::String &text, int16 foreColor, int16 backColor, int font, int16 skipColor, int16 borderColor, bool dimmed, void *unknown1);
+
+#pragma mark -
+#pragma mark Old stuff
+
reg_t createTextBitmap(reg_t textObject, uint16 maxWidth = 0, uint16 maxHeight = 0, reg_t prevHunk = NULL_REG);
reg_t createScrollTextBitmap(Common::String text, reg_t textObject, uint16 maxWidth = 0, uint16 maxHeight = 0, reg_t prevHunk = NULL_REG);
void drawTextBitmap(int16 x, int16 y, Common::Rect planeRect, reg_t textObject);
diff --git a/engines/sci/sci.cpp b/engines/sci/sci.cpp
index 9ef28b214b..49eb31de53 100644
--- a/engines/sci/sci.cpp
+++ b/engines/sci/sci.cpp
@@ -690,10 +690,10 @@ void SciEngine::initGraphics() {
_gfxCompare = new GfxCompare(_gamestate->_segMan, _gfxCache, _gfxScreen, _gfxCoordAdjuster);
_gfxPaint32 = new GfxPaint32(_resMan, _gfxCoordAdjuster, _gfxScreen, _gfxPalette32);
_gfxPaint = _gfxPaint32;
- _gfxText32 = new GfxText32(_gamestate->_segMan, _gfxCache, _gfxScreen);
- _gfxControls32 = new GfxControls32(_gamestate->_segMan, _gfxCache, _gfxText32);
_robotDecoder = new RobotDecoder(getPlatform() == Common::kPlatformMacintosh);
_gfxFrameout = new GfxFrameout(_gamestate->_segMan, _resMan, _gfxCoordAdjuster, _gfxCache, _gfxScreen, _gfxPalette32, _gfxPaint32);
+ _gfxText32 = new GfxText32(_gamestate->_segMan, _gfxCache, _gfxScreen);
+ _gfxControls32 = new GfxControls32(_gamestate->_segMan, _gfxCache, _gfxText32);
_gfxFrameout->run();
} else {
#endif
diff --git a/engines/sci/util.cpp b/engines/sci/util.cpp
index c72d3beb19..ccec41a1ab 100644
--- a/engines/sci/util.cpp
+++ b/engines/sci/util.cpp
@@ -69,4 +69,13 @@ void WRITE_SCI11ENDIAN_UINT16(void *ptr, uint16 val) {
WRITE_LE_UINT16(ptr, val);
}
+#ifdef ENABLE_SCI32
+void WRITE_SCI11ENDIAN_UINT32(void *ptr, uint32 val) {
+ if (g_sci->getPlatform() == Common::kPlatformMacintosh && getSciVersion() >= SCI_VERSION_1_1)
+ WRITE_BE_UINT32(ptr, val);
+ else
+ WRITE_LE_UINT32(ptr, val);
+}
+#endif
+
} // End of namespace Sci
diff --git a/engines/sci/util.h b/engines/sci/util.h
index 378030939c..b0fee5151e 100644
--- a/engines/sci/util.h
+++ b/engines/sci/util.h
@@ -37,6 +37,9 @@ void WRITE_SCIENDIAN_UINT16(void *ptr, uint16 val);
uint16 READ_SCI11ENDIAN_UINT16(const void *ptr);
uint32 READ_SCI11ENDIAN_UINT32(const void *ptr);
void WRITE_SCI11ENDIAN_UINT16(void *ptr, uint16 val);
+#ifdef ENABLE_SCI32
+void WRITE_SCI11ENDIAN_UINT32(void *ptr, uint32 val);
+#endif
// Wrappers for reading integer values in resources that are
// LE in SCI1.1 Mac, but BE in SCI32 Mac