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 of the License, or
12 (at your option) any later version.
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. If not, see <http://www.gnu.org/licenses/>. */
28 #include "dispextern.h"
31 #include "blockinput.h"
32 #include "character.h"
39 /* X core font driver. */
48 /* Prototypes of support functions. */
49 extern void x_clear_errors
P_ ((Display
*));
51 static XCharStruct
*xfont_get_pcm
P_ ((XFontStruct
*, XChar2b
*));
52 static void xfont_find_ccl_program
P_ ((struct font
*));
53 static int xfont_registry_charsets
P_ ((Lisp_Object
, struct charset
**,
57 /* Get metrics of character CHAR2B in XFONT. Value is null if CHAR2B
58 is not contained in the font. */
61 xfont_get_pcm (xfont
, char2b
)
65 /* The result metric information. */
66 XCharStruct
*pcm
= NULL
;
68 xassert (xfont
&& char2b
);
70 if (xfont
->per_char
!= NULL
)
72 if (xfont
->min_byte1
== 0 && xfont
->max_byte1
== 0)
74 /* min_char_or_byte2 specifies the linear character index
75 corresponding to the first element of the per_char array,
76 max_char_or_byte2 is the index of the last character. A
77 character with non-zero CHAR2B->byte1 is not in the font.
78 A character with byte2 less than min_char_or_byte2 or
79 greater max_char_or_byte2 is not in the font. */
80 if (char2b
->byte1
== 0
81 && char2b
->byte2
>= xfont
->min_char_or_byte2
82 && char2b
->byte2
<= xfont
->max_char_or_byte2
)
83 pcm
= xfont
->per_char
+ char2b
->byte2
- xfont
->min_char_or_byte2
;
87 /* If either min_byte1 or max_byte1 are nonzero, both
88 min_char_or_byte2 and max_char_or_byte2 are less than
89 256, and the 2-byte character index values corresponding
90 to the per_char array element N (counting from 0) are:
92 byte1 = N/D + min_byte1
93 byte2 = N\D + min_char_or_byte2
97 D = max_char_or_byte2 - min_char_or_byte2 + 1
99 \ = integer modulus */
100 if (char2b
->byte1
>= xfont
->min_byte1
101 && char2b
->byte1
<= xfont
->max_byte1
102 && char2b
->byte2
>= xfont
->min_char_or_byte2
103 && char2b
->byte2
<= xfont
->max_char_or_byte2
)
104 pcm
= (xfont
->per_char
105 + ((xfont
->max_char_or_byte2
- xfont
->min_char_or_byte2
+ 1)
106 * (char2b
->byte1
- xfont
->min_byte1
))
107 + (char2b
->byte2
- xfont
->min_char_or_byte2
));
112 /* If the per_char pointer is null, all glyphs between the first
113 and last character indexes inclusive have the same
114 information, as given by both min_bounds and max_bounds. */
115 if (char2b
->byte2
>= xfont
->min_char_or_byte2
116 && char2b
->byte2
<= xfont
->max_char_or_byte2
)
117 pcm
= &xfont
->max_bounds
;
121 || (pcm
->width
== 0 && (pcm
->rbearing
- pcm
->lbearing
) == 0))
125 /* Find a CCL program for a font specified by FONTP, and set the member
126 `encoder' of the structure. */
129 xfont_find_ccl_program (font
)
132 Lisp_Object list
, elt
;
135 for (list
= Vfont_ccl_encoder_alist
; CONSP (list
); list
= XCDR (list
))
139 && STRINGP (XCAR (elt
))
140 && ((fast_string_match_ignore_case (XCAR (elt
),
141 font
->props
[FONT_NAME_INDEX
])
143 || (fast_string_match_ignore_case (XCAR (elt
),
144 font
->props
[FONT_FULLNAME_INDEX
])
151 struct ccl_program
*ccl
152 = (struct ccl_program
*) xmalloc (sizeof (struct ccl_program
));
154 if (setup_ccl_program (ccl
, XCDR (elt
)) < 0)
157 font
->font_encoder
= ccl
;
161 static Lisp_Object xfont_get_cache
P_ ((FRAME_PTR
));
162 static Lisp_Object xfont_list
P_ ((Lisp_Object
, Lisp_Object
));
163 static Lisp_Object xfont_match
P_ ((Lisp_Object
, Lisp_Object
));
164 static Lisp_Object xfont_list_family
P_ ((Lisp_Object
));
165 static Lisp_Object xfont_open
P_ ((FRAME_PTR
, Lisp_Object
, int));
166 static void xfont_close
P_ ((FRAME_PTR
, struct font
*));
167 static int xfont_prepare_face
P_ ((FRAME_PTR
, struct face
*));
168 static int xfont_has_char
P_ ((Lisp_Object
, int));
169 static unsigned xfont_encode_char
P_ ((struct font
*, int));
170 static int xfont_text_extents
P_ ((struct font
*, unsigned *, int,
171 struct font_metrics
*));
172 static int xfont_draw
P_ ((struct glyph_string
*, int, int, int, int, int));
173 static int xfont_check
P_ ((FRAME_PTR
, struct font
*));
175 struct font_driver xfont_driver
=
178 0, /* case insensitive */
192 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
,
196 extern Lisp_Object QCname
;
202 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
204 return (dpyinfo
->name_list_element
);
207 extern Lisp_Object Vface_alternative_font_registry_alist
;
210 compare_font_names (const void *name1
, const void *name2
)
212 return strcasecmp (*(const char **) name1
, *(const char **) name2
);
215 static Lisp_Object xfont_list_pattern
P_ ((Lisp_Object
, Display
*, char *));
218 xfont_list_pattern (frame
, display
, pattern
)
223 Lisp_Object list
= Qnil
;
224 int i
, limit
, num_fonts
;
228 x_catch_errors (display
);
230 for (limit
= 512; ; limit
*= 2)
232 names
= XListFonts (display
, pattern
, limit
, &num_fonts
);
233 if (x_had_errors_p (display
))
235 /* This error is perhaps due to insufficient memory on X
236 server. Let's just ignore it. */
237 x_clear_errors (display
);
241 if (num_fonts
< limit
)
243 XFreeFontNames (names
);
248 char **indices
= alloca (sizeof (char *) * num_fonts
);
250 for (i
= 0; i
< num_fonts
; i
++)
251 indices
[i
] = names
[i
];
252 qsort (indices
, num_fonts
, sizeof (char *), compare_font_names
);
254 for (i
= 0; i
< num_fonts
; i
++)
259 if (i
> 0 && strcasecmp (indices
[i
- 1], indices
[i
]) == 0)
262 entity
= font_make_entity ();
263 ASET (entity
, FONT_TYPE_INDEX
, Qx
);
265 result
= font_parse_xlfd (indices
[i
], entity
);
268 /* This may be an alias name. Try to get the full XLFD name
269 from XA_FONT property of the font. */
270 XFontStruct
*font
= XLoadQueryFont (display
, indices
[i
]);
275 if (XGetFontProperty (font
, XA_FONT
, &value
))
277 char *name
= (char *) XGetAtomName (display
, (Atom
) value
);
278 int len
= strlen (name
);
280 /* If DXPC (a Differential X Protocol Compressor)
281 Ver.3.7 is running, XGetAtomName will return null
282 string. We must avoid such a name. */
284 result
= font_parse_xlfd (name
, entity
);
287 XFreeFont (display
, font
);
291 /* Avoid auto-scaled fonts. */
292 && (XINT (AREF (entity
, FONT_DPI_INDEX
)) == 0
293 || XINT (AREF (entity
, FONT_AVGWIDTH_INDEX
)) > 0))
294 list
= Fcons (entity
, list
);
305 xfont_list (frame
, spec
)
306 Lisp_Object frame
, spec
;
308 FRAME_PTR f
= XFRAME (frame
);
309 Display
*display
= FRAME_X_DISPLAY_INFO (f
)->display
;
310 Lisp_Object registry
, list
, val
, extra
, font_name
;
311 Lisp_Object dpi
, avgwidth
;
315 extra
= AREF (spec
, FONT_EXTRA_INDEX
);
318 val
= assq_no_quit (QCotf
, extra
);
321 val
= assq_no_quit (QCscript
, extra
);
324 val
= assq_no_quit (QClang
, extra
);
329 registry
= AREF (spec
, FONT_REGISTRY_INDEX
);
331 ASET (spec
, FONT_REGISTRY_INDEX
, Qiso8859_1
);
332 len
= font_unparse_xlfd (spec
, 0, name
, 256);
333 ASET (spec
, FONT_REGISTRY_INDEX
, registry
);
336 list
= xfont_list_pattern (frame
, display
, name
);
337 if (NILP (list
) && NILP (registry
))
340 char *r
= name
+ len
- 9; /* 9 == strlen (iso8859-1) */
342 if (r
- name
+ 10 < 256) /* 10 == strlen (iso10646-1) */
344 strcpy (r
, "iso10646-1");
345 list
= xfont_list_pattern (frame
, display
, name
);
348 if (NILP (list
) && ! NILP (registry
))
352 if ((alter
= Fassoc (SYMBOL_NAME (registry
),
353 Vface_alternative_font_registry_alist
),
356 /* Pointer to REGISTRY-ENCODING field. */
357 char *r
= name
+ len
- SBYTES (SYMBOL_NAME (registry
));
359 for (alter
= XCDR (alter
); CONSP (alter
); alter
= XCDR (alter
))
360 if (STRINGP (XCAR (alter
))
361 && ((r
- name
) + SBYTES (XCAR (alter
))) < 256)
363 strcpy (r
, (char *) SDATA (XCAR (alter
)));
364 list
= xfont_list_pattern (frame
, display
, name
);
375 xfont_match (frame
, spec
)
376 Lisp_Object frame
, spec
;
378 FRAME_PTR f
= XFRAME (frame
);
379 Display
*display
= FRAME_X_DISPLAY_INFO (f
)->display
;
380 Lisp_Object extra
, val
, entity
;
381 char buf
[256], *name
;
385 extra
= AREF (spec
, FONT_EXTRA_INDEX
);
386 val
= assq_no_quit (QCname
, extra
);
387 if (! CONSP (val
) || ! STRINGP (XCDR (val
)))
389 if (font_unparse_xlfd (spec
, 0, buf
, 256) < 0)
394 name
= (char *) SDATA (XCDR (val
));
398 xfont
= XLoadQueryFont (display
, name
);
401 if (XGetFontProperty (xfont
, XA_FONT
, &value
))
405 name
= (char *) XGetAtomName (display
, (Atom
) value
);
408 /* If DXPC (a Differential X Protocol Compressor)
409 Ver.3.7 is running, XGetAtomName will return null
410 string. We must avoid such a name. */
413 entity
= font_make_entity ();
414 ASET (entity
, FONT_TYPE_INDEX
, Qx
);
415 if (font_parse_xlfd (name
, entity
) < 0)
420 XFreeFont (display
, xfont
);
428 memq_no_quit (elt
, list
)
429 Lisp_Object elt
, list
;
431 while (CONSP (list
) && ! EQ (XCAR (list
), elt
))
433 return (CONSP (list
));
437 xfont_list_family (frame
)
440 FRAME_PTR f
= XFRAME (frame
);
441 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
449 x_catch_errors (dpyinfo
->display
);
450 names
= XListFonts (dpyinfo
->display
, "-*-*-*-*-*-*-*-*-*-*-*-*-*-*",
452 if (x_had_errors_p (dpyinfo
->display
))
454 /* This error is perhaps due to insufficient memory on X server.
455 Let's just ignore it. */
456 x_clear_errors (dpyinfo
->display
);
461 for (i
= 0, last_len
= 0; i
< num_fonts
; i
++)
463 char *p0
= names
[i
], *p1
;
466 p0
++; /* skip the leading '-' */
467 while (*p0
&& *p0
!= '-') p0
++; /* skip foundry */
471 while (*p1
&& *p1
!= '-') p1
++; /* find the end of family */
472 if (! *p1
|| p1
== p0
)
474 if (last_len
== p1
- p0
475 && bcmp (last_family
, p0
, last_len
) == 0)
479 family
= make_unibyte_string (p0
, last_len
);
480 if (NILP (Fassoc_string (family
, list
, Qt
)))
481 list
= Fcons (family
, list
);
484 XFreeFontNames (names
);
491 extern Lisp_Object QCavgwidth
;
494 xfont_open (f
, entity
, pixel_size
)
499 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
500 Display
*display
= dpyinfo
->display
;
504 Lisp_Object registry
;
505 struct charset
*encoding
, *repertory
;
506 Lisp_Object font_object
, fullname
;
511 /* At first, check if we know how to encode characters for this
513 registry
= AREF (entity
, FONT_REGISTRY_INDEX
);
514 if (font_registry_charsets (registry
, &encoding
, &repertory
) < 0)
517 if (XINT (AREF (entity
, FONT_SIZE_INDEX
)) != 0)
518 pixel_size
= XINT (AREF (entity
, FONT_SIZE_INDEX
));
519 else if (pixel_size
== 0)
522 pixel_size
= FRAME_FONT (f
)->pixel_size
;
526 len
= font_unparse_xlfd (entity
, pixel_size
, name
, 256);
531 x_catch_errors (display
);
532 xfont
= XLoadQueryFont (display
, name
);
533 if (x_had_errors_p (display
))
535 /* This error is perhaps due to insufficient memory on X server.
536 Let's just ignore it. */
537 x_clear_errors (display
);
541 /* Try to get the full name of FONT. */
542 if (xfont
&& XGetFontProperty (xfont
, XA_FONT
, &value
))
547 p0
= p
= (char *) XGetAtomName (FRAME_X_DISPLAY (f
), (Atom
) value
);;
548 /* Count the number of dashes in the "full name".
549 If it is too few, this isn't really the font's full name,
551 In X11R4, the fonts did not come with their canonical names
561 fullname
= Fdowncase (make_unibyte_string (p0
, p
- p0
));
570 font_object
= font_make_object (VECSIZE (struct xfont_info
));
571 ASET (font_object
, FONT_TYPE_INDEX
, Qx
);
572 if (STRINGP (fullname
))
573 font_parse_xlfd (SDATA (fullname
), font_object
);
574 for (i
= 1; i
< FONT_ENTITY_MAX
; i
++)
575 ASET (font_object
, i
, AREF (entity
, i
));
576 ASET (font_object
, FONT_SIZE_INDEX
, make_number (pixel_size
));
577 if (STRINGP (fullname
))
578 ASET (font_object
, FONT_NAME_INDEX
, fullname
);
580 ASET (font_object
, FONT_NAME_INDEX
, make_unibyte_string (name
, len
));
581 ASET (font_object
, FONT_FULLNAME_INDEX
, fullname
);
582 ASET (font_object
, FONT_FILE_INDEX
, Qnil
);
583 ASET (font_object
, FONT_FORMAT_INDEX
, Qx
);
584 font
= XFONT_OBJECT (font_object
);
585 ((struct xfont_info
*) font
)->xfont
= xfont
;
586 ((struct xfont_info
*) font
)->display
= FRAME_X_DISPLAY (f
);
587 font
->pixel_size
= pixel_size
;
588 font
->driver
= &xfont_driver
;
589 font
->encoding_charset
= encoding
->id
;
590 font
->repertory_charset
= repertory
? repertory
->id
: -1;
591 font
->ascent
= xfont
->ascent
;
592 font
->descent
= xfont
->descent
;
593 font
->height
= font
->ascent
+ font
->descent
;
594 font
->min_width
= xfont
->min_bounds
.width
;
595 if (xfont
->min_bounds
.width
== xfont
->max_bounds
.width
)
597 /* Fixed width font. */
598 font
->average_width
= font
->space_width
= xfont
->min_bounds
.width
;
606 char2b
.byte1
= 0x00, char2b
.byte2
= 0x20;
607 pcm
= xfont_get_pcm (xfont
, &char2b
);
609 font
->space_width
= pcm
->width
;
611 font
->space_width
= 0;
613 val
= Ffont_get (font_object
, QCavgwidth
);
615 font
->average_width
= XINT (val
);
616 if (font
->average_width
< 0)
617 font
->average_width
= - font
->average_width
;
618 if (font
->average_width
== 0
619 && encoding
->ascii_compatible_p
)
621 int width
= font
->space_width
, n
= pcm
!= NULL
;
623 for (char2b
.byte2
= 33; char2b
.byte2
<= 126; char2b
.byte2
++)
624 if ((pcm
= xfont_get_pcm (xfont
, &char2b
)) != NULL
)
625 width
+= pcm
->width
, n
++;
626 font
->average_width
= width
/ n
;
631 font
->underline_thickness
632 = (XGetFontProperty (xfont
, XA_UNDERLINE_THICKNESS
, &value
)
634 font
->underline_position
635 = (XGetFontProperty (xfont
, XA_UNDERLINE_POSITION
, &value
)
636 ? (long) value
: -1);
637 font
->baseline_offset
638 = (XGetFontProperty (xfont
, dpyinfo
->Xatom_MULE_BASELINE_OFFSET
, &value
)
640 font
->relative_compose
641 = (XGetFontProperty (xfont
, dpyinfo
->Xatom_MULE_RELATIVE_COMPOSE
, &value
)
644 = (XGetFontProperty (xfont
, dpyinfo
->Xatom_MULE_DEFAULT_ASCENT
, &value
)
649 fullname
= AREF (font_object
, FONT_NAME_INDEX
);
650 font
->vertical_centering
651 = (STRINGP (Vvertical_centering_font_regexp
)
652 && (fast_string_match_ignore_case
653 (Vvertical_centering_font_regexp
, fullname
) >= 0));
659 xfont_close (f
, font
)
664 XFreeFont (FRAME_X_DISPLAY (f
), ((struct xfont_info
*) font
)->xfont
);
669 xfont_prepare_face (f
, face
)
674 XSetFont (FRAME_X_DISPLAY (f
), face
->gc
,
675 ((struct xfont_info
*) face
->font
)->xfont
->fid
);
682 xfont_has_char (entity
, c
)
686 Lisp_Object registry
= AREF (entity
, FONT_REGISTRY_INDEX
);
687 struct charset
*repertory
;
689 if (font_registry_charsets (registry
, NULL
, &repertory
) < 0)
693 return (ENCODE_CHAR (repertory
, c
) != CHARSET_INVALID_CODE (repertory
));
697 xfont_encode_char (font
, c
)
701 XFontStruct
*xfont
= ((struct xfont_info
*) font
)->xfont
;
702 struct charset
*charset
;
706 charset
= CHARSET_FROM_ID (font
->encoding_charset
);
707 code
= ENCODE_CHAR (charset
, c
);
708 if (code
== CHARSET_INVALID_CODE (charset
))
709 return FONT_INVALID_CODE
;
710 if (font
->repertory_charset
>= 0)
712 charset
= CHARSET_FROM_ID (font
->repertory_charset
);
713 return (ENCODE_CHAR (charset
, c
) != CHARSET_INVALID_CODE (charset
)
714 ? code
: FONT_INVALID_CODE
);
716 char2b
.byte1
= code
>> 8;
717 char2b
.byte2
= code
& 0xFF;
718 return (xfont_get_pcm (xfont
, &char2b
) ? code
: FONT_INVALID_CODE
);
722 xfont_text_extents (font
, code
, nglyphs
, metrics
)
726 struct font_metrics
*metrics
;
728 XFontStruct
*xfont
= ((struct xfont_info
*) font
)->xfont
;
733 bzero (metrics
, sizeof (struct font_metrics
));
734 for (i
= 0, x
= 0; i
< nglyphs
; i
++)
737 static XCharStruct
*pcm
;
739 if (code
[i
] >= 0x10000)
741 char2b
.byte1
= code
[i
] >> 8, char2b
.byte2
= code
[i
] & 0xFF;
742 pcm
= xfont_get_pcm (xfont
, &char2b
);
745 if (metrics
->lbearing
> width
+ pcm
->lbearing
)
746 metrics
->lbearing
= width
+ pcm
->lbearing
;
747 if (metrics
->rbearing
< width
+ pcm
->rbearing
)
748 metrics
->rbearing
= width
+ pcm
->rbearing
;
749 if (metrics
->ascent
< pcm
->ascent
)
750 metrics
->ascent
= pcm
->ascent
;
751 if (metrics
->descent
< pcm
->descent
)
752 metrics
->descent
= pcm
->descent
;
756 metrics
->width
= width
;
761 xfont_draw (s
, from
, to
, x
, y
, with_background
)
762 struct glyph_string
*s
;
763 int from
, to
, x
, y
, with_background
;
765 XFontStruct
*xfont
= ((struct xfont_info
*) s
->font
)->xfont
;
770 if (s
->gc
!= s
->face
->gc
)
773 XSetFont (s
->display
, gc
, xfont
->fid
);
777 if (xfont
->min_byte1
== 0 && xfont
->max_byte1
== 0)
782 SAFE_ALLOCA (str
, char *, len
);
783 for (i
= 0; i
< len
; i
++)
784 str
[i
] = XCHAR2B_BYTE2 (s
->char2b
+ from
+ i
);
786 if (with_background
> 0)
789 for (i
= 0; i
< len
; i
++)
790 XDrawImageString (FRAME_X_DISPLAY (s
->f
), FRAME_X_WINDOW (s
->f
),
791 gc
, x
+ i
, y
, str
+ i
, 1);
793 XDrawImageString (FRAME_X_DISPLAY (s
->f
), FRAME_X_WINDOW (s
->f
),
799 for (i
= 0; i
< len
; i
++)
800 XDrawString (FRAME_X_DISPLAY (s
->f
), FRAME_X_WINDOW (s
->f
),
801 gc
, x
+ i
, y
, str
+ i
, 1);
803 XDrawString (FRAME_X_DISPLAY (s
->f
), FRAME_X_WINDOW (s
->f
),
812 if (with_background
> 0)
815 for (i
= 0; i
< len
; i
++)
816 XDrawImageString16 (FRAME_X_DISPLAY (s
->f
), FRAME_X_WINDOW (s
->f
),
817 gc
, x
+ i
, y
, s
->char2b
+ from
+ i
, 1);
819 XDrawImageString16 (FRAME_X_DISPLAY (s
->f
), FRAME_X_WINDOW (s
->f
),
820 gc
, x
, y
, s
->char2b
+ from
, len
);
825 for (i
= 0; i
< len
; i
++)
826 XDrawString16 (FRAME_X_DISPLAY (s
->f
), FRAME_X_WINDOW (s
->f
),
827 gc
, x
+ i
, y
, s
->char2b
+ from
+ i
, 1);
829 XDrawString16 (FRAME_X_DISPLAY (s
->f
), FRAME_X_WINDOW (s
->f
),
830 gc
, x
, y
, s
->char2b
+ from
, len
);
838 xfont_check (f
, font
)
842 struct xfont_info
*xfont
= (struct xfont_info
*) font
;
844 return (FRAME_X_DISPLAY (f
) == xfont
->display
? 0 : -1);
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) */