diff options
author | Filippos Karapetis | 2011-10-11 01:24:28 +0300 |
---|---|---|
committer | Filippos Karapetis | 2011-10-11 01:25:08 +0300 |
commit | 96ce226967741e65684c8b4d55adfbb5526fa787 (patch) | |
tree | fb0ef824d0566157c661ab41798346a1ff3efc27 /engines/sci | |
parent | 1402b47674f83a7f021417a4eebb8e132036cdcd (diff) | |
download | scummvm-rg350-96ce226967741e65684c8b4d55adfbb5526fa787.tar.gz scummvm-rg350-96ce226967741e65684c8b4d55adfbb5526fa787.tar.bz2 scummvm-rg350-96ce226967741e65684c8b4d55adfbb5526fa787.zip |
SCI: Proper implementation of text drawing for SCI2+
Diffstat (limited to 'engines/sci')
-rw-r--r-- | engines/sci/engine/kernel.h | 1 | ||||
-rw-r--r-- | engines/sci/engine/kernel_tables.h | 2 | ||||
-rw-r--r-- | engines/sci/engine/kgraphics.cpp | 5 | ||||
-rw-r--r-- | engines/sci/engine/selector.cpp | 1 | ||||
-rw-r--r-- | engines/sci/engine/selector.h | 1 | ||||
-rw-r--r-- | engines/sci/graphics/frameout.cpp | 11 | ||||
-rw-r--r-- | engines/sci/graphics/text32.cpp | 183 | ||||
-rw-r--r-- | engines/sci/graphics/text32.h | 23 |
8 files changed, 81 insertions, 146 deletions
diff --git a/engines/sci/engine/kernel.h b/engines/sci/engine/kernel.h index e3e3f51f75..e0ab954641 100644 --- a/engines/sci/engine/kernel.h +++ b/engines/sci/engine/kernel.h @@ -442,6 +442,7 @@ reg_t kUpdateScreenItem(EngineState *s, int argc, reg_t *argv); reg_t kDeleteScreenItem(EngineState *s, int argc, reg_t *argv); // Text reg_t kCreateTextBitmap(EngineState *s, int argc, reg_t *argv); +reg_t kDisposeTextBitmap(EngineState *s, int argc, reg_t *argv); // "Planes" in SCI32 are pictures reg_t kAddPlane(EngineState *s, int argc, reg_t *argv); reg_t kDeletePlane(EngineState *s, int argc, reg_t *argv); diff --git a/engines/sci/engine/kernel_tables.h b/engines/sci/engine/kernel_tables.h index 22f9c9556a..d32482d155 100644 --- a/engines/sci/engine/kernel_tables.h +++ b/engines/sci/engine/kernel_tables.h @@ -477,6 +477,7 @@ static SciKernelMapEntry s_kernelMap[] = { { MAP_CALL(CreateTextBitmap), SIG_EVERYWHERE, "i(.*)", NULL, NULL }, { MAP_CALL(DeletePlane), SIG_EVERYWHERE, "o", NULL, NULL }, { MAP_CALL(DeleteScreenItem), SIG_EVERYWHERE, "o", NULL, NULL }, + { MAP_CALL(DisposeTextBitmap), SIG_EVERYWHERE, "r", NULL, NULL }, { MAP_CALL(FrameOut), SIG_EVERYWHERE, "", NULL, NULL }, { MAP_CALL(GetHighPlanePri), SIG_EVERYWHERE, "", NULL, NULL }, { MAP_CALL(InPolygon), SIG_EVERYWHERE, "iio", NULL, NULL }, @@ -501,7 +502,6 @@ static SciKernelMapEntry s_kernelMap[] = { // SCI2 unmapped functions - TODO! // SetScroll - called by script 64909, Styler::doit() - // DisposeTextBitmap // PalCycle - called by Game::newRoom. Related to RemapColors. // VibrateMouse - used in QFG4 // ObjectIntersect - used in QFG4 diff --git a/engines/sci/engine/kgraphics.cpp b/engines/sci/engine/kgraphics.cpp index 4b35864268..b1314ef02f 100644 --- a/engines/sci/engine/kgraphics.cpp +++ b/engines/sci/engine/kgraphics.cpp @@ -1405,6 +1405,11 @@ reg_t kCreateTextBitmap(EngineState *s, int argc, reg_t *argv) { } } +reg_t kDisposeTextBitmap(EngineState *s, int argc, reg_t *argv) { + g_sci->_gfxText32->disposeTextBitmap(argv[0]); + return s->r_acc; +} + reg_t kGetWindowsOption(EngineState *s, int argc, reg_t *argv) { uint16 windowsOption = argv[0].toUint16(); switch (windowsOption) { diff --git a/engines/sci/engine/selector.cpp b/engines/sci/engine/selector.cpp index c2f857f319..a9aca9e22f 100644 --- a/engines/sci/engine/selector.cpp +++ b/engines/sci/engine/selector.cpp @@ -167,6 +167,7 @@ void Kernel::mapSelectors() { #ifdef ENABLE_SCI32 FIND_SELECTOR(data); FIND_SELECTOR(picture); + FIND_SELECTOR(bitmap); FIND_SELECTOR(plane); FIND_SELECTOR(top); FIND_SELECTOR(left); diff --git a/engines/sci/engine/selector.h b/engines/sci/engine/selector.h index 085dd6e832..bbd86bb03e 100644 --- a/engines/sci/engine/selector.h +++ b/engines/sci/engine/selector.h @@ -132,6 +132,7 @@ struct SelectorCache { #ifdef ENABLE_SCI32 Selector data; // Used by Array()/String() Selector picture; // Used to hold the picture ID for SCI32 pictures + Selector bitmap; // Used to hold the text bitmap for SCI32 texts Selector plane; Selector top; diff --git a/engines/sci/graphics/frameout.cpp b/engines/sci/graphics/frameout.cpp index 432ad051ca..17b4b015d5 100644 --- a/engines/sci/graphics/frameout.cpp +++ b/engines/sci/graphics/frameout.cpp @@ -547,16 +547,7 @@ void GfxFrameout::kernelFrameout() { } else { // Most likely a text entry if (lookupSelector(_segMan, itemEntry->object, SELECTOR(text), NULL, NULL) == kSelectorVariable) { - 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; - // 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(); - } - - g_sci->_gfxText32->drawTextBitmap(itemEntry->object, startX, startY, it->planeRect.width()); + g_sci->_gfxText32->drawTextBitmap(itemEntry->object); } } } diff --git a/engines/sci/graphics/text32.cpp b/engines/sci/graphics/text32.cpp index 7be3874ed0..8337d16fe6 100644 --- a/engines/sci/graphics/text32.cpp +++ b/engines/sci/graphics/text32.cpp @@ -43,163 +43,114 @@ GfxText32::GfxText32(SegManager *segMan, GfxCache *fonts, GfxScreen *screen) } GfxText32::~GfxText32() { - purgeCache(); -} - -void GfxText32::purgeCache() { - for (TextCache::iterator cacheIterator = _textCache.begin(); cacheIterator != _textCache.end(); cacheIterator++) { - delete[] cacheIterator->_value->surface; - delete cacheIterator->_value; - cacheIterator->_value = 0; - } - - _textCache.clear(); } reg_t GfxText32::createTextBitmap(reg_t textObject, uint16 maxWidth, uint16 maxHeight) { - if (_textCache.size() >= MAX_CACHED_TEXTS) - purgeCache(); - - uint32 textId = (textObject.segment << 16) | textObject.offset; - - if (_textCache.contains(textId)) { - // Delete the old entry - TextEntry *oldEntry = _textCache[textId]; - delete[] oldEntry->surface; - delete oldEntry; - _textCache.erase(textId); - } - - _textCache[textId] = createTextEntry(textObject, maxWidth, maxHeight); + reg_t stringObject = readSelector(_segMan, textObject, SELECTOR(text)); - // TODO: Create a new hunk pointer with the created surface - return NULL_REG; -} + // The object in the text selector of the item can be either a raw string + // or a Str object. In the latter case, we need to access the object's data + // selector to get the raw string. + if (_segMan->isHeapObject(stringObject)) + stringObject = readSelector(_segMan, stringObject, SELECTOR(data)); -// TODO: Finish this! -void GfxText32::drawTextBitmap(reg_t textObject, uint16 textX, uint16 textY, uint16 planeWidth) { - uint32 textId = (textObject.segment << 16) | textObject.offset; + Common::String text = _segMan->getString(stringObject); + GfxFont *font = _cache->getFont(readSelectorValue(_segMan, textObject, SELECTOR(font))); + bool dimmed = readSelectorValue(_segMan, textObject, SELECTOR(dimmed)); + uint16 foreColor = readSelectorValue(_segMan, textObject, SELECTOR(fore)); + uint16 x = readSelectorValue(_segMan, textObject, SELECTOR(x)); + uint16 y = readSelectorValue(_segMan, textObject, SELECTOR(y)); - if (!_textCache.contains(textId)) - createTextBitmap(textObject); + Common::Rect planeRect = getPlaneRect(textObject); + uint16 width = planeRect.width(); + uint16 height = planeRect.height(); - TextEntry *entry = _textCache[textId]; + // Limit rectangle dimensions, if requested + if (maxWidth > 0) + width = maxWidth; + if (maxHeight > 0) + height = maxHeight; - // This draws text the "SCI0-SCI11" way. In SCI2, text is prerendered in kCreateTextBitmap - // TODO: rewrite this the "SCI2" way (i.e. implement the text buffer to draw inside kCreateTextBitmap) - GfxFont *font = _cache->getFont(readSelectorValue(_segMan, textObject, SELECTOR(font))); - bool dimmed = readSelectorValue(_segMan,textObject, SELECTOR(dimmed)); - uint16 foreColor = readSelectorValue(_segMan, textObject, SELECTOR(fore)); + int entrySize = width * height; + reg_t memoryId = _segMan->allocateHunkEntry("TextBitmap()", entrySize); + writeSelector(_segMan, textObject, SELECTOR(bitmap), memoryId); + byte *memoryPtr = _segMan->getHunkPointer(memoryId); + memset(memoryPtr, 0, entrySize); - const char *txt = entry->text.c_str(); - int16 charCount; - uint16 maxWidth = (planeWidth > 0) ? planeWidth : _screen->getWidth() - textX; + int16 charCount = 0; + uint16 curX = 0, curY = 0; + const char *txt = text.c_str(); while (*txt) { - charCount = GetLongest(txt, maxWidth, font); + charCount = GetLongest(txt, width, font); if (charCount == 0) break; - uint16 curX = textX; - for (int i = 0; i < charCount; i++) { unsigned char curChar = txt[i]; - font->draw(curChar, textY, curX, foreColor, dimmed); + font->drawToBuffer(curChar, curY, curX, foreColor, dimmed, memoryPtr, width, height); curX += font->getCharWidth(curChar); } - textY += font->getHeight(); + curX = 0; + curY += font->getHeight(); txt += charCount; while (*txt == ' ') txt++; // skip over breaking spaces } - // TODO: The "SCI2" way of font drawing. Currently buggy - /* - for (int x = textX; x < entry->width; x++) { - for (int y = textY; y < entry->height; y++) { - byte pixel = entry->surface[y * entry->width + x]; - if (pixel) - _screen->putPixel(x, y, 1, pixel, 0, 0); - } - } - */ + return memoryId; } -TextEntry *GfxText32::getTextEntry(reg_t textObject) { - uint32 textId = (textObject.segment << 16) | textObject.offset; - - if (!_textCache.contains(textId)) - createTextBitmap(textObject); - - return _textCache[textId]; +void GfxText32::disposeTextBitmap(reg_t hunkId) { + _segMan->freeHunkEntry(hunkId); } -// TODO: Finish this! Currently buggy. -TextEntry *GfxText32::createTextEntry(reg_t textObject, uint16 maxWidth, uint16 maxHeight) { - reg_t stringObject = readSelector(_segMan, textObject, SELECTOR(text)); +void GfxText32::drawTextBitmap(reg_t textObject) { + reg_t hunkId = readSelector(_segMan, textObject, SELECTOR(bitmap)); + byte *surface = _segMan->getHunkPointer(hunkId); - // TODO: maxWidth, maxHeight (if > 0) + if (!surface) + error("Attempt to draw an invalid text bitmap"); - // The object in the text selector of the item can be either a raw string - // or a Str object. In the latter case, we need to access the object's data - // selector to get the raw string. - if (_segMan->isHeapObject(stringObject)) - stringObject = readSelector(_segMan, stringObject, SELECTOR(data)); + int curByte = 0; + Common::Rect nsRect = getNSRect(textObject); + Common::Rect planeRect = getPlaneRect(textObject); + uint16 textX = planeRect.left + nsRect.left; + uint16 textY = planeRect.top + nsRect.top; + uint16 width = nsRect.width(); + uint16 height = nsRect.height(); - const char *text = _segMan->getString(stringObject).c_str(); - GfxFont *font = _cache->getFont(readSelectorValue(_segMan, textObject, SELECTOR(font))); - bool dimmed = readSelectorValue(_segMan, textObject, SELECTOR(dimmed)); - uint16 foreColor = readSelectorValue(_segMan, textObject, SELECTOR(fore)); - uint16 x = readSelectorValue(_segMan, textObject, SELECTOR(x)); - uint16 y = readSelectorValue(_segMan, textObject, SELECTOR(y)); + for (int y = 0; y < height; y++) { + for (int x = 0; x < width; x++) { + byte pixel = surface[curByte++]; + if (pixel) + _screen->putPixel(x + textX, y + textY, 1, pixel, 0, 0); + } + } +} + +Common::Rect GfxText32::getPlaneRect(reg_t textObject) { + Common::Rect planeRect(0, 0, _screen->getWidth(), _screen->getHeight()); - // Now get the bounding box from the associated plane reg_t planeObject = readSelector(_segMan, textObject, SELECTOR(plane)); - Common::Rect planeRect; if (!planeObject.isNull()) { planeRect.top = readSelectorValue(_segMan, planeObject, SELECTOR(top)); planeRect.left = readSelectorValue(_segMan, planeObject, SELECTOR(left)); planeRect.bottom = readSelectorValue(_segMan, planeObject, SELECTOR(bottom)) + 1; planeRect.right = readSelectorValue(_segMan, planeObject, SELECTOR(right)) + 1; - } else { - planeRect.top = 0; - planeRect.left = 0; - planeRect.bottom = _screen->getHeight(); - planeRect.right = _screen->getWidth(); } - TextEntry *newEntry = new TextEntry(); - newEntry->object = stringObject; - newEntry->x = x; - newEntry->y = y; - newEntry->width = planeRect.width(); - newEntry->height = planeRect.height(); - newEntry->surface = new byte[newEntry->width * newEntry->height]; - memset(newEntry->surface, 0, newEntry->width * newEntry->height); - newEntry->text = _segMan->getString(stringObject); - - int16 /*maxTextWidth = 0,*/ charCount = 0; - uint16 curX = 0, curY = 0; - - while (*text) { - charCount = GetLongest(text, planeRect.width(), font); - if (charCount == 0) - break; - - for (int i = 0; i < charCount; i++) { - unsigned char curChar = text[i]; - font->drawToBuffer(curChar, curY, curX, foreColor, dimmed, newEntry->surface, newEntry->width, newEntry->height); - curX += font->getCharWidth(curChar); - } - - curY += font->getHeight(); - text += charCount; - while (*text == ' ') - text++; // skip over breaking spaces - } + return planeRect; +} - return newEntry; +Common::Rect GfxText32::getNSRect(reg_t textObject) { + Common::Rect nsRect; + nsRect.top = readSelectorValue(_segMan, textObject, SELECTOR(nsTop)); + nsRect.left = readSelectorValue(_segMan, textObject, SELECTOR(nsLeft)); + nsRect.bottom = readSelectorValue(_segMan, textObject, SELECTOR(nsBottom)) + 1; + nsRect.right = readSelectorValue(_segMan, textObject, SELECTOR(nsRight)) + 1; + return nsRect; } int16 GfxText32::GetLongest(const char *text, int16 maxWidth, GfxFont *font) { diff --git a/engines/sci/graphics/text32.h b/engines/sci/graphics/text32.h index 113fbb46a2..4c1e53d971 100644 --- a/engines/sci/graphics/text32.h +++ b/engines/sci/graphics/text32.h @@ -30,20 +30,6 @@ namespace Sci { -struct TextEntry { - reg_t object; - uint16 x; - uint16 y; - uint16 width; - uint16 height; - byte *surface; - Common::String text; -}; - -// TODO: Move to Cache, perhaps? -#define MAX_CACHED_TEXTS 20 -typedef Common::HashMap<uint32, TextEntry *> TextCache; - /** * Text32 class, handles text calculation and displaying of text for SCI2, SCI21 and SCI3 games */ @@ -52,22 +38,21 @@ public: GfxText32(SegManager *segMan, GfxCache *fonts, GfxScreen *screen); ~GfxText32(); reg_t createTextBitmap(reg_t textObject, uint16 maxWidth = 0, uint16 maxHeight = 0); - void drawTextBitmap(reg_t textObject, uint16 textX, uint16 textY, uint16 planeWidth); + void disposeTextBitmap(reg_t hunkId); + void drawTextBitmap(reg_t textObject); 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, uint16 maxWidth, uint16 maxHeight); 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(); + Common::Rect getPlaneRect(reg_t textObject); + Common::Rect getNSRect(reg_t textObject); SegManager *_segMan; GfxCache *_cache; - TextCache _textCache; GfxScreen *_screen; }; |