Mercurial > emacs
annotate src/xftfont.c @ 90906:f8694254fa1d
(w32font_info): Remove subranges.
(QCsubranges, Qmodern, Qswiss, Qroman): Remove.
(QCfamily, Qmonospace, Qsans_serif, Qmono, Qsans, Qsans__serif)
(Qraster, Qoutline, Qlatin, Qgreek, Qcoptic, Qcyrillic, Qarmenian)
(Qhebrew, Qarabic, Qsyriac, Qnko, Qthaana, Qdevanagari, Qbengali)
(Qgurmukhi, Qgujarati, Qoriya, Qtamil, Qtelugu, Qkannada)
(Qmalayalam, Qsinhala, Qthai, Qlao, Qtibetan, Qmyanmar, Qgeorgian)
(Qhangul, Qethiopic, Qcherokee, Qcanadian_aboriginal, Qogham)
(Qrunic, Qkhmer, Qmongolian, Qsymbol, Qbraille, Qhan)
(Qideographic_description, Qcjk_misc, Qkana, Qbopomofo, Qkanbun)
(Qyi, Qbyzantine_musical_symbol, Qmusical_symbol, Qmathematical):
New symbols.
(font_callback_data): New struct.
(w32font_list, w32font_match): Use it.
(w32font_open): Don't populate subranges.
(w32font_has_char): Use script Lisp symbols, not subrange bitmask.
(w32font_encode_char): Always return unicode code-point as-is.
(w32font_text_extents): Supply a tranformation matrix to
GetGlyphOutline. Never look up by glyph index. Avoid looping
twice. Use unicode version of GetTexExtentPoint32 instead of
glyph index version.
(set_fonts_frame): Remove
(w32_enumfont_pattern_entity): Add frame parameter, use it to
set frame parameter. Use backward compatible fake foundries.
Save generic family in extra slot under QCfamily. Make width slot
constant. Save QCspacing value. Save list of scripts instead of
binary subranges.
(w32_generic_family, logfonts_match, font_matches_spec): New functions.
(add_font_entity_to_list): Use font_callback_data struct. Filter
unwanted fonts.
(add_one_font_entity_to_list): Use font_callback_data struct.
(w32_registry): Default to iso10646_1;
(fill_in_logfont): Use dpi from extra slot. Don't bother with
string font registries. Don't fill in font name if it is a generic
family name, fill family instead. Use spacing, family and script
extra info to fill pitch, family and charset fields.
(list_all_matching_fonts): Use font_callback_data struct.
(unicode_range_for_char): Remove.
(font_supported_scripts): New function.
(w32font_initialize): Remove.
(syms_of_w32font): Update which symbols are defined.
author | Jason Rumney <jasonr@gnu.org> |
---|---|
date | Sat, 02 Jun 2007 23:42:23 +0000 |
parents | 698001835583 |
children | 3f83c9d3f96c |
rev | line source |
---|---|
90400 | 1 /* xftfont.c -- XFT font driver. |
2 Copyright (C) 2006 Free Software Foundation, Inc. | |
3 Copyright (C) 2006 | |
4 National Institute of Advanced Industrial Science and Technology (AIST) | |
5 Registration Number H13PRO009 | |
6 | |
7 This file is part of GNU Emacs. | |
8 | |
9 GNU Emacs is free software; you can redistribute it and/or modify | |
10 it under the terms of the GNU General Public License as published by | |
11 the Free Software Foundation; either version 2, or (at your option) | |
12 any later version. | |
13 | |
14 GNU Emacs is distributed in the hope that it will be useful, | |
15 but WITHOUT ANY WARRANTY; without even the implied warranty of | |
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
17 GNU General Public License for more details. | |
18 | |
19 You should have received a copy of the GNU General Public License | |
20 along with GNU Emacs; see the file COPYING. If not, write to | |
21 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | |
22 Boston, MA 02110-1301, USA. */ | |
23 | |
24 #include <config.h> | |
25 #include <stdio.h> | |
26 #include <X11/Xlib.h> | |
27 #include <X11/Xft/Xft.h> | |
28 | |
29 #include "lisp.h" | |
30 #include "dispextern.h" | |
31 #include "xterm.h" | |
32 #include "frame.h" | |
33 #include "blockinput.h" | |
34 #include "character.h" | |
35 #include "charset.h" | |
36 #include "fontset.h" | |
37 #include "font.h" | |
38 | |
39 /* Xft font driver. */ | |
40 | |
41 static Lisp_Object Qxft; | |
42 | |
43 /* The actual structure for Xft font that can be casted to struct | |
44 font. */ | |
45 | |
46 struct xftfont_info | |
47 { | |
48 struct font font; | |
49 Display *display; | |
50 int screen; | |
51 XftFont *xftfont; | |
90559
fb5d3ac2d786
(xftfont_match): New function.
Kenichi Handa <handa@m17n.org>
parents:
90527
diff
changeset
|
52 FT_Face ft_face; /* set to XftLockFace (xftfont) */ |
90400 | 53 }; |
54 | |
55 /* Structure pointed by (struct face *)->extra */ | |
90559
fb5d3ac2d786
(xftfont_match): New function.
Kenichi Handa <handa@m17n.org>
parents:
90527
diff
changeset
|
56 |
90400 | 57 struct xftface_info |
58 { | |
90559
fb5d3ac2d786
(xftfont_match): New function.
Kenichi Handa <handa@m17n.org>
parents:
90527
diff
changeset
|
59 XftColor xft_fg; /* color for face->foreground */ |
fb5d3ac2d786
(xftfont_match): New function.
Kenichi Handa <handa@m17n.org>
parents:
90527
diff
changeset
|
60 XftColor xft_bg; /* color for face->background */ |
90400 | 61 XftDraw *xft_draw; |
62 }; | |
63 | |
64 static void xftfont_get_colors P_ ((FRAME_PTR, struct face *, GC gc, | |
65 struct xftface_info *, | |
66 XftColor *fg, XftColor *bg)); | |
67 static Font xftfont_default_fid P_ ((FRAME_PTR)); | |
68 | |
69 | |
90559
fb5d3ac2d786
(xftfont_match): New function.
Kenichi Handa <handa@m17n.org>
parents:
90527
diff
changeset
|
70 /* Setup foreground and background colors of GC into FG and BG. If |
fb5d3ac2d786
(xftfont_match): New function.
Kenichi Handa <handa@m17n.org>
parents:
90527
diff
changeset
|
71 XFTFACE_INFO is not NULL, reuse the colors in it if possible. BG |
fb5d3ac2d786
(xftfont_match): New function.
Kenichi Handa <handa@m17n.org>
parents:
90527
diff
changeset
|
72 may be NULL. */ |
fb5d3ac2d786
(xftfont_match): New function.
Kenichi Handa <handa@m17n.org>
parents:
90527
diff
changeset
|
73 |
90400 | 74 static void |
75 xftfont_get_colors (f, face, gc, xftface_info, fg, bg) | |
76 FRAME_PTR f; | |
77 struct face *face; | |
78 GC gc; | |
79 struct xftface_info *xftface_info; | |
80 XftColor *fg, *bg; | |
81 { | |
82 if (xftface_info && face->gc == gc) | |
83 { | |
84 *fg = xftface_info->xft_fg; | |
85 if (bg) | |
86 *bg = xftface_info->xft_bg; | |
87 } | |
88 else | |
89 { | |
90 XGCValues xgcv; | |
91 int fg_done = 0, bg_done = 0; | |
92 | |
93 BLOCK_INPUT; | |
94 XGetGCValues (FRAME_X_DISPLAY (f), gc, | |
95 GCForeground | GCBackground, &xgcv); | |
96 if (xftface_info) | |
97 { | |
98 if (xgcv.foreground == face->foreground) | |
99 *fg = xftface_info->xft_fg, fg_done = 1; | |
100 else if (xgcv.foreground == face->background) | |
101 *fg = xftface_info->xft_bg, fg_done = 1; | |
102 if (! bg) | |
103 bg_done = 1; | |
104 else if (xgcv.background == face->background) | |
105 *bg = xftface_info->xft_bg, bg_done = 1; | |
106 else if (xgcv.background == face->foreground) | |
107 *bg = xftface_info->xft_fg, bg_done = 1; | |
108 } | |
109 | |
110 if (fg_done + bg_done < 2) | |
111 { | |
112 XColor colors[2]; | |
113 | |
114 colors[0].pixel = fg->pixel = xgcv.foreground; | |
115 if (bg) | |
116 colors[1].pixel = bg->pixel = xgcv.background; | |
117 XQueryColors (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), colors, | |
118 bg ? 2 : 1); | |
119 fg->color.alpha = 0xFFFF; | |
120 fg->color.red = colors[0].red; | |
121 fg->color.green = colors[0].green; | |
122 fg->color.blue = colors[0].blue; | |
123 if (bg) | |
124 { | |
125 bg->color.alpha = 0xFFFF; | |
126 bg->color.red = colors[1].red; | |
127 bg->color.green = colors[1].green; | |
128 bg->color.blue = colors[1].blue; | |
129 } | |
130 } | |
131 UNBLOCK_INPUT; | |
132 } | |
133 } | |
134 | |
90559
fb5d3ac2d786
(xftfont_match): New function.
Kenichi Handa <handa@m17n.org>
parents:
90527
diff
changeset
|
135 /* Return the default Font ID on frame F. The Returned Font ID is |
fb5d3ac2d786
(xftfont_match): New function.
Kenichi Handa <handa@m17n.org>
parents:
90527
diff
changeset
|
136 stored in the GC of the frame F, but the font is never used. So, |
fb5d3ac2d786
(xftfont_match): New function.
Kenichi Handa <handa@m17n.org>
parents:
90527
diff
changeset
|
137 any ID is ok as long as it is valid. */ |
90400 | 138 |
139 static Font | |
140 xftfont_default_fid (f) | |
141 FRAME_PTR f; | |
142 { | |
143 static int fid_known; | |
144 static Font fid; | |
145 | |
146 if (! fid_known) | |
147 { | |
148 fid = XLoadFont (FRAME_X_DISPLAY (f), "fixed"); | |
149 if (! fid) | |
150 { | |
151 fid = XLoadFont (FRAME_X_DISPLAY (f), "*"); | |
152 if (! fid) | |
153 abort (); | |
154 } | |
90426
e9ed7d437c21
(xftfont_default_fid): Set fid_known to 1.
Kenichi Handa <handa@m17n.org>
parents:
90400
diff
changeset
|
155 fid_known = 1; |
90400 | 156 } |
157 return fid; | |
158 } | |
159 | |
160 | |
161 static Lisp_Object xftfont_list P_ ((Lisp_Object, Lisp_Object)); | |
90559
fb5d3ac2d786
(xftfont_match): New function.
Kenichi Handa <handa@m17n.org>
parents:
90527
diff
changeset
|
162 static Lisp_Object xftfont_match P_ ((Lisp_Object, Lisp_Object)); |
90400 | 163 static struct font *xftfont_open P_ ((FRAME_PTR, Lisp_Object, int)); |
164 static void xftfont_close P_ ((FRAME_PTR, struct font *)); | |
165 static int xftfont_prepare_face P_ ((FRAME_PTR, struct face *)); | |
166 static void xftfont_done_face P_ ((FRAME_PTR, struct face *)); | |
167 static unsigned xftfont_encode_char P_ ((struct font *, int)); | |
168 static int xftfont_text_extents P_ ((struct font *, unsigned *, int, | |
169 struct font_metrics *)); | |
170 static int xftfont_draw P_ ((struct glyph_string *, int, int, int, int, int)); | |
171 | |
172 static int xftfont_anchor_point P_ ((struct font *, unsigned, int, | |
173 int *, int *)); | |
174 | |
175 struct font_driver xftfont_driver; | |
176 | |
177 static Lisp_Object | |
178 xftfont_list (frame, spec) | |
179 Lisp_Object frame; | |
180 Lisp_Object spec; | |
181 { | |
182 Lisp_Object val = ftfont_driver.list (frame, spec); | |
90559
fb5d3ac2d786
(xftfont_match): New function.
Kenichi Handa <handa@m17n.org>
parents:
90527
diff
changeset
|
183 int i; |
90400 | 184 |
185 if (! NILP (val)) | |
90559
fb5d3ac2d786
(xftfont_match): New function.
Kenichi Handa <handa@m17n.org>
parents:
90527
diff
changeset
|
186 for (i = 0; i < ASIZE (val); i++) |
fb5d3ac2d786
(xftfont_match): New function.
Kenichi Handa <handa@m17n.org>
parents:
90527
diff
changeset
|
187 ASET (AREF (val, i), FONT_TYPE_INDEX, Qxft); |
fb5d3ac2d786
(xftfont_match): New function.
Kenichi Handa <handa@m17n.org>
parents:
90527
diff
changeset
|
188 return val; |
fb5d3ac2d786
(xftfont_match): New function.
Kenichi Handa <handa@m17n.org>
parents:
90527
diff
changeset
|
189 } |
90400 | 190 |
90559
fb5d3ac2d786
(xftfont_match): New function.
Kenichi Handa <handa@m17n.org>
parents:
90527
diff
changeset
|
191 static Lisp_Object |
fb5d3ac2d786
(xftfont_match): New function.
Kenichi Handa <handa@m17n.org>
parents:
90527
diff
changeset
|
192 xftfont_match (frame, spec) |
fb5d3ac2d786
(xftfont_match): New function.
Kenichi Handa <handa@m17n.org>
parents:
90527
diff
changeset
|
193 Lisp_Object frame; |
fb5d3ac2d786
(xftfont_match): New function.
Kenichi Handa <handa@m17n.org>
parents:
90527
diff
changeset
|
194 Lisp_Object spec; |
fb5d3ac2d786
(xftfont_match): New function.
Kenichi Handa <handa@m17n.org>
parents:
90527
diff
changeset
|
195 { |
fb5d3ac2d786
(xftfont_match): New function.
Kenichi Handa <handa@m17n.org>
parents:
90527
diff
changeset
|
196 Lisp_Object entity = ftfont_driver.match (frame, spec); |
fb5d3ac2d786
(xftfont_match): New function.
Kenichi Handa <handa@m17n.org>
parents:
90527
diff
changeset
|
197 |
fb5d3ac2d786
(xftfont_match): New function.
Kenichi Handa <handa@m17n.org>
parents:
90527
diff
changeset
|
198 if (VECTORP (entity)) |
fb5d3ac2d786
(xftfont_match): New function.
Kenichi Handa <handa@m17n.org>
parents:
90527
diff
changeset
|
199 ASET (entity, FONT_TYPE_INDEX, Qxft); |
fb5d3ac2d786
(xftfont_match): New function.
Kenichi Handa <handa@m17n.org>
parents:
90527
diff
changeset
|
200 return entity; |
90400 | 201 } |
202 | |
90700
b165eceb829f
(ftfont_font_format): Extern declaration.
Kenichi Handa <handa@m17n.org>
parents:
90675
diff
changeset
|
203 extern Lisp_Object ftfont_font_format P_ ((FcPattern *)); |
b165eceb829f
(ftfont_font_format): Extern declaration.
Kenichi Handa <handa@m17n.org>
parents:
90675
diff
changeset
|
204 |
90400 | 205 static FcChar8 ascii_printable[95]; |
206 | |
207 static struct font * | |
208 xftfont_open (f, entity, pixel_size) | |
209 FRAME_PTR f; | |
210 Lisp_Object entity; | |
211 int pixel_size; | |
212 { | |
213 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f); | |
214 Display *display = FRAME_X_DISPLAY (f); | |
215 Lisp_Object val; | |
90460
86449661f321
(xftfont_open): Change coding style of error
Kenichi Handa <handa@m17n.org>
parents:
90442
diff
changeset
|
216 FcPattern *pattern, *pat = NULL; |
86449661f321
(xftfont_open): Change coding style of error
Kenichi Handa <handa@m17n.org>
parents:
90442
diff
changeset
|
217 FcChar8 *file; |
86449661f321
(xftfont_open): Change coding style of error
Kenichi Handa <handa@m17n.org>
parents:
90442
diff
changeset
|
218 struct xftfont_info *xftfont_info = NULL; |
86449661f321
(xftfont_open): Change coding style of error
Kenichi Handa <handa@m17n.org>
parents:
90442
diff
changeset
|
219 XFontStruct *xfont = NULL; |
90400 | 220 struct font *font; |
221 double size = 0; | |
90460
86449661f321
(xftfont_open): Change coding style of error
Kenichi Handa <handa@m17n.org>
parents:
90442
diff
changeset
|
222 XftFont *xftfont = NULL; |
90400 | 223 int spacing; |
90460
86449661f321
(xftfont_open): Change coding style of error
Kenichi Handa <handa@m17n.org>
parents:
90442
diff
changeset
|
224 char *name; |
90442
d6abf2344438
(xftfont_open): Make the font name fontconfig's
Kenichi Handa <handa@m17n.org>
parents:
90427
diff
changeset
|
225 int len; |
90400 | 226 |
227 val = AREF (entity, FONT_EXTRA_INDEX); | |
228 if (XTYPE (val) != Lisp_Misc | |
229 || XMISCTYPE (val) != Lisp_Misc_Save_Value) | |
230 return NULL; | |
231 pattern = XSAVE_VALUE (val)->pointer; | |
232 if (FcPatternGetString (pattern, FC_FILE, 0, &file) != FcResultMatch) | |
233 return NULL; | |
234 | |
235 size = XINT (AREF (entity, FONT_SIZE_INDEX)); | |
236 if (size == 0) | |
237 size = pixel_size; | |
90442
d6abf2344438
(xftfont_open): Make the font name fontconfig's
Kenichi Handa <handa@m17n.org>
parents:
90427
diff
changeset
|
238 |
90400 | 239 pat = FcPatternCreate (); |
240 FcPatternAddString (pat, FC_FILE, file); | |
241 FcPatternAddDouble (pat, FC_PIXEL_SIZE, pixel_size); | |
90712
8594053c8fec
(xftfont_open): Don't enable antialias explicitly.
Kenichi Handa <handa@m17n.org>
parents:
90700
diff
changeset
|
242 /*FcPatternAddBool (pat, FC_ANTIALIAS, FcTrue);*/ |
90714
698001835583
(xftfont_open): Call FcConfigSubstitute.
Kenichi Handa <handa@m17n.org>
parents:
90712
diff
changeset
|
243 val = AREF (entity, FONT_FAMILY_INDEX); |
698001835583
(xftfont_open): Call FcConfigSubstitute.
Kenichi Handa <handa@m17n.org>
parents:
90712
diff
changeset
|
244 if (! NILP (val)) |
698001835583
(xftfont_open): Call FcConfigSubstitute.
Kenichi Handa <handa@m17n.org>
parents:
90712
diff
changeset
|
245 FcPatternAddString (pat, FC_FAMILY, (FcChar8 *) SDATA (SYMBOL_NAME (val))); |
698001835583
(xftfont_open): Call FcConfigSubstitute.
Kenichi Handa <handa@m17n.org>
parents:
90712
diff
changeset
|
246 FcConfigSubstitute (NULL, pat, FcMatchPattern); |
90442
d6abf2344438
(xftfont_open): Make the font name fontconfig's
Kenichi Handa <handa@m17n.org>
parents:
90427
diff
changeset
|
247 |
d6abf2344438
(xftfont_open): Make the font name fontconfig's
Kenichi Handa <handa@m17n.org>
parents:
90427
diff
changeset
|
248 BLOCK_INPUT; |
90589
697dcc1df88d
(xftfont_open): Call XftDefaultSubstitute before
Kenichi Handa <handa@m17n.org>
parents:
90559
diff
changeset
|
249 XftDefaultSubstitute (display, FRAME_X_SCREEN_NUMBER (f), pat); |
90400 | 250 xftfont = XftFontOpenPattern (display, pat); |
251 /* We should not destroy PAT here because it is kept in XFTFONT and | |
252 destroyed automatically when XFTFONT is closed. */ | |
253 if (! xftfont) | |
90460
86449661f321
(xftfont_open): Change coding style of error
Kenichi Handa <handa@m17n.org>
parents:
90442
diff
changeset
|
254 goto err; |
90400 | 255 |
256 xftfont_info = malloc (sizeof (struct xftfont_info)); | |
257 if (! xftfont_info) | |
90460
86449661f321
(xftfont_open): Change coding style of error
Kenichi Handa <handa@m17n.org>
parents:
90442
diff
changeset
|
258 goto err; |
90400 | 259 xfont = malloc (sizeof (XFontStruct)); |
90460
86449661f321
(xftfont_open): Change coding style of error
Kenichi Handa <handa@m17n.org>
parents:
90442
diff
changeset
|
260 if (! xfont) |
86449661f321
(xftfont_open): Change coding style of error
Kenichi Handa <handa@m17n.org>
parents:
90442
diff
changeset
|
261 goto err; |
90400 | 262 xftfont_info->display = display; |
263 xftfont_info->screen = FRAME_X_SCREEN_NUMBER (f); | |
264 xftfont_info->xftfont = xftfont; | |
265 xftfont_info->ft_face = XftLockFace (xftfont); | |
266 | |
267 font = (struct font *) xftfont_info; | |
90675
dfe6bfcd570f
(xftfont_open): Set font->format.
Kenichi Handa <handa@m17n.org>
parents:
90616
diff
changeset
|
268 font->format = ftfont_font_format (xftfont->pattern); |
90400 | 269 font->entity = entity; |
270 font->pixel_size = size; | |
271 font->driver = &xftfont_driver; | |
90473
9c75458ea910
(xftfont_open): For generating a name, start from
Kenichi Handa <handa@m17n.org>
parents:
90460
diff
changeset
|
272 len = 96; |
90460
86449661f321
(xftfont_open): Change coding style of error
Kenichi Handa <handa@m17n.org>
parents:
90442
diff
changeset
|
273 name = malloc (len); |
86449661f321
(xftfont_open): Change coding style of error
Kenichi Handa <handa@m17n.org>
parents:
90442
diff
changeset
|
274 while (name && font_unparse_fcname (entity, pixel_size, name, len) < 0) |
86449661f321
(xftfont_open): Change coding style of error
Kenichi Handa <handa@m17n.org>
parents:
90442
diff
changeset
|
275 { |
86449661f321
(xftfont_open): Change coding style of error
Kenichi Handa <handa@m17n.org>
parents:
90442
diff
changeset
|
276 char *new = realloc (name, len += 32); |
86449661f321
(xftfont_open): Change coding style of error
Kenichi Handa <handa@m17n.org>
parents:
90442
diff
changeset
|
277 |
86449661f321
(xftfont_open): Change coding style of error
Kenichi Handa <handa@m17n.org>
parents:
90442
diff
changeset
|
278 if (! new) |
86449661f321
(xftfont_open): Change coding style of error
Kenichi Handa <handa@m17n.org>
parents:
90442
diff
changeset
|
279 free (name); |
86449661f321
(xftfont_open): Change coding style of error
Kenichi Handa <handa@m17n.org>
parents:
90442
diff
changeset
|
280 name = new; |
86449661f321
(xftfont_open): Change coding style of error
Kenichi Handa <handa@m17n.org>
parents:
90442
diff
changeset
|
281 } |
86449661f321
(xftfont_open): Change coding style of error
Kenichi Handa <handa@m17n.org>
parents:
90442
diff
changeset
|
282 if (! name) |
86449661f321
(xftfont_open): Change coding style of error
Kenichi Handa <handa@m17n.org>
parents:
90442
diff
changeset
|
283 goto err; |
86449661f321
(xftfont_open): Change coding style of error
Kenichi Handa <handa@m17n.org>
parents:
90442
diff
changeset
|
284 font->font.full_name = font->font.name = name; |
90400 | 285 font->file_name = (char *) file; |
286 font->font.size = xftfont->max_advance_width; | |
90511
2cd8e24f656a
(xftfont_open): Set charset related members to -1.
Kenichi Handa <handa@m17n.org>
parents:
90499
diff
changeset
|
287 font->font.charset = font->encoding_charset = font->repertory_charset = -1; |
90400 | 288 font->ascent = xftfont->ascent; |
289 font->descent = xftfont->descent; | |
290 font->font.height = xftfont->ascent + xftfont->descent; | |
291 | |
292 if (FcPatternGetInteger (xftfont->pattern, FC_SPACING, 0, &spacing) | |
293 != FcResultMatch) | |
294 spacing = FC_PROPORTIONAL; | |
295 if (spacing != FC_PROPORTIONAL) | |
296 font->font.average_width = font->font.space_width | |
297 = xftfont->max_advance_width; | |
298 else | |
299 { | |
300 XGlyphInfo extents; | |
301 | |
302 if (! ascii_printable[0]) | |
303 { | |
304 int i; | |
305 for (i = 0; i < 95; i++) | |
306 ascii_printable[i] = ' ' + i; | |
307 } | |
308 XftTextExtents8 (display, xftfont, ascii_printable, 1, &extents); | |
309 font->font.space_width = extents.xOff; | |
310 if (font->font.space_width <= 0) | |
311 /* dirty workaround */ | |
312 font->font.space_width = pixel_size; | |
313 XftTextExtents8 (display, xftfont, ascii_printable + 1, 94, &extents); | |
314 font->font.average_width = (font->font.space_width + extents.xOff) / 95; | |
315 } | |
90442
d6abf2344438
(xftfont_open): Make the font name fontconfig's
Kenichi Handa <handa@m17n.org>
parents:
90427
diff
changeset
|
316 UNBLOCK_INPUT; |
90400 | 317 |
318 /* Unfortunately Xft doesn't provide a way to get minimum char | |
319 width. So, we use space_width instead. */ | |
320 font->min_width = font->font.space_width; | |
321 | |
322 font->font.baseline_offset = 0; | |
323 font->font.relative_compose = 0; | |
324 font->font.default_ascent = 0; | |
325 font->font.vertical_centering = 0; | |
326 | |
327 /* Setup pseudo XFontStruct */ | |
328 xfont->fid = xftfont_default_fid (f); | |
329 xfont->ascent = xftfont->ascent; | |
330 xfont->descent = xftfont->descent; | |
331 xfont->max_bounds.descent = xftfont->descent; | |
332 xfont->max_bounds.width = xftfont->max_advance_width; | |
333 xfont->min_bounds.width = font->font.space_width; | |
334 font->font.font = xfont; | |
335 | |
336 dpyinfo->n_fonts++; | |
337 | |
338 /* Set global flag fonts_changed_p to non-zero if the font loaded | |
339 has a character with a smaller width than any other character | |
340 before, or if the font loaded has a smaller height than any other | |
341 font loaded before. If this happens, it will make a glyph matrix | |
342 reallocation necessary. */ | |
343 if (dpyinfo->n_fonts == 1) | |
344 { | |
345 dpyinfo->smallest_font_height = font->font.height; | |
346 dpyinfo->smallest_char_width = font->min_width; | |
347 fonts_changed_p = 1; | |
348 } | |
349 else | |
350 { | |
351 if (dpyinfo->smallest_font_height > font->font.height) | |
352 dpyinfo->smallest_font_height = font->font.height, | |
353 fonts_changed_p |= 1; | |
354 if (dpyinfo->smallest_char_width > font->min_width) | |
355 dpyinfo->smallest_char_width = font->min_width, | |
356 fonts_changed_p |= 1; | |
357 } | |
358 | |
359 return font; | |
90460
86449661f321
(xftfont_open): Change coding style of error
Kenichi Handa <handa@m17n.org>
parents:
90442
diff
changeset
|
360 |
86449661f321
(xftfont_open): Change coding style of error
Kenichi Handa <handa@m17n.org>
parents:
90442
diff
changeset
|
361 err: |
86449661f321
(xftfont_open): Change coding style of error
Kenichi Handa <handa@m17n.org>
parents:
90442
diff
changeset
|
362 if (xftfont) XftFontClose (display, xftfont); |
86449661f321
(xftfont_open): Change coding style of error
Kenichi Handa <handa@m17n.org>
parents:
90442
diff
changeset
|
363 UNBLOCK_INPUT; |
86449661f321
(xftfont_open): Change coding style of error
Kenichi Handa <handa@m17n.org>
parents:
90442
diff
changeset
|
364 if (xftfont_info) free (xftfont_info); |
86449661f321
(xftfont_open): Change coding style of error
Kenichi Handa <handa@m17n.org>
parents:
90442
diff
changeset
|
365 if (xfont) free (xfont); |
86449661f321
(xftfont_open): Change coding style of error
Kenichi Handa <handa@m17n.org>
parents:
90442
diff
changeset
|
366 return NULL; |
90400 | 367 } |
368 | |
369 static void | |
370 xftfont_close (f, font) | |
371 FRAME_PTR f; | |
372 struct font *font; | |
373 { | |
374 struct xftfont_info *xftfont_info = (struct xftfont_info *) font; | |
375 | |
376 XftUnlockFace (xftfont_info->xftfont); | |
377 XftFontClose (xftfont_info->display, xftfont_info->xftfont); | |
90442
d6abf2344438
(xftfont_open): Make the font name fontconfig's
Kenichi Handa <handa@m17n.org>
parents:
90427
diff
changeset
|
378 if (font->font.name) |
d6abf2344438
(xftfont_open): Make the font name fontconfig's
Kenichi Handa <handa@m17n.org>
parents:
90427
diff
changeset
|
379 free (font->font.name); |
90400 | 380 free (font); |
381 FRAME_X_DISPLAY_INFO (f)->n_fonts--; | |
382 } | |
383 | |
384 static int | |
385 xftfont_prepare_face (f, face) | |
386 FRAME_PTR f; | |
387 struct face *face; | |
388 { | |
90489
78a820ef12db
(xftfont_prepare_face): Make non-ascii face share
Kenichi Handa <handa@m17n.org>
parents:
90473
diff
changeset
|
389 struct xftface_info *xftface_info; |
90400 | 390 |
90499
32b8f672da38
(xftfont_prepare_face): Cancel previous change.
Kenichi Handa <handa@m17n.org>
parents:
90489
diff
changeset
|
391 #if 0 |
32b8f672da38
(xftfont_prepare_face): Cancel previous change.
Kenichi Handa <handa@m17n.org>
parents:
90489
diff
changeset
|
392 /* This doesn't work if face->ascii_face doesn't use an Xft font. */ |
90489
78a820ef12db
(xftfont_prepare_face): Make non-ascii face share
Kenichi Handa <handa@m17n.org>
parents:
90473
diff
changeset
|
393 if (face != face->ascii_face) |
78a820ef12db
(xftfont_prepare_face): Make non-ascii face share
Kenichi Handa <handa@m17n.org>
parents:
90473
diff
changeset
|
394 { |
78a820ef12db
(xftfont_prepare_face): Make non-ascii face share
Kenichi Handa <handa@m17n.org>
parents:
90473
diff
changeset
|
395 face->extra = face->ascii_face->extra; |
78a820ef12db
(xftfont_prepare_face): Make non-ascii face share
Kenichi Handa <handa@m17n.org>
parents:
90473
diff
changeset
|
396 return 0; |
78a820ef12db
(xftfont_prepare_face): Make non-ascii face share
Kenichi Handa <handa@m17n.org>
parents:
90473
diff
changeset
|
397 } |
90499
32b8f672da38
(xftfont_prepare_face): Cancel previous change.
Kenichi Handa <handa@m17n.org>
parents:
90489
diff
changeset
|
398 #endif |
90489
78a820ef12db
(xftfont_prepare_face): Make non-ascii face share
Kenichi Handa <handa@m17n.org>
parents:
90473
diff
changeset
|
399 |
78a820ef12db
(xftfont_prepare_face): Make non-ascii face share
Kenichi Handa <handa@m17n.org>
parents:
90473
diff
changeset
|
400 xftface_info = malloc (sizeof (struct xftface_info)); |
90400 | 401 if (! xftface_info) |
402 return -1; | |
403 | |
404 BLOCK_INPUT; | |
405 xftface_info->xft_draw = XftDrawCreate (FRAME_X_DISPLAY (f), | |
406 FRAME_X_WINDOW (f), | |
407 FRAME_X_VISUAL (f), | |
408 FRAME_X_COLORMAP (f)); | |
409 xftfont_get_colors (f, face, face->gc, NULL, | |
410 &xftface_info->xft_fg, &xftface_info->xft_bg); | |
411 UNBLOCK_INPUT; | |
412 | |
413 face->extra = xftface_info; | |
414 return 0; | |
415 } | |
416 | |
417 static void | |
418 xftfont_done_face (f, face) | |
419 FRAME_PTR f; | |
420 struct face *face; | |
421 { | |
90489
78a820ef12db
(xftfont_prepare_face): Make non-ascii face share
Kenichi Handa <handa@m17n.org>
parents:
90473
diff
changeset
|
422 struct xftface_info *xftface_info; |
78a820ef12db
(xftfont_prepare_face): Make non-ascii face share
Kenichi Handa <handa@m17n.org>
parents:
90473
diff
changeset
|
423 |
90499
32b8f672da38
(xftfont_prepare_face): Cancel previous change.
Kenichi Handa <handa@m17n.org>
parents:
90489
diff
changeset
|
424 #if 0 |
32b8f672da38
(xftfont_prepare_face): Cancel previous change.
Kenichi Handa <handa@m17n.org>
parents:
90489
diff
changeset
|
425 /* This doesn't work if face->ascii_face doesn't use an Xft font. */ |
90489
78a820ef12db
(xftfont_prepare_face): Make non-ascii face share
Kenichi Handa <handa@m17n.org>
parents:
90473
diff
changeset
|
426 if (face != face->ascii_face |
78a820ef12db
(xftfont_prepare_face): Make non-ascii face share
Kenichi Handa <handa@m17n.org>
parents:
90473
diff
changeset
|
427 || ! face->extra) |
78a820ef12db
(xftfont_prepare_face): Make non-ascii face share
Kenichi Handa <handa@m17n.org>
parents:
90473
diff
changeset
|
428 return; |
90499
32b8f672da38
(xftfont_prepare_face): Cancel previous change.
Kenichi Handa <handa@m17n.org>
parents:
90489
diff
changeset
|
429 #endif |
90400 | 430 |
90489
78a820ef12db
(xftfont_prepare_face): Make non-ascii face share
Kenichi Handa <handa@m17n.org>
parents:
90473
diff
changeset
|
431 xftface_info = (struct xftface_info *) face->extra; |
90527
63b888896eba
* xftfont.c (xftfont_done_face): Call XftDrawDestroy only if xftface_info
Jan Djärv <jan.h.d@swipnet.se>
parents:
90511
diff
changeset
|
432 if (xftface_info) |
63b888896eba
* xftfont.c (xftfont_done_face): Call XftDrawDestroy only if xftface_info
Jan Djärv <jan.h.d@swipnet.se>
parents:
90511
diff
changeset
|
433 { |
63b888896eba
* xftfont.c (xftfont_done_face): Call XftDrawDestroy only if xftface_info
Jan Djärv <jan.h.d@swipnet.se>
parents:
90511
diff
changeset
|
434 BLOCK_INPUT; |
63b888896eba
* xftfont.c (xftfont_done_face): Call XftDrawDestroy only if xftface_info
Jan Djärv <jan.h.d@swipnet.se>
parents:
90511
diff
changeset
|
435 XftDrawDestroy (xftface_info->xft_draw); |
63b888896eba
* xftfont.c (xftfont_done_face): Call XftDrawDestroy only if xftface_info
Jan Djärv <jan.h.d@swipnet.se>
parents:
90511
diff
changeset
|
436 UNBLOCK_INPUT; |
63b888896eba
* xftfont.c (xftfont_done_face): Call XftDrawDestroy only if xftface_info
Jan Djärv <jan.h.d@swipnet.se>
parents:
90511
diff
changeset
|
437 free (xftface_info); |
63b888896eba
* xftfont.c (xftfont_done_face): Call XftDrawDestroy only if xftface_info
Jan Djärv <jan.h.d@swipnet.se>
parents:
90511
diff
changeset
|
438 } |
90489
78a820ef12db
(xftfont_prepare_face): Make non-ascii face share
Kenichi Handa <handa@m17n.org>
parents:
90473
diff
changeset
|
439 face->extra = NULL; |
90400 | 440 } |
441 | |
442 static unsigned | |
443 xftfont_encode_char (font, c) | |
444 struct font *font; | |
445 int c; | |
446 { | |
447 struct xftfont_info *xftfont_info = (struct xftfont_info *) font; | |
448 unsigned code = XftCharIndex (xftfont_info->display, xftfont_info->xftfont, | |
449 (FcChar32) c); | |
450 | |
451 return (code ? code : 0xFFFFFFFF); | |
452 } | |
453 | |
454 static int | |
455 xftfont_text_extents (font, code, nglyphs, metrics) | |
456 struct font *font; | |
457 unsigned *code; | |
458 int nglyphs; | |
459 struct font_metrics *metrics; | |
460 { | |
461 struct xftfont_info *xftfont_info = (struct xftfont_info *) font; | |
462 XGlyphInfo extents; | |
463 | |
464 BLOCK_INPUT; | |
465 XftGlyphExtents (xftfont_info->display, xftfont_info->xftfont, code, nglyphs, | |
466 &extents); | |
467 UNBLOCK_INPUT; | |
468 if (metrics) | |
469 { | |
470 metrics->lbearing = - extents.x; | |
471 metrics->rbearing = - extents.x + extents.width; | |
472 metrics->width = extents.xOff; | |
473 metrics->ascent = extents.y; | |
90616
68d59ef20174
(xftfont_text_extents): Fix calculation of descent
Kenichi Handa <handa@m17n.org>
parents:
90589
diff
changeset
|
474 metrics->descent = extents.height - extents.y; |
90400 | 475 } |
476 return extents.xOff; | |
477 } | |
478 | |
479 static int | |
480 xftfont_draw (s, from, to, x, y, with_background) | |
481 struct glyph_string *s; | |
482 int from, to, x, y, with_background; | |
483 { | |
484 FRAME_PTR f = s->f; | |
485 struct face *face = s->face; | |
486 struct xftfont_info *xftfont_info = (struct xftfont_info *) face->font_info; | |
487 struct xftface_info *xftface_info = (struct xftface_info *) face->extra; | |
488 FT_UInt *code; | |
489 XftColor fg, bg; | |
490 XRectangle r; | |
491 int len = to - from; | |
492 int i; | |
493 | |
494 xftfont_get_colors (f, face, s->gc, xftface_info, | |
90426
e9ed7d437c21
(xftfont_default_fid): Set fid_known to 1.
Kenichi Handa <handa@m17n.org>
parents:
90400
diff
changeset
|
495 &fg, with_background ? &bg : NULL); |
90400 | 496 BLOCK_INPUT; |
497 if (s->clip_width) | |
498 { | |
499 r.x = s->clip_x, r.width = s->clip_width; | |
500 r.y = s->clip_y, r.height = s->clip_height; | |
501 XftDrawSetClipRectangles (xftface_info->xft_draw, 0, 0, &r, 1); | |
502 } | |
503 if (with_background) | |
504 { | |
505 struct font *font = (struct font *) face->font_info; | |
506 | |
507 XftDrawRect (xftface_info->xft_draw, &bg, | |
508 x, y - face->font->ascent, s->width, font->font.height); | |
509 } | |
510 code = alloca (sizeof (FT_UInt) * len); | |
511 for (i = 0; i < len; i++) | |
512 code[i] = ((XCHAR2B_BYTE1 (s->char2b + from + i) << 8) | |
513 | XCHAR2B_BYTE2 (s->char2b + from + i)); | |
514 | |
515 XftDrawGlyphs (xftface_info->xft_draw, &fg, xftfont_info->xftfont, | |
516 x, y, code, len); | |
517 if (s->clip_width) | |
518 XftDrawSetClip (xftface_info->xft_draw, NULL); | |
519 UNBLOCK_INPUT; | |
520 | |
521 return len; | |
522 } | |
523 | |
524 static int | |
525 xftfont_anchor_point (font, code, index, x, y) | |
526 struct font *font; | |
527 unsigned code; | |
528 int index; | |
529 int *x, *y; | |
530 { | |
531 struct xftfont_info *xftfont_info = (struct xftfont_info *) font; | |
532 FT_Face ft_face = xftfont_info->ft_face; | |
533 | |
534 if (FT_Load_Glyph (ft_face, code, FT_LOAD_DEFAULT) != 0) | |
535 return -1; | |
536 if (ft_face->glyph->format != FT_GLYPH_FORMAT_OUTLINE) | |
537 return -1; | |
538 if (index >= ft_face->glyph->outline.n_points) | |
539 return -1; | |
540 *x = ft_face->glyph->outline.points[index].x; | |
541 *y = ft_face->glyph->outline.points[index].y; | |
542 return 0; | |
543 } | |
544 | |
545 | |
546 void | |
547 syms_of_xftfont () | |
548 { | |
549 DEFSYM (Qxft, "xft"); | |
550 | |
551 xftfont_driver = ftfont_driver; | |
552 xftfont_driver.type = Qxft; | |
553 xftfont_driver.get_cache = xfont_driver.get_cache; | |
554 xftfont_driver.list = xftfont_list; | |
90559
fb5d3ac2d786
(xftfont_match): New function.
Kenichi Handa <handa@m17n.org>
parents:
90527
diff
changeset
|
555 xftfont_driver.match = xftfont_match; |
90400 | 556 xftfont_driver.open = xftfont_open; |
557 xftfont_driver.close = xftfont_close; | |
558 xftfont_driver.prepare_face = xftfont_prepare_face; | |
559 xftfont_driver.done_face = xftfont_done_face; | |
560 xftfont_driver.encode_char = xftfont_encode_char; | |
561 xftfont_driver.text_extents = xftfont_text_extents; | |
562 xftfont_driver.draw = xftfont_draw; | |
563 xftfont_driver.anchor_point = xftfont_anchor_point; | |
564 | |
565 register_font_driver (&xftfont_driver, NULL); | |
566 } | |
90427 | 567 |
568 /* arch-tag: 64ec61bf-7c8e-4fe6-b953-c6a85d5e1605 | |
569 (do not change this comment) */ |