Initial Import
[profile/ivi/pango.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_base_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_base_metrics_for_context = pango_cairo_win32_font_create_base_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_base_metrics_for_context (PangoCairoFont *font,
108                                                         PangoContext   *context)
109 {
110   PangoFontMetrics *metrics;
111   cairo_scaled_font_t *scaled_font;
112   cairo_font_extents_t font_extents;
113   double height;
114
115   metrics = pango_font_metrics_new ();
116
117   scaled_font = pango_cairo_font_get_scaled_font ((PangoFont *) font);
118
119   cairo_scaled_font_extents (scaled_font, &font_extents);
120   cairo_win32_scaled_font_done_font (scaled_font);
121
122   metrics->ascent = font_extents.ascent * PANGO_SCALE;
123   metrics->descent = font_extents.descent * PANGO_SCALE;
124
125   /* FIXME: Should get the real settings for these from the TrueType
126    * font file.
127    */
128   height = metrics->ascent + metrics->descent;
129   metrics->underline_thickness = height / 14;
130   metrics->underline_position = - metrics->underline_thickness;
131   metrics->strikethrough_thickness = metrics->underline_thickness;
132   metrics->strikethrough_position = height / 4;
133
134   pango_quantize_line_geometry (&metrics->underline_thickness,
135                                 &metrics->underline_position);
136   pango_quantize_line_geometry (&metrics->strikethrough_thickness,
137                                 &metrics->strikethrough_position);
138   /* Quantizing may have pushed underline_position to 0.  Not good */
139   if (metrics->underline_position == 0)
140     metrics->underline_position = - metrics->underline_thickness;
141
142   return metrics;
143 }
144
145 static void
146 pango_cairo_win32_font_finalize (GObject *object)
147 {
148   PangoCairoWin32Font *cwfont = (PangoCairoWin32Font *) object;
149
150   _pango_cairo_font_private_finalize (&cwfont->cf_priv);
151
152   G_OBJECT_CLASS (pango_cairo_win32_font_parent_class)->finalize (object);
153 }
154
155 static void
156 pango_cairo_win32_font_get_glyph_extents (PangoFont        *font,
157                                           PangoGlyph        glyph,
158                                           PangoRectangle   *ink_rect,
159                                           PangoRectangle   *logical_rect)
160 {
161   PangoCairoWin32Font *cwfont = (PangoCairoWin32Font *) font;
162
163   _pango_cairo_font_private_get_glyph_extents (&cwfont->cf_priv,
164                                                glyph,
165                                                ink_rect,
166                                                logical_rect);
167 }
168
169 static gboolean
170 pango_cairo_win32_font_select_font (PangoFont *font,
171                                     HDC        hdc)
172 {
173   cairo_scaled_font_t *scaled_font = _pango_cairo_font_private_get_scaled_font (&PANGO_CAIRO_WIN32_FONT (font)->cf_priv);
174
175   return cairo_win32_scaled_font_select_font (scaled_font, hdc) == CAIRO_STATUS_SUCCESS;
176 }
177
178 static void
179 pango_cairo_win32_font_done_font (PangoFont *font)
180 {
181   cairo_scaled_font_t *scaled_font = _pango_cairo_font_private_get_scaled_font (&PANGO_CAIRO_WIN32_FONT (font)->cf_priv);
182
183   cairo_win32_scaled_font_done_font (scaled_font);
184 }
185
186 static double
187 pango_cairo_win32_font_get_metrics_factor (PangoFont *font)
188 {
189   PangoWin32Font *win32font = PANGO_WIN32_FONT (font);
190   cairo_scaled_font_t *scaled_font = _pango_cairo_font_private_get_scaled_font (&PANGO_CAIRO_WIN32_FONT (font)->cf_priv);
191
192   return cairo_win32_scaled_font_get_metrics_factor (scaled_font) * win32font->size;
193 }
194
195 static void
196 pango_cairo_win32_font_class_init (PangoCairoWin32FontClass *class)
197 {
198   GObjectClass *object_class = G_OBJECT_CLASS (class);
199   PangoFontClass *font_class = PANGO_FONT_CLASS (class);
200   PangoWin32FontClass *win32_font_class = PANGO_WIN32_FONT_CLASS (class);
201
202   object_class->finalize = pango_cairo_win32_font_finalize;
203
204   font_class->get_glyph_extents = pango_cairo_win32_font_get_glyph_extents;
205   font_class->get_metrics = _pango_cairo_font_get_metrics;
206
207   win32_font_class->select_font = pango_cairo_win32_font_select_font;
208   win32_font_class->done_font = pango_cairo_win32_font_done_font;
209   win32_font_class->get_metrics_factor = pango_cairo_win32_font_get_metrics_factor;
210 }
211
212 static void
213 pango_cairo_win32_font_init (PangoCairoWin32Font *cwfont G_GNUC_UNUSED)
214 {
215 }
216
217 /********************
218  *    Private API   *
219  ********************/
220
221 PangoFont *
222 _pango_cairo_win32_font_new (PangoCairoWin32FontMap     *cwfontmap,
223                              PangoContext               *context,
224                              PangoWin32Face             *face,
225                              const PangoFontDescription *desc)
226 {
227   PangoCairoWin32Font *cwfont;
228   PangoWin32Font *win32font;
229   double size;
230   double dpi;
231 #define USE_FACE_CACHED_FONTS
232 #ifdef USE_FACE_CACHED_FONTS
233   PangoWin32FontMap *win32fontmap;
234   GSList *tmp_list;
235 #endif
236   cairo_matrix_t font_matrix;
237
238   g_return_val_if_fail (PANGO_IS_CAIRO_WIN32_FONT_MAP (cwfontmap), NULL);
239
240   size = (double) pango_font_description_get_size (desc) / PANGO_SCALE;
241
242   if (context)
243     {
244       dpi = pango_cairo_context_get_resolution (context);
245
246       if (dpi <= 0)
247         dpi = cwfontmap->dpi;
248     }
249   else
250     dpi = cwfontmap->dpi;
251
252   if (!pango_font_description_get_size_is_absolute (desc))
253     size *= dpi / 72.;
254
255 #ifdef USE_FACE_CACHED_FONTS
256   win32fontmap = PANGO_WIN32_FONT_MAP (cwfontmap);
257
258   tmp_list = face->cached_fonts;
259   while (tmp_list)
260     {
261       win32font = tmp_list->data;
262       if (ABS (win32font->size - size * PANGO_SCALE) < 2)
263         {
264           g_object_ref (win32font);
265           if (win32font->in_cache)
266             _pango_win32_fontmap_cache_remove (PANGO_FONT_MAP (win32fontmap), win32font);
267
268           return PANGO_FONT (win32font);
269         }
270       tmp_list = tmp_list->next;
271     }
272 #endif
273   cwfont = g_object_new (PANGO_TYPE_CAIRO_WIN32_FONT, NULL);
274   win32font = PANGO_WIN32_FONT (cwfont);
275
276   g_assert (win32font->fontmap == NULL);
277   win32font->fontmap = (PangoFontMap *) cwfontmap;
278   g_object_add_weak_pointer (G_OBJECT (win32font->fontmap), (gpointer *) (gpointer) &win32font->fontmap);
279
280   win32font->win32face = face;
281
282 #ifdef USE_FACE_CACHED_FONTS
283   face->cached_fonts = g_slist_prepend (face->cached_fonts, win32font);
284 #endif
285
286   /* FIXME: This is a pixel size, so not really what we want for describe(),
287    * but it's what we need when computing the scale factor.
288    */
289   win32font->size = size * PANGO_SCALE;
290
291   _pango_win32_make_matching_logfontw (win32font->fontmap,
292                                        &face->logfontw,
293                                        win32font->size,
294                                        &win32font->logfontw);
295
296   cairo_matrix_init_identity (&font_matrix);
297
298   cairo_matrix_scale (&font_matrix, size, size);
299
300   _pango_cairo_font_private_initialize (&cwfont->cf_priv,
301                                         (PangoCairoFont *) cwfont,
302                                         pango_font_description_get_gravity (desc),
303                                         _pango_cairo_context_get_merged_font_options (context),
304                                         pango_context_get_matrix (context),
305                                         &font_matrix);
306
307   return PANGO_FONT (cwfont);
308 }