diff options
| -rw-r--r-- | saga/actor.cpp | 101 | ||||
| -rw-r--r-- | saga/actor.h | 13 | ||||
| -rw-r--r-- | saga/events.cpp | 7 | ||||
| -rw-r--r-- | saga/font.cpp | 662 | ||||
| -rw-r--r-- | saga/font.h | 111 | ||||
| -rw-r--r-- | saga/image.cpp | 2 | ||||
| -rw-r--r-- | saga/interface.cpp | 77 | ||||
| -rw-r--r-- | saga/ite_introproc.cpp | 59 | ||||
| -rw-r--r-- | saga/module.mk | 1 | ||||
| -rw-r--r-- | saga/objectmap.cpp | 7 | ||||
| -rw-r--r-- | saga/puzzle.cpp | 16 | ||||
| -rw-r--r-- | saga/puzzle.h | 1 | ||||
| -rw-r--r-- | saga/render.cpp | 43 | ||||
| -rw-r--r-- | saga/render.h | 1 | ||||
| -rw-r--r-- | saga/saga.h | 29 | ||||
| -rw-r--r-- | saga/scene.cpp | 25 | ||||
| -rw-r--r-- | saga/scene.h | 5 | ||||
| -rw-r--r-- | saga/script.h | 4 | ||||
| -rw-r--r-- | saga/sfuncs.cpp | 38 | ||||
| -rw-r--r-- | saga/sprite.cpp | 1 | 
20 files changed, 721 insertions, 482 deletions
diff --git a/saga/actor.cpp b/saga/actor.cpp index d8394c505d..e4c48c266a 100644 --- a/saga/actor.cpp +++ b/saga/actor.cpp @@ -30,7 +30,6 @@  #include "saga/sndres.h"  #include "saga/sprite.h"  #include "saga/font.h" -#include "saga/text.h"  #include "saga/sound.h"  #include "saga/scene.h" @@ -733,6 +732,8 @@ void Actor::handleSpeech(int msec) {  	int i;  	int talkspeed;  	ActorData *actor; +	int width, height, height2; +	Point posPoint;  	if (_activeSpeech.playing) {  		_activeSpeech.playingTime -= msec; @@ -817,13 +818,39 @@ void Actor::handleSpeech(int msec) {  			actor->currentAction = kActionSpeak;  			actor->actionCycle = _vm->_rnd.getRandomNumber(63);  		} -		for (i = 0; i < _activeSpeech.actorsCount; i++) { -			actor = getActor(_activeSpeech.actorIds[i]); -			_activeSpeech.speechCoords[i] = actor->screenPosition; -			_activeSpeech.speechCoords[i].y -= ACTOR_DIALOGUE_HEIGHT; -			_activeSpeech.speechCoords[i].y = MAX(_activeSpeech.speechCoords[i].y, (int16)10); -		}  	} + +	if (_activeSpeech.actorsCount == 1) { +		width = _activeSpeech.speechBox.width(); +		height = _vm->_font->getHeight(kMediumFont, _activeSpeech.strings[0], width - 2, _activeSpeech.getFontFlags(0)) + 1; + +		if (height > 40 && width < _vm->getDisplayWidth() - 100) { +			width = _vm->getDisplayWidth() - 100; +			height = _vm->_font->getHeight(kMediumFont, _activeSpeech.strings[0], width - 2, _activeSpeech.getFontFlags(0)) + 1; +		} + +		_activeSpeech.speechBox.setWidth(width); +		 +		if (_activeSpeech.actorIds[0] != 0) { +			actor = getActor(_activeSpeech.actorIds[0]); +			_activeSpeech.speechBox.setHeight(height); + +			if (_activeSpeech.speechBox.right > _vm->getDisplayWidth() - 10) { +				_activeSpeech.drawRect.left = _vm->getDisplayWidth() - 10 - width; +			} else { +				_activeSpeech.drawRect.left = _activeSpeech.speechBox.left; +			} + +			height2 =  actor->screenPosition.y - 50; +			_activeSpeech.speechBox.top = _activeSpeech.drawRect.top = MAX(10, (height2 - height) / 2); +		} else { +			_activeSpeech.drawRect.left = _activeSpeech.speechBox.left; +			_activeSpeech.drawRect.top = _activeSpeech.speechBox.top + (_activeSpeech.speechBox.height() - height) / 2; +		} +		_activeSpeech.drawRect.setWidth(width); +		_activeSpeech.drawRect.setHeight(height); +	}		 +  	_activeSpeech.playing = true;			  } @@ -1404,7 +1431,9 @@ void Actor::drawActors() {  void Actor::drawSpeech(void) {  	if (isSpeaking() && _activeSpeech.playing && !_vm->_script->_skipSpeeches) {  		int i; -		int textDrawFlags; +		Point textPoint; +		ActorData *actor; +		int width, height;  		char oneChar[2];  		oneChar[1] = 0;  		const char *outputString; @@ -1419,26 +1448,24 @@ void Actor::drawSpeech(void) {  			outputString = _activeSpeech.strings[0];  		} -		textDrawFlags = FONT_CENTERED; -		if (_activeSpeech.outlineColor != 0) { -			textDrawFlags |= FONT_OUTLINE; -		} - -		if (_activeSpeech.actorIds[0] != 0) { +		if (_activeSpeech.actorsCount > 1) { +			height = _vm->_font->getHeight(kMediumFont); +			width = _vm->_font->getStringWidth(kMediumFont, _activeSpeech.strings[0], 0, kFontNormal); -			for (i = 0; i < _activeSpeech.actorsCount; i++){ -				_vm->textDraw(MEDIUM_FONT_ID, backBuffer, outputString, -					_activeSpeech.speechCoords[i].x,  -					_activeSpeech.speechCoords[i].y,  -					_activeSpeech.speechColor[i],  -					_activeSpeech.outlineColor[i], textDrawFlags); -			} +			for ( i = 0; i < _activeSpeech.actorsCount; i++) { +				actor = getActor(_activeSpeech.actorIds[i]); +				calcScreenPosition(actor); -		} else { // non actors speech -			warning("non actors speech occures"); -			//todo: write it -		} +				textPoint.x = clamp( 10, actor->screenPosition.x - width / 2, _vm->getDisplayWidth() - 10 - width); +				textPoint.y = clamp( 10, actor->screenPosition.y - 58, _vm->getSceneHeight() - 10 - height); +				_vm->_font->textDraw(kMediumFont, backBuffer, _activeSpeech.strings[0], textPoint,  +					_activeSpeech.speechColor[i], _activeSpeech.outlineColor[i], _activeSpeech.getFontFlags(i)); +			} +		} else { +			_vm->_font->textDrawRect(kMediumFont, backBuffer, _activeSpeech.strings[0], _activeSpeech.drawRect, _activeSpeech.speechColor[0], +				_activeSpeech.outlineColor[0], _activeSpeech.getFontFlags(0)); +		}  	}  } @@ -1820,6 +1847,7 @@ bool Actor::actorWalkTo(uint16 actorId, const Location &toLocation) {  void Actor::actorSpeech(uint16 actorId, const char **strings, int stringsCount, int sampleResourceId, int speechFlags) {  	ActorData *actor;  	int i; +	int16 dist;  	if (_vm->getGameType() == GType_IHNM) {  		warning("Actors aren't implemented for IHNM yet"); @@ -1827,6 +1855,7 @@ void Actor::actorSpeech(uint16 actorId, const char **strings, int stringsCount,  	}  	actor = getActor(actorId); +	calcScreenPosition(actor);  	for (i = 0; i < stringsCount; i++) {  		_activeSpeech.strings[i] = strings[i];  	} @@ -1840,9 +1869,24 @@ void Actor::actorSpeech(uint16 actorId, const char **strings, int stringsCount,  	_activeSpeech.sampleResourceId = sampleResourceId;  	_activeSpeech.playing = false;  	_activeSpeech.slowModeCharIndex = 0; + +	dist = MIN(actor->screenPosition.x - 10, _vm->getDisplayWidth() - 10 - actor->screenPosition.x ); +	dist = clamp( 60, dist, 150 ); + +	_activeSpeech.speechBox.left = actor->screenPosition.x - dist; +	_activeSpeech.speechBox.right = actor->screenPosition.x + dist; + +	if (_activeSpeech.speechBox.left < 10) { +		_activeSpeech.speechBox.right += 10 - _activeSpeech.speechBox.left;  +		_activeSpeech.speechBox.left = 10;  +	} +	if (_activeSpeech.speechBox.right > _vm->getDisplayWidth() - 10) { +		_activeSpeech.speechBox.left -= _activeSpeech.speechBox.right - _vm->getDisplayWidth() - 10; +		_activeSpeech.speechBox.right = _vm->getDisplayWidth() - 10;  +	}	  } -void Actor::nonActorSpeech(const char **strings, int stringsCount, int speechFlags) { +void Actor::nonActorSpeech(const Common::Rect &box, const char **strings, int stringsCount, int speechFlags) {  	int i;  	_vm->_script->wakeUpThreads(kWaitTypeSpeech); @@ -1854,13 +1898,10 @@ void Actor::nonActorSpeech(const char **strings, int stringsCount, int speechFla  	_activeSpeech.speechFlags = speechFlags;  	_activeSpeech.actorsCount = 1;  	_activeSpeech.actorIds[0] = 0; -	//_activeSpeech.speechColor[0] = ; -	//_activeSpeech.outlineColor[0] = ; -	//_activeSpeech.speechCoords[0].x = ; -	//_activeSpeech.speechCoords[0].y = ;  	_activeSpeech.sampleResourceId = -1;  	_activeSpeech.playing = false;  	_activeSpeech.slowModeCharIndex = 0; +	_activeSpeech.speechBox = box;  }  void Actor::simulSpeech(const char *string, uint16 *actorIds, int actorIdsCount, int speechFlags, int sampleResourceId) { diff --git a/saga/actor.h b/saga/actor.h index 0f2b4255db..271d7a39dc 100644 --- a/saga/actor.h +++ b/saga/actor.h @@ -470,7 +470,8 @@ struct SpeechData {  	int outlineColor[ACTOR_SPEECH_ACTORS_MAX];  	int speechFlags;  	const char *strings[ACTOR_SPEECH_STRING_MAX]; -	Point speechCoords[ACTOR_SPEECH_ACTORS_MAX]; +	Rect speechBox; +	Rect drawRect;  	int stringsCount;  	int slowModeCharIndex;  	uint16 actorIds[ACTOR_SPEECH_ACTORS_MAX]; @@ -482,6 +483,14 @@ struct SpeechData {  	SpeechData() {   		memset(this, 0, sizeof(*this));   	} + +	FontEffectFlags getFontFlags(int i) { +		if (outlineColor[i] != 0) { +			return kFontOutline; +		} else { +			return kFontNormal; +		} +	}  }; @@ -545,7 +554,7 @@ public:  //	speech   	void actorSpeech(uint16 actorId, const char **strings, int stringsCount, int sampleResourceId, int speechFlags); -	void nonActorSpeech(const char **strings, int stringsCount, int speechFlags); +	void nonActorSpeech(const Common::Rect &box, const char **strings, int stringsCount, int speechFlags);  	void simulSpeech(const char *string, uint16 *actorIds, int actorIdsCount, int speechFlags, int sampleResourceId);  	void setSpeechColor(int speechColor, int outlineColor) {  		_activeSpeech.speechColor[0] = speechColor; diff --git a/saga/events.cpp b/saga/events.cpp index 5bc603751d..0b7ea0c4ca 100644 --- a/saga/events.cpp +++ b/saga/events.cpp @@ -32,7 +32,6 @@  #include "saga/console.h"  #include "saga/scene.h"  #include "saga/interface.h" -#include "saga/text.h"  #include "saga/palanim.h"  #include "saga/render.h"  #include "saga/sndres.h" @@ -279,12 +278,10 @@ int Events::handleOneShot(EVENT *event) {  	case TEXT_EVENT:  		switch (event->op) {  		case EVENT_DISPLAY: -			_vm->textSetDisplay((TEXTLIST_ENTRY *)event->data, 1); +			((TextListEntry *)event->data)->display = 1;  			break;  		case EVENT_REMOVE: -			{ -				_vm->textDeleteEntry(_vm->_scene->_textList, (TEXTLIST_ENTRY *)event->data); -			} +			_vm->_scene->_textList.remove((TextListEntry *)event->data);  			break;  		default:  			break; diff --git a/saga/font.cpp b/saga/font.cpp index c18f9f338f..4af061eb6d 100644 --- a/saga/font.cpp +++ b/saga/font.cpp @@ -36,19 +36,11 @@ Font::Font(SagaEngine *vm) : _vm(vm), _initialized(false) {  	int i;  	// Load font module resource context  -	_fontContext = _vm->getFileContext(GAME_RESOURCEFILE, 0); -	if (_fontContext == NULL) { -		error("Font::Font(): Couldn't get resource context."); -	}  	assert(_vm->getFontsCount() > 0); -	_nFonts = 0; - -	_fonts = (FONT **)malloc(_vm->getFontsCount() * sizeof(*_fonts)); -	if (_fonts == NULL) { -		memoryError("Font::Font"); -	} +	_fonts = (FontData **)calloc(_vm->getFontsCount(), sizeof(*_fonts)); +	_loadedFonts = 0;  	for (i = 0; i < _vm->getFontsCount(); i++) {  		loadFont(_vm->getFontDescription(i)->fontResourceId); @@ -58,377 +50,303 @@ Font::Font(SagaEngine *vm) : _vm(vm), _initialized(false) {  }  Font::~Font(void) { -//	int i; -  	debug(8, "Font::~Font(): Freeing fonts."); -/* -	for (i = 0 ; i < FONT_COUNT ; i++) { -		if (_fonts[i] != NULL) { -			if (_fonts[i]->normal_loaded) { -				free(_fonts[i]->normal->font_free_p); -				free(_fonts[i]->normal); -			} +	int i; -			if (_fonts[i]->outline_loaded) { -				free(_fonts[i]->outline->font_free_p); -				free(_fonts[i]->outline); -			} +	for (i = 0 ; i < _loadedFonts ; i++) { +		if (_fonts[i] != NULL) { +			free(_fonts[i]->normal.font); +			free(_fonts[i]->outline.font);  		}  		free(_fonts[i]);  	} -*/  } -int Font::loadFont(uint32 fontResourceId) { -	FONT_HEADER fh; -	FONT *font; -	FONT_STYLE *normal_font; -	byte *fontres_p; -	size_t fontres_len; -	int nbits; +void Font::loadFont(uint32 fontResourceId) { +	FontData *font; +	byte *fontResourcePointer; +	size_t fontResourceLength; +	int numBits;  	int c; +	RSCFILE_CONTEXT *fontContext; + + +	debug(1, "Font::loadFont(): Reading fontResourceId %d...", fontResourceId); + +	fontContext = _vm->getFileContext(GAME_RESOURCEFILE, 0); +	if (fontContext == NULL) { +		error("Font::Font(): Couldn't get resource context."); +	}  	// Load font resource -	if (RSC_LoadResource(_fontContext, fontResourceId, &fontres_p, &fontres_len) != SUCCESS) { +	if (RSC_LoadResource(fontContext, fontResourceId, &fontResourcePointer, &fontResourceLength) != SUCCESS) {  		error("Font::loadFont(): Couldn't load font resource.");  	} -	if (fontres_len < FONT_DESCSIZE) { -		warning("Font::loadFont(): Invalid font length (%d < %d)", fontres_len, FONT_DESCSIZE); -		return FAILURE; +	if (fontResourceLength < FONT_DESCSIZE) { +		error("Font::loadFont(): Invalid font length (%d < %d)", fontResourceLength, FONT_DESCSIZE);  	} -	MemoryReadStreamEndian readS(fontres_p, fontres_len, IS_BIG_ENDIAN); +	MemoryReadStreamEndian readS(fontResourcePointer, fontResourceLength, IS_BIG_ENDIAN);  	// Create new font structure -	font = (FONT *)malloc(sizeof(*font)); -	if (font == NULL) { -		memoryError("Font::loadFont"); -	} - +	font = (FontData *)malloc(sizeof(*font)); +	  	// Read font header -	fh.c_height = readS.readUint16(); -	fh.c_width = readS.readUint16(); -	fh.row_length = readS.readUint16(); +	font->normal.header.charHeight = readS.readUint16(); +	font->normal.header.charWidth = readS.readUint16(); +	font->normal.header.rowLength = readS.readUint16(); -	debug(1, "Font::loadFont(): Reading fontResourceId %d...", fontResourceId); - -	debug(2, "Character width: %d", fh.c_width); -	debug(2, "Character height: %d", fh.c_height); -	debug(2, "Row padding: %d", fh.row_length); - -	// Create normal font style -	normal_font = (FONT_STYLE *)malloc(sizeof(*normal_font)); -	if (normal_font == NULL) { -		memoryError("Font::loadFont"); -	} -	normal_font->font_free_p = fontres_p; -	normal_font->hdr.c_height = fh.c_height; -	normal_font->hdr.c_width = fh.c_width; -	normal_font->hdr.row_length = fh.row_length; +	debug(2, "Character width: %d", font->normal.header.charWidth); +	debug(2, "Character height: %d", font->normal.header.charHeight); +	debug(2, "Row padding: %d", font->normal.header.rowLength);  	for (c = 0; c < FONT_CHARCOUNT; c++) { -		normal_font->fce[c].index = readS.readUint16(); +		font->normal.fontCharEntry[c].index = readS.readUint16();  	}  	for (c = 0; c < FONT_CHARCOUNT; c++) { -		nbits = normal_font->fce[c].width = readS.readByte(); -		normal_font->fce[c].byte_width = getByteLen(nbits); +		numBits = font->normal.fontCharEntry[c].width = readS.readByte(); +		font->normal.fontCharEntry[c].byteWidth = getByteLen(numBits);  	}  	for (c = 0; c < FONT_CHARCOUNT; c++) { -		normal_font->fce[c].flag = readS.readByte(); +		font->normal.fontCharEntry[c].flag = readS.readByte();  	}  	for (c = 0; c < FONT_CHARCOUNT; c++) { -		normal_font->fce[c].tracking = readS.readByte(); +		font->normal.fontCharEntry[c].tracking = readS.readByte();  	}  	if (readS.pos() != FONT_DESCSIZE) { -		warning("Invalid font resource size."); -		return FAILURE; +		error("Invalid font resource size.");  	} -	normal_font->font_p = fontres_p + FONT_DESCSIZE; +	font->normal.font = (byte*)malloc(fontResourceLength - FONT_DESCSIZE); +	memcpy(font->normal.font, fontResourcePointer + FONT_DESCSIZE, fontResourceLength - FONT_DESCSIZE); -	font->normal = normal_font; -	font->normal_loaded = 1; +	RSC_FreeResource(fontResourcePointer); -	// Create outline font style -	font->outline = createOutline(normal_font); -	font->outline_loaded = 1; +	// Create outline font style +	createOutline(font); +	  	// Set font data  -	_fonts[_nFonts++] = font; - -	return SUCCESS; +	_fonts[_loadedFonts++] = font;	  } -int Font::getHeight(int font_id) { -	FONT *font; - -	if (!_initialized) { -		return FAILURE; -	} - -	if ((font_id < 0) || (font_id >= _nFonts) || (_fonts[font_id] == NULL)) { -		error("Font::getHeight(): Invalid font id."); -	} - -	font = _fonts[font_id]; -	return font->normal->hdr.c_height; -} - -FONT_STYLE *Font::createOutline(FONT_STYLE *src_font) { -	FONT_STYLE *new_font; -	unsigned char *new_font_data; -	size_t new_font_data_len; -	int s_width = src_font->hdr.c_width; -	int s_height = src_font->hdr.c_height; -	int new_row_len = 0; -	int row; +void Font::createOutline(FontData *font) {  	int i; +	int row; +	int newByteWidth; +	int oldByteWidth; +	int newRowLength = 0; +	size_t indexOffset = 0;  	int index; -	size_t index_offset = 0; -	int new_byte_width; -	int old_byte_width; -	int current_byte; -	unsigned char *base_ptr; -	unsigned char *src_ptr; -	unsigned char *dest_ptr1; -	unsigned char *dest_ptr2; -	unsigned char *dest_ptr3; -	unsigned char c_rep; - -	// Create new font style structure -	new_font = (FONT_STYLE *)malloc(sizeof(*new_font)); - -	if (new_font == NULL) { -		memoryError("Font::createOutline"); -	} +	int currentByte; +	unsigned char *basePointer; +	unsigned char *srcPointer; +	unsigned char *destPointer1; +	unsigned char *destPointer2; +	unsigned char *destPointer3; +	unsigned char charRep; -	memset(new_font, 0, sizeof(*new_font));  	// Populate new font style character data   	for (i = 0; i < FONT_CHARCOUNT; i++) { -		new_byte_width = 0; -		old_byte_width = 0; -		index = src_font->fce[i].index; +		newByteWidth = 0; +		oldByteWidth = 0; +		index = font->normal.fontCharEntry[i].index;  		if ((index > 0) || (i == FONT_FIRSTCHAR)) { -			index += index_offset; +			index += indexOffset;  		} -		new_font->fce[i].index = index; -		new_font->fce[i].tracking = src_font->fce[i].tracking; -		new_font->fce[i].flag = src_font->fce[i].flag; +		font->outline.fontCharEntry[i].index = index; +		font->outline.fontCharEntry[i].tracking = font->normal.fontCharEntry[i].tracking; +		font->outline.fontCharEntry[i].flag = font->normal.fontCharEntry[i].flag; -		if (src_font->fce[i].width != 0) { -			new_byte_width = getByteLen(src_font->fce[i].width + 2); -			old_byte_width = getByteLen(src_font->fce[i].width); +		if (font->normal.fontCharEntry[i].width != 0) { +			newByteWidth = getByteLen(font->normal.fontCharEntry[i].width + 2); +			oldByteWidth = getByteLen(font->normal.fontCharEntry[i].width); -			if (new_byte_width > old_byte_width) { -				index_offset++; +			if (newByteWidth > oldByteWidth) { +				indexOffset++;  			}  		} -		new_font->fce[i].width = src_font->fce[i].width + 2; -		new_font->fce[i].byte_width = new_byte_width; -		new_row_len += new_byte_width; +		font->outline.fontCharEntry[i].width = font->normal.fontCharEntry[i].width + 2; +		font->outline.fontCharEntry[i].byteWidth = newByteWidth; +		newRowLength += newByteWidth;  	} -	debug(2, "New row length: %d", new_row_len); +	debug(2, "New row length: %d", newRowLength); -	new_font->hdr.c_width = s_width + 2; -	new_font->hdr.c_height = s_height + 2; -	new_font->hdr.row_length = new_row_len; +	font->outline.header = font->normal.header; +	font->outline.header.charWidth += 2; +	font->outline.header.charHeight += 2; +	font->outline.header.rowLength = newRowLength;  	// Allocate new font representation storage  -	new_font_data_len = new_row_len * (s_height + 2); -	new_font_data = (unsigned char *)malloc(new_font_data_len); - -	if (new_font_data == NULL) { -		memoryError("Font::createOutline"); -	} - -	memset(new_font_data, 0, new_font_data_len); - -	new_font->font_free_p = new_font_data; -	new_font->font_p = new_font_data; +	font->outline.font = (unsigned char *)calloc(newRowLength, font->outline.header.charHeight); +	  	// Generate outline font representation  	for (i = 0; i < FONT_CHARCOUNT; i++) { -		for (row = 0; row < s_height; row++) { -			for (current_byte = 0; current_byte < new_font->fce[i].byte_width; current_byte++) { -				base_ptr = new_font->font_p + new_font->fce[i].index + current_byte; -				dest_ptr1 = base_ptr + new_font->hdr.row_length * row; -				dest_ptr2 = base_ptr + new_font->hdr.row_length * (row + 1); -				dest_ptr3 = base_ptr + new_font->hdr.row_length * (row + 2); -				if (current_byte > 0) { +		for (row = 0; row < font->normal.header.charHeight; row++) { +			for (currentByte = 0; currentByte < font->outline.fontCharEntry[i].byteWidth; currentByte++) { +				basePointer = font->outline.font + font->outline.fontCharEntry[i].index + currentByte; +				destPointer1 = basePointer + newRowLength * row; +				destPointer2 = basePointer + newRowLength * (row + 1); +				destPointer3 = basePointer + newRowLength * (row + 2); +				if (currentByte > 0) {  					// Get last two columns from previous byte -					src_ptr = src_font->font_p + src_font->hdr.row_length * row + src_font->fce[i].index + -								(current_byte - 1); -					c_rep = *src_ptr; -					*dest_ptr1 |= ((c_rep << 6) | (c_rep << 7)); -					*dest_ptr2 |= ((c_rep << 6) | (c_rep << 7)); -					*dest_ptr3 |= ((c_rep << 6) | (c_rep << 7)); +					srcPointer = font->normal.font + font->normal.header.rowLength * row + font->normal.fontCharEntry[i].index + (currentByte - 1); +					charRep = *srcPointer; +					*destPointer1 |= ((charRep << 6) | (charRep << 7)); +					*destPointer2 |= ((charRep << 6) | (charRep << 7)); +					*destPointer3 |= ((charRep << 6) | (charRep << 7));  				} -				if (current_byte < src_font->fce[i].byte_width) { -					src_ptr = src_font->font_p + src_font->hdr.row_length * row + src_font->fce[i].index + -								current_byte; -					c_rep = *src_ptr; -					*dest_ptr1 |= c_rep | (c_rep >> 1) | (c_rep >> 2); -					*dest_ptr2 |= c_rep | (c_rep >> 1) | (c_rep >> 2); -					*dest_ptr3 |= c_rep | (c_rep >> 1) | (c_rep >> 2); +				if (currentByte < font->normal.fontCharEntry[i].byteWidth) { +					srcPointer = font->normal.font + font->normal.header.rowLength * row + font->normal.fontCharEntry[i].index + currentByte; +					charRep = *srcPointer; +					*destPointer1 |= charRep | (charRep >> 1) | (charRep >> 2); +					*destPointer2 |= charRep | (charRep >> 1) | (charRep >> 2); +					*destPointer3 |= charRep | (charRep >> 1) | (charRep >> 2);  				}  			}  		}  		// "Hollow out" character to prevent overdraw -		for (row = 0; row < s_height; row++) { -			for (current_byte = 0; current_byte < new_font->fce[i].byte_width; current_byte++) { -				dest_ptr2 = new_font->font_p +  new_font->hdr.row_length * (row + 1) + new_font->fce[i].index + current_byte; -				if (current_byte > 0) { +		for (row = 0; row < font->normal.header.charHeight; row++) { +			for (currentByte = 0; currentByte < font->outline.fontCharEntry[i].byteWidth; currentByte++) { +				destPointer2 = font->outline.font +  font->outline.header.rowLength * (row + 1) + font->outline.fontCharEntry[i].index + currentByte; +				if (currentByte > 0) {  					// Get last two columns from previous byte -					src_ptr = src_font->font_p + src_font->hdr.row_length * row + src_font->fce[i].index + -								(current_byte - 1); -					*dest_ptr2 &= ((*src_ptr << 7) ^ 0xFFU); +					srcPointer = font->normal.font + font->normal.header.rowLength * row + font->normal.fontCharEntry[i].index + (currentByte - 1); +					*destPointer2 &= ((*srcPointer << 7) ^ 0xFFU);  				} -				if (current_byte < src_font->fce[i].byte_width) { -					src_ptr = src_font->font_p + src_font->hdr.row_length * row + src_font->fce[i].index + -								current_byte; -					*dest_ptr2 &= ((*src_ptr >> 1) ^ 0xFFU); +				if (currentByte < font->normal.fontCharEntry[i].byteWidth) { +					srcPointer = font->normal.font + font->normal.header.rowLength * row + font->normal.fontCharEntry[i].index + currentByte; +					*destPointer2 &= ((*srcPointer >> 1) ^ 0xFFU);  				}  			}  		} -	} - -	return new_font; -} - -int Font::getByteLen(int num_bits) { -	int byte_len; -	byte_len = num_bits / 8; - -	if (num_bits % 8) { -		byte_len++; -	} - -	return byte_len; +	}	  }  // Returns the horizontal length in pixels of the graphical representation  // of at most 'test_str_ct' characters of the string 'test_str', taking  // into account any formatting options specified by 'flags'.  // If 'test_str_ct' is 0, all characters of 'test_str' are counted. -int Font::getStringWidth(int font_id, const char *test_str, size_t test_str_ct, int flags) { -	FONT *font; +int Font::getStringWidth(FontId fontId, const char *text, size_t count, FontEffectFlags flags) { +	FontData *font;  	size_t ct;  	int width = 0;  	int ch; -	const byte *txt_p; +	const byte *txt; -	if (!_initialized) { -		return FAILURE; -	} +	validate(fontId); -	if ((font_id < 0) || (font_id >= _nFonts) || (_fonts[font_id] == NULL)) { -		error("Font::getStringWidth(): Invalid font id."); -	} - -	font = _fonts[font_id]; -	assert(font != NULL); +	font = _fonts[fontId]; -	txt_p = (const byte *) test_str; +	txt = (const byte *) text; -	for (ct = test_str_ct; *txt_p && (!test_str_ct || ct > 0); txt_p++, ct--) { -		ch = *txt_p & 0xFFU; +	for (ct = count; *txt && (!count || ct > 0); txt++, ct--) { +		ch = *txt & 0xFFU;  		// Translate character  		ch = _charMap[ch];  		assert(ch < FONT_CHARCOUNT); -		width += font->normal->fce[ch].tracking; +		width += font->normal.fontCharEntry[ch].tracking;  	} -	if ((flags & FONT_BOLD) || (flags & FONT_OUTLINE)) { +	if ((flags & kFontBold) || (flags & kFontOutline)) {  		width += 1;  	}  	return width;  } -int Font::draw(int font_id, Surface *ds, const char *draw_str, size_t draw_str_ct, -			int text_x, int text_y, int color, int effect_color, int flags) { -	FONT *font; +int Font::getHeight(FontId fontId) { +	FontData *font; -	if (!_initialized) { -		error("Font::draw(): Font Module not initialized."); -	} +	validate(fontId); -	if ((font_id < 0) || (font_id >= _nFonts) || (_fonts[font_id] == NULL)) { -		error("Font::draw(): Invalid font id."); -	} +	font = _fonts[fontId]; -	font = _fonts[font_id]; +	return font->normal.header.charHeight; +} -	if (flags & FONT_OUTLINE) {  -		outFont(font->outline, ds, draw_str, draw_str_ct, text_x - 1, text_y - 1, effect_color, flags); -		outFont(font->normal, ds, draw_str, draw_str_ct, text_x, text_y, color, flags); -	} else if (flags & FONT_SHADOW) { -		outFont(font->normal, ds, draw_str, draw_str_ct, text_x - 1, text_y + 1, effect_color, flags); -		outFont(font->normal, ds, draw_str, draw_str_ct, text_x, text_y, color, flags); +void Font::draw(FontId fontId, Surface *ds, const char *text, size_t count, const Common::Point &point, +			   int color, int effectColor, FontEffectFlags flags) { +	FontData *font; +	Point offsetPoint(point); + +	validate(fontId); + +	font = _fonts[fontId]; + +	if (flags & kFontOutline) {  +		offsetPoint.x--; +		offsetPoint.y--; +		outFont(font->outline, ds, text, count, offsetPoint, effectColor, flags); +		outFont(font->normal, ds, text, count, point, color, flags); +	} else if (flags & kFontShadow) { +		offsetPoint.x--; +		offsetPoint.y++; +		outFont(font->normal, ds, text, count, offsetPoint, effectColor, flags); +		outFont(font->normal, ds, text, count, point, color, flags);  	} else { // FONT_NORMAL -		outFont(font->normal, ds, draw_str, draw_str_ct, text_x, text_y, color, flags); +		outFont(font->normal, ds, text, count, point, color, flags);  	} - -	return SUCCESS;  } -int Font::outFont(FONT_STYLE * draw_font, Surface *ds, const char *draw_str, size_t draw_str_ct, -				  int text_x, int text_y, int color, int flags) { -	const byte *draw_str_p; -	byte *c_data_ptr; +void Font::outFont(const FontStyle & drawFont, Surface *ds, const char *text, size_t count, const Common::Point &point, int color, FontEffectFlags flags) { +	const byte *textPointer; +	byte *c_dataPointer;  	int c_code; -	int char_row; +	int charRow; +	Point textPoint(point); -	byte *output_ptr; -	byte *output_ptr_min; -	byte *output_ptr_max; +	byte *outputPointer; +	byte *outputPointer_min; +	byte *outputPointer_max;  	int row; -	int row_limit; +	int rowLimit;  	int c_byte_len;  	int c_byte;  	int c_bit;  	int ct; -	if ((text_x > ds->w) || (text_y > ds->h)) { +	if ((point.x > ds->w) || (point.y > ds->h)) {  		// Output string can't be visible -		return SUCCESS; +		return;  	} -	draw_str_p = (const byte *) draw_str; -	ct = draw_str_ct; +	textPointer = (const byte *) text; +	ct = count;  	// Draw string one character at a time, maximum of 'draw_str'_ct   	// characters, or no limit if 'draw_str_ct' is 0 -	for (; *draw_str_p && (!draw_str_ct || ct); draw_str_p++, ct--) { -		c_code = *draw_str_p & 0xFFU; +	for (; *textPointer && (!count || ct); textPointer++, ct--) { +		c_code = *textPointer & 0xFFU;  		// Translate character -		if (!(flags & FONT_DONTMAP)) +		if (!(flags & kFontDontmap))  			c_code = _charMap[c_code];  		assert(c_code < FONT_CHARCOUNT);  		// Check if character is defined -		if ((draw_font->fce[c_code].index == 0) && (c_code != FONT_FIRSTCHAR)) { +		if ((drawFont.fontCharEntry[c_code].index == 0) && (c_code != FONT_FIRSTCHAR)) {  #if FONT_SHOWUNDEFINED  			if (c_code == FONT_CH_SPACE) { -				text_x += draw_font->fce[c_code].tracking; +				textPoint.x += drawFont.fontCharEntry[c_code].tracking;  				continue;  			}  			c_code = FONT_CH_QMARK; @@ -436,49 +354,269 @@ int Font::outFont(FONT_STYLE * draw_font, Surface *ds, const char *draw_str, siz  			// Character code is not defined, but advance tracking  			// ( Not defined if offset is 0, except for 33 ('!') which  			//   is defined ) -			text_x += draw_font->fce[c_code].tracking; +			textPoint.x += drawFont.fontCharEntry[c_code].tracking;  			continue;  #endif  		}  		// Get length of character in bytes -		c_byte_len = ((draw_font->fce[c_code].width - 1) / 8) + 1; -		row_limit = (ds->h < (text_y + draw_font->hdr.c_height)) ? ds->h : text_y + draw_font->hdr.c_height; -		char_row = 0; +		c_byte_len = ((drawFont.fontCharEntry[c_code].width - 1) / 8) + 1; +		rowLimit = (ds->h < (textPoint.y + drawFont.header.charHeight)) ? ds->h : textPoint.y + drawFont.header.charHeight; +		charRow = 0; -		for (row = text_y; row < row_limit; row++, char_row++) { +		for (row = textPoint.y; row < rowLimit; row++, charRow++) {  			// Clip negative rows */  			if (row < 0) {  				continue;  			} -			output_ptr = (byte *)ds->pixels + (ds->pitch * row) + text_x; -			output_ptr_min = (byte *)ds->pixels + (ds->pitch * row) + (text_x > 0 ? text_x : 0); -			output_ptr_max = output_ptr + (ds->pitch - text_x); +			outputPointer = (byte *)ds->pixels + (ds->pitch * row) + textPoint.x; +			outputPointer_min = (byte *)ds->pixels + (ds->pitch * row) + (textPoint.x > 0 ? textPoint.x : 0); +			outputPointer_max = outputPointer + (ds->pitch - textPoint.x);  			// If character starts off the screen, jump to next character -			if (output_ptr < output_ptr_min) { +			if (outputPointer < outputPointer_min) {  				break;  			} -			c_data_ptr = draw_font->font_p + char_row * draw_font->hdr.row_length + draw_font->fce[c_code].index; +			c_dataPointer = drawFont.font + charRow * drawFont.header.rowLength + drawFont.fontCharEntry[c_code].index; -			for (c_byte = 0; c_byte < c_byte_len; c_byte++, c_data_ptr++) { +			for (c_byte = 0; c_byte < c_byte_len; c_byte++, c_dataPointer++) {  				// Check each bit, draw pixel if bit is set -				for (c_bit = 7; c_bit >= 0 && (output_ptr < output_ptr_max); c_bit--) { -					if ((*c_data_ptr >> c_bit) & 0x01) { -						*output_ptr = (byte) color; +				for (c_bit = 7; c_bit >= 0 && (outputPointer < outputPointer_max); c_bit--) { +					if ((*c_dataPointer >> c_bit) & 0x01) { +						*outputPointer = (byte) color;  					} -					output_ptr++; +					outputPointer++;  				} // end per-bit processing  			} // end per-byte processing  		} // end per-row processing  		// Advance tracking position -		text_x += draw_font->fce[c_code].tracking; +		textPoint.x += drawFont.fontCharEntry[c_code].tracking;  	} // end per-character processing +} + + +void Font::textDraw(FontId fontId, Surface *ds, const char *text, const Common::Point &point, int color, int effectColor, FontEffectFlags flags) { +	int textWidth; +	int textLength; +	int fitWidth; +	Common::Point textPoint(point); + +	textLength = strlen(text); + +	if (!(flags & kFontCentered)) { +		// Text is not centered; No formatting required +		draw(fontId, ds, text, textLength, point, color, effectColor, flags); +		return; +	} + +	// Text is centered... format output +	// Enforce minimum and maximum center points for centered text +	if (textPoint.x < TEXT_CENTERLIMIT) { +		textPoint.x = TEXT_CENTERLIMIT; +	} + +	if (textPoint.x > ds->w - TEXT_CENTERLIMIT) { +		textPoint.x = ds->w - TEXT_CENTERLIMIT; +	} + +	if (textPoint.x < (TEXT_MARGIN * 2)) { +		// Text can't be centered if it's too close to the margin +		return; +	} + +	textWidth = getStringWidth(fontId, text, textLength, flags); + +	if (textPoint.x < (ds->w / 2)) { +		// Fit to right side +		fitWidth = (textPoint.x - TEXT_MARGIN) * 2; +	} else { +		// Fit to left side +		fitWidth = ((ds->w - TEXT_MARGIN) - textPoint.x) * 2; +	} + +	if (fitWidth >= textWidth) { +		// Entire string fits, draw it +		textPoint.x = textPoint.x - (textWidth / 2); +		draw(fontId, ds, text, textLength, textPoint, color, effectColor, flags); +		return; +	} +} + +int Font::getHeight(FontId fontId, const char *text, int width, FontEffectFlags flags) { +	int textWidth; +	int textLength; +	int fitWidth; +	const char *startPointer; +	const char *searchPointer; +	const char *measurePointer; +	const char *foundPointer; +	int len; +	int w; +	const char *endPointer; +	int h; +	int wc; +	int w_total; +	int len_total; +	Common::Point textPoint; +	Common::Point textPoint2; + +	textLength = strlen(text); + +	textWidth = getStringWidth(fontId, text, textLength, flags); +	h = getHeight(fontId); +	fitWidth = width; + +	textPoint.x = (fitWidth / 2); +	textPoint.y = 0; + +	if (fitWidth >= textWidth) {		 +		return h; +	} + +	// String won't fit on one line +	w_total = 0; +	len_total = 0; +	wc = 0; + +	startPointer = text; +	measurePointer = text; +	searchPointer = text; +	endPointer = text + textLength; + +	for (;;) { +		foundPointer = strchr(searchPointer, ' '); +		if (foundPointer == NULL) { +			// Ran to the end of the buffer +			len = endPointer - measurePointer; +		} else { +			len = foundPointer - measurePointer; +		} + +		w = getStringWidth(fontId, measurePointer, len, flags); +		measurePointer = foundPointer; + +		if ((w_total + w) > fitWidth) { +			// This word won't fit +			if (wc == 0) { +				// The first word in the line didn't fit. abort +				return textPoint.y; +			} +			// Wrap what we've got and restart +			textPoint.y += h + TEXT_LINESPACING; +			w_total = 0; +			len_total = 0; +			wc = 0; +			measurePointer = searchPointer; +			startPointer = searchPointer; +		} else { +			// Word will fit ok +			w_total += w; +			len_total += len; +			wc++; +			if (foundPointer == NULL) { +				// Since word hit NULL but fit, we are done +				return textPoint.y + h; +			} +			searchPointer = measurePointer + 1; +		} +	} +} -	return SUCCESS; +void Font::textDrawRect(FontId fontId, Surface *ds, const char *text, const Common::Rect &rect, int color, int effectColor, FontEffectFlags flags) { +	int textWidth; +	int textLength; +	int fitWidth; +	const char *startPointer; +	const char *searchPointer; +	const char *measurePointer; +	const char *foundPointer; +	int len; +	int w; +	const char *endPointer; +	int h; +	int wc; +	int w_total; +	int len_total; +	Common::Point textPoint; +	Common::Point textPoint2; + +	textLength = strlen(text); + +	textWidth = getStringWidth(fontId, text, textLength, flags); +	fitWidth = rect.width(); + +	textPoint.x = rect.left + (fitWidth / 2); +	textPoint.y = rect.top; + +	if (fitWidth >= textWidth) { +	// Entire string fits, draw it +		textPoint.x -= (textWidth / 2); +		draw(fontId, ds, text, textLength, textPoint, color, effectColor, flags); +		return; +	} + +	// String won't fit on one line +	h = getHeight(fontId); +	w_total = 0; +	len_total = 0; +	wc = 0; + +	startPointer = text; +	measurePointer = text; +	searchPointer = text; +	endPointer = text + textLength; + +	for (;;) { +		foundPointer = strchr(searchPointer, ' '); +		if (foundPointer == NULL) { +			// Ran to the end of the buffer +			len = endPointer - measurePointer; +		} else { +			len = foundPointer - measurePointer; +		} + +		w = getStringWidth(fontId, measurePointer, len, flags); +		measurePointer = foundPointer; + +		if ((w_total + w) > fitWidth) { +			// This word won't fit +			if (wc == 0) { +				// The first word in the line didn't fit. abort +				return; +			} + +			// Wrap what we've got and restart +			textPoint2.x = textPoint.x - (w_total / 2); +			textPoint2.y = textPoint.y; +			draw(fontId, ds, startPointer, len_total, textPoint2, color, effectColor, flags); +			textPoint.y += h + TEXT_LINESPACING; +			if (textPoint.y >= rect.bottom) { +				return; +			} +			w_total = 0; +			len_total = 0; +			wc = 0; +			measurePointer = searchPointer; +			startPointer = searchPointer; +		} else { +			// Word will fit ok +			w_total += w; +			len_total += len; +			wc++; +			if (foundPointer == NULL) { +				// Since word hit NULL but fit, we are done +				textPoint2.x = textPoint.x - (w_total / 2); +				textPoint2.y = textPoint.y; +				draw(fontId, ds, startPointer, len_total, textPoint2, color, +					effectColor, flags); +				return; +			} +			searchPointer = measurePointer + 1; +		} +	}  }  } // End of namespace Saga diff --git a/saga/font.h b/saga/font.h index 5e1043aae4..5b5963b9b4 100644 --- a/saga/font.h +++ b/saga/font.h @@ -26,6 +26,7 @@  #ifndef SAGA_FONT_H__  #define SAGA_FONT_H__ +#include "saga/list.h"  #include "saga/gfx.h"  namespace Saga { @@ -48,80 +49,98 @@ namespace Saga {  #define SAGA_FONT_HEADER_LEN 6 -enum FONT_ID { -	SMALL_FONT_ID, -	MEDIUM_FONT_ID, -	BIG_FONT_ID +#define TEXT_CENTERLIMIT 50 +#define TEXT_MARGIN 10 +#define TEXT_LINESPACING 2 + +struct TextListEntry { +	int display; +//	int id; +	Common::Point point; +	int color; +	int effectColor; +	FontEffectFlags flags; +	FontId fontId; +	const char *text; +	TextListEntry() { +		memset(this, 0, sizeof(*this));  +	}  }; -enum FONT_EFFECT_FLAGS { -	FONT_NORMAL   = 0, -	FONT_OUTLINE  = 1 << 0, -	FONT_SHADOW   = 1 << 1, -	FONT_BOLD     = 1 << 2, -	FONT_CENTERED = 1 << 3, -	FONT_DONTMAP  = 1 << 4 +class TextList: public SortedList<TextListEntry> { +public: + +	TextListEntry *addEntry(const TextListEntry &entry) { +		return pushBack(entry).operator->(); +	}  }; -struct FONT_HEADER { -	int c_height; -	int c_width; -	int row_length; + +struct FontHeader { +	int charHeight; +	int charWidth; +	int rowLength;  }; -struct FONT_CHAR_ENTRY { +struct FontCharEntry {  	int index; -	int byte_width; +	int byteWidth;  	int width;  	int flag;  	int tracking;  }; -struct FONT_STYLE { -	FONT_HEADER hdr; -	FONT_CHAR_ENTRY fce[256]; -	byte *font_free_p; -	byte *font_p; +struct FontStyle { +	FontHeader header; +	FontCharEntry fontCharEntry[256]; +	byte *font;  }; -struct FONT { -	uint32 font_rn; -	int font_id; - -	int normal_loaded; -	FONT_STYLE *normal; -	int outline_loaded; -	FONT_STYLE *outline; - -	byte *res_data; -	size_t res_len; +struct FontData { +	FontStyle normal; +	FontStyle outline;  };  class Font {   public:  	Font(SagaEngine *vm);  	~Font(void); -	int draw(int font_id, Surface *ds, const char *draw_str, size_t draw_str_len, -				  int text_x, int text_y, int color, int effect_color, int flags); -	int getStringWidth(int font_id, const char *test_str, size_t test_str_ct, int flags); -	int getHeight(int font_id); - +	int getStringWidth(FontId fontId, const char *text, size_t count, FontEffectFlags flags); +	int getHeight(FontId fontId); +	int getHeight(FontId fontId, const char *text, int width, FontEffectFlags flags); + +	void textDraw(FontId fontId, Surface *ds, const char *string, const Common::Point &point, int color, int effectColor, FontEffectFlags flags); +	void textDrawRect(FontId fontId, Surface *ds, const char *text, const Common::Rect &rect, int color, int effectColor, FontEffectFlags flags); +	 +	void validate(FontId fontId) { +		if ((fontId < 0) || (fontId >= _loadedFonts)) { +			error("Font::validate: Invalid font id."); +		} +	}   private: -	int loadFont(uint32 fontResourceId); -	FONT_STYLE *createOutline(FONT_STYLE * src_font); -	int outFont(FONT_STYLE *font, Surface *ds, const char *draw_str, size_t draw_str_ct, -				int text_x, int text_y, int color, int flags); -	int getByteLen(int num_bits); +	void loadFont(uint32 fontResourceId); +	void createOutline(FontData *font); +	void draw(FontId fontId, Surface *ds, const char *text, size_t count, const Common::Point &point, int color, int effectColor, FontEffectFlags flags); +	void outFont(const FontStyle &drawFont, Surface *ds, const char *text, size_t count, const Common::Point &point, int color, FontEffectFlags flags); +	int getByteLen(int numBits) const { +		int byteLength = numBits / 8; + +		if (numBits % 8) { +			byteLength++; +		} + +		return byteLength; +	} +  	static const int _charMap[256];  	SagaEngine *_vm;  	bool _initialized; -	RSCFILE_CONTEXT *_fontContext; -	int _nFonts; -	FONT **_fonts; +	int _loadedFonts; +	FontData **_fonts;  };  } // End of namespace Saga diff --git a/saga/image.cpp b/saga/image.cpp index 379eae2cfc..2ca190c266 100644 --- a/saga/image.cpp +++ b/saga/image.cpp @@ -48,7 +48,7 @@ static int granulate(int value, int granularity) {  int SagaEngine::decodeBGImage(const byte *image_data, size_t image_size,  					byte **output_buf, size_t *output_buf_len, int *w, int *h) { -	IMAGE_HEADER hdr; +	ImageHeader hdr;  	int modex_height;  	const byte *RLE_data_ptr;  	size_t RLE_data_len; diff --git a/saga/interface.cpp b/saga/interface.cpp index 286e8460eb..cd3570ca58 100644 --- a/saga/interface.cpp +++ b/saga/interface.cpp @@ -644,16 +644,20 @@ void Interface::drawPanelText(Surface *ds, InterfacePanel *panel, PanelButton *p  	const char *text;  	int textWidth;  	Rect rect; +	Point textPoint;  	text = _vm->getTextString(panelButton->id);  	panel->calcPanelButtonRect(panelButton, rect);  	if (panelButton->xOffset < 0) { -		textWidth = _vm->_font->getStringWidth(MEDIUM_FONT_ID, text, 0, 0); +		textWidth = _vm->_font->getStringWidth(kMediumFont, text, 0, kFontNormal);  		rect.left += 2 + (panel->imageWidth - 1 - textWidth) / 2;  	} -	_vm->_font->draw(MEDIUM_FONT_ID, ds, text, 0, rect.left , rect.top + 1, -		_vm->getDisplayInfo().verbTextColor, _vm->getDisplayInfo().verbTextShadowColor, FONT_SHADOW); +	textPoint.x = rect.left; +	textPoint.y = rect.top + 1; +	 +	_vm->_font->textDraw(kMediumFont, ds, text, textPoint, +		_vm->getDisplayInfo().verbTextColor, _vm->getDisplayInfo().verbTextShadowColor, kFontShadow);  }  void Interface::drawOption() { @@ -667,6 +671,7 @@ void Interface::drawOption() {  	Rect rect;  	Rect rect2;  	PanelButton *panelButton; +	Point textPoint;  	backBuffer = _vm->_gfx->getBackBuffer(); @@ -696,7 +701,7 @@ void Interface::drawOption() {  	_optionPanel.calcPanelButtonRect(_optionSaveFilePanel, rect);  	rect.top++;  	rect2 = rect; -	fontHeight = _vm->_font->getHeight(SMALL_FONT_ID); +	fontHeight = _vm->_font->getHeight(kSmallFont);  	for (j = 0; j < _vm->getDisplayInfo().optionSaveFileVisible; j++) {  		bgColor = kITEColorDarkGrey0C;  		fgColor = kITEColorBrightWhite; @@ -710,8 +715,9 @@ void Interface::drawOption() {  			rect2.bottom = rect2.top + fontHeight;  			backBuffer->fillRect(rect2, bgColor);  			text = _vm->getSaveFile(idx)->name; -			_vm->_font->draw(SMALL_FONT_ID, backBuffer, text, 0, -				 rect.left + 1, rect2.top, fgColor, 0, 0); +			textPoint.x = rect.left + 1; +			textPoint.y = rect2.top; +			_vm->_font->textDraw(kSmallFont, backBuffer, text, textPoint, fgColor, 0, kFontNormal);  		}  	} @@ -918,8 +924,8 @@ bool Interface::processTextInput(uint16 ascii) {  			(ascii == ' ')) {  			if (_textInputStringLength < SAVE_TITLE_SIZE - 1) {  				ch[0] = ascii; -				tempWidth = _vm->_font->getStringWidth(SMALL_FONT_ID, ch, 0, 0); -				tempWidth += _vm->_font->getStringWidth(SMALL_FONT_ID, _textInputString, 0, 0); +				tempWidth = _vm->_font->getStringWidth(kSmallFont, ch, 0, kFontNormal); +				tempWidth += _vm->_font->getStringWidth(kSmallFont, _textInputString, 0, kFontNormal);  				if (tempWidth > _textInputMaxWidth) {  									break;  				} @@ -945,6 +951,7 @@ bool Interface::processTextInput(uint16 ascii) {  }  void Interface::drawTextInput(Surface *ds, InterfacePanel *panel, PanelButton *panelButton) { +	Point textPoint;  	Rect rect;  	char ch[2];  	int fgColor; @@ -955,24 +962,26 @@ void Interface::drawTextInput(Surface *ds, InterfacePanel *panel, PanelButton *p  	drawButtonBox(ds, rect, kEdit, _textInput);  	rect.left += 4;   	rect.top += 4; -	rect.setHeight(_vm->_font->getHeight(SMALL_FONT_ID)); +	rect.setHeight(_vm->_font->getHeight(kSmallFont));  	i = 0;	  	while ((ch[0] = _textInputString[i++]) != 0) { -		rect.setWidth(_vm->_font->getStringWidth(SMALL_FONT_ID, ch, 0, 0)); +		rect.setWidth(_vm->_font->getStringWidth(kSmallFont, ch, 0, kFontNormal));  		if ((i == _textInputPos) && _textInput) {  			fgColor = kITEColorBlack;	  			ds->fillRect(rect, kITEColorWhite);  		} else {  			fgColor = kITEColorWhite;	  		} -		_vm->_font->draw(SMALL_FONT_ID, ds, ch, 0, rect.left,  -			rect.top + 1, fgColor, 0, 0);  +		textPoint.x = rect.left; +		textPoint.y = rect.top + 1; + +		_vm->_font->textDraw(kSmallFont, ds, ch, textPoint, fgColor, 0, kFontNormal);   		rect.left += rect.width();  	}  	if (_textInput && (_textInputPos >= i)) {  		ch[0] = ' '; -		rect.setWidth(_vm->_font->getStringWidth(SMALL_FONT_ID, ch, 0, 0)); +		rect.setWidth(_vm->_font->getStringWidth(kSmallFont, ch, 0, kFontNormal));  		ds->fillRect(rect, kITEColorWhite);  	}  } @@ -1141,7 +1150,7 @@ void Interface::handleOptionClick(const Point& mousePoint) {  	} else {  		if (_optionPanel.currentButton == _optionSaveFilePanel) {  			_optionPanel.calcPanelButtonRect(_optionSaveFilePanel, rect); -			_optionSaveFileTitleNumber = (mousePoint.y - rect.top) / (_vm->_font->getHeight(SMALL_FONT_ID) + 1); +			_optionSaveFileTitleNumber = (mousePoint.y - rect.top) / (_vm->_font->getHeight(kSmallFont) + 1);  			if (_optionSaveFileTitleNumber >= _vm->getDisplayInfo().optionSaveFileVisible) {  				_optionSaveFileTitleNumber = _vm->getDisplayInfo().optionSaveFileVisible - 1; @@ -1315,8 +1324,8 @@ void Interface::update(const Point& mousePoint, int updateFlag) {  void Interface::drawStatusBar() {  	Surface *backBuffer;  	Rect rect; - -	int string_w; +	Point textPoint; +	int stringWidth;  	int color;  	backBuffer = _vm->_gfx->getBackBuffer(); @@ -1337,15 +1346,16 @@ void Interface::drawStatusBar() {  	backBuffer->drawRect(rect, _vm->getDisplayInfo().statusBGColor); -	string_w = _vm->_font->getStringWidth(SMALL_FONT_ID, _statusText, 0, 0); +	stringWidth = _vm->_font->getStringWidth(kSmallFont, _statusText, 0, kFontNormal);  	if (_statusOnceColor == -1)  		color = _vm->getDisplayInfo().statusTextColor;  	else  		color = _statusOnceColor; -	_vm->_font->draw(SMALL_FONT_ID, backBuffer, _statusText, 0, _vm->getDisplayInfo().statusXOffset + (_vm->getDisplayInfo().statusWidth - string_w) / 2, -			_vm->getDisplayInfo().statusYOffset + _vm->getDisplayInfo().statusTextY, color, 0, 0); +	textPoint.x = _vm->getDisplayInfo().statusXOffset + (_vm->getDisplayInfo().statusWidth - stringWidth) / 2; +	textPoint.y = _vm->getDisplayInfo().statusYOffset + _vm->getDisplayInfo().statusTextY; +	_vm->_font->textDraw(kSmallFont, backBuffer, _statusText, textPoint, color, 0, kFontNormal);  	if (_saveReminderState > 0) {  		rect.left = _vm->getDisplayInfo().saveReminderXOffset; @@ -1701,8 +1711,8 @@ void Interface::drawPanelButtonText(Surface *ds, InterfacePanel *panel, PanelBut  	}  	text = _vm->getTextString(textId); -	textWidth = _vm->_font->getStringWidth(MEDIUM_FONT_ID, text, 0, 0); -	textHeight = _vm->_font->getHeight(MEDIUM_FONT_ID); +	textWidth = _vm->_font->getStringWidth(kMediumFont, text, 0, kFontNormal); +	textHeight = _vm->_font->getHeight(kMediumFont);  	point.x = panel->x + panelButton->xOffset + (panelButton->width / 2) - (textWidth / 2);  	point.y = panel->y + panelButton->yOffset + (panelButton->height / 2) - (textHeight / 2); @@ -1716,8 +1726,8 @@ void Interface::drawPanelButtonText(Surface *ds, InterfacePanel *panel, PanelBut  	panel->calcPanelButtonRect(panelButton, rect);  	drawButtonBox(ds, rect, kButton, panelButton->state > 0); -	_vm->_font->draw(MEDIUM_FONT_ID, ds, text, 0, point.x , point.y,  -		textColor, _vm->getDisplayInfo().verbTextShadowColor, FONT_SHADOW); +	_vm->_font->textDraw(kMediumFont, ds, text, point,  +		textColor, _vm->getDisplayInfo().verbTextShadowColor, kFontShadow);  }  void Interface::drawPanelButtonArrow(Surface *ds, InterfacePanel *panel, PanelButton *panelButton) { @@ -1753,12 +1763,12 @@ void Interface::drawVerbPanelText(Surface *ds, PanelButton *panelButton, int tex  	text = _vm->getTextString(textId); -	textWidth = _vm->_font->getStringWidth(SMALL_FONT_ID, text, 0, 0); +	textWidth = _vm->_font->getStringWidth(kSmallFont, text, 0, kFontNormal);  	point.x = _mainPanel.x + panelButton->xOffset + 1 + (panelButton->width - 1 - textWidth) / 2;  	point.y = _mainPanel.y + panelButton->yOffset + 1; -	_vm->_font->draw(SMALL_FONT_ID, ds, text, 0, point.x , point.y, textColor, textShadowColor, (textShadowColor != 0) ? FONT_SHADOW : 0); +	_vm->_font->textDraw(kSmallFont, ds, text, point, textColor, textShadowColor, (textShadowColor != 0) ? kFontShadow : kFontNormal);  } @@ -1804,10 +1814,9 @@ bool Interface::converseAddText(const char *text, int replyId, byte replyFlags,  		for (i = len; i >= 0; i--) {  			c = _converseWorkString[i]; -			if ((c == ' ' || c == '\0') -				&& _vm->_font->getStringWidth(SMALL_FONT_ID, _converseWorkString, i, 0)  -					<= CONVERSE_MAX_TEXT_WIDTH) +			if ((c == ' ' || c == '\0') && (_vm->_font->getStringWidth(kSmallFont, _converseWorkString, i, kFontNormal) <= CONVERSE_MAX_TEXT_WIDTH)) {  				break; +			}				  		}  		if (i < 0) {  			return true; @@ -1877,6 +1886,7 @@ void Interface::converseDisplayTextLines(Surface *ds) {  		(char)0xb7, 0   	};  	Rect rect(8, CONVERSE_TEXT_LINES * CONVERSE_TEXT_HEIGHT); +	Point textPoint;  	assert(_conversePanel.buttonsCount >= 6); @@ -1910,11 +1920,14 @@ void Interface::converseDisplayTextLines(Surface *ds) {  		str = _converseText[relPos].text;  		if (_converseText[relPos].textNum == 0) { // first entry -			_vm->_font->draw(SMALL_FONT_ID, ds, bullet, 1, -				rect.left - 6, rect.top, bulletForegnd, bulletBackgnd, FONT_SHADOW | FONT_DONTMAP); +			textPoint.x = rect.left - 6; +			textPoint.y = rect.top; + +			_vm->_font->textDraw(kSmallFont, ds, bullet, textPoint, bulletForegnd, bulletBackgnd, (FontEffectFlags)(kFontShadow | kFontDontmap));  		} -		_vm->_font->draw(SMALL_FONT_ID, ds, str, strlen(str), -			rect.left + 1, rect.top, foregnd, kITEColorBlack, FONT_SHADOW); +		textPoint.x = rect.left + 1; +		textPoint.y = rect.top; +		_vm->_font->textDraw(kSmallFont, ds, str, textPoint, foregnd, kITEColorBlack, kFontShadow);  	}  	if (_converseStartPos != 0) { diff --git a/saga/ite_introproc.cpp b/saga/ite_introproc.cpp index 7f3b0cd3ba..5da6b42cbe 100644 --- a/saga/ite_introproc.cpp +++ b/saga/ite_introproc.cpp @@ -32,7 +32,6 @@  #include "saga/font.h"  #include "saga/rscfile_mod.h"  #include "saga/sndres.h" -#include "saga/text.h"  #include "saga/palanim.h"  #include "saga/music.h" @@ -86,29 +85,29 @@ int Scene::ITEStartProc() {  }  EVENT *Scene::ITEQueueDialogue(EVENT *q_event, int n_dialogues, const INTRO_DIALOGUE dialogue[]) { -	TEXTLIST_ENTRY text_entry; -	TEXTLIST_ENTRY *entry_p; +	TextListEntry textEntry; +	TextListEntry *entry;  	EVENT event;  	int voice_len;  	int i;  	// Queue narrator dialogue list -	text_entry.color = 255; -	text_entry.effect_color = 0; -	text_entry.text_x = 320 / 2; -	text_entry.text_y = (_vm->getFeatures() & GF_LANG_DE) ? INTRO_DE_CAPTION_Y : INTRO_CAPTION_Y; -	text_entry.font_id = MEDIUM_FONT_ID; -	text_entry.flags = FONT_OUTLINE | FONT_CENTERED; +	textEntry.color = 255; +	textEntry.effectColor = 0; +	textEntry.point.x = 320 / 2; +	textEntry.point.y = (_vm->getFeatures() & GF_LANG_DE) ? INTRO_DE_CAPTION_Y : INTRO_CAPTION_Y; +	textEntry.fontId = kMediumFont; +	textEntry.flags = (FontEffectFlags)(kFontOutline | kFontCentered);  	for (i = 0; i < n_dialogues; i++) { -		text_entry.string = dialogue[i].i_str; -		entry_p = _vm->textAddEntry(_textList, &text_entry); +		textEntry.text = dialogue[i].i_str; +		entry = _vm->_scene->_textList.addEntry(textEntry);  		// Display text  		event.type = ONESHOT_EVENT;  		event.code = TEXT_EVENT;  		event.op = EVENT_DISPLAY; -		event.data = entry_p; +		event.data = entry;  		event.time = (i == 0) ? 0 : VOICE_PAD;  		q_event = _vm->_events->chain(q_event, &event); @@ -131,7 +130,7 @@ EVENT *Scene::ITEQueueDialogue(EVENT *q_event, int n_dialogues, const INTRO_DIAL  		event.type = ONESHOT_EVENT;  		event.code = TEXT_EVENT;  		event.op = EVENT_REMOVE; -		event.data = entry_p; +		event.data = entry;  		event.time = voice_len;  		q_event = _vm->_events->chain(q_event, &event); @@ -182,7 +181,7 @@ EVENT *Scene::ITEQueueCredits(int delta_time, int duration, int n_credits, const  	int line_spacing = 0;  	int paragraph_spacing; -	int font = 0; +	FontId font = kSmallFont;  	int i;  	int n_paragraphs = 0; @@ -199,12 +198,12 @@ EVENT *Scene::ITEQueueCredits(int delta_time, int duration, int n_credits, const  		switch (credits[i].type) {  		case kCHeader: -			font = SMALL_FONT_ID; +			font = kSmallFont;  			line_spacing = 4;  			n_paragraphs++;  			break;  		case kCText: -			font = MEDIUM_FONT_ID; +			font = kMediumFont;  			line_spacing = 2;  			break;  		default: @@ -219,15 +218,15 @@ EVENT *Scene::ITEQueueCredits(int delta_time, int duration, int n_credits, const  	int y = paragraph_spacing; -	TEXTLIST_ENTRY text_entry; -	TEXTLIST_ENTRY *entry_p; +	TextListEntry textEntry; +	TextListEntry *entry;  	EVENT event;  	EVENT *q_event = NULL; -	text_entry.color = 255; -	text_entry.effect_color = 0; -	text_entry.flags = FONT_OUTLINE | FONT_CENTERED; -	text_entry.text_x = 160; +	textEntry.color = 255; +	textEntry.effectColor = 0; +	textEntry.flags = (FontEffectFlags)(kFontOutline | kFontCentered); +	textEntry.point.x = 160;  	for (i = 0; i < n_credits; i++) {  		if (credits[i].lang != lang && credits[i].lang != UNK_LANG) { @@ -240,29 +239,29 @@ EVENT *Scene::ITEQueueCredits(int delta_time, int duration, int n_credits, const  		switch (credits[i].type) {  		case kCHeader: -			font = SMALL_FONT_ID; +			font = kSmallFont;  			line_spacing = 4;  			y += paragraph_spacing;  			break;  		case kCText: -			font = MEDIUM_FONT_ID; +			font = kMediumFont;  			line_spacing = 2;  			break;  		default:  			break;  		} -		text_entry.string = credits[i].string; -		text_entry.font_id = font; -		text_entry.text_y = y; +		textEntry.text = credits[i].string; +		textEntry.fontId = font; +		textEntry.point.y = y; -		entry_p = _vm->textAddEntry(_textList, &text_entry); +		entry = _vm->_scene->_textList.addEntry(textEntry);  		// Display text  		event.type = ONESHOT_EVENT;  		event.code = TEXT_EVENT;  		event.op = EVENT_DISPLAY; -		event.data = entry_p; +		event.data = entry;  		event.time = delta_time;  		q_event = _vm->_events->queue(&event); @@ -271,7 +270,7 @@ EVENT *Scene::ITEQueueCredits(int delta_time, int duration, int n_credits, const  		event.type = ONESHOT_EVENT;  		event.code = TEXT_EVENT;  		event.op = EVENT_REMOVE; -		event.data = entry_p; +		event.data = entry;  		event.time = duration;  		q_event = _vm->_events->chain(q_event, &event); diff --git a/saga/module.mk b/saga/module.mk index 3e28da3163..0f648fea48 100644 --- a/saga/module.mk +++ b/saga/module.mk @@ -28,7 +28,6 @@ MODULE_OBJS := \  	saga/sndres.o \  	saga/sprite.o \  	saga/sthread.o \ -	saga/text.o \  	saga/input.o \  	saga/music.o \  	saga/sound.o diff --git a/saga/objectmap.cpp b/saga/objectmap.cpp index 2122bf72f3..32798e16b9 100644 --- a/saga/objectmap.cpp +++ b/saga/objectmap.cpp @@ -219,6 +219,7 @@ void ObjectMap::draw(Surface *ds, const Point& testPoint, int color, int color2)  	int hitZoneIndex;  	char txtBuf[32];  	Point pickPoint; +	Point textPoint;  	Location pickLocation;  	pickPoint = testPoint;  	if (_vm->_scene->getFlags() & kSceneFlagISO) { @@ -236,9 +237,9 @@ void ObjectMap::draw(Surface *ds, const Point& testPoint, int color, int color2)  	if (hitZoneIndex != -1) {		  		snprintf(txtBuf, sizeof(txtBuf), "hitZone %d", hitZoneIndex); -		_vm->_font->draw(SMALL_FONT_ID, ds, txtBuf, 0, 2, 2, -			kITEColorBrightWhite, kITEColorBlack, FONT_OUTLINE); - +		textPoint.x = 2; +		textPoint.y = 2; +		_vm->_font->textDraw(kSmallFont, ds, txtBuf, textPoint, kITEColorBrightWhite, kITEColorBlack, kFontOutline);  	}  } diff --git a/saga/puzzle.cpp b/saga/puzzle.cpp index 3d932907e4..44cfde0a6c 100644 --- a/saga/puzzle.cpp +++ b/saga/puzzle.cpp @@ -165,6 +165,10 @@ Puzzle::Puzzle(SagaEngine *vm) : _vm(vm), _solved(false), _active(false) {  	_puzzlePiece = -1;  	_newPuzzle = true;  	_sliding = false; +	_hintBox.left = 70; +	_hintBox.top = 105; +	_hintBox.setWidth(240); +	_hintBox.setHeight(30);  	initPieceInfo( 0, 268,  18,  0, 0,  0 + PUZZLE_X_OFFSET,   0 + PUZZLE_Y_OFFSET, 0, 3,  		  Point(0, 1),  Point(0, 62), Point(15, 31), Point(0, 0), Point(0, 0), Point(0,0)); @@ -480,7 +484,7 @@ void Puzzle::solicitHint(void) {  		if (_hintOffer >= NUM_SOLICIT_REPLIES)  			_hintOffer = 0; -		_vm->_actor->nonActorSpeech(&solicitStr[_lang][i], 1, 0); +		_vm->_actor->nonActorSpeech(_hintBox, &solicitStr[_lang][i], 1, 0);  		//	Determine which of the journeymen will offer then  		//	hint, and then show that character's portrait. @@ -503,7 +507,7 @@ void Puzzle::solicitHint(void) {  	case kRQHintRequested:  		i = _vm->_rnd.getRandomNumber(NUM_SAKKA - 1); -		_vm->_actor->nonActorSpeech(&sakkaStr[_lang][i], 1, 0); +		_vm->_actor->nonActorSpeech(_hintBox, &sakkaStr[_lang][i], 1, 0);  		_vm->_interface->setRightPortrait(RID_ITE_SAKKA_APPRAISING); @@ -520,7 +524,7 @@ void Puzzle::solicitHint(void) {  	case kRQHintRequestedStage2:  		if (_vm->_rnd.getRandomNumber(1)) {			//	Skip Reply part  			i = _vm->_rnd.getRandomNumber(NUM_WHINES - 1); -			_vm->_actor->nonActorSpeech(&whineStr[_lang][i], 1, 0); +			_vm->_actor->nonActorSpeech(_hintBox, &whineStr[_lang][i], 1, 0);  		}  		_vm->_interface->setRightPortrait(_hintGiver); @@ -588,7 +592,7 @@ void Puzzle::giveHint(void) {  	_vm->_actor->setSpeechColor(1, kITEColorBlack);  	if (_hintCount < 3) { -		_vm->_actor->nonActorSpeech(&hintStr[_lang][_hintCount], 1, 0 ); +		_vm->_actor->nonActorSpeech(_hintBox, &hintStr[_lang][_hintCount], 1, 0 );  	} else {  		int piece = 0; @@ -607,11 +611,11 @@ void Puzzle::giveHint(void) {  			const char *hintPtr = hintBuf;  			sprintf(hintBuf, optionsStr[_lang][kROHint], pieceNames[piece]); -			_vm->_actor->nonActorSpeech(&hintPtr, 1, 0); +			_vm->_actor->nonActorSpeech(_hintBox, &hintPtr, 1, 0);  		}  		else {  				//	If no pieces are in the wrong place -			_vm->_actor->nonActorSpeech(&hintStr[_lang][3], 1, 0); +			_vm->_actor->nonActorSpeech(_hintBox, &hintStr[_lang][3], 1, 0);  		}  	}  	_hintCount++; diff --git a/saga/puzzle.h b/saga/puzzle.h index 0b61c00bc3..6210c5c389 100644 --- a/saga/puzzle.h +++ b/saga/puzzle.h @@ -102,6 +102,7 @@ private:  	PieceInfo _pieceInfo[PUZZLE_PIECES];  	int _slidePointX, _slidePointY; +	Rect _hintBox;  };  } // End of namespace Saga diff --git a/saga/render.cpp b/saga/render.cpp index 8083ed2431..bd73296ff8 100644 --- a/saga/render.cpp +++ b/saga/render.cpp @@ -32,7 +32,6 @@  #include "saga/puzzle.h"  #include "saga/render.h"  #include "saga/scene.h" -#include "saga/text.h"  #include "common/timer.h"  #include "common/system.h" @@ -40,6 +39,7 @@  namespace Saga {  const char *test_txt = "The quick brown fox jumped over the lazy dog. She sells sea shells down by the sea shore."; +const char *pauseString = "PAWS GAME";  Render::Render(SagaEngine *vm, OSystem *system) {  	_vm = vm; @@ -69,9 +69,9 @@ bool Render::initialized() {  void Render::drawScene() {  	Surface *backBufferSurface; -	char txt_buf[20]; -	int fps_width; -	Point mouse_pt; +	char txtBuffer[20]; +	Point mousePoint; +	Point textPoint;  	assert(_initialized); @@ -80,7 +80,7 @@ void Render::drawScene() {  	backBufferSurface = _vm->_gfx->getBackBuffer();  	// Get mouse coordinates -	mouse_pt = _vm->mousePos(); +	mousePoint = _vm->mousePos();  	if (/*_vm->_interface->getMode() != kPanelPlacard*/!(_flags & (RF_PLACARD | RF_MAP))) {  		// Display scene background @@ -88,7 +88,7 @@ void Render::drawScene() {  		if (_vm->_interface->getFadeMode() != kFadeOut) {  			if (_vm->_puzzle->isActive()) { -				_vm->_puzzle->movePiece(mouse_pt); +				_vm->_puzzle->movePiece(mousePoint);  				_vm->_actor->drawSpeech();  			} else {  				// Draw queued actors @@ -98,9 +98,9 @@ void Render::drawScene() {  			if (getFlags() & RF_OBJECTMAP_TEST) {  				if (_vm->_scene->_objectMap) -					_vm->_scene->_objectMap->draw(backBufferSurface, mouse_pt, kITEColorBrightWhite, kITEColorBlack); +					_vm->_scene->_objectMap->draw(backBufferSurface, mousePoint, kITEColorBrightWhite, kITEColorBlack);  				if (_vm->_scene->_actionMap) -					_vm->_scene->_actionMap->draw(backBufferSurface, mouse_pt, kITEColorRed, kITEColorBlack); +					_vm->_scene->_actionMap->draw(backBufferSurface, mousePoint, kITEColorRed, kITEColorBlack);  			}  			if (getFlags() & RF_ACTOR_PATH_TEST) {  				_vm->_actor->drawPathTest(); @@ -129,35 +129,36 @@ void Render::drawScene() {  	}  	// Draw queued text strings -	_vm->textDrawList(_vm->_scene->_textList, backBufferSurface); +	_vm->_scene->drawTextList(backBufferSurface);  	// Handle user input  	_vm->processInput();  	// Display rendering information  	if (_flags & RF_SHOW_FPS) { -		sprintf(txt_buf, "%d", _fps); -		fps_width = _vm->_font->getStringWidth(SMALL_FONT_ID, txt_buf, 0, FONT_NORMAL); -		_vm->_font->draw(SMALL_FONT_ID, backBufferSurface, txt_buf, 0, backBufferSurface->w - fps_width, 2, -					kITEColorBrightWhite, kITEColorBlack, FONT_OUTLINE); +		sprintf(txtBuffer, "%d", _fps); +		textPoint.x = backBufferSurface->w - _vm->_font->getStringWidth(kSmallFont, txtBuffer, 0, kFontOutline);  +		textPoint.y = 2; + +		_vm->_font->textDraw(kSmallFont, backBufferSurface, txtBuffer, textPoint, kITEColorBrightWhite, kITEColorBlack, kFontOutline);  	}  	// Display "paused game" message, if applicable  	if (_flags & RF_RENDERPAUSE) { -		int msg_len = strlen(PAUSEGAME_MSG); -		int msg_w = _vm->_font->getStringWidth(BIG_FONT_ID, PAUSEGAME_MSG, msg_len, FONT_OUTLINE); -		_vm->_font->draw(BIG_FONT_ID, backBufferSurface, PAUSEGAME_MSG, msg_len, -				(backBufferSurface->w - msg_w) / 2, 90, kITEColorBrightWhite, kITEColorBlack, FONT_OUTLINE); +		textPoint.x = (backBufferSurface->w - _vm->_font->getStringWidth(kBigFont, pauseString, 0, kFontOutline)) / 2;  +		textPoint.y = 90; + +		_vm->_font->textDraw(kBigFont, backBufferSurface, pauseString, textPoint, kITEColorBrightWhite, kITEColorBlack, kFontOutline);  	}  	// Update user interface - -	_vm->_interface->update(mouse_pt, UPDATE_MOUSEMOVE); +	_vm->_interface->update(mousePoint, UPDATE_MOUSEMOVE);  	// Display text formatting test, if applicable  	if (_flags & RF_TEXT_TEST) { -		_vm->textDraw(MEDIUM_FONT_ID, backBufferSurface, test_txt, mouse_pt.x, mouse_pt.y, -				kITEColorBrightWhite, kITEColorBlack, FONT_OUTLINE | FONT_CENTERED); +		Rect rect(mousePoint.x, mousePoint.y, mousePoint.x + 100, mousePoint.y + 50); +		_vm->_font->textDrawRect(kMediumFont, backBufferSurface, test_txt, rect, +				kITEColorBrightWhite, kITEColorBlack, (FontEffectFlags)(kFontOutline | kFontCentered));  	}  	// Display palette test, if applicable diff --git a/saga/render.h b/saga/render.h index dee9d3579a..99d8d7b5a9 100644 --- a/saga/render.h +++ b/saga/render.h @@ -30,7 +30,6 @@  namespace Saga { -#define PAUSEGAME_MSG "PAWS GAME"  enum RENDER_FLAGS {  	RF_SHOW_FPS = (1 << 0),  	RF_PALETTE_TEST = (1 << 1), diff --git a/saga/saga.h b/saga/saga.h index c845fe893e..1719e40409 100644 --- a/saga/saga.h +++ b/saga/saga.h @@ -33,7 +33,6 @@  #include "common/stream.h"  #include "common/rect.h" -#include "saga/text.h"  #include "saga/gfx.h"  #include "saga/list.h" @@ -215,7 +214,7 @@ enum TextStringIds {  	kTextEnterSaveGameName  }; -struct IMAGE_HEADER { +struct ImageHeader {  	int width;  	int height;  }; @@ -311,6 +310,21 @@ enum GameFeatures {  	GF_CD_FX             = 1 << 6  }; +enum FontId { +	kSmallFont, +	kMediumFont, +	kBigFont +}; + +enum FontEffectFlags { +	kFontNormal   = 0, +	kFontOutline  = 1 << 0, +	kFontShadow   = 1 << 1, +	kFontBold     = 1 << 2, +	kFontCentered = 1 << 3, +	kFontDontmap  = 1 << 4 +}; +  struct GameSoundInfo {  	int res_type;  	long freq; @@ -574,17 +588,6 @@ public:  	const char *getObjectName(uint16 objectId);  public: -	TEXTLIST *textCreateList(); -	void textDestroyList(TEXTLIST *textlist); -	void textClearList(TEXTLIST *textlist); -	int textDrawList(TEXTLIST *textlist, Surface *ds); -	TEXTLIST_ENTRY *textAddEntry(TEXTLIST *textlist, TEXTLIST_ENTRY *entry); -	int textDeleteEntry(TEXTLIST *textlist, TEXTLIST_ENTRY *entry); -	int textSetDisplay(TEXTLIST_ENTRY *entry, int val); -	int textDraw(int font_id, Surface *ds, const char *string, int text_x, int text_y, int color, -				  int effect_color, int flags); -	int textProcessList(TEXTLIST *textlist, long ms); -  	int processInput(void);  	const Point &mousePos() const {  		return _mousePos; diff --git a/saga/scene.cpp b/saga/scene.cpp index 753a758dbf..5f738b20e7 100644 --- a/saga/scene.cpp +++ b/saga/scene.cpp @@ -36,7 +36,6 @@  #include "saga/render.h"  #include "saga/rscfile_mod.h"  #include "saga/script.h" -#include "saga/text.h"  #include "saga/sound.h"  #include "saga/music.h" @@ -95,15 +94,7 @@ Scene::Scene(SagaEngine *vm) : _vm(vm), _initialized(false) {  	debug(3, "First scene set to %d.", _firstScene); -	debug(3, "LUT has %d entries.", _sceneCount); - -	// Create scene module text list -	_textList = _vm->textCreateList(); - -	if (_textList == NULL) { -		warning("Scene::Scene(): Error: Couldn't create scene text list"); -		return; -	} +	debug(3, "LUT has %d entries.", _sceneCount);		  	_sceneLoaded = false;  	_sceneNumber = 0; @@ -129,6 +120,18 @@ Scene::~Scene() {  	}  } +void Scene::drawTextList(Surface *ds) { +	TextListEntry *entry; + +	for (TextList::iterator textIterator = _textList.begin(); textIterator != _textList.end(); ++textIterator) { +		entry = (TextListEntry *)textIterator.operator->(); +		if (entry->display != 0) { +			_vm->_font->textDraw(entry->fontId, ds, entry->text, entry->point, entry->color, entry->effectColor, entry->flags); +		} +	} +} + +  void Scene::startScene() {  	SceneQueueList::iterator queueIterator;  	LoadSceneParams *sceneQueue; @@ -953,7 +956,7 @@ void Scene::endScene() {  	_vm->_isoMap->freeMem();  	_vm->_events->clearList(); -	_vm->textClearList(_textList); +	_textList.clear();  	_sceneLoaded = false; diff --git a/saga/scene.h b/saga/scene.h index 2233b05874..ed621b649f 100644 --- a/saga/scene.h +++ b/saga/scene.h @@ -26,7 +26,7 @@  #ifndef SAGA_SCENE_H  #define SAGA_SCENE_H -#include "saga/text.h" +#include "saga/font.h"  #include "saga/list.h"  #include "saga/actor.h" @@ -263,6 +263,7 @@ class Scene {  	int getOutsetSceneNumber() const { return _outsetSceneNumber; }  	int currentSceneResourceId() const { return _sceneResourceId; } +	void drawTextList(Surface *ds);   private:  	void loadScene(LoadSceneParams *loadSceneParams);  	int loadSceneDescriptor(uint32 res_number); @@ -301,7 +302,7 @@ class Scene {  	ObjectMap *_objectMap;  	SceneEntryList _entryList;  	StringsTable _sceneStrings; -	TEXTLIST *_textList; +	TextList _textList;   private:  	int IHNMStartProc(); diff --git a/saga/script.h b/saga/script.h index 80cfc78ab5..d40b59cf21 100644 --- a/saga/script.h +++ b/saga/script.h @@ -26,7 +26,7 @@  #ifndef SAGA_SCRIPT_H  #define SAGA_SCRIPT_H -#include "saga/text.h" +#include "saga/font.h"  #include "saga/list.h"  namespace Saga { @@ -390,6 +390,7 @@ private:  	uint16 _modulesLUTEntryLen;  	ModuleData *_modules;  	int _modulesCount; +	TextListEntry *_placardTextEntry;  protected:  	friend class SagaEngine; @@ -424,7 +425,6 @@ public:  	int _dbg_singlestep;  	int _dbg_dostep;  	ScriptThread *_dbg_thread; -	TEXTLIST_ENTRY *_dbg_txtentry;  public:  	ScriptThread *createThread(uint16 scriptModuleNumber, uint16 scriptEntryPointNumber); diff --git a/saga/sfuncs.cpp b/saga/sfuncs.cpp index 626791c60a..5ec1fa45dd 100644 --- a/saga/sfuncs.cpp +++ b/saga/sfuncs.cpp @@ -1186,7 +1186,6 @@ void Script::sfSimulSpeech2(SCRIPTFUNC_PARAMS) {  	thread->wait(kWaitTypeSpeech);  } -static TEXTLIST_ENTRY *placardTextEntry;  // Script function #48 (0x30)  // Param1: string rid @@ -1253,22 +1252,22 @@ void Script::sfPlacard(SCRIPTFUNC_PARAMS) {  	// It doesn't end up in exactly the same spot as the original did it,  	// but it's close enough for now at least. -	TEXTLIST_ENTRY text_entry; +	TextListEntry textEntry; -	text_entry.color = kITEColorBrightWhite; -	text_entry.effect_color = kITEColorBlack; -	text_entry.text_x = _vm->getDisplayWidth() / 2; -	text_entry.text_y = (_vm->getSceneHeight() - _vm->_font->getHeight(MEDIUM_FONT_ID)) / 2; -	text_entry.font_id = MEDIUM_FONT_ID; -	text_entry.flags = FONT_OUTLINE | FONT_CENTERED; -	text_entry.string = thread->_strings->getString(stringId); +	textEntry.color = kITEColorBrightWhite; +	textEntry.effectColor = kITEColorBlack; +	textEntry.point.x = _vm->getDisplayWidth() / 2; +	textEntry.point.y = (_vm->getSceneHeight() - _vm->_font->getHeight(kMediumFont)) / 2; +	textEntry.fontId = kMediumFont; +	textEntry.flags = (FontEffectFlags)(kFontOutline | kFontCentered); +	textEntry.text = thread->_strings->getString(stringId); -	placardTextEntry = _vm->textAddEntry(_vm->_scene->_textList, &text_entry); +	_placardTextEntry = _vm->_scene->_textList.addEntry(textEntry);  	event.type = ONESHOT_EVENT;  	event.code = TEXT_EVENT;  	event.op = EVENT_DISPLAY; -	event.data = placardTextEntry; +	event.data = _placardTextEntry;  	q_event = _vm->_events->chain(q_event, &event); @@ -1324,7 +1323,7 @@ void Script::sfPlacardOff(SCRIPTFUNC_PARAMS) {  	event.type = ONESHOT_EVENT;  	event.code = TEXT_EVENT;  	event.op = EVENT_REMOVE; -	event.data = placardTextEntry; +	event.data = _placardTextEntry;  	q_event = _vm->_events->chain(q_event, &event); @@ -1520,13 +1519,26 @@ void Script::sfSetActorZ(SCRIPTFUNC_PARAMS) {  void Script::sfScriptText(SCRIPTFUNC_PARAMS) {  	int16 stringId;  	int16 flags; +	Rect rect; +	int color;  	Point point; +	int width; +	const char*text;  	stringId = thread->pop();  	flags = thread->pop(); +	color = thread->pop();  	point.x = thread->pop();  	point.y = thread->pop(); -//TODO: do it!!! +	text = thread->_strings->getString(stringId); +	width = _vm->_font->getStringWidth(kMediumFont, text, 0, kFontOutline); +	rect.top = point.y - 6; +	rect.setHeight(12);	 +	rect.left = point.x - width / 2; +	rect.setWidth(width); + +	_vm->_actor->setSpeechColor(color, kITEColorBlack); +	_vm->_actor->nonActorSpeech(rect, &text, 1, flags);  }  // Script function #60 (0x3C) diff --git a/saga/sprite.cpp b/saga/sprite.cpp index 2c469a3066..58ed711493 100644 --- a/saga/sprite.cpp +++ b/saga/sprite.cpp @@ -28,7 +28,6 @@  #include "saga/scene.h"  #include "saga/rscfile_mod.h" -#include "saga/text.h"  #include "saga/font.h"  #include "saga/sprite.h"  | 
