1685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com 23ee74d5653c16a5aa318f1d6274467a23f6049b5reed@android.com/* 3685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com * Copyright 2006 The Android Open Source Project 4685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com * 5685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com * Use of this source code is governed by a BSD-style license that can be 6685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com * found in the LICENSE file. 7685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com */ 8685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com 9e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org#include <vector> 10e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org#ifdef SK_BUILD_FOR_MAC 11e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org#import <ApplicationServices/ApplicationServices.h> 12e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org#endif 13e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 14e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org#ifdef SK_BUILD_FOR_IOS 15e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org#include <CoreText/CoreText.h> 169c28f1149c205580cbb0f018b083d065a7ae9222reed@google.com#include <CoreText/CTFontManager.h> 17e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org#include <CoreGraphics/CoreGraphics.h> 18e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org#include <CoreFoundation/CoreFoundation.h> 19e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org#endif 203ee74d5653c16a5aa318f1d6274467a23f6049b5reed@android.com 21e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org#include "SkFontHost.h" 22e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org#include "SkCGUtils.h" 23e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org#include "SkColorPriv.h" 24e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org#include "SkDescriptor.h" 25e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org#include "SkEndian.h" 26e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org#include "SkFontDescriptor.h" 27e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org#include "SkFloatingPoint.h" 28e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org#include "SkGlyph.h" 29e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org#include "SkMaskGamma.h" 30e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org#include "SkSFNTHeader.h" 31e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org#include "SkOTTable_glyf.h" 32e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org#include "SkOTTable_head.h" 33e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org#include "SkOTTable_hhea.h" 34e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org#include "SkOTTable_loca.h" 35e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org#include "SkOTUtils.h" 36e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org#include "SkPaint.h" 37e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org#include "SkPath.h" 38e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org#include "SkString.h" 39e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org#include "SkStream.h" 40e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org#include "SkThread.h" 41e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org#include "SkTypeface_mac.h" 42e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org#include "SkUtils.h" 43e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org#include "SkTypefaceCache.h" 44b6950743ce31468a5ca478f7916da10cf7b8c16areed@google.com#include "SkFontMgr.h" 4548c173d413ecc4c3661064be0f6f65022c1dc40dreed@google.com#include "SkUtils.h" 463ee74d5653c16a5aa318f1d6274467a23f6049b5reed@android.com 471ac3facef9444119e9d389e6b7b082c3120f0791reed@google.com//#define HACK_COLORGLYPHS 481ac3facef9444119e9d389e6b7b082c3120f0791reed@google.com 49e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.orgclass SkScalerContext_Mac; 50e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 519c28f1149c205580cbb0f018b083d065a7ae9222reed@google.com// CTFontManagerCopyAvailableFontFamilyNames() is not always available, so we 529c28f1149c205580cbb0f018b083d065a7ae9222reed@google.com// provide a wrapper here that will return an empty array if need be. 539c28f1149c205580cbb0f018b083d065a7ae9222reed@google.comstatic CFArrayRef SkCTFontManagerCopyAvailableFontFamilyNames() { 549c28f1149c205580cbb0f018b083d065a7ae9222reed@google.com#ifdef SK_BUILD_FOR_IOS 559c28f1149c205580cbb0f018b083d065a7ae9222reed@google.com return CFArrayCreate(NULL, NULL, 0, NULL); 569c28f1149c205580cbb0f018b083d065a7ae9222reed@google.com#else 579c28f1149c205580cbb0f018b083d065a7ae9222reed@google.com return CTFontManagerCopyAvailableFontFamilyNames(); 589c28f1149c205580cbb0f018b083d065a7ae9222reed@google.com#endif 599c28f1149c205580cbb0f018b083d065a7ae9222reed@google.com} 609c28f1149c205580cbb0f018b083d065a7ae9222reed@google.com 619c28f1149c205580cbb0f018b083d065a7ae9222reed@google.com 62e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org// Being templated and taking const T* prevents calling 63e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org// CFSafeRelease(autoCFRelease) through implicit conversion. 64e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.orgtemplate <typename T> static void CFSafeRelease(/*CFTypeRef*/const T* cfTypeRef) { 65e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org if (cfTypeRef) { 66e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org CFRelease(cfTypeRef); 67e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org } 68e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org} 69e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 70e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org// Being templated and taking const T* prevents calling 71e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org// CFSafeRetain(autoCFRelease) through implicit conversion. 72e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.orgtemplate <typename T> static void CFSafeRetain(/*CFTypeRef*/const T* cfTypeRef) { 73e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org if (cfTypeRef) { 74e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org CFRetain(cfTypeRef); 75e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org } 76e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org} 77e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 78e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org/** Acts like a CFRef, but calls CFSafeRelease when it goes out of scope. */ 79e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.orgtemplate<typename CFRef> class AutoCFRelease : private SkNoncopyable { 80e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.orgpublic: 81e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org explicit AutoCFRelease(CFRef cfRef = NULL) : fCFRef(cfRef) { } 82e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org ~AutoCFRelease() { CFSafeRelease(fCFRef); } 83e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 84e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org void reset(CFRef that = NULL) { 85e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org CFSafeRetain(that); 86e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org CFSafeRelease(fCFRef); 87e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org fCFRef = that; 88e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org } 89e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 90e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org AutoCFRelease& operator =(CFRef that) { 91e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org reset(that); 92e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org return *this; 93e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org } 94e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 95e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org operator CFRef() const { return fCFRef; } 96e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org CFRef get() const { return fCFRef; } 97e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 98ee8341d57355c54ea8db5fb21be75e7354069fb3bungeman@google.com CFRef* operator&() { SkASSERT(fCFRef == NULL); return &fCFRef; } 99e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.orgprivate: 100e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org CFRef fCFRef; 101e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org}; 102e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 103ab8665f8e88927b1a9b82aca38483d8a963fd2e0reed@google.comstatic CFStringRef make_CFString(const char str[]) { 104ab8665f8e88927b1a9b82aca38483d8a963fd2e0reed@google.com return CFStringCreateWithCString(NULL, str, kCFStringEncodingUTF8); 105ab8665f8e88927b1a9b82aca38483d8a963fd2e0reed@google.com} 106ab8665f8e88927b1a9b82aca38483d8a963fd2e0reed@google.com 107e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.orgtemplate<typename T> class AutoCGTable : SkNoncopyable { 108e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.orgpublic: 109e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org AutoCGTable(CGFontRef font) 110e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org //Undocumented: the tag parameter in this call is expected in machine order and not BE order. 111e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org : fCFData(CGFontCopyTableForTag(font, SkSetFourByteTag(T::TAG0, T::TAG1, T::TAG2, T::TAG3))) 112e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org , fData(fCFData ? reinterpret_cast<const T*>(CFDataGetBytePtr(fCFData)) : NULL) 113e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org { } 114e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 115e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org const T* operator->() const { return fData; } 116e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 117e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.orgprivate: 118e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org AutoCFRelease<CFDataRef> fCFData; 119e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.orgpublic: 120e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org const T* fData; 121e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org}; 122e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 123e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org// inline versions of these rect helpers 124e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 125e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.orgstatic bool CGRectIsEmpty_inline(const CGRect& rect) { 126e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org return rect.size.width <= 0 || rect.size.height <= 0; 127e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org} 128e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 129e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.orgstatic CGFloat CGRectGetMinX_inline(const CGRect& rect) { 130e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org return rect.origin.x; 131e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org} 132e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 133e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.orgstatic CGFloat CGRectGetMaxX_inline(const CGRect& rect) { 134e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org return rect.origin.x + rect.size.width; 135e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org} 136e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 137e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.orgstatic CGFloat CGRectGetMinY_inline(const CGRect& rect) { 138e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org return rect.origin.y; 139e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org} 140e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 141e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.orgstatic CGFloat CGRectGetMaxY_inline(const CGRect& rect) { 142e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org return rect.origin.y + rect.size.height; 143e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org} 144e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 145e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.orgstatic CGFloat CGRectGetWidth_inline(const CGRect& rect) { 146e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org return rect.size.width; 147e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org} 148e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 149e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org/////////////////////////////////////////////////////////////////////////////// 150e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 151e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.orgstatic void sk_memset_rect32(uint32_t* ptr, uint32_t value, 152e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org size_t width, size_t height, size_t rowBytes) { 153e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org SkASSERT(width); 154e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org SkASSERT(width * sizeof(uint32_t) <= rowBytes); 155e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 156e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org if (width >= 32) { 157e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org while (height) { 158e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org sk_memset32(ptr, value, width); 159e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org ptr = (uint32_t*)((char*)ptr + rowBytes); 160e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org height -= 1; 161e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org } 162e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org return; 163e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org } 164e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 165e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org rowBytes -= width * sizeof(uint32_t); 166e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 167e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org if (width >= 8) { 168e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org while (height) { 169e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org int w = width; 170e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org do { 171e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org *ptr++ = value; *ptr++ = value; 172e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org *ptr++ = value; *ptr++ = value; 173e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org *ptr++ = value; *ptr++ = value; 174e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org *ptr++ = value; *ptr++ = value; 175e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org w -= 8; 176e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org } while (w >= 8); 177e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org while (--w >= 0) { 178e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org *ptr++ = value; 179e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org } 180e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org ptr = (uint32_t*)((char*)ptr + rowBytes); 181e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org height -= 1; 182e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org } 183e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org } else { 184e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org while (height) { 185e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org int w = width; 186e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org do { 187e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org *ptr++ = value; 188e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org } while (--w > 0); 189e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org ptr = (uint32_t*)((char*)ptr + rowBytes); 190e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org height -= 1; 191e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org } 192e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org } 193e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org} 194e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 195e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org#include <sys/utsname.h> 196e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 197e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.orgtypedef uint32_t CGRGBPixel; 198e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 199e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.orgstatic unsigned CGRGBPixel_getAlpha(CGRGBPixel pixel) { 200e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org return pixel & 0xFF; 201e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org} 202e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 203e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org// The calls to support subpixel are present in 10.5, but are not included in 204e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org// the 10.5 SDK. The needed calls have been extracted from the 10.6 SDK and are 205e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org// included below. To verify that CGContextSetShouldSubpixelQuantizeFonts, for 206e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org// instance, is present in the 10.5 CoreGraphics libary, use: 207e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org// cd /Developer/SDKs/MacOSX10.5.sdk/System/Library/Frameworks/ 208e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org// cd ApplicationServices.framework/Frameworks/CoreGraphics.framework/ 209e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org// nm CoreGraphics | grep CGContextSetShouldSubpixelQuantizeFonts 210e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 211e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org#if !defined(MAC_OS_X_VERSION_10_6) || (MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_6) 212e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.orgCG_EXTERN void CGContextSetAllowsFontSmoothing(CGContextRef context, bool value); 213e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.orgCG_EXTERN void CGContextSetAllowsFontSubpixelPositioning(CGContextRef context, bool value); 214e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.orgCG_EXTERN void CGContextSetShouldSubpixelPositionFonts(CGContextRef context, bool value); 215e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.orgCG_EXTERN void CGContextSetAllowsFontSubpixelQuantization(CGContextRef context, bool value); 216e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.orgCG_EXTERN void CGContextSetShouldSubpixelQuantizeFonts(CGContextRef context, bool value); 217aa2f67cf5e22a8d3b7f86ba9be565ff94cf4e2b2reed@android.com#endif 21836a54d5bdd040d4df9c53c298bb0c3af26497e33reed@android.com 219e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.orgstatic const char FONT_DEFAULT_NAME[] = "Lucida Sans"; 220e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 221e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org// See Source/WebKit/chromium/base/mac/mac_util.mm DarwinMajorVersionInternal for original source. 222e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.orgstatic int readVersion() { 223e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org struct utsname info; 224e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org if (uname(&info) != 0) { 225e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org SkDebugf("uname failed\n"); 226e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org return 0; 227e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org } 228e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org if (strcmp(info.sysname, "Darwin") != 0) { 229e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org SkDebugf("unexpected uname sysname %s\n", info.sysname); 230e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org return 0; 231e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org } 232e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org char* dot = strchr(info.release, '.'); 233e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org if (!dot) { 234e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org SkDebugf("expected dot in uname release %s\n", info.release); 235e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org return 0; 236e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org } 237e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org int version = atoi(info.release); 238e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org if (version == 0) { 239e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org SkDebugf("could not parse uname release %s\n", info.release); 240e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org } 241e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org return version; 242e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org} 243e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 244e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.orgstatic int darwinVersion() { 245e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org static int darwin_version = readVersion(); 246e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org return darwin_version; 247e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org} 248e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 249e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.orgstatic bool isSnowLeopard() { 250e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org return darwinVersion() == 10; 251e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org} 252e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 253e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.orgstatic bool isLion() { 254e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org return darwinVersion() == 11; 255e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org} 256e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 257e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.orgstatic bool isMountainLion() { 258e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org return darwinVersion() == 12; 259e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org} 260e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 261e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.orgstatic bool isLCDFormat(unsigned format) { 262e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org return SkMask::kLCD16_Format == format || SkMask::kLCD32_Format == format; 263e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org} 264e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 265e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.orgstatic CGFloat ScalarToCG(SkScalar scalar) { 266e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org if (sizeof(CGFloat) == sizeof(float)) { 267e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org return SkScalarToFloat(scalar); 268e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org } else { 269e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org SkASSERT(sizeof(CGFloat) == sizeof(double)); 270e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org return (CGFloat) SkScalarToDouble(scalar); 271e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org } 272e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org} 273e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 274e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.orgstatic SkScalar CGToScalar(CGFloat cgFloat) { 275e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org if (sizeof(CGFloat) == sizeof(float)) { 276e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org return SkFloatToScalar(cgFloat); 277e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org } else { 278e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org SkASSERT(sizeof(CGFloat) == sizeof(double)); 279e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org return SkDoubleToScalar(cgFloat); 280e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org } 281e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org} 282e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 283e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.orgstatic CGAffineTransform MatrixToCGAffineTransform(const SkMatrix& matrix, 284e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org SkScalar sx = SK_Scalar1, 285e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org SkScalar sy = SK_Scalar1) { 286e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org return CGAffineTransformMake( ScalarToCG(matrix[SkMatrix::kMScaleX] * sx), 287e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org -ScalarToCG(matrix[SkMatrix::kMSkewY] * sy), 288e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org -ScalarToCG(matrix[SkMatrix::kMSkewX] * sx), 289e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org ScalarToCG(matrix[SkMatrix::kMScaleY] * sy), 290e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org ScalarToCG(matrix[SkMatrix::kMTransX] * sx), 291e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org ScalarToCG(matrix[SkMatrix::kMTransY] * sy)); 292e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org} 293e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 294e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org/////////////////////////////////////////////////////////////////////////////// 295e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 296e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org#define BITMAP_INFO_RGB (kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Host) 297e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org#define BITMAP_INFO_GRAY (kCGImageAlphaNone) 298e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 299e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org/** 300e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org * There does not appear to be a publicly accessable API for determining if lcd 301e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org * font smoothing will be applied if we request it. The main issue is that if 302e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org * smoothing is applied a gamma of 2.0 will be used, if not a gamma of 1.0. 303e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org */ 304e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.orgstatic bool supports_LCD() { 305e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org static int gSupportsLCD = -1; 306e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org if (gSupportsLCD >= 0) { 307e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org return (bool) gSupportsLCD; 308e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org } 309e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org uint32_t rgb = 0; 310e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org AutoCFRelease<CGColorSpaceRef> colorspace(CGColorSpaceCreateDeviceRGB()); 311e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org AutoCFRelease<CGContextRef> cgContext(CGBitmapContextCreate(&rgb, 1, 1, 8, 4, 312e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org colorspace, BITMAP_INFO_RGB)); 313e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org CGContextSelectFont(cgContext, "Helvetica", 16, kCGEncodingMacRoman); 314e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org CGContextSetShouldSmoothFonts(cgContext, true); 315e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org CGContextSetShouldAntialias(cgContext, true); 316e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org CGContextSetTextDrawingMode(cgContext, kCGTextFill); 317e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org CGContextSetGrayFillColor(cgContext, 1, 1); 318e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org CGContextShowTextAtPoint(cgContext, -1, 0, "|", 1); 319e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org uint32_t r = (rgb >> 16) & 0xFF; 320e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org uint32_t g = (rgb >> 8) & 0xFF; 321e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org uint32_t b = (rgb >> 0) & 0xFF; 322e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org gSupportsLCD = (r != g || r != b); 323e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org return (bool) gSupportsLCD; 324e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org} 325e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 326e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.orgclass Offscreen { 327e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.orgpublic: 328e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org Offscreen(); 329e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 330e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org CGRGBPixel* getCG(const SkScalerContext_Mac& context, const SkGlyph& glyph, 331e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org CGGlyph glyphID, size_t* rowBytesPtr, 332e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org bool generateA8FromLCD); 333e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 334e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.orgprivate: 335e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org enum { 336e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org kSize = 32 * 32 * sizeof(CGRGBPixel) 337e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org }; 338e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org SkAutoSMalloc<kSize> fImageStorage; 339e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org AutoCFRelease<CGColorSpaceRef> fRGBSpace; 340e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 341e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org // cached state 342e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org AutoCFRelease<CGContextRef> fCG; 343e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org SkISize fSize; 344e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org bool fDoAA; 345e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org bool fDoLCD; 346e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 347e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org static int RoundSize(int dimension) { 348e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org return SkNextPow2(dimension); 349e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org } 350e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org}; 351e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 352e0a1ec938fbf36150f4d0869cf95fb5b7e0edcceskia.committer@gmail.comOffscreen::Offscreen() : fRGBSpace(NULL), fCG(NULL), 353bae2c4d75eabc19e9ce74ec250d1901c02bdb9derobertphillips@google.com fDoAA(false), fDoLCD(false) { 354e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org fSize.set(0, 0); 355e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org} 356e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 357e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org/////////////////////////////////////////////////////////////////////////////// 358e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 35902799b558fe28f9869ebb4291834e93101ef44f4bungeman@google.comstatic SkTypeface::Style computeStyleBits(CTFontRef font, bool* isFixedPitch) { 360e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org unsigned style = SkTypeface::kNormal; 361e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org CTFontSymbolicTraits traits = CTFontGetSymbolicTraits(font); 362e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 363e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org if (traits & kCTFontBoldTrait) { 364e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org style |= SkTypeface::kBold; 365e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org } 366e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org if (traits & kCTFontItalicTrait) { 367e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org style |= SkTypeface::kItalic; 368e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org } 36902799b558fe28f9869ebb4291834e93101ef44f4bungeman@google.com if (isFixedPitch) { 37002799b558fe28f9869ebb4291834e93101ef44f4bungeman@google.com *isFixedPitch = (traits & kCTFontMonoSpaceTrait) != 0; 371e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org } 372e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org return (SkTypeface::Style)style; 373e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org} 374e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 375e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.orgstatic SkFontID CTFontRef_to_SkFontID(CTFontRef fontRef) { 376e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org SkFontID id = 0; 377e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org// CTFontGetPlatformFont and ATSFontRef are not supported on iOS, so we have to 378e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org// bracket this to be Mac only. 379e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org#ifdef SK_BUILD_FOR_MAC 380e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org ATSFontRef ats = CTFontGetPlatformFont(fontRef, NULL); 381e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org id = (SkFontID)ats; 382e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org if (id != 0) { 383e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org id &= 0x3FFFFFFF; // make top two bits 00 384e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org return id; 385e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org } 386e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org#endif 387e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org // CTFontGetPlatformFont returns NULL if the font is local 388e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org // (e.g., was created by a CSS3 @font-face rule). 389e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org AutoCFRelease<CGFontRef> cgFont(CTFontCopyGraphicsFont(fontRef, NULL)); 390e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org AutoCGTable<SkOTTableHead> headTable(cgFont); 391e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org if (headTable.fData) { 392e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org id = (SkFontID) headTable->checksumAdjustment; 393e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org id = (id & 0x3FFFFFFF) | 0x40000000; // make top two bits 01 394e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org } 395e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org // well-formed fonts have checksums, but as a last resort, use the pointer. 396e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org if (id == 0) { 397e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org id = (SkFontID) (uintptr_t) fontRef; 398e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org id = (id & 0x3FFFFFFF) | 0x80000000; // make top two bits 10 399e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org } 400e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org return id; 401e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org} 402e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 403b6950743ce31468a5ca478f7916da10cf7b8c16areed@google.comstatic SkFontStyle stylebits2fontstyle(SkTypeface::Style styleBits) { 404b6950743ce31468a5ca478f7916da10cf7b8c16areed@google.com return SkFontStyle((styleBits & SkTypeface::kBold) 405b6950743ce31468a5ca478f7916da10cf7b8c16areed@google.com ? SkFontStyle::kBold_Weight 406b6950743ce31468a5ca478f7916da10cf7b8c16areed@google.com : SkFontStyle::kNormal_Weight, 407b6950743ce31468a5ca478f7916da10cf7b8c16areed@google.com SkFontStyle::kNormal_Width, 408b6950743ce31468a5ca478f7916da10cf7b8c16areed@google.com (styleBits & SkTypeface::kItalic) 409b6950743ce31468a5ca478f7916da10cf7b8c16areed@google.com ? SkFontStyle::kItalic_Slant 410b6950743ce31468a5ca478f7916da10cf7b8c16areed@google.com : SkFontStyle::kUpright_Slant); 411b6950743ce31468a5ca478f7916da10cf7b8c16areed@google.com} 412b6950743ce31468a5ca478f7916da10cf7b8c16areed@google.com 413b6950743ce31468a5ca478f7916da10cf7b8c16areed@google.com#define WEIGHT_THRESHOLD ((SkFontStyle::kNormal_Weight + SkFontStyle::kBold_Weight)/2) 414b6950743ce31468a5ca478f7916da10cf7b8c16areed@google.com 415b6950743ce31468a5ca478f7916da10cf7b8c16areed@google.comstatic SkTypeface::Style fontstyle2stylebits(const SkFontStyle& fs) { 416b6950743ce31468a5ca478f7916da10cf7b8c16areed@google.com unsigned style = 0; 417b6950743ce31468a5ca478f7916da10cf7b8c16areed@google.com if (fs.width() >= WEIGHT_THRESHOLD) { 418b6950743ce31468a5ca478f7916da10cf7b8c16areed@google.com style |= SkTypeface::kBold; 419b6950743ce31468a5ca478f7916da10cf7b8c16areed@google.com } 420b6950743ce31468a5ca478f7916da10cf7b8c16areed@google.com if (fs.isItalic()) { 421b6950743ce31468a5ca478f7916da10cf7b8c16areed@google.com style |= SkTypeface::kItalic; 422b6950743ce31468a5ca478f7916da10cf7b8c16areed@google.com } 423b6950743ce31468a5ca478f7916da10cf7b8c16areed@google.com return (SkTypeface::Style)style; 424b6950743ce31468a5ca478f7916da10cf7b8c16areed@google.com} 425b6950743ce31468a5ca478f7916da10cf7b8c16areed@google.com 426e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.orgclass SkTypeface_Mac : public SkTypeface { 427e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.orgpublic: 42802799b558fe28f9869ebb4291834e93101ef44f4bungeman@google.com SkTypeface_Mac(SkTypeface::Style style, SkFontID fontID, bool isFixedPitch, 429e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org CTFontRef fontRef, const char name[]) 430b6950743ce31468a5ca478f7916da10cf7b8c16areed@google.com : SkTypeface(style, fontID, isFixedPitch) 431b6950743ce31468a5ca478f7916da10cf7b8c16areed@google.com , fName(name) 432b6950743ce31468a5ca478f7916da10cf7b8c16areed@google.com , fFontRef(fontRef) // caller has already called CFRetain for us 433b6950743ce31468a5ca478f7916da10cf7b8c16areed@google.com , fFontStyle(stylebits2fontstyle(style)) 434e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org { 435e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org SkASSERT(fontRef); 436e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org } 437cb9a1cd72d397d254c18441743b79de0bbc3da09skia.committer@gmail.com 438b6950743ce31468a5ca478f7916da10cf7b8c16areed@google.com SkTypeface_Mac(const SkFontStyle& fs, SkFontID fontID, bool isFixedPitch, 439b6950743ce31468a5ca478f7916da10cf7b8c16areed@google.com CTFontRef fontRef, const char name[]) 440b6950743ce31468a5ca478f7916da10cf7b8c16areed@google.com : SkTypeface(fontstyle2stylebits(fs), fontID, isFixedPitch) 441b6950743ce31468a5ca478f7916da10cf7b8c16areed@google.com , fName(name) 442b6950743ce31468a5ca478f7916da10cf7b8c16areed@google.com , fFontRef(fontRef) // caller has already called CFRetain for us 443b6950743ce31468a5ca478f7916da10cf7b8c16areed@google.com , fFontStyle(fs) 444b6950743ce31468a5ca478f7916da10cf7b8c16areed@google.com { 445b6950743ce31468a5ca478f7916da10cf7b8c16areed@google.com SkASSERT(fontRef); 446b6950743ce31468a5ca478f7916da10cf7b8c16areed@google.com } 447cb9a1cd72d397d254c18441743b79de0bbc3da09skia.committer@gmail.com 448e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org SkString fName; 449e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org AutoCFRelease<CTFontRef> fFontRef; 450b6950743ce31468a5ca478f7916da10cf7b8c16areed@google.com SkFontStyle fFontStyle; 451e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 452e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.orgprotected: 453e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org friend class SkFontHost; // to access our protected members for deprecated methods 454e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 455e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org virtual int onGetUPEM() const SK_OVERRIDE; 456bbad7fe187bd8c112148dd7958bb645291f642ddreed@google.com virtual SkStream* onOpenStream(int* ttcIndex) const SK_OVERRIDE; 4576e20a74d8cbcf19195559e8d98896fa22ebc535fbungeman@google.com virtual SkTypeface::LocalizedStrings* onCreateFamilyNameIterator() const SK_OVERRIDE; 458e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org virtual int onGetTableTags(SkFontTableTag tags[]) const SK_OVERRIDE; 459e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org virtual size_t onGetTableData(SkFontTableTag, size_t offset, 460e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org size_t length, void* data) const SK_OVERRIDE; 461e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org virtual SkScalerContext* onCreateScalerContext(const SkDescriptor*) const SK_OVERRIDE; 462e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org virtual void onFilterRec(SkScalerContextRec*) const SK_OVERRIDE; 4633d8295f60b8b733ec0210b08261e968ad79bf5c6reed@google.com virtual void onGetFontDescriptor(SkFontDescriptor*, bool*) const SK_OVERRIDE; 4643dca9a6576d2baaf6132bbe736e8597723cbc5acreed@google.com virtual SkAdvancedTypefaceMetrics* onGetAdvancedTypefaceMetrics( 4653dca9a6576d2baaf6132bbe736e8597723cbc5acreed@google.com SkAdvancedTypefaceMetrics::PerGlyphInfo, 4663dca9a6576d2baaf6132bbe736e8597723cbc5acreed@google.com const uint32_t*, uint32_t) const SK_OVERRIDE; 46748c173d413ecc4c3661064be0f6f65022c1dc40dreed@google.com virtual int onCharsToGlyphs(const void* chars, Encoding, uint16_t glyphs[], 46848c173d413ecc4c3661064be0f6f65022c1dc40dreed@google.com int glyphCount) const SK_OVERRIDE; 46948c173d413ecc4c3661064be0f6f65022c1dc40dreed@google.com virtual int onCountGlyphs() const SK_OVERRIDE; 470836008c1588a111f090a606726822d62d3026e00reed@google.com virtual SkTypeface* onRefMatchingStyle(Style) const SK_OVERRIDE; 471f2b481703f64ccb4e7e25ccd5e80f2eed95a35ddskia.committer@gmail.com 472e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.orgprivate: 473b6950743ce31468a5ca478f7916da10cf7b8c16areed@google.com 474e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org typedef SkTypeface INHERITED; 475e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org}; 476e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 477e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.orgstatic SkTypeface* NewFromFontRef(CTFontRef fontRef, const char name[]) { 478e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org SkASSERT(fontRef); 47902799b558fe28f9869ebb4291834e93101ef44f4bungeman@google.com bool isFixedPitch; 48002799b558fe28f9869ebb4291834e93101ef44f4bungeman@google.com SkTypeface::Style style = computeStyleBits(fontRef, &isFixedPitch); 481e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org SkFontID fontID = CTFontRef_to_SkFontID(fontRef); 482e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 48302799b558fe28f9869ebb4291834e93101ef44f4bungeman@google.com return new SkTypeface_Mac(style, fontID, isFixedPitch, fontRef, name); 484e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org} 485e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 486e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.orgstatic SkTypeface* NewFromName(const char familyName[], SkTypeface::Style theStyle) { 487e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org CTFontRef ctFont = NULL; 488e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 489e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org CTFontSymbolicTraits ctFontTraits = 0; 490e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org if (theStyle & SkTypeface::kBold) { 491e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org ctFontTraits |= kCTFontBoldTrait; 492e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org } 493e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org if (theStyle & SkTypeface::kItalic) { 494e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org ctFontTraits |= kCTFontItalicTrait; 495e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org } 496e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 497e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org // Create the font info 498ab8665f8e88927b1a9b82aca38483d8a963fd2e0reed@google.com AutoCFRelease<CFStringRef> cfFontName(make_CFString(familyName)); 499e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 500e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org AutoCFRelease<CFNumberRef> cfFontTraits( 501e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &ctFontTraits)); 502e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 503e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org AutoCFRelease<CFMutableDictionaryRef> cfAttributes( 504e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org CFDictionaryCreateMutable(kCFAllocatorDefault, 0, 505e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org &kCFTypeDictionaryKeyCallBacks, 506e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org &kCFTypeDictionaryValueCallBacks)); 507e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 508e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org AutoCFRelease<CFMutableDictionaryRef> cfTraits( 509e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org CFDictionaryCreateMutable(kCFAllocatorDefault, 0, 510e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org &kCFTypeDictionaryKeyCallBacks, 511e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org &kCFTypeDictionaryValueCallBacks)); 512e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 513e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org // Create the font 514e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org if (cfFontName != NULL && cfFontTraits != NULL && cfAttributes != NULL && cfTraits != NULL) { 515e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org CFDictionaryAddValue(cfTraits, kCTFontSymbolicTrait, cfFontTraits); 516e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 517e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org CFDictionaryAddValue(cfAttributes, kCTFontFamilyNameAttribute, cfFontName); 518e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org CFDictionaryAddValue(cfAttributes, kCTFontTraitsAttribute, cfTraits); 519e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 520e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org AutoCFRelease<CTFontDescriptorRef> ctFontDesc( 521e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org CTFontDescriptorCreateWithAttributes(cfAttributes)); 522e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 523e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org if (ctFontDesc != NULL) { 524039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com ctFont = CTFontCreateWithFontDescriptor(ctFontDesc, 0, NULL); 525e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org } 526e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org } 527e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 528e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org return ctFont ? NewFromFontRef(ctFont, familyName) : NULL; 529e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org} 530e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 531e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.orgstatic SkTypeface* GetDefaultFace() { 532e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org SK_DECLARE_STATIC_MUTEX(gMutex); 533e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org SkAutoMutexAcquire ma(gMutex); 534e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 535e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org static SkTypeface* gDefaultFace; 536e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 537e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org if (NULL == gDefaultFace) { 538e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org gDefaultFace = NewFromName(FONT_DEFAULT_NAME, SkTypeface::kNormal); 539e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org SkTypefaceCache::Add(gDefaultFace, SkTypeface::kNormal); 540e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org } 541e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org return gDefaultFace; 542e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org} 543e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 544e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org/////////////////////////////////////////////////////////////////////////////// 545e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 546e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.orgextern CTFontRef SkTypeface_GetCTFontRef(const SkTypeface* face); 547e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.orgCTFontRef SkTypeface_GetCTFontRef(const SkTypeface* face) { 548e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org const SkTypeface_Mac* macface = (const SkTypeface_Mac*)face; 549e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org return macface ? macface->fFontRef.get() : NULL; 550e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org} 551e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 552e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org/* This function is visible on the outside. It first searches the cache, and if 553e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org * not found, returns a new entry (after adding it to the cache). 554e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org */ 555e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.orgSkTypeface* SkCreateTypefaceFromCTFont(CTFontRef fontRef) { 556e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org SkFontID fontID = CTFontRef_to_SkFontID(fontRef); 557e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org SkTypeface* face = SkTypefaceCache::FindByID(fontID); 558e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org if (face) { 559e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org face->ref(); 560e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org } else { 561e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org face = NewFromFontRef(fontRef, NULL); 562e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org SkTypefaceCache::Add(face, face->style()); 563e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org // NewFromFontRef doesn't retain the parameter, but the typeface it 564e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org // creates does release it in its destructor, so we balance that with 565e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org // a retain call here. 566e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org CFRetain(fontRef); 567e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org } 568e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org SkASSERT(face->getRefCnt() > 1); 569e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org return face; 570e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org} 571e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 572e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.orgstruct NameStyleRec { 573e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org const char* fName; 574e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org SkTypeface::Style fStyle; 575e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org}; 576e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 577e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.orgstatic bool FindByNameStyle(SkTypeface* face, SkTypeface::Style style, 578e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org void* ctx) { 579e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org const SkTypeface_Mac* mface = reinterpret_cast<SkTypeface_Mac*>(face); 580e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org const NameStyleRec* rec = reinterpret_cast<const NameStyleRec*>(ctx); 581e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 582e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org return rec->fStyle == style && mface->fName.equals(rec->fName); 583e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org} 584e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 585e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.orgstatic const char* map_css_names(const char* name) { 586e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org static const struct { 587e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org const char* fFrom; // name the caller specified 588e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org const char* fTo; // "canonical" name we map to 589e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org } gPairs[] = { 590e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org { "sans-serif", "Helvetica" }, 591e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org { "serif", "Times" }, 592e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org { "monospace", "Courier" } 593e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org }; 594e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 595e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org for (size_t i = 0; i < SK_ARRAY_COUNT(gPairs); i++) { 596e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org if (strcmp(name, gPairs[i].fFrom) == 0) { 597e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org return gPairs[i].fTo; 598e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org } 599e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org } 600e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org return name; // no change 601e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org} 602e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 603836008c1588a111f090a606726822d62d3026e00reed@google.comstatic SkTypeface* create_typeface(const SkTypeface* familyFace, 604836008c1588a111f090a606726822d62d3026e00reed@google.com const char familyName[], 605836008c1588a111f090a606726822d62d3026e00reed@google.com SkTypeface::Style style) { 606e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org if (familyName) { 607e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org familyName = map_css_names(familyName); 608e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org } 609ff58f8b49a03197747998f4069e0980d9f6d34c0skia.committer@gmail.com 610e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org // Clone an existing typeface 611e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org // TODO: only clone if style matches the familyFace's style... 612e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org if (familyName == NULL && familyFace != NULL) { 613e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org familyFace->ref(); 614e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org return const_cast<SkTypeface*>(familyFace); 615e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org } 616ff58f8b49a03197747998f4069e0980d9f6d34c0skia.committer@gmail.com 617e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org if (!familyName || !*familyName) { 618e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org familyName = FONT_DEFAULT_NAME; 619e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org } 620ff58f8b49a03197747998f4069e0980d9f6d34c0skia.committer@gmail.com 621e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org NameStyleRec rec = { familyName, style }; 622e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org SkTypeface* face = SkTypefaceCache::FindByProcAndRef(FindByNameStyle, &rec); 623ff58f8b49a03197747998f4069e0980d9f6d34c0skia.committer@gmail.com 624e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org if (NULL == face) { 625e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org face = NewFromName(familyName, style); 626e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org if (face) { 627e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org SkTypefaceCache::Add(face, style); 628e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org } else { 629e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org face = GetDefaultFace(); 630e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org face->ref(); 631e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org } 632e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org } 633e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org return face; 634e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org} 635e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 636836008c1588a111f090a606726822d62d3026e00reed@google.comSkTypeface* SkTypeface_Mac::onRefMatchingStyle(Style styleBits) const { 637836008c1588a111f090a606726822d62d3026e00reed@google.com return create_typeface(this, NULL, styleBits); 638836008c1588a111f090a606726822d62d3026e00reed@google.com} 639836008c1588a111f090a606726822d62d3026e00reed@google.com 640e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org/////////////////////////////////////////////////////////////////////////////// 641e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 642039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com/** GlyphRect is in FUnits (em space, y up). */ 643e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.orgstruct GlyphRect { 644e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org int16_t fMinX; 645e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org int16_t fMinY; 646e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org int16_t fMaxX; 647e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org int16_t fMaxY; 648e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org}; 649e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 650e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.orgclass SkScalerContext_Mac : public SkScalerContext { 651e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.orgpublic: 6528e01453029702b114d4eb939e4fbe7fd33b57b50reed@google.com SkScalerContext_Mac(SkTypeface_Mac*, const SkDescriptor*); 653e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 654e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.orgprotected: 655e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org unsigned generateGlyphCount(void) SK_OVERRIDE; 656e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org uint16_t generateCharToGlyph(SkUnichar uni) SK_OVERRIDE; 657e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org void generateAdvance(SkGlyph* glyph) SK_OVERRIDE; 658e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org void generateMetrics(SkGlyph* glyph) SK_OVERRIDE; 659e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org void generateImage(const SkGlyph& glyph) SK_OVERRIDE; 660e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org void generatePath(const SkGlyph& glyph, SkPath* path) SK_OVERRIDE; 661e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org void generateFontMetrics(SkPaint::FontMetrics* mX, SkPaint::FontMetrics* mY) SK_OVERRIDE; 662e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 663e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.orgprivate: 664e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org static void CTPathElement(void *info, const CGPathElement *element); 665a35ae01b7f409c673e990ea3b6a19a55080a1dcbskia.committer@gmail.com 666039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com /** Returns the offset from the horizontal origin to the vertical origin in SkGlyph units. */ 667039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com void getVerticalOffset(CGGlyph glyphID, SkPoint* offset) const; 668039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com 669039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com /** Initializes and returns the value of fFBoundingBoxesGlyphOffset. 670039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com * 671039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com * For use with (and must be called before) generateBBoxes. 672039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com */ 673039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com uint16_t getFBoundingBoxesGlyphOffset(); 674a35ae01b7f409c673e990ea3b6a19a55080a1dcbskia.committer@gmail.com 675039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com /** Initializes fFBoundingBoxes and returns true on success. 676039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com * 677039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com * On Lion and Mountain Lion, CTFontGetBoundingRectsForGlyphs has a bug which causes it to 678039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com * return a bad value in bounds.origin.x for SFNT fonts whose hhea::numberOfHMetrics is 679039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com * less than its maxp::numGlyphs. When this is the case we try to read the bounds from the 680039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com * font directly. 681039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com * 682039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com * This routine initializes fFBoundingBoxes to an array of 683039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com * fGlyphCount - fFBoundingBoxesGlyphOffset GlyphRects which contain the bounds in FUnits 684039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com * (em space, y up) of glyphs with ids in the range [fFBoundingBoxesGlyphOffset, fGlyphCount). 685039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com * 686039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com * Returns true if fFBoundingBoxes is properly initialized. The table can only be properly 687039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com * initialized for a TrueType font with 'head', 'loca', and 'glyf' tables. 688039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com * 689039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com * TODO: A future optimization will compute fFBoundingBoxes once per fCTFont. 690039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com */ 691e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org bool generateBBoxes(); 692e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 693039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com /** Converts from FUnits (em space, y up) to SkGlyph units (pixels, y down). 694039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com * 695039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com * Used on Snow Leopard to correct CTFontGetVerticalTranslationsForGlyphs. 696039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com * Used on Lion to correct CTFontGetBoundingRectsForGlyphs. 697039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com */ 698039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com SkMatrix fFUnitMatrix; 699a35ae01b7f409c673e990ea3b6a19a55080a1dcbskia.committer@gmail.com 700e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org Offscreen fOffscreen; 701e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org AutoCFRelease<CTFontRef> fCTFont; 702a35ae01b7f409c673e990ea3b6a19a55080a1dcbskia.committer@gmail.com 703039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com /** Vertical variant of fCTFont. 704039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com * 705039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com * CT vertical metrics are pre-rotated (in em space, before transform) 90deg clock-wise. 706039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com * This makes kCTFontDefaultOrientation dangerous, because the metrics from 707039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com * kCTFontHorizontalOrientation are in a different space from kCTFontVerticalOrientation. 708039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com * Use fCTVerticalFont with kCTFontVerticalOrientation to get metrics in the same space. 709039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com */ 710039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com AutoCFRelease<CTFontRef> fCTVerticalFont; 711a35ae01b7f409c673e990ea3b6a19a55080a1dcbskia.committer@gmail.com 712e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org AutoCFRelease<CGFontRef> fCGFont; 713039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com SkAutoTMalloc<GlyphRect> fFBoundingBoxes; 714e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org uint16_t fFBoundingBoxesGlyphOffset; 715e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org uint16_t fGlyphCount; 716e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org bool fGeneratedFBoundingBoxes; 717039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com const bool fDoSubPosition; 718039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com const bool fVertical; 719039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com 720e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org friend class Offscreen; 7218e01453029702b114d4eb939e4fbe7fd33b57b50reed@google.com 7228e01453029702b114d4eb939e4fbe7fd33b57b50reed@google.com typedef SkScalerContext INHERITED; 723e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org}; 724e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 7258e01453029702b114d4eb939e4fbe7fd33b57b50reed@google.comSkScalerContext_Mac::SkScalerContext_Mac(SkTypeface_Mac* typeface, 7268e01453029702b114d4eb939e4fbe7fd33b57b50reed@google.com const SkDescriptor* desc) 7278e01453029702b114d4eb939e4fbe7fd33b57b50reed@google.com : INHERITED(typeface, desc) 728039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com , fFBoundingBoxes() 729e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org , fFBoundingBoxesGlyphOffset(0) 730e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org , fGeneratedFBoundingBoxes(false) 731039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com , fDoSubPosition(SkToBool(fRec.fFlags & kSubpixelPositioning_Flag)) 732039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com , fVertical(SkToBool(fRec.fFlags & kVertical_Flag)) 733039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com 734e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org{ 7353dca9a6576d2baaf6132bbe736e8597723cbc5acreed@google.com CTFontRef ctFont = typeface->fFontRef.get(); 736e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org CFIndex numGlyphs = CTFontGetGlyphCount(ctFont); 737039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com SkASSERT(numGlyphs >= 1 && numGlyphs <= 0xFFFF); 738039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com fGlyphCount = SkToU16(numGlyphs); 739a35ae01b7f409c673e990ea3b6a19a55080a1dcbskia.committer@gmail.com 740039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com fRec.getSingleMatrix(&fFUnitMatrix); 741039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com CGAffineTransform transform = MatrixToCGAffineTransform(fFUnitMatrix); 742039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com 743e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org AutoCFRelease<CTFontDescriptorRef> ctFontDesc; 744e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org if (fVertical) { 745e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org AutoCFRelease<CFMutableDictionaryRef> cfAttributes(CFDictionaryCreateMutable( 746e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org kCFAllocatorDefault, 0, 747e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org &kCFTypeDictionaryKeyCallBacks, 748e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org &kCFTypeDictionaryValueCallBacks)); 749e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org if (cfAttributes) { 750e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org CTFontOrientation ctOrientation = kCTFontVerticalOrientation; 751e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org AutoCFRelease<CFNumberRef> cfVertical(CFNumberCreate( 752e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org kCFAllocatorDefault, kCFNumberSInt32Type, &ctOrientation)); 753e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org CFDictionaryAddValue(cfAttributes, kCTFontOrientationAttribute, cfVertical); 754e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org ctFontDesc = CTFontDescriptorCreateWithAttributes(cfAttributes); 755e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org } 756e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org } 757039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com // Since our matrix includes everything, we pass 1 for size. 758039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com fCTFont = CTFontCreateCopyWithAttributes(ctFont, 1, &transform, ctFontDesc); 759e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org fCGFont = CTFontCopyGraphicsFont(fCTFont, NULL); 760e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org if (fVertical) { 761e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org CGAffineTransform rotateLeft = CGAffineTransformMake(0, -1, 1, 0, 0, 0); 762e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org transform = CGAffineTransformConcat(rotateLeft, transform); 763039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com fCTVerticalFont = CTFontCreateCopyWithAttributes(ctFont, 1, &transform, NULL); 764e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org } 765ebcf3fdc3ebc30b2a3cd73347b996a7a6da19cd3commit-bot@chromium.org 766039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com SkScalar emPerFUnit = SkScalarInvert(SkIntToScalar(CGFontGetUnitsPerEm(fCGFont))); 767039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com fFUnitMatrix.preScale(emPerFUnit, -emPerFUnit); 768e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org} 769e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 770e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.orgCGRGBPixel* Offscreen::getCG(const SkScalerContext_Mac& context, const SkGlyph& glyph, 771e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org CGGlyph glyphID, size_t* rowBytesPtr, 772e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org bool generateA8FromLCD) { 773e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org if (!fRGBSpace) { 774e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org //It doesn't appear to matter what color space is specified. 775e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org //Regular blends and antialiased text are always (s*a + d*(1-a)) 776e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org //and smoothed text is always g=2.0. 777e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org fRGBSpace = CGColorSpaceCreateDeviceRGB(); 778e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org } 779e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 780e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org // default to kBW_Format 781e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org bool doAA = false; 782e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org bool doLCD = false; 783e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 784e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org if (SkMask::kBW_Format != glyph.fMaskFormat) { 785e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org doLCD = true; 786e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org doAA = true; 787e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org } 788e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 789e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org // FIXME: lcd smoothed un-hinted rasterization unsupported. 790e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org if (!generateA8FromLCD && SkMask::kA8_Format == glyph.fMaskFormat) { 791e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org doLCD = false; 792e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org doAA = true; 793e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org } 794e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 795e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org size_t rowBytes = fSize.fWidth * sizeof(CGRGBPixel); 796e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org if (!fCG || fSize.fWidth < glyph.fWidth || fSize.fHeight < glyph.fHeight) { 797e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org if (fSize.fWidth < glyph.fWidth) { 798e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org fSize.fWidth = RoundSize(glyph.fWidth); 799e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org } 800e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org if (fSize.fHeight < glyph.fHeight) { 801e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org fSize.fHeight = RoundSize(glyph.fHeight); 802e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org } 803e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 804e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org rowBytes = fSize.fWidth * sizeof(CGRGBPixel); 805e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org void* image = fImageStorage.reset(rowBytes * fSize.fHeight); 806e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org fCG = CGBitmapContextCreate(image, fSize.fWidth, fSize.fHeight, 8, 807e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org rowBytes, fRGBSpace, BITMAP_INFO_RGB); 808e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 809e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org // skia handles quantization itself, so we disable this for cg to get 810e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org // full fractional data from them. 811e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org CGContextSetAllowsFontSubpixelQuantization(fCG, false); 812e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org CGContextSetShouldSubpixelQuantizeFonts(fCG, false); 813e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 814e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org CGContextSetTextDrawingMode(fCG, kCGTextFill); 815e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org CGContextSetFont(fCG, context.fCGFont); 816039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com CGContextSetFontSize(fCG, 1 /*CTFontGetSize(context.fCTFont)*/); 817039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com CGContextSetTextMatrix(fCG, CTFontGetMatrix(context.fCTFont)); 818e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 819039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com // Because CG always draws from the horizontal baseline, 820039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com // if there is a non-integral translation from the horizontal origin to the vertical origin, 821039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com // then CG cannot draw the glyph in the correct location without subpixel positioning. 822039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com CGContextSetAllowsFontSubpixelPositioning(fCG, context.fDoSubPosition || context.fVertical); 823039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com CGContextSetShouldSubpixelPositionFonts(fCG, context.fDoSubPosition || context.fVertical); 824e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 825e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org // Draw white on black to create mask. 826e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org // TODO: Draw black on white and invert, CG has a special case codepath. 827e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org CGContextSetGrayFillColor(fCG, 1.0f, 1.0f); 828e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 829e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org // force our checks below to happen 830e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org fDoAA = !doAA; 831e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org fDoLCD = !doLCD; 832e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org } 833e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 834e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org if (fDoAA != doAA) { 835e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org CGContextSetShouldAntialias(fCG, doAA); 836e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org fDoAA = doAA; 837e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org } 838e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org if (fDoLCD != doLCD) { 839e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org CGContextSetShouldSmoothFonts(fCG, doLCD); 840e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org fDoLCD = doLCD; 841e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org } 842e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 843e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org CGRGBPixel* image = (CGRGBPixel*)fImageStorage.get(); 844e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org // skip rows based on the glyph's height 845e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org image += (fSize.fHeight - glyph.fHeight) * fSize.fWidth; 846e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 847e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org // erase to black 848e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org sk_memset_rect32(image, 0, glyph.fWidth, glyph.fHeight, rowBytes); 849e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 850e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org float subX = 0; 851e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org float subY = 0; 852e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org if (context.fDoSubPosition) { 853e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org subX = SkFixedToFloat(glyph.getSubXFixed()); 854e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org subY = SkFixedToFloat(glyph.getSubYFixed()); 855e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org } 856a35ae01b7f409c673e990ea3b6a19a55080a1dcbskia.committer@gmail.com 857039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com // CGContextShowGlyphsAtPoint always draws using the horizontal baseline origin. 858e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org if (context.fVertical) { 859039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com SkPoint offset; 860e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org context.getVerticalOffset(glyphID, &offset); 861e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org subX += offset.fX; 862e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org subY += offset.fY; 863e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org } 864a35ae01b7f409c673e990ea3b6a19a55080a1dcbskia.committer@gmail.com 865e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org CGContextShowGlyphsAtPoint(fCG, -glyph.fLeft + subX, 866e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org glyph.fTop + glyph.fHeight - subY, 867e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org &glyphID, 1); 868e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 869e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org SkASSERT(rowBytesPtr); 870e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org *rowBytesPtr = rowBytes; 871e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org return image; 872e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org} 873e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 874039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.comvoid SkScalerContext_Mac::getVerticalOffset(CGGlyph glyphID, SkPoint* offset) const { 875039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com // Snow Leopard returns cgVertOffset in completely un-transformed FUnits (em space, y up). 876039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com // Lion and Leopard return cgVertOffset in CG units (pixels, y up). 877039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com CGSize cgVertOffset; 878039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com CTFontGetVerticalTranslationsForGlyphs(fCTFont, &glyphID, &cgVertOffset, 1); 879039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com 880039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com SkPoint skVertOffset = { CGToScalar(cgVertOffset.width), CGToScalar(cgVertOffset.height) }; 881039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com if (isSnowLeopard()) { 882039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com // From FUnits (em space, y up) to SkGlyph units (pixels, y down). 883039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com fFUnitMatrix.mapPoints(&skVertOffset, 1); 884039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com } else { 885039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com // From CG units (pixels, y up) to SkGlyph units (pixels, y down). 886039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com skVertOffset.fY = -skVertOffset.fY; 887039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com } 888a35ae01b7f409c673e990ea3b6a19a55080a1dcbskia.committer@gmail.com 889039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com *offset = skVertOffset; 890039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com} 891e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 892e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.orguint16_t SkScalerContext_Mac::getFBoundingBoxesGlyphOffset() { 893e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org if (fFBoundingBoxesGlyphOffset) { 894e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org return fFBoundingBoxesGlyphOffset; 895e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org } 896e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org fFBoundingBoxesGlyphOffset = fGlyphCount; // fallback for all fonts 897e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org AutoCGTable<SkOTTableHorizontalHeader> hheaTable(fCGFont); 898e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org if (hheaTable.fData) { 899e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org fFBoundingBoxesGlyphOffset = SkEndian_SwapBE16(hheaTable->numberOfHMetrics); 900e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org } 901e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org return fFBoundingBoxesGlyphOffset; 902e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org} 903e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 904e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.orgbool SkScalerContext_Mac::generateBBoxes() { 905e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org if (fGeneratedFBoundingBoxes) { 906039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com return NULL != fFBoundingBoxes.get(); 907e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org } 908e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org fGeneratedFBoundingBoxes = true; 909e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 910e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org AutoCGTable<SkOTTableHead> headTable(fCGFont); 911e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org if (!headTable.fData) { 912e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org return false; 913e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org } 914e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 915e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org AutoCGTable<SkOTTableIndexToLocation> locaTable(fCGFont); 916e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org if (!locaTable.fData) { 917e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org return false; 918e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org } 919e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 920e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org AutoCGTable<SkOTTableGlyph> glyfTable(fCGFont); 921e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org if (!glyfTable.fData) { 922e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org return false; 923e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org } 924e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 925e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org uint16_t entries = fGlyphCount - fFBoundingBoxesGlyphOffset; 926039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com fFBoundingBoxes.reset(entries); 927e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 928e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org SkOTTableHead::IndexToLocFormat locaFormat = headTable->indexToLocFormat; 929e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org SkOTTableGlyph::Iterator glyphDataIter(*glyfTable.fData, *locaTable.fData, locaFormat); 930e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org glyphDataIter.advance(fFBoundingBoxesGlyphOffset); 931e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org for (uint16_t boundingBoxesIndex = 0; boundingBoxesIndex < entries; ++boundingBoxesIndex) { 932e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org const SkOTTableGlyphData* glyphData = glyphDataIter.next(); 933e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org GlyphRect& rect = fFBoundingBoxes[boundingBoxesIndex]; 934e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org rect.fMinX = SkEndian_SwapBE16(glyphData->xMin); 935e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org rect.fMinY = SkEndian_SwapBE16(glyphData->yMin); 936e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org rect.fMaxX = SkEndian_SwapBE16(glyphData->xMax); 937e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org rect.fMaxY = SkEndian_SwapBE16(glyphData->yMax); 938e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org } 939ebcf3fdc3ebc30b2a3cd73347b996a7a6da19cd3commit-bot@chromium.org 940e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org return true; 941e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org} 942e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 943e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.orgunsigned SkScalerContext_Mac::generateGlyphCount(void) { 944e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org return fGlyphCount; 945e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org} 946e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 947e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.orguint16_t SkScalerContext_Mac::generateCharToGlyph(SkUnichar uni) { 948e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org CGGlyph cgGlyph; 949e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org UniChar theChar; 950e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 951e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org // Validate our parameters and state 952e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org SkASSERT(uni <= 0x0000FFFF); 953e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org SkASSERT(sizeof(CGGlyph) <= sizeof(uint16_t)); 954e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 955e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org // Get the glyph 956e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org theChar = (UniChar) uni; 957e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 958e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org if (!CTFontGetGlyphsForCharacters(fCTFont, &theChar, &cgGlyph, 1)) { 959e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org cgGlyph = 0; 960e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org } 961e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 962e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org return cgGlyph; 963e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org} 964e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 965e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.orgvoid SkScalerContext_Mac::generateAdvance(SkGlyph* glyph) { 966e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org this->generateMetrics(glyph); 967e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org} 968e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 969039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.comvoid SkScalerContext_Mac::generateMetrics(SkGlyph* glyph) { 970039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com const CGGlyph cgGlyph = (CGGlyph) glyph->getGlyphID(fBaseGlyphCount); 971039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com glyph->zeroMetrics(); 972a35ae01b7f409c673e990ea3b6a19a55080a1dcbskia.committer@gmail.com 973039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com // The following block produces cgAdvance in CG units (pixels, y up). 974039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com CGSize cgAdvance; 975039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com if (fVertical) { 976039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com CTFontGetAdvancesForGlyphs(fCTVerticalFont, kCTFontVerticalOrientation, 977039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com &cgGlyph, &cgAdvance, 1); 978039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com } else { 979039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com CTFontGetAdvancesForGlyphs(fCTFont, kCTFontHorizontalOrientation, 980039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com &cgGlyph, &cgAdvance, 1); 981039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com } 982039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com glyph->fAdvanceX = SkFloatToFixed_Check(cgAdvance.width); 983039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com glyph->fAdvanceY = -SkFloatToFixed_Check(cgAdvance.height); 984039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com 985039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com // The following produces skBounds in SkGlyph units (pixels, y down), 986039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com // or returns early if skBounds would be empty. 987039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com SkRect skBounds; 988a35ae01b7f409c673e990ea3b6a19a55080a1dcbskia.committer@gmail.com 989039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com // On Mountain Lion, CTFontGetBoundingRectsForGlyphs with kCTFontVerticalOrientation and 990039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com // CTFontGetVerticalTranslationsForGlyphs do not agree when using OTF CFF fonts. 991039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com // For TTF fonts these two do agree and we can use CTFontGetBoundingRectsForGlyphs to get 992039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com // the bounding box and CTFontGetVerticalTranslationsForGlyphs to then draw the glyph 993039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com // inside that bounding box. However, with OTF CFF fonts this does not work. It appears that 994039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com // CTFontGetBoundingRectsForGlyphs with kCTFontVerticalOrientation on OTF CFF fonts tries 995039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com // to center the glyph along the vertical baseline and also perform some mysterious shift 996039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com // along the baseline. CTFontGetVerticalTranslationsForGlyphs does not appear to perform 997039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com // these steps. 998039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com // 999039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com // It is not known which is correct (or if either is correct). However, we must always draw 1000039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com // from the horizontal origin and must use CTFontGetVerticalTranslationsForGlyphs to draw. 1001039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com // As a result, we do not call CTFontGetBoundingRectsForGlyphs for vertical glyphs. 1002a35ae01b7f409c673e990ea3b6a19a55080a1dcbskia.committer@gmail.com 1003039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com // On Snow Leopard, CTFontGetBoundingRectsForGlyphs ignores kCTFontVerticalOrientation and 1004039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com // returns horizontal bounds. 1005a35ae01b7f409c673e990ea3b6a19a55080a1dcbskia.committer@gmail.com 1006039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com // On Lion and Mountain Lion, CTFontGetBoundingRectsForGlyphs has a bug which causes it to 1007039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com // return a bad value in cgBounds.origin.x for SFNT fonts whose hhea::numberOfHMetrics is 1008039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com // less than its maxp::numGlyphs. When this is the case we try to read the bounds from the 1009039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com // font directly. 1010039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com if ((isLion() || isMountainLion()) && 1011039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com (cgGlyph < fGlyphCount && cgGlyph >= getFBoundingBoxesGlyphOffset() && generateBBoxes())) 1012039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com { 1013039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com const GlyphRect& gRect = fFBoundingBoxes[cgGlyph - fFBoundingBoxesGlyphOffset]; 1014039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com if (gRect.fMinX >= gRect.fMaxX || gRect.fMinY >= gRect.fMaxY) { 1015039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com return; 1016039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com } 1017039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com skBounds = SkRect::MakeLTRB(gRect.fMinX, gRect.fMinY, gRect.fMaxX, gRect.fMaxY); 1018039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com // From FUnits (em space, y up) to SkGlyph units (pixels, y down). 1019039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com fFUnitMatrix.mapRect(&skBounds); 1020039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com 1021039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com } else { 1022039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com // CTFontGetBoundingRectsForGlyphs produces cgBounds in CG units (pixels, y up). 1023039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com CGRect cgBounds; 1024039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com CTFontGetBoundingRectsForGlyphs(fCTFont, kCTFontHorizontalOrientation, 1025039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com &cgGlyph, &cgBounds, 1); 1026a35ae01b7f409c673e990ea3b6a19a55080a1dcbskia.committer@gmail.com 1027039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com // BUG? 1028039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com // 0x200B (zero-advance space) seems to return a huge (garbage) bounds, when 1029039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com // it should be empty. So, if we see a zero-advance, we check if it has an 1030039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com // empty path or not, and if so, we jam the bounds to 0. Hopefully a zero-advance 1031039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com // is rare, so we won't incur a big performance cost for this extra check. 1032039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com if (0 == cgAdvance.width && 0 == cgAdvance.height) { 1033039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com AutoCFRelease<CGPathRef> path(CTFontCreatePathForGlyph(fCTFont, cgGlyph, NULL)); 1034039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com if (NULL == path || CGPathIsEmpty(path)) { 1035039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com return; 1036039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com } 1037039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com } 1038039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com 1039039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com if (CGRectIsEmpty_inline(cgBounds)) { 1040039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com return; 1041039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com } 1042039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com 1043039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com // Convert cgBounds to SkGlyph units (pixels, y down). 1044039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com skBounds = SkRect::MakeXYWH(cgBounds.origin.x, -cgBounds.origin.y - cgBounds.size.height, 1045039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com cgBounds.size.width, cgBounds.size.height); 1046039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com } 1047039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com 1048039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com if (fVertical) { 1049039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com // Due to all of the vertical bounds bugs, skBounds is always the horizontal bounds. 1050039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com // Convert these horizontal bounds into vertical bounds. 1051039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com SkPoint offset; 1052039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com getVerticalOffset(cgGlyph, &offset); 1053039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com skBounds.offset(offset); 1054039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com } 1055a35ae01b7f409c673e990ea3b6a19a55080a1dcbskia.committer@gmail.com 1056039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com // Currently the bounds are based on being rendered at (0,0). 1057039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com // The top left must not move, since that is the base from which subpixel positioning is offset. 1058039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com if (fDoSubPosition) { 1059039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com skBounds.fRight += SkFixedToFloat(glyph->getSubXFixed()); 1060039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com skBounds.fBottom += SkFixedToFloat(glyph->getSubYFixed()); 1061039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com } 1062a35ae01b7f409c673e990ea3b6a19a55080a1dcbskia.committer@gmail.com 1063039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com SkIRect skIBounds; 1064039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com skBounds.roundOut(&skIBounds); 1065039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com // Expand the bounds by 1 pixel, to give CG room for anti-aliasing. 1066039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com // Note that this outset is to allow room for LCD smoothed glyphs. However, the correct outset 1067039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com // is not currently known, as CG dilates the outlines by some percentage. 1068039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com // Note that if this context is A8 and not back-forming from LCD, there is no need to outset. 1069039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com skIBounds.outset(1, 1); 1070039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com glyph->fLeft = SkToS16(skIBounds.fLeft); 1071039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com glyph->fTop = SkToS16(skIBounds.fTop); 1072039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com glyph->fWidth = SkToU16(skIBounds.width()); 1073039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com glyph->fHeight = SkToU16(skIBounds.height()); 1074a35ae01b7f409c673e990ea3b6a19a55080a1dcbskia.committer@gmail.com 1075039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com#ifdef HACK_COLORGLYPHS 1076039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com glyph->fMaskFormat = SkMask::kARGB32_Format; 1077039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com#endif 1078039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com} 1079e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 1080e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org#include "SkColorPriv.h" 1081e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 1082e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.orgstatic void build_power_table(uint8_t table[], float ee) { 1083e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org for (int i = 0; i < 256; i++) { 1084e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org float x = i / 255.f; 1085e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org x = sk_float_pow(x, ee); 1086e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org int xx = SkScalarRoundToInt(SkFloatToScalar(x * 255)); 1087e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org table[i] = SkToU8(xx); 1088e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org } 1089e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org} 1090e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 1091e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org/** 1092e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org * This will invert the gamma applied by CoreGraphics, so we can get linear 1093e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org * values. 1094e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org * 1095e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org * CoreGraphics obscurely defaults to 2.0 as the smoothing gamma value. 1096e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org * The color space used does not appear to affect this choice. 1097e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org */ 1098e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.orgstatic const uint8_t* getInverseGammaTableCoreGraphicSmoothing() { 1099e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org static bool gInited; 1100e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org static uint8_t gTableCoreGraphicsSmoothing[256]; 1101e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org if (!gInited) { 1102e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org build_power_table(gTableCoreGraphicsSmoothing, 2.0f); 1103e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org gInited = true; 1104e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org } 1105e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org return gTableCoreGraphicsSmoothing; 1106e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org} 1107e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 1108e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.orgstatic void cgpixels_to_bits(uint8_t dst[], const CGRGBPixel src[], int count) { 1109e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org while (count > 0) { 1110e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org uint8_t mask = 0; 1111e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org for (int i = 7; i >= 0; --i) { 1112e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org mask |= (CGRGBPixel_getAlpha(*src++) >> 7) << i; 1113e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org if (0 == --count) { 1114e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org break; 1115e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org } 1116e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org } 1117e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org *dst++ = mask; 1118e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org } 1119e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org} 1120e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 1121e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.orgtemplate<bool APPLY_PREBLEND> 1122e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.orgstatic inline uint8_t rgb_to_a8(CGRGBPixel rgb, const uint8_t* table8) { 1123e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org U8CPU r = (rgb >> 16) & 0xFF; 1124e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org U8CPU g = (rgb >> 8) & 0xFF; 1125e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org U8CPU b = (rgb >> 0) & 0xFF; 1126e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org return sk_apply_lut_if<APPLY_PREBLEND>(SkComputeLuminance(r, g, b), table8); 1127e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org} 1128e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.orgtemplate<bool APPLY_PREBLEND> 1129e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.orgstatic void rgb_to_a8(const CGRGBPixel* SK_RESTRICT cgPixels, size_t cgRowBytes, 1130e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org const SkGlyph& glyph, const uint8_t* table8) { 1131e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org const int width = glyph.fWidth; 1132e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org size_t dstRB = glyph.rowBytes(); 1133e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org uint8_t* SK_RESTRICT dst = (uint8_t*)glyph.fImage; 1134e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 1135e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org for (int y = 0; y < glyph.fHeight; y++) { 1136e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org for (int i = 0; i < width; ++i) { 1137e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org dst[i] = rgb_to_a8<APPLY_PREBLEND>(cgPixels[i], table8); 1138e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org } 1139e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org cgPixels = (CGRGBPixel*)((char*)cgPixels + cgRowBytes); 1140e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org dst += dstRB; 1141e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org } 1142e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org} 1143e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 1144e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.orgtemplate<bool APPLY_PREBLEND> 1145e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.orgstatic inline uint16_t rgb_to_lcd16(CGRGBPixel rgb, const uint8_t* tableR, 1146e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org const uint8_t* tableG, 1147e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org const uint8_t* tableB) { 1148e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org U8CPU r = sk_apply_lut_if<APPLY_PREBLEND>((rgb >> 16) & 0xFF, tableR); 1149e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org U8CPU g = sk_apply_lut_if<APPLY_PREBLEND>((rgb >> 8) & 0xFF, tableG); 1150e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org U8CPU b = sk_apply_lut_if<APPLY_PREBLEND>((rgb >> 0) & 0xFF, tableB); 1151e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org return SkPack888ToRGB16(r, g, b); 1152e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org} 1153e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.orgtemplate<bool APPLY_PREBLEND> 1154e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.orgstatic void rgb_to_lcd16(const CGRGBPixel* SK_RESTRICT cgPixels, size_t cgRowBytes, const SkGlyph& glyph, 1155e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org const uint8_t* tableR, const uint8_t* tableG, const uint8_t* tableB) { 1156e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org const int width = glyph.fWidth; 1157e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org size_t dstRB = glyph.rowBytes(); 1158e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org uint16_t* SK_RESTRICT dst = (uint16_t*)glyph.fImage; 1159e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 1160e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org for (int y = 0; y < glyph.fHeight; y++) { 1161e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org for (int i = 0; i < width; i++) { 1162e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org dst[i] = rgb_to_lcd16<APPLY_PREBLEND>(cgPixels[i], tableR, tableG, tableB); 1163e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org } 1164e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org cgPixels = (CGRGBPixel*)((char*)cgPixels + cgRowBytes); 1165e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org dst = (uint16_t*)((char*)dst + dstRB); 1166e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org } 1167e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org} 1168e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 1169e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.orgtemplate<bool APPLY_PREBLEND> 1170e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.orgstatic inline uint32_t rgb_to_lcd32(CGRGBPixel rgb, const uint8_t* tableR, 1171e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org const uint8_t* tableG, 1172e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org const uint8_t* tableB) { 1173e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org U8CPU r = sk_apply_lut_if<APPLY_PREBLEND>((rgb >> 16) & 0xFF, tableR); 1174e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org U8CPU g = sk_apply_lut_if<APPLY_PREBLEND>((rgb >> 8) & 0xFF, tableG); 1175e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org U8CPU b = sk_apply_lut_if<APPLY_PREBLEND>((rgb >> 0) & 0xFF, tableB); 1176e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org return SkPackARGB32(0xFF, r, g, b); 1177e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org} 1178e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.orgtemplate<bool APPLY_PREBLEND> 1179e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.orgstatic void rgb_to_lcd32(const CGRGBPixel* SK_RESTRICT cgPixels, size_t cgRowBytes, const SkGlyph& glyph, 1180e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org const uint8_t* tableR, const uint8_t* tableG, const uint8_t* tableB) { 1181e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org const int width = glyph.fWidth; 1182e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org size_t dstRB = glyph.rowBytes(); 1183e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org uint32_t* SK_RESTRICT dst = (uint32_t*)glyph.fImage; 1184e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org for (int y = 0; y < glyph.fHeight; y++) { 1185e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org for (int i = 0; i < width; i++) { 1186e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org dst[i] = rgb_to_lcd32<APPLY_PREBLEND>(cgPixels[i], tableR, tableG, tableB); 1187e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org } 1188e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org cgPixels = (CGRGBPixel*)((char*)cgPixels + cgRowBytes); 1189e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org dst = (uint32_t*)((char*)dst + dstRB); 1190e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org } 1191e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org} 1192e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 11931ac3facef9444119e9d389e6b7b082c3120f0791reed@google.com#ifdef HACK_COLORGLYPHS 11941ac3facef9444119e9d389e6b7b082c3120f0791reed@google.com// hack to colorize the output for testing kARGB32_Format 11951ac3facef9444119e9d389e6b7b082c3120f0791reed@google.comstatic SkPMColor cgpixels_to_pmcolor(CGRGBPixel rgb, const SkGlyph& glyph, 11961ac3facef9444119e9d389e6b7b082c3120f0791reed@google.com int x, int y) { 11971ac3facef9444119e9d389e6b7b082c3120f0791reed@google.com U8CPU r = (rgb >> 16) & 0xFF; 11981ac3facef9444119e9d389e6b7b082c3120f0791reed@google.com U8CPU g = (rgb >> 8) & 0xFF; 11991ac3facef9444119e9d389e6b7b082c3120f0791reed@google.com U8CPU b = (rgb >> 0) & 0xFF; 12001ac3facef9444119e9d389e6b7b082c3120f0791reed@google.com unsigned a = SkComputeLuminance(r, g, b); 120174546d80ff050eecbf2d3a21194f10860504e68dskia.committer@gmail.com 12021ac3facef9444119e9d389e6b7b082c3120f0791reed@google.com // compute gradient from x,y 12031ac3facef9444119e9d389e6b7b082c3120f0791reed@google.com r = x * 255 / glyph.fWidth; 12041ac3facef9444119e9d389e6b7b082c3120f0791reed@google.com g = 0; 12051ac3facef9444119e9d389e6b7b082c3120f0791reed@google.com b = (glyph.fHeight - y) * 255 / glyph.fHeight; 12061ac3facef9444119e9d389e6b7b082c3120f0791reed@google.com return SkPreMultiplyARGB(a, r, g, b); // red 12071ac3facef9444119e9d389e6b7b082c3120f0791reed@google.com} 12081ac3facef9444119e9d389e6b7b082c3120f0791reed@google.com#endif 12091ac3facef9444119e9d389e6b7b082c3120f0791reed@google.com 1210e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.orgtemplate <typename T> T* SkTAddByteOffset(T* ptr, size_t byteOffset) { 1211e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org return (T*)((char*)ptr + byteOffset); 1212e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org} 1213e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 1214e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.orgvoid SkScalerContext_Mac::generateImage(const SkGlyph& glyph) { 1215e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org CGGlyph cgGlyph = (CGGlyph) glyph.getGlyphID(fBaseGlyphCount); 1216e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 1217e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org // FIXME: lcd smoothed un-hinted rasterization unsupported. 1218e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org bool generateA8FromLCD = fRec.getHinting() != SkPaint::kNo_Hinting; 1219e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 1220e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org // Draw the glyph 1221e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org size_t cgRowBytes; 1222e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org CGRGBPixel* cgPixels = fOffscreen.getCG(*this, glyph, cgGlyph, &cgRowBytes, generateA8FromLCD); 1223e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org if (cgPixels == NULL) { 1224e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org return; 1225e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org } 1226e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 1227e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org //TODO: see if drawing black on white and inverting is faster (at least in 1228e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org //lcd case) as core graphics appears to have special case code for drawing 1229e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org //black text. 1230e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 1231e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org // Fix the glyph 1232e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org const bool isLCD = isLCDFormat(glyph.fMaskFormat); 1233e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org if (isLCD || (glyph.fMaskFormat == SkMask::kA8_Format && supports_LCD() && generateA8FromLCD)) { 1234e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org const uint8_t* table = getInverseGammaTableCoreGraphicSmoothing(); 1235e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 1236e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org //Note that the following cannot really be integrated into the 1237e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org //pre-blend, since we may not be applying the pre-blend; when we aren't 1238e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org //applying the pre-blend it means that a filter wants linear anyway. 1239e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org //Other code may also be applying the pre-blend, so we'd need another 1240e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org //one with this and one without. 1241e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org CGRGBPixel* addr = cgPixels; 1242e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org for (int y = 0; y < glyph.fHeight; ++y) { 1243e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org for (int x = 0; x < glyph.fWidth; ++x) { 1244e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org int r = (addr[x] >> 16) & 0xFF; 1245e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org int g = (addr[x] >> 8) & 0xFF; 1246e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org int b = (addr[x] >> 0) & 0xFF; 1247e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org addr[x] = (table[r] << 16) | (table[g] << 8) | table[b]; 1248e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org } 1249e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org addr = SkTAddByteOffset(addr, cgRowBytes); 1250e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org } 1251e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org } 1252e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 1253e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org // Convert glyph to mask 1254e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org switch (glyph.fMaskFormat) { 1255e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org case SkMask::kLCD32_Format: { 1256e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org if (fPreBlend.isApplicable()) { 1257e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org rgb_to_lcd32<true>(cgPixels, cgRowBytes, glyph, 1258e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org fPreBlend.fR, fPreBlend.fG, fPreBlend.fB); 1259e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org } else { 1260e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org rgb_to_lcd32<false>(cgPixels, cgRowBytes, glyph, 1261e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org fPreBlend.fR, fPreBlend.fG, fPreBlend.fB); 1262e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org } 1263e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org } break; 1264e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org case SkMask::kLCD16_Format: { 1265e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org if (fPreBlend.isApplicable()) { 1266e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org rgb_to_lcd16<true>(cgPixels, cgRowBytes, glyph, 1267e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org fPreBlend.fR, fPreBlend.fG, fPreBlend.fB); 1268e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org } else { 1269e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org rgb_to_lcd16<false>(cgPixels, cgRowBytes, glyph, 1270e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org fPreBlend.fR, fPreBlend.fG, fPreBlend.fB); 1271e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org } 1272e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org } break; 1273e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org case SkMask::kA8_Format: { 1274e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org if (fPreBlend.isApplicable()) { 1275e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org rgb_to_a8<true>(cgPixels, cgRowBytes, glyph, fPreBlend.fG); 1276e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org } else { 1277e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org rgb_to_a8<false>(cgPixels, cgRowBytes, glyph, fPreBlend.fG); 1278e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org } 1279e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org } break; 1280e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org case SkMask::kBW_Format: { 1281e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org const int width = glyph.fWidth; 1282e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org size_t dstRB = glyph.rowBytes(); 1283e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org uint8_t* dst = (uint8_t*)glyph.fImage; 1284e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org for (int y = 0; y < glyph.fHeight; y++) { 1285e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org cgpixels_to_bits(dst, cgPixels, width); 1286e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org cgPixels = (CGRGBPixel*)((char*)cgPixels + cgRowBytes); 1287e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org dst += dstRB; 1288e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org } 1289e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org } break; 12901ac3facef9444119e9d389e6b7b082c3120f0791reed@google.com#ifdef HACK_COLORGLYPHS 12911ac3facef9444119e9d389e6b7b082c3120f0791reed@google.com case SkMask::kARGB32_Format: { 12921ac3facef9444119e9d389e6b7b082c3120f0791reed@google.com const int width = glyph.fWidth; 12931ac3facef9444119e9d389e6b7b082c3120f0791reed@google.com size_t dstRB = glyph.rowBytes(); 12941ac3facef9444119e9d389e6b7b082c3120f0791reed@google.com SkPMColor* dst = (SkPMColor*)glyph.fImage; 12951ac3facef9444119e9d389e6b7b082c3120f0791reed@google.com for (int y = 0; y < glyph.fHeight; y++) { 12961ac3facef9444119e9d389e6b7b082c3120f0791reed@google.com for (int x = 0; x < width; ++x) { 12971ac3facef9444119e9d389e6b7b082c3120f0791reed@google.com dst[x] = cgpixels_to_pmcolor(cgPixels[x], glyph, x, y); 12981ac3facef9444119e9d389e6b7b082c3120f0791reed@google.com } 12991ac3facef9444119e9d389e6b7b082c3120f0791reed@google.com cgPixels = (CGRGBPixel*)((char*)cgPixels + cgRowBytes); 13001ac3facef9444119e9d389e6b7b082c3120f0791reed@google.com dst = (SkPMColor*)((char*)dst + dstRB); 13011ac3facef9444119e9d389e6b7b082c3120f0791reed@google.com } 13021ac3facef9444119e9d389e6b7b082c3120f0791reed@google.com } break; 13031ac3facef9444119e9d389e6b7b082c3120f0791reed@google.com#endif 1304e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org default: 1305e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org SkDEBUGFAIL("unexpected mask format"); 1306e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org break; 1307e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org } 1308e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org} 1309e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 1310e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org/* 1311e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org * Our subpixel resolution is only 2 bits in each direction, so a scale of 4 1312e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org * seems sufficient, and possibly even correct, to allow the hinted outline 1313e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org * to be subpixel positioned. 1314e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org */ 1315e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org#define kScaleForSubPixelPositionHinting (4.0f) 1316e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 1317e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.orgvoid SkScalerContext_Mac::generatePath(const SkGlyph& glyph, SkPath* path) { 1318e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org CTFontRef font = fCTFont; 1319e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org SkScalar scaleX = SK_Scalar1; 1320e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org SkScalar scaleY = SK_Scalar1; 1321e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 1322e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org /* 1323e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org * For subpixel positioning, we want to return an unhinted outline, so it 1324e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org * can be positioned nicely at fractional offsets. However, we special-case 1325e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org * if the baseline of the (horizontal) text is axis-aligned. In those cases 1326e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org * we want to retain hinting in the direction orthogonal to the baseline. 1327e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org * e.g. for horizontal baseline, we want to retain hinting in Y. 1328e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org * The way we remove hinting is to scale the font by some value (4) in that 1329e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org * direction, ask for the path, and then scale the path back down. 1330e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org */ 1331e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org if (fRec.fFlags & SkScalerContext::kSubpixelPositioning_Flag) { 1332e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org SkMatrix m; 1333e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org fRec.getSingleMatrix(&m); 1334e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 1335e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org // start out by assuming that we want no hining in X and Y 1336e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org scaleX = scaleY = SkFloatToScalar(kScaleForSubPixelPositionHinting); 1337e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org // now see if we need to restore hinting for axis-aligned baselines 1338e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org switch (SkComputeAxisAlignmentForHText(m)) { 1339e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org case kX_SkAxisAlignment: 1340e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org scaleY = SK_Scalar1; // want hinting in the Y direction 1341e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org break; 1342e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org case kY_SkAxisAlignment: 1343e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org scaleX = SK_Scalar1; // want hinting in the X direction 1344e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org break; 1345e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org default: 1346e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org break; 1347e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org } 1348e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 1349e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org CGAffineTransform xform = MatrixToCGAffineTransform(m, scaleX, scaleY); 1350e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org // need to release font when we're done 1351e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org font = CTFontCreateCopyWithAttributes(fCTFont, 1, &xform, NULL); 1352e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org } 1353e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 1354e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org CGGlyph cgGlyph = (CGGlyph)glyph.getGlyphID(fBaseGlyphCount); 1355e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org AutoCFRelease<CGPathRef> cgPath(CTFontCreatePathForGlyph(font, cgGlyph, NULL)); 1356e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 1357e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org path->reset(); 1358e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org if (cgPath != NULL) { 1359e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org CGPathApply(cgPath, path, SkScalerContext_Mac::CTPathElement); 1360e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org } 1361e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 1362039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com if (fDoSubPosition) { 1363e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org SkMatrix m; 1364e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org m.setScale(SkScalarInvert(scaleX), SkScalarInvert(scaleY)); 1365e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org path->transform(m); 1366e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org // balance the call to CTFontCreateCopyWithAttributes 1367e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org CFSafeRelease(font); 1368e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org } 1369039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com if (fVertical) { 1370039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com SkPoint offset; 1371039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com getVerticalOffset(cgGlyph, &offset); 1372039261bd15e9a1dfa7871703d7baac2b84a25298bungeman@google.com path->offset(offset.fX, offset.fY); 1373e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org } 1374e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org} 1375e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 1376e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.orgvoid SkScalerContext_Mac::generateFontMetrics(SkPaint::FontMetrics* mx, 1377e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org SkPaint::FontMetrics* my) { 1378e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org CGRect theBounds = CTFontGetBoundingBox(fCTFont); 1379e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 1380e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org SkPaint::FontMetrics theMetrics; 1381e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org theMetrics.fTop = CGToScalar(-CGRectGetMaxY_inline(theBounds)); 1382e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org theMetrics.fAscent = CGToScalar(-CTFontGetAscent(fCTFont)); 1383e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org theMetrics.fDescent = CGToScalar( CTFontGetDescent(fCTFont)); 1384e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org theMetrics.fBottom = CGToScalar(-CGRectGetMinY_inline(theBounds)); 1385e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org theMetrics.fLeading = CGToScalar( CTFontGetLeading(fCTFont)); 1386e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org theMetrics.fAvgCharWidth = CGToScalar( CGRectGetWidth_inline(theBounds)); 1387e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org theMetrics.fXMin = CGToScalar( CGRectGetMinX_inline(theBounds)); 1388e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org theMetrics.fXMax = CGToScalar( CGRectGetMaxX_inline(theBounds)); 1389e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org theMetrics.fXHeight = CGToScalar( CTFontGetXHeight(fCTFont)); 1390e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 1391e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org if (mx != NULL) { 1392e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org *mx = theMetrics; 1393e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org } 1394e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org if (my != NULL) { 1395e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org *my = theMetrics; 1396e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org } 1397e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org} 1398e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 1399e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.orgvoid SkScalerContext_Mac::CTPathElement(void *info, const CGPathElement *element) { 1400e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org SkPath* skPath = (SkPath*)info; 1401e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 1402e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org // Process the path element 1403e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org switch (element->type) { 1404e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org case kCGPathElementMoveToPoint: 1405e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org skPath->moveTo(element->points[0].x, -element->points[0].y); 1406e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org break; 1407e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 1408e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org case kCGPathElementAddLineToPoint: 1409e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org skPath->lineTo(element->points[0].x, -element->points[0].y); 1410e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org break; 1411e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 1412e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org case kCGPathElementAddQuadCurveToPoint: 1413e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org skPath->quadTo(element->points[0].x, -element->points[0].y, 1414e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org element->points[1].x, -element->points[1].y); 1415e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org break; 1416e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 1417e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org case kCGPathElementAddCurveToPoint: 1418e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org skPath->cubicTo(element->points[0].x, -element->points[0].y, 1419e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org element->points[1].x, -element->points[1].y, 1420e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org element->points[2].x, -element->points[2].y); 1421e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org break; 1422e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 1423e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org case kCGPathElementCloseSubpath: 1424e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org skPath->close(); 1425e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org break; 1426e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 1427e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org default: 1428e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org SkDEBUGFAIL("Unknown path element!"); 1429e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org break; 1430e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org } 1431e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org} 1432e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 1433e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 1434e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org/////////////////////////////////////////////////////////////////////////////// 1435e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 1436e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org// Returns NULL on failure 1437e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org// Call must still manage its ownership of provider 1438e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.orgstatic SkTypeface* create_from_dataProvider(CGDataProviderRef provider) { 1439e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org AutoCFRelease<CGFontRef> cg(CGFontCreateWithDataProvider(provider)); 1440e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org if (NULL == cg) { 1441e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org return NULL; 1442e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org } 1443e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org CTFontRef ct = CTFontCreateWithGraphicsFont(cg, 0, NULL, NULL); 1444e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org return cg ? SkCreateTypefaceFromCTFont(ct) : NULL; 1445e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org} 1446e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 1447e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org// Web fonts added to the the CTFont registry do not return their character set. 1448e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org// Iterate through the font in this case. The existing caller caches the result, 1449e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org// so the performance impact isn't too bad. 1450e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.orgstatic void populate_glyph_to_unicode_slow(CTFontRef ctFont, CFIndex glyphCount, 1451e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org SkTDArray<SkUnichar>* glyphToUnicode) { 1452e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org glyphToUnicode->setCount(glyphCount); 1453e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org SkUnichar* out = glyphToUnicode->begin(); 1454e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org sk_bzero(out, glyphCount * sizeof(SkUnichar)); 1455e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org UniChar unichar = 0; 1456e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org while (glyphCount > 0) { 1457e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org CGGlyph glyph; 1458e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org if (CTFontGetGlyphsForCharacters(ctFont, &unichar, &glyph, 1)) { 1459e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org out[glyph] = unichar; 1460e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org --glyphCount; 1461e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org } 1462e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org if (++unichar == 0) { 1463e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org break; 1464e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org } 1465e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org } 1466e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org} 1467e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 1468e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org// Construct Glyph to Unicode table. 1469e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org// Unicode code points that require conjugate pairs in utf16 are not 1470e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org// supported. 1471e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.orgstatic void populate_glyph_to_unicode(CTFontRef ctFont, CFIndex glyphCount, 1472e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org SkTDArray<SkUnichar>* glyphToUnicode) { 1473e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org AutoCFRelease<CFCharacterSetRef> charSet(CTFontCopyCharacterSet(ctFont)); 1474e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org if (!charSet) { 1475e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org populate_glyph_to_unicode_slow(ctFont, glyphCount, glyphToUnicode); 1476e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org return; 1477e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org } 1478e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 1479e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org AutoCFRelease<CFDataRef> bitmap(CFCharacterSetCreateBitmapRepresentation(kCFAllocatorDefault, 1480e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org charSet)); 1481e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org if (!bitmap) { 1482e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org return; 1483e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org } 1484e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org CFIndex length = CFDataGetLength(bitmap); 1485e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org if (!length) { 1486e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org return; 1487e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org } 1488e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org if (length > 8192) { 1489e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org // TODO: Add support for Unicode above 0xFFFF 1490e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org // Consider only the BMP portion of the Unicode character points. 1491e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org // The bitmap may contain other planes, up to plane 16. 1492e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org // See http://developer.apple.com/library/ios/#documentation/CoreFoundation/Reference/CFCharacterSetRef/Reference/reference.html 1493e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org length = 8192; 1494e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org } 1495e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org const UInt8* bits = CFDataGetBytePtr(bitmap); 1496e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org glyphToUnicode->setCount(glyphCount); 1497e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org SkUnichar* out = glyphToUnicode->begin(); 1498e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org sk_bzero(out, glyphCount * sizeof(SkUnichar)); 1499e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org for (int i = 0; i < length; i++) { 1500e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org int mask = bits[i]; 1501e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org if (!mask) { 1502e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org continue; 1503e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org } 1504e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org for (int j = 0; j < 8; j++) { 1505e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org CGGlyph glyph; 1506e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org UniChar unichar = static_cast<UniChar>((i << 3) + j); 1507e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org if (mask & (1 << j) && CTFontGetGlyphsForCharacters(ctFont, &unichar, &glyph, 1)) { 1508e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org out[glyph] = unichar; 1509e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org } 1510e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org } 1511e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org } 1512e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org} 1513e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 1514e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.orgstatic bool getWidthAdvance(CTFontRef ctFont, int gId, int16_t* data) { 1515e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org CGSize advance; 1516e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org advance.width = 0; 1517e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org CGGlyph glyph = gId; 1518e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org CTFontGetAdvancesForGlyphs(ctFont, kCTFontHorizontalOrientation, &glyph, &advance, 1); 1519e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org *data = sk_float_round2int(advance.width); 1520e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org return true; 1521e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org} 1522e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 1523e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org// we might move this into our CGUtils... 1524e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.orgstatic void CFStringToSkString(CFStringRef src, SkString* dst) { 1525e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org // Reserve enough room for the worst-case string, 1526e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org // plus 1 byte for the trailing null. 1527e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org CFIndex length = CFStringGetMaximumSizeForEncoding(CFStringGetLength(src), 1528e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org kCFStringEncodingUTF8) + 1; 1529e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org dst->resize(length); 1530e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org CFStringGetCString(src, dst->writable_str(), length, kCFStringEncodingUTF8); 1531e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org // Resize to the actual UTF-8 length used, stripping the null character. 1532e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org dst->resize(strlen(dst->c_str())); 1533e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org} 1534e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 15353dca9a6576d2baaf6132bbe736e8597723cbc5acreed@google.comSkAdvancedTypefaceMetrics* SkTypeface_Mac::onGetAdvancedTypefaceMetrics( 1536e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org SkAdvancedTypefaceMetrics::PerGlyphInfo perGlyphInfo, 1537e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org const uint32_t* glyphIDs, 15383dca9a6576d2baaf6132bbe736e8597723cbc5acreed@google.com uint32_t glyphIDsCount) const { 15393dca9a6576d2baaf6132bbe736e8597723cbc5acreed@google.com 15403dca9a6576d2baaf6132bbe736e8597723cbc5acreed@google.com CTFontRef originalCTFont = fFontRef.get(); 1541e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org AutoCFRelease<CTFontRef> ctFont(CTFontCreateCopyWithAttributes( 1542e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org originalCTFont, CTFontGetUnitsPerEm(originalCTFont), NULL, NULL)); 1543e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org SkAdvancedTypefaceMetrics* info = new SkAdvancedTypefaceMetrics; 1544e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 1545e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org { 1546e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org AutoCFRelease<CFStringRef> fontName(CTFontCopyPostScriptName(ctFont)); 1547e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org CFStringToSkString(fontName, &info->fFontName); 1548e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org } 1549e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 1550e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org info->fMultiMaster = false; 1551e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org CFIndex glyphCount = CTFontGetGlyphCount(ctFont); 1552e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org info->fLastGlyphID = SkToU16(glyphCount - 1); 1553e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org info->fEmSize = CTFontGetUnitsPerEm(ctFont); 1554e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 1555e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org if (perGlyphInfo & SkAdvancedTypefaceMetrics::kToUnicode_PerGlyphInfo) { 1556e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org populate_glyph_to_unicode(ctFont, glyphCount, &info->fGlyphToUnicode); 1557e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org } 1558e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 1559e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org info->fStyle = 0; 1560e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 1561e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org // If it's not a truetype font, mark it as 'other'. Assume that TrueType 1562e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org // fonts always have both glyf and loca tables. At the least, this is what 1563e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org // sfntly needs to subset the font. CTFontCopyAttribute() does not always 1564e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org // succeed in determining this directly. 15653dca9a6576d2baaf6132bbe736e8597723cbc5acreed@google.com if (!this->getTableSize('glyf') || !this->getTableSize('loca')) { 1566e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org info->fType = SkAdvancedTypefaceMetrics::kOther_Font; 1567e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org info->fItalicAngle = 0; 1568e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org info->fAscent = 0; 1569e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org info->fDescent = 0; 1570e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org info->fStemV = 0; 1571e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org info->fCapHeight = 0; 1572e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org info->fBBox = SkIRect::MakeEmpty(); 1573e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org return info; 1574e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org } 1575e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 1576e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org info->fType = SkAdvancedTypefaceMetrics::kTrueType_Font; 1577e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org CTFontSymbolicTraits symbolicTraits = CTFontGetSymbolicTraits(ctFont); 1578e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org if (symbolicTraits & kCTFontMonoSpaceTrait) { 1579e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org info->fStyle |= SkAdvancedTypefaceMetrics::kFixedPitch_Style; 1580e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org } 1581e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org if (symbolicTraits & kCTFontItalicTrait) { 1582e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org info->fStyle |= SkAdvancedTypefaceMetrics::kItalic_Style; 1583e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org } 1584e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org CTFontStylisticClass stylisticClass = symbolicTraits & kCTFontClassMaskTrait; 1585e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org if (stylisticClass >= kCTFontOldStyleSerifsClass && stylisticClass <= kCTFontSlabSerifsClass) { 1586e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org info->fStyle |= SkAdvancedTypefaceMetrics::kSerif_Style; 1587e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org } else if (stylisticClass & kCTFontScriptsClass) { 1588e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org info->fStyle |= SkAdvancedTypefaceMetrics::kScript_Style; 1589e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org } 1590e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org info->fItalicAngle = (int16_t) CTFontGetSlantAngle(ctFont); 1591e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org info->fAscent = (int16_t) CTFontGetAscent(ctFont); 1592e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org info->fDescent = (int16_t) CTFontGetDescent(ctFont); 1593e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org info->fCapHeight = (int16_t) CTFontGetCapHeight(ctFont); 1594e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org CGRect bbox = CTFontGetBoundingBox(ctFont); 1595e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 1596e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org SkRect r; 1597e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org r.set( CGToScalar(CGRectGetMinX_inline(bbox)), // Left 1598e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org CGToScalar(CGRectGetMaxY_inline(bbox)), // Top 1599e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org CGToScalar(CGRectGetMaxX_inline(bbox)), // Right 1600e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org CGToScalar(CGRectGetMinY_inline(bbox))); // Bottom 1601e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 1602e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org r.roundOut(&(info->fBBox)); 1603e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 1604e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org // Figure out a good guess for StemV - Min width of i, I, !, 1. 1605e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org // This probably isn't very good with an italic font. 1606e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org int16_t min_width = SHRT_MAX; 1607e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org info->fStemV = 0; 1608e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org static const UniChar stem_chars[] = {'i', 'I', '!', '1'}; 1609e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org const size_t count = sizeof(stem_chars) / sizeof(stem_chars[0]); 1610e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org CGGlyph glyphs[count]; 1611e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org CGRect boundingRects[count]; 1612e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org if (CTFontGetGlyphsForCharacters(ctFont, stem_chars, glyphs, count)) { 1613e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org CTFontGetBoundingRectsForGlyphs(ctFont, kCTFontHorizontalOrientation, 1614e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org glyphs, boundingRects, count); 1615e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org for (size_t i = 0; i < count; i++) { 1616e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org int16_t width = (int16_t) boundingRects[i].size.width; 1617e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org if (width > 0 && width < min_width) { 1618e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org min_width = width; 1619e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org info->fStemV = min_width; 1620e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org } 1621e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org } 1622e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org } 1623e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 1624e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org if (false) { // TODO: haven't figured out how to know if font is embeddable 1625e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org // (information is in the OS/2 table) 1626e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org info->fType = SkAdvancedTypefaceMetrics::kNotEmbeddable_Font; 1627e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org } else if (perGlyphInfo & SkAdvancedTypefaceMetrics::kHAdvance_PerGlyphInfo) { 1628e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org if (info->fStyle & SkAdvancedTypefaceMetrics::kFixedPitch_Style) { 1629e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org skia_advanced_typeface_metrics_utils::appendRange(&info->fGlyphWidths, 0); 1630e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org info->fGlyphWidths->fAdvance.append(1, &min_width); 1631e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org skia_advanced_typeface_metrics_utils::finishRange(info->fGlyphWidths.get(), 0, 1632e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org SkAdvancedTypefaceMetrics::WidthRange::kDefault); 1633e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org } else { 1634e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org info->fGlyphWidths.reset( 1635e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org skia_advanced_typeface_metrics_utils::getAdvanceData(ctFont.get(), 1636e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org glyphCount, 1637e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org glyphIDs, 1638e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org glyphIDsCount, 1639e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org &getWidthAdvance)); 1640e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org } 1641e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org } 1642e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org return info; 1643e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org} 1644e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 1645e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org/////////////////////////////////////////////////////////////////////////////// 1646e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 1647bbad7fe187bd8c112148dd7958bb645291f642ddreed@google.comstatic SK_SFNT_ULONG get_font_type_tag(const SkTypeface_Mac* typeface) { 1648bbad7fe187bd8c112148dd7958bb645291f642ddreed@google.com CTFontRef ctFont = typeface->fFontRef.get(); 1649e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org AutoCFRelease<CFNumberRef> fontFormatRef( 1650e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org static_cast<CFNumberRef>(CTFontCopyAttribute(ctFont, kCTFontFormatAttribute))); 1651e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org if (!fontFormatRef) { 1652e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org return 0; 1653e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org } 1654e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 1655e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org SInt32 fontFormatValue; 1656e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org if (!CFNumberGetValue(fontFormatRef, kCFNumberSInt32Type, &fontFormatValue)) { 1657e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org return 0; 1658e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org } 1659e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 1660e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org switch (fontFormatValue) { 1661e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org case kCTFontFormatOpenTypePostScript: 1662e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org return SkSFNTHeader::fontType_OpenTypeCFF::TAG; 1663e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org case kCTFontFormatOpenTypeTrueType: 1664e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org return SkSFNTHeader::fontType_WindowsTrueType::TAG; 1665e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org case kCTFontFormatTrueType: 1666e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org return SkSFNTHeader::fontType_MacTrueType::TAG; 1667e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org case kCTFontFormatPostScript: 1668e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org return SkSFNTHeader::fontType_PostScript::TAG; 1669e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org case kCTFontFormatBitmap: 1670e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org return SkSFNTHeader::fontType_MacTrueType::TAG; 1671e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org case kCTFontFormatUnrecognized: 1672e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org default: 1673e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org //CT seems to be unreliable in being able to obtain the type, 1674e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org //even if all we want is the first four bytes of the font resource. 1675e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org //Just the presence of the FontForge 'FFTM' table seems to throw it off. 1676e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org return SkSFNTHeader::fontType_WindowsTrueType::TAG; 1677e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org } 1678e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org} 1679e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 1680bbad7fe187bd8c112148dd7958bb645291f642ddreed@google.comSkStream* SkTypeface_Mac::onOpenStream(int* ttcIndex) const { 1681bbad7fe187bd8c112148dd7958bb645291f642ddreed@google.com SK_SFNT_ULONG fontType = get_font_type_tag(this); 1682e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org if (0 == fontType) { 1683e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org return NULL; 1684e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org } 1685e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 1686e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org // get table tags 1687bbad7fe187bd8c112148dd7958bb645291f642ddreed@google.com int numTables = this->countTables(); 1688e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org SkTDArray<SkFontTableTag> tableTags; 1689e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org tableTags.setCount(numTables); 1690bbad7fe187bd8c112148dd7958bb645291f642ddreed@google.com this->getTableTags(tableTags.begin()); 1691e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 1692e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org // calc total size for font, save sizes 1693e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org SkTDArray<size_t> tableSizes; 1694e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org size_t totalSize = sizeof(SkSFNTHeader) + sizeof(SkSFNTHeader::TableDirectoryEntry) * numTables; 1695e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org for (int tableIndex = 0; tableIndex < numTables; ++tableIndex) { 1696bbad7fe187bd8c112148dd7958bb645291f642ddreed@google.com size_t tableSize = this->getTableSize(tableTags[tableIndex]); 1697e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org totalSize += (tableSize + 3) & ~3; 1698e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org *tableSizes.append() = tableSize; 1699e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org } 1700e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 1701e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org // reserve memory for stream, and zero it (tables must be zero padded) 1702e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org SkMemoryStream* stream = new SkMemoryStream(totalSize); 1703e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org char* dataStart = (char*)stream->getMemoryBase(); 1704e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org sk_bzero(dataStart, totalSize); 1705e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org char* dataPtr = dataStart; 1706e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 1707e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org // compute font header entries 1708e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org uint16_t entrySelector = 0; 1709e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org uint16_t searchRange = 1; 1710e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org while (searchRange < numTables >> 1) { 1711e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org entrySelector++; 1712e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org searchRange <<= 1; 1713e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org } 1714e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org searchRange <<= 4; 1715e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org uint16_t rangeShift = (numTables << 4) - searchRange; 1716e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 1717e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org // write font header 1718e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org SkSFNTHeader* header = (SkSFNTHeader*)dataPtr; 1719e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org header->fontType = fontType; 1720e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org header->numTables = SkEndian_SwapBE16(numTables); 1721e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org header->searchRange = SkEndian_SwapBE16(searchRange); 1722e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org header->entrySelector = SkEndian_SwapBE16(entrySelector); 1723e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org header->rangeShift = SkEndian_SwapBE16(rangeShift); 1724e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org dataPtr += sizeof(SkSFNTHeader); 1725e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 1726e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org // write tables 1727e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org SkSFNTHeader::TableDirectoryEntry* entry = (SkSFNTHeader::TableDirectoryEntry*)dataPtr; 1728e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org dataPtr += sizeof(SkSFNTHeader::TableDirectoryEntry) * numTables; 1729e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org for (int tableIndex = 0; tableIndex < numTables; ++tableIndex) { 1730e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org size_t tableSize = tableSizes[tableIndex]; 1731bbad7fe187bd8c112148dd7958bb645291f642ddreed@google.com this->getTableData(tableTags[tableIndex], 0, tableSize, dataPtr); 1732e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org entry->tag = SkEndian_SwapBE32(tableTags[tableIndex]); 1733e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org entry->checksum = SkEndian_SwapBE32(SkOTUtils::CalcTableChecksum((SK_OT_ULONG*)dataPtr, 1734e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org tableSize)); 1735e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org entry->offset = SkEndian_SwapBE32(dataPtr - dataStart); 1736e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org entry->logicalLength = SkEndian_SwapBE32(tableSize); 1737e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 1738e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org dataPtr += (tableSize + 3) & ~3; 1739e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org ++entry; 1740e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org } 1741e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 1742e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org return stream; 1743e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org} 1744e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 1745e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org/////////////////////////////////////////////////////////////////////////////// 1746e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org/////////////////////////////////////////////////////////////////////////////// 1747e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 1748e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.orgint SkTypeface_Mac::onGetUPEM() const { 1749e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org AutoCFRelease<CGFontRef> cgFont(CTFontCopyGraphicsFont(fFontRef, NULL)); 1750e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org return CGFontGetUnitsPerEm(cgFont); 1751e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org} 1752e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 17536e20a74d8cbcf19195559e8d98896fa22ebc535fbungeman@google.comSkTypeface::LocalizedStrings* SkTypeface_Mac::onCreateFamilyNameIterator() const { 1754ee8341d57355c54ea8db5fb21be75e7354069fb3bungeman@google.com SkTypeface::LocalizedStrings* nameIter = 1755ee8341d57355c54ea8db5fb21be75e7354069fb3bungeman@google.com SkOTUtils::LocalizedStrings_NameTable::CreateForFamilyNames(*this); 1756ee8341d57355c54ea8db5fb21be75e7354069fb3bungeman@google.com if (NULL == nameIter) { 1757ee8341d57355c54ea8db5fb21be75e7354069fb3bungeman@google.com AutoCFRelease<CFStringRef> cfLanguage; 1758ee8341d57355c54ea8db5fb21be75e7354069fb3bungeman@google.com AutoCFRelease<CFStringRef> cfFamilyName( 1759ee8341d57355c54ea8db5fb21be75e7354069fb3bungeman@google.com CTFontCopyLocalizedName(fFontRef, kCTFontFamilyNameKey, &cfLanguage)); 1760ee8341d57355c54ea8db5fb21be75e7354069fb3bungeman@google.com 1761ee8341d57355c54ea8db5fb21be75e7354069fb3bungeman@google.com SkString skLanguage; 1762ee8341d57355c54ea8db5fb21be75e7354069fb3bungeman@google.com SkString skFamilyName; 1763ee8341d57355c54ea8db5fb21be75e7354069fb3bungeman@google.com if (cfLanguage.get()) { 1764ee8341d57355c54ea8db5fb21be75e7354069fb3bungeman@google.com CFStringToSkString(cfLanguage.get(), &skLanguage); 1765ee8341d57355c54ea8db5fb21be75e7354069fb3bungeman@google.com } else { 1766ee8341d57355c54ea8db5fb21be75e7354069fb3bungeman@google.com skLanguage = "und"; //undetermined 1767ee8341d57355c54ea8db5fb21be75e7354069fb3bungeman@google.com } 1768ee8341d57355c54ea8db5fb21be75e7354069fb3bungeman@google.com if (cfFamilyName.get()) { 1769ee8341d57355c54ea8db5fb21be75e7354069fb3bungeman@google.com CFStringToSkString(cfFamilyName.get(), &skFamilyName); 1770ee8341d57355c54ea8db5fb21be75e7354069fb3bungeman@google.com } 1771ee8341d57355c54ea8db5fb21be75e7354069fb3bungeman@google.com 1772ee8341d57355c54ea8db5fb21be75e7354069fb3bungeman@google.com nameIter = new SkOTUtils::LocalizedStrings_SingleName(skFamilyName, skLanguage); 1773ee8341d57355c54ea8db5fb21be75e7354069fb3bungeman@google.com } 1774ee8341d57355c54ea8db5fb21be75e7354069fb3bungeman@google.com return nameIter; 1775ee8341d57355c54ea8db5fb21be75e7354069fb3bungeman@google.com} 1776ee8341d57355c54ea8db5fb21be75e7354069fb3bungeman@google.com 1777e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org// If, as is the case with web fonts, the CTFont data isn't available, 1778e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org// the CGFont data may work. While the CGFont may always provide the 1779e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org// right result, leave the CTFont code path to minimize disruption. 1780e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.orgstatic CFDataRef copyTableFromFont(CTFontRef ctFont, SkFontTableTag tag) { 1781e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org CFDataRef data = CTFontCopyTable(ctFont, (CTFontTableTag) tag, 1782e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org kCTFontTableOptionNoOptions); 1783e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org if (NULL == data) { 1784e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org AutoCFRelease<CGFontRef> cgFont(CTFontCopyGraphicsFont(ctFont, NULL)); 1785e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org data = CGFontCopyTableForTag(cgFont, tag); 1786e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org } 1787e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org return data; 1788e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org} 1789e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 1790e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.orgint SkTypeface_Mac::onGetTableTags(SkFontTableTag tags[]) const { 1791e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org AutoCFRelease<CFArrayRef> cfArray(CTFontCopyAvailableTables(fFontRef, 1792e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org kCTFontTableOptionNoOptions)); 1793e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org if (NULL == cfArray) { 1794e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org return 0; 1795e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org } 1796e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org int count = CFArrayGetCount(cfArray); 1797e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org if (tags) { 1798e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org for (int i = 0; i < count; ++i) { 1799e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org uintptr_t fontTag = reinterpret_cast<uintptr_t>(CFArrayGetValueAtIndex(cfArray, i)); 1800e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org tags[i] = static_cast<SkFontTableTag>(fontTag); 1801e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org } 1802e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org } 1803e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org return count; 1804e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org} 1805e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 1806e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.orgsize_t SkTypeface_Mac::onGetTableData(SkFontTableTag tag, size_t offset, 1807e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org size_t length, void* dstData) const { 1808e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org AutoCFRelease<CFDataRef> srcData(copyTableFromFont(fFontRef, tag)); 1809e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org if (NULL == srcData) { 1810e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org return 0; 1811e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org } 1812e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 1813e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org size_t srcSize = CFDataGetLength(srcData); 1814e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org if (offset >= srcSize) { 1815e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org return 0; 1816e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org } 1817e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org if (length > srcSize - offset) { 1818e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org length = srcSize - offset; 1819e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org } 1820e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org if (dstData) { 1821e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org memcpy(dstData, CFDataGetBytePtr(srcData) + offset, length); 1822e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org } 1823e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org return length; 1824e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org} 1825e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 1826e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.orgSkScalerContext* SkTypeface_Mac::onCreateScalerContext(const SkDescriptor* desc) const { 18278e01453029702b114d4eb939e4fbe7fd33b57b50reed@google.com return new SkScalerContext_Mac(const_cast<SkTypeface_Mac*>(this), desc); 1828e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org} 1829e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 1830e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.orgvoid SkTypeface_Mac::onFilterRec(SkScalerContextRec* rec) const { 1831722656683cb3806f36b45f481fda19f73f4dca5ccommit-bot@chromium.org if (rec->fFlags & SkScalerContext::kLCD_BGROrder_Flag || 1832722656683cb3806f36b45f481fda19f73f4dca5ccommit-bot@chromium.org rec->fFlags & SkScalerContext::kLCD_Vertical_Flag) 1833722656683cb3806f36b45f481fda19f73f4dca5ccommit-bot@chromium.org { 1834722656683cb3806f36b45f481fda19f73f4dca5ccommit-bot@chromium.org rec->fMaskFormat = SkMask::kA8_Format; 1835722656683cb3806f36b45f481fda19f73f4dca5ccommit-bot@chromium.org // Render the glyphs as close as possible to what was requested. 1836722656683cb3806f36b45f481fda19f73f4dca5ccommit-bot@chromium.org // The above turns off subpixel rendering, but the user requested it. 1837722656683cb3806f36b45f481fda19f73f4dca5ccommit-bot@chromium.org // Normal hinting will cause the A8 masks to be generated from CoreGraphics subpixel masks. 1838722656683cb3806f36b45f481fda19f73f4dca5ccommit-bot@chromium.org // See comments below for more details. 1839722656683cb3806f36b45f481fda19f73f4dca5ccommit-bot@chromium.org rec->setHinting(SkPaint::kNormal_Hinting); 1840722656683cb3806f36b45f481fda19f73f4dca5ccommit-bot@chromium.org } 18414f43eb3b716935a2905f8071f3ca21d59aeee676skia.committer@gmail.com 1842722656683cb3806f36b45f481fda19f73f4dca5ccommit-bot@chromium.org unsigned flagsWeDontSupport = SkScalerContext::kDevKernText_Flag | 1843722656683cb3806f36b45f481fda19f73f4dca5ccommit-bot@chromium.org SkScalerContext::kAutohinting_Flag | 1844722656683cb3806f36b45f481fda19f73f4dca5ccommit-bot@chromium.org SkScalerContext::kLCD_BGROrder_Flag | 1845722656683cb3806f36b45f481fda19f73f4dca5ccommit-bot@chromium.org SkScalerContext::kLCD_Vertical_Flag; 1846f35b0ddb7e95937c441c95d5d36f64a38fa83f7fskia.committer@gmail.com 1847e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org rec->fFlags &= ~flagsWeDontSupport; 1848f35b0ddb7e95937c441c95d5d36f64a38fa83f7fskia.committer@gmail.com 1849e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org bool lcdSupport = supports_LCD(); 1850f35b0ddb7e95937c441c95d5d36f64a38fa83f7fskia.committer@gmail.com 1851e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org // Only two levels of hinting are supported. 1852e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org // kNo_Hinting means avoid CoreGraphics outline dilation. 1853e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org // kNormal_Hinting means CoreGraphics outline dilation is allowed. 1854e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org // If there is no lcd support, hinting (dilation) cannot be supported. 1855e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org SkPaint::Hinting hinting = rec->getHinting(); 1856e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org if (SkPaint::kSlight_Hinting == hinting || !lcdSupport) { 1857e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org hinting = SkPaint::kNo_Hinting; 1858e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org } else if (SkPaint::kFull_Hinting == hinting) { 1859e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org hinting = SkPaint::kNormal_Hinting; 1860e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org } 1861e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org rec->setHinting(hinting); 1862f35b0ddb7e95937c441c95d5d36f64a38fa83f7fskia.committer@gmail.com 1863e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org // FIXME: lcd smoothed un-hinted rasterization unsupported. 1864e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org // Tracked by http://code.google.com/p/skia/issues/detail?id=915 . 1865e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org // There is no current means to honor a request for unhinted lcd, 1866e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org // so arbitrarilly ignore the hinting request and honor lcd. 1867f35b0ddb7e95937c441c95d5d36f64a38fa83f7fskia.committer@gmail.com 1868e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org // Hinting and smoothing should be orthogonal, but currently they are not. 1869e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org // CoreGraphics has no API to influence hinting. However, its lcd smoothed 1870e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org // output is drawn from auto-dilated outlines (the amount of which is 1871e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org // determined by AppleFontSmoothing). Its regular anti-aliased output is 1872e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org // drawn from un-dilated outlines. 1873f35b0ddb7e95937c441c95d5d36f64a38fa83f7fskia.committer@gmail.com 1874e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org // The behavior of Skia is as follows: 1875e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org // [AA][no-hint]: generate AA using CoreGraphic's AA output. 1876e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org // [AA][yes-hint]: use CoreGraphic's LCD output and reduce it to a single 1877e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org // channel. This matches [LCD][yes-hint] in weight. 1878e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org // [LCD][no-hint]: curently unable to honor, and must pick which to respect. 1879e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org // Currenly side with LCD, effectively ignoring the hinting setting. 1880e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org // [LCD][yes-hint]: generate LCD using CoreGraphic's LCD output. 1881f35b0ddb7e95937c441c95d5d36f64a38fa83f7fskia.committer@gmail.com 1882e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org if (isLCDFormat(rec->fMaskFormat)) { 1883e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org if (lcdSupport) { 1884e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org //CoreGraphics creates 555 masks for smoothed text anyway. 1885e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org rec->fMaskFormat = SkMask::kLCD16_Format; 1886e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org rec->setHinting(SkPaint::kNormal_Hinting); 1887e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org } else { 1888e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org rec->fMaskFormat = SkMask::kA8_Format; 1889e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org } 1890e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org } 1891f35b0ddb7e95937c441c95d5d36f64a38fa83f7fskia.committer@gmail.com 1892e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org // Unhinted A8 masks (those not derived from LCD masks) must respect SK_GAMMA_APPLY_TO_A8. 1893e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org // All other masks can use regular gamma. 1894e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org if (SkMask::kA8_Format == rec->fMaskFormat && SkPaint::kNo_Hinting == hinting) { 1895e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org#ifndef SK_GAMMA_APPLY_TO_A8 1896e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org rec->ignorePreBlend(); 1897a4bcd158e63c2c000fb01ad2bc013859546dd788reed@android.com#endif 1898e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org } else { 1899e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org //CoreGraphics dialates smoothed text as needed. 1900e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org rec->setContrast(0); 1901e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org } 1902e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org} 1903e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 1904e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org// we take ownership of the ref 1905e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.orgstatic const char* get_str(CFStringRef ref, SkString* str) { 1906e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org CFStringToSkString(ref, str); 1907e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org CFSafeRelease(ref); 1908e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org return str->c_str(); 1909e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org} 1910e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org 19113d8295f60b8b733ec0210b08261e968ad79bf5c6reed@google.comvoid SkTypeface_Mac::onGetFontDescriptor(SkFontDescriptor* desc, 19123d8295f60b8b733ec0210b08261e968ad79bf5c6reed@google.com bool* isLocalStream) const { 1913e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org SkString tmpStr; 1914f35b0ddb7e95937c441c95d5d36f64a38fa83f7fskia.committer@gmail.com 1915e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org desc->setFamilyName(get_str(CTFontCopyFamilyName(fFontRef), &tmpStr)); 1916e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org desc->setFullName(get_str(CTFontCopyFullName(fFontRef), &tmpStr)); 1917e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org desc->setPostscriptName(get_str(CTFontCopyPostScriptName(fFontRef), &tmpStr)); 19183d8295f60b8b733ec0210b08261e968ad79bf5c6reed@google.com // TODO: need to add support for local-streams (here and openStream) 19193d8295f60b8b733ec0210b08261e968ad79bf5c6reed@google.com *isLocalStream = false; 1920e7705126b25c9078339b2de7e0a78ded6b39cd75mike@reedtribe.org} 19213d8295f60b8b733ec0210b08261e968ad79bf5c6reed@google.com 192248c173d413ecc4c3661064be0f6f65022c1dc40dreed@google.comint SkTypeface_Mac::onCharsToGlyphs(const void* chars, Encoding encoding, 192348c173d413ecc4c3661064be0f6f65022c1dc40dreed@google.com uint16_t glyphs[], int glyphCount) const { 192448c173d413ecc4c3661064be0f6f65022c1dc40dreed@google.com // UniChar is utf16 192548c173d413ecc4c3661064be0f6f65022c1dc40dreed@google.com SkAutoSTMalloc<1024, UniChar> charStorage; 192648c173d413ecc4c3661064be0f6f65022c1dc40dreed@google.com const UniChar* src; 192748c173d413ecc4c3661064be0f6f65022c1dc40dreed@google.com switch (encoding) { 192848c173d413ecc4c3661064be0f6f65022c1dc40dreed@google.com case kUTF8_Encoding: { 192948c173d413ecc4c3661064be0f6f65022c1dc40dreed@google.com const char* u8 = (const char*)chars; 193048c173d413ecc4c3661064be0f6f65022c1dc40dreed@google.com const UniChar* u16 = src = charStorage.reset(2 * glyphCount); 193148c173d413ecc4c3661064be0f6f65022c1dc40dreed@google.com for (int i = 0; i < glyphCount; ++i) { 193248c173d413ecc4c3661064be0f6f65022c1dc40dreed@google.com SkUnichar uni = SkUTF8_NextUnichar(&u8); 193348c173d413ecc4c3661064be0f6f65022c1dc40dreed@google.com int n = SkUTF16_FromUnichar(uni, (uint16_t*)u16); 193448c173d413ecc4c3661064be0f6f65022c1dc40dreed@google.com u16 += n; 193548c173d413ecc4c3661064be0f6f65022c1dc40dreed@google.com } 193648c173d413ecc4c3661064be0f6f65022c1dc40dreed@google.com break; 193748c173d413ecc4c3661064be0f6f65022c1dc40dreed@google.com } 193848c173d413ecc4c3661064be0f6f65022c1dc40dreed@google.com case kUTF16_Encoding: 193948c173d413ecc4c3661064be0f6f65022c1dc40dreed@google.com src = (const UniChar*)chars; 194048c173d413ecc4c3661064be0f6f65022c1dc40dreed@google.com break; 194148c173d413ecc4c3661064be0f6f65022c1dc40dreed@google.com case kUTF32_Encoding: { 194248c173d413ecc4c3661064be0f6f65022c1dc40dreed@google.com const SkUnichar* u32 = (const SkUnichar*)chars; 194348c173d413ecc4c3661064be0f6f65022c1dc40dreed@google.com const UniChar* u16 = src = charStorage.reset(2 * glyphCount); 194448c173d413ecc4c3661064be0f6f65022c1dc40dreed@google.com for (int i = 0; i < glyphCount; ++i) { 194548c173d413ecc4c3661064be0f6f65022c1dc40dreed@google.com int n = SkUTF16_FromUnichar(u32[i], (uint16_t*)u16); 194648c173d413ecc4c3661064be0f6f65022c1dc40dreed@google.com u16 += n; 194748c173d413ecc4c3661064be0f6f65022c1dc40dreed@google.com } 194848c173d413ecc4c3661064be0f6f65022c1dc40dreed@google.com break; 194948c173d413ecc4c3661064be0f6f65022c1dc40dreed@google.com } 195048c173d413ecc4c3661064be0f6f65022c1dc40dreed@google.com } 195148c173d413ecc4c3661064be0f6f65022c1dc40dreed@google.com 195248c173d413ecc4c3661064be0f6f65022c1dc40dreed@google.com // Our caller may not want glyphs for output, but we need to give that 195348c173d413ecc4c3661064be0f6f65022c1dc40dreed@google.com // storage to CT, so we can walk it looking for the first non-zero. 195448c173d413ecc4c3661064be0f6f65022c1dc40dreed@google.com SkAutoSTMalloc<1024, uint16_t> glyphStorage; 195548c173d413ecc4c3661064be0f6f65022c1dc40dreed@google.com uint16_t* macGlyphs = glyphs; 195648c173d413ecc4c3661064be0f6f65022c1dc40dreed@google.com if (NULL == macGlyphs) { 195748c173d413ecc4c3661064be0f6f65022c1dc40dreed@google.com macGlyphs = glyphStorage.reset(glyphCount); 195848c173d413ecc4c3661064be0f6f65022c1dc40dreed@google.com } 195948c173d413ecc4c3661064be0f6f65022c1dc40dreed@google.com 196048c173d413ecc4c3661064be0f6f65022c1dc40dreed@google.com if (CTFontGetGlyphsForCharacters(fFontRef, src, macGlyphs, glyphCount)) { 196148c173d413ecc4c3661064be0f6f65022c1dc40dreed@google.com return glyphCount; 196248c173d413ecc4c3661064be0f6f65022c1dc40dreed@google.com } 196348c173d413ecc4c3661064be0f6f65022c1dc40dreed@google.com // If we got false, then we need to manually look for first failure 196448c173d413ecc4c3661064be0f6f65022c1dc40dreed@google.com for (int i = 0; i < glyphCount; ++i) { 196548c173d413ecc4c3661064be0f6f65022c1dc40dreed@google.com if (0 == macGlyphs[i]) { 196648c173d413ecc4c3661064be0f6f65022c1dc40dreed@google.com return i; 196748c173d413ecc4c3661064be0f6f65022c1dc40dreed@google.com } 196848c173d413ecc4c3661064be0f6f65022c1dc40dreed@google.com } 196948c173d413ecc4c3661064be0f6f65022c1dc40dreed@google.com // odd to get here, as we expected CT to have returned true up front. 197048c173d413ecc4c3661064be0f6f65022c1dc40dreed@google.com return glyphCount; 197148c173d413ecc4c3661064be0f6f65022c1dc40dreed@google.com} 197248c173d413ecc4c3661064be0f6f65022c1dc40dreed@google.com 197348c173d413ecc4c3661064be0f6f65022c1dc40dreed@google.comint SkTypeface_Mac::onCountGlyphs() const { 197448c173d413ecc4c3661064be0f6f65022c1dc40dreed@google.com return CTFontGetGlyphCount(fFontRef); 197548c173d413ecc4c3661064be0f6f65022c1dc40dreed@google.com} 197648c173d413ecc4c3661064be0f6f65022c1dc40dreed@google.com 1977e621e833c89b7621721bbc8a162c5685aa33ade0reed@google.com/////////////////////////////////////////////////////////////////////////////// 1978e621e833c89b7621721bbc8a162c5685aa33ade0reed@google.com/////////////////////////////////////////////////////////////////////////////// 1979e621e833c89b7621721bbc8a162c5685aa33ade0reed@google.com#if 1 198001ffa71f87664453998e2870808c82610584929areed@google.com 198101ffa71f87664453998e2870808c82610584929areed@google.comstatic bool find_desc_str(CTFontDescriptorRef desc, CFStringRef name, SkString* value) { 198201ffa71f87664453998e2870808c82610584929areed@google.com AutoCFRelease<CFStringRef> ref((CFStringRef)CTFontDescriptorCopyAttribute(desc, name)); 198301ffa71f87664453998e2870808c82610584929areed@google.com if (NULL == ref.get()) { 198401ffa71f87664453998e2870808c82610584929areed@google.com return false; 198501ffa71f87664453998e2870808c82610584929areed@google.com } 198601ffa71f87664453998e2870808c82610584929areed@google.com CFStringToSkString(ref, value); 198701ffa71f87664453998e2870808c82610584929areed@google.com return true; 198801ffa71f87664453998e2870808c82610584929areed@google.com} 198901ffa71f87664453998e2870808c82610584929areed@google.com 199001ffa71f87664453998e2870808c82610584929areed@google.comstatic bool find_dict_float(CFDictionaryRef dict, CFStringRef name, float* value) { 199101ffa71f87664453998e2870808c82610584929areed@google.com CFNumberRef num; 199201ffa71f87664453998e2870808c82610584929areed@google.com return CFDictionaryGetValueIfPresent(dict, name, (const void**)&num) 199301ffa71f87664453998e2870808c82610584929areed@google.com && CFNumberIsFloatType(num) 199401ffa71f87664453998e2870808c82610584929areed@google.com && CFNumberGetValue(num, kCFNumberFloatType, value); 199501ffa71f87664453998e2870808c82610584929areed@google.com} 199601ffa71f87664453998e2870808c82610584929areed@google.com 1997e621e833c89b7621721bbc8a162c5685aa33ade0reed@google.com#include "SkFontMgr.h" 1998e621e833c89b7621721bbc8a162c5685aa33ade0reed@google.com 199901ffa71f87664453998e2870808c82610584929areed@google.comstatic int unit_weight_to_fontstyle(float unit) { 200001ffa71f87664453998e2870808c82610584929areed@google.com float value; 200101ffa71f87664453998e2870808c82610584929areed@google.com if (unit < 0) { 200201ffa71f87664453998e2870808c82610584929areed@google.com value = 100 + (1 + unit) * 300; 200301ffa71f87664453998e2870808c82610584929areed@google.com } else { 200401ffa71f87664453998e2870808c82610584929areed@google.com value = 400 + unit * 500; 200501ffa71f87664453998e2870808c82610584929areed@google.com } 200601ffa71f87664453998e2870808c82610584929areed@google.com return sk_float_round2int(value); 200701ffa71f87664453998e2870808c82610584929areed@google.com} 200801ffa71f87664453998e2870808c82610584929areed@google.com 200901ffa71f87664453998e2870808c82610584929areed@google.comstatic int unit_width_to_fontstyle(float unit) { 201001ffa71f87664453998e2870808c82610584929areed@google.com float value; 201101ffa71f87664453998e2870808c82610584929areed@google.com if (unit < 0) { 201201ffa71f87664453998e2870808c82610584929areed@google.com value = 1 + (1 + unit) * 4; 201301ffa71f87664453998e2870808c82610584929areed@google.com } else { 201401ffa71f87664453998e2870808c82610584929areed@google.com value = 5 + unit * 4; 201501ffa71f87664453998e2870808c82610584929areed@google.com } 201601ffa71f87664453998e2870808c82610584929areed@google.com return sk_float_round2int(value); 201701ffa71f87664453998e2870808c82610584929areed@google.com} 201801ffa71f87664453998e2870808c82610584929areed@google.com 2019ab8665f8e88927b1a9b82aca38483d8a963fd2e0reed@google.comstatic inline int sqr(int value) { 2020ab8665f8e88927b1a9b82aca38483d8a963fd2e0reed@google.com SkASSERT(SkAbs32(value) < 0x7FFF); // check for overflow 2021ab8665f8e88927b1a9b82aca38483d8a963fd2e0reed@google.com return value * value; 2022ab8665f8e88927b1a9b82aca38483d8a963fd2e0reed@google.com} 2023ab8665f8e88927b1a9b82aca38483d8a963fd2e0reed@google.com 2024ab8665f8e88927b1a9b82aca38483d8a963fd2e0reed@google.com// We normalize each axis (weight, width, italic) to be base-900 2025ab8665f8e88927b1a9b82aca38483d8a963fd2e0reed@google.comstatic int compute_metric(const SkFontStyle& a, const SkFontStyle& b) { 2026ab8665f8e88927b1a9b82aca38483d8a963fd2e0reed@google.com return sqr(a.weight() - b.weight()) + 2027ab8665f8e88927b1a9b82aca38483d8a963fd2e0reed@google.com sqr((a.width() - b.width()) * 100) + 2028ab8665f8e88927b1a9b82aca38483d8a963fd2e0reed@google.com sqr((a.isItalic() != b.isItalic()) * 900); 2029ab8665f8e88927b1a9b82aca38483d8a963fd2e0reed@google.com} 2030ab8665f8e88927b1a9b82aca38483d8a963fd2e0reed@google.com 203101ffa71f87664453998e2870808c82610584929areed@google.comstatic SkFontStyle desc2fontstyle(CTFontDescriptorRef desc) { 203201ffa71f87664453998e2870808c82610584929areed@google.com AutoCFRelease<CFDictionaryRef> dict( 203301ffa71f87664453998e2870808c82610584929areed@google.com (CFDictionaryRef)CTFontDescriptorCopyAttribute(desc, 203401ffa71f87664453998e2870808c82610584929areed@google.com kCTFontTraitsAttribute)); 203501ffa71f87664453998e2870808c82610584929areed@google.com if (NULL == dict.get()) { 203601ffa71f87664453998e2870808c82610584929areed@google.com return SkFontStyle(); 203701ffa71f87664453998e2870808c82610584929areed@google.com } 203801ffa71f87664453998e2870808c82610584929areed@google.com 203901ffa71f87664453998e2870808c82610584929areed@google.com float weight, width, slant; 204001ffa71f87664453998e2870808c82610584929areed@google.com if (!find_dict_float(dict, kCTFontWeightTrait, &weight)) { 204101ffa71f87664453998e2870808c82610584929areed@google.com weight = 0; 204201ffa71f87664453998e2870808c82610584929areed@google.com } 204301ffa71f87664453998e2870808c82610584929areed@google.com if (!find_dict_float(dict, kCTFontWidthTrait, &width)) { 204401ffa71f87664453998e2870808c82610584929areed@google.com width = 0; 204501ffa71f87664453998e2870808c82610584929areed@google.com } 204601ffa71f87664453998e2870808c82610584929areed@google.com if (!find_dict_float(dict, kCTFontSlantTrait, &slant)) { 204701ffa71f87664453998e2870808c82610584929areed@google.com slant = 0; 204801ffa71f87664453998e2870808c82610584929areed@google.com } 2049cb9a1cd72d397d254c18441743b79de0bbc3da09skia.committer@gmail.com 205001ffa71f87664453998e2870808c82610584929areed@google.com return SkFontStyle(unit_weight_to_fontstyle(weight), 205101ffa71f87664453998e2870808c82610584929areed@google.com unit_width_to_fontstyle(width), 205201ffa71f87664453998e2870808c82610584929areed@google.com slant ? SkFontStyle::kItalic_Slant 205301ffa71f87664453998e2870808c82610584929areed@google.com : SkFontStyle::kUpright_Slant); 205401ffa71f87664453998e2870808c82610584929areed@google.com} 205501ffa71f87664453998e2870808c82610584929areed@google.com 2056159dfb6076b6a25e4bb87c5723567f1caf12e03freed@google.comstruct NameFontStyleRec { 2057159dfb6076b6a25e4bb87c5723567f1caf12e03freed@google.com SkString fFamilyName; 2058159dfb6076b6a25e4bb87c5723567f1caf12e03freed@google.com SkFontStyle fFontStyle; 2059159dfb6076b6a25e4bb87c5723567f1caf12e03freed@google.com}; 2060159dfb6076b6a25e4bb87c5723567f1caf12e03freed@google.com 2061159dfb6076b6a25e4bb87c5723567f1caf12e03freed@google.comstatic bool nameFontStyleProc(SkTypeface* face, SkTypeface::Style, 2062159dfb6076b6a25e4bb87c5723567f1caf12e03freed@google.com void* ctx) { 2063159dfb6076b6a25e4bb87c5723567f1caf12e03freed@google.com SkTypeface_Mac* macFace = (SkTypeface_Mac*)face; 2064159dfb6076b6a25e4bb87c5723567f1caf12e03freed@google.com const NameFontStyleRec* rec = (const NameFontStyleRec*)ctx; 2065159dfb6076b6a25e4bb87c5723567f1caf12e03freed@google.com 2066159dfb6076b6a25e4bb87c5723567f1caf12e03freed@google.com return macFace->fFontStyle == rec->fFontStyle && 2067159dfb6076b6a25e4bb87c5723567f1caf12e03freed@google.com macFace->fName == rec->fFamilyName; 2068159dfb6076b6a25e4bb87c5723567f1caf12e03freed@google.com} 2069159dfb6076b6a25e4bb87c5723567f1caf12e03freed@google.com 2070b6950743ce31468a5ca478f7916da10cf7b8c16areed@google.comstatic SkTypeface* createFromDesc(CFStringRef cfFamilyName, 2071b6950743ce31468a5ca478f7916da10cf7b8c16areed@google.com CTFontDescriptorRef desc) { 2072159dfb6076b6a25e4bb87c5723567f1caf12e03freed@google.com NameFontStyleRec rec; 2073159dfb6076b6a25e4bb87c5723567f1caf12e03freed@google.com CFStringToSkString(cfFamilyName, &rec.fFamilyName); 2074159dfb6076b6a25e4bb87c5723567f1caf12e03freed@google.com rec.fFontStyle = desc2fontstyle(desc); 2075159dfb6076b6a25e4bb87c5723567f1caf12e03freed@google.com 2076159dfb6076b6a25e4bb87c5723567f1caf12e03freed@google.com SkTypeface* face = SkTypefaceCache::FindByProcAndRef(nameFontStyleProc, 2077159dfb6076b6a25e4bb87c5723567f1caf12e03freed@google.com &rec); 2078159dfb6076b6a25e4bb87c5723567f1caf12e03freed@google.com if (face) { 2079159dfb6076b6a25e4bb87c5723567f1caf12e03freed@google.com return face; 2080159dfb6076b6a25e4bb87c5723567f1caf12e03freed@google.com } 2081159dfb6076b6a25e4bb87c5723567f1caf12e03freed@google.com 2082b6950743ce31468a5ca478f7916da10cf7b8c16areed@google.com AutoCFRelease<CTFontRef> ctNamed(CTFontCreateWithName(cfFamilyName, 1, NULL)); 2083b6950743ce31468a5ca478f7916da10cf7b8c16areed@google.com CTFontRef ctFont = CTFontCreateCopyWithAttributes(ctNamed, 1, NULL, desc); 2084b6950743ce31468a5ca478f7916da10cf7b8c16areed@google.com if (NULL == ctFont) { 2085b6950743ce31468a5ca478f7916da10cf7b8c16areed@google.com return NULL; 2086b6950743ce31468a5ca478f7916da10cf7b8c16areed@google.com } 2087cb9a1cd72d397d254c18441743b79de0bbc3da09skia.committer@gmail.com 2088b6950743ce31468a5ca478f7916da10cf7b8c16areed@google.com SkString str; 2089b6950743ce31468a5ca478f7916da10cf7b8c16areed@google.com CFStringToSkString(cfFamilyName, &str); 2090cb9a1cd72d397d254c18441743b79de0bbc3da09skia.committer@gmail.com 2091b6950743ce31468a5ca478f7916da10cf7b8c16areed@google.com bool isFixedPitch; 2092b6950743ce31468a5ca478f7916da10cf7b8c16areed@google.com (void)computeStyleBits(ctFont, &isFixedPitch); 2093b6950743ce31468a5ca478f7916da10cf7b8c16areed@google.com SkFontID fontID = CTFontRef_to_SkFontID(ctFont); 2094cb9a1cd72d397d254c18441743b79de0bbc3da09skia.committer@gmail.com 2095159dfb6076b6a25e4bb87c5723567f1caf12e03freed@google.com face = SkNEW_ARGS(SkTypeface_Mac, (rec.fFontStyle, fontID, isFixedPitch, 2096159dfb6076b6a25e4bb87c5723567f1caf12e03freed@google.com ctFont, str.c_str())); 2097159dfb6076b6a25e4bb87c5723567f1caf12e03freed@google.com SkTypefaceCache::Add(face, face->style()); 2098159dfb6076b6a25e4bb87c5723567f1caf12e03freed@google.com return face; 2099b6950743ce31468a5ca478f7916da10cf7b8c16areed@google.com} 2100b6950743ce31468a5ca478f7916da10cf7b8c16areed@google.com 210101ffa71f87664453998e2870808c82610584929areed@google.comclass SkFontStyleSet_Mac : public SkFontStyleSet { 210201ffa71f87664453998e2870808c82610584929areed@google.compublic: 210301ffa71f87664453998e2870808c82610584929areed@google.com SkFontStyleSet_Mac(CFStringRef familyName, CTFontDescriptorRef desc) 210401ffa71f87664453998e2870808c82610584929areed@google.com : fArray(CTFontDescriptorCreateMatchingFontDescriptors(desc, NULL)) 2105159dfb6076b6a25e4bb87c5723567f1caf12e03freed@google.com , fFamilyName(familyName) 2106159dfb6076b6a25e4bb87c5723567f1caf12e03freed@google.com , fCount(0) { 210701ffa71f87664453998e2870808c82610584929areed@google.com CFRetain(familyName); 2108159dfb6076b6a25e4bb87c5723567f1caf12e03freed@google.com if (NULL == fArray) { 2109159dfb6076b6a25e4bb87c5723567f1caf12e03freed@google.com fArray = CFArrayCreate(NULL, NULL, 0, NULL); 2110159dfb6076b6a25e4bb87c5723567f1caf12e03freed@google.com } 2111159dfb6076b6a25e4bb87c5723567f1caf12e03freed@google.com fCount = CFArrayGetCount(fArray); 211201ffa71f87664453998e2870808c82610584929areed@google.com } 2113cb9a1cd72d397d254c18441743b79de0bbc3da09skia.committer@gmail.com 211401ffa71f87664453998e2870808c82610584929areed@google.com virtual ~SkFontStyleSet_Mac() { 2115159dfb6076b6a25e4bb87c5723567f1caf12e03freed@google.com CFRelease(fArray); 211601ffa71f87664453998e2870808c82610584929areed@google.com CFRelease(fFamilyName); 211701ffa71f87664453998e2870808c82610584929areed@google.com } 211801ffa71f87664453998e2870808c82610584929areed@google.com 211901ffa71f87664453998e2870808c82610584929areed@google.com virtual int count() SK_OVERRIDE { 2120159dfb6076b6a25e4bb87c5723567f1caf12e03freed@google.com return fCount; 212101ffa71f87664453998e2870808c82610584929areed@google.com } 212201ffa71f87664453998e2870808c82610584929areed@google.com 212301ffa71f87664453998e2870808c82610584929areed@google.com virtual void getStyle(int index, SkFontStyle* style, 212401ffa71f87664453998e2870808c82610584929areed@google.com SkString* name) SK_OVERRIDE { 2125159dfb6076b6a25e4bb87c5723567f1caf12e03freed@google.com SkASSERT((unsigned)index < (unsigned)fCount); 212601ffa71f87664453998e2870808c82610584929areed@google.com CTFontDescriptorRef desc = (CTFontDescriptorRef)CFArrayGetValueAtIndex(fArray, index); 212701ffa71f87664453998e2870808c82610584929areed@google.com if (style) { 212801ffa71f87664453998e2870808c82610584929areed@google.com *style = desc2fontstyle(desc); 212901ffa71f87664453998e2870808c82610584929areed@google.com } 213001ffa71f87664453998e2870808c82610584929areed@google.com if (name) { 213101ffa71f87664453998e2870808c82610584929areed@google.com if (!find_desc_str(desc, kCTFontStyleNameAttribute, name)) { 213201ffa71f87664453998e2870808c82610584929areed@google.com name->reset(); 213301ffa71f87664453998e2870808c82610584929areed@google.com } 213401ffa71f87664453998e2870808c82610584929areed@google.com } 213501ffa71f87664453998e2870808c82610584929areed@google.com } 213601ffa71f87664453998e2870808c82610584929areed@google.com 213701ffa71f87664453998e2870808c82610584929areed@google.com virtual SkTypeface* createTypeface(int index) SK_OVERRIDE { 213801ffa71f87664453998e2870808c82610584929areed@google.com SkASSERT((unsigned)index < (unsigned)CFArrayGetCount(fArray)); 213901ffa71f87664453998e2870808c82610584929areed@google.com CTFontDescriptorRef desc = (CTFontDescriptorRef)CFArrayGetValueAtIndex(fArray, index); 2140cb9a1cd72d397d254c18441743b79de0bbc3da09skia.committer@gmail.com 214101ffa71f87664453998e2870808c82610584929areed@google.com return createFromDesc(fFamilyName, desc); 214201ffa71f87664453998e2870808c82610584929areed@google.com } 2143cb9a1cd72d397d254c18441743b79de0bbc3da09skia.committer@gmail.com 2144ab8665f8e88927b1a9b82aca38483d8a963fd2e0reed@google.com virtual SkTypeface* matchStyle(const SkFontStyle& pattern) SK_OVERRIDE { 2145ab8665f8e88927b1a9b82aca38483d8a963fd2e0reed@google.com if (0 == fCount) { 2146ab8665f8e88927b1a9b82aca38483d8a963fd2e0reed@google.com return NULL; 2147ab8665f8e88927b1a9b82aca38483d8a963fd2e0reed@google.com } 2148ab8665f8e88927b1a9b82aca38483d8a963fd2e0reed@google.com return createFromDesc(fFamilyName, findMatchingDesc(pattern)); 2149ab8665f8e88927b1a9b82aca38483d8a963fd2e0reed@google.com } 2150ab8665f8e88927b1a9b82aca38483d8a963fd2e0reed@google.com 215101ffa71f87664453998e2870808c82610584929areed@google.comprivate: 215201ffa71f87664453998e2870808c82610584929areed@google.com CFArrayRef fArray; 215301ffa71f87664453998e2870808c82610584929areed@google.com CFStringRef fFamilyName; 2154159dfb6076b6a25e4bb87c5723567f1caf12e03freed@google.com int fCount; 2155ab8665f8e88927b1a9b82aca38483d8a963fd2e0reed@google.com 2156ab8665f8e88927b1a9b82aca38483d8a963fd2e0reed@google.com CTFontDescriptorRef findMatchingDesc(const SkFontStyle& pattern) const { 2157ab8665f8e88927b1a9b82aca38483d8a963fd2e0reed@google.com int bestMetric = SK_MaxS32; 2158ab8665f8e88927b1a9b82aca38483d8a963fd2e0reed@google.com CTFontDescriptorRef bestDesc = NULL; 2159e0a1ec938fbf36150f4d0869cf95fb5b7e0edcceskia.committer@gmail.com 2160ab8665f8e88927b1a9b82aca38483d8a963fd2e0reed@google.com for (int i = 0; i < fCount; ++i) { 2161ab8665f8e88927b1a9b82aca38483d8a963fd2e0reed@google.com CTFontDescriptorRef desc = (CTFontDescriptorRef)CFArrayGetValueAtIndex(fArray, i); 2162ab8665f8e88927b1a9b82aca38483d8a963fd2e0reed@google.com int metric = compute_metric(pattern, desc2fontstyle(desc)); 2163ab8665f8e88927b1a9b82aca38483d8a963fd2e0reed@google.com if (0 == metric) { 2164ab8665f8e88927b1a9b82aca38483d8a963fd2e0reed@google.com return desc; 2165ab8665f8e88927b1a9b82aca38483d8a963fd2e0reed@google.com } 2166ab8665f8e88927b1a9b82aca38483d8a963fd2e0reed@google.com if (metric < bestMetric) { 2167ab8665f8e88927b1a9b82aca38483d8a963fd2e0reed@google.com bestMetric = metric; 2168ab8665f8e88927b1a9b82aca38483d8a963fd2e0reed@google.com bestDesc = desc; 2169ab8665f8e88927b1a9b82aca38483d8a963fd2e0reed@google.com } 2170ab8665f8e88927b1a9b82aca38483d8a963fd2e0reed@google.com } 2171ab8665f8e88927b1a9b82aca38483d8a963fd2e0reed@google.com SkASSERT(bestDesc); 2172ab8665f8e88927b1a9b82aca38483d8a963fd2e0reed@google.com return bestDesc; 2173ab8665f8e88927b1a9b82aca38483d8a963fd2e0reed@google.com } 217401ffa71f87664453998e2870808c82610584929areed@google.com}; 217501ffa71f87664453998e2870808c82610584929areed@google.com 2176e621e833c89b7621721bbc8a162c5685aa33ade0reed@google.comclass SkFontMgr_Mac : public SkFontMgr { 217701ffa71f87664453998e2870808c82610584929areed@google.com int fCount; 217801ffa71f87664453998e2870808c82610584929areed@google.com CFArrayRef fNames; 217901ffa71f87664453998e2870808c82610584929areed@google.com 218001ffa71f87664453998e2870808c82610584929areed@google.com CFStringRef stringAt(int index) const { 218101ffa71f87664453998e2870808c82610584929areed@google.com SkASSERT((unsigned)index < (unsigned)fCount); 218201ffa71f87664453998e2870808c82610584929areed@google.com return (CFStringRef)CFArrayGetValueAtIndex(fNames, index); 218301ffa71f87664453998e2870808c82610584929areed@google.com } 218401ffa71f87664453998e2870808c82610584929areed@google.com 218501ffa71f87664453998e2870808c82610584929areed@google.com void lazyInit() { 218601ffa71f87664453998e2870808c82610584929areed@google.com if (NULL == fNames) { 21879c28f1149c205580cbb0f018b083d065a7ae9222reed@google.com fNames = SkCTFontManagerCopyAvailableFontFamilyNames(); 218801ffa71f87664453998e2870808c82610584929areed@google.com fCount = fNames ? CFArrayGetCount(fNames) : 0; 218901ffa71f87664453998e2870808c82610584929areed@google.com } 219001ffa71f87664453998e2870808c82610584929areed@google.com } 219101ffa71f87664453998e2870808c82610584929areed@google.com 2192ab8665f8e88927b1a9b82aca38483d8a963fd2e0reed@google.com static SkFontStyleSet* CreateSet(CFStringRef cfFamilyName) { 2193ab8665f8e88927b1a9b82aca38483d8a963fd2e0reed@google.com AutoCFRelease<CFMutableDictionaryRef> cfAttr( 2194ab8665f8e88927b1a9b82aca38483d8a963fd2e0reed@google.com CFDictionaryCreateMutable(kCFAllocatorDefault, 0, 2195ab8665f8e88927b1a9b82aca38483d8a963fd2e0reed@google.com &kCFTypeDictionaryKeyCallBacks, 2196ab8665f8e88927b1a9b82aca38483d8a963fd2e0reed@google.com &kCFTypeDictionaryValueCallBacks)); 2197e0a1ec938fbf36150f4d0869cf95fb5b7e0edcceskia.committer@gmail.com 2198ab8665f8e88927b1a9b82aca38483d8a963fd2e0reed@google.com CFDictionaryAddValue(cfAttr, kCTFontFamilyNameAttribute, cfFamilyName); 2199e0a1ec938fbf36150f4d0869cf95fb5b7e0edcceskia.committer@gmail.com 2200ab8665f8e88927b1a9b82aca38483d8a963fd2e0reed@google.com AutoCFRelease<CTFontDescriptorRef> desc( 2201ab8665f8e88927b1a9b82aca38483d8a963fd2e0reed@google.com CTFontDescriptorCreateWithAttributes(cfAttr)); 2202ab8665f8e88927b1a9b82aca38483d8a963fd2e0reed@google.com return SkNEW_ARGS(SkFontStyleSet_Mac, (cfFamilyName, desc)); 2203ab8665f8e88927b1a9b82aca38483d8a963fd2e0reed@google.com } 2204e0a1ec938fbf36150f4d0869cf95fb5b7e0edcceskia.committer@gmail.com 2205e621e833c89b7621721bbc8a162c5685aa33ade0reed@google.compublic: 220601ffa71f87664453998e2870808c82610584929areed@google.com SkFontMgr_Mac() : fCount(0), fNames(NULL) {} 220701ffa71f87664453998e2870808c82610584929areed@google.com 220801ffa71f87664453998e2870808c82610584929areed@google.com virtual ~SkFontMgr_Mac() { 220901ffa71f87664453998e2870808c82610584929areed@google.com CFSafeRelease(fNames); 221001ffa71f87664453998e2870808c82610584929areed@google.com } 2211e621e833c89b7621721bbc8a162c5685aa33ade0reed@google.com 2212e621e833c89b7621721bbc8a162c5685aa33ade0reed@google.comprotected: 2213e621e833c89b7621721bbc8a162c5685aa33ade0reed@google.com virtual int onCountFamilies() SK_OVERRIDE { 221401ffa71f87664453998e2870808c82610584929areed@google.com this->lazyInit(); 221501ffa71f87664453998e2870808c82610584929areed@google.com return fCount; 2216e621e833c89b7621721bbc8a162c5685aa33ade0reed@google.com } 2217e621e833c89b7621721bbc8a162c5685aa33ade0reed@google.com 2218e621e833c89b7621721bbc8a162c5685aa33ade0reed@google.com virtual void onGetFamilyName(int index, SkString* familyName) SK_OVERRIDE { 221901ffa71f87664453998e2870808c82610584929areed@google.com this->lazyInit(); 222001ffa71f87664453998e2870808c82610584929areed@google.com if ((unsigned)index < (unsigned)fCount) { 222101ffa71f87664453998e2870808c82610584929areed@google.com CFStringToSkString(this->stringAt(index), familyName); 222201ffa71f87664453998e2870808c82610584929areed@google.com } else { 222301ffa71f87664453998e2870808c82610584929areed@google.com familyName->reset(); 222401ffa71f87664453998e2870808c82610584929areed@google.com } 2225e621e833c89b7621721bbc8a162c5685aa33ade0reed@google.com } 2226e621e833c89b7621721bbc8a162c5685aa33ade0reed@google.com 2227e621e833c89b7621721bbc8a162c5685aa33ade0reed@google.com virtual SkFontStyleSet* onCreateStyleSet(int index) SK_OVERRIDE { 222801ffa71f87664453998e2870808c82610584929areed@google.com this->lazyInit(); 222901ffa71f87664453998e2870808c82610584929areed@google.com if ((unsigned)index >= (unsigned)fCount) { 223001ffa71f87664453998e2870808c82610584929areed@google.com return NULL; 223101ffa71f87664453998e2870808c82610584929areed@google.com } 2232ab8665f8e88927b1a9b82aca38483d8a963fd2e0reed@google.com return CreateSet(this->stringAt(index)); 2233e621e833c89b7621721bbc8a162c5685aa33ade0reed@google.com } 2234e0a1ec938fbf36150f4d0869cf95fb5b7e0edcceskia.committer@gmail.com 2235ab8665f8e88927b1a9b82aca38483d8a963fd2e0reed@google.com virtual SkFontStyleSet* onMatchFamily(const char familyName[]) SK_OVERRIDE { 2236ab8665f8e88927b1a9b82aca38483d8a963fd2e0reed@google.com AutoCFRelease<CFStringRef> cfName(make_CFString(familyName)); 2237ab8665f8e88927b1a9b82aca38483d8a963fd2e0reed@google.com return CreateSet(cfName); 2238ab8665f8e88927b1a9b82aca38483d8a963fd2e0reed@google.com } 2239e0a1ec938fbf36150f4d0869cf95fb5b7e0edcceskia.committer@gmail.com 2240e621e833c89b7621721bbc8a162c5685aa33ade0reed@google.com virtual SkTypeface* onMatchFamilyStyle(const char familyName[], 2241e621e833c89b7621721bbc8a162c5685aa33ade0reed@google.com const SkFontStyle&) SK_OVERRIDE { 2242e621e833c89b7621721bbc8a162c5685aa33ade0reed@google.com return NULL; 2243e621e833c89b7621721bbc8a162c5685aa33ade0reed@google.com } 2244b691cc7b343bbe193c11aa423f95783c073bef6dskia.committer@gmail.com 2245e621e833c89b7621721bbc8a162c5685aa33ade0reed@google.com virtual SkTypeface* onMatchFaceStyle(const SkTypeface* familyMember, 2246e621e833c89b7621721bbc8a162c5685aa33ade0reed@google.com const SkFontStyle&) SK_OVERRIDE { 2247e621e833c89b7621721bbc8a162c5685aa33ade0reed@google.com return NULL; 2248e621e833c89b7621721bbc8a162c5685aa33ade0reed@google.com } 2249b691cc7b343bbe193c11aa423f95783c073bef6dskia.committer@gmail.com 2250e621e833c89b7621721bbc8a162c5685aa33ade0reed@google.com virtual SkTypeface* onCreateFromData(SkData* data, 2251e621e833c89b7621721bbc8a162c5685aa33ade0reed@google.com int ttcIndex) SK_OVERRIDE { 2252e621e833c89b7621721bbc8a162c5685aa33ade0reed@google.com AutoCFRelease<CGDataProviderRef> pr(SkCreateDataProviderFromData(data)); 2253e621e833c89b7621721bbc8a162c5685aa33ade0reed@google.com if (NULL == pr) { 2254e621e833c89b7621721bbc8a162c5685aa33ade0reed@google.com return NULL; 2255e621e833c89b7621721bbc8a162c5685aa33ade0reed@google.com } 2256e621e833c89b7621721bbc8a162c5685aa33ade0reed@google.com return create_from_dataProvider(pr); 2257e621e833c89b7621721bbc8a162c5685aa33ade0reed@google.com } 2258e621e833c89b7621721bbc8a162c5685aa33ade0reed@google.com 2259e621e833c89b7621721bbc8a162c5685aa33ade0reed@google.com virtual SkTypeface* onCreateFromStream(SkStream* stream, 2260e621e833c89b7621721bbc8a162c5685aa33ade0reed@google.com int ttcIndex) SK_OVERRIDE { 2261e621e833c89b7621721bbc8a162c5685aa33ade0reed@google.com AutoCFRelease<CGDataProviderRef> pr(SkCreateDataProviderFromStream(stream)); 2262e621e833c89b7621721bbc8a162c5685aa33ade0reed@google.com if (NULL == pr) { 2263e621e833c89b7621721bbc8a162c5685aa33ade0reed@google.com return NULL; 2264e621e833c89b7621721bbc8a162c5685aa33ade0reed@google.com } 2265e621e833c89b7621721bbc8a162c5685aa33ade0reed@google.com return create_from_dataProvider(pr); 2266e621e833c89b7621721bbc8a162c5685aa33ade0reed@google.com } 2267e621e833c89b7621721bbc8a162c5685aa33ade0reed@google.com 2268e621e833c89b7621721bbc8a162c5685aa33ade0reed@google.com virtual SkTypeface* onCreateFromFile(const char path[], 2269e621e833c89b7621721bbc8a162c5685aa33ade0reed@google.com int ttcIndex) SK_OVERRIDE { 2270e621e833c89b7621721bbc8a162c5685aa33ade0reed@google.com AutoCFRelease<CGDataProviderRef> pr(CGDataProviderCreateWithFilename(path)); 2271e621e833c89b7621721bbc8a162c5685aa33ade0reed@google.com if (NULL == pr) { 2272e621e833c89b7621721bbc8a162c5685aa33ade0reed@google.com return NULL; 2273e621e833c89b7621721bbc8a162c5685aa33ade0reed@google.com } 2274e621e833c89b7621721bbc8a162c5685aa33ade0reed@google.com return create_from_dataProvider(pr); 2275e621e833c89b7621721bbc8a162c5685aa33ade0reed@google.com } 2276ff58f8b49a03197747998f4069e0980d9f6d34c0skia.committer@gmail.com 2277836008c1588a111f090a606726822d62d3026e00reed@google.com virtual SkTypeface* onLegacyCreateTypeface(const char familyName[], 2278836008c1588a111f090a606726822d62d3026e00reed@google.com unsigned styleBits) SK_OVERRIDE { 2279836008c1588a111f090a606726822d62d3026e00reed@google.com return create_typeface(NULL, familyName, (SkTypeface::Style)styleBits); 2280836008c1588a111f090a606726822d62d3026e00reed@google.com } 2281e621e833c89b7621721bbc8a162c5685aa33ade0reed@google.com}; 2282e621e833c89b7621721bbc8a162c5685aa33ade0reed@google.com 2283836008c1588a111f090a606726822d62d3026e00reed@google.com/////////////////////////////////////////////////////////////////////////////// 2284836008c1588a111f090a606726822d62d3026e00reed@google.com 2285836008c1588a111f090a606726822d62d3026e00reed@google.com#ifndef SK_FONTHOST_USES_FONTMGR 2286836008c1588a111f090a606726822d62d3026e00reed@google.com 2287836008c1588a111f090a606726822d62d3026e00reed@google.comSkTypeface* SkFontHost::CreateTypeface(const SkTypeface* familyFace, 2288836008c1588a111f090a606726822d62d3026e00reed@google.com const char familyName[], 2289836008c1588a111f090a606726822d62d3026e00reed@google.com SkTypeface::Style style) { 2290836008c1588a111f090a606726822d62d3026e00reed@google.com return create_typeface(familyFace, familyName, style); 2291836008c1588a111f090a606726822d62d3026e00reed@google.com} 2292836008c1588a111f090a606726822d62d3026e00reed@google.com 2293836008c1588a111f090a606726822d62d3026e00reed@google.comSkTypeface* SkFontHost::CreateTypefaceFromStream(SkStream* stream) { 2294836008c1588a111f090a606726822d62d3026e00reed@google.com AutoCFRelease<CGDataProviderRef> provider(SkCreateDataProviderFromStream(stream)); 2295836008c1588a111f090a606726822d62d3026e00reed@google.com if (NULL == provider) { 2296836008c1588a111f090a606726822d62d3026e00reed@google.com return NULL; 2297836008c1588a111f090a606726822d62d3026e00reed@google.com } 2298836008c1588a111f090a606726822d62d3026e00reed@google.com return create_from_dataProvider(provider); 2299836008c1588a111f090a606726822d62d3026e00reed@google.com} 2300836008c1588a111f090a606726822d62d3026e00reed@google.com 2301836008c1588a111f090a606726822d62d3026e00reed@google.comSkTypeface* SkFontHost::CreateTypefaceFromFile(const char path[]) { 2302836008c1588a111f090a606726822d62d3026e00reed@google.com AutoCFRelease<CGDataProviderRef> provider(CGDataProviderCreateWithFilename(path)); 2303836008c1588a111f090a606726822d62d3026e00reed@google.com if (NULL == provider) { 2304836008c1588a111f090a606726822d62d3026e00reed@google.com return NULL; 2305836008c1588a111f090a606726822d62d3026e00reed@google.com } 2306836008c1588a111f090a606726822d62d3026e00reed@google.com return create_from_dataProvider(provider); 2307836008c1588a111f090a606726822d62d3026e00reed@google.com} 2308836008c1588a111f090a606726822d62d3026e00reed@google.com 2309836008c1588a111f090a606726822d62d3026e00reed@google.com#endif 2310836008c1588a111f090a606726822d62d3026e00reed@google.com 2311e621e833c89b7621721bbc8a162c5685aa33ade0reed@google.comSkFontMgr* SkFontMgr::Factory() { 2312e621e833c89b7621721bbc8a162c5685aa33ade0reed@google.com return SkNEW(SkFontMgr_Mac); 2313e621e833c89b7621721bbc8a162c5685aa33ade0reed@google.com} 2314e621e833c89b7621721bbc8a162c5685aa33ade0reed@google.com#endif 2315