Git init
[external/pango1.0.git] / pango / pangocairo-win32font.c
1 /* Pango
2  * pangocairowin32-font.c: Cairo font handling, Win32 backend
3  *
4  * Copyright (C) 2000-2005 Red Hat Software
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Library General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Library General Public License for more details.
15  *
16  * You should have received a copy of the GNU Library General Public
17  * License along with this library; if not, write to the
18  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19  * Boston, MA 02111-1307, USA.
20  */
21
22 #include "config.h"
23
24 #include <math.h>
25 #include <stdlib.h>
26 #include <string.h>
27
28 #include "pango-fontmap.h"
29 #include "pango-impl-utils.h"
30 #include "pangocairo-private.h"
31 #include "pangocairo-win32.h"
32
33 #include <cairo-win32.h>
34
35 #define PANGO_TYPE_CAIRO_WIN32_FONT           (pango_cairo_win32_font_get_type ())
36 #define PANGO_CAIRO_WIN32_FONT(object)        (G_TYPE_CHECK_INSTANCE_CAST ((object), PANGO_TYPE_CAIRO_WIN32_FONT, PangoCairoWin32Font))
37 #define PANGO_CAIRO_WIN32_FONT_CLASS(klass)   (G_TYPE_CHECK_CLASS_CAST ((klass), PANGO_TYPE_CAIRO_WIN32_FONT, PangoCairoWin32FontClass))
38 #define PANGO_CAIRO_IS_FONT_CLASS(klass)   (G_TYPE_CHECK_CLASS_TYPE ((klass), PANGO_TYPE_CAIRO_WIN32_FONT))
39 #define PANGO_CAIRO_WIN32_FONT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PANGO_TYPE_CAIRO_WIN32_FONT, PangoCairoWin32FontClass))
40
41 typedef struct _PangoCairoWin32Font      PangoCairoWin32Font;
42 typedef struct _PangoCairoWin32FontClass PangoCairoWin32FontClass;
43
44 struct _PangoCairoWin32Font
45 {
46   PangoWin32Font font;
47   PangoCairoFontPrivate cf_priv;
48 };
49
50 struct _PangoCairoWin32FontClass
51 {
52   PangoWin32FontClass  parent_class;
53 };
54
55 GType pango_cairo_win32_font_get_type (void);
56
57 static cairo_font_face_t *pango_cairo_win32_font_create_font_face           (PangoCairoFont *font);
58 static PangoFontMetrics  *pango_cairo_win32_font_create_metrics_for_context (PangoCairoFont *font,
59                                                                              PangoContext    *context);
60
61
62 static void
63 cairo_font_iface_init (PangoCairoFontIface *iface)
64 {
65   iface->create_font_face = pango_cairo_win32_font_create_font_face;
66   iface->create_metrics_for_context = pango_cairo_win32_font_create_metrics_for_context;
67   iface->cf_priv_offset = G_STRUCT_OFFSET (PangoCairoWin32Font, cf_priv);
68 }
69
70 G_DEFINE_TYPE_WITH_CODE (PangoCairoWin32Font, pango_cairo_win32_font, PANGO_TYPE_WIN32_FONT,
71     { G_IMPLEMENT_INTERFACE (PANGO_TYPE_CAIRO_FONT, cairo_font_iface_init) });
72
73 static cairo_font_face_t *
74 pango_cairo_win32_font_create_font_face (PangoCairoFont *font)
75 {
76   PangoCairoWin32Font *cwfont = PANGO_CAIRO_WIN32_FONT (font);
77   PangoWin32Font *win32font =  &cwfont->font;
78
79   return cairo_win32_font_face_create_for_logfontw (&win32font->logfontw);
80 }
81
82 static int
83 max_glyph_width (PangoLayout *layout)
84 {
85   int max_width = 0;
86   GSList *l, *r;
87
88   for (l = pango_layout_get_lines_readonly (layout); l; l = l->next)
89     {
90       PangoLayoutLine *line = l->data;
91
92       for (r = line->runs; r; r = r->next)
93         {
94           PangoGlyphString *glyphs = ((PangoGlyphItem *)r->data)->glyphs;
95           int i;
96
97           for (i = 0; i < glyphs->num_glyphs; i++)
98             if (glyphs->glyphs[i].geometry.width > max_width)
99               max_width = glyphs->glyphs[i].geometry.width;
100         }
101     }
102
103   return max_width;
104 }
105
106 static PangoFontMetrics *
107 pango_cairo_win32_font_create_metrics_for_context (PangoCairoFont *font,
108                                                    PangoContext   *context)
109 {
110   PangoFontMetrics *metrics;
111   PangoFontDescription *font_desc;
112   PangoLayout *layout;
113   PangoRectangle extents;
114   PangoLanguage *language = pango_context_get_language (context);
115   const char *sample_str = pango_language_get_sample_string (language);
116   cairo_scaled_font_t *scaled_font;
117   cairo_font_extents_t font_extents;
118   double height;
119
120   metrics = pango_font_metrics_new ();
121
122   scaled_font = pango_cairo_font_get_scaled_font ((PangoFont *) font);
123
124   cairo_scaled_font_extents (scaled_font, &font_extents);
125   cairo_win32_scaled_font_done_font (scaled_font);
126
127   metrics->ascent = font_extents.ascent * PANGO_SCALE;
128   metrics->descent = font_extents.descent * PANGO_SCALE;
129
130   /* FIXME: Should get the real settings for these from the TrueType
131    * font file.
132    */
133   height = metrics->ascent + metrics->descent;
134   metrics->underline_thickness = height / 14;
135   metrics->underline_position = - metrics->underline_thickness;
136   metrics->strikethrough_thickness = metrics->underline_thickness;
137   metrics->strikethrough_position = height / 4;
138
139   pango_quantize_line_geometry (&metrics->underline_thickness,
140                                 &metrics->underline_position);
141   pango_quantize_line_geometry (&metrics->strikethrough_thickness,
142                                 &metrics->strikethrough_position);
143   /* Quantizing may have pushed underline_position to 0.  Not good */
144   if (metrics->underline_position == 0)
145     metrics->underline_position = - metrics->underline_thickness;
146
147   layout = pango_layout_new (context);
148   font_desc = pango_font_describe_with_absolute_size ((PangoFont *) font);
149   pango_layout_set_font_description (layout, font_desc);
150   pango_layout_set_text (layout, sample_str, -1);
151   pango_layout_get_extents (layout, NULL, &extents);
152
153   metrics->approximate_char_width = extents.width / pango_utf8_strwidth (sample_str);
154
155   pango_layout_set_text (layout, "0123456789", -1);
156   metrics->approximate_digit_width = max_glyph_width (layout);
157
158   pango_font_description_free (font_desc);
159   g_object_unref (layout);
160
161   return metrics;
162 }
163
164 static void
165 pango_cairo_win32_font_finalize (GObject *object)
166 {
167   PangoCairoWin32Font *cwfont = (PangoCairoWin32Font *) object;
168
169   _pango_cairo_font_private_finalize (&cwfont->cf_priv);
170
171   G_OBJECT_CLASS (pango_cairo_win32_font_parent_class)->finalize (object);
172 }
173
174 static void
175 pango_cairo_win32_font_get_glyph_extents (PangoFont        *font,
176                                           PangoGlyph        glyph,
177                                           PangoRectangle   *ink_rect,
178                                           PangoRectangle   *logical_rect)
179 {
180   PangoCairoWin32Font *cwfont = (PangoCairoWin32Font *) font;
181
182   _pango_cairo_font_private_get_glyph_extents (&cwfont->cf_priv,
183                                                glyph,
184                                                ink_rect,
185                                                logical_rect);
186 }
187
188 static gboolean
189 pango_cairo_win32_font_select_font (PangoFont *font,
190                                     HDC        hdc)
191 {
192   cairo_scaled_font_t *scaled_font = _pango_cairo_font_private_get_scaled_font (&PANGO_CAIRO_WIN32_FONT (font)->cf_priv);
193
194   return cairo_win32_scaled_font_select_font (scaled_font, hdc) == CAIRO_STATUS_SUCCESS;
195 }
196
197 static void
198 pango_cairo_win32_font_done_font (PangoFont *font)
199 {
200   cairo_scaled_font_t *scaled_font = _pango_cairo_font_private_get_scaled_font (&PANGO_CAIRO_WIN32_FONT (font)->cf_priv);
201
202   cairo_win32_scaled_font_done_font (scaled_font);
203 }
204
205 static double
206 pango_cairo_win32_font_get_metrics_factor (PangoFont *font)
207 {
208   PangoWin32Font *win32font = PANGO_WIN32_FONT (font);
209   cairo_scaled_font_t *scaled_font = _pango_cairo_font_private_get_scaled_font (&PANGO_CAIRO_WIN32_FONT (font)->cf_priv);
210
211   return cairo_win32_scaled_font_get_metrics_factor (scaled_font) * win32font->size;
212 }
213
214 static void
215 pango_cairo_win32_font_class_init (PangoCairoWin32FontClass *class)
216 {
217   GObjectClass *object_class = G_OBJECT_CLASS (class);
218   PangoFontClass *font_class = PANGO_FONT_CLASS (class);
219   PangoWin32FontClass *win32_font_class = PANGO_WIN32_FONT_CLASS (class);
220
221   object_class->finalize = pango_cairo_win32_font_finalize;
222
223   font_class->get_glyph_extents = pango_cairo_win32_font_get_glyph_extents;
224   font_class->get_metrics = _pango_cairo_font_get_metrics;
225
226   win32_font_class->select_font = pango_cairo_win32_font_select_font;
227   win32_font_class->done_font = pango_cairo_win32_font_done_font;
228   win32_font_class->get_metrics_factor = pango_cairo_win32_font_get_metrics_factor;
229 }
230
231 static void
232 pango_cairo_win32_font_init (PangoCairoWin32Font *cwfont G_GNUC_UNUSED)
233 {
234 }
235
236 /********************
237  *    Private API   *
238  ********************/
239
240 PangoFont *
241 _pango_cairo_win32_font_new (PangoCairoWin32FontMap     *cwfontmap,
242                              PangoContext               *context,
243                              PangoWin32Face             *face,
244                              const PangoFontDescription *desc)
245 {
246   PangoCairoWin32Font *cwfont;
247   PangoWin32Font *win32font;
248   double size;
249   double dpi;
250 #define USE_FACE_CACHED_FONTS
251 #ifdef USE_FACE_CACHED_FONTS
252   PangoWin32FontMap *win32fontmap;
253   GSList *tmp_list;
254 #endif
255   cairo_matrix_t font_matrix;
256
257   g_return_val_if_fail (PANGO_IS_CAIRO_WIN32_FONT_MAP (cwfontmap), NULL);
258
259   size = (double) pango_font_description_get_size (desc) / PANGO_SCALE;
260
261   if (context)
262     {
263       dpi = pango_cairo_context_get_resolution (context);
264
265       if (dpi <= 0)
266         dpi = cwfontmap->dpi;
267     }
268   else
269     dpi = cwfontmap->dpi;
270
271   if (!pango_font_description_get_size_is_absolute (desc))
272     size *= dpi / 72.;
273
274 #ifdef USE_FACE_CACHED_FONTS
275   win32fontmap = PANGO_WIN32_FONT_MAP (cwfontmap);
276
277   tmp_list = face->cached_fonts;
278   while (tmp_list)
279     {
280       win32font = tmp_list->data;
281       if (ABS (win32font->size - size * PANGO_SCALE) < 2)
282         {
283           g_object_ref (win32font);
284           if (win32font->in_cache)
285             _pango_win32_fontmap_cache_remove (PANGO_FONT_MAP (win32fontmap), win32font);
286
287           return PANGO_FONT (win32font);
288         }
289       tmp_list = tmp_list->next;
290     }
291 #endif
292   cwfont = g_object_new (PANGO_TYPE_CAIRO_WIN32_FONT, NULL);
293   win32font = PANGO_WIN32_FONT (cwfont);
294
295   g_assert (win32font->fontmap == NULL);
296   win32font->fontmap = (PangoFontMap *) cwfontmap;
297   g_object_add_weak_pointer (G_OBJECT (win32font->fontmap), (gpointer *) (gpointer) &win32font->fontmap);
298
299   win32font->win32face = face;
300
301 #ifdef USE_FACE_CACHED_FONTS
302   face->cached_fonts = g_slist_prepend (face->cached_fonts, win32font);
303 #endif
304
305   /* FIXME: This is a pixel size, so not really what we want for describe(),
306    * but it's what we need when computing the scale factor.
307    */
308   win32font->size = size * PANGO_SCALE;
309
310   _pango_win32_make_matching_logfontw (win32font->fontmap,
311                                        &face->logfontw,
312                                        win32font->size,
313                                        &win32font->logfontw);
314
315   cairo_matrix_init_identity (&font_matrix);
316
317   cairo_matrix_scale (&font_matrix, size, size);
318
319   _pango_cairo_font_private_initialize (&cwfont->cf_priv,
320                                         (PangoCairoFont *) cwfont,
321                                         pango_font_description_get_gravity (desc),
322                                         _pango_cairo_context_get_merged_font_options (context),
323                                         pango_context_get_matrix (context),
324                                         &font_matrix);
325
326   return PANGO_FONT (cwfont);
327 }