diff options
author | Jef <jef@targetspot.com> | 2024-09-24 08:54:57 -0400 |
---|---|---|
committer | Jef <jef@targetspot.com> | 2024-09-24 08:54:57 -0400 |
commit | 20d28e80a5c861a9d5f449ea911ab75b4f37ad0d (patch) | |
tree | 12f17f78986871dd2cfb0a56e5e93b545c1ae0d0 /Src/Wasabi/api/font/bitmapfont.cpp | |
parent | 537bcbc86291b32fc04ae4133ce4d7cac8ebe9a7 (diff) | |
download | winamp-20d28e80a5c861a9d5f449ea911ab75b4f37ad0d.tar.gz |
Initial community commit
Diffstat (limited to 'Src/Wasabi/api/font/bitmapfont.cpp')
-rw-r--r-- | Src/Wasabi/api/font/bitmapfont.cpp | 394 |
1 files changed, 394 insertions, 0 deletions
diff --git a/Src/Wasabi/api/font/bitmapfont.cpp b/Src/Wasabi/api/font/bitmapfont.cpp new file mode 100644 index 00000000..fe85abda --- /dev/null +++ b/Src/Wasabi/api/font/bitmapfont.cpp @@ -0,0 +1,394 @@ +#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': /**/ ic = L'c'; break; + case L'\u00E8': /**/ case L'\u00E9': /**/ case L'\u00EB': /**/case L'\u00EA':/**/ 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'':/**/ 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'' || 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 +} + |