module patch.font2; import std.conv : to; import std.string : toStringz; import patches : isPatchEnabled; import config : font2; import st : xw, xrealloc, die; import xft_types : XftFont; import deimos.X11.Xlib : Display; // Import font cache variables from x module import x : Fontcache, frc, frclen, frccap, defaultfontsize, usedfontsize; enum FRC_NORMAL = 0; enum FRC_ITALIC = 1; enum FRC_BOLD = 2; enum FRC_ITALICBOLD = 3; // External C declarations for Xft and fontconfig functions extern(C) { struct FcPattern; alias FcChar8 = ubyte; // FcResult as an enum enum FcResult { FcResultMatch = 0, FcResultNoMatch, FcResultTypeMismatch, FcResultNoId, FcResultOutOfMemory } // Xft functions XftFont* XftFontOpenPattern(Display*, FcPattern*); FcPattern* XftXlfdParse(const(char)*, int, int); void XftDefaultSubstitute(Display*, int, FcPattern*); static if (isPatchEnabled!"USE_XFTFONTMATCH_PATCH") { FcPattern* XftFontMatch(Display*, int, FcPattern*, FcResult*); } // Fontconfig functions void FcPatternDestroy(FcPattern*); FcPattern* FcNameParse(const(FcChar8)*); int FcPatternGetDouble(FcPattern*, const(char)*, int, double*); int FcPatternDel(FcPattern*, const(char)*); int FcPatternAddDouble(FcPattern*, const(char)*, double); int FcPatternAddBool(FcPattern*, const(char)*, int); int FcPatternAddInteger(FcPattern*, const(char)*, int); void FcConfigSubstitute(void*, FcPattern*, int); FcPattern* FcFontMatch(void*, FcPattern*, FcResult*); // Constants enum FC_PIXEL_SIZE = "pixelsize"; enum FC_SIZE = "size"; enum FC_SCALABLE = "scalable"; enum FC_SLANT = "slant"; enum FC_WEIGHT = "weight"; enum FC_SLANT_ITALIC = 100; enum FC_SLANT_ROMAN = 0; enum FC_WEIGHT_BOLD = 200; enum FcResultMatch = 0; enum FcMatchPattern = 0; } static if (isPatchEnabled!"FONT2_PATCH") { int xloadsparefont(FcPattern* pattern, int flags) { FcPattern* match; FcResult result; static if (isPatchEnabled!"USE_XFTFONTMATCH_PATCH") { match = XftFontMatch(xw.dpy, xw.scr, pattern, &result); } else { match = FcFontMatch(null, pattern, &result); } if (!match) { return 1; } frc[frclen].font = XftFontOpenPattern(xw.dpy, match); if (!frc[frclen].font) { FcPatternDestroy(match); return 1; } frc[frclen].flags = flags; frc[frclen].unicodep = 0; frclen++; return 0; } void xloadsparefonts() { FcPattern* pattern; double fontval; int fc; if (frclen != 0) die("can't embed spare fonts. cache isn't empty"); fc = cast(int)font2.length; if (fc == 0) return; if (frccap < 4 * fc) { frccap += 4 * fc - frccap; frc = cast(Fontcache*)xrealloc(frc, frccap * Fontcache.sizeof); } foreach (i, fp; font2) { if (fp[0] == '-') pattern = XftXlfdParse(fp.toStringz, 0, 0); else pattern = FcNameParse(cast(FcChar8*)fp.toStringz); if (!pattern) die("can't open spare font %s\n", fp.toStringz); if (defaultfontsize > 0 && defaultfontsize != usedfontsize) { if (FcPatternGetDouble(pattern, FC_PIXEL_SIZE, 0, &fontval) == FcResultMatch) { fontval *= usedfontsize / defaultfontsize; FcPatternDel(pattern, FC_PIXEL_SIZE); FcPatternDel(pattern, FC_SIZE); FcPatternAddDouble(pattern, FC_PIXEL_SIZE, fontval); } else if (FcPatternGetDouble(pattern, FC_SIZE, 0, &fontval) == FcResultMatch) { fontval *= usedfontsize / defaultfontsize; FcPatternDel(pattern, FC_PIXEL_SIZE); FcPatternDel(pattern, FC_SIZE); FcPatternAddDouble(pattern, FC_SIZE, fontval); } } FcPatternAddBool(pattern, FC_SCALABLE, 1); static if (!isPatchEnabled!"USE_XFTFONTMATCH_PATCH") { FcConfigSubstitute(null, pattern, FcMatchPattern); XftDefaultSubstitute(xw.dpy, xw.scr, pattern); } if (xloadsparefont(pattern, FRC_NORMAL)) die("can't open spare font %s\n", fp.toStringz); FcPatternDel(pattern, FC_SLANT); FcPatternAddInteger(pattern, FC_SLANT, FC_SLANT_ITALIC); if (xloadsparefont(pattern, FRC_ITALIC)) die("can't open spare font %s\n", fp.toStringz); FcPatternDel(pattern, FC_WEIGHT); FcPatternAddInteger(pattern, FC_WEIGHT, FC_WEIGHT_BOLD); if (xloadsparefont(pattern, FRC_ITALICBOLD)) die("can't open spare font %s\n", fp.toStringz); FcPatternDel(pattern, FC_SLANT); FcPatternAddInteger(pattern, FC_SLANT, FC_SLANT_ROMAN); if (xloadsparefont(pattern, FRC_BOLD)) die("can't open spare font %s\n", fp.toStringz); FcPatternDestroy(pattern); } } }