1ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com 20680d6c7caa9c2d4b1e5ee49e5816b96be0cc7bfreed@android.com/* 3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2006 The Android Open Source Project 4ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * 5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be 6ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file. 7ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com */ 8ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com 9b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org#include <vector> 10b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org#ifdef SK_BUILD_FOR_MAC 11b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org#import <ApplicationServices/ApplicationServices.h> 12b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org#endif 13b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 14b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org#ifdef SK_BUILD_FOR_IOS 15b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org#include <CoreText/CoreText.h> 163dcbd4673d7ee03ded1c08e6d58713cb07e9d1f1reed@google.com#include <CoreText/CTFontManager.h> 17b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org#include <CoreGraphics/CoreGraphics.h> 18b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org#include <CoreFoundation/CoreFoundation.h> 19b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org#endif 200680d6c7caa9c2d4b1e5ee49e5816b96be0cc7bfreed@android.com 21b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org#include "SkFontHost.h" 22b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org#include "SkCGUtils.h" 23b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org#include "SkColorPriv.h" 24b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org#include "SkDescriptor.h" 25b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org#include "SkEndian.h" 26b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org#include "SkFontDescriptor.h" 27b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org#include "SkFloatingPoint.h" 28b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org#include "SkGlyph.h" 29b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org#include "SkMaskGamma.h" 30b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org#include "SkSFNTHeader.h" 31b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org#include "SkOTTable_glyf.h" 32b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org#include "SkOTTable_head.h" 33b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org#include "SkOTTable_hhea.h" 34b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org#include "SkOTTable_loca.h" 35b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org#include "SkOTUtils.h" 36b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org#include "SkPaint.h" 37b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org#include "SkPath.h" 38b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org#include "SkString.h" 39b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org#include "SkStream.h" 40b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org#include "SkThread.h" 41b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org#include "SkTypeface_mac.h" 42b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org#include "SkUtils.h" 43b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org#include "SkTypefaceCache.h" 44ce8b3de6058eae07ddc2eed6f96701e009bb91ecreed@google.com#include "SkFontMgr.h" 45bcb42aecf1bdb9ae80d766d203b4f636b954cf03reed@google.com#include "SkUtils.h" 460680d6c7caa9c2d4b1e5ee49e5816b96be0cc7bfreed@android.com 47f77b35d86ad439917bda78334deb31fbcc16cdaereed@google.com//#define HACK_COLORGLYPHS 48f77b35d86ad439917bda78334deb31fbcc16cdaereed@google.com 49b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.orgclass SkScalerContext_Mac; 50b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 513dcbd4673d7ee03ded1c08e6d58713cb07e9d1f1reed@google.com// CTFontManagerCopyAvailableFontFamilyNames() is not always available, so we 523dcbd4673d7ee03ded1c08e6d58713cb07e9d1f1reed@google.com// provide a wrapper here that will return an empty array if need be. 533dcbd4673d7ee03ded1c08e6d58713cb07e9d1f1reed@google.comstatic CFArrayRef SkCTFontManagerCopyAvailableFontFamilyNames() { 543dcbd4673d7ee03ded1c08e6d58713cb07e9d1f1reed@google.com#ifdef SK_BUILD_FOR_IOS 553dcbd4673d7ee03ded1c08e6d58713cb07e9d1f1reed@google.com return CFArrayCreate(NULL, NULL, 0, NULL); 563dcbd4673d7ee03ded1c08e6d58713cb07e9d1f1reed@google.com#else 573dcbd4673d7ee03ded1c08e6d58713cb07e9d1f1reed@google.com return CTFontManagerCopyAvailableFontFamilyNames(); 583dcbd4673d7ee03ded1c08e6d58713cb07e9d1f1reed@google.com#endif 593dcbd4673d7ee03ded1c08e6d58713cb07e9d1f1reed@google.com} 603dcbd4673d7ee03ded1c08e6d58713cb07e9d1f1reed@google.com 613dcbd4673d7ee03ded1c08e6d58713cb07e9d1f1reed@google.com 62b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org// Being templated and taking const T* prevents calling 63b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org// CFSafeRelease(autoCFRelease) through implicit conversion. 64b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.orgtemplate <typename T> static void CFSafeRelease(/*CFTypeRef*/const T* cfTypeRef) { 65b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org if (cfTypeRef) { 66b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org CFRelease(cfTypeRef); 67b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org } 68b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org} 69b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 70b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org// Being templated and taking const T* prevents calling 71b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org// CFSafeRetain(autoCFRelease) through implicit conversion. 72b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.orgtemplate <typename T> static void CFSafeRetain(/*CFTypeRef*/const T* cfTypeRef) { 73b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org if (cfTypeRef) { 74b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org CFRetain(cfTypeRef); 75b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org } 76b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org} 77b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 78b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org/** Acts like a CFRef, but calls CFSafeRelease when it goes out of scope. */ 79b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.orgtemplate<typename CFRef> class AutoCFRelease : private SkNoncopyable { 80b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.orgpublic: 81b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org explicit AutoCFRelease(CFRef cfRef = NULL) : fCFRef(cfRef) { } 82b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org ~AutoCFRelease() { CFSafeRelease(fCFRef); } 83b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 84b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org void reset(CFRef that = NULL) { 85e9d2d09ea53d20828d2f5320fc1f19a9952f2b31ljagielski if (that != fCFRef) { 86e9d2d09ea53d20828d2f5320fc1f19a9952f2b31ljagielski CFSafeRelease(fCFRef); 87e9d2d09ea53d20828d2f5320fc1f19a9952f2b31ljagielski fCFRef = that; 88e9d2d09ea53d20828d2f5320fc1f19a9952f2b31ljagielski } 89b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org } 90b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 91b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org operator CFRef() const { return fCFRef; } 92b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org CFRef get() const { return fCFRef; } 93b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 94a980269c2498836101146adc729ef780fb89824ebungeman@google.com CFRef* operator&() { SkASSERT(fCFRef == NULL); return &fCFRef; } 95b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.orgprivate: 96b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org CFRef fCFRef; 97b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org}; 98b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 99964988f0e93f4a559b7e41db53d70d0282527350reed@google.comstatic CFStringRef make_CFString(const char str[]) { 100964988f0e93f4a559b7e41db53d70d0282527350reed@google.com return CFStringCreateWithCString(NULL, str, kCFStringEncodingUTF8); 101964988f0e93f4a559b7e41db53d70d0282527350reed@google.com} 102964988f0e93f4a559b7e41db53d70d0282527350reed@google.com 103b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.orgtemplate<typename T> class AutoCGTable : SkNoncopyable { 104b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.orgpublic: 105b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org AutoCGTable(CGFontRef font) 106b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org //Undocumented: the tag parameter in this call is expected in machine order and not BE order. 107b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org : fCFData(CGFontCopyTableForTag(font, SkSetFourByteTag(T::TAG0, T::TAG1, T::TAG2, T::TAG3))) 108b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org , fData(fCFData ? reinterpret_cast<const T*>(CFDataGetBytePtr(fCFData)) : NULL) 109b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org { } 110b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 111b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org const T* operator->() const { return fData; } 112b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 113b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.orgprivate: 114b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org AutoCFRelease<CFDataRef> fCFData; 115b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.orgpublic: 116b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org const T* fData; 117b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org}; 118b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 119b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org// inline versions of these rect helpers 120b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 121b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.orgstatic bool CGRectIsEmpty_inline(const CGRect& rect) { 122b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org return rect.size.width <= 0 || rect.size.height <= 0; 123b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org} 124b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 125b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.orgstatic CGFloat CGRectGetMinX_inline(const CGRect& rect) { 126b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org return rect.origin.x; 127b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org} 128b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 129b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.orgstatic CGFloat CGRectGetMaxX_inline(const CGRect& rect) { 130b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org return rect.origin.x + rect.size.width; 131b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org} 132b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 133b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.orgstatic CGFloat CGRectGetMinY_inline(const CGRect& rect) { 134b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org return rect.origin.y; 135b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org} 136b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 137b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.orgstatic CGFloat CGRectGetMaxY_inline(const CGRect& rect) { 138b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org return rect.origin.y + rect.size.height; 139b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org} 140b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 141b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.orgstatic CGFloat CGRectGetWidth_inline(const CGRect& rect) { 142b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org return rect.size.width; 143b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org} 144b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 145b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org/////////////////////////////////////////////////////////////////////////////// 146b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 147b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.orgstatic void sk_memset_rect32(uint32_t* ptr, uint32_t value, 1487fa2a65c0cfc714364490cb715171461143024e0reed@google.com int width, int height, size_t rowBytes) { 149b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org SkASSERT(width); 150b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org SkASSERT(width * sizeof(uint32_t) <= rowBytes); 151b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 152b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org if (width >= 32) { 153b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org while (height) { 154b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org sk_memset32(ptr, value, width); 155b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org ptr = (uint32_t*)((char*)ptr + rowBytes); 156b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org height -= 1; 157b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org } 158b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org return; 159b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org } 160b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 161b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org rowBytes -= width * sizeof(uint32_t); 162b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 163b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org if (width >= 8) { 164b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org while (height) { 165b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org int w = width; 166b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org do { 167b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org *ptr++ = value; *ptr++ = value; 168b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org *ptr++ = value; *ptr++ = value; 169b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org *ptr++ = value; *ptr++ = value; 170b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org *ptr++ = value; *ptr++ = value; 171b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org w -= 8; 172b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org } while (w >= 8); 173b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org while (--w >= 0) { 174b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org *ptr++ = value; 175b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org } 176b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org ptr = (uint32_t*)((char*)ptr + rowBytes); 177b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org height -= 1; 178b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org } 179b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org } else { 180b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org while (height) { 181b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org int w = width; 182b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org do { 183b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org *ptr++ = value; 184b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org } while (--w > 0); 185b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org ptr = (uint32_t*)((char*)ptr + rowBytes); 186b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org height -= 1; 187b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org } 188b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org } 189b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org} 190b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 191b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org#include <sys/utsname.h> 192b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 193b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.orgtypedef uint32_t CGRGBPixel; 194b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 195b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.orgstatic unsigned CGRGBPixel_getAlpha(CGRGBPixel pixel) { 196b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org return pixel & 0xFF; 197b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org} 198b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 199b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org// The calls to support subpixel are present in 10.5, but are not included in 200b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org// the 10.5 SDK. The needed calls have been extracted from the 10.6 SDK and are 201b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org// included below. To verify that CGContextSetShouldSubpixelQuantizeFonts, for 202b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org// instance, is present in the 10.5 CoreGraphics libary, use: 203b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org// cd /Developer/SDKs/MacOSX10.5.sdk/System/Library/Frameworks/ 204b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org// cd ApplicationServices.framework/Frameworks/CoreGraphics.framework/ 205b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org// nm CoreGraphics | grep CGContextSetShouldSubpixelQuantizeFonts 206b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 207b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org#if !defined(MAC_OS_X_VERSION_10_6) || (MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_6) 208b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.orgCG_EXTERN void CGContextSetAllowsFontSmoothing(CGContextRef context, bool value); 209b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.orgCG_EXTERN void CGContextSetAllowsFontSubpixelPositioning(CGContextRef context, bool value); 210b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.orgCG_EXTERN void CGContextSetShouldSubpixelPositionFonts(CGContextRef context, bool value); 211b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.orgCG_EXTERN void CGContextSetAllowsFontSubpixelQuantization(CGContextRef context, bool value); 212b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.orgCG_EXTERN void CGContextSetShouldSubpixelQuantizeFonts(CGContextRef context, bool value); 21304225dcdec5a01bc9889b7fb03e7aceb87fccc6ereed@android.com#endif 2140bf64d48cc18d551dadc7cce0c990352e04f9af8reed@android.com 215b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.orgstatic const char FONT_DEFAULT_NAME[] = "Lucida Sans"; 216b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 217b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org// See Source/WebKit/chromium/base/mac/mac_util.mm DarwinMajorVersionInternal for original source. 218b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.orgstatic int readVersion() { 219b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org struct utsname info; 220b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org if (uname(&info) != 0) { 221b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org SkDebugf("uname failed\n"); 222b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org return 0; 223b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org } 224b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org if (strcmp(info.sysname, "Darwin") != 0) { 225b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org SkDebugf("unexpected uname sysname %s\n", info.sysname); 226b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org return 0; 227b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org } 228b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org char* dot = strchr(info.release, '.'); 229b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org if (!dot) { 230b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org SkDebugf("expected dot in uname release %s\n", info.release); 231b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org return 0; 232b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org } 233b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org int version = atoi(info.release); 234b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org if (version == 0) { 235b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org SkDebugf("could not parse uname release %s\n", info.release); 236b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org } 237b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org return version; 238b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org} 239b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 240b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.orgstatic int darwinVersion() { 241b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org static int darwin_version = readVersion(); 242b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org return darwin_version; 243b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org} 244b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 245b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.orgstatic bool isSnowLeopard() { 246b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org return darwinVersion() == 10; 247b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org} 248b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 249b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.orgstatic bool isLion() { 250b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org return darwinVersion() == 11; 251b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org} 252b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 253b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.orgstatic bool isMountainLion() { 254b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org return darwinVersion() == 12; 255b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org} 256b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 257b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.orgstatic bool isLCDFormat(unsigned format) { 258b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org return SkMask::kLCD16_Format == format || SkMask::kLCD32_Format == format; 259b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org} 260b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 261b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.orgstatic CGFloat ScalarToCG(SkScalar scalar) { 262b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org if (sizeof(CGFloat) == sizeof(float)) { 263b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org return SkScalarToFloat(scalar); 264b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org } else { 265b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org SkASSERT(sizeof(CGFloat) == sizeof(double)); 266b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org return (CGFloat) SkScalarToDouble(scalar); 267b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org } 268b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org} 269b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 270b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.orgstatic SkScalar CGToScalar(CGFloat cgFloat) { 271b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org if (sizeof(CGFloat) == sizeof(float)) { 2724b413c8bb123e42ca4b9c7bfa6bc2167283cb84ccommit-bot@chromium.org return cgFloat; 273b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org } else { 274b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org SkASSERT(sizeof(CGFloat) == sizeof(double)); 275b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org return SkDoubleToScalar(cgFloat); 276b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org } 277b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org} 278b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 279b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.orgstatic CGAffineTransform MatrixToCGAffineTransform(const SkMatrix& matrix, 280b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org SkScalar sx = SK_Scalar1, 281b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org SkScalar sy = SK_Scalar1) { 282b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org return CGAffineTransformMake( ScalarToCG(matrix[SkMatrix::kMScaleX] * sx), 283b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org -ScalarToCG(matrix[SkMatrix::kMSkewY] * sy), 284b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org -ScalarToCG(matrix[SkMatrix::kMSkewX] * sx), 285b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org ScalarToCG(matrix[SkMatrix::kMScaleY] * sy), 286b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org ScalarToCG(matrix[SkMatrix::kMTransX] * sx), 287b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org ScalarToCG(matrix[SkMatrix::kMTransY] * sy)); 288b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org} 289b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 290b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org/////////////////////////////////////////////////////////////////////////////// 291b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 292b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org#define BITMAP_INFO_RGB (kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Host) 293b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org#define BITMAP_INFO_GRAY (kCGImageAlphaNone) 294b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 295b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org/** 296b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org * There does not appear to be a publicly accessable API for determining if lcd 297b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org * font smoothing will be applied if we request it. The main issue is that if 298b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org * smoothing is applied a gamma of 2.0 will be used, if not a gamma of 1.0. 299b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org */ 300b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.orgstatic bool supports_LCD() { 301b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org static int gSupportsLCD = -1; 302b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org if (gSupportsLCD >= 0) { 303b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org return (bool) gSupportsLCD; 304b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org } 305b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org uint32_t rgb = 0; 306b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org AutoCFRelease<CGColorSpaceRef> colorspace(CGColorSpaceCreateDeviceRGB()); 307b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org AutoCFRelease<CGContextRef> cgContext(CGBitmapContextCreate(&rgb, 1, 1, 8, 4, 308b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org colorspace, BITMAP_INFO_RGB)); 309b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org CGContextSelectFont(cgContext, "Helvetica", 16, kCGEncodingMacRoman); 310b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org CGContextSetShouldSmoothFonts(cgContext, true); 311b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org CGContextSetShouldAntialias(cgContext, true); 312b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org CGContextSetTextDrawingMode(cgContext, kCGTextFill); 313b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org CGContextSetGrayFillColor(cgContext, 1, 1); 314b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org CGContextShowTextAtPoint(cgContext, -1, 0, "|", 1); 315b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org uint32_t r = (rgb >> 16) & 0xFF; 316b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org uint32_t g = (rgb >> 8) & 0xFF; 317b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org uint32_t b = (rgb >> 0) & 0xFF; 318b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org gSupportsLCD = (r != g || r != b); 319b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org return (bool) gSupportsLCD; 320b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org} 321b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 322b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.orgclass Offscreen { 323b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.orgpublic: 324b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org Offscreen(); 325b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 326b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org CGRGBPixel* getCG(const SkScalerContext_Mac& context, const SkGlyph& glyph, 327b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org CGGlyph glyphID, size_t* rowBytesPtr, 328b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org bool generateA8FromLCD); 329b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 330b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.orgprivate: 331b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org enum { 332b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org kSize = 32 * 32 * sizeof(CGRGBPixel) 333b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org }; 334b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org SkAutoSMalloc<kSize> fImageStorage; 335b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org AutoCFRelease<CGColorSpaceRef> fRGBSpace; 336b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 337b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org // cached state 338b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org AutoCFRelease<CGContextRef> fCG; 339b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org SkISize fSize; 340b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org bool fDoAA; 341b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org bool fDoLCD; 342b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 343b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org static int RoundSize(int dimension) { 344b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org return SkNextPow2(dimension); 345b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org } 346b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org}; 347b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 348d55846d100bb09448b398b41798bd4ab100a753askia.committer@gmail.comOffscreen::Offscreen() : fRGBSpace(NULL), fCG(NULL), 34987379e17c5e95c6fe0d88b3b9ae134355cfafc66robertphillips@google.com fDoAA(false), fDoLCD(false) { 350b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org fSize.set(0, 0); 351b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org} 352b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 353b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org/////////////////////////////////////////////////////////////////////////////// 354b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 355fe74765f0d302669ae49e68074492bdfe0ce6e6fbungeman@google.comstatic SkTypeface::Style computeStyleBits(CTFontRef font, bool* isFixedPitch) { 356b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org unsigned style = SkTypeface::kNormal; 357b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org CTFontSymbolicTraits traits = CTFontGetSymbolicTraits(font); 358b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 359b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org if (traits & kCTFontBoldTrait) { 360b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org style |= SkTypeface::kBold; 361b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org } 362b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org if (traits & kCTFontItalicTrait) { 363b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org style |= SkTypeface::kItalic; 364b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org } 365fe74765f0d302669ae49e68074492bdfe0ce6e6fbungeman@google.com if (isFixedPitch) { 366fe74765f0d302669ae49e68074492bdfe0ce6e6fbungeman@google.com *isFixedPitch = (traits & kCTFontMonoSpaceTrait) != 0; 367b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org } 368b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org return (SkTypeface::Style)style; 369b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org} 370b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 371b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.orgstatic SkFontID CTFontRef_to_SkFontID(CTFontRef fontRef) { 372b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org SkFontID id = 0; 373b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org// CTFontGetPlatformFont and ATSFontRef are not supported on iOS, so we have to 374b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org// bracket this to be Mac only. 375b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org#ifdef SK_BUILD_FOR_MAC 376b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org ATSFontRef ats = CTFontGetPlatformFont(fontRef, NULL); 377b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org id = (SkFontID)ats; 378b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org if (id != 0) { 379b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org id &= 0x3FFFFFFF; // make top two bits 00 380b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org return id; 381b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org } 382b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org#endif 383b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org // CTFontGetPlatformFont returns NULL if the font is local 384b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org // (e.g., was created by a CSS3 @font-face rule). 385b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org AutoCFRelease<CGFontRef> cgFont(CTFontCopyGraphicsFont(fontRef, NULL)); 386b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org AutoCGTable<SkOTTableHead> headTable(cgFont); 387b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org if (headTable.fData) { 388b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org id = (SkFontID) headTable->checksumAdjustment; 389b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org id = (id & 0x3FFFFFFF) | 0x40000000; // make top two bits 01 390b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org } 391b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org // well-formed fonts have checksums, but as a last resort, use the pointer. 392b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org if (id == 0) { 393b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org id = (SkFontID) (uintptr_t) fontRef; 394b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org id = (id & 0x3FFFFFFF) | 0x80000000; // make top two bits 10 395b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org } 396b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org return id; 397b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org} 398b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 399ce8b3de6058eae07ddc2eed6f96701e009bb91ecreed@google.comstatic SkFontStyle stylebits2fontstyle(SkTypeface::Style styleBits) { 400ce8b3de6058eae07ddc2eed6f96701e009bb91ecreed@google.com return SkFontStyle((styleBits & SkTypeface::kBold) 401ce8b3de6058eae07ddc2eed6f96701e009bb91ecreed@google.com ? SkFontStyle::kBold_Weight 402ce8b3de6058eae07ddc2eed6f96701e009bb91ecreed@google.com : SkFontStyle::kNormal_Weight, 403ce8b3de6058eae07ddc2eed6f96701e009bb91ecreed@google.com SkFontStyle::kNormal_Width, 404ce8b3de6058eae07ddc2eed6f96701e009bb91ecreed@google.com (styleBits & SkTypeface::kItalic) 405ce8b3de6058eae07ddc2eed6f96701e009bb91ecreed@google.com ? SkFontStyle::kItalic_Slant 406ce8b3de6058eae07ddc2eed6f96701e009bb91ecreed@google.com : SkFontStyle::kUpright_Slant); 407ce8b3de6058eae07ddc2eed6f96701e009bb91ecreed@google.com} 408ce8b3de6058eae07ddc2eed6f96701e009bb91ecreed@google.com 409ce8b3de6058eae07ddc2eed6f96701e009bb91ecreed@google.com#define WEIGHT_THRESHOLD ((SkFontStyle::kNormal_Weight + SkFontStyle::kBold_Weight)/2) 410ce8b3de6058eae07ddc2eed6f96701e009bb91ecreed@google.com 411ce8b3de6058eae07ddc2eed6f96701e009bb91ecreed@google.comstatic SkTypeface::Style fontstyle2stylebits(const SkFontStyle& fs) { 412ce8b3de6058eae07ddc2eed6f96701e009bb91ecreed@google.com unsigned style = 0; 413ce8b3de6058eae07ddc2eed6f96701e009bb91ecreed@google.com if (fs.width() >= WEIGHT_THRESHOLD) { 414ce8b3de6058eae07ddc2eed6f96701e009bb91ecreed@google.com style |= SkTypeface::kBold; 415ce8b3de6058eae07ddc2eed6f96701e009bb91ecreed@google.com } 416ce8b3de6058eae07ddc2eed6f96701e009bb91ecreed@google.com if (fs.isItalic()) { 417ce8b3de6058eae07ddc2eed6f96701e009bb91ecreed@google.com style |= SkTypeface::kItalic; 418ce8b3de6058eae07ddc2eed6f96701e009bb91ecreed@google.com } 419ce8b3de6058eae07ddc2eed6f96701e009bb91ecreed@google.com return (SkTypeface::Style)style; 420ce8b3de6058eae07ddc2eed6f96701e009bb91ecreed@google.com} 421ce8b3de6058eae07ddc2eed6f96701e009bb91ecreed@google.com 422b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.orgclass SkTypeface_Mac : public SkTypeface { 423b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.orgpublic: 424fe74765f0d302669ae49e68074492bdfe0ce6e6fbungeman@google.com SkTypeface_Mac(SkTypeface::Style style, SkFontID fontID, bool isFixedPitch, 42526337e970201cae39f44b49546b8d9b0bc5e5c98caseq CTFontRef fontRef, const char name[], bool isLocalStream) 426ce8b3de6058eae07ddc2eed6f96701e009bb91ecreed@google.com : SkTypeface(style, fontID, isFixedPitch) 427ce8b3de6058eae07ddc2eed6f96701e009bb91ecreed@google.com , fName(name) 428ce8b3de6058eae07ddc2eed6f96701e009bb91ecreed@google.com , fFontRef(fontRef) // caller has already called CFRetain for us 429ce8b3de6058eae07ddc2eed6f96701e009bb91ecreed@google.com , fFontStyle(stylebits2fontstyle(style)) 43026337e970201cae39f44b49546b8d9b0bc5e5c98caseq , fIsLocalStream(isLocalStream) 431b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org { 432b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org SkASSERT(fontRef); 433b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org } 43437cbc7fd014e3b35833523dbdbe3bc3ac52ecacdskia.committer@gmail.com 435ce8b3de6058eae07ddc2eed6f96701e009bb91ecreed@google.com SkTypeface_Mac(const SkFontStyle& fs, SkFontID fontID, bool isFixedPitch, 43626337e970201cae39f44b49546b8d9b0bc5e5c98caseq CTFontRef fontRef, const char name[], bool isLocalStream) 437ce8b3de6058eae07ddc2eed6f96701e009bb91ecreed@google.com : SkTypeface(fontstyle2stylebits(fs), fontID, isFixedPitch) 438ce8b3de6058eae07ddc2eed6f96701e009bb91ecreed@google.com , fName(name) 439ce8b3de6058eae07ddc2eed6f96701e009bb91ecreed@google.com , fFontRef(fontRef) // caller has already called CFRetain for us 440ce8b3de6058eae07ddc2eed6f96701e009bb91ecreed@google.com , fFontStyle(fs) 44126337e970201cae39f44b49546b8d9b0bc5e5c98caseq , fIsLocalStream(isLocalStream) 442ce8b3de6058eae07ddc2eed6f96701e009bb91ecreed@google.com { 443ce8b3de6058eae07ddc2eed6f96701e009bb91ecreed@google.com SkASSERT(fontRef); 444ce8b3de6058eae07ddc2eed6f96701e009bb91ecreed@google.com } 44537cbc7fd014e3b35833523dbdbe3bc3ac52ecacdskia.committer@gmail.com 446b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org SkString fName; 447b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org AutoCFRelease<CTFontRef> fFontRef; 448ce8b3de6058eae07ddc2eed6f96701e009bb91ecreed@google.com SkFontStyle fFontStyle; 449b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 450b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.orgprotected: 451b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org friend class SkFontHost; // to access our protected members for deprecated methods 452b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 453b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org virtual int onGetUPEM() const SK_OVERRIDE; 454cc9aad5787b52216f46b9d6d95a781240e3e6b6breed@google.com virtual SkStream* onOpenStream(int* ttcIndex) const SK_OVERRIDE; 455b374d6a62c0259387d90cad74753d8bad9ee1beabungeman virtual void onGetFamilyName(SkString* familyName) const SK_OVERRIDE; 456839702b61934914118ec557dd641be322eba3b5fbungeman@google.com virtual SkTypeface::LocalizedStrings* onCreateFamilyNameIterator() const SK_OVERRIDE; 457b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org virtual int onGetTableTags(SkFontTableTag tags[]) const SK_OVERRIDE; 458b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org virtual size_t onGetTableData(SkFontTableTag, size_t offset, 459b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org size_t length, void* data) const SK_OVERRIDE; 460b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org virtual SkScalerContext* onCreateScalerContext(const SkDescriptor*) const SK_OVERRIDE; 461b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org virtual void onFilterRec(SkScalerContextRec*) const SK_OVERRIDE; 4625526ede94a2fc58bcf6b578b12a29f6addad776dreed@google.com virtual void onGetFontDescriptor(SkFontDescriptor*, bool*) const SK_OVERRIDE; 4632689f615e364dc48ad73826564f5b13d2329179dreed@google.com virtual SkAdvancedTypefaceMetrics* onGetAdvancedTypefaceMetrics( 4642689f615e364dc48ad73826564f5b13d2329179dreed@google.com SkAdvancedTypefaceMetrics::PerGlyphInfo, 4652689f615e364dc48ad73826564f5b13d2329179dreed@google.com const uint32_t*, uint32_t) const SK_OVERRIDE; 466bcb42aecf1bdb9ae80d766d203b4f636b954cf03reed@google.com virtual int onCharsToGlyphs(const void* chars, Encoding, uint16_t glyphs[], 467bcb42aecf1bdb9ae80d766d203b4f636b954cf03reed@google.com int glyphCount) const SK_OVERRIDE; 468bcb42aecf1bdb9ae80d766d203b4f636b954cf03reed@google.com virtual int onCountGlyphs() const SK_OVERRIDE; 469c1641fc92259a1ca5cfc32cd5c8c55ea316b2bd1skia.committer@gmail.com 470b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.orgprivate: 47126337e970201cae39f44b49546b8d9b0bc5e5c98caseq bool fIsLocalStream; 472ce8b3de6058eae07ddc2eed6f96701e009bb91ecreed@google.com 473b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org typedef SkTypeface INHERITED; 474b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org}; 475b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 47626337e970201cae39f44b49546b8d9b0bc5e5c98caseqstatic SkTypeface* NewFromFontRef(CTFontRef fontRef, const char name[], bool isLocalStream) { 477b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org SkASSERT(fontRef); 478fe74765f0d302669ae49e68074492bdfe0ce6e6fbungeman@google.com bool isFixedPitch; 479fe74765f0d302669ae49e68074492bdfe0ce6e6fbungeman@google.com SkTypeface::Style style = computeStyleBits(fontRef, &isFixedPitch); 480b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org SkFontID fontID = CTFontRef_to_SkFontID(fontRef); 481b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 48226337e970201cae39f44b49546b8d9b0bc5e5c98caseq return new SkTypeface_Mac(style, fontID, isFixedPitch, fontRef, name, isLocalStream); 483b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org} 484b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 485b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.orgstatic SkTypeface* NewFromName(const char familyName[], SkTypeface::Style theStyle) { 486b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org CTFontRef ctFont = NULL; 487b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 488b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org CTFontSymbolicTraits ctFontTraits = 0; 489b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org if (theStyle & SkTypeface::kBold) { 490b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org ctFontTraits |= kCTFontBoldTrait; 491b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org } 492b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org if (theStyle & SkTypeface::kItalic) { 493b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org ctFontTraits |= kCTFontItalicTrait; 494b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org } 495b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 496b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org // Create the font info 497964988f0e93f4a559b7e41db53d70d0282527350reed@google.com AutoCFRelease<CFStringRef> cfFontName(make_CFString(familyName)); 498b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 499b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org AutoCFRelease<CFNumberRef> cfFontTraits( 500b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &ctFontTraits)); 501b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 502b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org AutoCFRelease<CFMutableDictionaryRef> cfAttributes( 503b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org CFDictionaryCreateMutable(kCFAllocatorDefault, 0, 504b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org &kCFTypeDictionaryKeyCallBacks, 505b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org &kCFTypeDictionaryValueCallBacks)); 506b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 507b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org AutoCFRelease<CFMutableDictionaryRef> cfTraits( 508b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org CFDictionaryCreateMutable(kCFAllocatorDefault, 0, 509b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org &kCFTypeDictionaryKeyCallBacks, 510b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org &kCFTypeDictionaryValueCallBacks)); 511b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 512b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org // Create the font 513b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org if (cfFontName != NULL && cfFontTraits != NULL && cfAttributes != NULL && cfTraits != NULL) { 514b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org CFDictionaryAddValue(cfTraits, kCTFontSymbolicTrait, cfFontTraits); 515b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 516b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org CFDictionaryAddValue(cfAttributes, kCTFontFamilyNameAttribute, cfFontName); 517b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org CFDictionaryAddValue(cfAttributes, kCTFontTraitsAttribute, cfTraits); 518b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 519b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org AutoCFRelease<CTFontDescriptorRef> ctFontDesc( 520b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org CTFontDescriptorCreateWithAttributes(cfAttributes)); 521b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 522b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org if (ctFontDesc != NULL) { 523cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com ctFont = CTFontCreateWithFontDescriptor(ctFontDesc, 0, NULL); 524b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org } 525b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org } 526b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 52726337e970201cae39f44b49546b8d9b0bc5e5c98caseq return ctFont ? NewFromFontRef(ctFont, familyName, false) : NULL; 528b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org} 529b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 530d6aeb6dc8fe21066f1a2c4813a4256a3acd3edf5bungemanSK_DECLARE_STATIC_MUTEX(gGetDefaultFaceMutex); 531b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.orgstatic SkTypeface* GetDefaultFace() { 532d6aeb6dc8fe21066f1a2c4813a4256a3acd3edf5bungeman SkAutoMutexAcquire ma(gGetDefaultFaceMutex); 533b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 534b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org static SkTypeface* gDefaultFace; 535b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 536b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org if (NULL == gDefaultFace) { 537b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org gDefaultFace = NewFromName(FONT_DEFAULT_NAME, SkTypeface::kNormal); 538b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org SkTypefaceCache::Add(gDefaultFace, SkTypeface::kNormal); 539b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org } 540b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org return gDefaultFace; 541b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org} 542b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 543b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org/////////////////////////////////////////////////////////////////////////////// 544b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 545b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.orgextern CTFontRef SkTypeface_GetCTFontRef(const SkTypeface* face); 546b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.orgCTFontRef SkTypeface_GetCTFontRef(const SkTypeface* face) { 547b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org const SkTypeface_Mac* macface = (const SkTypeface_Mac*)face; 548b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org return macface ? macface->fFontRef.get() : NULL; 549b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org} 550b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 551b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org/* This function is visible on the outside. It first searches the cache, and if 552b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org * not found, returns a new entry (after adding it to the cache). 553b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org */ 554b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.orgSkTypeface* SkCreateTypefaceFromCTFont(CTFontRef fontRef) { 555b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org SkFontID fontID = CTFontRef_to_SkFontID(fontRef); 556b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org SkTypeface* face = SkTypefaceCache::FindByID(fontID); 557b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org if (face) { 558b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org face->ref(); 559b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org } else { 56026337e970201cae39f44b49546b8d9b0bc5e5c98caseq face = NewFromFontRef(fontRef, NULL, false); 561b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org SkTypefaceCache::Add(face, face->style()); 562b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org // NewFromFontRef doesn't retain the parameter, but the typeface it 563b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org // creates does release it in its destructor, so we balance that with 564b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org // a retain call here. 565b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org CFRetain(fontRef); 566b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org } 567b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org SkASSERT(face->getRefCnt() > 1); 568b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org return face; 569b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org} 570b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 571b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.orgstruct NameStyleRec { 572b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org const char* fName; 573b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org SkTypeface::Style fStyle; 574b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org}; 575b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 576b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.orgstatic bool FindByNameStyle(SkTypeface* face, SkTypeface::Style style, 577b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org void* ctx) { 578b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org const SkTypeface_Mac* mface = reinterpret_cast<SkTypeface_Mac*>(face); 579b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org const NameStyleRec* rec = reinterpret_cast<const NameStyleRec*>(ctx); 580b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 581b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org return rec->fStyle == style && mface->fName.equals(rec->fName); 582b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org} 583b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 584b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.orgstatic const char* map_css_names(const char* name) { 585b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org static const struct { 586b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org const char* fFrom; // name the caller specified 587b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org const char* fTo; // "canonical" name we map to 588b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org } gPairs[] = { 589b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org { "sans-serif", "Helvetica" }, 590b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org { "serif", "Times" }, 591b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org { "monospace", "Courier" } 592b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org }; 593b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 594b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org for (size_t i = 0; i < SK_ARRAY_COUNT(gPairs); i++) { 595b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org if (strcmp(name, gPairs[i].fFrom) == 0) { 596b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org return gPairs[i].fTo; 597b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org } 598b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org } 599b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org return name; // no change 600b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org} 601b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 6027fdcd444a1bd6a2f173c141e09e7ad9c11730ad2reed@google.comstatic SkTypeface* create_typeface(const SkTypeface* familyFace, 6037fdcd444a1bd6a2f173c141e09e7ad9c11730ad2reed@google.com const char familyName[], 6047fdcd444a1bd6a2f173c141e09e7ad9c11730ad2reed@google.com SkTypeface::Style style) { 605b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org if (familyName) { 606b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org familyName = map_css_names(familyName); 607b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org } 60876015b09536c664bd59b370be7691d4b69553d95skia.committer@gmail.com 609b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org // Clone an existing typeface 610b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org // TODO: only clone if style matches the familyFace's style... 611b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org if (familyName == NULL && familyFace != NULL) { 612b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org familyFace->ref(); 613b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org return const_cast<SkTypeface*>(familyFace); 614b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org } 61576015b09536c664bd59b370be7691d4b69553d95skia.committer@gmail.com 616b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org if (!familyName || !*familyName) { 617b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org familyName = FONT_DEFAULT_NAME; 618b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org } 61976015b09536c664bd59b370be7691d4b69553d95skia.committer@gmail.com 620b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org NameStyleRec rec = { familyName, style }; 621b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org SkTypeface* face = SkTypefaceCache::FindByProcAndRef(FindByNameStyle, &rec); 62276015b09536c664bd59b370be7691d4b69553d95skia.committer@gmail.com 623b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org if (NULL == face) { 624b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org face = NewFromName(familyName, style); 625b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org if (face) { 626b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org SkTypefaceCache::Add(face, style); 627b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org } else { 628b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org face = GetDefaultFace(); 629b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org face->ref(); 630b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org } 631b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org } 632b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org return face; 633b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org} 634b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 635b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org/////////////////////////////////////////////////////////////////////////////// 636b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 637cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com/** GlyphRect is in FUnits (em space, y up). */ 638b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.orgstruct GlyphRect { 639b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org int16_t fMinX; 640b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org int16_t fMinY; 641b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org int16_t fMaxX; 642b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org int16_t fMaxY; 643b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org}; 644b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 645b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.orgclass SkScalerContext_Mac : public SkScalerContext { 646b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.orgpublic: 6470da48618a758ef46c2174bdc1eaeb6dd8a693a2ereed@google.com SkScalerContext_Mac(SkTypeface_Mac*, const SkDescriptor*); 648b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 649b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.orgprotected: 650b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org unsigned generateGlyphCount(void) SK_OVERRIDE; 651b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org uint16_t generateCharToGlyph(SkUnichar uni) SK_OVERRIDE; 652b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org void generateAdvance(SkGlyph* glyph) SK_OVERRIDE; 653b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org void generateMetrics(SkGlyph* glyph) SK_OVERRIDE; 654b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org void generateImage(const SkGlyph& glyph) SK_OVERRIDE; 655b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org void generatePath(const SkGlyph& glyph, SkPath* path) SK_OVERRIDE; 656410780677af260e32948b02c0725ef6ad761260cbungeman void generateFontMetrics(SkPaint::FontMetrics*) SK_OVERRIDE; 657b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 658b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.orgprivate: 659b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org static void CTPathElement(void *info, const CGPathElement *element); 660539f364e80a1e8ee35845b93fd6547e855380cadskia.committer@gmail.com 661cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com /** Returns the offset from the horizontal origin to the vertical origin in SkGlyph units. */ 662cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com void getVerticalOffset(CGGlyph glyphID, SkPoint* offset) const; 663cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com 664cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com /** Initializes and returns the value of fFBoundingBoxesGlyphOffset. 665cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com * 666cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com * For use with (and must be called before) generateBBoxes. 667cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com */ 668cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com uint16_t getFBoundingBoxesGlyphOffset(); 669539f364e80a1e8ee35845b93fd6547e855380cadskia.committer@gmail.com 670cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com /** Initializes fFBoundingBoxes and returns true on success. 671cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com * 672cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com * On Lion and Mountain Lion, CTFontGetBoundingRectsForGlyphs has a bug which causes it to 673cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com * return a bad value in bounds.origin.x for SFNT fonts whose hhea::numberOfHMetrics is 674cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com * less than its maxp::numGlyphs. When this is the case we try to read the bounds from the 675cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com * font directly. 676cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com * 677cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com * This routine initializes fFBoundingBoxes to an array of 678cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com * fGlyphCount - fFBoundingBoxesGlyphOffset GlyphRects which contain the bounds in FUnits 679cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com * (em space, y up) of glyphs with ids in the range [fFBoundingBoxesGlyphOffset, fGlyphCount). 680cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com * 681cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com * Returns true if fFBoundingBoxes is properly initialized. The table can only be properly 682cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com * initialized for a TrueType font with 'head', 'loca', and 'glyf' tables. 683cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com * 684cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com * TODO: A future optimization will compute fFBoundingBoxes once per fCTFont. 685cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com */ 686b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org bool generateBBoxes(); 687b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 688cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com /** Converts from FUnits (em space, y up) to SkGlyph units (pixels, y down). 689cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com * 690cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com * Used on Snow Leopard to correct CTFontGetVerticalTranslationsForGlyphs. 691cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com * Used on Lion to correct CTFontGetBoundingRectsForGlyphs. 692cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com */ 693cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com SkMatrix fFUnitMatrix; 694539f364e80a1e8ee35845b93fd6547e855380cadskia.committer@gmail.com 695b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org Offscreen fOffscreen; 696b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org AutoCFRelease<CTFontRef> fCTFont; 697539f364e80a1e8ee35845b93fd6547e855380cadskia.committer@gmail.com 698cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com /** Vertical variant of fCTFont. 699cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com * 700cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com * CT vertical metrics are pre-rotated (in em space, before transform) 90deg clock-wise. 701cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com * This makes kCTFontDefaultOrientation dangerous, because the metrics from 702cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com * kCTFontHorizontalOrientation are in a different space from kCTFontVerticalOrientation. 703cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com * Use fCTVerticalFont with kCTFontVerticalOrientation to get metrics in the same space. 704cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com */ 705cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com AutoCFRelease<CTFontRef> fCTVerticalFont; 706539f364e80a1e8ee35845b93fd6547e855380cadskia.committer@gmail.com 707b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org AutoCFRelease<CGFontRef> fCGFont; 708cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com SkAutoTMalloc<GlyphRect> fFBoundingBoxes; 709b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org uint16_t fFBoundingBoxesGlyphOffset; 710b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org uint16_t fGlyphCount; 711b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org bool fGeneratedFBoundingBoxes; 712cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com const bool fDoSubPosition; 713cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com const bool fVertical; 714cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com 715b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org friend class Offscreen; 7160da48618a758ef46c2174bdc1eaeb6dd8a693a2ereed@google.com 7170da48618a758ef46c2174bdc1eaeb6dd8a693a2ereed@google.com typedef SkScalerContext INHERITED; 718b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org}; 719b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 7200da48618a758ef46c2174bdc1eaeb6dd8a693a2ereed@google.comSkScalerContext_Mac::SkScalerContext_Mac(SkTypeface_Mac* typeface, 7210da48618a758ef46c2174bdc1eaeb6dd8a693a2ereed@google.com const SkDescriptor* desc) 7220da48618a758ef46c2174bdc1eaeb6dd8a693a2ereed@google.com : INHERITED(typeface, desc) 723cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com , fFBoundingBoxes() 724b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org , fFBoundingBoxesGlyphOffset(0) 725b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org , fGeneratedFBoundingBoxes(false) 726cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com , fDoSubPosition(SkToBool(fRec.fFlags & kSubpixelPositioning_Flag)) 727cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com , fVertical(SkToBool(fRec.fFlags & kVertical_Flag)) 728cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com 729b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org{ 7302689f615e364dc48ad73826564f5b13d2329179dreed@google.com CTFontRef ctFont = typeface->fFontRef.get(); 731b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org CFIndex numGlyphs = CTFontGetGlyphCount(ctFont); 732cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com SkASSERT(numGlyphs >= 1 && numGlyphs <= 0xFFFF); 733cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com fGlyphCount = SkToU16(numGlyphs); 734539f364e80a1e8ee35845b93fd6547e855380cadskia.committer@gmail.com 735cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com fRec.getSingleMatrix(&fFUnitMatrix); 736cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com CGAffineTransform transform = MatrixToCGAffineTransform(fFUnitMatrix); 737cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com 738b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org AutoCFRelease<CTFontDescriptorRef> ctFontDesc; 739b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org if (fVertical) { 740b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org AutoCFRelease<CFMutableDictionaryRef> cfAttributes(CFDictionaryCreateMutable( 741b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org kCFAllocatorDefault, 0, 742b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org &kCFTypeDictionaryKeyCallBacks, 743b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org &kCFTypeDictionaryValueCallBacks)); 744b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org if (cfAttributes) { 745b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org CTFontOrientation ctOrientation = kCTFontVerticalOrientation; 746b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org AutoCFRelease<CFNumberRef> cfVertical(CFNumberCreate( 747b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org kCFAllocatorDefault, kCFNumberSInt32Type, &ctOrientation)); 748b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org CFDictionaryAddValue(cfAttributes, kCTFontOrientationAttribute, cfVertical); 749e194c495e95cbe92dfb9ed04515904a417fe7e9bbungeman ctFontDesc.reset(CTFontDescriptorCreateWithAttributes(cfAttributes)); 750b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org } 751b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org } 752cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com // Since our matrix includes everything, we pass 1 for size. 753e194c495e95cbe92dfb9ed04515904a417fe7e9bbungeman fCTFont.reset(CTFontCreateCopyWithAttributes(ctFont, 1, &transform, ctFontDesc)); 754e194c495e95cbe92dfb9ed04515904a417fe7e9bbungeman fCGFont.reset(CTFontCopyGraphicsFont(fCTFont, NULL)); 755b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org if (fVertical) { 756b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org CGAffineTransform rotateLeft = CGAffineTransformMake(0, -1, 1, 0, 0, 0); 757b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org transform = CGAffineTransformConcat(rotateLeft, transform); 758e194c495e95cbe92dfb9ed04515904a417fe7e9bbungeman fCTVerticalFont.reset(CTFontCreateCopyWithAttributes(ctFont, 1, &transform, NULL)); 759b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org } 760371add80f51205d53391840164f37ade6aff8012commit-bot@chromium.org 761cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com SkScalar emPerFUnit = SkScalarInvert(SkIntToScalar(CGFontGetUnitsPerEm(fCGFont))); 762cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com fFUnitMatrix.preScale(emPerFUnit, -emPerFUnit); 763b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org} 764b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 765b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.orgCGRGBPixel* Offscreen::getCG(const SkScalerContext_Mac& context, const SkGlyph& glyph, 766b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org CGGlyph glyphID, size_t* rowBytesPtr, 767b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org bool generateA8FromLCD) { 768b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org if (!fRGBSpace) { 769b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org //It doesn't appear to matter what color space is specified. 770b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org //Regular blends and antialiased text are always (s*a + d*(1-a)) 771b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org //and smoothed text is always g=2.0. 772e194c495e95cbe92dfb9ed04515904a417fe7e9bbungeman fRGBSpace.reset(CGColorSpaceCreateDeviceRGB()); 773b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org } 774b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 775b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org // default to kBW_Format 776b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org bool doAA = false; 777b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org bool doLCD = false; 778b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 779b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org if (SkMask::kBW_Format != glyph.fMaskFormat) { 780b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org doLCD = true; 781b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org doAA = true; 782b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org } 783b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 784b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org // FIXME: lcd smoothed un-hinted rasterization unsupported. 785b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org if (!generateA8FromLCD && SkMask::kA8_Format == glyph.fMaskFormat) { 786b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org doLCD = false; 787b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org doAA = true; 788b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org } 789b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 790b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org size_t rowBytes = fSize.fWidth * sizeof(CGRGBPixel); 791b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org if (!fCG || fSize.fWidth < glyph.fWidth || fSize.fHeight < glyph.fHeight) { 792b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org if (fSize.fWidth < glyph.fWidth) { 793b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org fSize.fWidth = RoundSize(glyph.fWidth); 794b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org } 795b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org if (fSize.fHeight < glyph.fHeight) { 796b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org fSize.fHeight = RoundSize(glyph.fHeight); 797b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org } 798b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 799b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org rowBytes = fSize.fWidth * sizeof(CGRGBPixel); 800b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org void* image = fImageStorage.reset(rowBytes * fSize.fHeight); 801e194c495e95cbe92dfb9ed04515904a417fe7e9bbungeman fCG.reset(CGBitmapContextCreate(image, fSize.fWidth, fSize.fHeight, 8, 802e194c495e95cbe92dfb9ed04515904a417fe7e9bbungeman rowBytes, fRGBSpace, BITMAP_INFO_RGB)); 803b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 804b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org // skia handles quantization itself, so we disable this for cg to get 805b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org // full fractional data from them. 806b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org CGContextSetAllowsFontSubpixelQuantization(fCG, false); 807b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org CGContextSetShouldSubpixelQuantizeFonts(fCG, false); 808b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 809b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org CGContextSetTextDrawingMode(fCG, kCGTextFill); 810b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org CGContextSetFont(fCG, context.fCGFont); 811cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com CGContextSetFontSize(fCG, 1 /*CTFontGetSize(context.fCTFont)*/); 812cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com CGContextSetTextMatrix(fCG, CTFontGetMatrix(context.fCTFont)); 813b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 814cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com // Because CG always draws from the horizontal baseline, 815cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com // if there is a non-integral translation from the horizontal origin to the vertical origin, 816cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com // then CG cannot draw the glyph in the correct location without subpixel positioning. 817cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com CGContextSetAllowsFontSubpixelPositioning(fCG, context.fDoSubPosition || context.fVertical); 818cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com CGContextSetShouldSubpixelPositionFonts(fCG, context.fDoSubPosition || context.fVertical); 819b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 820b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org // Draw white on black to create mask. 821b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org // TODO: Draw black on white and invert, CG has a special case codepath. 822b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org CGContextSetGrayFillColor(fCG, 1.0f, 1.0f); 823b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 824b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org // force our checks below to happen 825b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org fDoAA = !doAA; 826b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org fDoLCD = !doLCD; 827b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org } 828b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 829b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org if (fDoAA != doAA) { 830b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org CGContextSetShouldAntialias(fCG, doAA); 831b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org fDoAA = doAA; 832b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org } 833b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org if (fDoLCD != doLCD) { 834b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org CGContextSetShouldSmoothFonts(fCG, doLCD); 835b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org fDoLCD = doLCD; 836b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org } 837b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 838b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org CGRGBPixel* image = (CGRGBPixel*)fImageStorage.get(); 839b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org // skip rows based on the glyph's height 840b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org image += (fSize.fHeight - glyph.fHeight) * fSize.fWidth; 841b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 842b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org // erase to black 843b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org sk_memset_rect32(image, 0, glyph.fWidth, glyph.fHeight, rowBytes); 844b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 845b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org float subX = 0; 846b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org float subY = 0; 847b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org if (context.fDoSubPosition) { 848b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org subX = SkFixedToFloat(glyph.getSubXFixed()); 849b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org subY = SkFixedToFloat(glyph.getSubYFixed()); 850b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org } 851539f364e80a1e8ee35845b93fd6547e855380cadskia.committer@gmail.com 852cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com // CGContextShowGlyphsAtPoint always draws using the horizontal baseline origin. 853b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org if (context.fVertical) { 854cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com SkPoint offset; 855b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org context.getVerticalOffset(glyphID, &offset); 856b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org subX += offset.fX; 857b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org subY += offset.fY; 858b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org } 859539f364e80a1e8ee35845b93fd6547e855380cadskia.committer@gmail.com 860b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org CGContextShowGlyphsAtPoint(fCG, -glyph.fLeft + subX, 861b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org glyph.fTop + glyph.fHeight - subY, 862b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org &glyphID, 1); 863b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 864b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org SkASSERT(rowBytesPtr); 865b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org *rowBytesPtr = rowBytes; 866b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org return image; 867b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org} 868b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 869cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.comvoid SkScalerContext_Mac::getVerticalOffset(CGGlyph glyphID, SkPoint* offset) const { 870cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com // Snow Leopard returns cgVertOffset in completely un-transformed FUnits (em space, y up). 871cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com // Lion and Leopard return cgVertOffset in CG units (pixels, y up). 872cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com CGSize cgVertOffset; 873cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com CTFontGetVerticalTranslationsForGlyphs(fCTFont, &glyphID, &cgVertOffset, 1); 874cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com 875cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com SkPoint skVertOffset = { CGToScalar(cgVertOffset.width), CGToScalar(cgVertOffset.height) }; 876cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com if (isSnowLeopard()) { 877cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com // From FUnits (em space, y up) to SkGlyph units (pixels, y down). 878cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com fFUnitMatrix.mapPoints(&skVertOffset, 1); 879cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com } else { 880cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com // From CG units (pixels, y up) to SkGlyph units (pixels, y down). 881cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com skVertOffset.fY = -skVertOffset.fY; 882cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com } 883539f364e80a1e8ee35845b93fd6547e855380cadskia.committer@gmail.com 884cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com *offset = skVertOffset; 885cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com} 886b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 887b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.orguint16_t SkScalerContext_Mac::getFBoundingBoxesGlyphOffset() { 888b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org if (fFBoundingBoxesGlyphOffset) { 889b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org return fFBoundingBoxesGlyphOffset; 890b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org } 891b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org fFBoundingBoxesGlyphOffset = fGlyphCount; // fallback for all fonts 892b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org AutoCGTable<SkOTTableHorizontalHeader> hheaTable(fCGFont); 893b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org if (hheaTable.fData) { 894b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org fFBoundingBoxesGlyphOffset = SkEndian_SwapBE16(hheaTable->numberOfHMetrics); 895b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org } 896b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org return fFBoundingBoxesGlyphOffset; 897b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org} 898b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 899b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.orgbool SkScalerContext_Mac::generateBBoxes() { 900b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org if (fGeneratedFBoundingBoxes) { 90149f085dddff10473b6ebf832a974288300224e60bsalomon return SkToBool(fFBoundingBoxes.get()); 902b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org } 903b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org fGeneratedFBoundingBoxes = true; 904b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 905b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org AutoCGTable<SkOTTableHead> headTable(fCGFont); 906b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org if (!headTable.fData) { 907b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org return false; 908b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org } 909b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 910b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org AutoCGTable<SkOTTableIndexToLocation> locaTable(fCGFont); 911b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org if (!locaTable.fData) { 912b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org return false; 913b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org } 914b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 915b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org AutoCGTable<SkOTTableGlyph> glyfTable(fCGFont); 916b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org if (!glyfTable.fData) { 917b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org return false; 918b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org } 919b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 920b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org uint16_t entries = fGlyphCount - fFBoundingBoxesGlyphOffset; 921cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com fFBoundingBoxes.reset(entries); 922b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 923b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org SkOTTableHead::IndexToLocFormat locaFormat = headTable->indexToLocFormat; 924b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org SkOTTableGlyph::Iterator glyphDataIter(*glyfTable.fData, *locaTable.fData, locaFormat); 925b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org glyphDataIter.advance(fFBoundingBoxesGlyphOffset); 926b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org for (uint16_t boundingBoxesIndex = 0; boundingBoxesIndex < entries; ++boundingBoxesIndex) { 927b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org const SkOTTableGlyphData* glyphData = glyphDataIter.next(); 928b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org GlyphRect& rect = fFBoundingBoxes[boundingBoxesIndex]; 929b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org rect.fMinX = SkEndian_SwapBE16(glyphData->xMin); 930b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org rect.fMinY = SkEndian_SwapBE16(glyphData->yMin); 931b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org rect.fMaxX = SkEndian_SwapBE16(glyphData->xMax); 932b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org rect.fMaxY = SkEndian_SwapBE16(glyphData->yMax); 933b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org } 934371add80f51205d53391840164f37ade6aff8012commit-bot@chromium.org 935b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org return true; 936b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org} 937b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 938b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.orgunsigned SkScalerContext_Mac::generateGlyphCount(void) { 939b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org return fGlyphCount; 940b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org} 941b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 942b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.orguint16_t SkScalerContext_Mac::generateCharToGlyph(SkUnichar uni) { 943fb1663a0a57656328277d02bef088d3afb695a7cbungeman@google.com CGGlyph cgGlyph[2]; 94472b8cb2320dddc6e006a2857746014e607e9e151bungeman@google.com UniChar theChar[2]; // UniChar is a UTF-16 16-bit code unit. 945b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 946b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org // Get the glyph 947fb1663a0a57656328277d02bef088d3afb695a7cbungeman@google.com size_t numUniChar = SkUTF16_FromUnichar(uni, theChar); 948fb1663a0a57656328277d02bef088d3afb695a7cbungeman@google.com SkASSERT(sizeof(CGGlyph) <= sizeof(uint16_t)); 949b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 95072b8cb2320dddc6e006a2857746014e607e9e151bungeman@google.com // Undocumented behavior of CTFontGetGlyphsForCharacters with non-bmp code points: 95172b8cb2320dddc6e006a2857746014e607e9e151bungeman@google.com // When a surrogate pair is detected, the glyph index used is the index of the high surrogate. 95272b8cb2320dddc6e006a2857746014e607e9e151bungeman@google.com // It is documented that if a mapping is unavailable, the glyph will be set to 0. 95372b8cb2320dddc6e006a2857746014e607e9e151bungeman@google.com CTFontGetGlyphsForCharacters(fCTFont, theChar, cgGlyph, numUniChar); 954fb1663a0a57656328277d02bef088d3afb695a7cbungeman@google.com return cgGlyph[0]; 955b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org} 956b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 957b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.orgvoid SkScalerContext_Mac::generateAdvance(SkGlyph* glyph) { 958b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org this->generateMetrics(glyph); 959b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org} 960b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 961cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.comvoid SkScalerContext_Mac::generateMetrics(SkGlyph* glyph) { 9621b27704eba15be4e9d1997faac42038493a30be5djsollen const CGGlyph cgGlyph = (CGGlyph) glyph->getGlyphID(); 963cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com glyph->zeroMetrics(); 964539f364e80a1e8ee35845b93fd6547e855380cadskia.committer@gmail.com 965cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com // The following block produces cgAdvance in CG units (pixels, y up). 966cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com CGSize cgAdvance; 967cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com if (fVertical) { 968cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com CTFontGetAdvancesForGlyphs(fCTVerticalFont, kCTFontVerticalOrientation, 969cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com &cgGlyph, &cgAdvance, 1); 970cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com } else { 971cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com CTFontGetAdvancesForGlyphs(fCTFont, kCTFontHorizontalOrientation, 972cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com &cgGlyph, &cgAdvance, 1); 973cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com } 974cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com glyph->fAdvanceX = SkFloatToFixed_Check(cgAdvance.width); 975cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com glyph->fAdvanceY = -SkFloatToFixed_Check(cgAdvance.height); 976cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com 977cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com // The following produces skBounds in SkGlyph units (pixels, y down), 978cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com // or returns early if skBounds would be empty. 979cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com SkRect skBounds; 980539f364e80a1e8ee35845b93fd6547e855380cadskia.committer@gmail.com 981cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com // On Mountain Lion, CTFontGetBoundingRectsForGlyphs with kCTFontVerticalOrientation and 982cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com // CTFontGetVerticalTranslationsForGlyphs do not agree when using OTF CFF fonts. 983cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com // For TTF fonts these two do agree and we can use CTFontGetBoundingRectsForGlyphs to get 984cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com // the bounding box and CTFontGetVerticalTranslationsForGlyphs to then draw the glyph 985cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com // inside that bounding box. However, with OTF CFF fonts this does not work. It appears that 986cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com // CTFontGetBoundingRectsForGlyphs with kCTFontVerticalOrientation on OTF CFF fonts tries 987cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com // to center the glyph along the vertical baseline and also perform some mysterious shift 988cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com // along the baseline. CTFontGetVerticalTranslationsForGlyphs does not appear to perform 989cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com // these steps. 990cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com // 991cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com // It is not known which is correct (or if either is correct). However, we must always draw 992cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com // from the horizontal origin and must use CTFontGetVerticalTranslationsForGlyphs to draw. 993cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com // As a result, we do not call CTFontGetBoundingRectsForGlyphs for vertical glyphs. 994539f364e80a1e8ee35845b93fd6547e855380cadskia.committer@gmail.com 995cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com // On Snow Leopard, CTFontGetBoundingRectsForGlyphs ignores kCTFontVerticalOrientation and 996cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com // returns horizontal bounds. 997539f364e80a1e8ee35845b93fd6547e855380cadskia.committer@gmail.com 998cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com // On Lion and Mountain Lion, CTFontGetBoundingRectsForGlyphs has a bug which causes it to 999cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com // return a bad value in cgBounds.origin.x for SFNT fonts whose hhea::numberOfHMetrics is 1000cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com // less than its maxp::numGlyphs. When this is the case we try to read the bounds from the 1001cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com // font directly. 1002cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com if ((isLion() || isMountainLion()) && 1003cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com (cgGlyph < fGlyphCount && cgGlyph >= getFBoundingBoxesGlyphOffset() && generateBBoxes())) 1004cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com { 1005cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com const GlyphRect& gRect = fFBoundingBoxes[cgGlyph - fFBoundingBoxesGlyphOffset]; 1006cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com if (gRect.fMinX >= gRect.fMaxX || gRect.fMinY >= gRect.fMaxY) { 1007cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com return; 1008cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com } 1009cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com skBounds = SkRect::MakeLTRB(gRect.fMinX, gRect.fMinY, gRect.fMaxX, gRect.fMaxY); 1010cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com // From FUnits (em space, y up) to SkGlyph units (pixels, y down). 1011cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com fFUnitMatrix.mapRect(&skBounds); 1012cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com 1013cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com } else { 1014cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com // CTFontGetBoundingRectsForGlyphs produces cgBounds in CG units (pixels, y up). 1015cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com CGRect cgBounds; 1016cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com CTFontGetBoundingRectsForGlyphs(fCTFont, kCTFontHorizontalOrientation, 1017cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com &cgGlyph, &cgBounds, 1); 1018539f364e80a1e8ee35845b93fd6547e855380cadskia.committer@gmail.com 1019cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com // BUG? 1020cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com // 0x200B (zero-advance space) seems to return a huge (garbage) bounds, when 1021cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com // it should be empty. So, if we see a zero-advance, we check if it has an 1022cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com // empty path or not, and if so, we jam the bounds to 0. Hopefully a zero-advance 1023cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com // is rare, so we won't incur a big performance cost for this extra check. 1024cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com if (0 == cgAdvance.width && 0 == cgAdvance.height) { 1025cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com AutoCFRelease<CGPathRef> path(CTFontCreatePathForGlyph(fCTFont, cgGlyph, NULL)); 1026cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com if (NULL == path || CGPathIsEmpty(path)) { 1027cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com return; 1028cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com } 1029cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com } 1030cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com 1031cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com if (CGRectIsEmpty_inline(cgBounds)) { 1032cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com return; 1033cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com } 1034cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com 1035cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com // Convert cgBounds to SkGlyph units (pixels, y down). 1036cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com skBounds = SkRect::MakeXYWH(cgBounds.origin.x, -cgBounds.origin.y - cgBounds.size.height, 1037cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com cgBounds.size.width, cgBounds.size.height); 1038cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com } 1039cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com 1040cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com if (fVertical) { 1041cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com // Due to all of the vertical bounds bugs, skBounds is always the horizontal bounds. 1042cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com // Convert these horizontal bounds into vertical bounds. 1043cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com SkPoint offset; 1044cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com getVerticalOffset(cgGlyph, &offset); 1045cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com skBounds.offset(offset); 1046cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com } 1047539f364e80a1e8ee35845b93fd6547e855380cadskia.committer@gmail.com 1048cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com // Currently the bounds are based on being rendered at (0,0). 1049cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com // The top left must not move, since that is the base from which subpixel positioning is offset. 1050cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com if (fDoSubPosition) { 1051cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com skBounds.fRight += SkFixedToFloat(glyph->getSubXFixed()); 1052cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com skBounds.fBottom += SkFixedToFloat(glyph->getSubYFixed()); 1053cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com } 1054539f364e80a1e8ee35845b93fd6547e855380cadskia.committer@gmail.com 1055cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com SkIRect skIBounds; 1056cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com skBounds.roundOut(&skIBounds); 1057cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com // Expand the bounds by 1 pixel, to give CG room for anti-aliasing. 1058cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com // Note that this outset is to allow room for LCD smoothed glyphs. However, the correct outset 1059cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com // is not currently known, as CG dilates the outlines by some percentage. 1060cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com // Note that if this context is A8 and not back-forming from LCD, there is no need to outset. 1061cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com skIBounds.outset(1, 1); 1062cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com glyph->fLeft = SkToS16(skIBounds.fLeft); 1063cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com glyph->fTop = SkToS16(skIBounds.fTop); 1064cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com glyph->fWidth = SkToU16(skIBounds.width()); 1065cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com glyph->fHeight = SkToU16(skIBounds.height()); 1066539f364e80a1e8ee35845b93fd6547e855380cadskia.committer@gmail.com 1067cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com#ifdef HACK_COLORGLYPHS 1068cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com glyph->fMaskFormat = SkMask::kARGB32_Format; 1069cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com#endif 1070cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com} 1071b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 1072b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org#include "SkColorPriv.h" 1073b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 1074b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.orgstatic void build_power_table(uint8_t table[], float ee) { 1075b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org for (int i = 0; i < 256; i++) { 1076b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org float x = i / 255.f; 1077b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org x = sk_float_pow(x, ee); 10784b413c8bb123e42ca4b9c7bfa6bc2167283cb84ccommit-bot@chromium.org int xx = SkScalarRoundToInt(x * 255); 1079b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org table[i] = SkToU8(xx); 1080b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org } 1081b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org} 1082b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 1083b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org/** 1084b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org * This will invert the gamma applied by CoreGraphics, so we can get linear 1085b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org * values. 1086b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org * 1087b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org * CoreGraphics obscurely defaults to 2.0 as the smoothing gamma value. 1088b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org * The color space used does not appear to affect this choice. 1089b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org */ 1090b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.orgstatic const uint8_t* getInverseGammaTableCoreGraphicSmoothing() { 1091b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org static bool gInited; 1092b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org static uint8_t gTableCoreGraphicsSmoothing[256]; 1093b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org if (!gInited) { 1094b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org build_power_table(gTableCoreGraphicsSmoothing, 2.0f); 1095b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org gInited = true; 1096b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org } 1097b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org return gTableCoreGraphicsSmoothing; 1098b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org} 1099b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 1100b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.orgstatic void cgpixels_to_bits(uint8_t dst[], const CGRGBPixel src[], int count) { 1101b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org while (count > 0) { 1102b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org uint8_t mask = 0; 1103b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org for (int i = 7; i >= 0; --i) { 1104b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org mask |= (CGRGBPixel_getAlpha(*src++) >> 7) << i; 1105b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org if (0 == --count) { 1106b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org break; 1107b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org } 1108b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org } 1109b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org *dst++ = mask; 1110b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org } 1111b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org} 1112b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 1113b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.orgtemplate<bool APPLY_PREBLEND> 1114b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.orgstatic inline uint8_t rgb_to_a8(CGRGBPixel rgb, const uint8_t* table8) { 1115b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org U8CPU r = (rgb >> 16) & 0xFF; 1116b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org U8CPU g = (rgb >> 8) & 0xFF; 1117b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org U8CPU b = (rgb >> 0) & 0xFF; 1118b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org return sk_apply_lut_if<APPLY_PREBLEND>(SkComputeLuminance(r, g, b), table8); 1119b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org} 1120b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.orgtemplate<bool APPLY_PREBLEND> 1121b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.orgstatic void rgb_to_a8(const CGRGBPixel* SK_RESTRICT cgPixels, size_t cgRowBytes, 1122b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org const SkGlyph& glyph, const uint8_t* table8) { 1123b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org const int width = glyph.fWidth; 1124b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org size_t dstRB = glyph.rowBytes(); 1125b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org uint8_t* SK_RESTRICT dst = (uint8_t*)glyph.fImage; 1126b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 1127b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org for (int y = 0; y < glyph.fHeight; y++) { 1128b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org for (int i = 0; i < width; ++i) { 1129b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org dst[i] = rgb_to_a8<APPLY_PREBLEND>(cgPixels[i], table8); 1130b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org } 1131b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org cgPixels = (CGRGBPixel*)((char*)cgPixels + cgRowBytes); 1132b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org dst += dstRB; 1133b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org } 1134b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org} 1135b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 1136b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.orgtemplate<bool APPLY_PREBLEND> 1137b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.orgstatic inline uint16_t rgb_to_lcd16(CGRGBPixel rgb, const uint8_t* tableR, 1138b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org const uint8_t* tableG, 1139b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org const uint8_t* tableB) { 1140b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org U8CPU r = sk_apply_lut_if<APPLY_PREBLEND>((rgb >> 16) & 0xFF, tableR); 1141b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org U8CPU g = sk_apply_lut_if<APPLY_PREBLEND>((rgb >> 8) & 0xFF, tableG); 1142b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org U8CPU b = sk_apply_lut_if<APPLY_PREBLEND>((rgb >> 0) & 0xFF, tableB); 1143b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org return SkPack888ToRGB16(r, g, b); 1144b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org} 1145b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.orgtemplate<bool APPLY_PREBLEND> 1146b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.orgstatic void rgb_to_lcd16(const CGRGBPixel* SK_RESTRICT cgPixels, size_t cgRowBytes, const SkGlyph& glyph, 1147b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org const uint8_t* tableR, const uint8_t* tableG, const uint8_t* tableB) { 1148b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org const int width = glyph.fWidth; 1149b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org size_t dstRB = glyph.rowBytes(); 1150b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org uint16_t* SK_RESTRICT dst = (uint16_t*)glyph.fImage; 1151b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 1152b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org for (int y = 0; y < glyph.fHeight; y++) { 1153b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org for (int i = 0; i < width; i++) { 1154b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org dst[i] = rgb_to_lcd16<APPLY_PREBLEND>(cgPixels[i], tableR, tableG, tableB); 1155b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org } 1156b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org cgPixels = (CGRGBPixel*)((char*)cgPixels + cgRowBytes); 1157b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org dst = (uint16_t*)((char*)dst + dstRB); 1158b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org } 1159b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org} 1160b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 1161b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.orgtemplate<bool APPLY_PREBLEND> 1162b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.orgstatic inline uint32_t rgb_to_lcd32(CGRGBPixel rgb, const uint8_t* tableR, 1163b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org const uint8_t* tableG, 1164b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org const uint8_t* tableB) { 1165b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org U8CPU r = sk_apply_lut_if<APPLY_PREBLEND>((rgb >> 16) & 0xFF, tableR); 1166b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org U8CPU g = sk_apply_lut_if<APPLY_PREBLEND>((rgb >> 8) & 0xFF, tableG); 1167b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org U8CPU b = sk_apply_lut_if<APPLY_PREBLEND>((rgb >> 0) & 0xFF, tableB); 1168b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org return SkPackARGB32(0xFF, r, g, b); 1169b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org} 1170b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.orgtemplate<bool APPLY_PREBLEND> 1171b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.orgstatic void rgb_to_lcd32(const CGRGBPixel* SK_RESTRICT cgPixels, size_t cgRowBytes, const SkGlyph& glyph, 1172b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org const uint8_t* tableR, const uint8_t* tableG, const uint8_t* tableB) { 1173b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org const int width = glyph.fWidth; 1174b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org size_t dstRB = glyph.rowBytes(); 1175b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org uint32_t* SK_RESTRICT dst = (uint32_t*)glyph.fImage; 1176b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org for (int y = 0; y < glyph.fHeight; y++) { 1177b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org for (int i = 0; i < width; i++) { 1178b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org dst[i] = rgb_to_lcd32<APPLY_PREBLEND>(cgPixels[i], tableR, tableG, tableB); 1179b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org } 1180b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org cgPixels = (CGRGBPixel*)((char*)cgPixels + cgRowBytes); 1181b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org dst = (uint32_t*)((char*)dst + dstRB); 1182b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org } 1183b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org} 1184b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 1185f77b35d86ad439917bda78334deb31fbcc16cdaereed@google.com#ifdef HACK_COLORGLYPHS 1186f77b35d86ad439917bda78334deb31fbcc16cdaereed@google.com// hack to colorize the output for testing kARGB32_Format 1187f77b35d86ad439917bda78334deb31fbcc16cdaereed@google.comstatic SkPMColor cgpixels_to_pmcolor(CGRGBPixel rgb, const SkGlyph& glyph, 1188f77b35d86ad439917bda78334deb31fbcc16cdaereed@google.com int x, int y) { 1189f77b35d86ad439917bda78334deb31fbcc16cdaereed@google.com U8CPU r = (rgb >> 16) & 0xFF; 1190f77b35d86ad439917bda78334deb31fbcc16cdaereed@google.com U8CPU g = (rgb >> 8) & 0xFF; 1191f77b35d86ad439917bda78334deb31fbcc16cdaereed@google.com U8CPU b = (rgb >> 0) & 0xFF; 1192f77b35d86ad439917bda78334deb31fbcc16cdaereed@google.com unsigned a = SkComputeLuminance(r, g, b); 11932fd42c471c77f54ace35c13975651e17d5b2e8c6skia.committer@gmail.com 1194f77b35d86ad439917bda78334deb31fbcc16cdaereed@google.com // compute gradient from x,y 1195f77b35d86ad439917bda78334deb31fbcc16cdaereed@google.com r = x * 255 / glyph.fWidth; 1196f77b35d86ad439917bda78334deb31fbcc16cdaereed@google.com g = 0; 1197f77b35d86ad439917bda78334deb31fbcc16cdaereed@google.com b = (glyph.fHeight - y) * 255 / glyph.fHeight; 1198f77b35d86ad439917bda78334deb31fbcc16cdaereed@google.com return SkPreMultiplyARGB(a, r, g, b); // red 1199f77b35d86ad439917bda78334deb31fbcc16cdaereed@google.com} 1200f77b35d86ad439917bda78334deb31fbcc16cdaereed@google.com#endif 1201f77b35d86ad439917bda78334deb31fbcc16cdaereed@google.com 1202b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.orgtemplate <typename T> T* SkTAddByteOffset(T* ptr, size_t byteOffset) { 1203b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org return (T*)((char*)ptr + byteOffset); 1204b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org} 1205b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 1206b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.orgvoid SkScalerContext_Mac::generateImage(const SkGlyph& glyph) { 12071b27704eba15be4e9d1997faac42038493a30be5djsollen CGGlyph cgGlyph = (CGGlyph) glyph.getGlyphID(); 1208b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 1209b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org // FIXME: lcd smoothed un-hinted rasterization unsupported. 1210b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org bool generateA8FromLCD = fRec.getHinting() != SkPaint::kNo_Hinting; 1211b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 1212b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org // Draw the glyph 1213b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org size_t cgRowBytes; 1214b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org CGRGBPixel* cgPixels = fOffscreen.getCG(*this, glyph, cgGlyph, &cgRowBytes, generateA8FromLCD); 1215b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org if (cgPixels == NULL) { 1216b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org return; 1217b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org } 1218b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 1219b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org //TODO: see if drawing black on white and inverting is faster (at least in 1220b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org //lcd case) as core graphics appears to have special case code for drawing 1221b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org //black text. 1222b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 1223b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org // Fix the glyph 1224b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org const bool isLCD = isLCDFormat(glyph.fMaskFormat); 1225b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org if (isLCD || (glyph.fMaskFormat == SkMask::kA8_Format && supports_LCD() && generateA8FromLCD)) { 1226b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org const uint8_t* table = getInverseGammaTableCoreGraphicSmoothing(); 1227b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 1228b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org //Note that the following cannot really be integrated into the 1229b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org //pre-blend, since we may not be applying the pre-blend; when we aren't 1230b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org //applying the pre-blend it means that a filter wants linear anyway. 1231b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org //Other code may also be applying the pre-blend, so we'd need another 1232b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org //one with this and one without. 1233b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org CGRGBPixel* addr = cgPixels; 1234b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org for (int y = 0; y < glyph.fHeight; ++y) { 1235b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org for (int x = 0; x < glyph.fWidth; ++x) { 1236b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org int r = (addr[x] >> 16) & 0xFF; 1237b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org int g = (addr[x] >> 8) & 0xFF; 1238b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org int b = (addr[x] >> 0) & 0xFF; 1239b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org addr[x] = (table[r] << 16) | (table[g] << 8) | table[b]; 1240b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org } 1241b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org addr = SkTAddByteOffset(addr, cgRowBytes); 1242b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org } 1243b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org } 1244b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 1245b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org // Convert glyph to mask 1246b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org switch (glyph.fMaskFormat) { 1247b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org case SkMask::kLCD32_Format: { 1248b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org if (fPreBlend.isApplicable()) { 1249b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org rgb_to_lcd32<true>(cgPixels, cgRowBytes, glyph, 1250b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org fPreBlend.fR, fPreBlend.fG, fPreBlend.fB); 1251b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org } else { 1252b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org rgb_to_lcd32<false>(cgPixels, cgRowBytes, glyph, 1253b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org fPreBlend.fR, fPreBlend.fG, fPreBlend.fB); 1254b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org } 1255b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org } break; 1256b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org case SkMask::kLCD16_Format: { 1257b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org if (fPreBlend.isApplicable()) { 1258b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org rgb_to_lcd16<true>(cgPixels, cgRowBytes, glyph, 1259b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org fPreBlend.fR, fPreBlend.fG, fPreBlend.fB); 1260b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org } else { 1261b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org rgb_to_lcd16<false>(cgPixels, cgRowBytes, glyph, 1262b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org fPreBlend.fR, fPreBlend.fG, fPreBlend.fB); 1263b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org } 1264b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org } break; 1265b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org case SkMask::kA8_Format: { 1266b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org if (fPreBlend.isApplicable()) { 1267b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org rgb_to_a8<true>(cgPixels, cgRowBytes, glyph, fPreBlend.fG); 1268b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org } else { 1269b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org rgb_to_a8<false>(cgPixels, cgRowBytes, glyph, fPreBlend.fG); 1270b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org } 1271b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org } break; 1272b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org case SkMask::kBW_Format: { 1273b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org const int width = glyph.fWidth; 1274b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org size_t dstRB = glyph.rowBytes(); 1275b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org uint8_t* dst = (uint8_t*)glyph.fImage; 1276b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org for (int y = 0; y < glyph.fHeight; y++) { 1277b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org cgpixels_to_bits(dst, cgPixels, width); 1278b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org cgPixels = (CGRGBPixel*)((char*)cgPixels + cgRowBytes); 1279b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org dst += dstRB; 1280b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org } 1281b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org } break; 1282f77b35d86ad439917bda78334deb31fbcc16cdaereed@google.com#ifdef HACK_COLORGLYPHS 1283f77b35d86ad439917bda78334deb31fbcc16cdaereed@google.com case SkMask::kARGB32_Format: { 1284f77b35d86ad439917bda78334deb31fbcc16cdaereed@google.com const int width = glyph.fWidth; 1285f77b35d86ad439917bda78334deb31fbcc16cdaereed@google.com size_t dstRB = glyph.rowBytes(); 1286f77b35d86ad439917bda78334deb31fbcc16cdaereed@google.com SkPMColor* dst = (SkPMColor*)glyph.fImage; 1287f77b35d86ad439917bda78334deb31fbcc16cdaereed@google.com for (int y = 0; y < glyph.fHeight; y++) { 1288f77b35d86ad439917bda78334deb31fbcc16cdaereed@google.com for (int x = 0; x < width; ++x) { 1289f77b35d86ad439917bda78334deb31fbcc16cdaereed@google.com dst[x] = cgpixels_to_pmcolor(cgPixels[x], glyph, x, y); 1290f77b35d86ad439917bda78334deb31fbcc16cdaereed@google.com } 1291f77b35d86ad439917bda78334deb31fbcc16cdaereed@google.com cgPixels = (CGRGBPixel*)((char*)cgPixels + cgRowBytes); 1292f77b35d86ad439917bda78334deb31fbcc16cdaereed@google.com dst = (SkPMColor*)((char*)dst + dstRB); 1293f77b35d86ad439917bda78334deb31fbcc16cdaereed@google.com } 1294f77b35d86ad439917bda78334deb31fbcc16cdaereed@google.com } break; 1295f77b35d86ad439917bda78334deb31fbcc16cdaereed@google.com#endif 1296b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org default: 1297b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org SkDEBUGFAIL("unexpected mask format"); 1298b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org break; 1299b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org } 1300b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org} 1301b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 1302b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org/* 1303b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org * Our subpixel resolution is only 2 bits in each direction, so a scale of 4 1304b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org * seems sufficient, and possibly even correct, to allow the hinted outline 1305b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org * to be subpixel positioned. 1306b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org */ 1307b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org#define kScaleForSubPixelPositionHinting (4.0f) 1308b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 1309b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.orgvoid SkScalerContext_Mac::generatePath(const SkGlyph& glyph, SkPath* path) { 1310b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org CTFontRef font = fCTFont; 1311b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org SkScalar scaleX = SK_Scalar1; 1312b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org SkScalar scaleY = SK_Scalar1; 1313b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 1314b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org /* 1315b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org * For subpixel positioning, we want to return an unhinted outline, so it 1316b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org * can be positioned nicely at fractional offsets. However, we special-case 1317b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org * if the baseline of the (horizontal) text is axis-aligned. In those cases 1318b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org * we want to retain hinting in the direction orthogonal to the baseline. 1319b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org * e.g. for horizontal baseline, we want to retain hinting in Y. 1320b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org * The way we remove hinting is to scale the font by some value (4) in that 1321b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org * direction, ask for the path, and then scale the path back down. 1322b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org */ 1323b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org if (fRec.fFlags & SkScalerContext::kSubpixelPositioning_Flag) { 1324b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org SkMatrix m; 1325b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org fRec.getSingleMatrix(&m); 1326b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 1327b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org // start out by assuming that we want no hining in X and Y 13284b413c8bb123e42ca4b9c7bfa6bc2167283cb84ccommit-bot@chromium.org scaleX = scaleY = kScaleForSubPixelPositionHinting; 1329b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org // now see if we need to restore hinting for axis-aligned baselines 1330b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org switch (SkComputeAxisAlignmentForHText(m)) { 1331b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org case kX_SkAxisAlignment: 1332b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org scaleY = SK_Scalar1; // want hinting in the Y direction 1333b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org break; 1334b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org case kY_SkAxisAlignment: 1335b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org scaleX = SK_Scalar1; // want hinting in the X direction 1336b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org break; 1337b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org default: 1338b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org break; 1339b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org } 1340b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 1341b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org CGAffineTransform xform = MatrixToCGAffineTransform(m, scaleX, scaleY); 1342b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org // need to release font when we're done 1343b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org font = CTFontCreateCopyWithAttributes(fCTFont, 1, &xform, NULL); 1344b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org } 1345b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 13461b27704eba15be4e9d1997faac42038493a30be5djsollen CGGlyph cgGlyph = (CGGlyph)glyph.getGlyphID(); 1347b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org AutoCFRelease<CGPathRef> cgPath(CTFontCreatePathForGlyph(font, cgGlyph, NULL)); 1348b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 1349b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org path->reset(); 1350b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org if (cgPath != NULL) { 1351b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org CGPathApply(cgPath, path, SkScalerContext_Mac::CTPathElement); 1352b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org } 1353b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 1354cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com if (fDoSubPosition) { 1355b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org SkMatrix m; 1356b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org m.setScale(SkScalarInvert(scaleX), SkScalarInvert(scaleY)); 1357b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org path->transform(m); 1358b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org // balance the call to CTFontCreateCopyWithAttributes 1359b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org CFSafeRelease(font); 1360b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org } 1361cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com if (fVertical) { 1362cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com SkPoint offset; 1363cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com getVerticalOffset(cgGlyph, &offset); 1364cefd981a4c4e90be33d1433592f11f84a102d2e0bungeman@google.com path->offset(offset.fX, offset.fY); 1365b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org } 1366b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org} 1367b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 1368410780677af260e32948b02c0725ef6ad761260cbungemanvoid SkScalerContext_Mac::generateFontMetrics(SkPaint::FontMetrics* metrics) { 1369410780677af260e32948b02c0725ef6ad761260cbungeman if (NULL == metrics) { 1370410780677af260e32948b02c0725ef6ad761260cbungeman return; 1371410780677af260e32948b02c0725ef6ad761260cbungeman } 13720bc406df48ac6f358ab8dcff08f71fe9c32b79decommit-bot@chromium.org 1373410780677af260e32948b02c0725ef6ad761260cbungeman CGRect theBounds = CTFontGetBoundingBox(fCTFont); 1374b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 1375410780677af260e32948b02c0725ef6ad761260cbungeman metrics->fTop = CGToScalar(-CGRectGetMaxY_inline(theBounds)); 1376410780677af260e32948b02c0725ef6ad761260cbungeman metrics->fAscent = CGToScalar(-CTFontGetAscent(fCTFont)); 1377410780677af260e32948b02c0725ef6ad761260cbungeman metrics->fDescent = CGToScalar( CTFontGetDescent(fCTFont)); 1378410780677af260e32948b02c0725ef6ad761260cbungeman metrics->fBottom = CGToScalar(-CGRectGetMinY_inline(theBounds)); 1379410780677af260e32948b02c0725ef6ad761260cbungeman metrics->fLeading = CGToScalar( CTFontGetLeading(fCTFont)); 1380410780677af260e32948b02c0725ef6ad761260cbungeman metrics->fAvgCharWidth = CGToScalar( CGRectGetWidth_inline(theBounds)); 1381410780677af260e32948b02c0725ef6ad761260cbungeman metrics->fXMin = CGToScalar( CGRectGetMinX_inline(theBounds)); 1382410780677af260e32948b02c0725ef6ad761260cbungeman metrics->fXMax = CGToScalar( CGRectGetMaxX_inline(theBounds)); 1383410780677af260e32948b02c0725ef6ad761260cbungeman metrics->fXHeight = CGToScalar( CTFontGetXHeight(fCTFont)); 1384410780677af260e32948b02c0725ef6ad761260cbungeman metrics->fUnderlineThickness = CGToScalar( CTFontGetUnderlineThickness(fCTFont)); 1385410780677af260e32948b02c0725ef6ad761260cbungeman metrics->fUnderlinePosition = -CGToScalar( CTFontGetUnderlinePosition(fCTFont)); 1386410780677af260e32948b02c0725ef6ad761260cbungeman 1387410780677af260e32948b02c0725ef6ad761260cbungeman metrics->fFlags |= SkPaint::FontMetrics::kUnderlineThinknessIsValid_Flag; 1388410780677af260e32948b02c0725ef6ad761260cbungeman metrics->fFlags |= SkPaint::FontMetrics::kUnderlinePositionIsValid_Flag; 1389b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org} 1390b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 1391b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.orgvoid SkScalerContext_Mac::CTPathElement(void *info, const CGPathElement *element) { 1392b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org SkPath* skPath = (SkPath*)info; 1393b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 1394b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org // Process the path element 1395b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org switch (element->type) { 1396b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org case kCGPathElementMoveToPoint: 1397b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org skPath->moveTo(element->points[0].x, -element->points[0].y); 1398b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org break; 1399b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 1400b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org case kCGPathElementAddLineToPoint: 1401b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org skPath->lineTo(element->points[0].x, -element->points[0].y); 1402b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org break; 1403b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 1404b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org case kCGPathElementAddQuadCurveToPoint: 1405b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org skPath->quadTo(element->points[0].x, -element->points[0].y, 1406b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org element->points[1].x, -element->points[1].y); 1407b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org break; 1408b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 1409b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org case kCGPathElementAddCurveToPoint: 1410b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org skPath->cubicTo(element->points[0].x, -element->points[0].y, 1411b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org element->points[1].x, -element->points[1].y, 1412b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org element->points[2].x, -element->points[2].y); 1413b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org break; 1414b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 1415b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org case kCGPathElementCloseSubpath: 1416b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org skPath->close(); 1417b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org break; 1418b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 1419b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org default: 1420b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org SkDEBUGFAIL("Unknown path element!"); 1421b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org break; 1422b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org } 1423b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org} 1424b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 1425b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 1426b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org/////////////////////////////////////////////////////////////////////////////// 1427b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 1428b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org// Returns NULL on failure 1429b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org// Call must still manage its ownership of provider 1430b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.orgstatic SkTypeface* create_from_dataProvider(CGDataProviderRef provider) { 1431b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org AutoCFRelease<CGFontRef> cg(CGFontCreateWithDataProvider(provider)); 1432b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org if (NULL == cg) { 1433b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org return NULL; 1434b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org } 1435b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org CTFontRef ct = CTFontCreateWithGraphicsFont(cg, 0, NULL, NULL); 143626337e970201cae39f44b49546b8d9b0bc5e5c98caseq return ct ? NewFromFontRef(ct, NULL, true) : NULL; 1437b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org} 1438b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 1439b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org// Web fonts added to the the CTFont registry do not return their character set. 1440b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org// Iterate through the font in this case. The existing caller caches the result, 1441b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org// so the performance impact isn't too bad. 1442b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.orgstatic void populate_glyph_to_unicode_slow(CTFontRef ctFont, CFIndex glyphCount, 1443b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org SkTDArray<SkUnichar>* glyphToUnicode) { 14447fa2a65c0cfc714364490cb715171461143024e0reed@google.com glyphToUnicode->setCount(SkToInt(glyphCount)); 1445b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org SkUnichar* out = glyphToUnicode->begin(); 1446b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org sk_bzero(out, glyphCount * sizeof(SkUnichar)); 1447b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org UniChar unichar = 0; 1448b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org while (glyphCount > 0) { 1449b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org CGGlyph glyph; 1450b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org if (CTFontGetGlyphsForCharacters(ctFont, &unichar, &glyph, 1)) { 1451b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org out[glyph] = unichar; 1452b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org --glyphCount; 1453b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org } 1454b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org if (++unichar == 0) { 1455b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org break; 1456b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org } 1457b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org } 1458b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org} 1459b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 1460b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org// Construct Glyph to Unicode table. 1461b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org// Unicode code points that require conjugate pairs in utf16 are not 1462b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org// supported. 1463b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.orgstatic void populate_glyph_to_unicode(CTFontRef ctFont, CFIndex glyphCount, 1464b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org SkTDArray<SkUnichar>* glyphToUnicode) { 1465b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org AutoCFRelease<CFCharacterSetRef> charSet(CTFontCopyCharacterSet(ctFont)); 1466b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org if (!charSet) { 1467b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org populate_glyph_to_unicode_slow(ctFont, glyphCount, glyphToUnicode); 1468b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org return; 1469b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org } 1470b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 1471b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org AutoCFRelease<CFDataRef> bitmap(CFCharacterSetCreateBitmapRepresentation(kCFAllocatorDefault, 1472b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org charSet)); 1473b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org if (!bitmap) { 1474b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org return; 1475b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org } 1476b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org CFIndex length = CFDataGetLength(bitmap); 1477b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org if (!length) { 1478b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org return; 1479b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org } 1480b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org if (length > 8192) { 1481b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org // TODO: Add support for Unicode above 0xFFFF 1482b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org // Consider only the BMP portion of the Unicode character points. 1483b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org // The bitmap may contain other planes, up to plane 16. 1484b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org // See http://developer.apple.com/library/ios/#documentation/CoreFoundation/Reference/CFCharacterSetRef/Reference/reference.html 1485b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org length = 8192; 1486b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org } 1487b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org const UInt8* bits = CFDataGetBytePtr(bitmap); 14887fa2a65c0cfc714364490cb715171461143024e0reed@google.com glyphToUnicode->setCount(SkToInt(glyphCount)); 1489b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org SkUnichar* out = glyphToUnicode->begin(); 1490b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org sk_bzero(out, glyphCount * sizeof(SkUnichar)); 1491b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org for (int i = 0; i < length; i++) { 1492b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org int mask = bits[i]; 1493b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org if (!mask) { 1494b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org continue; 1495b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org } 1496b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org for (int j = 0; j < 8; j++) { 1497b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org CGGlyph glyph; 1498b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org UniChar unichar = static_cast<UniChar>((i << 3) + j); 1499b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org if (mask & (1 << j) && CTFontGetGlyphsForCharacters(ctFont, &unichar, &glyph, 1)) { 1500b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org out[glyph] = unichar; 1501b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org } 1502b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org } 1503b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org } 1504b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org} 1505b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 1506b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.orgstatic bool getWidthAdvance(CTFontRef ctFont, int gId, int16_t* data) { 1507b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org CGSize advance; 1508b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org advance.width = 0; 1509b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org CGGlyph glyph = gId; 1510b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org CTFontGetAdvancesForGlyphs(ctFont, kCTFontHorizontalOrientation, &glyph, &advance, 1); 1511b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org *data = sk_float_round2int(advance.width); 1512b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org return true; 1513b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org} 1514b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 1515256b351fb1d33f3e3156d090a6a533b54ad66117bungeman/** Assumes src and dst are not NULL. */ 1516b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.orgstatic void CFStringToSkString(CFStringRef src, SkString* dst) { 1517b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org // Reserve enough room for the worst-case string, 1518b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org // plus 1 byte for the trailing null. 1519b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org CFIndex length = CFStringGetMaximumSizeForEncoding(CFStringGetLength(src), 1520b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org kCFStringEncodingUTF8) + 1; 1521b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org dst->resize(length); 1522b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org CFStringGetCString(src, dst->writable_str(), length, kCFStringEncodingUTF8); 1523b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org // Resize to the actual UTF-8 length used, stripping the null character. 1524b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org dst->resize(strlen(dst->c_str())); 1525b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org} 1526b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 15272689f615e364dc48ad73826564f5b13d2329179dreed@google.comSkAdvancedTypefaceMetrics* SkTypeface_Mac::onGetAdvancedTypefaceMetrics( 1528b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org SkAdvancedTypefaceMetrics::PerGlyphInfo perGlyphInfo, 1529b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org const uint32_t* glyphIDs, 15302689f615e364dc48ad73826564f5b13d2329179dreed@google.com uint32_t glyphIDsCount) const { 15312689f615e364dc48ad73826564f5b13d2329179dreed@google.com 15322689f615e364dc48ad73826564f5b13d2329179dreed@google.com CTFontRef originalCTFont = fFontRef.get(); 1533b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org AutoCFRelease<CTFontRef> ctFont(CTFontCreateCopyWithAttributes( 1534b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org originalCTFont, CTFontGetUnitsPerEm(originalCTFont), NULL, NULL)); 1535b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org SkAdvancedTypefaceMetrics* info = new SkAdvancedTypefaceMetrics; 1536b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 1537b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org { 1538b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org AutoCFRelease<CFStringRef> fontName(CTFontCopyPostScriptName(ctFont)); 1539256b351fb1d33f3e3156d090a6a533b54ad66117bungeman if (fontName.get()) { 1540256b351fb1d33f3e3156d090a6a533b54ad66117bungeman CFStringToSkString(fontName, &info->fFontName); 1541256b351fb1d33f3e3156d090a6a533b54ad66117bungeman } 1542b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org } 1543b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 1544b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org CFIndex glyphCount = CTFontGetGlyphCount(ctFont); 1545b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org info->fLastGlyphID = SkToU16(glyphCount - 1); 1546b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org info->fEmSize = CTFontGetUnitsPerEm(ctFont); 15470f9bad01b0e7ad592ffb342dcf1d238b15329be1vandebo info->fFlags = SkAdvancedTypefaceMetrics::kEmpty_FontFlag; 15480f9bad01b0e7ad592ffb342dcf1d238b15329be1vandebo info->fStyle = 0; 1549b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 1550b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org if (perGlyphInfo & SkAdvancedTypefaceMetrics::kToUnicode_PerGlyphInfo) { 1551b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org populate_glyph_to_unicode(ctFont, glyphCount, &info->fGlyphToUnicode); 1552b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org } 1553b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 1554b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org // If it's not a truetype font, mark it as 'other'. Assume that TrueType 1555b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org // fonts always have both glyf and loca tables. At the least, this is what 1556b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org // sfntly needs to subset the font. CTFontCopyAttribute() does not always 1557b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org // succeed in determining this directly. 15582689f615e364dc48ad73826564f5b13d2329179dreed@google.com if (!this->getTableSize('glyf') || !this->getTableSize('loca')) { 1559b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org info->fType = SkAdvancedTypefaceMetrics::kOther_Font; 1560b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org info->fItalicAngle = 0; 1561b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org info->fAscent = 0; 1562b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org info->fDescent = 0; 1563b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org info->fStemV = 0; 1564b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org info->fCapHeight = 0; 1565b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org info->fBBox = SkIRect::MakeEmpty(); 1566b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org return info; 1567b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org } 1568b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 1569b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org info->fType = SkAdvancedTypefaceMetrics::kTrueType_Font; 1570b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org CTFontSymbolicTraits symbolicTraits = CTFontGetSymbolicTraits(ctFont); 1571b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org if (symbolicTraits & kCTFontMonoSpaceTrait) { 1572b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org info->fStyle |= SkAdvancedTypefaceMetrics::kFixedPitch_Style; 1573b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org } 1574b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org if (symbolicTraits & kCTFontItalicTrait) { 1575b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org info->fStyle |= SkAdvancedTypefaceMetrics::kItalic_Style; 1576b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org } 1577b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org CTFontStylisticClass stylisticClass = symbolicTraits & kCTFontClassMaskTrait; 1578b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org if (stylisticClass >= kCTFontOldStyleSerifsClass && stylisticClass <= kCTFontSlabSerifsClass) { 1579b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org info->fStyle |= SkAdvancedTypefaceMetrics::kSerif_Style; 1580b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org } else if (stylisticClass & kCTFontScriptsClass) { 1581b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org info->fStyle |= SkAdvancedTypefaceMetrics::kScript_Style; 1582b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org } 1583b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org info->fItalicAngle = (int16_t) CTFontGetSlantAngle(ctFont); 1584b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org info->fAscent = (int16_t) CTFontGetAscent(ctFont); 1585b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org info->fDescent = (int16_t) CTFontGetDescent(ctFont); 1586b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org info->fCapHeight = (int16_t) CTFontGetCapHeight(ctFont); 1587b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org CGRect bbox = CTFontGetBoundingBox(ctFont); 1588b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 1589b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org SkRect r; 1590b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org r.set( CGToScalar(CGRectGetMinX_inline(bbox)), // Left 1591b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org CGToScalar(CGRectGetMaxY_inline(bbox)), // Top 1592b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org CGToScalar(CGRectGetMaxX_inline(bbox)), // Right 1593b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org CGToScalar(CGRectGetMinY_inline(bbox))); // Bottom 1594b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 1595b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org r.roundOut(&(info->fBBox)); 1596b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 1597b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org // Figure out a good guess for StemV - Min width of i, I, !, 1. 1598b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org // This probably isn't very good with an italic font. 1599b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org int16_t min_width = SHRT_MAX; 1600b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org info->fStemV = 0; 1601b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org static const UniChar stem_chars[] = {'i', 'I', '!', '1'}; 1602b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org const size_t count = sizeof(stem_chars) / sizeof(stem_chars[0]); 1603b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org CGGlyph glyphs[count]; 1604b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org CGRect boundingRects[count]; 1605b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org if (CTFontGetGlyphsForCharacters(ctFont, stem_chars, glyphs, count)) { 1606b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org CTFontGetBoundingRectsForGlyphs(ctFont, kCTFontHorizontalOrientation, 1607b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org glyphs, boundingRects, count); 1608b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org for (size_t i = 0; i < count; i++) { 1609b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org int16_t width = (int16_t) boundingRects[i].size.width; 1610b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org if (width > 0 && width < min_width) { 1611b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org min_width = width; 1612b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org info->fStemV = min_width; 1613b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org } 1614b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org } 1615b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org } 1616b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 16170f9bad01b0e7ad592ffb342dcf1d238b15329be1vandebo if (perGlyphInfo & SkAdvancedTypefaceMetrics::kHAdvance_PerGlyphInfo) { 1618b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org if (info->fStyle & SkAdvancedTypefaceMetrics::kFixedPitch_Style) { 1619b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org skia_advanced_typeface_metrics_utils::appendRange(&info->fGlyphWidths, 0); 1620b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org info->fGlyphWidths->fAdvance.append(1, &min_width); 1621b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org skia_advanced_typeface_metrics_utils::finishRange(info->fGlyphWidths.get(), 0, 1622b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org SkAdvancedTypefaceMetrics::WidthRange::kDefault); 1623b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org } else { 1624b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org info->fGlyphWidths.reset( 1625b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org skia_advanced_typeface_metrics_utils::getAdvanceData(ctFont.get(), 16267fa2a65c0cfc714364490cb715171461143024e0reed@google.com SkToInt(glyphCount), 1627b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org glyphIDs, 1628b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org glyphIDsCount, 1629b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org &getWidthAdvance)); 1630b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org } 1631b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org } 1632b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org return info; 1633b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org} 1634b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 1635b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org/////////////////////////////////////////////////////////////////////////////// 1636b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 1637cc9aad5787b52216f46b9d6d95a781240e3e6b6breed@google.comstatic SK_SFNT_ULONG get_font_type_tag(const SkTypeface_Mac* typeface) { 1638cc9aad5787b52216f46b9d6d95a781240e3e6b6breed@google.com CTFontRef ctFont = typeface->fFontRef.get(); 1639b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org AutoCFRelease<CFNumberRef> fontFormatRef( 1640b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org static_cast<CFNumberRef>(CTFontCopyAttribute(ctFont, kCTFontFormatAttribute))); 1641b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org if (!fontFormatRef) { 1642b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org return 0; 1643b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org } 1644b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 1645b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org SInt32 fontFormatValue; 1646b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org if (!CFNumberGetValue(fontFormatRef, kCFNumberSInt32Type, &fontFormatValue)) { 1647b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org return 0; 1648b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org } 1649b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 1650b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org switch (fontFormatValue) { 1651b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org case kCTFontFormatOpenTypePostScript: 1652b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org return SkSFNTHeader::fontType_OpenTypeCFF::TAG; 1653b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org case kCTFontFormatOpenTypeTrueType: 1654b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org return SkSFNTHeader::fontType_WindowsTrueType::TAG; 1655b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org case kCTFontFormatTrueType: 1656b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org return SkSFNTHeader::fontType_MacTrueType::TAG; 1657b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org case kCTFontFormatPostScript: 1658b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org return SkSFNTHeader::fontType_PostScript::TAG; 1659b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org case kCTFontFormatBitmap: 1660b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org return SkSFNTHeader::fontType_MacTrueType::TAG; 1661b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org case kCTFontFormatUnrecognized: 1662b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org default: 1663b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org //CT seems to be unreliable in being able to obtain the type, 1664b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org //even if all we want is the first four bytes of the font resource. 1665b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org //Just the presence of the FontForge 'FFTM' table seems to throw it off. 1666b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org return SkSFNTHeader::fontType_WindowsTrueType::TAG; 1667b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org } 1668b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org} 1669b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 1670cc9aad5787b52216f46b9d6d95a781240e3e6b6breed@google.comSkStream* SkTypeface_Mac::onOpenStream(int* ttcIndex) const { 1671cc9aad5787b52216f46b9d6d95a781240e3e6b6breed@google.com SK_SFNT_ULONG fontType = get_font_type_tag(this); 1672b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org if (0 == fontType) { 1673b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org return NULL; 1674b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org } 1675b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 1676b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org // get table tags 1677cc9aad5787b52216f46b9d6d95a781240e3e6b6breed@google.com int numTables = this->countTables(); 1678b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org SkTDArray<SkFontTableTag> tableTags; 1679b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org tableTags.setCount(numTables); 1680cc9aad5787b52216f46b9d6d95a781240e3e6b6breed@google.com this->getTableTags(tableTags.begin()); 1681b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 1682b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org // calc total size for font, save sizes 1683b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org SkTDArray<size_t> tableSizes; 1684b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org size_t totalSize = sizeof(SkSFNTHeader) + sizeof(SkSFNTHeader::TableDirectoryEntry) * numTables; 1685b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org for (int tableIndex = 0; tableIndex < numTables; ++tableIndex) { 1686cc9aad5787b52216f46b9d6d95a781240e3e6b6breed@google.com size_t tableSize = this->getTableSize(tableTags[tableIndex]); 1687b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org totalSize += (tableSize + 3) & ~3; 1688b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org *tableSizes.append() = tableSize; 1689b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org } 1690b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 1691b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org // reserve memory for stream, and zero it (tables must be zero padded) 1692b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org SkMemoryStream* stream = new SkMemoryStream(totalSize); 1693b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org char* dataStart = (char*)stream->getMemoryBase(); 1694b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org sk_bzero(dataStart, totalSize); 1695b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org char* dataPtr = dataStart; 1696b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 1697b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org // compute font header entries 1698b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org uint16_t entrySelector = 0; 1699b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org uint16_t searchRange = 1; 1700b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org while (searchRange < numTables >> 1) { 1701b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org entrySelector++; 1702b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org searchRange <<= 1; 1703b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org } 1704b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org searchRange <<= 4; 1705b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org uint16_t rangeShift = (numTables << 4) - searchRange; 1706b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 1707b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org // write font header 1708b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org SkSFNTHeader* header = (SkSFNTHeader*)dataPtr; 1709b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org header->fontType = fontType; 1710b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org header->numTables = SkEndian_SwapBE16(numTables); 1711b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org header->searchRange = SkEndian_SwapBE16(searchRange); 1712b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org header->entrySelector = SkEndian_SwapBE16(entrySelector); 1713b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org header->rangeShift = SkEndian_SwapBE16(rangeShift); 1714b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org dataPtr += sizeof(SkSFNTHeader); 1715b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 1716b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org // write tables 1717b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org SkSFNTHeader::TableDirectoryEntry* entry = (SkSFNTHeader::TableDirectoryEntry*)dataPtr; 1718b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org dataPtr += sizeof(SkSFNTHeader::TableDirectoryEntry) * numTables; 1719b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org for (int tableIndex = 0; tableIndex < numTables; ++tableIndex) { 1720b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org size_t tableSize = tableSizes[tableIndex]; 1721cc9aad5787b52216f46b9d6d95a781240e3e6b6breed@google.com this->getTableData(tableTags[tableIndex], 0, tableSize, dataPtr); 1722b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org entry->tag = SkEndian_SwapBE32(tableTags[tableIndex]); 1723b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org entry->checksum = SkEndian_SwapBE32(SkOTUtils::CalcTableChecksum((SK_OT_ULONG*)dataPtr, 1724b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org tableSize)); 17257fa2a65c0cfc714364490cb715171461143024e0reed@google.com entry->offset = SkEndian_SwapBE32(SkToU32(dataPtr - dataStart)); 17267fa2a65c0cfc714364490cb715171461143024e0reed@google.com entry->logicalLength = SkEndian_SwapBE32(SkToU32(tableSize)); 1727b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 1728b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org dataPtr += (tableSize + 3) & ~3; 1729b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org ++entry; 1730b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org } 1731b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 1732b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org return stream; 1733b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org} 1734b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 1735b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org/////////////////////////////////////////////////////////////////////////////// 1736b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org/////////////////////////////////////////////////////////////////////////////// 1737b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 1738b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.orgint SkTypeface_Mac::onGetUPEM() const { 1739b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org AutoCFRelease<CGFontRef> cgFont(CTFontCopyGraphicsFont(fFontRef, NULL)); 1740b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org return CGFontGetUnitsPerEm(cgFont); 1741b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org} 1742b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 1743839702b61934914118ec557dd641be322eba3b5fbungeman@google.comSkTypeface::LocalizedStrings* SkTypeface_Mac::onCreateFamilyNameIterator() const { 1744a980269c2498836101146adc729ef780fb89824ebungeman@google.com SkTypeface::LocalizedStrings* nameIter = 1745a980269c2498836101146adc729ef780fb89824ebungeman@google.com SkOTUtils::LocalizedStrings_NameTable::CreateForFamilyNames(*this); 1746a980269c2498836101146adc729ef780fb89824ebungeman@google.com if (NULL == nameIter) { 1747a980269c2498836101146adc729ef780fb89824ebungeman@google.com AutoCFRelease<CFStringRef> cfLanguage; 1748a980269c2498836101146adc729ef780fb89824ebungeman@google.com AutoCFRelease<CFStringRef> cfFamilyName( 1749a980269c2498836101146adc729ef780fb89824ebungeman@google.com CTFontCopyLocalizedName(fFontRef, kCTFontFamilyNameKey, &cfLanguage)); 1750a980269c2498836101146adc729ef780fb89824ebungeman@google.com 1751a980269c2498836101146adc729ef780fb89824ebungeman@google.com SkString skLanguage; 1752a980269c2498836101146adc729ef780fb89824ebungeman@google.com SkString skFamilyName; 1753a980269c2498836101146adc729ef780fb89824ebungeman@google.com if (cfLanguage.get()) { 1754a980269c2498836101146adc729ef780fb89824ebungeman@google.com CFStringToSkString(cfLanguage.get(), &skLanguage); 1755a980269c2498836101146adc729ef780fb89824ebungeman@google.com } else { 1756a980269c2498836101146adc729ef780fb89824ebungeman@google.com skLanguage = "und"; //undetermined 1757a980269c2498836101146adc729ef780fb89824ebungeman@google.com } 1758a980269c2498836101146adc729ef780fb89824ebungeman@google.com if (cfFamilyName.get()) { 1759a980269c2498836101146adc729ef780fb89824ebungeman@google.com CFStringToSkString(cfFamilyName.get(), &skFamilyName); 1760a980269c2498836101146adc729ef780fb89824ebungeman@google.com } 1761a980269c2498836101146adc729ef780fb89824ebungeman@google.com 1762a980269c2498836101146adc729ef780fb89824ebungeman@google.com nameIter = new SkOTUtils::LocalizedStrings_SingleName(skFamilyName, skLanguage); 1763a980269c2498836101146adc729ef780fb89824ebungeman@google.com } 1764a980269c2498836101146adc729ef780fb89824ebungeman@google.com return nameIter; 1765a980269c2498836101146adc729ef780fb89824ebungeman@google.com} 1766a980269c2498836101146adc729ef780fb89824ebungeman@google.com 1767b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org// If, as is the case with web fonts, the CTFont data isn't available, 1768b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org// the CGFont data may work. While the CGFont may always provide the 1769b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org// right result, leave the CTFont code path to minimize disruption. 1770b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.orgstatic CFDataRef copyTableFromFont(CTFontRef ctFont, SkFontTableTag tag) { 1771b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org CFDataRef data = CTFontCopyTable(ctFont, (CTFontTableTag) tag, 1772b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org kCTFontTableOptionNoOptions); 1773b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org if (NULL == data) { 1774b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org AutoCFRelease<CGFontRef> cgFont(CTFontCopyGraphicsFont(ctFont, NULL)); 1775b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org data = CGFontCopyTableForTag(cgFont, tag); 1776b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org } 1777b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org return data; 1778b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org} 1779b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 1780b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.orgint SkTypeface_Mac::onGetTableTags(SkFontTableTag tags[]) const { 1781b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org AutoCFRelease<CFArrayRef> cfArray(CTFontCopyAvailableTables(fFontRef, 1782b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org kCTFontTableOptionNoOptions)); 1783b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org if (NULL == cfArray) { 1784b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org return 0; 1785b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org } 17867fa2a65c0cfc714364490cb715171461143024e0reed@google.com int count = SkToInt(CFArrayGetCount(cfArray)); 1787b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org if (tags) { 1788b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org for (int i = 0; i < count; ++i) { 1789b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org uintptr_t fontTag = reinterpret_cast<uintptr_t>(CFArrayGetValueAtIndex(cfArray, i)); 1790b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org tags[i] = static_cast<SkFontTableTag>(fontTag); 1791b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org } 1792b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org } 1793b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org return count; 1794b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org} 1795b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 1796b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.orgsize_t SkTypeface_Mac::onGetTableData(SkFontTableTag tag, size_t offset, 1797b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org size_t length, void* dstData) const { 1798b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org AutoCFRelease<CFDataRef> srcData(copyTableFromFont(fFontRef, tag)); 1799b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org if (NULL == srcData) { 1800b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org return 0; 1801b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org } 1802b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 1803b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org size_t srcSize = CFDataGetLength(srcData); 1804b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org if (offset >= srcSize) { 1805b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org return 0; 1806b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org } 1807b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org if (length > srcSize - offset) { 1808b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org length = srcSize - offset; 1809b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org } 1810b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org if (dstData) { 1811b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org memcpy(dstData, CFDataGetBytePtr(srcData) + offset, length); 1812b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org } 1813b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org return length; 1814b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org} 1815b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 1816b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.orgSkScalerContext* SkTypeface_Mac::onCreateScalerContext(const SkDescriptor* desc) const { 18170da48618a758ef46c2174bdc1eaeb6dd8a693a2ereed@google.com return new SkScalerContext_Mac(const_cast<SkTypeface_Mac*>(this), desc); 1818b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org} 1819b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 1820b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.orgvoid SkTypeface_Mac::onFilterRec(SkScalerContextRec* rec) const { 1821c5fd46171841711973b9433c726ff8608335940ccommit-bot@chromium.org if (rec->fFlags & SkScalerContext::kLCD_BGROrder_Flag || 1822c5fd46171841711973b9433c726ff8608335940ccommit-bot@chromium.org rec->fFlags & SkScalerContext::kLCD_Vertical_Flag) 1823c5fd46171841711973b9433c726ff8608335940ccommit-bot@chromium.org { 1824c5fd46171841711973b9433c726ff8608335940ccommit-bot@chromium.org rec->fMaskFormat = SkMask::kA8_Format; 1825c5fd46171841711973b9433c726ff8608335940ccommit-bot@chromium.org // Render the glyphs as close as possible to what was requested. 1826c5fd46171841711973b9433c726ff8608335940ccommit-bot@chromium.org // The above turns off subpixel rendering, but the user requested it. 1827c5fd46171841711973b9433c726ff8608335940ccommit-bot@chromium.org // Normal hinting will cause the A8 masks to be generated from CoreGraphics subpixel masks. 1828c5fd46171841711973b9433c726ff8608335940ccommit-bot@chromium.org // See comments below for more details. 1829c5fd46171841711973b9433c726ff8608335940ccommit-bot@chromium.org rec->setHinting(SkPaint::kNormal_Hinting); 1830c5fd46171841711973b9433c726ff8608335940ccommit-bot@chromium.org } 1831e944de7523ddd0ffffdc423c0b99a83fe83c5d5askia.committer@gmail.com 1832c5fd46171841711973b9433c726ff8608335940ccommit-bot@chromium.org unsigned flagsWeDontSupport = SkScalerContext::kDevKernText_Flag | 1833f6f56878bc96386882721b15ba610984185d3dc9bungeman@google.com SkScalerContext::kForceAutohinting_Flag | 1834c5fd46171841711973b9433c726ff8608335940ccommit-bot@chromium.org SkScalerContext::kLCD_BGROrder_Flag | 1835c5fd46171841711973b9433c726ff8608335940ccommit-bot@chromium.org SkScalerContext::kLCD_Vertical_Flag; 18360c23faf222c24529781139495a5f4f4ab61f7cb2skia.committer@gmail.com 1837b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org rec->fFlags &= ~flagsWeDontSupport; 18380c23faf222c24529781139495a5f4f4ab61f7cb2skia.committer@gmail.com 1839b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org bool lcdSupport = supports_LCD(); 18400c23faf222c24529781139495a5f4f4ab61f7cb2skia.committer@gmail.com 1841b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org // Only two levels of hinting are supported. 1842b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org // kNo_Hinting means avoid CoreGraphics outline dilation. 1843b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org // kNormal_Hinting means CoreGraphics outline dilation is allowed. 1844b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org // If there is no lcd support, hinting (dilation) cannot be supported. 1845b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org SkPaint::Hinting hinting = rec->getHinting(); 1846b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org if (SkPaint::kSlight_Hinting == hinting || !lcdSupport) { 1847b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org hinting = SkPaint::kNo_Hinting; 1848b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org } else if (SkPaint::kFull_Hinting == hinting) { 1849b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org hinting = SkPaint::kNormal_Hinting; 1850b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org } 1851b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org rec->setHinting(hinting); 18520c23faf222c24529781139495a5f4f4ab61f7cb2skia.committer@gmail.com 1853b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org // FIXME: lcd smoothed un-hinted rasterization unsupported. 1854b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org // Tracked by http://code.google.com/p/skia/issues/detail?id=915 . 1855b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org // There is no current means to honor a request for unhinted lcd, 1856b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org // so arbitrarilly ignore the hinting request and honor lcd. 18570c23faf222c24529781139495a5f4f4ab61f7cb2skia.committer@gmail.com 1858b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org // Hinting and smoothing should be orthogonal, but currently they are not. 1859b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org // CoreGraphics has no API to influence hinting. However, its lcd smoothed 1860b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org // output is drawn from auto-dilated outlines (the amount of which is 1861b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org // determined by AppleFontSmoothing). Its regular anti-aliased output is 1862b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org // drawn from un-dilated outlines. 18630c23faf222c24529781139495a5f4f4ab61f7cb2skia.committer@gmail.com 1864b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org // The behavior of Skia is as follows: 1865b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org // [AA][no-hint]: generate AA using CoreGraphic's AA output. 1866b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org // [AA][yes-hint]: use CoreGraphic's LCD output and reduce it to a single 1867b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org // channel. This matches [LCD][yes-hint] in weight. 1868b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org // [LCD][no-hint]: curently unable to honor, and must pick which to respect. 1869b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org // Currenly side with LCD, effectively ignoring the hinting setting. 1870b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org // [LCD][yes-hint]: generate LCD using CoreGraphic's LCD output. 18710c23faf222c24529781139495a5f4f4ab61f7cb2skia.committer@gmail.com 1872b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org if (isLCDFormat(rec->fMaskFormat)) { 1873b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org if (lcdSupport) { 1874b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org //CoreGraphics creates 555 masks for smoothed text anyway. 1875b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org rec->fMaskFormat = SkMask::kLCD16_Format; 1876b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org rec->setHinting(SkPaint::kNormal_Hinting); 1877b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org } else { 1878b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org rec->fMaskFormat = SkMask::kA8_Format; 1879b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org } 1880b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org } 18810c23faf222c24529781139495a5f4f4ab61f7cb2skia.committer@gmail.com 1882b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org // Unhinted A8 masks (those not derived from LCD masks) must respect SK_GAMMA_APPLY_TO_A8. 1883b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org // All other masks can use regular gamma. 1884b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org if (SkMask::kA8_Format == rec->fMaskFormat && SkPaint::kNo_Hinting == hinting) { 1885b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org#ifndef SK_GAMMA_APPLY_TO_A8 1886b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org rec->ignorePreBlend(); 1887feda2f90a4ad9625e14d8cb02a90b9644d803dd4reed@android.com#endif 1888b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org } else { 1889b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org //CoreGraphics dialates smoothed text as needed. 1890b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org rec->setContrast(0); 1891b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org } 1892b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org} 1893b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 1894b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org// we take ownership of the ref 1895b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.orgstatic const char* get_str(CFStringRef ref, SkString* str) { 1896256b351fb1d33f3e3156d090a6a533b54ad66117bungeman if (NULL == ref) { 1897256b351fb1d33f3e3156d090a6a533b54ad66117bungeman return NULL; 1898256b351fb1d33f3e3156d090a6a533b54ad66117bungeman } 1899b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org CFStringToSkString(ref, str); 1900b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org CFSafeRelease(ref); 1901b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org return str->c_str(); 1902b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org} 1903b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org 1904b374d6a62c0259387d90cad74753d8bad9ee1beabungemanvoid SkTypeface_Mac::onGetFamilyName(SkString* familyName) const { 1905b374d6a62c0259387d90cad74753d8bad9ee1beabungeman get_str(CTFontCopyFamilyName(fFontRef), familyName); 1906b374d6a62c0259387d90cad74753d8bad9ee1beabungeman} 1907b374d6a62c0259387d90cad74753d8bad9ee1beabungeman 19085526ede94a2fc58bcf6b578b12a29f6addad776dreed@google.comvoid SkTypeface_Mac::onGetFontDescriptor(SkFontDescriptor* desc, 19095526ede94a2fc58bcf6b578b12a29f6addad776dreed@google.com bool* isLocalStream) const { 1910b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org SkString tmpStr; 19110c23faf222c24529781139495a5f4f4ab61f7cb2skia.committer@gmail.com 1912b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org desc->setFamilyName(get_str(CTFontCopyFamilyName(fFontRef), &tmpStr)); 1913b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org desc->setFullName(get_str(CTFontCopyFullName(fFontRef), &tmpStr)); 1914b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org desc->setPostscriptName(get_str(CTFontCopyPostScriptName(fFontRef), &tmpStr)); 191526337e970201cae39f44b49546b8d9b0bc5e5c98caseq *isLocalStream = fIsLocalStream; 1916b103ed4e39613cac823b94df3e5b0e92857d3b4dmike@reedtribe.org} 19175526ede94a2fc58bcf6b578b12a29f6addad776dreed@google.com 1918bcb42aecf1bdb9ae80d766d203b4f636b954cf03reed@google.comint SkTypeface_Mac::onCharsToGlyphs(const void* chars, Encoding encoding, 191972b8cb2320dddc6e006a2857746014e607e9e151bungeman@google.com uint16_t glyphs[], int glyphCount) const 192072b8cb2320dddc6e006a2857746014e607e9e151bungeman@google.com{ 192172b8cb2320dddc6e006a2857746014e607e9e151bungeman@google.com // Undocumented behavior of CTFontGetGlyphsForCharacters with non-bmp code points: 192272b8cb2320dddc6e006a2857746014e607e9e151bungeman@google.com // When a surrogate pair is detected, the glyph index used is the index of the high surrogate. 192372b8cb2320dddc6e006a2857746014e607e9e151bungeman@google.com // It is documented that if a mapping is unavailable, the glyph will be set to 0. 19240673efeea2be3b6b6198ddbac7217d7ab30fe59cskia.committer@gmail.com 1925bcb42aecf1bdb9ae80d766d203b4f636b954cf03reed@google.com SkAutoSTMalloc<1024, UniChar> charStorage; 192672b8cb2320dddc6e006a2857746014e607e9e151bungeman@google.com const UniChar* src; // UniChar is a UTF-16 16-bit code unit. 192772b8cb2320dddc6e006a2857746014e607e9e151bungeman@google.com int srcCount; 1928bcb42aecf1bdb9ae80d766d203b4f636b954cf03reed@google.com switch (encoding) { 1929bcb42aecf1bdb9ae80d766d203b4f636b954cf03reed@google.com case kUTF8_Encoding: { 193072b8cb2320dddc6e006a2857746014e607e9e151bungeman@google.com const char* utf8 = reinterpret_cast<const char*>(chars); 193172b8cb2320dddc6e006a2857746014e607e9e151bungeman@google.com UniChar* utf16 = charStorage.reset(2 * glyphCount); 193272b8cb2320dddc6e006a2857746014e607e9e151bungeman@google.com src = utf16; 1933bcb42aecf1bdb9ae80d766d203b4f636b954cf03reed@google.com for (int i = 0; i < glyphCount; ++i) { 193472b8cb2320dddc6e006a2857746014e607e9e151bungeman@google.com SkUnichar uni = SkUTF8_NextUnichar(&utf8); 193572b8cb2320dddc6e006a2857746014e607e9e151bungeman@google.com utf16 += SkUTF16_FromUnichar(uni, utf16); 1936bcb42aecf1bdb9ae80d766d203b4f636b954cf03reed@google.com } 19377fa2a65c0cfc714364490cb715171461143024e0reed@google.com srcCount = SkToInt(utf16 - src); 1938bcb42aecf1bdb9ae80d766d203b4f636b954cf03reed@google.com break; 1939bcb42aecf1bdb9ae80d766d203b4f636b954cf03reed@google.com } 194072b8cb2320dddc6e006a2857746014e607e9e151bungeman@google.com case kUTF16_Encoding: { 194172b8cb2320dddc6e006a2857746014e607e9e151bungeman@google.com src = reinterpret_cast<const UniChar*>(chars); 194272b8cb2320dddc6e006a2857746014e607e9e151bungeman@google.com int extra = 0; 194372b8cb2320dddc6e006a2857746014e607e9e151bungeman@google.com for (int i = 0; i < glyphCount; ++i) { 194472b8cb2320dddc6e006a2857746014e607e9e151bungeman@google.com if (SkUTF16_IsHighSurrogate(src[i + extra])) { 194572b8cb2320dddc6e006a2857746014e607e9e151bungeman@google.com ++extra; 194672b8cb2320dddc6e006a2857746014e607e9e151bungeman@google.com } 194772b8cb2320dddc6e006a2857746014e607e9e151bungeman@google.com } 194872b8cb2320dddc6e006a2857746014e607e9e151bungeman@google.com srcCount = glyphCount + extra; 1949bcb42aecf1bdb9ae80d766d203b4f636b954cf03reed@google.com break; 195072b8cb2320dddc6e006a2857746014e607e9e151bungeman@google.com } 1951bcb42aecf1bdb9ae80d766d203b4f636b954cf03reed@google.com case kUTF32_Encoding: { 195272b8cb2320dddc6e006a2857746014e607e9e151bungeman@google.com const SkUnichar* utf32 = reinterpret_cast<const SkUnichar*>(chars); 195372b8cb2320dddc6e006a2857746014e607e9e151bungeman@google.com UniChar* utf16 = charStorage.reset(2 * glyphCount); 195472b8cb2320dddc6e006a2857746014e607e9e151bungeman@google.com src = utf16; 1955bcb42aecf1bdb9ae80d766d203b4f636b954cf03reed@google.com for (int i = 0; i < glyphCount; ++i) { 195672b8cb2320dddc6e006a2857746014e607e9e151bungeman@google.com utf16 += SkUTF16_FromUnichar(utf32[i], utf16); 1957bcb42aecf1bdb9ae80d766d203b4f636b954cf03reed@google.com } 19587fa2a65c0cfc714364490cb715171461143024e0reed@google.com srcCount = SkToInt(utf16 - src); 1959bcb42aecf1bdb9ae80d766d203b4f636b954cf03reed@google.com break; 1960bcb42aecf1bdb9ae80d766d203b4f636b954cf03reed@google.com } 1961bcb42aecf1bdb9ae80d766d203b4f636b954cf03reed@google.com } 1962bcb42aecf1bdb9ae80d766d203b4f636b954cf03reed@google.com 196372b8cb2320dddc6e006a2857746014e607e9e151bungeman@google.com // If glyphs is NULL, CT still needs glyph storage for finding the first failure. 196472b8cb2320dddc6e006a2857746014e607e9e151bungeman@google.com // Also, if there are any non-bmp code points, the provided 'glyphs' storage will be inadequate. 1965bcb42aecf1bdb9ae80d766d203b4f636b954cf03reed@google.com SkAutoSTMalloc<1024, uint16_t> glyphStorage; 1966bcb42aecf1bdb9ae80d766d203b4f636b954cf03reed@google.com uint16_t* macGlyphs = glyphs; 196772b8cb2320dddc6e006a2857746014e607e9e151bungeman@google.com if (NULL == macGlyphs || srcCount > glyphCount) { 196872b8cb2320dddc6e006a2857746014e607e9e151bungeman@google.com macGlyphs = glyphStorage.reset(srcCount); 1969bcb42aecf1bdb9ae80d766d203b4f636b954cf03reed@google.com } 1970bcb42aecf1bdb9ae80d766d203b4f636b954cf03reed@google.com 197172b8cb2320dddc6e006a2857746014e607e9e151bungeman@google.com bool allEncoded = CTFontGetGlyphsForCharacters(fFontRef, src, macGlyphs, srcCount); 197272b8cb2320dddc6e006a2857746014e607e9e151bungeman@google.com 197372b8cb2320dddc6e006a2857746014e607e9e151bungeman@google.com // If there were any non-bmp, then copy and compact. 197472b8cb2320dddc6e006a2857746014e607e9e151bungeman@google.com // If 'glyphs' is NULL, then compact glyphStorage in-place. 197572b8cb2320dddc6e006a2857746014e607e9e151bungeman@google.com // If all are bmp and 'glyphs' is non-NULL, 'glyphs' already contains the compact glyphs. 197672b8cb2320dddc6e006a2857746014e607e9e151bungeman@google.com // If some are non-bmp and 'glyphs' is non-NULL, copy and compact into 'glyphs'. 197772b8cb2320dddc6e006a2857746014e607e9e151bungeman@google.com uint16_t* compactedGlyphs = glyphs; 197872b8cb2320dddc6e006a2857746014e607e9e151bungeman@google.com if (NULL == compactedGlyphs) { 197972b8cb2320dddc6e006a2857746014e607e9e151bungeman@google.com compactedGlyphs = macGlyphs; 198072b8cb2320dddc6e006a2857746014e607e9e151bungeman@google.com } 198172b8cb2320dddc6e006a2857746014e607e9e151bungeman@google.com if (srcCount > glyphCount) { 198272b8cb2320dddc6e006a2857746014e607e9e151bungeman@google.com int extra = 0; 198372b8cb2320dddc6e006a2857746014e607e9e151bungeman@google.com for (int i = 0; i < glyphCount; ++i) { 19847b09aab7130c174c6a2dd4becedbddaa6cf7945dbungeman compactedGlyphs[i] = macGlyphs[i + extra]; 198572b8cb2320dddc6e006a2857746014e607e9e151bungeman@google.com if (SkUTF16_IsHighSurrogate(src[i + extra])) { 198672b8cb2320dddc6e006a2857746014e607e9e151bungeman@google.com ++extra; 198772b8cb2320dddc6e006a2857746014e607e9e151bungeman@google.com } 198872b8cb2320dddc6e006a2857746014e607e9e151bungeman@google.com } 198972b8cb2320dddc6e006a2857746014e607e9e151bungeman@google.com } 199072b8cb2320dddc6e006a2857746014e607e9e151bungeman@google.com 199172b8cb2320dddc6e006a2857746014e607e9e151bungeman@google.com if (allEncoded) { 1992bcb42aecf1bdb9ae80d766d203b4f636b954cf03reed@google.com return glyphCount; 1993bcb42aecf1bdb9ae80d766d203b4f636b954cf03reed@google.com } 199472b8cb2320dddc6e006a2857746014e607e9e151bungeman@google.com 199572b8cb2320dddc6e006a2857746014e607e9e151bungeman@google.com // If we got false, then we need to manually look for first failure. 1996bcb42aecf1bdb9ae80d766d203b4f636b954cf03reed@google.com for (int i = 0; i < glyphCount; ++i) { 199772b8cb2320dddc6e006a2857746014e607e9e151bungeman@google.com if (0 == compactedGlyphs[i]) { 1998bcb42aecf1bdb9ae80d766d203b4f636b954cf03reed@google.com return i; 1999bcb42aecf1bdb9ae80d766d203b4f636b954cf03reed@google.com } 2000bcb42aecf1bdb9ae80d766d203b4f636b954cf03reed@google.com } 200172b8cb2320dddc6e006a2857746014e607e9e151bungeman@google.com // Odd to get here, as we expected CT to have returned true up front. 2002bcb42aecf1bdb9ae80d766d203b4f636b954cf03reed@google.com return glyphCount; 2003bcb42aecf1bdb9ae80d766d203b4f636b954cf03reed@google.com} 2004bcb42aecf1bdb9ae80d766d203b4f636b954cf03reed@google.com 2005bcb42aecf1bdb9ae80d766d203b4f636b954cf03reed@google.comint SkTypeface_Mac::onCountGlyphs() const { 20067fa2a65c0cfc714364490cb715171461143024e0reed@google.com return SkToInt(CTFontGetGlyphCount(fFontRef)); 2007bcb42aecf1bdb9ae80d766d203b4f636b954cf03reed@google.com} 2008bcb42aecf1bdb9ae80d766d203b4f636b954cf03reed@google.com 200995625dbcb6b2960732bc27ad0dd0fc4adbb4f7c0reed@google.com/////////////////////////////////////////////////////////////////////////////// 201095625dbcb6b2960732bc27ad0dd0fc4adbb4f7c0reed@google.com/////////////////////////////////////////////////////////////////////////////// 201195625dbcb6b2960732bc27ad0dd0fc4adbb4f7c0reed@google.com#if 1 201283787c55db37e382ae36231a7b9458991228c10areed@google.com 201383787c55db37e382ae36231a7b9458991228c10areed@google.comstatic bool find_desc_str(CTFontDescriptorRef desc, CFStringRef name, SkString* value) { 201483787c55db37e382ae36231a7b9458991228c10areed@google.com AutoCFRelease<CFStringRef> ref((CFStringRef)CTFontDescriptorCopyAttribute(desc, name)); 201583787c55db37e382ae36231a7b9458991228c10areed@google.com if (NULL == ref.get()) { 201683787c55db37e382ae36231a7b9458991228c10areed@google.com return false; 201783787c55db37e382ae36231a7b9458991228c10areed@google.com } 201883787c55db37e382ae36231a7b9458991228c10areed@google.com CFStringToSkString(ref, value); 201983787c55db37e382ae36231a7b9458991228c10areed@google.com return true; 202083787c55db37e382ae36231a7b9458991228c10areed@google.com} 202183787c55db37e382ae36231a7b9458991228c10areed@google.com 202283787c55db37e382ae36231a7b9458991228c10areed@google.comstatic bool find_dict_float(CFDictionaryRef dict, CFStringRef name, float* value) { 202383787c55db37e382ae36231a7b9458991228c10areed@google.com CFNumberRef num; 202483787c55db37e382ae36231a7b9458991228c10areed@google.com return CFDictionaryGetValueIfPresent(dict, name, (const void**)&num) 202583787c55db37e382ae36231a7b9458991228c10areed@google.com && CFNumberIsFloatType(num) 202683787c55db37e382ae36231a7b9458991228c10areed@google.com && CFNumberGetValue(num, kCFNumberFloatType, value); 202783787c55db37e382ae36231a7b9458991228c10areed@google.com} 202883787c55db37e382ae36231a7b9458991228c10areed@google.com 202995625dbcb6b2960732bc27ad0dd0fc4adbb4f7c0reed@google.com#include "SkFontMgr.h" 203095625dbcb6b2960732bc27ad0dd0fc4adbb4f7c0reed@google.com 203183787c55db37e382ae36231a7b9458991228c10areed@google.comstatic int unit_weight_to_fontstyle(float unit) { 203283787c55db37e382ae36231a7b9458991228c10areed@google.com float value; 203383787c55db37e382ae36231a7b9458991228c10areed@google.com if (unit < 0) { 203483787c55db37e382ae36231a7b9458991228c10areed@google.com value = 100 + (1 + unit) * 300; 203583787c55db37e382ae36231a7b9458991228c10areed@google.com } else { 203683787c55db37e382ae36231a7b9458991228c10areed@google.com value = 400 + unit * 500; 203783787c55db37e382ae36231a7b9458991228c10areed@google.com } 203883787c55db37e382ae36231a7b9458991228c10areed@google.com return sk_float_round2int(value); 203983787c55db37e382ae36231a7b9458991228c10areed@google.com} 204083787c55db37e382ae36231a7b9458991228c10areed@google.com 204183787c55db37e382ae36231a7b9458991228c10areed@google.comstatic int unit_width_to_fontstyle(float unit) { 204283787c55db37e382ae36231a7b9458991228c10areed@google.com float value; 204383787c55db37e382ae36231a7b9458991228c10areed@google.com if (unit < 0) { 204483787c55db37e382ae36231a7b9458991228c10areed@google.com value = 1 + (1 + unit) * 4; 204583787c55db37e382ae36231a7b9458991228c10areed@google.com } else { 204683787c55db37e382ae36231a7b9458991228c10areed@google.com value = 5 + unit * 4; 204783787c55db37e382ae36231a7b9458991228c10areed@google.com } 204883787c55db37e382ae36231a7b9458991228c10areed@google.com return sk_float_round2int(value); 204983787c55db37e382ae36231a7b9458991228c10areed@google.com} 205083787c55db37e382ae36231a7b9458991228c10areed@google.com 2051964988f0e93f4a559b7e41db53d70d0282527350reed@google.comstatic inline int sqr(int value) { 2052964988f0e93f4a559b7e41db53d70d0282527350reed@google.com SkASSERT(SkAbs32(value) < 0x7FFF); // check for overflow 2053964988f0e93f4a559b7e41db53d70d0282527350reed@google.com return value * value; 2054964988f0e93f4a559b7e41db53d70d0282527350reed@google.com} 2055964988f0e93f4a559b7e41db53d70d0282527350reed@google.com 2056964988f0e93f4a559b7e41db53d70d0282527350reed@google.com// We normalize each axis (weight, width, italic) to be base-900 2057964988f0e93f4a559b7e41db53d70d0282527350reed@google.comstatic int compute_metric(const SkFontStyle& a, const SkFontStyle& b) { 2058964988f0e93f4a559b7e41db53d70d0282527350reed@google.com return sqr(a.weight() - b.weight()) + 2059964988f0e93f4a559b7e41db53d70d0282527350reed@google.com sqr((a.width() - b.width()) * 100) + 2060964988f0e93f4a559b7e41db53d70d0282527350reed@google.com sqr((a.isItalic() != b.isItalic()) * 900); 2061964988f0e93f4a559b7e41db53d70d0282527350reed@google.com} 2062964988f0e93f4a559b7e41db53d70d0282527350reed@google.com 206383787c55db37e382ae36231a7b9458991228c10areed@google.comstatic SkFontStyle desc2fontstyle(CTFontDescriptorRef desc) { 206483787c55db37e382ae36231a7b9458991228c10areed@google.com AutoCFRelease<CFDictionaryRef> dict( 206583787c55db37e382ae36231a7b9458991228c10areed@google.com (CFDictionaryRef)CTFontDescriptorCopyAttribute(desc, 206683787c55db37e382ae36231a7b9458991228c10areed@google.com kCTFontTraitsAttribute)); 206783787c55db37e382ae36231a7b9458991228c10areed@google.com if (NULL == dict.get()) { 206883787c55db37e382ae36231a7b9458991228c10areed@google.com return SkFontStyle(); 206983787c55db37e382ae36231a7b9458991228c10areed@google.com } 207083787c55db37e382ae36231a7b9458991228c10areed@google.com 207183787c55db37e382ae36231a7b9458991228c10areed@google.com float weight, width, slant; 207283787c55db37e382ae36231a7b9458991228c10areed@google.com if (!find_dict_float(dict, kCTFontWeightTrait, &weight)) { 207383787c55db37e382ae36231a7b9458991228c10areed@google.com weight = 0; 207483787c55db37e382ae36231a7b9458991228c10areed@google.com } 207583787c55db37e382ae36231a7b9458991228c10areed@google.com if (!find_dict_float(dict, kCTFontWidthTrait, &width)) { 207683787c55db37e382ae36231a7b9458991228c10areed@google.com width = 0; 207783787c55db37e382ae36231a7b9458991228c10areed@google.com } 207883787c55db37e382ae36231a7b9458991228c10areed@google.com if (!find_dict_float(dict, kCTFontSlantTrait, &slant)) { 207983787c55db37e382ae36231a7b9458991228c10areed@google.com slant = 0; 208083787c55db37e382ae36231a7b9458991228c10areed@google.com } 208137cbc7fd014e3b35833523dbdbe3bc3ac52ecacdskia.committer@gmail.com 208283787c55db37e382ae36231a7b9458991228c10areed@google.com return SkFontStyle(unit_weight_to_fontstyle(weight), 208383787c55db37e382ae36231a7b9458991228c10areed@google.com unit_width_to_fontstyle(width), 208483787c55db37e382ae36231a7b9458991228c10areed@google.com slant ? SkFontStyle::kItalic_Slant 208583787c55db37e382ae36231a7b9458991228c10areed@google.com : SkFontStyle::kUpright_Slant); 208683787c55db37e382ae36231a7b9458991228c10areed@google.com} 208783787c55db37e382ae36231a7b9458991228c10areed@google.com 2088dea7ee04d31d0f269cdc8db49b9225fc937b9622reed@google.comstruct NameFontStyleRec { 2089dea7ee04d31d0f269cdc8db49b9225fc937b9622reed@google.com SkString fFamilyName; 2090dea7ee04d31d0f269cdc8db49b9225fc937b9622reed@google.com SkFontStyle fFontStyle; 2091dea7ee04d31d0f269cdc8db49b9225fc937b9622reed@google.com}; 2092dea7ee04d31d0f269cdc8db49b9225fc937b9622reed@google.com 2093dea7ee04d31d0f269cdc8db49b9225fc937b9622reed@google.comstatic bool nameFontStyleProc(SkTypeface* face, SkTypeface::Style, 2094dea7ee04d31d0f269cdc8db49b9225fc937b9622reed@google.com void* ctx) { 2095dea7ee04d31d0f269cdc8db49b9225fc937b9622reed@google.com SkTypeface_Mac* macFace = (SkTypeface_Mac*)face; 2096dea7ee04d31d0f269cdc8db49b9225fc937b9622reed@google.com const NameFontStyleRec* rec = (const NameFontStyleRec*)ctx; 2097dea7ee04d31d0f269cdc8db49b9225fc937b9622reed@google.com 2098dea7ee04d31d0f269cdc8db49b9225fc937b9622reed@google.com return macFace->fFontStyle == rec->fFontStyle && 2099dea7ee04d31d0f269cdc8db49b9225fc937b9622reed@google.com macFace->fName == rec->fFamilyName; 2100dea7ee04d31d0f269cdc8db49b9225fc937b9622reed@google.com} 2101dea7ee04d31d0f269cdc8db49b9225fc937b9622reed@google.com 2102ce8b3de6058eae07ddc2eed6f96701e009bb91ecreed@google.comstatic SkTypeface* createFromDesc(CFStringRef cfFamilyName, 2103ce8b3de6058eae07ddc2eed6f96701e009bb91ecreed@google.com CTFontDescriptorRef desc) { 2104dea7ee04d31d0f269cdc8db49b9225fc937b9622reed@google.com NameFontStyleRec rec; 2105dea7ee04d31d0f269cdc8db49b9225fc937b9622reed@google.com CFStringToSkString(cfFamilyName, &rec.fFamilyName); 2106dea7ee04d31d0f269cdc8db49b9225fc937b9622reed@google.com rec.fFontStyle = desc2fontstyle(desc); 2107dea7ee04d31d0f269cdc8db49b9225fc937b9622reed@google.com 2108dea7ee04d31d0f269cdc8db49b9225fc937b9622reed@google.com SkTypeface* face = SkTypefaceCache::FindByProcAndRef(nameFontStyleProc, 2109dea7ee04d31d0f269cdc8db49b9225fc937b9622reed@google.com &rec); 2110dea7ee04d31d0f269cdc8db49b9225fc937b9622reed@google.com if (face) { 2111dea7ee04d31d0f269cdc8db49b9225fc937b9622reed@google.com return face; 2112dea7ee04d31d0f269cdc8db49b9225fc937b9622reed@google.com } 2113dea7ee04d31d0f269cdc8db49b9225fc937b9622reed@google.com 211445dfe6bb55828b8e819933279edc815f2fd6229acommit-bot@chromium.org AutoCFRelease<CFDictionaryRef> fontFamilyNameDictionary( 211545dfe6bb55828b8e819933279edc815f2fd6229acommit-bot@chromium.org CFDictionaryCreate(kCFAllocatorDefault, 211645dfe6bb55828b8e819933279edc815f2fd6229acommit-bot@chromium.org (const void**)&kCTFontFamilyNameAttribute, (const void**)&cfFamilyName, 211745dfe6bb55828b8e819933279edc815f2fd6229acommit-bot@chromium.org 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks)); 211845dfe6bb55828b8e819933279edc815f2fd6229acommit-bot@chromium.org AutoCFRelease<CTFontDescriptorRef> fontDescriptor( 211945dfe6bb55828b8e819933279edc815f2fd6229acommit-bot@chromium.org CTFontDescriptorCreateWithAttributes(fontFamilyNameDictionary)); 212045dfe6bb55828b8e819933279edc815f2fd6229acommit-bot@chromium.org AutoCFRelease<CTFontRef> ctNamed(CTFontCreateWithFontDescriptor(fontDescriptor, 0, NULL)); 2121ce8b3de6058eae07ddc2eed6f96701e009bb91ecreed@google.com CTFontRef ctFont = CTFontCreateCopyWithAttributes(ctNamed, 1, NULL, desc); 2122ce8b3de6058eae07ddc2eed6f96701e009bb91ecreed@google.com if (NULL == ctFont) { 2123ce8b3de6058eae07ddc2eed6f96701e009bb91ecreed@google.com return NULL; 2124ce8b3de6058eae07ddc2eed6f96701e009bb91ecreed@google.com } 212537cbc7fd014e3b35833523dbdbe3bc3ac52ecacdskia.committer@gmail.com 2126ce8b3de6058eae07ddc2eed6f96701e009bb91ecreed@google.com SkString str; 2127ce8b3de6058eae07ddc2eed6f96701e009bb91ecreed@google.com CFStringToSkString(cfFamilyName, &str); 212837cbc7fd014e3b35833523dbdbe3bc3ac52ecacdskia.committer@gmail.com 2129ce8b3de6058eae07ddc2eed6f96701e009bb91ecreed@google.com bool isFixedPitch; 2130ce8b3de6058eae07ddc2eed6f96701e009bb91ecreed@google.com (void)computeStyleBits(ctFont, &isFixedPitch); 2131ce8b3de6058eae07ddc2eed6f96701e009bb91ecreed@google.com SkFontID fontID = CTFontRef_to_SkFontID(ctFont); 213237cbc7fd014e3b35833523dbdbe3bc3ac52ecacdskia.committer@gmail.com 2133dea7ee04d31d0f269cdc8db49b9225fc937b9622reed@google.com face = SkNEW_ARGS(SkTypeface_Mac, (rec.fFontStyle, fontID, isFixedPitch, 213426337e970201cae39f44b49546b8d9b0bc5e5c98caseq ctFont, str.c_str(), false)); 2135dea7ee04d31d0f269cdc8db49b9225fc937b9622reed@google.com SkTypefaceCache::Add(face, face->style()); 2136dea7ee04d31d0f269cdc8db49b9225fc937b9622reed@google.com return face; 2137ce8b3de6058eae07ddc2eed6f96701e009bb91ecreed@google.com} 2138ce8b3de6058eae07ddc2eed6f96701e009bb91ecreed@google.com 213983787c55db37e382ae36231a7b9458991228c10areed@google.comclass SkFontStyleSet_Mac : public SkFontStyleSet { 214083787c55db37e382ae36231a7b9458991228c10areed@google.compublic: 214183787c55db37e382ae36231a7b9458991228c10areed@google.com SkFontStyleSet_Mac(CFStringRef familyName, CTFontDescriptorRef desc) 214283787c55db37e382ae36231a7b9458991228c10areed@google.com : fArray(CTFontDescriptorCreateMatchingFontDescriptors(desc, NULL)) 2143dea7ee04d31d0f269cdc8db49b9225fc937b9622reed@google.com , fFamilyName(familyName) 2144dea7ee04d31d0f269cdc8db49b9225fc937b9622reed@google.com , fCount(0) { 214583787c55db37e382ae36231a7b9458991228c10areed@google.com CFRetain(familyName); 2146dea7ee04d31d0f269cdc8db49b9225fc937b9622reed@google.com if (NULL == fArray) { 2147dea7ee04d31d0f269cdc8db49b9225fc937b9622reed@google.com fArray = CFArrayCreate(NULL, NULL, 0, NULL); 2148dea7ee04d31d0f269cdc8db49b9225fc937b9622reed@google.com } 21497fa2a65c0cfc714364490cb715171461143024e0reed@google.com fCount = SkToInt(CFArrayGetCount(fArray)); 215083787c55db37e382ae36231a7b9458991228c10areed@google.com } 215137cbc7fd014e3b35833523dbdbe3bc3ac52ecacdskia.committer@gmail.com 215283787c55db37e382ae36231a7b9458991228c10areed@google.com virtual ~SkFontStyleSet_Mac() { 2153dea7ee04d31d0f269cdc8db49b9225fc937b9622reed@google.com CFRelease(fArray); 215483787c55db37e382ae36231a7b9458991228c10areed@google.com CFRelease(fFamilyName); 215583787c55db37e382ae36231a7b9458991228c10areed@google.com } 215683787c55db37e382ae36231a7b9458991228c10areed@google.com 215783787c55db37e382ae36231a7b9458991228c10areed@google.com virtual int count() SK_OVERRIDE { 2158dea7ee04d31d0f269cdc8db49b9225fc937b9622reed@google.com return fCount; 215983787c55db37e382ae36231a7b9458991228c10areed@google.com } 216083787c55db37e382ae36231a7b9458991228c10areed@google.com 216183787c55db37e382ae36231a7b9458991228c10areed@google.com virtual void getStyle(int index, SkFontStyle* style, 216283787c55db37e382ae36231a7b9458991228c10areed@google.com SkString* name) SK_OVERRIDE { 2163dea7ee04d31d0f269cdc8db49b9225fc937b9622reed@google.com SkASSERT((unsigned)index < (unsigned)fCount); 216483787c55db37e382ae36231a7b9458991228c10areed@google.com CTFontDescriptorRef desc = (CTFontDescriptorRef)CFArrayGetValueAtIndex(fArray, index); 216583787c55db37e382ae36231a7b9458991228c10areed@google.com if (style) { 216683787c55db37e382ae36231a7b9458991228c10areed@google.com *style = desc2fontstyle(desc); 216783787c55db37e382ae36231a7b9458991228c10areed@google.com } 216883787c55db37e382ae36231a7b9458991228c10areed@google.com if (name) { 216983787c55db37e382ae36231a7b9458991228c10areed@google.com if (!find_desc_str(desc, kCTFontStyleNameAttribute, name)) { 217083787c55db37e382ae36231a7b9458991228c10areed@google.com name->reset(); 217183787c55db37e382ae36231a7b9458991228c10areed@google.com } 217283787c55db37e382ae36231a7b9458991228c10areed@google.com } 217383787c55db37e382ae36231a7b9458991228c10areed@google.com } 217483787c55db37e382ae36231a7b9458991228c10areed@google.com 217583787c55db37e382ae36231a7b9458991228c10areed@google.com virtual SkTypeface* createTypeface(int index) SK_OVERRIDE { 217683787c55db37e382ae36231a7b9458991228c10areed@google.com SkASSERT((unsigned)index < (unsigned)CFArrayGetCount(fArray)); 217783787c55db37e382ae36231a7b9458991228c10areed@google.com CTFontDescriptorRef desc = (CTFontDescriptorRef)CFArrayGetValueAtIndex(fArray, index); 217837cbc7fd014e3b35833523dbdbe3bc3ac52ecacdskia.committer@gmail.com 217983787c55db37e382ae36231a7b9458991228c10areed@google.com return createFromDesc(fFamilyName, desc); 218083787c55db37e382ae36231a7b9458991228c10areed@google.com } 218137cbc7fd014e3b35833523dbdbe3bc3ac52ecacdskia.committer@gmail.com 2182964988f0e93f4a559b7e41db53d70d0282527350reed@google.com virtual SkTypeface* matchStyle(const SkFontStyle& pattern) SK_OVERRIDE { 2183964988f0e93f4a559b7e41db53d70d0282527350reed@google.com if (0 == fCount) { 2184964988f0e93f4a559b7e41db53d70d0282527350reed@google.com return NULL; 2185964988f0e93f4a559b7e41db53d70d0282527350reed@google.com } 2186964988f0e93f4a559b7e41db53d70d0282527350reed@google.com return createFromDesc(fFamilyName, findMatchingDesc(pattern)); 2187964988f0e93f4a559b7e41db53d70d0282527350reed@google.com } 2188964988f0e93f4a559b7e41db53d70d0282527350reed@google.com 218983787c55db37e382ae36231a7b9458991228c10areed@google.comprivate: 219083787c55db37e382ae36231a7b9458991228c10areed@google.com CFArrayRef fArray; 219183787c55db37e382ae36231a7b9458991228c10areed@google.com CFStringRef fFamilyName; 2192dea7ee04d31d0f269cdc8db49b9225fc937b9622reed@google.com int fCount; 2193964988f0e93f4a559b7e41db53d70d0282527350reed@google.com 2194964988f0e93f4a559b7e41db53d70d0282527350reed@google.com CTFontDescriptorRef findMatchingDesc(const SkFontStyle& pattern) const { 2195964988f0e93f4a559b7e41db53d70d0282527350reed@google.com int bestMetric = SK_MaxS32; 2196964988f0e93f4a559b7e41db53d70d0282527350reed@google.com CTFontDescriptorRef bestDesc = NULL; 2197d55846d100bb09448b398b41798bd4ab100a753askia.committer@gmail.com 2198964988f0e93f4a559b7e41db53d70d0282527350reed@google.com for (int i = 0; i < fCount; ++i) { 2199964988f0e93f4a559b7e41db53d70d0282527350reed@google.com CTFontDescriptorRef desc = (CTFontDescriptorRef)CFArrayGetValueAtIndex(fArray, i); 2200964988f0e93f4a559b7e41db53d70d0282527350reed@google.com int metric = compute_metric(pattern, desc2fontstyle(desc)); 2201964988f0e93f4a559b7e41db53d70d0282527350reed@google.com if (0 == metric) { 2202964988f0e93f4a559b7e41db53d70d0282527350reed@google.com return desc; 2203964988f0e93f4a559b7e41db53d70d0282527350reed@google.com } 2204964988f0e93f4a559b7e41db53d70d0282527350reed@google.com if (metric < bestMetric) { 2205964988f0e93f4a559b7e41db53d70d0282527350reed@google.com bestMetric = metric; 2206964988f0e93f4a559b7e41db53d70d0282527350reed@google.com bestDesc = desc; 2207964988f0e93f4a559b7e41db53d70d0282527350reed@google.com } 2208964988f0e93f4a559b7e41db53d70d0282527350reed@google.com } 2209964988f0e93f4a559b7e41db53d70d0282527350reed@google.com SkASSERT(bestDesc); 2210964988f0e93f4a559b7e41db53d70d0282527350reed@google.com return bestDesc; 2211964988f0e93f4a559b7e41db53d70d0282527350reed@google.com } 221283787c55db37e382ae36231a7b9458991228c10areed@google.com}; 221383787c55db37e382ae36231a7b9458991228c10areed@google.com 221495625dbcb6b2960732bc27ad0dd0fc4adbb4f7c0reed@google.comclass SkFontMgr_Mac : public SkFontMgr { 221583787c55db37e382ae36231a7b9458991228c10areed@google.com CFArrayRef fNames; 2216967dee32ef540b7c0fed6d0cd518d42b9b345c78commit-bot@chromium.org int fCount; 221783787c55db37e382ae36231a7b9458991228c10areed@google.com 221883787c55db37e382ae36231a7b9458991228c10areed@google.com CFStringRef stringAt(int index) const { 221983787c55db37e382ae36231a7b9458991228c10areed@google.com SkASSERT((unsigned)index < (unsigned)fCount); 222083787c55db37e382ae36231a7b9458991228c10areed@google.com return (CFStringRef)CFArrayGetValueAtIndex(fNames, index); 222183787c55db37e382ae36231a7b9458991228c10areed@google.com } 222283787c55db37e382ae36231a7b9458991228c10areed@google.com 2223964988f0e93f4a559b7e41db53d70d0282527350reed@google.com static SkFontStyleSet* CreateSet(CFStringRef cfFamilyName) { 2224964988f0e93f4a559b7e41db53d70d0282527350reed@google.com AutoCFRelease<CFMutableDictionaryRef> cfAttr( 2225964988f0e93f4a559b7e41db53d70d0282527350reed@google.com CFDictionaryCreateMutable(kCFAllocatorDefault, 0, 2226964988f0e93f4a559b7e41db53d70d0282527350reed@google.com &kCFTypeDictionaryKeyCallBacks, 2227964988f0e93f4a559b7e41db53d70d0282527350reed@google.com &kCFTypeDictionaryValueCallBacks)); 2228d55846d100bb09448b398b41798bd4ab100a753askia.committer@gmail.com 2229964988f0e93f4a559b7e41db53d70d0282527350reed@google.com CFDictionaryAddValue(cfAttr, kCTFontFamilyNameAttribute, cfFamilyName); 2230d55846d100bb09448b398b41798bd4ab100a753askia.committer@gmail.com 2231964988f0e93f4a559b7e41db53d70d0282527350reed@google.com AutoCFRelease<CTFontDescriptorRef> desc( 2232964988f0e93f4a559b7e41db53d70d0282527350reed@google.com CTFontDescriptorCreateWithAttributes(cfAttr)); 2233964988f0e93f4a559b7e41db53d70d0282527350reed@google.com return SkNEW_ARGS(SkFontStyleSet_Mac, (cfFamilyName, desc)); 2234964988f0e93f4a559b7e41db53d70d0282527350reed@google.com } 2235d55846d100bb09448b398b41798bd4ab100a753askia.committer@gmail.com 223695625dbcb6b2960732bc27ad0dd0fc4adbb4f7c0reed@google.compublic: 2237967dee32ef540b7c0fed6d0cd518d42b9b345c78commit-bot@chromium.org SkFontMgr_Mac() 2238967dee32ef540b7c0fed6d0cd518d42b9b345c78commit-bot@chromium.org : fNames(SkCTFontManagerCopyAvailableFontFamilyNames()) 2239967dee32ef540b7c0fed6d0cd518d42b9b345c78commit-bot@chromium.org , fCount(fNames ? SkToInt(CFArrayGetCount(fNames)) : 0) {} 224083787c55db37e382ae36231a7b9458991228c10areed@google.com 224183787c55db37e382ae36231a7b9458991228c10areed@google.com virtual ~SkFontMgr_Mac() { 224283787c55db37e382ae36231a7b9458991228c10areed@google.com CFSafeRelease(fNames); 224383787c55db37e382ae36231a7b9458991228c10areed@google.com } 224495625dbcb6b2960732bc27ad0dd0fc4adbb4f7c0reed@google.com 224595625dbcb6b2960732bc27ad0dd0fc4adbb4f7c0reed@google.comprotected: 2246967dee32ef540b7c0fed6d0cd518d42b9b345c78commit-bot@chromium.org virtual int onCountFamilies() const SK_OVERRIDE { 224783787c55db37e382ae36231a7b9458991228c10areed@google.com return fCount; 224895625dbcb6b2960732bc27ad0dd0fc4adbb4f7c0reed@google.com } 224995625dbcb6b2960732bc27ad0dd0fc4adbb4f7c0reed@google.com 2250967dee32ef540b7c0fed6d0cd518d42b9b345c78commit-bot@chromium.org virtual void onGetFamilyName(int index, SkString* familyName) const SK_OVERRIDE { 225183787c55db37e382ae36231a7b9458991228c10areed@google.com if ((unsigned)index < (unsigned)fCount) { 225283787c55db37e382ae36231a7b9458991228c10areed@google.com CFStringToSkString(this->stringAt(index), familyName); 225383787c55db37e382ae36231a7b9458991228c10areed@google.com } else { 225483787c55db37e382ae36231a7b9458991228c10areed@google.com familyName->reset(); 225583787c55db37e382ae36231a7b9458991228c10areed@google.com } 225695625dbcb6b2960732bc27ad0dd0fc4adbb4f7c0reed@google.com } 225795625dbcb6b2960732bc27ad0dd0fc4adbb4f7c0reed@google.com 2258967dee32ef540b7c0fed6d0cd518d42b9b345c78commit-bot@chromium.org virtual SkFontStyleSet* onCreateStyleSet(int index) const SK_OVERRIDE { 225983787c55db37e382ae36231a7b9458991228c10areed@google.com if ((unsigned)index >= (unsigned)fCount) { 226083787c55db37e382ae36231a7b9458991228c10areed@google.com return NULL; 226183787c55db37e382ae36231a7b9458991228c10areed@google.com } 2262964988f0e93f4a559b7e41db53d70d0282527350reed@google.com return CreateSet(this->stringAt(index)); 226395625dbcb6b2960732bc27ad0dd0fc4adbb4f7c0reed@google.com } 2264d55846d100bb09448b398b41798bd4ab100a753askia.committer@gmail.com 2265967dee32ef540b7c0fed6d0cd518d42b9b345c78commit-bot@chromium.org virtual SkFontStyleSet* onMatchFamily(const char familyName[]) const SK_OVERRIDE { 2266964988f0e93f4a559b7e41db53d70d0282527350reed@google.com AutoCFRelease<CFStringRef> cfName(make_CFString(familyName)); 2267964988f0e93f4a559b7e41db53d70d0282527350reed@google.com return CreateSet(cfName); 2268964988f0e93f4a559b7e41db53d70d0282527350reed@google.com } 2269d55846d100bb09448b398b41798bd4ab100a753askia.committer@gmail.com 227095625dbcb6b2960732bc27ad0dd0fc4adbb4f7c0reed@google.com virtual SkTypeface* onMatchFamilyStyle(const char familyName[], 2271967dee32ef540b7c0fed6d0cd518d42b9b345c78commit-bot@chromium.org const SkFontStyle&) const SK_OVERRIDE { 227295625dbcb6b2960732bc27ad0dd0fc4adbb4f7c0reed@google.com return NULL; 227395625dbcb6b2960732bc27ad0dd0fc4adbb4f7c0reed@google.com } 2274e60ed08a3568b5e253dfb5dec2b52d13a16fff1cskia.committer@gmail.com 227595625dbcb6b2960732bc27ad0dd0fc4adbb4f7c0reed@google.com virtual SkTypeface* onMatchFaceStyle(const SkTypeface* familyMember, 2276967dee32ef540b7c0fed6d0cd518d42b9b345c78commit-bot@chromium.org const SkFontStyle&) const SK_OVERRIDE { 227795625dbcb6b2960732bc27ad0dd0fc4adbb4f7c0reed@google.com return NULL; 227895625dbcb6b2960732bc27ad0dd0fc4adbb4f7c0reed@google.com } 2279e60ed08a3568b5e253dfb5dec2b52d13a16fff1cskia.committer@gmail.com 228095625dbcb6b2960732bc27ad0dd0fc4adbb4f7c0reed@google.com virtual SkTypeface* onCreateFromData(SkData* data, 2281967dee32ef540b7c0fed6d0cd518d42b9b345c78commit-bot@chromium.org int ttcIndex) const SK_OVERRIDE { 228295625dbcb6b2960732bc27ad0dd0fc4adbb4f7c0reed@google.com AutoCFRelease<CGDataProviderRef> pr(SkCreateDataProviderFromData(data)); 228395625dbcb6b2960732bc27ad0dd0fc4adbb4f7c0reed@google.com if (NULL == pr) { 228495625dbcb6b2960732bc27ad0dd0fc4adbb4f7c0reed@google.com return NULL; 228595625dbcb6b2960732bc27ad0dd0fc4adbb4f7c0reed@google.com } 228695625dbcb6b2960732bc27ad0dd0fc4adbb4f7c0reed@google.com return create_from_dataProvider(pr); 228795625dbcb6b2960732bc27ad0dd0fc4adbb4f7c0reed@google.com } 228895625dbcb6b2960732bc27ad0dd0fc4adbb4f7c0reed@google.com 228995625dbcb6b2960732bc27ad0dd0fc4adbb4f7c0reed@google.com virtual SkTypeface* onCreateFromStream(SkStream* stream, 2290967dee32ef540b7c0fed6d0cd518d42b9b345c78commit-bot@chromium.org int ttcIndex) const SK_OVERRIDE { 229195625dbcb6b2960732bc27ad0dd0fc4adbb4f7c0reed@google.com AutoCFRelease<CGDataProviderRef> pr(SkCreateDataProviderFromStream(stream)); 229295625dbcb6b2960732bc27ad0dd0fc4adbb4f7c0reed@google.com if (NULL == pr) { 229395625dbcb6b2960732bc27ad0dd0fc4adbb4f7c0reed@google.com return NULL; 229495625dbcb6b2960732bc27ad0dd0fc4adbb4f7c0reed@google.com } 229595625dbcb6b2960732bc27ad0dd0fc4adbb4f7c0reed@google.com return create_from_dataProvider(pr); 229695625dbcb6b2960732bc27ad0dd0fc4adbb4f7c0reed@google.com } 229795625dbcb6b2960732bc27ad0dd0fc4adbb4f7c0reed@google.com 229895625dbcb6b2960732bc27ad0dd0fc4adbb4f7c0reed@google.com virtual SkTypeface* onCreateFromFile(const char path[], 2299967dee32ef540b7c0fed6d0cd518d42b9b345c78commit-bot@chromium.org int ttcIndex) const SK_OVERRIDE { 230095625dbcb6b2960732bc27ad0dd0fc4adbb4f7c0reed@google.com AutoCFRelease<CGDataProviderRef> pr(CGDataProviderCreateWithFilename(path)); 230195625dbcb6b2960732bc27ad0dd0fc4adbb4f7c0reed@google.com if (NULL == pr) { 230295625dbcb6b2960732bc27ad0dd0fc4adbb4f7c0reed@google.com return NULL; 230395625dbcb6b2960732bc27ad0dd0fc4adbb4f7c0reed@google.com } 230495625dbcb6b2960732bc27ad0dd0fc4adbb4f7c0reed@google.com return create_from_dataProvider(pr); 230595625dbcb6b2960732bc27ad0dd0fc4adbb4f7c0reed@google.com } 230676015b09536c664bd59b370be7691d4b69553d95skia.committer@gmail.com 23077fdcd444a1bd6a2f173c141e09e7ad9c11730ad2reed@google.com virtual SkTypeface* onLegacyCreateTypeface(const char familyName[], 2308967dee32ef540b7c0fed6d0cd518d42b9b345c78commit-bot@chromium.org unsigned styleBits) const SK_OVERRIDE { 23097fdcd444a1bd6a2f173c141e09e7ad9c11730ad2reed@google.com return create_typeface(NULL, familyName, (SkTypeface::Style)styleBits); 23107fdcd444a1bd6a2f173c141e09e7ad9c11730ad2reed@google.com } 231195625dbcb6b2960732bc27ad0dd0fc4adbb4f7c0reed@google.com}; 231295625dbcb6b2960732bc27ad0dd0fc4adbb4f7c0reed@google.com 23137fdcd444a1bd6a2f173c141e09e7ad9c11730ad2reed@google.com/////////////////////////////////////////////////////////////////////////////// 23147fdcd444a1bd6a2f173c141e09e7ad9c11730ad2reed@google.com 231595625dbcb6b2960732bc27ad0dd0fc4adbb4f7c0reed@google.comSkFontMgr* SkFontMgr::Factory() { 231695625dbcb6b2960732bc27ad0dd0fc4adbb4f7c0reed@google.com return SkNEW(SkFontMgr_Mac); 231795625dbcb6b2960732bc27ad0dd0fc4adbb4f7c0reed@google.com} 231895625dbcb6b2960732bc27ad0dd0fc4adbb4f7c0reed@google.com#endif 2319