# HG changeset patch # User Jan D. # Date 1262806991 -3600 # Node ID 0865d6c0506d156e05abafe5401b3b2b4965562e # Parent 16b52378e95a2b93171820a12d99e6375bdace44# Parent 53e52339f8c2923ad1221118bccd80f3543f04e2 Fix slowdown and wrong font choosed by XSETTINGS changes. bug #5157. * font.c (font_open_entity): Enable chache and call cached_font_ok for the driver if defined. (QCuser_spec): New symbol. (font_spec_from_name): Save name as user-spec. (font_load_for_lface): Keep user-spec instead of name. (font_open_by_name): Save name as user-spec. (syms_of_font): Initialize QCuser_spec. * xftfont.c (xftfont_open): Call xftfont_add_rendering_parameters. (xftfont_add_rendering_parameters, xftfont_cached_font_ok): New. (syms_of_xftfont): Initialize xftfont_driver.cached_font_ok. * font.h (struct font_driver): Add cached_font_ok. * font-setting.el (font-setting-change-default-font): Use user-spec instead of name. diff -r 16b52378e95a -r 0865d6c0506d lisp/ChangeLog --- a/lisp/ChangeLog Wed Jan 06 09:41:59 2010 -0700 +++ b/lisp/ChangeLog Wed Jan 06 20:43:11 2010 +0100 @@ -1,3 +1,8 @@ +2010-01-06 Jan Djärv + + * font-setting.el (font-setting-change-default-font): Use user-spec + instead of name. + 2010-01-06 Dan Nicolaescu * vc-bzr.el (vc-bzr-after-dir-status): Ignore pending merges. diff -r 16b52378e95a -r 0865d6c0506d lisp/font-setting.el --- a/lisp/font-setting.el Wed Jan 06 09:41:59 2010 -0700 +++ b/lisp/font-setting.el Wed Jan 06 20:43:11 2010 +0100 @@ -57,7 +57,7 @@ (if (display-graphic-p f) (let* ((frame-font (or (font-get (face-attribute 'default :font f - 'default) :name) + 'default) :user-spec) (frame-parameter f 'font-parameter))) (font-to-set (if set-font new-font diff -r 16b52378e95a -r 0865d6c0506d src/ChangeLog --- a/src/ChangeLog Wed Jan 06 09:41:59 2010 -0700 +++ b/src/ChangeLog Wed Jan 06 20:43:11 2010 +0100 @@ -6,6 +6,21 @@ 2010-01-06 Jan Djärv + * font.c (font_open_entity): Enable chache and call cached_font_ok + for the driver if defined. + (QCuser_spec): New symbol. + (font_spec_from_name): Save name as user-spec. + (font_load_for_lface): Keep user-spec instead of name. + (font_open_by_name): Save name as user-spec. + (syms_of_font): Initialize QCuser_spec. + (font_clear_prop): Clear name if it exists in font (bug#5157). + + * xftfont.c (xftfont_open): Call xftfont_add_rendering_parameters. + (xftfont_add_rendering_parameters, xftfont_cached_font_ok): New. + (syms_of_xftfont): Initialize xftfont_driver.cached_font_ok. + + * font.h (struct font_driver): Add cached_font_ok. + * xterm.c (x_clear_frame): Queue draw for scroll bars. 2010-01-05 Jan Djärv diff -r 16b52378e95a -r 0865d6c0506d src/font.c --- a/src/font.c Wed Jan 06 09:41:59 2010 -0700 +++ b/src/font.c Wed Jan 06 20:43:11 2010 +0100 @@ -143,6 +143,8 @@ characters; used in xfont.c and ftfont.c. */ Lisp_Object Qja, Qko; +Lisp_Object QCuser_spec; + Lisp_Object Vfont_encoding_alist; /* Alist of font registry symbol and the corresponding charsets @@ -2989,16 +2991,6 @@ else if (CONSP (Vface_font_rescale_alist)) scaled_pixel_size = pixel_size * font_rescale_ratio (entity); -#if 0 - /* This doesn't work if you have changed hinting or any other parameter. - We need to make a new object in every case to be sure. */ - for (objlist = AREF (entity, FONT_OBJLIST_INDEX); CONSP (objlist); - objlist = XCDR (objlist)) - if (! NILP (AREF (XCAR (objlist), FONT_TYPE_INDEX)) - && XFONT_OBJECT (XCAR (objlist))->pixel_size == pixel_size) - return XCAR (objlist); -#endif - val = AREF (entity, FONT_TYPE_INDEX); for (driver_list = f->font_driver_list; driver_list && ! EQ (driver_list->driver->type, val); @@ -3006,6 +2998,19 @@ if (! driver_list) return Qnil; + for (objlist = AREF (entity, FONT_OBJLIST_INDEX); CONSP (objlist); + objlist = XCDR (objlist)) + { + Lisp_Object fn = XCAR (objlist); + if (! NILP (AREF (fn, FONT_TYPE_INDEX)) + && XFONT_OBJECT (fn)->pixel_size == pixel_size) + { + if (driver_list->driver->cached_font_ok == NULL + || driver_list->driver->cached_font_ok (f, fn, entity)) + return fn; + } + } + font_object = driver_list->driver->open (f, entity, scaled_pixel_size); if (!NILP (font_object)) ASET (font_object, FONT_SIZE_INDEX, make_number (pixel_size)); @@ -3161,6 +3166,7 @@ if (font_parse_name ((char *) SDATA (font_name), spec) == -1) return Qnil; font_put_extra (spec, QCname, font_name); + font_put_extra (spec, QCuser_spec, font_name); return spec; } @@ -3174,14 +3180,13 @@ if (! FONTP (font)) return; -#if 0 + if (! NILP (Ffont_get (font, QCname))) { font = Fcopy_font_spec (font); font_put_extra (font, QCname, Qnil); } -#endif if (NILP (AREF (font, prop)) && prop != FONT_FAMILY_INDEX && prop != FONT_FOUNDRY_INDEX @@ -3539,8 +3544,8 @@ entity = font_open_for_lface (f, entity, attrs, spec); if (!NILP (entity)) { - name = Ffont_get (spec, QCname); - if (STRINGP (name)) font_put_extra (entity, QCname, name); + name = Ffont_get (spec, QCuser_spec); + if (STRINGP (name)) font_put_extra (entity, QCuser_spec, name); } return entity; } @@ -3614,7 +3619,7 @@ ret = font_open_by_spec (f, spec); /* Do not loose name originally put in. */ if (!NILP (ret)) - font_put_extra (ret, QCname, args[1]); + font_put_extra (ret, QCuser_spec, args[1]); return ret; } @@ -5269,6 +5274,8 @@ DEFSYM (Qja, "ja"); DEFSYM (Qko, "ko"); + DEFSYM (QCuser_spec, "user-spec"); + staticpro (&null_vector); null_vector = Fmake_vector (make_number (0), Qnil); diff -r 16b52378e95a -r 0865d6c0506d src/font.h --- a/src/font.h Wed Jan 06 09:41:59 2010 -0700 +++ b/src/font.h Wed Jan 06 20:43:11 2010 +0100 @@ -689,6 +689,14 @@ int c, unsigned variations[256])); void (*filter_properties) P_ ((Lisp_Object font, Lisp_Object properties)); + + /* Optional. + + Return non-zero if FONT_OBJECT can be used as a (cached) font + for ENTITY on frame F. */ + int (*cached_font_ok) P_ ((struct frame *f, + Lisp_Object font_object, + Lisp_Object entity)); }; diff -r 16b52378e95a -r 0865d6c0506d src/xftfont.c --- a/src/xftfont.c Wed Jan 06 09:41:59 2010 -0700 +++ b/src/xftfont.c Wed Jan 06 20:43:11 2010 +0100 @@ -237,6 +237,56 @@ } } +static void +xftfont_add_rendering_parameters (pat, entity) + FcPattern *pat; + Lisp_Object entity; +{ + Lisp_Object tail; + int ival; + + for (tail = AREF (entity, FONT_EXTRA_INDEX); CONSP (tail); tail = XCDR (tail)) + { + Lisp_Object key = XCAR (XCAR (tail)); + Lisp_Object val = XCDR (XCAR (tail)); + + if (EQ (key, QCantialias)) + FcPatternAddBool (pat, FC_ANTIALIAS, NILP (val) ? FcFalse : FcTrue); + else if (EQ (key, QChinting)) + FcPatternAddBool (pat, FC_HINTING, NILP (val) ? FcFalse : FcTrue); + else if (EQ (key, QCautohint)) + FcPatternAddBool (pat, FC_AUTOHINT, NILP (val) ? FcFalse : FcTrue); + else if (EQ (key, QChintstyle)) + { + if (INTEGERP (val)) + FcPatternAddInteger (pat, FC_HINT_STYLE, XINT (val)); + else if (SYMBOLP (val) + && FcNameConstant (SDATA (SYMBOL_NAME (val)), &ival)) + FcPatternAddInteger (pat, FC_HINT_STYLE, ival); + } + else if (EQ (key, QCrgba)) + { + if (INTEGERP (val)) + FcPatternAddInteger (pat, FC_RGBA, XINT (val)); + else if (SYMBOLP (val) + && FcNameConstant (SDATA (SYMBOL_NAME (val)), &ival)) + FcPatternAddInteger (pat, FC_RGBA, ival); + } + else if (EQ (key, QClcdfilter)) + { + if (INTEGERP (val)) + FcPatternAddInteger (pat, FC_LCD_FILTER, ival = XINT (val)); + else if (SYMBOLP (val) + && FcNameConstant (SDATA (SYMBOL_NAME (val)), &ival)) + FcPatternAddInteger (pat, FC_LCD_FILTER, ival); + } +#ifdef FC_EMBOLDEN + else if (EQ (key, QCembolden)) + FcPatternAddBool (pat, FC_EMBOLDEN, NILP (val) ? FcFalse : FcTrue); +#endif + } +} + static Lisp_Object xftfont_open (f, entity, pixel_size) FRAME_PTR f; @@ -245,7 +295,7 @@ { FcResult result; Display *display = FRAME_X_DISPLAY (f); - Lisp_Object val, filename, index, tail, font_object; + Lisp_Object val, filename, index, font_object; FcPattern *pat = NULL, *match; struct xftfont_info *xftfont_info = NULL; struct font *font; @@ -253,7 +303,7 @@ XftFont *xftfont = NULL; int spacing; char name[256]; - int len, i, ival; + int len, i; XGlyphInfo extents; FT_Face ft_face; FcMatrix *matrix; @@ -297,46 +347,7 @@ over 10x20-ISO8859-1.pcf.gz). */ FcPatternAddCharSet (pat, FC_CHARSET, ftfont_get_fc_charset (entity)); - for (tail = AREF (entity, FONT_EXTRA_INDEX); CONSP (tail); tail = XCDR (tail)) - { - Lisp_Object key, val; - - key = XCAR (XCAR (tail)), val = XCDR (XCAR (tail)); - if (EQ (key, QCantialias)) - FcPatternAddBool (pat, FC_ANTIALIAS, NILP (val) ? FcFalse : FcTrue); - else if (EQ (key, QChinting)) - FcPatternAddBool (pat, FC_HINTING, NILP (val) ? FcFalse : FcTrue); - else if (EQ (key, QCautohint)) - FcPatternAddBool (pat, FC_AUTOHINT, NILP (val) ? FcFalse : FcTrue); - else if (EQ (key, QChintstyle)) - { - if (INTEGERP (val)) - FcPatternAddInteger (pat, FC_HINT_STYLE, XINT (val)); - else if (SYMBOLP (val) - && FcNameConstant (SDATA (SYMBOL_NAME (val)), &ival)) - FcPatternAddInteger (pat, FC_HINT_STYLE, ival); - } - else if (EQ (key, QCrgba)) - { - if (INTEGERP (val)) - FcPatternAddInteger (pat, FC_RGBA, XINT (val)); - else if (SYMBOLP (val) - && FcNameConstant (SDATA (SYMBOL_NAME (val)), &ival)) - FcPatternAddInteger (pat, FC_RGBA, ival); - } - else if (EQ (key, QClcdfilter)) - { - if (INTEGERP (val)) - FcPatternAddInteger (pat, FC_LCD_FILTER, ival = XINT (val)); - else if (SYMBOLP (val) - && FcNameConstant (SDATA (SYMBOL_NAME (val)), &ival)) - FcPatternAddInteger (pat, FC_LCD_FILTER, ival); - } -#ifdef FC_EMBOLDEN - else if (EQ (key, QCembolden)) - FcPatternAddBool (pat, FC_EMBOLDEN, NILP (val) ? FcFalse : FcTrue); -#endif - } + xftfont_add_rendering_parameters (pat, entity); FcPatternAddString (pat, FC_FILE, (FcChar8 *) SDATA (filename)); FcPatternAddInteger (pat, FC_INDEX, XINT (index)); @@ -712,6 +723,53 @@ return 0; } +static int +xftfont_cached_font_ok (f, font_object, entity) + struct frame *f; + Lisp_Object font_object; + Lisp_Object entity; + +{ + struct xftfont_info *info = (struct xftfont_info *) XFONT_OBJECT (font_object); + FcPattern *oldpat = info->xftfont->pattern; + Display *display = FRAME_X_DISPLAY (f); + FcPattern *pat = FcPatternCreate (); + FcBool b1, b2; + int ok = 0, i1, i2, r1, r2; + + xftfont_add_rendering_parameters (pat, entity); + XftDefaultSubstitute (display, FRAME_X_SCREEN_NUMBER (f), pat); + + r1 = FcPatternGetBool (pat, FC_ANTIALIAS, 0, &b1); + r2 = FcPatternGetBool (oldpat, FC_ANTIALIAS, 0, &b2); + if (r1 != r2 || b1 != b2) goto out; + r1 = FcPatternGetBool (pat, FC_HINTING, 0, &b1); + r2 = FcPatternGetBool (oldpat, FC_HINTING, 0, &b2); + if (r1 != r2 || b1 != b2) goto out; + r1 = FcPatternGetBool (pat, FC_AUTOHINT, 0, &b1); + r2 = FcPatternGetBool (oldpat, FC_AUTOHINT, 0, &b2); + if (r1 != r2 || b1 != b2) goto out; +#ifdef FC_EMBOLDEN + r1 = FcPatternGetBool (pat, FC_EMBOLDEN, 0, &b1); + r2 = FcPatternGetBool (oldpat, FC_EMBOLDEN, 0, &b2); + if (r1 != r2 || b1 != b2) goto out; +#endif + r1 = FcPatternGetInteger (pat, FC_HINT_STYLE, 0, &i1); + r2 = FcPatternGetInteger (oldpat, FC_HINT_STYLE, 0, &i2); + if (r1 != r2 || i1 != i2) goto out; + r1 = FcPatternGetInteger (pat, FC_LCD_FILTER, 0, &i1); + r2 = FcPatternGetInteger (oldpat, FC_LCD_FILTER, 0, &i2); + if (r1 != r2 || i1 != i2) goto out; + r1 = FcPatternGetInteger (pat, FC_RGBA, 0, &i1); + r2 = FcPatternGetInteger (oldpat, FC_RGBA, 0, &i2); + if (r1 != r2 || i1 != i2) goto out; + + ok = 1; + out: + FcPatternDestroy (pat); + return ok; +} + void syms_of_xftfont () { @@ -737,6 +795,7 @@ xftfont_driver.text_extents = xftfont_text_extents; xftfont_driver.draw = xftfont_draw; xftfont_driver.end_for_frame = xftfont_end_for_frame; + xftfont_driver.cached_font_ok = xftfont_cached_font_ok; register_font_driver (&xftfont_driver, NULL); }