diff options
| -rw-r--r-- | engines/sci/engine/kgraphics32.cpp | 9 | ||||
| -rw-r--r-- | engines/sci/engine/selector.cpp | 6 | ||||
| -rw-r--r-- | engines/sci/engine/selector.h | 4 | ||||
| -rw-r--r-- | engines/sci/event.cpp | 38 | ||||
| -rw-r--r-- | engines/sci/event.h | 16 | ||||
| -rw-r--r-- | engines/sci/graphics/controls32.cpp | 435 | ||||
| -rw-r--r-- | engines/sci/graphics/controls32.h | 82 | ||||
| -rw-r--r-- | engines/sci/graphics/frameout.cpp | 19 | ||||
| -rw-r--r-- | engines/sci/graphics/frameout.h | 33 | ||||
| -rw-r--r-- | engines/sci/graphics/plane32.cpp | 4 | ||||
| -rw-r--r-- | engines/sci/graphics/plane32.h | 25 | ||||
| -rw-r--r-- | engines/sci/graphics/screen_item32.cpp | 4 | ||||
| -rw-r--r-- | engines/sci/graphics/screen_item32.h | 2 | ||||
| -rw-r--r-- | engines/sci/graphics/text32.cpp | 69 | ||||
| -rw-r--r-- | engines/sci/graphics/text32.h | 82 | ||||
| -rw-r--r-- | engines/sci/sci.cpp | 2 | 
16 files changed, 610 insertions, 220 deletions
| diff --git a/engines/sci/engine/kgraphics32.cpp b/engines/sci/engine/kgraphics32.cpp index 0463b125ae..8d8b96167c 100644 --- a/engines/sci/engine/kgraphics32.cpp +++ b/engines/sci/engine/kgraphics32.cpp @@ -670,14 +670,9 @@ reg_t kBitmapCreateFromUnknown(EngineState *s, int argc, reg_t *argv) {  // but it handles events on its own, using an internal loop, instead of using SCI  // scripts for event management like kEditControl does. Called by script 64914,  // DEdit::hilite(). -reg_t kEditText(EngineState *s, int argc, reg_t *argv) { -	reg_t controlObject = argv[0]; - -	if (!controlObject.isNull()) { -		g_sci->_gfxControls32->kernelTexteditChange(controlObject); -	} -	return s->r_acc; +reg_t kEditText(EngineState *s, int argc, reg_t *argv) { +	return g_sci->_gfxControls32->kernelEditText(argv[0]);  }  reg_t kAddLine(EngineState *s, int argc, reg_t *argv) { diff --git a/engines/sci/engine/selector.cpp b/engines/sci/engine/selector.cpp index 1393e96880..ac621f58ae 100644 --- a/engines/sci/engine/selector.cpp +++ b/engines/sci/engine/selector.cpp @@ -180,6 +180,7 @@ void Kernel::mapSelectors() {  	FIND_SELECTOR(back);  	FIND_SELECTOR(skip);  	FIND_SELECTOR(borderColor); +	FIND_SELECTOR(width);  	FIND_SELECTOR(fixPriority);  	FIND_SELECTOR(mirrored);  	FIND_SELECTOR(visible); @@ -192,7 +193,12 @@ void Kernel::mapSelectors() {  	FIND_SELECTOR(textLeft);  	FIND_SELECTOR(textBottom);  	FIND_SELECTOR(textRight); +	FIND_SELECTOR(title); +	FIND_SELECTOR(titleFont); +	FIND_SELECTOR(titleFore); +	FIND_SELECTOR(titleBack);  	FIND_SELECTOR(magnifier); +	FIND_SELECTOR(frameOut);  	FIND_SELECTOR(casts);  #endif  } diff --git a/engines/sci/engine/selector.h b/engines/sci/engine/selector.h index a8bbbe75e3..f2d06d1cf4 100644 --- a/engines/sci/engine/selector.h +++ b/engines/sci/engine/selector.h @@ -147,6 +147,7 @@ struct SelectorCache {  	Selector skip;  	Selector dimmed;  	Selector borderColor; +	Selector width;  	Selector fixPriority;  	Selector mirrored; @@ -155,9 +156,10 @@ struct SelectorCache {  	Selector useInsetRect;  	Selector inTop, inLeft, inBottom, inRight;  	Selector textTop, textLeft, textBottom, textRight; +	Selector title, titleFont, titleFore, titleBack;  	Selector magnifier; - +	Selector frameOut;  	Selector casts; // needed for sync'ing screen items/planes with scripts, when our save/restore code is patched in (see GfxFrameout::syncWithScripts)  #endif  }; diff --git a/engines/sci/event.cpp b/engines/sci/event.cpp index 3322a273ae..34f1618514 100644 --- a/engines/sci/event.cpp +++ b/engines/sci/event.cpp @@ -29,6 +29,9 @@  #include "sci/console.h"  #include "sci/engine/state.h"  #include "sci/engine/kernel.h" +#ifdef ENABLE_SCI32 +#include "sci/graphics/frameout.h" +#endif  #include "sci/graphics/screen.h"  namespace Sci { @@ -133,8 +136,13 @@ static int altify(int ch) {  }  SciEvent EventManager::getScummVMEvent() { -	SciEvent input = { SCI_EVENT_NONE, 0, 0, Common::Point(0, 0) }; -	SciEvent noEvent = { SCI_EVENT_NONE, 0, 0, Common::Point(0, 0) }; +#ifdef ENABLE_SCI32 +	SciEvent input = { SCI_EVENT_NONE, 0, 0, Common::Point(), Common::Point() }; +	SciEvent noEvent = { SCI_EVENT_NONE, 0, 0, Common::Point(), Common::Point() }; +#else +	SciEvent input = { SCI_EVENT_NONE, 0, 0, Common::Point() }; +	SciEvent noEvent = { SCI_EVENT_NONE, 0, 0, Common::Point() }; +#endif  	Common::EventManager *em = g_system->getEventManager();  	Common::Event ev; @@ -155,7 +163,20 @@ SciEvent EventManager::getScummVMEvent() {  	// via pollEvent.  	// We also adjust the position based on the scaling of the screen.  	Common::Point mousePos = em->getMousePos(); -	g_sci->_gfxScreen->adjustBackUpscaledCoordinates(mousePos.y, mousePos.x); + +#if ENABLE_SCI32 +	if (getSciVersion() >= SCI_VERSION_2) { +		Buffer &screen = g_sci->_gfxFrameout->getCurrentBuffer(); + +		Common::Point mousePosSci = mousePos; +		mulru(mousePosSci, Ratio(screen.scriptWidth, screen.screenWidth), Ratio(screen.scriptHeight, screen.screenHeight)); +		noEvent.mousePosSci = input.mousePosSci = mousePosSci; +	} else { +#endif +		g_sci->_gfxScreen->adjustBackUpscaledCoordinates(mousePos.y, mousePos.x); +#if ENABLE_SCI32 +	} +#endif  	noEvent.mousePos = input.mousePos = mousePos; @@ -302,6 +323,11 @@ SciEvent EventManager::getScummVMEvent() {  		input.character = altify(input.character);  	if (getSciVersion() <= SCI_VERSION_1_MIDDLE && (scummVMKeyFlags & Common::KBD_CTRL) && input.character > 0 && input.character < 27)  		input.character += 96; // 0x01 -> 'a' +#ifdef ENABLE_SCI32 +	if (getSciVersion() >= SCI_VERSION_2 && (scummVMKeyFlags & Common::KBD_CTRL) && input.character == 'c') { +		input.character = SCI_KEY_ETX; +	} +#endif  	// If no actual key was pressed (e.g. if only a modifier key was pressed),  	// ignore the event @@ -329,7 +355,11 @@ void EventManager::updateScreen() {  }  SciEvent EventManager::getSciEvent(uint32 mask) { -	SciEvent event = { SCI_EVENT_NONE, 0, 0, Common::Point(0, 0) }; +#ifdef ENABLE_SCI32 +	SciEvent event = { SCI_EVENT_NONE, 0, 0, Common::Point(), Common::Point() }; +#else +	SciEvent event = { SCI_EVENT_NONE, 0, 0, Common::Point() }; +#endif  	EventManager::updateScreen(); diff --git a/engines/sci/event.h b/engines/sci/event.h index 0d0c550622..15a94b3e73 100644 --- a/engines/sci/event.h +++ b/engines/sci/event.h @@ -39,11 +39,18 @@ struct SciEvent {  	uint16 character;  	/** -	 * The mouse position at the time the event was created. -	 * -	 * These are display coordinates! +	 * The mouse position at the time the event was created, +	 * in display coordinates.  	 */  	Common::Point mousePos; + +#ifdef ENABLE_SCI32 +	/** +	 * The mouse position at the time the event was created, +	 * in script coordinates. +	 */ +	Common::Point mousePosSci; +#endif  };  /*Values for type*/ @@ -59,6 +66,9 @@ struct SciEvent {  #define SCI_EVENT_ANY             0x7fff  /* Keycodes of special keys: */ +#ifdef ENABLE_SCI32 +#define SCI_KEY_ETX           3 +#endif  #define SCI_KEY_ESC          27  #define SCI_KEY_BACKSPACE     8  #define SCI_KEY_ENTER        13 diff --git a/engines/sci/graphics/controls32.cpp b/engines/sci/graphics/controls32.cpp index df518888a9..fc028f7584 100644 --- a/engines/sci/graphics/controls32.cpp +++ b/engines/sci/graphics/controls32.cpp @@ -23,9 +23,11 @@  #include "common/system.h"  #include "sci/sci.h" +#include "sci/console.h"  #include "sci/event.h"  #include "sci/engine/kernel.h"  #include "sci/engine/seg_manager.h" +#include "sci/engine/state.h"  #include "sci/graphics/cache.h"  #include "sci/graphics/compare.h"  #include "sci/graphics/controls32.h" @@ -34,174 +36,323 @@  #include "sci/graphics/text32.h"  namespace Sci { +GfxControls32::GfxControls32(SegManager *segMan, GfxCache *cache, GfxText32 *text) : +	_segMan(segMan), +	_gfxCache(cache), +	_gfxText32(text), +	_overwriteMode(false), +	_nextCursorFlashTick(0) {} -GfxControls32::GfxControls32(SegManager *segMan, GfxCache *cache, GfxText32 *text) -	: _segMan(segMan), _cache(cache), _text(text) { -} +GfxControls32::~GfxControls32() {} -GfxControls32::~GfxControls32() { -} +reg_t GfxControls32::kernelEditText(const reg_t controlObject) { +	SegManager *segMan = _segMan; -void GfxControls32::kernelTexteditChange(reg_t controlObject) { -	SciEvent curEvent; -	uint16 maxChars = 40;	//readSelectorValue(_segMan, controlObject, SELECTOR(max));	// TODO -	reg_t textReference = readSelector(_segMan, controlObject, SELECTOR(text)); -	GfxFont *font = _cache->getFont(readSelectorValue(_segMan, controlObject, SELECTOR(font))); -	Common::String text; -	uint16 textSize; -	bool textChanged = false; -	bool textAddChar = false; -	Common::Rect rect; +	TextEditor editor; +	reg_t textObject = readSelector(_segMan, controlObject, SELECTOR(text)); +	editor.text = _segMan->getString(textObject); +	editor.foreColor = readSelectorValue(_segMan, controlObject, SELECTOR(fore)); +	editor.backColor = readSelectorValue(_segMan, controlObject, SELECTOR(back)); +	editor.skipColor = readSelectorValue(_segMan, controlObject, SELECTOR(skip)); +	editor.fontId = readSelectorValue(_segMan, controlObject, SELECTOR(font)); +	editor.maxLength = readSelectorValue(_segMan, controlObject, SELECTOR(width)); +	editor.bitmap = readSelector(_segMan, controlObject, SELECTOR(bitmap)); +	editor.cursorCharPosition = 0; +	editor.cursorIsDrawn = false; +	editor.borderColor = readSelectorValue(_segMan, controlObject, SELECTOR(borderColor)); -	if (textReference.isNull()) -		error("kEditControl called on object that doesn't have a text reference"); -	text = _segMan->getString(textReference); +	reg_t titleObject = readSelector(_segMan, controlObject, SELECTOR(title)); + +	int16 titleHeight = 0; +	GuiResourceId titleFontId = readSelectorValue(_segMan, controlObject, SELECTOR(titleFont)); +	if (!titleObject.isNull()) { +		GfxFont *titleFont = _gfxCache->getFont(titleFontId); +		titleHeight += _gfxText32->scaleUpHeight(titleFont->getHeight()) + 1; +		if (editor.borderColor != -1) { +			titleHeight += 2; +		} +	} -	// TODO: Finish this -	warning("kEditText ('%s')", text.c_str()); -	return; +	int16 width = 0; +	int16 height = titleHeight; -	uint16 cursorPos = 0; -	//uint16 oldCursorPos = cursorPos; -	bool captureEvents = true; -	EventManager* eventMan = g_sci->getEventManager(); +	GfxFont *editorFont = _gfxCache->getFont(editor.fontId); +	height += _gfxText32->scaleUpHeight(editorFont->getHeight()) + 1; +	_gfxText32->setFont(editor.fontId); +	int16 emSize = _gfxText32->getCharWidth('M', true); +	width += editor.maxLength * emSize + 1; +	if (editor.borderColor != -1) { +		width += 4; +		height += 2; +	} -	while (captureEvents) { -		curEvent = g_sci->getEventManager()->getSciEvent(SCI_EVENT_KEYBOARD | SCI_EVENT_PEEK); +	Common::Rect editorPlaneRect(width, height); +	editorPlaneRect.translate(readSelectorValue(_segMan, controlObject, SELECTOR(x)), readSelectorValue(_segMan, controlObject, SELECTOR(y))); -		if (curEvent.type == SCI_EVENT_NONE) { -			eventMan->getSciEvent(SCI_EVENT_KEYBOARD);	// consume the event +	reg_t planeObj = readSelector(_segMan, controlObject, SELECTOR(plane)); +	Plane *sourcePlane = g_sci->_gfxFrameout->getVisiblePlanes().findByObject(planeObj); +	if (sourcePlane == nullptr) { +		error("Could not find plane %04x:%04x", PRINT_REG(planeObj)); +	} +	editorPlaneRect.translate(sourcePlane->_gameRect.left, sourcePlane->_gameRect.top); + +	editor.textRect = Common::Rect(2, titleHeight + 2, width - 1, height - 1); +	editor.width = width; + +	if (editor.bitmap.isNull()) { +		reg_t out; +		TextAlign alignment = (TextAlign)readSelectorValue(_segMan, controlObject, SELECTOR(mode)); + +		if (titleObject.isNull()) { +			bool dimmed = readSelectorValue(_segMan, controlObject, SELECTOR(dimmed)); +			editor.bitmap = _gfxText32->createFontBitmap(width, height, editor.textRect, editor.text, editor.foreColor, editor.backColor, editor.skipColor, editor.fontId, alignment, editor.borderColor, dimmed, true, &out);  		} else { -			textSize = text.size(); +			Common::String title = _segMan->getString(titleObject); +			int16 titleBackColor = readSelectorValue(_segMan, controlObject, SELECTOR(titleBack)); +			int16 titleForeColor = readSelectorValue(_segMan, controlObject, SELECTOR(titleFore)); +			editor.bitmap = _gfxText32->createTitledBitmap(width, height, editor.textRect, editor.text, editor.foreColor, editor.backColor, editor.skipColor, editor.fontId, alignment, editor.borderColor, title, titleForeColor, titleBackColor, titleFontId, true, &out); +		} +	} -			switch (curEvent.type) { -			case SCI_EVENT_MOUSE_PRESS: -				// TODO: Implement mouse support for cursor change +	drawCursor(editor); + +	Plane *plane = new Plane(editorPlaneRect, kPlanePicTransparent); +	plane->changePic(); +	g_sci->_gfxFrameout->addPlane(*plane); + +	CelInfo32 celInfo; +	celInfo.type = kCelTypeMem; +	celInfo.bitmap = editor.bitmap; + +	ScreenItem *screenItem = new ScreenItem(plane->_object, celInfo, Common::Point(), ScaleInfo()); +	plane->_screenItemList.add(screenItem); + +	// frameOut must be called after the screen item is +	// created, and before it is updated at the end of the +	// event loop, otherwise it has both created and updated +	// flags set which crashes the engine (it runs updates +	// before creations) +	g_sci->_gfxFrameout->frameOut(true); + +	EventManager *eventManager = g_sci->getEventManager(); +	bool clearTextOnInput = true; +	bool textChanged = false; +	for (;;) { +		// We peek here because the last event needs to be allowed to +		// dispatch a second time to the normal event handling system. +		// In the actual engine, the event is always consumed and then +		// the last event just gets posted back to the event manager for +		// reprocessing, but instead, we only remove the event from the +		// queue *after* we have determined it is not a defocusing event +		const SciEvent event = eventManager->getSciEvent(SCI_EVENT_ANY | SCI_EVENT_PEEK); + +		bool focused = true; +		// Original engine did not have a QUIT event but we have to handle it +		if (event.type == SCI_EVENT_QUIT) { +			return NULL_REG; +		} else if (event.type == SCI_EVENT_MOUSE_PRESS && !editorPlaneRect.contains(event.mousePosSci)) { +			focused = false; +		} else if (event.type == SCI_EVENT_KEYBOARD) { +			switch (event.character) { +			case SCI_KEY_ESC: +			case SCI_KEY_UP: +			case SCI_KEY_DOWN: +			case SCI_KEY_TAB: +			case SCI_KEY_SHIFT_TAB: +			case SCI_KEY_ENTER: +				focused = false;  				break; -			case SCI_EVENT_KEYBOARD: -				switch (curEvent.character) { -				case SCI_KEY_BACKSPACE: -					if (cursorPos > 0) { -						cursorPos--; text.deleteChar(cursorPos); -						textChanged = true; -					} -					eventMan->getSciEvent(SCI_EVENT_KEYBOARD);	// consume the event -					break; -				case SCI_KEY_DELETE: -					if (cursorPos < textSize) { -						text.deleteChar(cursorPos); -						textChanged = true; -					} -					eventMan->getSciEvent(SCI_EVENT_KEYBOARD);	// consume the event -					break; -				case SCI_KEY_HOME: // HOME -					cursorPos = 0; textChanged = true; -					eventMan->getSciEvent(SCI_EVENT_KEYBOARD);	// consume the event -					break; -				case SCI_KEY_END: // END -					cursorPos = textSize; textChanged = true; -					eventMan->getSciEvent(SCI_EVENT_KEYBOARD);	// consume the event -					break; -				case SCI_KEY_LEFT: // LEFT -					if (cursorPos > 0) { -						cursorPos--; textChanged = true; -					} -					eventMan->getSciEvent(SCI_EVENT_KEYBOARD);	// consume the event -					break; -				case SCI_KEY_RIGHT: // RIGHT -					if (cursorPos + 1 <= textSize) { -						cursorPos++; textChanged = true; -					} -					eventMan->getSciEvent(SCI_EVENT_KEYBOARD);	// consume the event -					break; -				case 3:	// returned in SCI1 late and newer when Control - C is pressed -					if (curEvent.modifiers & SCI_KEYMOD_CTRL) { -						// Control-C erases the whole line -						cursorPos = 0; text.clear(); -						textChanged = true; +			} +		} + +		if (!focused) { +			break; +		} + +		// Consume the event now that we know it is not one of the +		// defocusing events above +		eventManager->getSciEvent(SCI_EVENT_ANY); + +		// NOTE: In the original engine, the font and bitmap were +		// reset here on each iteration through the loop, but it +		// doesn't seem like this should be necessary since +		// control is not yielded back to the VM until input is +		// received, which means there is nothing that could modify +		// the GfxText32's state with a different font in the +		// meantime + +		bool shouldDeleteChar = false; +		bool shouldRedrawText = false; +		uint16 lastCursorPosition = editor.cursorCharPosition; + 		if (event.type == SCI_EVENT_KEYBOARD) { +			switch (event.character) { +			case SCI_KEY_LEFT: +				clearTextOnInput = false; +				if (editor.cursorCharPosition > 0) { +					--editor.cursorCharPosition; +				} +				break; + +			case SCI_KEY_RIGHT: +				clearTextOnInput = false; +				if (editor.cursorCharPosition < editor.text.size()) { +					++editor.cursorCharPosition; +				} +				break; + +			case SCI_KEY_HOME: +				clearTextOnInput = false; +				editor.cursorCharPosition = 0; +				break; + +			case SCI_KEY_END: +				clearTextOnInput = false; +				editor.cursorCharPosition = editor.text.size(); +				break; + +			case SCI_KEY_INSERT: +				clearTextOnInput = false; +				// Redrawing also changes the cursor rect to +				// reflect the new insertion mode +				shouldRedrawText = true; +				_overwriteMode = !_overwriteMode; +				break; + +			case SCI_KEY_DELETE: +				clearTextOnInput = false; +				if (editor.cursorCharPosition < editor.text.size()) { +					shouldDeleteChar = true; +				} +				break; + +			case SCI_KEY_BACKSPACE: +				clearTextOnInput = false; +				shouldDeleteChar = true; +				if (editor.cursorCharPosition > 0) { +					--editor.cursorCharPosition; +				} +				break; + +			case SCI_KEY_ETX: +				editor.text.clear(); +				editor.cursorCharPosition = 0; +				shouldRedrawText = true; +				break; + +			default: { +				if (event.character >= 20 && event.character < 257) { +					if (clearTextOnInput) { +						clearTextOnInput = false; +						editor.text.clear();  					} -					eventMan->getSciEvent(SCI_EVENT_KEYBOARD);	// consume the event -					break; -				case SCI_KEY_UP: -				case SCI_KEY_DOWN: -				case SCI_KEY_ENTER: -				case SCI_KEY_ESC: -				case SCI_KEY_TAB: -				case SCI_KEY_SHIFT_TAB: -					captureEvents = false; -					break; -				default: -					if ((curEvent.modifiers & SCI_KEYMOD_CTRL) && curEvent.character == 'c') { -						// Control-C in earlier SCI games (SCI0 - SCI1 middle) -						// Control-C erases the whole line -						cursorPos = 0; text.clear(); -						textChanged = true; -					} else if (curEvent.character > 31 && curEvent.character < 256 && textSize < maxChars) { -						// insert pressed character -						textAddChar = true; -						textChanged = true; + +					if ( +						(_overwriteMode && editor.cursorCharPosition < editor.maxLength) || +						(editor.text.size() < editor.maxLength && _gfxText32->getCharWidth(event.character, true) + _gfxText32->getStringWidth(editor.text) < editor.textRect.width()) +					) { +						if (_overwriteMode && editor.cursorCharPosition < editor.text.size()) { +							editor.text.setChar(event.character, editor.cursorCharPosition); +						} else { +							editor.text.insertChar(event.character, editor.cursorCharPosition); +						} + +						++editor.cursorCharPosition; +						shouldRedrawText = true;  					} -					eventMan->getSciEvent(SCI_EVENT_KEYBOARD);	// consume the event -					break;  				} -				break; +			}  			}  		} -		if (textChanged) { -			rect = g_sci->_gfxCompare->getNSRect(controlObject); +		if (shouldDeleteChar) { +			shouldRedrawText = true; +			if (editor.cursorCharPosition < editor.text.size()) { +				editor.text.deleteChar(editor.cursorCharPosition); +			} +		} -			if (textAddChar) { -				const char *textPtr = text.c_str(); +		if (shouldRedrawText) { +			eraseCursor(editor); +			_gfxText32->erase(editor.textRect, true); +			_gfxText32->drawTextBox(editor.text); +			drawCursor(editor); +			textChanged = true; +			screenItem->_updated = g_sci->_gfxFrameout->getScreenCount(); +		} else if (editor.cursorCharPosition != lastCursorPosition) { +			eraseCursor(editor); +			drawCursor(editor); +			screenItem->_updated = g_sci->_gfxFrameout->getScreenCount(); +		} else { +			flashCursor(editor); +			screenItem->_updated = g_sci->_gfxFrameout->getScreenCount(); +		} -				// We check if we are really able to add the new char -				uint16 textWidth = 0; -				while (*textPtr) -					textWidth += font->getCharWidth((byte)*textPtr++); -				textWidth += font->getCharWidth(curEvent.character); +		g_sci->_gfxFrameout->frameOut(true); +		g_sci->getSciDebugger()->onFrame(); +		g_sci->getEngineState()->speedThrottler(16); +		g_sci->getEngineState()->_throttleTrigger = true; +	} -				// Does it fit? -				if (textWidth >= rect.width()) { -					return; -				} +	g_sci->_gfxFrameout->deletePlane(*plane); +	if (readSelectorValue(segMan, controlObject, SELECTOR(frameOut))) { +		g_sci->_gfxFrameout->frameOut(true); +	} -				text.insertChar(curEvent.character, cursorPos++); +	_segMan->freeHunkEntry(editor.bitmap); -				// Note: the following checkAltInput call might make the text -				// too wide to fit, but SSCI fails to check that too. -			} +	if (textChanged) { +		editor.text.trim(); +		SciString *string = _segMan->lookupString(textObject); +		string->fromString(editor.text); +	} -			reg_t hunkId = readSelector(_segMan, controlObject, SELECTOR(bitmap)); -			Common::Rect nsRect = g_sci->_gfxCompare->getNSRect(controlObject); -			//texteditCursorErase();	// TODO: Cursor - -			// Write back string -			_segMan->strcpy(textReference, text.c_str()); -			// Modify the buffer and show it -			warning("kernelTexteditChange"); -#if 0 -			_text->createTextBitmap(controlObject, 0, 0, hunkId); - -			_text->drawTextBitmap(0, 0, nsRect, controlObject); -			//texteditCursorDraw(rect, text.c_str(), cursorPos);	// TODO: Cursor -			g_system->updateScreen(); -#endif +	return make_reg(0, textChanged); +} + +void GfxControls32::drawCursor(TextEditor &editor) { +	if (!editor.cursorIsDrawn) { +		editor.cursorRect.left = editor.textRect.left + _gfxText32->getTextWidth(editor.text, 0, editor.cursorCharPosition); + +		const int16 scaledFontHeight = _gfxText32->scaleUpHeight(_gfxText32->_font->getHeight()); + +		// NOTE: The original code branched on borderColor here but +		// the two branches appeared to be identical, differing only +		// because the compiler decided to be differently clever +		// when optimising multiplication in each branch +		if (_overwriteMode) { +			editor.cursorRect.top = editor.textRect.top; +			editor.cursorRect.setHeight(scaledFontHeight);  		} else { -			// TODO: Cursor -			/* -			if (g_system->getMillis() >= _texteditBlinkTime) { -				_paint16->invertRect(_texteditCursorRect); -				_paint16->bitsShow(_texteditCursorRect); -				_texteditCursorVisible = !_texteditCursorVisible; -				texteditSetBlinkTime(); -			} -			*/ +			editor.cursorRect.top = editor.textRect.top + scaledFontHeight - 1; +			editor.cursorRect.setHeight(1);  		} -		textAddChar = false; -		textChanged = false; -		g_sci->sleep(10); -	}	// while +		const char currentChar = editor.cursorCharPosition < editor.text.size() ? editor.text[editor.cursorCharPosition] : ' '; +		editor.cursorRect.setWidth(_gfxText32->getCharWidth(currentChar, true)); + +		_gfxText32->invertRect(editor.bitmap, editor.width, editor.cursorRect, editor.foreColor, editor.backColor, true); + +		editor.cursorIsDrawn = true; +	} + +	_nextCursorFlashTick = g_sci->getTickCount() + 30; +} + +void GfxControls32::eraseCursor(TextEditor &editor) { +	if (editor.cursorIsDrawn) { +		_gfxText32->invertRect(editor.bitmap, editor.width, editor.cursorRect, editor.foreColor, editor.backColor, true); +		editor.cursorIsDrawn = false; +	} + +	_nextCursorFlashTick = g_sci->getTickCount() + 30;  } +void GfxControls32::flashCursor(TextEditor &editor) { +	if (g_sci->getTickCount() > _nextCursorFlashTick) { +		_gfxText32->invertRect(editor.bitmap, editor.width, editor.cursorRect, editor.foreColor, editor.backColor, true); + +		editor.cursorIsDrawn = !editor.cursorIsDrawn; +		_nextCursorFlashTick = g_sci->getTickCount() + 30; +	} +}  } // End of namespace Sci diff --git a/engines/sci/graphics/controls32.h b/engines/sci/graphics/controls32.h index 5af7c20f16..0dc3b9ce6f 100644 --- a/engines/sci/graphics/controls32.h +++ b/engines/sci/graphics/controls32.h @@ -29,6 +29,76 @@ class GfxCache;  class GfxScreen;  class GfxText32; +struct TextEditor { +	/** +	 * The bitmap where the editor is rendered. +	 */ +	reg_t bitmap; + +	/** +	 * The width of the editor, in bitmap pixels. +	 */ +	int16 width; + +	/** +	 * The text in the editor. +	 */ +	Common::String text; + +	/** +	 * The rect where text should be drawn into the editor, +	 * in bitmap pixels. +	 */ +	Common::Rect textRect; + +	/** +	 * The color of the border. -1 indicates no border. +	 */ +	int16 borderColor; + +	/** +	 * The text color. +	 */ +	uint8 foreColor; + +	/** +	 * The background color. +	 */ +	uint8 backColor; + +	/** +	 * The transparent color. +	 */ +	uint8 skipColor; + +	/** +	 * The font used to render the text in the editor. +	 */ +	GuiResourceId fontId; + +	/** +	 * The current position of the cursor within the editor. +	 */ +	uint16 cursorCharPosition; + +	/** +	 * Whether or not the cursor is currently drawn to the +	 * screen. +	 */ +	bool cursorIsDrawn; + +	/** +	 * The rectangle for drawing the input cursor, in bitmap +	 * pixels. +	 */ +	Common::Rect cursorRect; + +	/** +	 * The maximum allowed text length, in characters. +	 */ +	uint16 maxLength; +}; +  /**   * Controls class, handles drawing of controls in SCI32 (SCI2, SCI2.1, SCI3) games   */ @@ -37,12 +107,18 @@ public:  	GfxControls32(SegManager *segMan, GfxCache *cache, GfxText32 *text);  	~GfxControls32(); -	void kernelTexteditChange(reg_t controlObject); +	reg_t kernelEditText(const reg_t controlObject);  private:  	SegManager *_segMan; -	GfxCache *_cache; -	GfxText32 *_text; +	GfxCache *_gfxCache; +	GfxText32 *_gfxText32; + +	bool _overwriteMode; +	uint32 _nextCursorFlashTick; +	void drawCursor(TextEditor &editor); +	void eraseCursor(TextEditor &editor); +	void flashCursor(TextEditor &editor);  };  } // End of namespace Sci diff --git a/engines/sci/graphics/frameout.cpp b/engines/sci/graphics/frameout.cpp index ab2ed7a4a5..55f5b36f56 100644 --- a/engines/sci/graphics/frameout.cpp +++ b/engines/sci/graphics/frameout.cpp @@ -365,6 +365,21 @@ void GfxFrameout::kernelDeletePlane(const reg_t object) {  	}  } +void GfxFrameout::deletePlane(Plane &planeToFind) { +	Plane *plane = _planes.findByObject(planeToFind._object); +	if (plane == nullptr) { +		error("Invalid plane passed to deletePlane"); +	} + +	if (plane->_created) { +		_planes.erase(plane); +	} else { +		plane->_created = 0; +		plane->_moved = 0; +		plane->_deleted = getScreenCount(); +	} +} +  int16 GfxFrameout::kernelGetHighPlanePri() {  	return _planes.getTopSciPlanePriority();  } @@ -765,7 +780,7 @@ void GfxFrameout::drawScreenItemList(const DrawList &screenItemList) {  		mergeToShowList(drawItem.rect, _showList, _overdrawThreshold);  		ScreenItem &screenItem = *drawItem.screenItem;  		// TODO: Remove -//		debug("Drawing item %04x:%04x to %d %d %d %d", PRINT_REG(screenItem._object), drawItem.rect.left, drawItem.rect.top, drawItem.rect.right, drawItem.rect.bottom); +//		debug("Drawing item %04x:%04x to %d %d %d %d", PRINT_REG(screenItem._object), PRINT_RECT(drawItem.rect));  		CelObj &celObj = *screenItem._celObj;  		celObj.draw(_currentBuffer, screenItem, drawItem.rect, screenItem._mirrorX ^ celObj._mirrorX);  	} @@ -1010,8 +1025,6 @@ void GfxFrameout::alterVmap(const Palette &palette1, const Palette &palette2, co  	// NOTE: This is currBuffer->ptr in SCI engine  	byte *pixels = (byte *)_currentBuffer.getPixels(); -	// TODO: Guessing that display width/height is the correct -	// equivalent to screen width/height in SCI engine  	for (int pixelIndex = 0, numPixels = _currentBuffer.screenWidth * _currentBuffer.screenHeight; pixelIndex < numPixels; ++pixelIndex) {  		byte currentValue = pixels[pixelIndex];  		int8 styleRangeValue = styleRanges[currentValue]; diff --git a/engines/sci/graphics/frameout.h b/engines/sci/graphics/frameout.h index f172997704..738011a84f 100644 --- a/engines/sci/graphics/frameout.h +++ b/engines/sci/graphics/frameout.h @@ -259,6 +259,13 @@ private:  	PlaneList _planes;  	/** +	 * Updates an existing plane with properties from the +	 * given VM object. +	 */ +	void updatePlane(Plane &plane); + +public: +	/**  	 * Creates and adds a new plane to the plane list, or  	 * cancels deletion and updates an already-existing  	 * plane if a plane matching the given plane VM object @@ -270,15 +277,19 @@ private:  	void addPlane(Plane &plane);  	/** -	 * Updates an existing plane with properties from the -	 * given VM object. +	 * Deletes a plane within the current plane list. +	 * +	 * @note This method is on Screen in SCI engine, but it +	 * is only ever called on `GraphicsMgr.screen`.  	 */ -	void updatePlane(Plane &plane); +	void deletePlane(Plane &plane); -public:  	const PlaneList &getPlanes() const {  		return _planes;  	} +	const PlaneList &getVisiblePlanes() const { +		return _visiblePlanes; +	}  	void kernelAddPlane(const reg_t object);  	void kernelUpdatePlane(const reg_t object);  	void kernelDeletePlane(const reg_t object); @@ -423,13 +434,6 @@ private:  	void drawScreenItemList(const DrawList &screenItemList);  	/** -	 * Updates the internal screen buffer for the next -	 * frame. If `shouldShowBits` is true, also sends the -	 * buffer to hardware. -	 */ -	void frameOut(const bool shouldShowBits, const Common::Rect &rect = Common::Rect()); - -	/**  	 * Adds a new rectangle to the list of regions to write  	 * out to the hardware. The provided rect may be merged  	 * into an existing rectangle to reduce the number of @@ -469,6 +473,13 @@ public:  	void kernelFrameOut(const bool showBits);  	/** +	 * Updates the internal screen buffer for the next +	 * frame. If `shouldShowBits` is true, also sends the +	 * buffer to hardware. +	 */ +	void frameOut(const bool shouldShowBits, const Common::Rect &rect = Common::Rect()); + +	/**  	 * Modifies the raw pixel data for the next frame with  	 * new palette indexes based on matched style ranges.  	 */ diff --git a/engines/sci/graphics/plane32.cpp b/engines/sci/graphics/plane32.cpp index e23017f21e..7d1487bd7c 100644 --- a/engines/sci/graphics/plane32.cpp +++ b/engines/sci/graphics/plane32.cpp @@ -43,10 +43,10 @@ void DrawList::add(ScreenItem *screenItem, const Common::Rect &rect) {  #pragma mark Plane  uint16 Plane::_nextObjectId = 20000; -Plane::Plane(const Common::Rect &gameRect) : +Plane::Plane(const Common::Rect &gameRect, PlanePictureCodes pictureId) :  _width(g_sci->_gfxFrameout->getCurrentBuffer().scriptWidth),  _height(g_sci->_gfxFrameout->getCurrentBuffer().scriptHeight), -_pictureId(kPlanePicColored), +_pictureId(pictureId),  _mirrored(false),  _back(0),  _priorityChanged(0), diff --git a/engines/sci/graphics/plane32.h b/engines/sci/graphics/plane32.h index be6f71464a..65df19d924 100644 --- a/engines/sci/graphics/plane32.h +++ b/engines/sci/graphics/plane32.h @@ -133,7 +133,7 @@ private:  	 * synchronised to another plane (which calls  	 * changePic).  	 */ -	bool _pictureChanged; // ? +	bool _pictureChanged;  	// TODO: Are these ever actually used?  	int _field_34, _field_38; // probably a point or ratio @@ -241,10 +241,18 @@ public:  	 */  	static void init(); -	Plane(const Common::Rect &gameRect); +	// NOTE: This constructor signature originally did not accept a +	// picture ID, but some calls to construct planes with this signature +	// immediately set the picture ID and then called setType again, so +	// it made more sense to just make the picture ID a parameter instead. +	Plane(const Common::Rect &gameRect, PlanePictureCodes pictureId = kPlanePicColored); +  	Plane(const reg_t object); +  	Plane(const Plane &other); +  	void operator=(const Plane &other); +  	inline bool operator<(const Plane &other) const {  		// TODO: In SCI engine, _object is actually a uint16 and can either  		// contain a MemID (a handle to MemoryMgr, similar to reg_t) or @@ -318,12 +326,6 @@ private:  	inline void addPicInternal(const GuiResourceId pictureId, const Common::Point *position, const bool mirrorX);  	/** -	 * If the plane is a picture plane, re-adds all cels -	 * from its picture resource to the plane. -	 */ -	void changePic(); - -	/**  	 * Marks all screen items to be deleted that are within  	 * this plane and match the given picture ID.  	 */ @@ -352,6 +354,13 @@ public:  	 */  	void addPic(const GuiResourceId pictureId, const Common::Point &position, const bool mirrorX); +	/** +	 * If the plane is a picture plane, re-adds all cels +	 * from its picture resource to the plane. Otherwise, +	 * just clears the _pictureChanged flag. +	 */ +	void changePic(); +  #pragma mark -  #pragma mark Plane - Rendering  private: diff --git a/engines/sci/graphics/screen_item32.cpp b/engines/sci/graphics/screen_item32.cpp index a07dacee83..c8c9cbea0f 100644 --- a/engines/sci/graphics/screen_item32.cpp +++ b/engines/sci/graphics/screen_item32.cpp @@ -83,7 +83,7 @@ _mirrorX(false) {  	}  } -ScreenItem::ScreenItem(const reg_t plane, const CelInfo32 &celInfo, const Common::Rect &rect, const ScaleInfo &scaleInfo) : +ScreenItem::ScreenItem(const reg_t plane, const CelInfo32 &celInfo, const Common::Point &position, const ScaleInfo &scaleInfo) :  _plane(plane),  _scale(scaleInfo),  _useInsetRect(false), @@ -91,7 +91,7 @@ _z(0),  _celInfo(celInfo),  _celObj(nullptr),  _fixPriority(false), -_position(rect.left, rect.top), +_position(position),  _object(make_reg(0, _nextObjectId++)),  _pictureId(-1),  _created(g_sci->_gfxFrameout->getScreenCount()), diff --git a/engines/sci/graphics/screen_item32.h b/engines/sci/graphics/screen_item32.h index 0ca840a13a..e054cf32f3 100644 --- a/engines/sci/graphics/screen_item32.h +++ b/engines/sci/graphics/screen_item32.h @@ -213,7 +213,7 @@ public:  	ScreenItem(const reg_t screenItem);  	ScreenItem(const reg_t plane, const CelInfo32 &celInfo);  	ScreenItem(const reg_t plane, const CelInfo32 &celInfo, const Common::Rect &rect); -	ScreenItem(const reg_t plane, const CelInfo32 &celInfo, const Common::Rect &rect, const ScaleInfo &scaleInfo); +	ScreenItem(const reg_t plane, const CelInfo32 &celInfo, const Common::Point &position, const ScaleInfo &scaleInfo);  	ScreenItem(const ScreenItem &other);  	void operator=(const ScreenItem &); diff --git a/engines/sci/graphics/text32.cpp b/engines/sci/graphics/text32.cpp index 8e3222f580..c1335b9b4d 100644 --- a/engines/sci/graphics/text32.cpp +++ b/engines/sci/graphics/text32.cpp @@ -40,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 @@ -179,6 +178,11 @@ reg_t GfxText32::createFontBitmap(const CelInfo32 &celInfo, const Common::Rect &  	return _bitmap;  } +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, reg_t *outBitmapObject) { +	warning("TODO: createTitledBitmap incomplete !"); +	return createFontBitmap(width, height, textRect, text, foreColor, backColor, skipColor, fontId, alignment, borderColor, false, doScaling, outBitmapObject); +} +  void GfxText32::setFont(const GuiResourceId fontId) {  	// NOTE: In SCI engine this calls FontMgr::BuildFontTable and then a font  	// table is built on the FontMgr directly; instead, because we already have @@ -202,7 +206,7 @@ void GfxText32::drawFrame(const Common::Rect &rect, const int16 size, const uint  	buffer.frameRect(targetRect, color);  } -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); @@ -210,7 +214,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); @@ -253,6 +257,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()); @@ -309,6 +318,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); @@ -543,7 +597,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); @@ -556,10 +610,7 @@ void GfxText32::erase(const Common::Rect &rect, const bool doScaling) {  }  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)); +	return getTextWidth(text, 0, 10000);  }  } // End of namespace Sci diff --git a/engines/sci/graphics/text32.h b/engines/sci/graphics/text32.h index 5de54d318f..9e268e3485 100644 --- a/engines/sci/graphics/text32.h +++ b/engines/sci/graphics/text32.h @@ -45,7 +45,6 @@ class GfxText32 {  private:  	SegManager *_segMan;  	GfxCache *_cache; -	GfxScreen *_screen;  	/**  	 * The resource ID of the default font used by the game. @@ -111,11 +110,6 @@ private:  	 */  	TextAlign _alignment; -	/** -	 * The memory handle of the currently active bitmap. -	 */ -	reg_t _bitmap; -  	int16 _field_20;  	/** @@ -133,18 +127,10 @@ private:  	Common::Point _drawPosition;  	void drawFrame(const Common::Rect &rect, const int16 size, const uint8 color, const bool doScaling); -	void drawTextBox(); -	void erase(const Common::Rect &rect, const bool doScaling); -	void drawChar(const uint8 charIndex); -	uint16 getCharWidth(const uint8 charIndex, const bool doScaling) const; +	void drawChar(const char charIndex);  	void drawText(const uint index, uint length); -	inline int scaleUpWidth(int value) const { -		const int scriptWidth = g_sci->_gfxFrameout->getCurrentBuffer().scriptWidth; -		return (value * scriptWidth + _scaledWidth - 1) / _scaledWidth; -	} -  	/**  	 * Gets the length of the longest run of text available  	 * within the currently loaded text, starting from the @@ -162,24 +148,23 @@ private:  	 */  	int16 getTextWidth(const uint index, uint length) const; -	/** -	 * Gets the pixel width of a substring of the currently -	 * loaded text, with scaling. -	 */ -	int16 getTextWidth(const Common::String &text, const uint index, const uint length); -  	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); +		mulinc(scaledRect, scaleX, scaleY);  		return scaledRect;  	}  public: -	GfxText32(SegManager *segMan, GfxCache *fonts, GfxScreen *screen); +	GfxText32(SegManager *segMan, GfxCache *fonts); + +	/** +	 * The memory handle of the currently active bitmap. +	 */ +	reg_t _bitmap;  	/**  	 * The size of the x-dimension of the coordinate system @@ -214,17 +199,68 @@ public:  	reg_t 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, reg_t *outBitmapObject);  	/** +	 * Creates a font bitmap with a title. +	 */ +	reg_t 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, reg_t *outBitmapObject); + +	inline int scaleUpWidth(int value) const { +		const int scriptWidth = g_sci->_gfxFrameout->getCurrentBuffer().scriptWidth; +		return (value * scriptWidth + _scaledWidth - 1) / _scaledWidth; +	} + +	inline int scaleUpHeight(int value) const { +		const int scriptHeight = g_sci->_gfxFrameout->getCurrentBuffer().scriptHeight; +		return (value * scriptHeight + _scaledHeight - 1) / _scaledHeight; +	} + +	/** +	 * Draws the text to the bitmap. +	 */ +	void drawTextBox(); + +	/** +	 * Draws the given text to the bitmap. +	 * +	 * @note The original engine holds a reference to a +	 * shared string which lets the text be updated from +	 * outside of the font manager. Instead, we give this +	 * extra signature to send the text to draw. +	 * +	 * TODO: Use shared string instead? +	 */ +	void drawTextBox(const Common::String &text); + +	/** +	 * Erases the given rect by filling with the background +	 * color. +	 */ +	void erase(const Common::Rect &rect, const bool doScaling); + +	void invertRect(const reg_t bitmap, const int16 bitmapStride, const Common::Rect &rect, const uint8 foreColor, const uint8 backColor, const bool doScaling); + +	/**  	 * Sets the font to be used for rendering and  	 * calculation of text dimensions.  	 */  	void setFont(const GuiResourceId fontId);  	/** +	 * Gets the width of a character. +	 */ +	uint16 getCharWidth(const char charIndex, const bool doScaling) const; + +	/**  	 * Retrieves the width and height of a block of text.  	 */  	Common::Rect getTextSize(const Common::String &text, const int16 maxWidth, bool doScaling);  	/** +	 * Gets the pixel width of a substring of the currently +	 * loaded text, with scaling. +	 */ +	int16 getTextWidth(const Common::String &text, const uint index, const uint length); + +	/**  	 * Retrieves the width of a line of text.  	 */  	int16 getStringWidth(const Common::String &text); diff --git a/engines/sci/sci.cpp b/engines/sci/sci.cpp index 52188db0fb..7c985dfab4 100644 --- a/engines/sci/sci.cpp +++ b/engines/sci/sci.cpp @@ -705,7 +705,7 @@ void SciEngine::initGraphics() {  		_gfxPaint = _gfxPaint32;  		_robotDecoder = new RobotDecoder(getPlatform() == Common::kPlatformMacintosh);  		_gfxFrameout = new GfxFrameout(_gamestate->_segMan, _resMan, _gfxCoordAdjuster, _gfxCache, _gfxScreen, _gfxPalette32, _gfxPaint32); -		_gfxText32 = new GfxText32(_gamestate->_segMan, _gfxCache, _gfxScreen); +		_gfxText32 = new GfxText32(_gamestate->_segMan, _gfxCache);  		_gfxControls32 = new GfxControls32(_gamestate->_segMan, _gfxCache, _gfxText32);  		_gfxFrameout->run();  	} else { | 
