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) */