ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/Deliantra-Client/pango-font.c
Revision: 1.2
Committed: Wed Dec 26 11:10:53 2007 UTC (16 years, 4 months ago) by root
Content type: text/plain
Branch: MAIN
CVS Tags: rel-2_03, rel-2_02, rel-0_9965, rel-0_9964, rel-0_9963, rel-0_9968, rel-2_0, rel-0_9972, rel-0_9973, rel-0_9974, rel-0_9975, rel-0_9976, rel-0_9977, rel-0_9978, rel-0_9971, rel-0_9967, rel-1_21, rel-0_9966
Changes since 1.1: +0 -1 lines
Log Message:
update dejavu fonts

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