1 /* xfont.c -- X core font driver.
2 Copyright (C) 2006, 2007, 2008 Free Software Foundation, Inc.
3 Copyright (C) 2006, 2007, 2008
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 3, 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. */
41 /* Prototypes of support functions. */
42 extern void x_clear_errors
P_ ((Display
*));
44 static char *xfont_query_font
P_ ((Display
*, char *, Lisp_Object
));
45 static XCharStruct
*xfont_get_pcm
P_ ((XFontStruct
*, XChar2b
*));
46 static int xfont_registry_charsets
P_ ((Lisp_Object
, struct charset
**,
50 xfont_query_font (display
, name
, spec
)
58 x_catch_errors (display
);
59 font
= XLoadQueryFont (display
, name
);
61 if (x_had_errors_p (display
))
63 /* This error is perhaps due to insufficient memory on X
64 server. Let's just ignore it. */
65 x_clear_errors (display
);
71 if (XGetFontProperty (font
, XA_FONT
, &value
))
73 char *n
= (char *) XGetAtomName (display
, (Atom
) value
);
75 if (font_parse_xlfd (n
, spec
) >= 0)
80 XFreeFont (display
, font
);
89 /* Get metrics of character CHAR2B in XFONT. Value is null if CHAR2B
90 is not contained in the font. */
93 xfont_get_pcm (xfont
, char2b
)
97 /* The result metric information. */
98 XCharStruct
*pcm
= NULL
;
100 xassert (xfont
&& char2b
);
102 if (xfont
->per_char
!= NULL
)
104 if (xfont
->min_byte1
== 0 && xfont
->max_byte1
== 0)
106 /* min_char_or_byte2 specifies the linear character index
107 corresponding to the first element of the per_char array,
108 max_char_or_byte2 is the index of the last character. A
109 character with non-zero CHAR2B->byte1 is not in the font.
110 A character with byte2 less than min_char_or_byte2 or
111 greater max_char_or_byte2 is not in the font. */
112 if (char2b
->byte1
== 0
113 && char2b
->byte2
>= xfont
->min_char_or_byte2
114 && char2b
->byte2
<= xfont
->max_char_or_byte2
)
115 pcm
= xfont
->per_char
+ char2b
->byte2
- xfont
->min_char_or_byte2
;
119 /* If either min_byte1 or max_byte1 are nonzero, both
120 min_char_or_byte2 and max_char_or_byte2 are less than
121 256, and the 2-byte character index values corresponding
122 to the per_char array element N (counting from 0) are:
124 byte1 = N/D + min_byte1
125 byte2 = N\D + min_char_or_byte2
129 D = max_char_or_byte2 - min_char_or_byte2 + 1
131 \ = integer modulus */
132 if (char2b
->byte1
>= xfont
->min_byte1
133 && char2b
->byte1
<= xfont
->max_byte1
134 && char2b
->byte2
>= xfont
->min_char_or_byte2
135 && char2b
->byte2
<= xfont
->max_char_or_byte2
)
136 pcm
= (xfont
->per_char
137 + ((xfont
->max_char_or_byte2
- xfont
->min_char_or_byte2
+ 1)
138 * (char2b
->byte1
- xfont
->min_byte1
))
139 + (char2b
->byte2
- xfont
->min_char_or_byte2
));
144 /* If the per_char pointer is null, all glyphs between the first
145 and last character indexes inclusive have the same
146 information, as given by both min_bounds and max_bounds. */
147 if (char2b
->byte2
>= xfont
->min_char_or_byte2
148 && char2b
->byte2
<= xfont
->max_char_or_byte2
)
149 pcm
= &xfont
->max_bounds
;
153 || (pcm
->width
== 0 && (pcm
->rbearing
- pcm
->lbearing
) == 0))
157 static Lisp_Object xfont_get_cache
P_ ((FRAME_PTR
));
158 static Lisp_Object xfont_list
P_ ((Lisp_Object
, Lisp_Object
));
159 static Lisp_Object xfont_match
P_ ((Lisp_Object
, Lisp_Object
));
160 static Lisp_Object xfont_list_family
P_ ((Lisp_Object
));
161 static struct font
*xfont_open
P_ ((FRAME_PTR
, Lisp_Object
, int));
162 static void xfont_close
P_ ((FRAME_PTR
, struct font
*));
163 static int xfont_prepare_face
P_ ((FRAME_PTR
, struct face
*));
165 static void xfont_done_face
P_ ((FRAME_PTR
, struct face
*));
167 static int xfont_has_char
P_ ((Lisp_Object
, int));
168 static unsigned xfont_encode_char
P_ ((struct font
*, int));
169 static int xfont_text_extents
P_ ((struct font
*, unsigned *, int,
170 struct font_metrics
*));
171 static int xfont_draw
P_ ((struct glyph_string
*, int, int, int, int, int));
173 struct font_driver xfont_driver
=
184 NULL
/*xfont_done_face*/,
191 extern Lisp_Object QCname
;
197 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
199 return (dpyinfo
->name_list_element
);
202 extern Lisp_Object Vface_alternative_font_registry_alist
;
205 xfont_list_pattern (frame
, display
, pattern
)
210 Lisp_Object list
= Qnil
;
211 int i
, limit
, num_fonts
;
215 x_catch_errors (display
);
217 for (limit
= 512; ; limit
*= 2)
219 names
= XListFonts (display
, pattern
, limit
, &num_fonts
);
220 if (x_had_errors_p (display
))
222 /* This error is perhaps due to insufficient memory on X
223 server. Let's just ignore it. */
224 x_clear_errors (display
);
228 if (num_fonts
< limit
)
230 XFreeFontNames (names
);
233 for (i
= 0; i
< num_fonts
; i
++)
235 Lisp_Object entity
= Fmake_vector (make_number (FONT_ENTITY_MAX
), Qnil
);
238 ASET (entity
, FONT_TYPE_INDEX
, Qx
);
239 ASET (entity
, FONT_FRAME_INDEX
, frame
);
241 result
= font_parse_xlfd (names
[i
], entity
);
244 /* This may be an alias name. Try to get the full XLFD name
245 from XA_FONT property of the font. */
246 XFontStruct
*font
= XLoadQueryFont (display
, names
[i
]);
251 if (XGetFontProperty (font
, XA_FONT
, &value
))
253 char *name
= (char *) XGetAtomName (display
, (Atom
) value
);
254 int len
= strlen (name
);
256 /* If DXPC (a Differential X Protocol Compressor)
257 Ver.3.7 is running, XGetAtomName will return null
258 string. We must avoid such a name. */
260 result
= font_parse_xlfd (name
, entity
);
263 XFreeFont (display
, font
);
268 Lisp_Object val
= AREF (entity
, FONT_EXTRA_INDEX
);
269 char *p
= (char *) SDATA (SYMBOL_NAME (val
));
271 /* P == "RESX-RESY-SPACING-AVGWIDTH. We rejust this font if
272 it's an autoscaled one (i.e. RESX > 0 && AVGWIDTH == 0). */
275 p
+= SBYTES (SYMBOL_NAME (val
));
276 while (p
[-1] != '-') p
--;
280 list
= Fcons (entity
, list
);
291 xfont_list (frame
, spec
)
292 Lisp_Object frame
, spec
;
294 FRAME_PTR f
= XFRAME (frame
);
295 Display
*display
= FRAME_X_DISPLAY_INFO (f
)->display
;
296 Lisp_Object list
, val
, extra
, font_name
;
300 extra
= AREF (spec
, FONT_EXTRA_INDEX
);
304 val
= assq_no_quit (QCotf
, extra
);
307 val
= assq_no_quit (QCscript
, extra
);
310 val
= assq_no_quit (QClanguage
, extra
);
313 val
= assq_no_quit (QCname
, extra
);
315 font_name
= XCDR (val
);
318 if (STRINGP (font_name
)
319 && ! strchr ((char *) SDATA (font_name
), ':'))
320 list
= xfont_list_pattern (frame
, display
, (char *) SDATA (font_name
));
321 else if ((len
= font_unparse_xlfd (spec
, 0, name
, 256)) < 0)
325 list
= xfont_list_pattern (frame
, display
, name
);
328 Lisp_Object registry
= AREF (spec
, FONT_REGISTRY_INDEX
);
331 if (! NILP (registry
)
332 && (alter
= Fassoc (SYMBOL_NAME (registry
),
333 Vface_alternative_font_registry_alist
),
336 /* Pointer to REGISTRY-ENCODING field. */
337 char *r
= name
+ len
- SBYTES (SYMBOL_NAME (registry
));
339 for (alter
= XCDR (alter
); CONSP (alter
); alter
= XCDR (alter
))
340 if (STRINGP (XCAR (alter
))
341 && ((r
- name
) + SBYTES (XCAR (alter
))) < 255)
343 strcpy (r
, (char *) SDATA (XCAR (alter
)));
344 list
= xfont_list_pattern (frame
, display
, name
);
352 return (NILP (list
) ? null_vector
: Fvconcat (1, &list
));
356 xfont_match (frame
, spec
)
357 Lisp_Object frame
, spec
;
359 FRAME_PTR f
= XFRAME (frame
);
360 Display
*display
= FRAME_X_DISPLAY_INFO (f
)->display
;
361 Lisp_Object extra
, val
, entity
;
366 extra
= AREF (spec
, FONT_EXTRA_INDEX
);
367 val
= assq_no_quit (QCname
, extra
);
368 if (! CONSP (val
) || ! STRINGP (XCDR (val
)))
373 name
= (char *) SDATA (XCDR (val
));
374 xfont
= XLoadQueryFont (display
, name
);
377 if (XGetFontProperty (xfont
, XA_FONT
, &value
))
381 name
= (char *) XGetAtomName (display
, (Atom
) value
);
384 /* If DXPC (a Differential X Protocol Compressor)
385 Ver.3.7 is running, XGetAtomName will return null
386 string. We must avoid such a name. */
389 entity
= Fmake_vector (make_number (FONT_ENTITY_MAX
), Qnil
);
390 ASET (entity
, FONT_TYPE_INDEX
, Qx
);
391 ASET (entity
, FONT_FRAME_INDEX
, frame
);
392 if (font_parse_xlfd (name
, entity
) < 0)
397 XFreeFont (display
, xfont
);
405 memq_no_quit (elt
, list
)
406 Lisp_Object elt
, list
;
408 while (CONSP (list
) && ! EQ (XCAR (list
), elt
))
410 return (CONSP (list
));
414 xfont_list_family (frame
)
417 FRAME_PTR f
= XFRAME (frame
);
418 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
426 x_catch_errors (dpyinfo
->display
);
427 names
= XListFonts (dpyinfo
->display
, "-*-*-*-*-*-*-*-*-*-*-*-*-*-*",
429 if (x_had_errors_p (dpyinfo
->display
))
431 /* This error is perhaps due to insufficient memory on X server.
432 Let's just ignore it. */
433 x_clear_errors (dpyinfo
->display
);
438 for (i
= 0, last_len
= 0; i
< num_fonts
; i
++)
440 char *p0
= names
[i
], *p1
;
443 p0
++; /* skip the leading '-' */
444 while (*p0
&& *p0
!= '-') p0
++; /* skip foundry */
448 while (*p1
&& *p1
!= '-') p1
++; /* find the end of family */
449 if (! *p1
|| p1
== p0
)
451 if (last_len
== p1
- p0
452 && bcmp (last_family
, p0
, last_len
) == 0)
456 family
= intern_downcase (p0
, last_len
);
457 if (! memq_no_quit (family
, list
))
458 list
= Fcons (family
, list
);
461 XFreeFontNames (names
);
469 xfont_open (f
, entity
, pixel_size
)
474 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
475 Display
*display
= dpyinfo
->display
;
479 Lisp_Object registry
;
480 struct charset
*encoding
, *repertory
;
484 /* At first, check if we know how to encode characters for this
486 registry
= AREF (entity
, FONT_REGISTRY_INDEX
);
487 if (font_registry_charsets (registry
, &encoding
, &repertory
) < 0)
490 if (XINT (AREF (entity
, FONT_SIZE_INDEX
)) != 0)
491 pixel_size
= XINT (AREF (entity
, FONT_SIZE_INDEX
));
492 len
= font_unparse_xlfd (entity
, pixel_size
, name
, 256);
497 x_catch_errors (display
);
498 xfont
= XLoadQueryFont (display
, name
);
499 if (x_had_errors_p (display
))
501 /* This error is perhaps due to insufficient memory on X server.
502 Let's just ignore it. */
503 x_clear_errors (display
);
511 font
= malloc (sizeof (struct font
));
513 font
->font
.font
= xfont
;
514 font
->entity
= entity
;
515 font
->pixel_size
= pixel_size
;
516 font
->driver
= &xfont_driver
;
517 font
->font
.name
= malloc (len
+ 1);
518 if (! font
->font
.name
)
520 XFreeFont (display
, xfont
);
524 bcopy (name
, font
->font
.name
, len
+ 1);
525 font
->font
.charset
= encoding
->id
;
526 font
->encoding_charset
= encoding
->id
;
527 font
->repertory_charset
= repertory
? repertory
->id
: -1;
528 font
->ascent
= xfont
->ascent
;
529 font
->descent
= xfont
->descent
;
531 if (xfont
->min_bounds
.width
== xfont
->max_bounds
.width
)
533 /* Fixed width font. */
534 font
->font
.average_width
= font
->font
.space_width
535 = xfont
->min_bounds
.width
;
542 char2b
.byte1
= 0x00, char2b
.byte2
= 0x20;
543 pcm
= xfont_get_pcm (xfont
, &char2b
);
545 font
->font
.space_width
= pcm
->width
;
547 font
->font
.space_width
= xfont
->max_bounds
.width
;
549 font
->font
.average_width
550 = (XGetFontProperty (xfont
, dpyinfo
->Xatom_AVERAGE_WIDTH
, &value
)
551 ? (long) value
/ 10 : 0);
552 if (font
->font
.average_width
< 0)
553 font
->font
.average_width
= - font
->font
.average_width
;
554 if (font
->font
.average_width
== 0)
558 int width
= pcm
->width
;
559 for (char2b
.byte2
= 33; char2b
.byte2
<= 126; char2b
.byte2
++)
560 if ((pcm
= xfont_get_pcm (xfont
, &char2b
)) != NULL
)
562 font
->font
.average_width
= width
/ 95;
565 font
->font
.average_width
= xfont
->max_bounds
.width
;
568 font
->min_width
= xfont
->min_bounds
.width
;
569 if (font
->min_width
<= 0)
570 font
->min_width
= font
->font
.space_width
;
573 /* Try to get the full name of FONT. Put it in FULL_NAME. */
574 if (XGetFontProperty (xfont
, XA_FONT
, &value
))
576 char *full_name
= NULL
, *p0
, *p
;
579 p0
= p
= (char *) XGetAtomName (FRAME_X_DISPLAY (f
), (Atom
) value
);;
580 /* Count the number of dashes in the "full name".
581 If it is too few, this isn't really the font's full name,
583 In X11R4, the fonts did not come with their canonical names
594 full_name
= (char *) malloc (p
- p0
+ 1);
596 bcopy (p0
, full_name
, p
- p0
+ 1);
601 font
->font
.full_name
= full_name
;
603 font
->font
.full_name
= font
->font
.name
;
605 font
->file_name
= NULL
;
607 font
->font
.size
= xfont
->max_bounds
.width
;
608 font
->font
.height
= xfont
->ascent
+ xfont
->descent
;
609 font
->font
.baseline_offset
610 = (XGetFontProperty (xfont
, dpyinfo
->Xatom_MULE_BASELINE_OFFSET
, &value
)
612 font
->font
.relative_compose
613 = (XGetFontProperty (xfont
, dpyinfo
->Xatom_MULE_RELATIVE_COMPOSE
, &value
)
615 font
->font
.default_ascent
616 = (XGetFontProperty (xfont
, dpyinfo
->Xatom_MULE_DEFAULT_ASCENT
, &value
)
618 font
->font
.vertical_centering
619 = (STRINGP (Vvertical_centering_font_regexp
)
620 && (fast_c_string_match_ignore_case
621 (Vvertical_centering_font_regexp
, font
->font
.full_name
) >= 0));
627 /* Set global flag fonts_changed_p to non-zero if the font loaded
628 has a character with a smaller width than any other character
629 before, or if the font loaded has a smaller height than any other
630 font loaded before. If this happens, it will make a glyph matrix
631 reallocation necessary. */
632 if (dpyinfo
->n_fonts
== 1)
634 dpyinfo
->smallest_font_height
= font
->font
.height
;
635 dpyinfo
->smallest_char_width
= font
->min_width
;
640 if (dpyinfo
->smallest_font_height
> font
->font
.height
)
641 dpyinfo
->smallest_font_height
= font
->font
.height
, fonts_changed_p
|= 1;
642 if (dpyinfo
->smallest_char_width
> font
->min_width
)
643 dpyinfo
->smallest_char_width
= font
->min_width
, fonts_changed_p
|= 1;
650 xfont_close (f
, font
)
655 XFreeFont (FRAME_X_DISPLAY (f
), font
->font
.font
);
658 if (font
->font
.name
!= font
->font
.full_name
)
659 free (font
->font
.full_name
);
660 free (font
->font
.name
);
662 FRAME_X_DISPLAY_INFO (f
)->n_fonts
--;
666 xfont_prepare_face (f
, face
)
671 XSetFont (FRAME_X_DISPLAY (f
), face
->gc
, face
->font
->fid
);
679 xfont_done_face (f
, face
)
686 XFreeGC (FRAME_X_DISPLAY (f
), (GC
) face
->extra
);
694 xfont_has_char (entity
, c
)
698 Lisp_Object registry
= AREF (entity
, FONT_REGISTRY_INDEX
);
699 struct charset
*repertory
;
701 if (font_registry_charsets (registry
, NULL
, &repertory
) < 0)
705 return (ENCODE_CHAR (repertory
, c
) != CHARSET_INVALID_CODE (repertory
));
709 xfont_encode_char (font
, c
)
713 struct charset
*charset
;
717 charset
= CHARSET_FROM_ID (font
->encoding_charset
);
718 code
= ENCODE_CHAR (charset
, c
);
719 if (code
== CHARSET_INVALID_CODE (charset
))
720 return FONT_INVALID_CODE
;
721 if (font
->repertory_charset
>= 0)
723 charset
= CHARSET_FROM_ID (font
->repertory_charset
);
724 return (ENCODE_CHAR (charset
, c
) != CHARSET_INVALID_CODE (charset
)
725 ? code
: FONT_INVALID_CODE
);
727 char2b
.byte1
= code
>> 8;
728 char2b
.byte2
= code
& 0xFF;
729 return (xfont_get_pcm (font
->font
.font
, &char2b
) ? code
: FONT_INVALID_CODE
);
733 xfont_text_extents (font
, code
, nglyphs
, metrics
)
737 struct font_metrics
*metrics
;
743 bzero (metrics
, sizeof (struct font_metrics
));
744 for (i
= 0, x
= 0; i
< nglyphs
; i
++)
747 static XCharStruct
*pcm
;
749 if (code
[i
] >= 0x10000)
751 char2b
.byte1
= code
[i
] >> 8, char2b
.byte2
= code
[i
] & 0xFF;
752 pcm
= xfont_get_pcm (font
->font
.font
, &char2b
);
755 if (metrics
->lbearing
> width
+ pcm
->lbearing
)
756 metrics
->lbearing
= width
+ pcm
->lbearing
;
757 if (metrics
->rbearing
< width
+ pcm
->rbearing
)
758 metrics
->rbearing
= width
+ pcm
->rbearing
;
759 if (metrics
->ascent
< pcm
->ascent
)
760 metrics
->ascent
= pcm
->ascent
;
761 if (metrics
->descent
< pcm
->descent
)
762 metrics
->descent
= pcm
->descent
;
766 metrics
->width
= width
;
771 xfont_draw (s
, from
, to
, x
, y
, with_background
)
772 struct glyph_string
*s
;
773 int from
, to
, x
, y
, with_background
;
775 XFontStruct
*xfont
= s
->face
->font
;
780 if (gc
!= s
->face
->gc
)
783 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (s
->f
);
786 XGetGCValues (s
->display
, gc
, GCFont
, &xgcv
);
787 if (xgcv
.font
!= xfont
->fid
)
788 XSetFont (s
->display
, gc
, xfont
->fid
);
792 if (xfont
->min_byte1
== 0 && xfont
->max_byte1
== 0)
797 SAFE_ALLOCA (str
, char *, len
);
798 for (i
= 0; i
< len
; i
++)
799 str
[i
] = XCHAR2B_BYTE2 (s
->char2b
+ from
+ i
);
801 if (with_background
> 0)
804 for (i
= 0; i
< len
; i
++)
805 XDrawImageString (FRAME_X_DISPLAY (s
->f
), FRAME_X_WINDOW (s
->f
),
806 gc
, x
+ i
, y
, str
+ i
, 1);
808 XDrawImageString (FRAME_X_DISPLAY (s
->f
), FRAME_X_WINDOW (s
->f
),
814 for (i
= 0; i
< len
; i
++)
815 XDrawString (FRAME_X_DISPLAY (s
->f
), FRAME_X_WINDOW (s
->f
),
816 gc
, x
+ i
, y
, str
+ i
, 1);
818 XDrawString (FRAME_X_DISPLAY (s
->f
), FRAME_X_WINDOW (s
->f
),
827 if (with_background
> 0)
830 for (i
= 0; i
< len
; i
++)
831 XDrawImageString16 (FRAME_X_DISPLAY (s
->f
), FRAME_X_WINDOW (s
->f
),
832 gc
, x
+ i
, y
, s
->char2b
+ from
+ i
, 1);
834 XDrawImageString16 (FRAME_X_DISPLAY (s
->f
), FRAME_X_WINDOW (s
->f
),
835 gc
, x
, y
, s
->char2b
+ from
, len
);
840 for (i
= 0; i
< len
; i
++)
841 XDrawString16 (FRAME_X_DISPLAY (s
->f
), FRAME_X_WINDOW (s
->f
),
842 gc
, x
+ i
, y
, s
->char2b
+ from
+ i
, 1);
844 XDrawString16 (FRAME_X_DISPLAY (s
->f
), FRAME_X_WINDOW (s
->f
),
845 gc
, x
, y
, s
->char2b
+ from
, len
);
856 xfont_driver
.type
= Qx
;
857 register_font_driver (&xfont_driver
, NULL
);
860 /* arch-tag: 23c5f366-a5ee-44b7-a3b7-90d6da7fd749
861 (do not change this comment) */