Files
winamp/Src/Wasabi/api/font/bitmapfont.cpp
2024-09-24 14:54:57 +02:00

395 lines
16 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#include "precomp.h"
// ============================================================================================================================================================
// Font abstract class + statics to install TT fonts and Bitmap fonts
// ============================================================================================================================================================
#include "bitmapfont.h"
#include <api/wnd/fontdef.h>
#include <api/config/items/cfgitem.h>
#ifdef WASABI_COMPILE_SKIN
#include <api/skin/skin.h>
#endif
#ifdef WA3COMPATIBILITY
#endif
#include <tataki/canvas/ifc_canvas.h>
#include <tataki/region/api_region.h>
#include <api/skin/skinparse.h>
// ============================================================================================================================================================
// BitmapFont implementation.
// ============================================================================================================================================================
// -------------------------------------------------------------------------------------------------------------------------------------------------------------
BitmapFont::BitmapFont() : scriptid(0), char_width(0), char_height(0), hor_spacing(0), vert_spacing(0) {
}
// -------------------------------------------------------------------------------------------------------------------------------------------------------------
BitmapFont::~BitmapFont() {
}
// -------------------------------------------------------------------------------------------------------------------------------------------------------------
int BitmapFont::isBitmap() {
return 1;
}
// -------------------------------------------------------------------------------------------------------------------------------------------------------------
const wchar_t *BitmapFont::getFaceName() {
return getFontId();
}
// -------------------------------------------------------------------------------------------------------------------------------------------------------------
void BitmapFont::textOut(ifc_canvas *c, int x, int y, const wchar_t *txt, int size, int bold, int opaque, int underline, int italic, ARGB32 color, ARGB32 bkcolor, int xoffset, int yoffset, int antialiased) {
do_textOut(this, c, x+xoffset, y+yoffset, -1, -1, txt, size, bold, opaque, underline, italic, STDFONT_LEFT, color, WA_FONT_TEXTOUT_NORMAL);
}
// -------------------------------------------------------------------------------------------------------------------------------------------------------------
void BitmapFont::textOut2(ifc_canvas *c, int x, int y, int w, int h, const wchar_t *txt, int size, int bold, int opaque, int underline, int italic, int align, ARGB32 color, ARGB32 bkcolor, int xoffset, int yoffset, int antialiased) {
do_textOut(this, c, x+xoffset, y+yoffset, x+xoffset+w, y+yoffset+h, txt, size, bold, opaque, underline, italic, align, color, WA_FONT_TEXTOUT_RECT);
}
// -------------------------------------------------------------------------------------------------------------------------------------------------------------
void BitmapFont::textOutEllipsed(ifc_canvas *c, int x, int y, int w, int h, const wchar_t *txt, int size, int bold, int opaque, int underline, int italic, int align, ARGB32 color, ARGB32 bkcolor, int xoffset, int yoffset, int antialiased) {
do_textOut(this, c, x+xoffset, y+yoffset, x+xoffset+w, y+yoffset+h, txt, size, bold, opaque, underline, italic, align, color, WA_FONT_TEXTOUT_ELLIPSED);
}
// -------------------------------------------------------------------------------------------------------------------------------------------------------------
void BitmapFont::textOutWrapped(ifc_canvas *c, int x, int y, int w, int h, const wchar_t *txt, int size, int bold, int opaque, int underline, int italic, int align, ARGB32 color, ARGB32 bkcolor, int xoffset, int yoffset, int antialiased) {
do_textOut(this, c, x+xoffset, y+yoffset, x+xoffset+w, y+yoffset+h, txt, size, bold, opaque, underline, italic, align, color, WA_FONT_TEXTOUT_WRAPPED);
}
// -------------------------------------------------------------------------------------------------------------------------------------------------------------
void BitmapFont::textOutWrappedPathed(ifc_canvas *c, int x, int y, int w, const wchar_t *txt, int size, int bold, int opaque, int underline, int italic, int align, ARGB32 color, ARGB32 bkcolor, int xoffset, int yoffset, int antialiased) {
do_textOut(this, c, x+xoffset, y+yoffset, x+xoffset+w, -1, txt, size, bold, opaque, underline, italic, align, color, WA_FONT_TEXTOUT_WRAPPEDPATHED);
}
// -------------------------------------------------------------------------------------------------------------------------------------------------------------
void BitmapFont::textOutCentered(ifc_canvas *c, RECT *r, const wchar_t *txt, int size, int bold, int opaque, int underline, int italic, int align, ARGB32 color, ARGB32 bkcolor, int xoffset, int yoffset, int antialiased) {
do_textOut(this, c, r->left, r->top, r->right-r->left, r->bottom-r->top, txt, size, bold, opaque, underline, italic, align, color, WA_FONT_TEXTOUT_CENTERED);
}
// -------------------------------------------------------------------------------------------------------------------------------------------------------------
int BitmapFont::getTextWidth(ifc_canvas *c, const wchar_t *text, int size, int bold, int underline, int italic, int antialiased)
{
return wcslen(text) * char_width + wcslen(text)*hor_spacing;
}
// -------------------------------------------------------------------------------------------------------------------------------------------------------------
int BitmapFont::getTextHeight(ifc_canvas *c, const wchar_t *text, int size, int bold, int underline, int italic, int antialiased)
{
return char_height;
}
// -------------------------------------------------------------------------------------------------------------------------------------------------------------
int BitmapFont::getTextHeight2(ifc_canvas *c, int size, int bold, int underline, int italic, int antialiased)
{
return char_height;
}
// -------------------------------------------------------------------------------------------------------------------------------------------------------------
void BitmapFont::getTextExtent(ifc_canvas *c, const wchar_t *text, int *w, int *h, int size, int bold, int underline, int italic, int antialiased)
{
if (w) *w = getTextWidth(c, text, size, bold, underline, italic, antialiased);
if (h) *h = char_height;
}
// -------------------------------------------------------------------------------------------------------------------------------------------------------------
void BitmapFont::setFontBitmap(const wchar_t *name_or_element, const wchar_t *path)
{
StringW pathfile;
if (!wcschr(name_or_element, L':'))
{
pathfile = path;
pathfile.AddBackslash();
}
pathfile.cat(name_or_element);
if (!WACCESS(pathfile, 0))
table = pathfile;
else
table = name_or_element;
}
// -------------------------------------------------------------------------------------------------------------------------------------------------------------
void BitmapFont::setFontMetrics(int _char_width, int _char_height, int _hor_spacing, int _vert_spacing) {
char_width = _char_width;
char_height = _char_height;
hor_spacing = _hor_spacing;
vert_spacing = _vert_spacing;
}
// -------------------------------------------------------------------------------------------------------------------------------------------------------------
int BitmapFont::getHorizontalSpacing() {
return hor_spacing;
}
// -------------------------------------------------------------------------------------------------------------------------------------------------------------
int BitmapFont::getVerticalSpacing() {
return vert_spacing;
}
// -------------------------------------------------------------------------------------------------------------------------------------------------------------
int BitmapFont::getCharWidth() {
return char_width;
}
// -------------------------------------------------------------------------------------------------------------------------------------------------------------
int BitmapFont::getCharHeight() {
return char_height;
}
AutoSkinBitmap *BitmapFont::getCharTable() {
return &table;
}
// -------------------------------------------------------------------------------------------------------------------------------------------------------------
void BitmapFont::getXYfromChar(wchar_t ic, int *x, int *y)
{
int c,c2=0;
switch (ic)
{
case L'\u00B0': /*¡*/ ic = L'0'; break;
case L'\u00C6':/*®*/ ic = L'A'; break;
// case '\u00C1':/*ç*/ ic = L'A'; break;
// case '\u00C2': ic = L'A'; break;
case L'\u00C7': /**/ ic = L'C'; break;
case L'\u00C9':/*ƒ*/ ic = L'E'; break;
case L'\u00E0': /*ˆ*/ case L'\u00E1': /*‡*/ case L'\u00E2': /*‰*/ ic = L'a'; break;
case L'\u00E6':/*¾*/ ic = L'a'; break;
case L'\u00E7': /*<2A>*/ ic = L'c'; break;
case L'\u00E8': /*<2A>*/ case L'\u00E9': /*Ž*/ case L'\u00EB': /**/case L'\u00EA':/*<2A>*/ ic = L'e'; break;
case L'\u00EC':/*“*/ case L'\u00ED':/**/ case L'\u00EE':/*”*/ case L'\u00EF':/*•*/ ic = L'i'; break;
#ifdef _WIN32
case L'':/*—*/ case L'˜':/*˜*/ case L'':/*™*/ ic = L'o'; break;
case L'œ':/*œ*/ case L'<EFBFBD>':/*<2A>*/ case L'ž':/*ž*/ ic = L'u'; break;
case L'Ø':/*Ø*/ ic = L'y'; break;
case L'':/*†*/ ic = L'U'; break;
#else
#warning change these to \u
#endif
case L'\u00D1':/*„*/ ic = L'N'; break;
case L'\u00F1':/**/ ic = L'n'; break;
case L'\u00FC': /*Ÿ*/ ic = L'u'; break;
case L'\u0192':/*Ä*/ ic = L'f'; break;
default: break;
} // quick relocations
if (ic <= L'Z' && ic >= L'A') c = (ic-'A');
else if (ic <= L'z' && ic >= L'a') c = (ic-'a');
else if (ic == L' ') c = 30;
else {
c2 += char_height;
if (ic == L'\1') c=10;
else if (ic == L'.') c = 11;
else if (ic <= L'9' && ic >= L'0') c = ic - L'0';
else if (ic == L':') c = 12;
else if (ic == L'(') c = 13;
else if (ic == L')') c = 14;
else if (ic == L'-') c = 15;
else if (ic == L'\'' || ic=='`') c = 16;
else if (ic == L'!') c = 17;
else if (ic == L'_') c = 18;
else if (ic == L'+') c = 19;
else if (ic == L'\\') c = 20;
else if (ic == L'/') c = 21;
else if (ic == L'[' || ic == L'{' || ic == L'<') c = 22;
else if (ic == L']' || ic == L'}' || ic == L'>') c = 23;
else if (ic == L'~' || ic == L'^') c = 24;
else if (ic == L'&') c = 25;
else if (ic == L'%') c = 26;
else if (ic == L',') c = 27;
else if (ic == L'=') c = 28;
else if (ic == L'$') c = 29;
else if (ic == L'#') c = 30;
else
{
c2 += char_height;
#ifdef _WIN32
if (ic == L'<EFBFBD>' || ic == L'Œ') c = 0;
else if (ic == L'' || ic == L'š') c = 1;
else if (ic == L'' || ic == L'Š') c = 2;
else
#else
#warning change these to \u
#endif
if (ic == L'?') c = 3;
else if (ic == L'*') c = 4;
else {
c2 = 0;
if (ic == L'"') c = 26;
else if (ic == L'@') c = 27;
else c = 30;
}
}
}
c*=char_width;
*x=c;
*y=c2;
}
// -------------------------------------------------------------------------------------------------------------------------------------------------------------
int BitmapFont::getWordLength(const wchar_t *p) {
int n=0;
while (p && *p && *p != L' ') {
p++;
n++;
}
return n;
}
// -------------------------------------------------------------------------------------------------------------------------------------------------------------
wchar_t *BitmapFont::makeLine(const wchar_t *t, BitmapFont *font, int line, int width, int style) {
static wchar_t str[4096];
wchar_t *p = (wchar_t *)t;
size_t len = wcslen(t);
switch (style) {
case WA_FONT_TEXTOUT_NORMAL:
case WA_FONT_TEXTOUT_RECT:
case WA_FONT_TEXTOUT_ELLIPSED:
case WA_FONT_TEXTOUT_CENTERED:
return line == 0 ? (wchar_t *)t : NULL;
case WA_FONT_TEXTOUT_WRAPPEDPATHED:
case WA_FONT_TEXTOUT_WRAPPED: {
size_t maxchar = width / (font->getCharWidth() + font->getVerticalSpacing());
for (int i = 0; i < line; i++) {
wchar_t *oldp = p;
p += maxchar;
if ((size_t)(p-t) >= len) return NULL;
while (p >= t) {
if (p == t || *(p-1) == L' ')
break;
p--;
}
if (p == oldp) {
p += maxchar;
while (p && *p && *p != L' ')
p++;
}
}
WCSCPYN(str, p, maxchar);
wchar_t *d = &str[maxchar-1];
int wr=0;
if (wcslen(p) > maxchar && *(p+maxchar) != L' ' && wcschr(str, L' '))
while (d >= str) {
if (*d == L' ') {
*d = 0;
wr=1;
}
else {
if (wr) break;
d--;
}
}
return str;
}
}
return NULL;
}
// -------------------------------------------------------------------------------------------------------------------------------------------------------------
void BitmapFont::do_textOut(BitmapFont *font, ifc_canvas *c, int x, int y, int x2, int y2, const wchar_t *text, int size, int bold, int opaque, int underline, int italic, int align, ARGB32 color, int style)
{
static wchar_t *dotdotdot=L"...";
if (!text) return;
BaseCloneCanvas canvas;
int ret = canvas.clone(c);
if (!ret) return;
RECT bounds;
RECT defbounds={x,y,x2,y2};
int __w, __h;
c->getDim(&__w, &__h, NULL);
if (x2 == -1) defbounds.right = defbounds.left + __w;
if (y2 == -1) defbounds.bottom = defbounds.top + __h;
#ifdef _WIN32
RegionI oldclip(&canvas, &defbounds); // get clipping region in oldclip
RegionI *andclip=NULL;
oldclip.getBox(&bounds); // get boundaries
#else
bounds = defbounds;
#warning port me
#endif
/* if (x2 != -1 && y2 != -1) {
andclip = new RegionI(x, y, x2, y2); // create region for rect
andclip->andRegion(oldclip); // and them
canvas.selectClipRgn(andclip); // select new clipping rect
andclip->getBox(&bounds); // update boundaries
}*/
int lc=-1;
wchar_t *p = dotdotdot+3; // just a zero to triger next line
int _x = x+(font->getHorizontalSpacing()/2);
int _y = y;
if (style == WA_FONT_TEXTOUT_CENTERED) {
_y += (y2 - y - font->getCharHeight()) / 2;
}
_y -= font->getCharHeight() + font->getVerticalSpacing();
int xp, yp;
while (p) {
if (!*p) {
lc++;
p = makeLine(text, font, lc, x2-x, style);
if (!p || !*p) break;
_x = x+(font->getHorizontalSpacing()/2);
_y += font->getCharHeight() + font->getVerticalSpacing();
if ((align == STDFONT_RIGHT || align == STDFONT_CENTER) && x2 != -1) {
int l = wcslen(p);
_x -= l * (font->getCharWidth() + font->getHorizontalSpacing()) - (x2-x);
}
if (align == STDFONT_CENTER)
_x = x + (_x - x) / 2;
}
if ((style == WA_FONT_TEXTOUT_ELLIPSED || style == WA_FONT_TEXTOUT_WRAPPEDPATHED) && x2 != -1) {
if (_x > x2 - 4 * (font->getCharWidth() + font->getHorizontalSpacing()) && wcslen(p) > 3) {
p = dotdotdot;
}
}
font->getXYfromChar(*p, &xp, &yp);
RECT r;
r.left = xp;
r.top = yp;
r.right = xp + font->getCharWidth();
r.bottom = yp + font->getCharHeight();
RECT dst;
dst.left = _x;
dst.top = _y;
dst.right = _x + font->getCharWidth();
dst.bottom = _y + font->getCharHeight();
if (Wasabi::Std::rectIntersect(dst, bounds))
// if (IntersectRect(&dummy, &dst, &bounds)) // port me / checks clipping, not passed x,y,x2,y2
font->getCharTable()->stretchToRectAlpha(&canvas, &r, &dst, 255);
p++;
_x += font->getCharWidth();
_x += font->getHorizontalSpacing();
}
#ifdef _WIN32
if (andclip) {
canvas.selectClipRgn(&oldclip); // restore previously saved clipping region
delete andclip;
}
#else
#warning port me
#endif
}