1 | /* Pango |
2 | * pangoft2-fontmap.c: |
3 | * |
4 | * Copyright (C) 2000 Red Hat Software |
5 | * Copyright (C) 2000 Tor Lillqvist |
6 | * |
7 | * This library is free software; you can redistribute it and/or |
8 | * modify it under the terms of the GNU Library General Public |
9 | * License as published by the Free Software Foundation; either |
10 | * version 2 of the License, or (at your option) any later version. |
11 | * |
12 | * This library is distributed in the hope that it will be useful, |
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
15 | * Library General Public License for more details. |
16 | * |
17 | * You should have received a copy of the GNU Library General Public |
18 | * License along with this library; if not, write to the |
19 | * Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
20 | * Boston, MA 02111-1307, USA. |
21 | */ |
22 | |
23 | #include "config.h" |
24 | |
25 | #include <glib.h> |
26 | #include <stdio.h> |
27 | #include <stdlib.h> |
28 | #include <string.h> |
29 | #include <errno.h> |
30 | |
31 | #include <fontconfig/fontconfig.h> |
32 | |
33 | #include "pango-impl-utils.h" |
34 | #include "pangoft2-private.h" |
35 | #include "pangofc-fontmap.h" |
36 | |
37 | typedef struct _PangoFT2Family PangoFT2Family; |
38 | typedef struct _PangoFT2FontMapClass PangoFT2FontMapClass; |
39 | |
40 | /** |
41 | * PangoFT2FontMap: |
42 | * |
43 | * The `PangoFT2FontMap` is the `PangoFontMap` implementation for FreeType fonts. |
44 | */ |
45 | struct _PangoFT2FontMap |
46 | { |
47 | PangoFcFontMap parent_instance; |
48 | |
49 | FT_Library library; |
50 | |
51 | guint serial; |
52 | double dpi_x; |
53 | double dpi_y; |
54 | |
55 | PangoRenderer *renderer; |
56 | }; |
57 | |
58 | struct _PangoFT2FontMapClass |
59 | { |
60 | PangoFcFontMapClass parent_class; |
61 | }; |
62 | |
63 | static void pango_ft2_font_map_finalize (GObject *object); |
64 | static PangoFcFont * pango_ft2_font_map_new_font (PangoFcFontMap *fcfontmap, |
65 | FcPattern *pattern); |
66 | static double pango_ft2_font_map_get_resolution (PangoFcFontMap *fcfontmap, |
67 | PangoContext *context); |
68 | static guint pango_ft2_font_map_get_serial (PangoFontMap *fontmap); |
69 | static void pango_ft2_font_map_changed (PangoFontMap *fontmap); |
70 | |
71 | static PangoFT2FontMap *pango_ft2_global_fontmap = NULL; /* MT-safe */ |
72 | |
73 | G_DEFINE_TYPE (PangoFT2FontMap, pango_ft2_font_map, PANGO_TYPE_FC_FONT_MAP) |
74 | |
75 | static void |
76 | pango_ft2_font_map_class_init (PangoFT2FontMapClass *class) |
77 | { |
78 | GObjectClass *gobject_class = G_OBJECT_CLASS (class); |
79 | PangoFontMapClass *fontmap_class = PANGO_FONT_MAP_CLASS (class); |
80 | PangoFcFontMapClass *fcfontmap_class = PANGO_FC_FONT_MAP_CLASS (class); |
81 | |
82 | gobject_class->finalize = pango_ft2_font_map_finalize; |
83 | fontmap_class->get_serial = pango_ft2_font_map_get_serial; |
84 | fontmap_class->changed = pango_ft2_font_map_changed; |
85 | fcfontmap_class->default_substitute = _pango_ft2_font_map_default_substitute; |
86 | fcfontmap_class->new_font = pango_ft2_font_map_new_font; |
87 | fcfontmap_class->get_resolution = pango_ft2_font_map_get_resolution; |
88 | } |
89 | |
90 | static void |
91 | pango_ft2_font_map_init (PangoFT2FontMap *fontmap) |
92 | { |
93 | FT_Error error; |
94 | |
95 | fontmap->serial = 1; |
96 | fontmap->library = NULL; |
97 | fontmap->dpi_x = 72.0; |
98 | fontmap->dpi_y = 72.0; |
99 | |
100 | error = FT_Init_FreeType (alibrary: &fontmap->library); |
101 | if (error != FT_Err_Ok) |
102 | g_critical ("pango_ft2_font_map_init: Could not initialize freetype" ); |
103 | } |
104 | |
105 | static void |
106 | pango_ft2_font_map_finalize (GObject *object) |
107 | { |
108 | PangoFT2FontMap *ft2fontmap = PANGO_FT2_FONT_MAP (object); |
109 | |
110 | if (ft2fontmap->renderer) |
111 | g_object_unref (object: ft2fontmap->renderer); |
112 | |
113 | G_OBJECT_CLASS (pango_ft2_font_map_parent_class)->finalize (object); |
114 | |
115 | FT_Done_FreeType (library: ft2fontmap->library); |
116 | } |
117 | |
118 | /** |
119 | * pango_ft2_font_map_new: |
120 | * |
121 | * Create a new `PangoFT2FontMap` object. |
122 | * |
123 | * A fontmap is used to cache information about available fonts, |
124 | * and holds certain global parameters such as the resolution and |
125 | * the default substitute function (see |
126 | * [method@PangoFT2.FontMap.set_default_substitute]). |
127 | * |
128 | * Return value: the newly created fontmap object. Unref |
129 | * with g_object_unref() when you are finished with it. |
130 | * |
131 | * Since: 1.2 |
132 | **/ |
133 | PangoFontMap * |
134 | pango_ft2_font_map_new (void) |
135 | { |
136 | return (PangoFontMap *) g_object_new (PANGO_TYPE_FT2_FONT_MAP, NULL); |
137 | } |
138 | |
139 | static guint |
140 | pango_ft2_font_map_get_serial (PangoFontMap *fontmap) |
141 | { |
142 | PangoFT2FontMap *ft2fontmap = PANGO_FT2_FONT_MAP (fontmap); |
143 | |
144 | return ft2fontmap->serial; |
145 | } |
146 | |
147 | static void |
148 | pango_ft2_font_map_changed (PangoFontMap *fontmap) |
149 | { |
150 | PangoFT2FontMap *ft2fontmap = PANGO_FT2_FONT_MAP (fontmap); |
151 | |
152 | ft2fontmap->serial++; |
153 | if (ft2fontmap->serial == 0) |
154 | ft2fontmap->serial++; |
155 | } |
156 | |
157 | /** |
158 | * pango_ft2_font_map_set_default_substitute: |
159 | * @fontmap: a `PangoFT2FontMap` |
160 | * @func: function to call to to do final config tweaking |
161 | * on #FcPattern objects. |
162 | * @data: data to pass to @func |
163 | * @notify: function to call when @data is no longer used. |
164 | * |
165 | * Sets a function that will be called to do final configuration |
166 | * substitution on a `FcPattern` before it is used to load |
167 | * the font. |
168 | * |
169 | * This function can be used to do things like set |
170 | * hinting and antialiasing options. |
171 | * |
172 | * Deprecated: 1.46: Use [method@PangoFc.FontMap.set_default_substitute] |
173 | * instead. |
174 | * |
175 | * Since: 1.2 |
176 | **/ |
177 | void |
178 | pango_ft2_font_map_set_default_substitute (PangoFT2FontMap *fontmap, |
179 | PangoFT2SubstituteFunc func, |
180 | gpointer data, |
181 | GDestroyNotify notify) |
182 | { |
183 | PangoFcFontMap *fcfontmap = PANGO_FC_FONT_MAP (fontmap); |
184 | pango_fc_font_map_set_default_substitute(fontmap: fcfontmap, func, data, notify); |
185 | } |
186 | |
187 | /** |
188 | * pango_ft2_font_map_substitute_changed: |
189 | * @fontmap: a `PangoFT2FontMap` |
190 | * |
191 | * Call this function any time the results of the |
192 | * default substitution function set with |
193 | * pango_ft2_font_map_set_default_substitute() change. |
194 | * |
195 | * That is, if your substitution function will return different |
196 | * results for the same input pattern, you must call this function. |
197 | * |
198 | * Deprecated: 1.46: Use [method@PangoFc.FontMap.substitute_changed] |
199 | * instead. |
200 | * |
201 | * Since: 1.2 |
202 | **/ |
203 | void |
204 | pango_ft2_font_map_substitute_changed (PangoFT2FontMap *fontmap) |
205 | { |
206 | pango_fc_font_map_substitute_changed(PANGO_FC_FONT_MAP (fontmap)); |
207 | } |
208 | |
209 | /** |
210 | * pango_ft2_font_map_set_resolution: |
211 | * @fontmap: a `PangoFT2FontMap` |
212 | * @dpi_x: dots per inch in the X direction |
213 | * @dpi_y: dots per inch in the Y direction |
214 | * |
215 | * Sets the horizontal and vertical resolutions for the fontmap. |
216 | * |
217 | * Since: 1.2 |
218 | **/ |
219 | void |
220 | pango_ft2_font_map_set_resolution (PangoFT2FontMap *fontmap, |
221 | double dpi_x, |
222 | double dpi_y) |
223 | { |
224 | g_return_if_fail (PANGO_FT2_IS_FONT_MAP (fontmap)); |
225 | |
226 | fontmap->dpi_x = dpi_x; |
227 | fontmap->dpi_y = dpi_y; |
228 | |
229 | pango_ft2_font_map_substitute_changed (fontmap); |
230 | } |
231 | |
232 | /** |
233 | * pango_ft2_font_map_create_context: (skip) |
234 | * @fontmap: a `PangoFT2FontMap` |
235 | * |
236 | * Create a `PangoContext` for the given fontmap. |
237 | * |
238 | * Return value: (transfer full): the newly created context; free with |
239 | * g_object_unref(). |
240 | * |
241 | * Since: 1.2 |
242 | * |
243 | * Deprecated: 1.22: Use [method@Pango.FontMap.create_context] instead. |
244 | **/ |
245 | PangoContext * |
246 | pango_ft2_font_map_create_context (PangoFT2FontMap *fontmap) |
247 | { |
248 | g_return_val_if_fail (PANGO_FT2_IS_FONT_MAP (fontmap), NULL); |
249 | |
250 | return pango_font_map_create_context (PANGO_FONT_MAP (fontmap)); |
251 | } |
252 | |
253 | /** |
254 | * pango_ft2_get_context: (skip) |
255 | * @dpi_x: the horizontal DPI of the target device |
256 | * @dpi_y: the vertical DPI of the target device |
257 | * |
258 | * Retrieves a `PangoContext` for the default PangoFT2 fontmap |
259 | * (see pango_ft2_font_map_for_display()) and sets the resolution |
260 | * for the default fontmap to @dpi_x by @dpi_y. |
261 | * |
262 | * Return value: (transfer full): the new `PangoContext` |
263 | * |
264 | * Deprecated: 1.22: Use [method@Pango.FontMap.create_context] instead. |
265 | **/ |
266 | G_GNUC_BEGIN_IGNORE_DEPRECATIONS |
267 | PangoContext * |
268 | pango_ft2_get_context (double dpi_x, double dpi_y) |
269 | { |
270 | PangoFontMap *fontmap; |
271 | |
272 | fontmap = pango_ft2_font_map_for_display (); |
273 | pango_ft2_font_map_set_resolution (PANGO_FT2_FONT_MAP (fontmap), dpi_x, dpi_y); |
274 | |
275 | return pango_font_map_create_context (fontmap); |
276 | } |
277 | G_GNUC_END_IGNORE_DEPRECATIONS |
278 | |
279 | /** |
280 | * pango_ft2_font_map_for_display: (skip) |
281 | * |
282 | * Returns a `PangoFT2FontMap`. |
283 | * |
284 | * This font map is cached and should |
285 | * not be freed. If the font map is no longer needed, it can |
286 | * be released with pango_ft2_shutdown_display(). Use of the |
287 | * global PangoFT2 fontmap is deprecated; use pango_ft2_font_map_new() |
288 | * instead. |
289 | * |
290 | * Return value: (transfer none): a `PangoFT2FontMap`. |
291 | **/ |
292 | PangoFontMap * |
293 | pango_ft2_font_map_for_display (void) |
294 | { |
295 | if (g_once_init_enter (&pango_ft2_global_fontmap)) |
296 | g_once_init_leave (&pango_ft2_global_fontmap, PANGO_FT2_FONT_MAP (pango_ft2_font_map_new ())); |
297 | |
298 | return PANGO_FONT_MAP (pango_ft2_global_fontmap); |
299 | } |
300 | |
301 | /** |
302 | * pango_ft2_shutdown_display: |
303 | * |
304 | * Free the global fontmap. (See pango_ft2_font_map_for_display()) |
305 | * Use of the global PangoFT2 fontmap is deprecated. |
306 | **/ |
307 | void |
308 | pango_ft2_shutdown_display (void) |
309 | { |
310 | if (pango_ft2_global_fontmap) |
311 | { |
312 | pango_fc_font_map_cache_clear (PANGO_FC_FONT_MAP (pango_ft2_global_fontmap)); |
313 | |
314 | g_object_unref (object: pango_ft2_global_fontmap); |
315 | |
316 | pango_ft2_global_fontmap = NULL; |
317 | } |
318 | } |
319 | |
320 | FT_Library |
321 | _pango_ft2_font_map_get_library (PangoFontMap *fontmap) |
322 | { |
323 | PangoFT2FontMap *ft2fontmap = (PangoFT2FontMap *)fontmap; |
324 | |
325 | return ft2fontmap->library; |
326 | } |
327 | |
328 | |
329 | /** |
330 | * _pango_ft2_font_map_get_renderer: |
331 | * @fontmap: a `PangoFT2FontMap` |
332 | * |
333 | * Gets the singleton PangoFT2Renderer for this fontmap. |
334 | * |
335 | * Return value: the renderer. |
336 | **/ |
337 | PangoRenderer * |
338 | _pango_ft2_font_map_get_renderer (PangoFT2FontMap *ft2fontmap) |
339 | { |
340 | if (!ft2fontmap->renderer) |
341 | ft2fontmap->renderer = g_object_new (PANGO_TYPE_FT2_RENDERER, NULL); |
342 | |
343 | return ft2fontmap->renderer; |
344 | } |
345 | |
346 | void |
347 | _pango_ft2_font_map_default_substitute (PangoFcFontMap *fcfontmap, |
348 | FcPattern *pattern) |
349 | { |
350 | PangoFT2FontMap *ft2fontmap = PANGO_FT2_FONT_MAP (fcfontmap); |
351 | FcValue v; |
352 | |
353 | FcConfigSubstitute (NULL, p: pattern, kind: FcMatchPattern); |
354 | |
355 | if (fcfontmap->substitute_func) |
356 | fcfontmap->substitute_func (pattern, fcfontmap->substitute_data); |
357 | |
358 | if (FcPatternGet (p: pattern, FC_DPI, id: 0, v: &v) == FcResultNoMatch) |
359 | FcPatternAddDouble (p: pattern, FC_DPI, d: ft2fontmap->dpi_y); |
360 | FcDefaultSubstitute (pattern); |
361 | } |
362 | |
363 | static double |
364 | pango_ft2_font_map_get_resolution (PangoFcFontMap *fcfontmap, |
365 | PangoContext *context G_GNUC_UNUSED) |
366 | { |
367 | return ((PangoFT2FontMap *)fcfontmap)->dpi_y; |
368 | } |
369 | |
370 | static PangoFcFont * |
371 | pango_ft2_font_map_new_font (PangoFcFontMap *fcfontmap, |
372 | FcPattern *pattern) |
373 | { |
374 | return (PangoFcFont *)_pango_ft2_font_new (PANGO_FT2_FONT_MAP (fcfontmap), pattern); |
375 | } |
376 | |