diff options
author | Torbjörn Andersson | 2003-10-11 12:26:53 +0000 |
---|---|---|
committer | Torbjörn Andersson | 2003-10-11 12:26:53 +0000 |
commit | 02a157e745210d8986df83dd2114c2ee0ae86c88 (patch) | |
tree | 160b1cb10dbbf5ca5ea8a6ebd2f510ab6d3ee88d | |
parent | 650581eef80bcf2fbe5bb55218ae329a8673498e (diff) | |
download | scummvm-rg350-02a157e745210d8986df83dd2114c2ee0ae86c88.tar.gz scummvm-rg350-02a157e745210d8986df83dd2114c2ee0ae86c88.tar.bz2 scummvm-rg350-02a157e745210d8986df83dd2114c2ee0ae86c88.zip |
Moved the text drawing stuff into a class of its own. (Adding another
global variable which will hopefully be dealt with later.)
svn-id: r10734
-rw-r--r-- | sword2/anims.cpp | 9 | ||||
-rw-r--r-- | sword2/build_display.cpp | 10 | ||||
-rw-r--r-- | sword2/console.cpp | 8 | ||||
-rw-r--r-- | sword2/controls.cpp | 66 | ||||
-rw-r--r-- | sword2/driver/d_draw.cpp | 2 | ||||
-rw-r--r-- | sword2/maketext.cpp | 208 | ||||
-rw-r--r-- | sword2/maketext.h | 113 | ||||
-rw-r--r-- | sword2/mouse.cpp | 6 | ||||
-rw-r--r-- | sword2/resman.cpp | 10 | ||||
-rw-r--r-- | sword2/speech.cpp | 9 | ||||
-rw-r--r-- | sword2/startup.cpp | 12 | ||||
-rw-r--r-- | sword2/sword2.cpp | 9 | ||||
-rw-r--r-- | sword2/sword2.h | 6 |
13 files changed, 239 insertions, 229 deletions
diff --git a/sword2/anims.cpp b/sword2/anims.cpp index 55f014b1ed..e61826ef03 100644 --- a/sword2/anims.cpp +++ b/sword2/anims.cpp @@ -33,7 +33,7 @@ #include "bs2/defs.h" #include "bs2/header.h" #include "bs2/interpreter.h" -#include "bs2/maketext.h" // for MakeTextSprite used by FN_play_sequence ultimately +#include "bs2/maketext.h" // for makeTextSprite used by FN_play_sequence ultimately #include "bs2/object.h" #include "bs2/protocol.h" #include "bs2/resman.h" @@ -475,7 +475,7 @@ typedef struct { } _sequenceTextInfo; // keeps count of number of text lines to disaply during the sequence -uint32 sequenceTextLines = 0; +static uint32 sequenceTextLines = 0; static _sequenceTextInfo sequence_text_list[MAX_SEQUENCE_TEXT_LINES]; @@ -574,7 +574,10 @@ void CreateSequenceSpeech(_movieTextObject *sequenceText[]) { // NB. The mem block containing the text sprite is // currently FLOATING! - sequence_text_list[line].text_mem = MakeTextSprite(text + 2, 600, 255, speech_font_id); + // When rendering text over a sequence we need a + // different colour for the border. + + sequence_text_list[line].text_mem = fontRenderer.makeTextSprite(text + 2, 600, 255, g_sword2->_speechFontId, 1); // ok to close the text resource now res_man.close(text_res); diff --git a/sword2/build_display.cpp b/sword2/build_display.cpp index 60f122e641..a4c14d663d 100644 --- a/sword2/build_display.cpp +++ b/sword2/build_display.cpp @@ -250,7 +250,7 @@ void Build_display(void) { // text blocks // speech blocks and headup debug text - Print_text_blocs(); + fontRenderer.printTextBlocs(); // --------------------------------------------------- // menu bar & icons @@ -297,7 +297,7 @@ void Build_display(void) { spriteInfo.scale = 0; spriteInfo.scaledWidth = 0; spriteInfo.scaledHeight = 0; - spriteInfo.type = RDSPR_DISPLAYALIGN + RDSPR_NOCOMPRESSION; + spriteInfo.type = RDSPR_DISPLAYALIGN | RDSPR_NOCOMPRESSION; spriteInfo.blend = 0; spriteInfo.data = console_sprite->ad; spriteInfo.colourTable = 0; @@ -340,7 +340,7 @@ void DisplayMsg(uint8 *text, int time) { CloseMenuImmediately(); EraseBackBuffer(); - text_spr = MakeTextSprite(text, 640, 187, speech_font_id); + text_spr = fontRenderer.makeTextSprite(text, 640, 187, g_sword2->_speechFontId); frame = (_frameHeader *) text_spr->ad; @@ -354,7 +354,7 @@ void DisplayMsg(uint8 *text, int time) { spriteInfo.scale = 0; spriteInfo.scaledWidth = 0; spriteInfo.scaledHeight = 0; - spriteInfo.type = RDSPR_DISPLAYALIGN + RDSPR_NOCOMPRESSION + RDSPR_TRANS; + spriteInfo.type = RDSPR_DISPLAYALIGN | RDSPR_NOCOMPRESSION | RDSPR_TRANS; spriteInfo.blend = 0; spriteInfo.data = text_spr->ad + sizeof(_frameHeader); spriteInfo.colourTable = 0; @@ -494,7 +494,7 @@ void Process_layer(uint32 layer_number) { spriteInfo.scaledWidth = 0; spriteInfo.scaledHeight = 0; spriteInfo.h = layer_head->height; - spriteInfo.type = RDSPR_TRANS + RDSPR_RLE256FAST; + spriteInfo.type = RDSPR_TRANS | RDSPR_RLE256FAST; spriteInfo.blend = 0; spriteInfo.data = file + sizeof(_standardHeader) + layer_head->offset; spriteInfo.colourTable = 0; diff --git a/sword2/console.cpp b/sword2/console.cpp index 5f125ff117..bd43cf6662 100644 --- a/sword2/console.cpp +++ b/sword2/console.cpp @@ -36,7 +36,7 @@ uint32 console_status = 0; //0 off // LEFT IN RELEASE VERSION #include "bs2/header.h" #include "bs2/layers.h" #include "bs2/logic.h" -#include "bs2/maketext.h" // for InitialiseFontResourceFlags() +#include "bs2/maketext.h" // for initialiseFontResourceFlags() #include "bs2/mouse.h" #include "bs2/mem_view.h" #include "bs2/memory.h" @@ -672,15 +672,15 @@ uint32 Parse_user_input(void) { Print_to_console("SFX logging deactivated"); return 0; case 44: // ENGLISH - InitialiseFontResourceFlags(DEFAULT_TEXT); + initialiseFontResourceFlags(DEFAULT_TEXT); Print_to_console("Default fonts selected"); return 0; case 45: // FINNISH - InitialiseFontResourceFlags(FINNISH_TEXT); + initialiseFontResourceFlags(FINNISH_TEXT); Print_to_console("Finnish fonts selected"); return 0; case 46: // POLISH - InitialiseFontResourceFlags(POLISH_TEXT); + initialiseFontResourceFlags(POLISH_TEXT); Print_to_console("Polish fonts selected"); return 0; default: diff --git a/sword2/controls.cpp b/sword2/controls.cpp index a87e91bf74..28adfe2246 100644 --- a/sword2/controls.cpp +++ b/sword2/controls.cpp @@ -657,14 +657,14 @@ public: class MiniDialog : public Dialog { private: int _textId; - FontRendererGui *_fontRenderer; + FontRendererGui *_fr; Widget *_panel; Button *_okButton; Button *_cancelButton; public: MiniDialog(uint32 textId) : _textId(textId) { - _fontRenderer = new FontRendererGui(controls_font_id); + _fr = new FontRendererGui(g_sword2->_controlsFontId); _panel = new Widget(this, 1); _panel->createSurfaceImages(1996, 203, 104); @@ -681,15 +681,15 @@ public: } ~MiniDialog() { - delete _fontRenderer; + delete _fr; } virtual void paint() { Dialog::paint(); - _fontRenderer->drawText(_textId, 310, 134, kAlignCenter); - _fontRenderer->drawText(149618688, 270, 214); // ok - _fontRenderer->drawText(149618689, 270, 276); // cancel + _fr->drawText(_textId, 310, 134, kAlignCenter); + _fr->drawText(149618688, 270, 214); // ok + _fr->drawText(149618689, 270, 276); // cancel } virtual void onAction(Widget *widget, int result = 0) { @@ -702,7 +702,7 @@ public: class OptionsDialog : public Dialog { private: - FontRendererGui *_fontRenderer; + FontRendererGui *_fr; Widget *_panel; Switch *_objectLabelsSwitch; Switch *_subtitlesSwitch; @@ -722,7 +722,7 @@ private: public: OptionsDialog() { - _fontRenderer = new FontRendererGui(controls_font_id); + _fr = new FontRendererGui(g_sword2->_controlsFontId); _panel = new Widget(this, 1); _panel->createSurfaceImages(3405, 0, 40); @@ -793,7 +793,7 @@ public: } ~OptionsDialog() { - delete _fontRenderer; + delete _fr; } virtual void paint() { @@ -812,31 +812,31 @@ public: }; for (int i = 0; i < ARRAYSIZE(alignTextIds); i++) { - width = _fontRenderer->getTextWidth(alignTextIds[i]); + width = _fr->getTextWidth(alignTextIds[i]); if (width > maxWidth) maxWidth = width; } // Options - _fontRenderer->drawText(149618698, 321, 55, kAlignCenter); + _fr->drawText(149618698, 321, 55, kAlignCenter); // Subtitles - _fontRenderer->drawText(149618699, 500, 103, kAlignRight); + _fr->drawText(149618699, 500, 103, kAlignRight); // Object labels - _fontRenderer->drawText(149618700, 299 - maxWidth, 103); + _fr->drawText(149618700, 299 - maxWidth, 103); // Music volume - _fontRenderer->drawText(149618702, 299 - maxWidth, 161); + _fr->drawText(149618702, 299 - maxWidth, 161); // Speech volume - _fontRenderer->drawText(149618703, 299 - maxWidth, 208); + _fr->drawText(149618703, 299 - maxWidth, 208); // FX volume - _fontRenderer->drawText(149618704, 299 - maxWidth, 254); + _fr->drawText(149618704, 299 - maxWidth, 254); // Reverse stereo - _fontRenderer->drawText(149618709, 299 - maxWidth, 296); + _fr->drawText(149618709, 299 - maxWidth, 296); // Graphics quality - _fontRenderer->drawText(149618705, 299 - maxWidth, 341); + _fr->drawText(149618705, 299 - maxWidth, 341); // Ok - _fontRenderer->drawText(149618688, 193, 382, kAlignRight); + _fr->drawText(149618688, 193, 382, kAlignRight); // Cancel - _fontRenderer->drawText(149618689, 385, 382, kAlignRight); + _fr->drawText(149618689, 385, 382, kAlignRight); } virtual void onAction(Widget *widget, int result = 0) { @@ -1032,8 +1032,8 @@ private: int _editPos, _firstPos; int _cursorTick; - FontRendererGui *_fontRenderer1; - FontRendererGui *_fontRenderer2; + FontRendererGui *_fr1; + FontRendererGui *_fr2; Widget *_panel; Slot *_slotButton[8]; ScrollButton *_zupButton; @@ -1052,8 +1052,8 @@ public: // FIXME: The "control font" and the "red font" are currently // always the same font, so one should be eliminated. - _fontRenderer1 = new FontRendererGui(controls_font_id); - _fontRenderer2 = new FontRendererGui(red_font_id); + _fr1 = new FontRendererGui(g_sword2->_controlsFontId); + _fr2 = new FontRendererGui(g_sword2->_redFontId); _panel = new Widget(this, 1); _panel->createSurfaceImages(2016, 0, 40); @@ -1101,8 +1101,8 @@ public: } ~SaveLoadDialog() { - delete _fontRenderer1; - delete _fontRenderer2; + delete _fr1; + delete _fr2; } // There aren't really a hundred different button objects of course, @@ -1119,11 +1119,11 @@ public: if (gui._baseSlot + i == _selectedSlot) { slot->setEditable(_mode == kSaveDialog); slot->setState(1); - fr = _fontRenderer2; + fr = _fr2; } else { slot->setEditable(false); slot->setState(0); - fr = _fontRenderer1; + fr = _fr1; } if (GetSaveDescription(gui._baseSlot + i, description) == SR_OK) { @@ -1211,7 +1211,7 @@ public: tmp = _editBuffer[_editPos]; _editBuffer[_editPos] = 0; - textWidth = _fontRenderer2->getTextWidth(_editBuffer); + textWidth = _fr2->getTextWidth(_editBuffer); _editBuffer[_editPos] = tmp; if (textWidth < 340 && _editPos < SAVE_DESCRIPTION_LEN - 2) { @@ -1251,7 +1251,7 @@ public: // but I doubt that will make any noticeable difference. slot->paint(); - _fontRenderer2->drawText(_editBuffer, 130, 78 + (_selectedSlot - gui._baseSlot) * 36); + _fr2->drawText(_editBuffer, 130, 78 + (_selectedSlot - gui._baseSlot) * 36); } virtual void paint() { @@ -1259,13 +1259,13 @@ public: if (_mode == kLoadDialog) { // Restore - _fontRenderer1->drawText(149618690, 165, 377); + _fr1->drawText(149618690, 165, 377); } else { // Save - _fontRenderer1->drawText(149618691, 165, 377); + _fr1->drawText(149618691, 165, 377); } // Cancel - _fontRenderer1->drawText(149618689, 382, 377); + _fr1->drawText(149618689, 382, 377); } virtual void setResult(int result) { diff --git a/sword2/driver/d_draw.cpp b/sword2/driver/d_draw.cpp index 2cf7959db4..f01c2314e1 100644 --- a/sword2/driver/d_draw.cpp +++ b/sword2/driver/d_draw.cpp @@ -171,7 +171,7 @@ int32 MoviePlayer::play(char *filename, _movieTextObject *text[], uint8 *musicOu memset(lpBackBuffer, 0, screenWide * MENUDEEP); uint8 msg[] = "Cutscene - Press ESC to exit"; - mem *data = MakeTextSprite(msg, 640, 255, speech_font_id); + mem *data = fontRenderer.makeTextSprite(msg, 640, 255, g_sword2->_speechFontId); _frameHeader *frame = (_frameHeader *) data->ad; _spriteInfo msgSprite; uint8 *msgSurface; diff --git a/sword2/maketext.cpp b/sword2/maketext.cpp index f813a897d6..92ed4147b5 100644 --- a/sword2/maketext.cpp +++ b/sword2/maketext.cpp @@ -40,10 +40,6 @@ #define BORDER_COL 200 // source colour for character border (only // needed for remapping colours) #define LETTER_COL 193 // source colour for bulk of character ( " ) -#define BORDER_PEN 194 // output colour for character border - should - // be black ( " ) but note that we have to use - // a different pen number during sequences - #define NO_COL 0 // sprite background - 0 for transparency! #define SPACE ' ' #define FIRST_CHAR SPACE // first character in character set @@ -64,39 +60,11 @@ namespace Sword2 { -extern uint32 sequenceTextLines; // see anims.cpp +FontRenderer fontRenderer; // info for each line of words in the output text sprite -typedef struct { - uint16 width; // width of line in pixels - uint16 length; // length of line in characters -} _lineInfo; - -uint16 AnalyseSentence(uint8 *sentence, uint16 maxWidth, uint32 fontRes, _lineInfo *line); -mem* BuildTextSprite(uint8 *sentence, uint32 fontRes, uint8 pen, _lineInfo *line, uint16 noOfLines); -uint16 CharWidth(uint8 ch, uint32 fontRes); -uint16 CharHeight(uint32 fontRes); -_frameHeader* FindChar(uint8 ch, uint8 *charSet); -void CopyChar(_frameHeader *charPtr, uint8 *spritePtr, uint16 spriteWidth, uint8 pen); - -// global layout variables - these used to be defines, but now we're dealing -// with 2 character sets (10dec96 JEL) - -int8 line_spacing; // no. of pixels to separate lines of characters in - // the output sprite - negative for overlap -int8 char_spacing; // no. of pixels to separate characters along each - // line - negative for overlap -uint8 border_pen; // output pen colour of character borders - -// Global font resource id variables, set up in 'SetUpFontResources()' at -// bottom of this file - -uint32 speech_font_id; -uint32 controls_font_id; -uint32 red_font_id; - -mem* MakeTextSprite(uint8 *sentence, uint16 maxWidth, uint8 pen, uint32 fontRes) { +mem* FontRenderer::makeTextSprite(uint8 *sentence, uint16 maxWidth, uint8 pen, uint32 fontRes, uint8 border) { mem *line; // handle for the memory block which will // contain the array of lineInfo structures mem *textSprite; // handle for the block to contain the text @@ -104,45 +72,39 @@ mem* MakeTextSprite(uint8 *sentence, uint16 maxWidth, uint8 pen, uint32 fontRes) uint16 noOfLines; // no of lines of text required to fit within // a sprite of width 'maxWidth' pixels - debug(5, "MakeTextSprite(\"%s\", maxWidth=%u)", sentence, maxWidth); + debug(5, "makeTextSprite(\"%s\", maxWidth=%u)", sentence, maxWidth); + + _borderPen = border; // NB. ensure sentence contains no leading/tailing/extra spaces - if // necessary, copy to another array first, missing the extra spaces. - // set the global layout variables (10dec96 JEL) + // set the global layout variables - if (fontRes == speech_font_id) { - line_spacing = -6; // overlap lines by 6 pixels - char_spacing = -3; // overlap characters by 3 pixels + if (fontRes == g_sword2->_speechFontId) { + _lineSpacing = -6; // overlap lines by 6 pixels + _charSpacing = -3; // overlap characters by 3 pixels } else if (fontRes == CONSOLE_FONT_ID) { - line_spacing = 0; // no space or overlap between lines - char_spacing = 1; // 1 pixel spacing between each character + _lineSpacing = 0; // no space or overlap between lines + _charSpacing = 1; // 1 pixel spacing between each character } else { - line_spacing = 0; - char_spacing = 0; + _lineSpacing = 0; + _charSpacing = 0; } - // If rendering text over a sequence we need a different colour for - // the border. - - if (sequenceTextLines) - border_pen = 1; - else - border_pen = BORDER_PEN; - // allocate memory for array of lineInfo structures - line = memory.allocMemory(MAX_LINES * sizeof(_lineInfo), MEM_locked, UID_temp); + line = memory.allocMemory(MAX_LINES * sizeof(LineInfo), MEM_locked, UID_temp); - // get details of sentence breakdown into array of _lineInfo structures + // get details of sentence breakdown into array of LineInfo structures // and get the no of lines involved - noOfLines = AnalyseSentence(sentence, maxWidth, fontRes, (_lineInfo *) line->ad); + noOfLines = analyseSentence(sentence, maxWidth, fontRes, (LineInfo *) line->ad); // construct the sprite based on the info gathered - returns floating // mem block - textSprite = BuildTextSprite(sentence, fontRes, pen, (_lineInfo *) line->ad, noOfLines); + textSprite = buildTextSprite(sentence, fontRes, pen, (LineInfo *) line->ad, noOfLines); // free up the lineInfo array now memory.freeMemory(line); @@ -150,17 +112,17 @@ mem* MakeTextSprite(uint8 *sentence, uint16 maxWidth, uint8 pen, uint32 fontRes) return textSprite; } -uint16 AnalyseSentence(uint8 *sentence, uint16 maxWidth, uint32 fontRes, _lineInfo *line) { +uint16 FontRenderer::analyseSentence(uint8 *sentence, uint16 maxWidth, uint32 fontRes, LineInfo *line) { uint16 pos = 0, wordWidth, wordLength, spaceNeeded; uint16 lineNo = 0; uint8 ch; bool firstWord = true; // joinWidth = how much extra space is needed to append a word to a - // line. NB. SPACE requires TWICE the 'char_spacing' to join a word + // line. NB. SPACE requires TWICE the '_charSpacing' to join a word // to line - uint16 joinWidth = CharWidth(SPACE, fontRes) + 2 * char_spacing; + uint16 joinWidth = charWidth(SPACE, fontRes) + 2 * _charSpacing; // while not reached the NULL terminator @@ -175,13 +137,13 @@ uint16 AnalyseSentence(uint8 *sentence, uint16 maxWidth, uint32 fontRes, _lineIn // while not SPACE or NULL terminator while ((ch != SPACE) && ch) { - wordWidth += CharWidth(ch, fontRes) + char_spacing; + wordWidth += charWidth(ch, fontRes) + _charSpacing; wordLength++; ch = sentence[pos++]; } - // no char_spacing after final letter of word! - wordWidth -= char_spacing; + // no _charSpacing after final letter of word! + wordWidth -= _charSpacing; // 'ch' is now the SPACE or NULL following the word // 'pos' indexes to the position following 'ch' @@ -209,7 +171,7 @@ uint16 AnalyseSentence(uint8 *sentence, uint16 maxWidth, uint32 fontRes, _lineIn // put word (without separating SPACE) at // start of next line - // for next _lineInfo structure in the array + // for next LineInfo structure in the array lineNo++; // exception if lineNo >= MAX_LINES @@ -228,16 +190,16 @@ uint16 AnalyseSentence(uint8 *sentence, uint16 maxWidth, uint32 fontRes, _lineIn // Returns a handle to a floating memory block containing a text sprite, given // a pointer to a null-terminated string, pointer to required character set, // required text pen colour (or zero to use source colours), pointer to the -// array of linInfo structures created by 'AnalyseSentence()', and the number +// array of linInfo structures created by 'analyseSentence()', and the number // of lines (ie. no. of elements in the 'line' array). // PC Version of BuildTextSprite -mem* BuildTextSprite(uint8 *sentence, uint32 fontRes, uint8 pen, _lineInfo *line, uint16 noOfLines) { +mem* FontRenderer::buildTextSprite(uint8 *sentence, uint32 fontRes, uint8 pen, LineInfo *line, uint16 noOfLines) { uint8 *linePtr, *spritePtr; uint16 lineNo, pos = 0, posInLine, spriteWidth = 0, spriteHeight; uint16 sizeOfSprite; - uint16 charHeight = CharHeight(fontRes); + uint16 char_height = charHeight(fontRes); _frameHeader *frameHeadPtr, *charPtr; mem *textSprite; uint8 *charSet; @@ -251,7 +213,7 @@ mem* BuildTextSprite(uint8 *sentence, uint32 fontRes, uint8 pen, _lineInfo *line // spriteHeight = tot height of char lines + tot height of separating // lines - spriteHeight = charHeight * noOfLines + line_spacing * (noOfLines - 1); + spriteHeight = char_height * noOfLines + _lineSpacing * (noOfLines - 1); // total size (no of pixels) sizeOfSprite = spriteWidth * spriteHeight; @@ -286,7 +248,7 @@ mem* BuildTextSprite(uint8 *sentence, uint32 fontRes, uint8 pen, _lineInfo *line // fill sprite with characters, one line at a time - for(lineNo = 0; lineNo < noOfLines; lineNo++) { + for (lineNo = 0; lineNo < noOfLines; lineNo++) { // position the start of the line so that it is centred // across the sprite @@ -297,22 +259,22 @@ mem* BuildTextSprite(uint8 *sentence, uint32 fontRes, uint8 pen, _lineInfo *line // width minus the 'overlap' for (posInLine = 0; posInLine < line[lineNo].length; posInLine++) { - charPtr = FindChar(sentence[pos++], charSet); + charPtr = findChar(sentence[pos++], charSet); #ifdef _SWORD2_DEBUG - if (charPtr->height != charHeight) + if (charPtr->height != char_height) Con_fatal_error("FONT ERROR: '%c' is not same height as the space", sentence[pos - 1]); #endif - CopyChar(charPtr, spritePtr, spriteWidth, pen); - spritePtr += charPtr->width + char_spacing; + copyChar(charPtr, spritePtr, spriteWidth, pen); + spritePtr += charPtr->width + _charSpacing; } // skip space at end of last word in this line pos++; // move to start of next character line in text sprite - linePtr += (charHeight + line_spacing) * spriteWidth; + linePtr += (char_height + _lineSpacing) * spriteWidth; } // close font file @@ -327,7 +289,7 @@ mem* BuildTextSprite(uint8 *sentence, uint32 fontRes, uint8 pen, _lineInfo *line // Returns the width of a character sprite, given the character's ASCII code // and a pointer to the start of the character set. -uint16 CharWidth(uint8 ch, uint32 fontRes) { +uint16 FontRenderer::charWidth(uint8 ch, uint32 fontRes) { _frameHeader *charFrame; uint8 *charSet; uint16 width; @@ -336,7 +298,7 @@ uint16 CharWidth(uint8 ch, uint32 fontRes) { charSet = res_man.open(fontRes); // move to approp. sprite (header) - charFrame = FindChar(ch, charSet); + charFrame = findChar(ch, charSet); width = charFrame->width; // close font file @@ -349,7 +311,7 @@ uint16 CharWidth(uint8 ch, uint32 fontRes) { // Returns the height of a character sprite, given the character's ASCII code // and a pointer to the start of the character set. -uint16 CharHeight(uint32 fontRes) { +uint16 FontRenderer::charHeight(uint32 fontRes) { _frameHeader *charFrame; uint8 *charSet; uint16 height; @@ -358,7 +320,7 @@ uint16 CharHeight(uint32 fontRes) { charSet = res_man.open(fontRes); // assume all chars the same height, i.e. FIRST_CHAR is as good as any - charFrame = FindChar(FIRST_CHAR, charSet); + charFrame = findChar(FIRST_CHAR, charSet); height = charFrame->height; // close font file @@ -371,7 +333,7 @@ uint16 CharHeight(uint32 fontRes) { // Returns a pointer to the header of a character sprite, given the character's // ASCII code and a pointer to the start of the character set. -_frameHeader* FindChar(uint8 ch, uint8 *charSet) { +_frameHeader* FontRenderer::findChar(uint8 ch, uint8 *charSet) { // if 'ch' out of range, print the 'dud' character (chequered flag) if (ch < FIRST_CHAR) ch = DUD; @@ -381,10 +343,10 @@ _frameHeader* FindChar(uint8 ch, uint8 *charSet) { // Copies a character sprite from 'charPtr' to the sprite buffer at 'spritePtr' // of width 'spriteWidth'. If pen is zero, it copies the data across directly, -// otherwise it maps pixels of BORDER_COL to 'border_pen', and LETTER_COL to +// otherwise it maps pixels of BORDER_COL to '_borderPen', and LETTER_COL to // 'pen'. -void CopyChar(_frameHeader *charPtr, uint8 *spritePtr, uint16 spriteWidth, uint8 pen) { +void FontRenderer::copyChar(_frameHeader *charPtr, uint8 *spritePtr, uint16 spriteWidth, uint8 pen) { uint8 *rowPtr, *source, *dest; uint16 rows, cols; @@ -412,7 +374,7 @@ void CopyChar(_frameHeader *charPtr, uint8 *spritePtr, uint16 spriteWidth, uint8 // underneath (for overlapping!) if (!*dest) - *dest = border_pen; + *dest = _borderPen; break; // do nothing if source pixel is zero, @@ -434,30 +396,6 @@ void CopyChar(_frameHeader *charPtr, uint8 *spritePtr, uint16 spriteWidth, uint8 } } -#ifdef _SWORD2_DEBUG -// allow enough for all the debug text blocks (see debug.cpp) -#define MAX_text_blocs MAX_DEBUG_TEXT_BLOCKS + 1 -#else -// only need one for speech, and possibly one for "PAUSED" -#define MAX_text_blocs 2 -#endif - -typedef struct { - int16 x; - int16 y; - // RDSPR_ status bits - see defintion of _spriteInfo structure for - // correct size! - uint16 type; - mem *text_mem; -} text_bloc; - -static text_bloc text_sprite_list[MAX_text_blocs]; - -void Init_text_bloc_system(void) { - for (int j = 0; j < MAX_text_blocs; j++) - text_sprite_list[j].text_mem = 0; -} - // distance to keep speech text from edges of screen #define TEXT_MARGIN 12 @@ -465,7 +403,7 @@ void Init_text_bloc_system(void) { // blocs are read and blitted at render time choose alignment type // RDSPR_DISPLAYALIGN or 0 -uint32 Build_new_block(uint8 *ascii, int16 x, int16 y, uint16 width, uint8 pen, uint32 type, uint32 fontRes, uint8 justification) { +uint32 FontRenderer::buildNewBloc(uint8 *ascii, int16 x, int16 y, uint16 width, uint8 pen, uint32 type, uint32 fontRes, uint8 justification) { uint32 j = 0; _frameHeader *frame_head; int16 text_left_margin; @@ -474,7 +412,7 @@ uint32 Build_new_block(uint8 *ascii, int16 x, int16 y, uint16 width, uint8 pen, int16 text_bottom_margin; // find a free slot - while(j < MAX_text_blocs && text_sprite_list[j].text_mem) + while (j < MAX_text_blocs && _blocList[j].text_mem) j++; #ifdef _SWORD2_DEBUG @@ -484,7 +422,7 @@ uint32 Build_new_block(uint8 *ascii, int16 x, int16 y, uint16 width, uint8 pen, #endif // make the sprite! - text_sprite_list[j].text_mem = MakeTextSprite(ascii, width, pen, fontRes); + _blocList[j].text_mem = makeTextSprite(ascii, width, pen, fontRes); // speech to be centred above point (x,y), but kept on-screen // where (x,y) is a point somewhere just above the talker's head @@ -497,7 +435,7 @@ uint32 Build_new_block(uint8 *ascii, int16 x, int16 y, uint16 width, uint8 pen, // without margin checking - used for debug text if (justification != NO_JUSTIFICATION) { - frame_head = (_frameHeader *) text_sprite_list[j].text_mem->ad; + frame_head = (_frameHeader *) _blocList[j].text_mem->ad; switch (justification) { // this one is always used for SPEECH TEXT; possibly @@ -554,16 +492,16 @@ uint32 Build_new_block(uint8 *ascii, int16 x, int16 y, uint16 width, uint8 pen, y = text_bottom_margin; } - text_sprite_list[j].x = x; - text_sprite_list[j].y = y; + _blocList[j].x = x; + _blocList[j].y = y; // always uncompressed - text_sprite_list[j].type = type | RDSPR_NOCOMPRESSION; + _blocList[j].type = type | RDSPR_NOCOMPRESSION; return j + 1; } -void Print_text_blocs(void) { +void FontRenderer::printTextBlocs(void) { //called by build_display _frameHeader *frame; @@ -572,19 +510,19 @@ void Print_text_blocs(void) { uint32 j; for (j = 0; j < MAX_text_blocs; j++) { - if (text_sprite_list[j].text_mem) { - frame = (_frameHeader*) text_sprite_list[j].text_mem->ad; + if (_blocList[j].text_mem) { + frame = (_frameHeader*) _blocList[j].text_mem->ad; - spriteInfo.x = text_sprite_list[j].x; - spriteInfo.y = text_sprite_list[j].y; + spriteInfo.x = _blocList[j].x; + spriteInfo.y = _blocList[j].y; spriteInfo.w = frame->width; spriteInfo.h = frame->height; spriteInfo.scale = 0; spriteInfo.scaledWidth = 0; spriteInfo.scaledHeight = 0; - spriteInfo.type = text_sprite_list[j].type; + spriteInfo.type = _blocList[j].type; spriteInfo.blend = 0; - spriteInfo.data = text_sprite_list[j].text_mem->ad + sizeof(_frameHeader); + spriteInfo.data = _blocList[j].text_mem->ad + sizeof(_frameHeader); spriteInfo.colourTable = 0; rv = DrawSprite(&spriteInfo); @@ -594,20 +532,22 @@ void Print_text_blocs(void) { } } -void Kill_text_bloc(uint32 bloc_number) { +void FontRenderer::killTextBloc(uint32 bloc_number) { //back to real bloc_number--; - if (text_sprite_list[bloc_number].text_mem) { + if (_blocList[bloc_number].text_mem) { // release the floating memory and mark it as free - memory.freeMemory(text_sprite_list[bloc_number].text_mem); - text_sprite_list[bloc_number].text_mem = 0; + memory.freeMemory(_blocList[bloc_number].text_mem); + _blocList[bloc_number].text_mem = 0; } else { // illegal kill - stop the system Con_fatal_error("closing closed text bloc number %d", bloc_number); } } +// The rest of this file doesn't belong in the FontRenderer class! + // called from InitialiseGame() in sword2.cpp // resource 3258 contains text from location script for 152 (install, save & @@ -619,7 +559,7 @@ void Kill_text_bloc(uint32 bloc_number) { #define SAVE_LINE_NO 1 -void InitialiseFontResourceFlags(void) { +void Sword2Engine::initialiseFontResourceFlags(void) { uint8 *textFile, *textLine; uint8 language; @@ -644,7 +584,7 @@ void InitialiseFontResourceFlags(void) { language = DEFAULT_TEXT; // Set the game to use the appropriate fonts - InitialiseFontResourceFlags(language); + initialiseFontResourceFlags(language); // Get the game name for the windows application @@ -671,22 +611,22 @@ void InitialiseFontResourceFlags(void) { // called from the above function, and also from console.cpp -void InitialiseFontResourceFlags(uint8 language) { +void Sword2Engine::initialiseFontResourceFlags(uint8 language) { switch (language) { case FINNISH_TEXT: // special Finnish fonts - speech_font_id = FINNISH_SPEECH_FONT_ID; - controls_font_id = FINNISH_CONTROLS_FONT_ID; - red_font_id = FINNISH_RED_FONT_ID; + _speechFontId = FINNISH_SPEECH_FONT_ID; + _controlsFontId = FINNISH_CONTROLS_FONT_ID; + _redFontId = FINNISH_RED_FONT_ID; break; case POLISH_TEXT: // special Polish fonts - speech_font_id = POLISH_SPEECH_FONT_ID; - controls_font_id = POLISH_CONTROLS_FONT_ID; - red_font_id = POLISH_RED_FONT_ID; + _speechFontId = POLISH_SPEECH_FONT_ID; + _controlsFontId = POLISH_CONTROLS_FONT_ID; + _redFontId = POLISH_RED_FONT_ID; break; default: // DEFAULT_TEXT - regular fonts - speech_font_id = ENGLISH_SPEECH_FONT_ID; - controls_font_id = ENGLISH_CONTROLS_FONT_ID; - red_font_id = ENGLISH_RED_FONT_ID; + _speechFontId = ENGLISH_SPEECH_FONT_ID; + _controlsFontId = ENGLISH_CONTROLS_FONT_ID; + _redFontId = ENGLISH_RED_FONT_ID; break; } } diff --git a/sword2/maketext.h b/sword2/maketext.h index d3defa1c55..47be05cfc6 100644 --- a/sword2/maketext.h +++ b/sword2/maketext.h @@ -59,40 +59,105 @@ #include "bs2/memory.h" +#ifdef _SWORD2_DEBUG +#include "bs2/debug.h" +#endif + +// Output colour for character border - should be be black but note that we +// have to use a different pen number during sequences + +#define BORDER_PEN 194 + namespace Sword2 { -// only for debug text, since it doesn't keep text inside the screen margin! -#define NO_JUSTIFICATION 0 -// these all force text inside the screen edge margin when necessary -#define POSITION_AT_CENTRE_OF_BASE 1 -#define POSITION_AT_CENTRE_OF_TOP 2 -#define POSITION_AT_LEFT_OF_TOP 3 -#define POSITION_AT_RIGHT_OF_TOP 4 -#define POSITION_AT_LEFT_OF_BASE 5 -#define POSITION_AT_RIGHT_OF_BASE 6 -#define POSITION_AT_LEFT_OF_CENTRE 7 -#define POSITION_AT_RIGHT_OF_CENTRE 8 +#ifdef _SWORD2_DEBUG +// allow enough for all the debug text blocks (see debug.cpp) +#define MAX_text_blocs MAX_DEBUG_TEXT_BLOCKS + 1 +#else +// only need one for speech, and possibly one for "PAUSED" +#define MAX_text_blocs 2 +#endif + +enum { + // only for debug text, since it doesn't keep text inside the screen + // margin! + NO_JUSTIFICATION = 0, + + // these all force text inside the screen edge margin when necessary + POSITION_AT_CENTRE_OF_BASE = 1, + POSITION_AT_CENTRE_OF_TOP = 2, + POSITION_AT_LEFT_OF_TOP = 3, + POSITION_AT_RIGHT_OF_TOP = 4, + POSITION_AT_LEFT_OF_BASE = 5, + POSITION_AT_RIGHT_OF_BASE = 6, + POSITION_AT_LEFT_OF_CENTRE = 7, + POSITION_AT_RIGHT_OF_CENTRE = 8 +}; + +enum { + DEFAULT_TEXT = 0, + FINNISH_TEXT = 1, + POLISH_TEXT = 2 +}; -mem* MakeTextSprite(uint8 *sentence, uint16 maxWidth, uint8 pen, uint32 fontRes); -void Init_text_bloc_system(void); +typedef struct { + int16 x; + int16 y; + // RDSPR_ status bits - see defintion of _spriteInfo structure for + // correct size! + uint16 type; + mem *text_mem; +} TextBloc; -void Kill_text_bloc(uint32 bloc_number); -void Print_text_blocs(void); +typedef struct { + uint16 width; // width of line in pixels + uint16 length; // length of line in characters +} LineInfo; -uint32 Build_new_block(uint8 *ascii, int16 x, int16 y, uint16 width, uint8 pen, uint32 type, uint32 fontRes, uint8 justification); +class FontRenderer { +private: + TextBloc _blocList[MAX_text_blocs]; -#define DEFAULT_TEXT 0 -#define FINNISH_TEXT 1 -#define POLISH_TEXT 2 + // layout variables - these used to be defines, but now we're dealing + // with 2 character sets + + int8 _lineSpacing; // no. of pixels to separate lines of + // characters in the output sprite - negative + // for overlap + int8 _charSpacing; // no. of pixels to separate characters along + // each line - negative for overlap + uint8 _borderPen; // output pen colour of character borders + + uint16 analyseSentence(uint8 *sentence, uint16 maxWidth, uint32 fontRes, LineInfo *line); + mem* buildTextSprite(uint8 *sentence, uint32 fontRes, uint8 pen, LineInfo *line, uint16 noOfLines); + uint16 charWidth(uint8 ch, uint32 fontRes); + uint16 charHeight(uint32 fontRes); + _frameHeader* findChar(uint8 ch, uint8 *charSet); + void copyChar(_frameHeader *charPtr, uint8 *spritePtr, uint16 spriteWidth, uint8 pen); + +public: + FontRenderer() { + for (int i = 0; i < MAX_text_blocs; i++) + _blocList[i].text_mem = NULL; + } + + mem* makeTextSprite(uint8 *sentence, uint16 maxWidth, uint8 pen, uint32 fontRes, uint8 border = BORDER_PEN); + + void killTextBloc(uint32 bloc_number); + void printTextBlocs(void); + + uint32 buildNewBloc(uint8 *ascii, int16 x, int16 y, uint16 width, uint8 pen, uint32 type, uint32 fontRes, uint8 justification); +}; + +extern // this one works out the language from the text cluster -void InitialiseFontResourceFlags(void); +void initialiseFontResourceFlags(void); + // this one allow you to select the fonts yourself -void InitialiseFontResourceFlags(uint8 language); +void initialiseFontResourceFlags(uint8 language); -extern uint32 speech_font_id; -extern uint32 controls_font_id; -extern uint32 red_font_id; +extern FontRenderer fontRenderer; } // End of namespace Sword2 diff --git a/sword2/mouse.cpp b/sword2/mouse.cpp index 9291efa7c5..c429baf6c4 100644 --- a/sword2/mouse.cpp +++ b/sword2/mouse.cpp @@ -1016,11 +1016,11 @@ void CreatePointerText(uint32 textId, uint32 pointerRes) { // 'text+2' to skip the first 2 bytes which form the // line reference number - pointer_text_bloc_no = Build_new_block( + pointer_text_bloc_no = fontRenderer.buildNewBloc( text + 2, mousex + xOffset, mousey + yOffset, POINTER_TEXT_WIDTH, POINTER_TEXT_PEN, RDSPR_TRANS | RDSPR_DISPLAYALIGN, - speech_font_id, justification); + g_sword2->_speechFontId, justification); // now ok to close the text file res_man.close(text_res); @@ -1030,7 +1030,7 @@ void CreatePointerText(uint32 textId, uint32 pointerRes) { void ClearPointerText(void) { if (pointer_text_bloc_no) { - Kill_text_bloc(pointer_text_bloc_no); + fontRenderer.killTextBloc(pointer_text_bloc_no); pointer_text_bloc_no = 0; } } diff --git a/sword2/resman.cpp b/sword2/resman.cpp index 5e3f523f7e..b6db4f0361 100644 --- a/sword2/resman.cpp +++ b/sword2/resman.cpp @@ -1149,7 +1149,7 @@ void ResourceManager::cacheNewCluster(uint32 newCluster) { uint8 *loadingBar; _cdtEntry *cdt; - text_spr = MakeTextSprite(FetchTextLine(res_man.open(2283), 8) + 2, 640, 187, speech_font_id); + text_spr = fontRenderer.makeTextSprite(FetchTextLine(res_man.open(2283), 8) + 2, 640, 187, g_sword2->_speechFontId); frame = (_frameHeader*) text_spr->ad; @@ -1160,7 +1160,7 @@ void ResourceManager::cacheNewCluster(uint32 newCluster) { textSprite.scale = 0; textSprite.scaledWidth = 0; textSprite.scaledHeight = 0; - textSprite.type = RDSPR_DISPLAYALIGN + RDSPR_NOCOMPRESSION + RDSPR_TRANS; + textSprite.type = RDSPR_DISPLAYALIGN | RDSPR_NOCOMPRESSION | RDSPR_TRANS; textSprite.blend = 0; textSprite.colourTable = 0; @@ -1178,7 +1178,7 @@ void ResourceManager::cacheNewCluster(uint32 newCluster) { barSprite.scale = 0; barSprite.scaledWidth = 0; barSprite.scaledHeight = 0; - barSprite.type = RDSPR_RLE256FAST + RDSPR_TRANS; + barSprite.type = RDSPR_RLE256FAST | RDSPR_TRANS; barSprite.blend = 0; barSprite.colourTable = 0; @@ -1375,7 +1375,7 @@ void ResourceManager::getCd(int cd) { textRes = res_man.open(2283); DisplayMsg(FetchTextLine(textRes, 5 + cd) + 2, 0); - text_spr = MakeTextSprite(FetchTextLine(textRes, 5 + cd) + 2, 640, 187, speech_font_id); + text_spr = fontRenderer.makeTextSprite(FetchTextLine(textRes, 5 + cd) + 2, 640, 187, g_sword2->_speechFontId); frame = (_frameHeader*) text_spr->ad; @@ -1386,7 +1386,7 @@ void ResourceManager::getCd(int cd) { spriteInfo.scale = 0; spriteInfo.scaledWidth = 0; spriteInfo.scaledHeight = 0; - spriteInfo.type = RDSPR_DISPLAYALIGN + RDSPR_NOCOMPRESSION + RDSPR_TRANS; + spriteInfo.type = RDSPR_DISPLAYALIGN | RDSPR_NOCOMPRESSION | RDSPR_TRANS; spriteInfo.blend = 0; spriteInfo.data = text_spr->ad + sizeof(_frameHeader); spriteInfo.colourTable = 0; diff --git a/sword2/speech.cpp b/sword2/speech.cpp index 8c61702857..b09f46155d 100644 --- a/sword2/speech.cpp +++ b/sword2/speech.cpp @@ -1356,7 +1356,7 @@ int32 FN_i_speak(int32 *params) { // if there is text if (speech_text_bloc_no) { // kill the text block - Kill_text_bloc(speech_text_bloc_no); + fontRenderer.killTextBloc(speech_text_bloc_no); speech_text_bloc_no = 0; } @@ -1547,10 +1547,11 @@ void Form_text(int32 *params) { // 'text + 2' to skip the first 2 bytes which form the line // reference number - speech_text_bloc_no = Build_new_block(text + 2, text_x, text_y, + speech_text_bloc_no = fontRenderer.buildNewBloc( + text + 2, text_x, text_y, textWidth, ob_speech->pen, - RDSPR_TRANS | RDSPR_DISPLAYALIGN, speech_font_id, - POSITION_AT_CENTRE_OF_BASE); + RDSPR_TRANS | RDSPR_DISPLAYALIGN, + g_sword2->_speechFontId, POSITION_AT_CENTRE_OF_BASE); // now ok to close the text file res_man.close(text_res); diff --git a/sword2/startup.cpp b/sword2/startup.cpp index c4bd03445a..623ff682e7 100644 --- a/sword2/startup.cpp +++ b/sword2/startup.cpp @@ -225,14 +225,14 @@ uint32 Con_start(uint8 *input) { char *raw_data_ad; uint32 null_pc; - // so that typing 'S' then <enter> works on NT (James26feb97) + // so that typing 'S' then <enter> works on NT if (input[0] == 0) { Con_print_start_menu(); return 1; } while (input[j]) { - if (input[j] >= '0' && input[j] <= '9') + if (isdigit(input[j])) j++; else break; @@ -276,15 +276,15 @@ uint32 Con_start(uint8 *input) { // if there was speech text, kill the text block if (speech_text_bloc_no) { - Kill_text_bloc(speech_text_bloc_no); - speech_text_bloc_no=0; + fontRenderer.killTextBloc(speech_text_bloc_no); + speech_text_bloc_no = 0; } // set the key // Open George - raw_data_ad = (char*) (res_man.open(8)); - raw_script = (char*) (res_man.open(start_list[start].start_res_id)); + raw_data_ad = (char *) (res_man.open(8)); + raw_script = (char *) (res_man.open(start_list[start].start_res_id)); // denotes script to run null_pc = start_list[start].key & 0xffff; diff --git a/sword2/sword2.cpp b/sword2/sword2.cpp index 42e671762b..a143184369 100644 --- a/sword2/sword2.cpp +++ b/sword2/sword2.cpp @@ -157,8 +157,8 @@ int32 Sword2Engine::InitialiseGame(void) { // Set up font resource variables for this language version - debug(5, "CALLING: InitialiseFontResourceFlags"); - InitialiseFontResourceFlags(); + debug(5, "CALLING: initialiseFontResourceFlags"); + initialiseFontResourceFlags(); // set up the console system @@ -172,11 +172,6 @@ int32 Sword2Engine::InitialiseGame(void) { Init_start_menu(); #endif - // no blocs live - - debug(5, "CALLING: Init_text_bloc_system"); - Init_text_bloc_system(); - debug(5, "CALLING: Init_sync_system"); Init_sync_system(); diff --git a/sword2/sword2.h b/sword2/sword2.h index 0e0fd28447..8d4da8fc3e 100644 --- a/sword2/sword2.h +++ b/sword2/sword2.h @@ -73,6 +73,10 @@ public: Sound *_sound; Common::RandomSource _rnd; + uint32 _speechFontId; + uint32 _controlsFontId; + uint32 _redFontId; + private: bool _quit; uint32 _bootParam; @@ -80,6 +84,8 @@ private: public: void errorString(const char *buf_input, char *buf_output); + void initialiseFontResourceFlags(void); + void initialiseFontResourceFlags(uint8 language); }; extern Sword2Engine *g_sword2; |