--- config.def.h | 10 ++++- x.c | 120 +++++++++++++++++++++++++++++++++------------------ 2 files changed, 85 insertions(+), 45 deletions(-) diff --git a/config.def.h b/config.def.h index 2cd740a..1da0d69 100644 --- a/config.def.h +++ b/config.def.h _AT_@ -3,9 +3,15 @@ /* * appearance * - * font: see http://freedesktop.org/software/fontconfig/fontconfig-user.html + * fonts: see http://freedesktop.org/software/fontconfig/fontconfig-user.html */ -static char *font = "Liberation Mono:pixelsize=12:antialias=true:autohint=true"; +static char *fonts[] = { + "Liberation Mono:pixelsize=12:antialias=true:autohint=true", + + /* CJK Fonts */ + "VL Gothic:pixelsize=12:antialias=true:autohint=true", + "WenQuanYi Micro Hei:pixelsize=12:antialias=true:autohint=true", +}; static int borderpx = 2; /* diff --git a/x.c b/x.c index bd23686..b8e6187 100644 --- a/x.c +++ b/x.c _AT_@ -132,11 +132,18 @@ typedef struct { FcPattern *pattern; } Font; +typedef struct { + Font font; + Font bfont; + Font ifont; + Font ibfont; +} FontFamily; + /* Drawing Context */ typedef struct { Color *col; size_t collen; - Font font, bfont, ifont, ibfont; + FontFamily fontfamily; GC gc; } DC; _AT_@ -221,6 +228,10 @@ static XWindow xw; static XSelection xsel; static TermWindow win; +static FontFamily EmptyFontFamily; +static FontFamily fontfamilies[16]; +static int fontfamiliescount = 0; + /* Font Ring Cache */ enum { FRC_NORMAL, _AT_@ -985,6 +996,11 @@ xloadfonts(const char *fontstr, double fontsize) { FcPattern *pattern; double fontval; + FontFamily fontfamily = EmptyFontFamily; + + if (fontfamiliescount >= LEN(fontfamilies)) { + die("Font family array is full.\n"); + } if (fontstr[0] == '-') pattern = XftXlfdParse(fontstr, False, False); _AT_@ -1017,37 +1033,43 @@ xloadfonts(const char *fontstr, double fontsize) defaultfontsize = usedfontsize; } - if (xloadfont(&dc.font, pattern)) + if (xloadfont(&fontfamily.font, pattern)) die("can't open font %s\n", fontstr); if (usedfontsize < 0) { - FcPatternGetDouble(dc.font.match->pattern, + FcPatternGetDouble(fontfamily.font.match->pattern, FC_PIXEL_SIZE, 0, &fontval); usedfontsize = fontval; if (fontsize == 0) defaultfontsize = fontval; } - /* Setting character width and height. */ - win.cw = ceilf(dc.font.width * cwscale); - win.ch = ceilf(dc.font.height * chscale); - FcPatternDel(pattern, FC_SLANT); FcPatternAddInteger(pattern, FC_SLANT, FC_SLANT_ITALIC); - if (xloadfont(&dc.ifont, pattern)) + if (xloadfont(&fontfamily.ifont, pattern)) die("can't open font %s\n", fontstr); FcPatternDel(pattern, FC_WEIGHT); FcPatternAddInteger(pattern, FC_WEIGHT, FC_WEIGHT_BOLD); - if (xloadfont(&dc.ibfont, pattern)) + if (xloadfont(&fontfamily.ibfont, pattern)) die("can't open font %s\n", fontstr); FcPatternDel(pattern, FC_SLANT); FcPatternAddInteger(pattern, FC_SLANT, FC_SLANT_ROMAN); - if (xloadfont(&dc.bfont, pattern)) + if (xloadfont(&fontfamily.bfont, pattern)) die("can't open font %s\n", fontstr); FcPatternDestroy(pattern); + + /* Setting character width and height. */ + if (!fontfamiliescount) { + win.cw = ceilf(fontfamily.font.width * cwscale); + win.ch = ceilf(fontfamily.font.height * chscale); + dc.fontfamily = fontfamily; + usedfont = (char *) fontstr; + } + + fontfamilies[fontfamiliescount++] = fontfamily; } void _AT_@ -1066,10 +1088,13 @@ xunloadfonts(void) while (frclen > 0) XftFontClose(xw.dpy, frc[--frclen].font); - xunloadfont(&dc.font); - xunloadfont(&dc.bfont); - xunloadfont(&dc.ifont); - xunloadfont(&dc.ibfont); + while (fontfamiliescount > 0) { + fontfamiliescount--; + xunloadfont(&fontfamilies[fontfamiliescount].font); + xunloadfont(&fontfamilies[fontfamiliescount].bfont); + xunloadfont(&fontfamilies[fontfamiliescount].ifont); + xunloadfont(&fontfamilies[fontfamiliescount].ibfont); + } } int _AT_@ -1134,6 +1159,7 @@ xinit(int cols, int rows) Window parent; pid_t thispid = getpid(); XColor xmousefg, xmousebg; + int i; if (!(xw.dpy = XOpenDisplay(NULL))) die("can't open display\n"); _AT_@ -1144,8 +1170,13 @@ xinit(int cols, int rows) if (!FcInit()) die("could not init fontconfig.\n"); - usedfont = (opt_font == NULL)? font : opt_font; - xloadfonts(usedfont, 0); + if (opt_font) { + xloadfonts(opt_font, 0); + } + + for (i = 0; i < LEN(fonts); i++) { + xloadfonts(fonts[i], 0); + } /* colors */ xw.cmap = XDefaultColormap(xw.dpy, xw.scr); _AT_@ -1242,9 +1273,9 @@ xinit(int cols, int rows) int xmakeglyphfontspecs(XftGlyphFontSpec *specs, const Glyph *glyphs, int len, int x, int y) { - float winx = borderpx + x * win.cw, winy = borderpx + y * win.ch, xp, yp; - ushort mode, prevmode = USHRT_MAX; - Font *font = &dc.font; + float winx = borderpx + x * win.cw, winy = borderpx + y * win.ch, xp; + ushort mode; + Font *font, *reference = NULL; int frcflags = FRC_NORMAL; float runewidth = win.cw; Rune rune; _AT_@ -1255,7 +1286,7 @@ xmakeglyphfontspecs(XftGlyphFontSpec *specs, const Glyph *glyphs, int len, int x FcCharSet *fccharset; int i, f, numspecs = 0; - for (i = 0, xp = winx, yp = winy + font->ascent; i < len; ++i) { + for (i = 0, xp = winx; i < len; ++i) { /* Fetch rune and mode for current glyph. */ rune = glyphs[i].u; mode = glyphs[i].mode; _AT_@ -1264,32 +1295,33 @@ xmakeglyphfontspecs(XftGlyphFontSpec *specs, const Glyph *glyphs, int len, int x if (mode == ATTR_WDUMMY) continue; - /* Determine font for glyph if different from previous glyph. */ - if (prevmode != mode) { - prevmode = mode; - font = &dc.font; + /* Lookup character index within user-defined fonts. */ + for (glyphidx = 0, f = 0; f < fontfamiliescount && !glyphidx; f++) { + font = &fontfamilies[f].font; frcflags = FRC_NORMAL; runewidth = win.cw * ((mode & ATTR_WIDE) ? 2.0f : 1.0f); if ((mode & ATTR_ITALIC) && (mode & ATTR_BOLD)) { - font = &dc.ibfont; + font = &fontfamilies[f].ibfont; frcflags = FRC_ITALICBOLD; } else if (mode & ATTR_ITALIC) { - font = &dc.ifont; + font = &fontfamilies[f].ifont; frcflags = FRC_ITALIC; } else if (mode & ATTR_BOLD) { - font = &dc.bfont; + font = &fontfamilies[f].bfont; frcflags = FRC_BOLD; } - yp = winy + font->ascent; + + if (!f) { + reference = font; + } + glyphidx = XftCharIndex(xw.dpy, font->match, rune); } - /* Lookup character index with default font. */ - glyphidx = XftCharIndex(xw.dpy, font->match, rune); if (glyphidx) { specs[numspecs].font = font->match; specs[numspecs].glyph = glyphidx; specs[numspecs].x = (short)xp; - specs[numspecs].y = (short)yp; + specs[numspecs].y = (short) (winy + font->ascent); xp += runewidth; numspecs++; continue; _AT_@ -1308,12 +1340,14 @@ xmakeglyphfontspecs(XftGlyphFontSpec *specs, const Glyph *glyphs, int len, int x } } - /* Nothing was found. Use fontconfig to find matching font. */ + /* Nothing was found. Use fontconfig to find matching font using the + * default font as the reference font. + */ if (f >= frclen) { - if (!font->set) - font->set = FcFontSort(0, font->pattern, - 1, 0, &fcres); - fcsets[0] = font->set; + if (!reference->set) + reference->set = FcFontSort(0, reference->pattern, + 1, 0, &fcres); + fcsets[0] = reference->set; /* * Nothing was found in the cache. Now use _AT_@ -1322,7 +1356,7 @@ xmakeglyphfontspecs(XftGlyphFontSpec *specs, const Glyph *glyphs, int len, int x * * Xft and fontconfig are design failures. */ - fcpattern = FcPatternDuplicate(font->pattern); + fcpattern = FcPatternDuplicate(reference->pattern); fccharset = FcCharSetCreate(); FcCharSetAddChar(fccharset, rune); _AT_@ -1363,7 +1397,7 @@ xmakeglyphfontspecs(XftGlyphFontSpec *specs, const Glyph *glyphs, int len, int x specs[numspecs].font = frc[f].font; specs[numspecs].glyph = glyphidx; specs[numspecs].x = (short)xp; - specs[numspecs].y = (short)yp; + specs[numspecs].y = (short) (winy + frc[f].font->ascent); xp += runewidth; numspecs++; } _AT_@ -1383,10 +1417,10 @@ xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, int x, i /* Fallback on color display for attributes not supported by the font */ if (base.mode & ATTR_ITALIC && base.mode & ATTR_BOLD) { - if (dc.ibfont.badslant || dc.ibfont.badweight) + if (dc.fontfamily.ibfont.badslant || dc.fontfamily.ibfont.badweight) base.fg = defaultattr; - } else if ((base.mode & ATTR_ITALIC && dc.ifont.badslant) || - (base.mode & ATTR_BOLD && dc.bfont.badweight)) { + } else if ((base.mode & ATTR_ITALIC && dc.fontfamily.ifont.badslant) || + (base.mode & ATTR_BOLD && dc.fontfamily.bfont.badweight)) { base.fg = defaultattr; } _AT_@ -1493,12 +1527,12 @@ xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, int x, i /* Render underline and strikethrough. */ if (base.mode & ATTR_UNDERLINE) { - XftDrawRect(xw.draw, fg, winx, winy + dc.font.ascent * chscale + 1, + XftDrawRect(xw.draw, fg, winx, winy + dc.fontfamily.font.ascent * chscale + 1, width, 1); } if (base.mode & ATTR_STRUCK) { - XftDrawRect(xw.draw, fg, winx, winy + 2 * dc.font.ascent * chscale / 3, + XftDrawRect(xw.draw, fg, winx, winy + 2 * dc.fontfamily.font.ascent * chscale / 3, width, 1); } -- 2.39.2Received on Sat Aug 03 2024 - 08:23:43 CEST
This archive was generated by hypermail 2.3.0 : Sat Aug 03 2024 - 10:36:08 CEST