--- rxvt-unicode/src/rxvtfont.C 2007/12/26 14:22:30 1.126 +++ rxvt-unicode/src/rxvtfont.C 2010/05/22 23:55:56 1.165 @@ -1,7 +1,7 @@ /*----------------------------------------------------------------------* * File: rxvtfont.C *----------------------------------------------------------------------* - * Copyright (c) 2003-2006 Marc Lehmann + * Copyright (c) 2003-2008 Marc Lehmann * - original version. * * This program is free software; you can redistribute it and/or modify @@ -81,8 +81,8 @@ #if ENCODING_JP || ENCODING_JP_EXT # if XFT // prefer xft for complex scripts - { CS_JIS0208_1990_0, "xft:Kochi Gothic:antialias=false" }, { CS_JIS0208_1990_0, "xft:Sazanami Mincho:antialias=false" }, + { CS_JIS0208_1990_0, "xft:Kochi Gothic:antialias=false" }, { CS_JIS0208_1990_0, "xft:Mincho:antialias=false" }, { CS_JIS0208_1990_0, "xft::lang=ja:antialias=false" }, # endif @@ -218,13 +218,13 @@ } void -rxvt_font::set_name (char *name) +rxvt_font::set_name (char *name_) { - if (this->name == name) + if (name == name_) return; - if (this->name) free (this->name); // let the compiler optimize - this->name = name; + if (name) free (name); // let the compiler optimize + name = name_; } void @@ -238,22 +238,22 @@ else if (color >= 0) { #if XFT - bool done = false; -#ifdef HAVE_BG_PIXMAP - if (term->bgPixmap.pixmap && color >= 0 && term->pix_colors[color].c.color.alpha < 0x0ff00) + Picture dst; + +# ifdef HAVE_BG_PIXMAP + if (term->bgPixmap.pixmap + && !term->pix_colors[color].is_opaque () + && ((dst = XftDrawPicture (d)))) { - Picture dst = XftDrawPicture (d); - if (dst != 0) - { - XClearArea (disp, d, x, y, w, h, false); - Picture solid_color_pict = XftDrawSrcPicture (d, &term->pix_colors[color].c); - XRenderComposite (disp, PictOpOver, solid_color_pict, None, dst, 0, 0, 0, 0, x, y, w, h); - done = true; - } + XClearArea (disp, d, x, y, w, h, false); + + Picture solid_color_pict = XftDrawSrcPicture (d, &term->pix_colors[color].c); + XRenderComposite (disp, PictOpOver, solid_color_pict, None, dst, 0, 0, 0, 0, x, y, w, h); } -#endif - if (!done) + else +# endif XftDrawRect (d, &term->pix_colors[color].c, x, y, w, h); + #else XSetForeground (disp, gc, term->pix_colors[color]); XFillRectangle (disp, d, gc, x, y, w, h); @@ -450,7 +450,7 @@ chrs [1] = NOCHAR; *chrs = cc->c1; - rxvt_font *f1 = (*fs)[fs->find_font (cc->c1)]; + rxvt_font *f1 = (*fs)[fs->find_font_idx (cc->c1)]; f1->draw (d, x, y, chrs, width, fg, bg); if (cc->c2 != NOCHAR) @@ -461,7 +461,7 @@ *chrs = cc->c2; rxvt_font *f2 = (f1->has_char (cc->c2, 0, careful) && !careful) ? f1 - : (*fs)[fs->find_font (cc->c2)]; + : (*fs)[fs->find_font_idx (cc->c2)]; f2->draw (d, x, y, chrs, width, fg, Color_none); } @@ -484,6 +484,56 @@ } } +struct rxvt_font_overflow : rxvt_font { + struct rxvt_fontset *fs; + + rxvt_font_overflow (rxvt_fontset *fs) + : rxvt_font () + { + this->fs = fs; + } + + rxvt_fontprop properties () + { + rxvt_fontprop p; + + p.width = p.height = 1; + p.ascent = rxvt_fontprop::unset; + p.weight = rxvt_fontprop::medium; + p.slant = rxvt_fontprop::roman; + + return p; + } + + bool load (const rxvt_fontprop &prop, bool force_prop) + { + width = 1; height = 1; + ascent = 1; descent = 0; + + set_name (strdup ("built-in rendition overflow font")); + + return true; + } + + bool has_char (unicode_t unicode, const rxvt_fontprop *prop, bool &careful) const + { + return false; + } + + void draw (rxvt_drawable &d, int x, int y, + const text_t *text, int len, + int fg, int bg) + { + while (len--) + { + int fid = fs->find_font_idx (*text); + (*fs)[fid]->draw (d, x, y, text, 1, fg, bg); + ++text; + x += term->fwidth; + } + } +}; + ///////////////////////////////////////////////////////////////////////////// struct rxvt_font_x11 : rxvt_font { @@ -501,7 +551,7 @@ const text_t *text, int len, int fg, int bg); - bool slow; // wether this is a proportional font or has other funny characteristics + bool slow; // whether this is a proportional font or has other funny characteristics XFontStruct *f; bool enc2b, encm; @@ -633,7 +683,7 @@ { size_t len = field - name; *ptr = (char *)malloc (len + strlen (replace) + strlen (end) + 1); - strncpy (*ptr, name, len); + memcpy (*ptr, name, len); strcpy (*ptr + len, replace); strcat (*ptr, end); @@ -794,14 +844,23 @@ char *registry = get_property (f, term->xa [XA_CHARSET_REGISTRY], 0); char *encoding = get_property (f, term->xa [XA_CHARSET_ENCODING], 0); + cs = CS_UNKNOWN; + if (registry && encoding) { char charset[64]; snprintf (charset, 64, "%s-%s", registry, encoding); cs = codeset_from_name (charset); + + if (cs == CS_UNKNOWN) + rxvt_warn ("%s: cannot deduce encoding from registry/encoding properties \"%s\", ignoring font.\n", name, charset); } - else + + free (registry); + free (encoding); + + if (cs == CS_UNKNOWN) { const char *charset = get_property (f, XA_FONT, 0); @@ -814,10 +873,15 @@ break; cs = codeset_from_name (charset); + if (cs == CS_UNKNOWN) + rxvt_warn ("%s: cannot deduce encoding from font name property \"%s\", ignoring font.\n", name, charset); } - free (registry); - free (encoding); + if (cs == CS_UNKNOWN) + { + clear (); + return false; + } if (cs == CS_UNICODE) cs = CS_UNICODE_16; // X11 can have a max. of 65536 chars per font @@ -874,14 +938,6 @@ if (width < g.width) width = g.width; } - if (cs == CS_UNKNOWN) - { - fprintf (stderr, "unable to deduce codeset, ignoring font '%s'\n", name); - - clear (); - return false; - } - #if 0 // do it per-character if (prop && width > prop->width) { @@ -911,7 +967,7 @@ if (ch == NOCHAR) return false; - /* check wether the character exists in _this_ font. horrible. */ + /* check whether the character exists in _this_ font. horrible. */ XCharStruct *xcs; if (encm) @@ -951,7 +1007,7 @@ if (!prop || prop->width == rxvt_fontprop::unset) return true; - // check wether character overlaps previous/next character + // check whether character overlaps previous/next character int w = xcs->rbearing - xcs->lbearing; int wcw = max (WCWIDTH (unicode), 1); @@ -1135,7 +1191,7 @@ #if 0 // clipping unfortunately destroys our precious double-width-characters // clip width, we can't do better, or can we? if (FcPatternGet (p, FC_CHAR_WIDTH, 0, &v) != FcResultMatch) - FcPatternAddInteger (p, FC_CHAR_WIDTH, prop->width); + FcPatternAddInteger (p, FC_CHAR_WIDTH, prop.width); #endif if (FcPatternGet (p, FC_MINSPACE, 0, &v) != FcResultMatch) @@ -1289,7 +1345,7 @@ int fg, int bg) { XGlyphInfo extents; - XftGlyphSpec *enc = (XftGlyphSpec *)rxvt_temp_buf (len * sizeof (XftGlyphSpec)); + XftGlyphSpec *enc = rxvt_temp_buf (len); XftGlyphSpec *ep = enc; dTermDisplay; @@ -1298,15 +1354,9 @@ int w = term->fwidth * len; int h = term->fheight; - /* TODO: this logic needs some more thinking, since we no longer do pseudo-transparency. - * Maybe make buffering into a resource flag? Compile time option doesn't seems like a - * good idea from the perspective of packaging for wide variety of user configs. - */ - bool buffered = true -#ifdef FORCE_UNBUFFERED_XFT - && bg >= 0 -#endif - ; + bool buffered = bg >= Color_transparent + && term->option (Opt_buffered); + // cut trailing spaces while (len && text [len - 1] == ' ') len--; @@ -1342,67 +1392,61 @@ if (buffered) { - bool back_rendered = false; if (ep != enc) { rxvt_drawable &d2 = d.screen->scratch_drawable (w, h); #ifdef HAVE_BG_PIXMAP - if (term->bgPixmap.pixmap) - { - Picture dst = 0; + Picture dst = 0; // the only assignment is done conditionally in the following if condition - if (bg >= 0 && term->pix_colors[bg].c.color.alpha < 0x0ff00) - dst = XftDrawPicture (d2); + if (term->bgPixmap.pixmap + && (bg == Color_transparent || bg == Color_bg + || (bg >= 0 && !term->pix_colors[bg].is_opaque () && ((dst = XftDrawPicture (d2)))))) + { + int src_x = x, src_y = y; - if (bg < 0 || dst != 0) + if (term->bgPixmap.is_parentOrigin ()) { - int src_x = x, src_y = y ; - - if (term->bgPixmap.is_parentOrigin ()) - { - src_x += term->window_vt_x; - src_y += term->window_vt_y; - } + src_x += term->window_vt_x; + src_y += term->window_vt_y; + } - if (term->bgPixmap.pmap_width >= src_x+w - && term->bgPixmap.pmap_height >= src_y+h) - { - XCopyArea (disp, term->bgPixmap.pixmap, d2, gc, - src_x, src_y, w, h, 0, 0); - } - else - { - XGCValues gcv; + if (term->bgPixmap.pmap_width >= src_x + w + && term->bgPixmap.pmap_height >= src_y + h) + { + XCopyArea (disp, term->bgPixmap.pixmap, d2, gc, + src_x, src_y, w, h, 0, 0); + } + else + { + XGCValues gcv; - gcv.fill_style = FillTiled; - gcv.tile = term->bgPixmap.pixmap; - gcv.ts_x_origin = -src_x; - gcv.ts_y_origin = -src_y; + gcv.fill_style = FillTiled; + gcv.tile = term->bgPixmap.pixmap; + gcv.ts_x_origin = -src_x; + gcv.ts_y_origin = -src_y; - XChangeGC (disp, gc, - GCTile | GCTileStipXOrigin | GCTileStipYOrigin | GCFillStyle, - &gcv); + XChangeGC (disp, gc, + GCTile | GCTileStipXOrigin | GCTileStipYOrigin | GCFillStyle, + &gcv); - XFillRectangle (disp, d2, gc, 0, 0, w, h); + XFillRectangle (disp, d2, gc, 0, 0, w, h); - gcv.fill_style = FillSolid; - XChangeGC (disp, gc, GCFillStyle, &gcv); - } + gcv.fill_style = FillSolid; + XChangeGC (disp, gc, GCFillStyle, &gcv); + } - if (bg >= 0) - { - Picture solid_color_pict = XftDrawSrcPicture (d2, &term->pix_colors[bg].c); - XRenderComposite (disp, PictOpOver, solid_color_pict, None, dst, 0, 0, 0, 0, 0, 0, w, h); - } + if (dst) + { + Picture solid_color_pict = XftDrawSrcPicture (d2, &term->pix_colors[bg].c); - back_rendered = true; + // dst can only be set when bg >= 0 + XRenderComposite (disp, PictOpOver, solid_color_pict, None, dst, 0, 0, 0, 0, 0, 0, w, h); } } + else #endif - - if (bg >= 0 && !back_rendered) - XftDrawRect (d2, &term->pix_colors[bg].c, 0, 0, w, h); + XftDrawRect (d2, &term->pix_colors[bg >= 0 ? bg : Color_bg].c, 0, 0, w, h); XftDrawGlyphSpec (d2, &term->pix_colors[fg].c, f, enc, ep - enc); XCopyArea (disp, d2, d, gc, 0, 0, w, h, x, y); @@ -1440,7 +1484,7 @@ force_prop = false; for (rxvt_font **i = fonts.begin (); i != fonts.end (); i++) - FONT_UNREF (*i); + (*i)->unref (); for (pagemap **p = fmap.begin (); p != fmap.end (); p++) delete *p; @@ -1452,6 +1496,15 @@ fallback = fallback_fonts; } +void +rxvt_fontset::prepare_font (rxvt_font *font, codeset cs) +{ + font->set_term (term); + + font->cs = cs; + font->loaded = false; +} + rxvt_font * rxvt_fontset::new_font (const char *name, codeset cs) { @@ -1477,11 +1530,8 @@ else f = new rxvt_font_x11; - f->set_term (term); f->set_name (strdup (name)); - - f->cs = cs; - f->loaded = false; + prepare_font (f, cs); return f; } @@ -1489,6 +1539,23 @@ ///////////////////////////////////////////////////////////////////////////// void +rxvt_fontset::push_font (rxvt_font *font) +{ + // the fontCount index is reserved for the overflow font, it is only + // necessary when we get fontCount or more fonts, as they cannot be + // represented in the rendition. + if (fonts.size () == fontCount) + { + rxvt_font *f = new rxvt_font_overflow (this); + + prepare_font (f, CS_UNICODE); + fonts.push_back (f); + } + + fonts.push_back (font); +} + +void rxvt_fontset::add_fonts (const char *desc) { if (desc) @@ -1534,10 +1601,10 @@ if (end - desc < 511) { - strncpy (buf, desc, end - desc); + memcpy (buf, desc, end - desc); buf[end - desc] = 0; - fonts.push_back (new_font (buf, cs)); + push_font (new_font (buf, cs)); } else rxvt_warn ("fontset element too long (>511 bytes), ignored."); @@ -1575,7 +1642,7 @@ fontdesc = strdup (desc); - fonts.push_back (new_font (0, CS_UNICODE)); + push_font (new_font (0, CS_UNICODE)); realize_font (0); add_fonts (desc); @@ -1594,7 +1661,7 @@ } int -rxvt_fontset::find_font (unicode_t unicode) +rxvt_fontset::find_font_idx (unicode_t unicode) { if (unicode >= 1<<20) return 0; @@ -1630,8 +1697,7 @@ bool careful; if (f->has_char (unicode, &prop, careful)) { - if (careful) - i |= 128; + i = (i << 1) | careful; goto found; } @@ -1642,7 +1708,7 @@ if (fallback->name) { // search through the fallback list - fonts.push_back (new_font (fallback->name, fallback->cs)); + push_font (new_font (fallback->name, fallback->cs)); fallback++; } else @@ -1683,9 +1749,9 @@ if (find_font (font) < 0) { char fontname[4096]; - sprintf (fontname, "xft:%-.4090s", font); + snprintf (fontname, sizeof (fontname), "xft:%s", font); - fonts.push_back (new_font (fontname, CS_UNICODE)); + push_font (new_font (fontname, CS_UNICODE)); } free (font); @@ -1717,5 +1783,3 @@ return i; } - -