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" |