1 /* xfont.c -- X core font driver.
2 Copyright (C) 2006 Free Software Foundation, Inc.
4 National Institute of Advanced Industrial Science and Technology (AIST)
5 Registration Number H13PRO009
7 This file is part of GNU Emacs.
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)
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.
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. */
29 #include "dispextern.h"
32 #include "blockinput.h"
33 #include "character.h"
39 /* X core font driver. */
43 /* Alist of font registry symbol and the corresponding charsets
44 information. The information is retrieved from
45 Vfont_encoding_alist on demand.
47 Eash element has the form:
48 (REGISTRY . (ENCODING-CHARSET-ID . REPERTORY-CHARSET-ID))
52 In the former form, ENCODING-CHARSET-ID is an ID of a charset that
53 encodes a character code to a glyph code of a font, and
54 REPERTORY-CHARSET-ID is an ID of a charset that tells if a
55 character is supported by a font.
57 The latter form means that the information for REGISTRY couldn't be
59 static Lisp_Object x_font_charset_alist
;
61 /* Prototypes of support functions. */
62 extern void x_clear_errors
P_ ((Display
*));
64 static char *xfont_query_font
P_ ((Display
*, char *, Lisp_Object
));
65 static XCharStruct
*xfont_get_pcm
P_ ((XFontStruct
*, XChar2b
*));
66 static int xfont_registry_charsets
P_ ((Lisp_Object
, struct charset
**,
70 xfont_query_font (display
, name
, spec
)
78 x_catch_errors (display
);
79 font
= XLoadQueryFont (display
, name
);
81 if (x_had_errors_p (display
))
83 /* This error is perhaps due to insufficient memory on X
84 server. Let's just ignore it. */
85 x_clear_errors (display
);
91 if (XGetFontProperty (font
, XA_FONT
, &value
))
93 char *n
= (char *) XGetAtomName (display
, (Atom
) value
);
95 if (font_parse_xlfd (n
, spec
, 0) >= 0)
100 XFreeFont (display
, font
);
109 /* Get metrics of character CHAR2B in XFONT. Value is null if CHAR2B
110 is not contained in the font. */
113 xfont_get_pcm (xfont
, char2b
)
117 /* The result metric information. */
118 XCharStruct
*pcm
= NULL
;
120 xassert (xfont
&& char2b
);
122 if (xfont
->per_char
!= NULL
)
124 if (xfont
->min_byte1
== 0 && xfont
->max_byte1
== 0)
126 /* min_char_or_byte2 specifies the linear character index
127 corresponding to the first element of the per_char array,
128 max_char_or_byte2 is the index of the last character. A
129 character with non-zero CHAR2B->byte1 is not in the font.
130 A character with byte2 less than min_char_or_byte2 or
131 greater max_char_or_byte2 is not in the font. */
132 if (char2b
->byte1
== 0
133 && char2b
->byte2
>= xfont
->min_char_or_byte2
134 && char2b
->byte2
<= xfont
->max_char_or_byte2
)
135 pcm
= xfont
->per_char
+ char2b
->byte2
- xfont
->min_char_or_byte2
;
139 /* If either min_byte1 or max_byte1 are nonzero, both
140 min_char_or_byte2 and max_char_or_byte2 are less than
141 256, and the 2-byte character index values corresponding
142 to the per_char array element N (counting from 0) are:
144 byte1 = N/D + min_byte1
145 byte2 = N\D + min_char_or_byte2
149 D = max_char_or_byte2 - min_char_or_byte2 + 1
151 \ = integer modulus */
152 if (char2b
->byte1
>= xfont
->min_byte1
153 && char2b
->byte1
<= xfont
->max_byte1
154 && char2b
->byte2
>= xfont
->min_char_or_byte2
155 && char2b
->byte2
<= xfont
->max_char_or_byte2
)
156 pcm
= (xfont
->per_char
157 + ((xfont
->max_char_or_byte2
- xfont
->min_char_or_byte2
+ 1)
158 * (char2b
->byte1
- xfont
->min_byte1
))
159 + (char2b
->byte2
- xfont
->min_char_or_byte2
));
164 /* If the per_char pointer is null, all glyphs between the first
165 and last character indexes inclusive have the same
166 information, as given by both min_bounds and max_bounds. */
167 if (char2b
->byte2
>= xfont
->min_char_or_byte2
168 && char2b
->byte2
<= xfont
->max_char_or_byte2
)
169 pcm
= &xfont
->max_bounds
;
173 || (pcm
->width
== 0 && (pcm
->rbearing
- pcm
->lbearing
) == 0))
177 extern Lisp_Object find_font_encoding
P_ ((Lisp_Object
));
179 /* Return encoding charset and repertory charset for REGISTRY in
180 ENCODING and REPERTORY correspondingly. If correct information for
181 REGISTRY is available, return 0. Otherwise return -1. */
184 xfont_registry_charsets (registry
, encoding
, repertory
)
185 Lisp_Object registry
;
186 struct charset
**encoding
, **repertory
;
189 int encoding_id
, repertory_id
;
191 val
= assq_no_quit (registry
, x_font_charset_alist
);
197 encoding_id
= XINT (XCAR (val
));
198 repertory_id
= XINT (XCDR (val
));
202 val
= find_font_encoding (SYMBOL_NAME (registry
));
203 if (SYMBOLP (val
) && CHARSETP (val
))
205 encoding_id
= repertory_id
= XINT (CHARSET_SYMBOL_ID (val
));
207 else if (CONSP (val
))
209 if (! CHARSETP (XCAR (val
)))
211 encoding_id
= XINT (CHARSET_SYMBOL_ID (XCAR (val
)));
212 if (NILP (XCDR (val
)))
216 if (! CHARSETP (XCDR (val
)))
218 repertory_id
= XINT (CHARSET_SYMBOL_ID (XCDR (val
)));
223 val
= Fcons (make_number (encoding_id
), make_number (repertory_id
));
225 = nconc2 (x_font_charset_alist
, Fcons (Fcons (registry
, val
), Qnil
));
229 *encoding
= CHARSET_FROM_ID (encoding_id
);
231 *repertory
= repertory_id
>= 0 ? CHARSET_FROM_ID (repertory_id
) : NULL
;
236 = nconc2 (x_font_charset_alist
, Fcons (Fcons (registry
, Qnil
), Qnil
));
240 static Lisp_Object xfont_get_cache
P_ ((Lisp_Object
));
241 static int xfont_parse_name
P_ ((FRAME_PTR
, char *, Lisp_Object
));
242 static Lisp_Object xfont_list
P_ ((Lisp_Object
, Lisp_Object
));
243 static Lisp_Object xfont_list_family
P_ ((Lisp_Object
));
244 static struct font
*xfont_open
P_ ((FRAME_PTR
, Lisp_Object
, int));
245 static void xfont_close
P_ ((FRAME_PTR
, struct font
*));
246 static int xfont_prepare_face
P_ ((FRAME_PTR
, struct face
*));
248 static void xfont_done_face
P_ ((FRAME_PTR
, struct face
*));
250 static int xfont_has_char
P_ ((Lisp_Object
, int));
251 static unsigned xfont_encode_char
P_ ((struct font
*, int));
252 static int xfont_text_extents
P_ ((struct font
*, unsigned *, int,
253 struct font_metrics
*));
254 static int xfont_draw
P_ ((struct glyph_string
*, int, int, int, int, int));
256 struct font_driver xfont_driver
=
258 (Lisp_Object
) NULL
, /* Qx */
267 NULL
/*xfont_done_face*/,
274 extern Lisp_Object QCname
;
277 xfont_get_cache (frame
)
280 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (XFRAME (frame
));
282 return (dpyinfo
->name_list_element
);
286 xfont_parse_name (f
, name
, spec
)
291 if (font_parse_xlfd (name
, spec
, 0) >= 0)
293 name
= xfont_query_font (FRAME_X_DISPLAY (f
), name
, spec
);
302 extern Lisp_Object Vface_alternative_font_registry_alist
;
305 xfont_list (frame
, spec
)
306 Lisp_Object frame
, spec
;
308 FRAME_PTR f
= XFRAME (frame
);
309 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
310 Lisp_Object
*vec
, val
, extra
, font_name
, entity
;
311 char name
[256], **names
;
312 int i
, idx
, limit
, num_fonts
;
313 int error_occurred
= 0;
316 extra
= AREF (spec
, FONT_EXTRA_INDEX
);
320 val
= Fassq (QCotf
, extra
);
323 val
= Fassq (QCscript
, extra
);
326 val
= Fassq (QCname
, extra
);
328 font_name
= XCDR (val
);
331 if (! STRINGP (font_name
)
332 && font_unparse_xlfd (spec
, 0, name
, 256) < 0)
336 x_catch_errors (dpyinfo
->display
);
338 if (STRINGP (font_name
))
340 XFontStruct
*font
= XLoadQueryFont (dpyinfo
->display
,
341 (char *) SDATA (font_name
));
345 if (x_had_errors_p (dpyinfo
->display
))
347 /* This error is perhaps due to insufficient memory on X
348 server. Let's just ignore it. */
351 x_clear_errors (dpyinfo
->display
);
355 if (XGetFontProperty (font
, XA_FONT
, &value
))
357 char *n
= (char *) XGetAtomName (dpyinfo
->display
, (Atom
) value
);
358 int len
= strlen (n
);
361 /* If DXPC (a Differential X Protocol Compressor)
362 Ver.3.7 is running, XGetAtomName will return null
363 string. We must avoid such a name. */
367 names
= (char **) alloca (sizeof (char *));
368 /* Some systems only allow alloca assigned to a
370 tmp
= (char *) alloca (len
+ 1); names
[0] = tmp
;
371 bcopy (n
, names
[0], len
+ 1);
375 XFreeFont (dpyinfo
->display
, font
);
380 Lisp_Object registry
= AREF (spec
, FONT_REGISTRY_INDEX
);
381 Lisp_Object alter
= Qnil
;
384 if (! NILP (registry
))
385 alter
= Fassoc_string (SYMBOL_NAME (registry
),
386 Vface_alternative_font_registry_alist
);
389 for (limit
= 512, num_fonts
= 0; ; limit
*= 2)
391 names
= XListFonts (dpyinfo
->display
, name
, limit
, &num_fonts
);
392 if (x_had_errors_p (dpyinfo
->display
))
394 /* This error is perhaps due to insufficient memory
395 on X server. Let's just ignore it. */
396 x_clear_errors (dpyinfo
->display
);
401 if (num_fonts
< limit
)
403 XFreeFontNames (names
);
409 /* Setup for trying alternatives. */
411 && ! (r
= strstr (name
, (char *) SDATA (SYMBOL_NAME (registry
)))))
416 alter
= XCDR (alter
);
419 registry
= XCAR (alter
);
420 if ((r
- name
) + SBYTES (registry
) < 255)
425 bcopy (SDATA (registry
), r
, SBYTES (registry
));
437 entity
= Fmake_vector (make_number (FONT_ENTITY_MAX
), Qnil
);
438 ASET (entity
, FONT_TYPE_INDEX
, Qx
);
439 ASET (entity
, FONT_FRAME_INDEX
, frame
);
441 SAFE_ALLOCA_LISP (vec
, num_fonts
);
442 for (i
= idx
= 0; i
< num_fonts
; i
++)
444 if (font_parse_xlfd (names
[i
], entity
, 0) > 0)
445 vec
[idx
++] = Fcopy_sequence (entity
);
447 if (! STRINGP (font_name
))
450 XFreeFontNames (names
);
453 val
= Fvector (idx
, vec
);
460 memq_no_quit (elt
, list
)
461 Lisp_Object elt
, list
;
463 while (CONSP (list
) && ! EQ (XCAR (list
), elt
))
465 return (CONSP (list
));
469 xfont_list_family (frame
)
472 FRAME_PTR f
= XFRAME (frame
);
473 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
481 x_catch_errors (dpyinfo
->display
);
482 names
= XListFonts (dpyinfo
->display
, "-*-*-*-*-*-*-*-*-*-*-*-*-*-*",
484 if (x_had_errors_p (dpyinfo
->display
))
486 /* This error is perhaps due to insufficient memory on X server.
487 Let's just ignore it. */
488 x_clear_errors (dpyinfo
->display
);
493 for (i
= 0, last_len
= 0; i
< num_fonts
; i
++)
495 char *p0
= names
[i
], *p1
;
498 p0
++; /* skip the leading '-' */
499 while (*p0
&& *p0
!= '-') p0
++; /* skip foundry */
503 while (*p1
&& *p1
!= '-') p1
++; /* find the end of family */
504 if (! *p1
|| p1
== p0
)
506 if (last_len
== p1
- p0
507 && bcmp (last_family
, p0
, last_len
) == 0)
511 family
= intern_downcase (p0
, last_len
);
512 if (! memq_no_quit (family
, list
))
513 list
= Fcons (family
, list
);
516 XFreeFontNames (names
);
524 xfont_open (f
, entity
, pixel_size
)
529 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
530 Display
*display
= dpyinfo
->display
;
534 Lisp_Object registry
;
535 struct charset
*encoding
, *repertory
;
539 /* At first, check if we know how to encode characters for this
541 registry
= AREF (entity
, FONT_REGISTRY_INDEX
);
542 if (xfont_registry_charsets (registry
, &encoding
, &repertory
) < 0)
545 if (XINT (AREF (entity
, FONT_SIZE_INDEX
)) != 0)
546 pixel_size
= XINT (AREF (entity
, FONT_SIZE_INDEX
));
547 len
= font_unparse_xlfd (entity
, pixel_size
, name
, 256);
552 x_catch_errors (display
);
553 xfont
= XLoadQueryFont (display
, name
);
554 if (x_had_errors_p (display
))
556 /* This error is perhaps due to insufficient memory on X server.
557 Let's just ignore it. */
558 x_clear_errors (display
);
566 font
= malloc (sizeof (struct font
));
567 font
->font
.font
= xfont
;
568 font
->entity
= entity
;
569 font
->pixel_size
= pixel_size
;
570 font
->driver
= &xfont_driver
;
571 font
->font
.name
= malloc (len
+ 1);
572 if (! font
->font
.name
)
574 XFreeFont (display
, xfont
);
578 bcopy (name
, font
->font
.name
, len
+ 1);
579 font
->font
.charset
= encoding
->id
;
580 font
->encoding_charset
= encoding
->id
;
581 font
->repertory_charet
= repertory
? repertory
->id
: -1;
582 font
->ascent
= xfont
->ascent
;
583 font
->descent
= xfont
->descent
;
585 if (xfont
->min_bounds
.width
== xfont
->max_bounds
.width
)
587 /* Fixed width font. */
588 font
->font
.average_width
= font
->font
.space_width
589 = xfont
->min_bounds
.width
;
596 char2b
.byte1
= 0x00, char2b
.byte2
= 0x20;
597 pcm
= xfont_get_pcm (xfont
, &char2b
);
599 font
->font
.space_width
= pcm
->width
;
601 font
->font
.space_width
= xfont
->max_bounds
.width
;
603 font
->font
.average_width
604 = (XGetFontProperty (xfont
, dpyinfo
->Xatom_AVERAGE_WIDTH
, &value
)
605 ? (long) value
/ 10 : 0);
606 if (font
->font
.average_width
< 0)
607 font
->font
.average_width
= - font
->font
.average_width
;
608 if (font
->font
.average_width
== 0)
612 int width
= pcm
->width
;
613 for (char2b
.byte2
= 33; char2b
.byte2
<= 126; char2b
.byte2
++)
614 if ((pcm
= xfont_get_pcm (xfont
, &char2b
)) != NULL
)
616 font
->font
.average_width
= width
/ 95;
619 font
->font
.average_width
= xfont
->max_bounds
.width
;
622 font
->min_width
= xfont
->min_bounds
.width
;
623 if (font
->min_width
<= 0)
624 font
->min_width
= font
->font
.space_width
;
627 /* Try to get the full name of FONT. Put it in FULL_NAME. */
628 if (XGetFontProperty (xfont
, XA_FONT
, &value
))
630 char *full_name
= NULL
, *p0
, *p
;
633 p0
= p
= (char *) XGetAtomName (FRAME_X_DISPLAY (f
), (Atom
) value
);;
634 /* Count the number of dashes in the "full name".
635 If it is too few, this isn't really the font's full name,
637 In X11R4, the fonts did not come with their canonical names
648 full_name
= (char *) malloc (p
- p0
+ 1);
650 bcopy (p0
, full_name
, p
- p0
+ 1);
655 font
->font
.full_name
= full_name
;
657 font
->font
.full_name
= font
->font
.name
;
659 font
->file_name
= NULL
;
661 font
->font
.size
= xfont
->max_bounds
.width
;
662 font
->font
.height
= xfont
->ascent
+ xfont
->descent
;
663 font
->font
.baseline_offset
664 = (XGetFontProperty (xfont
, dpyinfo
->Xatom_MULE_BASELINE_OFFSET
, &value
)
666 font
->font
.relative_compose
667 = (XGetFontProperty (xfont
, dpyinfo
->Xatom_MULE_RELATIVE_COMPOSE
, &value
)
669 font
->font
.default_ascent
670 = (XGetFontProperty (xfont
, dpyinfo
->Xatom_MULE_DEFAULT_ASCENT
, &value
)
672 font
->font
.vertical_centering
673 = (STRINGP (Vvertical_centering_font_regexp
)
674 && (fast_c_string_match_ignore_case
675 (Vvertical_centering_font_regexp
, font
->font
.full_name
) >= 0));
681 /* Set global flag fonts_changed_p to non-zero if the font loaded
682 has a character with a smaller width than any other character
683 before, or if the font loaded has a smaller height than any other
684 font loaded before. If this happens, it will make a glyph matrix
685 reallocation necessary. */
686 if (dpyinfo
->n_fonts
== 1)
688 dpyinfo
->smallest_font_height
= font
->font
.height
;
689 dpyinfo
->smallest_char_width
= font
->min_width
;
694 if (dpyinfo
->smallest_font_height
> font
->font
.height
)
695 dpyinfo
->smallest_font_height
= font
->font
.height
, fonts_changed_p
|= 1;
696 if (dpyinfo
->smallest_char_width
> font
->min_width
)
697 dpyinfo
->smallest_char_width
= font
->min_width
, fonts_changed_p
|= 1;
704 xfont_close (f
, font
)
709 XFreeFont (FRAME_X_DISPLAY (f
), font
->font
.font
);
712 if (font
->font
.name
!= font
->font
.full_name
)
713 free (font
->font
.full_name
);
714 free (font
->font
.name
);
716 FRAME_X_DISPLAY_INFO (f
)->n_fonts
--;
720 xfont_prepare_face (f
, face
)
725 XSetFont (FRAME_X_DISPLAY (f
), face
->gc
, face
->font
->fid
);
733 xfont_done_face (f
, face
)
740 XFreeGC (FRAME_X_DISPLAY (f
), (GC
) face
->extra
);
748 xfont_has_char (entity
, c
)
752 Lisp_Object registry
= AREF (entity
, FONT_REGISTRY_INDEX
);
753 struct charset
*repertory
;
755 if (xfont_registry_charsets (registry
, NULL
, &repertory
) < 0)
759 return (ENCODE_CHAR (repertory
, c
) != CHARSET_INVALID_CODE (repertory
));
763 xfont_encode_char (font
, c
)
767 struct charset
*charset
;
771 charset
= CHARSET_FROM_ID (font
->encoding_charset
);
772 code
= ENCODE_CHAR (charset
, c
);
773 if (code
== CHARSET_INVALID_CODE (charset
))
775 if (font
->repertory_charet
>= 0)
777 charset
= CHARSET_FROM_ID (font
->repertory_charet
);
778 return (ENCODE_CHAR (charset
, c
) != CHARSET_INVALID_CODE (charset
)
779 ? code
: 0xFFFFFFFF);
781 char2b
.byte1
= code
>> 8;
782 char2b
.byte2
= code
& 0xFF;
783 return (xfont_get_pcm (font
->font
.font
, &char2b
) ? code
: 0xFFFFFFFF);
787 xfont_text_extents (font
, code
, nglyphs
, metrics
)
791 struct font_metrics
*metrics
;
797 bzero (metrics
, sizeof (struct font_metrics
));
798 for (i
= 0, x
= 0; i
< nglyphs
; i
++)
801 static XCharStruct
*pcm
;
803 if (code
[i
] >= 0x10000)
805 char2b
.byte1
= code
[i
] >> 8, char2b
.byte2
= code
[i
] & 0xFF;
806 pcm
= xfont_get_pcm (font
->font
.font
, &char2b
);
809 if (metrics
->lbearing
> width
+ pcm
->lbearing
)
810 metrics
->lbearing
= width
+ pcm
->lbearing
;
811 if (metrics
->rbearing
< width
+ pcm
->rbearing
)
812 metrics
->rbearing
= width
+ pcm
->rbearing
;
813 if (metrics
->ascent
< pcm
->ascent
)
814 metrics
->ascent
= pcm
->ascent
;
815 if (metrics
->descent
< pcm
->descent
)
816 metrics
->descent
= pcm
->descent
;
820 metrics
->width
= width
;
825 xfont_draw (s
, from
, to
, x
, y
, with_background
)
826 struct glyph_string
*s
;
827 int from
, to
, x
, y
, with_background
;
829 XFontStruct
*xfont
= s
->face
->font
;
832 if (xfont
->min_byte1
== 0 && xfont
->max_byte1
== 0)
838 SAFE_ALLOCA (str
, char *, len
);
839 for (i
= 0; i
< len
; i
++)
840 str
[i
] = XCHAR2B_BYTE2 (s
->char2b
+ from
+ i
);
841 if (with_background
> 0)
842 XDrawImageString (FRAME_X_DISPLAY (s
->f
), FRAME_X_WINDOW (s
->f
),
843 s
->gc
, x
, y
, str
, len
);
845 XDrawString (FRAME_X_DISPLAY (s
->f
), FRAME_X_WINDOW (s
->f
),
846 s
->gc
, x
, y
, str
, len
);
851 if (with_background
> 0)
852 XDrawImageString16 (FRAME_X_DISPLAY (s
->f
), FRAME_X_WINDOW (s
->f
),
853 s
->gc
, x
, y
, s
->char2b
+ from
, len
);
855 XDrawString16 (FRAME_X_DISPLAY (s
->f
), FRAME_X_WINDOW (s
->f
),
856 s
->gc
, x
, y
, s
->char2b
+ from
, len
);
866 staticpro (&x_font_charset_alist
);
867 x_font_charset_alist
= Qnil
;
870 xfont_driver
.type
= Qx
;
871 register_font_driver (&xfont_driver
, NULL
);
874 /* arch-tag: 23c5f366-a5ee-44b7-a3b7-90d6da7fd749
875 (do not change this comment) */