Back to index

lightning-sunbird  0.9+nobinonly
cairo-atsui-font.c
Go to the documentation of this file.
00001 /* cairo - a vector graphics library with display and print output
00002  *
00003  * Copyright © 2004 Calum Robinson
00004  *
00005  * This library is free software; you can redistribute it and/or
00006  * modify it either under the terms of the GNU Lesser General Public
00007  * License version 2.1 as published by the Free Software Foundation
00008  * (the "LGPL") or, at your option, under the terms of the Mozilla
00009  * Public License Version 1.1 (the "MPL"). If you do not alter this
00010  * notice, a recipient may use your version of this file under either
00011  * the MPL or the LGPL.
00012  *
00013  * You should have received a copy of the LGPL along with this library
00014  * in the file COPYING-LGPL-2.1; if not, write to the Free Software
00015  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
00016  * You should have received a copy of the MPL along with this library
00017  * in the file COPYING-MPL-1.1
00018  *
00019  * The contents of this file are subject to the Mozilla Public License
00020  * Version 1.1 (the "License"); you may not use this file except in
00021  * compliance with the License. You may obtain a copy of the License at
00022  * http://www.mozilla.org/MPL/
00023  *
00024  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
00025  * OF ANY KIND, either express or implied. See the LGPL or the MPL for
00026  * the specific language governing rights and limitations.
00027  *
00028  * The Original Code is the cairo graphics library.
00029  *
00030  * The Initial Developer of the Original Code is Calum Robinson
00031  *
00032  * Contributor(s):
00033  *  Calum Robinson <calumr@mac.com>
00034  */
00035 
00036 #include <stdlib.h>
00037 #include <math.h>
00038 #include "cairo-atsui.h"
00039 #include "cairo-quartz.h"
00040 #include "cairoint.h"
00041 #include "cairo.h"
00042 
00043 /*
00044  * FixedToFloat/FloatToFixed are 10.3+ SDK items - include definitions
00045  * here so we can use older SDKs.
00046  */
00047 #ifndef FixedToFloat
00048 #define fixed1              ((Fixed) 0x00010000L)
00049 #define FixedToFloat(a)     ((float)(a) / fixed1)
00050 #define FloatToFixed(a)     ((Fixed)((float)(a) * fixed1))
00051 #endif
00052 
00053 typedef struct {
00054     cairo_scaled_font_t base;
00055 
00056     cairo_matrix_t scale;
00057     ATSUStyle style;
00058     ATSUStyle unscaled_style;
00059     ATSUFontID fontID;
00060 } cairo_atsui_font_t;
00061 
00062 typedef struct cairo_ATSUI_glyph_path_callback_info_t {
00063     cairo_path_fixed_t *path;
00064     cairo_matrix_t scale;
00065 } cairo_ATSUI_glyph_path_callback_info_t;
00066 
00067 const cairo_scaled_font_backend_t cairo_atsui_scaled_font_backend;
00068 
00069 static CGAffineTransform
00070 CGAffineTransformMakeWithCairoFontScale(cairo_matrix_t *scale)
00071 {
00072     return CGAffineTransformMake(scale->xx, scale->yx,
00073                                  scale->xy, scale->yy,
00074                                  0, 0);
00075 }
00076 
00077 static ATSUStyle
00078 CreateSizedCopyOfStyle(ATSUStyle inStyle, cairo_matrix_t *scale)
00079 {
00080     ATSUStyle style;
00081     OSStatus err;
00082 
00083 
00084     // Set the style's size
00085     CGAffineTransform theTransform =
00086         CGAffineTransformMakeWithCairoFontScale(scale);
00087     Fixed theSize =
00088         FloatToFixed(CGSizeApplyAffineTransform
00089                      (CGSizeMake(1.0, 1.0), theTransform).height);
00090     const ATSUAttributeTag theFontStyleTags[] = { kATSUSizeTag };
00091     const ByteCount theFontStyleSizes[] = { sizeof(Fixed) };
00092     ATSUAttributeValuePtr theFontStyleValues[] = { &theSize };
00093 
00094     err = ATSUCreateAndCopyStyle(inStyle, &style);
00095 
00096     err = ATSUSetAttributes(style,
00097                             sizeof(theFontStyleTags) /
00098                             sizeof(ATSUAttributeTag), theFontStyleTags,
00099                             theFontStyleSizes, theFontStyleValues);
00100 
00101     return style;
00102 }
00103 
00104 
00105 static cairo_status_t
00106 _cairo_atsui_font_create_toy(cairo_toy_font_face_t *toy_face,
00107                           const cairo_matrix_t *font_matrix,
00108                           const cairo_matrix_t *ctm,
00109                           const cairo_font_options_t *options,
00110                           cairo_scaled_font_t **font_out)
00111 {
00112     cairo_atsui_font_t *font = NULL;
00113     ATSUStyle style;
00114     ATSUFontID fontID;
00115     OSStatus err;
00116     Boolean isItalic, isBold;
00117     cairo_matrix_t scale;
00118     const char *family = toy_face->family;
00119 
00120     err = ATSUCreateStyle(&style);
00121 
00122     switch (toy_face->weight) {
00123     case CAIRO_FONT_WEIGHT_BOLD:
00124         isBold = true;
00125         break;
00126     case CAIRO_FONT_WEIGHT_NORMAL:
00127     default:
00128         isBold = false;
00129         break;
00130     }
00131 
00132     switch (toy_face->slant) {
00133     case CAIRO_FONT_SLANT_ITALIC:
00134         isItalic = true;
00135         break;
00136     case CAIRO_FONT_SLANT_OBLIQUE:
00137         isItalic = false;
00138         break;
00139     case CAIRO_FONT_SLANT_NORMAL:
00140     default:
00141         isItalic = false;
00142         break;
00143     }
00144 
00145     err = ATSUFindFontFromName(family, strlen(family),
00146                                kFontFamilyName,
00147                                kFontNoPlatformCode,
00148                                kFontRomanScript,
00149                                kFontNoLanguageCode, &fontID);
00150 
00151     if (err != noErr) {
00152        // couldn't get the font - remap css names and try again
00153 
00154        if (!strcmp(family, "serif"))
00155            family = "Times";
00156        else if (!strcmp(family, "sans-serif"))
00157            family = "Helvetica";
00158        else if (!strcmp(family, "cursive"))
00159            family = "Apple Chancery";
00160        else if (!strcmp(family, "fantasy"))
00161            family = "Gadget";
00162        else if (!strcmp(family, "monospace"))
00163            family = "Courier";
00164        else // anything else - return error instead?
00165            family = "Courier";
00166 
00167        err = ATSUFindFontFromName(family, strlen(family),
00168                                kFontFamilyName,
00169                                kFontNoPlatformCode,
00170                                kFontRomanScript,
00171                                kFontNoLanguageCode, &fontID);
00172     }
00173 
00174 
00175     ATSUAttributeTag styleTags[] =
00176         { kATSUQDItalicTag, kATSUQDBoldfaceTag, kATSUFontTag };
00177     ATSUAttributeValuePtr styleValues[] = { &isItalic, &isBold, &fontID };
00178     ByteCount styleSizes[] =
00179         { sizeof(Boolean), sizeof(Boolean), sizeof(ATSUFontID) };
00180 
00181 
00182     err = ATSUSetAttributes(style,
00183                             sizeof(styleTags) / sizeof(styleTags[0]),
00184                             styleTags, styleSizes, styleValues);
00185 
00186     font = malloc(sizeof(cairo_atsui_font_t));
00187 
00188     _cairo_scaled_font_init(&font->base, toy_face, font_matrix, ctm, options,
00189                          &cairo_atsui_scaled_font_backend);
00190 
00191     cairo_matrix_multiply(&scale, font_matrix, ctm);
00192     font->style = CreateSizedCopyOfStyle(style, &scale);
00193 
00194     Fixed theSize = FloatToFixed(1.0);
00195     const ATSUAttributeTag theFontStyleTags[] = { kATSUSizeTag };
00196     const ByteCount theFontStyleSizes[] = { sizeof(Fixed) };
00197     ATSUAttributeValuePtr theFontStyleValues[] = { &theSize };
00198     err = ATSUSetAttributes(style,
00199                             sizeof(theFontStyleTags) /
00200                             sizeof(ATSUAttributeTag), theFontStyleTags,
00201                             theFontStyleSizes, theFontStyleValues);
00202 
00203     font->unscaled_style = style;
00204 
00205     font->fontID = fontID;
00206     font->scale = scale;
00207 
00208     *font_out = &font->base;
00209 
00210     return CAIRO_STATUS_SUCCESS;
00211 }
00212 
00213 static void
00214 _cairo_atsui_font_fini(void *abstract_font)
00215 {
00216     cairo_atsui_font_t *font = abstract_font;
00217 
00218     if (font == NULL)
00219         return;
00220 
00221     if (font->style)
00222         ATSUDisposeStyle(font->style);
00223     if (font->unscaled_style)
00224         ATSUDisposeStyle(font->unscaled_style);
00225 }
00226 
00227 
00228 static void
00229 _cairo_atsui_font_get_glyph_cache_key(void *abstract_font,
00230                                   cairo_glyph_cache_key_t *key)
00231 {
00232 }
00233 
00234 
00235 static cairo_status_t
00236 _cairo_atsui_font_text_to_glyphs(void            *abstract_font,
00237                                  const char     *utf8,
00238                                  cairo_glyph_t **glyphs,
00239                              int          *num_glyphs)
00240 {
00241     cairo_atsui_font_t *font = abstract_font;
00242     size_t i;
00243     OSStatus err;
00244     ATSUTextLayout textLayout;
00245     ATSLayoutRecord *layoutRecords;
00246     ItemCount glyphCount;
00247     int charCount;
00248     UniChar *theText;
00249     cairo_status_t status;
00250 
00251     // liberal estimate of size
00252     charCount = strlen(utf8);
00253 
00254     if (charCount == 0) {
00255        *glyphs = NULL;
00256        *num_glyphs = 0;
00257        return CAIRO_STATUS_SUCCESS;
00258     }
00259 
00260     status = _cairo_utf8_to_utf16 (utf8, -1, &theText, &charCount);
00261     if (status)
00262        return status;
00263 
00264     err = ATSUCreateTextLayout(&textLayout);
00265 
00266     err = ATSUSetTextPointerLocation(textLayout,
00267                                      theText, 0, charCount, charCount);
00268 
00269 
00270     // Set the style for all of the text
00271     err = ATSUSetRunStyle(textLayout,
00272                           font->unscaled_style, kATSUFromTextBeginning, kATSUToTextEnd);
00273 
00274     // Get the glyphs from the text layout object
00275     err = ATSUDirectGetLayoutDataArrayPtrFromTextLayout(textLayout,
00276                                                         0,
00277                                                         kATSUDirectDataLayoutRecordATSLayoutRecordCurrent,
00278                                                         (void *)
00279                                                         &layoutRecords,
00280                                                         &glyphCount);
00281 
00282     *num_glyphs = glyphCount - 1;
00283 
00284 
00285     *glyphs =
00286         (cairo_glyph_t *) malloc(*num_glyphs * (sizeof(cairo_glyph_t)));
00287     if (*glyphs == NULL) {
00288         return CAIRO_STATUS_NO_MEMORY;
00289     }
00290 
00291     for (i = 0; i < *num_glyphs; i++) {
00292         (*glyphs)[i].index = layoutRecords[i].glyphID;
00293         (*glyphs)[i].x = FixedToFloat(layoutRecords[i].realPos);
00294         (*glyphs)[i].y = 0;
00295     }
00296 
00297 
00298     free(theText);
00299 
00300     ATSUDirectReleaseLayoutDataArrayPtr(NULL,
00301                                         kATSUDirectDataLayoutRecordATSLayoutRecordCurrent,
00302                                         (void *) &layoutRecords);
00303 
00304     ATSUDisposeTextLayout(textLayout);
00305 
00306     return CAIRO_STATUS_SUCCESS;
00307 }
00308 
00309 
00310 static cairo_status_t
00311 _cairo_atsui_font_font_extents(void *abstract_font,
00312                                cairo_font_extents_t * extents)
00313 {
00314     cairo_atsui_font_t *font = abstract_font;
00315     ATSFontRef atsFont;
00316     ATSFontMetrics metrics;
00317     OSStatus err;
00318 
00319     // TODO - test this
00320 
00321     atsFont = FMGetATSFontRefFromFont(font->fontID);
00322 
00323     if (atsFont) {
00324         err =
00325             ATSFontGetHorizontalMetrics(atsFont, kATSOptionFlagsDefault,
00326                                         &metrics);
00327 
00328         if (err == noErr) {
00329             extents->ascent = metrics.ascent;
00330             extents->descent = metrics.descent;
00331             extents->height = metrics.capHeight;
00332             extents->max_x_advance = metrics.maxAdvanceWidth;
00333 
00334             // The FT backend doesn't handle max_y_advance either, so we'll ignore it for now. 
00335             extents->max_y_advance = 0.0;
00336 
00337             return CAIRO_STATUS_SUCCESS;
00338         }
00339     }
00340 
00341 
00342     return CAIRO_STATUS_NULL_POINTER;
00343 }
00344 
00345 
00346 static cairo_status_t
00347 _cairo_atsui_font_glyph_extents(void *abstract_font,
00348                                 cairo_glyph_t * glyphs,
00349                                 int num_glyphs,
00350                                 cairo_text_extents_t * extents)
00351 {
00352     cairo_atsui_font_t *font = abstract_font;
00353     OSStatus err;
00354 
00355     assert(num_glyphs == 1);
00356 
00357     GlyphID theGlyph = glyphs[0].index;
00358 
00359     ATSGlyphIdealMetrics metricsH, metricsV;
00360     ATSUStyle style;
00361 
00362     ATSUCreateAndCopyStyle(font->unscaled_style, &style);
00363 
00364     err = ATSUGlyphGetIdealMetrics(style,
00365                                1, &theGlyph, 0, &metricsH);
00366 
00367     ATSUVerticalCharacterType verticalType = kATSUStronglyVertical;
00368     const ATSUAttributeTag theTag[] = { kATSUVerticalCharacterTag };
00369     const ByteCount theSizes[] = { sizeof(verticalType) };
00370     ATSUAttributeValuePtr theValues[] = { &verticalType };
00371     
00372     err = ATSUSetAttributes(style, 1, theTag, theSizes, theValues);
00373 
00374     err = ATSUGlyphGetIdealMetrics(style,
00375                                1, &theGlyph, 0, &metricsV);
00376 
00377     extents->x_bearing = metricsH.sideBearing.x;
00378     extents->y_bearing = metricsV.advance.y;
00379     extents->width = 
00380        metricsH.advance.x - metricsH.sideBearing.x - metricsH.otherSideBearing.x;
00381     extents->height = 
00382        -metricsV.advance.y - metricsV.sideBearing.y - metricsV.otherSideBearing.y;
00383     extents->x_advance = metricsH.advance.x;
00384     extents->y_advance = 0;
00385 
00386     ATSUDisposeStyle(style);
00387 
00388     return CAIRO_STATUS_SUCCESS;
00389 }
00390 
00391 
00392 static cairo_status_t
00393 _cairo_atsui_font_glyph_bbox(void *abstract_font,
00394                              const cairo_glyph_t *glyphs,
00395                              int num_glyphs, cairo_box_t *bbox)
00396 {
00397     cairo_atsui_font_t *font = abstract_font;
00398     cairo_fixed_t x1, y1, x2, y2;
00399     int i;
00400 
00401     bbox->p1.x = bbox->p1.y = CAIRO_MAXSHORT << 16;
00402     bbox->p2.x = bbox->p2.y = CAIRO_MINSHORT << 16;
00403 
00404 
00405     for (i = 0; i < num_glyphs; i++) {
00406         GlyphID theGlyph = glyphs[i].index;
00407 
00408        ATSGlyphScreenMetrics metrics;
00409        ATSUGlyphGetScreenMetrics(font->style, 
00410                               1, &theGlyph, 0, true, true, &metrics);
00411 
00412        x1 = _cairo_fixed_from_double(glyphs[i].x + metrics.topLeft.x);
00413        y1 = _cairo_fixed_from_double(glyphs[i].y - metrics.topLeft.y);
00414        x2 = x1 + _cairo_fixed_from_double(metrics.height);
00415        y2 = y1 + _cairo_fixed_from_double(metrics.width);
00416 
00417         if (x1 < bbox->p1.x)
00418             bbox->p1.x = x1;
00419 
00420         if (y1 < bbox->p1.y)
00421             bbox->p1.y = y1;
00422 
00423         if (x2 > bbox->p2.x)
00424             bbox->p2.x = x2;
00425 
00426         if (y2 > bbox->p2.y)
00427             bbox->p2.y = y2;
00428     }
00429 
00430     return CAIRO_STATUS_SUCCESS;
00431 }
00432 
00433 
00434 static cairo_status_t
00435 _cairo_atsui_font_show_glyphs(void *abstract_font,
00436                               cairo_operator_t operator,
00437                               cairo_pattern_t *pattern,
00438                               cairo_surface_t *generic_surface,
00439                               int source_x,
00440                               int source_y,
00441                               int dest_x,
00442                               int dest_y,
00443                            unsigned int width,
00444                            unsigned int height,
00445                               const cairo_glyph_t *glyphs,
00446                            int num_glyphs)
00447 {
00448     cairo_atsui_font_t *font = abstract_font;
00449     CGContextRef myBitmapContext;
00450     CGColorSpaceRef colorSpace;
00451     cairo_image_surface_t *destImageSurface;
00452     int i;
00453     void *extra = NULL;
00454 
00455     cairo_rectangle_t rect = {dest_x, dest_y, width, height};
00456     _cairo_surface_acquire_dest_image(generic_surface,
00457                                   &rect,
00458                                   &destImageSurface,
00459                                   &rect,
00460                                   &extra);
00461 
00462     // Create a CGBitmapContext for the dest surface for drawing into
00463     colorSpace = CGColorSpaceCreateDeviceRGB();
00464 
00465     myBitmapContext = CGBitmapContextCreate(destImageSurface->data,
00466                                             destImageSurface->width,
00467                                             destImageSurface->height,
00468                                             destImageSurface->depth / 4,
00469                                             destImageSurface->stride,
00470                                             colorSpace,
00471                                             kCGImageAlphaPremultipliedFirst |
00472                                             kCGBitmapByteOrder32Host);
00473     CGContextTranslateCTM(myBitmapContext, 0, destImageSurface->height);
00474     CGContextScaleCTM(myBitmapContext, 1.0f, -1.0f);
00475 
00476     ATSFontRef atsFont = FMGetATSFontRefFromFont(font->fontID);
00477     CGFontRef cgFont = CGFontCreateWithPlatformFont(&atsFont);
00478 
00479     CGContextSetFont(myBitmapContext, cgFont);
00480 
00481     CGAffineTransform textTransform =
00482         CGAffineTransformMakeWithCairoFontScale(&font->scale);
00483 
00484     textTransform = CGAffineTransformScale(textTransform, 1.0f, -1.0f);
00485 
00486     CGContextSetFontSize(myBitmapContext, 1.0);
00487     CGContextSetTextMatrix(myBitmapContext, textTransform);
00488 
00489     if (pattern->type == CAIRO_PATTERN_SOLID &&
00490        _cairo_pattern_is_opaque_solid(pattern))
00491     {
00492        cairo_solid_pattern_t *solid = (cairo_solid_pattern_t *)pattern;
00493        CGContextSetRGBFillColor(myBitmapContext,
00494                              solid->color.red,
00495                              solid->color.green,
00496                              solid->color.blue, 1.0f);
00497     } else {
00498        CGContextSetRGBFillColor(myBitmapContext, 0.0f, 0.0f, 0.0f, 0.0f);
00499     }
00500 
00501     // TODO - bold and italic text
00502     //
00503     // We could draw the text using ATSUI and get bold, italics
00504     // etc. for free, but ATSUI does a lot of text layout work
00505     // that we don't really need...
00506 
00507 
00508     for (i = 0; i < num_glyphs; i++) {
00509         CGGlyph theGlyph = glyphs[i].index;
00510 
00511         CGContextShowGlyphsAtPoint(myBitmapContext,
00512                                glyphs[i].x,
00513                                    glyphs[i].y,
00514                                    &theGlyph, 1);
00515     }
00516 
00517 
00518     CGColorSpaceRelease(colorSpace);
00519     CGContextRelease(myBitmapContext);
00520 
00521     _cairo_surface_release_dest_image(generic_surface,
00522                                   &rect,
00523                                   destImageSurface,
00524                                   &rect,
00525                                   extra);
00526 
00527     return CAIRO_STATUS_SUCCESS;
00528 }
00529 
00530 
00531 static OSStatus MyATSCubicMoveToCallback(const Float32Point * pt,
00532                                          void *callBackDataPtr)
00533 {
00534     cairo_ATSUI_glyph_path_callback_info_t *info = callBackDataPtr;
00535     double scaledPt[2];
00536     cairo_fixed_t x, y;
00537 
00538     scaledPt[0] = pt->x;
00539     scaledPt[1] = pt->y;
00540 
00541     cairo_matrix_transform_point(&info->scale, &scaledPt[0], &scaledPt[1]);
00542 
00543     x = _cairo_fixed_from_double(scaledPt[0]);
00544     y = _cairo_fixed_from_double(scaledPt[1]);
00545 
00546     _cairo_path_fixed_close_path(info->path);
00547     _cairo_path_fixed_move_to(info->path, x, y);
00548 
00549     return noErr;
00550 }
00551 
00552 
00553 static OSStatus MyATSCubicLineToCallback(const Float32Point * pt,
00554                                          void *callBackDataPtr)
00555 {
00556     cairo_ATSUI_glyph_path_callback_info_t *info = callBackDataPtr;
00557     double scaledPt[2];
00558     cairo_fixed_t x, y;
00559 
00560     scaledPt[0] = pt->x;
00561     scaledPt[1] = pt->y;
00562 
00563     cairo_matrix_transform_point(&info->scale, &scaledPt[0], &scaledPt[1]);
00564 
00565     x = _cairo_fixed_from_double(scaledPt[0]);
00566     y = _cairo_fixed_from_double(scaledPt[1]);
00567 
00568     _cairo_path_fixed_line_to(info->path, x, y);
00569 
00570 
00571     return noErr;
00572 }
00573 
00574 
00575 static OSStatus MyATSCubicCurveToCallback(const Float32Point * pt1,
00576                                           const Float32Point * pt2,
00577                                           const Float32Point * pt3,
00578                                           void *callBackDataPtr)
00579 {
00580     cairo_ATSUI_glyph_path_callback_info_t *info = callBackDataPtr;
00581     double scaledPt[2];
00582     cairo_fixed_t x0, y0;
00583     cairo_fixed_t x1, y1;
00584     cairo_fixed_t x2, y2;
00585 
00586 
00587     scaledPt[0] = pt1->x;
00588     scaledPt[1] = pt1->y;
00589 
00590     cairo_matrix_transform_point(&info->scale, &scaledPt[0], &scaledPt[1]);
00591 
00592     x0 = _cairo_fixed_from_double(scaledPt[0]);
00593     y0 = _cairo_fixed_from_double(scaledPt[1]);
00594 
00595 
00596     scaledPt[0] = pt2->x;
00597     scaledPt[1] = pt2->y;
00598 
00599     cairo_matrix_transform_point(&info->scale, &scaledPt[0], &scaledPt[1]);
00600 
00601     x1 = _cairo_fixed_from_double(scaledPt[0]);
00602     y1 = _cairo_fixed_from_double(scaledPt[1]);
00603 
00604 
00605     scaledPt[0] = pt3->x;
00606     scaledPt[1] = pt3->y;
00607 
00608     cairo_matrix_transform_point(&info->scale, &scaledPt[0], &scaledPt[1]);
00609 
00610     x2 = _cairo_fixed_from_double(scaledPt[0]);
00611     y2 = _cairo_fixed_from_double(scaledPt[1]);
00612 
00613 
00614     _cairo_path_fixed_curve_to(info->path, x0, y0, x1, y1, x2, y2);
00615 
00616 
00617     return noErr;
00618 }
00619 
00620 
00621 static OSStatus MyCubicClosePathProc(void *callBackDataPtr)
00622 {
00623     cairo_ATSUI_glyph_path_callback_info_t *info = callBackDataPtr;
00624 
00625 
00626     _cairo_path_fixed_close_path(info->path);
00627 
00628 
00629     return noErr;
00630 }
00631 
00632 
00633 static cairo_status_t
00634 _cairo_atsui_font_glyph_path(void *abstract_font,
00635                              cairo_glyph_t *glyphs, int num_glyphs,
00636                           cairo_path_fixed_t *path)
00637 {
00638     int i;
00639     cairo_atsui_font_t *font = abstract_font;
00640     OSStatus err;
00641     cairo_ATSUI_glyph_path_callback_info_t info;
00642 
00643 
00644     static ATSCubicMoveToUPP moveProc = NULL;
00645     static ATSCubicLineToUPP lineProc = NULL;
00646     static ATSCubicCurveToUPP curveProc = NULL;
00647     static ATSCubicClosePathUPP closePathProc = NULL;
00648 
00649 
00650     if (moveProc == NULL) {
00651         moveProc = NewATSCubicMoveToUPP(MyATSCubicMoveToCallback);
00652         lineProc = NewATSCubicLineToUPP(MyATSCubicLineToCallback);
00653         curveProc = NewATSCubicCurveToUPP(MyATSCubicCurveToCallback);
00654         closePathProc = NewATSCubicClosePathUPP(MyCubicClosePathProc);
00655     }
00656 
00657 
00658     info.path = path;
00659 
00660 
00661     for (i = 0; i < num_glyphs; i++) {
00662         GlyphID theGlyph = glyphs[i].index;
00663 
00664        info.scale = font->scale;
00665        info.scale.x0 = glyphs[i].x;
00666        info.scale.y0 = glyphs[i].y;
00667 
00668         err = ATSUGlyphGetCubicPaths(font->unscaled_style,
00669                                      theGlyph,
00670                                      moveProc,
00671                                      lineProc,
00672                                      curveProc,
00673                                      closePathProc, (void *) &info, &err);
00674     }
00675 
00676     return CAIRO_STATUS_SUCCESS;
00677 }
00678 
00679 const cairo_scaled_font_backend_t cairo_atsui_scaled_font_backend = {
00680     _cairo_atsui_font_create_toy,
00681     _cairo_atsui_font_fini,
00682     _cairo_atsui_font_font_extents,
00683     _cairo_atsui_font_text_to_glyphs,
00684     _cairo_atsui_font_glyph_extents,
00685     _cairo_atsui_font_glyph_bbox,
00686     _cairo_atsui_font_show_glyphs,
00687     _cairo_atsui_font_glyph_path,
00688     _cairo_atsui_font_get_glyph_cache_key,
00689 };
00690