1fe755b47052bc5bdf8a32e1e21f8dd81ba44d2e8bungeman@google.com 2ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.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 9ba9354b9d4de62988cc2a56c0760fd5e52da3679commit-bot@chromium.org#include "SkAdvancedTypefaceMetrics.h" 108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkBitmap.h" 118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkCanvas.h" 122a22e10ab2946c5590cd2a258427ce3ccfca9bfavandebo@chromium.org#include "SkColorPriv.h" 138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkDescriptor.h" 148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkFDot6.h" 153aacb419ca50c86341756624e7b031bf29b8a47cbungeman@google.com#include "SkFloatingPoint.h" 168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkFontHost.h" 17c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.com#include "SkFontHost_FreeType_common.h" 18bbe50131413098bffed9186660c41f047d881596bungeman@google.com#include "SkGlyph.h" 198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkMask.h" 2097efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com#include "SkMaskGamma.h" 21d3fbd34099a530b5415c95b1f2f8149ac417b9b3bungeman@google.com#include "SkMatrix22.h" 22a980269c2498836101146adc729ef780fb89824ebungeman@google.com#include "SkOTUtils.h" 23ba9354b9d4de62988cc2a56c0760fd5e52da3679commit-bot@chromium.org#include "SkOnce.h" 242a22e10ab2946c5590cd2a258427ce3ccfca9bfavandebo@chromium.org#include "SkScalerContext.h" 258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkStream.h" 268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkString.h" 278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkTemplates.h" 282a22e10ab2946c5590cd2a258427ce3ccfca9bfavandebo@chromium.org#include "SkThread.h" 298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 30fd668cfffe3fdcfbf6e0b858343a62818d337590bungeman@google.com#if defined(SK_CAN_USE_DLOPEN) 31fd668cfffe3fdcfbf6e0b858343a62818d337590bungeman@google.com#include <dlfcn.h> 32fd668cfffe3fdcfbf6e0b858343a62818d337590bungeman@google.com#endif 338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include <ft2build.h> 348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include FT_FREETYPE_H 358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include FT_OUTLINE_H 368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include FT_SIZES_H 37cc3096ba6d437b29f1cbd34c237607419cbed72bagl@chromium.org#include FT_TRUETYPE_TABLES_H 382a22e10ab2946c5590cd2a258427ce3ccfca9bfavandebo@chromium.org#include FT_TYPE1_TABLES_H 39e76073bfcd30f8742a377d636bbad84183b275ecagl@chromium.org#include FT_BITMAP_H 4036bb697683f63f0ed8a37d7a7ef28c134dff856cagl@chromium.org// In the past, FT_GlyphSlot_Own_Bitmap was defined in this header file. 4136bb697683f63f0ed8a37d7a7ef28c134dff856cagl@chromium.org#include FT_SYNTHESIS_H 422a22e10ab2946c5590cd2a258427ce3ccfca9bfavandebo@chromium.org#include FT_XFREE86_H 435070d79edd54450f2980f7ff1e2d04762e89aa0bepoger@google.com#ifdef FT_LCD_FILTER_H 44309485b7b51f4cae4c0361ab4da00fe9cc89515cagl@chromium.org#include FT_LCD_FILTER_H 455070d79edd54450f2980f7ff1e2d04762e89aa0bepoger@google.com#endif 46309485b7b51f4cae4c0361ab4da00fe9cc89515cagl@chromium.org 47d3fbd34099a530b5415c95b1f2f8149ac417b9b3bungeman@google.com// Defined in FreeType 2.3.8 and later. 48d3fbd34099a530b5415c95b1f2f8149ac417b9b3bungeman@google.com// This is a silly build time check, we would need a runtime check if we really cared. 498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifdef FT_ADVANCES_H 508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include FT_ADVANCES_H 518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif 528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 53cc3096ba6d437b29f1cbd34c237607419cbed72bagl@chromium.org#if 0 54cc3096ba6d437b29f1cbd34c237607419cbed72bagl@chromium.org// Also include the files by name for build tools which require this. 55cc3096ba6d437b29f1cbd34c237607419cbed72bagl@chromium.org#include <freetype/freetype.h> 56cc3096ba6d437b29f1cbd34c237607419cbed72bagl@chromium.org#include <freetype/ftoutln.h> 57cc3096ba6d437b29f1cbd34c237607419cbed72bagl@chromium.org#include <freetype/ftsizes.h> 58cc3096ba6d437b29f1cbd34c237607419cbed72bagl@chromium.org#include <freetype/tttables.h> 59cc3096ba6d437b29f1cbd34c237607419cbed72bagl@chromium.org#include <freetype/ftadvanc.h> 60309485b7b51f4cae4c0361ab4da00fe9cc89515cagl@chromium.org#include <freetype/ftlcdfil.h> 61e76073bfcd30f8742a377d636bbad84183b275ecagl@chromium.org#include <freetype/ftbitmap.h> 6236bb697683f63f0ed8a37d7a7ef28c134dff856cagl@chromium.org#include <freetype/ftsynth.h> 63cc3096ba6d437b29f1cbd34c237607419cbed72bagl@chromium.org#endif 64cc3096ba6d437b29f1cbd34c237607419cbed72bagl@chromium.org 65c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com// FT_LOAD_COLOR and the corresponding FT_Pixel_Mode::FT_PIXEL_MODE_BGRA 66c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com// were introduced in FreeType 2.5.0. 67c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com// The following may be removed once FreeType 2.5.0 is required to build. 68c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com#ifndef FT_LOAD_COLOR 69c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com# define FT_LOAD_COLOR ( 1L << 20 ) 70c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com# define FT_PIXEL_MODE_BGRA 7 71c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com#endif 72c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com 73c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com// FT_HAS_COLOR and the corresponding FT_FACE_FLAG_COLOR 74c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com// were introduced in FreeType 2.5.1 75c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com// The following may be removed once FreeType 2.5.1 is required to build. 76c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com#ifndef FT_HAS_COLOR 77c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com# define FT_HAS_COLOR(face) false 78c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com#endif 79c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com 808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//#define ENABLE_GLYPH_SPEW // for tracing calls 818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//#define DUMP_STRIKE_CREATION 828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 831ac8350821f5343333e48f000df5b5106b6f7497reed@google.com//#define SK_GAMMA_APPLY_TO_A8 841ac8350821f5343333e48f000df5b5106b6f7497reed@google.com 856f72d1eacd66d2a9c0059962a75c0ca6a99ff98evandebo@chromium.orgusing namespace skia_advanced_typeface_metrics_utils; 866f72d1eacd66d2a9c0059962a75c0ca6a99ff98evandebo@chromium.org 87effc5016f040945a53ab0ea47f9ea02404c17805reed@google.comstatic bool isLCD(const SkScalerContext::Rec& rec) { 88effc5016f040945a53ab0ea47f9ea02404c17805reed@google.com switch (rec.fMaskFormat) { 89effc5016f040945a53ab0ea47f9ea02404c17805reed@google.com case SkMask::kLCD16_Format: 90effc5016f040945a53ab0ea47f9ea02404c17805reed@google.com case SkMask::kLCD32_Format: 91effc5016f040945a53ab0ea47f9ea02404c17805reed@google.com return true; 92effc5016f040945a53ab0ea47f9ea02404c17805reed@google.com default: 93effc5016f040945a53ab0ea47f9ea02404c17805reed@google.com return false; 94effc5016f040945a53ab0ea47f9ea02404c17805reed@google.com } 95effc5016f040945a53ab0ea47f9ea02404c17805reed@google.com} 96effc5016f040945a53ab0ea47f9ea02404c17805reed@google.com 978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com////////////////////////////////////////////////////////////////////////// 988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstruct SkFaceRec; 1008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1011771cbf43d9a1334e3d870c635b4215bb888dd98digit@google.comSK_DECLARE_STATIC_MUTEX(gFTMutex); 1028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic int gFTCount; 1038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic FT_Library gFTLibrary; 1048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic SkFaceRec* gFaceRecHead; 105f18d8760019ae999c63d1f0b0e6e52815202b23bagl@chromium.orgstatic bool gLCDSupportValid; // true iff |gLCDSupport| has been set. 106f18d8760019ae999c63d1f0b0e6e52815202b23bagl@chromium.orgstatic bool gLCDSupport; // true iff LCD is supported by the runtime. 107a1c32563cf218c9eddc79fad303eb4185c774224reed@google.comstatic int gLCDExtra; // number of extra pixels for filtering. 1088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 10962566f361f44bfaefcef69c2a6635aabdc44361bbungeman@google.com///////////////////////////////////////////////////////////////////////// 11062566f361f44bfaefcef69c2a6635aabdc44361bbungeman@google.com 111fd668cfffe3fdcfbf6e0b858343a62818d337590bungeman@google.com// FT_Library_SetLcdFilterWeights was introduced in FreeType 2.4.0. 112fd668cfffe3fdcfbf6e0b858343a62818d337590bungeman@google.com// The following platforms provide FreeType of at least 2.4.0. 113fd668cfffe3fdcfbf6e0b858343a62818d337590bungeman@google.com// Ubuntu >= 11.04 (previous deprecated April 2013) 114fd668cfffe3fdcfbf6e0b858343a62818d337590bungeman@google.com// Debian >= 6.0 (good) 115fd668cfffe3fdcfbf6e0b858343a62818d337590bungeman@google.com// OpenSuse >= 11.4 (previous deprecated January 2012 / Nov 2013 for Evergreen 11.2) 116fd668cfffe3fdcfbf6e0b858343a62818d337590bungeman@google.com// Fedora >= 14 (good) 117fd668cfffe3fdcfbf6e0b858343a62818d337590bungeman@google.com// Android >= Gingerbread (good) 118fd668cfffe3fdcfbf6e0b858343a62818d337590bungeman@google.comtypedef FT_Error (*FT_Library_SetLcdFilterWeightsProc)(FT_Library, unsigned char*); 119fd668cfffe3fdcfbf6e0b858343a62818d337590bungeman@google.com 12094bc60f9864094edbfb787b09c963d8818c8962fscroggo@google.com// Caller must lock gFTMutex before calling this function. 121fd668cfffe3fdcfbf6e0b858343a62818d337590bungeman@google.comstatic bool InitFreetype() { 122309485b7b51f4cae4c0361ab4da00fe9cc89515cagl@chromium.org FT_Error err = FT_Init_FreeType(&gFTLibrary); 123ea2333de1e93da38045111560295ef825be99956reed@google.com if (err) { 124309485b7b51f4cae4c0361ab4da00fe9cc89515cagl@chromium.org return false; 125ea2333de1e93da38045111560295ef825be99956reed@google.com } 126309485b7b51f4cae4c0361ab4da00fe9cc89515cagl@chromium.org 127fd668cfffe3fdcfbf6e0b858343a62818d337590bungeman@google.com // Setup LCD filtering. This reduces color fringes for LCD smoothed glyphs. 128b371ed1784fcc594131abb7fc2f76b0abd20ca9eepoger@google.com#ifdef FT_LCD_FILTER_H 12962566f361f44bfaefcef69c2a6635aabdc44361bbungeman@google.com // Use default { 0x10, 0x40, 0x70, 0x40, 0x10 }, as it adds up to 0x110, simulating ink spread. 13062566f361f44bfaefcef69c2a6635aabdc44361bbungeman@google.com // SetLcdFilter must be called before SetLcdFilterWeights. 13162566f361f44bfaefcef69c2a6635aabdc44361bbungeman@google.com err = FT_Library_SetLcdFilter(gFTLibrary, FT_LCD_FILTER_DEFAULT); 132fd668cfffe3fdcfbf6e0b858343a62818d337590bungeman@google.com if (0 == err) { 133fd668cfffe3fdcfbf6e0b858343a62818d337590bungeman@google.com gLCDSupport = true; 134fd668cfffe3fdcfbf6e0b858343a62818d337590bungeman@google.com gLCDExtra = 2; //Using a filter adds one full pixel to each side. 135fd668cfffe3fdcfbf6e0b858343a62818d337590bungeman@google.com 13662566f361f44bfaefcef69c2a6635aabdc44361bbungeman@google.com#ifdef SK_FONTHOST_FREETYPE_USE_NORMAL_LCD_FILTER 13762566f361f44bfaefcef69c2a6635aabdc44361bbungeman@google.com // This also adds to 0x110 simulating ink spread, but provides better results than default. 13862566f361f44bfaefcef69c2a6635aabdc44361bbungeman@google.com static unsigned char gGaussianLikeHeavyWeights[] = { 0x1A, 0x43, 0x56, 0x43, 0x1A, }; 139fd668cfffe3fdcfbf6e0b858343a62818d337590bungeman@google.com 140fd668cfffe3fdcfbf6e0b858343a62818d337590bungeman@google.com#if defined(SK_FONTHOST_FREETYPE_RUNTIME_VERSION) && \ 141fd668cfffe3fdcfbf6e0b858343a62818d337590bungeman@google.com SK_FONTHOST_FREETYPE_RUNTIME_VERSION > 0x020400 14262566f361f44bfaefcef69c2a6635aabdc44361bbungeman@google.com err = FT_Library_SetLcdFilterWeights(gFTLibrary, gGaussianLikeHeavyWeights); 143fd668cfffe3fdcfbf6e0b858343a62818d337590bungeman@google.com#elif defined(SK_CAN_USE_DLOPEN) && SK_CAN_USE_DLOPEN == 1 144fd668cfffe3fdcfbf6e0b858343a62818d337590bungeman@google.com //The FreeType library is already loaded, so symbols are available in process. 145fd668cfffe3fdcfbf6e0b858343a62818d337590bungeman@google.com void* self = dlopen(NULL, RTLD_LAZY); 14649f085dddff10473b6ebf832a974288300224e60bsalomon if (self) { 147fd668cfffe3fdcfbf6e0b858343a62818d337590bungeman@google.com FT_Library_SetLcdFilterWeightsProc setLcdFilterWeights; 148fd668cfffe3fdcfbf6e0b858343a62818d337590bungeman@google.com //The following cast is non-standard, but safe for POSIX. 149fd668cfffe3fdcfbf6e0b858343a62818d337590bungeman@google.com *reinterpret_cast<void**>(&setLcdFilterWeights) = dlsym(self, "FT_Library_SetLcdFilterWeights"); 150fd668cfffe3fdcfbf6e0b858343a62818d337590bungeman@google.com dlclose(self); 151fd668cfffe3fdcfbf6e0b858343a62818d337590bungeman@google.com 15249f085dddff10473b6ebf832a974288300224e60bsalomon if (setLcdFilterWeights) { 15362566f361f44bfaefcef69c2a6635aabdc44361bbungeman@google.com err = setLcdFilterWeights(gFTLibrary, gGaussianLikeHeavyWeights); 154fd668cfffe3fdcfbf6e0b858343a62818d337590bungeman@google.com } 155fd668cfffe3fdcfbf6e0b858343a62818d337590bungeman@google.com } 156fd668cfffe3fdcfbf6e0b858343a62818d337590bungeman@google.com#endif 15762566f361f44bfaefcef69c2a6635aabdc44361bbungeman@google.com#endif 158a1c32563cf218c9eddc79fad303eb4185c774224reed@google.com } 1595070d79edd54450f2980f7ff1e2d04762e89aa0bepoger@google.com#else 1605070d79edd54450f2980f7ff1e2d04762e89aa0bepoger@google.com gLCDSupport = false; 1615070d79edd54450f2980f7ff1e2d04762e89aa0bepoger@google.com#endif 16261608aaf932708e3e8ac05097ead1bf7885ec87dreed@android.com gLCDSupportValid = true; 163309485b7b51f4cae4c0361ab4da00fe9cc89515cagl@chromium.org 164309485b7b51f4cae4c0361ab4da00fe9cc89515cagl@chromium.org return true; 165309485b7b51f4cae4c0361ab4da00fe9cc89515cagl@chromium.org} 166309485b7b51f4cae4c0361ab4da00fe9cc89515cagl@chromium.org 167ba9354b9d4de62988cc2a56c0760fd5e52da3679commit-bot@chromium.org// Called while holding gFTMutex. 168ba9354b9d4de62988cc2a56c0760fd5e52da3679commit-bot@chromium.orgstatic void determine_lcd_support(bool* lcdSupported) { 169fb2fdcca206fbcac6254a9524c2d06dc98dd5421reed@google.com if (!gLCDSupportValid) { 170ba9354b9d4de62988cc2a56c0760fd5e52da3679commit-bot@chromium.org // This will determine LCD support as a side effect. 171ba9354b9d4de62988cc2a56c0760fd5e52da3679commit-bot@chromium.org InitFreetype(); 172ba9354b9d4de62988cc2a56c0760fd5e52da3679commit-bot@chromium.org FT_Done_FreeType(gFTLibrary); 173fb2fdcca206fbcac6254a9524c2d06dc98dd5421reed@google.com } 174ba9354b9d4de62988cc2a56c0760fd5e52da3679commit-bot@chromium.org SkASSERT(gLCDSupportValid); 175ba9354b9d4de62988cc2a56c0760fd5e52da3679commit-bot@chromium.org *lcdSupported = gLCDSupport; 176ba9354b9d4de62988cc2a56c0760fd5e52da3679commit-bot@chromium.org} 177ba9354b9d4de62988cc2a56c0760fd5e52da3679commit-bot@chromium.org 178ba9354b9d4de62988cc2a56c0760fd5e52da3679commit-bot@chromium.org// Lazy, once, wrapper to ask the FreeType Library if it can support LCD text 179ba9354b9d4de62988cc2a56c0760fd5e52da3679commit-bot@chromium.orgstatic bool is_lcd_supported() { 180ba9354b9d4de62988cc2a56c0760fd5e52da3679commit-bot@chromium.org static bool lcdSupported = false; 181ba9354b9d4de62988cc2a56c0760fd5e52da3679commit-bot@chromium.org SkOnce(&gLCDSupportValid, &gFTMutex, determine_lcd_support, &lcdSupported); 182ba9354b9d4de62988cc2a56c0760fd5e52da3679commit-bot@chromium.org return lcdSupported; 183fb2fdcca206fbcac6254a9524c2d06dc98dd5421reed@google.com} 184fb2fdcca206fbcac6254a9524c2d06dc98dd5421reed@google.com 185c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.comclass SkScalerContext_FreeType : public SkScalerContext_FreeType_Base { 1868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic: 1870da48618a758ef46c2174bdc1eaeb6dd8a693a2ereed@google.com SkScalerContext_FreeType(SkTypeface*, const SkDescriptor* desc); 1888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com virtual ~SkScalerContext_FreeType(); 189cc3096ba6d437b29f1cbd34c237607419cbed72bagl@chromium.org 19062900b4c64401bc80ae85f6f5c87309a273cae10reed@android.com bool success() const { 191a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com return fFaceRec != NULL && 192a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com fFTSize != NULL && 193a0f5d1546d499ef0cd7dbfba9a866ae5a27e1541reed@android.com fFace != NULL; 19462900b4c64401bc80ae85f6f5c87309a273cae10reed@android.com } 1958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprotected: 197a76de72a6036da0a6b051b14411b80941971f881bungeman@google.com virtual unsigned generateGlyphCount() SK_OVERRIDE; 198a76de72a6036da0a6b051b14411b80941971f881bungeman@google.com virtual uint16_t generateCharToGlyph(SkUnichar uni) SK_OVERRIDE; 199a76de72a6036da0a6b051b14411b80941971f881bungeman@google.com virtual void generateAdvance(SkGlyph* glyph) SK_OVERRIDE; 200a76de72a6036da0a6b051b14411b80941971f881bungeman@google.com virtual void generateMetrics(SkGlyph* glyph) SK_OVERRIDE; 201a76de72a6036da0a6b051b14411b80941971f881bungeman@google.com virtual void generateImage(const SkGlyph& glyph) SK_OVERRIDE; 202a76de72a6036da0a6b051b14411b80941971f881bungeman@google.com virtual void generatePath(const SkGlyph& glyph, SkPath* path) SK_OVERRIDE; 203410780677af260e32948b02c0725ef6ad761260cbungeman virtual void generateFontMetrics(SkPaint::FontMetrics*) SK_OVERRIDE; 204a76de72a6036da0a6b051b14411b80941971f881bungeman@google.com virtual SkUnichar generateGlyphToChar(uint16_t glyph) SK_OVERRIDE; 2058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate: 2078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkFaceRec* fFaceRec; 2088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com FT_Face fFace; // reference to shared face in gFaceRecHead 2098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com FT_Size fFTSize; // our own copy 210c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com FT_Int fStrikeIndex; 2118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkFixed fScaleX, fScaleY; 2128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com FT_Matrix fMatrix22; 2138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com uint32_t fLoadGlyphFlags; 214bdc9988bf238fc752826c313807044bca4e0b448reed@google.com bool fDoLinearMetrics; 215a1bfa214c55fc1332a43c0343c909549f4178d05reed@google.com bool fLCDIsVert; 2168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 217f073b3332d7c9f7dba6bcf7eb93708593a90036creed@google.com // Need scalar versions for generateFontMetrics 218f073b3332d7c9f7dba6bcf7eb93708593a90036creed@google.com SkVector fScale; 219f073b3332d7c9f7dba6bcf7eb93708593a90036creed@google.com SkMatrix fMatrix22Scalar; 220f073b3332d7c9f7dba6bcf7eb93708593a90036creed@google.com 2218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com FT_Error setupSize(); 222d8b599cb264b2228e0fb1bee6d3604be6d3c2855djsollen@google.com void getBBoxForCurrentGlyph(SkGlyph* glyph, FT_BBox* bbox, 223d8b599cb264b2228e0fb1bee6d3604be6d3c2855djsollen@google.com bool snapToPixelBoundary = false); 224cbe1b54c30b9a1061577c91e0b914dbe9acdc563bungeman@google.com bool getCBoxForLetter(char letter, FT_BBox* bbox); 22594bc60f9864094edbfb787b09c963d8818c8962fscroggo@google.com // Caller must lock gFTMutex before calling this function. 226d8b599cb264b2228e0fb1bee6d3604be6d3c2855djsollen@google.com void updateGlyphIfLCD(SkGlyph* glyph); 2276fa81d7878d20b9e46ea9395e2efb58026447142commit-bot@chromium.org // Caller must lock gFTMutex before calling this function. 2286fa81d7878d20b9e46ea9395e2efb58026447142commit-bot@chromium.org // update FreeType2 glyph slot with glyph emboldened 2296fa81d7878d20b9e46ea9395e2efb58026447142commit-bot@chromium.org void emboldenIfNeeded(FT_Face face, FT_GlyphSlot glyph); 2308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}; 2318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////////////////////////////////////////////////////////// 2338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////////////////////////////////////////////////////////// 2348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstruct SkFaceRec { 2368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkFaceRec* fNext; 2378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com FT_Face fFace; 2388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com FT_StreamRec fFTStream; 2398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkStream* fSkStream; 2408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com uint32_t fRefCnt; 2418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com uint32_t fFontID; 2428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 243b1d9d2ef2803bd55fdc886d13033b48f8450dd14reed@android.com // assumes ownership of the stream, will call unref() when its done 2448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkFaceRec(SkStream* strm, uint32_t fontID); 2458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ~SkFaceRec() { 246b1d9d2ef2803bd55fdc886d13033b48f8450dd14reed@android.com fSkStream->unref(); 2478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}; 2498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comextern "C" { 2518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com static unsigned long sk_stream_read(FT_Stream stream, 2528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com unsigned long offset, 2538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com unsigned char* buffer, 2548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com unsigned long count ) { 2558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkStream* str = (SkStream*)stream->descriptor.pointer; 2568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (count) { 2588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (!str->rewind()) { 2598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return 0; 2608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 2618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com unsigned long ret; 2628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (offset) { 2638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ret = str->read(NULL, offset); 2648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (ret != offset) { 2658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return 0; 2668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ret = str->read(buffer, count); 2698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (ret != count) { 2708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return 0; 2718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com count = ret; 2738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return count; 2768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 27866a58aca8379a33ccc7572a31c74a3334d08b47csugoi@google.com static void sk_stream_close(FT_Stream) {} 2798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 2808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkFaceRec::SkFaceRec(SkStream* strm, uint32_t fontID) 2829af25f3d98ba99955af6e25995b457152ec2cf91vandebo@chromium.org : fNext(NULL), fSkStream(strm), fRefCnt(1), fFontID(fontID) { 2838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// SkDEBUGF(("SkFaceRec: opening %s (%p)\n", key.c_str(), strm)); 2848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2854516f4786f5dda1b86a8f825b9e8e910d9c2363creed@android.com sk_bzero(&fFTStream, sizeof(fFTStream)); 2868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fFTStream.size = fSkStream->getLength(); 2878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fFTStream.descriptor.pointer = fSkStream; 2888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fFTStream.read = sk_stream_read; 2898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fFTStream.close = sk_stream_close; 2908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 2918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 29262900b4c64401bc80ae85f6f5c87309a273cae10reed@android.com// Will return 0 on failure 29394bc60f9864094edbfb787b09c963d8818c8962fscroggo@google.com// Caller must lock gFTMutex before calling this function. 2942cdc6713fb04c46ecbc73a724029a8b266004ddfreed@google.comstatic SkFaceRec* ref_ft_face(const SkTypeface* typeface) { 2952cdc6713fb04c46ecbc73a724029a8b266004ddfreed@google.com const SkFontID fontID = typeface->uniqueID(); 2968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkFaceRec* rec = gFaceRecHead; 2978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while (rec) { 2988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (rec->fFontID == fontID) { 2998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(rec->fFace); 3008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com rec->fRefCnt += 1; 3018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return rec; 3028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 3038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com rec = rec->fNext; 3048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 3058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3062cdc6713fb04c46ecbc73a724029a8b266004ddfreed@google.com int face_index; 3072cdc6713fb04c46ecbc73a724029a8b266004ddfreed@google.com SkStream* strm = typeface->openStream(&face_index); 3088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (NULL == strm) { 3092cdc6713fb04c46ecbc73a724029a8b266004ddfreed@google.com return NULL; 3108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 3118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // this passes ownership of strm to the rec 3138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com rec = SkNEW_ARGS(SkFaceRec, (strm, fontID)); 3148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com FT_Open_Args args; 3168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com memset(&args, 0, sizeof(args)); 3178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const void* memoryBase = strm->getMemoryBase(); 3188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 31949f085dddff10473b6ebf832a974288300224e60bsalomon if (memoryBase) { 3208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//printf("mmap(%s)\n", keyString.c_str()); 3218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com args.flags = FT_OPEN_MEMORY; 3228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com args.memory_base = (const FT_Byte*)memoryBase; 3238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com args.memory_size = strm->getLength(); 3248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 3258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//printf("fopen(%s)\n", keyString.c_str()); 3268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com args.flags = FT_OPEN_STREAM; 3278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com args.stream = &rec->fFTStream; 3288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 3298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3302cdc6713fb04c46ecbc73a724029a8b266004ddfreed@google.com FT_Error err = FT_Open_Face(gFTLibrary, &args, face_index, &rec->fFace); 3318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (err) { // bad filename, try the default font 3328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fprintf(stderr, "ERROR: unable to open font '%x'\n", fontID); 3338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDELETE(rec); 3342cdc6713fb04c46ecbc73a724029a8b266004ddfreed@google.com return NULL; 3358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 3368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(rec->fFace); 3378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com //fprintf(stderr, "Opened font '%s'\n", filename.c_str()); 3388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com rec->fNext = gFaceRecHead; 3398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com gFaceRecHead = rec; 3408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return rec; 3418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 3428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 3438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 34494bc60f9864094edbfb787b09c963d8818c8962fscroggo@google.com// Caller must lock gFTMutex before calling this function. 3458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic void unref_ft_face(FT_Face face) { 3468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkFaceRec* rec = gFaceRecHead; 3478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkFaceRec* prev = NULL; 3488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while (rec) { 3498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkFaceRec* next = rec->fNext; 3508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (rec->fFace == face) { 3518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (--rec->fRefCnt == 0) { 3528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (prev) { 3538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com prev->fNext = next; 3548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 3558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com gFaceRecHead = next; 3568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 3578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com FT_Done_Face(face); 3588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDELETE(rec); 3598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 3608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 3618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 3628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com prev = rec; 3638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com rec = next; 3648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 3650c00f21fee3f5cfa3aa7e5d46ff94cb8cf340451tomhudson@google.com SkDEBUGFAIL("shouldn't get here, face not in list"); 3668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 3678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 368b4162b12b1e8e38c48b328f819c97199a0825d2breed@google.comclass AutoFTAccess { 369b4162b12b1e8e38c48b328f819c97199a0825d2breed@google.compublic: 370b4162b12b1e8e38c48b328f819c97199a0825d2breed@google.com AutoFTAccess(const SkTypeface* tf) : fRec(NULL), fFace(NULL) { 371b4162b12b1e8e38c48b328f819c97199a0825d2breed@google.com gFTMutex.acquire(); 372b4162b12b1e8e38c48b328f819c97199a0825d2breed@google.com if (1 == ++gFTCount) { 373b4162b12b1e8e38c48b328f819c97199a0825d2breed@google.com if (!InitFreetype()) { 374b4162b12b1e8e38c48b328f819c97199a0825d2breed@google.com sk_throw(); 375b4162b12b1e8e38c48b328f819c97199a0825d2breed@google.com } 376b4162b12b1e8e38c48b328f819c97199a0825d2breed@google.com } 377b4162b12b1e8e38c48b328f819c97199a0825d2breed@google.com fRec = ref_ft_face(tf); 378b4162b12b1e8e38c48b328f819c97199a0825d2breed@google.com if (fRec) { 379b4162b12b1e8e38c48b328f819c97199a0825d2breed@google.com fFace = fRec->fFace; 380b4162b12b1e8e38c48b328f819c97199a0825d2breed@google.com } 381b4162b12b1e8e38c48b328f819c97199a0825d2breed@google.com } 382b4162b12b1e8e38c48b328f819c97199a0825d2breed@google.com 383b4162b12b1e8e38c48b328f819c97199a0825d2breed@google.com ~AutoFTAccess() { 384b4162b12b1e8e38c48b328f819c97199a0825d2breed@google.com if (fFace) { 385b4162b12b1e8e38c48b328f819c97199a0825d2breed@google.com unref_ft_face(fFace); 386b4162b12b1e8e38c48b328f819c97199a0825d2breed@google.com } 387b4162b12b1e8e38c48b328f819c97199a0825d2breed@google.com if (0 == --gFTCount) { 388b4162b12b1e8e38c48b328f819c97199a0825d2breed@google.com FT_Done_FreeType(gFTLibrary); 389b4162b12b1e8e38c48b328f819c97199a0825d2breed@google.com } 390b4162b12b1e8e38c48b328f819c97199a0825d2breed@google.com gFTMutex.release(); 391b4162b12b1e8e38c48b328f819c97199a0825d2breed@google.com } 392b4162b12b1e8e38c48b328f819c97199a0825d2breed@google.com 393b4162b12b1e8e38c48b328f819c97199a0825d2breed@google.com SkFaceRec* rec() { return fRec; } 394b4162b12b1e8e38c48b328f819c97199a0825d2breed@google.com FT_Face face() { return fFace; } 395b4162b12b1e8e38c48b328f819c97199a0825d2breed@google.com 396b4162b12b1e8e38c48b328f819c97199a0825d2breed@google.comprivate: 397b4162b12b1e8e38c48b328f819c97199a0825d2breed@google.com SkFaceRec* fRec; 398b4162b12b1e8e38c48b328f819c97199a0825d2breed@google.com FT_Face fFace; 399b4162b12b1e8e38c48b328f819c97199a0825d2breed@google.com}; 400b4162b12b1e8e38c48b328f819c97199a0825d2breed@google.com 4018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////////////////////////////////////////////////////////// 4028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 40316be6b8fdfa625b36964fd8150ab1a6b1e3a56bdvandebo@chromium.org// Work around for old versions of freetype. 40416be6b8fdfa625b36964fd8150ab1a6b1e3a56bdvandebo@chromium.orgstatic FT_Error getAdvances(FT_Face face, FT_UInt start, FT_UInt count, 40516be6b8fdfa625b36964fd8150ab1a6b1e3a56bdvandebo@chromium.org FT_Int32 loadFlags, FT_Fixed* advances) { 40616be6b8fdfa625b36964fd8150ab1a6b1e3a56bdvandebo@chromium.org#ifdef FT_ADVANCES_H 40716be6b8fdfa625b36964fd8150ab1a6b1e3a56bdvandebo@chromium.org return FT_Get_Advances(face, start, count, loadFlags, advances); 40816be6b8fdfa625b36964fd8150ab1a6b1e3a56bdvandebo@chromium.org#else 40916be6b8fdfa625b36964fd8150ab1a6b1e3a56bdvandebo@chromium.org if (!face || start >= face->num_glyphs || 41016be6b8fdfa625b36964fd8150ab1a6b1e3a56bdvandebo@chromium.org start + count > face->num_glyphs || loadFlags != FT_LOAD_NO_SCALE) { 41116be6b8fdfa625b36964fd8150ab1a6b1e3a56bdvandebo@chromium.org return 6; // "Invalid argument." 41216be6b8fdfa625b36964fd8150ab1a6b1e3a56bdvandebo@chromium.org } 41316be6b8fdfa625b36964fd8150ab1a6b1e3a56bdvandebo@chromium.org if (count == 0) 41416be6b8fdfa625b36964fd8150ab1a6b1e3a56bdvandebo@chromium.org return 0; 41516be6b8fdfa625b36964fd8150ab1a6b1e3a56bdvandebo@chromium.org 41616be6b8fdfa625b36964fd8150ab1a6b1e3a56bdvandebo@chromium.org for (int i = 0; i < count; i++) { 41716be6b8fdfa625b36964fd8150ab1a6b1e3a56bdvandebo@chromium.org FT_Error err = FT_Load_Glyph(face, start + i, FT_LOAD_NO_SCALE); 41816be6b8fdfa625b36964fd8150ab1a6b1e3a56bdvandebo@chromium.org if (err) 41916be6b8fdfa625b36964fd8150ab1a6b1e3a56bdvandebo@chromium.org return err; 42016be6b8fdfa625b36964fd8150ab1a6b1e3a56bdvandebo@chromium.org advances[i] = face->glyph->advance.x; 42116be6b8fdfa625b36964fd8150ab1a6b1e3a56bdvandebo@chromium.org } 42216be6b8fdfa625b36964fd8150ab1a6b1e3a56bdvandebo@chromium.org 42316be6b8fdfa625b36964fd8150ab1a6b1e3a56bdvandebo@chromium.org return 0; 42416be6b8fdfa625b36964fd8150ab1a6b1e3a56bdvandebo@chromium.org#endif 42516be6b8fdfa625b36964fd8150ab1a6b1e3a56bdvandebo@chromium.org} 42616be6b8fdfa625b36964fd8150ab1a6b1e3a56bdvandebo@chromium.org 42716be6b8fdfa625b36964fd8150ab1a6b1e3a56bdvandebo@chromium.orgstatic bool canEmbed(FT_Face face) { 428fa394d491b6e625159f83787619fcb852d245471djsollen@google.com#ifdef FT_FSTYPE_RESTRICTED_LICENSE_EMBEDDING 42916be6b8fdfa625b36964fd8150ab1a6b1e3a56bdvandebo@chromium.org FT_UShort fsType = FT_Get_FSType_Flags(face); 43016be6b8fdfa625b36964fd8150ab1a6b1e3a56bdvandebo@chromium.org return (fsType & (FT_FSTYPE_RESTRICTED_LICENSE_EMBEDDING | 43116be6b8fdfa625b36964fd8150ab1a6b1e3a56bdvandebo@chromium.org FT_FSTYPE_BITMAP_EMBEDDING_ONLY)) == 0; 43216be6b8fdfa625b36964fd8150ab1a6b1e3a56bdvandebo@chromium.org#else 43316be6b8fdfa625b36964fd8150ab1a6b1e3a56bdvandebo@chromium.org // No embedding is 0x2 and bitmap embedding only is 0x200. 43416be6b8fdfa625b36964fd8150ab1a6b1e3a56bdvandebo@chromium.org TT_OS2* os2_table; 43516be6b8fdfa625b36964fd8150ab1a6b1e3a56bdvandebo@chromium.org if ((os2_table = (TT_OS2*)FT_Get_Sfnt_Table(face, ft_sfnt_os2)) != NULL) { 43616be6b8fdfa625b36964fd8150ab1a6b1e3a56bdvandebo@chromium.org return (os2_table->fsType & 0x202) == 0; 43716be6b8fdfa625b36964fd8150ab1a6b1e3a56bdvandebo@chromium.org } 43816be6b8fdfa625b36964fd8150ab1a6b1e3a56bdvandebo@chromium.org return false; // We tried, fail safe. 43916be6b8fdfa625b36964fd8150ab1a6b1e3a56bdvandebo@chromium.org#endif 44016be6b8fdfa625b36964fd8150ab1a6b1e3a56bdvandebo@chromium.org} 44116be6b8fdfa625b36964fd8150ab1a6b1e3a56bdvandebo@chromium.org 4420f9bad01b0e7ad592ffb342dcf1d238b15329be1vandebostatic bool canSubset(FT_Face face) { 4430f9bad01b0e7ad592ffb342dcf1d238b15329be1vandebo#ifdef FT_FSTYPE_NO_SUBSETTING 4440f9bad01b0e7ad592ffb342dcf1d238b15329be1vandebo FT_UShort fsType = FT_Get_FSType_Flags(face); 4450f9bad01b0e7ad592ffb342dcf1d238b15329be1vandebo return (fsType & FT_FSTYPE_NO_SUBSETTING) == 0; 4460f9bad01b0e7ad592ffb342dcf1d238b15329be1vandebo#else 4470f9bad01b0e7ad592ffb342dcf1d238b15329be1vandebo // No subset is 0x100. 4480f9bad01b0e7ad592ffb342dcf1d238b15329be1vandebo TT_OS2* os2_table; 4490f9bad01b0e7ad592ffb342dcf1d238b15329be1vandebo if ((os2_table = (TT_OS2*)FT_Get_Sfnt_Table(face, ft_sfnt_os2)) != NULL) { 4500f9bad01b0e7ad592ffb342dcf1d238b15329be1vandebo return (os2_table->fsType & 0x100) == 0; 4510f9bad01b0e7ad592ffb342dcf1d238b15329be1vandebo } 4520f9bad01b0e7ad592ffb342dcf1d238b15329be1vandebo return false; // We tried, fail safe. 4530f9bad01b0e7ad592ffb342dcf1d238b15329be1vandebo#endif 4540f9bad01b0e7ad592ffb342dcf1d238b15329be1vandebo} 4550f9bad01b0e7ad592ffb342dcf1d238b15329be1vandebo 4562a22e10ab2946c5590cd2a258427ce3ccfca9bfavandebo@chromium.orgstatic bool GetLetterCBox(FT_Face face, char letter, FT_BBox* bbox) { 4572a22e10ab2946c5590cd2a258427ce3ccfca9bfavandebo@chromium.org const FT_UInt glyph_id = FT_Get_Char_Index(face, letter); 4582a22e10ab2946c5590cd2a258427ce3ccfca9bfavandebo@chromium.org if (!glyph_id) 4592a22e10ab2946c5590cd2a258427ce3ccfca9bfavandebo@chromium.org return false; 460cbe1b54c30b9a1061577c91e0b914dbe9acdc563bungeman@google.com if (FT_Load_Glyph(face, glyph_id, FT_LOAD_NO_SCALE) != 0) 461cbe1b54c30b9a1061577c91e0b914dbe9acdc563bungeman@google.com return false; 4622a22e10ab2946c5590cd2a258427ce3ccfca9bfavandebo@chromium.org FT_Outline_Get_CBox(&face->glyph->outline, bbox); 4632a22e10ab2946c5590cd2a258427ce3ccfca9bfavandebo@chromium.org return true; 4642a22e10ab2946c5590cd2a258427ce3ccfca9bfavandebo@chromium.org} 4652a22e10ab2946c5590cd2a258427ce3ccfca9bfavandebo@chromium.org 4666f72d1eacd66d2a9c0059962a75c0ca6a99ff98evandebo@chromium.orgstatic bool getWidthAdvance(FT_Face face, int gId, int16_t* data) { 467c48b2b330f8bf0e01381e27ca36f48ef5c7d8d5fvandebo@chromium.org FT_Fixed advance = 0; 4686f72d1eacd66d2a9c0059962a75c0ca6a99ff98evandebo@chromium.org if (getAdvances(face, gId, 1, FT_LOAD_NO_SCALE, &advance)) { 4696f72d1eacd66d2a9c0059962a75c0ca6a99ff98evandebo@chromium.org return false; 4702a22e10ab2946c5590cd2a258427ce3ccfca9bfavandebo@chromium.org } 4716f72d1eacd66d2a9c0059962a75c0ca6a99ff98evandebo@chromium.org SkASSERT(data); 4726f72d1eacd66d2a9c0059962a75c0ca6a99ff98evandebo@chromium.org *data = advance; 4736f72d1eacd66d2a9c0059962a75c0ca6a99ff98evandebo@chromium.org return true; 4742a22e10ab2946c5590cd2a258427ce3ccfca9bfavandebo@chromium.org} 4752a22e10ab2946c5590cd2a258427ce3ccfca9bfavandebo@chromium.org 4766744d498fcbbbcf503ec80c4d43dd8f118a88597vandebo@chromium.orgstatic void populate_glyph_to_unicode(FT_Face& face, 4776744d498fcbbbcf503ec80c4d43dd8f118a88597vandebo@chromium.org SkTDArray<SkUnichar>* glyphToUnicode) { 4786744d498fcbbbcf503ec80c4d43dd8f118a88597vandebo@chromium.org // Check and see if we have Unicode cmaps. 4796744d498fcbbbcf503ec80c4d43dd8f118a88597vandebo@chromium.org for (int i = 0; i < face->num_charmaps; ++i) { 4806744d498fcbbbcf503ec80c4d43dd8f118a88597vandebo@chromium.org // CMaps known to support Unicode: 4816744d498fcbbbcf503ec80c4d43dd8f118a88597vandebo@chromium.org // Platform ID Encoding ID Name 4826744d498fcbbbcf503ec80c4d43dd8f118a88597vandebo@chromium.org // ----------- ----------- ----------------------------------- 4836744d498fcbbbcf503ec80c4d43dd8f118a88597vandebo@chromium.org // 0 0,1 Apple Unicode 4846744d498fcbbbcf503ec80c4d43dd8f118a88597vandebo@chromium.org // 0 3 Apple Unicode 2.0 (preferred) 4856744d498fcbbbcf503ec80c4d43dd8f118a88597vandebo@chromium.org // 3 1 Microsoft Unicode UCS-2 4866744d498fcbbbcf503ec80c4d43dd8f118a88597vandebo@chromium.org // 3 10 Microsoft Unicode UCS-4 (preferred) 4876744d498fcbbbcf503ec80c4d43dd8f118a88597vandebo@chromium.org // 4886744d498fcbbbcf503ec80c4d43dd8f118a88597vandebo@chromium.org // See Apple TrueType Reference Manual 4896744d498fcbbbcf503ec80c4d43dd8f118a88597vandebo@chromium.org // http://developer.apple.com/fonts/TTRefMan/RM06/Chap6cmap.html 4906744d498fcbbbcf503ec80c4d43dd8f118a88597vandebo@chromium.org // http://developer.apple.com/fonts/TTRefMan/RM06/Chap6name.html#ID 4916744d498fcbbbcf503ec80c4d43dd8f118a88597vandebo@chromium.org // Microsoft OpenType Specification 4926744d498fcbbbcf503ec80c4d43dd8f118a88597vandebo@chromium.org // http://www.microsoft.com/typography/otspec/cmap.htm 4936744d498fcbbbcf503ec80c4d43dd8f118a88597vandebo@chromium.org 4946744d498fcbbbcf503ec80c4d43dd8f118a88597vandebo@chromium.org FT_UShort platformId = face->charmaps[i]->platform_id; 4956744d498fcbbbcf503ec80c4d43dd8f118a88597vandebo@chromium.org FT_UShort encodingId = face->charmaps[i]->encoding_id; 4966744d498fcbbbcf503ec80c4d43dd8f118a88597vandebo@chromium.org 4976744d498fcbbbcf503ec80c4d43dd8f118a88597vandebo@chromium.org if (platformId != 0 && platformId != 3) { 4986744d498fcbbbcf503ec80c4d43dd8f118a88597vandebo@chromium.org continue; 4996744d498fcbbbcf503ec80c4d43dd8f118a88597vandebo@chromium.org } 5006744d498fcbbbcf503ec80c4d43dd8f118a88597vandebo@chromium.org if (platformId == 3 && encodingId != 1 && encodingId != 10) { 5016744d498fcbbbcf503ec80c4d43dd8f118a88597vandebo@chromium.org continue; 5026744d498fcbbbcf503ec80c4d43dd8f118a88597vandebo@chromium.org } 5036744d498fcbbbcf503ec80c4d43dd8f118a88597vandebo@chromium.org bool preferredMap = ((platformId == 3 && encodingId == 10) || 5046744d498fcbbbcf503ec80c4d43dd8f118a88597vandebo@chromium.org (platformId == 0 && encodingId == 3)); 5056744d498fcbbbcf503ec80c4d43dd8f118a88597vandebo@chromium.org 5066744d498fcbbbcf503ec80c4d43dd8f118a88597vandebo@chromium.org FT_Set_Charmap(face, face->charmaps[i]); 5076744d498fcbbbcf503ec80c4d43dd8f118a88597vandebo@chromium.org if (glyphToUnicode->isEmpty()) { 5086744d498fcbbbcf503ec80c4d43dd8f118a88597vandebo@chromium.org glyphToUnicode->setCount(face->num_glyphs); 5096744d498fcbbbcf503ec80c4d43dd8f118a88597vandebo@chromium.org memset(glyphToUnicode->begin(), 0, 5106744d498fcbbbcf503ec80c4d43dd8f118a88597vandebo@chromium.org sizeof(SkUnichar) * face->num_glyphs); 5116744d498fcbbbcf503ec80c4d43dd8f118a88597vandebo@chromium.org } 5126744d498fcbbbcf503ec80c4d43dd8f118a88597vandebo@chromium.org 5136744d498fcbbbcf503ec80c4d43dd8f118a88597vandebo@chromium.org // Iterate through each cmap entry. 5146744d498fcbbbcf503ec80c4d43dd8f118a88597vandebo@chromium.org FT_UInt glyphIndex; 5156744d498fcbbbcf503ec80c4d43dd8f118a88597vandebo@chromium.org for (SkUnichar charCode = FT_Get_First_Char(face, &glyphIndex); 5166744d498fcbbbcf503ec80c4d43dd8f118a88597vandebo@chromium.org glyphIndex != 0; 5176744d498fcbbbcf503ec80c4d43dd8f118a88597vandebo@chromium.org charCode = FT_Get_Next_Char(face, charCode, &glyphIndex)) { 5186744d498fcbbbcf503ec80c4d43dd8f118a88597vandebo@chromium.org if (charCode && 5196744d498fcbbbcf503ec80c4d43dd8f118a88597vandebo@chromium.org ((*glyphToUnicode)[glyphIndex] == 0 || preferredMap)) { 5206744d498fcbbbcf503ec80c4d43dd8f118a88597vandebo@chromium.org (*glyphToUnicode)[glyphIndex] = charCode; 5216744d498fcbbbcf503ec80c4d43dd8f118a88597vandebo@chromium.org } 5226744d498fcbbbcf503ec80c4d43dd8f118a88597vandebo@chromium.org } 5236744d498fcbbbcf503ec80c4d43dd8f118a88597vandebo@chromium.org } 5246744d498fcbbbcf503ec80c4d43dd8f118a88597vandebo@chromium.org} 5256744d498fcbbbcf503ec80c4d43dd8f118a88597vandebo@chromium.org 5262689f615e364dc48ad73826564f5b13d2329179dreed@google.comSkAdvancedTypefaceMetrics* SkTypeface_FreeType::onGetAdvancedTypefaceMetrics( 52737ad8fb72ff1b3faac93b01ead2c79e1a06fc172vandebo@chromium.org SkAdvancedTypefaceMetrics::PerGlyphInfo perGlyphInfo, 52837ad8fb72ff1b3faac93b01ead2c79e1a06fc172vandebo@chromium.org const uint32_t* glyphIDs, 5292689f615e364dc48ad73826564f5b13d2329179dreed@google.com uint32_t glyphIDsCount) const { 530da957724d2a1fe97113f1464740d1fe76c1bb077djsollen@google.com#if defined(SK_BUILD_FOR_MAC) 5318a5d692c034b4f027391b4e659c7562714f62804reed@google.com return NULL; 5328a5d692c034b4f027391b4e659c7562714f62804reed@google.com#else 533b4162b12b1e8e38c48b328f819c97199a0825d2breed@google.com AutoFTAccess fta(this); 534b4162b12b1e8e38c48b328f819c97199a0825d2breed@google.com FT_Face face = fta.face(); 535b4162b12b1e8e38c48b328f819c97199a0825d2breed@google.com if (!face) { 5362a22e10ab2946c5590cd2a258427ce3ccfca9bfavandebo@chromium.org return NULL; 537b4162b12b1e8e38c48b328f819c97199a0825d2breed@google.com } 5382a22e10ab2946c5590cd2a258427ce3ccfca9bfavandebo@chromium.org 539c48b2b330f8bf0e01381e27ca36f48ef5c7d8d5fvandebo@chromium.org SkAdvancedTypefaceMetrics* info = new SkAdvancedTypefaceMetrics; 540c48b2b330f8bf0e01381e27ca36f48ef5c7d8d5fvandebo@chromium.org info->fFontName.set(FT_Get_Postscript_Name(face)); 5410f9bad01b0e7ad592ffb342dcf1d238b15329be1vandebo info->fFlags = SkAdvancedTypefaceMetrics::kEmpty_FontFlag; 5420f9bad01b0e7ad592ffb342dcf1d238b15329be1vandebo if (FT_HAS_MULTIPLE_MASTERS(face)) { 5430f9bad01b0e7ad592ffb342dcf1d238b15329be1vandebo info->fFlags = SkTBitOr<SkAdvancedTypefaceMetrics::FontFlags>( 5440f9bad01b0e7ad592ffb342dcf1d238b15329be1vandebo info->fFlags, SkAdvancedTypefaceMetrics::kMultiMaster_FontFlag); 5450f9bad01b0e7ad592ffb342dcf1d238b15329be1vandebo } 5460f9bad01b0e7ad592ffb342dcf1d238b15329be1vandebo if (!canEmbed(face)) { 5470f9bad01b0e7ad592ffb342dcf1d238b15329be1vandebo info->fFlags = SkTBitOr<SkAdvancedTypefaceMetrics::FontFlags>( 5480f9bad01b0e7ad592ffb342dcf1d238b15329be1vandebo info->fFlags, 5490f9bad01b0e7ad592ffb342dcf1d238b15329be1vandebo SkAdvancedTypefaceMetrics::kNotEmbeddable_FontFlag); 5500f9bad01b0e7ad592ffb342dcf1d238b15329be1vandebo } 5510f9bad01b0e7ad592ffb342dcf1d238b15329be1vandebo if (!canSubset(face)) { 5520f9bad01b0e7ad592ffb342dcf1d238b15329be1vandebo info->fFlags = SkTBitOr<SkAdvancedTypefaceMetrics::FontFlags>( 5530f9bad01b0e7ad592ffb342dcf1d238b15329be1vandebo info->fFlags, 5540f9bad01b0e7ad592ffb342dcf1d238b15329be1vandebo SkAdvancedTypefaceMetrics::kNotSubsettable_FontFlag); 5550f9bad01b0e7ad592ffb342dcf1d238b15329be1vandebo } 556c48b2b330f8bf0e01381e27ca36f48ef5c7d8d5fvandebo@chromium.org info->fLastGlyphID = face->num_glyphs - 1; 557c48b2b330f8bf0e01381e27ca36f48ef5c7d8d5fvandebo@chromium.org info->fEmSize = 1000; 558c48b2b330f8bf0e01381e27ca36f48ef5c7d8d5fvandebo@chromium.org 5592a22e10ab2946c5590cd2a258427ce3ccfca9bfavandebo@chromium.org bool cid = false; 5602a22e10ab2946c5590cd2a258427ce3ccfca9bfavandebo@chromium.org const char* fontType = FT_Get_X11_Font_Format(face); 561c3a2ae5823049f589c1841a855bb5675d69e31ddvandebo@chromium.org if (strcmp(fontType, "Type 1") == 0) { 562c48b2b330f8bf0e01381e27ca36f48ef5c7d8d5fvandebo@chromium.org info->fType = SkAdvancedTypefaceMetrics::kType1_Font; 5632a22e10ab2946c5590cd2a258427ce3ccfca9bfavandebo@chromium.org } else if (strcmp(fontType, "CID Type 1") == 0) { 564c48b2b330f8bf0e01381e27ca36f48ef5c7d8d5fvandebo@chromium.org info->fType = SkAdvancedTypefaceMetrics::kType1CID_Font; 5652a22e10ab2946c5590cd2a258427ce3ccfca9bfavandebo@chromium.org cid = true; 5662a22e10ab2946c5590cd2a258427ce3ccfca9bfavandebo@chromium.org } else if (strcmp(fontType, "CFF") == 0) { 567c48b2b330f8bf0e01381e27ca36f48ef5c7d8d5fvandebo@chromium.org info->fType = SkAdvancedTypefaceMetrics::kCFF_Font; 5682a22e10ab2946c5590cd2a258427ce3ccfca9bfavandebo@chromium.org } else if (strcmp(fontType, "TrueType") == 0) { 569c48b2b330f8bf0e01381e27ca36f48ef5c7d8d5fvandebo@chromium.org info->fType = SkAdvancedTypefaceMetrics::kTrueType_Font; 5702a22e10ab2946c5590cd2a258427ce3ccfca9bfavandebo@chromium.org cid = true; 5712a22e10ab2946c5590cd2a258427ce3ccfca9bfavandebo@chromium.org TT_Header* ttHeader; 5722a22e10ab2946c5590cd2a258427ce3ccfca9bfavandebo@chromium.org if ((ttHeader = (TT_Header*)FT_Get_Sfnt_Table(face, 5732a22e10ab2946c5590cd2a258427ce3ccfca9bfavandebo@chromium.org ft_sfnt_head)) != NULL) { 574c48b2b330f8bf0e01381e27ca36f48ef5c7d8d5fvandebo@chromium.org info->fEmSize = ttHeader->Units_Per_EM; 5752a22e10ab2946c5590cd2a258427ce3ccfca9bfavandebo@chromium.org } 5764d71db85301f2d47874b43c4496c26cf21bba107bungeman@google.com } else { 5774d71db85301f2d47874b43c4496c26cf21bba107bungeman@google.com info->fType = SkAdvancedTypefaceMetrics::kOther_Font; 5782a22e10ab2946c5590cd2a258427ce3ccfca9bfavandebo@chromium.org } 5792a22e10ab2946c5590cd2a258427ce3ccfca9bfavandebo@chromium.org 5802a22e10ab2946c5590cd2a258427ce3ccfca9bfavandebo@chromium.org info->fStyle = 0; 5812a22e10ab2946c5590cd2a258427ce3ccfca9bfavandebo@chromium.org if (FT_IS_FIXED_WIDTH(face)) 582c48b2b330f8bf0e01381e27ca36f48ef5c7d8d5fvandebo@chromium.org info->fStyle |= SkAdvancedTypefaceMetrics::kFixedPitch_Style; 5832a22e10ab2946c5590cd2a258427ce3ccfca9bfavandebo@chromium.org if (face->style_flags & FT_STYLE_FLAG_ITALIC) 584c48b2b330f8bf0e01381e27ca36f48ef5c7d8d5fvandebo@chromium.org info->fStyle |= SkAdvancedTypefaceMetrics::kItalic_Style; 585c48b2b330f8bf0e01381e27ca36f48ef5c7d8d5fvandebo@chromium.org 586c48b2b330f8bf0e01381e27ca36f48ef5c7d8d5fvandebo@chromium.org PS_FontInfoRec ps_info; 587c48b2b330f8bf0e01381e27ca36f48ef5c7d8d5fvandebo@chromium.org TT_Postscript* tt_info; 588c48b2b330f8bf0e01381e27ca36f48ef5c7d8d5fvandebo@chromium.org if (FT_Get_PS_Font_Info(face, &ps_info) == 0) { 589c48b2b330f8bf0e01381e27ca36f48ef5c7d8d5fvandebo@chromium.org info->fItalicAngle = ps_info.italic_angle; 590c48b2b330f8bf0e01381e27ca36f48ef5c7d8d5fvandebo@chromium.org } else if ((tt_info = 591c48b2b330f8bf0e01381e27ca36f48ef5c7d8d5fvandebo@chromium.org (TT_Postscript*)FT_Get_Sfnt_Table(face, 592c48b2b330f8bf0e01381e27ca36f48ef5c7d8d5fvandebo@chromium.org ft_sfnt_post)) != NULL) { 593c48b2b330f8bf0e01381e27ca36f48ef5c7d8d5fvandebo@chromium.org info->fItalicAngle = SkFixedToScalar(tt_info->italicAngle); 594c48b2b330f8bf0e01381e27ca36f48ef5c7d8d5fvandebo@chromium.org } else { 595c48b2b330f8bf0e01381e27ca36f48ef5c7d8d5fvandebo@chromium.org info->fItalicAngle = 0; 596c48b2b330f8bf0e01381e27ca36f48ef5c7d8d5fvandebo@chromium.org } 597c48b2b330f8bf0e01381e27ca36f48ef5c7d8d5fvandebo@chromium.org 598c48b2b330f8bf0e01381e27ca36f48ef5c7d8d5fvandebo@chromium.org info->fAscent = face->ascender; 599c48b2b330f8bf0e01381e27ca36f48ef5c7d8d5fvandebo@chromium.org info->fDescent = face->descender; 600c48b2b330f8bf0e01381e27ca36f48ef5c7d8d5fvandebo@chromium.org 601c48b2b330f8bf0e01381e27ca36f48ef5c7d8d5fvandebo@chromium.org // Figure out a good guess for StemV - Min width of i, I, !, 1. 602c48b2b330f8bf0e01381e27ca36f48ef5c7d8d5fvandebo@chromium.org // This probably isn't very good with an italic font. 603c48b2b330f8bf0e01381e27ca36f48ef5c7d8d5fvandebo@chromium.org int16_t min_width = SHRT_MAX; 6046f72d1eacd66d2a9c0059962a75c0ca6a99ff98evandebo@chromium.org info->fStemV = 0; 605c48b2b330f8bf0e01381e27ca36f48ef5c7d8d5fvandebo@chromium.org char stem_chars[] = {'i', 'I', '!', '1'}; 606c48b2b330f8bf0e01381e27ca36f48ef5c7d8d5fvandebo@chromium.org for (size_t i = 0; i < SK_ARRAY_COUNT(stem_chars); i++) { 607c48b2b330f8bf0e01381e27ca36f48ef5c7d8d5fvandebo@chromium.org FT_BBox bbox; 608c48b2b330f8bf0e01381e27ca36f48ef5c7d8d5fvandebo@chromium.org if (GetLetterCBox(face, stem_chars[i], &bbox)) { 609c48b2b330f8bf0e01381e27ca36f48ef5c7d8d5fvandebo@chromium.org int16_t width = bbox.xMax - bbox.xMin; 610c48b2b330f8bf0e01381e27ca36f48ef5c7d8d5fvandebo@chromium.org if (width > 0 && width < min_width) { 611c48b2b330f8bf0e01381e27ca36f48ef5c7d8d5fvandebo@chromium.org min_width = width; 612c48b2b330f8bf0e01381e27ca36f48ef5c7d8d5fvandebo@chromium.org info->fStemV = min_width; 613c48b2b330f8bf0e01381e27ca36f48ef5c7d8d5fvandebo@chromium.org } 614c48b2b330f8bf0e01381e27ca36f48ef5c7d8d5fvandebo@chromium.org } 615c48b2b330f8bf0e01381e27ca36f48ef5c7d8d5fvandebo@chromium.org } 6162a22e10ab2946c5590cd2a258427ce3ccfca9bfavandebo@chromium.org 6172a22e10ab2946c5590cd2a258427ce3ccfca9bfavandebo@chromium.org TT_PCLT* pclt_info; 6182a22e10ab2946c5590cd2a258427ce3ccfca9bfavandebo@chromium.org TT_OS2* os2_table; 6192a22e10ab2946c5590cd2a258427ce3ccfca9bfavandebo@chromium.org if ((pclt_info = (TT_PCLT*)FT_Get_Sfnt_Table(face, ft_sfnt_pclt)) != NULL) { 6202a22e10ab2946c5590cd2a258427ce3ccfca9bfavandebo@chromium.org info->fCapHeight = pclt_info->CapHeight; 6212a22e10ab2946c5590cd2a258427ce3ccfca9bfavandebo@chromium.org uint8_t serif_style = pclt_info->SerifStyle & 0x3F; 6222a22e10ab2946c5590cd2a258427ce3ccfca9bfavandebo@chromium.org if (serif_style >= 2 && serif_style <= 6) 623c48b2b330f8bf0e01381e27ca36f48ef5c7d8d5fvandebo@chromium.org info->fStyle |= SkAdvancedTypefaceMetrics::kSerif_Style; 6242a22e10ab2946c5590cd2a258427ce3ccfca9bfavandebo@chromium.org else if (serif_style >= 9 && serif_style <= 12) 625c48b2b330f8bf0e01381e27ca36f48ef5c7d8d5fvandebo@chromium.org info->fStyle |= SkAdvancedTypefaceMetrics::kScript_Style; 626cbe1b54c30b9a1061577c91e0b914dbe9acdc563bungeman@google.com } else if (((os2_table = (TT_OS2*)FT_Get_Sfnt_Table(face, ft_sfnt_os2)) != NULL) && 627cbe1b54c30b9a1061577c91e0b914dbe9acdc563bungeman@google.com // sCapHeight is available only when version 2 or later. 628cbe1b54c30b9a1061577c91e0b914dbe9acdc563bungeman@google.com os2_table->version != 0xFFFF && 629cbe1b54c30b9a1061577c91e0b914dbe9acdc563bungeman@google.com os2_table->version >= 2) { 6302a22e10ab2946c5590cd2a258427ce3ccfca9bfavandebo@chromium.org info->fCapHeight = os2_table->sCapHeight; 6312a22e10ab2946c5590cd2a258427ce3ccfca9bfavandebo@chromium.org } else { 6322a22e10ab2946c5590cd2a258427ce3ccfca9bfavandebo@chromium.org // Figure out a good guess for CapHeight: average the height of M and X. 6332a22e10ab2946c5590cd2a258427ce3ccfca9bfavandebo@chromium.org FT_BBox m_bbox, x_bbox; 6342a22e10ab2946c5590cd2a258427ce3ccfca9bfavandebo@chromium.org bool got_m, got_x; 6352a22e10ab2946c5590cd2a258427ce3ccfca9bfavandebo@chromium.org got_m = GetLetterCBox(face, 'M', &m_bbox); 6362a22e10ab2946c5590cd2a258427ce3ccfca9bfavandebo@chromium.org got_x = GetLetterCBox(face, 'X', &x_bbox); 6372a22e10ab2946c5590cd2a258427ce3ccfca9bfavandebo@chromium.org if (got_m && got_x) { 6382a22e10ab2946c5590cd2a258427ce3ccfca9bfavandebo@chromium.org info->fCapHeight = (m_bbox.yMax - m_bbox.yMin + x_bbox.yMax - 6392a22e10ab2946c5590cd2a258427ce3ccfca9bfavandebo@chromium.org x_bbox.yMin) / 2; 6402a22e10ab2946c5590cd2a258427ce3ccfca9bfavandebo@chromium.org } else if (got_m && !got_x) { 6412a22e10ab2946c5590cd2a258427ce3ccfca9bfavandebo@chromium.org info->fCapHeight = m_bbox.yMax - m_bbox.yMin; 6422a22e10ab2946c5590cd2a258427ce3ccfca9bfavandebo@chromium.org } else if (!got_m && got_x) { 6432a22e10ab2946c5590cd2a258427ce3ccfca9bfavandebo@chromium.org info->fCapHeight = x_bbox.yMax - x_bbox.yMin; 64412bd4a014745acc3cffc20f23952bbb6f8477351bungeman@google.com } else { 64512bd4a014745acc3cffc20f23952bbb6f8477351bungeman@google.com // Last resort, use the ascent. 64612bd4a014745acc3cffc20f23952bbb6f8477351bungeman@google.com info->fCapHeight = info->fAscent; 6472a22e10ab2946c5590cd2a258427ce3ccfca9bfavandebo@chromium.org } 6482a22e10ab2946c5590cd2a258427ce3ccfca9bfavandebo@chromium.org } 6492a22e10ab2946c5590cd2a258427ce3ccfca9bfavandebo@chromium.org 650c48b2b330f8bf0e01381e27ca36f48ef5c7d8d5fvandebo@chromium.org info->fBBox = SkIRect::MakeLTRB(face->bbox.xMin, face->bbox.yMax, 651c48b2b330f8bf0e01381e27ca36f48ef5c7d8d5fvandebo@chromium.org face->bbox.xMax, face->bbox.yMin); 652c48b2b330f8bf0e01381e27ca36f48ef5c7d8d5fvandebo@chromium.org 6530f9bad01b0e7ad592ffb342dcf1d238b15329be1vandebo if (!FT_IS_SCALABLE(face)) { 654325cb9aa17b94258b362082eb3a799524f4345f3vandebo@chromium.org perGlyphInfo = SkAdvancedTypefaceMetrics::kNo_PerGlyphInfo; 655325cb9aa17b94258b362082eb3a799524f4345f3vandebo@chromium.org } 656325cb9aa17b94258b362082eb3a799524f4345f3vandebo@chromium.org 657325cb9aa17b94258b362082eb3a799524f4345f3vandebo@chromium.org if (perGlyphInfo & SkAdvancedTypefaceMetrics::kHAdvance_PerGlyphInfo) { 658c48b2b330f8bf0e01381e27ca36f48ef5c7d8d5fvandebo@chromium.org if (FT_IS_FIXED_WIDTH(face)) { 659c48b2b330f8bf0e01381e27ca36f48ef5c7d8d5fvandebo@chromium.org appendRange(&info->fGlyphWidths, 0); 660c48b2b330f8bf0e01381e27ca36f48ef5c7d8d5fvandebo@chromium.org int16_t advance = face->max_advance_width; 661c48b2b330f8bf0e01381e27ca36f48ef5c7d8d5fvandebo@chromium.org info->fGlyphWidths->fAdvance.append(1, &advance); 662c48b2b330f8bf0e01381e27ca36f48ef5c7d8d5fvandebo@chromium.org finishRange(info->fGlyphWidths.get(), 0, 663c48b2b330f8bf0e01381e27ca36f48ef5c7d8d5fvandebo@chromium.org SkAdvancedTypefaceMetrics::WidthRange::kDefault); 6646f72d1eacd66d2a9c0059962a75c0ca6a99ff98evandebo@chromium.org } else if (!cid) { 665c48b2b330f8bf0e01381e27ca36f48ef5c7d8d5fvandebo@chromium.org appendRange(&info->fGlyphWidths, 0); 666c48b2b330f8bf0e01381e27ca36f48ef5c7d8d5fvandebo@chromium.org // So as to not blow out the stack, get advances in batches. 667c48b2b330f8bf0e01381e27ca36f48ef5c7d8d5fvandebo@chromium.org for (int gID = 0; gID < face->num_glyphs; gID += 128) { 668c48b2b330f8bf0e01381e27ca36f48ef5c7d8d5fvandebo@chromium.org FT_Fixed advances[128]; 669c48b2b330f8bf0e01381e27ca36f48ef5c7d8d5fvandebo@chromium.org int advanceCount = 128; 670c48b2b330f8bf0e01381e27ca36f48ef5c7d8d5fvandebo@chromium.org if (gID + advanceCount > face->num_glyphs) 671b8aa4ddb2d8b2542b3fa4df28888bcd0fee51bd4bungeman@google.com advanceCount = face->num_glyphs - gID; 672c48b2b330f8bf0e01381e27ca36f48ef5c7d8d5fvandebo@chromium.org getAdvances(face, gID, advanceCount, FT_LOAD_NO_SCALE, 673c48b2b330f8bf0e01381e27ca36f48ef5c7d8d5fvandebo@chromium.org advances); 674c48b2b330f8bf0e01381e27ca36f48ef5c7d8d5fvandebo@chromium.org for (int i = 0; i < advanceCount; i++) { 675ce8a195111246e2f84d1414f78e6c2112d9f8ee9vandebo@chromium.org int16_t advance = advances[i]; 676c48b2b330f8bf0e01381e27ca36f48ef5c7d8d5fvandebo@chromium.org info->fGlyphWidths->fAdvance.append(1, &advance); 677c48b2b330f8bf0e01381e27ca36f48ef5c7d8d5fvandebo@chromium.org } 6782a22e10ab2946c5590cd2a258427ce3ccfca9bfavandebo@chromium.org } 679c48b2b330f8bf0e01381e27ca36f48ef5c7d8d5fvandebo@chromium.org finishRange(info->fGlyphWidths.get(), face->num_glyphs - 1, 680c48b2b330f8bf0e01381e27ca36f48ef5c7d8d5fvandebo@chromium.org SkAdvancedTypefaceMetrics::WidthRange::kRange); 681c48b2b330f8bf0e01381e27ca36f48ef5c7d8d5fvandebo@chromium.org } else { 6826f72d1eacd66d2a9c0059962a75c0ca6a99ff98evandebo@chromium.org info->fGlyphWidths.reset( 68337ad8fb72ff1b3faac93b01ead2c79e1a06fc172vandebo@chromium.org getAdvanceData(face, 68437ad8fb72ff1b3faac93b01ead2c79e1a06fc172vandebo@chromium.org face->num_glyphs, 68537ad8fb72ff1b3faac93b01ead2c79e1a06fc172vandebo@chromium.org glyphIDs, 68637ad8fb72ff1b3faac93b01ead2c79e1a06fc172vandebo@chromium.org glyphIDsCount, 68737ad8fb72ff1b3faac93b01ead2c79e1a06fc172vandebo@chromium.org &getWidthAdvance)); 6882a22e10ab2946c5590cd2a258427ce3ccfca9bfavandebo@chromium.org } 689325cb9aa17b94258b362082eb3a799524f4345f3vandebo@chromium.org } 6902a22e10ab2946c5590cd2a258427ce3ccfca9bfavandebo@chromium.org 691325cb9aa17b94258b362082eb3a799524f4345f3vandebo@chromium.org if (perGlyphInfo & SkAdvancedTypefaceMetrics::kVAdvance_PerGlyphInfo && 692325cb9aa17b94258b362082eb3a799524f4345f3vandebo@chromium.org FT_HAS_VERTICAL(face)) { 693325cb9aa17b94258b362082eb3a799524f4345f3vandebo@chromium.org SkASSERT(false); // Not implemented yet. 694325cb9aa17b94258b362082eb3a799524f4345f3vandebo@chromium.org } 695325cb9aa17b94258b362082eb3a799524f4345f3vandebo@chromium.org 696325cb9aa17b94258b362082eb3a799524f4345f3vandebo@chromium.org if (perGlyphInfo & SkAdvancedTypefaceMetrics::kGlyphNames_PerGlyphInfo && 697325cb9aa17b94258b362082eb3a799524f4345f3vandebo@chromium.org info->fType == SkAdvancedTypefaceMetrics::kType1_Font) { 698325cb9aa17b94258b362082eb3a799524f4345f3vandebo@chromium.org // Postscript fonts may contain more than 255 glyphs, so we end up 699325cb9aa17b94258b362082eb3a799524f4345f3vandebo@chromium.org // using multiple font descriptions with a glyph ordering. Record 700325cb9aa17b94258b362082eb3a799524f4345f3vandebo@chromium.org // the name of each glyph. 701325cb9aa17b94258b362082eb3a799524f4345f3vandebo@chromium.org info->fGlyphNames.reset( 702325cb9aa17b94258b362082eb3a799524f4345f3vandebo@chromium.org new SkAutoTArray<SkString>(face->num_glyphs)); 703325cb9aa17b94258b362082eb3a799524f4345f3vandebo@chromium.org for (int gID = 0; gID < face->num_glyphs; gID++) { 704325cb9aa17b94258b362082eb3a799524f4345f3vandebo@chromium.org char glyphName[128]; // PS limit for names is 127 bytes. 705325cb9aa17b94258b362082eb3a799524f4345f3vandebo@chromium.org FT_Get_Glyph_Name(face, gID, glyphName, 128); 706325cb9aa17b94258b362082eb3a799524f4345f3vandebo@chromium.org info->fGlyphNames->get()[gID].set(glyphName); 707c48b2b330f8bf0e01381e27ca36f48ef5c7d8d5fvandebo@chromium.org } 7082a22e10ab2946c5590cd2a258427ce3ccfca9bfavandebo@chromium.org } 7092a22e10ab2946c5590cd2a258427ce3ccfca9bfavandebo@chromium.org 7106744d498fcbbbcf503ec80c4d43dd8f118a88597vandebo@chromium.org if (perGlyphInfo & SkAdvancedTypefaceMetrics::kToUnicode_PerGlyphInfo && 7116744d498fcbbbcf503ec80c4d43dd8f118a88597vandebo@chromium.org info->fType != SkAdvancedTypefaceMetrics::kType1_Font && 7126744d498fcbbbcf503ec80c4d43dd8f118a88597vandebo@chromium.org face->num_charmaps) { 7136744d498fcbbbcf503ec80c4d43dd8f118a88597vandebo@chromium.org populate_glyph_to_unicode(face, &(info->fGlyphToUnicode)); 7146744d498fcbbbcf503ec80c4d43dd8f118a88597vandebo@chromium.org } 7156744d498fcbbbcf503ec80c4d43dd8f118a88597vandebo@chromium.org 7162a22e10ab2946c5590cd2a258427ce3ccfca9bfavandebo@chromium.org return info; 7178a5d692c034b4f027391b4e659c7562714f62804reed@google.com#endif 7182a22e10ab2946c5590cd2a258427ce3ccfca9bfavandebo@chromium.org} 71937ad8fb72ff1b3faac93b01ead2c79e1a06fc172vandebo@chromium.org 720618ef5ee3bc1fae284c766597fd518faabf7373dreed@google.com/////////////////////////////////////////////////////////////////////////// 721618ef5ee3bc1fae284c766597fd518faabf7373dreed@google.com 7228ed436c9b04548787442ddf3d7895a217b258fd5reed@google.comstatic bool bothZero(SkScalar a, SkScalar b) { 7238ed436c9b04548787442ddf3d7895a217b258fd5reed@google.com return 0 == a && 0 == b; 7248ed436c9b04548787442ddf3d7895a217b258fd5reed@google.com} 7258ed436c9b04548787442ddf3d7895a217b258fd5reed@google.com 7268ed436c9b04548787442ddf3d7895a217b258fd5reed@google.com// returns false if there is any non-90-rotation or skew 7278ed436c9b04548787442ddf3d7895a217b258fd5reed@google.comstatic bool isAxisAligned(const SkScalerContext::Rec& rec) { 7288ed436c9b04548787442ddf3d7895a217b258fd5reed@google.com return 0 == rec.fPreSkewX && 7298ed436c9b04548787442ddf3d7895a217b258fd5reed@google.com (bothZero(rec.fPost2x2[0][1], rec.fPost2x2[1][0]) || 7308ed436c9b04548787442ddf3d7895a217b258fd5reed@google.com bothZero(rec.fPost2x2[0][0], rec.fPost2x2[1][1])); 7318ed436c9b04548787442ddf3d7895a217b258fd5reed@google.com} 7328ed436c9b04548787442ddf3d7895a217b258fd5reed@google.com 7330da48618a758ef46c2174bdc1eaeb6dd8a693a2ereed@google.comSkScalerContext* SkTypeface_FreeType::onCreateScalerContext( 7340da48618a758ef46c2174bdc1eaeb6dd8a693a2ereed@google.com const SkDescriptor* desc) const { 7350da48618a758ef46c2174bdc1eaeb6dd8a693a2ereed@google.com SkScalerContext_FreeType* c = SkNEW_ARGS(SkScalerContext_FreeType, 7360da48618a758ef46c2174bdc1eaeb6dd8a693a2ereed@google.com (const_cast<SkTypeface_FreeType*>(this), 7370da48618a758ef46c2174bdc1eaeb6dd8a693a2ereed@google.com desc)); 7380da48618a758ef46c2174bdc1eaeb6dd8a693a2ereed@google.com if (!c->success()) { 7390da48618a758ef46c2174bdc1eaeb6dd8a693a2ereed@google.com SkDELETE(c); 7400da48618a758ef46c2174bdc1eaeb6dd8a693a2ereed@google.com c = NULL; 7410da48618a758ef46c2174bdc1eaeb6dd8a693a2ereed@google.com } 7420da48618a758ef46c2174bdc1eaeb6dd8a693a2ereed@google.com return c; 7430da48618a758ef46c2174bdc1eaeb6dd8a693a2ereed@google.com} 7440da48618a758ef46c2174bdc1eaeb6dd8a693a2ereed@google.com 7450da48618a758ef46c2174bdc1eaeb6dd8a693a2ereed@google.comvoid SkTypeface_FreeType::onFilterRec(SkScalerContextRec* rec) const { 7468cf322666faaba298ca66b0acfe32c634c308e2fbungeman@google.com //BOGUS: http://code.google.com/p/chromium/issues/detail?id=121119 7478cf322666faaba298ca66b0acfe32c634c308e2fbungeman@google.com //Cap the requested size as larger sizes give bogus values. 7488cf322666faaba298ca66b0acfe32c634c308e2fbungeman@google.com //Remove when http://code.google.com/p/skia/issues/detail?id=554 is fixed. 7495582e63606cf23fefeef652ad556b0a998467e0cbungeman@google.com if (rec->fTextSize > SkIntToScalar(1 << 14)) { 75094bc60f9864094edbfb787b09c963d8818c8962fscroggo@google.com rec->fTextSize = SkIntToScalar(1 << 14); 7518cf322666faaba298ca66b0acfe32c634c308e2fbungeman@google.com } 752a27096b4740775ae141fd0abaf456d706065c5eeskia.committer@gmail.com 753fb2fdcca206fbcac6254a9524c2d06dc98dd5421reed@google.com if (!is_lcd_supported() && isLCD(*rec)) { 754618ef5ee3bc1fae284c766597fd518faabf7373dreed@google.com // If the runtime Freetype library doesn't support LCD mode, we disable 755618ef5ee3bc1fae284c766597fd518faabf7373dreed@google.com // it here. 756618ef5ee3bc1fae284c766597fd518faabf7373dreed@google.com rec->fMaskFormat = SkMask::kA8_Format; 757618ef5ee3bc1fae284c766597fd518faabf7373dreed@google.com } 7585b31b0f1eaca0cdc3aa5697e8efa1baf68b0774ereed@google.com 759618ef5ee3bc1fae284c766597fd518faabf7373dreed@google.com SkPaint::Hinting h = rec->getHinting(); 760effc5016f040945a53ab0ea47f9ea02404c17805reed@google.com if (SkPaint::kFull_Hinting == h && !isLCD(*rec)) { 761618ef5ee3bc1fae284c766597fd518faabf7373dreed@google.com // collapse full->normal hinting if we're not doing LCD 762618ef5ee3bc1fae284c766597fd518faabf7373dreed@google.com h = SkPaint::kNormal_Hinting; 763618ef5ee3bc1fae284c766597fd518faabf7373dreed@google.com } 764f4f2b8010a6e733f0ecbacef4a3ede570dca883abungeman@google.com if ((rec->fFlags & SkScalerContext::kSubpixelPositioning_Flag)) { 7651ac8350821f5343333e48f000df5b5106b6f7497reed@google.com if (SkPaint::kNo_Hinting != h) { 7661ac8350821f5343333e48f000df5b5106b6f7497reed@google.com h = SkPaint::kSlight_Hinting; 7671ac8350821f5343333e48f000df5b5106b6f7497reed@google.com } 7681ac8350821f5343333e48f000df5b5106b6f7497reed@google.com } 7691ac8350821f5343333e48f000df5b5106b6f7497reed@google.com 7708ed436c9b04548787442ddf3d7895a217b258fd5reed@google.com // rotated text looks bad with hinting, so we disable it as needed 7718ed436c9b04548787442ddf3d7895a217b258fd5reed@google.com if (!isAxisAligned(*rec)) { 7728ed436c9b04548787442ddf3d7895a217b258fd5reed@google.com h = SkPaint::kNo_Hinting; 7738ed436c9b04548787442ddf3d7895a217b258fd5reed@google.com } 774618ef5ee3bc1fae284c766597fd518faabf7373dreed@google.com rec->setHinting(h); 775ffe49f5380dd5062073efeda70f2f91682c828careed@google.com 77697efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com#ifndef SK_GAMMA_APPLY_TO_A8 77797efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com if (!isLCD(*rec)) { 77897efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com rec->ignorePreBlend(); 779ffe49f5380dd5062073efeda70f2f91682c828careed@google.com } 7801ac8350821f5343333e48f000df5b5106b6f7497reed@google.com#endif 781618ef5ee3bc1fae284c766597fd518faabf7373dreed@google.com} 7822a22e10ab2946c5590cd2a258427ce3ccfca9bfavandebo@chromium.org 78338c37ddbaf3b29cdacbc25d4aa2acca1869d276freed@google.comint SkTypeface_FreeType::onGetUPEM() const { 784b4162b12b1e8e38c48b328f819c97199a0825d2breed@google.com AutoFTAccess fta(this); 785b4162b12b1e8e38c48b328f819c97199a0825d2breed@google.com FT_Face face = fta.face(); 786b4162b12b1e8e38c48b328f819c97199a0825d2breed@google.com return face ? face->units_per_EM : 0; 787cd9d69b9ce7eb301a9fd8d91b9f95fd99b07bae5djsollen@google.com} 788cd9d69b9ce7eb301a9fd8d91b9f95fd99b07bae5djsollen@google.com 78935fe7372b1b897a77578a220c334e1fb36d144e9reed@google.combool SkTypeface_FreeType::onGetKerningPairAdjustments(const uint16_t glyphs[], 79035fe7372b1b897a77578a220c334e1fb36d144e9reed@google.com int count, int32_t adjustments[]) const { 79135fe7372b1b897a77578a220c334e1fb36d144e9reed@google.com AutoFTAccess fta(this); 79235fe7372b1b897a77578a220c334e1fb36d144e9reed@google.com FT_Face face = fta.face(); 79335fe7372b1b897a77578a220c334e1fb36d144e9reed@google.com if (!face || !FT_HAS_KERNING(face)) { 79435fe7372b1b897a77578a220c334e1fb36d144e9reed@google.com return false; 79535fe7372b1b897a77578a220c334e1fb36d144e9reed@google.com } 79635fe7372b1b897a77578a220c334e1fb36d144e9reed@google.com 79735fe7372b1b897a77578a220c334e1fb36d144e9reed@google.com for (int i = 0; i < count - 1; ++i) { 79835fe7372b1b897a77578a220c334e1fb36d144e9reed@google.com FT_Vector delta; 79935fe7372b1b897a77578a220c334e1fb36d144e9reed@google.com FT_Error err = FT_Get_Kerning(face, glyphs[i], glyphs[i+1], 80035fe7372b1b897a77578a220c334e1fb36d144e9reed@google.com FT_KERNING_UNSCALED, &delta); 80135fe7372b1b897a77578a220c334e1fb36d144e9reed@google.com if (err) { 80235fe7372b1b897a77578a220c334e1fb36d144e9reed@google.com return false; 80335fe7372b1b897a77578a220c334e1fb36d144e9reed@google.com } 80435fe7372b1b897a77578a220c334e1fb36d144e9reed@google.com adjustments[i] = delta.x; 80535fe7372b1b897a77578a220c334e1fb36d144e9reed@google.com } 80635fe7372b1b897a77578a220c334e1fb36d144e9reed@google.com return true; 80735fe7372b1b897a77578a220c334e1fb36d144e9reed@google.com} 80835fe7372b1b897a77578a220c334e1fb36d144e9reed@google.com 809c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.comstatic FT_Int chooseBitmapStrike(FT_Face face, SkFixed scaleY) { 810c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com // early out if face is bad 811c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com if (face == NULL) { 812c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com SkDEBUGF(("chooseBitmapStrike aborted due to NULL face\n")); 813c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com return -1; 814c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com } 815c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com // determine target ppem 816c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com FT_Pos targetPPEM = SkFixedToFDot6(scaleY); 817c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com // find a bitmap strike equal to or just larger than the requested size 818c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com FT_Int chosenStrikeIndex = -1; 819c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com FT_Pos chosenPPEM = 0; 820c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com for (FT_Int strikeIndex = 0; strikeIndex < face->num_fixed_sizes; ++strikeIndex) { 821c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com FT_Pos thisPPEM = face->available_sizes[strikeIndex].y_ppem; 822c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com if (thisPPEM == targetPPEM) { 823c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com // exact match - our search stops here 824c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com chosenPPEM = thisPPEM; 825c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com chosenStrikeIndex = strikeIndex; 826c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com break; 827c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com } else if (chosenPPEM < targetPPEM) { 828c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com // attempt to increase chosenPPEM 829c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com if (thisPPEM > chosenPPEM) { 830c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com chosenPPEM = thisPPEM; 831c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com chosenStrikeIndex = strikeIndex; 832c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com } 833c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com } else { 834c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com // attempt to decrease chosenPPEM, but not below targetPPEM 835c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com if (thisPPEM < chosenPPEM && thisPPEM > targetPPEM) { 836c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com chosenPPEM = thisPPEM; 837c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com chosenStrikeIndex = strikeIndex; 838c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com } 839c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com } 840c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com } 841c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com if (chosenStrikeIndex != -1) { 842c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com // use the chosen strike 843c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com FT_Error err = FT_Select_Size(face, chosenStrikeIndex); 844c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com if (err != 0) { 845c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com SkDEBUGF(("FT_Select_Size(%s, %d) returned 0x%x\n", face->family_name, 846c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com chosenStrikeIndex, err)); 847c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com chosenStrikeIndex = -1; 848c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com } 849c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com } 850c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com return chosenStrikeIndex; 851c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com} 852c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com 8530da48618a758ef46c2174bdc1eaeb6dd8a693a2ereed@google.comSkScalerContext_FreeType::SkScalerContext_FreeType(SkTypeface* typeface, 8540da48618a758ef46c2174bdc1eaeb6dd8a693a2ereed@google.com const SkDescriptor* desc) 8550da48618a758ef46c2174bdc1eaeb6dd8a693a2ereed@google.com : SkScalerContext_FreeType_Base(typeface, desc) { 8568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkAutoMutexAcquire ac(gFTMutex); 8578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 8588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (gFTCount == 0) { 859659aaf9e9a3f139ee2a1ce4a49f06fc74f430703reed@android.com if (!InitFreetype()) { 860659aaf9e9a3f139ee2a1ce4a49f06fc74f430703reed@android.com sk_throw(); 861659aaf9e9a3f139ee2a1ce4a49f06fc74f430703reed@android.com } 8628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 8638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ++gFTCount; 8648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 8658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // load the font file 866c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com fStrikeIndex = -1; 86762900b4c64401bc80ae85f6f5c87309a273cae10reed@android.com fFTSize = NULL; 86862900b4c64401bc80ae85f6f5c87309a273cae10reed@android.com fFace = NULL; 8692cdc6713fb04c46ecbc73a724029a8b266004ddfreed@google.com fFaceRec = ref_ft_face(typeface); 87062900b4c64401bc80ae85f6f5c87309a273cae10reed@android.com if (NULL == fFaceRec) { 87162900b4c64401bc80ae85f6f5c87309a273cae10reed@android.com return; 87262900b4c64401bc80ae85f6f5c87309a273cae10reed@android.com } 87362900b4c64401bc80ae85f6f5c87309a273cae10reed@android.com fFace = fFaceRec->fFace; 8748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 875d3fbd34099a530b5415c95b1f2f8149ac417b9b3bungeman@google.com // A is the total matrix. 876d3fbd34099a530b5415c95b1f2f8149ac417b9b3bungeman@google.com SkMatrix A; 877d3fbd34099a530b5415c95b1f2f8149ac417b9b3bungeman@google.com fRec.getSingleMatrix(&A); 8788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 879d3fbd34099a530b5415c95b1f2f8149ac417b9b3bungeman@google.com SkScalar sx = A.getScaleX(); 880d3fbd34099a530b5415c95b1f2f8149ac417b9b3bungeman@google.com SkScalar sy = A.getScaleY(); 881f073b3332d7c9f7dba6bcf7eb93708593a90036creed@google.com fMatrix22Scalar.reset(); 882f073b3332d7c9f7dba6bcf7eb93708593a90036creed@google.com 883d3fbd34099a530b5415c95b1f2f8149ac417b9b3bungeman@google.com // In GDI, the hinter is aware of the current transformation 884d3fbd34099a530b5415c95b1f2f8149ac417b9b3bungeman@google.com // (the transform is in some sense applied before/with the hinting). 885d3fbd34099a530b5415c95b1f2f8149ac417b9b3bungeman@google.com // The bytecode can then test if it is rotated or stretched and decide 886d3fbd34099a530b5415c95b1f2f8149ac417b9b3bungeman@google.com // to apply instructions or not. 887d3fbd34099a530b5415c95b1f2f8149ac417b9b3bungeman@google.com // 888d3fbd34099a530b5415c95b1f2f8149ac417b9b3bungeman@google.com // FreeType, however, always does the transformation strictly after hinting. 889d3fbd34099a530b5415c95b1f2f8149ac417b9b3bungeman@google.com // It just sets 'rotated' and 'stretched' to false and only applies the 890d3fbd34099a530b5415c95b1f2f8149ac417b9b3bungeman@google.com // size before hinting. 891d3fbd34099a530b5415c95b1f2f8149ac417b9b3bungeman@google.com // 892d3fbd34099a530b5415c95b1f2f8149ac417b9b3bungeman@google.com // Also, FreeType respects the head::flags::IntegerScaling flag, 893d3fbd34099a530b5415c95b1f2f8149ac417b9b3bungeman@google.com // (although this is patched out on most major distros) 894d3fbd34099a530b5415c95b1f2f8149ac417b9b3bungeman@google.com // so it is critical to get the size correct on the request. 895d3fbd34099a530b5415c95b1f2f8149ac417b9b3bungeman@google.com // 896d3fbd34099a530b5415c95b1f2f8149ac417b9b3bungeman@google.com // This also gets us the actual closest size on bitmap fonts as well. 897d3fbd34099a530b5415c95b1f2f8149ac417b9b3bungeman@google.com if (A.getSkewX() || A.getSkewY() || sx < 0 || sy < 0) { 898d3fbd34099a530b5415c95b1f2f8149ac417b9b3bungeman@google.com // h is where A maps the horizontal baseline. 899d3fbd34099a530b5415c95b1f2f8149ac417b9b3bungeman@google.com SkPoint h = SkPoint::Make(SK_Scalar1, 0); 900d3fbd34099a530b5415c95b1f2f8149ac417b9b3bungeman@google.com A.mapPoints(&h, 1); 901d3fbd34099a530b5415c95b1f2f8149ac417b9b3bungeman@google.com 902d3fbd34099a530b5415c95b1f2f8149ac417b9b3bungeman@google.com // G is the Givens Matrix for A (rotational matrix where GA[0][1] == 0). 903d3fbd34099a530b5415c95b1f2f8149ac417b9b3bungeman@google.com SkMatrix G; 904d3fbd34099a530b5415c95b1f2f8149ac417b9b3bungeman@google.com SkComputeGivensRotation(h, &G); 905d3fbd34099a530b5415c95b1f2f8149ac417b9b3bungeman@google.com 906d3fbd34099a530b5415c95b1f2f8149ac417b9b3bungeman@google.com // GA is the matrix A with rotation removed. 907d3fbd34099a530b5415c95b1f2f8149ac417b9b3bungeman@google.com SkMatrix GA(G); 908d3fbd34099a530b5415c95b1f2f8149ac417b9b3bungeman@google.com GA.preConcat(A); 909d3fbd34099a530b5415c95b1f2f8149ac417b9b3bungeman@google.com 910d3fbd34099a530b5415c95b1f2f8149ac417b9b3bungeman@google.com sx = SkScalarAbs(GA.get(SkMatrix::kMScaleX)); 911d3fbd34099a530b5415c95b1f2f8149ac417b9b3bungeman@google.com sy = SkScalarAbs(GA.get(SkMatrix::kMScaleY)); 912d3fbd34099a530b5415c95b1f2f8149ac417b9b3bungeman@google.com 913d3fbd34099a530b5415c95b1f2f8149ac417b9b3bungeman@google.com // sA is the total matrix A without the text scale. 914d3fbd34099a530b5415c95b1f2f8149ac417b9b3bungeman@google.com SkMatrix sA(A); 915d3fbd34099a530b5415c95b1f2f8149ac417b9b3bungeman@google.com sA.preScale(SkScalarInvert(sx), SkScalarInvert(sy)); //remove text size 916d3fbd34099a530b5415c95b1f2f8149ac417b9b3bungeman@google.com 917d3fbd34099a530b5415c95b1f2f8149ac417b9b3bungeman@google.com fMatrix22Scalar.setScaleX(sA.getScaleX()); 918d3fbd34099a530b5415c95b1f2f8149ac417b9b3bungeman@google.com fMatrix22Scalar.setSkewX(-sA.getSkewX()); 919d3fbd34099a530b5415c95b1f2f8149ac417b9b3bungeman@google.com fMatrix22Scalar.setSkewY(-sA.getSkewY()); 920d3fbd34099a530b5415c95b1f2f8149ac417b9b3bungeman@google.com fMatrix22Scalar.setScaleY(sA.getScaleY()); 921d3fbd34099a530b5415c95b1f2f8149ac417b9b3bungeman@google.com } 922d3fbd34099a530b5415c95b1f2f8149ac417b9b3bungeman@google.com fScale.set(sx, sy); 923d3fbd34099a530b5415c95b1f2f8149ac417b9b3bungeman@google.com fScaleX = SkScalarToFixed(sx); 924d3fbd34099a530b5415c95b1f2f8149ac417b9b3bungeman@google.com fScaleY = SkScalarToFixed(sy); 925d3fbd34099a530b5415c95b1f2f8149ac417b9b3bungeman@google.com fMatrix22.xx = SkScalarToFixed(fMatrix22Scalar.getScaleX()); 926d3fbd34099a530b5415c95b1f2f8149ac417b9b3bungeman@google.com fMatrix22.xy = SkScalarToFixed(fMatrix22Scalar.getSkewX()); 927d3fbd34099a530b5415c95b1f2f8149ac417b9b3bungeman@google.com fMatrix22.yx = SkScalarToFixed(fMatrix22Scalar.getSkewY()); 928d3fbd34099a530b5415c95b1f2f8149ac417b9b3bungeman@google.com fMatrix22.yy = SkScalarToFixed(fMatrix22Scalar.getScaleY()); 9298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 930a1bfa214c55fc1332a43c0343c909549f4178d05reed@google.com fLCDIsVert = SkToBool(fRec.fFlags & SkScalerContext::kLCD_Vertical_Flag); 931a1bfa214c55fc1332a43c0343c909549f4178d05reed@google.com 9328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // compute the flags we send to Load_Glyph 933c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com bool linearMetrics = SkToBool(fRec.fFlags & SkScalerContext::kSubpixelPositioning_Flag); 9348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com { 935e4d0bc0b57bd2236ed591d2c505556963777156breed@android.com FT_Int32 loadFlags = FT_LOAD_DEFAULT; 9368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 93770a303f3c949707ce36ed2847701571cd047f14eagl@chromium.org if (SkMask::kBW_Format == fRec.fMaskFormat) { 93870a303f3c949707ce36ed2847701571cd047f14eagl@chromium.org // See http://code.google.com/p/chromium/issues/detail?id=43252#c24 93970a303f3c949707ce36ed2847701571cd047f14eagl@chromium.org loadFlags = FT_LOAD_TARGET_MONO; 940effc5016f040945a53ab0ea47f9ea02404c17805reed@google.com if (fRec.getHinting() == SkPaint::kNo_Hinting) { 94170a303f3c949707ce36ed2847701571cd047f14eagl@chromium.org loadFlags = FT_LOAD_NO_HINTING; 942bdc9988bf238fc752826c313807044bca4e0b448reed@google.com linearMetrics = true; 943effc5016f040945a53ab0ea47f9ea02404c17805reed@google.com } 94470a303f3c949707ce36ed2847701571cd047f14eagl@chromium.org } else { 94570a303f3c949707ce36ed2847701571cd047f14eagl@chromium.org switch (fRec.getHinting()) { 94670a303f3c949707ce36ed2847701571cd047f14eagl@chromium.org case SkPaint::kNo_Hinting: 94770a303f3c949707ce36ed2847701571cd047f14eagl@chromium.org loadFlags = FT_LOAD_NO_HINTING; 948bdc9988bf238fc752826c313807044bca4e0b448reed@google.com linearMetrics = true; 94970a303f3c949707ce36ed2847701571cd047f14eagl@chromium.org break; 95070a303f3c949707ce36ed2847701571cd047f14eagl@chromium.org case SkPaint::kSlight_Hinting: 95170a303f3c949707ce36ed2847701571cd047f14eagl@chromium.org loadFlags = FT_LOAD_TARGET_LIGHT; // This implies FORCE_AUTOHINT 95270a303f3c949707ce36ed2847701571cd047f14eagl@chromium.org break; 95370a303f3c949707ce36ed2847701571cd047f14eagl@chromium.org case SkPaint::kNormal_Hinting: 954f6f56878bc96386882721b15ba610984185d3dc9bungeman@google.com if (fRec.fFlags & SkScalerContext::kForceAutohinting_Flag) { 955a2c71cbd51da8b7767d43fe8954e7a4c674b2005agl@chromium.org loadFlags = FT_LOAD_FORCE_AUTOHINT; 956858a78912473a60b77f23618859670f721adcec9djsollen#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK 957858a78912473a60b77f23618859670f721adcec9djsollen } else { 958858a78912473a60b77f23618859670f721adcec9djsollen loadFlags = FT_LOAD_NO_AUTOHINT; 959858a78912473a60b77f23618859670f721adcec9djsollen#endif 960f6f56878bc96386882721b15ba610984185d3dc9bungeman@google.com } 96170a303f3c949707ce36ed2847701571cd047f14eagl@chromium.org break; 96270a303f3c949707ce36ed2847701571cd047f14eagl@chromium.org case SkPaint::kFull_Hinting: 963f6f56878bc96386882721b15ba610984185d3dc9bungeman@google.com if (fRec.fFlags & SkScalerContext::kForceAutohinting_Flag) { 964a2c71cbd51da8b7767d43fe8954e7a4c674b2005agl@chromium.org loadFlags = FT_LOAD_FORCE_AUTOHINT; 965a2c71cbd51da8b7767d43fe8954e7a4c674b2005agl@chromium.org break; 966a2c71cbd51da8b7767d43fe8954e7a4c674b2005agl@chromium.org } 96770a303f3c949707ce36ed2847701571cd047f14eagl@chromium.org loadFlags = FT_LOAD_TARGET_NORMAL; 968effc5016f040945a53ab0ea47f9ea02404c17805reed@google.com if (isLCD(fRec)) { 969a1bfa214c55fc1332a43c0343c909549f4178d05reed@google.com if (fLCDIsVert) { 970effc5016f040945a53ab0ea47f9ea02404c17805reed@google.com loadFlags = FT_LOAD_TARGET_LCD_V; 971effc5016f040945a53ab0ea47f9ea02404c17805reed@google.com } else { 972effc5016f040945a53ab0ea47f9ea02404c17805reed@google.com loadFlags = FT_LOAD_TARGET_LCD; 973effc5016f040945a53ab0ea47f9ea02404c17805reed@google.com } 974ea2333de1e93da38045111560295ef825be99956reed@google.com } 97570a303f3c949707ce36ed2847701571cd047f14eagl@chromium.org break; 97670a303f3c949707ce36ed2847701571cd047f14eagl@chromium.org default: 97770a303f3c949707ce36ed2847701571cd047f14eagl@chromium.org SkDebugf("---------- UNKNOWN hinting %d\n", fRec.getHinting()); 97870a303f3c949707ce36ed2847701571cd047f14eagl@chromium.org break; 97970a303f3c949707ce36ed2847701571cd047f14eagl@chromium.org } 9808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 9818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 982effc5016f040945a53ab0ea47f9ea02404c17805reed@google.com if ((fRec.fFlags & SkScalerContext::kEmbeddedBitmapText_Flag) == 0) { 983e0d089900e898cdb834d48e3062622008d9da687agl@chromium.org loadFlags |= FT_LOAD_NO_BITMAP; 984effc5016f040945a53ab0ea47f9ea02404c17805reed@google.com } 985e0d089900e898cdb834d48e3062622008d9da687agl@chromium.org 98696a9f791f2dbad2671db4f5270416c1e74fc8ec6reed@google.com // Always using FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH to get correct 98796a9f791f2dbad2671db4f5270416c1e74fc8ec6reed@google.com // advances, as fontconfig and cairo do. 98896a9f791f2dbad2671db4f5270416c1e74fc8ec6reed@google.com // See http://code.google.com/p/skia/issues/detail?id=222. 98996a9f791f2dbad2671db4f5270416c1e74fc8ec6reed@google.com loadFlags |= FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH; 99096a9f791f2dbad2671db4f5270416c1e74fc8ec6reed@google.com 9918ff8a1959f514b969198ec2242c7de57fbf413cdbungeman@google.com // Use vertical layout if requested. 9928ff8a1959f514b969198ec2242c7de57fbf413cdbungeman@google.com if (fRec.fFlags & SkScalerContext::kVertical_Flag) { 9938ff8a1959f514b969198ec2242c7de57fbf413cdbungeman@google.com loadFlags |= FT_LOAD_VERTICAL_LAYOUT; 9948ff8a1959f514b969198ec2242c7de57fbf413cdbungeman@google.com } 9958ff8a1959f514b969198ec2242c7de57fbf413cdbungeman@google.com 996c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com loadFlags |= FT_LOAD_COLOR; 997c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com 998e4d0bc0b57bd2236ed591d2c505556963777156breed@android.com fLoadGlyphFlags = loadFlags; 9998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 10008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1001c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com FT_Error err = FT_New_Size(fFace, &fFTSize); 1002c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com if (err != 0) { 1003c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com SkDEBUGF(("FT_New_Size returned %x for face %s\n", err, fFace->family_name)); 1004c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com fFace = NULL; 1005c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com return; 1006c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com } 1007c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com err = FT_Activate_Size(fFTSize); 1008c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com if (err != 0) { 1009c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com SkDEBUGF(("FT_Activate_Size(%08x, 0x%x, 0x%x) returned 0x%x\n", fFace, fScaleX, fScaleY, 1010c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com err)); 1011c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com fFTSize = NULL; 1012c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com return; 1013c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com } 10148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1015c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com if (FT_IS_SCALABLE(fFace)) { 1016c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com err = FT_Set_Char_Size(fFace, SkFixedToFDot6(fScaleX), SkFixedToFDot6(fScaleY), 72, 72); 10178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (err != 0) { 1018c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com SkDEBUGF(("FT_Set_CharSize(%08x, 0x%x, 0x%x) returned 0x%x\n", 1019c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com fFace, fScaleX, fScaleY, err)); 10208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fFace = NULL; 10218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 10228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1023c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com FT_Set_Transform(fFace, &fMatrix22, NULL); 1024c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com } else if (FT_HAS_FIXED_SIZES(fFace)) { 1025c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com fStrikeIndex = chooseBitmapStrike(fFace, fScaleY); 1026c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com if (fStrikeIndex == -1) { 1027c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com SkDEBUGF(("no glyphs for font \"%s\" size %f?\n", 1028c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com fFace->family_name, SkFixedToScalar(fScaleY))); 1029c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com } else { 1030c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com // FreeType does no provide linear metrics for bitmap fonts. 1031c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com linearMetrics = false; 1032c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com 1033c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com // FreeType documentation says: 1034c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com // FT_LOAD_NO_BITMAP -- Ignore bitmap strikes when loading. 1035c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com // Bitmap-only fonts ignore this flag. 1036c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com // 1037c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com // However, in FreeType 2.5.1 color bitmap only fonts do not ignore this flag. 1038c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com // Force this flag off for bitmap only fonts. 1039c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com fLoadGlyphFlags &= ~FT_LOAD_NO_BITMAP; 10408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1041c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com } else { 1042c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com SkDEBUGF(("unknown kind of font \"%s\" size %f?\n", 1043c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com fFace->family_name, SkFixedToScalar(fScaleY))); 10448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1045c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com 1046c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com fDoLinearMetrics = linearMetrics; 10478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 10488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 10498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkScalerContext_FreeType::~SkScalerContext_FreeType() { 105094bc60f9864094edbfb787b09c963d8818c8962fscroggo@google.com SkAutoMutexAcquire ac(gFTMutex); 105194bc60f9864094edbfb787b09c963d8818c8962fscroggo@google.com 10528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (fFTSize != NULL) { 10538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com FT_Done_Size(fFTSize); 10548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 10558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 10568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (fFace != NULL) { 10578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com unref_ft_face(fFace); 10588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 10598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (--gFTCount == 0) { 10608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com FT_Done_FreeType(gFTLibrary); 10618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDEBUGCODE(gFTLibrary = NULL;) 10628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 10638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 10648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 10658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/* We call this before each use of the fFace, since we may be sharing 10668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this face with other context (at different sizes). 10678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com*/ 10688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comFT_Error SkScalerContext_FreeType::setupSize() { 1069c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com FT_Error err = FT_Activate_Size(fFTSize); 10708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (err != 0) { 10718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDEBUGF(("SkScalerContext_FreeType::FT_Activate_Size(%x, 0x%x, 0x%x) returned 0x%x\n", 1072c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com fFaceRec->fFontID, fScaleX, fScaleY, err)); 10738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fFTSize = NULL; 1074c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com return err; 10758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1076c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com 1077c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com // seems we need to reset this every time (not sure why, but without it 1078c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com // I get random italics from some other fFTSize) 1079c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com FT_Set_Transform(fFace, &fMatrix22, NULL); 1080c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com return 0; 10818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 10828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 10830bc7bf5fe418191473f8325d89dd9e74be3ff928ctguil@chromium.orgunsigned SkScalerContext_FreeType::generateGlyphCount() { 10848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return fFace->num_glyphs; 10858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 10868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 10878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comuint16_t SkScalerContext_FreeType::generateCharToGlyph(SkUnichar uni) { 10888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return SkToU16(FT_Get_Char_Index( fFace, uni )); 10898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 10908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 10919d3a985aa3c82605346ed1518375a8c384b925e5reed@android.comSkUnichar SkScalerContext_FreeType::generateGlyphToChar(uint16_t glyph) { 10929d3a985aa3c82605346ed1518375a8c384b925e5reed@android.com // iterate through each cmap entry, looking for matching glyph indices 10939d3a985aa3c82605346ed1518375a8c384b925e5reed@android.com FT_UInt glyphIndex; 10949d3a985aa3c82605346ed1518375a8c384b925e5reed@android.com SkUnichar charCode = FT_Get_First_Char( fFace, &glyphIndex ); 10959d3a985aa3c82605346ed1518375a8c384b925e5reed@android.com 10969d3a985aa3c82605346ed1518375a8c384b925e5reed@android.com while (glyphIndex != 0) { 10979d3a985aa3c82605346ed1518375a8c384b925e5reed@android.com if (glyphIndex == glyph) { 10989d3a985aa3c82605346ed1518375a8c384b925e5reed@android.com return charCode; 10999d3a985aa3c82605346ed1518375a8c384b925e5reed@android.com } 11009d3a985aa3c82605346ed1518375a8c384b925e5reed@android.com charCode = FT_Get_Next_Char( fFace, charCode, &glyphIndex ); 11019d3a985aa3c82605346ed1518375a8c384b925e5reed@android.com } 11029d3a985aa3c82605346ed1518375a8c384b925e5reed@android.com 11039d3a985aa3c82605346ed1518375a8c384b925e5reed@android.com return 0; 11049d3a985aa3c82605346ed1518375a8c384b925e5reed@android.com} 11059d3a985aa3c82605346ed1518375a8c384b925e5reed@android.com 11068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkScalerContext_FreeType::generateAdvance(SkGlyph* glyph) { 11078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifdef FT_ADVANCES_H 11088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com /* unhinted and light hinted text have linearly scaled advances 11098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com * which are very cheap to compute with some font formats... 11108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */ 1111bdc9988bf238fc752826c313807044bca4e0b448reed@google.com if (fDoLinearMetrics) { 11128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkAutoMutexAcquire ac(gFTMutex); 11138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 11148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (this->setupSize()) { 111562900b4c64401bc80ae85f6f5c87309a273cae10reed@android.com glyph->zeroMetrics(); 11168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 11178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 11188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 11198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com FT_Error error; 11208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com FT_Fixed advance; 11218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 11221b27704eba15be4e9d1997faac42038493a30be5djsollen error = FT_Get_Advance( fFace, glyph->getGlyphID(), 11238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fLoadGlyphFlags | FT_ADVANCE_FLAG_FAST_ONLY, 11248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com &advance ); 11258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (0 == error) { 11268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com glyph->fRsbDelta = 0; 11278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com glyph->fLsbDelta = 0; 1128d074c3709afa6ea70888262a402603197d71dd11reed@google.com glyph->fAdvanceX = SkFixedMul(fMatrix22.xx, advance); 1129d074c3709afa6ea70888262a402603197d71dd11reed@google.com glyph->fAdvanceY = - SkFixedMul(fMatrix22.yx, advance); 11308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 11318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 11328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 11338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif /* FT_ADVANCES_H */ 11348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com /* otherwise, we need to load/hint the glyph, which is slower */ 11358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->generateMetrics(glyph); 11368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 11378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 11388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1139d8b599cb264b2228e0fb1bee6d3604be6d3c2855djsollen@google.comvoid SkScalerContext_FreeType::getBBoxForCurrentGlyph(SkGlyph* glyph, 1140d8b599cb264b2228e0fb1bee6d3604be6d3c2855djsollen@google.com FT_BBox* bbox, 1141d8b599cb264b2228e0fb1bee6d3604be6d3c2855djsollen@google.com bool snapToPixelBoundary) { 1142d8b599cb264b2228e0fb1bee6d3604be6d3c2855djsollen@google.com 1143d8b599cb264b2228e0fb1bee6d3604be6d3c2855djsollen@google.com FT_Outline_Get_CBox(&fFace->glyph->outline, bbox); 1144d8b599cb264b2228e0fb1bee6d3604be6d3c2855djsollen@google.com 1145d8b599cb264b2228e0fb1bee6d3604be6d3c2855djsollen@google.com if (fRec.fFlags & SkScalerContext::kSubpixelPositioning_Flag) { 1146c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.com int dx = SkFixedToFDot6(glyph->getSubXFixed()); 1147c59b5dac9081e3613ed80d8b6d498e093c03eb87george@mozilla.com int dy = SkFixedToFDot6(glyph->getSubYFixed()); 1148d8b599cb264b2228e0fb1bee6d3604be6d3c2855djsollen@google.com // negate dy since freetype-y-goes-up and skia-y-goes-down 1149d8b599cb264b2228e0fb1bee6d3604be6d3c2855djsollen@google.com bbox->xMin += dx; 1150d8b599cb264b2228e0fb1bee6d3604be6d3c2855djsollen@google.com bbox->yMin -= dy; 1151d8b599cb264b2228e0fb1bee6d3604be6d3c2855djsollen@google.com bbox->xMax += dx; 1152d8b599cb264b2228e0fb1bee6d3604be6d3c2855djsollen@google.com bbox->yMax -= dy; 1153d8b599cb264b2228e0fb1bee6d3604be6d3c2855djsollen@google.com } 1154d8b599cb264b2228e0fb1bee6d3604be6d3c2855djsollen@google.com 1155d8b599cb264b2228e0fb1bee6d3604be6d3c2855djsollen@google.com // outset the box to integral boundaries 1156d8b599cb264b2228e0fb1bee6d3604be6d3c2855djsollen@google.com if (snapToPixelBoundary) { 1157d8b599cb264b2228e0fb1bee6d3604be6d3c2855djsollen@google.com bbox->xMin &= ~63; 1158d8b599cb264b2228e0fb1bee6d3604be6d3c2855djsollen@google.com bbox->yMin &= ~63; 1159d8b599cb264b2228e0fb1bee6d3604be6d3c2855djsollen@google.com bbox->xMax = (bbox->xMax + 63) & ~63; 1160d8b599cb264b2228e0fb1bee6d3604be6d3c2855djsollen@google.com bbox->yMax = (bbox->yMax + 63) & ~63; 1161d8b599cb264b2228e0fb1bee6d3604be6d3c2855djsollen@google.com } 11628ff8a1959f514b969198ec2242c7de57fbf413cdbungeman@google.com 11638ff8a1959f514b969198ec2242c7de57fbf413cdbungeman@google.com // Must come after snapToPixelBoundary so that the width and height are 11648ff8a1959f514b969198ec2242c7de57fbf413cdbungeman@google.com // consistent. Otherwise asserts will fire later on when generating the 11658ff8a1959f514b969198ec2242c7de57fbf413cdbungeman@google.com // glyph image. 11668ff8a1959f514b969198ec2242c7de57fbf413cdbungeman@google.com if (fRec.fFlags & SkScalerContext::kVertical_Flag) { 11678ff8a1959f514b969198ec2242c7de57fbf413cdbungeman@google.com FT_Vector vector; 11688ff8a1959f514b969198ec2242c7de57fbf413cdbungeman@google.com vector.x = fFace->glyph->metrics.vertBearingX - fFace->glyph->metrics.horiBearingX; 11698ff8a1959f514b969198ec2242c7de57fbf413cdbungeman@google.com vector.y = -fFace->glyph->metrics.vertBearingY - fFace->glyph->metrics.horiBearingY; 11708ff8a1959f514b969198ec2242c7de57fbf413cdbungeman@google.com FT_Vector_Transform(&vector, &fMatrix22); 11718ff8a1959f514b969198ec2242c7de57fbf413cdbungeman@google.com bbox->xMin += vector.x; 11728ff8a1959f514b969198ec2242c7de57fbf413cdbungeman@google.com bbox->xMax += vector.x; 11738ff8a1959f514b969198ec2242c7de57fbf413cdbungeman@google.com bbox->yMin += vector.y; 11748ff8a1959f514b969198ec2242c7de57fbf413cdbungeman@google.com bbox->yMax += vector.y; 11758ff8a1959f514b969198ec2242c7de57fbf413cdbungeman@google.com } 1176d8b599cb264b2228e0fb1bee6d3604be6d3c2855djsollen@google.com} 1177d8b599cb264b2228e0fb1bee6d3604be6d3c2855djsollen@google.com 1178cbe1b54c30b9a1061577c91e0b914dbe9acdc563bungeman@google.combool SkScalerContext_FreeType::getCBoxForLetter(char letter, FT_BBox* bbox) { 1179cbe1b54c30b9a1061577c91e0b914dbe9acdc563bungeman@google.com const FT_UInt glyph_id = FT_Get_Char_Index(fFace, letter); 1180cbe1b54c30b9a1061577c91e0b914dbe9acdc563bungeman@google.com if (!glyph_id) 1181cbe1b54c30b9a1061577c91e0b914dbe9acdc563bungeman@google.com return false; 1182cbe1b54c30b9a1061577c91e0b914dbe9acdc563bungeman@google.com if (FT_Load_Glyph(fFace, glyph_id, fLoadGlyphFlags) != 0) 1183cbe1b54c30b9a1061577c91e0b914dbe9acdc563bungeman@google.com return false; 11846fa81d7878d20b9e46ea9395e2efb58026447142commit-bot@chromium.org emboldenIfNeeded(fFace, fFace->glyph); 1185cbe1b54c30b9a1061577c91e0b914dbe9acdc563bungeman@google.com FT_Outline_Get_CBox(&fFace->glyph->outline, bbox); 1186cbe1b54c30b9a1061577c91e0b914dbe9acdc563bungeman@google.com return true; 1187cbe1b54c30b9a1061577c91e0b914dbe9acdc563bungeman@google.com} 1188cbe1b54c30b9a1061577c91e0b914dbe9acdc563bungeman@google.com 1189d8b599cb264b2228e0fb1bee6d3604be6d3c2855djsollen@google.comvoid SkScalerContext_FreeType::updateGlyphIfLCD(SkGlyph* glyph) { 1190d8b599cb264b2228e0fb1bee6d3604be6d3c2855djsollen@google.com if (isLCD(fRec)) { 1191d8b599cb264b2228e0fb1bee6d3604be6d3c2855djsollen@google.com if (fLCDIsVert) { 1192d8b599cb264b2228e0fb1bee6d3604be6d3c2855djsollen@google.com glyph->fHeight += gLCDExtra; 1193d8b599cb264b2228e0fb1bee6d3604be6d3c2855djsollen@google.com glyph->fTop -= gLCDExtra >> 1; 1194d8b599cb264b2228e0fb1bee6d3604be6d3c2855djsollen@google.com } else { 1195d8b599cb264b2228e0fb1bee6d3604be6d3c2855djsollen@google.com glyph->fWidth += gLCDExtra; 1196d8b599cb264b2228e0fb1bee6d3604be6d3c2855djsollen@google.com glyph->fLeft -= gLCDExtra >> 1; 1197d8b599cb264b2228e0fb1bee6d3604be6d3c2855djsollen@google.com } 1198d8b599cb264b2228e0fb1bee6d3604be6d3c2855djsollen@google.com } 1199d8b599cb264b2228e0fb1bee6d3604be6d3c2855djsollen@google.com} 1200d8b599cb264b2228e0fb1bee6d3604be6d3c2855djsollen@google.com 1201c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.cominline void scaleGlyphMetrics(SkGlyph& glyph, SkScalar scale) { 1202c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com glyph.fWidth *= scale; 1203c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com glyph.fHeight *= scale; 1204c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com glyph.fTop *= scale; 1205c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com glyph.fLeft *= scale; 1206c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com 1207c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com SkFixed fixedScale = SkScalarToFixed(scale); 1208c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com glyph.fAdvanceX = SkFixedMul(glyph.fAdvanceX, fixedScale); 1209c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com glyph.fAdvanceY = SkFixedMul(glyph.fAdvanceY, fixedScale); 1210c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com} 1211c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com 12128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkScalerContext_FreeType::generateMetrics(SkGlyph* glyph) { 12138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkAutoMutexAcquire ac(gFTMutex); 12148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 12158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com glyph->fRsbDelta = 0; 12168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com glyph->fLsbDelta = 0; 12178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 12188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com FT_Error err; 12198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 12208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (this->setupSize()) { 12218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com goto ERROR; 12228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 12238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 12241b27704eba15be4e9d1997faac42038493a30be5djsollen err = FT_Load_Glyph( fFace, glyph->getGlyphID(), fLoadGlyphFlags ); 12258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (err != 0) { 12267a722f0ebf6acfd02899bc30a5529d0b23b3ffaemike@reedtribe.org#if 0 12277a722f0ebf6acfd02899bc30a5529d0b23b3ffaemike@reedtribe.org SkDEBUGF(("SkScalerContext_FreeType::generateMetrics(%x): FT_Load_Glyph(glyph:%d flags:%x) returned 0x%x\n", 12281b27704eba15be4e9d1997faac42038493a30be5djsollen fFaceRec->fFontID, glyph->getGlyphID(), fLoadGlyphFlags, err)); 12297a722f0ebf6acfd02899bc30a5529d0b23b3ffaemike@reedtribe.org#endif 12308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ERROR: 123162900b4c64401bc80ae85f6f5c87309a273cae10reed@android.com glyph->zeroMetrics(); 12328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 12338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 12346fa81d7878d20b9e46ea9395e2efb58026447142commit-bot@chromium.org emboldenIfNeeded(fFace, fFace->glyph); 12358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 12368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com switch ( fFace->glyph->format ) { 1237c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com case FT_GLYPH_FORMAT_OUTLINE: 12380f0c2888e09f7a2a153efbc8e41fe1e90a9f2112bungeman@google.com if (0 == fFace->glyph->outline.n_contours) { 12390f0c2888e09f7a2a153efbc8e41fe1e90a9f2112bungeman@google.com glyph->fWidth = 0; 12400f0c2888e09f7a2a153efbc8e41fe1e90a9f2112bungeman@google.com glyph->fHeight = 0; 12410f0c2888e09f7a2a153efbc8e41fe1e90a9f2112bungeman@google.com glyph->fTop = 0; 12420f0c2888e09f7a2a153efbc8e41fe1e90a9f2112bungeman@google.com glyph->fLeft = 0; 1243c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com } else { 1244c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com FT_BBox bbox; 1245c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com getBBoxForCurrentGlyph(glyph, &bbox, true); 1246d8b599cb264b2228e0fb1bee6d3604be6d3c2855djsollen@google.com 1247c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com glyph->fWidth = SkToU16(SkFDot6Floor(bbox.xMax - bbox.xMin)); 1248c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com glyph->fHeight = SkToU16(SkFDot6Floor(bbox.yMax - bbox.yMin)); 1249c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com glyph->fTop = -SkToS16(SkFDot6Floor(bbox.yMax)); 1250c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com glyph->fLeft = SkToS16(SkFDot6Floor(bbox.xMin)); 1251d8b599cb264b2228e0fb1bee6d3604be6d3c2855djsollen@google.com 1252c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com updateGlyphIfLCD(glyph); 1253c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com } 12548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com break; 12558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 12568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com case FT_GLYPH_FORMAT_BITMAP: 12578ff8a1959f514b969198ec2242c7de57fbf413cdbungeman@google.com if (fRec.fFlags & SkScalerContext::kVertical_Flag) { 12588ff8a1959f514b969198ec2242c7de57fbf413cdbungeman@google.com FT_Vector vector; 12598ff8a1959f514b969198ec2242c7de57fbf413cdbungeman@google.com vector.x = fFace->glyph->metrics.vertBearingX - fFace->glyph->metrics.horiBearingX; 12608ff8a1959f514b969198ec2242c7de57fbf413cdbungeman@google.com vector.y = -fFace->glyph->metrics.vertBearingY - fFace->glyph->metrics.horiBearingY; 12618ff8a1959f514b969198ec2242c7de57fbf413cdbungeman@google.com FT_Vector_Transform(&vector, &fMatrix22); 12628ff8a1959f514b969198ec2242c7de57fbf413cdbungeman@google.com fFace->glyph->bitmap_left += SkFDot6Floor(vector.x); 12638ff8a1959f514b969198ec2242c7de57fbf413cdbungeman@google.com fFace->glyph->bitmap_top += SkFDot6Floor(vector.y); 12648ff8a1959f514b969198ec2242c7de57fbf413cdbungeman@google.com } 12658ff8a1959f514b969198ec2242c7de57fbf413cdbungeman@google.com 1266c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com if (fFace->glyph->bitmap.pixel_mode == FT_PIXEL_MODE_BGRA) { 1267c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com glyph->fMaskFormat = SkMask::kARGB32_Format; 1268c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com } 1269c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com 12708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com glyph->fWidth = SkToU16(fFace->glyph->bitmap.width); 12718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com glyph->fHeight = SkToU16(fFace->glyph->bitmap.rows); 12728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com glyph->fTop = -SkToS16(fFace->glyph->bitmap_top); 12738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com glyph->fLeft = SkToS16(fFace->glyph->bitmap_left); 12748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com break; 12758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 12768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com default: 12770c00f21fee3f5cfa3aa7e5d46ff94cb8cf340451tomhudson@google.com SkDEBUGFAIL("unknown glyph format"); 12788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com goto ERROR; 12798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 12808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 12818ff8a1959f514b969198ec2242c7de57fbf413cdbungeman@google.com if (fRec.fFlags & SkScalerContext::kVertical_Flag) { 12828ff8a1959f514b969198ec2242c7de57fbf413cdbungeman@google.com if (fDoLinearMetrics) { 12838ff8a1959f514b969198ec2242c7de57fbf413cdbungeman@google.com glyph->fAdvanceX = -SkFixedMul(fMatrix22.xy, fFace->glyph->linearVertAdvance); 12848ff8a1959f514b969198ec2242c7de57fbf413cdbungeman@google.com glyph->fAdvanceY = SkFixedMul(fMatrix22.yy, fFace->glyph->linearVertAdvance); 12858ff8a1959f514b969198ec2242c7de57fbf413cdbungeman@google.com } else { 12868ff8a1959f514b969198ec2242c7de57fbf413cdbungeman@google.com glyph->fAdvanceX = -SkFDot6ToFixed(fFace->glyph->advance.x); 12878ff8a1959f514b969198ec2242c7de57fbf413cdbungeman@google.com glyph->fAdvanceY = SkFDot6ToFixed(fFace->glyph->advance.y); 12888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 12898ff8a1959f514b969198ec2242c7de57fbf413cdbungeman@google.com } else { 12908ff8a1959f514b969198ec2242c7de57fbf413cdbungeman@google.com if (fDoLinearMetrics) { 12918ff8a1959f514b969198ec2242c7de57fbf413cdbungeman@google.com glyph->fAdvanceX = SkFixedMul(fMatrix22.xx, fFace->glyph->linearHoriAdvance); 12928ff8a1959f514b969198ec2242c7de57fbf413cdbungeman@google.com glyph->fAdvanceY = -SkFixedMul(fMatrix22.yx, fFace->glyph->linearHoriAdvance); 12938ff8a1959f514b969198ec2242c7de57fbf413cdbungeman@google.com } else { 12948ff8a1959f514b969198ec2242c7de57fbf413cdbungeman@google.com glyph->fAdvanceX = SkFDot6ToFixed(fFace->glyph->advance.x); 12958ff8a1959f514b969198ec2242c7de57fbf413cdbungeman@google.com glyph->fAdvanceY = -SkFDot6ToFixed(fFace->glyph->advance.y); 1296d8b599cb264b2228e0fb1bee6d3604be6d3c2855djsollen@google.com 12978ff8a1959f514b969198ec2242c7de57fbf413cdbungeman@google.com if (fRec.fFlags & kDevKernText_Flag) { 12988ff8a1959f514b969198ec2242c7de57fbf413cdbungeman@google.com glyph->fRsbDelta = SkToS8(fFace->glyph->rsb_delta); 12998ff8a1959f514b969198ec2242c7de57fbf413cdbungeman@google.com glyph->fLsbDelta = SkToS8(fFace->glyph->lsb_delta); 1300d8b599cb264b2228e0fb1bee6d3604be6d3c2855djsollen@google.com } 1301d8b599cb264b2228e0fb1bee6d3604be6d3c2855djsollen@google.com } 1302d8b599cb264b2228e0fb1bee6d3604be6d3c2855djsollen@google.com } 1303d8b599cb264b2228e0fb1bee6d3604be6d3c2855djsollen@google.com 1304a85511adc0173bd44ec18dd7f026ef191b2d683ebungeman // If the font isn't scalable, scale the metrics from the non-scalable strike. 1305a85511adc0173bd44ec18dd7f026ef191b2d683ebungeman // This means do not try to scale embedded bitmaps; only scale bitmaps in bitmap only fonts. 1306a85511adc0173bd44ec18dd7f026ef191b2d683ebungeman if (!FT_IS_SCALABLE(fFace) && fScaleY && fFace->size->metrics.y_ppem) { 1307c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com // NOTE: both dimensions are scaled by y_ppem. this is WAI. 1308c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com scaleGlyphMetrics(*glyph, SkScalarDiv(SkFixedToScalar(fScaleY), 1309c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com SkIntToScalar(fFace->size->metrics.y_ppem))); 1310c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com } 1311d8b599cb264b2228e0fb1bee6d3604be6d3c2855djsollen@google.com 13128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifdef ENABLE_GLYPH_SPEW 13138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDEBUGF(("FT_Set_Char_Size(this:%p sx:%x sy:%x ", this, fScaleX, fScaleY)); 13141b27704eba15be4e9d1997faac42038493a30be5djsollen SkDEBUGF(("Metrics(glyph:%d flags:0x%x) w:%d\n", glyph->getGlyphID(), fLoadGlyphFlags, glyph->fWidth)); 13158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif 13168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 13178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1318ea2333de1e93da38045111560295ef825be99956reed@google.com 1319a76de72a6036da0a6b051b14411b80941971f881bungeman@google.comvoid SkScalerContext_FreeType::generateImage(const SkGlyph& glyph) { 13208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkAutoMutexAcquire ac(gFTMutex); 13218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 13228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com FT_Error err; 13238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 13248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (this->setupSize()) { 13258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com goto ERROR; 13268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 13278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 13281b27704eba15be4e9d1997faac42038493a30be5djsollen err = FT_Load_Glyph( fFace, glyph.getGlyphID(), fLoadGlyphFlags); 13298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (err != 0) { 13308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDEBUGF(("SkScalerContext_FreeType::generateImage: FT_Load_Glyph(glyph:%d width:%d height:%d rb:%d flags:%d) returned 0x%x\n", 13311b27704eba15be4e9d1997faac42038493a30be5djsollen glyph.getGlyphID(), glyph.fWidth, glyph.fHeight, glyph.rowBytes(), fLoadGlyphFlags, err)); 13328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ERROR: 13338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com memset(glyph.fImage, 0, glyph.rowBytes() * glyph.fHeight); 13348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 13358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 13368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 13376fa81d7878d20b9e46ea9395e2efb58026447142commit-bot@chromium.org emboldenIfNeeded(fFace, fFace->glyph); 1338a76de72a6036da0a6b051b14411b80941971f881bungeman@google.com generateGlyphImage(fFace, glyph); 13398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 13408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 13418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 13428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkScalerContext_FreeType::generatePath(const SkGlyph& glyph, 13438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPath* path) { 13448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkAutoMutexAcquire ac(gFTMutex); 13458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1346a10742c69ce47d346e3cf23e7be909c9f29b401ecaryclark SkASSERT(path); 13478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 13488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (this->setupSize()) { 13498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com path->reset(); 13508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 13518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 13528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 13538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com uint32_t flags = fLoadGlyphFlags; 13548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com flags |= FT_LOAD_NO_BITMAP; // ignore embedded bitmaps so we're sure to get the outline 13558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com flags &= ~FT_LOAD_RENDER; // don't scan convert (we just want the outline) 13568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 13571b27704eba15be4e9d1997faac42038493a30be5djsollen FT_Error err = FT_Load_Glyph( fFace, glyph.getGlyphID(), flags); 13588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 13598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (err != 0) { 13608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDEBUGF(("SkScalerContext_FreeType::generatePath: FT_Load_Glyph(glyph:%d flags:%d) returned 0x%x\n", 13611b27704eba15be4e9d1997faac42038493a30be5djsollen glyph.getGlyphID(), flags, err)); 13628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com path->reset(); 13638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 13648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 13656fa81d7878d20b9e46ea9395e2efb58026447142commit-bot@chromium.org emboldenIfNeeded(fFace, fFace->glyph); 13668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 136766a58aca8379a33ccc7572a31c74a3334d08b47csugoi@google.com generateGlyphPath(fFace, path); 13688ff8a1959f514b969198ec2242c7de57fbf413cdbungeman@google.com 13698ff8a1959f514b969198ec2242c7de57fbf413cdbungeman@google.com // The path's origin from FreeType is always the horizontal layout origin. 13708ff8a1959f514b969198ec2242c7de57fbf413cdbungeman@google.com // Offset the path so that it is relative to the vertical origin if needed. 13718ff8a1959f514b969198ec2242c7de57fbf413cdbungeman@google.com if (fRec.fFlags & SkScalerContext::kVertical_Flag) { 13728ff8a1959f514b969198ec2242c7de57fbf413cdbungeman@google.com FT_Vector vector; 13738ff8a1959f514b969198ec2242c7de57fbf413cdbungeman@google.com vector.x = fFace->glyph->metrics.vertBearingX - fFace->glyph->metrics.horiBearingX; 13748ff8a1959f514b969198ec2242c7de57fbf413cdbungeman@google.com vector.y = -fFace->glyph->metrics.vertBearingY - fFace->glyph->metrics.horiBearingY; 13758ff8a1959f514b969198ec2242c7de57fbf413cdbungeman@google.com FT_Vector_Transform(&vector, &fMatrix22); 13768ff8a1959f514b969198ec2242c7de57fbf413cdbungeman@google.com path->offset(SkFDot6ToScalar(vector.x), -SkFDot6ToScalar(vector.y)); 13778ff8a1959f514b969198ec2242c7de57fbf413cdbungeman@google.com } 13788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 13798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1380410780677af260e32948b02c0725ef6ad761260cbungemanvoid SkScalerContext_FreeType::generateFontMetrics(SkPaint::FontMetrics* metrics) { 1381410780677af260e32948b02c0725ef6ad761260cbungeman if (NULL == metrics) { 13828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 13838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 13848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1385410780677af260e32948b02c0725ef6ad761260cbungeman SkAutoMutexAcquire ac(gFTMutex); 13868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 13878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (this->setupSize()) { 1388a8a8b8b80e2b6be2dd83ef2c1333851fd03a87d7reed@android.com ERROR: 1389410780677af260e32948b02c0725ef6ad761260cbungeman sk_bzero(metrics, sizeof(*metrics)); 13908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 13918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 13928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1393a8a8b8b80e2b6be2dd83ef2c1333851fd03a87d7reed@android.com FT_Face face = fFace; 1394c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com SkScalar scaleX = fScale.x(); 1395f073b3332d7c9f7dba6bcf7eb93708593a90036creed@google.com SkScalar scaleY = fScale.y(); 1396c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com SkScalar mxy = fMatrix22Scalar.getSkewX() * scaleY; 1397c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com SkScalar myy = fMatrix22Scalar.getScaleY() * scaleY; 1398c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com 1399c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com // fetch units/EM from "head" table if needed (ie for bitmap fonts) 1400c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com SkScalar upem = SkIntToScalar(face->units_per_EM); 1401c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com if (!upem) { 1402c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com TT_Header* ttHeader = (TT_Header*)FT_Get_Sfnt_Table(face, ft_sfnt_head); 1403c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com if (ttHeader) { 1404c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com upem = SkIntToScalar(ttHeader->Units_Per_EM); 1405c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com } 14068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 14078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1408c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com // use the os/2 table as a source of reasonable defaults. 1409c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com SkScalar x_height = 0.0f; 1410c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com SkScalar avgCharWidth = 0.0f; 1411cbe1b54c30b9a1061577c91e0b914dbe9acdc563bungeman@google.com SkScalar cap_height = 0.0f; 1412cc3096ba6d437b29f1cbd34c237607419cbed72bagl@chromium.org TT_OS2* os2 = (TT_OS2*) FT_Get_Sfnt_Table(face, ft_sfnt_os2); 1413c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com if (os2) { 1414c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com x_height = scaleX * SkIntToScalar(os2->sxHeight) / upem; 1415c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com avgCharWidth = SkIntToScalar(os2->xAvgCharWidth) / upem; 1416cbe1b54c30b9a1061577c91e0b914dbe9acdc563bungeman@google.com if (os2->version != 0xFFFF && os2->version >= 2) { 1417cbe1b54c30b9a1061577c91e0b914dbe9acdc563bungeman@google.com cap_height = scaleX * SkIntToScalar(os2->sCapHeight) / upem; 1418cbe1b54c30b9a1061577c91e0b914dbe9acdc563bungeman@google.com } 1419c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com } 1420c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com 1421c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com // pull from format-specific metrics as needed 1422c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com SkScalar ascent, descent, leading, xmin, xmax, ymin, ymax; 14230bc406df48ac6f358ab8dcff08f71fe9c32b79decommit-bot@chromium.org SkScalar underlineThickness, underlinePosition; 1424c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com if (face->face_flags & FT_FACE_FLAG_SCALABLE) { // scalable outline font 1425c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com ascent = -SkIntToScalar(face->ascender) / upem; 1426c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com descent = -SkIntToScalar(face->descender) / upem; 1427c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com leading = SkIntToScalar(face->height + (face->descender - face->ascender)) / upem; 1428c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com xmin = SkIntToScalar(face->bbox.xMin) / upem; 1429c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com xmax = SkIntToScalar(face->bbox.xMax) / upem; 1430c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com ymin = -SkIntToScalar(face->bbox.yMin) / upem; 1431c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com ymax = -SkIntToScalar(face->bbox.yMax) / upem; 14320bc406df48ac6f358ab8dcff08f71fe9c32b79decommit-bot@chromium.org underlineThickness = SkIntToScalar(face->underline_thickness) / upem; 1433d3031aa5ae90b796593a04c0da062024198e4769commit-bot@chromium.org underlinePosition = -SkIntToScalar(face->underline_position + 1434d3031aa5ae90b796593a04c0da062024198e4769commit-bot@chromium.org face->underline_thickness / 2) / upem; 14350bc406df48ac6f358ab8dcff08f71fe9c32b79decommit-bot@chromium.org 1436410780677af260e32948b02c0725ef6ad761260cbungeman metrics->fFlags |= SkPaint::FontMetrics::kUnderlineThinknessIsValid_Flag; 1437410780677af260e32948b02c0725ef6ad761260cbungeman metrics->fFlags |= SkPaint::FontMetrics::kUnderlinePositionIsValid_Flag; 1438410780677af260e32948b02c0725ef6ad761260cbungeman 1439cbe1b54c30b9a1061577c91e0b914dbe9acdc563bungeman@google.com // we may be able to synthesize x_height and cap_height from outline 1440c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com if (!x_height) { 1441cbe1b54c30b9a1061577c91e0b914dbe9acdc563bungeman@google.com FT_BBox bbox; 1442cbe1b54c30b9a1061577c91e0b914dbe9acdc563bungeman@google.com if (getCBoxForLetter('x', &bbox)) { 1443c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com x_height = SkIntToScalar(bbox.yMax) / 64.0f; 14444526a847da6dc738dc73103ec4d47cc0dbdec478senorblanco@chromium.org } 1445cc3096ba6d437b29f1cbd34c237607419cbed72bagl@chromium.org } 1446cbe1b54c30b9a1061577c91e0b914dbe9acdc563bungeman@google.com if (!cap_height) { 1447cbe1b54c30b9a1061577c91e0b914dbe9acdc563bungeman@google.com FT_BBox bbox; 1448cbe1b54c30b9a1061577c91e0b914dbe9acdc563bungeman@google.com if (getCBoxForLetter('H', &bbox)) { 1449cbe1b54c30b9a1061577c91e0b914dbe9acdc563bungeman@google.com cap_height = SkIntToScalar(bbox.yMax) / 64.0f; 1450cbe1b54c30b9a1061577c91e0b914dbe9acdc563bungeman@google.com } 1451cbe1b54c30b9a1061577c91e0b914dbe9acdc563bungeman@google.com } 1452c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com } else if (fStrikeIndex != -1) { // bitmap strike metrics 1453c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com SkScalar xppem = SkIntToScalar(face->size->metrics.x_ppem); 1454c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com SkScalar yppem = SkIntToScalar(face->size->metrics.y_ppem); 1455c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com ascent = -SkIntToScalar(face->size->metrics.ascender) / (yppem * 64.0f); 1456c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com descent = -SkIntToScalar(face->size->metrics.descender) / (yppem * 64.0f); 1457c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com leading = (SkIntToScalar(face->size->metrics.height) / (yppem * 64.0f)) 1458c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com + ascent - descent; 1459c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com xmin = 0.0f; 1460c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com xmax = SkIntToScalar(face->available_sizes[fStrikeIndex].width) / xppem; 1461c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com ymin = descent + leading; 1462c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com ymax = ascent - descent; 14630bc406df48ac6f358ab8dcff08f71fe9c32b79decommit-bot@chromium.org underlineThickness = 0; 14640bc406df48ac6f358ab8dcff08f71fe9c32b79decommit-bot@chromium.org underlinePosition = 0; 14650bc406df48ac6f358ab8dcff08f71fe9c32b79decommit-bot@chromium.org 1466410780677af260e32948b02c0725ef6ad761260cbungeman metrics->fFlags &= ~SkPaint::FontMetrics::kUnderlineThinknessIsValid_Flag; 1467410780677af260e32948b02c0725ef6ad761260cbungeman metrics->fFlags &= ~SkPaint::FontMetrics::kUnderlinePositionIsValid_Flag; 1468c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com } else { 1469c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com goto ERROR; 1470c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com } 1471c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com 1472c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com // synthesize elements that were not provided by the os/2 table or format-specific metrics 1473c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com if (!x_height) { 1474c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com x_height = -ascent; 1475c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com } 1476c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com if (!avgCharWidth) { 1477c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com avgCharWidth = xmax - xmin; 1478cc3096ba6d437b29f1cbd34c237607419cbed72bagl@chromium.org } 1479cbe1b54c30b9a1061577c91e0b914dbe9acdc563bungeman@google.com if (!cap_height) { 1480cbe1b54c30b9a1061577c91e0b914dbe9acdc563bungeman@google.com cap_height = -ascent; 1481cbe1b54c30b9a1061577c91e0b914dbe9acdc563bungeman@google.com } 14828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1483c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com // disallow negative linespacing 1484c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com if (leading < 0.0f) { 1485c9a8a7e23de576ac91e9b34a221382f7c0e69813bungeman@google.com leading = 0.0f; 14868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 14878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1488410780677af260e32948b02c0725ef6ad761260cbungeman SkScalar scale = myy; 1489410780677af260e32948b02c0725ef6ad761260cbungeman if (this->isVertical()) { 1490410780677af260e32948b02c0725ef6ad761260cbungeman scale = mxy; 1491410780677af260e32948b02c0725ef6ad761260cbungeman } 1492410780677af260e32948b02c0725ef6ad761260cbungeman metrics->fTop = ymax * scale; 1493410780677af260e32948b02c0725ef6ad761260cbungeman metrics->fAscent = ascent * scale; 1494410780677af260e32948b02c0725ef6ad761260cbungeman metrics->fDescent = descent * scale; 1495410780677af260e32948b02c0725ef6ad761260cbungeman metrics->fBottom = ymin * scale; 1496410780677af260e32948b02c0725ef6ad761260cbungeman metrics->fLeading = leading * scale; 1497410780677af260e32948b02c0725ef6ad761260cbungeman metrics->fAvgCharWidth = avgCharWidth * scale; 1498410780677af260e32948b02c0725ef6ad761260cbungeman metrics->fXMin = xmin; 1499410780677af260e32948b02c0725ef6ad761260cbungeman metrics->fXMax = xmax; 1500410780677af260e32948b02c0725ef6ad761260cbungeman metrics->fXHeight = x_height; 1501410780677af260e32948b02c0725ef6ad761260cbungeman metrics->fCapHeight = cap_height; 1502410780677af260e32948b02c0725ef6ad761260cbungeman metrics->fUnderlineThickness = underlineThickness * scale; 1503410780677af260e32948b02c0725ef6ad761260cbungeman metrics->fUnderlinePosition = underlinePosition * scale; 15048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 15058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 15066fa81d7878d20b9e46ea9395e2efb58026447142commit-bot@chromium.orgvoid SkScalerContext_FreeType::emboldenIfNeeded(FT_Face face, FT_GlyphSlot glyph) 15076fa81d7878d20b9e46ea9395e2efb58026447142commit-bot@chromium.org{ 1508921d2b3f6c4b32345f9561be91806793b4842283commit-bot@chromium.org // check to see if the embolden bit is set 1509921d2b3f6c4b32345f9561be91806793b4842283commit-bot@chromium.org if (0 == (fRec.fFlags & SkScalerContext::kEmbolden_Flag)) { 1510921d2b3f6c4b32345f9561be91806793b4842283commit-bot@chromium.org return; 1511921d2b3f6c4b32345f9561be91806793b4842283commit-bot@chromium.org } 1512921d2b3f6c4b32345f9561be91806793b4842283commit-bot@chromium.org 1513921d2b3f6c4b32345f9561be91806793b4842283commit-bot@chromium.org switch (glyph->format) { 1514921d2b3f6c4b32345f9561be91806793b4842283commit-bot@chromium.org case FT_GLYPH_FORMAT_OUTLINE: 1515921d2b3f6c4b32345f9561be91806793b4842283commit-bot@chromium.org FT_Pos strength; 1516921d2b3f6c4b32345f9561be91806793b4842283commit-bot@chromium.org strength = FT_MulFix(face->units_per_EM, face->size->metrics.y_scale) / 24; 1517921d2b3f6c4b32345f9561be91806793b4842283commit-bot@chromium.org FT_Outline_Embolden(&glyph->outline, strength); 1518921d2b3f6c4b32345f9561be91806793b4842283commit-bot@chromium.org break; 1519921d2b3f6c4b32345f9561be91806793b4842283commit-bot@chromium.org case FT_GLYPH_FORMAT_BITMAP: 1520921d2b3f6c4b32345f9561be91806793b4842283commit-bot@chromium.org FT_GlyphSlot_Own_Bitmap(glyph); 1521921d2b3f6c4b32345f9561be91806793b4842283commit-bot@chromium.org FT_Bitmap_Embolden(glyph->library, &glyph->bitmap, kBitmapEmboldenStrength, 0); 1522921d2b3f6c4b32345f9561be91806793b4842283commit-bot@chromium.org break; 1523921d2b3f6c4b32345f9561be91806793b4842283commit-bot@chromium.org default: 1524921d2b3f6c4b32345f9561be91806793b4842283commit-bot@chromium.org SkDEBUGFAIL("unknown glyph format"); 15256fa81d7878d20b9e46ea9395e2efb58026447142commit-bot@chromium.org } 15266fa81d7878d20b9e46ea9395e2efb58026447142commit-bot@chromium.org} 15276fa81d7878d20b9e46ea9395e2efb58026447142commit-bot@chromium.org 1528b4162b12b1e8e38c48b328f819c97199a0825d2breed@google.com/////////////////////////////////////////////////////////////////////////////// 1529b4162b12b1e8e38c48b328f819c97199a0825d2breed@google.com 1530b4162b12b1e8e38c48b328f819c97199a0825d2breed@google.com#include "SkUtils.h" 1531b4162b12b1e8e38c48b328f819c97199a0825d2breed@google.com 1532b4162b12b1e8e38c48b328f819c97199a0825d2breed@google.comstatic SkUnichar next_utf8(const void** chars) { 1533b4162b12b1e8e38c48b328f819c97199a0825d2breed@google.com return SkUTF8_NextUnichar((const char**)chars); 1534b4162b12b1e8e38c48b328f819c97199a0825d2breed@google.com} 1535b4162b12b1e8e38c48b328f819c97199a0825d2breed@google.com 1536b4162b12b1e8e38c48b328f819c97199a0825d2breed@google.comstatic SkUnichar next_utf16(const void** chars) { 1537b4162b12b1e8e38c48b328f819c97199a0825d2breed@google.com return SkUTF16_NextUnichar((const uint16_t**)chars); 1538b4162b12b1e8e38c48b328f819c97199a0825d2breed@google.com} 1539b4162b12b1e8e38c48b328f819c97199a0825d2breed@google.com 1540b4162b12b1e8e38c48b328f819c97199a0825d2breed@google.comstatic SkUnichar next_utf32(const void** chars) { 1541b4162b12b1e8e38c48b328f819c97199a0825d2breed@google.com const SkUnichar** uniChars = (const SkUnichar**)chars; 1542b4162b12b1e8e38c48b328f819c97199a0825d2breed@google.com SkUnichar uni = **uniChars; 1543b4162b12b1e8e38c48b328f819c97199a0825d2breed@google.com *uniChars += 1; 1544b4162b12b1e8e38c48b328f819c97199a0825d2breed@google.com return uni; 1545b4162b12b1e8e38c48b328f819c97199a0825d2breed@google.com} 1546b4162b12b1e8e38c48b328f819c97199a0825d2breed@google.com 1547b4162b12b1e8e38c48b328f819c97199a0825d2breed@google.comtypedef SkUnichar (*EncodingProc)(const void**); 1548b4162b12b1e8e38c48b328f819c97199a0825d2breed@google.com 1549b4162b12b1e8e38c48b328f819c97199a0825d2breed@google.comstatic EncodingProc find_encoding_proc(SkTypeface::Encoding enc) { 1550b4162b12b1e8e38c48b328f819c97199a0825d2breed@google.com static const EncodingProc gProcs[] = { 1551b4162b12b1e8e38c48b328f819c97199a0825d2breed@google.com next_utf8, next_utf16, next_utf32 1552b4162b12b1e8e38c48b328f819c97199a0825d2breed@google.com }; 1553b4162b12b1e8e38c48b328f819c97199a0825d2breed@google.com SkASSERT((size_t)enc < SK_ARRAY_COUNT(gProcs)); 1554b4162b12b1e8e38c48b328f819c97199a0825d2breed@google.com return gProcs[enc]; 1555b4162b12b1e8e38c48b328f819c97199a0825d2breed@google.com} 1556b4162b12b1e8e38c48b328f819c97199a0825d2breed@google.com 1557b4162b12b1e8e38c48b328f819c97199a0825d2breed@google.comint SkTypeface_FreeType::onCharsToGlyphs(const void* chars, Encoding encoding, 1558b4162b12b1e8e38c48b328f819c97199a0825d2breed@google.com uint16_t glyphs[], int glyphCount) const { 1559b4162b12b1e8e38c48b328f819c97199a0825d2breed@google.com AutoFTAccess fta(this); 1560b4162b12b1e8e38c48b328f819c97199a0825d2breed@google.com FT_Face face = fta.face(); 1561b4162b12b1e8e38c48b328f819c97199a0825d2breed@google.com if (!face) { 1562b4162b12b1e8e38c48b328f819c97199a0825d2breed@google.com if (glyphs) { 1563b4162b12b1e8e38c48b328f819c97199a0825d2breed@google.com sk_bzero(glyphs, glyphCount * sizeof(glyphs[0])); 1564b4162b12b1e8e38c48b328f819c97199a0825d2breed@google.com } 1565b4162b12b1e8e38c48b328f819c97199a0825d2breed@google.com return 0; 1566b4162b12b1e8e38c48b328f819c97199a0825d2breed@google.com } 1567b4162b12b1e8e38c48b328f819c97199a0825d2breed@google.com 1568b4162b12b1e8e38c48b328f819c97199a0825d2breed@google.com EncodingProc next_uni_proc = find_encoding_proc(encoding); 1569b4162b12b1e8e38c48b328f819c97199a0825d2breed@google.com 1570b4162b12b1e8e38c48b328f819c97199a0825d2breed@google.com if (NULL == glyphs) { 1571b4162b12b1e8e38c48b328f819c97199a0825d2breed@google.com for (int i = 0; i < glyphCount; ++i) { 1572b4162b12b1e8e38c48b328f819c97199a0825d2breed@google.com if (0 == FT_Get_Char_Index(face, next_uni_proc(&chars))) { 1573b4162b12b1e8e38c48b328f819c97199a0825d2breed@google.com return i; 1574b4162b12b1e8e38c48b328f819c97199a0825d2breed@google.com } 1575b4162b12b1e8e38c48b328f819c97199a0825d2breed@google.com } 1576b4162b12b1e8e38c48b328f819c97199a0825d2breed@google.com return glyphCount; 1577b4162b12b1e8e38c48b328f819c97199a0825d2breed@google.com } else { 1578b4162b12b1e8e38c48b328f819c97199a0825d2breed@google.com int first = glyphCount; 1579b4162b12b1e8e38c48b328f819c97199a0825d2breed@google.com for (int i = 0; i < glyphCount; ++i) { 1580b4162b12b1e8e38c48b328f819c97199a0825d2breed@google.com unsigned id = FT_Get_Char_Index(face, next_uni_proc(&chars)); 1581b4162b12b1e8e38c48b328f819c97199a0825d2breed@google.com glyphs[i] = SkToU16(id); 1582b4162b12b1e8e38c48b328f819c97199a0825d2breed@google.com if (0 == id && i < first) { 1583b4162b12b1e8e38c48b328f819c97199a0825d2breed@google.com first = i; 1584b4162b12b1e8e38c48b328f819c97199a0825d2breed@google.com } 1585b4162b12b1e8e38c48b328f819c97199a0825d2breed@google.com } 1586b4162b12b1e8e38c48b328f819c97199a0825d2breed@google.com return first; 1587b4162b12b1e8e38c48b328f819c97199a0825d2breed@google.com } 1588b4162b12b1e8e38c48b328f819c97199a0825d2breed@google.com} 1589b4162b12b1e8e38c48b328f819c97199a0825d2breed@google.com 1590b4162b12b1e8e38c48b328f819c97199a0825d2breed@google.comint SkTypeface_FreeType::onCountGlyphs() const { 1591b4162b12b1e8e38c48b328f819c97199a0825d2breed@google.com // we cache this value, using -1 as a sentinel for "not computed" 1592b4162b12b1e8e38c48b328f819c97199a0825d2breed@google.com if (fGlyphCount < 0) { 1593b4162b12b1e8e38c48b328f819c97199a0825d2breed@google.com AutoFTAccess fta(this); 1594b4162b12b1e8e38c48b328f819c97199a0825d2breed@google.com FT_Face face = fta.face(); 1595b4162b12b1e8e38c48b328f819c97199a0825d2breed@google.com // if the face failed, we still assign a non-negative value 1596b4162b12b1e8e38c48b328f819c97199a0825d2breed@google.com fGlyphCount = face ? face->num_glyphs : 0; 1597b4162b12b1e8e38c48b328f819c97199a0825d2breed@google.com } 1598b4162b12b1e8e38c48b328f819c97199a0825d2breed@google.com return fGlyphCount; 1599b4162b12b1e8e38c48b328f819c97199a0825d2breed@google.com} 1600b4162b12b1e8e38c48b328f819c97199a0825d2breed@google.com 1601839702b61934914118ec557dd641be322eba3b5fbungeman@google.comSkTypeface::LocalizedStrings* SkTypeface_FreeType::onCreateFamilyNameIterator() const { 1602a980269c2498836101146adc729ef780fb89824ebungeman@google.com SkTypeface::LocalizedStrings* nameIter = 1603a980269c2498836101146adc729ef780fb89824ebungeman@google.com SkOTUtils::LocalizedStrings_NameTable::CreateForFamilyNames(*this); 1604a980269c2498836101146adc729ef780fb89824ebungeman@google.com if (NULL == nameIter) { 1605a980269c2498836101146adc729ef780fb89824ebungeman@google.com SkString familyName; 1606a980269c2498836101146adc729ef780fb89824ebungeman@google.com this->getFamilyName(&familyName); 1607a980269c2498836101146adc729ef780fb89824ebungeman@google.com SkString language("und"); //undetermined 1608a980269c2498836101146adc729ef780fb89824ebungeman@google.com nameIter = new SkOTUtils::LocalizedStrings_SingleName(familyName, language); 1609a980269c2498836101146adc729ef780fb89824ebungeman@google.com } 1610a980269c2498836101146adc729ef780fb89824ebungeman@google.com return nameIter; 1611a980269c2498836101146adc729ef780fb89824ebungeman@google.com} 1612a980269c2498836101146adc729ef780fb89824ebungeman@google.com 1613ddc218e508c4cdd16ff3461498cbbc2b5189b2bebungeman@google.comint SkTypeface_FreeType::onGetTableTags(SkFontTableTag tags[]) const { 1614ddc218e508c4cdd16ff3461498cbbc2b5189b2bebungeman@google.com AutoFTAccess fta(this); 1615ddc218e508c4cdd16ff3461498cbbc2b5189b2bebungeman@google.com FT_Face face = fta.face(); 1616ddc218e508c4cdd16ff3461498cbbc2b5189b2bebungeman@google.com 1617ddc218e508c4cdd16ff3461498cbbc2b5189b2bebungeman@google.com FT_ULong tableCount = 0; 1618ddc218e508c4cdd16ff3461498cbbc2b5189b2bebungeman@google.com FT_Error error; 1619ddc218e508c4cdd16ff3461498cbbc2b5189b2bebungeman@google.com 1620ddc218e508c4cdd16ff3461498cbbc2b5189b2bebungeman@google.com // When 'tag' is NULL, returns number of tables in 'length'. 1621ddc218e508c4cdd16ff3461498cbbc2b5189b2bebungeman@google.com error = FT_Sfnt_Table_Info(face, 0, NULL, &tableCount); 1622ddc218e508c4cdd16ff3461498cbbc2b5189b2bebungeman@google.com if (error) { 1623ddc218e508c4cdd16ff3461498cbbc2b5189b2bebungeman@google.com return 0; 1624ddc218e508c4cdd16ff3461498cbbc2b5189b2bebungeman@google.com } 1625ddc218e508c4cdd16ff3461498cbbc2b5189b2bebungeman@google.com 1626ddc218e508c4cdd16ff3461498cbbc2b5189b2bebungeman@google.com if (tags) { 1627ddc218e508c4cdd16ff3461498cbbc2b5189b2bebungeman@google.com for (FT_ULong tableIndex = 0; tableIndex < tableCount; ++tableIndex) { 1628ddc218e508c4cdd16ff3461498cbbc2b5189b2bebungeman@google.com FT_ULong tableTag; 1629ddc218e508c4cdd16ff3461498cbbc2b5189b2bebungeman@google.com FT_ULong tablelength; 1630ddc218e508c4cdd16ff3461498cbbc2b5189b2bebungeman@google.com error = FT_Sfnt_Table_Info(face, tableIndex, &tableTag, &tablelength); 1631ddc218e508c4cdd16ff3461498cbbc2b5189b2bebungeman@google.com if (error) { 1632ddc218e508c4cdd16ff3461498cbbc2b5189b2bebungeman@google.com return 0; 1633ddc218e508c4cdd16ff3461498cbbc2b5189b2bebungeman@google.com } 1634ddc218e508c4cdd16ff3461498cbbc2b5189b2bebungeman@google.com tags[tableIndex] = static_cast<SkFontTableTag>(tableTag); 1635ddc218e508c4cdd16ff3461498cbbc2b5189b2bebungeman@google.com } 1636ddc218e508c4cdd16ff3461498cbbc2b5189b2bebungeman@google.com } 1637ddc218e508c4cdd16ff3461498cbbc2b5189b2bebungeman@google.com return tableCount; 1638ddc218e508c4cdd16ff3461498cbbc2b5189b2bebungeman@google.com} 1639ddc218e508c4cdd16ff3461498cbbc2b5189b2bebungeman@google.com 1640ddc218e508c4cdd16ff3461498cbbc2b5189b2bebungeman@google.comsize_t SkTypeface_FreeType::onGetTableData(SkFontTableTag tag, size_t offset, 1641ddc218e508c4cdd16ff3461498cbbc2b5189b2bebungeman@google.com size_t length, void* data) const 1642ddc218e508c4cdd16ff3461498cbbc2b5189b2bebungeman@google.com{ 1643ddc218e508c4cdd16ff3461498cbbc2b5189b2bebungeman@google.com AutoFTAccess fta(this); 1644ddc218e508c4cdd16ff3461498cbbc2b5189b2bebungeman@google.com FT_Face face = fta.face(); 1645ddc218e508c4cdd16ff3461498cbbc2b5189b2bebungeman@google.com 1646ddc218e508c4cdd16ff3461498cbbc2b5189b2bebungeman@google.com FT_ULong tableLength = 0; 1647ddc218e508c4cdd16ff3461498cbbc2b5189b2bebungeman@google.com FT_Error error; 1648ddc218e508c4cdd16ff3461498cbbc2b5189b2bebungeman@google.com 1649ddc218e508c4cdd16ff3461498cbbc2b5189b2bebungeman@google.com // When 'length' is 0 it is overwritten with the full table length; 'offset' is ignored. 1650ddc218e508c4cdd16ff3461498cbbc2b5189b2bebungeman@google.com error = FT_Load_Sfnt_Table(face, tag, 0, NULL, &tableLength); 1651ddc218e508c4cdd16ff3461498cbbc2b5189b2bebungeman@google.com if (error) { 1652ddc218e508c4cdd16ff3461498cbbc2b5189b2bebungeman@google.com return 0; 1653ddc218e508c4cdd16ff3461498cbbc2b5189b2bebungeman@google.com } 1654ddc218e508c4cdd16ff3461498cbbc2b5189b2bebungeman@google.com 1655ddc218e508c4cdd16ff3461498cbbc2b5189b2bebungeman@google.com if (offset > tableLength) { 1656ddc218e508c4cdd16ff3461498cbbc2b5189b2bebungeman@google.com return 0; 1657ddc218e508c4cdd16ff3461498cbbc2b5189b2bebungeman@google.com } 16585ecd4fac89e854b85850bee1920d96c6ba1af259bungeman@google.com FT_ULong size = SkTMin((FT_ULong)length, tableLength - (FT_ULong)offset); 165949f085dddff10473b6ebf832a974288300224e60bsalomon if (data) { 1660ddc218e508c4cdd16ff3461498cbbc2b5189b2bebungeman@google.com error = FT_Load_Sfnt_Table(face, tag, offset, reinterpret_cast<FT_Byte*>(data), &size); 1661ddc218e508c4cdd16ff3461498cbbc2b5189b2bebungeman@google.com if (error) { 1662ddc218e508c4cdd16ff3461498cbbc2b5189b2bebungeman@google.com return 0; 1663ddc218e508c4cdd16ff3461498cbbc2b5189b2bebungeman@google.com } 1664ddc218e508c4cdd16ff3461498cbbc2b5189b2bebungeman@google.com } 1665ddc218e508c4cdd16ff3461498cbbc2b5189b2bebungeman@google.com 1666ddc218e508c4cdd16ff3461498cbbc2b5189b2bebungeman@google.com return size; 1667ddc218e508c4cdd16ff3461498cbbc2b5189b2bebungeman@google.com} 1668ddc218e508c4cdd16ff3461498cbbc2b5189b2bebungeman@google.com 1669b4162b12b1e8e38c48b328f819c97199a0825d2breed@google.com/////////////////////////////////////////////////////////////////////////////// 1670b4162b12b1e8e38c48b328f819c97199a0825d2breed@google.com/////////////////////////////////////////////////////////////////////////////// 16718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 16723a21d61668e0ac6529f9930669dd47be123ec333bungeman/*static*/ bool SkTypeface_FreeType::ScanFont( 16733a21d61668e0ac6529f9930669dd47be123ec333bungeman SkStream* stream, int ttcIndex, SkString* name, SkTypeface::Style* style, bool* isFixedPitch) 16743a21d61668e0ac6529f9930669dd47be123ec333bungeman{ 16758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com FT_Library library; 1676bfbd4fff66da7fa4409a4d4bf838b85ef69a7200reed@android.com if (FT_Init_FreeType(&library)) { 16774dc686d75353235260c716242f4ed596b70beb95djsollen@google.com return false; 16788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 16798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 16808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com FT_Open_Args args; 16818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com memset(&args, 0, sizeof(args)); 16828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 16838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const void* memoryBase = stream->getMemoryBase(); 16848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com FT_StreamRec streamRec; 16858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 168649f085dddff10473b6ebf832a974288300224e60bsalomon if (memoryBase) { 16878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com args.flags = FT_OPEN_MEMORY; 16888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com args.memory_base = (const FT_Byte*)memoryBase; 16898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com args.memory_size = stream->getLength(); 16908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 16918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com memset(&streamRec, 0, sizeof(streamRec)); 16925dd45021c37e24cd2c8e91a0f1a1d28a77ad613cdjsollen@google.com streamRec.size = stream->getLength(); 16938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com streamRec.descriptor.pointer = stream; 16948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com streamRec.read = sk_stream_read; 16958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com streamRec.close = sk_stream_close; 16968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 16978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com args.flags = FT_OPEN_STREAM; 16988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com args.stream = &streamRec; 16998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 17008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 17018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com FT_Face face; 17023a21d61668e0ac6529f9930669dd47be123ec333bungeman if (FT_Open_Face(library, &args, ttcIndex, &face)) { 17038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com FT_Done_FreeType(library); 17044dc686d75353235260c716242f4ed596b70beb95djsollen@google.com return false; 17058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 17068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 17074dc686d75353235260c716242f4ed596b70beb95djsollen@google.com int tempStyle = SkTypeface::kNormal; 17088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (face->style_flags & FT_STYLE_FLAG_BOLD) { 17094dc686d75353235260c716242f4ed596b70beb95djsollen@google.com tempStyle |= SkTypeface::kBold; 17108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 17118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (face->style_flags & FT_STYLE_FLAG_ITALIC) { 17124dc686d75353235260c716242f4ed596b70beb95djsollen@google.com tempStyle |= SkTypeface::kItalic; 17134dc686d75353235260c716242f4ed596b70beb95djsollen@google.com } 17144dc686d75353235260c716242f4ed596b70beb95djsollen@google.com 17154dc686d75353235260c716242f4ed596b70beb95djsollen@google.com if (name) { 17164dc686d75353235260c716242f4ed596b70beb95djsollen@google.com name->set(face->family_name); 17174dc686d75353235260c716242f4ed596b70beb95djsollen@google.com } 17184dc686d75353235260c716242f4ed596b70beb95djsollen@google.com if (style) { 17194dc686d75353235260c716242f4ed596b70beb95djsollen@google.com *style = (SkTypeface::Style) tempStyle; 17208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1721fe74765f0d302669ae49e68074492bdfe0ce6e6fbungeman@google.com if (isFixedPitch) { 1722fe74765f0d302669ae49e68074492bdfe0ce6e6fbungeman@google.com *isFixedPitch = FT_IS_FIXED_WIDTH(face); 17235b31b0f1eaca0cdc3aa5697e8efa1baf68b0774ereed@google.com } 17248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 17258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com FT_Done_Face(face); 17268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com FT_Done_FreeType(library); 17274dc686d75353235260c716242f4ed596b70beb95djsollen@google.com return true; 17288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 1729