aboutsummaryrefslogtreecommitdiff
path: root/engines/sci/graphics/text32.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'engines/sci/graphics/text32.cpp')
-rw-r--r--engines/sci/graphics/text32.cpp231
1 files changed, 174 insertions, 57 deletions
diff --git a/engines/sci/graphics/text32.cpp b/engines/sci/graphics/text32.cpp
index d7738b22c9..99ffc6e328 100644
--- a/engines/sci/graphics/text32.cpp
+++ b/engines/sci/graphics/text32.cpp
@@ -29,6 +29,7 @@
#include "sci/engine/selector.h"
#include "sci/engine/state.h"
#include "sci/graphics/cache.h"
+#include "sci/graphics/celobj32.h"
#include "sci/graphics/compare.h"
#include "sci/graphics/font.h"
#include "sci/graphics/frameout.h"
@@ -39,10 +40,9 @@ namespace Sci {
int16 GfxText32::_defaultFontId = 0;
-GfxText32::GfxText32(SegManager *segMan, GfxCache *fonts, GfxScreen *screen) :
+GfxText32::GfxText32(SegManager *segMan, GfxCache *fonts) :
_segMan(segMan),
_cache(fonts),
- _screen(screen),
_scaledWidth(g_sci->_gfxFrameout->getCurrentBuffer().scriptWidth),
_scaledHeight(g_sci->_gfxFrameout->getCurrentBuffer().scriptHeight),
// Not a typo, the original engine did not initialise height, only width
@@ -59,38 +59,7 @@ GfxText32::GfxText32(SegManager *segMan, GfxCache *fonts, GfxScreen *screen) :
_font = _cache->getFont(_defaultFontId);
}
-#define BITMAP_HEADER_SIZE 46
-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);
-}
-
-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) {
+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) {
_field_22 = 0;
_borderColor = borderColor;
@@ -128,10 +97,8 @@ reg_t GfxText32::createFontBitmap(int16 width, int16 height, const Common::Rect
_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);
+ BitmapResource bitmap(_segMan, _width, _height, _skipColor, 0, 0, _scaledWidth, _scaledHeight, 0, false);
+ _bitmap = bitmap.getObject();
erase(bitmapRect, false);
@@ -140,14 +107,73 @@ reg_t GfxText32::createFontBitmap(int16 width, int16 height, const Common::Rect
}
drawTextBox();
+ return _bitmap;
+}
+
+reg_t GfxText32::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) {
+ _field_22 = 0;
+ _borderColor = borderColor;
+ _text = text;
+ _textRect = rect;
+ _foreColor = foreColor;
+ _dimmed = dimmed;
+
+ setFont(fontId);
+
+ int16 scriptWidth = g_sci->_gfxFrameout->getCurrentBuffer().scriptWidth;
+ int16 scriptHeight = g_sci->_gfxFrameout->getCurrentBuffer().scriptHeight;
+
+ int borderSize = 1;
+ mulinc(_textRect, Ratio(_scaledWidth, scriptWidth), Ratio(_scaledHeight, scriptHeight));
+
+ CelObjView view(celInfo.resourceId, celInfo.loopNo, celInfo.celNo);
+ _skipColor = view._transparentColor;
+ _width = view._width * _scaledWidth / view._scaledWidth;
+ _height = view._height * _scaledHeight / view._scaledHeight;
+
+ Common::Rect bitmapRect(_width, _height);
+ if (_textRect.intersects(bitmapRect)) {
+ _textRect.clip(bitmapRect);
+ } else {
+ _textRect = Common::Rect();
+ }
+
+ BitmapResource bitmap(_segMan, _width, _height, _skipColor, 0, 0, _scaledWidth, _scaledHeight, 0, false);
+ _bitmap = bitmap.getObject();
+ Buffer buffer(_width, _height, bitmap.getPixels());
+
+ // NOTE: The engine filled the bitmap pixels with 11 here, which is silly
+ // because then it just erased the bitmap using the skip color. So we don't
+ // fill the bitmap redundantly here.
+
+ _backColor = _skipColor;
+ erase(bitmapRect, false);
+ _backColor = backColor;
+
+ view.draw(buffer, bitmapRect, Common::Point(0, 0), false, Ratio(_scaledWidth, view._scaledWidth), Ratio(_scaledHeight, view._scaledHeight));
+
+ if (_backColor != skipColor && _foreColor != skipColor) {
+ erase(_textRect, false);
+ }
+
+ if (text.size() > 0) {
+ if (_foreColor == skipColor) {
+ error("TODO: Implement transparent text");
+ } else {
+ if (borderColor != -1) {
+ drawFrame(bitmapRect, borderSize, _borderColor, false);
+ }
+
+ drawTextBox();
+ }
+ }
- *outBitmapObject = _bitmap;
return _bitmap;
}
-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;
+reg_t GfxText32::createTitledBitmap(const int16 width, const int16 height, const Common::Rect &textRect, const Common::String &text, const int16 foreColor, const int16 backColor, const int16 skipColor, const GuiResourceId fontId, const TextAlign alignment, const int16 borderColor, Common::String &title, const int16 titleForeColor, const int16 titleBackColor, const GuiResourceId titleFontId, const bool doScaling) {
+ warning("TODO: createTitledBitmap incomplete !");
+ return createFontBitmap(width, height, textRect, text, foreColor, backColor, skipColor, fontId, alignment, borderColor, false, doScaling);
}
void GfxText32::setFont(const GuiResourceId fontId) {
@@ -164,16 +190,35 @@ void GfxText32::drawFrame(const Common::Rect &rect, const int16 size, const uint
Common::Rect targetRect = doScaling ? scaleRect(rect) : rect;
byte *bitmap = _segMan->getHunkPointer(_bitmap);
- byte *pixels = bitmap + READ_SCI11ENDIAN_UINT32(bitmap + 28);
+ byte *pixels = bitmap + READ_SCI11ENDIAN_UINT32(bitmap + 28) + rect.top * _width + rect.left;
// 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);
+ int16 rectWidth = targetRect.width();
+ int16 sidesHeight = targetRect.height() - size * 2;
+ int16 centerWidth = rectWidth - size * 2;
+ int16 stride = _width - rectWidth;
+
+ for (int16 y = 0; y < size; ++y) {
+ memset(pixels, color, rectWidth);
+ pixels += _width;
+ }
+ for (int16 y = 0; y < sidesHeight; ++y) {
+ for (int16 x = 0; x < size; ++x) {
+ *pixels++ = color;
+ }
+ pixels += centerWidth;
+ for (int16 x = 0; x < size; ++x) {
+ *pixels++ = color;
+ }
+ pixels += stride;
+ }
+ for (int16 y = 0; y < size; ++y) {
+ memset(pixels, color, rectWidth);
+ pixels += _width;
+ }
}
-void GfxText32::drawChar(const uint8 charIndex) {
+void GfxText32::drawChar(const char charIndex) {
byte *bitmap = _segMan->getHunkPointer(_bitmap);
byte *pixels = bitmap + READ_SCI11ENDIAN_UINT32(bitmap + 28);
@@ -181,7 +226,7 @@ void GfxText32::drawChar(const uint8 charIndex) {
_drawPosition.x += _font->getCharWidth(charIndex);
}
-uint16 GfxText32::getCharWidth(const uint8 charIndex, const bool doScaling) const {
+uint16 GfxText32::getCharWidth(const char charIndex, const bool doScaling) const {
uint16 width = _font->getCharWidth(charIndex);
if (doScaling) {
width = scaleUpWidth(width);
@@ -224,6 +269,11 @@ void GfxText32::drawTextBox() {
}
}
+void GfxText32::drawTextBox(const Common::String &text) {
+ _text = text;
+ drawTextBox();
+}
+
void GfxText32::drawText(const uint index, uint length) {
assert(index + length <= _text.size());
@@ -280,6 +330,51 @@ void GfxText32::drawText(const uint index, uint length) {
}
}
+void GfxText32::invertRect(const reg_t bitmap, int16 bitmapStride, const Common::Rect &rect, const uint8 foreColor, const uint8 backColor, const bool doScaling) {
+ Common::Rect targetRect = rect;
+ if (doScaling) {
+ bitmapStride = bitmapStride * _scaledWidth / g_sci->_gfxFrameout->getCurrentBuffer().scriptWidth;
+ targetRect = scaleRect(rect);
+ }
+
+ byte *bitmapData = _segMan->getHunkPointer(bitmap);
+
+ // NOTE: SCI code is super weird here; it seems to be trying to look at the
+ // entire size of the bitmap including the header, instead of just the pixel
+ // data size. We just look at the pixel size. This function generally is an
+ // odd duck since the stride dimension for a bitmap is built in to the bitmap
+ // header, so perhaps it was once an unheadered bitmap format and this
+ // function was never updated to match? Or maybe they exploit the
+ // configurable stride length somewhere else to do stair stepping inverts...
+ uint32 invertSize = targetRect.height() * bitmapStride + targetRect.width();
+ uint32 bitmapSize = READ_SCI11ENDIAN_UINT32(bitmapData + 12);
+
+ if (invertSize >= bitmapSize) {
+ error("InvertRect too big: %u >= %u", invertSize, bitmapSize);
+ }
+
+ // NOTE: Actual engine just added the bitmap header size hardcoded here
+ byte *pixel = bitmapData + READ_SCI11ENDIAN_UINT32(bitmapData + 28) + bitmapStride * targetRect.top + targetRect.left;
+
+ int16 stride = bitmapStride - targetRect.width();
+ int16 targetHeight = targetRect.height();
+ int16 targetWidth = targetRect.width();
+
+ for (int16 y = 0; y < targetHeight; ++y) {
+ for (int16 x = 0; x < targetWidth; ++x) {
+ if (*pixel == foreColor) {
+ *pixel = backColor;
+ } else if (*pixel == backColor) {
+ *pixel = foreColor;
+ }
+
+ ++pixel;
+ }
+
+ pixel += stride;
+ }
+}
+
uint GfxText32::getLongest(uint *charIndex, const int16 width) {
assert(width > 0);
@@ -514,7 +609,7 @@ Common::Rect GfxText32::getTextSize(const Common::String &text, int16 maxWidth,
}
void GfxText32::erase(const Common::Rect &rect, const bool doScaling) {
- Common::Rect targetRect = doScaling ? rect : scaleRect(rect);
+ Common::Rect targetRect = doScaling ? scaleRect(rect) : rect;
byte *bitmap = _segMan->getHunkPointer(_bitmap);
byte *pixels = bitmap + READ_SCI11ENDIAN_UINT32(bitmap + 28);
@@ -526,15 +621,37 @@ void GfxText32::erase(const Common::Rect &rect, const bool doScaling) {
buffer.fillRect(targetRect, _backColor);
}
-void GfxText32::disposeTextBitmap(reg_t hunkId) {
- _segMan->freeHunkEntry(hunkId);
+int16 GfxText32::getStringWidth(const Common::String &text) {
+ return getTextWidth(text, 0, 10000);
}
-int16 GfxText32::getStringWidth(const Common::String &text) {
- // TODO: The fact that this double-scales the text makes it
- // seem pretty unlikely that this is ever called in real life
- error("Called weirdo getStringWidth (FontMgr::StringWidth)");
- return scaleUpWidth(getTextWidth(text, 0, 10000));
+int16 GfxText32::getTextCount(const Common::String &text, const uint index, const Common::Rect &textRect, const bool doScaling) {
+ const int16 scriptWidth = g_sci->_gfxFrameout->getCurrentBuffer().scriptWidth;
+ const int16 scriptHeight = g_sci->_gfxFrameout->getCurrentBuffer().scriptHeight;
+
+ Common::Rect scaledRect(textRect);
+ if (doScaling) {
+ mulinc(scaledRect, Ratio(_scaledWidth, scriptWidth), Ratio(_scaledHeight, scriptHeight));
+ }
+
+ Common::String oldText = _text;
+ _text = text;
+
+ uint charIndex = index;
+ int16 maxWidth = scaledRect.width();
+ int16 lineCount = (scaledRect.height() - 2) / _font->getHeight();
+ while (lineCount--) {
+ getLongest(&charIndex, maxWidth);
+ }
+
+ _text = oldText;
+ return charIndex - index;
}
+int16 GfxText32::getTextCount(const Common::String &text, const uint index, const GuiResourceId fontId, const Common::Rect &textRect, const bool doScaling) {
+ setFont(fontId);
+ return getTextCount(text, index, textRect, doScaling);
+}
+
+
} // End of namespace Sci