/*--------------------------------*-C-*---------------------------------*
- * File: defaultfont.C
+ * File: rxvtfont.C
*----------------------------------------------------------------------*
* Copyright (c) 2003-2004 Marc Lehmann <pcg@goof.com>
* - original version.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*---------------------------------------------------------------------*/
#include "../config.h"
#if ENCODING_ZH || ENCODING_ZH_EXT
# if XFT
+ { CS_GBK_0, "xft:AR PL KaitiM GB" },
+ { CS_GBK_0, "xft:AR PL SungtiL GB" },
+ { CS_GBK_0, "xft::spacing=100:lang=zh" },
{ CS_BIG5_EXT, "xft:AR PL Mingti2L Big5" },
{ CS_BIG5_EXT, "xft:AR PL KaitiM Big5" },
{ CS_GB2312_1980_0, "xft:AR PL KaitiM GB" },
{ CS_GB2312_1980_0, "xft:AR PL SungtiL GB" },
{ CS_GB2312_1980_0, "xft::spacing=100:lang=zh" },
# endif
+ { CS_GBK_0, "-*-*-*-*-*-*-*-*-*-*-c-*-gbk*-0" },
{ CS_BIG5, "-*-*-*-*-*-*-*-*-*-*-c-*-big5-0" },
{ CS_BIG5_PLUS, "-*-*-*-*-*-*-*-*-*-*-c-*-big5p-0" },
{ CS_BIG5_EXT, "-*-*-*-*-*-*-*-*-*-*-c-*-big5.eten-0" },
+ { CS_GB2312_1980_0, "-*-*-*-*-*-*-*-*-*-*-c-*-gb2312*-0" },
{ CS_CNS11643_1992_1, "-*-*-*-*-*-*-*-*-*-*-c-*-gb2312*-0" },
{ CS_CNS11643_1992_1, "-*-*-*-*-*-*-*-*-*-*-c-*-cns11643*-1" },
{ CS_CNS11643_1992_2, "-*-*-*-*-*-*-*-*-*-*-c-*-cns11643*-2" },
{ CS_UNICODE, "-*-*-*-r-*-*-*-*-*-*-c-*-iso10646-1" },
{ CS_UNICODE, "-*-*-*-r-*-*-*-*-*-*-m-*-iso10646-1" },
#if XFT
- { CS_UNICODE, "xft:Bitstream Vera Sans Mono:antialias=false:autohint=true"},
- { CS_UNICODE, "xft:Courier New:antialias=false:autohint=true" },
- { CS_UNICODE, "xft:Andale Mono:antialias=false" },
- { CS_UNICODE, "xft:Arial Unicode MS:antialias=false" },
+ { CS_UNICODE, "xft:Bitstream Vera Sans Mono:antialias=false:autohint=true" },
+ { CS_UNICODE, "xft:Courier New:antialias=false:autohint=true" },
+ { CS_UNICODE, "xft:Andale Mono:antialias=false:autohint=false" },
+ { CS_UNICODE, "xft:Arial Unicode MS:antialias=false:autohint=false" },
// FreeMono is usually uglier than x fonts, so try last only.
{ CS_UNICODE, "xft:FreeMono:autohint=true" },
};
// these characters are used to guess the font height and width
-// pango uses a similar algorithm and eosn't trust the font either.
+// pango uses a similar algorithm and doesn't trust the font either.
static uint16_t extent_test_chars[] = {
'0', '1', '8', 'a', 'd', 'x', 'm', 'y', 'g', 'W', 'X', '\'', '_',
0x00cd, 0x00d5, 0x0114, 0x0177, 0x0643, // ÍÕĔŷﻙ
const text_t *text, int len,
int fg, int bg)
{
+ Display *disp = d.display->display;
+
clear_rect (d, x, y, r->TermWin.fwidth * len, r->TermWin.fheight, bg);
- XSetForeground (d.display->display, TGC, r->pix_colors[fg]);
+ XSetForeground (disp, TGC, r->pix_colors[fg]);
- while (len--)
+ while (len)
{
#if ENABLE_COMBINING
compose_char *cc;
#endif
- text_t t = *text++;
+ const text_t *tp = text;
+ text_t t = *tp;
+
+ while (++text, --len && *text == NOCHAR)
+ ;
+
+ int width = text - tp;
+ int fwidth = r->TermWin.fwidth * width;
if (0x2500 <= t && t <= 0x259f)
{
uint32_t *a = linedraw_command + (offs >> 4);
uint32_t *b = a + (offs & 15);
- int W = r->TermWin.fwidth;
+ int W = fwidth;
int H = r->TermWin.fheight;
- // support double-width (but not more) graphics chars
- // TODO: do this outside the if/elsif.. statement for all cases
- if (len && *text == NOCHAR)
- W += r->TermWin.fwidth;
-
int x_[16];
int y_[16];
gcv.cap_style = CapButt;
gcv.line_width = 0;
- XChangeGC (d.display->display, TGC, GCLineWidth | GCCapStyle, &gcv);
+ XChangeGC (disp, TGC, GCLineWidth | GCCapStyle, &gcv);
while (a < b)
{
switch (op)
{
case 0: // line
- XDrawLine (d.display->display, d, TGC, x1, y1, x2, y2);
+ XDrawLine (disp, d, TGC, x1, y1, x2, y2);
break;
case 1: // rectangle, possibly stippled
static char bm[] = { 0,0 , 3,1 , 1,2 , 1,0 };
gcv.fill_style = FillStippled;
- gcv.stipple = XCreateBitmapFromData (d.display->display, d, bm + a * 2, 2, 2);
+ gcv.stipple = XCreateBitmapFromData (disp, d, bm + a * 2, 2, 2);
gcv.ts_x_origin = x;
gcv.ts_y_origin = y;
- XChangeGC (d.display->display, TGC,
+ XChangeGC (disp, TGC,
GCFillStyle | GCStipple | GCTileStipXOrigin | GCTileStipYOrigin,
&gcv);
}
- XFillRectangle (d.display->display, d, TGC, x1, y1, x2 - x1 + 1, y2 - y1 + 1);
+ XFillRectangle (disp, d, TGC, x1, y1, x2 - x1 + 1, y2 - y1 + 1);
if (a)
{
- XFreePixmap (d.display->display, gcv.stipple);
+ XFreePixmap (disp, gcv.stipple);
gcv.stipple = 0;
gcv.fill_style = FillSolid;
- XChangeGC (d.display->display, TGC, GCFillStyle, &gcv);
+ XChangeGC (disp, TGC, GCFillStyle, &gcv);
}
break;
case 2: // arc
- XDrawArc (d.display->display, d, TGC,
+ XDrawArc (disp, d, TGC,
x1 - W/2, y1 - H/2, W-1, H-1,
(a - 1) * 90*64, (b - 1) * 90*64);
break;
#if ENABLE_COMBINING
else if (IS_COMPOSE (t) && (cc = rxvt_composite[t]))
{
- text_t c2[2];
- int len2 = 1;
-
- // support double-width (but not more) combining characters
- if (len && *text == NOCHAR)
- {
- c2[1] = *text; // not text++ to get correct x-width
- len2++;
- }
+ text_t chrs[2];
+ width = min (2, width);
+ chrs [1] = NOCHAR;
- c2[0] = cc->c1;
- rxvt_font *f1 = (*fs)[fs->find_font (c2[0])];
- f1->draw (d, x, y, c2, len2, fg, bg);
+ *chrs = cc->c1;
+ rxvt_font *f1 = (*fs)[fs->find_font (cc->c1)];
+ f1->draw (d, x, y, chrs, width, fg, bg);
if (cc->c2 != NOCHAR)
{
bool careful;
// prefer font of first character, for no good reasons
- c2[0] = cc->c2;
- rxvt_font *f2 = (f1->has_char (c2[0], 0, careful) && !careful)
+ *chrs = cc->c2;
+ rxvt_font *f2 = (f1->has_char (cc->c2, 0, careful) && !careful)
? f1
- : (*fs)[fs->find_font (c2[0])];
+ : (*fs)[fs->find_font (cc->c2)];
- f2->draw (d, x, y, c2, len2, fg, -1);
+ f2->draw (d, x, y, chrs, width, fg, -1);
}
}
#endif
break;
default:
- int w = 0;
- while (len > 0 && *text == NOCHAR)
- {
- ++text;
- --len;
- w += r->TermWin.fwidth;
- }
-
- XDrawRectangle (d.display->display, d, TGC, x + 2, y + 2,
- w + r->TermWin.fwidth - 4, r->TermWin.fheight - 4);
- x += w;
+ XDrawRectangle (disp, d, TGC, x + 2, y + 2,
+ fwidth - 4, r->TermWin.fheight - 4);
}
- x += r->TermWin.fwidth;
+ x += fwidth;
}
}
rxvt_font_x11::set_properties (rxvt_fontprop &p, XFontStruct *f)
{
unsigned long height;
+
+#if 0
if (!XGetFontProperty (f, XInternAtom (DISPLAY, "PIXEL_SIZE", 0), &height))
return false;
+#else
+ height = f->ascent + f->descent;
+#endif
unsigned long avgwidth;
if (!XGetFontProperty (f, XInternAtom (DISPLAY, "AVERAGE_WIDTH", 0), &avgwidth))
bool
rxvt_font_x11::load (const rxvt_fontprop &prop)
{
+ Display *disp = DISPLAY;
+
clear ();
char field_str[64]; // enough for 128 bits
if (name[0] != '-')
{
- f = XLoadQueryFont (DISPLAY, name);
+ f = XLoadQueryFont (disp, name);
if (!f)
return false;
else
rxvt_warn ("font '%s' has no FONT property, continuing without.", name);
- XFreeFont (DISPLAY, f);
+ XFreeFont (disp, f);
f = 0;
}
}
}
+ sprintf (field_str, "%d", prop.height == rxvt_fontprop::unset
+ ? 0 : prop.height);
+
+ struct font_weight {
+ char *name;
+ int diff;
+
+ void clear ()
+ {
+ name = 0;
+ diff = 0x7fffffff;
+ }
+
+ font_weight () { clear (); }
+ ~font_weight () { free (name); }
+ };
+
char **list;
int count;
- list = XListFonts (DISPLAY, name, 1024, &count);
+ list = XListFonts (disp, name, 4000, &count);
set_name (0);
if (!list)
return false;
- sprintf (field_str, "%d", prop.height == rxvt_fontprop::unset
- ? 0 : prop.height);
+ font_weight *fonts = new font_weight[count];
- int bestdiff = 0x7fffffff;
for (int i = 0; i < count; i++)
{
rxvt_fontprop p;
if (replace_field (fname, list[i], 6, '0', field_str))
diff += 10; // slightly penalize scalable fonts
+ else if (replace_field (fname, list[i], 11, '0', "0"))
+ diff += 300; // more heavily penalize what looks like scaled bitmap fotns
if (!set_properties (p, fname))
continue;
if (prop.slant != rxvt_fontprop::unset) diff += abs (prop.slant - p.slant);
//if (prop.width != rxvt_fontprop::unset) diff += abs (prop.width - p.width);
- if (!name // compare against best found so far
- || diff < bestdiff)
- {
- set_name (strdup (fname));
- bestdiff = diff;
- }
+ fonts[i].name = strdup (fname);
+ fonts[i].diff = diff;
}
XFreeFontNames (list);
- if (!name)
- return false;
+ // this loop only iterates when the guessed font-size is too small
+ for (;;)
+ {
+ font_weight *best = fonts + count - 1;
+
+ for (font_weight *w = best; w-- > fonts; )
+ if (w->diff <= best->diff)
+ best = w;
- f = XLoadQueryFont (DISPLAY, name);
+ if (!best->name
+ || !(f = XLoadQueryFont (disp, best->name)))
+ break;
+
+ set_name (best->name);
+ best->clear ();
+
+ ascent = f->ascent;
+ descent = f->descent;
+ height = ascent + descent;
+
+ if (prop.height == rxvt_fontprop::unset
+ || height <= prop.height)
+ break; // font is ready for use
+
+ // PIXEL_SIZE small enough, but real height too large
+ clear ();
+ }
+
+ delete [] fonts;
if (!f)
return false;
encm = f->min_byte1 != 0 || f->max_byte1 != 0;
enc2b = encm || f->max_char_or_byte2 > 255;
- ascent = f->ascent;
- descent = f->descent;
- height = ascent + descent;
-
slow = false;
#if 1 // only used for slow detection, TODO optimize
bool
rxvt_font_xft::load (const rxvt_fontprop &prop)
{
+ Display *disp = DISPLAY;
+
clear ();
FcPattern *p = FcNameParse ((FcChar8 *) name);
FcValue v;
if (prop.height != rxvt_fontprop::unset
- || (FcPatternGet (p, FC_PIXEL_SIZE, 0, &v) != FcResultMatch
+ && (FcPatternGet (p, FC_PIXEL_SIZE, 0, &v) != FcResultMatch
&& FcPatternGet (p, FC_SIZE, 0, &v) != FcResultMatch))
FcPatternAddInteger (p, FC_PIXEL_SIZE, prop.height);
set_name ((char *)FcNameUnparse (p));
XftResult result;
- FcPattern *match = XftFontMatch (DISPLAY, DefaultScreen (DISPLAY), p, &result);
+ FcPattern *match = XftFontMatch (disp, r->display->screen, p, &result);
FcPatternDestroy (p);
for (;;)
{
- f = XftFontOpenPattern (DISPLAY, FcPatternDuplicate (match));
+ f = XftFontOpenPattern (disp, FcPatternDuplicate (match));
if (!f)
{
continue;
XGlyphInfo g;
- XftTextExtents16 (DISPLAY, f, &ch, 1, &g);
+ XftTextExtents16 (disp, f, &ch, 1, &g);
int wcw = wcwidth (ch);
if (wcw > 0) g.width = g.width / wcw;
else
ftheight = prop.height - 1;
- XftFontClose (DISPLAY, f);
+ XftFontClose (disp, f);
FcPatternDel (match, FC_PIXEL_SIZE);
FcPatternAddInteger (match, FC_PIXEL_SIZE, ftheight);
}
do
{
- while (*desc <= ' ') desc++;
+ while (*desc && *desc <= ' ')
+ desc++;
codeset cs = CS_UNICODE;
//FcPatternAddBool (p, FC_ANTIALIAS, 1);
XftResult result;
- FcPattern *match = XftFontMatch (DISPLAY, DefaultScreen (DISPLAY), p, &result);
+ FcPattern *match = XftFontMatch (DISPLAY, r->display->screen, p, &result);
FcPatternDestroy (p);