[cairo-commit] 9 commits - configure.in doc/public src/cairo-atsui-font.c src/cairoint.h src/cairo-quartz-font.c src/cairo-quartz.h src/cairo-quartz-private.h src/cairo-quartz-surface.c src/Makefile.am test/clip-operator-quartz-ref.png test/clip-operator-quartz-rgb24-ref.png test/font-matrix-translation-quartz-ref.png test/glyph-cache-pressure-quartz-ref.png test/linear-gradient-reflect-quartz-ref.png test/Makefile.am test/operator-clear-quartz-ref.png test/operator-clear-quartz-rgb24-ref.png test/operator-source-quartz-ref.png test/operator-source-quartz-rgb24-ref.png test/select-font-face-quartz-ref.png test/show-text-current-point-quartz-ref.png test/surface-pattern-scale-down-quartz-ref.png test/text-antialias-gray-quartz-ref.png test/text-antialias-none-quartz-ref.png test/text-antialias-subpixel-quartz-ref.png test/text-pattern-quartz-ref.png test/text-pattern-quartz-rgb24-ref.png test/text-rotate-quartz-ref.png test/unbounded-operator-quartz-ref.png test/unbounded-operator-quartz-rgb24-ref.png

Vladimir Vukicevic vladimir at kemper.freedesktop.org
Tue Apr 1 13:49:28 PDT 2008


 configure.in                                   |   10 
 doc/public/cairo-docs.xml                      |    1 
 doc/public/cairo-sections.txt                  |   14 
 doc/public/tmpl/cairo-ft.sgml                  |    8 
 doc/public/tmpl/cairo-quartz-fonts.sgml        |   48 +
 doc/public/tmpl/cairo-quartz.sgml              |   25 
 doc/public/tmpl/cairo-xlib.sgml                |    8 
 src/Makefile.am                                |    3 
 src/cairo-atsui-font.c                         | 1028 -------------------------
 src/cairo-quartz-font.c                        |  726 +++++++++++++++++
 src/cairo-quartz-private.h                     |    5 
 src/cairo-quartz-surface.c                     |   93 +-
 src/cairo-quartz.h                             |    5 
 src/cairoint.h                                 |    4 
 test/Makefile.am                               |    3 
 test/clip-operator-quartz-ref.png              |binary
 test/clip-operator-quartz-rgb24-ref.png        |binary
 test/font-matrix-translation-quartz-ref.png    |binary
 test/glyph-cache-pressure-quartz-ref.png       |binary
 test/linear-gradient-reflect-quartz-ref.png    |binary
 test/operator-clear-quartz-ref.png             |binary
 test/operator-clear-quartz-rgb24-ref.png       |binary
 test/operator-source-quartz-ref.png            |binary
 test/operator-source-quartz-rgb24-ref.png      |binary
 test/select-font-face-quartz-ref.png           |binary
 test/show-text-current-point-quartz-ref.png    |binary
 test/surface-pattern-scale-down-quartz-ref.png |binary
 test/text-antialias-gray-quartz-ref.png        |binary
 test/text-antialias-none-quartz-ref.png        |binary
 test/text-antialias-subpixel-quartz-ref.png    |binary
 test/text-pattern-quartz-ref.png               |binary
 test/text-pattern-quartz-rgb24-ref.png         |binary
 test/text-rotate-quartz-ref.png                |binary
 test/unbounded-operator-quartz-ref.png         |binary
 test/unbounded-operator-quartz-rgb24-ref.png   |binary
 35 files changed, 870 insertions(+), 1111 deletions(-)

New commits:
commit 56800e6ea0f7153e44f0cba14c89c4239067a60e
Author: Vladimir Vukicevic <vladimir at pobox.com>
Date:   Tue Apr 1 13:28:03 2008 -0700

    [quartz] Remove cairo-atsui-font.c

diff --git a/src/cairo-atsui-font.c b/src/cairo-atsui-font.c
deleted file mode 100644
index 42c209b..0000000
--- a/src/cairo-atsui-font.c
+++ /dev/null
@@ -1,1028 +0,0 @@
-/* -*- Mode: c; c-basic-offset: 4; tab-width: 8; indent-tabs-mode: t; -*- */
-/* cairo - a vector graphics library with display and print output
- *
- * Copyright © 2004 Calum Robinson
- *
- * This library is free software; you can redistribute it and/or
- * modify it either under the terms of the GNU Lesser General Public
- * License version 2.1 as published by the Free Software Foundation
- * (the "LGPL") or, at your option, under the terms of the Mozilla
- * Public License Version 1.1 (the "MPL"). If you do not alter this
- * notice, a recipient may use your version of this file under either
- * the MPL or the LGPL.
- *
- * You should have received a copy of the LGPL along with this library
- * in the file COPYING-LGPL-2.1; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- * You should have received a copy of the MPL along with this library
- * in the file COPYING-MPL-1.1
- *
- * The contents of this file are subject to the Mozilla Public License
- * Version 1.1 (the "License"); you may not use this file except in
- * compliance with the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
- * OF ANY KIND, either express or implied. See the LGPL or the MPL for
- * the specific language governing rights and limitations.
- *
- * The Original Code is the cairo graphics library.
- *
- * The Initial Developer of the Original Code is Calum Robinson
- *
- * Contributor(s):
- *  Calum Robinson <calumr at mac.com>
- */
-
-#include "cairoint.h"
-
-#include "cairo.h"
-#include "cairo-quartz.h"
-#include "cairo-quartz-private.h"
-
-/*
- * FixedToFloat/FloatToFixed are 10.3+ SDK items - include definitions
- * here so we can use older SDKs.
- */
-#ifndef FixedToFloat
-#define fixed1              ((Fixed) 0x00010000L)
-#define FixedToFloat(a)     ((float)(a) / fixed1)
-#define FloatToFixed(a)     ((Fixed)((float)(a) * fixed1))
-#endif
-
-/* If this isn't defined, we must be building on non-intel,
- * hence it will be 0.
- */
-#ifdef __BIG_ENDIAN__
-#define CG_BITMAP_BYTE_ORDER_FLAG 0
-#else    /* Little endian. */
-/* x86, and will be a 10.4u SDK; ByteOrder32Host will be defined */
-#define CG_BITMAP_BYTE_ORDER_FLAG kCGBitmapByteOrder32Host
-#endif
-
-/* Public in 10.4, present in 10.3.9 */
-CG_EXTERN CGRect CGRectApplyAffineTransform (CGRect, CGAffineTransform);
-
-/* Error code for path callbacks */
-static OSStatus CAIRO_CG_PATH_ERROR = 1001;
-
-typedef struct _cairo_atsui_font_face cairo_atsui_font_face_t;
-typedef struct _cairo_atsui_font cairo_atsui_font_t;
-typedef struct _cairo_atsui_scaled_path cairo_atsui_scaled_path_t;
-
-static cairo_status_t _cairo_atsui_font_create_scaled (cairo_font_face_t *font_face,
-						       ATSUFontID font_id,
-						       ATSUStyle style,
-						       const cairo_matrix_t *font_matrix,
-						       const cairo_matrix_t *ctm,
-						       const cairo_font_options_t *options,
-						       cairo_scaled_font_t **font_out);
-
-struct _cairo_atsui_font {
-    cairo_scaled_font_t base;
-
-    ATSUStyle style;
-    ATSUStyle unscaled_style;
-    ATSUFontID fontID;
-
-    Fixed size;
-    CGAffineTransform font_matrix;
-    CGFontRef cgfref;
-};
-
-struct _cairo_atsui_font_face {
-  cairo_font_face_t base;
-  ATSUFontID font_id;
-};
-
-struct _cairo_atsui_scaled_path {
-    cairo_path_fixed_t *path;
-    cairo_matrix_t *scale;
-};
-
-static void
-_cairo_atsui_font_face_destroy (void *abstract_face)
-{
-}
-
-static cairo_status_t
-_cairo_atsui_font_face_scaled_font_create (void	*abstract_face,
-					   const cairo_matrix_t	*font_matrix,
-					   const cairo_matrix_t	*ctm,
-					   const cairo_font_options_t *options,
-					   cairo_scaled_font_t **font)
-{
-    cairo_status_t status;
-    cairo_atsui_font_face_t *font_face = abstract_face;
-    OSStatus err;
-    ATSUAttributeTag styleTags[] = { kATSUFontTag };
-    ATSUAttributeValuePtr styleValues[] = { &font_face->font_id };
-    ByteCount styleSizes[] = {  sizeof(ATSUFontID) };
-    ATSUStyle style;
-
-    err = ATSUCreateStyle (&style);
-    if (err != noErr)
-	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-
-    err = ATSUSetAttributes(style, ARRAY_LENGTH (styleTags),
-                            styleTags, styleSizes, styleValues);
-    if (err != noErr) {
-        ATSUDisposeStyle (style);
-	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-    }
-
-    status = _cairo_atsui_font_create_scaled (&font_face->base, font_face->font_id, style,
-					    font_matrix, ctm, options, font);
-    if (status)
-        ATSUDisposeStyle (style);
-
-    return status;
-}
-
-static const cairo_font_face_backend_t _cairo_atsui_font_face_backend = {
-    CAIRO_FONT_TYPE_QUARTZ,
-    _cairo_atsui_font_face_destroy,
-    _cairo_atsui_font_face_scaled_font_create
-};
-
-/**
- * cairo_atsui_font_face_create_for_atsu_font_id
- * @font_id: an ATSUFontID for the font.
- *
- * Creates a new font for the Quartz font backend based on an
- * #ATSUFontID. This font can then be used with
- * cairo_set_font_face() or cairo_scaled_font_create().
- *
- * Return value: a newly created #cairo_font_face_t. Free with
- *  cairo_font_face_destroy() when you are done using it.
- *
- * Since: 1.6
- **/
-cairo_font_face_t *
-cairo_quartz_font_face_create_for_atsu_font_id (ATSUFontID font_id)
-{
-  cairo_atsui_font_face_t *font_face;
-
-  font_face = malloc (sizeof (cairo_atsui_font_face_t));
-  if (!font_face) {
-    _cairo_error (CAIRO_STATUS_NO_MEMORY);
-    return (cairo_font_face_t *)&_cairo_font_face_nil;
-  }
-
-  font_face->font_id = font_id;
-
-    _cairo_font_face_init (&font_face->base, &_cairo_atsui_font_face_backend);
-
-    return &font_face->base;
-}
-
-/* This is the old name for the above function, exported for compat purposes */
-cairo_font_face_t *cairo_atsui_font_face_create_for_atsu_font_id (ATSUFontID font_id);
-
-cairo_font_face_t *
-cairo_atsui_font_face_create_for_atsu_font_id (ATSUFontID font_id)
-{
-    return cairo_quartz_font_face_create_for_atsu_font_id (font_id);
-}
-
-static OSStatus
-CreateSizedCopyOfStyle(ATSUStyle inStyle, 
-		       const Fixed *theSize, 
-                      const CGAffineTransform *theTransform,
-                      ATSUStyle *style)
-{
-    OSStatus err;
-    const ATSUAttributeTag theFontStyleTags[] = { kATSUSizeTag, 
-                                                 kATSUFontMatrixTag };
-    const ByteCount theFontStyleSizes[] = { sizeof(Fixed), 
-                                           sizeof(CGAffineTransform) };
-    ATSUAttributeValuePtr theFontStyleValues[] = { (Fixed *)theSize, 
-                                                  (CGAffineTransform *)theTransform };
-
-    err = ATSUCreateAndCopyStyle (inStyle, style);
-    if (err != noErr)
-	return err;
-
-    err = ATSUSetAttributes(*style,
-                            sizeof(theFontStyleTags) /
-                            sizeof(ATSUAttributeTag), theFontStyleTags,
-                            theFontStyleSizes, theFontStyleValues);
-    if (err != noErr)
-	ATSUDisposeStyle (*style);
-
-    return err;
-}
-
-
-static cairo_status_t
-_cairo_atsui_font_set_metrics (cairo_atsui_font_t *font)
-{
-    cairo_status_t status;
-    ATSFontRef atsFont;
-    ATSFontMetrics metrics;
-    OSStatus err;
-
-    atsFont = FMGetATSFontRefFromFont(font->fontID);
-
-    if (atsFont) {
-        err = ATSFontGetHorizontalMetrics(atsFont, kATSOptionFlagsDefault, &metrics);
-
-        if (err == noErr) {
-	    cairo_font_extents_t extents;
-
-            extents.ascent = metrics.ascent;
-            extents.descent = -metrics.descent;
-            extents.height = extents.ascent + extents.descent + metrics.leading;
-            extents.max_x_advance = metrics.maxAdvanceWidth;
-
-            /* The FT backend doesn't handle max_y_advance either, so we'll ignore it for now. */
-            extents.max_y_advance = 0.0;
-
-	    status = _cairo_scaled_font_set_metrics (&font->base, &extents);
-
-            return status;
-        }
-    }
-
-    return _cairo_error (CAIRO_STATUS_NULL_POINTER);
-}
-
-static cairo_status_t
-_cairo_atsui_font_create_scaled (cairo_font_face_t *font_face,
-				 ATSUFontID font_id,
-				 ATSUStyle style,
-				 const cairo_matrix_t *font_matrix,
-				 const cairo_matrix_t *ctm,
-				 const cairo_font_options_t *options,
-				 cairo_scaled_font_t **font_out)
-{
-    cairo_atsui_font_t *font = NULL;
-    OSStatus err;
-    cairo_status_t status;
-    double xscale = 1.0;
-    double yscale = 1.0;
-
-    font = malloc(sizeof(cairo_atsui_font_t));
-    if (font == NULL)
-	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-
-    memset (font, 0, sizeof(cairo_atsui_font_t));
-
-    status = _cairo_scaled_font_init (&font->base,
-				      font_face, font_matrix, ctm, options,
-				      &cairo_atsui_scaled_font_backend);
-    if (status) {
-	free (font);
-	return status;
-    }
-
-    status = _cairo_matrix_compute_scale_factors (&font->base.scale,
-						  &xscale, &yscale, 1);
-    if (status)
-	goto FAIL;
-
-    /* ATS can't handle 0-sized bits; we end up in an odd infinite loop
-     * if we send down a size of 0. */
-    if (xscale == 0.0) {
-	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
-	goto FAIL;
-    }
-
-    font->font_matrix = CGAffineTransformMake (1., 0.,
-					       0., yscale/xscale,
-					       0., 0.);
-    font->size = FloatToFixed (xscale);
-    font->style = NULL;
-
-    err = CreateSizedCopyOfStyle (style, &font->size, &font->font_matrix, &font->style);
-    if (err != noErr) {
-	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
-	goto FAIL;
-    }
-
-    {
-	Fixed theSize = FloatToFixed(1.0);
-	const ATSUAttributeTag theFontStyleTags[] = { kATSUSizeTag };
-	const ByteCount theFontStyleSizes[] = { sizeof(Fixed) };
-	ATSUAttributeValuePtr theFontStyleValues[] = { &theSize };
-
-	err = ATSUSetAttributes(style,
-				sizeof(theFontStyleTags) /
-				sizeof(ATSUAttributeTag), theFontStyleTags,
-				theFontStyleSizes, theFontStyleValues);
-	if (err != noErr) {
-	    status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
-	    goto FAIL;
-	}
-    }
-
-    font->unscaled_style = style;
-    font->fontID = font_id;
-
-    *font_out = &font->base;
-
-    status = _cairo_atsui_font_set_metrics (font);
-
-    font->cgfref = 0;
-  FAIL:
-    if (status) {
-	if (font) {
-	    if (font->style)
-		ATSUDisposeStyle(font->style);
-	    _cairo_scaled_font_fini(&font->base);
-	    free (font);
-	}
-
-	return status;
-    }
-
-    return CAIRO_STATUS_SUCCESS;
-}
-
-static cairo_status_t
-_cairo_atsui_font_create_toy(cairo_toy_font_face_t *toy_face,
-			     const cairo_matrix_t *font_matrix,
-			     const cairo_matrix_t *ctm,
-			     const cairo_font_options_t *options,
-			     cairo_scaled_font_t **font_out)
-{
-    cairo_status_t status;
-    ATSUStyle style;
-    ATSUFontID fontID;
-    OSStatus err;
-    Boolean isItalic, isBold;
-    const char *family = toy_face->family;
-    const char *full_name;
-
-    err = ATSUCreateStyle(&style);
-    if (err != noErr) {
-	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-    }
-
-    switch (toy_face->weight) {
-    case CAIRO_FONT_WEIGHT_BOLD:
-        isBold = true;
-        break;
-    case CAIRO_FONT_WEIGHT_NORMAL:
-    default:
-        isBold = false;
-        break;
-    }
-
-    switch (toy_face->slant) {
-    case CAIRO_FONT_SLANT_ITALIC:
-        isItalic = true;
-        break;
-    case CAIRO_FONT_SLANT_OBLIQUE:
-        isItalic = false;
-        break;
-    case CAIRO_FONT_SLANT_NORMAL:
-    default:
-        isItalic = false;
-        break;
-    }
-
-    /* The APIs for resolving a font family to a regular
-     * font face are all broken or deprecated in 10.4, so
-     * just try our best to find a sensible font.
-     * 
-     * First we try to map the CSS generic font families
-     * to fonts that should always be available. 
-     * If the family isn't a CSS family, guess that the 
-     * font family name is the same as the full name of the 
-     * regular font instance, which works in many cases. 
-     * 'Times' is one common exception to this rule, so it's
-     * handled specially.
-     */
-    if (!strcmp(family, "serif") || !strcmp(family, "Times"))
-	full_name = "Times Roman";
-    else if (!strcmp(family, "sans-serif") || !strcmp(family, "sans"))
-	full_name = "Helvetica";
-    else if (!strcmp(family, "cursive"))
-	full_name = "Apple Chancery";
-    else if (!strcmp(family, "fantasy"))
-	full_name = "American Typewriter";
-    else if (!strcmp(family, "monospace") || !strcmp(family, "mono"))
-	full_name = "Courier";
-    else
-	full_name = family;
-
-    err = ATSUFindFontFromName(family, strlen(family),
-                               kFontFullName,
-                               kFontNoPlatformCode,
-                               kFontRomanScript,
-                               kFontNoLanguageCode, &fontID);
-
-    if (err != noErr) {
-	/* Look for any font instance in the family. This may 
-	 * succeed, but select the bold or italic face. It only
-	 * selects the first loaded font instance in the family.
-	 */
-	err = ATSUFindFontFromName(family, strlen(family),
-				   kFontFamilyName,
-				   kFontNoPlatformCode,
-				   kFontRomanScript,
-				   kFontNoLanguageCode, &fontID);
-	if (err != noErr) {
-	    /* Last chance - try Courier. */
-	    full_name = "Courier";
-	    err = ATSUFindFontFromName(full_name, strlen(full_name),
-				       kFontFullName,
-				       kFontNoPlatformCode,
-				       kFontRomanScript,
-				       kFontNoLanguageCode, &fontID);
-	    if (err != noErr) {
-		ATSUDisposeStyle (style);
-		return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-	    }
-	}
-    }
-
-    {
-	ATSUAttributeTag styleTags[] =
-	    { kATSUQDItalicTag, kATSUQDBoldfaceTag, kATSUFontTag };
-	ATSUAttributeValuePtr styleValues[] = { &isItalic, &isBold, &fontID };
-	ByteCount styleSizes[] =
-	    { sizeof(Boolean), sizeof(Boolean), sizeof(ATSUFontID) };
-
-	err = ATSUSetAttributes(style, ARRAY_LENGTH (styleTags),
-				styleTags, styleSizes, styleValues);
-	if (err != noErr) {
-	    ATSUDisposeStyle (style);
-	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-	}
-    }
-
-    status = _cairo_atsui_font_create_scaled (&toy_face->base, fontID, style,
-					    font_matrix, ctm, options, font_out);
-    if (status)
-	ATSUDisposeStyle (style);
-
-    return status;
-}
-
-static void
-_cairo_atsui_font_fini(void *abstract_font)
-{
-    cairo_atsui_font_t *font = abstract_font;
-
-    if (font == NULL)
-        return;
-
-    if (font->style)
-        ATSUDisposeStyle(font->style);
-    if (font->unscaled_style)
-        ATSUDisposeStyle(font->unscaled_style);
-    if (font->cgfref)
-	CGFontRelease(font->cgfref);
-
-}
-
-static GlyphID 
-_cairo_atsui_scaled_glyph_index (cairo_scaled_glyph_t *scaled_glyph) {
-    unsigned long index = _cairo_scaled_glyph_index (scaled_glyph);
-    if (index > 0xffff) 
-	return kATSDeletedGlyphcode;
-    return index;
-}
-
-static cairo_status_t
-_cairo_atsui_font_init_glyph_metrics (cairo_atsui_font_t *scaled_font,
-				      cairo_scaled_glyph_t *scaled_glyph)
-{
-    cairo_status_t status;
-    cairo_text_extents_t extents = {0, 0, 0, 0, 0, 0};
-    OSStatus err;
-    ATSGlyphScreenMetrics metricsH;
-    GlyphID theGlyph = _cairo_atsui_scaled_glyph_index (scaled_glyph);
-    double xscale, yscale;
-
-    if (theGlyph == kATSDeletedGlyphcode) {
-	_cairo_scaled_glyph_set_metrics (scaled_glyph,
-					 &scaled_font->base,
-					 &extents);
-	return CAIRO_STATUS_SUCCESS;
-    }
-
-    /* We calculate the advance from the screen metrics. We
-     * could probably take this from the glyph path.
-     */
-    err = ATSUGlyphGetScreenMetrics (scaled_font->style,
-				     1, &theGlyph, 0, false,
-				     false, &metricsH);
-    if (err != noErr)
-	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-
-    /* Scale down to font units.*/
-    status = _cairo_matrix_compute_scale_factors (&scaled_font->base.scale,
-						  &xscale, &yscale, 1);
-    if (status)
-	return status;
-
-    xscale = 1.0/xscale;
-    yscale = 1.0/yscale;
-
-    extents.x_advance = metricsH.deviceAdvance.x * xscale;
-    extents.y_advance = 0;
-    
-    extents.x_bearing = metricsH.topLeft.x * xscale;
-    extents.y_bearing = -metricsH.topLeft.y * yscale;
-    extents.width = metricsH.width * xscale;
-    extents.height = metricsH.height * yscale;
-
-    _cairo_scaled_glyph_set_metrics (scaled_glyph,
-				     &scaled_font->base,
-				     &extents);
-    return CAIRO_STATUS_SUCCESS;
-}
-
-static OSStatus
-_move_to (const Float32Point *point,
-	  void *callback_data)
-{
-    cairo_status_t status;
-    cairo_atsui_scaled_path_t *scaled_path = callback_data;
-    double x = point->x;
-    double y = point->y;
-    
-    cairo_matrix_transform_point (scaled_path->scale, &x, &y);
-    status = _cairo_path_fixed_close_path (scaled_path->path);
-    if (status)
-	return CAIRO_CG_PATH_ERROR;
-
-    status = _cairo_path_fixed_move_to (scaled_path->path,
-			       _cairo_fixed_from_double (x),
-			       _cairo_fixed_from_double (y));
-    if (status)
-	return CAIRO_CG_PATH_ERROR;
-    
-    return noErr;
-}
-
-static OSStatus
-_line_to (const Float32Point *point,
-	  void *callback_data)
-{
-    cairo_status_t status;
-    cairo_atsui_scaled_path_t *scaled_path = callback_data;
-    double x = point->x;
-    double y = point->y;
-    
-    cairo_matrix_transform_point (scaled_path->scale, &x, &y);
-
-    status = _cairo_path_fixed_line_to (scaled_path->path,
-			       _cairo_fixed_from_double (x),
-			       _cairo_fixed_from_double (y));
-    if (status)
-	return CAIRO_CG_PATH_ERROR;
-
-    return noErr;
-}
-
-static OSStatus
-_curve_to (const Float32Point *point1,
-	   const Float32Point *point2,
-	   const Float32Point *point3,
-	   void *callback_data)
-{
-    cairo_status_t status;
-    cairo_atsui_scaled_path_t *scaled_path = callback_data;
-    double x1 = point1->x;
-    double y1 = point1->y;
-    double x2 = point2->x;
-    double y2 = point2->y;
-    double x3 = point3->x;
-    double y3 = point3->y;
-    
-    cairo_matrix_transform_point (scaled_path->scale, &x1, &y1);
-    cairo_matrix_transform_point (scaled_path->scale, &x2, &y2);
-    cairo_matrix_transform_point (scaled_path->scale, &x3, &y3);
-
-    status = _cairo_path_fixed_curve_to (scaled_path->path,
-				_cairo_fixed_from_double (x1),
-				_cairo_fixed_from_double (y1),
-				_cairo_fixed_from_double (x2),
-				_cairo_fixed_from_double (y2),
-				_cairo_fixed_from_double (x3),
-				_cairo_fixed_from_double (y3));
-    if (status)
-	return CAIRO_CG_PATH_ERROR;
-
-    return noErr;
-}
-
-static OSStatus
-_close_path (void *callback_data)
-
-{
-    cairo_status_t status;
-    cairo_atsui_scaled_path_t *scaled_path = callback_data;
-
-    status = _cairo_path_fixed_close_path (scaled_path->path);
-    if (status)
-	return CAIRO_CG_PATH_ERROR;
-
-    return noErr;
-}
-
-static cairo_status_t
-_cairo_atsui_scaled_font_init_glyph_path (cairo_atsui_font_t *scaled_font,
-					  cairo_scaled_glyph_t *scaled_glyph)
-{
-    cairo_status_t status;
-    static ATSCubicMoveToUPP moveProc = NULL;
-    static ATSCubicLineToUPP lineProc = NULL;
-    static ATSCubicCurveToUPP curveProc = NULL;
-    static ATSCubicClosePathUPP closePathProc = NULL;
-    GlyphID theGlyph = _cairo_atsui_scaled_glyph_index (scaled_glyph);
-    OSStatus err;
-    cairo_atsui_scaled_path_t scaled_path;
-    cairo_matrix_t *font_to_device = &scaled_font->base.scale;
-    cairo_matrix_t unscaled_font_to_device;
-    double xscale;
-    double yscale;
-
-    scaled_path.path = _cairo_path_fixed_create ();
-    if (!scaled_path.path)
-	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-
-    if (theGlyph == kATSDeletedGlyphcode) {
-	_cairo_scaled_glyph_set_path (scaled_glyph, &scaled_font->base, 
-				      scaled_path.path);
-
-	return CAIRO_STATUS_SUCCESS;
-    }
-
-    /* extract the rotation/shear component of the scale matrix. */
-    status = _cairo_matrix_compute_scale_factors (font_to_device, &xscale, &yscale, 1);
-    if (status)
-	goto FAIL;
-
-    cairo_matrix_init (&unscaled_font_to_device, 
-		      font_to_device->xx, 
-		      font_to_device->yx, 
-		      font_to_device->xy, 
-		      font_to_device->yy, 0., 0.);
-    cairo_matrix_scale (&unscaled_font_to_device, 1.0/xscale, 1.0/yscale);
-
-    scaled_path.scale = &unscaled_font_to_device;
-
-    if (moveProc == NULL) {
-        moveProc = NewATSCubicMoveToUPP(_move_to);
-        lineProc = NewATSCubicLineToUPP(_line_to);
-        curveProc = NewATSCubicCurveToUPP(_curve_to);
-        closePathProc = NewATSCubicClosePathUPP(_close_path);
-    }
-
-    err = ATSUGlyphGetCubicPaths(scaled_font->style,
-				 theGlyph,
-				 moveProc,
-				 lineProc,
-				 curveProc,
-				 closePathProc, (void *)&scaled_path, &err);
-    if (err != noErr) {
-	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
-	goto FAIL;
-    }
-
-    _cairo_scaled_glyph_set_path (scaled_glyph, &scaled_font->base, 
-				  scaled_path.path);
-
-    return CAIRO_STATUS_SUCCESS;
-
-  FAIL:
-    _cairo_path_fixed_destroy (scaled_path.path);
-    return status;
-}
-
-static cairo_status_t
-_cairo_atsui_scaled_font_init_glyph_surface (cairo_atsui_font_t *scaled_font,
-					     cairo_scaled_glyph_t *scaled_glyph)
-{
-    OSStatus err;
-    CGContextRef drawingContext;
-    cairo_image_surface_t *surface;
-    cairo_format_t format;
-    cairo_status_t status;
-
-    ATSFontRef atsFont;
-    CGFontRef cgFont;
-    cairo_scaled_font_t base = scaled_font->base;
-    cairo_font_extents_t extents = base.extents;
-
-    GlyphID theGlyph = _cairo_atsui_scaled_glyph_index (scaled_glyph);
-    ATSGlyphScreenMetrics metricsH;
-    double left, bottom, width, height;
-    double xscale, yscale;
-    CGRect bbox;
-    CGAffineTransform transform;
-
-    if (theGlyph == kATSDeletedGlyphcode) {
-	surface = (cairo_image_surface_t *)cairo_image_surface_create (CAIRO_FORMAT_A8, 2, 2);
-	status = cairo_surface_status ((cairo_surface_t *)surface);
-	if (status)
-	    return status;
-
-	_cairo_scaled_glyph_set_surface (scaled_glyph,
-					 &base,
-					 surface);
-	return CAIRO_STATUS_SUCCESS;
-    }
-
-    /* Compute a box to contain the glyph mask. The vertical
-     * sizes come from the font extents; extra pixels are
-     * added to account for fractional sizes.
-     */
-    height = extents.ascent + extents.descent + 2.0;
-    bottom = -extents.descent - 1.0;
-
-    status = _cairo_matrix_compute_scale_factors (&base.scale,
-						  &xscale, &yscale, 1);
-    if (status)
-	return status;
-
-    bbox = CGRectApplyAffineTransform (CGRectMake (1.0, bottom, 1.0, height), CGAffineTransformMakeScale(xscale, yscale));
-    bottom = CGRectGetMinY (bbox);
-    height = bbox.size.height;
-
-    /* Horizontal sizes come from the glyph typographic metrics.
-     * It is possible that this might result in clipped text
-     * in fonts where the typographic bounds don't cover the ink.
-     * The width is recalculated, since metricsH.width is rounded.
-     */
-    err = ATSUGlyphGetScreenMetrics (scaled_font->style,
-				     1, &theGlyph, 0, false,
-				     false, &metricsH);    
-    if (err != noErr) {
-	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-    }
-
-    left = metricsH.sideBearing.x - 1.0;
-    width = metricsH.deviceAdvance.x 
-	- metricsH.sideBearing.x 
-	+ metricsH.otherSideBearing.x + 2.0;
-
-    /* The xy and yx components are negated because the y-axis
-     * is flipped into the cairo system then flipped back, ie:
-     * [1  0][xx yx][1  0]
-     * [0 -1][xy yy][0 -1]
-     */
-    transform = CGAffineTransformMake (base.scale.xx, 
-				      -base.scale.yx, 
-				      -base.scale.xy, 
-				      base.scale.yy, 
-				      0., 0.);
-    status = _cairo_matrix_compute_scale_factors (&base.scale,
-						  &xscale, &yscale, 1);
-    if (status)
-	return status;
-
-    transform = CGAffineTransformScale (transform, 1.0/xscale, 1.0/yscale);
-
-    /* Rotate the bounding box. This computes the smallest CGRect
-     * that would contain the bounding box after rotation.
-     */
-    bbox = CGRectApplyAffineTransform (CGRectMake (left, bottom, 
-						   width, height), transform);
-    /* Compute the smallest CGRect with  integer coordinates
-     * that contains the bounding box.
-     */
-    bbox = CGRectIntegral (bbox);
-
-    left = CGRectGetMinX (bbox);
-    bottom = CGRectGetMinY (bbox);
-
-    /* XXX should we select format based on antialiasing flags, as ft does? */
-    format = CAIRO_FORMAT_A8;
-
-    /* create the glyph mask surface */
-    surface = (cairo_image_surface_t *)cairo_image_surface_create (format, bbox.size.width, bbox.size.height);
-    status = cairo_surface_status ((cairo_surface_t *)surface);
-    if (status)
-	return status;
-
-    /* Create a CGBitmapContext for the dest surface for drawing into */
-    {
-	CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceGray ();
-    
-	drawingContext = CGBitmapContextCreate (surface->data,
-						surface->width,
-						surface->height,
-						8,
-						surface->stride,
-						colorSpace,
-						kCGImageAlphaNone);
-	CGColorSpaceRelease (colorSpace);
-    }
-
-    if (!drawingContext) {
-	cairo_surface_destroy ((cairo_surface_t *)surface);
-	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-    }
-    
-    atsFont = FMGetATSFontRefFromFont (scaled_font->fontID);
-    cgFont = CGFontCreateWithPlatformFont (&atsFont);
-
-    CGContextSetFont (drawingContext, cgFont);
-
-    if (base.options.antialias ==  CAIRO_ANTIALIAS_NONE) {
-    	CGContextSetShouldAntialias (drawingContext, false);
-    }
-
-    /* solid white */
-    CGContextSetRGBFillColor (drawingContext, 1.0, 1.0, 1.0, 1.0);
-
-    CGContextSetFontSize (drawingContext, 1.0);
-    CGContextTranslateCTM (drawingContext, -left, -bottom);
-    CGContextScaleCTM (drawingContext, xscale, yscale);
-    CGContextSetTextMatrix (drawingContext, transform);
-    CGContextShowGlyphsAtPoint (drawingContext, 0, 0,  
-				&theGlyph, 1);
-
-    CGContextRelease (drawingContext);
-
-    /* correct for difference between cairo and quartz 
-     * coordinate systems.
-     */
-    cairo_surface_set_device_offset ((cairo_surface_t *)surface,
-				     -left, (bbox.size.height + bottom));
-    _cairo_scaled_glyph_set_surface (scaled_glyph,
-				     &base,
-				     surface);
-
-    return CAIRO_STATUS_SUCCESS;
-}
-
-static cairo_int_status_t
-_cairo_atsui_font_scaled_glyph_init (void			*abstract_font,
-				     cairo_scaled_glyph_t	*scaled_glyph,
-				     cairo_scaled_glyph_info_t	 info)
-{
-    cairo_atsui_font_t *scaled_font = abstract_font;
-    cairo_status_t status;
-
-    if ((info & CAIRO_SCALED_GLYPH_INFO_METRICS) != 0) {
-      status = _cairo_atsui_font_init_glyph_metrics (scaled_font, scaled_glyph);
-      if (status)
-	return status;
-    }
-
-    if ((info & CAIRO_SCALED_GLYPH_INFO_PATH) != 0) {
-	status = _cairo_atsui_scaled_font_init_glyph_path (scaled_font, scaled_glyph);
-	if (status)
-	    return status;
-    }
-
-    if ((info & CAIRO_SCALED_GLYPH_INFO_SURFACE) != 0) {
-	status = _cairo_atsui_scaled_font_init_glyph_surface (scaled_font, scaled_glyph);
-	if (status)
-	    return status;
-    }
-
-    return CAIRO_STATUS_SUCCESS;
-}
-
-static cairo_int_status_t
-_cairo_atsui_font_text_to_glyphs (void		*abstract_font,
-				  double	 x,
-				  double	 y,
-				  const char	*utf8,
-				  cairo_glyph_t **glyphs,
-				  int		*num_glyphs)
-{
-    cairo_status_t status = CAIRO_STATUS_SUCCESS;
-    uint16_t *utf16;
-    int n16;
-    OSStatus err;
-    ATSUTextLayout textLayout;
-    ATSLayoutRecord *layoutRecords;
-    cairo_atsui_font_t *font = abstract_font;
-    ItemCount glyphCount;
-    int i;
-    CGPoint point;
-    double xscale, yscale;
-    CGAffineTransform device_to_user_scale;
-
-    status = _cairo_utf8_to_utf16 ((unsigned char *)utf8, -1, &utf16, &n16);
-    if (status)
-	goto BAIL3;
-
-    err = ATSUCreateTextLayout(&textLayout);
-    if (err != noErr) {
-	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
-	goto BAIL3;
-    }
-
-    err = ATSUSetTextPointerLocation(textLayout, utf16, 0, n16, n16);
-    if (err != noErr) {
-	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
-	goto BAIL2;
-    }
-
-    /* Set the style for all of the text */
-    err = ATSUSetRunStyle(textLayout,
-			  font->style, kATSUFromTextBeginning, kATSUToTextEnd);
-    if (err != noErr) {
-	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
-	goto BAIL2;
-    }
-
-    err = ATSUDirectGetLayoutDataArrayPtrFromTextLayout(textLayout,
-							0,
-							kATSUDirectDataLayoutRecordATSLayoutRecordCurrent,
-							(void *)&layoutRecords,
-							&glyphCount);
-    if (err != noErr) {
-	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
-	goto BAIL2;
-    }
-
-    status = _cairo_matrix_compute_scale_factors (&font->base.ctm,
-						  &xscale, &yscale, 1);
-    if (status)
-	goto BAIL2;
-
-    *num_glyphs = glyphCount - 1;
-    *glyphs =
-	(cairo_glyph_t *) _cairo_malloc_ab(*num_glyphs, sizeof (cairo_glyph_t));
-    if (*glyphs == NULL) {
-	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
-	goto BAIL1;
-    }
-
-    device_to_user_scale = 
-	CGAffineTransformInvert (CGAffineTransformMake (xscale, 0,
-							0, yscale,
-							0, 0));
-    for (i = 0; i < *num_glyphs; i++) {
-	(*glyphs)[i].index = layoutRecords[i].glyphID;
-	/* ATSLayoutRecord.realPos is in device units, convert to user units */
-	point = CGPointMake (FixedToFloat (layoutRecords[i].realPos), 0);
-	point = CGPointApplyAffineTransform (point, device_to_user_scale);
-
-	(*glyphs)[i].x = x + point.x;
-	(*glyphs)[i].y = y;
-    }
-
-  BAIL1:
-    /* TODO ignored return value. Is there anything we should do? */
-    ATSUDirectReleaseLayoutDataArrayPtr(NULL,
-					kATSUDirectDataLayoutRecordATSLayoutRecordCurrent,
-					(void *) &layoutRecords);
-  BAIL2:
-    ATSUDisposeTextLayout(textLayout);
-  BAIL3:
-    free (utf16);
-
-    return status;
-}
-
-CGFontRef
-_cairo_quartz_scaled_font_get_cg_font_ref (cairo_scaled_font_t *sfont)
-{
-    cairo_atsui_font_t *afont = (cairo_atsui_font_t *) sfont;
-
-    if (!afont->cgfref) {
-	ATSFontRef atsfref = FMGetATSFontRefFromFont (afont->fontID);
-	afont->cgfref = CGFontCreateWithPlatformFont (&atsfref);
-    }
-    return afont->cgfref;
-}
-
-
-static cairo_int_status_t
-_cairo_atsui_load_truetype_table (void	           *abstract_font,
-				  unsigned long     tag,
-				  long              offset,
-				  unsigned char    *buffer,
-				  unsigned long    *length)
-{
-    cairo_atsui_font_t *scaled_font = abstract_font;
-    ATSFontRef atsFont;
-    OSStatus err;
-	
-    atsFont = FMGetATSFontRefFromFont (scaled_font->fontID);
-    err = ATSFontGetTable ( atsFont, tag,
-			    (ByteOffset) offset,
-			    (ByteCount) *length,
-			    buffer,
-			    length);
-    if (err != noErr) {
-	return CAIRO_INT_STATUS_UNSUPPORTED;
-    }
-
-    return CAIRO_STATUS_SUCCESS;
-}
-
-const cairo_scaled_font_backend_t cairo_atsui_scaled_font_backend = {
-    CAIRO_FONT_TYPE_QUARTZ,
-    _cairo_atsui_font_create_toy,
-    _cairo_atsui_font_fini,
-    _cairo_atsui_font_scaled_glyph_init,
-    _cairo_atsui_font_text_to_glyphs,
-    NULL, /* ucs4_to_index */
-    NULL, /* show_glyphs */
-    _cairo_atsui_load_truetype_table,
-    NULL, /* map_glyphs_to_unicode */
-};
-
commit 8ddae11b544c35057a96ca0bdea34b4f473ee261
Author: Vladimir Vukicevic <vladimir at pobox.com>
Date:   Tue Apr 1 13:26:00 2008 -0700

    [quartz] Update documentation

diff --git a/doc/public/tmpl/cairo-ft.sgml b/doc/public/tmpl/cairo-ft.sgml
index 68a3fd4..8414c86 100644
--- a/doc/public/tmpl/cairo-ft.sgml
+++ b/doc/public/tmpl/cairo-ft.sgml
@@ -20,14 +20,6 @@ systems, but can be used on other platforms too.
 <!-- ##### SECTION Stability_Level ##### -->
 
 
-<!-- ##### MACRO CAIRO_HAS_FT_FONT ##### -->
-<para>
-Defined if the FreeType font backend is available.
-This macro can be used to conditionally compile backend-specific code.
-</para>
-
-
-
 <!-- ##### FUNCTION cairo_ft_font_face_create_for_ft_face ##### -->
 <para>
 
diff --git a/doc/public/tmpl/cairo-quartz-fonts.sgml b/doc/public/tmpl/cairo-quartz-fonts.sgml
index 28facca..3e7cd4d 100644
--- a/doc/public/tmpl/cairo-quartz-fonts.sgml
+++ b/doc/public/tmpl/cairo-quartz-fonts.sgml
@@ -21,3 +21,28 @@ implementation of the font backend methods.
 <!-- ##### SECTION Stability_Level ##### -->
 
 
+<!-- ##### MACRO CAIRO_HAS_QUARTZ_FONT ##### -->
+<para>
+
+</para>
+
+
+
+<!-- ##### FUNCTION cairo_quartz_font_face_create_for_cgfont ##### -->
+<para>
+
+</para>
+
+ at font: 
+ at Returns: 
+
+
+<!-- ##### FUNCTION cairo_quartz_font_face_create_for_atsu_font_id ##### -->
+<para>
+
+</para>
+
+ at font_id: 
+ at Returns: 
+
+
diff --git a/doc/public/tmpl/cairo-quartz.sgml b/doc/public/tmpl/cairo-quartz.sgml
index 56f4c8b..78fe8de 100644
--- a/doc/public/tmpl/cairo-quartz.sgml
+++ b/doc/public/tmpl/cairo-quartz.sgml
@@ -20,6 +20,13 @@ Apple OS X Quartz rendering system.
 <!-- ##### SECTION Stability_Level ##### -->
 
 
+<!-- ##### MACRO CAIRO_HAS_QUARTZ_SURFACE ##### -->
+<para>
+
+</para>
+
+
+
 <!-- ##### FUNCTION cairo_quartz_surface_create ##### -->
 <para>
 
@@ -51,21 +58,3 @@ Apple OS X Quartz rendering system.
 @Returns: 
 
 
-<!-- ##### FUNCTION cairo_quartz_image_surface_create ##### -->
-<para>
-
-</para>
-
- at image_surface: 
- at Returns: 
-
-
-<!-- ##### FUNCTION cairo_quartz_image_surface_get_image ##### -->
-<para>
-
-</para>
-
- at surface: 
- at Returns: 
-
-
diff --git a/doc/public/tmpl/cairo-xlib.sgml b/doc/public/tmpl/cairo-xlib.sgml
index df6977c..e0927d0 100644
--- a/doc/public/tmpl/cairo-xlib.sgml
+++ b/doc/public/tmpl/cairo-xlib.sgml
@@ -24,14 +24,6 @@ if it is available.
 <!-- ##### SECTION Stability_Level ##### -->
 
 
-<!-- ##### MACRO CAIRO_HAS_XLIB_SURFACE ##### -->
-<para>
-Defined if the XLib surface backend is available.
-This macro can be used to conditionally compile backend-specific code.
-</para>
-
-
-
 <!-- ##### FUNCTION cairo_xlib_surface_create ##### -->
 <para>
 
diff --git a/src/cairo-quartz-font.c b/src/cairo-quartz-font.c
index ae39f2b..52a5498 100644
--- a/src/cairo-quartz-font.c
+++ b/src/cairo-quartz-font.c
@@ -156,7 +156,16 @@ static const cairo_font_face_backend_t _cairo_quartz_font_face_backend = {
 
 /**
  * cairo_quartz_font_face_create_for_cgfont
- * @font: a CGFontRef obtained through other means
+ * @font: a #CGFontRef obtained through a method external to cairo.
+ *
+ * Creates a new font for the Quartz font backend based on a
+ * #CGFontRef.  This font can then be used with
+ * cairo_set_font_face() or cairo_scaled_font_create().
+ *
+ * Return value: a newly created #cairo_font_face_t. Free with
+ *  cairo_font_face_destroy() when you are done using it.
+ *
+ * Since: 1.6
  */
 cairo_font_face_t *
 cairo_quartz_font_face_create_for_cgfont (CGFontRef font)
@@ -684,8 +693,9 @@ _cairo_quartz_scaled_font_get_cg_font_ref (cairo_scaled_font_t *abstract_font)
 /*
  * compat with old ATSUI backend
  */
+
 /**
- * cairo_atsui_font_face_create_for_atsu_font_id
+ * cairo_quartz_font_face_create_for_atsu_font_id
  * @font_id: an ATSUFontID for the font.
  *
  * Creates a new font for the Quartz font backend based on an
diff --git a/src/cairo-quartz-surface.c b/src/cairo-quartz-surface.c
index 576e641..7d90fba 100644
--- a/src/cairo-quartz-surface.c
+++ b/src/cairo-quartz-surface.c
@@ -2373,22 +2373,20 @@ _cairo_quartz_surface_create_internal (CGContextRef cgContext,
  * @height: height of the surface, in pixels
  *
  * Creates a Quartz surface that wraps the given CGContext.  The
- * CGContext is assumed to be in the QuickDraw coordinate space (that
- * is, with the origin at the upper left and the Y axis increasing
- * downward.)  If the CGContext is in the Quartz coordinate space (with
- * the origin at the bottom left), then it should be flipped before
- * this function is called:
+ * CGContext is assumed to be in the standard Cairo coordinate space
+ * (that is, with the origin at the upper left and the Y axis
+ * increasing downward).  If the CGContext is in the Quartz coordinate
+ * space (with the origin at the bottom left), then it should be
+ * flipped before this function is called.  The flip can be accomplished
+ * using a translate and a scale; for example:
  *
  * <informalexample><programlisting>
  * CGContextTranslateCTM (cgContext, 0.0, height);
  * CGContextScaleCTM (cgContext, 1.0, -1.0);
  * </programlisting></informalexample>
  *
- * A very small number of Cairo operations cannot be translated to
- * Quartz operations; those operations will fail on this surface.
- * If all Cairo operations are required to succeed, consider rendering
- * to a surface created by cairo_quartz_surface_create() and then copying
- * the result to the CGContext.
+ * All Cairo operations are implemented in terms of Quartz operations,
+ * as long as Quartz-compatible elements are used (such as Quartz fonts).
  *
  * Return value: the newly created Cairo surface.
  *
commit 9a7162cfdf48f47bb8ee0a7c24c55c061e4fbc90
Author: Vladimir Vukicevic <vladimir at pobox.com>
Date:   Tue Apr 1 13:17:14 2008 -0700

    [doc] Add some Quartz/CGFont documentation templates

diff --git a/doc/public/cairo-docs.xml b/doc/public/cairo-docs.xml
index 9eb9b32..73eeeda 100644
--- a/doc/public/cairo-docs.xml
+++ b/doc/public/cairo-docs.xml
@@ -24,6 +24,7 @@
     <xi:include href="xml/cairo-font-options.xml"/>
     <xi:include href="xml/cairo-ft.xml"/>
     <xi:include href="xml/cairo-win32-fonts.xml"/>
+    <xi:include href="xml/cairo-quartz-fonts.xml"/>
   </chapter>
   <chapter id="Surfaces">
     <title>Surfaces</title>
diff --git a/doc/public/cairo-sections.txt b/doc/public/cairo-sections.txt
index 8abd2c6..98cc974 100644
--- a/doc/public/cairo-sections.txt
+++ b/doc/public/cairo-sections.txt
@@ -24,6 +24,14 @@ cairo_win32_scaled_font_get_device_to_logical
 </SECTION>
 
 <SECTION>
+<FILE>cairo-quartz-fonts</FILE>
+<TITLE>Quartz Fonts</TITLE>
+CAIRO_HAS_QUARTZ_FONT
+cairo_quartz_font_face_create_for_cgfont
+cairo_quartz_font_face_create_for_atsu_font_id
+</SECTION>
+
+<SECTION>
 <FILE>cairo-image</FILE>
 <TITLE>Image Surfaces</TITLE>
 cairo_format_t
@@ -95,6 +103,12 @@ CAIRO_HAS_QUARTZ_SURFACE
 cairo_quartz_surface_create
 cairo_quartz_surface_create_for_cg_context
 cairo_quartz_surface_get_cg_context
+</SECTION>
+
+<SECTION>
+<FILE>cairo-quartz-image</FILE>
+<TITLE>Quartz Image Surfaces</TITLE>
+CAIRO_HAS_QUARTZ_IMAGE_SURFACE
 cairo_quartz_image_surface_create
 cairo_quartz_image_surface_get_image
 </SECTION>
diff --git a/doc/public/tmpl/cairo-quartz-fonts.sgml b/doc/public/tmpl/cairo-quartz-fonts.sgml
new file mode 100644
index 0000000..28facca
--- /dev/null
+++ b/doc/public/tmpl/cairo-quartz-fonts.sgml
@@ -0,0 +1,23 @@
+<!-- ##### SECTION Title ##### -->
+Quartz (CGFont) Fonts
+
+<!-- ##### SECTION Short_Description ##### -->
+Font support via CGFont on OS X
+
+<!-- ##### SECTION Long_Description ##### -->
+<para>
+The Quartz font backend is primarily used to render text on Apple
+MacOS X systems.  The CGFont API is used for the internal
+implementation of the font backend methods.
+</para>
+
+<!-- ##### SECTION See_Also ##### -->
+<para>
+<itemizedlist>
+<listitem>#cairo_font_face_t</listitem>
+</itemizedlist>
+</para>
+
+<!-- ##### SECTION Stability_Level ##### -->
+
+
commit 56cabc352e44ee7cb2989dd81688f6c37c33fc21
Author: Vladimir Vukicevic <vladimir at pobox.com>
Date:   Tue Apr 1 13:01:41 2008 -0700

    [quartz] Update Quartz test reference images

diff --git a/test/Makefile.am b/test/Makefile.am
index 86b6de5..b1498bf 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -416,6 +416,7 @@ REFERENCE_IMAGES = \
 	linear-gradient-reflect-pdf-argb32-ref.png	\
 	linear-gradient-reflect-pdf-rgb24-ref.png	\
 	linear-gradient-reflect-ps-ref.png	\
+	linear-gradient-reflect-quartz-ref.png	\
 	linear-gradient-pdf-ref.png	\
 	linear-gradient-ps-ref.png	\
 	linear-gradient-quartz-ref.png	\
@@ -587,6 +588,7 @@ REFERENCE_IMAGES = \
 	surface-pattern-scale-down-pdf-argb32-ref.png	\
 	surface-pattern-scale-down-ps-argb32-ref.png	\
 	surface-pattern-scale-down-ref.png	\
+	surface-pattern-scale-down-quartz-ref.png	\
 	surface-pattern-scale-up-pdf-argb32-ref.png	\
 	surface-pattern-scale-up-ps-argb32-ref.png	\
 	surface-pattern-scale-up-ref.png	\
@@ -608,6 +610,7 @@ REFERENCE_IMAGES = \
 	text-pattern-svg-rgb24-ref.png	\
 	text-pattern-pdf-argb32-ref.png \
 	text-pattern-pdf-rgb24-ref.png \
+	text-pattern-quartz-ref.png \
 	text-pattern-quartz-rgb24-ref.png \
 	text-rotate-ref.png	\
 	text-rotate-ps-ref.png	\
diff --git a/test/clip-operator-quartz-ref.png b/test/clip-operator-quartz-ref.png
index 329f684..1726944 100644
Binary files a/test/clip-operator-quartz-ref.png and b/test/clip-operator-quartz-ref.png differ
diff --git a/test/clip-operator-quartz-rgb24-ref.png b/test/clip-operator-quartz-rgb24-ref.png
index f539baf..a18c6f2 100644
Binary files a/test/clip-operator-quartz-rgb24-ref.png and b/test/clip-operator-quartz-rgb24-ref.png differ
diff --git a/test/font-matrix-translation-quartz-ref.png b/test/font-matrix-translation-quartz-ref.png
index c0fbc16..90fd962 100644
Binary files a/test/font-matrix-translation-quartz-ref.png and b/test/font-matrix-translation-quartz-ref.png differ
diff --git a/test/glyph-cache-pressure-quartz-ref.png b/test/glyph-cache-pressure-quartz-ref.png
index b067e92..88d3db6 100644
Binary files a/test/glyph-cache-pressure-quartz-ref.png and b/test/glyph-cache-pressure-quartz-ref.png differ
diff --git a/test/linear-gradient-reflect-quartz-ref.png b/test/linear-gradient-reflect-quartz-ref.png
new file mode 100644
index 0000000..a0067ac
Binary files /dev/null and b/test/linear-gradient-reflect-quartz-ref.png differ
diff --git a/test/operator-clear-quartz-ref.png b/test/operator-clear-quartz-ref.png
index d0034a7..095f182 100644
Binary files a/test/operator-clear-quartz-ref.png and b/test/operator-clear-quartz-ref.png differ
diff --git a/test/operator-clear-quartz-rgb24-ref.png b/test/operator-clear-quartz-rgb24-ref.png
index 6f3fc2c..f978967 100644
Binary files a/test/operator-clear-quartz-rgb24-ref.png and b/test/operator-clear-quartz-rgb24-ref.png differ
diff --git a/test/operator-source-quartz-ref.png b/test/operator-source-quartz-ref.png
index d02f513..31fc441 100644
Binary files a/test/operator-source-quartz-ref.png and b/test/operator-source-quartz-ref.png differ
diff --git a/test/operator-source-quartz-rgb24-ref.png b/test/operator-source-quartz-rgb24-ref.png
index 7dc8d80..358e951 100644
Binary files a/test/operator-source-quartz-rgb24-ref.png and b/test/operator-source-quartz-rgb24-ref.png differ
diff --git a/test/select-font-face-quartz-ref.png b/test/select-font-face-quartz-ref.png
index 228b227..8f285b8 100644
Binary files a/test/select-font-face-quartz-ref.png and b/test/select-font-face-quartz-ref.png differ
diff --git a/test/show-text-current-point-quartz-ref.png b/test/show-text-current-point-quartz-ref.png
index d96b305..538b0d1 100644
Binary files a/test/show-text-current-point-quartz-ref.png and b/test/show-text-current-point-quartz-ref.png differ
diff --git a/test/surface-pattern-scale-down-quartz-ref.png b/test/surface-pattern-scale-down-quartz-ref.png
new file mode 100644
index 0000000..93a34da
Binary files /dev/null and b/test/surface-pattern-scale-down-quartz-ref.png differ
diff --git a/test/text-antialias-gray-quartz-ref.png b/test/text-antialias-gray-quartz-ref.png
index afe9928..573848d 100644
Binary files a/test/text-antialias-gray-quartz-ref.png and b/test/text-antialias-gray-quartz-ref.png differ
diff --git a/test/text-antialias-none-quartz-ref.png b/test/text-antialias-none-quartz-ref.png
index 32537fc..bcee5da 100644
Binary files a/test/text-antialias-none-quartz-ref.png and b/test/text-antialias-none-quartz-ref.png differ
diff --git a/test/text-antialias-subpixel-quartz-ref.png b/test/text-antialias-subpixel-quartz-ref.png
index bab8a72..ffd487f 100644
Binary files a/test/text-antialias-subpixel-quartz-ref.png and b/test/text-antialias-subpixel-quartz-ref.png differ
diff --git a/test/text-pattern-quartz-ref.png b/test/text-pattern-quartz-ref.png
new file mode 100644
index 0000000..5cb5874
Binary files /dev/null and b/test/text-pattern-quartz-ref.png differ
diff --git a/test/text-pattern-quartz-rgb24-ref.png b/test/text-pattern-quartz-rgb24-ref.png
index 9f4da3a..7eae4c8 100644
Binary files a/test/text-pattern-quartz-rgb24-ref.png and b/test/text-pattern-quartz-rgb24-ref.png differ
diff --git a/test/text-rotate-quartz-ref.png b/test/text-rotate-quartz-ref.png
index 9e2c59f..6fb7f3d 100644
Binary files a/test/text-rotate-quartz-ref.png and b/test/text-rotate-quartz-ref.png differ
diff --git a/test/unbounded-operator-quartz-ref.png b/test/unbounded-operator-quartz-ref.png
index 69c0d5e..b0501db 100644
Binary files a/test/unbounded-operator-quartz-ref.png and b/test/unbounded-operator-quartz-ref.png differ
diff --git a/test/unbounded-operator-quartz-rgb24-ref.png b/test/unbounded-operator-quartz-rgb24-ref.png
index a7a0b0e..f8dae18 100644
Binary files a/test/unbounded-operator-quartz-rgb24-ref.png and b/test/unbounded-operator-quartz-rgb24-ref.png differ
commit 94b67d13f38d860f1a768f9a088e3b6f5d188f7b
Author: Vladimir Vukicevic <vladimir at pobox.com>
Date:   Tue Apr 1 12:44:32 2008 -0700

    [quartz] Handle further 10.4 vs. 10.5 differences; fix text AA handling

diff --git a/src/cairo-quartz-surface.c b/src/cairo-quartz-surface.c
index 5b6cecb..576e641 100644
--- a/src/cairo-quartz-surface.c
+++ b/src/cairo-quartz-surface.c
@@ -101,13 +101,14 @@ CG_EXTERN void CGContextReplacePathWithStrokedPath (CGContextRef);
 CG_EXTERN CGImageRef CGBitmapContextCreateImage (CGContextRef);
 #endif
 
-/* Only present in 10.4+ */
+/* Some of these are present in earlier versions of the OS than where
+ * they are public; others are not public at all (CGContextCopyPath,
+ * CGContextReplacePathWithClipPath, many of the getters, etc.)
+ */
 static void (*CGContextClipToMaskPtr) (CGContextRef, CGRect, CGImageRef) = NULL;
-/* Only present in 10.5+ */
 static void (*CGContextDrawTiledImagePtr) (CGContextRef, CGRect, CGImageRef) = NULL;
 static unsigned int (*CGContextGetTypePtr) (CGContextRef) = NULL;
 static void (*CGContextSetShouldAntialiasFontsPtr) (CGContextRef, bool) = NULL;
-static void (*CGContextSetShouldSmoothFontsPtr) (CGContextRef, bool) = NULL;
 static bool (*CGContextGetShouldAntialiasFontsPtr) (CGContextRef) = NULL;
 static bool (*CGContextGetShouldSmoothFontsPtr) (CGContextRef) = NULL;
 static void (*CGContextSetAllowsFontSmoothingPtr) (CGContextRef, bool) = NULL;
@@ -115,6 +116,8 @@ static bool (*CGContextGetAllowsFontSmoothingPtr) (CGContextRef) = NULL;
 static CGPathRef (*CGContextCopyPathPtr) (CGContextRef) = NULL;
 static void (*CGContextReplacePathWithClipPathPtr) (CGContextRef) = NULL;
 
+static SInt32 _cairo_quartz_osx_version = 0x0;
+
 static cairo_bool_t _cairo_quartz_symbol_lookup_done = FALSE;
 
 /*
@@ -142,7 +145,6 @@ static void quartz_ensure_symbols(void)
     CGContextDrawTiledImagePtr = dlsym(RTLD_DEFAULT, "CGContextDrawTiledImage");
     CGContextGetTypePtr = dlsym(RTLD_DEFAULT, "CGContextGetType");
     CGContextSetShouldAntialiasFontsPtr = dlsym(RTLD_DEFAULT, "CGContextSetShouldAntialiasFonts");
-    CGContextSetShouldSmoothFontsPtr = dlsym(RTLD_DEFAULT, "CGContextSetShouldSmoothFonts");
     CGContextGetShouldAntialiasFontsPtr = dlsym(RTLD_DEFAULT, "CGContextGetShouldAntialiasFonts");
     CGContextGetShouldSmoothFontsPtr = dlsym(RTLD_DEFAULT, "CGContextGetShouldSmoothFonts");
     CGContextCopyPathPtr = dlsym(RTLD_DEFAULT, "CGContextCopyPath");
@@ -150,6 +152,11 @@ static void quartz_ensure_symbols(void)
     CGContextGetAllowsFontSmoothingPtr = dlsym(RTLD_DEFAULT, "CGContextGetAllowsFontSmoothing");
     CGContextSetAllowsFontSmoothingPtr = dlsym(RTLD_DEFAULT, "CGContextSetAllowsFontSmoothing");
 
+    if (Gestalt(gestaltSystemVersion, &_cairo_quartz_osx_version) != noErr) {
+	// assume 10.4
+	_cairo_quartz_osx_version = 0x1040;
+    }
+
     _cairo_quartz_symbol_lookup_done = TRUE;
 }
 
@@ -478,6 +485,10 @@ _cairo_quartz_fixup_unbounded_operation (cairo_quartz_surface_t *surface,
 	CGContextTranslateCTM (cgc, op->u.show_glyphs.origin.x, op->u.show_glyphs.origin.y);
 
 	if (op->u.show_glyphs.isClipping) {
+	    /* Note that the comment in show_glyphs about kCGTextClip
+	     * and the text transform still applies here; however, the
+	     * cg_advances we have were already transformed, so we
+	     * don't have to do anything. */
 	    CGContextSetTextDrawingMode (cgc, kCGTextClip);
 	    CGContextSaveGState (cgc);
 	}
@@ -1916,29 +1927,27 @@ _cairo_quartz_surface_show_glyphs (void *abstract_surface,
     CGContextSetFont (surface->cgContext, cgfref);
     CGContextSetFontSize (surface->cgContext, 1.0);
 
-    if (CGContextSetShouldAntialiasFontsPtr) {
-	switch (scaled_font->options.antialias) {
-	    case CAIRO_ANTIALIAS_SUBPIXEL:
-		CGContextSetShouldAntialiasFontsPtr (surface->cgContext, TRUE);
-		CGContextSetShouldSmoothFontsPtr (surface->cgContext, TRUE);
-		if (CGContextSetAllowsFontSmoothingPtr &&
-		    !CGContextGetAllowsFontSmoothingPtr (surface->cgContext))
-		{
-		    didForceFontSmoothing = TRUE;
-		    CGContextSetAllowsFontSmoothingPtr (surface->cgContext, TRUE);
-		}
-		break;
-	    case CAIRO_ANTIALIAS_NONE:
-		CGContextSetShouldAntialiasFontsPtr (surface->cgContext, FALSE);
-		break;
-	    case CAIRO_ANTIALIAS_GRAY:
-		CGContextSetShouldAntialiasFontsPtr (surface->cgContext, TRUE);
-		CGContextSetShouldSmoothFontsPtr (surface->cgContext, FALSE);
-		break;
-	    case CAIRO_ANTIALIAS_DEFAULT:
-		/* Don't do anything */
-		break;
-	}
+    switch (scaled_font->options.antialias) {
+	case CAIRO_ANTIALIAS_SUBPIXEL:
+	    CGContextSetShouldAntialias (surface->cgContext, TRUE);
+	    CGContextSetShouldSmoothFonts (surface->cgContext, TRUE);
+	    if (CGContextSetAllowsFontSmoothingPtr &&
+		!CGContextGetAllowsFontSmoothingPtr (surface->cgContext))
+	    {
+		didForceFontSmoothing = TRUE;
+		CGContextSetAllowsFontSmoothingPtr (surface->cgContext, TRUE);
+	    }
+	    break;
+	case CAIRO_ANTIALIAS_NONE:
+	    CGContextSetShouldAntialias (surface->cgContext, FALSE);
+	    break;
+	case CAIRO_ANTIALIAS_GRAY:
+	    CGContextSetShouldAntialias (surface->cgContext, TRUE);
+	    CGContextSetShouldSmoothFonts (surface->cgContext, FALSE);
+	    break;
+	case CAIRO_ANTIALIAS_DEFAULT:
+	    /* Don't do anything */
+	    break;
     }
 
     if (num_glyphs > STATIC_BUF_SIZE) {
@@ -1987,10 +1996,13 @@ _cairo_quartz_surface_show_glyphs (void *abstract_surface,
 	yprev = yf;
     }
 
-    if (isClipping) {
-	/* If we're clipping, we get multiplied by the inverse of our text matrix; no,
-	 * I don't understand why this is any different.  So pre-apply our textTransform.
-	 * Note that the new CGContextShowGlyphsAtPositions has a similar problem. */
+    if (_cairo_quartz_osx_version >= 0x1050 && isClipping) {
+	/* If we're clipping, OSX 10.5 (at least as of 10.5.2) has a
+	 * bug (apple bug ID #5834794) where the glyph
+	 * advances/positions are not transformed by the text matrix
+	 * if kCGTextClip is being used.  So, we pre-transform here.
+	 * 10.4 does not have this problem (as of 10.4.11).
+	 */
 	for (i = 0; i < num_glyphs - 1; i++)
 	    cg_advances[i] = CGSizeApplyAffineTransform(cg_advances[i], textTransform);
     }
commit a1d1be4234f7787c078ff096b4101e300494e7d1
Author: Vladimir Vukicevic <vladimir at pobox.com>
Date:   Thu Mar 27 23:46:53 2008 -0700

    [cgfont] Round surface rectangle outwards to ensure whole-pixel dimensions

diff --git a/src/cairo-quartz-font.c b/src/cairo-quartz-font.c
index 3cd83fe..ae39f2b 100644
--- a/src/cairo-quartz-font.c
+++ b/src/cairo-quartz-font.c
@@ -335,31 +335,57 @@ _cairo_quartz_init_glyph_metrics (cairo_quartz_scaled_font_t *font,
 
     cairo_quartz_font_face_t *font_face = _cairo_quartz_scaled_to_face(font);
     cairo_text_extents_t extents = {0, 0, 0, 0, 0, 0};
+    CGAffineTransform textMatrix;
     CGGlyph glyph = _cairo_quartz_scaled_glyph_index (scaled_glyph);
     int advance;
     CGRect bbox;
     double emscale = CGFontGetUnitsPerEmPtr (font_face->cgFont);
+    double xscale, yscale;
     double xmin, ymin, xmax, ymax;
 
     if (glyph == INVALID_GLYPH)
 	goto FAIL;
 
-    if (!CGFontGetGlyphAdvancesPtr (font_face->cgFont, &glyph, 1, &advance))
+    if (!CGFontGetGlyphAdvancesPtr (font_face->cgFont, &glyph, 1, &advance) ||
+	!CGFontGetGlyphBBoxesPtr (font_face->cgFont, &glyph, 1, &bbox))
 	goto FAIL;
 
-    if (!CGFontGetGlyphBBoxesPtr (font_face->cgFont, &glyph, 1, &bbox))
+    status = _cairo_matrix_compute_scale_factors (&font->base.scale,
+						  &xscale, &yscale, 1);
+    if (status)
 	goto FAIL;
 
+    bbox = CGRectMake (bbox.origin.x / emscale,
+		       bbox.origin.y / emscale,
+		       bbox.size.width / emscale,
+		       bbox.size.height / emscale);
+
+    /* Should we want to always integer-align glyph extents, we can do so in this way */
+#if 0
+    {
+	CGAffineTransform textMatrix;
+	textMatrix = CGAffineTransformMake (font->base.scale.xx,
+					    -font->base.scale.yx,
+					    -font->base.scale.xy,
+					    font->base.scale.yy,
+					    0.0f, 0.0f);
+
+	bbox = CGRectApplyAffineTransform (bbox, textMatrix);
+	bbox = CGRectIntegral (bbox);
+	bbox = CGRectApplyAffineTransform (bbox, CGAffineTransformInvert (textMatrix));
+    }
+#endif
+
 #if 0
     fprintf (stderr, "[0x%04x] bbox: %f %f %f %f\n", glyph,
 	     bbox.origin.x / emscale, bbox.origin.y / emscale,
 	     bbox.size.width / emscale, bbox.size.height / emscale);
 #endif
 
-    xmin = CGRectGetMinX(bbox) / emscale;
-    ymin = CGRectGetMinY(bbox) / emscale;
-    xmax = CGRectGetMaxX(bbox) / emscale;
-    ymax = CGRectGetMaxY(bbox) / emscale;
+    xmin = CGRectGetMinX(bbox);
+    ymin = CGRectGetMinY(bbox);
+    xmax = CGRectGetMaxX(bbox);
+    ymax = CGRectGetMaxY(bbox);
 
     extents.x_bearing = xmin;
     extents.y_bearing = - ymax;
@@ -494,7 +520,7 @@ _cairo_quartz_init_glyph_surface (cairo_quartz_scaled_font_t *font,
     CGColorSpaceRef gray;
     CGContextRef cgContext = NULL;
     CGAffineTransform textMatrix;
-    CGRect glyphRect;
+    CGRect glyphRect, glyphRectInt;
     CGPoint glyphOrigin;
 
     //fprintf (stderr, "scaled_glyph: %p surface: %p\n", scaled_glyph, scaled_glyph->surface);
@@ -536,16 +562,26 @@ _cairo_quartz_init_glyph_surface (cairo_quartz_scaled_font_t *font,
 			    bbox.size.width / emscale,
 			    bbox.size.height / emscale);
 
-    //fprintf (stderr, "glyphRect[o]: %f %f %f %f\n", glyphRect.origin.x, glyphRect.origin.y, glyphRect.size.width, glyphRect.size.height);
-
     glyphRect = CGRectApplyAffineTransform (glyphRect, textMatrix);
 
-    glyphOrigin = glyphRect.origin;
+    /* Round the rectangle outwards, so that we don't have to deal
+     * with non-integer-pixel origins or dimensions.
+     */
+    glyphRectInt = CGRectIntegral (glyphRect);
+
+#if 0
+    fprintf (stderr, "glyphRect[o]: %f %f %f %f\n",
+	     glyphRect.origin.x, glyphRect.origin.y, glyphRect.size.width, glyphRect.size.height);
+    fprintf (stderr, "glyphRectInt: %f %f %f %f\n",
+	     glyphRectInt.origin.x, glyphRectInt.origin.y, glyphRectInt.size.width, glyphRectInt.size.height);
+#endif
+
+    glyphOrigin = glyphRectInt.origin;
 
     //textMatrix = CGAffineTransformConcat (textMatrix, CGAffineTransformInvert (ctm));
 
-    width = ceil(glyphRect.size.width);
-    height = ceil(glyphRect.size.height);
+    width = glyphRectInt.size.width;
+    height = glyphRectInt.size.height;
 
     //fprintf (stderr, "glyphRect[n]: %f %f %f %f\n", glyphRect.origin.x, glyphRect.origin.y, glyphRect.size.width, glyphRect.size.height);
 
commit c064ad1b56d11950786a3fd0363e543f5aec1761
Author: Vladimir Vukicevic <vladimir at pobox.com>
Date:   Thu Mar 27 11:42:53 2008 -0700

    [cgfont] Fix whitespace errors

diff --git a/src/cairo-quartz-font.c b/src/cairo-quartz-font.c
index 2d05a62..3cd83fe 100644
--- a/src/cairo-quartz-font.c
+++ b/src/cairo-quartz-font.c
@@ -548,7 +548,7 @@ _cairo_quartz_init_glyph_surface (cairo_quartz_scaled_font_t *font,
     height = ceil(glyphRect.size.height);
 
     //fprintf (stderr, "glyphRect[n]: %f %f %f %f\n", glyphRect.origin.x, glyphRect.origin.y, glyphRect.size.width, glyphRect.size.height);
-    
+
     surface = (cairo_image_surface_t*) cairo_image_surface_create (CAIRO_FORMAT_A8, width, height);
     if (surface->base.status)
 	return surface->base.status;
@@ -570,7 +570,7 @@ _cairo_quartz_init_glyph_surface (cairo_quartz_scaled_font_t *font,
     CGContextClearRect (cgContext, CGRectMake (0.0f, 0.0f, width, height));
 
     if (font->base.options.antialias == CAIRO_ANTIALIAS_NONE)
-    	CGContextSetShouldAntialias (cgContext, false);
+	CGContextSetShouldAntialias (cgContext, false);
 
     CGContextSetRGBFillColor (cgContext, 1.0, 1.0, 1.0, 1.0);
     CGContextShowGlyphsAtPoint (cgContext, - glyphOrigin.x, - glyphOrigin.y, &glyph, 1);
commit 2be3e67db24ac34f772b5fc1182dfb9b730dce11
Author: Vladimir Vukicevic <vladimir at pobox.com>
Date:   Tue Mar 25 22:44:39 2008 -0700

    [cgfont] Add CGFont backend to replace deprecated ATSUI backend
    
    Create a new font backend that uses the CGFont API on MacOS X
    10.4 and beyond.

diff --git a/src/cairo-quartz-font.c b/src/cairo-quartz-font.c
index 7c714aa..2d05a62 100644
--- a/src/cairo-quartz-font.c
+++ b/src/cairo-quartz-font.c
@@ -41,12 +41,59 @@
 #include "cairo-quartz.h"
 #include "cairo-quartz-private.h"
 
+/* CreateWithFontName exists in 10.5, but not in 10.4; CreateWithName isn't public in 10.4 */
+static CGFontRef (*CGFontCreateWithFontNamePtr) (CFStringRef) = NULL;
+static CGFontRef (*CGFontCreateWithNamePtr) (const char *) = NULL;
+
+/* These aren't public before 10.5, and some have different names in 10.4 */
+static int (*CGFontGetUnitsPerEmPtr) (CGFontRef) = NULL;
+static bool (*CGFontGetGlyphAdvancesPtr) (CGFontRef, const CGGlyph[], size_t, int[]) = NULL;
+static bool (*CGFontGetGlyphBBoxesPtr) (CGFontRef, const CGGlyph[], size_t, CGRect[]) = NULL;
+
 /* Not public, but present */
-extern void CGFontGetGlyphsForUnichars (CGFontRef, const UniChar[], const CGGlyph[], size_t);
+static void (*CGFontGetGlyphsForUnicharsPtr) (CGFontRef, const UniChar[], const CGGlyph[], size_t) = NULL;
 
 /* Not public in the least bit */
 static CGPathRef (*CGFontGetGlyphPathPtr) (CGFontRef fontRef, CGAffineTransform *textTransform, int unknown, CGGlyph glyph) = NULL;
 
+static cairo_bool_t _cairo_quartz_font_symbol_lookup_done = FALSE;
+static cairo_bool_t _cairo_quartz_font_symbols_present = FALSE;
+
+static void
+quartz_font_ensure_symbols(void)
+{
+    if (_cairo_quartz_font_symbol_lookup_done)
+	return;
+
+    /* Look for the 10.5 versions first */
+    CGFontGetGlyphBBoxesPtr = dlsym(RTLD_DEFAULT, "CGFontGetGlyphBBoxes");
+    if (!CGFontGetGlyphBBoxesPtr)
+	CGFontGetGlyphBBoxesPtr = dlsym(RTLD_DEFAULT, "CGFontGetGlyphBoundingBoxes");
+
+    CGFontGetGlyphsForUnicharsPtr = dlsym(RTLD_DEFAULT, "CGFontGetGlyphsForUnichars");
+    if (!CGFontGetGlyphsForUnicharsPtr)
+	CGFontGetGlyphsForUnicharsPtr = dlsym(RTLD_DEFAULT, "CGFontGetGlyphsForUnicodes");
+
+    /* We just need one of these two */
+    CGFontCreateWithFontNamePtr = dlsym(RTLD_DEFAULT, "CGFontCreateWithFontName");
+    CGFontCreateWithNamePtr = dlsym(RTLD_DEFAULT, "CGFontCreateWithName");
+
+    /* These have the same name in 10.4 and 10.5 */
+    CGFontGetUnitsPerEmPtr = dlsym(RTLD_DEFAULT, "CGFontGetUnitsPerEm");
+    CGFontGetGlyphAdvancesPtr = dlsym(RTLD_DEFAULT, "CGFontGetGlyphAdvances");
+    CGFontGetGlyphPathPtr = dlsym(RTLD_DEFAULT, "CGFontGetGlyphPath");
+
+    if ((CGFontCreateWithFontNamePtr || CGFontCreateWithNamePtr) &&
+	CGFontGetGlyphBBoxesPtr &&
+	CGFontGetGlyphsForUnicharsPtr &&
+	CGFontGetUnitsPerEmPtr &&
+	CGFontGetGlyphAdvancesPtr &&
+	CGFontGetGlyphPathPtr)
+	_cairo_quartz_font_symbols_present = TRUE;
+
+    _cairo_quartz_font_symbol_lookup_done = TRUE;
+}
+
 typedef struct _cairo_quartz_font_face cairo_quartz_font_face_t;
 typedef struct _cairo_quartz_scaled_font cairo_quartz_scaled_font_t;
 
@@ -83,6 +130,10 @@ _cairo_quartz_font_face_scaled_font_create (void *abstract_face,
     cairo_quartz_scaled_font_t *font;
     cairo_status_t status;
 
+    quartz_font_ensure_symbols();
+    if (!_cairo_quartz_font_symbols_present)
+	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+
     font = malloc(sizeof(cairo_quartz_scaled_font_t));
     if (font == NULL)
 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
@@ -112,6 +163,8 @@ cairo_quartz_font_face_create_for_cgfont (CGFontRef font)
 {
     cairo_quartz_font_face_t *font_face;
 
+    quartz_font_ensure_symbols();
+
     font_face = malloc (sizeof (cairo_quartz_font_face_t));
     if (!font_face) {
 	_cairo_error (CAIRO_STATUS_NO_MEMORY);
@@ -157,6 +210,10 @@ _cairo_quartz_font_create_toy(cairo_toy_font_face_t *toy_face,
     cairo_font_face_t *face;
     cairo_scaled_font_t *scaled_font;
 
+    quartz_font_ensure_symbols();
+    if (!_cairo_quartz_font_symbols_present)
+	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+
     /* handle CSS-ish faces */
     if (!strcmp(family, "serif") || !strcmp(family, "Times Roman"))
 	family = "Times";
@@ -191,9 +248,13 @@ _cairo_quartz_font_create_toy(cairo_toy_font_face_t *toy_face,
 		strcat (full_name, " Oblique");
 	}
 
-	cgFontName = CFStringCreateWithCString (NULL, full_name, kCFStringEncodingASCII);
-	cgFont = CGFontCreateWithFontName (cgFontName);
-	CFRelease (cgFontName);
+	if (CGFontCreateWithFontNamePtr) {
+	    cgFontName = CFStringCreateWithCString (NULL, full_name, kCFStringEncodingASCII);
+	    cgFont = CGFontCreateWithFontNamePtr (cgFontName);
+	    CFRelease (cgFontName);
+	} else {
+	    cgFont = CGFontCreateWithNamePtr (full_name);
+	}
 
 	if (cgFont)
 	    break;
@@ -277,16 +338,16 @@ _cairo_quartz_init_glyph_metrics (cairo_quartz_scaled_font_t *font,
     CGGlyph glyph = _cairo_quartz_scaled_glyph_index (scaled_glyph);
     int advance;
     CGRect bbox;
-    double emscale = CGFontGetUnitsPerEm (font_face->cgFont);
+    double emscale = CGFontGetUnitsPerEmPtr (font_face->cgFont);
     double xmin, ymin, xmax, ymax;
 
     if (glyph == INVALID_GLYPH)
 	goto FAIL;
 
-    if (!CGFontGetGlyphAdvances (font_face->cgFont, &glyph, 1, &advance))
+    if (!CGFontGetGlyphAdvancesPtr (font_face->cgFont, &glyph, 1, &advance))
 	goto FAIL;
 
-    if (!CGFontGetGlyphBBoxes (font_face->cgFont, &glyph, 1, &bbox))
+    if (!CGFontGetGlyphBBoxesPtr (font_face->cgFont, &glyph, 1, &bbox))
 	goto FAIL;
 
 #if 0
@@ -379,12 +440,6 @@ _cairo_quartz_init_glyph_path (cairo_quartz_scaled_font_t *font,
     CGPathRef glyphPath;
     cairo_path_fixed_t *path;
 
-    if (CGFontGetGlyphPathPtr == NULL)
-	CGFontGetGlyphPathPtr = dlsym(RTLD_DEFAULT, "CGFontGetGlyphPath");
-
-    if (!CGFontGetGlyphPathPtr)
-	return CAIRO_INT_STATUS_UNSUPPORTED;
-
     if (glyph == INVALID_GLYPH) {
 	_cairo_scaled_glyph_set_path (scaled_glyph, &font->base, _cairo_path_fixed_create());
 	return CAIRO_STATUS_SUCCESS;
@@ -434,7 +489,7 @@ _cairo_quartz_init_glyph_surface (cairo_quartz_scaled_font_t *font,
     CGRect bbox;
     double width, height;
     double xscale, yscale;
-    double emscale = CGFontGetUnitsPerEm (font_face->cgFont);
+    double emscale = CGFontGetUnitsPerEmPtr (font_face->cgFont);
 
     CGColorSpaceRef gray;
     CGContextRef cgContext = NULL;
@@ -460,8 +515,8 @@ _cairo_quartz_init_glyph_surface (cairo_quartz_scaled_font_t *font,
 	return CAIRO_STATUS_SUCCESS;
     }
 
-    if (!CGFontGetGlyphAdvances (font_face->cgFont, &glyph, 1, &advance) ||
-	!CGFontGetGlyphBBoxes (font_face->cgFont, &glyph, 1, &bbox))
+    if (!CGFontGetGlyphAdvancesPtr (font_face->cgFont, &glyph, 1, &advance) ||
+	!CGFontGetGlyphBBoxesPtr (font_face->cgFont, &glyph, 1, &bbox))
     {
 	return CAIRO_INT_STATUS_UNSUPPORTED;
     }
@@ -560,7 +615,7 @@ _cairo_quartz_ucs4_to_index (void *abstract_font,
     UniChar u = (UniChar) ucs4;
     CGGlyph glyph;
 
-    CGFontGetGlyphsForUnichars (ffont->cgFont, &u, &glyph, 1);
+    CGFontGetGlyphsForUnicharsPtr (ffont->cgFont, &u, &glyph, 1);
 
     return glyph;
 }
@@ -588,3 +643,38 @@ _cairo_quartz_scaled_font_get_cg_font_ref (cairo_scaled_font_t *abstract_font)
 
     return ffont->cgFont;
 }
+
+
+/*
+ * compat with old ATSUI backend
+ */
+/**
+ * cairo_atsui_font_face_create_for_atsu_font_id
+ * @font_id: an ATSUFontID for the font.
+ *
+ * Creates a new font for the Quartz font backend based on an
+ * #ATSUFontID. This font can then be used with
+ * cairo_set_font_face() or cairo_scaled_font_create().
+ *
+ * Return value: a newly created #cairo_font_face_t. Free with
+ *  cairo_font_face_destroy() when you are done using it.
+ *
+ * Since: 1.6
+ **/
+cairo_font_face_t *
+cairo_quartz_font_face_create_for_atsu_font_id (ATSUFontID font_id)
+{
+    ATSFontRef atsFont = FMGetATSFontRefFromFont (font_id);
+    CGFontRef cgFont = CGFontCreateWithPlatformFont (&atsFont);
+
+    return cairo_quartz_font_face_create_for_cgfont (cgFont);
+}
+
+/* This is the old name for the above function, exported for compat purposes */
+cairo_font_face_t *cairo_atsui_font_face_create_for_atsu_font_id (ATSUFontID font_id);
+
+cairo_font_face_t *
+cairo_atsui_font_face_create_for_atsu_font_id (ATSUFontID font_id)
+{
+    return cairo_quartz_font_face_create_for_atsu_font_id (font_id);
+}
commit 30f7fae6475c36549badf1fcc11ae39d1d79b532
Author: Vladimir Vukicevic <vladimir at pobox.com>
Date:   Thu Mar 20 13:24:48 2008 -0700

    [cgfont] Add start of CGFont font backend to replace ATSUI

diff --git a/configure.in b/configure.in
index 62aafcf..65080bd 100644
--- a/configure.in
+++ b/configure.in
@@ -357,8 +357,14 @@ dnl ===========================================================================
 
 CAIRO_BACKEND_ENABLE(quartz, Quartz, quartz, QUARTZ_SURFACE, no, [
   dnl There is no pkgconfig for quartz; lets do a header check
-  AC_CHECK_HEADER(Carbon/Carbon.h, , [use_quartz="no (Carbon headers not found)"])
-  quartz_LIBS="-Xlinker -framework -Xlinker Carbon"
+  AC_CHECK_HEADER(ApplicationServices/ApplicationServices.h, , [use_quartz="no (ApplicationServices framework not found)"])
+  if test "x$use_quartz" != "xyes" ; then
+    dnl check for CoreGraphics as a separate framework
+    AC_CHECK_HEADER(CoreGraphics/CoreGraphics.h, , [use_quartz="no (CoreGraphics framework not found)"])
+    quartz_LIBS="-Xlinker -framework -Xlinker CoreGraphics"
+  else
+    quartz_LIBS="-Xlinker -framework -Xlinker ApplicationServices"
+  fi
 ])
 
 CAIRO_BACKEND_ENABLE(quartz_font, Quartz font, quartz-font, QUARTZ_FONT, auto, [
diff --git a/src/Makefile.am b/src/Makefile.am
index 32b2df2..dfdcf1e 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -191,11 +191,10 @@ cairo_headers += cairo-quartz-image.h
 backend_pkgconfigs += cairo-quartz-image.pc
 endif
 
-quartz_font_sources = cairo-atsui-font.c
+quartz_font_sources = cairo-quartz-font.c
 cairo_all_sources += $(quartz_font_sources)
 if CAIRO_HAS_QUARTZ_FONT
 cairo_sources += $(quartz_font_sources)
-backend_pkgconfigs += cairo-quartz-font.pc
 endif
 
 os_win32_sources = cairo-win32.c
diff --git a/src/cairo-atsui-font.c b/src/cairo-atsui-font.c
index 6866bb5..42c209b 100644
--- a/src/cairo-atsui-font.c
+++ b/src/cairo-atsui-font.c
@@ -641,7 +641,7 @@ _cairo_atsui_scaled_font_init_glyph_path (cairo_atsui_font_t *scaled_font,
     cairo_matrix_t unscaled_font_to_device;
     double xscale;
     double yscale;
-    
+
     scaled_path.path = _cairo_path_fixed_create ();
     if (!scaled_path.path)
 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
diff --git a/src/cairo-quartz-font.c b/src/cairo-quartz-font.c
new file mode 100644
index 0000000..7c714aa
--- /dev/null
+++ b/src/cairo-quartz-font.c
@@ -0,0 +1,590 @@
+/* -*- Mode: c; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 8; -*- */
+/* cairo - a vector graphics library with display and print output
+ *
+ * Copyright � 2008 Mozilla Corporation
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ *
+ * The Original Code is the cairo graphics library.
+ *
+ * The Initial Developer of the Original Code is Mozilla Corporation.
+ *
+ * Contributor(s):
+ *	Vladimir Vukicevic <vladimir at mozilla.com>
+ */
+
+#include <dlfcn.h>
+
+#include "cairoint.h"
+
+#include "cairo-quartz.h"
+#include "cairo-quartz-private.h"
+
+/* Not public, but present */
+extern void CGFontGetGlyphsForUnichars (CGFontRef, const UniChar[], const CGGlyph[], size_t);
+
+/* Not public in the least bit */
+static CGPathRef (*CGFontGetGlyphPathPtr) (CGFontRef fontRef, CGAffineTransform *textTransform, int unknown, CGGlyph glyph) = NULL;
+
+typedef struct _cairo_quartz_font_face cairo_quartz_font_face_t;
+typedef struct _cairo_quartz_scaled_font cairo_quartz_scaled_font_t;
+
+struct _cairo_quartz_scaled_font {
+    cairo_scaled_font_t base;
+};
+
+struct _cairo_quartz_font_face {
+    cairo_font_face_t base;
+
+    CGFontRef cgFont;
+};
+
+/**
+ ** font face backend
+ **/
+
+static void
+_cairo_quartz_font_face_destroy (void *abstract_face)
+{
+    cairo_quartz_font_face_t *font_face = (cairo_quartz_font_face_t*) abstract_face;
+
+    CGFontRelease (font_face->cgFont);
+}
+
+static cairo_status_t
+_cairo_quartz_font_face_scaled_font_create (void *abstract_face,
+					    const cairo_matrix_t *font_matrix,
+					    const cairo_matrix_t *ctm,
+					    const cairo_font_options_t *options,
+					    cairo_scaled_font_t **font_out)
+{
+    cairo_quartz_font_face_t *font_face = abstract_face;
+    cairo_quartz_scaled_font_t *font;
+    cairo_status_t status;
+
+    font = malloc(sizeof(cairo_quartz_scaled_font_t));
+    if (font == NULL)
+	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+
+    memset (font, 0, sizeof(cairo_quartz_scaled_font_t));
+
+    status = _cairo_scaled_font_init (&font->base,
+				      &font_face->base, font_matrix, ctm, options,
+				      &cairo_quartz_scaled_font_backend);
+
+    *font_out = (cairo_scaled_font_t*) font;
+    return status;
+}
+
+static const cairo_font_face_backend_t _cairo_quartz_font_face_backend = {
+    CAIRO_FONT_TYPE_QUARTZ,
+    _cairo_quartz_font_face_destroy,
+    _cairo_quartz_font_face_scaled_font_create
+};
+
+/**
+ * cairo_quartz_font_face_create_for_cgfont
+ * @font: a CGFontRef obtained through other means
+ */
+cairo_font_face_t *
+cairo_quartz_font_face_create_for_cgfont (CGFontRef font)
+{
+    cairo_quartz_font_face_t *font_face;
+
+    font_face = malloc (sizeof (cairo_quartz_font_face_t));
+    if (!font_face) {
+	_cairo_error (CAIRO_STATUS_NO_MEMORY);
+	return (cairo_font_face_t *)&_cairo_font_face_nil;
+    }
+
+    font_face->cgFont = CGFontRetain (font);
+
+    _cairo_font_face_init (&font_face->base, &_cairo_quartz_font_face_backend);
+
+    return &font_face->base;
+}
+
+/**
+ ** scaled font backend
+ **/
+
+static cairo_quartz_font_face_t *
+_cairo_quartz_scaled_to_face (void *abstract_font)
+{
+    cairo_quartz_scaled_font_t *sfont = (cairo_quartz_scaled_font_t*) abstract_font;
+    cairo_font_face_t *font_face = cairo_scaled_font_get_font_face (&sfont->base);
+    if (!font_face || font_face->backend->type != CAIRO_FONT_TYPE_QUARTZ)
+	return NULL;
+
+    return (cairo_quartz_font_face_t*) font_face;
+}
+
+static cairo_status_t
+_cairo_quartz_font_create_toy(cairo_toy_font_face_t *toy_face,
+			      const cairo_matrix_t *font_matrix,
+			      const cairo_matrix_t *ctm,
+			      const cairo_font_options_t *options,
+			      cairo_scaled_font_t **font_out)
+{
+    const char *family = toy_face->family;
+    char *full_name = malloc(strlen(family) + 64); // give us a bit of room to tack on Bold, Oblique, etc.
+    CFStringRef cgFontName = NULL;
+    CGFontRef cgFont = NULL;
+    int loop;
+
+    cairo_status_t status;
+    cairo_font_face_t *face;
+    cairo_scaled_font_t *scaled_font;
+
+    /* handle CSS-ish faces */
+    if (!strcmp(family, "serif") || !strcmp(family, "Times Roman"))
+	family = "Times";
+    else if (!strcmp(family, "sans-serif") || !strcmp(family, "sans"))
+	family = "Helvetica";
+    else if (!strcmp(family, "cursive"))
+	family = "Apple Chancery";
+    else if (!strcmp(family, "fantasy"))
+	family = "Papyrus";
+    else if (!strcmp(family, "monospace") || !strcmp(family, "mono"))
+	family = "Courier";
+
+    /* Try to build up the full name, e.g. "Helvetica Bold Oblique" first,
+     * then drop the bold, then drop the slant, then drop both.. finally
+     * just use "Helvetica".  And if Helvetica doesn't exist, give up.
+     */
+    for (loop = 0; loop < 5; loop++) {
+	if (loop == 4)
+	    family = "Helvetica";
+
+	strcpy (full_name, family);
+
+	if (loop < 3 && (loop & 1) == 0) {
+	    if (toy_face->weight == CAIRO_FONT_WEIGHT_BOLD)
+		strcat (full_name, " Bold");
+	}
+
+	if (loop < 3 && (loop & 2) == 0) {
+	    if (toy_face->slant == CAIRO_FONT_SLANT_ITALIC)
+		strcat (full_name, " Italic");
+	    else if (toy_face->slant == CAIRO_FONT_SLANT_OBLIQUE)
+		strcat (full_name, " Oblique");
+	}
+
+	cgFontName = CFStringCreateWithCString (NULL, full_name, kCFStringEncodingASCII);
+	cgFont = CGFontCreateWithFontName (cgFontName);
+	CFRelease (cgFontName);
+
+	if (cgFont)
+	    break;
+    }
+
+    if (!cgFont) {
+	/* Give up */
+	return CAIRO_STATUS_NO_MEMORY;
+    }
+
+    face = cairo_quartz_font_face_create_for_cgfont (cgFont);
+    if (face->status)
+	return face->status;
+
+    status = _cairo_quartz_font_face_scaled_font_create (face,
+							 font_matrix, ctm,
+							 options,
+							 &scaled_font);
+    cairo_font_face_destroy (face);
+    if (status)
+	return status;
+
+    *font_out = scaled_font;
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
+static void
+_cairo_quartz_font_fini(void *abstract_font)
+{
+}
+
+#define INVALID_GLYPH 0x00
+
+static inline CGGlyph
+_cairo_quartz_scaled_glyph_index (cairo_scaled_glyph_t *scaled_glyph) {
+    unsigned long index = _cairo_scaled_glyph_index (scaled_glyph);
+    if (index > 0xffff)
+	return INVALID_GLYPH;
+    return (CGGlyph) index;
+}
+
+static inline cairo_status_t
+_cairo_matrix_to_unit_quartz_matrix (const cairo_matrix_t *m, CGAffineTransform *txout,
+				     double *xout, double *yout)
+{
+    CGAffineTransform transform;
+    double xscale, yscale;
+    cairo_status_t status;
+
+    status = _cairo_matrix_compute_scale_factors (m, &xscale, &yscale, 1);
+    if (status)
+	return status;
+
+    transform = CGAffineTransformMake (m->xx, - m->yx,
+				       - m->xy, m->yy,
+				       0.0f, 0.0f);
+    if (xout)
+	*xout = xscale;
+    if (yout)
+	*yout = yscale;
+
+    if (xscale)
+	xscale = 1.0 / xscale;
+    if (yscale)
+	yscale = 1.0 / yscale;
+
+    *txout = CGAffineTransformScale (transform, xscale, yscale);
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_int_status_t
+_cairo_quartz_init_glyph_metrics (cairo_quartz_scaled_font_t *font,
+				  cairo_scaled_glyph_t *scaled_glyph)
+{
+    cairo_int_status_t status = CAIRO_STATUS_SUCCESS;
+
+    cairo_quartz_font_face_t *font_face = _cairo_quartz_scaled_to_face(font);
+    cairo_text_extents_t extents = {0, 0, 0, 0, 0, 0};
+    CGGlyph glyph = _cairo_quartz_scaled_glyph_index (scaled_glyph);
+    int advance;
+    CGRect bbox;
+    double emscale = CGFontGetUnitsPerEm (font_face->cgFont);
+    double xmin, ymin, xmax, ymax;
+
+    if (glyph == INVALID_GLYPH)
+	goto FAIL;
+
+    if (!CGFontGetGlyphAdvances (font_face->cgFont, &glyph, 1, &advance))
+	goto FAIL;
+
+    if (!CGFontGetGlyphBBoxes (font_face->cgFont, &glyph, 1, &bbox))
+	goto FAIL;
+
+#if 0
+    fprintf (stderr, "[0x%04x] bbox: %f %f %f %f\n", glyph,
+	     bbox.origin.x / emscale, bbox.origin.y / emscale,
+	     bbox.size.width / emscale, bbox.size.height / emscale);
+#endif
+
+    xmin = CGRectGetMinX(bbox) / emscale;
+    ymin = CGRectGetMinY(bbox) / emscale;
+    xmax = CGRectGetMaxX(bbox) / emscale;
+    ymax = CGRectGetMaxY(bbox) / emscale;
+
+    extents.x_bearing = xmin;
+    extents.y_bearing = - ymax;
+    extents.width = xmax - xmin;
+    extents.height = ymax - ymin;
+
+    extents.x_advance = (double) advance / emscale;
+    extents.y_advance = 0.0;
+
+#if 0
+    fprintf (stderr, "[0x%04x] extents: bearings: %f %f dim: %f %f adv: %f\n\n", glyph,
+	     extents.x_bearing, extents.y_bearing, extents.width, extents.height, extents.x_advance);
+#endif
+
+  FAIL:
+    _cairo_scaled_glyph_set_metrics (scaled_glyph,
+				     &font->base,
+				     &extents);
+
+    return status;
+}
+
+static void
+_cairo_quartz_path_apply_func (void *info, const CGPathElement *el)
+{
+    cairo_path_fixed_t *path = (cairo_path_fixed_t *) info;
+
+    switch (el->type) {
+	case kCGPathElementMoveToPoint:
+	    _cairo_path_fixed_move_to (path,
+				       _cairo_fixed_from_double(el->points[0].x),
+				       _cairo_fixed_from_double(el->points[0].y));
+	    break;
+	case kCGPathElementAddLineToPoint:
+	    _cairo_path_fixed_line_to (path,
+				       _cairo_fixed_from_double(el->points[0].x),
+				       _cairo_fixed_from_double(el->points[0].y));
+	    break;
+	case kCGPathElementAddQuadCurveToPoint: {
+	    cairo_fixed_t fx, fy;
+	    double x, y;
+	    if (!_cairo_path_fixed_get_current_point (path, &fx, &fy))
+		fx = fy = 0;
+	    x = _cairo_fixed_to_double (fx);
+	    y = _cairo_fixed_to_double (fy);
+
+	    _cairo_path_fixed_curve_to (path,
+					_cairo_fixed_from_double((x + el->points[0].x * 2.0) / 3.0),
+					_cairo_fixed_from_double((y + el->points[0].y * 2.0) / 3.0),
+					_cairo_fixed_from_double((el->points[0].x * 2.0 + el->points[1].x) / 3.0),
+					_cairo_fixed_from_double((el->points[0].y * 2.0 + el->points[1].y) / 3.0),
+					_cairo_fixed_from_double(el->points[1].x),
+					_cairo_fixed_from_double(el->points[1].y));
+	}
+	    break;
+	case kCGPathElementAddCurveToPoint:
+	    _cairo_path_fixed_curve_to (path,
+					_cairo_fixed_from_double(el->points[0].x),
+					_cairo_fixed_from_double(el->points[0].y),
+					_cairo_fixed_from_double(el->points[1].x),
+					_cairo_fixed_from_double(el->points[1].y),
+					_cairo_fixed_from_double(el->points[2].x),
+					_cairo_fixed_from_double(el->points[2].y));
+	    break;
+	case kCGPathElementCloseSubpath:
+	    _cairo_path_fixed_close_path (path);
+	    break;
+    }
+}
+
+static cairo_int_status_t
+_cairo_quartz_init_glyph_path (cairo_quartz_scaled_font_t *font,
+			       cairo_scaled_glyph_t *scaled_glyph)
+{
+    cairo_quartz_font_face_t *font_face = _cairo_quartz_scaled_to_face(font);
+    CGGlyph glyph = _cairo_quartz_scaled_glyph_index (scaled_glyph);
+    CGAffineTransform textMatrix;
+    CGPathRef glyphPath;
+    cairo_path_fixed_t *path;
+
+    if (CGFontGetGlyphPathPtr == NULL)
+	CGFontGetGlyphPathPtr = dlsym(RTLD_DEFAULT, "CGFontGetGlyphPath");
+
+    if (!CGFontGetGlyphPathPtr)
+	return CAIRO_INT_STATUS_UNSUPPORTED;
+
+    if (glyph == INVALID_GLYPH) {
+	_cairo_scaled_glyph_set_path (scaled_glyph, &font->base, _cairo_path_fixed_create());
+	return CAIRO_STATUS_SUCCESS;
+    }
+
+    textMatrix = CGAffineTransformMake (font->base.scale.xx,
+					-font->base.scale.yx,
+					-font->base.scale.xy,
+					font->base.scale.yy,
+					font->base.scale.x0,
+					font->base.scale.y0);
+
+    textMatrix = CGAffineTransformConcat (textMatrix, CGAffineTransformMake (1.0, 0.0, 0.0, -1.0, 0.0, 0.0));
+
+    glyphPath = CGFontGetGlyphPathPtr (font_face->cgFont, &textMatrix, 0, glyph);
+    if (!glyphPath)
+	return CAIRO_INT_STATUS_UNSUPPORTED;
+
+    path = _cairo_path_fixed_create ();
+    if (!path) {
+	CGPathRelease (glyphPath);
+	return _cairo_error(CAIRO_STATUS_NO_MEMORY);
+    }
+
+    CGPathApply (glyphPath, path, _cairo_quartz_path_apply_func);
+
+    CGPathRelease (glyphPath);
+
+    _cairo_scaled_glyph_set_path (scaled_glyph, &font->base, path);
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_int_status_t
+_cairo_quartz_init_glyph_surface (cairo_quartz_scaled_font_t *font,
+				  cairo_scaled_glyph_t *scaled_glyph)
+{
+    cairo_int_status_t status = CAIRO_STATUS_SUCCESS;
+
+    cairo_quartz_font_face_t *font_face = _cairo_quartz_scaled_to_face(font);
+
+    cairo_image_surface_t *surface = NULL;
+
+    CGGlyph glyph = _cairo_quartz_scaled_glyph_index (scaled_glyph);
+
+    int advance;
+    CGRect bbox;
+    double width, height;
+    double xscale, yscale;
+    double emscale = CGFontGetUnitsPerEm (font_face->cgFont);
+
+    CGColorSpaceRef gray;
+    CGContextRef cgContext = NULL;
+    CGAffineTransform textMatrix;
+    CGRect glyphRect;
+    CGPoint glyphOrigin;
+
+    //fprintf (stderr, "scaled_glyph: %p surface: %p\n", scaled_glyph, scaled_glyph->surface);
+
+    /* Create blank 2x2 image if we don't have this character.
+     * Maybe we should draw a better missing-glyph slug or something,
+     * but this is ok for now.
+     */
+    if (glyph == INVALID_GLYPH) {
+	surface = (cairo_image_surface_t*) cairo_image_surface_create (CAIRO_FORMAT_A8, 2, 2);
+	status = cairo_surface_status ((cairo_surface_t *) surface);
+	if (status)
+	    return status;
+
+	_cairo_scaled_glyph_set_surface (scaled_glyph,
+					 &font->base,
+					 surface);
+	return CAIRO_STATUS_SUCCESS;
+    }
+
+    if (!CGFontGetGlyphAdvances (font_face->cgFont, &glyph, 1, &advance) ||
+	!CGFontGetGlyphBBoxes (font_face->cgFont, &glyph, 1, &bbox))
+    {
+	return CAIRO_INT_STATUS_UNSUPPORTED;
+    }
+
+    status = _cairo_matrix_compute_scale_factors (&font->base.scale,
+						  &xscale, &yscale, 1);
+    if (status)
+	return status;
+
+    textMatrix = CGAffineTransformMake (font->base.scale.xx,
+					-font->base.scale.yx,
+					-font->base.scale.xy,
+					font->base.scale.yy,
+					0.0f, 0.0f);
+    glyphRect = CGRectMake (bbox.origin.x / emscale,
+			    bbox.origin.y / emscale,
+			    bbox.size.width / emscale,
+			    bbox.size.height / emscale);
+
+    //fprintf (stderr, "glyphRect[o]: %f %f %f %f\n", glyphRect.origin.x, glyphRect.origin.y, glyphRect.size.width, glyphRect.size.height);
+
+    glyphRect = CGRectApplyAffineTransform (glyphRect, textMatrix);
+
+    glyphOrigin = glyphRect.origin;
+
+    //textMatrix = CGAffineTransformConcat (textMatrix, CGAffineTransformInvert (ctm));
+
+    width = ceil(glyphRect.size.width);
+    height = ceil(glyphRect.size.height);
+
+    //fprintf (stderr, "glyphRect[n]: %f %f %f %f\n", glyphRect.origin.x, glyphRect.origin.y, glyphRect.size.width, glyphRect.size.height);
+    
+    surface = (cairo_image_surface_t*) cairo_image_surface_create (CAIRO_FORMAT_A8, width, height);
+    if (surface->base.status)
+	return surface->base.status;
+
+    gray = CGColorSpaceCreateDeviceGray ();
+    cgContext = CGBitmapContextCreate (surface->data,
+				       surface->width,
+				       surface->height,
+				       8,
+				       surface->stride,
+				       gray,
+				       kCGImageAlphaNone);
+    CGColorSpaceRelease (gray);
+
+    CGContextSetFont (cgContext, font_face->cgFont);
+    CGContextSetFontSize (cgContext, 1.0);
+    CGContextSetTextMatrix (cgContext, textMatrix);
+
+    CGContextClearRect (cgContext, CGRectMake (0.0f, 0.0f, width, height));
+
+    if (font->base.options.antialias == CAIRO_ANTIALIAS_NONE)
+    	CGContextSetShouldAntialias (cgContext, false);
+
+    CGContextSetRGBFillColor (cgContext, 1.0, 1.0, 1.0, 1.0);
+    CGContextShowGlyphsAtPoint (cgContext, - glyphOrigin.x, - glyphOrigin.y, &glyph, 1);
+
+    CGContextRelease (cgContext);
+
+    cairo_surface_set_device_offset (&surface->base,
+				     - glyphOrigin.x,
+				     height + glyphOrigin.y);
+
+    _cairo_scaled_glyph_set_surface (scaled_glyph, &font->base, surface);
+
+    return status;
+}
+
+static cairo_int_status_t
+_cairo_quartz_font_scaled_glyph_init (void *abstract_font,
+				      cairo_scaled_glyph_t *scaled_glyph,
+				      cairo_scaled_glyph_info_t info)
+{
+    cairo_quartz_scaled_font_t *font = (cairo_quartz_scaled_font_t *) abstract_font;
+    cairo_int_status_t status = CAIRO_STATUS_SUCCESS;
+
+    if (!status && (info & CAIRO_SCALED_GLYPH_INFO_METRICS))
+	status = _cairo_quartz_init_glyph_metrics (font, scaled_glyph);
+
+    if (!status && (info & CAIRO_SCALED_GLYPH_INFO_PATH))
+	status = _cairo_quartz_init_glyph_path (font, scaled_glyph);
+
+    if (!status && (info & CAIRO_SCALED_GLYPH_INFO_SURFACE))
+	status = _cairo_quartz_init_glyph_surface (font, scaled_glyph);
+
+    return status;
+}
+
+static unsigned long
+_cairo_quartz_ucs4_to_index (void *abstract_font,
+			     uint32_t ucs4)
+{
+    cairo_quartz_scaled_font_t *font = (cairo_quartz_scaled_font_t*) abstract_font;
+    cairo_quartz_font_face_t *ffont = _cairo_quartz_scaled_to_face(font);
+    UniChar u = (UniChar) ucs4;
+    CGGlyph glyph;
+
+    CGFontGetGlyphsForUnichars (ffont->cgFont, &u, &glyph, 1);
+
+    return glyph;
+}
+
+const cairo_scaled_font_backend_t cairo_quartz_scaled_font_backend = {
+    CAIRO_FONT_TYPE_QUARTZ,
+    _cairo_quartz_font_create_toy,
+    _cairo_quartz_font_fini,
+    _cairo_quartz_font_scaled_glyph_init,
+    NULL, /* text_to_glyphs */
+    _cairo_quartz_ucs4_to_index,
+    NULL, /* show_glyphs */
+    NULL, /* load_truetype_table */
+    NULL, /* map_glyphs_to_unicode */
+};
+
+/*
+ * private methods that the quartz surface uses
+ */
+
+CGFontRef
+_cairo_quartz_scaled_font_get_cg_font_ref (cairo_scaled_font_t *abstract_font)
+{
+    cairo_quartz_font_face_t *ffont = _cairo_quartz_scaled_to_face(abstract_font);
+
+    return ffont->cgFont;
+}
diff --git a/src/cairo-quartz-private.h b/src/cairo-quartz-private.h
index 0ab9bc0..07d5a8e 100644
--- a/src/cairo-quartz-private.h
+++ b/src/cairo-quartz-private.h
@@ -97,4 +97,9 @@ _cairo_quartz_scaled_font_get_cg_font_ref (cairo_scaled_font_t *sfont);
 
 #endif /* CAIRO_HAS_QUARTZ_SURFACE */
 
+#if CAIRO_HAS_CGFONT_FONT
+CGFontRef
+_cairo_cgfont_scaled_font_get_cg_font_ref (cairo_scaled_font_t *sfont);
+#endif /* CAIRO_HAS_CGFONT_FONT */
+
 #endif /* CAIRO_QUARTZ_PRIVATE_H */
diff --git a/src/cairo-quartz-surface.c b/src/cairo-quartz-surface.c
index 5296eb5..5b6cecb 100644
--- a/src/cairo-quartz-surface.c
+++ b/src/cairo-quartz-surface.c
@@ -48,7 +48,6 @@
 #define FloatToFixed(a)     ((Fixed)((float)(a) * fixed1))
 #endif
 
-#include <Carbon/Carbon.h>
 #include <limits.h>
 
 #undef QUARTZ_DEBUG
diff --git a/src/cairo-quartz.h b/src/cairo-quartz.h
index b5c20e6..7982fbb 100644
--- a/src/cairo-quartz.h
+++ b/src/cairo-quartz.h
@@ -40,7 +40,7 @@
 
 #if CAIRO_HAS_QUARTZ_SURFACE
 
-#include <Carbon/Carbon.h>
+#include <ApplicationServices/ApplicationServices.h>
 
 CAIRO_BEGIN_DECLS
 
@@ -64,6 +64,9 @@ cairo_quartz_surface_get_cg_context (cairo_surface_t *surface);
 #ifdef CAIRO_HAS_QUARTZ_FONT
 
 cairo_public cairo_font_face_t *
+cairo_quartz_font_face_create_for_cgfont (CGFontRef font);
+
+cairo_public cairo_font_face_t *
 cairo_quartz_font_face_create_for_atsu_font_id (ATSUFontID font_id);
 
 #endif /* CAIRO_HAS_QUARTZ_FONT */
diff --git a/src/cairoint.h b/src/cairoint.h
index 41d9182..6a89d71 100644
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -455,7 +455,7 @@ extern const cairo_private struct _cairo_scaled_font_backend cairo_win32_scaled_
 
 #if CAIRO_HAS_QUARTZ_FONT
 
-extern const cairo_private struct _cairo_scaled_font_backend cairo_atsui_scaled_font_backend;
+extern const cairo_private struct _cairo_scaled_font_backend cairo_quartz_scaled_font_backend;
 
 #endif
 
@@ -873,7 +873,7 @@ typedef struct _cairo_traps {
 #elif CAIRO_HAS_QUARTZ_FONT
 
 #define CAIRO_FONT_FAMILY_DEFAULT CAIRO_QUARTZ_FONT_FAMILY_DEFAULT
-#define CAIRO_SCALED_FONT_BACKEND_DEFAULT &cairo_atsui_scaled_font_backend
+#define CAIRO_SCALED_FONT_BACKEND_DEFAULT &cairo_quartz_scaled_font_backend
 
 #elif CAIRO_HAS_FT_FONT
 


More information about the cairo-commit mailing list