1 /* ftcrfont.c -- FreeType font driver on cairo.
2 Copyright (C) 2015 Free Software Foundation, Inc.
4 This file is part of GNU Emacs.
6 GNU Emacs is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
11 GNU Emacs is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
25 #include "dispextern.h"
28 #include "blockinput.h"
29 #include "character.h"
35 /* FTCR font driver. */
37 /* The actual structure for ftcr font that can be casted to struct
43 /* The following six members must be here in this order to be
44 compatible with struct ftfont_info (in ftfont.c). */
46 bool maybe_otf
; /* Flag to tell if this may be OTF or not. */
48 #endif /* HAVE_LIBOTF */
53 cairo_font_face_t
*cr_font_face
;
54 /* To prevent cairo from cluttering the activated FT_Size maintained
55 in ftfont.c, we activate this special FT_Size before drawing. */
57 /* Font metrics cache. */
58 struct font_metrics
**metrics
;
62 #define METRICS_NCOLS_PER_ROW (128)
66 METRICS_INVALID
= -1, /* metrics entry is invalid */
69 #define METRICS_STATUS(metrics) ((metrics)->ascent + (metrics)->descent)
70 #define METRICS_SET_STATUS(metrics, status) \
71 ((metrics)->ascent = 0, (metrics)->descent = (status))
73 /* Prototypes for helper function. */
74 static int ftcrfont_glyph_extents (struct font
*, unsigned,
75 struct font_metrics
*);
77 /* Prototypes for font-driver methods. */
78 static Lisp_Object
ftcrfont_list (struct frame
*, Lisp_Object
);
79 static Lisp_Object
ftcrfont_match (struct frame
*, Lisp_Object
);
80 static Lisp_Object
ftcrfont_open (struct frame
*, Lisp_Object
, int);
81 static void ftcrfont_close (struct font
*);
82 static void ftcrfont_text_extents (struct font
*, unsigned *, int,
83 struct font_metrics
*);
84 static int ftcrfont_draw (struct glyph_string
*, int, int, int, int, bool);
86 struct font_driver ftcrfont_driver
;
89 ftcrfont_glyph_extents (struct font
*font
,
91 struct font_metrics
*metrics
)
93 struct ftcrfont_info
*ftcrfont_info
= (struct ftcrfont_info
*) font
;
95 struct font_metrics
*cache
;
97 row
= glyph
/ METRICS_NCOLS_PER_ROW
;
98 col
= glyph
% METRICS_NCOLS_PER_ROW
;
99 if (row
>= ftcrfont_info
->metrics_nrows
)
101 ftcrfont_info
->metrics
=
102 xrealloc (ftcrfont_info
->metrics
,
103 sizeof (struct font_metrics
*) * (row
+ 1));
104 bzero (ftcrfont_info
->metrics
+ ftcrfont_info
->metrics_nrows
,
105 (sizeof (struct font_metrics
*)
106 * (row
+ 1 - ftcrfont_info
->metrics_nrows
)));
107 ftcrfont_info
->metrics_nrows
= row
+ 1;
109 if (ftcrfont_info
->metrics
[row
] == NULL
)
111 struct font_metrics
*new;
114 new = xmalloc (sizeof (struct font_metrics
) * METRICS_NCOLS_PER_ROW
);
115 for (i
= 0; i
< METRICS_NCOLS_PER_ROW
; i
++)
116 METRICS_SET_STATUS (new + i
, METRICS_INVALID
);
117 ftcrfont_info
->metrics
[row
] = new;
119 cache
= ftcrfont_info
->metrics
[row
] + col
;
121 if (METRICS_STATUS (cache
) == METRICS_INVALID
)
122 ftfont_driver
.text_extents (font
, &glyph
, 1, cache
);
131 ftcrfont_list (struct frame
*f
, Lisp_Object spec
)
133 Lisp_Object list
= ftfont_driver
.list (f
, spec
), tail
;
135 for (tail
= list
; CONSP (tail
); tail
= XCDR (tail
))
136 ASET (XCAR (tail
), FONT_TYPE_INDEX
, Qftcr
);
141 ftcrfont_match (struct frame
*f
, Lisp_Object spec
)
143 Lisp_Object entity
= ftfont_driver
.match (f
, spec
);
145 if (VECTORP (entity
))
146 ASET (entity
, FONT_TYPE_INDEX
, Qftcr
);
150 extern FT_Face
ftfont_get_ft_face (Lisp_Object
);
153 ftcrfont_open (struct frame
*f
, Lisp_Object entity
, int pixel_size
)
155 Lisp_Object font_object
;
157 struct ftcrfont_info
*ftcrfont_info
;
162 size
= XINT (AREF (entity
, FONT_SIZE_INDEX
));
165 font_object
= font_build_object (VECSIZE (struct ftcrfont_info
),
166 Qftcr
, entity
, size
);
167 font_object
= ftfont_open2 (f
, entity
, pixel_size
, font_object
);
168 if (NILP (font_object
)) return Qnil
;
170 font
= XFONT_OBJECT (font_object
);
171 font
->driver
= &ftcrfont_driver
;
172 ftcrfont_info
= (struct ftcrfont_info
*) font
;
173 ft_face
= ftcrfont_info
->ft_size
->face
;
174 FT_New_Size (ft_face
, &ftcrfont_info
->ft_size_draw
);
175 FT_Activate_Size (ftcrfont_info
->ft_size_draw
);
176 FT_Set_Pixel_Sizes (ft_face
, 0, font
->pixel_size
);
177 ftcrfont_info
->cr_font_face
=
178 cairo_ft_font_face_create_for_ft_face (ft_face
, 0);
179 ftcrfont_info
->metrics
= NULL
;
180 ftcrfont_info
->metrics_nrows
= 0;
187 ftcrfont_close (struct font
*font
)
189 struct ftcrfont_info
*ftcrfont_info
= (struct ftcrfont_info
*) font
;
193 for (i
= 0; i
< ftcrfont_info
->metrics_nrows
; i
++)
194 if (ftcrfont_info
->metrics
[i
])
195 xfree (ftcrfont_info
->metrics
[i
]);
196 if (ftcrfont_info
->metrics
)
197 xfree (ftcrfont_info
->metrics
);
198 FT_Done_Size (ftcrfont_info
->ft_size_draw
);
199 cairo_font_face_destroy (ftcrfont_info
->cr_font_face
);
202 ftfont_driver
.close (font
);
206 ftcrfont_text_extents (struct font
*font
,
209 struct font_metrics
*metrics
)
214 width
= ftcrfont_glyph_extents (font
, code
[0], metrics
);
215 for (i
= 1; i
< nglyphs
; i
++)
217 struct font_metrics m
;
218 int w
= ftcrfont_glyph_extents (font
, code
[i
], metrics
? &m
: NULL
);
222 if (width
+ m
.lbearing
< metrics
->lbearing
)
223 metrics
->lbearing
= width
+ m
.lbearing
;
224 if (width
+ m
.rbearing
> metrics
->rbearing
)
225 metrics
->rbearing
= width
+ m
.rbearing
;
226 if (m
.ascent
> metrics
->ascent
)
227 metrics
->ascent
= m
.ascent
;
228 if (m
.descent
> metrics
->descent
)
229 metrics
->descent
= m
.descent
;
236 metrics
->width
= width
;
240 ftcrfont_draw (struct glyph_string
*s
,
241 int from
, int to
, int x
, int y
, bool with_background
)
243 struct frame
*f
= s
->f
;
244 struct face
*face
= s
->face
;
245 struct ftcrfont_info
*ftcrfont_info
= (struct ftcrfont_info
*) s
->font
;
247 cairo_glyph_t
*glyphs
;
248 cairo_surface_t
*surface
;
249 cairo_surface_type_t surface_type
;
255 cr
= x_begin_cr_clip (f
, s
->gc
);
259 x_set_cr_source_with_gc_background (f
, s
->gc
);
260 cairo_rectangle (cr
, x
, y
- FONT_BASE (face
->font
),
261 s
->width
, FONT_HEIGHT (face
->font
));
265 glyphs
= alloca (sizeof (cairo_glyph_t
) * len
);
266 for (i
= 0; i
< len
; i
++)
268 unsigned code
= ((XCHAR2B_BYTE1 (s
->char2b
+ from
+ i
) << 8)
269 | XCHAR2B_BYTE2 (s
->char2b
+ from
+ i
));
271 glyphs
[i
].index
= code
;
274 x
+= (s
->padding_p
? 1 : ftcrfont_glyph_extents (s
->font
, code
, NULL
));
277 x_set_cr_source_with_gc_foreground (f
, s
->gc
);
278 cairo_set_font_face (cr
, ftcrfont_info
->cr_font_face
);
279 cairo_set_font_size (cr
, s
->font
->pixel_size
);
280 /* cairo_set_font_matrix */
281 /* cairo_set_font_options */
283 FT_Activate_Size (ftcrfont_info
->ft_size_draw
);
284 cairo_show_glyphs (cr
, glyphs
, len
);
285 surface
= cairo_get_target (cr
);
286 /* XXX: It used to be necessary to flush when exporting. It might
287 be the case that this is no longer necessary. */
288 surface_type
= cairo_surface_get_type (surface
);
289 if (surface_type
!= CAIRO_SURFACE_TYPE_XLIB
290 && (surface_type
!= CAIRO_SURFACE_TYPE_IMAGE
291 || cairo_image_surface_get_format (surface
) != CAIRO_FORMAT_ARGB32
))
292 cairo_surface_flush (surface
);
304 syms_of_ftcrfont (void)
306 if (ftfont_info_size
!= offsetof (struct ftcrfont_info
, cr_font_face
))
309 DEFSYM (Qftcr
, "ftcr");
311 ftcrfont_driver
= ftfont_driver
;
312 ftcrfont_driver
.type
= Qftcr
;
313 ftcrfont_driver
.list
= ftcrfont_list
;
314 ftcrfont_driver
.match
= ftcrfont_match
;
315 ftcrfont_driver
.open
= ftcrfont_open
;
316 ftcrfont_driver
.close
= ftcrfont_close
;
317 ftcrfont_driver
.text_extents
= ftcrfont_text_extents
;
318 ftcrfont_driver
.draw
= ftcrfont_draw
;
319 register_font_driver (&ftcrfont_driver
, NULL
);