ChangeLog entry from previous commit
[emacs.git] / src / ftxfont.c
blob7e4608b9b855dfd1ab0b404a18ef4f33e50865c7
1 /* ftxfont.c -- FreeType font driver on X (without using XFT).
2 Copyright (C) 2006-2014 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 static Lisp_Object Qftx;
40 struct font_driver ftxfont_driver;
42 struct ftxfont_frame_data
44 /* Background and foreground colors. */
45 XColor colors[2];
46 /* GCs interpolating the above colors. gcs[0] is for a color
47 closest to BACKGROUND, and gcs[5] is for a color closest to
48 FOREGROUND. */
49 GC gcs[6];
50 struct ftxfont_frame_data *next;
54 /* Return an array of 6 GCs for antialiasing. */
56 static GC *
57 ftxfont_get_gcs (struct frame *f, unsigned long foreground, unsigned long background)
59 XColor color;
60 XGCValues xgcv;
61 int i;
62 struct ftxfont_frame_data *data = font_get_frame_data (f, Qftx);
63 struct ftxfont_frame_data *prev = NULL, *this = NULL, *new;
65 if (data)
67 for (this = data; this; prev = this, this = this->next)
69 if (this->colors[0].pixel < background)
70 continue;
71 if (this->colors[0].pixel > background)
72 break;
73 if (this->colors[1].pixel < foreground)
74 continue;
75 if (this->colors[1].pixel > foreground)
76 break;
77 return this->gcs;
81 new = xmalloc (sizeof *new);
82 new->next = this;
83 if (prev)
84 prev->next = new;
85 font_put_frame_data (f, Qftx, new);
87 new->colors[0].pixel = background;
88 new->colors[1].pixel = foreground;
90 block_input ();
91 XQueryColors (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), new->colors, 2);
92 for (i = 1; i < 7; i++)
94 /* Interpolate colors linearly. Any better algorithm? */
95 color.red
96 = (new->colors[1].red * i + new->colors[0].red * (8 - i)) / 8;
97 color.green
98 = (new->colors[1].green * i + new->colors[0].green * (8 - i)) / 8;
99 color.blue
100 = (new->colors[1].blue * i + new->colors[0].blue * (8 - i)) / 8;
101 if (! x_alloc_nearest_color (f, FRAME_X_COLORMAP (f), &color))
102 break;
103 xgcv.foreground = color.pixel;
104 new->gcs[i - 1] = XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
105 GCForeground, &xgcv);
107 unblock_input ();
109 if (i < 7)
111 block_input ();
112 for (i--; i >= 0; i--)
113 XFreeGC (FRAME_X_DISPLAY (f), new->gcs[i]);
114 unblock_input ();
115 if (prev)
116 prev->next = new->next;
117 else if (data)
118 font_put_frame_data (f, Qftx, new->next);
119 xfree (new);
120 return NULL;
122 return new->gcs;
125 static int
126 ftxfont_draw_bitmap (struct frame *f, GC gc_fore, GC *gcs, struct font *font,
127 unsigned int code, int x, int y, XPoint *p, int size,
128 int *n, bool flush)
130 struct font_bitmap bitmap;
131 unsigned char *b;
132 int i, j;
134 if (ftfont_driver.get_bitmap (font, code, &bitmap, size > 0x100 ? 1 : 8) < 0)
135 return 0;
136 if (size > 0x100)
138 for (i = 0, b = bitmap.buffer; i < bitmap.rows;
139 i++, b += bitmap.pitch)
141 for (j = 0; j < bitmap.width; j++)
142 if (b[j / 8] & (1 << (7 - (j % 8))))
144 p[n[0]].x = x + bitmap.left + j;
145 p[n[0]].y = y - bitmap.top + i;
146 if (++n[0] == size)
148 XDrawPoints (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
149 gc_fore, p, size, CoordModeOrigin);
150 n[0] = 0;
154 if (flush && n[0] > 0)
155 XDrawPoints (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
156 gc_fore, p, n[0], CoordModeOrigin);
158 else
160 for (i = 0, b = bitmap.buffer; i < bitmap.rows;
161 i++, b += bitmap.pitch)
163 for (j = 0; j < bitmap.width; j++)
165 int idx = (bitmap.bits_per_pixel == 1
166 ? ((b[j / 8] & (1 << (7 - (j % 8)))) ? 6 : -1)
167 : (b[j] >> 5) - 1);
169 if (idx >= 0)
171 XPoint *pp = p + size * idx;
173 pp[n[idx]].x = x + bitmap.left + j;
174 pp[n[idx]].y = y - bitmap.top + i;
175 if (++(n[idx]) == size)
177 XDrawPoints (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
178 idx == 6 ? gc_fore : gcs[idx], pp, size,
179 CoordModeOrigin);
180 n[idx] = 0;
185 if (flush)
187 for (i = 0; i < 6; i++)
188 if (n[i] > 0)
189 XDrawPoints (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
190 gcs[i], p + 0x100 * i, n[i], CoordModeOrigin);
191 if (n[6] > 0)
192 XDrawPoints (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
193 gc_fore, p + 0x600, n[6], CoordModeOrigin);
197 if (ftfont_driver.free_bitmap)
198 ftfont_driver.free_bitmap (font, &bitmap);
200 return bitmap.advance;
203 static void
204 ftxfont_draw_background (struct frame *f, struct font *font, GC gc, int x, int y,
205 int width)
207 XGCValues xgcv;
209 XGetGCValues (FRAME_X_DISPLAY (f), gc,
210 GCForeground | GCBackground, &xgcv);
211 XSetForeground (FRAME_X_DISPLAY (f), gc, xgcv.background);
212 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
213 x, y - FONT_BASE (font), width, FONT_HEIGHT (font));
214 XSetForeground (FRAME_X_DISPLAY (f), gc, xgcv.foreground);
217 static Lisp_Object
218 ftxfont_list (struct frame *f, Lisp_Object spec)
220 Lisp_Object list = ftfont_driver.list (f, spec), tail;
222 for (tail = list; CONSP (tail); tail = XCDR (tail))
223 ASET (XCAR (tail), FONT_TYPE_INDEX, Qftx);
224 return list;
227 static Lisp_Object
228 ftxfont_match (struct frame *f, Lisp_Object spec)
230 Lisp_Object entity = ftfont_driver.match (f, spec);
232 if (VECTORP (entity))
233 ASET (entity, FONT_TYPE_INDEX, Qftx);
234 return entity;
237 static Lisp_Object
238 ftxfont_open (struct frame *f, Lisp_Object entity, int pixel_size)
240 Lisp_Object font_object;
241 struct font *font;
243 font_object = ftfont_driver.open (f, entity, pixel_size);
244 if (NILP (font_object))
245 return Qnil;
246 font = XFONT_OBJECT (font_object);
247 font->driver = &ftxfont_driver;
248 return font_object;
251 static void
252 ftxfont_close (struct font *font)
254 ftfont_driver.close (font);
257 static int
258 ftxfont_draw (struct glyph_string *s, int from, int to, int x, int y,
259 bool with_background)
261 struct frame *f = s->f;
262 struct face *face = s->face;
263 struct font *font = s->font;
264 XPoint p[0x700];
265 int n[7];
266 unsigned *code;
267 int len = to - from;
268 int i;
269 GC *gcs;
270 int xadvance;
272 n[0] = n[1] = n[2] = n[3] = n[4] = n[5] = n[6] = 0;
274 USE_SAFE_ALLOCA;
275 SAFE_NALLOCA (code, 1, len);
276 block_input ();
277 if (with_background)
278 ftxfont_draw_background (f, font, s->gc, x, y, s->width);
279 for (i = 0; i < len; i++)
280 code[i] = ((XCHAR2B_BYTE1 (s->char2b + from + i) << 8)
281 | XCHAR2B_BYTE2 (s->char2b + from + i));
283 if (face->gc == s->gc)
285 gcs = ftxfont_get_gcs (f, face->foreground, face->background);
287 else
289 XGCValues xgcv;
290 unsigned long mask = GCForeground | GCBackground;
292 XGetGCValues (FRAME_X_DISPLAY (f), s->gc, mask, &xgcv);
293 gcs = ftxfont_get_gcs (f, xgcv.foreground, xgcv.background);
296 if (gcs)
298 if (s->num_clips)
299 for (i = 0; i < 6; i++)
300 XSetClipRectangles (FRAME_X_DISPLAY (f), gcs[i], 0, 0,
301 s->clip, s->num_clips, Unsorted);
303 for (i = 0; i < len; i++)
305 xadvance = ftxfont_draw_bitmap (f, s->gc, gcs, font, code[i], x, y,
306 p, 0x100, n, i + 1 == len);
307 x += (s->padding_p ? 1 : xadvance);
309 if (s->num_clips)
310 for (i = 0; i < 6; i++)
311 XSetClipMask (FRAME_X_DISPLAY (f), gcs[i], None);
313 else
315 /* We can't draw with antialiasing.
316 s->gc should already have a proper clipping setting. */
317 for (i = 0; i < len; i++)
319 xadvance = ftxfont_draw_bitmap (f, s->gc, NULL, font, code[i], x, y,
320 p, 0x700, n, i + 1 == len);
321 x += (s->padding_p ? 1 : xadvance);
325 unblock_input ();
326 SAFE_FREE ();
328 return len;
331 static int
332 ftxfont_end_for_frame (struct frame *f)
334 struct ftxfont_frame_data *data = font_get_frame_data (f, Qftx);
336 block_input ();
337 while (data)
339 struct ftxfont_frame_data *next = data->next;
340 int i;
342 for (i = 0; i < 6; i++)
343 XFreeGC (FRAME_X_DISPLAY (f), data->gcs[i]);
344 xfree (data);
345 data = next;
347 unblock_input ();
348 font_put_frame_data (f, Qftx, NULL);
349 return 0;
354 void
355 syms_of_ftxfont (void)
357 DEFSYM (Qftx, "ftx");
359 ftxfont_driver = ftfont_driver;
360 ftxfont_driver.type = Qftx;
361 ftxfont_driver.list = ftxfont_list;
362 ftxfont_driver.match = ftxfont_match;
363 ftxfont_driver.open = ftxfont_open;
364 ftxfont_driver.close = ftxfont_close;
365 ftxfont_driver.draw = ftxfont_draw;
366 ftxfont_driver.end_for_frame = ftxfont_end_for_frame;
367 register_font_driver (&ftxfont_driver, NULL);