2 * pangocairo-atsuifont.c
4 * Copyright (C) 2000-2005 Red Hat Software
5 * Copyright (C) 2005-2007 Imendio AB
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.
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.
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.
25 #import <Cocoa/Cocoa.h>
27 #include "pango-impl-utils.h"
28 #include "pangoatsui-private.h"
29 #include "pangocairo.h"
30 #include "pangocairo-private.h"
31 #include "pangocairo-atsui.h"
32 #include "pangocairo-atsuifont.h"
34 struct _PangoCairoATSUIFont
37 PangoCairoFontPrivate cf_priv;
43 struct _PangoCairoATSUIFontClass
45 PangoATSUIFontClass parent_class;
50 static cairo_font_face_t *pango_cairo_atsui_font_create_font_face (PangoCairoFont *font);
51 static PangoFontMetrics *pango_cairo_atsui_font_create_metrics_for_context (PangoCairoFont *font,
52 PangoContext *context);
55 cairo_font_iface_init (PangoCairoFontIface *iface)
57 iface->create_font_face = pango_cairo_atsui_font_create_font_face;
58 iface->create_metrics_for_context = pango_cairo_atsui_font_create_metrics_for_context;
59 iface->cf_priv_offset = G_STRUCT_OFFSET (PangoCairoATSUIFont, cf_priv);
62 G_DEFINE_TYPE_WITH_CODE (PangoCairoATSUIFont, pango_cairo_atsui_font, PANGO_TYPE_ATSUI_FONT,
63 { G_IMPLEMENT_INTERFACE (PANGO_TYPE_CAIRO_FONT, cairo_font_iface_init) });
65 /* we want get_glyph_extents extremely fast, so we use a small wrapper here
66 * to avoid having to lookup the interface data like we do for get_metrics
67 * in _pango_cairo_font_get_metrics(). */
69 pango_cairo_atsui_font_get_glyph_extents (PangoFont *font,
71 PangoRectangle *ink_rect,
72 PangoRectangle *logical_rect)
74 PangoCairoATSUIFont *cafont = (PangoCairoATSUIFont *) (font);
76 _pango_cairo_font_private_get_glyph_extents (&cafont->cf_priv,
82 static cairo_font_face_t *
83 pango_cairo_atsui_font_create_font_face (PangoCairoFont *font)
85 PangoATSUIFont *afont = (PangoATSUIFont *) (font);
88 font_id = pango_atsui_font_get_cgfont (afont);
89 return cairo_quartz_font_face_create_for_cgfont (font_id);
93 max_glyph_width (PangoLayout *layout)
98 for (l = pango_layout_get_lines_readonly (layout); l; l = l->next)
100 PangoLayoutLine *line = l->data;
102 for (r = line->runs; r; r = r->next)
104 PangoGlyphString *glyphs = ((PangoGlyphItem *)r->data)->glyphs;
107 for (i = 0; i < glyphs->num_glyphs; i++)
108 if (glyphs->glyphs[i].geometry.width > max_width)
109 max_width = glyphs->glyphs[i].geometry.width;
116 static PangoFontMetrics *
117 pango_cairo_atsui_font_create_metrics_for_context (PangoCairoFont *font,
118 PangoContext *context)
120 PangoCairoATSUIFont *cafont = (PangoCairoATSUIFont *) font;
121 PangoATSUIFont *afont = (PangoATSUIFont *) font;
124 PangoFontMetrics *metrics;
125 PangoFontDescription *font_desc;
127 PangoRectangle extents;
128 PangoLanguage *language = pango_context_get_language (context);
129 const char *sample_str = pango_language_get_sample_string (language);
131 cg_font = pango_atsui_font_get_cgfont (afont);
132 ct_font = CTFontCreateWithGraphicsFont(cg_font, cafont->size, NULL, NULL);
134 metrics = pango_font_metrics_new ();
136 metrics->ascent = CTFontGetAscent(ct_font) * PANGO_SCALE;
137 metrics->descent = -CTFontGetDescent(ct_font) * PANGO_SCALE;
139 metrics->underline_position = CTFontGetUnderlinePosition(ct_font) * PANGO_SCALE;
140 metrics->underline_thickness = CTFontGetUnderlineThickness(ct_font) * PANGO_SCALE;
142 metrics->strikethrough_position = metrics->ascent / 3;
143 metrics->strikethrough_thickness = metrics->underline_thickness * PANGO_SCALE;
145 layout = pango_layout_new (context);
146 font_desc = pango_font_describe_with_absolute_size ((PangoFont *) font);
147 pango_layout_set_font_description (layout, font_desc);
148 pango_layout_set_text (layout, sample_str, -1);
149 pango_layout_get_extents (layout, NULL, &extents);
151 metrics->approximate_char_width = extents.width / pango_utf8_strwidth (sample_str);
153 pango_layout_set_text (layout, "0123456789", -1);
154 metrics->approximate_digit_width = max_glyph_width (layout);
156 pango_font_description_free (font_desc);
157 g_object_unref (layout);
164 static PangoFontDescription *
165 pango_cairo_atsui_font_describe_absolute (PangoFont *font)
167 PangoFontDescription *desc;
168 PangoCairoATSUIFont *cafont = (PangoCairoATSUIFont *) font;
170 desc = pango_font_describe (font);
171 pango_font_description_set_absolute_size (desc, cafont->absolute_size);
177 pango_cairo_atsui_font_finalize (GObject *object)
179 PangoCairoATSUIFont *cafont = (PangoCairoATSUIFont *) object;
181 _pango_cairo_font_private_finalize (&cafont->cf_priv);
183 G_OBJECT_CLASS (pango_cairo_atsui_font_parent_class)->finalize (object);
187 pango_cairo_atsui_font_class_init (PangoCairoATSUIFontClass *class)
189 GObjectClass *object_class = G_OBJECT_CLASS (class);
190 PangoFontClass *font_class = PANGO_FONT_CLASS (class);
192 object_class->finalize = pango_cairo_atsui_font_finalize;
194 font_class->get_glyph_extents = pango_cairo_atsui_font_get_glyph_extents;
195 font_class->get_metrics = _pango_cairo_font_get_metrics;
196 font_class->describe_absolute = pango_cairo_atsui_font_describe_absolute;
200 pango_cairo_atsui_font_init (PangoCairoATSUIFont *cafont G_GNUC_UNUSED)
205 _pango_cairo_atsui_font_new (PangoCairoATSUIFontMap *cafontmap,
206 PangoContext *context,
207 PangoATSUIFace *face,
208 const PangoFontDescription *desc)
210 const char *postscript_name;
211 gboolean synthesize_italic = FALSE;
212 PangoCairoATSUIFont *cafont;
213 PangoATSUIFont *afont;
220 cairo_matrix_t font_matrix;
222 postscript_name = _pango_atsui_face_get_postscript_name (face);
224 cfstr = CFStringCreateWithCString (NULL, postscript_name,
225 kCFStringEncodingUTF8);
226 font_ref = ATSFontFindFromPostScriptName (cfstr, kATSOptionFlagsDefault);
229 /* We synthesize italic in two cases. The first is when
230 * NSFontManager has handed out a face that it claims has italic but
231 * it doesn't. The other is when an italic face is requested that
232 * doesn't have a real version.
234 if (font_ref == kATSFontRefUnspecified &&
235 pango_font_description_get_style (desc) != PANGO_STYLE_NORMAL)
237 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
239 NSFont *nsfont, *converted_font;
241 size = (double) pango_font_description_get_size (desc) / PANGO_SCALE;
243 nsname = [NSString stringWithUTF8String:postscript_name];
244 nsfont = [NSFont fontWithName:nsname size:size];
246 converted_font = [[NSFontManager sharedFontManager] convertFont:nsfont
247 toHaveTrait:NSUnitalicFontMask];
248 font_ref = ATSFontFindFromPostScriptName ((CFStringRef) [converted_font fontName],
249 kATSOptionFlagsDefault);
253 synthesize_italic = TRUE;
255 else if (_pango_atsui_face_get_synthetic_italic (face))
256 synthesize_italic = TRUE;
258 if (font_ref == kATSFontRefUnspecified)
261 font_id = CGFontCreateWithPlatformFont (&font_ref);
265 cafont = g_object_new (PANGO_TYPE_CAIRO_ATSUI_FONT, NULL);
266 afont = PANGO_ATSUI_FONT (cafont);
268 _pango_atsui_font_set_font_description (afont, desc);
269 _pango_atsui_font_set_face (afont, face);
271 size = (double) pango_font_description_get_size (desc) / PANGO_SCALE;
272 _pango_atsui_font_set_cgfont (afont, font_id);
276 dpi = pango_cairo_context_get_resolution (context);
279 dpi = cafontmap->dpi;
282 dpi = cafontmap->dpi;
284 cafont->absolute_size = pango_font_description_get_size (desc);
286 if (!pango_font_description_get_size_is_absolute (desc))
291 /* When synthesizing italics, apply a shear matrix matching what Cocoa
292 * does. Cairo quartz had transformed text wrong before 1.5.13, stay
293 * backwards compatible until pango requires a new enough cairo.
295 if (cairo_version () >= CAIRO_VERSION_ENCODE(1,5,13))
300 if (synthesize_italic)
301 cairo_matrix_init (&font_matrix,
306 cairo_matrix_init_identity (&font_matrix);
308 cairo_matrix_scale (&font_matrix, size, size);
310 _pango_cairo_font_private_initialize (&cafont->cf_priv,
311 (PangoCairoFont *) cafont,
312 pango_font_description_get_gravity (desc),
313 _pango_cairo_context_get_merged_font_options (context),
314 pango_context_get_matrix (context),