コード例 #1
0
ファイル: text32.cpp プロジェクト: mauimauer/scummvm
void GfxText32::Width(const char *text, int16 from, int16 len, GuiResourceId fontId, int16 &textWidth, int16 &textHeight, bool restoreFont) {
	uint16 curChar;
	textWidth = 0; textHeight = 0;

	GfxFont *font = _cache->getFont(fontId);

	if (font) {
		text += from;
		while (len--) {
			curChar = (*(const byte *)text++);
			switch (curChar) {
			case 0x0A:
			case 0x0D:
			case 0x9781: // this one is used by SQ4/japanese as line break as well
				textHeight = MAX<int16> (textHeight, font->getHeight());
				break;
			case 0x7C:
				warning("Code processing isn't implemented in SCI32");
				break;
			default:
				textHeight = MAX<int16> (textHeight, font->getHeight());
				textWidth += font->getCharWidth(curChar);
				break;
			}
		}
	}
}
コード例 #2
0
ファイル: text32.cpp プロジェクト: 86400/scummvm
int16 GfxText32::getTextWidth(const uint index, uint length) const {
	int16 width = 0;

	const char *text = _text.c_str() + index;

	GfxFont *font = _font;

	char currentChar = *text++;
	while (length > 0 && currentChar != '\0') {
		// Control codes are in the format `|<code><value>|`
		if (currentChar == '|') {
			// NOTE: Original engine code changed the global state of the
			// FontMgr here upon encountering any color, alignment, or
			// font control code.
			// To avoid requiring all callers to manually restore these
			// values on every call, we ignore control codes other than
			// font change (since alignment and color do not change the
			// width of characters), and simply update the font pointer
			// on stack instead of the member property font.
			currentChar = *text++;
			--length;

			if (length > 0 && currentChar == 'f') {
				GuiResourceId fontId = 0;
				do {
					currentChar = *text++;
					--length;

					fontId = fontId * 10 + currentChar - '0';
				} while (length > 0 && *text >= '0' && *text <= '9');

				if (length > 0) {
					font = _cache->getFont(fontId);
				}
			}

			// Forward through any more unknown control character data
			while (length > 0 && *text != '|') {
				++text;
				--length;
			}
			if (length > 0) {
				++text;
				--length;
			}
		} else {
			width += font->getCharWidth((unsigned char)currentChar);
		}

		if (length > 0) {
			currentChar = *text++;
			--length;
		}
	}

	return width;
}
コード例 #3
0
ファイル: controls32.cpp プロジェクト: MisturDust319/scummvm
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;

	if (textReference.isNull())
		error("kEditControl called on object that doesn't have a text reference");
	text = _segMan->getString(textReference);

	// TODO: Finish this
	warning("kEditText ('%s')", text.c_str());
	return;

	uint16 cursorPos = 0;
	//uint16 oldCursorPos = cursorPos;
	bool captureEvents = true;
	EventManager* eventMan = g_sci->getEventManager();

	while (captureEvents) {
		curEvent = g_sci->getEventManager()->getSciEvent(SCI_EVENT_KEYBOARD | SCI_EVENT_PEEK);

		if (curEvent.type == SCI_EVENT_NONE) {
			eventMan->getSciEvent(SCI_EVENT_KEYBOARD);	// consume the event
		} else {
			textSize = text.size();

			switch (curEvent.type) {
			case SCI_EVENT_MOUSE_PRESS:
				// TODO: Implement mouse support for cursor change
				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;
					}
					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;
					}
					eventMan->getSciEvent(SCI_EVENT_KEYBOARD);	// consume the event
					break;
				}
				break;
			}
		}

		if (textChanged) {
			rect = g_sci->_gfxCompare->getNSRect(controlObject);

			if (textAddChar) {
				const char *textPtr = text.c_str();

				// 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);

				// Does it fit?
				if (textWidth >= rect.width()) {
					return;
				}

				text.insertChar(curEvent.character, cursorPos++);

				// Note: the following checkAltInput call might make the text
				// too wide to fit, but SSCI fails to check that too.
			}

			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
		} else {
			// TODO: Cursor
			/*
			if (g_system->getMillis() >= _texteditBlinkTime) {
				_paint16->invertRect(_texteditCursorRect);
				_paint16->bitsShow(_texteditCursorRect);
				_texteditCursorVisible = !_texteditCursorVisible;
				texteditSetBlinkTime();
			}
			*/
		}

		textAddChar = false;
		textChanged = false;
		g_sci->sleep(10);
	}	// while
}
コード例 #4
0
ファイル: text32.cpp プロジェクト: mauimauer/scummvm
reg_t GfxText32::createTextBitmap(reg_t textObject, uint16 maxWidth, uint16 maxHeight, reg_t prevHunk) {
	reg_t stringObject = readSelector(_segMan, textObject, SELECTOR(text));

	// 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));

	Common::String text = _segMan->getString(stringObject);
	// HACK: The character offsets of the up and down arrow buttons are off by one
	// in GK1, for some unknown reason. Fix them here.
	if (text.size() == 1 && (text[0] == 29 || text[0] == 30)) {
		text.setChar(text[0] + 1, 0);
	}
	GuiResourceId fontId = readSelectorValue(_segMan, textObject, SELECTOR(font));
	GfxFont *font = _cache->getFont(fontId);
	bool dimmed = readSelectorValue(_segMan, textObject, SELECTOR(dimmed));
	int16 alignment = readSelectorValue(_segMan, textObject, SELECTOR(mode));
	uint16 foreColor = readSelectorValue(_segMan, textObject, SELECTOR(fore));
	uint16 backColor = readSelectorValue(_segMan, textObject, SELECTOR(back));

	Common::Rect nsRect = g_sci->_gfxCompare->getNSRect(textObject);
	uint16 width = nsRect.width() + 1;
	uint16 height = nsRect.height() + 1;

	// Limit rectangle dimensions, if requested
	if (maxWidth > 0)
		width = maxWidth;
	if (maxHeight > 0)
		height = maxHeight;

	// Upscale the coordinates/width if the fonts are already upscaled
	if (_screen->fontIsUpscaled()) {
		width = width * _screen->getDisplayWidth() / _screen->getWidth();
		height = height * _screen->getDisplayHeight() / _screen->getHeight();
	}

	int entrySize = width * height + BITMAP_HEADER_SIZE;
	reg_t memoryId = NULL_REG;
	if (prevHunk.isNull()) {
		memoryId = _segMan->allocateHunkEntry("TextBitmap()", entrySize);
		writeSelector(_segMan, textObject, SELECTOR(bitmap), memoryId);
	} else {
		memoryId = prevHunk;
	}
	byte *memoryPtr = _segMan->getHunkPointer(memoryId);

	if (prevHunk.isNull())
		memset(memoryPtr, 0, BITMAP_HEADER_SIZE);

	byte *bitmap = memoryPtr + BITMAP_HEADER_SIZE;
	memset(bitmap, backColor, width * height);

	// Save totalWidth, totalHeight
	WRITE_LE_UINT16(memoryPtr, width);
	WRITE_LE_UINT16(memoryPtr + 2, height);

	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, 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();

	// Draw text in buffer
	while (*txt) {
		charCount = GetLongest(txt, width, font);
		if (charCount == 0)
			break;
		Width(txt, start, charCount, fontId, textWidth, textHeight, true);

		switch (alignment) {
		case SCI_TEXT32_ALIGNMENT_RIGHT:
			offsetX = width - textWidth;
			break;
		case SCI_TEXT32_ALIGNMENT_CENTER:
			// Center text both horizontally and vertically
			offsetX = (width - textWidth) / 2;
			offsetY = (height - totalHeight) / 2;
			break;
		case SCI_TEXT32_ALIGNMENT_LEFT:
			offsetX = 0;
			break;

		default:
			warning("Invalid alignment %d used in TextBox()", alignment);
		}

		for (int i = 0; i < charCount; i++) {
			unsigned char curChar = txt[i];
			font->drawToBuffer(curChar, curY + offsetY, curX + offsetX, foreColor, dimmed, bitmap, width, height);
			curX += font->getCharWidth(curChar);
		}

		curX = 0;
		curY += font->getHeight();
		txt += charCount;
		while (*txt == ' ')
			txt++; // skip over breaking spaces
	}

	return memoryId;
}
コード例 #5
0
ファイル: controls32.cpp プロジェクト: dividedmind/scummvm
void GfxControls32::kernelTexteditChange(reg_t controlObject) {
	SciEvent curEvent;
	uint16 maxChars = readSelectorValue(_segMan, controlObject, SELECTOR(max));
	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;

	if (textReference.isNull())
		error("kEditControl called on object that doesnt have a text reference");
	text = _segMan->getString(textReference);

	// TODO: Finish this, add a loop etc
	warning("kEditText ('%s')", text.c_str());
	return;

	uint16 cursorPos = 0;
	//uint16 oldCursorPos = cursorPos;

	curEvent = g_sci->getEventManager()->getSciEvent(SCI_EVENT_KEYBOARD);
	if (curEvent.type != SCI_EVENT_NONE) {
		textSize = text.size();

		switch (curEvent.type) {
		case SCI_EVENT_MOUSE_PRESS:
			// TODO: Implement mouse support for cursor change
			break;
		case SCI_EVENT_KEYBOARD:
			switch (curEvent.data) {
			case SCI_KEY_BACKSPACE:
				if (cursorPos > 0) {
					cursorPos--; text.deleteChar(cursorPos);
					textChanged = true;
				}
				break;
			case SCI_KEY_DELETE:
				if (cursorPos < textSize) {
					text.deleteChar(cursorPos);
					textChanged = true;
				}
				break;
			case SCI_KEY_HOME: // HOME
				cursorPos = 0; textChanged = true;
				break;
			case SCI_KEY_END: // END
				cursorPos = textSize; textChanged = true;
				break;
			case SCI_KEY_LEFT: // LEFT
				if (cursorPos > 0) {
					cursorPos--; textChanged = true;
				}
				break;
			case SCI_KEY_RIGHT: // RIGHT
				if (cursorPos + 1 <= textSize) {
					cursorPos++; textChanged = true;
				}
				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;
				}
				break;
			default:
				if ((curEvent.modifiers & SCI_KEYMOD_CTRL) && curEvent.data == 99) {
					// Control-C in earlier SCI games (SCI0 - SCI1 middle)
					// Control-C erases the whole line
					cursorPos = 0; text.clear();
					textChanged = true;
				} else if (curEvent.data > 31 && curEvent.data < 256 && textSize < maxChars) {
					// insert pressed character
					textAddChar = true;
					textChanged = true;
				}
				break;
			}
			break;
		}
	}

	if (textChanged) {
		rect = g_sci->_gfxCompare->getNSRect(controlObject);

		if (textAddChar) {
			const char *textPtr = text.c_str();

			// 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.data);

			// Does it fit?
			if (textWidth >= rect.width()) {
				return;
			}

			text.insertChar(curEvent.data, cursorPos++);

			// Note: the following checkAltInput call might make the text
			// too wide to fit, but SSCI fails to check that too.
		}
		// TODO: Cursor
		/*
		texteditCursorErase();
		_paint16->eraseRect(rect);
		_text16->Box(text.c_str(), false, rect, SCI_TEXT16_ALIGNMENT_LEFT, -1);
		_paint16->bitsShow(rect);
		texteditCursorDraw(rect, text.c_str(), cursorPos);
		*/
		// Write back string
		_segMan->strcpy(textReference, text.c_str());
	} else {
		// TODO: Cursor
		/*
		if (g_system->getMillis() >= _texteditBlinkTime) {
			_paint16->invertRect(_texteditCursorRect);
			_paint16->bitsShow(_texteditCursorRect);
			_texteditCursorVisible = !_texteditCursorVisible;
			texteditSetBlinkTime();
		}
		*/
	}
}
コード例 #6
0
ファイル: frameout.cpp プロジェクト: shailendji/nefertiti
void GfxFrameout::kernelFrameout() {
	if (g_sci->_robotDecoder->isVideoLoaded()) {
		bool skipVideo = false;
		RobotDecoder *videoDecoder = g_sci->_robotDecoder;
		uint16 x = videoDecoder->getPos().x;
		uint16 y = videoDecoder->getPos().y;

		if (videoDecoder->hasDirtyPalette())
			videoDecoder->setSystemPalette();

		while (!g_engine->shouldQuit() && !videoDecoder->endOfVideo() && !skipVideo) {
			if (videoDecoder->needsUpdate()) {
				const Graphics::Surface *frame = videoDecoder->decodeNextFrame();
				if (frame) {
					g_system->copyRectToScreen((byte *)frame->pixels, frame->pitch, x, y, frame->w, frame->h);

					if (videoDecoder->hasDirtyPalette())
						videoDecoder->setSystemPalette();

					g_system->updateScreen();
				}
			}

			Common::Event event;
			while (g_system->getEventManager()->pollEvent(event)) {
				if ((event.type == Common::EVENT_KEYDOWN && event.kbd.keycode == Common::KEYCODE_ESCAPE) || event.type == Common::EVENT_LBUTTONUP)
					skipVideo = true;
			}

			g_system->delayMillis(10);
		}
		return;
	}

	_palette->palVaryUpdate();

	for (PlaneList::iterator it = _planes.begin(); it != _planes.end(); it++) {
		reg_t planeObject = it->object;
		uint16 planeLastPriority = it->lastPriority;

		// Update priority here, sq6 sets it w/o UpdatePlane
		uint16 planePriority = it->priority = readSelectorValue(_segMan, planeObject, SELECTOR(priority));

		it->lastPriority = planePriority;
		if (planePriority == 0xffff) { // Plane currently not meant to be shown
			// If plane was shown before, delete plane rect
			if (planePriority != planeLastPriority)
				_paint32->fillRect(it->planeRect, 0);
			continue;
		}

		if (it->planeBack)
			_paint32->fillRect(it->planeRect, it->planeBack);

		GuiResourceId planeMainPictureId = it->pictureId;

		_coordAdjuster->pictureSetDisplayArea(it->planeRect);
		_palette->drewPicture(planeMainPictureId);

		FrameoutList itemList;

		// Copy screen items of the current frame to the list of items to be drawn
		for (FrameoutList::iterator listIterator = _screenItems.begin(); listIterator != _screenItems.end(); listIterator++) {
			reg_t itemPlane = readSelector(_segMan, (*listIterator)->object, SELECTOR(plane));
			if (planeObject == itemPlane) {
				kernelUpdateScreenItem((*listIterator)->object);	// TODO: Why is this necessary?
				itemList.push_back(*listIterator);
			}
		}

		for (PlanePictureList::iterator pictureIt = _planePictures.begin(); pictureIt != _planePictures.end(); pictureIt++) {
			if (pictureIt->object == planeObject) {
				GfxPicture *planePicture = pictureIt->picture;
				// Allocate memory for picture cels
				pictureIt->pictureCels = new FrameoutEntry[planePicture->getSci32celCount()];

				// Add following cels to the itemlist
				FrameoutEntry *picEntry = pictureIt->pictureCels;
				int planePictureCels = planePicture->getSci32celCount();
				for (int pictureCelNr = 0; pictureCelNr < planePictureCels; pictureCelNr++) {
					picEntry->celNo = pictureCelNr;
					picEntry->object = NULL_REG;
					picEntry->picture = planePicture;
					picEntry->y = planePicture->getSci32celY(pictureCelNr);
					picEntry->x = planePicture->getSci32celX(pictureCelNr);
					picEntry->picStartX = pictureIt->startX;

					picEntry->priority = planePicture->getSci32celPriority(pictureCelNr);

					itemList.push_back(picEntry);
					picEntry++;
				}
			}
		}

		// Now sort our itemlist
		Common::sort(itemList.begin(), itemList.end(), sortHelper);

//		warning("Plane %s", _segMan->getObjectName(planeObject));

		for (FrameoutList::iterator listIterator = itemList.begin(); listIterator != itemList.end(); listIterator++) {
			FrameoutEntry *itemEntry = *listIterator;

			if (itemEntry->object.isNull()) {
				// Picture cel data
				itemEntry->y = ((itemEntry->y * _screen->getHeight()) / scriptsRunningHeight);
				itemEntry->x = ((itemEntry->x * _screen->getWidth()) / scriptsRunningWidth);
				itemEntry->picStartX = ((itemEntry->picStartX * _screen->getWidth()) / scriptsRunningWidth);

				// Out of view
				int16 pictureCelStartX = itemEntry->picStartX + itemEntry->x;
				int16 pictureCelEndX = pictureCelStartX + itemEntry->picture->getSci32celWidth(itemEntry->celNo);
				int16 planeStartX = it->planeOffsetX;
				int16 planeEndX = planeStartX + it->planeRect.width();
				if (pictureCelEndX < planeStartX)
					continue;
				if (pictureCelStartX > planeEndX)
					continue;

				int16 pictureOffsetX = it->planeOffsetX;
				int16 pictureX = itemEntry->x;
				if ((it->planeOffsetX) || (itemEntry->picStartX)) {
					if (it->planeOffsetX <= itemEntry->picStartX) {
						pictureX += itemEntry->picStartX - it->planeOffsetX;
						pictureOffsetX = 0;
					} else {
						pictureOffsetX = it->planeOffsetX - itemEntry->picStartX;
					}
				}

				itemEntry->picture->drawSci32Vga(itemEntry->celNo, pictureX, itemEntry->y, pictureOffsetX, it->planePictureMirrored);
//				warning("picture cel %d %d", itemEntry->celNo, itemEntry->priority);

			} else if (itemEntry->viewId != 0xFFFF) {
				GfxView *view = _cache->getView(itemEntry->viewId);

//				warning("view %s %04x:%04x", _segMan->getObjectName(itemEntry->object), PRINT_REG(itemEntry->object));


				if (view->isSci2Hires()) {
					int16 dummyX = 0;
					_screen->adjustToUpscaledCoordinates(itemEntry->y, itemEntry->x);
					_screen->adjustToUpscaledCoordinates(itemEntry->z, dummyX);
				} else if (getSciVersion() == SCI_VERSION_2_1) {
					itemEntry->y = (itemEntry->y * _screen->getHeight()) / scriptsRunningHeight;
					itemEntry->x = (itemEntry->x * _screen->getWidth()) / scriptsRunningWidth;
					itemEntry->z = (itemEntry->z * _screen->getHeight()) / scriptsRunningHeight;
				}

				// Adjust according to current scroll position
				itemEntry->x -= it->planeOffsetX;

				uint16 useInsetRect = readSelectorValue(_segMan, itemEntry->object, SELECTOR(useInsetRect));
				if (useInsetRect) {
					itemEntry->celRect.top = readSelectorValue(_segMan, itemEntry->object, SELECTOR(inTop));
					itemEntry->celRect.left = readSelectorValue(_segMan, itemEntry->object, SELECTOR(inLeft));
					itemEntry->celRect.bottom = readSelectorValue(_segMan, itemEntry->object, SELECTOR(inBottom)) + 1;
					itemEntry->celRect.right = readSelectorValue(_segMan, itemEntry->object, SELECTOR(inRight)) + 1;
					if (view->isSci2Hires()) {
						_screen->adjustToUpscaledCoordinates(itemEntry->celRect.top, itemEntry->celRect.left);
						_screen->adjustToUpscaledCoordinates(itemEntry->celRect.bottom, itemEntry->celRect.right);
					}
					itemEntry->celRect.translate(itemEntry->x, itemEntry->y);
					// TODO: maybe we should clip the cels rect with this, i'm not sure
					//  the only currently known usage is game menu of gk1
				} else {
					if ((itemEntry->scaleX == 128) && (itemEntry->scaleY == 128))
						view->getCelRect(itemEntry->loopNo, itemEntry->celNo, itemEntry->x, itemEntry->y, itemEntry->z, itemEntry->celRect);
					else
						view->getCelScaledRect(itemEntry->loopNo, itemEntry->celNo, itemEntry->x, itemEntry->y, itemEntry->z, itemEntry->scaleX, itemEntry->scaleY, itemEntry->celRect);

					Common::Rect nsRect = itemEntry->celRect;
					// Translate back to actual coordinate within scrollable plane
					nsRect.translate(it->planeOffsetX, 0);

					if (view->isSci2Hires()) {
						_screen->adjustBackUpscaledCoordinates(nsRect.top, nsRect.left);
						_screen->adjustBackUpscaledCoordinates(nsRect.bottom, nsRect.right);
					} else if (getSciVersion() == SCI_VERSION_2_1) {
						nsRect.top = (nsRect.top * scriptsRunningHeight) / _screen->getHeight();
						nsRect.left = (nsRect.left * scriptsRunningWidth) / _screen->getWidth();
						nsRect.bottom = (nsRect.bottom * scriptsRunningHeight) / _screen->getHeight();
						nsRect.right = (nsRect.right * scriptsRunningWidth) / _screen->getWidth();
					}

					writeSelectorValue(_segMan, itemEntry->object, SELECTOR(nsLeft), nsRect.left);
					writeSelectorValue(_segMan, itemEntry->object, SELECTOR(nsTop), nsRect.top);
					writeSelectorValue(_segMan, itemEntry->object, SELECTOR(nsRight), nsRect.right);
					writeSelectorValue(_segMan, itemEntry->object, SELECTOR(nsBottom), nsRect.bottom);
				}

				int16 screenHeight = _screen->getHeight();
				int16 screenWidth = _screen->getWidth();
				if (view->isSci2Hires()) {
					screenHeight = _screen->getDisplayHeight();
					screenWidth = _screen->getDisplayWidth();
				}

				if (itemEntry->celRect.bottom < 0 || itemEntry->celRect.top >= screenHeight)
					continue;

				if (itemEntry->celRect.right < 0 || itemEntry->celRect.left >= screenWidth)
					continue;

				Common::Rect clipRect, translatedClipRect;
				clipRect = itemEntry->celRect;
				if (view->isSci2Hires()) {
					clipRect.clip(it->upscaledPlaneClipRect);
					translatedClipRect = clipRect;
					translatedClipRect.translate(it->upscaledPlaneRect.left, it->upscaledPlaneRect.top);
				} else {
					clipRect.clip(it->planeClipRect);
					translatedClipRect = clipRect;
					translatedClipRect.translate(it->planeRect.left, it->planeRect.top);
				}

				if (!clipRect.isEmpty()) {
					if ((itemEntry->scaleX == 128) && (itemEntry->scaleY == 128))
						view->draw(itemEntry->celRect, clipRect, translatedClipRect, itemEntry->loopNo, itemEntry->celNo, 255, 0, view->isSci2Hires());
					else
						view->drawScaled(itemEntry->celRect, clipRect, translatedClipRect, itemEntry->loopNo, itemEntry->celNo, 255, itemEntry->scaleX, itemEntry->scaleY);
				}
			} else {
				// Most likely a text entry
				// 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)
				if (lookupSelector(_segMan, itemEntry->object, SELECTOR(text), NULL, NULL) == kSelectorVariable) {
					reg_t stringObject = readSelector(_segMan, itemEntry->object, SELECTOR(text));

					// 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));

					Common::String text = _segMan->getString(stringObject);
					GfxFont *font = _cache->getFont(readSelectorValue(_segMan, itemEntry->object, SELECTOR(font)));
					bool dimmed = readSelectorValue(_segMan, itemEntry->object, SELECTOR(dimmed));
					uint16 foreColor = readSelectorValue(_segMan, itemEntry->object, SELECTOR(fore));

					itemEntry->y = ((itemEntry->y * _screen->getHeight()) / scriptsRunningHeight);
					itemEntry->x = ((itemEntry->x * _screen->getWidth()) / scriptsRunningWidth);

					uint16 startX = itemEntry->x + it->planeRect.left;
					uint16 curY = itemEntry->y + it->planeRect.top;
					const char *txt = text.c_str();
					// HACK. The plane sometimes doesn't contain the correct width. This
					// hack breaks the dialog options when speaking with Grace, but it's
					// the best we got up to now. This happens because of the unimplemented
					// kTextWidth function in SCI32.
					// TODO: Remove this once kTextWidth has been implemented.
					uint16 w = it->planeRect.width() >= 20 ? it->planeRect.width() : _screen->getWidth() - 10;
					int16 charCount;

					// Upscale the coordinates/width if the fonts are already upscaled
					if (_screen->fontIsUpscaled()) {
						startX = startX * _screen->getDisplayWidth() / _screen->getWidth();
						curY = curY * _screen->getDisplayHeight() / _screen->getHeight();
						w  = w * _screen->getDisplayWidth() / _screen->getWidth();
					}

					while (*txt) {
						charCount = GetLongest(txt, w, font);
						if (charCount == 0)
							break;

						uint16 curX = startX;

						for (int i = 0; i < charCount; i++) {
							unsigned char curChar = txt[i];
							font->draw(curChar, curY, curX, foreColor, dimmed);
							curX += font->getCharWidth(curChar);
						}

						curY += font->getHeight();
						txt += charCount;
						while (*txt == ' ')
							txt++; // skip over breaking spaces
					}

				}
			}
		}

		for (PlanePictureList::iterator pictureIt = _planePictures.begin(); pictureIt != _planePictures.end(); pictureIt++) {
			if (pictureIt->object == planeObject) {
				delete[] pictureIt->pictureCels;
				pictureIt->pictureCels = 0;
			}
		}
	}

	_screen->copyToScreen();

	g_sci->getEngineState()->_throttleTrigger = true;
}