* src/print.c (print_object): Minor simplification.
[emacs.git] / src / ftxfont.c
blobcd2bf3e7415b5e7439de18dab0e7e1487962a39e
1 /* ftxfont.c -- FreeType font driver on X (without using XFT).
2 Copyright (C) 2006-2015 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/>. */
22 #include <config.h>
23 #include <stdio.h>
24 #include <X11/Xlib.h>
26 #include "lisp.h"
27 #include "dispextern.h"
28 #include "xterm.h"
29 #include "frame.h"
30 #include "blockinput.h"
31 #include "character.h"
32 #include "charset.h"
33 #include "fontset.h"
34 #include "font.h"
36 /* FTX font driver. */
38 struct font_driver ftxfont_driver;
40 struct ftxfont_frame_data
42 /* Background and foreground colors. */
43 XColor colors[2];
44 /* GCs interpolating the above colors. gcs[0] is for a color
45 closest to BACKGROUND, and gcs[5] is for a color closest to
46 FOREGROUND. */
47 GC gcs[6];
48 struct ftxfont_frame_data *next;
52 /* Return an array of 6 GCs for antialiasing. */
54 static GC *
55 ftxfont_get_gcs (struct frame *f, unsigned long foreground, unsigned long background)
57 XColor color;
58 XGCValues xgcv;
59 int i;
60 struct ftxfont_frame_data *data = font_get_frame_data (f, Qftx);
61 struct ftxfont_frame_data *prev = NULL, *this = NULL, *new;
63 if (data)
65 for (this = data; this; prev = this, this = this->next)
67 if (this->colors[0].pixel < background)
68 continue;
69 if (this->colors[0].pixel > background)
70 break;
71 if (this->colors[1].pixel < foreground)
72 continue;
73 if (this->colors[1].pixel > foreground)
74 break;
75 return this->gcs;
79 new = xmalloc (sizeof *new);
80 new->next = this;
81 if (prev)
82 prev->next = new;
83 font_put_frame_data (f, Qftx, new);
85 new->colors[0].pixel = background;
86 new->colors[1].pixel = foreground;
88 block_input ();
89 XQueryColors (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), new->colors, 2);
90 for (i = 1; i < 7; i++)
92 /* Interpolate colors linearly. Any better algorithm? */
93 color.red
94 = (new->colors[1].red * i + new->colors[0].red * (8 - i)) / 8;
95 color.green
96 = (new->colors[1].green * i + new->colors[0].green * (8 - i)) / 8;
97 color.blue
98 = (new->colors[1].blue * i + new->colors[0].blue * (8 - i)) / 8;
99 if (! x_alloc_nearest_color (f, FRAME_X_COLORMAP (f), &color))
100 break;
101 xgcv.foreground = color.pixel;
102 new->gcs[i - 1] = XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
103 GCForeground, &xgcv);
105 unblock_input ();
107 if (i < 7)
109 block_input ();
110 for (i--; i >= 0; i--)
111 XFreeGC (FRAME_X_DISPLAY (f), new->gcs[i]);
112 unblock_input ();
113 if (prev)
114 prev->next = new->next;
115 else if (data)
116 font_put_frame_data (f, Qftx, new->next);
117 xfree (new);
118 return NULL;
120 return new->gcs;
123 static int
124 ftxfont_draw_bitmap (struct frame *f, GC gc_fore, GC *gcs, struct font *font,
125 unsigned int code, int x, int y, XPoint *p, int size,
126 int *n, bool flush)
128 struct font_bitmap bitmap;
129 unsigned char *b;
130 int i, j;
132 if (ftfont_driver.get_bitmap (font, code, &bitmap, size > 0x100 ? 1 : 8) < 0)
133 return 0;
134 if (size > 0x100)
136 for (i = 0, b = bitmap.buffer; i < bitmap.rows;
137 i++, b += bitmap.pitch)
139 for (j = 0; j < bitmap.width; j++)
140 if (b[j / 8] & (1 << (7 - (j % 8))))
142 p[n[0]].x = x + bitmap.left + j;
143 p[n[0]].y = y - bitmap.top + i;
144 if (++n[0] == size)
146 XDrawPoints (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
147 gc_fore, p, size, CoordModeOrigin);
148 n[0] = 0;
152 if (flush && n[0] > 0)
153 XDrawPoints (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
154 gc_fore, p, n[0], CoordModeOrigin);
156 else
158 for (i = 0, b = bitmap.buffer; i < bitmap.rows;
159 i++, b += bitmap.pitch)
161 for (j = 0; j < bitmap.width; j++)
163 int idx = (bitmap.bits_per_pixel == 1
164 ? ((b[j / 8] & (1 << (7 - (j % 8)))) ? 6 : -1)
165 : (b[j] >> 5) - 1);
167 if (idx >= 0)
169 XPoint *pp = p + size * idx;
171 pp[n[idx]].x = x + bitmap.left + j;
172 pp[n[idx]].y = y - bitmap.top + i;
173 if (++(n[idx]) == size)
175 XDrawPoints (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
176 idx == 6 ? gc_fore : gcs[idx], pp, size,
177 CoordModeOrigin);
178 n[idx] = 0;
183 if (flush)
185 for (i = 0; i < 6; i++)
186 if (n[i] > 0)
187 XDrawPoints (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
188 gcs[i], p + 0x100 * i, n[i], CoordModeOrigin);
189 if (n[6] > 0)
190 XDrawPoints (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
191 gc_fore, p + 0x600, n[6], CoordModeOrigin);
195 if (ftfont_driver.free_bitmap)
196 ftfont_driver.free_bitmap (font, &bitmap);
198 return bitmap.advance;
201 static void
202 ftxfont_draw_background (struct frame *f, struct font *font, GC gc, int x, int y,
203 int width)
205 XGCValues xgcv;
207 XGetGCValues (FRAME_X_DISPLAY (f), gc,
208 GCForeground | GCBackground, &xgcv);
209 XSetForeground (FRAME_X_DISPLAY (f), gc, xgcv.background);
210 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
211 x, y - FONT_BASE (font), width, FONT_HEIGHT (font));
212 XSetForeground (FRAME_X_DISPLAY (f), gc, xgcv.foreground);
215 static Lisp_Object
216 ftxfont_list (struct frame *f, Lisp_Object spec)
218 Lisp_Object list = ftfont_driver.list (f, spec), tail;
220 for (tail = list; CONSP (tail); tail = XCDR (tail))
221 ASET (XCAR (tail), FONT_TYPE_INDEX, Qftx);
222 return list;
225 static Lisp_Object
226 ftxfont_match (struct frame *f, Lisp_Object spec)
228 Lisp_Object entity = ftfont_driver.match (f, spec);
230 if (VECTORP (entity))
231 ASET (entity, FONT_TYPE_INDEX, Qftx);
232 return entity;
235 static Lisp_Object
236 ftxfont_open (struct frame *f, Lisp_Object entity, int pixel_size)
238 Lisp_Object font_object;
239 struct font *font;
241 font_object = ftfont_driver.open (f, entity, pixel_size);
242 if (NILP (font_object))
243 return Qnil;
244 font = XFONT_OBJECT (font_object);
245 font->driver = &ftxfont_driver;
246 return font_object;
249 static void
250 ftxfont_close (struct font *font)
252 ftfont_driver.close (font);
255 static int
256 ftxfont_draw (struct glyph_string *s, int from, int to, int x, int y,
257 bool with_background)
259 struct frame *f = s->f;
260 struct face *face = s->face;
261 struct font *font = s->font;
262 XPoint p[0x700];
263 int n[7];
264 unsigned *code;
265 int len = to - from;
266 int i;
267 GC *gcs;
268 int xadvance;
270 n[0] = n[1] = n[2] = n[3] = n[4] = n[5] = n[6] = 0;
272 USE_SAFE_ALLOCA;
273 SAFE_NALLOCA (code, 1, len);
274 block_input ();
275 if (with_background)
276 ftxfont_draw_background (f, font, s->gc, x, y, s->width);
277 for (i = 0; i < len; i++)
278 code[i] = ((XCHAR2B_BYTE1 (s->char2b + from + i) << 8)
279 | XCHAR2B_BYTE2 (s->char2b + from + i));
281 if (face->gc == s->gc)
283 gcs = ftxfont_get_gcs (f, face->foreground, face->background);
285 else
287 XGCValues xgcv;
288 unsigned long mask = GCForeground | GCBackground;
290 XGetGCValues (FRAME_X_DISPLAY (f), s->gc, mask, &xgcv);
291 gcs = ftxfont_get_gcs (f, xgcv.foreground, xgcv.background);
294 if (gcs)
296 if (s->num_clips)
297 for (i = 0; i < 6; i++)
298 XSetClipRectangles (FRAME_X_DISPLAY (f), gcs[i], 0, 0,
299 s->clip, s->num_clips, Unsorted);
301 for (i = 0; i < len; i++)
303 xadvance = ftxfont_draw_bitmap (f, s->gc, gcs, font, code[i], x, y,
304 p, 0x100, n, i + 1 == len);
305 x += (s->padding_p ? 1 : xadvance);
307 if (s->num_clips)
308 for (i = 0; i < 6; i++)
309 XSetClipMask (FRAME_X_DISPLAY (f), gcs[i], None);
311 else
313 /* We can't draw with antialiasing.
314 s->gc should already have a proper clipping setting. */
315 for (i = 0; i < len; i++)
317 xadvance = ftxfont_draw_bitmap (f, s->gc, NULL, font, code[i], x, y,
318 p, 0x700, n, i + 1 == len);
319 x += (s->padding_p ? 1 : xadvance);
323 unblock_input ();
324 SAFE_FREE ();
326 return len;
329 static int
330 ftxfont_end_for_frame (struct frame *f)
332 struct ftxfont_frame_data *data = font_get_frame_data (f, Qftx);
334 block_input ();
335 while (data)
337 struct ftxfont_frame_data *next = data->next;
338 int i;
340 for (i = 0; i < 6; i++)
341 XFreeGC (FRAME_X_DISPLAY (f), data->gcs[i]);
342 xfree (data);
343 data = next;
345 unblock_input ();
346 font_put_frame_data (f, Qftx, NULL);
347 return 0;
352 void
353 syms_of_ftxfont (void)
355 DEFSYM (Qftx, "ftx");
357 ftxfont_driver = ftfont_driver;
358 ftxfont_driver.type = Qftx;
359 ftxfont_driver.list = ftxfont_list;
360 ftxfont_driver.match = ftxfont_match;
361 ftxfont_driver.open = ftxfont_open;
362 ftxfont_driver.close = ftxfont_close;
363 ftxfont_driver.draw = ftxfont_draw;
364 ftxfont_driver.end_for_frame = ftxfont_end_for_frame;
365 register_font_driver (&ftxfont_driver, NULL);