mirror of
https://github.com/libretro/scummvm.git
synced 2025-01-05 17:20:30 +00:00
293 lines
8.0 KiB
C++
293 lines
8.0 KiB
C++
/* ScummVM - Graphic Adventure Engine
|
|
*
|
|
* ScummVM is the legal property of its developers, whose names
|
|
* are too numerous to list here. Please refer to the COPYRIGHT
|
|
* file distributed with this source distribution.
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*
|
|
* Text utilities.
|
|
*/
|
|
|
|
#include "tinsel/dw.h"
|
|
#include "tinsel/graphics.h" // object plotting
|
|
#include "tinsel/handle.h"
|
|
#include "tinsel/sched.h" // process scheduler defines
|
|
#include "tinsel/strres.h" // g_bMultiByte
|
|
#include "tinsel/text.h" // text defines
|
|
|
|
namespace Tinsel {
|
|
|
|
|
|
//----------------- LOCAL GLOBAL DATA --------------------
|
|
/** TinselV3, base color for the text color replacement */
|
|
static uint32 g_t3fontBaseColor;
|
|
|
|
/**
|
|
* Returns the length of one line of a string in pixels.
|
|
* @param szStr String
|
|
* @param pFont Which font to use for dimensions
|
|
*/
|
|
int StringLengthPix(char *szStr, const FONT *pFont) {
|
|
int strLen; // accumulated length of string
|
|
byte c;
|
|
SCNHANDLE hImg;
|
|
|
|
// while not end of string or end of line
|
|
for (strLen = 0; (c = *szStr) != EOS_CHAR && c != LF_CHAR; szStr++) {
|
|
if (g_bMultiByte) {
|
|
if (c & 0x80)
|
|
c = ((c & ~0x80) << 8) + *++szStr;
|
|
}
|
|
hImg = pFont->fontDef[c];
|
|
|
|
if (hImg) {
|
|
// there is a IMAGE for this character
|
|
const IMAGE *pChar = _vm->_handle->GetImage(hImg);
|
|
|
|
// add width of font bitmap
|
|
strLen += pChar->imgWidth;
|
|
|
|
delete pChar;
|
|
} else
|
|
// use width of space character
|
|
strLen += pFont->spaceSize;
|
|
|
|
// finally add the inter-character spacing
|
|
strLen += pFont->xSpacing;
|
|
}
|
|
|
|
// return length of line in pixels - minus inter-char spacing for last character
|
|
strLen -= pFont->xSpacing;
|
|
return (strLen > 0) ? strLen : 0;
|
|
}
|
|
|
|
/**
|
|
* Returns the justified x start position of a line of text.
|
|
* @param szStr String to output
|
|
* @param xPos X position of string
|
|
* @param pFont Which font to use
|
|
* @param mode Mode flags for the string
|
|
*/
|
|
int JustifyText(char *szStr, int xPos, const FONT *pFont, int mode) {
|
|
if (mode & TXT_CENTER) {
|
|
// center justify the text
|
|
|
|
// adjust x positioning by half the length of line in pixels
|
|
xPos -= StringLengthPix(szStr, pFont) / 2;
|
|
} else if (mode & TXT_RIGHT) {
|
|
// right justify the text
|
|
|
|
// adjust x positioning by length of line in pixels
|
|
xPos -= StringLengthPix(szStr, pFont);
|
|
}
|
|
|
|
// return text line x start position
|
|
return xPos;
|
|
}
|
|
|
|
/**
|
|
* Main text outputting routine. If a object list is specified a
|
|
* multi-object is created for the whole text and a pointer to the head
|
|
* of the list is returned.
|
|
* @param pList Object list to add text to
|
|
* @param szStr String to output
|
|
* @param color Color for monochrome text
|
|
* @param xPos X position of string
|
|
* @param yPos Y position of string
|
|
* @param hFont Which font to use
|
|
* @param mode Mode flags for the string
|
|
* @param sleepTime Sleep time between each character (if non-zero)
|
|
*/
|
|
OBJECT *ObjectTextOut(OBJECT **pList, char *szStr, int color,
|
|
int xPos, int yPos, SCNHANDLE hFont, int mode, int sleepTime) {
|
|
int xJustify; // x position of text after justification
|
|
int yOffset; // offset to next line of text
|
|
OBJECT *pFirst; // head of multi-object text list
|
|
OBJECT *pChar = 0; // object ptr for the character
|
|
byte c;
|
|
SCNHANDLE hImg;
|
|
|
|
// make sure there is a linked list to add text to
|
|
assert(pList);
|
|
|
|
// get font pointer
|
|
FONT *pFont = _vm->_handle->GetFont(hFont);
|
|
const OBJ_INIT *pFontInit = &pFont->fontInit;
|
|
|
|
// init head of text list
|
|
pFirst = nullptr;
|
|
|
|
// get image for capital W
|
|
SCNHANDLE imgHandle = pFont->fontDef[(int)'W'];
|
|
assert(imgHandle);
|
|
|
|
// get height of capital W for offset to next line
|
|
const IMAGE *pImgCapitalW = _vm->_handle->GetImage(imgHandle);
|
|
yOffset = pImgCapitalW->imgHeight & ~C16_FLAG_MASK;
|
|
delete pImgCapitalW;
|
|
|
|
while (*szStr) {
|
|
// x justify the text according to the mode flags
|
|
xJustify = JustifyText(szStr, xPos, pFont, mode);
|
|
|
|
// repeat until end of string or end of line
|
|
while ((c = *szStr) != EOS_CHAR && c != LF_CHAR) {
|
|
if (g_bMultiByte) {
|
|
if (c & 0x80)
|
|
c = ((c & ~0x80) << 8) + *++szStr;
|
|
}
|
|
hImg = pFont->fontDef[c];
|
|
|
|
if (hImg == 0) {
|
|
// no image for this character
|
|
|
|
// add font spacing for a space character
|
|
xJustify += pFont->spaceSize;
|
|
} else { // printable character
|
|
|
|
int aniX, aniY; // char image animation offsets
|
|
|
|
// allocate and init a character object
|
|
if (pFirst == NULL)
|
|
// first time - init head of list
|
|
pFirst = pChar = InitObject(pFontInit);
|
|
else
|
|
// chain to multi-char list
|
|
pChar = pChar->pSlave = InitObject(pFontInit);
|
|
|
|
// convert image handle to pointer
|
|
const IMAGE *pImg = _vm->_handle->GetImage(hImg);
|
|
|
|
// fill in character object
|
|
pChar->hImg = hImg; // image def
|
|
pChar->width = pImg->imgWidth; // width of chars bitmap
|
|
pChar->height = pImg->imgHeight & ~C16_FLAG_MASK; // height of chars bitmap
|
|
pChar->hBits = pImg->hImgBits; // bitmap
|
|
|
|
// check for absolute positioning
|
|
if (mode & TXT_ABSOLUTE)
|
|
pChar->flags |= DMA_ABS;
|
|
|
|
// set characters color - only effective for mono fonts
|
|
pChar->constant = color;
|
|
|
|
// set the base font color to be replaced with supplied color, only for Tinsel V3
|
|
g_t3fontBaseColor = TinselV3 ? pFont->baseColor : 0;
|
|
|
|
// get Y animation offset
|
|
GetAniOffset(hImg, pChar->flags, &aniX, &aniY);
|
|
|
|
// set x position - ignore animation point
|
|
pChar->xPos = intToFrac(xJustify);
|
|
|
|
// set y position - adjust for animation point
|
|
pChar->yPos = intToFrac(yPos - aniY);
|
|
|
|
if (mode & TXT_SHADOW) {
|
|
// we want to shadow the character
|
|
OBJECT *pShad;
|
|
|
|
// allocate a object for the shadow and chain to multi-char list
|
|
pShad = pChar->pSlave = AllocObject();
|
|
|
|
// copy the character for a shadow
|
|
CopyObject(pShad, pChar);
|
|
|
|
// add shadow offsets to characters position
|
|
pShad->xPos += intToFrac(pFont->xShadow);
|
|
pShad->yPos += intToFrac(pFont->yShadow);
|
|
|
|
// shadow is behind the character
|
|
pShad->zPos--;
|
|
|
|
// shadow is always mono
|
|
pShad->flags = DMA_CNZ | DMA_CHANGED;
|
|
|
|
// check for absolute positioning
|
|
if (mode & TXT_ABSOLUTE)
|
|
pShad->flags |= DMA_ABS;
|
|
|
|
// shadow always uses first palette entry
|
|
// should really alloc a palette here also ????
|
|
pShad->constant = 1;
|
|
|
|
// add shadow to object list
|
|
InsertObject(pList, pShad);
|
|
}
|
|
|
|
// add character to object list
|
|
InsertObject(pList, pChar);
|
|
|
|
// move to end of list
|
|
if (pChar->pSlave)
|
|
pChar = pChar->pSlave;
|
|
|
|
// add character spacing
|
|
xJustify += pImg->imgWidth;
|
|
|
|
delete pImg;
|
|
}
|
|
|
|
// finally add the inter-character spacing
|
|
xJustify += pFont->xSpacing;
|
|
|
|
// next character in string
|
|
++szStr;
|
|
}
|
|
|
|
// adjust the text y position and add the inter-line spacing
|
|
yPos += yOffset + pFont->ySpacing;
|
|
|
|
// check for newline
|
|
if (c == LF_CHAR)
|
|
// next character in string
|
|
++szStr;
|
|
}
|
|
|
|
delete pFont;
|
|
|
|
// return head of list
|
|
return pFirst;
|
|
}
|
|
|
|
/**
|
|
* Is there an image for this character in this font?
|
|
* @param hFont which font to use
|
|
* @param c character to test
|
|
*/
|
|
bool IsCharImage(SCNHANDLE hFont, char c) {
|
|
byte c2 = (byte)c;
|
|
|
|
// Inventory save game name editor needs to be more clever for
|
|
// multi-byte characters. This bodge will stop it erring.
|
|
if (g_bMultiByte && (c2 & 0x80))
|
|
return false;
|
|
|
|
// get font pointer
|
|
FONT *pFont = _vm->_handle->GetFont(hFont);
|
|
bool result = pFont->fontDef[c2] != 0;
|
|
delete pFont;
|
|
|
|
return result;
|
|
}
|
|
|
|
uint32 t3GetBaseColor()
|
|
{
|
|
return g_t3fontBaseColor;
|
|
}
|
|
|
|
|
|
} // End of namespace Tinsel
|