ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/Deliantra-Client/pango-font.c
Revision: 1.1
Committed: Tue Jul 4 23:23:31 2006 UTC (17 years, 10 months ago) by root
Content type: text/plain
Branch: MAIN
CVS Tags: rel-0_97, rel-0_98, rel-0_99, rel-0_9958, rel-0_9960, rel-0_52, rel-0_53, rel-0_51, rel-0_9956, rel-0_2, rel-0_5, rel-0_9957, rel-0_9955, rel-0_9959, rel-0_995
Log Message:
Get rid of cairo completely (yay!) and of ft2 factually (still need the
library as it included pangofc), by introducing a custom pango opengl
renderer.

Text rendering now no longer requires the distinction between rgba and
grayscale modes, requires much less texture space and memory, and is
faster on accelerated hardware (and possibly with software rendering, too).

All at the cost of only 1200 lines or so.

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