[Scummvm-cvs-logs] scummvm master -> 96ce226967741e65684c8b4d55adfbb5526fa787

bluegr md5 at scummvm.org
Tue Oct 11 00:34:21 CEST 2011


This automated email contains information about 1 new commit which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .

Summary:
96ce226967 SCI: Proper implementation of text drawing for SCI2+


Commit: 96ce226967741e65684c8b4d55adfbb5526fa787
    https://github.com/scummvm/scummvm/commit/96ce226967741e65684c8b4d55adfbb5526fa787
Author: Filippos Karapetis (md5 at scummvm.org)
Date: 2011-10-10T15:25:08-07:00

Commit Message:
SCI: Proper implementation of text drawing for SCI2+

Changed paths:
    engines/sci/engine/kernel.h
    engines/sci/engine/kernel_tables.h
    engines/sci/engine/kgraphics.cpp
    engines/sci/engine/selector.cpp
    engines/sci/engine/selector.h
    engines/sci/graphics/frameout.cpp
    engines/sci/graphics/text32.cpp
    engines/sci/graphics/text32.h



diff --git a/engines/sci/engine/kernel.h b/engines/sci/engine/kernel.h
index e3e3f51..e0ab954 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 22f9c95..d32482d 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 4b35864..b1314ef 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 c2f857f..a9aca9e 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 085dd6e..bbd86bb 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 432ad05..17b4b01 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 7be3874..8337d16 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 113fbb4..4c1e53d 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;
 };
 






More information about the Scummvm-git-logs mailing list