📄 cairo-atsui-font.c
字号:
/* 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 <stdlib.h>#include <math.h>#include "cairo-atsui.h"#include "cairoint.h"#include "cairo.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. */#ifndef kCGBitmapByteOrder32Host#define kCGBitmapByteOrder32Host 0#endiftypedef 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 { cairo_scaled_font_t base; ATSUStyle style; ATSUStyle unscaled_style; ATSUFontID fontID;};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_FONT_TYPE_ATSUI, _cairo_atsui_font_face_destroy, _cairo_atsui_font_face_scaled_font_create};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;}static CGAffineTransformCGAffineTransformMakeWithCairoFontScale(const cairo_matrix_t *scale){ return CGAffineTransformMake(scale->xx, scale->yx, scale->xy, scale->yy, 0, 0);}static ATSUStyleCreateSizedCopyOfStyle(ATSUStyle inStyle, const cairo_matrix_t *scale){ ATSUStyle style; OSStatus err; /* Set the style's size */ CGAffineTransform theTransform = CGAffineTransformMakeWithCairoFontScale(scale); Fixed theSize = FloatToFixed(CGSizeApplyAffineTransform (CGSizeMake(1.0, 1.0), theTransform).height); const ATSUAttributeTag theFontStyleTags[] = { kATSUSizeTag }; const ByteCount theFontStyleSizes[] = { sizeof(Fixed) }; ATSUAttributeValuePtr theFontStyleValues[] = { &theSize }; err = ATSUCreateAndCopyStyle(inStyle, &style); err = ATSUSetAttributes(style, sizeof(theFontStyleTags) / sizeof(ATSUAttributeTag), theFontStyleTags, theFontStyleSizes, theFontStyleValues); return style;}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; OSStatus err; cairo_status_t status; font = malloc(sizeof(cairo_atsui_font_t)); if (font == NULL) return CAIRO_STATUS_NO_MEMORY; _cairo_scaled_font_init(&font->base, font_face, font_matrix, ctm, options, &cairo_atsui_scaled_font_backend); font->style = CreateSizedCopyOfStyle(style, &font->base.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_out = &font->base; status = _cairo_atsui_font_set_metrics (font); if (status) { cairo_scaled_font_destroy (&font->base); 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){ ATSUStyle style; ATSUFontID fontID; OSStatus err; Boolean isItalic, isBold; const char *family = toy_face->family; err = ATSUCreateStyle(&style); 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; } 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); return _cairo_atsui_font_create_scaled (&toy_face->base, fontID, style, font_matrix, ctm, options, font_out);}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);}static cairo_status_t_cairo_atsui_font_init_glyph_metrics (cairo_atsui_font_t *font, cairo_scaled_glyph_t *scaled_glyph){ 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 };
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -