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

# User Rev Content
1 root 1.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     }