ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/Deliantra-Client/pango-font.c
Revision: 1.3
Committed: Sun Apr 5 19:28:54 2009 UTC (15 years, 1 month ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.2: +6 -0 lines
Log Message:
*** empty log message ***

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 /* pango 1.24 is ABI-incompatible with 1.22, but distros */
76 /* usually package it under the same name, so a runtime check */
77 /* is required */
78 if (pango_version () > PANGO_VERSION_ENCODE (1, 23, 0))
79 PANGO_FC_FONT (font)->fontmap = fontmap;
80
81 return font;
82 }
83
84 static void
85 load_fallback_face (PangoOpenGLFont *font, const char *original_file)
86 {
87 PangoFcFont *fcfont = PANGO_FC_FONT (font);
88 FcPattern *sans;
89 FcPattern *matched;
90 FcResult result;
91 FT_Error error;
92 FcChar8 *filename2 = NULL;
93 gchar *name;
94 int id;
95
96 sans = FcPatternBuild (NULL,
97 FC_FAMILY, FcTypeString, "sans",
98 FC_PIXEL_SIZE, FcTypeDouble, (double)font->size / PANGO_SCALE,
99 NULL);
100
101 matched = FcFontMatch (NULL, sans, &result);
102
103 if (FcPatternGetString (matched, FC_FILE, 0, &filename2) != FcResultMatch)
104 goto bail1;
105
106 if (FcPatternGetInteger (matched, FC_INDEX, 0, &id) != FcResultMatch)
107 goto bail1;
108
109 error = FT_New_Face (_pango_opengl_font_map_get_library (fcfont->fontmap),
110 (char *) filename2, id, &font->face);
111
112 if (error)
113 {
114 bail1:
115 name = pango_font_description_to_string (fcfont->description);
116 g_warning ("Unable to open font file %s for font %s, exiting\n", filename2, name);
117 exit (1);
118 }
119 else
120 {
121 name = pango_font_description_to_string (fcfont->description);
122 g_warning ("Unable to open font file %s for font %s, falling back to %s\n", original_file, name, filename2);
123 g_free (name);
124 }
125
126 FcPatternDestroy (sans);
127 FcPatternDestroy (matched);
128 }
129
130 static void
131 set_transform (PangoOpenGLFont *font)
132 {
133 PangoFcFont *fcfont = (PangoFcFont *)font;
134 FcMatrix *fc_matrix;
135
136 if (FcPatternGetMatrix (fcfont->font_pattern, FC_MATRIX, 0, &fc_matrix) == FcResultMatch)
137 {
138 FT_Matrix ft_matrix;
139
140 ft_matrix.xx = 0x10000L * fc_matrix->xx;
141 ft_matrix.yy = 0x10000L * fc_matrix->yy;
142 ft_matrix.xy = 0x10000L * fc_matrix->xy;
143 ft_matrix.yx = 0x10000L * fc_matrix->yx;
144
145 FT_Set_Transform (font->face, &ft_matrix, NULL);
146 }
147 }
148
149 FT_Face
150 pango_opengl_font_get_face (PangoFont *font)
151 {
152 PangoOpenGLFont *glfont = (PangoOpenGLFont *)font;
153 PangoFcFont *fcfont = (PangoFcFont *)font;
154 FT_Error error;
155 FcPattern *pattern;
156 FcChar8 *filename;
157 FcBool antialias, hinting, autohint;
158 int id;
159
160 pattern = fcfont->font_pattern;
161
162 if (!glfont->face)
163 {
164 glfont->load_flags = 0;
165
166 /* disable antialiasing if requested */
167 if (FcPatternGetBool (pattern, FC_ANTIALIAS, 0, &antialias) != FcResultMatch)
168 antialias = FcTrue;
169
170 glfont->load_flags |= FT_LOAD_NO_BITMAP;
171
172 /* disable hinting if requested */
173 if (FcPatternGetBool (pattern, FC_HINTING, 0, &hinting) != FcResultMatch)
174 hinting = FcTrue;
175
176 if (!hinting)
177 glfont->load_flags |= FT_LOAD_NO_HINTING;
178
179 /* force autohinting if requested */
180 if (FcPatternGetBool (pattern, FC_AUTOHINT, 0, &autohint) != FcResultMatch)
181 autohint = FcFalse;
182
183 if (autohint)
184 glfont->load_flags |= FT_LOAD_FORCE_AUTOHINT;
185
186 if (FcPatternGetString (pattern, FC_FILE, 0, &filename) != FcResultMatch)
187 goto bail0;
188
189 if (FcPatternGetInteger (pattern, FC_INDEX, 0, &id) != FcResultMatch)
190 goto bail0;
191
192 error = FT_New_Face (_pango_opengl_font_map_get_library (fcfont->fontmap),
193 (char *)filename, id, &glfont->face);
194
195 if (error != FT_Err_Ok)
196 {
197 bail0:
198 load_fallback_face (glfont, (char *)filename);
199 }
200
201 g_assert (glfont->face);
202
203 set_transform (glfont);
204
205 error = FT_Set_Char_Size (glfont->face,
206 PANGO_PIXELS_26_6 (glfont->size),
207 PANGO_PIXELS_26_6 (glfont->size),
208 0, 0);
209 if (error)
210 g_warning ("Error in FT_Set_Char_Size: %d", error);
211 }
212
213 return glfont->face;
214 }
215
216 G_DEFINE_TYPE (PangoOpenGLFont, pango_opengl_font, PANGO_TYPE_FC_FONT)
217
218 static void
219 pango_opengl_font_init (PangoOpenGLFont *font)
220 {
221 font->face = NULL;
222 font->size = 0;
223 font->glyph_info = g_hash_table_new (NULL, NULL);
224 }
225
226 static void
227 pango_opengl_font_class_init (PangoOpenGLFontClass *class)
228 {
229 GObjectClass *object_class = G_OBJECT_CLASS (class);
230 PangoFontClass *font_class = PANGO_FONT_CLASS (class);
231 PangoFcFontClass *fc_font_class = PANGO_FC_FONT_CLASS (class);
232
233 object_class->finalize = pango_opengl_font_finalize;
234
235 font_class->get_glyph_extents = pango_opengl_font_get_glyph_extents;
236
237 fc_font_class->lock_face = pango_opengl_font_real_lock_face;
238 fc_font_class->unlock_face = pango_opengl_font_real_unlock_face;
239 }
240
241 static PangoOpenGLGlyphInfo *
242 pango_opengl_font_get_glyph_info (PangoFont *font_, PangoGlyph glyph, gboolean create)
243 {
244 PangoOpenGLFont *font = (PangoOpenGLFont *)font_;
245 PangoFcFont *fcfont = (PangoFcFont *)font;
246 PangoOpenGLGlyphInfo *info;
247
248 info = g_hash_table_lookup (font->glyph_info, GUINT_TO_POINTER (glyph));
249
250 if ((info == NULL) && create)
251 {
252 info = g_slice_new0 (PangoOpenGLGlyphInfo);
253
254 pango_fc_font_get_raw_extents (fcfont, font->load_flags,
255 glyph,
256 &info->ink_rect,
257 &info->logical_rect);
258
259 g_hash_table_insert (font->glyph_info, GUINT_TO_POINTER(glyph), info);
260 }
261
262 return info;
263 }
264
265 PangoGlyph
266 pango_opengl_get_unknown_glyph (PangoFont *font)
267 {
268 FT_Face face = pango_opengl_font_get_face (font);
269
270 if (face && FT_IS_SFNT (face))
271 /* TrueType fonts have an 'unknown glyph' box on glyph index 0 */
272 return 0;
273 else
274 return PANGO_GLYPH_EMPTY;
275 }
276
277 static void
278 pango_opengl_font_get_glyph_extents (PangoFont *font,
279 PangoGlyph glyph,
280 PangoRectangle *ink_rect,
281 PangoRectangle *logical_rect)
282 {
283 PangoOpenGLGlyphInfo *info;
284
285 if (glyph == PANGO_GLYPH_EMPTY)
286 {
287 if (ink_rect)
288 ink_rect->x = ink_rect->y = ink_rect->height = ink_rect->width = 0;
289 if (logical_rect)
290 logical_rect->x = logical_rect->y = logical_rect->height = logical_rect->width = 0;
291 return;
292 }
293
294 if (glyph & PANGO_GLYPH_UNKNOWN_FLAG)
295 {
296 glyph = pango_opengl_get_unknown_glyph (font);
297 if (glyph == PANGO_GLYPH_EMPTY)
298 {
299 /* No unknown glyph found for the font, draw a box */
300 PangoFontMetrics *metrics = pango_font_get_metrics (font, NULL);
301
302 if (metrics)
303 {
304 if (ink_rect)
305 {
306 ink_rect->x = PANGO_SCALE;
307 ink_rect->width = metrics->approximate_char_width - 2 * PANGO_SCALE;
308 ink_rect->y = - (metrics->ascent - PANGO_SCALE);
309 ink_rect->height = metrics->ascent + metrics->descent - 2 * PANGO_SCALE;
310 }
311 if (logical_rect)
312 {
313 logical_rect->x = 0;
314 logical_rect->width = metrics->approximate_char_width;
315 logical_rect->y = -metrics->ascent;
316 logical_rect->height = metrics->ascent + metrics->descent;
317 }
318
319 pango_font_metrics_unref (metrics);
320 }
321 else
322 {
323 if (ink_rect)
324 ink_rect->x = ink_rect->y = ink_rect->height = ink_rect->width = 0;
325 if (logical_rect)
326 logical_rect->x = logical_rect->y = logical_rect->height = logical_rect->width = 0;
327 }
328
329 return;
330 }
331 }
332
333 info = pango_opengl_font_get_glyph_info (font, glyph, TRUE);
334
335 if (ink_rect)
336 *ink_rect = info->ink_rect;
337 if (logical_rect)
338 *logical_rect = info->logical_rect;
339 }
340
341 int
342 pango_opengl_font_get_kerning (PangoFont *font,
343 PangoGlyph left,
344 PangoGlyph right)
345 {
346 PangoFcFont *fc_font = PANGO_FC_FONT (font);
347
348 FT_Face face;
349 FT_Error error;
350 FT_Vector kerning;
351
352 face = pango_fc_font_lock_face (fc_font);
353 if (!face)
354 return 0;
355
356 if (!FT_HAS_KERNING (face))
357 {
358 pango_fc_font_unlock_face (fc_font);
359 return 0;
360 }
361
362 error = FT_Get_Kerning (face, left, right, ft_kerning_default, &kerning);
363 if (error != FT_Err_Ok)
364 {
365 pango_fc_font_unlock_face (fc_font);
366 return 0;
367 }
368
369 pango_fc_font_unlock_face (fc_font);
370 return PANGO_UNITS_26_6 (kerning.x);
371 }
372
373 static FT_Face
374 pango_opengl_font_real_lock_face (PangoFcFont *font)
375 {
376 return pango_opengl_font_get_face ((PangoFont *)font);
377 }
378
379 static void
380 pango_opengl_font_real_unlock_face (PangoFcFont *font)
381 {
382 }
383
384 static gboolean
385 pango_opengl_free_glyph_info_callback (gpointer key, gpointer value, gpointer data)
386 {
387 PangoOpenGLFont *font = PANGO_OPENGL_FONT (data);
388 PangoOpenGLGlyphInfo *info = value;
389
390 if (font->glyph_cache_destroy && info->cached_glyph)
391 (*font->glyph_cache_destroy) (info->cached_glyph);
392
393 g_slice_free (PangoOpenGLGlyphInfo, info);
394 return TRUE;
395 }
396
397 static void
398 pango_opengl_font_finalize (GObject *object)
399 {
400 PangoOpenGLFont *font = (PangoOpenGLFont *)object;
401
402 if (font->face)
403 {
404 FT_Done_Face (font->face);
405 font->face = NULL;
406 }
407
408 g_hash_table_foreach_remove (font->glyph_info, pango_opengl_free_glyph_info_callback, object);
409 g_hash_table_destroy (font->glyph_info);
410
411 G_OBJECT_CLASS (pango_opengl_font_parent_class)->finalize (object);
412 }
413
414 PangoCoverage *
415 pango_opengl_font_get_coverage (PangoFont *font, PangoLanguage *language)
416 {
417 return pango_font_get_coverage (font, language);
418 }
419
420 void *
421 _pango_opengl_font_get_cache_glyph_data (PangoFont *font, int glyph_index)
422 {
423 PangoOpenGLGlyphInfo *info = pango_opengl_font_get_glyph_info (font, glyph_index, FALSE);
424
425 return info ? info->cached_glyph : 0;
426 }
427
428 void
429 _pango_opengl_font_set_cache_glyph_data (PangoFont *font, int glyph_index, void *cached_glyph)
430 {
431 PangoOpenGLGlyphInfo *info = pango_opengl_font_get_glyph_info (font, glyph_index, TRUE);
432 info->cached_glyph = cached_glyph;
433 }
434
435 void
436 _pango_opengl_font_set_glyph_cache_destroy (PangoFont *font, GDestroyNotify destroy_notify)
437 {
438 PANGO_OPENGL_FONT (font)->glyph_cache_destroy = destroy_notify;
439 }