diff options
author | Vladimir Vukicevic <vladimir@pobox.com> | 2008-04-01 13:28:03 -0700 |
---|---|---|
committer | Vladimir Vukicevic <vladimir@h-232.office.mozilla.org> | 2008-04-01 13:28:03 -0700 |
commit | 56800e6ea0f7153e44f0cba14c89c4239067a60e (patch) | |
tree | f25a3d8e957de415be89afbe8486a787610fb567 | |
parent | 8ddae11b544c35057a96ca0bdea34b4f473ee261 (diff) |
[quartz] Remove cairo-atsui-font.c
-rw-r--r-- | src/cairo-atsui-font.c | 1028 |
1 files changed, 0 insertions, 1028 deletions
diff --git a/src/cairo-atsui-font.c b/src/cairo-atsui-font.c deleted file mode 100644 index 42c209b66..000000000 --- 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@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 */ -}; - |