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
*));
54 /* Get metrics of character CHAR2B in XFONT. Value is null if CHAR2B
55 is not contained in the font. */
58 xfont_get_pcm (xfont
, char2b
)
62 /* The result metric information. */
63 XCharStruct
*pcm
= NULL
;
65 font_assert (xfont
&& char2b
);
67 if (xfont
->per_char
!= NULL
)
69 if (xfont
->min_byte1
== 0 && xfont
->max_byte1
== 0)
71 /* min_char_or_byte2 specifies the linear character index
72 corresponding to the first element of the per_char array,
73 max_char_or_byte2 is the index of the last character. A
74 character with non-zero CHAR2B->byte1 is not in the font.
75 A character with byte2 less than min_char_or_byte2 or
76 greater max_char_or_byte2 is not in the font. */
77 if (char2b
->byte1
== 0
78 && char2b
->byte2
>= xfont
->min_char_or_byte2
79 && char2b
->byte2
<= xfont
->max_char_or_byte2
)
80 pcm
= xfont
->per_char
+ char2b
->byte2
- xfont
->min_char_or_byte2
;
84 /* If either min_byte1 or max_byte1 are nonzero, both
85 min_char_or_byte2 and max_char_or_byte2 are less than
86 256, and the 2-byte character index values corresponding
87 to the per_char array element N (counting from 0) are:
89 byte1 = N/D + min_byte1
90 byte2 = N\D + min_char_or_byte2
94 D = max_char_or_byte2 - min_char_or_byte2 + 1
96 \ = integer modulus */
97 if (char2b
->byte1
>= xfont
->min_byte1
98 && char2b
->byte1
<= xfont
->max_byte1
99 && char2b
->byte2
>= xfont
->min_char_or_byte2
100 && char2b
->byte2
<= xfont
->max_char_or_byte2
)
101 pcm
= (xfont
->per_char
102 + ((xfont
->max_char_or_byte2
- xfont
->min_char_or_byte2
+ 1)
103 * (char2b
->byte1
- xfont
->min_byte1
))
104 + (char2b
->byte2
- xfont
->min_char_or_byte2
));
109 /* If the per_char pointer is null, all glyphs between the first
110 and last character indexes inclusive have the same
111 information, as given by both min_bounds and max_bounds. */
112 if (char2b
->byte2
>= xfont
->min_char_or_byte2
113 && char2b
->byte2
<= xfont
->max_char_or_byte2
)
114 pcm
= &xfont
->max_bounds
;
118 || (pcm
->width
== 0 && (pcm
->rbearing
- pcm
->lbearing
) == 0))
122 /* Find a CCL program for a font specified by FONTP, and set the member
123 `encoder' of the structure. */
126 xfont_find_ccl_program (font
)
129 Lisp_Object list
, elt
;
132 for (list
= Vfont_ccl_encoder_alist
; CONSP (list
); list
= XCDR (list
))
136 && STRINGP (XCAR (elt
))
137 && ((fast_string_match_ignore_case (XCAR (elt
),
138 font
->props
[FONT_NAME_INDEX
])
140 || (fast_string_match_ignore_case (XCAR (elt
),
141 font
->props
[FONT_FULLNAME_INDEX
])
148 struct ccl_program
*ccl
149 = (struct ccl_program
*) xmalloc (sizeof (struct ccl_program
));
151 if (setup_ccl_program (ccl
, XCDR (elt
)) < 0)
154 font
->font_encoder
= ccl
;
158 static Lisp_Object xfont_get_cache
P_ ((FRAME_PTR
));
159 static Lisp_Object xfont_list
P_ ((Lisp_Object
, Lisp_Object
));
160 static Lisp_Object xfont_match
P_ ((Lisp_Object
, Lisp_Object
));
161 static Lisp_Object xfont_list_family
P_ ((Lisp_Object
));
162 static Lisp_Object xfont_open
P_ ((FRAME_PTR
, Lisp_Object
, int));
163 static void xfont_close
P_ ((FRAME_PTR
, struct font
*));
164 static int xfont_prepare_face
P_ ((FRAME_PTR
, struct face
*));
165 static int xfont_has_char
P_ ((Lisp_Object
, int));
166 static unsigned xfont_encode_char
P_ ((struct font
*, int));
167 static int xfont_text_extents
P_ ((struct font
*, unsigned *, int,
168 struct font_metrics
*));
169 static int xfont_draw
P_ ((struct glyph_string
*, int, int, int, int, int));
170 static int xfont_check
P_ ((FRAME_PTR
, struct font
*));
172 struct font_driver xfont_driver
=
175 0, /* case insensitive */
189 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
,
193 extern Lisp_Object QCname
;
199 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
201 return (dpyinfo
->name_list_element
);
204 extern Lisp_Object Vface_alternative_font_registry_alist
;
207 compare_font_names (const void *name1
, const void *name2
)
209 return xstrcasecmp (*(const char **) name1
, *(const char **) name2
);
212 static Lisp_Object xfont_list_pattern
P_ ((Lisp_Object
, Display
*, char *));
215 xfont_list_pattern (frame
, display
, pattern
)
220 Lisp_Object list
= Qnil
;
221 int i
, limit
, num_fonts
;
225 x_catch_errors (display
);
227 for (limit
= 512; ; limit
*= 2)
229 names
= XListFonts (display
, pattern
, limit
, &num_fonts
);
230 if (x_had_errors_p (display
))
232 /* This error is perhaps due to insufficient memory on X
233 server. Let's just ignore it. */
234 x_clear_errors (display
);
238 if (num_fonts
< limit
)
240 XFreeFontNames (names
);
245 char **indices
= alloca (sizeof (char *) * num_fonts
);
247 for (i
= 0; i
< num_fonts
; i
++)
248 indices
[i
] = names
[i
];
249 qsort (indices
, num_fonts
, sizeof (char *), compare_font_names
);
251 for (i
= 0; i
< num_fonts
; i
++)
256 if (i
> 0 && xstrcasecmp (indices
[i
- 1], indices
[i
]) == 0)
259 entity
= font_make_entity ();
260 ASET (entity
, FONT_TYPE_INDEX
, Qx
);
262 result
= font_parse_xlfd (indices
[i
], entity
);
265 /* This may be an alias name. Try to get the full XLFD name
266 from XA_FONT property of the font. */
267 XFontStruct
*font
= XLoadQueryFont (display
, indices
[i
]);
272 if (XGetFontProperty (font
, XA_FONT
, &value
))
274 char *name
= (char *) XGetAtomName (display
, (Atom
) value
);
275 int len
= strlen (name
);
277 /* If DXPC (a Differential X Protocol Compressor)
278 Ver.3.7 is running, XGetAtomName will return null
279 string. We must avoid such a name. */
281 result
= font_parse_xlfd (name
, entity
);
284 XFreeFont (display
, font
);
288 /* Avoid auto-scaled fonts. */
289 && (XINT (AREF (entity
, FONT_DPI_INDEX
)) == 0
290 || XINT (AREF (entity
, FONT_AVGWIDTH_INDEX
)) > 0))
291 list
= Fcons (entity
, list
);
293 XFreeFontNames (names
);
299 font_add_log ("xfont-list", build_string (pattern
), list
);
304 xfont_list (frame
, spec
)
305 Lisp_Object frame
, spec
;
307 FRAME_PTR f
= XFRAME (frame
);
308 Display
*display
= FRAME_X_DISPLAY_INFO (f
)->display
;
309 Lisp_Object registry
, list
, val
, extra
;
313 extra
= AREF (spec
, FONT_EXTRA_INDEX
);
316 val
= assq_no_quit (QCotf
, extra
);
319 val
= assq_no_quit (QCscript
, extra
);
322 val
= assq_no_quit (QClang
, extra
);
327 registry
= AREF (spec
, FONT_REGISTRY_INDEX
);
329 ASET (spec
, FONT_REGISTRY_INDEX
, Qiso8859_1
);
330 len
= font_unparse_xlfd (spec
, 0, name
, 256);
331 ASET (spec
, FONT_REGISTRY_INDEX
, registry
);
334 list
= xfont_list_pattern (frame
, display
, name
);
335 if (NILP (list
) && NILP (registry
))
338 char *r
= name
+ len
- 9; /* 9 == strlen (iso8859-1) */
340 if (r
- name
+ 10 < 256) /* 10 == strlen (iso10646-1) */
342 strcpy (r
, "iso10646-1");
343 list
= xfont_list_pattern (frame
, display
, name
);
346 if (NILP (list
) && ! NILP (registry
))
350 if ((alter
= Fassoc (SYMBOL_NAME (registry
),
351 Vface_alternative_font_registry_alist
),
354 /* Pointer to REGISTRY-ENCODING field. */
355 char *r
= name
+ len
- SBYTES (SYMBOL_NAME (registry
));
357 for (alter
= XCDR (alter
); CONSP (alter
); alter
= XCDR (alter
))
358 if (STRINGP (XCAR (alter
))
359 && ((r
- name
) + SBYTES (XCAR (alter
))) < 256)
361 strcpy (r
, (char *) SDATA (XCAR (alter
)));
362 list
= xfont_list_pattern (frame
, display
, name
);
373 xfont_match (frame
, spec
)
374 Lisp_Object frame
, spec
;
376 FRAME_PTR f
= XFRAME (frame
);
377 Display
*display
= FRAME_X_DISPLAY_INFO (f
)->display
;
378 Lisp_Object extra
, val
, entity
;
379 char buf
[256], *name
;
383 extra
= AREF (spec
, FONT_EXTRA_INDEX
);
384 val
= assq_no_quit (QCname
, extra
);
385 if (! CONSP (val
) || ! STRINGP (XCDR (val
)))
387 if (font_unparse_xlfd (spec
, 0, buf
, 256) < 0)
392 name
= (char *) SDATA (XCDR (val
));
396 xfont
= XLoadQueryFont (display
, name
);
399 if (XGetFontProperty (xfont
, XA_FONT
, &value
))
403 name
= (char *) XGetAtomName (display
, (Atom
) value
);
406 /* If DXPC (a Differential X Protocol Compressor)
407 Ver.3.7 is running, XGetAtomName will return null
408 string. We must avoid such a name. */
411 entity
= font_make_entity ();
412 ASET (entity
, FONT_TYPE_INDEX
, Qx
);
413 if (font_parse_xlfd (name
, entity
) < 0)
418 XFreeFont (display
, xfont
);
422 font_add_log ("xfont-match", spec
, entity
);
427 xfont_list_family (frame
)
430 FRAME_PTR f
= XFRAME (frame
);
431 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
439 x_catch_errors (dpyinfo
->display
);
440 names
= XListFonts (dpyinfo
->display
, "-*-*-*-*-*-*-*-*-*-*-*-*-*-*",
442 if (x_had_errors_p (dpyinfo
->display
))
444 /* This error is perhaps due to insufficient memory on X server.
445 Let's just ignore it. */
446 x_clear_errors (dpyinfo
->display
);
451 for (i
= 0, last_len
= 0; i
< num_fonts
; i
++)
453 char *p0
= names
[i
], *p1
;
456 p0
++; /* skip the leading '-' */
457 while (*p0
&& *p0
!= '-') p0
++; /* skip foundry */
461 while (*p1
&& *p1
!= '-') p1
++; /* find the end of family */
462 if (! *p1
|| p1
== p0
)
464 if (last_len
== p1
- p0
465 && bcmp (last_family
, p0
, last_len
) == 0)
469 family
= make_unibyte_string (p0
, last_len
);
470 if (NILP (Fassoc_string (family
, list
, Qt
)))
471 list
= Fcons (family
, list
);
474 XFreeFontNames (names
);
481 extern Lisp_Object QCavgwidth
;
484 xfont_open (f
, entity
, pixel_size
)
489 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
490 Display
*display
= dpyinfo
->display
;
494 Lisp_Object registry
;
495 struct charset
*encoding
, *repertory
;
496 Lisp_Object font_object
, fullname
;
501 /* At first, check if we know how to encode characters for this
503 registry
= AREF (entity
, FONT_REGISTRY_INDEX
);
504 if (font_registry_charsets (registry
, &encoding
, &repertory
) < 0)
507 if (XINT (AREF (entity
, FONT_SIZE_INDEX
)) != 0)
508 pixel_size
= XINT (AREF (entity
, FONT_SIZE_INDEX
));
509 else if (pixel_size
== 0)
512 pixel_size
= FRAME_FONT (f
)->pixel_size
;
516 len
= font_unparse_xlfd (entity
, pixel_size
, name
, 256);
521 x_catch_errors (display
);
522 xfont
= XLoadQueryFont (display
, name
);
523 if (x_had_errors_p (display
))
525 /* This error is perhaps due to insufficient memory on X server.
526 Let's just ignore it. */
527 x_clear_errors (display
);
531 /* Try to get the full name of FONT. */
532 if (xfont
&& XGetFontProperty (xfont
, XA_FONT
, &value
))
537 p0
= p
= (char *) XGetAtomName (FRAME_X_DISPLAY (f
), (Atom
) value
);;
538 /* Count the number of dashes in the "full name".
539 If it is too few, this isn't really the font's full name,
541 In X11R4, the fonts did not come with their canonical names
551 fullname
= Fdowncase (make_unibyte_string (p0
, p
- p0
));
560 font_object
= font_make_object (VECSIZE (struct xfont_info
));
561 ASET (font_object
, FONT_TYPE_INDEX
, Qx
);
562 if (STRINGP (fullname
))
563 font_parse_xlfd ((char *) SDATA (fullname
), font_object
);
564 for (i
= 1; i
< FONT_ENTITY_MAX
; i
++)
565 ASET (font_object
, i
, AREF (entity
, i
));
566 ASET (font_object
, FONT_SIZE_INDEX
, make_number (pixel_size
));
567 if (STRINGP (fullname
))
568 ASET (font_object
, FONT_NAME_INDEX
, fullname
);
570 ASET (font_object
, FONT_NAME_INDEX
, make_unibyte_string (name
, len
));
571 ASET (font_object
, FONT_FULLNAME_INDEX
, fullname
);
572 ASET (font_object
, FONT_FILE_INDEX
, Qnil
);
573 ASET (font_object
, FONT_FORMAT_INDEX
, Qx
);
574 font
= XFONT_OBJECT (font_object
);
575 ((struct xfont_info
*) font
)->xfont
= xfont
;
576 ((struct xfont_info
*) font
)->display
= FRAME_X_DISPLAY (f
);
577 font
->pixel_size
= pixel_size
;
578 font
->driver
= &xfont_driver
;
579 font
->encoding_charset
= encoding
->id
;
580 font
->repertory_charset
= repertory
? repertory
->id
: -1;
581 font
->ascent
= xfont
->ascent
;
582 font
->descent
= xfont
->descent
;
583 font
->height
= font
->ascent
+ font
->descent
;
584 font
->min_width
= xfont
->min_bounds
.width
;
585 if (xfont
->min_bounds
.width
== xfont
->max_bounds
.width
)
587 /* Fixed width font. */
588 font
->average_width
= font
->space_width
= xfont
->min_bounds
.width
;
596 char2b
.byte1
= 0x00, char2b
.byte2
= 0x20;
597 pcm
= xfont_get_pcm (xfont
, &char2b
);
599 font
->space_width
= pcm
->width
;
601 font
->space_width
= 0;
603 val
= Ffont_get (font_object
, QCavgwidth
);
605 font
->average_width
= XINT (val
);
606 if (font
->average_width
< 0)
607 font
->average_width
= - font
->average_width
;
608 if (font
->average_width
== 0
609 && encoding
->ascii_compatible_p
)
611 int width
= font
->space_width
, n
= pcm
!= NULL
;
613 for (char2b
.byte2
= 33; char2b
.byte2
<= 126; char2b
.byte2
++)
614 if ((pcm
= xfont_get_pcm (xfont
, &char2b
)) != NULL
)
615 width
+= pcm
->width
, n
++;
617 font
->average_width
= width
/ n
;
619 if (font
->average_width
== 0)
620 /* No easy way other than this to get a reasonable
623 = (xfont
->min_bounds
.width
+ xfont
->max_bounds
.width
) / 2;
627 font
->underline_thickness
628 = (XGetFontProperty (xfont
, XA_UNDERLINE_THICKNESS
, &value
)
630 font
->underline_position
631 = (XGetFontProperty (xfont
, XA_UNDERLINE_POSITION
, &value
)
632 ? (long) value
: -1);
633 font
->baseline_offset
634 = (XGetFontProperty (xfont
, dpyinfo
->Xatom_MULE_BASELINE_OFFSET
, &value
)
636 font
->relative_compose
637 = (XGetFontProperty (xfont
, dpyinfo
->Xatom_MULE_RELATIVE_COMPOSE
, &value
)
640 = (XGetFontProperty (xfont
, dpyinfo
->Xatom_MULE_DEFAULT_ASCENT
, &value
)
645 fullname
= AREF (font_object
, FONT_NAME_INDEX
);
646 font
->vertical_centering
647 = (STRINGP (Vvertical_centering_font_regexp
)
648 && (fast_string_match_ignore_case
649 (Vvertical_centering_font_regexp
, fullname
) >= 0));
655 xfont_close (f
, font
)
660 XFreeFont (FRAME_X_DISPLAY (f
), ((struct xfont_info
*) font
)->xfont
);
665 xfont_prepare_face (f
, face
)
670 XSetFont (FRAME_X_DISPLAY (f
), face
->gc
,
671 ((struct xfont_info
*) face
->font
)->xfont
->fid
);
678 xfont_has_char (entity
, c
)
682 Lisp_Object registry
= AREF (entity
, FONT_REGISTRY_INDEX
);
683 struct charset
*repertory
;
685 if (font_registry_charsets (registry
, NULL
, &repertory
) < 0)
689 return (ENCODE_CHAR (repertory
, c
) != CHARSET_INVALID_CODE (repertory
));
693 xfont_encode_char (font
, c
)
697 XFontStruct
*xfont
= ((struct xfont_info
*) font
)->xfont
;
698 struct charset
*charset
;
702 charset
= CHARSET_FROM_ID (font
->encoding_charset
);
703 code
= ENCODE_CHAR (charset
, c
);
704 if (code
== CHARSET_INVALID_CODE (charset
))
705 return FONT_INVALID_CODE
;
706 if (font
->repertory_charset
>= 0)
708 charset
= CHARSET_FROM_ID (font
->repertory_charset
);
709 return (ENCODE_CHAR (charset
, c
) != CHARSET_INVALID_CODE (charset
)
710 ? code
: FONT_INVALID_CODE
);
712 char2b
.byte1
= code
>> 8;
713 char2b
.byte2
= code
& 0xFF;
714 return (xfont_get_pcm (xfont
, &char2b
) ? code
: FONT_INVALID_CODE
);
718 xfont_text_extents (font
, code
, nglyphs
, metrics
)
722 struct font_metrics
*metrics
;
724 XFontStruct
*xfont
= ((struct xfont_info
*) font
)->xfont
;
729 bzero (metrics
, sizeof (struct font_metrics
));
730 for (i
= 0, x
= 0; i
< nglyphs
; i
++)
733 static XCharStruct
*pcm
;
735 if (code
[i
] >= 0x10000)
737 char2b
.byte1
= code
[i
] >> 8, char2b
.byte2
= code
[i
] & 0xFF;
738 pcm
= xfont_get_pcm (xfont
, &char2b
);
741 if (metrics
->lbearing
> width
+ pcm
->lbearing
)
742 metrics
->lbearing
= width
+ pcm
->lbearing
;
743 if (metrics
->rbearing
< width
+ pcm
->rbearing
)
744 metrics
->rbearing
= width
+ pcm
->rbearing
;
745 if (metrics
->ascent
< pcm
->ascent
)
746 metrics
->ascent
= pcm
->ascent
;
747 if (metrics
->descent
< pcm
->descent
)
748 metrics
->descent
= pcm
->descent
;
752 metrics
->width
= width
;
757 xfont_draw (s
, from
, to
, x
, y
, with_background
)
758 struct glyph_string
*s
;
759 int from
, to
, x
, y
, with_background
;
761 XFontStruct
*xfont
= ((struct xfont_info
*) s
->font
)->xfont
;
766 if (s
->gc
!= s
->face
->gc
)
769 XSetFont (s
->display
, gc
, xfont
->fid
);
773 if (xfont
->min_byte1
== 0 && xfont
->max_byte1
== 0)
778 SAFE_ALLOCA (str
, char *, len
);
779 for (i
= 0; i
< len
; i
++)
780 str
[i
] = XCHAR2B_BYTE2 (s
->char2b
+ from
+ i
);
782 if (with_background
> 0)
785 for (i
= 0; i
< len
; i
++)
786 XDrawImageString (FRAME_X_DISPLAY (s
->f
), FRAME_X_WINDOW (s
->f
),
787 gc
, x
+ i
, y
, str
+ i
, 1);
789 XDrawImageString (FRAME_X_DISPLAY (s
->f
), FRAME_X_WINDOW (s
->f
),
795 for (i
= 0; i
< len
; i
++)
796 XDrawString (FRAME_X_DISPLAY (s
->f
), FRAME_X_WINDOW (s
->f
),
797 gc
, x
+ i
, y
, str
+ i
, 1);
799 XDrawString (FRAME_X_DISPLAY (s
->f
), FRAME_X_WINDOW (s
->f
),
808 if (with_background
> 0)
811 for (i
= 0; i
< len
; i
++)
812 XDrawImageString16 (FRAME_X_DISPLAY (s
->f
), FRAME_X_WINDOW (s
->f
),
813 gc
, x
+ i
, y
, s
->char2b
+ from
+ i
, 1);
815 XDrawImageString16 (FRAME_X_DISPLAY (s
->f
), FRAME_X_WINDOW (s
->f
),
816 gc
, x
, y
, s
->char2b
+ from
, len
);
821 for (i
= 0; i
< len
; i
++)
822 XDrawString16 (FRAME_X_DISPLAY (s
->f
), FRAME_X_WINDOW (s
->f
),
823 gc
, x
+ i
, y
, s
->char2b
+ from
+ i
, 1);
825 XDrawString16 (FRAME_X_DISPLAY (s
->f
), FRAME_X_WINDOW (s
->f
),
826 gc
, x
, y
, s
->char2b
+ from
, len
);
834 xfont_check (f
, font
)
838 struct xfont_info
*xfont
= (struct xfont_info
*) font
;
840 return (FRAME_X_DISPLAY (f
) == xfont
->display
? 0 : -1);
847 xfont_driver
.type
= Qx
;
848 register_font_driver (&xfont_driver
, NULL
);
851 /* arch-tag: 23c5f366-a5ee-44b7-a3b7-90d6da7fd749
852 (do not change this comment) */