#include "precomp.h" // ============================================================================================================================================================ // Font abstract class + statics to install TT fonts and Bitmap fonts // ============================================================================================================================================================ #include "bitmapfont.h" #include #include #ifdef WASABI_COMPILE_SKIN #include #endif #ifdef WA3COMPATIBILITY #endif #include #include #include // ============================================================================================================================================================ // 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 }