2005-01-16 08:35:14 +00:00
|
|
|
/* cairo - a vector graphics library with display and print output
|
|
|
|
|
*
|
2005-02-22 11:32:02 +00:00
|
|
|
* Copyright © 2004 Calum Robinson
|
2005-01-16 08:35:14 +00:00
|
|
|
*
|
|
|
|
|
* 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):
|
2005-03-29 11:24:10 +00:00
|
|
|
* Calum Robinson <calumr@mac.com>
|
2005-01-16 08:35:14 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
#include <math.h>
|
2005-01-20 20:36:25 +00:00
|
|
|
#include "cairo-atsui.h"
|
2005-01-16 08:35:14 +00:00
|
|
|
#include "cairoint.h"
|
2005-05-11 15:39:26 +00:00
|
|
|
#include "cairo.h"
|
2005-06-21 09:54:58 +00:00
|
|
|
|
2005-09-30 08:31:36 +00:00
|
|
|
typedef struct _cairo_atsui_font_face cairo_atsui_font_face_t;
|
|
|
|
|
typedef struct _cairo_atsui_font cairo_atsui_font_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 {
|
2005-05-11 15:39:26 +00:00
|
|
|
cairo_scaled_font_t base;
|
2005-01-16 08:35:14 +00:00
|
|
|
|
2005-05-11 15:39:26 +00:00
|
|
|
cairo_matrix_t scale;
|
2005-03-29 11:24:10 +00:00
|
|
|
ATSUStyle style;
|
|
|
|
|
ATSUStyle unscaled_style;
|
|
|
|
|
ATSUFontID fontID;
|
2005-09-30 08:31:36 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
struct _cairo_atsui_font_face {
|
|
|
|
|
cairo_font_face_t base;
|
|
|
|
|
ATSUFontID font_id;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
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_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);
|
|
|
|
|
err = ATSUSetAttributes(style,
|
|
|
|
|
sizeof(styleTags) / sizeof(styleTags[0]),
|
|
|
|
|
styleTags, styleSizes, styleValues);
|
|
|
|
|
|
|
|
|
|
return _cairo_atsui_font_create_scaled (&font_face->base, font_face->font_id, style,
|
|
|
|
|
font_matrix, ctm, options, font);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static const cairo_font_face_backend_t _cairo_atsui_font_face_backend = {
|
|
|
|
|
_cairo_atsui_font_face_destroy,
|
|
|
|
|
_cairo_atsui_font_face_scaled_font_create
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
cairo_public cairo_font_face_t *
|
|
|
|
|
cairo_atsui_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;
|
|
|
|
|
}
|
2005-01-16 08:35:14 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2005-03-29 11:24:10 +00:00
|
|
|
static CGAffineTransform
|
2005-05-11 15:39:26 +00:00
|
|
|
CGAffineTransformMakeWithCairoFontScale(cairo_matrix_t *scale)
|
2005-03-29 11:24:10 +00:00
|
|
|
{
|
2005-05-11 15:39:26 +00:00
|
|
|
return CGAffineTransformMake(scale->xx, scale->yx,
|
|
|
|
|
scale->xy, scale->yy,
|
2005-03-29 11:24:10 +00:00
|
|
|
0, 0);
|
|
|
|
|
}
|
2005-01-16 08:35:14 +00:00
|
|
|
|
2005-03-29 11:24:10 +00:00
|
|
|
static ATSUStyle
|
2005-05-11 15:39:26 +00:00
|
|
|
CreateSizedCopyOfStyle(ATSUStyle inStyle, cairo_matrix_t *scale)
|
2005-03-29 11:24:10 +00:00
|
|
|
{
|
|
|
|
|
ATSUStyle style;
|
|
|
|
|
OSStatus err;
|
2005-01-16 08:35:14 +00:00
|
|
|
|
2005-03-29 11:24:10 +00:00
|
|
|
// Set the style's size
|
|
|
|
|
CGAffineTransform theTransform =
|
2005-05-11 15:39:26 +00:00
|
|
|
CGAffineTransformMakeWithCairoFontScale(scale);
|
2005-03-29 11:24:10 +00:00
|
|
|
Fixed theSize =
|
|
|
|
|
FloatToFixed(CGSizeApplyAffineTransform
|
|
|
|
|
(CGSizeMake(1.0, 1.0), theTransform).height);
|
|
|
|
|
const ATSUAttributeTag theFontStyleTags[] = { kATSUSizeTag };
|
|
|
|
|
const ByteCount theFontStyleSizes[] = { sizeof(Fixed) };
|
|
|
|
|
ATSUAttributeValuePtr theFontStyleValues[] = { &theSize };
|
2005-01-16 08:35:14 +00:00
|
|
|
|
2005-03-29 11:24:10 +00:00
|
|
|
err = ATSUCreateAndCopyStyle(inStyle, &style);
|
|
|
|
|
|
|
|
|
|
err = ATSUSetAttributes(style,
|
|
|
|
|
sizeof(theFontStyleTags) /
|
|
|
|
|
sizeof(ATSUAttributeTag), theFontStyleTags,
|
|
|
|
|
theFontStyleSizes, theFontStyleValues);
|
2005-01-16 08:35:14 +00:00
|
|
|
|
2005-03-29 11:24:10 +00:00
|
|
|
return style;
|
|
|
|
|
}
|
2005-01-16 08:35:14 +00:00
|
|
|
|
2005-09-30 08:31:36 +00:00
|
|
|
static cairo_status_t
|
|
|
|
|
_cairo_atsui_font_set_metrics (cairo_atsui_font_t *font)
|
|
|
|
|
{
|
|
|
|
|
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 = metrics.capHeight;
|
|
|
|
|
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;
|
|
|
|
|
|
|
|
|
|
_cairo_scaled_font_set_metrics (&font->base, &extents);
|
|
|
|
|
|
|
|
|
|
return CAIRO_STATUS_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 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;
|
|
|
|
|
cairo_matrix_t scale;
|
|
|
|
|
OSStatus err;
|
|
|
|
|
cairo_status_t status;
|
|
|
|
|
|
|
|
|
|
font = malloc(sizeof(cairo_atsui_font_t));
|
|
|
|
|
|
|
|
|
|
_cairo_scaled_font_init(&font->base, font_face, font_matrix, ctm, options,
|
|
|
|
|
&cairo_atsui_scaled_font_backend);
|
|
|
|
|
|
|
|
|
|
cairo_matrix_multiply(&scale, font_matrix, ctm);
|
|
|
|
|
font->style = CreateSizedCopyOfStyle(style, &scale);
|
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
|
|
|
|
|
font->unscaled_style = style;
|
|
|
|
|
|
|
|
|
|
font->fontID = font_id;
|
|
|
|
|
font->scale = scale;
|
|
|
|
|
|
|
|
|
|
*font_out = &font->base;
|
|
|
|
|
|
|
|
|
|
status = _cairo_atsui_font_set_metrics (font);
|
|
|
|
|
if (status) {
|
|
|
|
|
cairo_scaled_font_destroy (&font->base);
|
|
|
|
|
return status;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return CAIRO_STATUS_SUCCESS;
|
|
|
|
|
}
|
2005-01-16 08:35:14 +00:00
|
|
|
|
2005-03-29 11:24:10 +00:00
|
|
|
static cairo_status_t
|
2005-08-11 06:35:20 +00:00
|
|
|
_cairo_atsui_font_create_toy(cairo_toy_font_face_t *toy_face,
|
2005-08-05 16:44:20 +00:00
|
|
|
const cairo_matrix_t *font_matrix,
|
|
|
|
|
const cairo_matrix_t *ctm,
|
|
|
|
|
const cairo_font_options_t *options,
|
|
|
|
|
cairo_scaled_font_t **font_out)
|
2005-03-29 11:24:10 +00:00
|
|
|
{
|
|
|
|
|
ATSUStyle style;
|
|
|
|
|
ATSUFontID fontID;
|
|
|
|
|
OSStatus err;
|
|
|
|
|
Boolean isItalic, isBold;
|
2005-08-05 16:44:20 +00:00
|
|
|
const char *family = toy_face->family;
|
2005-03-29 11:24:10 +00:00
|
|
|
|
|
|
|
|
err = ATSUCreateStyle(&style);
|
|
|
|
|
|
2005-08-05 16:44:20 +00:00
|
|
|
switch (toy_face->weight) {
|
2005-03-29 11:24:10 +00:00
|
|
|
case CAIRO_FONT_WEIGHT_BOLD:
|
|
|
|
|
isBold = true;
|
|
|
|
|
break;
|
|
|
|
|
case CAIRO_FONT_WEIGHT_NORMAL:
|
|
|
|
|
default:
|
|
|
|
|
isBold = false;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
2005-08-05 16:44:20 +00:00
|
|
|
switch (toy_face->slant) {
|
2005-03-29 11:24:10 +00:00
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
err = ATSUFindFontFromName(family, strlen(family),
|
|
|
|
|
kFontFamilyName,
|
|
|
|
|
kFontNoPlatformCode,
|
|
|
|
|
kFontRomanScript,
|
|
|
|
|
kFontNoLanguageCode, &fontID);
|
|
|
|
|
|
|
|
|
|
if (err != noErr) {
|
|
|
|
|
// couldn't get the font - remap css names and try again
|
|
|
|
|
|
|
|
|
|
if (!strcmp(family, "serif"))
|
|
|
|
|
family = "Times";
|
|
|
|
|
else if (!strcmp(family, "sans-serif"))
|
|
|
|
|
family = "Helvetica";
|
|
|
|
|
else if (!strcmp(family, "cursive"))
|
|
|
|
|
family = "Apple Chancery";
|
|
|
|
|
else if (!strcmp(family, "fantasy"))
|
|
|
|
|
family = "Gadget";
|
|
|
|
|
else if (!strcmp(family, "monospace"))
|
|
|
|
|
family = "Courier";
|
|
|
|
|
else // anything else - return error instead?
|
|
|
|
|
family = "Courier";
|
|
|
|
|
|
|
|
|
|
err = ATSUFindFontFromName(family, strlen(family),
|
|
|
|
|
kFontFamilyName,
|
|
|
|
|
kFontNoPlatformCode,
|
|
|
|
|
kFontRomanScript,
|
|
|
|
|
kFontNoLanguageCode, &fontID);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ATSUAttributeTag styleTags[] =
|
|
|
|
|
{ kATSUQDItalicTag, kATSUQDBoldfaceTag, kATSUFontTag };
|
|
|
|
|
ATSUAttributeValuePtr styleValues[] = { &isItalic, &isBold, &fontID };
|
|
|
|
|
ByteCount styleSizes[] =
|
|
|
|
|
{ sizeof(Boolean), sizeof(Boolean), sizeof(ATSUFontID) };
|
|
|
|
|
|
|
|
|
|
err = ATSUSetAttributes(style,
|
|
|
|
|
sizeof(styleTags) / sizeof(styleTags[0]),
|
|
|
|
|
styleTags, styleSizes, styleValues);
|
|
|
|
|
|
|
|
|
|
|
2005-09-30 08:31:36 +00:00
|
|
|
return _cairo_atsui_font_create_scaled (&toy_face->base, fontID, style,
|
|
|
|
|
font_matrix, ctm, options, font_out);
|
2005-03-29 11:24:10 +00:00
|
|
|
}
|
2005-01-16 08:35:14 +00:00
|
|
|
|
2005-03-29 11:24:10 +00:00
|
|
|
static void
|
2005-08-05 17:00:38 +00:00
|
|
|
_cairo_atsui_font_fini(void *abstract_font)
|
2005-03-29 11:24:10 +00:00
|
|
|
{
|
|
|
|
|
cairo_atsui_font_t *font = abstract_font;
|
2005-01-16 08:35:14 +00:00
|
|
|
|
2005-03-29 11:24:10 +00:00
|
|
|
if (font == NULL)
|
|
|
|
|
return;
|
2005-01-16 08:35:14 +00:00
|
|
|
|
2005-03-29 11:24:10 +00:00
|
|
|
if (font->style)
|
|
|
|
|
ATSUDisposeStyle(font->style);
|
|
|
|
|
if (font->unscaled_style)
|
|
|
|
|
ATSUDisposeStyle(font->unscaled_style);
|
|
|
|
|
}
|
2005-01-16 08:35:14 +00:00
|
|
|
|
2005-09-30 08:31:36 +00:00
|
|
|
static cairo_status_t
|
|
|
|
|
_cairo_atsui_font_init_glyph_metrics (cairo_atsui_font_t *font,
|
|
|
|
|
cairo_scaled_glyph_t *scaled_glyph)
|
2005-01-16 08:35:14 +00:00
|
|
|
{
|
2005-09-30 08:31:36 +00:00
|
|
|
cairo_text_extents_t extents;
|
|
|
|
|
OSStatus err;
|
|
|
|
|
GlyphID theGlyph = _cairo_scaled_glyph_index (scaled_glyph);
|
|
|
|
|
ATSGlyphIdealMetrics metricsH, metricsV;
|
|
|
|
|
ATSUStyle style;
|
|
|
|
|
ATSUVerticalCharacterType verticalType = kATSUStronglyVertical;
|
|
|
|
|
const ATSUAttributeTag theTag[] = { kATSUVerticalCharacterTag };
|
|
|
|
|
const ByteCount theSizes[] = { sizeof(verticalType) };
|
|
|
|
|
ATSUAttributeValuePtr theValues[] = { &verticalType };
|
|
|
|
|
|
|
|
|
|
ATSUCreateAndCopyStyle(font->unscaled_style, &style);
|
|
|
|
|
|
|
|
|
|
err = ATSUGlyphGetIdealMetrics(style,
|
|
|
|
|
1, &theGlyph, 0, &metricsH);
|
|
|
|
|
err = ATSUSetAttributes(style, 1, theTag, theSizes, theValues);
|
|
|
|
|
err = ATSUGlyphGetIdealMetrics(style,
|
|
|
|
|
1, &theGlyph, 0, &metricsV);
|
|
|
|
|
|
|
|
|
|
extents.x_bearing = metricsH.sideBearing.x;
|
|
|
|
|
extents.y_bearing = metricsV.advance.y;
|
|
|
|
|
extents.width =
|
|
|
|
|
metricsH.advance.x - metricsH.sideBearing.x - metricsH.otherSideBearing.x;
|
|
|
|
|
extents.height =
|
|
|
|
|
-metricsV.advance.y - metricsV.sideBearing.y - metricsV.otherSideBearing.y;
|
|
|
|
|
extents.x_advance = metricsH.advance.x;
|
|
|
|
|
extents.y_advance = 0;
|
|
|
|
|
|
|
|
|
|
_cairo_scaled_glyph_set_metrics (scaled_glyph,
|
|
|
|
|
&font->base,
|
|
|
|
|
&extents);
|
|
|
|
|
|
|
|
|
|
return CAIRO_STATUS_SUCCESS;
|
2005-01-16 08:35:14 +00:00
|
|
|
}
|
|
|
|
|
|
2005-09-30 08:31:36 +00:00
|
|
|
static OSStatus
|
|
|
|
|
_move_to (const Float32Point *point,
|
|
|
|
|
void *callback_data)
|
2005-03-29 11:24:10 +00:00
|
|
|
{
|
2005-09-30 08:31:36 +00:00
|
|
|
cairo_path_fixed_t *path = callback_data;
|
2005-06-28 11:52:42 +00:00
|
|
|
|
2005-09-30 08:31:36 +00:00
|
|
|
_cairo_path_fixed_close_path (path);
|
|
|
|
|
_cairo_path_fixed_move_to (path,
|
|
|
|
|
_cairo_fixed_from_double(point->x),
|
|
|
|
|
_cairo_fixed_from_double(point->y));
|
2005-01-16 08:35:14 +00:00
|
|
|
|
2005-09-30 08:31:36 +00:00
|
|
|
return noErr;
|
|
|
|
|
}
|
2005-03-29 11:24:10 +00:00
|
|
|
|
2005-09-30 08:31:36 +00:00
|
|
|
static OSStatus
|
|
|
|
|
_line_to (const Float32Point *point,
|
|
|
|
|
void *callback_data)
|
|
|
|
|
{
|
|
|
|
|
cairo_path_fixed_t *path = callback_data;
|
2005-03-29 11:24:10 +00:00
|
|
|
|
2005-09-30 08:31:36 +00:00
|
|
|
_cairo_path_fixed_line_to (path,
|
|
|
|
|
_cairo_fixed_from_double(point->x),
|
|
|
|
|
_cairo_fixed_from_double(point->y));
|
|
|
|
|
|
|
|
|
|
return noErr;
|
|
|
|
|
}
|
2005-03-29 11:24:10 +00:00
|
|
|
|
2005-09-30 08:31:36 +00:00
|
|
|
static OSStatus
|
|
|
|
|
_curve_to (const Float32Point *point1,
|
|
|
|
|
const Float32Point *point2,
|
|
|
|
|
const Float32Point *point3,
|
|
|
|
|
void *callback_data)
|
|
|
|
|
{
|
|
|
|
|
cairo_path_fixed_t *path = callback_data;
|
|
|
|
|
|
|
|
|
|
_cairo_path_fixed_curve_to (path,
|
|
|
|
|
_cairo_fixed_from_double(point1->x),
|
|
|
|
|
_cairo_fixed_from_double(point1->y),
|
|
|
|
|
_cairo_fixed_from_double(point2->x),
|
|
|
|
|
_cairo_fixed_from_double(point2->y),
|
|
|
|
|
_cairo_fixed_from_double(point3->x),
|
|
|
|
|
_cairo_fixed_from_double(point3->y));
|
|
|
|
|
|
|
|
|
|
return noErr;
|
|
|
|
|
}
|
2005-03-29 11:24:10 +00:00
|
|
|
|
2005-09-30 08:31:36 +00:00
|
|
|
static OSStatus
|
|
|
|
|
_close_path (void *callback_data)
|
2005-03-29 11:24:10 +00:00
|
|
|
|
2005-09-30 08:31:36 +00:00
|
|
|
{
|
|
|
|
|
cairo_path_fixed_t *path = callback_data;
|
2005-03-29 11:24:10 +00:00
|
|
|
|
2005-09-30 08:31:36 +00:00
|
|
|
_cairo_path_fixed_close_path (path);
|
2005-03-29 11:24:10 +00:00
|
|
|
|
2005-09-30 08:31:36 +00:00
|
|
|
return noErr;
|
2005-01-16 08:35:14 +00:00
|
|
|
}
|
|
|
|
|
|
2005-09-30 08:31:36 +00:00
|
|
|
static cairo_status_t
|
|
|
|
|
_cairo_atsui_scaled_font_init_glyph_path (cairo_atsui_font_t *scaled_font,
|
|
|
|
|
cairo_scaled_glyph_t *scaled_glyph)
|
2005-01-16 08:35:14 +00:00
|
|
|
{
|
2005-09-30 08:31:36 +00:00
|
|
|
static ATSCubicMoveToUPP moveProc = NULL;
|
|
|
|
|
static ATSCubicLineToUPP lineProc = NULL;
|
|
|
|
|
static ATSCubicCurveToUPP curveProc = NULL;
|
|
|
|
|
static ATSCubicClosePathUPP closePathProc = NULL;
|
2005-03-29 11:24:10 +00:00
|
|
|
OSStatus err;
|
2005-09-30 08:31:36 +00:00
|
|
|
cairo_path_fixed_t *path;
|
2005-03-29 11:24:10 +00:00
|
|
|
|
2005-09-30 08:31:36 +00:00
|
|
|
path = _cairo_path_fixed_create ();
|
|
|
|
|
if (!path)
|
|
|
|
|
return CAIRO_STATUS_NO_MEMORY;
|
2005-03-29 11:24:10 +00:00
|
|
|
|
2005-09-30 08:31:36 +00:00
|
|
|
if (moveProc == NULL) {
|
|
|
|
|
moveProc = NewATSCubicMoveToUPP(_move_to);
|
|
|
|
|
lineProc = NewATSCubicLineToUPP(_line_to);
|
|
|
|
|
curveProc = NewATSCubicCurveToUPP(_curve_to);
|
|
|
|
|
closePathProc = NewATSCubicClosePathUPP(_close_path);
|
2005-03-29 11:24:10 +00:00
|
|
|
}
|
|
|
|
|
|
2005-09-30 08:31:36 +00:00
|
|
|
err = ATSUGlyphGetCubicPaths(scaled_font->style,
|
|
|
|
|
_cairo_scaled_glyph_index (scaled_glyph),
|
|
|
|
|
moveProc,
|
|
|
|
|
lineProc,
|
|
|
|
|
curveProc,
|
|
|
|
|
closePathProc, (void *)path, &err);
|
2005-03-29 11:24:10 +00:00
|
|
|
|
2005-09-30 08:31:36 +00:00
|
|
|
_cairo_scaled_glyph_set_path (scaled_glyph, &scaled_font->base, path);
|
2005-01-16 08:35:14 +00:00
|
|
|
|
2005-09-30 08:31:36 +00:00
|
|
|
return CAIRO_STATUS_SUCCESS;
|
|
|
|
|
}
|
2005-01-16 08:35:14 +00:00
|
|
|
|
2005-03-29 11:24:10 +00:00
|
|
|
static cairo_status_t
|
2005-09-30 08:31:36 +00:00
|
|
|
_cairo_atsui_font_scaled_glyph_init (void *abstract_font,
|
|
|
|
|
cairo_scaled_glyph_t *scaled_glyph,
|
|
|
|
|
cairo_scaled_glyph_info_t info)
|
2005-01-16 08:35:14 +00:00
|
|
|
{
|
2005-09-30 08:31:36 +00:00
|
|
|
cairo_atsui_font_t *scaled_font = abstract_font;
|
|
|
|
|
cairo_status_t status;
|
2005-03-29 11:24:10 +00:00
|
|
|
|
2005-09-30 08:31:36 +00:00
|
|
|
if ((info & CAIRO_SCALED_GLYPH_INFO_METRICS) != 0) {
|
|
|
|
|
status = _cairo_atsui_font_init_glyph_metrics (scaled_font, scaled_glyph);
|
|
|
|
|
if (status)
|
|
|
|
|
return status;
|
|
|
|
|
}
|
2005-03-29 11:24:10 +00:00
|
|
|
|
2005-09-30 08:31:36 +00:00
|
|
|
if ((info & CAIRO_SCALED_GLYPH_INFO_PATH) != 0) {
|
|
|
|
|
status = _cairo_atsui_scaled_font_init_glyph_path (scaled_font, scaled_glyph);
|
|
|
|
|
if (status)
|
|
|
|
|
return status;
|
|
|
|
|
}
|
2005-03-29 11:24:10 +00:00
|
|
|
|
|
|
|
|
return CAIRO_STATUS_SUCCESS;
|
2005-01-16 08:35:14 +00:00
|
|
|
}
|
|
|
|
|
|
2005-09-30 08:31:36 +00:00
|
|
|
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)
|
2005-01-16 08:35:14 +00:00
|
|
|
{
|
2005-09-30 08:31:36 +00:00
|
|
|
cairo_status_t status = CAIRO_STATUS_SUCCESS;
|
|
|
|
|
uint16_t *utf16;
|
|
|
|
|
int n16;
|
|
|
|
|
OSStatus err;
|
|
|
|
|
ATSUTextLayout textLayout;
|
|
|
|
|
ATSLayoutRecord *layoutRecords;
|
2005-03-29 11:24:10 +00:00
|
|
|
cairo_atsui_font_t *font = abstract_font;
|
2005-09-30 08:31:36 +00:00
|
|
|
ItemCount glyphCount;
|
2005-03-29 11:24:10 +00:00
|
|
|
int i;
|
|
|
|
|
|
2005-09-30 08:31:36 +00:00
|
|
|
status = _cairo_utf8_to_utf16 ((unsigned char *)utf8, -1, &utf16, &n16);
|
|
|
|
|
if (status)
|
|
|
|
|
return status;
|
2005-03-29 11:24:10 +00:00
|
|
|
|
2005-09-30 08:31:36 +00:00
|
|
|
err = ATSUCreateTextLayout(&textLayout);
|
2005-03-29 11:24:10 +00:00
|
|
|
|
2005-09-30 08:31:36 +00:00
|
|
|
err = ATSUSetTextPointerLocation(textLayout, utf16, 0, n16, n16);
|
2005-03-29 11:24:10 +00:00
|
|
|
|
2005-09-30 08:31:36 +00:00
|
|
|
// Set the style for all of the text
|
|
|
|
|
err = ATSUSetRunStyle(textLayout,
|
|
|
|
|
font->style, kATSUFromTextBeginning, kATSUToTextEnd);
|
2005-03-29 11:24:10 +00:00
|
|
|
|
2005-09-30 08:31:36 +00:00
|
|
|
err = ATSUDirectGetLayoutDataArrayPtrFromTextLayout(textLayout,
|
|
|
|
|
0,
|
|
|
|
|
kATSUDirectDataLayoutRecordATSLayoutRecordCurrent,
|
|
|
|
|
(void *)&layoutRecords,
|
|
|
|
|
&glyphCount);
|
2005-03-29 11:24:10 +00:00
|
|
|
|
2005-09-30 08:31:36 +00:00
|
|
|
*num_glyphs = glyphCount - 1;
|
|
|
|
|
*glyphs =
|
|
|
|
|
(cairo_glyph_t *) malloc(*num_glyphs * (sizeof (cairo_glyph_t)));
|
|
|
|
|
if (*glyphs == NULL) {
|
|
|
|
|
return CAIRO_STATUS_NO_MEMORY;
|
|
|
|
|
}
|
2005-03-29 11:24:10 +00:00
|
|
|
|
2005-09-30 08:31:36 +00:00
|
|
|
for (i = 0; i < *num_glyphs; i++) {
|
|
|
|
|
(*glyphs)[i].index = layoutRecords[i].glyphID;
|
|
|
|
|
(*glyphs)[i].x = x + FixedToFloat(layoutRecords[i].realPos);
|
|
|
|
|
(*glyphs)[i].y = y;
|
2005-03-29 11:24:10 +00:00
|
|
|
}
|
|
|
|
|
|
2005-09-30 08:31:36 +00:00
|
|
|
free (utf16);
|
|
|
|
|
|
|
|
|
|
ATSUDirectReleaseLayoutDataArrayPtr(NULL,
|
|
|
|
|
kATSUDirectDataLayoutRecordATSLayoutRecordCurrent,
|
|
|
|
|
(void *) &layoutRecords);
|
|
|
|
|
ATSUDisposeTextLayout(textLayout);
|
|
|
|
|
|
2005-03-29 11:24:10 +00:00
|
|
|
return CAIRO_STATUS_SUCCESS;
|
2005-01-16 08:35:14 +00:00
|
|
|
}
|
|
|
|
|
|
2005-09-30 08:31:36 +00:00
|
|
|
static cairo_int_status_t
|
2005-11-01 16:40:37 +00:00
|
|
|
_cairo_atsui_font_old_show_glyphs (void *abstract_font,
|
|
|
|
|
cairo_operator_t operator,
|
|
|
|
|
cairo_pattern_t *pattern,
|
|
|
|
|
cairo_surface_t *generic_surface,
|
|
|
|
|
int source_x,
|
|
|
|
|
int source_y,
|
|
|
|
|
int dest_x,
|
|
|
|
|
int dest_y,
|
|
|
|
|
unsigned int width,
|
|
|
|
|
unsigned int height,
|
|
|
|
|
const cairo_glyph_t *glyphs,
|
|
|
|
|
int num_glyphs)
|
2005-01-16 08:35:14 +00:00
|
|
|
{
|
2005-03-29 11:24:10 +00:00
|
|
|
cairo_atsui_font_t *font = abstract_font;
|
|
|
|
|
CGContextRef myBitmapContext;
|
|
|
|
|
CGColorSpaceRef colorSpace;
|
|
|
|
|
cairo_image_surface_t *destImageSurface;
|
|
|
|
|
int i;
|
2005-09-07 08:38:43 +00:00
|
|
|
void *extra = NULL;
|
2005-03-29 11:24:10 +00:00
|
|
|
|
|
|
|
|
cairo_rectangle_t rect = {dest_x, dest_y, width, height};
|
|
|
|
|
_cairo_surface_acquire_dest_image(generic_surface,
|
|
|
|
|
&rect,
|
|
|
|
|
&destImageSurface,
|
|
|
|
|
&rect,
|
2005-09-07 08:38:43 +00:00
|
|
|
&extra);
|
2005-03-29 11:24:10 +00:00
|
|
|
|
|
|
|
|
// Create a CGBitmapContext for the dest surface for drawing into
|
2005-01-16 08:35:14 +00:00
|
|
|
colorSpace = CGColorSpaceCreateDeviceRGB();
|
|
|
|
|
|
2005-03-29 11:24:10 +00:00
|
|
|
myBitmapContext = CGBitmapContextCreate(destImageSurface->data,
|
|
|
|
|
destImageSurface->width,
|
|
|
|
|
destImageSurface->height,
|
|
|
|
|
destImageSurface->depth / 4,
|
|
|
|
|
destImageSurface->stride,
|
|
|
|
|
colorSpace,
|
|
|
|
|
kCGImageAlphaPremultipliedFirst);
|
|
|
|
|
CGContextTranslateCTM(myBitmapContext, 0, destImageSurface->height);
|
|
|
|
|
CGContextScaleCTM(myBitmapContext, 1.0f, -1.0f);
|
|
|
|
|
|
|
|
|
|
ATSFontRef atsFont = FMGetATSFontRefFromFont(font->fontID);
|
|
|
|
|
CGFontRef cgFont = CGFontCreateWithPlatformFont(&atsFont);
|
2005-01-16 08:35:14 +00:00
|
|
|
|
2005-03-29 11:24:10 +00:00
|
|
|
CGContextSetFont(myBitmapContext, cgFont);
|
2005-01-16 08:35:14 +00:00
|
|
|
|
2005-03-29 11:24:10 +00:00
|
|
|
CGAffineTransform textTransform =
|
2005-05-11 15:39:26 +00:00
|
|
|
CGAffineTransformMakeWithCairoFontScale(&font->scale);
|
2005-01-16 08:35:14 +00:00
|
|
|
|
2005-03-29 11:24:10 +00:00
|
|
|
textTransform = CGAffineTransformScale(textTransform, 1.0f, -1.0f);
|
|
|
|
|
|
|
|
|
|
CGContextSetFontSize(myBitmapContext, 1.0);
|
|
|
|
|
CGContextSetTextMatrix(myBitmapContext, textTransform);
|
|
|
|
|
|
|
|
|
|
if (pattern->type == CAIRO_PATTERN_SOLID &&
|
2005-06-03 14:51:57 +00:00
|
|
|
_cairo_pattern_is_opaque_solid(pattern))
|
|
|
|
|
{
|
2005-03-29 11:24:10 +00:00
|
|
|
cairo_solid_pattern_t *solid = (cairo_solid_pattern_t *)pattern;
|
|
|
|
|
CGContextSetRGBFillColor(myBitmapContext,
|
2005-05-11 15:39:26 +00:00
|
|
|
solid->color.red,
|
|
|
|
|
solid->color.green,
|
|
|
|
|
solid->color.blue, 1.0f);
|
2005-06-03 14:51:57 +00:00
|
|
|
} else {
|
2005-03-29 11:24:10 +00:00
|
|
|
CGContextSetRGBFillColor(myBitmapContext, 0.0f, 0.0f, 0.0f, 0.0f);
|
2005-06-03 14:51:57 +00:00
|
|
|
}
|
2005-03-29 11:24:10 +00:00
|
|
|
|
|
|
|
|
// TODO - bold and italic text
|
|
|
|
|
//
|
|
|
|
|
// We could draw the text using ATSUI and get bold, italics
|
|
|
|
|
// etc. for free, but ATSUI does a lot of text layout work
|
|
|
|
|
// that we don't really need...
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < num_glyphs; i++) {
|
|
|
|
|
CGGlyph theGlyph = glyphs[i].index;
|
2005-09-30 08:31:36 +00:00
|
|
|
|
2005-03-29 11:24:10 +00:00
|
|
|
CGContextShowGlyphsAtPoint(myBitmapContext,
|
|
|
|
|
glyphs[i].x,
|
|
|
|
|
glyphs[i].y,
|
|
|
|
|
&theGlyph, 1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
CGColorSpaceRelease(colorSpace);
|
|
|
|
|
CGContextRelease(myBitmapContext);
|
|
|
|
|
|
|
|
|
|
_cairo_surface_release_dest_image(generic_surface,
|
|
|
|
|
&rect,
|
|
|
|
|
destImageSurface,
|
|
|
|
|
&rect,
|
2005-09-07 09:07:13 +00:00
|
|
|
extra);
|
2005-03-29 11:24:10 +00:00
|
|
|
|
|
|
|
|
return CAIRO_STATUS_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
2005-05-11 15:39:26 +00:00
|
|
|
const cairo_scaled_font_backend_t cairo_atsui_scaled_font_backend = {
|
2005-08-05 16:44:20 +00:00
|
|
|
_cairo_atsui_font_create_toy,
|
2005-08-05 17:00:38 +00:00
|
|
|
_cairo_atsui_font_fini,
|
2005-09-30 08:31:36 +00:00
|
|
|
_cairo_atsui_font_scaled_glyph_init,
|
2005-03-29 11:24:10 +00:00
|
|
|
_cairo_atsui_font_text_to_glyphs,
|
2005-09-30 08:31:36 +00:00
|
|
|
NULL, /* ucs4_to_index */
|
2005-11-01 16:40:37 +00:00
|
|
|
_cairo_atsui_font_old_show_glyphs,
|
2005-01-16 08:35:14 +00:00
|
|
|
};
|
2005-03-29 11:24:10 +00:00
|
|
|
|