1 /* xfont.c -- X core font driver.
2 Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
3 Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011
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/>. */
29 #include "dispextern.h"
32 #include "blockinput.h"
33 #include "character.h"
40 /* X core font driver. */
49 /* Prototypes of support functions. */
50 extern void x_clear_errors
P_ ((Display
*));
52 static XCharStruct
*xfont_get_pcm
P_ ((XFontStruct
*, XChar2b
*));
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 static Lisp_Object xfont_get_cache
P_ ((FRAME_PTR
));
123 static Lisp_Object xfont_list
P_ ((Lisp_Object
, Lisp_Object
));
124 static Lisp_Object xfont_match
P_ ((Lisp_Object
, Lisp_Object
));
125 static Lisp_Object xfont_list_family
P_ ((Lisp_Object
));
126 static Lisp_Object xfont_open
P_ ((FRAME_PTR
, Lisp_Object
, int));
127 static void xfont_close
P_ ((FRAME_PTR
, struct font
*));
128 static int xfont_prepare_face
P_ ((FRAME_PTR
, struct face
*));
129 static int xfont_has_char
P_ ((Lisp_Object
, int));
130 static unsigned xfont_encode_char
P_ ((struct font
*, int));
131 static int xfont_text_extents
P_ ((struct font
*, unsigned *, int,
132 struct font_metrics
*));
133 static int xfont_draw
P_ ((struct glyph_string
*, int, int, int, int, int));
134 static int xfont_check
P_ ((FRAME_PTR
, struct font
*));
136 struct font_driver xfont_driver
=
139 0, /* case insensitive */
153 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
,
155 NULL
, /* get_variation_glyphs */
156 NULL
, /* filter_properties */
159 extern Lisp_Object QCname
;
165 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
167 return (dpyinfo
->name_list_element
);
170 extern Lisp_Object Vface_alternative_font_registry_alist
;
173 compare_font_names (const void *name1
, const void *name2
)
175 return xstrcasecmp (*(const unsigned char **) name1
,
176 *(const unsigned char **) name2
);
179 /* Decode XLFD as iso-8859-1 into OUTPUT, and return the byte length
180 of the decoding result. LEN is the byte length of XLFD, or -1 if
181 XLFD is NULL terminated. The caller must assure that OUTPUT is at
182 least twice (plus 1) as large as XLFD. */
185 xfont_decode_coding_xlfd (char *xlfd
, int len
, char *output
)
187 char *p0
= xlfd
, *p1
= output
;
192 c
= *(unsigned char *) p0
++;
193 p1
+= CHAR_STRING (c
, p1
);
198 return (p1
- output
);
201 /* Encode XLFD from UTF-8 to iso-8859-1 destructively, and return the
202 resulting byte length. If XLFD contains unencodable character,
206 xfont_encode_coding_xlfd (char *xlfd
)
208 const unsigned char *p0
= (unsigned char *) xlfd
;
209 unsigned char *p1
= (unsigned char *) xlfd
;
214 int c
= STRING_CHAR_ADVANCE (p0
);
225 /* Check if CHARS (cons or vector) is supported by XFONT whose
226 encoding charset is ENCODING (XFONT is NULL) or by a font whose
227 registry corresponds to ENCODING and REPERTORY.
228 Return 1 if supported, return 0 otherwise. */
231 xfont_chars_supported (Lisp_Object chars
, XFontStruct
*xfont
,
232 struct charset
*encoding
, struct charset
*repertory
)
234 struct charset
*charset
= repertory
? repertory
: encoding
;
238 for (; CONSP (chars
); chars
= XCDR (chars
))
240 int c
= XINT (XCAR (chars
));
241 unsigned code
= ENCODE_CHAR (charset
, c
);
244 if (code
== CHARSET_INVALID_CODE (charset
))
250 char2b
.byte1
= code
>> 8;
251 char2b
.byte2
= code
& 0xFF;
252 if (! xfont_get_pcm (xfont
, &char2b
))
255 return (NILP (chars
));
257 else if (VECTORP (chars
))
261 for (i
= ASIZE (chars
) - 1; i
>= 0; i
--)
263 int c
= XINT (AREF (chars
, i
));
264 unsigned code
= ENCODE_CHAR (charset
, c
);
267 if (code
== CHARSET_INVALID_CODE (charset
))
273 char2b
.byte1
= code
>> 8;
274 char2b
.byte2
= code
& 0xFF;
275 if (xfont_get_pcm (xfont
, &char2b
))
283 /* A hash table recoding which font supports which scritps. Each key
284 is a vector of characteristic font propertis FOUNDRY to WIDTH and
285 ADDSTYLE, and each value is a list of script symbols.
287 We assume that fonts that have the same value in the above
288 properties supports the same set of characters on all displays. */
290 static Lisp_Object xfont_scripts_cache
;
292 /* Re-usable vector to store characteristic font properites. */
293 static Lisp_Object xfont_scratch_props
;
295 extern Lisp_Object Qlatin
;
297 /* Return a list of scripts supported by the font of FONTNAME whose
298 characteristic properties are in PROPS and whose encoding charset
299 is ENCODING. A caller must call BLOCK_INPUT in advance. */
302 xfont_supported_scripts (Display
*display
, char *fontname
, Lisp_Object props
,
303 struct charset
*encoding
)
307 /* Two special cases to avoid opening rather big fonts. */
308 if (EQ (AREF (props
, 2), Qja
))
309 return Fcons (intern ("kana"), Fcons (intern ("han"), Qnil
));
310 if (EQ (AREF (props
, 2), Qko
))
311 return Fcons (intern ("hangul"), Qnil
);
312 scripts
= Fgethash (props
, xfont_scripts_cache
, Qt
);
313 if (EQ (scripts
, Qt
))
319 xfont
= XLoadQueryFont (display
, fontname
);
324 for (val
= Vscript_representative_chars
; CONSP (val
);
326 if (CONSP (XCAR (val
)) && SYMBOLP (XCAR (XCAR (val
))))
328 Lisp_Object script
= XCAR (XCAR (val
));
329 Lisp_Object chars
= XCDR (XCAR (val
));
331 if (xfont_chars_supported (chars
, xfont
, encoding
, NULL
))
332 scripts
= Fcons (script
, scripts
);
335 XFreeFont (display
, xfont
);
337 if (EQ (AREF (props
, 3), Qiso10646_1
)
338 && NILP (Fmemq (Qlatin
, scripts
)))
339 scripts
= Fcons (Qlatin
, scripts
);
340 Fputhash (Fcopy_sequence (props
), scripts
, xfont_scripts_cache
);
345 extern Lisp_Object Vscalable_fonts_allowed
;
348 xfont_list_pattern (Display
*display
, char *pattern
,
349 Lisp_Object registry
, Lisp_Object script
)
351 Lisp_Object list
= Qnil
;
352 Lisp_Object chars
= Qnil
;
353 struct charset
*encoding
, *repertory
= NULL
;
354 int i
, limit
, num_fonts
;
356 /* Large enough to decode the longest XLFD (255 bytes). */
359 if (! NILP (registry
)
360 && font_registry_charsets (registry
, &encoding
, &repertory
) < 0)
361 /* Unknown REGISTRY, not supported. */
365 chars
= assq_no_quit (script
, Vscript_representative_chars
);
367 /* We can't tell whether or not a font supports SCRIPT. */
369 chars
= XCDR (chars
);
372 if (! xfont_chars_supported (chars
, NULL
, encoding
, repertory
))
379 x_catch_errors (display
);
381 for (limit
= 512; ; limit
*= 2)
383 names
= XListFonts (display
, pattern
, limit
, &num_fonts
);
384 if (x_had_errors_p (display
))
386 /* This error is perhaps due to insufficient memory on X
387 server. Let's just ignore it. */
388 x_clear_errors (display
);
392 if (num_fonts
< limit
)
394 XFreeFontNames (names
);
399 char **indices
= alloca (sizeof (char *) * num_fonts
);
400 Lisp_Object
*props
= XVECTOR (xfont_scratch_props
)->contents
;
401 Lisp_Object scripts
= Qnil
;
403 for (i
= 0; i
< ASIZE (xfont_scratch_props
); i
++)
405 for (i
= 0; i
< num_fonts
; i
++)
406 indices
[i
] = names
[i
];
407 qsort (indices
, num_fonts
, sizeof (char *), compare_font_names
);
409 for (i
= 0; i
< num_fonts
; i
++)
413 if (i
> 0 && xstrcasecmp (indices
[i
- 1], indices
[i
]) == 0)
415 entity
= font_make_entity ();
416 xfont_decode_coding_xlfd (indices
[i
], -1, buf
);
417 if (font_parse_xlfd (buf
, entity
) < 0)
419 ASET (entity
, FONT_TYPE_INDEX
, Qx
);
420 /* Avoid auto-scaled fonts. */
421 if (INTEGERP (AREF (entity
, FONT_DPI_INDEX
))
422 && INTEGERP (AREF (entity
, FONT_AVGWIDTH_INDEX
))
423 && XINT (AREF (entity
, FONT_DPI_INDEX
)) != 0
424 && XINT (AREF (entity
, FONT_AVGWIDTH_INDEX
)) == 0)
426 /* Avoid not-allowed scalable fonts. */
427 if (NILP (Vscalable_fonts_allowed
))
431 if (INTEGERP (AREF (entity
, FONT_SIZE_INDEX
)))
432 size
= XINT (AREF (entity
, FONT_SIZE_INDEX
));
433 else if (FLOATP (AREF (entity
, FONT_SIZE_INDEX
)))
434 size
= XFLOAT_DATA (AREF (entity
, FONT_SIZE_INDEX
));
438 else if (CONSP (Vscalable_fonts_allowed
))
440 Lisp_Object tail
, elt
;
442 for (tail
= Vscalable_fonts_allowed
; CONSP (tail
);
447 && fast_c_string_match_ignore_case (elt
, indices
[i
]) >= 0)
454 /* Avoid fonts of invalid registry. */
455 if (NILP (AREF (entity
, FONT_REGISTRY_INDEX
)))
458 /* Update encoding and repertory if necessary. */
459 if (! EQ (registry
, AREF (entity
, FONT_REGISTRY_INDEX
)))
461 registry
= AREF (entity
, FONT_REGISTRY_INDEX
);
462 if (font_registry_charsets (registry
, &encoding
, &repertory
) < 0)
466 /* Unknown REGISTRY, not supported. */
471 || xfont_chars_supported (chars
, NULL
, encoding
, repertory
))
472 list
= Fcons (entity
, list
);
475 if (memcmp (props
, &(AREF (entity
, FONT_FOUNDRY_INDEX
)),
476 sizeof (Lisp_Object
) * 7)
477 || ! EQ (AREF (entity
, FONT_SPACING_INDEX
), props
[7]))
479 memcpy (props
, &(AREF (entity
, FONT_FOUNDRY_INDEX
)),
480 sizeof (Lisp_Object
) * 7);
481 props
[7] = AREF (entity
, FONT_SPACING_INDEX
);
482 scripts
= xfont_supported_scripts (display
, indices
[i
],
483 xfont_scratch_props
, encoding
);
486 || ! NILP (Fmemq (script
, scripts
)))
487 list
= Fcons (entity
, list
);
489 XFreeFontNames (names
);
495 FONT_ADD_LOG ("xfont-list", build_string (pattern
), list
);
500 xfont_list (frame
, spec
)
501 Lisp_Object frame
, spec
;
503 FRAME_PTR f
= XFRAME (frame
);
504 Display
*display
= FRAME_X_DISPLAY_INFO (f
)->display
;
505 Lisp_Object registry
, list
, val
, extra
, script
;
507 /* Large enough to contain the longest XLFD (255 bytes) in UTF-8. */
510 extra
= AREF (spec
, FONT_EXTRA_INDEX
);
513 val
= assq_no_quit (QCotf
, extra
);
516 val
= assq_no_quit (QClang
, extra
);
521 registry
= AREF (spec
, FONT_REGISTRY_INDEX
);
522 len
= font_unparse_xlfd (spec
, 0, name
, 512);
523 if (len
< 0 || (len
= xfont_encode_coding_xlfd (name
)) < 0)
526 val
= assq_no_quit (QCscript
, extra
);
528 list
= xfont_list_pattern (display
, name
, registry
, script
);
529 if (NILP (list
) && NILP (registry
))
532 char *r
= name
+ len
- 9; /* 9 == strlen (iso8859-1) */
534 if (r
- name
+ 10 < 256) /* 10 == strlen (iso10646-1) */
536 strcpy (r
, "iso10646-1");
537 list
= xfont_list_pattern (display
, name
, Qiso10646_1
, script
);
540 if (NILP (list
) && ! NILP (registry
))
542 /* Try alternate registries. */
545 if ((alter
= Fassoc (SYMBOL_NAME (registry
),
546 Vface_alternative_font_registry_alist
),
549 /* Pointer to REGISTRY-ENCODING field. */
550 char *r
= name
+ len
- SBYTES (SYMBOL_NAME (registry
));
552 for (alter
= XCDR (alter
); CONSP (alter
); alter
= XCDR (alter
))
553 if (STRINGP (XCAR (alter
))
554 && ((r
- name
) + SBYTES (XCAR (alter
))) < 256)
556 strcpy (r
, (char *) SDATA (XCAR (alter
)));
557 list
= xfont_list_pattern (display
, name
, registry
, script
);
566 val
= assq_no_quit (QCname
, AREF (spec
, FONT_EXTRA_INDEX
));
567 if (CONSP (val
) && STRINGP (XCDR (val
)) && SBYTES (XCDR (val
)) < 512)
569 bcopy (SDATA (XCDR (val
)), name
, SBYTES (XCDR (val
)) + 1);
570 if (xfont_encode_coding_xlfd (name
) < 0)
572 list
= xfont_list_pattern (display
, name
, registry
, script
);
580 xfont_match (frame
, spec
)
581 Lisp_Object frame
, spec
;
583 FRAME_PTR f
= XFRAME (frame
);
584 Display
*display
= FRAME_X_DISPLAY_INFO (f
)->display
;
585 Lisp_Object extra
, val
, entity
;
590 extra
= AREF (spec
, FONT_EXTRA_INDEX
);
591 val
= assq_no_quit (QCname
, extra
);
592 if (! CONSP (val
) || ! STRINGP (XCDR (val
)))
594 if (font_unparse_xlfd (spec
, 0, name
, 512) < 0)
597 else if (SBYTES (XCDR (val
)) < 512)
598 bcopy (SDATA (XCDR (val
)), name
, SBYTES (XCDR (val
)) + 1);
601 if (xfont_encode_coding_xlfd (name
) < 0)
606 xfont
= XLoadQueryFont (display
, name
);
609 if (XGetFontProperty (xfont
, XA_FONT
, &value
))
614 s
= (char *) XGetAtomName (display
, (Atom
) value
);
617 /* If DXPC (a Differential X Protocol Compressor)
618 Ver.3.7 is running, XGetAtomName will return null
619 string. We must avoid such a name. */
622 entity
= font_make_entity ();
623 ASET (entity
, FONT_TYPE_INDEX
, Qx
);
624 xfont_decode_coding_xlfd (s
, -1, name
);
625 if (font_parse_xlfd (name
, entity
) < 0)
630 XFreeFont (display
, xfont
);
634 FONT_ADD_LOG ("xfont-match", spec
, entity
);
639 xfont_list_family (frame
)
642 FRAME_PTR f
= XFRAME (frame
);
643 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
651 x_catch_errors (dpyinfo
->display
);
652 names
= XListFonts (dpyinfo
->display
, "-*-*-*-*-*-*-*-*-*-*-*-*-*-*",
654 if (x_had_errors_p (dpyinfo
->display
))
656 /* This error is perhaps due to insufficient memory on X server.
657 Let's just ignore it. */
658 x_clear_errors (dpyinfo
->display
);
663 for (i
= 0, last_len
= 0; i
< num_fonts
; i
++)
665 char *p0
= names
[i
], *p1
, buf
[512];
669 p0
++; /* skip the leading '-' */
670 while (*p0
&& *p0
!= '-') p0
++; /* skip foundry */
674 while (*p1
&& *p1
!= '-') p1
++; /* find the end of family */
675 if (! *p1
|| p1
== p0
)
677 if (last_len
== p1
- p0
678 && bcmp (last_family
, p0
, last_len
) == 0)
683 decoded_len
= xfont_decode_coding_xlfd (p0
, last_len
, buf
);
684 family
= font_intern_prop (p0
, decoded_len
, 1);
685 if (NILP (assq_no_quit (family
, list
)))
686 list
= Fcons (family
, list
);
689 XFreeFontNames (names
);
696 extern Lisp_Object QCavgwidth
;
699 xfont_open (f
, entity
, pixel_size
)
704 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
705 Display
*display
= dpyinfo
->display
;
709 Lisp_Object registry
;
710 struct charset
*encoding
, *repertory
;
711 Lisp_Object font_object
, fullname
;
715 /* At first, check if we know how to encode characters for this
717 registry
= AREF (entity
, FONT_REGISTRY_INDEX
);
718 if (font_registry_charsets (registry
, &encoding
, &repertory
) < 0)
720 FONT_ADD_LOG (" x:unknown registry", registry
, Qnil
);
724 if (XINT (AREF (entity
, FONT_SIZE_INDEX
)) != 0)
725 pixel_size
= XINT (AREF (entity
, FONT_SIZE_INDEX
));
726 else if (pixel_size
== 0)
729 pixel_size
= FRAME_FONT (f
)->pixel_size
;
733 len
= font_unparse_xlfd (entity
, pixel_size
, name
, 512);
734 if (len
<= 0 || (len
= xfont_encode_coding_xlfd (name
)) < 0)
736 FONT_ADD_LOG (" x:unparse failed", entity
, Qnil
);
741 x_catch_errors (display
);
742 xfont
= XLoadQueryFont (display
, name
);
743 if (x_had_errors_p (display
))
745 /* This error is perhaps due to insufficient memory on X server.
746 Let's just ignore it. */
747 x_clear_errors (display
);
752 /* Some version of X lists:
753 -misc-fixed-medium-r-normal--20-*-75-75-c-100-iso8859-1
754 -misc-fixed-medium-r-normal--20-*-100-100-c-100-iso8859-1
756 -misc-fixed-medium-r-normal--20-*-100-100-c-100-iso8859-1
758 -misc-fixed-medium-r-normal--20-*-*-*-c-100-iso8859-1
759 So, we try again with wildcards in RESX and RESY. */
762 temp
= Fcopy_font_spec (entity
);
763 ASET (temp
, FONT_DPI_INDEX
, Qnil
);
764 len
= font_unparse_xlfd (temp
, pixel_size
, name
, 512);
765 if (len
<= 0 || (len
= xfont_encode_coding_xlfd (name
)) < 0)
767 FONT_ADD_LOG (" x:unparse failed", temp
, Qnil
);
770 xfont
= XLoadQueryFont (display
, name
);
771 if (x_had_errors_p (display
))
773 /* This error is perhaps due to insufficient memory on X server.
774 Let's just ignore it. */
775 x_clear_errors (display
);
780 /* Try to get the full name of FONT. */
781 if (xfont
&& XGetFontProperty (xfont
, XA_FONT
, &value
))
786 p0
= p
= (char *) XGetAtomName (FRAME_X_DISPLAY (f
), (Atom
) value
);
787 /* Count the number of dashes in the "full name".
788 If it is too few, this isn't really the font's full name,
790 In X11R4, the fonts did not come with their canonical names
801 len
= xfont_decode_coding_xlfd (p0
, -1, name
);
802 fullname
= Fdowncase (make_string (name
, len
));
811 FONT_ADD_LOG (" x:open failed", build_string (name
), Qnil
);
815 font_object
= font_make_object (VECSIZE (struct xfont_info
),
817 ASET (font_object
, FONT_TYPE_INDEX
, Qx
);
818 if (STRINGP (fullname
))
820 font_parse_xlfd ((char *) SDATA (fullname
), font_object
);
821 ASET (font_object
, FONT_NAME_INDEX
, fullname
);
827 len
= xfont_decode_coding_xlfd (name
, -1, buf
);
828 ASET (font_object
, FONT_NAME_INDEX
, make_string (buf
, len
));
830 ASET (font_object
, FONT_FULLNAME_INDEX
, fullname
);
831 ASET (font_object
, FONT_FILE_INDEX
, Qnil
);
832 ASET (font_object
, FONT_FORMAT_INDEX
, Qx
);
833 font
= XFONT_OBJECT (font_object
);
834 ((struct xfont_info
*) font
)->xfont
= xfont
;
835 ((struct xfont_info
*) font
)->display
= FRAME_X_DISPLAY (f
);
836 font
->pixel_size
= pixel_size
;
837 font
->driver
= &xfont_driver
;
838 font
->encoding_charset
= encoding
->id
;
839 font
->repertory_charset
= repertory
? repertory
->id
: -1;
840 font
->ascent
= xfont
->ascent
;
841 font
->descent
= xfont
->descent
;
842 font
->height
= font
->ascent
+ font
->descent
;
843 font
->min_width
= xfont
->min_bounds
.width
;
844 if (xfont
->min_bounds
.width
== xfont
->max_bounds
.width
)
846 /* Fixed width font. */
847 font
->average_width
= font
->space_width
= xfont
->min_bounds
.width
;
855 char2b
.byte1
= 0x00, char2b
.byte2
= 0x20;
856 pcm
= xfont_get_pcm (xfont
, &char2b
);
858 font
->space_width
= pcm
->width
;
860 font
->space_width
= 0;
862 val
= Ffont_get (font_object
, QCavgwidth
);
864 font
->average_width
= XINT (val
) / 10;
865 if (font
->average_width
< 0)
866 font
->average_width
= - font
->average_width
;
867 if (font
->average_width
== 0
868 && encoding
->ascii_compatible_p
)
870 int width
= font
->space_width
, n
= pcm
!= NULL
;
872 for (char2b
.byte2
= 33; char2b
.byte2
<= 126; char2b
.byte2
++)
873 if ((pcm
= xfont_get_pcm (xfont
, &char2b
)) != NULL
)
874 width
+= pcm
->width
, n
++;
876 font
->average_width
= width
/ n
;
878 if (font
->average_width
== 0)
879 /* No easy way other than this to get a reasonable
882 = (xfont
->min_bounds
.width
+ xfont
->max_bounds
.width
) / 2;
886 font
->underline_thickness
887 = (XGetFontProperty (xfont
, XA_UNDERLINE_THICKNESS
, &value
)
889 font
->underline_position
890 = (XGetFontProperty (xfont
, XA_UNDERLINE_POSITION
, &value
)
891 ? (long) value
: -1);
892 font
->baseline_offset
893 = (XGetFontProperty (xfont
, dpyinfo
->Xatom_MULE_BASELINE_OFFSET
, &value
)
895 font
->relative_compose
896 = (XGetFontProperty (xfont
, dpyinfo
->Xatom_MULE_RELATIVE_COMPOSE
, &value
)
899 = (XGetFontProperty (xfont
, dpyinfo
->Xatom_MULE_DEFAULT_ASCENT
, &value
)
904 fullname
= AREF (font_object
, FONT_NAME_INDEX
);
905 font
->vertical_centering
906 = (STRINGP (Vvertical_centering_font_regexp
)
907 && (fast_string_match_ignore_case
908 (Vvertical_centering_font_regexp
, fullname
) >= 0));
914 xfont_close (f
, font
)
919 XFreeFont (FRAME_X_DISPLAY (f
), ((struct xfont_info
*) font
)->xfont
);
924 xfont_prepare_face (f
, face
)
929 XSetFont (FRAME_X_DISPLAY (f
), face
->gc
,
930 ((struct xfont_info
*) face
->font
)->xfont
->fid
);
937 xfont_has_char (font
, c
)
941 Lisp_Object registry
= AREF (font
, FONT_REGISTRY_INDEX
);
942 struct charset
*encoding
;
943 struct charset
*repertory
= NULL
;
945 if (EQ (registry
, Qiso10646_1
))
947 encoding
= CHARSET_FROM_ID (charset_unicode
);
948 /* We use a font of `ja' and `ko' adstyle only for a character
949 in JISX0208 and KSC5601 charsets respectively. */
950 if (EQ (AREF (font
, FONT_ADSTYLE_INDEX
), Qja
)
951 && charset_jisx0208
>= 0)
952 repertory
= CHARSET_FROM_ID (charset_jisx0208
);
953 else if (EQ (AREF (font
, FONT_ADSTYLE_INDEX
), Qko
)
954 && charset_ksc5601
>= 0)
955 repertory
= CHARSET_FROM_ID (charset_ksc5601
);
957 else if (font_registry_charsets (registry
, &encoding
, &repertory
) < 0)
958 /* Unknown REGISTRY, not usable. */
960 if (ASCII_CHAR_P (c
) && encoding
->ascii_compatible_p
)
964 return (ENCODE_CHAR (repertory
, c
) != CHARSET_INVALID_CODE (repertory
));
968 xfont_encode_char (font
, c
)
972 XFontStruct
*xfont
= ((struct xfont_info
*) font
)->xfont
;
973 struct charset
*charset
;
977 charset
= CHARSET_FROM_ID (font
->encoding_charset
);
978 code
= ENCODE_CHAR (charset
, c
);
979 if (code
== CHARSET_INVALID_CODE (charset
))
980 return FONT_INVALID_CODE
;
981 if (font
->repertory_charset
>= 0)
983 charset
= CHARSET_FROM_ID (font
->repertory_charset
);
984 return (ENCODE_CHAR (charset
, c
) != CHARSET_INVALID_CODE (charset
)
985 ? code
: FONT_INVALID_CODE
);
987 char2b
.byte1
= code
>> 8;
988 char2b
.byte2
= code
& 0xFF;
989 return (xfont_get_pcm (xfont
, &char2b
) ? code
: FONT_INVALID_CODE
);
993 xfont_text_extents (font
, code
, nglyphs
, metrics
)
997 struct font_metrics
*metrics
;
999 XFontStruct
*xfont
= ((struct xfont_info
*) font
)->xfont
;
1004 bzero (metrics
, sizeof (struct font_metrics
));
1005 for (i
= 0, x
= 0, first
= 1; i
< nglyphs
; i
++)
1008 static XCharStruct
*pcm
;
1010 if (code
[i
] >= 0x10000)
1012 char2b
.byte1
= code
[i
] >> 8, char2b
.byte2
= code
[i
] & 0xFF;
1013 pcm
= xfont_get_pcm (xfont
, &char2b
);
1020 metrics
->lbearing
= pcm
->lbearing
;
1021 metrics
->rbearing
= pcm
->rbearing
;
1022 metrics
->ascent
= pcm
->ascent
;
1023 metrics
->descent
= pcm
->descent
;
1031 if (metrics
->lbearing
> width
+ pcm
->lbearing
)
1032 metrics
->lbearing
= width
+ pcm
->lbearing
;
1033 if (metrics
->rbearing
< width
+ pcm
->rbearing
)
1034 metrics
->rbearing
= width
+ pcm
->rbearing
;
1035 if (metrics
->ascent
< pcm
->ascent
)
1036 metrics
->ascent
= pcm
->ascent
;
1037 if (metrics
->descent
< pcm
->descent
)
1038 metrics
->descent
= pcm
->descent
;
1041 width
+= pcm
->width
;
1044 metrics
->width
= width
;
1049 xfont_draw (s
, from
, to
, x
, y
, with_background
)
1050 struct glyph_string
*s
;
1051 int from
, to
, x
, y
, with_background
;
1053 XFontStruct
*xfont
= ((struct xfont_info
*) s
->font
)->xfont
;
1054 int len
= to
- from
;
1058 if (s
->gc
!= s
->face
->gc
)
1061 XSetFont (s
->display
, gc
, xfont
->fid
);
1065 if (xfont
->min_byte1
== 0 && xfont
->max_byte1
== 0)
1070 SAFE_ALLOCA (str
, char *, len
);
1071 for (i
= 0; i
< len
; i
++)
1072 str
[i
] = XCHAR2B_BYTE2 (s
->char2b
+ from
+ i
);
1074 if (with_background
> 0)
1077 for (i
= 0; i
< len
; i
++)
1078 XDrawImageString (FRAME_X_DISPLAY (s
->f
), FRAME_X_WINDOW (s
->f
),
1079 gc
, x
+ i
, y
, str
+ i
, 1);
1081 XDrawImageString (FRAME_X_DISPLAY (s
->f
), FRAME_X_WINDOW (s
->f
),
1082 gc
, x
, y
, str
, len
);
1087 for (i
= 0; i
< len
; i
++)
1088 XDrawString (FRAME_X_DISPLAY (s
->f
), FRAME_X_WINDOW (s
->f
),
1089 gc
, x
+ i
, y
, str
+ i
, 1);
1091 XDrawString (FRAME_X_DISPLAY (s
->f
), FRAME_X_WINDOW (s
->f
),
1092 gc
, x
, y
, str
, len
);
1100 if (with_background
> 0)
1103 for (i
= 0; i
< len
; i
++)
1104 XDrawImageString16 (FRAME_X_DISPLAY (s
->f
), FRAME_X_WINDOW (s
->f
),
1105 gc
, x
+ i
, y
, s
->char2b
+ from
+ i
, 1);
1107 XDrawImageString16 (FRAME_X_DISPLAY (s
->f
), FRAME_X_WINDOW (s
->f
),
1108 gc
, x
, y
, s
->char2b
+ from
, len
);
1113 for (i
= 0; i
< len
; i
++)
1114 XDrawString16 (FRAME_X_DISPLAY (s
->f
), FRAME_X_WINDOW (s
->f
),
1115 gc
, x
+ i
, y
, s
->char2b
+ from
+ i
, 1);
1117 XDrawString16 (FRAME_X_DISPLAY (s
->f
), FRAME_X_WINDOW (s
->f
),
1118 gc
, x
, y
, s
->char2b
+ from
, len
);
1126 xfont_check (f
, font
)
1130 struct xfont_info
*xfont
= (struct xfont_info
*) font
;
1132 return (FRAME_X_DISPLAY (f
) == xfont
->display
? 0 : -1);
1139 staticpro (&xfont_scripts_cache
);
1140 { /* Here we rely on the fact that syms_of_xfont (via syms_of_font)
1141 is called fairly late, when QCtest and Qequal are known to be set. */
1142 Lisp_Object args
[2];
1145 xfont_scripts_cache
= Fmake_hash_table (2, args
);
1147 staticpro (&xfont_scratch_props
);
1148 xfont_scratch_props
= Fmake_vector (make_number (8), Qnil
);
1149 xfont_driver
.type
= Qx
;
1150 register_font_driver (&xfont_driver
, NULL
);
1153 /* arch-tag: 23c5f366-a5ee-44b7-a3b7-90d6da7fd749
1154 (do not change this comment) */