aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/xftfont.c199
1 files changed, 80 insertions, 119 deletions
diff --git a/src/xftfont.c b/src/xftfont.c
index 55d0b943c13..da72df45393 100644
--- a/src/xftfont.c
+++ b/src/xftfont.c
@@ -137,7 +137,7 @@ xftfont_get_colors (f, face, gc, xftface_info, fg, bg)
137 137
138static Lisp_Object xftfont_list P_ ((Lisp_Object, Lisp_Object)); 138static Lisp_Object xftfont_list P_ ((Lisp_Object, Lisp_Object));
139static Lisp_Object xftfont_match P_ ((Lisp_Object, Lisp_Object)); 139static Lisp_Object xftfont_match P_ ((Lisp_Object, Lisp_Object));
140static struct font *xftfont_open P_ ((FRAME_PTR, Lisp_Object, int)); 140static Lisp_Object xftfont_open P_ ((FRAME_PTR, Lisp_Object, int));
141static void xftfont_close P_ ((FRAME_PTR, struct font *)); 141static void xftfont_close P_ ((FRAME_PTR, struct font *));
142static int xftfont_prepare_face P_ ((FRAME_PTR, struct face *)); 142static int xftfont_prepare_face P_ ((FRAME_PTR, struct face *));
143static void xftfont_done_face P_ ((FRAME_PTR, struct face *)); 143static void xftfont_done_face P_ ((FRAME_PTR, struct face *));
@@ -157,13 +157,12 @@ xftfont_list (frame, spec)
157 Lisp_Object frame; 157 Lisp_Object frame;
158 Lisp_Object spec; 158 Lisp_Object spec;
159{ 159{
160 Lisp_Object val = ftfont_driver.list (frame, spec); 160 Lisp_Object list = ftfont_driver.list (frame, spec), tail;
161 int i; 161 int i;
162 162
163 if (! NILP (val)) 163 for (tail = list; CONSP (tail); tail = XCDR (tail))
164 for (i = 0; i < ASIZE (val); i++) 164 ASET (XCAR (tail), FONT_TYPE_INDEX, Qxft);
165 ASET (AREF (val, i), FONT_TYPE_INDEX, Qxft); 165 return list;
166 return val;
167} 166}
168 167
169static Lisp_Object 168static Lisp_Object
@@ -173,7 +172,7 @@ xftfont_match (frame, spec)
173{ 172{
174 Lisp_Object entity = ftfont_driver.match (frame, spec); 173 Lisp_Object entity = ftfont_driver.match (frame, spec);
175 174
176 if (VECTORP (entity)) 175 if (! NILP (entity))
177 ASET (entity, FONT_TYPE_INDEX, Qxft); 176 ASET (entity, FONT_TYPE_INDEX, Qxft);
178 return entity; 177 return entity;
179} 178}
@@ -182,7 +181,7 @@ extern Lisp_Object ftfont_font_format P_ ((FcPattern *));
182 181
183static FcChar8 ascii_printable[95]; 182static FcChar8 ascii_printable[95];
184 183
185static struct font * 184static Lisp_Object
186xftfont_open (f, entity, pixel_size) 185xftfont_open (f, entity, pixel_size)
187 FRAME_PTR f; 186 FRAME_PTR f;
188 Lisp_Object entity; 187 Lisp_Object entity;
@@ -190,7 +189,7 @@ xftfont_open (f, entity, pixel_size)
190{ 189{
191 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f); 190 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
192 Display *display = FRAME_X_DISPLAY (f); 191 Display *display = FRAME_X_DISPLAY (f);
193 Lisp_Object val; 192 Lisp_Object val, font_object;
194 FcPattern *pattern, *pat = NULL; 193 FcPattern *pattern, *pat = NULL;
195 FcChar8 *file; 194 FcChar8 *file;
196 struct xftfont_info *xftfont_info = NULL; 195 struct xftfont_info *xftfont_info = NULL;
@@ -199,18 +198,19 @@ xftfont_open (f, entity, pixel_size)
199 double size = 0; 198 double size = 0;
200 XftFont *xftfont = NULL; 199 XftFont *xftfont = NULL;
201 int spacing; 200 int spacing;
202 char *name; 201 char name[256];
203 int len; 202 int len, i;
204 XGlyphInfo extents; 203 XGlyphInfo extents;
205 FT_Face ft_face; 204 FT_Face ft_face;
206 205
207 val = AREF (entity, FONT_EXTRA_INDEX); 206 val = assq_no_quit (QCfont_entity, AREF (entity, FONT_EXTRA_INDEX));
208 if (XTYPE (val) != Lisp_Misc 207 if (! CONSP (val)
209 || XMISCTYPE (val) != Lisp_Misc_Save_Value) 208 || XTYPE (XCDR (val)) != Lisp_Misc
210 return NULL; 209 || XMISCTYPE (XCDR (val)) != Lisp_Misc_Save_Value)
211 pattern = XSAVE_VALUE (val)->pointer; 210 return Qnil;
211 pattern = XSAVE_VALUE (XCDR (val))->pointer;
212 if (FcPatternGetString (pattern, FC_FILE, 0, &file) != FcResultMatch) 212 if (FcPatternGetString (pattern, FC_FILE, 0, &file) != FcResultMatch)
213 return NULL; 213 return Qnil;
214 214
215 size = XINT (AREF (entity, FONT_SIZE_INDEX)); 215 size = XINT (AREF (entity, FONT_SIZE_INDEX));
216 if (size == 0) 216 if (size == 0)
@@ -228,49 +228,39 @@ xftfont_open (f, entity, pixel_size)
228 BLOCK_INPUT; 228 BLOCK_INPUT;
229 XftDefaultSubstitute (display, FRAME_X_SCREEN_NUMBER (f), pat); 229 XftDefaultSubstitute (display, FRAME_X_SCREEN_NUMBER (f), pat);
230 xftfont = XftFontOpenPattern (display, pat); 230 xftfont = XftFontOpenPattern (display, pat);
231 UNBLOCK_INPUT;
232 if (! xftfont)
233 return Qnil;
231 /* We should not destroy PAT here because it is kept in XFTFONT and 234 /* We should not destroy PAT here because it is kept in XFTFONT and
232 destroyed automatically when XFTFONT is closed. */ 235 destroyed automatically when XFTFONT is closed. */
233 if (! xftfont) 236 font_object = font_make_object (VECSIZE (struct xftfont_info));
234 goto err; 237 ASET (font_object, FONT_TYPE_INDEX, Qxft);
235 238 for (i = 1; i < FONT_ENTITY_MAX; i++)
236 xftfont_info = malloc (sizeof (struct xftfont_info)); 239 ASET (font_object, i, AREF (entity, i));
237 if (! xftfont_info) 240 ASET (font_object, FONT_SIZE_INDEX, make_number (size));
238 goto err; 241 len = font_unparse_xlfd (entity, size, name, 256);
239 xfont = malloc (sizeof (XFontStruct)); 242 if (len > 0)
240 if (! xfont) 243 ASET (font_object, FONT_NAME_INDEX, make_unibyte_string (name, len));
241 goto err; 244 len = font_unparse_fcname (entity, size, name, 256);
245 if (len > 0)
246 ASET (font_object, FONT_FULLNAME_INDEX, make_unibyte_string (name, len));
247 else
248 ASET (font_object, FONT_FULLNAME_INDEX,
249 AREF (font_object, FONT_NAME_INDEX));
250 ASET (font_object, FONT_FILE_INDEX,
251 make_unibyte_string ((char *) file, strlen ((char *) file)));
252 ASET (font_object, FONT_FORMAT_INDEX, ftfont_font_format (pattern));
253 font = XFONT_OBJECT (font_object);
254 font->pixel_size = pixel_size;
255 font->driver = &xftfont_driver;
256 font->encoding_charset = font->repertory_charset = -1;
257
258 xftfont_info = (struct xftfont_info *) font;
242 xftfont_info->display = display; 259 xftfont_info->display = display;
243 xftfont_info->screen = FRAME_X_SCREEN_NUMBER (f); 260 xftfont_info->screen = FRAME_X_SCREEN_NUMBER (f);
244 xftfont_info->xftfont = xftfont; 261 xftfont_info->xftfont = xftfont;
245#ifdef HAVE_LIBOTF
246 ft_face = XftLockFace (xftfont);
247 xftfont_info->maybe_otf = ft_face->face_flags & FT_FACE_FLAG_SFNT;
248 XftUnlockFace (xftfont);
249 xftfont_info->otf = NULL;
250#endif /* HAVE_LIBOTF */
251
252 font = (struct font *) xftfont_info;
253 font->format = ftfont_font_format (xftfont->pattern);
254 font->entity = entity;
255 font->pixel_size = size; 262 font->pixel_size = size;
256 font->driver = &xftfont_driver; 263 font->driver = &xftfont_driver;
257 len = 96;
258 name = malloc (len);
259 while (name && font_unparse_fcname (entity, pixel_size, name, len) < 0)
260 {
261 char *new = realloc (name, len += 32);
262
263 if (! new)
264 free (name);
265 name = new;
266 }
267 if (! name)
268 goto err;
269 font->font.full_name = font->font.name = name;
270 font->file_name = (char *) file;
271 font->font.size = xftfont->max_advance_width;
272 font->font.charset = font->encoding_charset = font->repertory_charset = -1;
273
274 if (FcPatternGetInteger (xftfont->pattern, FC_SPACING, 0, &spacing) 264 if (FcPatternGetInteger (xftfont->pattern, FC_SPACING, 0, &spacing)
275 != FcResultMatch) 265 != FcResultMatch)
276 spacing = FC_PROPORTIONAL; 266 spacing = FC_PROPORTIONAL;
@@ -280,21 +270,22 @@ xftfont_open (f, entity, pixel_size)
280 for (i = 0; i < 95; i++) 270 for (i = 0; i < 95; i++)
281 ascii_printable[i] = ' ' + i; 271 ascii_printable[i] = ' ' + i;
282 } 272 }
273 BLOCK_INPUT;
283 if (spacing != FC_PROPORTIONAL) 274 if (spacing != FC_PROPORTIONAL)
284 { 275 {
285 font->font.average_width = font->font.space_width 276 font->min_width = font->average_width = font->space_width
286 = xftfont->max_advance_width; 277 = xftfont->max_advance_width;
287 XftTextExtents8 (display, xftfont, ascii_printable + 1, 94, &extents); 278 XftTextExtents8 (display, xftfont, ascii_printable + 1, 94, &extents);
288 } 279 }
289 else 280 else
290 { 281 {
291 XftTextExtents8 (display, xftfont, ascii_printable, 1, &extents); 282 XftTextExtents8 (display, xftfont, ascii_printable, 1, &extents);
292 font->font.space_width = extents.xOff; 283 font->space_width = extents.xOff;
293 if (font->font.space_width <= 0) 284 if (font->space_width <= 0)
294 /* dirty workaround */ 285 /* dirty workaround */
295 font->font.space_width = pixel_size; 286 font->space_width = pixel_size;
296 XftTextExtents8 (display, xftfont, ascii_printable + 1, 94, &extents); 287 XftTextExtents8 (display, xftfont, ascii_printable + 1, 94, &extents);
297 font->font.average_width = (font->font.space_width + extents.xOff) / 95; 288 font->average_width = (font->space_width + extents.xOff) / 95;
298 } 289 }
299 UNBLOCK_INPUT; 290 UNBLOCK_INPUT;
300 291
@@ -304,57 +295,37 @@ xftfont_open (f, entity, pixel_size)
304 font->descent = xftfont->descent; 295 font->descent = xftfont->descent;
305 if (font->descent < extents.height - extents.y) 296 if (font->descent < extents.height - extents.y)
306 font->descent = extents.height - extents.y; 297 font->descent = extents.height - extents.y;
307 font->font.height = font->ascent + font->descent; 298 font->height = font->ascent + font->descent;
308 299
309 /* Unfortunately Xft doesn't provide a way to get minimum char 300 ft_face = XftLockFace (xftfont);
310 width. So, we use space_width instead. */ 301 if (XINT (AREF (entity, FONT_SIZE_INDEX)) == 0)
311 font->min_width = font->font.space_width;
312
313 font->font.baseline_offset = 0;
314 font->font.relative_compose = 0;
315 font->font.default_ascent = 0;
316 font->font.vertical_centering = 0;
317
318 /* Setup pseudo XFontStruct */
319 xfont->fid = 0;
320 xfont->ascent = font->ascent;
321 xfont->descent = font->descent;
322 xfont->max_bounds.descent = font->descent;
323 xfont->max_bounds.width = xftfont->max_advance_width;
324 xfont->min_bounds.width = font->font.space_width;
325 font->font.font = xfont;
326
327 dpyinfo->n_fonts++;
328
329 /* Set global flag fonts_changed_p to non-zero if the font loaded
330 has a character with a smaller width than any other character
331 before, or if the font loaded has a smaller height than any other
332 font loaded before. If this happens, it will make a glyph matrix
333 reallocation necessary. */
334 if (dpyinfo->n_fonts == 1)
335 { 302 {
336 dpyinfo->smallest_font_height = font->font.height; 303 int upEM = ft_face->units_per_EM;
337 dpyinfo->smallest_char_width = font->min_width; 304
338 fonts_changed_p = 1; 305 font->underline_position = -ft_face->underline_position * size / upEM;
306 font->underline_thickness = -ft_face->underline_thickness * size / upEM;
339 } 307 }
340 else 308 else
341 { 309 {
342 if (dpyinfo->smallest_font_height > font->font.height) 310 font->underline_position = -1;
343 dpyinfo->smallest_font_height = font->font.height, 311 font->underline_thickness = 0;
344 fonts_changed_p |= 1;
345 if (dpyinfo->smallest_char_width > font->min_width)
346 dpyinfo->smallest_char_width = font->min_width,
347 fonts_changed_p |= 1;
348 } 312 }
313#ifdef HAVE_LIBOTF
314 xftfont_info->maybe_otf = ft_face->face_flags & FT_FACE_FLAG_SFNT;
315 xftfont_info->otf = NULL;
316#endif /* HAVE_LIBOTF */
317 XftUnlockFace (xftfont);
349 318
350 return font; 319 /* Unfortunately Xft doesn't provide a way to get minimum char
320 width. So, we use space_width instead. */
321 font->min_width = font->space_width;
351 322
352 err: 323 font->baseline_offset = 0;
353 if (xftfont) XftFontClose (display, xftfont); 324 font->relative_compose = 0;
354 UNBLOCK_INPUT; 325 font->default_ascent = 0;
355 if (xftfont_info) free (xftfont_info); 326 font->vertical_centering = 0;
356 if (xfont) free (xfont); 327
357 return NULL; 328 return font_object;
358} 329}
359 330
360static void 331static void
@@ -368,11 +339,9 @@ xftfont_close (f, font)
368 if (xftfont_info->otf) 339 if (xftfont_info->otf)
369 OTF_close (xftfont_info->otf); 340 OTF_close (xftfont_info->otf);
370#endif 341#endif
342 BLOCK_INPUT;
371 XftFontClose (xftfont_info->display, xftfont_info->xftfont); 343 XftFontClose (xftfont_info->display, xftfont_info->xftfont);
372 if (font->font.name) 344 UNBLOCK_INPUT;
373 free (font->font.name);
374 free (font);
375 FRAME_X_DISPLAY_INFO (f)->n_fonts--;
376} 345}
377 346
378static int 347static int
@@ -394,12 +363,8 @@ xftfont_prepare_face (f, face)
394 xftface_info = malloc (sizeof (struct xftface_info)); 363 xftface_info = malloc (sizeof (struct xftface_info));
395 if (! xftface_info) 364 if (! xftface_info)
396 return -1; 365 return -1;
397
398 BLOCK_INPUT;
399 xftfont_get_colors (f, face, face->gc, NULL, 366 xftfont_get_colors (f, face, face->gc, NULL,
400 &xftface_info->xft_fg, &xftface_info->xft_bg); 367 &xftface_info->xft_fg, &xftface_info->xft_bg);
401 UNBLOCK_INPUT;
402
403 face->extra = xftface_info; 368 face->extra = xftface_info;
404 return 0; 369 return 0;
405} 370}
@@ -491,7 +456,7 @@ xftfont_draw (s, from, to, x, y, with_background)
491{ 456{
492 FRAME_PTR f = s->f; 457 FRAME_PTR f = s->f;
493 struct face *face = s->face; 458 struct face *face = s->face;
494 struct xftfont_info *xftfont_info = (struct xftfont_info *) s->font_info; 459 struct xftfont_info *xftfont_info = (struct xftfont_info *) s->font;
495 struct xftface_info *xftface_info = NULL; 460 struct xftface_info *xftface_info = NULL;
496 XftDraw *xft_draw = xftfont_get_xft_draw (f); 461 XftDraw *xft_draw = xftfont_get_xft_draw (f);
497 FT_UInt *code; 462 FT_UInt *code;
@@ -500,7 +465,7 @@ xftfont_draw (s, from, to, x, y, with_background)
500 int len = to - from; 465 int len = to - from;
501 int i; 466 int i;
502 467
503 if (s->font_info == face->font_info) 468 if (s->font == face->font)
504 xftface_info = (struct xftface_info *) face->extra; 469 xftface_info = (struct xftface_info *) face->extra;
505 xftfont_get_colors (f, face, s->gc, xftface_info, 470 xftfont_get_colors (f, face, s->gc, xftface_info,
506 &fg, with_background ? &bg : NULL); 471 &fg, with_background ? &bg : NULL);
@@ -511,12 +476,8 @@ xftfont_draw (s, from, to, x, y, with_background)
511 XftDrawSetClip (xft_draw, NULL); 476 XftDrawSetClip (xft_draw, NULL);
512 477
513 if (with_background) 478 if (with_background)
514 { 479 XftDrawRect (xft_draw, &bg,
515 struct font *font = (struct font *) face->font_info; 480 x, y - face->font->ascent, s->width, face->font->height);
516
517 XftDrawRect (xft_draw, &bg,
518 x, y - face->font->ascent, s->width, font->font.height);
519 }
520 code = alloca (sizeof (FT_UInt) * len); 481 code = alloca (sizeof (FT_UInt) * len);
521 for (i = 0; i < len; i++) 482 for (i = 0; i < len; i++)
522 code[i] = ((XCHAR2B_BYTE1 (s->char2b + from + i) << 8) 483 code[i] = ((XCHAR2B_BYTE1 (s->char2b + from + i) << 8)
@@ -584,7 +545,7 @@ xftfont_shape (lgstring)
584{ 545{
585 struct font *font; 546 struct font *font;
586 struct xftfont_info *xftfont_info; 547 struct xftfont_info *xftfont_info;
587 int result; 548 Lisp_Object result;
588 FT_Face ft_face; 549 FT_Face ft_face;
589 550
590 CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring), font); 551 CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring), font);
@@ -602,7 +563,7 @@ xftfont_shape (lgstring)
602 OTF_close (otf); 563 OTF_close (otf);
603 xftfont_info->maybe_otf = 0; 564 xftfont_info->maybe_otf = 0;
604 XftUnlockFace (xftfont_info->xftfont); 565 XftUnlockFace (xftfont_info->xftfont);
605 return 0; 566 return Qnil;
606 } 567 }
607 xftfont_info->otf = otf; 568 xftfont_info->otf = otf;
608 } 569 }