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 Lisp_Object xfont_list
P_ ((Lisp_Object
, Lisp_Object
));
242 static Lisp_Object xfont_list_family
P_ ((Lisp_Object
));
243 static struct font
*xfont_open
P_ ((FRAME_PTR
, Lisp_Object
, int));
244 static void xfont_close
P_ ((FRAME_PTR
, struct font
*));
245 static int xfont_prepare_face
P_ ((FRAME_PTR
, struct face
*));
247 static void xfont_done_face
P_ ((FRAME_PTR
, struct face
*));
249 static int xfont_has_char
P_ ((Lisp_Object
, int));
250 static unsigned xfont_encode_char
P_ ((struct font
*, int));
251 static int xfont_text_extents
P_ ((struct font
*, unsigned *, int,
252 struct font_metrics
*));
253 static int xfont_draw
P_ ((struct glyph_string
*, int, int, int, int, int));
255 struct font_driver xfont_driver
=
257 (Lisp_Object
) NULL
, /* Qx */
265 NULL
/*xfont_done_face*/,
272 extern Lisp_Object QCname
;
275 xfont_get_cache (frame
)
278 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (XFRAME (frame
));
280 return (dpyinfo
->name_list_element
);
283 extern Lisp_Object Vface_alternative_font_registry_alist
;
286 xfont_list (frame
, spec
)
287 Lisp_Object frame
, spec
;
289 FRAME_PTR f
= XFRAME (frame
);
290 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
291 Lisp_Object
*vec
, val
, extra
, font_name
, entity
;
292 char name
[256], **names
;
293 int i
, idx
, limit
, num_fonts
;
294 int error_occurred
= 0;
297 extra
= AREF (spec
, FONT_EXTRA_INDEX
);
301 val
= Fassq (QCotf
, extra
);
304 val
= Fassq (QCscript
, extra
);
307 val
= Fassq (QCname
, extra
);
309 font_name
= XCDR (val
);
312 if (! STRINGP (font_name
)
313 && font_unparse_xlfd (spec
, 0, name
, 256) < 0)
317 x_catch_errors (dpyinfo
->display
);
319 if (STRINGP (font_name
))
321 XFontStruct
*font
= XLoadQueryFont (dpyinfo
->display
,
322 (char *) SDATA (font_name
));
326 if (x_had_errors_p (dpyinfo
->display
))
328 /* This error is perhaps due to insufficient memory on X
329 server. Let's just ignore it. */
332 x_clear_errors (dpyinfo
->display
);
336 if (XGetFontProperty (font
, XA_FONT
, &value
))
338 char *n
= (char *) XGetAtomName (dpyinfo
->display
, (Atom
) value
);
339 int len
= strlen (n
);
342 /* If DXPC (a Differential X Protocol Compressor)
343 Ver.3.7 is running, XGetAtomName will return null
344 string. We must avoid such a name. */
348 names
= (char **) alloca (sizeof (char *));
349 /* Some systems only allow alloca assigned to a
351 tmp
= (char *) alloca (len
+ 1); names
[0] = tmp
;
352 bcopy (n
, names
[0], len
+ 1);
356 XFreeFont (dpyinfo
->display
, font
);
361 Lisp_Object registry
= AREF (spec
, FONT_REGISTRY_INDEX
);
362 Lisp_Object alter
= Qnil
;
365 if (! NILP (registry
))
366 alter
= Fassoc_string (SYMBOL_NAME (registry
),
367 Vface_alternative_font_registry_alist
);
370 for (limit
= 512, num_fonts
= 0; ; limit
*= 2)
372 names
= XListFonts (dpyinfo
->display
, name
, limit
, &num_fonts
);
373 if (x_had_errors_p (dpyinfo
->display
))
375 /* This error is perhaps due to insufficient memory
376 on X server. Let's just ignore it. */
377 x_clear_errors (dpyinfo
->display
);
382 if (num_fonts
< limit
)
384 XFreeFontNames (names
);
390 /* Setup for trying alternatives. */
392 && ! (r
= strstr (name
, (char *) SDATA (SYMBOL_NAME (registry
)))))
397 alter
= XCDR (alter
);
400 registry
= XCAR (alter
);
401 if ((r
- name
) + SBYTES (registry
) < 255)
406 bcopy (SDATA (registry
), r
, SBYTES (registry
));
418 entity
= Fmake_vector (make_number (FONT_ENTITY_MAX
), Qnil
);
419 ASET (entity
, FONT_TYPE_INDEX
, Qx
);
420 ASET (entity
, FONT_FRAME_INDEX
, frame
);
422 SAFE_ALLOCA_LISP (vec
, num_fonts
);
423 for (i
= idx
= 0; i
< num_fonts
; i
++)
425 if (font_parse_xlfd (names
[i
], entity
, 0) > 0)
426 vec
[idx
++] = Fcopy_sequence (entity
);
428 if (! STRINGP (font_name
))
431 XFreeFontNames (names
);
434 val
= Fvector (idx
, vec
);
441 memq_no_quit (elt
, list
)
442 Lisp_Object elt
, list
;
444 while (CONSP (list
) && ! EQ (XCAR (list
), elt
))
446 return (CONSP (list
));
450 xfont_list_family (frame
)
453 FRAME_PTR f
= XFRAME (frame
);
454 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
462 x_catch_errors (dpyinfo
->display
);
463 names
= XListFonts (dpyinfo
->display
, "-*-*-*-*-*-*-*-*-*-*-*-*-*-*",
465 if (x_had_errors_p (dpyinfo
->display
))
467 /* This error is perhaps due to insufficient memory on X server.
468 Let's just ignore it. */
469 x_clear_errors (dpyinfo
->display
);
474 for (i
= 0, last_len
= 0; i
< num_fonts
; i
++)
476 char *p0
= names
[i
], *p1
;
479 p0
++; /* skip the leading '-' */
480 while (*p0
&& *p0
!= '-') p0
++; /* skip foundry */
484 while (*p1
&& *p1
!= '-') p1
++; /* find the end of family */
485 if (! *p1
|| p1
== p0
)
487 if (last_len
== p1
- p0
488 && bcmp (last_family
, p0
, last_len
) == 0)
492 family
= intern_downcase (p0
, last_len
);
493 if (! memq_no_quit (family
, list
))
494 list
= Fcons (family
, list
);
497 XFreeFontNames (names
);
505 xfont_open (f
, entity
, pixel_size
)
510 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
511 Display
*display
= dpyinfo
->display
;
515 Lisp_Object registry
;
516 struct charset
*encoding
, *repertory
;
520 /* At first, check if we know how to encode characters for this
522 registry
= AREF (entity
, FONT_REGISTRY_INDEX
);
523 if (xfont_registry_charsets (registry
, &encoding
, &repertory
) < 0)
526 if (XINT (AREF (entity
, FONT_SIZE_INDEX
)) != 0)
527 pixel_size
= XINT (AREF (entity
, FONT_SIZE_INDEX
));
528 len
= font_unparse_xlfd (entity
, pixel_size
, name
, 256);
533 x_catch_errors (display
);
534 xfont
= XLoadQueryFont (display
, name
);
535 if (x_had_errors_p (display
))
537 /* This error is perhaps due to insufficient memory on X server.
538 Let's just ignore it. */
539 x_clear_errors (display
);
547 font
= malloc (sizeof (struct font
));
548 font
->font
.font
= xfont
;
549 font
->entity
= entity
;
550 font
->pixel_size
= pixel_size
;
551 font
->driver
= &xfont_driver
;
552 font
->font
.name
= malloc (len
+ 1);
553 if (! font
->font
.name
)
555 XFreeFont (display
, xfont
);
559 bcopy (name
, font
->font
.name
, len
+ 1);
560 font
->font
.charset
= encoding
->id
;
561 font
->encoding_charset
= encoding
->id
;
562 font
->repertory_charset
= repertory
? repertory
->id
: -1;
563 font
->ascent
= xfont
->ascent
;
564 font
->descent
= xfont
->descent
;
566 if (xfont
->min_bounds
.width
== xfont
->max_bounds
.width
)
568 /* Fixed width font. */
569 font
->font
.average_width
= font
->font
.space_width
570 = xfont
->min_bounds
.width
;
577 char2b
.byte1
= 0x00, char2b
.byte2
= 0x20;
578 pcm
= xfont_get_pcm (xfont
, &char2b
);
580 font
->font
.space_width
= pcm
->width
;
582 font
->font
.space_width
= xfont
->max_bounds
.width
;
584 font
->font
.average_width
585 = (XGetFontProperty (xfont
, dpyinfo
->Xatom_AVERAGE_WIDTH
, &value
)
586 ? (long) value
/ 10 : 0);
587 if (font
->font
.average_width
< 0)
588 font
->font
.average_width
= - font
->font
.average_width
;
589 if (font
->font
.average_width
== 0)
593 int width
= pcm
->width
;
594 for (char2b
.byte2
= 33; char2b
.byte2
<= 126; char2b
.byte2
++)
595 if ((pcm
= xfont_get_pcm (xfont
, &char2b
)) != NULL
)
597 font
->font
.average_width
= width
/ 95;
600 font
->font
.average_width
= xfont
->max_bounds
.width
;
603 font
->min_width
= xfont
->min_bounds
.width
;
604 if (font
->min_width
<= 0)
605 font
->min_width
= font
->font
.space_width
;
608 /* Try to get the full name of FONT. Put it in FULL_NAME. */
609 if (XGetFontProperty (xfont
, XA_FONT
, &value
))
611 char *full_name
= NULL
, *p0
, *p
;
614 p0
= p
= (char *) XGetAtomName (FRAME_X_DISPLAY (f
), (Atom
) value
);;
615 /* Count the number of dashes in the "full name".
616 If it is too few, this isn't really the font's full name,
618 In X11R4, the fonts did not come with their canonical names
629 full_name
= (char *) malloc (p
- p0
+ 1);
631 bcopy (p0
, full_name
, p
- p0
+ 1);
636 font
->font
.full_name
= full_name
;
638 font
->font
.full_name
= font
->font
.name
;
640 font
->file_name
= NULL
;
642 font
->font
.size
= xfont
->max_bounds
.width
;
643 font
->font
.height
= xfont
->ascent
+ xfont
->descent
;
644 font
->font
.baseline_offset
645 = (XGetFontProperty (xfont
, dpyinfo
->Xatom_MULE_BASELINE_OFFSET
, &value
)
647 font
->font
.relative_compose
648 = (XGetFontProperty (xfont
, dpyinfo
->Xatom_MULE_RELATIVE_COMPOSE
, &value
)
650 font
->font
.default_ascent
651 = (XGetFontProperty (xfont
, dpyinfo
->Xatom_MULE_DEFAULT_ASCENT
, &value
)
653 font
->font
.vertical_centering
654 = (STRINGP (Vvertical_centering_font_regexp
)
655 && (fast_c_string_match_ignore_case
656 (Vvertical_centering_font_regexp
, font
->font
.full_name
) >= 0));
662 /* Set global flag fonts_changed_p to non-zero if the font loaded
663 has a character with a smaller width than any other character
664 before, or if the font loaded has a smaller height than any other
665 font loaded before. If this happens, it will make a glyph matrix
666 reallocation necessary. */
667 if (dpyinfo
->n_fonts
== 1)
669 dpyinfo
->smallest_font_height
= font
->font
.height
;
670 dpyinfo
->smallest_char_width
= font
->min_width
;
675 if (dpyinfo
->smallest_font_height
> font
->font
.height
)
676 dpyinfo
->smallest_font_height
= font
->font
.height
, fonts_changed_p
|= 1;
677 if (dpyinfo
->smallest_char_width
> font
->min_width
)
678 dpyinfo
->smallest_char_width
= font
->min_width
, fonts_changed_p
|= 1;
685 xfont_close (f
, font
)
690 XFreeFont (FRAME_X_DISPLAY (f
), font
->font
.font
);
693 if (font
->font
.name
!= font
->font
.full_name
)
694 free (font
->font
.full_name
);
695 free (font
->font
.name
);
697 FRAME_X_DISPLAY_INFO (f
)->n_fonts
--;
701 xfont_prepare_face (f
, face
)
706 XSetFont (FRAME_X_DISPLAY (f
), face
->gc
, face
->font
->fid
);
714 xfont_done_face (f
, face
)
721 XFreeGC (FRAME_X_DISPLAY (f
), (GC
) face
->extra
);
729 xfont_has_char (entity
, c
)
733 Lisp_Object registry
= AREF (entity
, FONT_REGISTRY_INDEX
);
734 struct charset
*repertory
;
736 if (xfont_registry_charsets (registry
, NULL
, &repertory
) < 0)
740 return (ENCODE_CHAR (repertory
, c
) != CHARSET_INVALID_CODE (repertory
));
744 xfont_encode_char (font
, c
)
748 struct charset
*charset
;
752 charset
= CHARSET_FROM_ID (font
->encoding_charset
);
753 code
= ENCODE_CHAR (charset
, c
);
754 if (code
== CHARSET_INVALID_CODE (charset
))
756 if (font
->repertory_charset
>= 0)
758 charset
= CHARSET_FROM_ID (font
->repertory_charset
);
759 return (ENCODE_CHAR (charset
, c
) != CHARSET_INVALID_CODE (charset
)
760 ? code
: 0xFFFFFFFF);
762 char2b
.byte1
= code
>> 8;
763 char2b
.byte2
= code
& 0xFF;
764 return (xfont_get_pcm (font
->font
.font
, &char2b
) ? code
: 0xFFFFFFFF);
768 xfont_text_extents (font
, code
, nglyphs
, metrics
)
772 struct font_metrics
*metrics
;
778 bzero (metrics
, sizeof (struct font_metrics
));
779 for (i
= 0, x
= 0; i
< nglyphs
; i
++)
782 static XCharStruct
*pcm
;
784 if (code
[i
] >= 0x10000)
786 char2b
.byte1
= code
[i
] >> 8, char2b
.byte2
= code
[i
] & 0xFF;
787 pcm
= xfont_get_pcm (font
->font
.font
, &char2b
);
790 if (metrics
->lbearing
> width
+ pcm
->lbearing
)
791 metrics
->lbearing
= width
+ pcm
->lbearing
;
792 if (metrics
->rbearing
< width
+ pcm
->rbearing
)
793 metrics
->rbearing
= width
+ pcm
->rbearing
;
794 if (metrics
->ascent
< pcm
->ascent
)
795 metrics
->ascent
= pcm
->ascent
;
796 if (metrics
->descent
< pcm
->descent
)
797 metrics
->descent
= pcm
->descent
;
801 metrics
->width
= width
;
806 xfont_draw (s
, from
, to
, x
, y
, with_background
)
807 struct glyph_string
*s
;
808 int from
, to
, x
, y
, with_background
;
810 XFontStruct
*xfont
= s
->face
->font
;
813 if (xfont
->min_byte1
== 0 && xfont
->max_byte1
== 0)
819 SAFE_ALLOCA (str
, char *, len
);
820 for (i
= 0; i
< len
; i
++)
821 str
[i
] = XCHAR2B_BYTE2 (s
->char2b
+ from
+ i
);
822 if (with_background
> 0)
823 XDrawImageString (FRAME_X_DISPLAY (s
->f
), FRAME_X_WINDOW (s
->f
),
824 s
->gc
, x
, y
, str
, len
);
826 XDrawString (FRAME_X_DISPLAY (s
->f
), FRAME_X_WINDOW (s
->f
),
827 s
->gc
, x
, y
, str
, len
);
832 if (with_background
> 0)
833 XDrawImageString16 (FRAME_X_DISPLAY (s
->f
), FRAME_X_WINDOW (s
->f
),
834 s
->gc
, x
, y
, s
->char2b
+ from
, len
);
836 XDrawString16 (FRAME_X_DISPLAY (s
->f
), FRAME_X_WINDOW (s
->f
),
837 s
->gc
, x
, y
, s
->char2b
+ from
, len
);
847 staticpro (&x_font_charset_alist
);
848 x_font_charset_alist
= Qnil
;
851 xfont_driver
.type
= Qx
;
852 register_font_driver (&xfont_driver
, NULL
);
855 /* arch-tag: 23c5f366-a5ee-44b7-a3b7-90d6da7fd749
856 (do not change this comment) */