ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/Deliantra-Client/pango-font.c
Revision: 1.5
Committed: Sun Nov 18 00:52:22 2018 UTC (5 years, 5 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

# 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 root 1.4 #if PANGO_VERSION_CHECK (1, 16, 0)
76 root 1.3 /* 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 root 1.5 /* unfortunately, pango doesn't support runtime checks in < 1.16 */
80 root 1.4 /* so there is no real way to ensure binary compatibility portably */
81 root 1.5 /* great move, pango */
82 root 1.3 if (pango_version () > PANGO_VERSION_ENCODE (1, 23, 0))
83     PANGO_FC_FONT (font)->fontmap = fontmap;
84 root 1.4 #endif
85 root 1.3
86 root 1.1 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 root 1.5 pango_opengl_font_class_init (PangoOpenGLFontClass *klass)
233 root 1.1 {
234 root 1.5 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 root 1.1
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 root 1.5 info = (PangoOpenGLGlyphInfo *)g_hash_table_lookup (font->glyph_info, GUINT_TO_POINTER (glyph));
254 root 1.1
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 root 1.5 PangoOpenGLGlyphInfo *info = (PangoOpenGLGlyphInfo *)value;
394 root 1.1
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     }