123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394 |
- #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
- }
|