1 /* -*- Mode: c; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 8; -*- */
2 /* cairo - a vector graphics library with display and print output
4 * Copyright � 2008 Mozilla Corporation
6 * This library is free software; you can redistribute it and/or
7 * modify it either under the terms of the GNU Lesser General Public
8 * License version 2.1 as published by the Free Software Foundation
9 * (the "LGPL") or, at your option, under the terms of the Mozilla
10 * Public License Version 1.1 (the "MPL"). If you do not alter this
11 * notice, a recipient may use your version of this file under either
12 * the MPL or the LGPL.
14 * You should have received a copy of the LGPL along with this library
15 * in the file COPYING-LGPL-2.1; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 * You should have received a copy of the MPL along with this library
18 * in the file COPYING-MPL-1.1
20 * The contents of this file are subject to the Mozilla Public License
21 * Version 1.1 (the "License"); you may not use this file except in
22 * compliance with the License. You may obtain a copy of the License at
23 * http://www.mozilla.org/MPL/
25 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
26 * OF ANY KIND, either express or implied. See the LGPL or the MPL for
27 * the specific language governing rights and limitations.
29 * The Original Code is the cairo graphics library.
31 * The Initial Developer of the Original Code is Mozilla Corporation.
34 * Vladimir Vukicevic <vladimir@mozilla.com>
41 #include "cairo-quartz.h"
42 #include "cairo-quartz-private.h"
44 /* CreateWithFontName exists in 10.5, but not in 10.4; CreateWithName isn't public in 10.4 */
45 static CGFontRef (*CGFontCreateWithFontNamePtr
) (CFStringRef
) = NULL
;
46 static CGFontRef (*CGFontCreateWithNamePtr
) (const char *) = NULL
;
48 /* These aren't public before 10.5, and some have different names in 10.4 */
49 static int (*CGFontGetUnitsPerEmPtr
) (CGFontRef
) = NULL
;
50 static bool (*CGFontGetGlyphAdvancesPtr
) (CGFontRef
, const CGGlyph
[], size_t, int[]) = NULL
;
51 static bool (*CGFontGetGlyphBBoxesPtr
) (CGFontRef
, const CGGlyph
[], size_t, CGRect
[]) = NULL
;
52 static CGRect (*CGFontGetFontBBoxPtr
) (CGFontRef
) = NULL
;
54 /* Not public, but present */
55 static void (*CGFontGetGlyphsForUnicharsPtr
) (CGFontRef
, const UniChar
[], const CGGlyph
[], size_t) = NULL
;
57 /* Not public in the least bit */
58 static CGPathRef (*CGFontGetGlyphPathPtr
) (CGFontRef fontRef
, CGAffineTransform
*textTransform
, int unknown
, CGGlyph glyph
) = NULL
;
60 /* CGFontGetHMetrics isn't public, but the other functions are public/present in 10.5 */
65 } quartz_CGFontMetrics
;
66 static quartz_CGFontMetrics
* (*CGFontGetHMetricsPtr
) (CGFontRef fontRef
) = NULL
;
67 static int (*CGFontGetAscentPtr
) (CGFontRef fontRef
) = NULL
;
68 static int (*CGFontGetDescentPtr
) (CGFontRef fontRef
) = NULL
;
69 static int (*CGFontGetLeadingPtr
) (CGFontRef fontRef
) = NULL
;
71 static cairo_bool_t _cairo_quartz_font_symbol_lookup_done
= FALSE
;
72 static cairo_bool_t _cairo_quartz_font_symbols_present
= FALSE
;
75 quartz_font_ensure_symbols(void)
77 if (_cairo_quartz_font_symbol_lookup_done
)
80 /* Look for the 10.5 versions first */
81 CGFontGetGlyphBBoxesPtr
= dlsym(RTLD_DEFAULT
, "CGFontGetGlyphBBoxes");
82 if (!CGFontGetGlyphBBoxesPtr
)
83 CGFontGetGlyphBBoxesPtr
= dlsym(RTLD_DEFAULT
, "CGFontGetGlyphBoundingBoxes");
85 CGFontGetGlyphsForUnicharsPtr
= dlsym(RTLD_DEFAULT
, "CGFontGetGlyphsForUnichars");
86 if (!CGFontGetGlyphsForUnicharsPtr
)
87 CGFontGetGlyphsForUnicharsPtr
= dlsym(RTLD_DEFAULT
, "CGFontGetGlyphsForUnicodes");
89 CGFontGetFontBBoxPtr
= dlsym(RTLD_DEFAULT
, "CGFontGetFontBBox");
91 /* We just need one of these two */
92 CGFontCreateWithFontNamePtr
= dlsym(RTLD_DEFAULT
, "CGFontCreateWithFontName");
93 CGFontCreateWithNamePtr
= dlsym(RTLD_DEFAULT
, "CGFontCreateWithName");
95 /* These have the same name in 10.4 and 10.5 */
96 CGFontGetUnitsPerEmPtr
= dlsym(RTLD_DEFAULT
, "CGFontGetUnitsPerEm");
97 CGFontGetGlyphAdvancesPtr
= dlsym(RTLD_DEFAULT
, "CGFontGetGlyphAdvances");
98 CGFontGetGlyphPathPtr
= dlsym(RTLD_DEFAULT
, "CGFontGetGlyphPath");
100 CGFontGetHMetricsPtr
= dlsym(RTLD_DEFAULT
, "CGFontGetHMetrics");
101 CGFontGetAscentPtr
= dlsym(RTLD_DEFAULT
, "CGFontGetAscent");
102 CGFontGetDescentPtr
= dlsym(RTLD_DEFAULT
, "CGFontGetDescent");
103 CGFontGetLeadingPtr
= dlsym(RTLD_DEFAULT
, "CGFontGetLeading");
105 if ((CGFontCreateWithFontNamePtr
|| CGFontCreateWithNamePtr
) &&
106 CGFontGetGlyphBBoxesPtr
&&
107 CGFontGetGlyphsForUnicharsPtr
&&
108 CGFontGetUnitsPerEmPtr
&&
109 CGFontGetGlyphAdvancesPtr
&&
110 CGFontGetGlyphPathPtr
&&
111 (CGFontGetHMetricsPtr
|| (CGFontGetAscentPtr
&& CGFontGetDescentPtr
&& CGFontGetLeadingPtr
)))
112 _cairo_quartz_font_symbols_present
= TRUE
;
114 _cairo_quartz_font_symbol_lookup_done
= TRUE
;
117 typedef struct _cairo_quartz_font_face cairo_quartz_font_face_t
;
118 typedef struct _cairo_quartz_scaled_font cairo_quartz_scaled_font_t
;
120 struct _cairo_quartz_scaled_font
{
121 cairo_scaled_font_t base
;
124 struct _cairo_quartz_font_face
{
125 cairo_font_face_t base
;
134 static cairo_status_t
135 _cairo_quartz_font_face_create_for_toy (cairo_toy_font_face_t
*toy_face
,
136 cairo_font_face_t
**font_face
)
140 CFStringRef cgFontName
= NULL
;
141 CGFontRef cgFont
= NULL
;
144 quartz_font_ensure_symbols();
145 if (! _cairo_quartz_font_symbols_present
)
146 return _cairo_error (CAIRO_STATUS_NO_MEMORY
);
148 family
= toy_face
->family
;
149 full_name
= malloc (strlen (family
) + 64); // give us a bit of room to tack on Bold, Oblique, etc.
150 /* handle CSS-ish faces */
151 if (!strcmp(family
, "serif") || !strcmp(family
, "Times Roman"))
153 else if (!strcmp(family
, "sans-serif") || !strcmp(family
, "sans"))
154 family
= "Helvetica";
155 else if (!strcmp(family
, "cursive"))
156 family
= "Apple Chancery";
157 else if (!strcmp(family
, "fantasy"))
159 else if (!strcmp(family
, "monospace") || !strcmp(family
, "mono"))
162 /* Try to build up the full name, e.g. "Helvetica Bold Oblique" first,
163 * then drop the bold, then drop the slant, then drop both.. finally
164 * just use "Helvetica". And if Helvetica doesn't exist, give up.
166 for (loop
= 0; loop
< 5; loop
++) {
168 family
= "Helvetica";
170 strcpy (full_name
, family
);
172 if (loop
< 3 && (loop
& 1) == 0) {
173 if (toy_face
->weight
== CAIRO_FONT_WEIGHT_BOLD
)
174 strcat (full_name
, " Bold");
177 if (loop
< 3 && (loop
& 2) == 0) {
178 if (toy_face
->slant
== CAIRO_FONT_SLANT_ITALIC
)
179 strcat (full_name
, " Italic");
180 else if (toy_face
->slant
== CAIRO_FONT_SLANT_OBLIQUE
)
181 strcat (full_name
, " Oblique");
184 if (CGFontCreateWithFontNamePtr
) {
185 cgFontName
= CFStringCreateWithCString (NULL
, full_name
, kCFStringEncodingASCII
);
186 cgFont
= CGFontCreateWithFontNamePtr (cgFontName
);
187 CFRelease (cgFontName
);
189 cgFont
= CGFontCreateWithNamePtr (full_name
);
198 return _cairo_error (CAIRO_STATUS_NO_MEMORY
);
201 *font_face
= cairo_quartz_font_face_create_for_cgfont (cgFont
);
202 CGFontRelease (cgFont
);
204 return CAIRO_STATUS_SUCCESS
;
208 _cairo_quartz_font_face_destroy (void *abstract_face
)
210 cairo_quartz_font_face_t
*font_face
= (cairo_quartz_font_face_t
*) abstract_face
;
212 CGFontRelease (font_face
->cgFont
);
215 static const cairo_scaled_font_backend_t _cairo_quartz_scaled_font_backend
;
217 static cairo_status_t
218 _cairo_quartz_font_face_scaled_font_create (void *abstract_face
,
219 const cairo_matrix_t
*font_matrix
,
220 const cairo_matrix_t
*ctm
,
221 const cairo_font_options_t
*options
,
222 cairo_scaled_font_t
**font_out
)
224 cairo_quartz_font_face_t
*font_face
= abstract_face
;
225 cairo_quartz_scaled_font_t
*font
= NULL
;
226 cairo_status_t status
;
227 cairo_font_extents_t fs_metrics
;
231 quartz_font_ensure_symbols();
232 if (!_cairo_quartz_font_symbols_present
)
233 return _cairo_error (CAIRO_STATUS_NO_MEMORY
);
235 font
= malloc(sizeof(cairo_quartz_scaled_font_t
));
237 return _cairo_error (CAIRO_STATUS_NO_MEMORY
);
239 memset (font
, 0, sizeof(cairo_quartz_scaled_font_t
));
241 status
= _cairo_scaled_font_init (&font
->base
,
242 &font_face
->base
, font_matrix
, ctm
, options
,
243 &_cairo_quartz_scaled_font_backend
);
247 ems
= CGFontGetUnitsPerEmPtr (font_face
->cgFont
);
249 /* initialize metrics */
250 if (CGFontGetFontBBoxPtr
&& CGFontGetAscentPtr
) {
251 fs_metrics
.ascent
= (CGFontGetAscentPtr (font_face
->cgFont
) / ems
);
252 fs_metrics
.descent
= - (CGFontGetDescentPtr (font_face
->cgFont
) / ems
);
253 fs_metrics
.height
= fs_metrics
.ascent
+ fs_metrics
.descent
+
254 (CGFontGetLeadingPtr (font_face
->cgFont
) / ems
);
256 bbox
= CGFontGetFontBBoxPtr (font_face
->cgFont
);
257 fs_metrics
.max_x_advance
= CGRectGetMaxX(bbox
) / ems
;
258 fs_metrics
.max_y_advance
= 0.0;
263 quartz_CGFontMetrics
*m
;
264 m
= CGFontGetHMetricsPtr (font_face
->cgFont
);
266 /* On OX 10.4, GetHMetricsPtr sometimes returns NULL for unknown reasons */
268 status
= _cairo_error(CAIRO_STATUS_NULL_POINTER
);
272 fs_metrics
.ascent
= (m
->ascent
/ ems
);
273 fs_metrics
.descent
= - (m
->descent
/ ems
);
274 fs_metrics
.height
= fs_metrics
.ascent
+ fs_metrics
.descent
+ (m
->leading
/ ems
);
276 /* We kind of have to guess here; W's big, right? */
278 CGFontGetGlyphsForUnicharsPtr (font_face
->cgFont
, &u
, &wGlyph
, 1);
279 if (wGlyph
&& CGFontGetGlyphBBoxesPtr (font_face
->cgFont
, &wGlyph
, 1, &bbox
)) {
280 fs_metrics
.max_x_advance
= CGRectGetMaxX(bbox
) / ems
;
281 fs_metrics
.max_y_advance
= 0.0;
283 fs_metrics
.max_x_advance
= 0.0;
284 fs_metrics
.max_y_advance
= 0.0;
288 status
= _cairo_scaled_font_set_metrics (&font
->base
, &fs_metrics
);
291 if (status
!= CAIRO_STATUS_SUCCESS
) {
294 *font_out
= (cairo_scaled_font_t
*) font
;
300 const cairo_font_face_backend_t _cairo_quartz_font_face_backend
= {
301 CAIRO_FONT_TYPE_QUARTZ
,
302 _cairo_quartz_font_face_create_for_toy
,
303 _cairo_quartz_font_face_destroy
,
304 _cairo_quartz_font_face_scaled_font_create
308 * cairo_quartz_font_face_create_for_cgfont
309 * @font: a #CGFontRef obtained through a method external to cairo.
311 * Creates a new font for the Quartz font backend based on a
312 * #CGFontRef. This font can then be used with
313 * cairo_set_font_face() or cairo_scaled_font_create().
315 * Return value: a newly created #cairo_font_face_t. Free with
316 * cairo_font_face_destroy() when you are done using it.
321 cairo_quartz_font_face_create_for_cgfont (CGFontRef font
)
323 cairo_quartz_font_face_t
*font_face
;
325 quartz_font_ensure_symbols();
327 font_face
= malloc (sizeof (cairo_quartz_font_face_t
));
329 _cairo_error (CAIRO_STATUS_NO_MEMORY
);
330 return (cairo_font_face_t
*)&_cairo_font_face_nil
;
333 font_face
->cgFont
= CGFontRetain (font
);
335 _cairo_font_face_init (&font_face
->base
, &_cairo_quartz_font_face_backend
);
337 return &font_face
->base
;
341 * scaled font backend
344 static cairo_quartz_font_face_t
*
345 _cairo_quartz_scaled_to_face (void *abstract_font
)
347 cairo_quartz_scaled_font_t
*sfont
= (cairo_quartz_scaled_font_t
*) abstract_font
;
348 cairo_font_face_t
*font_face
= cairo_scaled_font_get_font_face (&sfont
->base
);
349 if (!font_face
|| font_face
->backend
->type
!= CAIRO_FONT_TYPE_QUARTZ
)
352 return (cairo_quartz_font_face_t
*) font_face
;
356 _cairo_quartz_scaled_font_fini(void *abstract_font
)
360 #define INVALID_GLYPH 0x00
362 static inline CGGlyph
363 _cairo_quartz_scaled_glyph_index (cairo_scaled_glyph_t
*scaled_glyph
) {
364 unsigned long index
= _cairo_scaled_glyph_index (scaled_glyph
);
366 return INVALID_GLYPH
;
367 return (CGGlyph
) index
;
370 static inline cairo_status_t
371 _cairo_matrix_to_unit_quartz_matrix (const cairo_matrix_t
*m
, CGAffineTransform
*txout
,
372 double *xout
, double *yout
)
374 CGAffineTransform transform
;
375 double xscale
, yscale
;
376 cairo_status_t status
;
378 status
= _cairo_matrix_compute_basis_scale_factors (m
, &xscale
, &yscale
, 1);
382 transform
= CGAffineTransformMake (m
->xx
, - m
->yx
,
391 xscale
= 1.0 / xscale
;
393 yscale
= 1.0 / yscale
;
395 *txout
= CGAffineTransformScale (transform
, xscale
, yscale
);
397 return CAIRO_STATUS_SUCCESS
;
400 static cairo_int_status_t
401 _cairo_quartz_init_glyph_metrics (cairo_quartz_scaled_font_t
*font
,
402 cairo_scaled_glyph_t
*scaled_glyph
)
404 cairo_int_status_t status
= CAIRO_STATUS_SUCCESS
;
406 cairo_quartz_font_face_t
*font_face
= _cairo_quartz_scaled_to_face(font
);
407 cairo_text_extents_t extents
= {0, 0, 0, 0, 0, 0};
408 CGAffineTransform textMatrix
;
409 CGGlyph glyph
= _cairo_quartz_scaled_glyph_index (scaled_glyph
);
412 double emscale
= CGFontGetUnitsPerEmPtr (font_face
->cgFont
);
413 double xscale
, yscale
;
414 double xmin
, ymin
, xmax
, ymax
;
416 if (glyph
== INVALID_GLYPH
)
419 if (!CGFontGetGlyphAdvancesPtr (font_face
->cgFont
, &glyph
, 1, &advance
) ||
420 !CGFontGetGlyphBBoxesPtr (font_face
->cgFont
, &glyph
, 1, &bbox
))
423 status
= _cairo_matrix_compute_basis_scale_factors (&font
->base
.scale
,
424 &xscale
, &yscale
, 1);
428 bbox
= CGRectMake (bbox
.origin
.x
/ emscale
,
429 bbox
.origin
.y
/ emscale
,
430 bbox
.size
.width
/ emscale
,
431 bbox
.size
.height
/ emscale
);
433 /* Should we want to always integer-align glyph extents, we can do so in this way */
436 CGAffineTransform textMatrix
;
437 textMatrix
= CGAffineTransformMake (font
->base
.scale
.xx
,
438 -font
->base
.scale
.yx
,
439 -font
->base
.scale
.xy
,
443 bbox
= CGRectApplyAffineTransform (bbox
, textMatrix
);
444 bbox
= CGRectIntegral (bbox
);
445 bbox
= CGRectApplyAffineTransform (bbox
, CGAffineTransformInvert (textMatrix
));
450 fprintf (stderr
, "[0x%04x] bbox: %f %f %f %f\n", glyph
,
451 bbox
.origin
.x
/ emscale
, bbox
.origin
.y
/ emscale
,
452 bbox
.size
.width
/ emscale
, bbox
.size
.height
/ emscale
);
455 xmin
= CGRectGetMinX(bbox
);
456 ymin
= CGRectGetMinY(bbox
);
457 xmax
= CGRectGetMaxX(bbox
);
458 ymax
= CGRectGetMaxY(bbox
);
460 extents
.x_bearing
= xmin
;
461 extents
.y_bearing
= - ymax
;
462 extents
.width
= xmax
- xmin
;
463 extents
.height
= ymax
- ymin
;
465 extents
.x_advance
= (double) advance
/ emscale
;
466 extents
.y_advance
= 0.0;
469 fprintf (stderr
, "[0x%04x] extents: bearings: %f %f dim: %f %f adv: %f\n\n", glyph
,
470 extents
.x_bearing
, extents
.y_bearing
, extents
.width
, extents
.height
, extents
.x_advance
);
474 _cairo_scaled_glyph_set_metrics (scaled_glyph
,
482 _cairo_quartz_path_apply_func (void *info
, const CGPathElement
*el
)
484 cairo_path_fixed_t
*path
= (cairo_path_fixed_t
*) info
;
487 case kCGPathElementMoveToPoint
:
488 _cairo_path_fixed_move_to (path
,
489 _cairo_fixed_from_double(el
->points
[0].x
),
490 _cairo_fixed_from_double(el
->points
[0].y
));
492 case kCGPathElementAddLineToPoint
:
493 _cairo_path_fixed_line_to (path
,
494 _cairo_fixed_from_double(el
->points
[0].x
),
495 _cairo_fixed_from_double(el
->points
[0].y
));
497 case kCGPathElementAddQuadCurveToPoint
: {
498 cairo_fixed_t fx
, fy
;
500 if (!_cairo_path_fixed_get_current_point (path
, &fx
, &fy
))
502 x
= _cairo_fixed_to_double (fx
);
503 y
= _cairo_fixed_to_double (fy
);
505 _cairo_path_fixed_curve_to (path
,
506 _cairo_fixed_from_double((x
+ el
->points
[0].x
* 2.0) / 3.0),
507 _cairo_fixed_from_double((y
+ el
->points
[0].y
* 2.0) / 3.0),
508 _cairo_fixed_from_double((el
->points
[0].x
* 2.0 + el
->points
[1].x
) / 3.0),
509 _cairo_fixed_from_double((el
->points
[0].y
* 2.0 + el
->points
[1].y
) / 3.0),
510 _cairo_fixed_from_double(el
->points
[1].x
),
511 _cairo_fixed_from_double(el
->points
[1].y
));
514 case kCGPathElementAddCurveToPoint
:
515 _cairo_path_fixed_curve_to (path
,
516 _cairo_fixed_from_double(el
->points
[0].x
),
517 _cairo_fixed_from_double(el
->points
[0].y
),
518 _cairo_fixed_from_double(el
->points
[1].x
),
519 _cairo_fixed_from_double(el
->points
[1].y
),
520 _cairo_fixed_from_double(el
->points
[2].x
),
521 _cairo_fixed_from_double(el
->points
[2].y
));
523 case kCGPathElementCloseSubpath
:
524 _cairo_path_fixed_close_path (path
);
529 static cairo_int_status_t
530 _cairo_quartz_init_glyph_path (cairo_quartz_scaled_font_t
*font
,
531 cairo_scaled_glyph_t
*scaled_glyph
)
533 cairo_quartz_font_face_t
*font_face
= _cairo_quartz_scaled_to_face(font
);
534 CGGlyph glyph
= _cairo_quartz_scaled_glyph_index (scaled_glyph
);
535 CGAffineTransform textMatrix
;
537 cairo_path_fixed_t
*path
;
539 if (glyph
== INVALID_GLYPH
) {
540 _cairo_scaled_glyph_set_path (scaled_glyph
, &font
->base
, _cairo_path_fixed_create());
541 return CAIRO_STATUS_SUCCESS
;
544 textMatrix
= CGAffineTransformMake (font
->base
.scale
.xx
,
545 -font
->base
.scale
.yx
,
546 -font
->base
.scale
.xy
,
549 font
->base
.scale
.y0
);
551 textMatrix
= CGAffineTransformConcat (textMatrix
, CGAffineTransformMake (1.0, 0.0, 0.0, -1.0, 0.0, 0.0));
553 glyphPath
= CGFontGetGlyphPathPtr (font_face
->cgFont
, &textMatrix
, 0, glyph
);
555 return CAIRO_INT_STATUS_UNSUPPORTED
;
557 path
= _cairo_path_fixed_create ();
559 CGPathRelease (glyphPath
);
560 return _cairo_error(CAIRO_STATUS_NO_MEMORY
);
563 CGPathApply (glyphPath
, path
, _cairo_quartz_path_apply_func
);
565 CGPathRelease (glyphPath
);
567 _cairo_scaled_glyph_set_path (scaled_glyph
, &font
->base
, path
);
569 return CAIRO_STATUS_SUCCESS
;
572 static cairo_int_status_t
573 _cairo_quartz_init_glyph_surface (cairo_quartz_scaled_font_t
*font
,
574 cairo_scaled_glyph_t
*scaled_glyph
)
576 cairo_int_status_t status
= CAIRO_STATUS_SUCCESS
;
578 cairo_quartz_font_face_t
*font_face
= _cairo_quartz_scaled_to_face(font
);
580 cairo_image_surface_t
*surface
= NULL
;
582 CGGlyph glyph
= _cairo_quartz_scaled_glyph_index (scaled_glyph
);
586 double width
, height
;
587 double xscale
, yscale
;
588 double emscale
= CGFontGetUnitsPerEmPtr (font_face
->cgFont
);
590 CGColorSpaceRef gray
;
591 CGContextRef cgContext
= NULL
;
592 CGAffineTransform textMatrix
;
593 CGRect glyphRect
, glyphRectInt
;
596 //fprintf (stderr, "scaled_glyph: %p surface: %p\n", scaled_glyph, scaled_glyph->surface);
598 /* Create blank 2x2 image if we don't have this character.
599 * Maybe we should draw a better missing-glyph slug or something,
600 * but this is ok for now.
602 if (glyph
== INVALID_GLYPH
) {
603 surface
= (cairo_image_surface_t
*) cairo_image_surface_create (CAIRO_FORMAT_A8
, 2, 2);
604 status
= cairo_surface_status ((cairo_surface_t
*) surface
);
608 _cairo_scaled_glyph_set_surface (scaled_glyph
,
611 return CAIRO_STATUS_SUCCESS
;
614 if (!CGFontGetGlyphAdvancesPtr (font_face
->cgFont
, &glyph
, 1, &advance
) ||
615 !CGFontGetGlyphBBoxesPtr (font_face
->cgFont
, &glyph
, 1, &bbox
))
617 return CAIRO_INT_STATUS_UNSUPPORTED
;
620 status
= _cairo_matrix_compute_basis_scale_factors (&font
->base
.scale
,
621 &xscale
, &yscale
, 1);
625 textMatrix
= CGAffineTransformMake (font
->base
.scale
.xx
,
626 -font
->base
.scale
.yx
,
627 -font
->base
.scale
.xy
,
630 glyphRect
= CGRectMake (bbox
.origin
.x
/ emscale
,
631 bbox
.origin
.y
/ emscale
,
632 bbox
.size
.width
/ emscale
,
633 bbox
.size
.height
/ emscale
);
635 glyphRect
= CGRectApplyAffineTransform (glyphRect
, textMatrix
);
637 /* Round the rectangle outwards, so that we don't have to deal
638 * with non-integer-pixel origins or dimensions.
640 glyphRectInt
= CGRectIntegral (glyphRect
);
643 fprintf (stderr
, "glyphRect[o]: %f %f %f %f\n",
644 glyphRect
.origin
.x
, glyphRect
.origin
.y
, glyphRect
.size
.width
, glyphRect
.size
.height
);
645 fprintf (stderr
, "glyphRectInt: %f %f %f %f\n",
646 glyphRectInt
.origin
.x
, glyphRectInt
.origin
.y
, glyphRectInt
.size
.width
, glyphRectInt
.size
.height
);
649 glyphOrigin
= glyphRectInt
.origin
;
651 //textMatrix = CGAffineTransformConcat (textMatrix, CGAffineTransformInvert (ctm));
653 width
= glyphRectInt
.size
.width
;
654 height
= glyphRectInt
.size
.height
;
656 //fprintf (stderr, "glyphRect[n]: %f %f %f %f\n", glyphRect.origin.x, glyphRect.origin.y, glyphRect.size.width, glyphRect.size.height);
658 surface
= (cairo_image_surface_t
*) cairo_image_surface_create (CAIRO_FORMAT_A8
, width
, height
);
659 if (surface
->base
.status
)
660 return surface
->base
.status
;
662 gray
= CGColorSpaceCreateDeviceGray ();
663 cgContext
= CGBitmapContextCreate (surface
->data
,
670 CGColorSpaceRelease (gray
);
672 CGContextSetFont (cgContext
, font_face
->cgFont
);
673 CGContextSetFontSize (cgContext
, 1.0);
674 CGContextSetTextMatrix (cgContext
, textMatrix
);
676 CGContextClearRect (cgContext
, CGRectMake (0.0f
, 0.0f
, width
, height
));
678 if (font
->base
.options
.antialias
== CAIRO_ANTIALIAS_NONE
)
679 CGContextSetShouldAntialias (cgContext
, false);
681 CGContextSetRGBFillColor (cgContext
, 1.0, 1.0, 1.0, 1.0);
682 CGContextShowGlyphsAtPoint (cgContext
, - glyphOrigin
.x
, - glyphOrigin
.y
, &glyph
, 1);
684 CGContextRelease (cgContext
);
686 cairo_surface_set_device_offset (&surface
->base
,
688 height
+ glyphOrigin
.y
);
690 _cairo_scaled_glyph_set_surface (scaled_glyph
, &font
->base
, surface
);
695 static cairo_int_status_t
696 _cairo_quartz_scaled_glyph_init (void *abstract_font
,
697 cairo_scaled_glyph_t
*scaled_glyph
,
698 cairo_scaled_glyph_info_t info
)
700 cairo_quartz_scaled_font_t
*font
= (cairo_quartz_scaled_font_t
*) abstract_font
;
701 cairo_int_status_t status
= CAIRO_STATUS_SUCCESS
;
703 if (!status
&& (info
& CAIRO_SCALED_GLYPH_INFO_METRICS
))
704 status
= _cairo_quartz_init_glyph_metrics (font
, scaled_glyph
);
706 if (!status
&& (info
& CAIRO_SCALED_GLYPH_INFO_PATH
))
707 status
= _cairo_quartz_init_glyph_path (font
, scaled_glyph
);
709 if (!status
&& (info
& CAIRO_SCALED_GLYPH_INFO_SURFACE
))
710 status
= _cairo_quartz_init_glyph_surface (font
, scaled_glyph
);
716 _cairo_quartz_ucs4_to_index (void *abstract_font
,
719 cairo_quartz_scaled_font_t
*font
= (cairo_quartz_scaled_font_t
*) abstract_font
;
720 cairo_quartz_font_face_t
*ffont
= _cairo_quartz_scaled_to_face(font
);
721 UniChar u
= (UniChar
) ucs4
;
724 CGFontGetGlyphsForUnicharsPtr (ffont
->cgFont
, &u
, &glyph
, 1);
729 static const cairo_scaled_font_backend_t _cairo_quartz_scaled_font_backend
= {
730 CAIRO_FONT_TYPE_QUARTZ
,
731 _cairo_quartz_scaled_font_fini
,
732 _cairo_quartz_scaled_glyph_init
,
733 NULL
, /* text_to_glyphs */
734 _cairo_quartz_ucs4_to_index
,
735 NULL
, /* show_glyphs */
736 NULL
, /* load_truetype_table */
737 NULL
, /* map_glyphs_to_unicode */
741 * private methods that the quartz surface uses
745 _cairo_quartz_scaled_font_get_cg_font_ref (cairo_scaled_font_t
*abstract_font
)
747 cairo_quartz_font_face_t
*ffont
= _cairo_quartz_scaled_to_face(abstract_font
);
749 return ffont
->cgFont
;
754 * compat with old ATSUI backend
758 * cairo_quartz_font_face_create_for_atsu_font_id
759 * @font_id: an ATSUFontID for the font.
761 * Creates a new font for the Quartz font backend based on an
762 * #ATSUFontID. This font can then be used with
763 * cairo_set_font_face() or cairo_scaled_font_create().
765 * Return value: a newly created #cairo_font_face_t. Free with
766 * cairo_font_face_destroy() when you are done using it.
771 cairo_quartz_font_face_create_for_atsu_font_id (ATSUFontID font_id
)
773 ATSFontRef atsFont
= FMGetATSFontRefFromFont (font_id
);
774 CGFontRef cgFont
= CGFontCreateWithPlatformFont (&atsFont
);
775 cairo_font_face_t
*ff
;
777 ff
= cairo_quartz_font_face_create_for_cgfont (cgFont
);
779 CGFontRelease (cgFont
);
784 /* This is the old name for the above function, exported for compat purposes */
785 cairo_font_face_t
*cairo_atsui_font_face_create_for_atsu_font_id (ATSUFontID font_id
);
788 cairo_atsui_font_face_create_for_atsu_font_id (ATSUFontID font_id
)
790 return cairo_quartz_font_face_create_for_atsu_font_id (font_id
);