diff --git a/uppsrc/CtrlCore/DrawTextX11.cpp b/uppsrc/CtrlCore/DrawTextX11.cpp index 369352d25..8da86ac23 100644 --- a/uppsrc/CtrlCore/DrawTextX11.cpp +++ b/uppsrc/CtrlCore/DrawTextX11.cpp @@ -1,251 +1,251 @@ -#include "CtrlCore.h" - -#ifdef GUI_X11 - -NAMESPACE_UPP - -#define LTIMING(x) -#define LLOG(x) - -int gtk_antialias = -1; -int gtk_hinting; -String gtk_hintstyle; -String gtk_rgba; - -XftFont *CreateXftFont(Font font, int angle) -{ - LTIMING("CreateXftFont"); - XftFont *xftfont; - double sina, cosa; - Std(font); - int hg = abs(font.GetHeight()); - if(hg == 0) hg = max(GetStdFontCy(), 10); - String face = font.GetFaceName(); - FcPattern *p = FcPatternCreate(); - FcPatternAddString(p, FC_FAMILY, (FcChar8*)~face); - FcPatternAddInteger(p, FC_SLANT, font.IsItalic() ? 110 : 0); - FcPatternAddInteger(p, FC_PIXEL_SIZE, hg); - FcPatternAddInteger(p, FC_WEIGHT, font.IsBold() ? 200 : 100); - FcPatternAddBool(p, FC_MINSPACE, 1); - if(angle) { - FcMatrix mx; - Draw::SinCos(angle, sina, cosa); - mx.xx = cosa; - mx.xy = -sina; - mx.yx = sina; - mx.yy = cosa; - FcPatternAddMatrix(p, FC_MATRIX, &mx); - } - FcResult result; - FcPattern *m = XftFontMatch(Xdisplay, Xscreenno, p, &result); - if(font.IsNonAntiAliased() || gtk_antialias >= 0) { - FcPatternDel(m, FC_ANTIALIAS); - FcPatternAddBool(m, FC_ANTIALIAS, - font.IsNonAntiAliased() ? FcFalse : gtk_antialias ? FcTrue : FcFalse); - } - if(gtk_hinting >= 0) { - FcPatternDel(m, FC_HINTING); - FcPatternAddBool(m, FC_HINTING, gtk_hinting); - } - const char *hs[] = { "hintnone", "hintslight", "hintmedium", "hintfull" }; - for(int i = 0; i < 4; i++) - if(gtk_hintstyle == hs[i]) { - FcPatternDel(m, FC_HINT_STYLE); - FcPatternAddInteger(m, FC_HINT_STYLE, i); - } - const char *rgba[] = { "_", "rgb", "bgr", "vrgb", "vbgr" }; - for(int i = 0; i < __countof(rgba); i++) - if(gtk_rgba == rgba[i]) { - FcPatternDel(m, FC_RGBA); - FcPatternAddInteger(m, FC_RGBA, i); - } - xftfont = XftFontOpenPattern(Xdisplay, m); - FcPatternDestroy(p); - return xftfont; -} - -#define FONTCACHE 37 - -struct XftEntry { - Font font; - int angle; - XftFont *xftfont; -}; - -XftFont *GetXftFont(Font fnt, int angle) -{ - static XftEntry cache[FONTCACHE]; - ONCELOCK { - for(int i = 0; i < FONTCACHE; i++) - cache[i].font.Height(-30000); - } - XftEntry be; - be = cache[0]; - for(int i = 0; i < FONTCACHE; i++) { - XftEntry e = cache[i]; - if(i) - cache[i] = be; - if(e.font == fnt && e.angle == angle) { - if(i) - cache[0] = e; - return e.xftfont; - } - be = e; - } - if(be.xftfont) { - XftFontClose(Xdisplay, be.xftfont); - } - be.font = fnt; - be.angle = angle; - be.xftfont = CreateXftFont(fnt, angle); - cache[0] = be; - return be.xftfont; -} - -CommonFontInfo XftGetFontInfoSys(Font font) -{ - CommonFontInfo fi; - String path; - XftFont *xftfont = GetXftFont(font, 0); - if(xftfont) { - fi.ascent = (int16)xftfont->ascent; - fi.descent = (int16)xftfont->descent; - fi.height = fi.ascent + fi.descent; - fi.lineheight = (int16)xftfont->height; - fi.external = 0; - fi.internal = 0; - fi.overhang = 0; - fi.maxwidth = (int16)xftfont->max_advance_width; - fi.avewidth = fi.maxwidth; - fi.default_char = '?'; - fi.fixedpitch = font.GetFaceInfo() & Font::FIXEDPITCH; - - char *fn = NULL; - XftPatternGetString(xftfont->pattern, XFT_FILE, 0, &fn); - if(fn && strlen(fn) < 250) - strcpy(fi.path, fn); - } - return fi; -} - -GlyphInfo XftGetGlyphInfoSys(Font font, int chr) -{ - wchar h = chr; - XGlyphInfo info; - XftTextExtents16(Xdisplay, GetXftFont(font, 0), &h, 1, &info); - GlyphInfo gi; - gi.width = info.xOff; - gi.lspc = -info.x; - gi.rspc = info.xOff - info.width + info.x; - return gi; -} - -INITBLOCK { -// extern FT_Face (*FTFaceXft)(Font fnt, String *rpath); - extern CommonFontInfo (*GetFontInfoSysXft)(Font font); - extern GlyphInfo (*GetGlyphInfoSysXft)(Font font, int chr); -// FTFaceXft = XftFTFace; - GetFontInfoSysXft = XftGetFontInfoSys; - GetGlyphInfoSysXft = XftGetGlyphInfoSys; -} - -void SystemDraw::DrawTextOp(int x, int y, int angle, const wchar *text, Font font, - Color ink, int n, const int *dx) { - GuiLock __; - LTIMING("DrawText"); - LLOG("DrawText " << ToUtf8(WString(text, n)) << " color:" << ink << " font:" << font); - //TODO - X11 seems to crash when displaying too long strings (?) - int ox = x + actual_offset.x; - int oy = y + actual_offset.y; - SetForeground(ink); - XftColor c; - c.color.red = ink.GetR() << 8; - c.color.green = ink.GetG() << 8; - c.color.blue = ink.GetB() << 8; - c.color.alpha = 0xffff; - c.pixel = GetXPixel(ink.GetR(), ink.GetG(), ink.GetB()); - XftFont *xftfont = GetXftFont(font, angle); - Size offset = Point(0, 0); - double sina, cosa; - int ascent = font.Info().GetAscent(); - if(angle) { - SinCos(angle, sina, cosa); - offset.cx = fround(ascent * sina); - offset.cy = fround(ascent * cosa); - } - int hg = abs(font.GetHeight()); - if(hg == 0) hg = 10; - int underline_thickness = max(hg / 20, 1); - int underline_position = max(hg / 15, int(font.Info().GetDescent() > 0)); - if(angle) { - int xpos = 0; - for(int i = 0; i < n; i++) { - wchar h = text[i]; - XftDrawString16(xftdraw, &c, xftfont, - int(ox + xpos * cosa + offset.cx), - int(oy - xpos * sina + offset.cy), - (FcChar16 *)&h, 1); - xpos += dx ? dx[i] : lastFont[text[i]]; - } - if(font.IsUnderline() || font.IsStrikeout()) { - x += offset.cx; - y += offset.cy; - if(font.IsUnderline()) - DrawLine( - int(x + underline_position * sina), - int(y + underline_position * cosa), - int(x + xpos * cosa + underline_position * sina), - int(y - xpos * sina + underline_position * cosa), - underline_thickness, - ink - ); - if(font.IsStrikeout()) { - int p = 2 * ascent / 3; - DrawLine( - int(x + p * sina), - int(y + p * cosa), - int(x + xpos * cosa + p * sina), - int(y - xpos * sina + p * cosa), - underline_thickness, - ink - ); - } - } - } - else { - if(dx) { - int xpos = ox; - Buffer ch(n); - for(int i = 0; i < n; i++) { - ch[i].ucs4 = text[i]; - ch[i].x = xpos; - ch[i].y = oy + ascent; - xpos += dx[i]; - } - XftDrawCharSpec(xftdraw, &c, xftfont, ch, n); - } - else - XftDrawString16(xftdraw, &c, xftfont, ox, oy + ascent, - (FcChar16 *)text, n); - LLOG("XftColor: r=" << c.color.red << ", g=" << c.color.green << ", b=" << c.color.blue - << ", alpha=" << c.color.alpha << ", pixel=" << FormatIntHex(c.pixel)); - if(font.IsUnderline() || font.IsStrikeout()) { - int cx; - if(dx && n > 0) { - cx = 0; - Sum(cx, dx, dx + n - 1); - cx += lastFont[text[n - 1]]; - } - else - cx = GetTextSize(text, font, n).cx; - if(font.IsUnderline()) - DrawRect(x, y + ascent + underline_position, cx, underline_thickness, ink); - if(font.IsStrikeout()) - DrawRect(x, y + 2 * ascent / 3, cx, underline_thickness, ink); - } - } -} - -END_UPP_NAMESPACE - -#endif +#include "CtrlCore.h" + +#ifdef GUI_X11 + +NAMESPACE_UPP + +#define LTIMING(x) +#define LLOG(x) + +int gtk_antialias = -1; +int gtk_hinting = -1; +String gtk_hintstyle; +String gtk_rgba; + +XftFont *CreateXftFont(Font font, int angle) +{ + LTIMING("CreateXftFont"); + XftFont *xftfont; + double sina, cosa; + Std(font); + int hg = abs(font.GetHeight()); + if(hg == 0) hg = max(GetStdFontCy(), 10); + String face = font.GetFaceName(); + FcPattern *p = FcPatternCreate(); + FcPatternAddString(p, FC_FAMILY, (FcChar8*)~face); + FcPatternAddInteger(p, FC_SLANT, font.IsItalic() ? 110 : 0); + FcPatternAddInteger(p, FC_PIXEL_SIZE, hg); + FcPatternAddInteger(p, FC_WEIGHT, font.IsBold() ? 200 : 100); + FcPatternAddBool(p, FC_MINSPACE, 1); + if(angle) { + FcMatrix mx; + Draw::SinCos(angle, sina, cosa); + mx.xx = cosa; + mx.xy = -sina; + mx.yx = sina; + mx.yy = cosa; + FcPatternAddMatrix(p, FC_MATRIX, &mx); + } + FcResult result; + FcPattern *m = XftFontMatch(Xdisplay, Xscreenno, p, &result); + if(font.IsNonAntiAliased() || gtk_antialias >= 0) { + FcPatternDel(m, FC_ANTIALIAS); + FcPatternAddBool(m, FC_ANTIALIAS, + font.IsNonAntiAliased() ? FcFalse : gtk_antialias ? FcTrue : FcFalse); + } + if(gtk_hinting >= 0) { + FcPatternDel(m, FC_HINTING); + FcPatternAddBool(m, FC_HINTING, gtk_hinting); + } + const char *hs[] = { "hintnone", "hintslight", "hintmedium", "hintfull" }; + for(int i = 0; i < 4; i++) + if(gtk_hintstyle == hs[i]) { + FcPatternDel(m, FC_HINT_STYLE); + FcPatternAddInteger(m, FC_HINT_STYLE, i); + } + const char *rgba[] = { "_", "rgb", "bgr", "vrgb", "vbgr" }; + for(int i = 0; i < __countof(rgba); i++) + if(gtk_rgba == rgba[i]) { + FcPatternDel(m, FC_RGBA); + FcPatternAddInteger(m, FC_RGBA, i); + } + xftfont = XftFontOpenPattern(Xdisplay, m); + FcPatternDestroy(p); + return xftfont; +} + +#define FONTCACHE 37 + +struct XftEntry { + Font font; + int angle; + XftFont *xftfont; +}; + +XftFont *GetXftFont(Font fnt, int angle) +{ + static XftEntry cache[FONTCACHE]; + ONCELOCK { + for(int i = 0; i < FONTCACHE; i++) + cache[i].font.Height(-30000); + } + XftEntry be; + be = cache[0]; + for(int i = 0; i < FONTCACHE; i++) { + XftEntry e = cache[i]; + if(i) + cache[i] = be; + if(e.font == fnt && e.angle == angle) { + if(i) + cache[0] = e; + return e.xftfont; + } + be = e; + } + if(be.xftfont) { + XftFontClose(Xdisplay, be.xftfont); + } + be.font = fnt; + be.angle = angle; + be.xftfont = CreateXftFont(fnt, angle); + cache[0] = be; + return be.xftfont; +} + +CommonFontInfo XftGetFontInfoSys(Font font) +{ + CommonFontInfo fi; + String path; + XftFont *xftfont = GetXftFont(font, 0); + if(xftfont) { + fi.ascent = (int16)xftfont->ascent; + fi.descent = (int16)xftfont->descent; + fi.height = fi.ascent + fi.descent; + fi.lineheight = (int16)xftfont->height; + fi.external = 0; + fi.internal = 0; + fi.overhang = 0; + fi.maxwidth = (int16)xftfont->max_advance_width; + fi.avewidth = fi.maxwidth; + fi.default_char = '?'; + fi.fixedpitch = font.GetFaceInfo() & Font::FIXEDPITCH; + + char *fn = NULL; + XftPatternGetString(xftfont->pattern, XFT_FILE, 0, &fn); + if(fn && strlen(fn) < 250) + strcpy(fi.path, fn); + } + return fi; +} + +GlyphInfo XftGetGlyphInfoSys(Font font, int chr) +{ + wchar h = chr; + XGlyphInfo info; + XftTextExtents16(Xdisplay, GetXftFont(font, 0), &h, 1, &info); + GlyphInfo gi; + gi.width = info.xOff; + gi.lspc = -info.x; + gi.rspc = info.xOff - info.width + info.x; + return gi; +} + +INITBLOCK { +// extern FT_Face (*FTFaceXft)(Font fnt, String *rpath); + extern CommonFontInfo (*GetFontInfoSysXft)(Font font); + extern GlyphInfo (*GetGlyphInfoSysXft)(Font font, int chr); +// FTFaceXft = XftFTFace; + GetFontInfoSysXft = XftGetFontInfoSys; + GetGlyphInfoSysXft = XftGetGlyphInfoSys; +} + +void SystemDraw::DrawTextOp(int x, int y, int angle, const wchar *text, Font font, + Color ink, int n, const int *dx) { + GuiLock __; + LTIMING("DrawText"); + LLOG("DrawText " << ToUtf8(WString(text, n)) << " color:" << ink << " font:" << font); + //TODO - X11 seems to crash when displaying too long strings (?) + int ox = x + actual_offset.x; + int oy = y + actual_offset.y; + SetForeground(ink); + XftColor c; + c.color.red = ink.GetR() << 8; + c.color.green = ink.GetG() << 8; + c.color.blue = ink.GetB() << 8; + c.color.alpha = 0xffff; + c.pixel = GetXPixel(ink.GetR(), ink.GetG(), ink.GetB()); + XftFont *xftfont = GetXftFont(font, angle); + Size offset = Point(0, 0); + double sina, cosa; + int ascent = font.Info().GetAscent(); + if(angle) { + SinCos(angle, sina, cosa); + offset.cx = fround(ascent * sina); + offset.cy = fround(ascent * cosa); + } + int hg = abs(font.GetHeight()); + if(hg == 0) hg = 10; + int underline_thickness = max(hg / 20, 1); + int underline_position = max(hg / 15, int(font.Info().GetDescent() > 0)); + if(angle) { + int xpos = 0; + for(int i = 0; i < n; i++) { + wchar h = text[i]; + XftDrawString16(xftdraw, &c, xftfont, + int(ox + xpos * cosa + offset.cx), + int(oy - xpos * sina + offset.cy), + (FcChar16 *)&h, 1); + xpos += dx ? dx[i] : lastFont[text[i]]; + } + if(font.IsUnderline() || font.IsStrikeout()) { + x += offset.cx; + y += offset.cy; + if(font.IsUnderline()) + DrawLine( + int(x + underline_position * sina), + int(y + underline_position * cosa), + int(x + xpos * cosa + underline_position * sina), + int(y - xpos * sina + underline_position * cosa), + underline_thickness, + ink + ); + if(font.IsStrikeout()) { + int p = 2 * ascent / 3; + DrawLine( + int(x + p * sina), + int(y + p * cosa), + int(x + xpos * cosa + p * sina), + int(y - xpos * sina + p * cosa), + underline_thickness, + ink + ); + } + } + } + else { + if(dx) { + int xpos = ox; + Buffer ch(n); + for(int i = 0; i < n; i++) { + ch[i].ucs4 = text[i]; + ch[i].x = xpos; + ch[i].y = oy + ascent; + xpos += dx[i]; + } + XftDrawCharSpec(xftdraw, &c, xftfont, ch, n); + } + else + XftDrawString16(xftdraw, &c, xftfont, ox, oy + ascent, + (FcChar16 *)text, n); + LLOG("XftColor: r=" << c.color.red << ", g=" << c.color.green << ", b=" << c.color.blue + << ", alpha=" << c.color.alpha << ", pixel=" << FormatIntHex(c.pixel)); + if(font.IsUnderline() || font.IsStrikeout()) { + int cx; + if(dx && n > 0) { + cx = 0; + Sum(cx, dx, dx + n - 1); + cx += lastFont[text[n - 1]]; + } + else + cx = GetTextSize(text, font, n).cx; + if(font.IsUnderline()) + DrawRect(x, y + ascent + underline_position, cx, underline_thickness, ink); + if(font.IsStrikeout()) + DrawRect(x, y + 2 * ascent / 3, cx, underline_thickness, ink); + } + } +} + +END_UPP_NAMESPACE + +#endif