1 /* ftxfont.c -- FreeType font driver on X (without using XFT).
2 Copyright (C) 2006-2017 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 (at
12 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 "blockinput.h"
32 /* FTX font driver. */
34 struct ftxfont_frame_data
36 /* Background and foreground colors. */
38 /* GCs interpolating the above colors. gcs[0] is for a color
39 closest to BACKGROUND, and gcs[5] is for a color closest to
42 struct ftxfont_frame_data
*next
;
46 /* Return an array of 6 GCs for antialiasing. */
49 ftxfont_get_gcs (struct frame
*f
, unsigned long foreground
, unsigned long background
)
54 struct ftxfont_frame_data
*data
= font_get_frame_data (f
, Qftx
);
55 struct ftxfont_frame_data
*prev
= NULL
, *this = NULL
, *new;
59 for (this = data
; this; prev
= this, this = this->next
)
61 if (this->colors
[0].pixel
< background
)
63 if (this->colors
[0].pixel
> background
)
65 if (this->colors
[1].pixel
< foreground
)
67 if (this->colors
[1].pixel
> foreground
)
73 new = xmalloc (sizeof *new);
77 font_put_frame_data (f
, Qftx
, new);
79 new->colors
[0].pixel
= background
;
80 new->colors
[1].pixel
= foreground
;
83 XQueryColors (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
), new->colors
, 2);
84 for (i
= 1; i
< 7; i
++)
86 /* Interpolate colors linearly. Any better algorithm? */
88 = (new->colors
[1].red
* i
+ new->colors
[0].red
* (8 - i
)) / 8;
90 = (new->colors
[1].green
* i
+ new->colors
[0].green
* (8 - i
)) / 8;
92 = (new->colors
[1].blue
* i
+ new->colors
[0].blue
* (8 - i
)) / 8;
93 if (! x_alloc_nearest_color (f
, FRAME_X_COLORMAP (f
), &color
))
95 xgcv
.foreground
= color
.pixel
;
96 new->gcs
[i
- 1] = XCreateGC (FRAME_X_DISPLAY (f
), FRAME_X_DRAWABLE (f
),
104 for (i
--; i
>= 0; i
--)
105 XFreeGC (FRAME_X_DISPLAY (f
), new->gcs
[i
]);
108 prev
->next
= new->next
;
110 font_put_frame_data (f
, Qftx
, new->next
);
118 ftxfont_draw_bitmap (struct frame
*f
, GC gc_fore
, GC
*gcs
, struct font
*font
,
119 unsigned int code
, int x
, int y
, XPoint
*p
, int size
,
122 struct font_bitmap bitmap
;
126 if (ftfont_get_bitmap (font
, code
, &bitmap
, size
> 0x100 ? 1 : 8) < 0)
130 for (i
= 0, b
= bitmap
.buffer
; i
< bitmap
.rows
;
131 i
++, b
+= bitmap
.pitch
)
133 for (j
= 0; j
< bitmap
.width
; j
++)
134 if (b
[j
/ 8] & (1 << (7 - (j
% 8))))
136 p
[n
[0]].x
= x
+ bitmap
.left
+ j
;
137 p
[n
[0]].y
= y
- bitmap
.top
+ i
;
140 XDrawPoints (FRAME_X_DISPLAY (f
), FRAME_X_DRAWABLE (f
),
141 gc_fore
, p
, size
, CoordModeOrigin
);
146 if (flush
&& n
[0] > 0)
147 XDrawPoints (FRAME_X_DISPLAY (f
), FRAME_X_DRAWABLE (f
),
148 gc_fore
, p
, n
[0], CoordModeOrigin
);
152 for (i
= 0, b
= bitmap
.buffer
; i
< bitmap
.rows
;
153 i
++, b
+= bitmap
.pitch
)
155 for (j
= 0; j
< bitmap
.width
; j
++)
157 int idx
= (bitmap
.bits_per_pixel
== 1
158 ? ((b
[j
/ 8] & (1 << (7 - (j
% 8)))) ? 6 : -1)
163 XPoint
*pp
= p
+ size
* idx
;
165 pp
[n
[idx
]].x
= x
+ bitmap
.left
+ j
;
166 pp
[n
[idx
]].y
= y
- bitmap
.top
+ i
;
167 if (++(n
[idx
]) == size
)
169 XDrawPoints (FRAME_X_DISPLAY (f
), FRAME_X_DRAWABLE (f
),
170 idx
== 6 ? gc_fore
: gcs
[idx
], pp
, size
,
179 for (i
= 0; i
< 6; i
++)
181 XDrawPoints (FRAME_X_DISPLAY (f
), FRAME_X_DRAWABLE (f
),
182 gcs
[i
], p
+ 0x100 * i
, n
[i
], CoordModeOrigin
);
184 XDrawPoints (FRAME_X_DISPLAY (f
), FRAME_X_DRAWABLE (f
),
185 gc_fore
, p
+ 0x600, n
[6], CoordModeOrigin
);
189 /* There is no ftfont_free_bitmap, so do not try to free BITMAP. */
191 return bitmap
.advance
;
195 ftxfont_draw_background (struct frame
*f
, struct font
*font
, GC gc
, int x
, int y
,
200 XGetGCValues (FRAME_X_DISPLAY (f
), gc
,
201 GCForeground
| GCBackground
, &xgcv
);
202 XSetForeground (FRAME_X_DISPLAY (f
), gc
, xgcv
.background
);
203 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_DRAWABLE (f
), gc
,
204 x
, y
- FONT_BASE (font
), width
, FONT_HEIGHT (font
));
205 XSetForeground (FRAME_X_DISPLAY (f
), gc
, xgcv
.foreground
);
209 ftxfont_list (struct frame
*f
, Lisp_Object spec
)
211 Lisp_Object list
= ftfont_list (f
, spec
), tail
;
213 for (tail
= list
; CONSP (tail
); tail
= XCDR (tail
))
214 ASET (XCAR (tail
), FONT_TYPE_INDEX
, Qftx
);
219 ftxfont_match (struct frame
*f
, Lisp_Object spec
)
221 Lisp_Object entity
= ftfont_match (f
, spec
);
223 if (VECTORP (entity
))
224 ASET (entity
, FONT_TYPE_INDEX
, Qftx
);
229 ftxfont_open (struct frame
*f
, Lisp_Object entity
, int pixel_size
)
231 Lisp_Object font_object
= ftfont_open (f
, entity
, pixel_size
);
232 if (NILP (font_object
))
234 struct font
*font
= XFONT_OBJECT (font_object
);
235 font
->driver
= &ftxfont_driver
;
240 ftxfont_close (struct font
*font
)
246 ftxfont_draw (struct glyph_string
*s
, int from
, int to
, int x
, int y
,
247 bool with_background
)
249 struct frame
*f
= s
->f
;
250 struct face
*face
= s
->face
;
251 struct font
*font
= s
->font
;
260 n
[0] = n
[1] = n
[2] = n
[3] = n
[4] = n
[5] = n
[6] = 0;
263 SAFE_NALLOCA (code
, 1, len
);
266 ftxfont_draw_background (f
, font
, s
->gc
, x
, y
, s
->width
);
267 for (i
= 0; i
< len
; i
++)
268 code
[i
] = ((XCHAR2B_BYTE1 (s
->char2b
+ from
+ i
) << 8)
269 | XCHAR2B_BYTE2 (s
->char2b
+ from
+ i
));
271 if (face
->gc
== s
->gc
)
273 gcs
= ftxfont_get_gcs (f
, face
->foreground
, face
->background
);
278 unsigned long mask
= GCForeground
| GCBackground
;
280 XGetGCValues (FRAME_X_DISPLAY (f
), s
->gc
, mask
, &xgcv
);
281 gcs
= ftxfont_get_gcs (f
, xgcv
.foreground
, xgcv
.background
);
287 for (i
= 0; i
< 6; i
++)
288 XSetClipRectangles (FRAME_X_DISPLAY (f
), gcs
[i
], 0, 0,
289 s
->clip
, s
->num_clips
, Unsorted
);
291 for (i
= 0; i
< len
; i
++)
293 xadvance
= ftxfont_draw_bitmap (f
, s
->gc
, gcs
, font
, code
[i
], x
, y
,
294 p
, 0x100, n
, i
+ 1 == len
);
295 x
+= (s
->padding_p
? 1 : xadvance
);
298 for (i
= 0; i
< 6; i
++)
299 XSetClipMask (FRAME_X_DISPLAY (f
), gcs
[i
], None
);
303 /* We can't draw with antialiasing.
304 s->gc should already have a proper clipping setting. */
305 for (i
= 0; i
< len
; i
++)
307 xadvance
= ftxfont_draw_bitmap (f
, s
->gc
, NULL
, font
, code
[i
], x
, y
,
308 p
, 0x700, n
, i
+ 1 == len
);
309 x
+= (s
->padding_p
? 1 : xadvance
);
320 ftxfont_end_for_frame (struct frame
*f
)
322 struct ftxfont_frame_data
*data
= font_get_frame_data (f
, Qftx
);
327 struct ftxfont_frame_data
*next
= data
->next
;
330 for (i
= 0; i
< 6; i
++)
331 XFreeGC (FRAME_X_DISPLAY (f
), data
->gcs
[i
]);
336 font_put_frame_data (f
, Qftx
, NULL
);
342 struct font_driver
const ftxfont_driver
=
344 /* We can't draw a text without device dependent functions. */
345 .type
= LISPSYM_INITIALLY (Qftx
),
346 .get_cache
= ftfont_get_cache
,
347 .list
= ftxfont_list
,
348 .match
= ftxfont_match
,
349 .list_family
= ftfont_list_family
,
350 .open
= ftxfont_open
,
351 .close
= ftxfont_close
,
352 .has_char
= ftfont_has_char
,
353 .encode_char
= ftfont_encode_char
,
354 .text_extents
= ftfont_text_extents
,
355 .draw
= ftxfont_draw
,
356 .get_bitmap
= ftfont_get_bitmap
,
357 .anchor_point
= ftfont_anchor_point
,
359 .otf_capability
= ftfont_otf_capability
,
361 .end_for_frame
= ftxfont_end_for_frame
,
362 #if defined HAVE_M17N_FLT && defined HAVE_LIBOTF
363 .shape
= ftfont_shape
,
365 #ifdef HAVE_OTF_GET_VARIATION_GLYPHS
366 .get_variation_glyphs
= ftfont_variation_glyphs
,
368 .filter_properties
= ftfont_filter_properties
,
369 .combining_capability
= ftfont_combining_capability
,
373 syms_of_ftxfont (void)
375 DEFSYM (Qftx
, "ftx");
376 register_font_driver (&ftxfont_driver
, NULL
);