diff options
Diffstat (limited to 'graphics')
| -rw-r--r-- | graphics/VectorRenderer.h | 11 | ||||
| -rw-r--r-- | graphics/cursorman.cpp | 6 | ||||
| -rw-r--r-- | graphics/cursorman.h | 27 | ||||
| -rw-r--r-- | graphics/iff.cpp | 258 | ||||
| -rw-r--r-- | graphics/iff.h | 101 | 
5 files changed, 222 insertions, 181 deletions
| diff --git a/graphics/VectorRenderer.h b/graphics/VectorRenderer.h index acc2f77357..136a8d55b3 100644 --- a/graphics/VectorRenderer.h +++ b/graphics/VectorRenderer.h @@ -37,6 +37,10 @@  namespace Graphics {  class VectorRenderer; + +typedef void (VectorRenderer::*DrawingFunctionCallback)(const Common::Rect &, const Graphics::DrawStep &); + +  struct DrawStep {  	struct Color {  		uint8 r, g, b; @@ -59,7 +63,10 @@ struct DrawStep {  		kVectorAlignBottom,  		kVectorAlignTop,  		kVectorAlignCenter -	} xAlign, yAlign; +	}; + +	VectorAlignment xAlign; +	VectorAlignment yAlign;  	uint8 shadow, stroke, factor, radius, bevel; /**< Misc options... */ @@ -68,7 +75,7 @@ struct DrawStep {  	uint32 scale; /**< scale of all the coordinates in FIXED POINT with 16 bits mantissa */ -	void (VectorRenderer::*drawingCall)(const Common::Rect &, const DrawStep &); /** Pointer to drawing function */ +	DrawingFunctionCallback drawingCall; /**< Pointer to drawing function */  	Graphics::Surface *blitSrc;  }; diff --git a/graphics/cursorman.cpp b/graphics/cursorman.cpp index fe5f653b94..2e71b548bc 100644 --- a/graphics/cursorman.cpp +++ b/graphics/cursorman.cpp @@ -129,6 +129,10 @@ void CursorManager::replaceCursor(const byte *buf, uint w, uint h, int hotspotX,  	g_system->setMouseCursor(cur->_data, w, h, hotspotX, hotspotY, keycolor, targetScale);  } +bool CursorManager::supportsCursorPalettes() { +	return g_system->hasFeature(OSystem::kFeatureCursorHasPalette); +} +  void CursorManager::disableCursorPalette(bool disable) {  	if (!g_system->hasFeature(OSystem::kFeatureCursorHasPalette))  		return; @@ -139,7 +143,7 @@ void CursorManager::disableCursorPalette(bool disable) {  	Palette *pal = _cursorPaletteStack.top();  	pal->_disabled = disable; -	g_system->disableCursorPalette(true); +	g_system->disableCursorPalette(disable);  }  void CursorManager::pushCursorPalette(const byte *colors, uint start, uint num) { diff --git a/graphics/cursorman.h b/graphics/cursorman.h index bc38466eda..f019e37b04 100644 --- a/graphics/cursorman.h +++ b/graphics/cursorman.h @@ -36,7 +36,21 @@ public:  	/** Query whether the mouse cursor is visible. */  	bool isVisible(); -	/** Show or hide the mouse cursor. */ +	/** +	 * Show or hide the mouse cursor. +	 * +	 * This function does not call OSystem::updateScreen, when visible is true. +	 * This fact might result in a non visible mouse cursor if the caller does +	 * not call OSystem::updateScreen itself after a showMouse(true) call. +	 * +	 * TODO: We might want to reconsider this behavior, it might be confusing +	 * for the user to call OSystem::updateScreen separately, on the other +	 * hand OSystem::updateScreen might as well display unwanted changes on +	 * the screen. Another alternative would be to let the backend worry +	 * about this on OSystem::showMouse call. +	 * +	 * @see OSystem::showMouse. +	 */  	bool showMouse(bool visible);  	/** @@ -88,6 +102,17 @@ public:  	void popAllCursors();  	/** +	 * Test whether cursor palettes are supported. +	 * +	 * This is just an convenience wrapper for checking for +	 * OSystem::kFeatureCursorHasPalette to be supported by OSystem. +	 * +	 * @see OSystem::kFeatureCursorHasPalette +	 * @see OSystem::hasFeature +	 */ +	bool supportsCursorPalettes(); + +	/**  	 * Enable/Disable the current cursor palette.  	 *  	 * @param disable diff --git a/graphics/iff.cpp b/graphics/iff.cpp index ea6447ac01..902f97499a 100644 --- a/graphics/iff.cpp +++ b/graphics/iff.cpp @@ -48,194 +48,179 @@ char *ID2string(Common::IFF_ID id) {  namespace Graphics { - -void fillBMHD(BMHD &bitmapHeader, Common::ReadStream &stream) { - -	bitmapHeader.width = stream.readUint16BE(); -	bitmapHeader.height = stream.readUint16BE(); -	bitmapHeader.x = stream.readUint16BE(); -	bitmapHeader.y = stream.readUint16BE(); -	bitmapHeader.depth = stream.readByte(); -	bitmapHeader.masking = stream.readByte(); -	bitmapHeader.pack = stream.readByte(); -	bitmapHeader.flags = stream.readByte(); -	bitmapHeader.transparentColor = stream.readUint16BE(); -	bitmapHeader.xAspect = stream.readByte(); -	bitmapHeader.yAspect = stream.readByte(); -	bitmapHeader.pageWidth = stream.readUint16BE(); -	bitmapHeader.pageHeight = stream.readUint16BE(); - +void BMHD::load(Common::ReadStream *stream) { +	assert(stream); +	stream->read(this, sizeof(BMHD)); +	width = FROM_BE_16(width); +	height = FROM_BE_16(height); +	x = FROM_BE_16(x); +	y = FROM_BE_16(y); +	transparentColor = FROM_BE_16(transparentColor); +	pageWidth = FROM_BE_16(pageWidth); +	pageHeight = FROM_BE_16(pageHeight);  } -ILBMDecoder::ILBMDecoder(Common::ReadStream &input, Surface &surface, byte *&colors) : IFFParser(input), _surface(&surface), _colors(&colors) { -	if (_typeId != ID_ILBM) -		error("unsupported IFF subtype '%s'", Common::ID2string(_typeId)); +void ILBMDecoder::loadHeader(Common::ReadStream *stream) { +	_header.load(stream);  } -void ILBMDecoder::decode() { - -	Common::IFFChunk *chunk; -	while ((chunk = nextChunk()) != 0) { -		switch (chunk->id) { -		case ID_BMHD: -			readBMHD(*chunk); -			break; +void ILBMDecoder::loadBitmap(uint32 mode, byte *buffer, Common::ReadStream *stream) { +	assert(stream); +	uint32 numPlanes = MIN(mode & ILBM_UNPACK_PLANES, (uint32)_header.depth); +	assert(numPlanes == 1 || numPlanes == 2 || numPlanes == 3 || numPlanes == 4 || numPlanes == 5 || numPlanes == 8); -		case ID_CMAP: -			readCMAP(*chunk); -			break; - -		case ID_BODY: -			readBODY(*chunk); -			break; -		} +	bool packPixels = (mode & ILBM_PACK_PLANES) != 0; +	if (numPlanes != 1 && numPlanes != 2 && numPlanes != 4) { +		packPixels = false;  	} -	return; -} +	uint32 outPitch = _header.width; +	if (packPixels) { +		outPitch /= (8 / numPlanes); +	} +	byte *out = buffer; -void ILBMDecoder::readBMHD(Common::IFFChunk &chunk) { +	switch (_header.pack) { +	case 1: {	// PackBits compressed bitmap +		Graphics::PackBitsReadStream packStream(*stream); -	fillBMHD(_bitmapHeader, chunk); +		// setup a buffer to hold enough data to build a line in the output +		uint32 scanlineWidth = ((_header.width + 15)/16) << 1; +		byte *scanline = new byte[scanlineWidth * _header.depth]; -	_colorCount = 1 << _bitmapHeader.depth; -	*_colors = (byte*)malloc(sizeof(**_colors) * _colorCount * 3); -	_surface->create(_bitmapHeader.width, _bitmapHeader.height, 1); +		for (uint i = 0; i < _header.height; ++i) { +			byte *s = scanline; +			for (uint32 j = 0; j < _header.depth; ++j) { +				packStream.read(s, scanlineWidth); +				s += scanlineWidth; +			} -} +			planarToChunky(out, outPitch, scanline, scanlineWidth, numPlanes, packPixels); +			out += outPitch; +		} -void ILBMDecoder::readCMAP(Common::IFFChunk &chunk) { -	if (*_colors == NULL) { -		error("wrong input chunk sequence"); +		delete []scanline; +		break;  	} -	for (uint32 i = 0; i < _colorCount; i++) { -		(*_colors)[i * 3 + 0] = chunk.readByte(); -		(*_colors)[i * 3 + 1] = chunk.readByte(); -		(*_colors)[i * 3 + 2] = chunk.readByte(); + +	default: +		// implement other compression types here! +		error("only RLE compressed ILBM files are supported"); +		break;  	}  } -void ILBMDecoder::readBODY(Common::IFFChunk& chunk) { +void ILBMDecoder::planarToChunky(byte *out, uint32 outPitch, byte *in, uint32 inWidth, uint32 nPlanes, bool packPlanes) { +	byte pix, ofs, bit; +	byte *s; -	switch (_bitmapHeader.pack) { -	case 0: -		error("unpacked ILBM files are not supported"); -		break; +	uint32 pixels = outPitch; +	if (packPlanes) { +		pixels *= (8 / nPlanes); +	} -	case 1: { -		uint32 scanWidth = (_bitmapHeader.width + 7) >> 3; -		byte *scan = (byte*)malloc(scanWidth); -		byte *out = (byte*)_surface->pixels; +	for (uint32 x = 0; x < pixels; ++x) { -		PackBitsReadStream stream(chunk); +		pix = 0; +		ofs = x >> 3; +		bit = 0x80 >> (x & 7); -		for (uint32 i = 0; i < _bitmapHeader.height; i++) { -			for (uint32 j = 0; j < _bitmapHeader.depth; j++) { -				stream.read(scan, scanWidth); -				fillPlane(out, scan, scanWidth, j); +		// first build a pixel by scanning all the usable planes in the input +		s = in; +		for (uint32 plane = 0; plane < nPlanes; ++plane) { +			if (s[ofs] & bit) { +				pix |= (1 << plane);  			} - -			out += _bitmapHeader.width; +			s += inWidth;  		} -		free(scan); -		break; -	} - -	} -} -void ILBMDecoder::fillPlane(byte *out, byte* buf, uint32 width, uint32 plane) { -	byte src, idx, set; -	byte mask = 1 << plane; - -	for (uint32 j = 0; j < _bitmapHeader.width; j++) { -		src = buf[j >> 3]; -		idx = 7 - (j & 7); -		set = src & (1 << idx); - -		if (set) -			out[j] |= mask; +		// then output the pixel according to the requested packing +		if (!packPlanes) { +			out[x] = pix; +		} else +		if (nPlanes == 1) { +			out[x/8] |= (pix << (x & 7)); +		} else +		if (nPlanes == 2) { +			out[x/4] |= (pix << ((x & 3) << 1)); +		} else +		if (nPlanes == 4) { +			out[x/2] |= (pix << ((x & 1) << 2)); +		}  	}  } - - -PBMDecoder::PBMDecoder(Common::ReadStream &input, Surface &surface, byte *&colors) : IFFParser(input), _surface(&surface), _colors(&colors) { -	if (_typeId != ID_PBM) -		error("unsupported IFF subtype '%s'", Common::ID2string(_typeId)); +void PBMDecoder::loadHeader(Common::ReadStream *stream) { +	_header.load(stream);  } -void PBMDecoder::decode() { -	Common::IFFChunk *chunk; -	while ((chunk = nextChunk()) != 0) { -		switch (chunk->id) { -		case ID_BMHD: -			readBMHD(*chunk); -			break; +void PBMDecoder::loadBitmap(byte *buffer, Common::ReadStream *stream) { +	uint32 outSize = _header.width * _header.height; -		case ID_CMAP: -			readCMAP(*chunk); -			break; +	switch (_header.pack) { +	case 0: +		stream->read(buffer, outSize); +		break; -		case ID_BODY: -			readBODY(*chunk); -			break; +	case 1: { +		PackBitsReadStream packStream(*stream); +		packStream.read(buffer, outSize); +		break;  		}  	} - -	return;  } -void PBMDecoder::readBMHD(Common::IFFChunk &chunk) { -	fillBMHD(_bitmapHeader, chunk); +struct PBMLoader { +	PBMDecoder _decoder; +	Surface *_surface; +	byte *_colors; -	_colorCount = 1 << _bitmapHeader.depth; -	*_colors = (byte*)malloc(sizeof(**_colors) * _colorCount * 3); -	_surface->create(_bitmapHeader.width, _bitmapHeader.height, 1); - -} - -void PBMDecoder::readCMAP(Common::IFFChunk &chunk) { -	if (*_colors == NULL) { -		error("wrong input chunk sequence"); -	} -	for (uint32 i = 0; i < _colorCount; i++) { -		(*_colors)[i * 3 + 0] = chunk.readByte(); -		(*_colors)[i * 3 + 1] = chunk.readByte(); -		(*_colors)[i * 3 + 2] = chunk.readByte(); +	void load(Common::ReadStream &input, Surface &surface, byte *&colors) { +		_surface = &surface; +		_colors = colors; +		Common::IFFParser parser(&input); +		Common::Functor1Mem< Common::IFFChunk&, bool, PBMLoader > c(this, &PBMLoader::callback); +		parser.parse(c);  	} -} -void PBMDecoder::readBODY(Common::IFFChunk& chunk) { +	bool callback(Common::IFFChunk &chunk) { +		switch (chunk._type) { +		case ID_BMHD: +			_decoder.loadHeader(chunk._stream); +			break; -	uint si = 0; +		case ID_CMAP: +			if (_colors) { +				chunk._stream->read(_colors, chunk._size); +			} +			break; -	switch (_bitmapHeader.pack) { -	case 0: -		while (!chunk.hasReadAll()) { -			((byte*)_surface->pixels)[si++] = chunk.readByte(); +		case ID_BODY: +			if (_surface) { +				_surface->create(_decoder._header.width, _decoder._header.height, 1); +				_decoder.loadBitmap((byte*)_surface->pixels, chunk._stream); +			} +			return true;	// stop the parser  		} -		break; -	case 1: { -		PackBitsReadStream stream(chunk); -		stream.read((byte*)_surface->pixels, _surface->w * _surface->h); -		break; +		return false;  	} +}; -	} +void decodePBM(Common::ReadStream &input, Surface &surface, byte *colors) { +	PBMLoader loader; +	loader.load(input, surface, colors);  } -  PackBitsReadStream::PackBitsReadStream(Common::ReadStream &input) : _input(&input) {  } @@ -282,9 +267,4 @@ uint32 PackBitsReadStream::read(void *dataPtr, uint32 dataSize) {  } -void decodePBM(Common::ReadStream &input, Surface &surface, byte *&colors) { -	PBMDecoder decoder(input, surface, colors); -	decoder.decode(); -} -  } diff --git a/graphics/iff.h b/graphics/iff.h index 13b82a673c..fc1b6ceefa 100644 --- a/graphics/iff.h +++ b/graphics/iff.h @@ -52,55 +52,80 @@ struct BMHD {  	BMHD() {  		memset(this, 0, sizeof(*this));  	} -}; - -//	handles ILBM subtype of IFF FORM files -// -class ILBMDecoder : public Common::IFFParser { +	void load(Common::ReadStream *stream); +}; -protected: -	void readBMHD(Common::IFFChunk &chunk); -	void readCMAP(Common::IFFChunk &chunk); -	void readBODY(Common::IFFChunk &chunk); -	BMHD	_bitmapHeader; -	uint32	_colorCount; +struct ILBMDecoder { +	/** +	 * ILBM header data, necessary for loadBitmap() +	 */ +	Graphics::BMHD	_header; + +	/** +	 * Available decoding modes for loadBitmap(). +	 */ +	enum { +		ILBM_UNPACK_PLANES = 0xFF,		//!< Decode all bitplanes, and map 1 pixel to 1 byte. +		ILBM_PACK_PLANES   = 0x100,		//!< Request unpacking, used as a mask with below options. + +		ILBM_1_PLANES      = 1,									//!< Decode only the first bitplane, don't pack. +		ILBM_1_PACK_PLANES = ILBM_1_PLANES | ILBM_PACK_PLANES, 	//!< Decode only the first bitplane, pack 8 pixels in 1 byte. +		ILBM_2_PLANES      = 2,									//!< Decode first 2 bitplanes, don't pack. +		ILBM_2_PACK_PLANES = ILBM_2_PLANES | ILBM_PACK_PLANES,	//!< Decode first 2 bitplanes, pack 4 pixels in 1 byte. +		ILBM_3_PLANES      = 3,									//!< Decode first 3 bitplanes, don't pack. +		ILBM_4_PLANES      = 4,									//!< Decode first 4 bitplanes, don't pack. +		ILBM_4_PACK_PLANES = ILBM_4_PLANES | ILBM_PACK_PLANES,	//!< Decode first 4 bitplanes, pack 2 pixels in 1 byte. +		ILBM_5_PLANES      = 5,									//!< Decode first 5 bitplanes, don't pack. +		ILBM_8_PLANES      = 8									//!< Decode all 8 bitplanes. +	}; + +	/** +	 * Fills the _header member from the given stream. +	 */ +	void loadHeader(Common::ReadStream *stream); + +	/** +	 * Loads and unpacks the ILBM bitmap data from the stream into the buffer. +	 * The functions assumes the buffer is large enough to contain all data. +	 * The caller controls how data should be packed by choosing mode from +	 * the enum above. +	 */ +	void loadBitmap(uint32 mode, byte *buffer, Common::ReadStream *stream); + +	/** +	 * Converts from bitplanar to chunky representation. Intended for internal +	 * usage, but you can be (ab)use it from client code if you know what you +	 * are doing. +	 */ +	void planarToChunky(byte *out, uint32 width, byte *in, uint32 planeWidth, uint32 nPlanes, bool packPlanes); +}; -	Surface *_surface; -	byte    **_colors; -	void fillPlane(byte *out, byte* buf, uint32 width, uint32 plane); - -public: -	ILBMDecoder(Common::ReadStream &input, Surface &surface, byte *&colors); -	virtual ~ILBMDecoder() { } -	void decode(); -};  //	handles PBM subtype of IFF FORM files  // -class PBMDecoder : public Common::IFFParser { - -protected: -	void readBMHD(Common::IFFChunk &chunk); -	void readCMAP(Common::IFFChunk &chunk); -	void readBODY(Common::IFFChunk &chunk); - -	BMHD	_bitmapHeader; -	uint32	_colorCount; - -	Surface *_surface; -	byte    **_colors; - -public: -	PBMDecoder(Common::ReadStream &input, Surface &surface, byte *&colors); -	virtual ~PBMDecoder() { } -	void decode(); +struct PBMDecoder { +	/** +	 * PBM header data, necessary for loadBitmap() +	 */ +	Graphics::BMHD	_header; + +	/** +	 * Fills the _header member from the given stream. +	 */ +	void loadHeader(Common::ReadStream *stream); + +	/** +	 * Loads and unpacks the PBM bitmap data from the stream into the buffer. +	 * The functions assumes the buffer is large enough to contain all data. +	 */ +	void loadBitmap(byte *buffer, Common::ReadStream *stream);  }; -void decodePBM(Common::ReadStream &input, Surface &surface, byte *&colors); +void decodePBM(Common::ReadStream &input, Surface &surface, byte *colors);  /* | 
