openmohaa/code/uilib/uifont.cpp

426 lines
9.4 KiB
C++
Raw Normal View History

2016-03-27 11:49:47 +02:00
/*
===========================================================================
Copyright (C) 2015 the OpenMoHAA team
This file is part of OpenMoHAA source code.
OpenMoHAA source code 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.
OpenMoHAA source code 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 OpenMoHAA source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
#include "ui_local.h"
2023-10-02 20:18:24 +02:00
qboolean UI_FontDBCSIsLeadByte(fontheader_t *font, unsigned short uch);
int UI_FontCodeSearch(const fontheader_t *font, unsigned short uch);
2016-03-27 11:49:47 +02:00
UIFont::UIFont()
{
2023-10-02 20:18:24 +02:00
m_font = uii.Rend_LoadFont("verdana-14");
if (!m_font) {
uii.Sys_Error(ERR_DROP, "Couldn't load font Verdana\n");
}
2016-03-27 11:49:47 +02:00
2023-10-02 20:18:24 +02:00
color = UBlack;
setColor(color);
2016-03-27 11:49:47 +02:00
}
2023-10-02 20:18:24 +02:00
UIFont::UIFont(const char *fn)
2016-03-27 11:49:47 +02:00
{
2023-10-02 20:18:24 +02:00
setFont(fn);
2016-03-27 11:49:47 +02:00
}
2023-10-02 20:18:24 +02:00
void UIFont::Print(float x, float y, const char *text, size_t maxlen, qboolean bVirtualScreen)
2016-03-27 11:49:47 +02:00
{
2023-10-02 20:18:24 +02:00
uii.Rend_SetColor(color);
uii.Rend_DrawString(m_font, text, x, y, maxlen, bVirtualScreen);
2016-03-27 11:49:47 +02:00
}
2023-10-02 20:18:24 +02:00
void UIFont::PrintJustified(
const UIRect2D& rect, fonthorzjustify_t horz, fontvertjustify_t vert, const char *text, float *vVirtualScale
)
2016-03-27 11:49:47 +02:00
{
2023-10-02 20:18:24 +02:00
float newx, newy;
int textwidth, textheight;
UIRect2D sizedRect;
const char *source;
char *dest;
char string[2048];
if (vVirtualScale) {
sizedRect.pos.x = rect.pos.x / vVirtualScale[0];
sizedRect.pos.y = rect.pos.y / vVirtualScale[1];
sizedRect.size.width = rect.size.width / vVirtualScale[0];
sizedRect.size.height = rect.size.height / vVirtualScale[1];
} else {
sizedRect = rect;
}
if (horz == FONT_JUSTHORZ_LEFT && vert == FONT_JUSTVERT_TOP) {
// no need to justify
Print(sizedRect.pos.x, sizedRect.pos.y, text, -1, vVirtualScale != NULL);
return;
}
textheight = getHeight(text, -1, qfalse);
switch (vert) {
case FONT_JUSTVERT_TOP:
newy = sizedRect.pos.y;
break;
case FONT_JUSTVERT_CENTER:
newy = sizedRect.pos.y + (sizedRect.size.height - textheight) * 0.5;
break;
case FONT_JUSTVERT_BOTTOM:
newy = sizedRect.pos.y + sizedRect.size.height - textheight;
break;
default:
newy = 0;
break;
}
source = text;
while (*source) {
// skip new lines
while (*source == '\n') {
source++;
}
if (!*source) {
// don't print an empty string
return;
}
dest = string;
do {
*dest++ = *source++;
} while (*source && *source != '\n');
*dest = 0;
textwidth = getWidth(string, -1);
switch (horz) {
case FONT_JUSTHORZ_CENTER:
newx = sizedRect.pos.x + (sizedRect.size.width - textwidth) * 0.5;
break;
case FONT_JUSTHORZ_LEFT:
newx = sizedRect.pos.x;
break;
case FONT_JUSTHORZ_RIGHT:
newx = sizedRect.pos.x + sizedRect.size.width - textwidth;
break;
default:
newx = 0.0;
break;
}
Print(newx, newy, string, -1, vVirtualScale != NULL);
// expand for newline
newy += getHeight(" ", -1, qfalse);
}
2016-03-27 11:49:47 +02:00
}
2023-10-02 20:18:24 +02:00
void UIFont::setColor(UColor col)
2016-03-27 11:49:47 +02:00
{
2023-10-02 20:18:24 +02:00
color = col;
2016-03-27 11:49:47 +02:00
}
2023-10-02 20:18:24 +02:00
void UIFont::setAlpha(float alpha)
2016-03-27 11:49:47 +02:00
{
2023-10-02 20:18:24 +02:00
color.a = alpha;
2016-03-27 11:49:47 +02:00
}
2023-10-02 20:18:24 +02:00
void UIFont::setFont(const char *fontname)
2016-03-27 11:49:47 +02:00
{
2023-10-02 20:18:24 +02:00
m_font = uii.Rend_LoadFont(fontname);
if (!m_font) {
uii.Sys_Error(ERR_DROP, "Couldn't load font %s\n", fontname);
}
2016-03-27 11:49:47 +02:00
}
2023-10-02 20:18:24 +02:00
int UIFont::getWidth(const char *text, int maxlen)
2016-03-27 11:49:47 +02:00
{
2023-10-02 20:18:24 +02:00
return UI_FontStringWidth(m_font, text, maxlen);
2016-03-27 11:49:47 +02:00
}
2023-10-02 20:18:24 +02:00
int UIFont::getCharWidth(unsigned short ch)
2016-03-27 11:49:47 +02:00
{
2023-10-02 20:18:24 +02:00
int index;
int indirected;
if (!m_font) {
return 0;
}
if (ch == '\t') {
ch = ' ';
}
if (m_font->numPages) {
int code = CodeSearch(ch);
if (code < 0) {
return 0;
}
index = m_font->charTable[code].index;
indirected = m_font->charTable[code].loc;
} else {
indirected = m_font->sgl[0]->indirection[ch];
if (indirected < 0 || indirected > 255) {
return 0;
}
index = 0;
}
if (ch == '\t') {
return m_font->sgl[index]->locations[indirected].size[0] * 256.0 * 3.0;
2023-10-02 20:18:24 +02:00
} else {
return m_font->sgl[index]->locations[indirected].size[0] * 256.0;
}
2016-03-27 11:49:47 +02:00
}
2023-10-02 20:18:24 +02:00
int UIFont::getHeight(const char *text, int maxlen, qboolean bVirtual)
2016-03-27 11:49:47 +02:00
{
2023-10-02 20:18:24 +02:00
float height;
int i;
2016-03-27 11:49:47 +02:00
2023-10-02 20:18:24 +02:00
if (!m_font) {
return 0;
}
2016-03-27 11:49:47 +02:00
2023-10-02 20:18:24 +02:00
height = getHeight(bVirtual);
2016-03-27 11:49:47 +02:00
2023-10-02 20:18:24 +02:00
for (i = 0; text[i]; i++) {
if (maxlen != -1 && i > maxlen) {
break;
}
2016-03-27 11:49:47 +02:00
2023-10-02 20:18:24 +02:00
if (text[i] == '\n') {
height += getHeight(bVirtual);
}
}
2016-03-27 11:49:47 +02:00
2023-10-02 20:18:24 +02:00
return height;
2016-03-27 11:49:47 +02:00
}
2023-10-02 20:18:24 +02:00
int UIFont::getHeight(qboolean bVirtual)
2016-03-27 11:49:47 +02:00
{
2023-10-02 20:18:24 +02:00
if (bVirtual) {
if (m_font) {
return (m_font->sgl[0]->height * uid.vidHeight / 480.0);
} else {
return (16.0 * uid.vidHeight / 480.0);
}
} else {
if (m_font) {
return m_font->sgl[0]->height;
} else {
return 16;
}
}
2016-03-27 11:49:47 +02:00
}
int UIFont::CodeSearch(unsigned short uch)
{
2023-10-02 20:18:24 +02:00
return UI_FontCodeSearch(m_font, uch);
}
2016-03-27 11:49:47 +02:00
2023-10-02 20:18:24 +02:00
qboolean UI_FontDBCSIsLeadByte(fontheader_t *font, unsigned short uch)
2016-03-27 11:49:47 +02:00
{
// Byte ranges found in Wikipedia articles with relevant search strings in each case
switch (font->codePage) {
case 932:
// Shift_jis
2023-10-02 20:18:24 +02:00
return ((uch >= 0x81) && (uch <= 0x9F)) || ((uch >= 0xE0) && (uch <= 0xFC));
// Lead bytes F0 to FC may be a Microsoft addition.
case 936:
// GBK
return (uch >= 0x81) && (uch <= 0xFE);
case 949:
// Korean Wansung KS C-5601-1987
return (uch >= 0x81) && (uch <= 0xFE);
case 950:
// Big5
return (uch >= 0x81) && (uch <= 0xFE);
case 1361:
// Korean Johab KS C-5601-1992
2023-10-02 20:18:24 +02:00
return ((uch >= 0x84) && (uch <= 0xD3)) || ((uch >= 0xD8) && (uch <= 0xDE)) || ((uch >= 0xE0) && (uch <= 0xF9));
}
return false;
}
2023-10-02 20:18:24 +02:00
int UI_FontCodeSearch(const fontheader_t *font, unsigned short uch)
{
int mid;
int l, r;
r = font->charTableLength;
l = 0;
while (l < r) {
mid = (l + r) / 2;
if (font->charTable[mid].cp > uch) {
r = (l + r) / 2;
continue;
}
if (uch == font->charTable[mid].cp) {
return (l + r) / 2;
}
l = mid + 1;
}
if (uch != font->charTable[l].cp) {
return -1;
}
return l;
}
2023-10-02 20:18:24 +02:00
float UI_FontgetCharWidthf(fontheader_t *font, unsigned short uch)
{
2023-10-02 20:18:24 +02:00
int index;
int indirected;
if (!font) {
return 0.f;
}
if (uch == '\t') {
uch = ' ';
}
if (font->numPages) {
int code = UI_FontCodeSearch(font, uch);
if (code < 0) {
return 0.f;
}
index = font->charTable[code].index;
indirected = font->charTable[code].loc;
} else {
indirected = font->sgl[0]->indirection[uch];
if (indirected < 0 || indirected > 255) {
return 0.f;
}
index = 0;
}
if (uch == '\t') {
return font->sgl[index]->locations[indirected].size[0] * 3.0;
} else {
return font->sgl[index]->locations[indirected].size[0];
}
}
2023-10-02 20:18:24 +02:00
int UI_FontStringMaxWidth(fontheader_t *pFont, const char *pszString, int iMaxLen)
{
2023-10-02 20:18:24 +02:00
float widths = 0.0;
float maxwidths = iMaxLen / 256.0f;
2023-10-02 20:18:24 +02:00
int i;
if (!pFont) {
return 0;
}
2023-10-02 20:18:24 +02:00
i = 0;
for (;;) {
unsigned short uch = pszString[i++];
2023-10-02 20:18:24 +02:00
if (uch == 0 || (iMaxLen != -1 && i > iMaxLen)) {
break;
}
2023-10-02 20:18:24 +02:00
if (UI_FontDBCSIsLeadByte(pFont, uch)) {
uch = (uch << 8) | pszString[i];
if (!pszString[i]) {
break;
}
2023-10-02 20:18:24 +02:00
i++;
}
2016-03-27 11:49:47 +02:00
2023-10-02 20:18:24 +02:00
if (uch == '\n') {
widths = 0.0;
2023-10-02 20:18:24 +02:00
} else {
widths += UI_FontgetCharWidthf(pFont, uch);
if (maxwidths < widths) {
return i - 1;
}
}
}
return -1;
}
2023-10-02 20:18:24 +02:00
int UI_FontStringWidth(fontheader_t *pFont, const char *pszString, int iMaxLen)
{
2023-10-02 20:18:24 +02:00
float widths = 0.0;
float maxwidths = 0.0;
2023-10-02 20:18:24 +02:00
int i;
if (!pFont) {
return 0;
}
2023-10-02 20:18:24 +02:00
i = 0;
for (;;) {
unsigned short uch = pszString[i++];
2023-10-02 20:18:24 +02:00
if (uch == 0 || (iMaxLen != -1 && i > iMaxLen)) {
break;
}
2023-10-02 20:18:24 +02:00
if (UI_FontDBCSIsLeadByte(pFont, uch)) {
uch = (uch << 8) | pszString[i];
if (!pszString[i]) {
break;
}
2016-03-27 11:49:47 +02:00
2023-10-02 20:18:24 +02:00
i++;
}
2016-03-27 11:49:47 +02:00
2023-10-02 20:18:24 +02:00
if (uch == '\n') {
widths = 0.0;
2023-10-02 20:18:24 +02:00
} else {
widths += UI_FontgetCharWidthf(pFont, uch);
if (maxwidths < widths) {
maxwidths = widths;
}
}
}
return maxwidths * 256.0;
2016-03-27 11:49:47 +02:00
}