ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/cf.schmorp.de/Deliantra-Client/pango-font.c
Revision: 1.5
Committed: Sun Nov 18 00:52:22 2018 UTC (5 years, 7 months ago) by root
Content type: text/plain
Branch: MAIN
CVS Tags: HEAD
Changes since 1.4: +8 -8 lines
Log Message:
port to c++

File Contents

# Content
1 /* Pango
2 * OpenGL Freetype2 handling
3 *
4 * Copyright (C) 1999 Red Hat Software
5 * Copyright (C) 2000 Tor Lillqvist
6 * Copyright (C) 2006 Marc Lehmann <pcg@goof.com>
7 *
8 * This file is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Library General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
12 *
13 * This file is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Library General Public License for more details.
17 *
18 * You should have received a copy of the GNU Library General Public
19 * License along with this library; if not, write to the
20 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21 * Boston, MA 02111-1307, USA.
22 */
23
24 #define PANGO_ENABLE_BACKEND
25
26 #include <string.h>
27 #include <stdlib.h>
28 #include <math.h>
29 #include <glib.h>
30 #include <glib/gprintf.h>
31
32 #include "pangoopengl.h"
33
34 #include "pango/pangofc-font.h"
35 #include "pango/pangofc-fontmap.h"
36
37 #define PANGO_OPENGL_FONT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PANGO_TYPE_OPENGL_FONT, PangoOpenGLFontClass))
38 #define PANGO_OPENGL_IS_FONT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PANGO_TYPE_OPENGL_FONT))
39 #define PANGO_OPENGL_FONT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PANGO_TYPE_OPENGL_FONT, PangoOpenGLFontClass))
40
41 typedef struct _PangoOpenGLFontClass PangoOpenGLFontClass;
42
43 struct _PangoOpenGLFontClass
44 {
45 PangoFcFontClass parent_class;
46 };
47
48 static void pango_opengl_font_finalize (GObject *object);
49
50 static void pango_opengl_font_get_glyph_extents (PangoFont *font,
51 PangoGlyph glyph,
52 PangoRectangle *ink_rect,
53 PangoRectangle *logical_rect);
54
55 static FT_Face pango_opengl_font_real_lock_face (PangoFcFont *font);
56 static void pango_opengl_font_real_unlock_face (PangoFcFont *font);
57
58 PangoOpenGLFont *
59 _pango_opengl_font_new (PangoOpenGLFontMap *fontmap_, FcPattern *pattern)
60 {
61 PangoFontMap *fontmap = PANGO_FONT_MAP (fontmap_);
62 PangoOpenGLFont *font;
63 double d;
64
65 g_return_val_if_fail (fontmap != NULL, NULL);
66 g_return_val_if_fail (pattern != NULL, NULL);
67
68 font = (PangoOpenGLFont *)g_object_new (PANGO_TYPE_OPENGL_FONT,
69 "pattern", pattern,
70 NULL);
71
72 if (FcPatternGetDouble (pattern, FC_PIXEL_SIZE, 0, &d) == FcResultMatch)
73 font->size = d * PANGO_SCALE;
74
75 #if PANGO_VERSION_CHECK (1, 16, 0)
76 /* pango 1.24 is ABI-incompatible with 1.22, but distros */
77 /* usually package it under the same name, so a runtime check */
78 /* is required */
79 /* unfortunately, pango doesn't support runtime checks in < 1.16 */
80 /* so there is no real way to ensure binary compatibility portably */
81 /* great move, pango */
82 if (pango_version () > PANGO_VERSION_ENCODE (1, 23, 0))
83 PANGO_FC_FONT (font)->fontmap = fontmap;
84 #endif
85
86 return font;
87 }
88
89 static void
90 load_fallback_face (PangoOpenGLFont *font, const char *original_file)
91 {
92 PangoFcFont *fcfont = PANGO_FC_FONT (font);
93 FcPattern *sans;
94 FcPattern *matched;
95 FcResult result;
96 FT_Error error;
97 FcChar8 *filename2 = NULL;
98 gchar *name;
99 int id;
100
101 sans = FcPatternBuild (NULL,
102 FC_FAMILY, FcTypeString, "sans",
103 FC_PIXEL_SIZE, FcTypeDouble, (double)font->size / PANGO_SCALE,
104 NULL);
105
106 matched = FcFontMatch (NULL, sans, &result);
107
108 if (FcPatternGetString (matched, FC_FILE, 0, &filename2) != FcResultMatch)
109 goto bail1;
110
111 if (FcPatternGetInteger (matched, FC_INDEX, 0, &id) != FcResultMatch)
112 goto bail1;
113
114 error = FT_New_Face (_pango_opengl_font_map_get_library (fcfont->fontmap),
115 (char *) filename2, id, &font->face);
116
117 if (error)
118 {
119 bail1:
120 name = pango_font_description_to_string (fcfont->description);
121 g_warning ("Unable to open font file %s for font %s, exiting\n", filename2, name);
122 exit (1);
123 }
124 else
125 {
126 name = pango_font_description_to_string (fcfont->description);
127 g_warning ("Unable to open font file %s for font %s, falling back to %s\n", original_file, name, filename2);
128 g_free (name);
129 }
130
131 FcPatternDestroy (sans);
132 FcPatternDestroy (matched);
133 }
134
135 static void
136 set_transform (PangoOpenGLFont *font)
137 {
138 PangoFcFont *fcfont = (PangoFcFont *)font;
139 FcMatrix *fc_matrix;
140
141 if (FcPatternGetMatrix (fcfont->font_pattern, FC_MATRIX, 0, &fc_matrix) == FcResultMatch)
142 {
143 FT_Matrix ft_matrix;
144
145 ft_matrix.xx = 0x10000L * fc_matrix->xx;
146 ft_matrix.yy = 0x10000L * fc_matrix->yy;
147 ft_matrix.xy = 0x10000L * fc_matrix->xy;
148 ft_matrix.yx = 0x10000L * fc_matrix->yx;
149
150 FT_Set_Transform (font->face, &ft_matrix, NULL);
151 }
152 }
153
154 FT_Face
155 pango_opengl_font_get_face (PangoFont *font)
156 {
157 PangoOpenGLFont *glfont = (PangoOpenGLFont *)font;
158 PangoFcFont *fcfont = (PangoFcFont *)font;
159 FT_Error error;
160 FcPattern *pattern;
161 FcChar8 *filename;
162 FcBool antialias, hinting, autohint;
163 int id;
164
165 pattern = fcfont->font_pattern;
166
167 if (!glfont->face)
168 {
169 glfont->load_flags = 0;
170
171 /* disable antialiasing if requested */
172 if (FcPatternGetBool (pattern, FC_ANTIALIAS, 0, &antialias) != FcResultMatch)
173 antialias = FcTrue;
174
175 glfont->load_flags |= FT_LOAD_NO_BITMAP;
176
177 /* disable hinting if requested */
178 if (FcPatternGetBool (pattern, FC_HINTING, 0, &hinting) != FcResultMatch)
179 hinting = FcTrue;
180
181 if (!hinting)
182 glfont->load_flags |= FT_LOAD_NO_HINTING;
183
184 /* force autohinting if requested */
185 if (FcPatternGetBool (pattern, FC_AUTOHINT, 0, &autohint) != FcResultMatch)
186 autohint = FcFalse;
187
188 if (autohint)
189 glfont->load_flags |= FT_LOAD_FORCE_AUTOHINT;
190
191 if (FcPatternGetString (pattern, FC_FILE, 0, &filename) != FcResultMatch)
192 goto bail0;
193
194 if (FcPatternGetInteger (pattern, FC_INDEX, 0, &id) != FcResultMatch)
195 goto bail0;
196
197 error = FT_New_Face (_pango_opengl_font_map_get_library (fcfont->fontmap),
198 (char *)filename, id, &glfont->face);
199
200 if (error != FT_Err_Ok)
201 {
202 bail0:
203 load_fallback_face (glfont, (char *)filename);
204 }
205
206 g_assert (glfont->face);
207
208 set_transform (glfont);
209
210 error = FT_Set_Char_Size (glfont->face,
211 PANGO_PIXELS_26_6 (glfont->size),
212 PANGO_PIXELS_26_6 (glfont->size),
213 0, 0);
214 if (error)
215 g_warning ("Error in FT_Set_Char_Size: %d", error);
216 }
217
218 return glfont->face;
219 }
220
221 G_DEFINE_TYPE (PangoOpenGLFont, pango_opengl_font, PANGO_TYPE_FC_FONT)
222
223 static void
224 pango_opengl_font_init (PangoOpenGLFont *font)
225 {
226 font->face = NULL;
227 font->size = 0;
228 font->glyph_info = g_hash_table_new (NULL, NULL);
229 }
230
231 static void
232 pango_opengl_font_class_init (PangoOpenGLFontClass *klass)
233 {
234 GObjectClass *object_class = G_OBJECT_CLASS (klass);
235 PangoFontClass *font_class = PANGO_FONT_CLASS (klass);
236 PangoFcFontClass *fc_font_class = PANGO_FC_FONT_CLASS (klass);
237
238 object_class->finalize = pango_opengl_font_finalize;
239
240 font_class->get_glyph_extents = pango_opengl_font_get_glyph_extents;
241
242 fc_font_class->lock_face = pango_opengl_font_real_lock_face;
243 fc_font_class->unlock_face = pango_opengl_font_real_unlock_face;
244 }
245
246 static PangoOpenGLGlyphInfo *
247 pango_opengl_font_get_glyph_info (PangoFont *font_, PangoGlyph glyph, gboolean create)
248 {
249 PangoOpenGLFont *font = (PangoOpenGLFont *)font_;
250 PangoFcFont *fcfont = (PangoFcFont *)font;
251 PangoOpenGLGlyphInfo *info;
252
253 info = (PangoOpenGLGlyphInfo *)g_hash_table_lookup (font->glyph_info, GUINT_TO_POINTER (glyph));
254
255 if ((info == NULL) && create)
256 {
257 info = g_slice_new0 (PangoOpenGLGlyphInfo);
258
259 pango_fc_font_get_raw_extents (fcfont, font->load_flags,
260 glyph,
261 &info->ink_rect,
262 &info->logical_rect);
263
264 g_hash_table_insert (font->glyph_info, GUINT_TO_POINTER(glyph), info);
265 }
266
267 return info;
268 }
269
270 PangoGlyph
271 pango_opengl_get_unknown_glyph (PangoFont *font)
272 {
273 FT_Face face = pango_opengl_font_get_face (font);
274
275 if (face && FT_IS_SFNT (face))
276 /* TrueType fonts have an 'unknown glyph' box on glyph index 0 */
277 return 0;
278 else
279 return PANGO_GLYPH_EMPTY;
280 }
281
282 static void
283 pango_opengl_font_get_glyph_extents (PangoFont *font,
284 PangoGlyph glyph,
285 PangoRectangle *ink_rect,
286 PangoRectangle *logical_rect)
287 {
288 PangoOpenGLGlyphInfo *info;
289
290 if (glyph == PANGO_GLYPH_EMPTY)
291 {
292 if (ink_rect)
293 ink_rect->x = ink_rect->y = ink_rect->height = ink_rect->width = 0;
294 if (logical_rect)
295 logical_rect->x = logical_rect->y = logical_rect->height = logical_rect->width = 0;
296 return;
297 }
298
299 if (glyph & PANGO_GLYPH_UNKNOWN_FLAG)
300 {
301 glyph = pango_opengl_get_unknown_glyph (font);
302 if (glyph == PANGO_GLYPH_EMPTY)
303 {
304 /* No unknown glyph found for the font, draw a box */
305 PangoFontMetrics *metrics = pango_font_get_metrics (font, NULL);
306
307 if (metrics)
308 {
309 if (ink_rect)
310 {
311 ink_rect->x = PANGO_SCALE;
312 ink_rect->width = metrics->approximate_char_width - 2 * PANGO_SCALE;
313 ink_rect->y = - (metrics->ascent - PANGO_SCALE);
314 ink_rect->height = metrics->ascent + metrics->descent - 2 * PANGO_SCALE;
315 }
316 if (logical_rect)
317 {
318 logical_rect->x = 0;
319 logical_rect->width = metrics->approximate_char_width;
320 logical_rect->y = -metrics->ascent;
321 logical_rect->height = metrics->ascent + metrics->descent;
322 }
323
324 pango_font_metrics_unref (metrics);
325 }
326 else
327 {
328 if (ink_rect)
329 ink_rect->x = ink_rect->y = ink_rect->height = ink_rect->width = 0;
330 if (logical_rect)
331 logical_rect->x = logical_rect->y = logical_rect->height = logical_rect->width = 0;
332 }
333
334 return;
335 }
336 }
337
338 info = pango_opengl_font_get_glyph_info (font, glyph, TRUE);
339
340 if (ink_rect)
341 *ink_rect = info->ink_rect;
342 if (logical_rect)
343 *logical_rect = info->logical_rect;
344 }
345
346 int
347 pango_opengl_font_get_kerning (PangoFont *font,
348 PangoGlyph left,
349 PangoGlyph right)
350 {
351 PangoFcFont *fc_font = PANGO_FC_FONT (font);
352
353 FT_Face face;
354 FT_Error error;
355 FT_Vector kerning;
356
357 face = pango_fc_font_lock_face (fc_font);
358 if (!face)
359 return 0;
360
361 if (!FT_HAS_KERNING (face))
362 {
363 pango_fc_font_unlock_face (fc_font);
364 return 0;
365 }
366
367 error = FT_Get_Kerning (face, left, right, ft_kerning_default, &kerning);
368 if (error != FT_Err_Ok)
369 {
370 pango_fc_font_unlock_face (fc_font);
371 return 0;
372 }
373
374 pango_fc_font_unlock_face (fc_font);
375 return PANGO_UNITS_26_6 (kerning.x);
376 }
377
378 static FT_Face
379 pango_opengl_font_real_lock_face (PangoFcFont *font)
380 {
381 return pango_opengl_font_get_face ((PangoFont *)font);
382 }
383
384 static void
385 pango_opengl_font_real_unlock_face (PangoFcFont *font)
386 {
387 }
388
389 static gboolean
390 pango_opengl_free_glyph_info_callback (gpointer key, gpointer value, gpointer data)
391 {
392 PangoOpenGLFont *font = PANGO_OPENGL_FONT (data);
393 PangoOpenGLGlyphInfo *info = (PangoOpenGLGlyphInfo *)value;
394
395 if (font->glyph_cache_destroy && info->cached_glyph)
396 (*font->glyph_cache_destroy) (info->cached_glyph);
397
398 g_slice_free (PangoOpenGLGlyphInfo, info);
399 return TRUE;
400 }
401
402 static void
403 pango_opengl_font_finalize (GObject *object)
404 {
405 PangoOpenGLFont *font = (PangoOpenGLFont *)object;
406
407 if (font->face)
408 {
409 FT_Done_Face (font->face);
410 font->face = NULL;
411 }
412
413 g_hash_table_foreach_remove (font->glyph_info, pango_opengl_free_glyph_info_callback, object);
414 g_hash_table_destroy (font->glyph_info);
415
416 G_OBJECT_CLASS (pango_opengl_font_parent_class)->finalize (object);
417 }
418
419 PangoCoverage *
420 pango_opengl_font_get_coverage (PangoFont *font, PangoLanguage *language)
421 {
422 return pango_font_get_coverage (font, language);
423 }
424
425 void *
426 _pango_opengl_font_get_cache_glyph_data (PangoFont *font, int glyph_index)
427 {
428 PangoOpenGLGlyphInfo *info = pango_opengl_font_get_glyph_info (font, glyph_index, FALSE);
429
430 return info ? info->cached_glyph : 0;
431 }
432
433 void
434 _pango_opengl_font_set_cache_glyph_data (PangoFont *font, int glyph_index, void *cached_glyph)
435 {
436 PangoOpenGLGlyphInfo *info = pango_opengl_font_get_glyph_info (font, glyph_index, TRUE);
437 info->cached_glyph = cached_glyph;
438 }
439
440 void
441 _pango_opengl_font_set_glyph_cache_destroy (PangoFont *font, GDestroyNotify destroy_notify)
442 {
443 PANGO_OPENGL_FONT (font)->glyph_cache_destroy = destroy_notify;
444 }