[Scummvm-cvs-logs] SF.net SVN: scummvm:[54079] scummvm/trunk

athrxx at users.sourceforge.net athrxx at users.sourceforge.net
Fri Nov 5 01:36:24 CET 2010


Revision: 54079
          http://scummvm.svn.sourceforge.net/scummvm/?rev=54079&view=rev
Author:   athrxx
Date:     2010-11-05 00:36:23 +0000 (Fri, 05 Nov 2010)

Log Message:
-----------
SCUMM/FM-TOWNS JAPANESE: fix out of bounds text drawing

(could cause invalid memory access in MI1)

Modified Paths:
--------------
    scummvm/trunk/engines/scumm/charset.cpp
    scummvm/trunk/engines/scumm/charset.h
    scummvm/trunk/engines/scumm/gfx.cpp
    scummvm/trunk/graphics/sjis.cpp
    scummvm/trunk/graphics/sjis.h

Modified: scummvm/trunk/engines/scumm/charset.cpp
===================================================================
--- scummvm/trunk/engines/scumm/charset.cpp	2010-11-05 00:10:26 UTC (rev 54078)
+++ scummvm/trunk/engines/scumm/charset.cpp	2010-11-05 00:36:23 UTC (rev 54079)
@@ -773,13 +773,13 @@
 		if (charPtr)
 			drawBits1(*vs, dst, charPtr, drawTop, origWidth, origHeight, vs->bytesPerPixel);
 		else if (_vm->_cjkFont)
-			_vm->_cjkFont->drawChar(dst, chr, vs->pitch, vs->bytesPerPixel, _color, _shadowColor);
+			_vm->_cjkFont->drawChar(vs, chr, _left, drawTop, _color, _shadowColor);
 	} else {
 		dst = (byte *)_vm->_textSurface.getBasePtr(_left * _vm->_textSurfaceMultiplier, _top * _vm->_textSurfaceMultiplier);
 		if (charPtr)
 			drawBits1(_vm->_textSurface, dst, charPtr, drawTop, origWidth, origHeight, _vm->_textSurface.bytesPerPixel, (_vm->_textSurfaceMultiplier == 2 && !is2byte));
 		else if (_vm->_cjkFont)
-			_vm->_cjkFont->drawChar(dst, chr, _vm->_textSurface.pitch, vs->bytesPerPixel, _color, _shadowColor);
+			_vm->_cjkFont->drawChar(_vm->_textSurface, chr, _left * _vm->_textSurfaceMultiplier, _top * _vm->_textSurfaceMultiplier, _color, _shadowColor);
 		if (is2byte)
 			origWidth /= _vm->_textSurfaceMultiplier;
 	}
@@ -799,17 +799,14 @@
 		_str.bottom = _top + height / _vm->_textSurfaceMultiplier;
 }
 
-void CharsetRendererV3::drawChar(int chr, const Graphics::Surface &s, int x, int y) {
+void CharsetRendererV3::drawChar(int chr, Graphics::Surface &s, int x, int y) {
 	const byte *charPtr;
 	byte *dst;
 	int width, height;
 	int is2byte = (chr >= 0x80 && _vm->_useCJKMode) ? 1 : 0;
 	if (is2byte) {
 		if (_vm->_game.platform == Common::kPlatformFMTowns) {
-			width = _vm->_cjkFont->getCharWidth(chr);
-			height = _vm->_cjkFont->getFontHeight();
-			dst = (byte *)s.pixels + y * s.pitch + x;
-			_vm->_cjkFont->drawChar(dst, chr, s.pitch, s.bytesPerPixel, _color, _shadowColor);
+			_vm->_cjkFont->drawChar(s, chr, x * _vm->_textSurfaceMultiplier, y * _vm->_textSurfaceMultiplier, _color, _shadowColor);
 			return;
 		} else {
 			charPtr = _vm->get2byteCharPtr(chr);
@@ -1079,9 +1076,9 @@
 			drawTop = _top - _vm->_screenTop;
 		}
 
-		if (!charPtr && _vm->_cjkFont)
-			_vm->_cjkFont->drawChar(dstPtr, _vm->_cjkChar, dstSurface.pitch, dstSurface.bytesPerPixel, _vm->_townsCharsetColorMap[1], _shadowColor);
-		else if (is2byte) {
+		if (!charPtr && _vm->_cjkFont) {
+			_vm->_cjkFont->drawChar(dstSurface, _vm->_cjkChar, _left * _vm->_textSurfaceMultiplier, (_top - _vm->_screenTop) * _vm->_textSurfaceMultiplier, _vm->_townsCharsetColorMap[1], _shadowColor);
+		} else if (is2byte) {
 			drawBits1(dstSurface, dstPtr, charPtr, drawTop, origWidth, origHeight, dstSurface.bytesPerPixel);
 		} else {
 			drawBitsN(dstSurface, dstPtr, charPtr, *_fontPtr, drawTop, origWidth, origHeight, _vm->_textSurfaceMultiplier == 2);
@@ -1124,7 +1121,7 @@
 	}
 }
 
-void CharsetRendererClassic::drawChar(int chr, const Graphics::Surface &s, int x, int y) {
+void CharsetRendererClassic::drawChar(int chr, Graphics::Surface &s, int x, int y) {
 	const byte *charPtr;
 	byte *dst;
 	int width, height;
@@ -1133,10 +1130,7 @@
 	if (is2byte) {
 		enableShadow(true);
 		if (_vm->_game.platform == Common::kPlatformFMTowns) {
-			width = _vm->_cjkFont->getCharWidth(chr);
-			height = _vm->_cjkFont->getFontHeight();
-			dst = (byte *)s.pixels + y * s.pitch + x;
-			_vm->_cjkFont->drawChar(dst, chr, s.pitch, s.bytesPerPixel, _color, _shadowColor);
+			_vm->_cjkFont->drawChar(s, chr, x * _vm->_textSurfaceMultiplier, y * _vm->_textSurfaceMultiplier, _color, _shadowColor);
 			return;
 		} else {
 			charPtr = _vm->get2byteCharPtr(chr);
@@ -1525,7 +1519,7 @@
 		_str.bottom = _top + height;
 }
 
-void CharsetRendererNES::drawChar(int chr, const Graphics::Surface &s, int x, int y) {
+void CharsetRendererNES::drawChar(int chr, Graphics::Surface &s, int x, int y) {
 	byte *charPtr, *dst;
 	int width, height;
 

Modified: scummvm/trunk/engines/scumm/charset.h
===================================================================
--- scummvm/trunk/engines/scumm/charset.h	2010-11-05 00:10:26 UTC (rev 54078)
+++ scummvm/trunk/engines/scumm/charset.h	2010-11-05 00:36:23 UTC (rev 54079)
@@ -75,7 +75,7 @@
 	virtual ~CharsetRenderer();
 
 	virtual void printChar(int chr, bool ignoreCharsetMask) = 0;
-	virtual void drawChar(int chr, const Graphics::Surface &s, int x, int y) {}
+	virtual void drawChar(int chr, Graphics::Surface &s, int x, int y) {}
 
 	int getStringWidth(int a, const byte *str);
 	void addLinebreaks(int a, byte *str, int pos, int maxwidth);
@@ -134,7 +134,7 @@
 	CharsetRendererClassic(ScummEngine *vm) : CharsetRendererCommon(vm) {}
 
 	void printChar(int chr, bool ignoreCharsetMask);
-	void drawChar(int chr, const Graphics::Surface &s, int x, int y);
+	void drawChar(int chr, Graphics::Surface &s, int x, int y);
 
 	int getCharWidth(uint16 chr);
 
@@ -155,7 +155,7 @@
 
 	void setCurID(int32 id) {}
 	void printChar(int chr, bool ignoreCharsetMask);
-	void drawChar(int chr, const Graphics::Surface &s, int x, int y);
+	void drawChar(int chr, Graphics::Surface &s, int x, int y);
 
 	int getFontHeight() { return 8; }
 	int getCharWidth(uint16 chr) { return 8; }
@@ -169,7 +169,7 @@
 	CharsetRendererV3(ScummEngine *vm) : CharsetRendererCommon(vm) {}
 
 	void printChar(int chr, bool ignoreCharsetMask);
-	void drawChar(int chr, const Graphics::Surface &s, int x, int y);
+	void drawChar(int chr, Graphics::Surface &s, int x, int y);
 	void setCurID(int32 id);
 	void setColor(byte color);
 	int getCharWidth(uint16 chr);

Modified: scummvm/trunk/engines/scumm/gfx.cpp
===================================================================
--- scummvm/trunk/engines/scumm/gfx.cpp	2010-11-05 00:10:26 UTC (rev 54078)
+++ scummvm/trunk/engines/scumm/gfx.cpp	2010-11-05 00:36:23 UTC (rev 54079)
@@ -1025,7 +1025,7 @@
 
 #ifndef DISABLE_TOWNS_DUAL_LAYER_MODE
 	if (_game.platform == Common::kPlatformFMTowns && _game.id == GID_MONKEY && vs->number == kVerbVirtScreen && rect.bottom <= 154)
-		rect.right = 320;
+		rect.right = 319;
 #endif
 
 	markRectAsDirty(vs->number, rect, USAGE_BIT_RESTORED);

Modified: scummvm/trunk/graphics/sjis.cpp
===================================================================
--- scummvm/trunk/graphics/sjis.cpp	2010-11-05 00:10:26 UTC (rev 54078)
+++ scummvm/trunk/graphics/sjis.cpp	2010-11-05 00:36:23 UTC (rev 54079)
@@ -138,9 +138,12 @@
 }
 #endif
 
-void FontSJISBase::drawChar(void *dst, uint16 ch, int pitch, int bpp, uint32 c1, uint32 c2) const {
+void FontSJISBase::drawChar(void *dst, uint16 ch, int pitch, int bpp, uint32 c1, uint32 c2, int maxW, int maxH) const {
 	const uint8 *glyphSource = 0;
 	int width = 0, height = 0;
+	int outlineExtraWidth = 2, outlineExtraHeight = 2;
+	int outlineXOffset = 0, outlineYOffset = 0;
+
 	if (is8x16(ch)) {
 		glyphSource = getCharData8x16(ch);
 		width = 8;
@@ -151,6 +154,21 @@
 		height = 16;
 	}
 
+	if (maxW != -1 && maxW < width) {
+		width = maxW;
+		outlineExtraWidth = 0;
+		outlineXOffset = 1;
+	}
+	
+	if (maxH != -1 && maxH < height) {
+		height = maxH;
+		outlineExtraHeight = 0;
+		outlineYOffset = 1;
+	}
+
+	if (width <= 0 || height <= 0)
+		return;
+
 	if (!glyphSource) {
 		warning("FontSJISBase::drawChar: Font does not offer data for %02X %02X", ch & 0xFF, ch >> 8);
 		return;
@@ -169,15 +187,15 @@
 
 	if (bpp == 1) {
 		if (_drawMode == kOutlineMode) {
-			blitCharacter<uint8>(outline, width + 2, height + 2, (uint8 *)dst, pitch, c2);
-			blitCharacter<uint8>(glyphSource, width, height, (uint8 *)dst + pitch + 1, pitch, c1);
+			blitCharacter<uint8>(outline, width + outlineExtraWidth, height + outlineExtraHeight, (uint8 *)dst, pitch, c2);
+			blitCharacter<uint8>(glyphSource, width - outlineXOffset, height - outlineYOffset, (uint8 *)dst + pitch + 1, pitch, c1);
 		} else {
 			blitCharacter<uint8>(glyphSource, width, height, (uint8 *)dst, pitch, c1, c2);
 		}
 	} else if (bpp == 2) {
 		if (_drawMode == kOutlineMode) {
-			blitCharacter<uint16>(outline, width + 2, height + 2, (uint8 *)dst, pitch, c2);
-			blitCharacter<uint16>(glyphSource, width, height, (uint8 *)dst + pitch + 2, pitch, c1);
+			blitCharacter<uint16>(outline, width + outlineExtraWidth, height + outlineExtraHeight, (uint8 *)dst, pitch, c2);
+			blitCharacter<uint16>(glyphSource, width - outlineXOffset, height - outlineYOffset, (uint8 *)dst + pitch + 2, pitch, c1);
 		} else {
 			blitCharacter<uint16>(glyphSource, width, height, (uint8 *)dst, pitch, c1, c2);
 		}

Modified: scummvm/trunk/graphics/sjis.h
===================================================================
--- scummvm/trunk/graphics/sjis.h	2010-11-05 00:10:26 UTC (rev 54078)
+++ scummvm/trunk/graphics/sjis.h	2010-11-05 00:36:23 UTC (rev 54079)
@@ -115,13 +115,9 @@
 
 	/**
 	 * Draws a SJIS encoded character on the given surface.
-	 *
-	 * TODO: Currently there is no assurance, that this method will only draw within
-	 * the surface boundaries. Thus the caller has to assure the glyph will fit at
-	 * the specified position.
 	 */
 	void drawChar(Graphics::Surface &dst, uint16 ch, int x, int y, uint32 c1, uint32 c2) const {
-		drawChar(dst.getBasePtr(x, y), ch, c1, c2, dst.pitch, dst.bytesPerPixel);
+		drawChar(dst.getBasePtr(x, y), ch, dst.pitch, dst.bytesPerPixel, c1, c2, dst.w - x, dst.h - y);
 	}
 
 	/**
@@ -133,8 +129,10 @@
 	 * @param bpp   bytes per pixel of the destination buffer
 	 * @param c1    forground color
 	 * @param c2    outline color
+	 * @param maxW  max draw width (to ensure that character drawing takes place within surface boundaries)
+	 * @param maxH  max draw height (to ensure that character drawing takes place within surface boundaries)
 	 */
-	virtual void drawChar(void *dst, uint16 ch, int pitch, int bpp, uint32 c1, uint32 c2) const = 0;
+	virtual void drawChar(void *dst, uint16 ch, int pitch, int bpp, uint32 c1, uint32 c2, int maxW = -1, int maxH = -1) const = 0;
 };
 
 /**
@@ -154,7 +152,7 @@
 
 	uint getCharWidth(uint16 ch) const;
 
-	void drawChar(void *dst, uint16 ch, int pitch, int bpp, uint32 c1, uint32 c2) const;
+	void drawChar(void *dst, uint16 ch, int pitch, int bpp, uint32 c1, uint32 c2, int maxW = -1, int maxH = -1) const;
 private:
 	template<typename Color>
 	void blitCharacter(const uint8 *glyph, const int w, const int h, uint8 *dst, int pitch, Color c1, Color c2 = 0) const;


This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.




More information about the Scummvm-git-logs mailing list