mirror of
https://github.com/libretro/scummvm.git
synced 2024-12-20 16:59:06 +00:00
278 lines
8.1 KiB
C++
278 lines
8.1 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 2
|
|
* 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, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
*
|
|
* 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 {
|
|
|
|
/**
|
|
* 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 = FROM_32(pFont->fontDef[c]);
|
|
|
|
if (hImg) {
|
|
// there is a IMAGE for this character
|
|
const IMAGE *pChar = (const IMAGE *)LockMem(hImg);
|
|
|
|
// add width of font bitmap
|
|
strLen += FROM_16(pChar->imgWidth);
|
|
} else
|
|
// use width of space character
|
|
strLen += FROM_32(pFont->spaceSize);
|
|
|
|
// finally add the inter-character spacing
|
|
strLen += FROM_32(pFont->xSpacing);
|
|
}
|
|
|
|
// return length of line in pixels - minus inter-char spacing for last character
|
|
strLen -= FROM_32(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;
|
|
const IMAGE *pImg;
|
|
|
|
// make sure there is a linked list to add text to
|
|
assert(pList);
|
|
|
|
// get font pointer
|
|
const FONT *pFont = (const FONT *)LockMem(hFont);
|
|
|
|
// init head of text list
|
|
pFirst = NULL;
|
|
|
|
// get image for capital W
|
|
assert(pFont->fontDef[(int)'W']);
|
|
pImg = (const IMAGE *)LockMem(FROM_32(pFont->fontDef[(int)'W']));
|
|
|
|
// get height of capital W for offset to next line
|
|
yOffset = FROM_16(pImg->imgHeight) & ~C16_FLAG_MASK;
|
|
|
|
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 = FROM_32(pFont->fontDef[c]);
|
|
|
|
if (hImg == 0) {
|
|
// no image for this character
|
|
|
|
// add font spacing for a space character
|
|
xJustify += FROM_32(pFont->spaceSize);
|
|
} else { // printable character
|
|
|
|
int aniX, aniY; // char image animation offsets
|
|
|
|
OBJ_INIT oi;
|
|
oi.hObjImg = FROM_32(pFont->fontInit.hObjImg);
|
|
oi.objFlags = FROM_32(pFont->fontInit.objFlags);
|
|
oi.objID = FROM_32(pFont->fontInit.objID);
|
|
oi.objX = FROM_32(pFont->fontInit.objX);
|
|
oi.objY = FROM_32(pFont->fontInit.objY);
|
|
oi.objZ = FROM_32(pFont->fontInit.objZ);
|
|
|
|
// allocate and init a character object
|
|
if (pFirst == NULL)
|
|
// first time - init head of list
|
|
pFirst = pChar = InitObject(&oi); // FIXME: endian issue using fontInit!!!
|
|
else
|
|
// chain to multi-char list
|
|
pChar = pChar->pSlave = InitObject(&oi); // FIXME: endian issue using fontInit!!!
|
|
|
|
// convert image handle to pointer
|
|
pImg = (const IMAGE *)LockMem(hImg);
|
|
|
|
// fill in character object
|
|
pChar->hImg = hImg; // image def
|
|
pChar->width = FROM_16(pImg->imgWidth); // width of chars bitmap
|
|
pChar->height = FROM_16(pImg->imgHeight) & ~C16_FLAG_MASK; // height of chars bitmap
|
|
pChar->hBits = FROM_32(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;
|
|
|
|
// 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(FROM_32(pFont->xShadow));
|
|
pShad->yPos += intToFrac(FROM_32(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 += FROM_16(pImg->imgWidth);
|
|
}
|
|
|
|
// finally add the inter-character spacing
|
|
xJustify += FROM_32(pFont->xSpacing);
|
|
|
|
// next character in string
|
|
++szStr;
|
|
}
|
|
|
|
// adjust the text y position and add the inter-line spacing
|
|
yPos += yOffset + FROM_32(pFont->ySpacing);
|
|
|
|
// check for newline
|
|
if (c == LF_CHAR)
|
|
// next character in string
|
|
++szStr;
|
|
}
|
|
|
|
// 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
|
|
const FONT *pFont = (const FONT *)LockMem(hFont);
|
|
|
|
return pFont->fontDef[c2] != 0;
|
|
}
|
|
|
|
} // End of namespace Tinsel
|