1 /* ftxfont.c -- FreeType font driver on X (without using XFT).
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"
38 /* FTX font driver. */
40 static Lisp_Object Qftx
;
42 /* Prototypes for helper function. */
43 static GC
*ftxfont_get_gcs
P_ ((FRAME_PTR
, unsigned long, unsigned long));
44 static int ftxfont_draw_bitmap
P_ ((FRAME_PTR
, GC
, GC
*, struct font
*,
45 unsigned, int, int, XPoint
*, int, int *,
47 static void ftxfont_draw_backgrond
P_ ((FRAME_PTR
, struct font
*, GC
,
49 static Font ftxfont_default_fid
P_ ((FRAME_PTR
));
51 struct ftxfont_frame_data
53 /* Background and foreground colors. */
55 /* GCs interporationg the above colors. gcs[0] is for a color
56 closest to BACKGROUND, and gcs[5] is for a color closest to
59 struct ftxfont_frame_data
*next
;
63 /* Return an array of 6 GCs for antialiasing. */
66 ftxfont_get_gcs (f
, foreground
, background
)
68 unsigned long foreground
, background
;
73 struct ftxfont_frame_data
*data
= font_get_frame_data (f
, &ftxfont_driver
);
74 struct ftxfont_frame_data
*prev
= NULL
, *this = NULL
, *new;
78 for (this = data
; this; prev
= this, this = this->next
)
80 if (this->colors
[0].pixel
< background
)
82 if (this->colors
[0].pixel
> background
)
84 if (this->colors
[1].pixel
< foreground
)
86 if (this->colors
[1].pixel
> foreground
)
92 new = malloc (sizeof (struct ftxfont_frame_data
));
100 else if (font_put_frame_data (f
, &ftxfont_driver
, new) < 0)
106 new->colors
[0].pixel
= background
;
107 new->colors
[1].pixel
= foreground
;
110 XQueryColors (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
), new->colors
, 2);
111 for (i
= 1; i
< 7; i
++)
113 /* Interpolate colors linearly. Any better algorithm? */
115 = (new->colors
[1].red
* i
+ new->colors
[0].red
* (8 - i
)) / 8;
117 = (new->colors
[1].green
* i
+ new->colors
[0].green
* (8 - i
)) / 8;
119 = (new->colors
[1].blue
* i
+ new->colors
[0].blue
* (8 - i
)) / 8;
120 if (! x_alloc_nearest_color (f
, FRAME_X_COLORMAP (f
), &color
))
122 xgcv
.foreground
= color
.pixel
;
123 new->gcs
[i
- 1] = XCreateGC (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
124 GCForeground
, &xgcv
);
131 for (i
--; i
>= 0; i
--)
132 XFreeGC (FRAME_X_DISPLAY (f
), new->gcs
[i
]);
135 prev
->next
= new->next
;
137 font_put_frame_data (f
, &ftxfont_driver
, new->next
);
145 ftxfont_draw_bitmap (f
, gc_fore
, gcs
, font
, code
, x
, y
, p
, size
, n
, flush
)
155 struct font_bitmap bitmap
;
159 if (ftfont_driver
.get_bitmap (font
, code
, &bitmap
, size
> 0x100 ? 1 : 8) < 0)
163 for (i
= 0, b
= bitmap
.buffer
; i
< bitmap
.rows
;
164 i
++, b
+= bitmap
.pitch
)
166 for (j
= 0; j
< bitmap
.width
; j
++)
167 if (b
[j
/ 8] & (1 << (7 - (j
% 8))))
169 p
[n
[0]].x
= x
+ bitmap
.left
+ j
;
170 p
[n
[0]].y
= y
- bitmap
.top
+ i
;
173 XDrawPoints (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
174 gc_fore
, p
, size
, CoordModeOrigin
);
179 if (flush
&& n
[0] > 0)
180 XDrawPoints (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
181 gc_fore
, p
, n
[0], CoordModeOrigin
);
185 for (i
= 0, b
= bitmap
.buffer
; i
< bitmap
.rows
;
186 i
++, b
+= bitmap
.pitch
)
188 for (j
= 0; j
< bitmap
.width
; j
++)
190 int idx
= (bitmap
.bits_per_pixel
== 1
191 ? ((b
[j
/ 8] & (1 << (7 - (j
% 8)))) ? 6 : -1)
196 XPoint
*pp
= p
+ size
* idx
;
198 pp
[n
[idx
]].x
= x
+ bitmap
.left
+ j
;
199 pp
[n
[idx
]].y
= y
- bitmap
.top
+ i
;
200 if (++(n
[idx
]) == size
)
202 XDrawPoints (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
203 idx
== 6 ? gc_fore
: gcs
[idx
], pp
, size
,
212 for (i
= 0; i
< 6; i
++)
214 XDrawPoints (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
215 gcs
[i
], p
+ 0x100 * i
, n
[i
], CoordModeOrigin
);
217 XDrawPoints (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
218 gc_fore
, p
+ 0x600, n
[6], CoordModeOrigin
);
222 if (ftfont_driver
.free_bitmap
)
223 ftfont_driver
.free_bitmap (font
, &bitmap
);
225 return bitmap
.advance
;
229 ftxfont_draw_backgrond (f
, font
, gc
, x
, y
, width
)
237 XGetGCValues (FRAME_X_DISPLAY (f
), gc
,
238 GCForeground
| GCBackground
, &xgcv
);
239 XSetForeground (FRAME_X_DISPLAY (f
), gc
, xgcv
.background
);
240 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
241 x
, y
- font
->ascent
, width
, y
+ font
->descent
);
242 XSetForeground (FRAME_X_DISPLAY (f
), gc
, xgcv
.foreground
);
245 /* Return the default Font ID on frame F. */
248 ftxfont_default_fid (f
)
251 static int fid_known
;
256 fid
= XLoadFont (FRAME_X_DISPLAY (f
), "fixed");
259 fid
= XLoadFont (FRAME_X_DISPLAY (f
), "*");
268 /* Prototypes for font-driver methods. */
269 static Lisp_Object ftxfont_list
P_ ((Lisp_Object
, Lisp_Object
));
270 static Lisp_Object ftxfont_match
P_ ((Lisp_Object
, Lisp_Object
));
271 static struct font
*ftxfont_open
P_ ((FRAME_PTR
, Lisp_Object
, int));
272 static void ftxfont_close
P_ ((FRAME_PTR
, struct font
*));
273 static int ftxfont_draw
P_ ((struct glyph_string
*, int, int, int, int, int));
275 struct font_driver ftxfont_driver
;
278 ftxfont_list (frame
, spec
)
282 Lisp_Object val
= ftfont_driver
.list (frame
, spec
);
288 for (i
= 0; i
< ASIZE (val
); i
++)
289 ASET (AREF (val
, i
), FONT_TYPE_INDEX
, Qftx
);
295 ftxfont_match (frame
, spec
)
299 Lisp_Object entity
= ftfont_driver
.match (frame
, spec
);
301 if (VECTORP (entity
))
302 ASET (entity
, FONT_TYPE_INDEX
, Qftx
);
307 ftxfont_open (f
, entity
, pixel_size
)
312 Display_Info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
314 XFontStruct
*xfont
= malloc (sizeof (XFontStruct
));
318 font
= ftfont_driver
.open (f
, entity
, pixel_size
);
325 xfont
->fid
= ftxfont_default_fid (f
);
326 xfont
->ascent
= font
->ascent
;
327 xfont
->descent
= font
->descent
;
328 xfont
->max_bounds
.width
= font
->font
.size
;
329 xfont
->min_bounds
.width
= font
->min_width
;
330 font
->font
.font
= xfont
;
331 font
->driver
= &ftxfont_driver
;
335 /* Set global flag fonts_changed_p to non-zero if the font loaded
336 has a character with a smaller width than any other character
337 before, or if the font loaded has a smaller height than any other
338 font loaded before. If this happens, it will make a glyph matrix
339 reallocation necessary. */
340 if (dpyinfo
->n_fonts
== 1)
342 dpyinfo
->smallest_font_height
= font
->font
.height
;
343 dpyinfo
->smallest_char_width
= font
->min_width
;
348 if (dpyinfo
->smallest_font_height
> font
->font
.height
)
349 dpyinfo
->smallest_font_height
= font
->font
.height
, fonts_changed_p
|= 1;
350 if (dpyinfo
->smallest_char_width
> font
->min_width
)
351 dpyinfo
->smallest_char_width
= font
->min_width
, fonts_changed_p
|= 1;
356 if (dpyinfo
->smallest_font_height
== 0)
357 dpyinfo
->smallest_font_height
= 1;
358 if (dpyinfo
->smallest_char_width
== 0)
359 dpyinfo
->smallest_char_width
= 1;
366 ftxfont_close (f
, font
)
370 ftfont_driver
.close (f
, font
);
371 FRAME_X_DISPLAY_INFO (f
)->n_fonts
--;
375 ftxfont_draw (s
, from
, to
, x
, y
, with_background
)
376 struct glyph_string
*s
;
377 int from
, to
, x
, y
, with_background
;
380 struct face
*face
= s
->face
;
381 struct font
*font
= (struct font
*) s
->font_info
;
389 n
[0] = n
[1] = n
[2] = n
[3] = n
[4] = n
[5] = n
[6] = 0;
393 ftxfont_draw_backgrond (f
, font
, s
->gc
, x
, y
, s
->width
);
394 code
= alloca (sizeof (unsigned) * len
);
395 for (i
= 0; i
< len
; i
++)
396 code
[i
] = ((XCHAR2B_BYTE1 (s
->char2b
+ from
+ i
) << 8)
397 | XCHAR2B_BYTE2 (s
->char2b
+ from
+ i
));
399 if (face
->gc
== s
->gc
)
401 gcs
= ftxfont_get_gcs (f
, face
->foreground
, face
->background
);
406 unsigned long mask
= GCForeground
| GCBackground
;
408 XGetGCValues (FRAME_X_DISPLAY (f
), s
->gc
, mask
, &xgcv
);
409 gcs
= ftxfont_get_gcs (f
, xgcv
.foreground
, xgcv
.background
);
415 for (i
= 0; i
< 6; i
++)
416 XSetClipRectangles (FRAME_X_DISPLAY (f
), gcs
[i
], 0, 0,
417 s
->clip
, s
->num_clips
, Unsorted
);
419 for (i
= 0; i
< len
; i
++)
420 x
+= ftxfont_draw_bitmap (f
, s
->gc
, gcs
, font
, code
[i
], x
, y
,
421 p
, 0x100, n
, i
+ 1 == len
);
423 for (i
= 0; i
< 6; i
++)
424 XSetClipMask (FRAME_X_DISPLAY (f
), gcs
[i
], None
);
428 /* We can't draw with antialiasing.
429 s->gc should already have a proper clipping setting. */
430 for (i
= 0; i
< len
; i
++)
431 x
+= ftxfont_draw_bitmap (f
, s
->gc
, NULL
, font
, code
[i
], x
, y
,
432 p
, 0x700, n
, i
+ 1 == len
);
441 ftxfont_end_for_frame (f
)
444 struct ftxfont_frame_data
*data
= font_get_frame_data (f
, &ftxfont_driver
);
449 struct ftxfont_frame_data
*next
= data
->next
;
452 for (i
= 0; i
< 6; i
++)
453 XFreeGC (FRAME_X_DISPLAY (f
), data
->gcs
[i
]);
466 DEFSYM (Qftx
, "ftx");
468 ftxfont_driver
= ftfont_driver
;
469 ftxfont_driver
.type
= Qftx
;
470 ftxfont_driver
.list
= ftxfont_list
;
471 ftxfont_driver
.match
= ftxfont_match
;
472 ftxfont_driver
.open
= ftxfont_open
;
473 ftxfont_driver
.close
= ftxfont_close
;
474 ftxfont_driver
.draw
= ftxfont_draw
;
475 ftxfont_driver
.end_for_frame
= ftxfont_end_for_frame
;
476 register_font_driver (&ftxfont_driver
, NULL
);
479 /* arch-tag: 59bd3469-5330-413f-b29d-1aa36492abe8
480 (do not change this comment) */