1fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot/* 2fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * Copyright 2006 The Android Open Source Project 3fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * 4fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * Use of this source code is governed by a BSD-style license that can be 5fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * found in the LICENSE file. 6fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot */ 7fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 8fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkAdvancedTypefaceMetrics.h" 9fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkBitmap.h" 10fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkCanvas.h" 11fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkColorData.h" 12fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkDescriptor.h" 13fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkFDot6.h" 14fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkFontDescriptor.h" 15fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkFontHost_FreeType_common.h" 16fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkGlyph.h" 17fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkMakeUnique.h" 18fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkMask.h" 19fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkMaskGamma.h" 20fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkMatrix22.h" 21fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkMalloc.h" 22fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkMutex.h" 23fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkOTUtils.h" 24fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkPath.h" 25fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkScalerContext.h" 26fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkStream.h" 27fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkString.h" 28fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkTemplates.h" 29fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include <memory> 30fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 31fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include <ft2build.h> 32fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include FT_ADVANCES_H 33fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include FT_BITMAP_H 34fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include FT_FREETYPE_H 35fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include FT_LCD_FILTER_H 36fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include FT_MODULE_H 37fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include FT_MULTIPLE_MASTERS_H 38fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include FT_OUTLINE_H 39fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include FT_SIZES_H 40fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include FT_SYSTEM_H 41fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include FT_TRUETYPE_TABLES_H 42fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include FT_TYPE1_TABLES_H 43fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include FT_XFREE86_H 44fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 45fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// SK_FREETYPE_MINIMUM_RUNTIME_VERSION 0x<major><minor><patch><flags> 46fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// Flag SK_FREETYPE_DLOPEN: also try dlopen to get newer features. 47fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#define SK_FREETYPE_DLOPEN (0x1) 48fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#ifndef SK_FREETYPE_MINIMUM_RUNTIME_VERSION 49fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot# if defined(SK_BUILD_FOR_ANDROID_FRAMEWORK) || defined (SK_BUILD_FOR_GOOGLE3) 50fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot# define SK_FREETYPE_MINIMUM_RUNTIME_VERSION (((FREETYPE_MAJOR) << 24) | ((FREETYPE_MINOR) << 16) | ((FREETYPE_PATCH) << 8)) 51fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot# else 52fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot# define SK_FREETYPE_MINIMUM_RUNTIME_VERSION ((2 << 24) | (3 << 16) | (11 << 8) | (SK_FREETYPE_DLOPEN)) 53fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot# endif 54fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif 55fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#if SK_FREETYPE_MINIMUM_RUNTIME_VERSION & SK_FREETYPE_DLOPEN 56fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot# include <dlfcn.h> 57fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif 58fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 59fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// FT_LOAD_COLOR and the corresponding FT_Pixel_Mode::FT_PIXEL_MODE_BGRA 60fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// were introduced in FreeType 2.5.0. 61fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// The following may be removed once FreeType 2.5.0 is required to build. 62fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#ifndef FT_LOAD_COLOR 63fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot# define FT_LOAD_COLOR ( 1L << 20 ) 64fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot# define FT_PIXEL_MODE_BGRA 7 65fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif 66fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 67fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// FT_LOAD_BITMAP_METRICS_ONLY was introduced in FreeType 2.7.1 68fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// The following may be removed once FreeType 2.7.1 is required to build. 69fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#ifndef FT_LOAD_BITMAP_METRICS_ONLY 70fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot# define FT_LOAD_BITMAP_METRICS_ONLY ( 1L << 22 ) 71fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif 72fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 73fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot//#define ENABLE_GLYPH_SPEW // for tracing calls 74fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot//#define DUMP_STRIKE_CREATION 75fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot//#define SK_FONTHOST_FREETYPE_RUNTIME_VERSION 76fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot//#define SK_GAMMA_APPLY_TO_A8 77fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 78fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic bool isLCD(const SkScalerContextRec& rec) { 79fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return SkMask::kLCD16_Format == rec.fMaskFormat; 80fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 81fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 82fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot////////////////////////////////////////////////////////////////////////// 83fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 84fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotextern "C" { 85fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot static void* sk_ft_alloc(FT_Memory, long size) { 86fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return sk_malloc_throw(size); 87fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 88fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot static void sk_ft_free(FT_Memory, void* block) { 89fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot sk_free(block); 90fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 91fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot static void* sk_ft_realloc(FT_Memory, long cur_size, long new_size, void* block) { 92fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return sk_realloc_throw(block, new_size); 93fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 94fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}; 95fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotFT_MemoryRec_ gFTMemory = { nullptr, sk_ft_alloc, sk_ft_free, sk_ft_realloc }; 96fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 97fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotclass FreeTypeLibrary : SkNoncopyable { 98fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotpublic: 99fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FreeTypeLibrary() 100fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot : fGetVarDesignCoordinates(nullptr) 101fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot , fLibrary(nullptr) 102fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot , fIsLCDSupported(false) 103fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot , fLCDExtra(0) 104fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot { 105fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (FT_New_Library(&gFTMemory, &fLibrary)) { 106fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 107fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 108fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FT_Add_Default_Modules(fLibrary); 109fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 110fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // When using dlsym 111fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // *(void**)(&procPtr) = dlsym(self, "proc"); 112fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // is non-standard, but safe for POSIX. Cannot write 113fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // *reinterpret_cast<void**>(&procPtr) = dlsym(self, "proc"); 114fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // because clang has not implemented DR573. See http://clang.llvm.org/cxx_dr_status.html . 115fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 116fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FT_Int major, minor, patch; 117fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FT_Library_Version(fLibrary, &major, &minor, &patch); 118fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 119fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#if SK_FREETYPE_MINIMUM_RUNTIME_VERSION >= 0x02070100 120fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fGetVarDesignCoordinates = FT_Get_Var_Design_Coordinates; 121fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#elif SK_FREETYPE_MINIMUM_RUNTIME_VERSION & SK_FREETYPE_DLOPEN 122fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (major > 2 || ((major == 2 && minor > 7) || (major == 2 && minor == 7 && patch >= 0))) { 123fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot //The FreeType library is already loaded, so symbols are available in process. 124fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot void* self = dlopen(nullptr, RTLD_LAZY); 125fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (self) { 126fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot *(void**)(&fGetVarDesignCoordinates) = dlsym(self, "FT_Get_Var_Design_Coordinates"); 127fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot dlclose(self); 128fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 129fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 130fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif 131fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 132fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#if SK_FREETYPE_MINIMUM_RUNTIME_VERSION >= 0x02070200 133fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FT_Set_Default_Properties(fLibrary); 134fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#elif SK_FREETYPE_MINIMUM_RUNTIME_VERSION & SK_FREETYPE_DLOPEN 135fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (major > 2 || ((major == 2 && minor > 7) || (major == 2 && minor == 7 && patch >= 1))) { 136fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot //The FreeType library is already loaded, so symbols are available in process. 137fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot void* self = dlopen(nullptr, RTLD_LAZY); 138fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (self) { 139fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FT_Set_Default_PropertiesProc setDefaultProperties; 140fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot *(void**)(&setDefaultProperties) = dlsym(self, "FT_Set_Default_Properties"); 141fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot dlclose(self); 142fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 143fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (setDefaultProperties) { 144fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot setDefaultProperties(fLibrary); 145fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 146fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 147fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 148fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif 149fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 150fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Setup LCD filtering. This reduces color fringes for LCD smoothed glyphs. 151fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // The default has changed over time, so this doesn't mean the same thing to all users. 152fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (FT_Library_SetLcdFilter(fLibrary, FT_LCD_FILTER_DEFAULT) == 0) { 153fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fIsLCDSupported = true; 154fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fLCDExtra = 2; //Using a filter adds one full pixel to each side. 155fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 156fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 157fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot ~FreeTypeLibrary() { 158fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (fLibrary) { 159fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FT_Done_Library(fLibrary); 160fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 161fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 162fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 163fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FT_Library library() { return fLibrary; } 164fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bool isLCDSupported() { return fIsLCDSupported; } 165fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot int lcdExtra() { return fLCDExtra; } 166fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 167fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // FT_Get_{MM,Var}_{Blend,Design}_Coordinates were added in FreeType 2.7.1. 168fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Prior to this there was no way to get the coordinates out of the FT_Face. 169fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // This wasn't too bad because you needed to specify them anyway, and the clamp was provided. 170fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // However, this doesn't work when face_index specifies named variations as introduced in 2.6.1. 171fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot using FT_Get_Var_Blend_CoordinatesProc = FT_Error (*)(FT_Face, FT_UInt, FT_Fixed*); 172fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FT_Get_Var_Blend_CoordinatesProc fGetVarDesignCoordinates; 173fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 174fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotprivate: 175fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FT_Library fLibrary; 176fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bool fIsLCDSupported; 177fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot int fLCDExtra; 178fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 179fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // FT_Library_SetLcdFilterWeights was introduced in FreeType 2.4.0. 180fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // The following platforms provide FreeType of at least 2.4.0. 181fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Ubuntu >= 11.04 (previous deprecated April 2013) 182fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Debian >= 6.0 (good) 183fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // OpenSuse >= 11.4 (previous deprecated January 2012 / Nov 2013 for Evergreen 11.2) 184fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Fedora >= 14 (good) 185fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Android >= Gingerbread (good) 186fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // RHEL >= 7 (6 has 2.3.11, EOL Nov 2020, Phase 3 May 2017) 187fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot using FT_Library_SetLcdFilterWeightsProc = FT_Error (*)(FT_Library, unsigned char*); 188fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 189fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // FreeType added the ability to read global properties in 2.7.0. After 2.7.1 a means for users 190fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // of FT_New_Library to request these global properties to be read was added. 191fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot using FT_Set_Default_PropertiesProc = void (*)(FT_Library); 192fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}; 193fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 194fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstruct SkFaceRec; 195fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 196fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotSK_DECLARE_STATIC_MUTEX(gFTMutex); 197fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic FreeTypeLibrary* gFTLibrary; 198fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic SkFaceRec* gFaceRecHead; 199fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 200fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// Private to ref_ft_library and unref_ft_library 201fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic int gFTCount; 202fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 203fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// Caller must lock gFTMutex before calling this function. 204fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic bool ref_ft_library() { 205fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot gFTMutex.assertHeld(); 206fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(gFTCount >= 0); 207fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 208fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (0 == gFTCount) { 209fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(nullptr == gFTLibrary); 210fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot gFTLibrary = new FreeTypeLibrary; 211fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 212fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot ++gFTCount; 213fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return gFTLibrary->library(); 214fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 215fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 216fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// Caller must lock gFTMutex before calling this function. 217fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic void unref_ft_library() { 218fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot gFTMutex.assertHeld(); 219fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(gFTCount > 0); 220fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 221fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot --gFTCount; 222fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (0 == gFTCount) { 223fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(nullptr == gFaceRecHead); 224fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(nullptr != gFTLibrary); 225fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot delete gFTLibrary; 226fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDEBUGCODE(gFTLibrary = nullptr;) 227fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 228fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 229fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 230fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot/////////////////////////////////////////////////////////////////////////// 231fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 232fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstruct SkFaceRec { 233fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkFaceRec* fNext; 234fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot std::unique_ptr<FT_FaceRec, SkFunctionWrapper<FT_Error, FT_FaceRec, FT_Done_Face>> fFace; 235fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FT_StreamRec fFTStream; 236fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot std::unique_ptr<SkStreamAsset> fSkStream; 237fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot uint32_t fRefCnt; 238fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot uint32_t fFontID; 239fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 240fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // FreeType prior to 2.7.1 does not implement retreiving variation design metrics. 241fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Cache the variation design metrics used to create the font if the user specifies them. 242fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkAutoSTMalloc<4, SkFixed> fAxes; 243fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot int fAxesCount; 244fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 245fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // FreeType from 2.6.1 (14d6b5d7) until 2.7.0 (ee3f36f6b38) uses font_index for both font index 246fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // and named variation index on input, but masks the named variation index part on output. 247fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Manually keep track of when a named variation is requested for 2.6.1 until 2.7.1. 248fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bool fNamedVariationSpecified; 249fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 250fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkFaceRec(std::unique_ptr<SkStreamAsset> stream, uint32_t fontID); 251fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}; 252fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 253fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotextern "C" { 254fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot static unsigned long sk_ft_stream_io(FT_Stream ftStream, 255fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot unsigned long offset, 256fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot unsigned char* buffer, 257fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot unsigned long count) 258fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot { 259fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkStreamAsset* stream = static_cast<SkStreamAsset*>(ftStream->descriptor.pointer); 260fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 261fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (count) { 262fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!stream->seek(offset)) { 263fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return 0; 264fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 265fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot count = stream->read(buffer, count); 266fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 267fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return count; 268fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 269fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 270fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot static void sk_ft_stream_close(FT_Stream) {} 271fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 272fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 273fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotSkFaceRec::SkFaceRec(std::unique_ptr<SkStreamAsset> stream, uint32_t fontID) 274fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot : fNext(nullptr), fSkStream(std::move(stream)), fRefCnt(1), fFontID(fontID) 275fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot , fAxesCount(0), fNamedVariationSpecified(false) 276fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot{ 277fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot sk_bzero(&fFTStream, sizeof(fFTStream)); 278fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fFTStream.size = fSkStream->getLength(); 279fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fFTStream.descriptor.pointer = fSkStream.get(); 280fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fFTStream.read = sk_ft_stream_io; 281fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fFTStream.close = sk_ft_stream_close; 282fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 283fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 284fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic void ft_face_setup_axes(SkFaceRec* rec, const SkFontData& data) { 285fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!(rec->fFace->face_flags & FT_FACE_FLAG_MULTIPLE_MASTERS)) { 286fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 287fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 288fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 289fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // If a named variation is requested, don't overwrite the named variation's position. 290fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (data.getIndex() > 0xFFFF) { 291fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot rec->fNamedVariationSpecified = true; 292fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 293fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 294fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 295fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDEBUGCODE( 296fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FT_MM_Var* variations = nullptr; 297fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (FT_Get_MM_Var(rec->fFace.get(), &variations)) { 298fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDEBUGF(("INFO: font %s claims variations, but none found.\n", 299fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot rec->fFace->family_name)); 300fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 301fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 302fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkAutoFree autoFreeVariations(variations); 303fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 304fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (static_cast<FT_UInt>(data.getAxisCount()) != variations->num_axis) { 305fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDEBUGF(("INFO: font %s has %d variations, but %d were specified.\n", 306fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot rec->fFace->family_name, variations->num_axis, data.getAxisCount())); 307fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 308fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 309fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot ) 310fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 311fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkAutoSTMalloc<4, FT_Fixed> coords(data.getAxisCount()); 312fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot for (int i = 0; i < data.getAxisCount(); ++i) { 313fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot coords[i] = data.getAxis()[i]; 314fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 315fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (FT_Set_Var_Design_Coordinates(rec->fFace.get(), data.getAxisCount(), coords.get())) { 316fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDEBUGF(("INFO: font %s has variations, but specified variations could not be set.\n", 317fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot rec->fFace->family_name)); 318fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 319fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 320fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 321fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot rec->fAxesCount = data.getAxisCount(); 322fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot rec->fAxes.reset(rec->fAxesCount); 323fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot for (int i = 0; i < rec->fAxesCount; ++i) { 324fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot rec->fAxes[i] = data.getAxis()[i]; 325fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 326fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 327fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 328fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// Will return nullptr on failure 329fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// Caller must lock gFTMutex before calling this function. 330fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic SkFaceRec* ref_ft_face(const SkTypeface* typeface) { 331fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot gFTMutex.assertHeld(); 332fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 333fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkFontID fontID = typeface->uniqueID(); 334fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkFaceRec* cachedRec = gFaceRecHead; 335fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot while (cachedRec) { 336fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (cachedRec->fFontID == fontID) { 337fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(cachedRec->fFace); 338fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot cachedRec->fRefCnt += 1; 339fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return cachedRec; 340fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 341fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot cachedRec = cachedRec->fNext; 342fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 343fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 344fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot std::unique_ptr<SkFontData> data = typeface->makeFontData(); 345fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (nullptr == data || !data->hasStream()) { 346fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return nullptr; 347fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 348fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 349fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot std::unique_ptr<SkFaceRec> rec(new SkFaceRec(data->detachStream(), fontID)); 350fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 351fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FT_Open_Args args; 352fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot memset(&args, 0, sizeof(args)); 353fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const void* memoryBase = rec->fSkStream->getMemoryBase(); 354fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (memoryBase) { 355fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot args.flags = FT_OPEN_MEMORY; 356fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot args.memory_base = (const FT_Byte*)memoryBase; 357fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot args.memory_size = rec->fSkStream->getLength(); 358fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else { 359fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot args.flags = FT_OPEN_STREAM; 360fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot args.stream = &rec->fFTStream; 361fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 362fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 363fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot { 364fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FT_Face rawFace; 365fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FT_Error err = FT_Open_Face(gFTLibrary->library(), &args, data->getIndex(), &rawFace); 366fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (err) { 367fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SK_TRACEFTR(err, "unable to open font '%x'", fontID); 368fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return nullptr; 369fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 370fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot rec->fFace.reset(rawFace); 371fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 372fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(rec->fFace); 373fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 374fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot ft_face_setup_axes(rec.get(), *data); 375fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 376fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // FreeType will set the charmap to the "most unicode" cmap if it exists. 377fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // If there are no unicode cmaps, the charmap is set to nullptr. 378fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // However, "symbol" cmaps should also be considered "fallback unicode" cmaps 379fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // because they are effectively private use area only (even if they aren't). 380fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // This is the last on the fallback list at 381fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6cmap.html 382fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!rec->fFace->charmap) { 383fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FT_Select_Charmap(rec->fFace.get(), FT_ENCODING_MS_SYMBOL); 384fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 385fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 386fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot rec->fNext = gFaceRecHead; 387fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot gFaceRecHead = rec.get(); 388fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return rec.release(); 389fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 390fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 391fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// Caller must lock gFTMutex before calling this function. 392fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// Marked extern because vc++ does not support internal linkage template parameters. 393fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotextern /*static*/ void unref_ft_face(SkFaceRec* faceRec) { 394fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot gFTMutex.assertHeld(); 395fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 396fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkFaceRec* rec = gFaceRecHead; 397fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkFaceRec* prev = nullptr; 398fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot while (rec) { 399fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkFaceRec* next = rec->fNext; 400fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (rec->fFace == faceRec->fFace) { 401fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (--rec->fRefCnt == 0) { 402fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (prev) { 403fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot prev->fNext = next; 404fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else { 405fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot gFaceRecHead = next; 406fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 407fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot delete rec; 408fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 409fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 410fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 411fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot prev = rec; 412fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot rec = next; 413fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 414fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDEBUGFAIL("shouldn't get here, face not in list"); 415fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 416fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 417fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotclass AutoFTAccess { 418fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotpublic: 419fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot AutoFTAccess(const SkTypeface* tf) : fFaceRec(nullptr) { 420fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot gFTMutex.acquire(); 421fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT_RELEASE(ref_ft_library()); 422fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fFaceRec = ref_ft_face(tf); 423fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 424fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 425fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot ~AutoFTAccess() { 426fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (fFaceRec) { 427fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot unref_ft_face(fFaceRec); 428fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 429fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot unref_ft_library(); 430fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot gFTMutex.release(); 431fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 432fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 433fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FT_Face face() { return fFaceRec ? fFaceRec->fFace.get() : nullptr; } 434fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot int getAxesCount() { return fFaceRec ? fFaceRec->fAxesCount : 0; } 435fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkFixed* getAxes() { return fFaceRec ? fFaceRec->fAxes.get() : nullptr; } 436fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bool isNamedVariationSpecified() { 437fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return fFaceRec ? fFaceRec->fNamedVariationSpecified : false; 438fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 439fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 440fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotprivate: 441fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkFaceRec* fFaceRec; 442fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}; 443fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 444fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot/////////////////////////////////////////////////////////////////////////// 445fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 446fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotclass SkScalerContext_FreeType : public SkScalerContext_FreeType_Base { 447fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotpublic: 448fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkScalerContext_FreeType(sk_sp<SkTypeface>, 449fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkScalerContextEffects&, 450fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkDescriptor* desc); 451fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot ~SkScalerContext_FreeType() override; 452fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 453fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bool success() const { 454fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return fFTSize != nullptr && fFace != nullptr; 455fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 456fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 457fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotprotected: 458fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot unsigned generateGlyphCount() override; 459fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot uint16_t generateCharToGlyph(SkUnichar uni) override; 460fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot void generateAdvance(SkGlyph* glyph) override; 461fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot void generateMetrics(SkGlyph* glyph) override; 462fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot void generateImage(const SkGlyph& glyph) override; 463fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot void generatePath(SkGlyphID glyphID, SkPath* path) override; 464fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot void generateFontMetrics(SkPaint::FontMetrics*) override; 465fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkUnichar generateGlyphToChar(uint16_t glyph) override; 466fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 467fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotprivate: 468fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot using UnrefFTFace = SkFunctionWrapper<void, SkFaceRec, unref_ft_face>; 469fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot std::unique_ptr<SkFaceRec, UnrefFTFace> fFaceRec; 470fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 471fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FT_Face fFace; // Borrowed face from gFaceRecHead. 472fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FT_Size fFTSize; // The size on the fFace for this scaler. 473fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FT_Int fStrikeIndex; 474fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 475fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot /** The rest of the matrix after FreeType handles the size. 476fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * With outline font rasterization this is handled by FreeType with FT_Set_Transform. 477fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * With bitmap only fonts this matrix must be applied to scale the bitmap. 478fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot */ 479fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkMatrix fMatrix22Scalar; 480fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot /** Same as fMatrix22Scalar, but in FreeType units and space. */ 481fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FT_Matrix fMatrix22; 482fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot /** The actual size requested. */ 483fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkVector fScale; 484fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 485fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot uint32_t fLoadGlyphFlags; 486fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bool fDoLinearMetrics; 487fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bool fLCDIsVert; 488fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 489fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FT_Error setupSize(); 490fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot void getBBoxForCurrentGlyph(SkGlyph* glyph, FT_BBox* bbox, 491fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bool snapToPixelBoundary = false); 492fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bool getCBoxForLetter(char letter, FT_BBox* bbox); 493fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Caller must lock gFTMutex before calling this function. 494fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot void updateGlyphIfLCD(SkGlyph* glyph); 495fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Caller must lock gFTMutex before calling this function. 496fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // update FreeType2 glyph slot with glyph emboldened 497fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot void emboldenIfNeeded(FT_Face face, FT_GlyphSlot glyph, SkGlyphID gid); 498fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bool shouldSubpixelBitmap(const SkGlyph&, const SkMatrix&); 499fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}; 500fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 501fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot/////////////////////////////////////////////////////////////////////////// 502fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 503fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic bool canEmbed(FT_Face face) { 504fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FT_UShort fsType = FT_Get_FSType_Flags(face); 505fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return (fsType & (FT_FSTYPE_RESTRICTED_LICENSE_EMBEDDING | 506fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FT_FSTYPE_BITMAP_EMBEDDING_ONLY)) == 0; 507fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 508fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 509fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic bool canSubset(FT_Face face) { 510fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FT_UShort fsType = FT_Get_FSType_Flags(face); 511fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return (fsType & FT_FSTYPE_NO_SUBSETTING) == 0; 512fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 513fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 514fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic void populate_glyph_to_unicode(FT_Face& face, SkTDArray<SkUnichar>* glyphToUnicode) { 515fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FT_Long numGlyphs = face->num_glyphs; 516fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot glyphToUnicode->setCount(SkToInt(numGlyphs)); 517fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot sk_bzero(glyphToUnicode->begin(), sizeof((*glyphToUnicode)[0]) * numGlyphs); 518fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 519fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FT_UInt glyphIndex; 520fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkUnichar charCode = FT_Get_First_Char(face, &glyphIndex); 521fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot while (glyphIndex) { 522fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(glyphIndex < SkToUInt(numGlyphs)); 523fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Use the first character that maps to this glyphID. https://crbug.com/359065 524fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (0 == (*glyphToUnicode)[glyphIndex]) { 525fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot (*glyphToUnicode)[glyphIndex] = charCode; 526fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 527fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot charCode = FT_Get_Next_Char(face, charCode, &glyphIndex); 528fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 529fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 530fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 531fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstd::unique_ptr<SkAdvancedTypefaceMetrics> SkTypeface_FreeType::onGetAdvancedMetrics() const { 532fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot AutoFTAccess fta(this); 533fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FT_Face face = fta.face(); 534fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!face) { 535fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return nullptr; 536fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 537fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 538fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot std::unique_ptr<SkAdvancedTypefaceMetrics> info(new SkAdvancedTypefaceMetrics); 539fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot info->fFontName.set(FT_Get_Postscript_Name(face)); 540fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 541fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (FT_HAS_MULTIPLE_MASTERS(face)) { 542fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot info->fFlags |= SkAdvancedTypefaceMetrics::kMultiMaster_FontFlag; 543fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 544fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!canEmbed(face)) { 545fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot info->fFlags |= SkAdvancedTypefaceMetrics::kNotEmbeddable_FontFlag; 546fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 547fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!canSubset(face)) { 548fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot info->fFlags |= SkAdvancedTypefaceMetrics::kNotSubsettable_FontFlag; 549fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 550fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 551fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const char* fontType = FT_Get_X11_Font_Format(face); 552fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (strcmp(fontType, "Type 1") == 0) { 553fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot info->fType = SkAdvancedTypefaceMetrics::kType1_Font; 554fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else if (strcmp(fontType, "CID Type 1") == 0) { 555fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot info->fType = SkAdvancedTypefaceMetrics::kType1CID_Font; 556fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else if (strcmp(fontType, "CFF") == 0) { 557fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot info->fType = SkAdvancedTypefaceMetrics::kCFF_Font; 558fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else if (strcmp(fontType, "TrueType") == 0) { 559fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot info->fType = SkAdvancedTypefaceMetrics::kTrueType_Font; 560fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else { 561fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot info->fType = SkAdvancedTypefaceMetrics::kOther_Font; 562fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 563fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 564fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot info->fStyle = (SkAdvancedTypefaceMetrics::StyleFlags)0; 565fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (FT_IS_FIXED_WIDTH(face)) { 566fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot info->fStyle |= SkAdvancedTypefaceMetrics::kFixedPitch_Style; 567fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 568fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (face->style_flags & FT_STYLE_FLAG_ITALIC) { 569fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot info->fStyle |= SkAdvancedTypefaceMetrics::kItalic_Style; 570fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 571fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 572fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot PS_FontInfoRec psFontInfo; 573fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot TT_Postscript* postTable; 574fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (FT_Get_PS_Font_Info(face, &psFontInfo) == 0) { 575fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot info->fItalicAngle = psFontInfo.italic_angle; 576fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else if ((postTable = (TT_Postscript*)FT_Get_Sfnt_Table(face, ft_sfnt_post)) != nullptr) { 577fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot info->fItalicAngle = SkFixedFloorToInt(postTable->italicAngle); 578fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else { 579fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot info->fItalicAngle = 0; 580fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 581fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 582fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot info->fAscent = face->ascender; 583fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot info->fDescent = face->descender; 584fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 585fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot TT_PCLT* pcltTable; 586fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot TT_OS2* os2Table; 587fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if ((pcltTable = (TT_PCLT*)FT_Get_Sfnt_Table(face, ft_sfnt_pclt)) != nullptr) { 588fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot info->fCapHeight = pcltTable->CapHeight; 589fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot uint8_t serif_style = pcltTable->SerifStyle & 0x3F; 590fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (2 <= serif_style && serif_style <= 6) { 591fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot info->fStyle |= SkAdvancedTypefaceMetrics::kSerif_Style; 592fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else if (9 <= serif_style && serif_style <= 12) { 593fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot info->fStyle |= SkAdvancedTypefaceMetrics::kScript_Style; 594fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 595fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else if (((os2Table = (TT_OS2*)FT_Get_Sfnt_Table(face, ft_sfnt_os2)) != nullptr) && 596fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // sCapHeight is available only when version 2 or later. 597fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot os2Table->version != 0xFFFF && 598fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot os2Table->version >= 2) 599fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot { 600fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot info->fCapHeight = os2Table->sCapHeight; 601fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 602fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot info->fBBox = SkIRect::MakeLTRB(face->bbox.xMin, face->bbox.yMax, 603fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot face->bbox.xMax, face->bbox.yMin); 604fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 605fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bool perGlyphInfo = FT_IS_SCALABLE(face); 606fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 607fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (perGlyphInfo && info->fType == SkAdvancedTypefaceMetrics::kType1_Font) { 608fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Postscript fonts may contain more than 255 glyphs, so we end up 609fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // using multiple font descriptions with a glyph ordering. Record 610fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // the name of each glyph. 611fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot info->fGlyphNames.reset(face->num_glyphs); 612fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot for (int gID = 0; gID < face->num_glyphs; gID++) { 613fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot char glyphName[128]; // PS limit for names is 127 bytes. 614fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FT_Get_Glyph_Name(face, gID, glyphName, 128); 615fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot info->fGlyphNames[gID].set(glyphName); 616fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 617fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 618fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 619fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (perGlyphInfo && 620fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot info->fType != SkAdvancedTypefaceMetrics::kType1_Font && 621fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot face->num_charmaps) 622fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot { 623fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot populate_glyph_to_unicode(face, &(info->fGlyphToUnicode)); 624fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 625fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 626fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return info; 627fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 628fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 629fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot/////////////////////////////////////////////////////////////////////////// 630fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 631fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic bool bothZero(SkScalar a, SkScalar b) { 632fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return 0 == a && 0 == b; 633fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 634fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 635fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// returns false if there is any non-90-rotation or skew 636fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic bool isAxisAligned(const SkScalerContextRec& rec) { 637fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return 0 == rec.fPreSkewX && 638fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot (bothZero(rec.fPost2x2[0][1], rec.fPost2x2[1][0]) || 639fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bothZero(rec.fPost2x2[0][0], rec.fPost2x2[1][1])); 640fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 641fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 642fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotSkScalerContext* SkTypeface_FreeType::onCreateScalerContext(const SkScalerContextEffects& effects, 643fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkDescriptor* desc) const { 644fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot auto c = skstd::make_unique<SkScalerContext_FreeType>( 645fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot sk_ref_sp(const_cast<SkTypeface_FreeType*>(this)), effects, desc); 646fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!c->success()) { 647fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return nullptr; 648fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 649fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return c.release(); 650fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 651fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 652fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkTypeface_FreeType::onFilterRec(SkScalerContextRec* rec) const { 653fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot //BOGUS: http://code.google.com/p/chromium/issues/detail?id=121119 654fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot //Cap the requested size as larger sizes give bogus values. 655fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot //Remove when http://code.google.com/p/skia/issues/detail?id=554 is fixed. 656fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot //Note that this also currently only protects against large text size requests, 657fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot //the total matrix is not taken into account here. 658fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (rec->fTextSize > SkIntToScalar(1 << 14)) { 659fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot rec->fTextSize = SkIntToScalar(1 << 14); 660fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 661fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 662fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (isLCD(*rec)) { 663fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // TODO: re-work so that FreeType is set-up and selected by the SkFontMgr. 664fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkAutoMutexAcquire ama(gFTMutex); 665fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot ref_ft_library(); 666fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!gFTLibrary->isLCDSupported()) { 667fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // If the runtime Freetype library doesn't support LCD, disable it here. 668fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot rec->fMaskFormat = SkMask::kA8_Format; 669fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 670fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot unref_ft_library(); 671fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 672fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 673fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkPaint::Hinting h = rec->getHinting(); 674fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (SkPaint::kFull_Hinting == h && !isLCD(*rec)) { 675fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // collapse full->normal hinting if we're not doing LCD 676fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot h = SkPaint::kNormal_Hinting; 677fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 678fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 679fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // rotated text looks bad with hinting, so we disable it as needed 680fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!isAxisAligned(*rec)) { 681fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot h = SkPaint::kNo_Hinting; 682fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 683fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot rec->setHinting(h); 684fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 685fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#ifndef SK_GAMMA_APPLY_TO_A8 686fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!isLCD(*rec)) { 687fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // SRGBTODO: Is this correct? Do we want contrast boost? 688fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot rec->ignorePreBlend(); 689fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 690fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif 691fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 692fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 693fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotint SkTypeface_FreeType::onGetUPEM() const { 694fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot AutoFTAccess fta(this); 695fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FT_Face face = fta.face(); 696fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return face ? face->units_per_EM : 0; 697fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 698fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 699fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotbool SkTypeface_FreeType::onGetKerningPairAdjustments(const uint16_t glyphs[], 700fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot int count, int32_t adjustments[]) const { 701fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot AutoFTAccess fta(this); 702fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FT_Face face = fta.face(); 703fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!face || !FT_HAS_KERNING(face)) { 704fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return false; 705fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 706fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 707fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot for (int i = 0; i < count - 1; ++i) { 708fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FT_Vector delta; 709fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FT_Error err = FT_Get_Kerning(face, glyphs[i], glyphs[i+1], 710fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FT_KERNING_UNSCALED, &delta); 711fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (err) { 712fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return false; 713fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 714fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot adjustments[i] = delta.x; 715fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 716fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return true; 717fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 718fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 719fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot/** Returns the bitmap strike equal to or just larger than the requested size. */ 720fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic FT_Int chooseBitmapStrike(FT_Face face, FT_F26Dot6 scaleY) { 721fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (face == nullptr) { 722fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDEBUGF(("chooseBitmapStrike aborted due to nullptr face.\n")); 723fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return -1; 724fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 725fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 726fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FT_Pos requestedPPEM = scaleY; // FT_Bitmap_Size::y_ppem is in 26.6 format. 727fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FT_Int chosenStrikeIndex = -1; 728fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FT_Pos chosenPPEM = 0; 729fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot for (FT_Int strikeIndex = 0; strikeIndex < face->num_fixed_sizes; ++strikeIndex) { 730fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FT_Pos strikePPEM = face->available_sizes[strikeIndex].y_ppem; 731fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (strikePPEM == requestedPPEM) { 732fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // exact match - our search stops here 733fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return strikeIndex; 734fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else if (chosenPPEM < requestedPPEM) { 735fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // attempt to increase chosenPPEM 736fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (chosenPPEM < strikePPEM) { 737fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot chosenPPEM = strikePPEM; 738fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot chosenStrikeIndex = strikeIndex; 739fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 740fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else { 741fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // attempt to decrease chosenPPEM, but not below requestedPPEM 742fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (requestedPPEM < strikePPEM && strikePPEM < chosenPPEM) { 743fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot chosenPPEM = strikePPEM; 744fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot chosenStrikeIndex = strikeIndex; 745fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 746fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 747fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 748fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return chosenStrikeIndex; 749fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 750fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 751fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotSkScalerContext_FreeType::SkScalerContext_FreeType(sk_sp<SkTypeface> typeface, 752fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkScalerContextEffects& effects, 753fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkDescriptor* desc) 754fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot : SkScalerContext_FreeType_Base(std::move(typeface), effects, desc) 755fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot , fFace(nullptr) 756fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot , fFTSize(nullptr) 757fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot , fStrikeIndex(-1) 758fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot{ 759fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkAutoMutexAcquire ac(gFTMutex); 760fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT_RELEASE(ref_ft_library()); 761fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 762fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fFaceRec.reset(ref_ft_face(this->getTypeface())); 763fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 764fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // load the font file 765fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (nullptr == fFaceRec) { 766fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDEBUGF(("Could not create FT_Face.\n")); 767fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 768fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 769fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 770fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fRec.computeMatrices(SkScalerContextRec::kFull_PreMatrixScale, &fScale, &fMatrix22Scalar); 771fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 772fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FT_F26Dot6 scaleX = SkScalarToFDot6(fScale.fX); 773fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FT_F26Dot6 scaleY = SkScalarToFDot6(fScale.fY); 774fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fMatrix22.xx = SkScalarToFixed(fMatrix22Scalar.getScaleX()); 775fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fMatrix22.xy = SkScalarToFixed(-fMatrix22Scalar.getSkewX()); 776fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fMatrix22.yx = SkScalarToFixed(-fMatrix22Scalar.getSkewY()); 777fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fMatrix22.yy = SkScalarToFixed(fMatrix22Scalar.getScaleY()); 778fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 779fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fLCDIsVert = SkToBool(fRec.fFlags & SkScalerContext::kLCD_Vertical_Flag); 780fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 781fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // compute the flags we send to Load_Glyph 782fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bool linearMetrics = SkToBool(fRec.fFlags & SkScalerContext::kSubpixelPositioning_Flag); 783fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot { 784fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FT_Int32 loadFlags = FT_LOAD_DEFAULT; 785fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 786fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (SkMask::kBW_Format == fRec.fMaskFormat) { 787fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // See http://code.google.com/p/chromium/issues/detail?id=43252#c24 788fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot loadFlags = FT_LOAD_TARGET_MONO; 789fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (fRec.getHinting() == SkPaint::kNo_Hinting) { 790fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot loadFlags = FT_LOAD_NO_HINTING; 791fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot linearMetrics = true; 792fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 793fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else { 794fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot switch (fRec.getHinting()) { 795fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot case SkPaint::kNo_Hinting: 796fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot loadFlags = FT_LOAD_NO_HINTING; 797fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot linearMetrics = true; 798fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot break; 799fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot case SkPaint::kSlight_Hinting: 800fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot loadFlags = FT_LOAD_TARGET_LIGHT; // This implies FORCE_AUTOHINT 801fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot break; 802fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot case SkPaint::kNormal_Hinting: 803fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (fRec.fFlags & SkScalerContext::kForceAutohinting_Flag) { 804fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot loadFlags = FT_LOAD_FORCE_AUTOHINT; 805fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK 806fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else { 807fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot loadFlags = FT_LOAD_NO_AUTOHINT; 808fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif 809fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 810fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot break; 811fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot case SkPaint::kFull_Hinting: 812fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (fRec.fFlags & SkScalerContext::kForceAutohinting_Flag) { 813fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot loadFlags = FT_LOAD_FORCE_AUTOHINT; 814fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot break; 815fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 816fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot loadFlags = FT_LOAD_TARGET_NORMAL; 817fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (isLCD(fRec)) { 818fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (fLCDIsVert) { 819fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot loadFlags = FT_LOAD_TARGET_LCD_V; 820fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else { 821fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot loadFlags = FT_LOAD_TARGET_LCD; 822fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 823fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 824fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot break; 825fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot default: 826fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDebugf("---------- UNKNOWN hinting %d\n", fRec.getHinting()); 827fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot break; 828fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 829fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 830fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 831fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if ((fRec.fFlags & SkScalerContext::kEmbeddedBitmapText_Flag) == 0) { 832fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot loadFlags |= FT_LOAD_NO_BITMAP; 833fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 834fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 835fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Always using FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH to get correct 836fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // advances, as fontconfig and cairo do. 837fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // See http://code.google.com/p/skia/issues/detail?id=222. 838fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot loadFlags |= FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH; 839fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 840fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Use vertical layout if requested. 841fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (fRec.fFlags & SkScalerContext::kVertical_Flag) { 842fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot loadFlags |= FT_LOAD_VERTICAL_LAYOUT; 843fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 844fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 845fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot loadFlags |= FT_LOAD_COLOR; 846fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 847fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fLoadGlyphFlags = loadFlags; 848fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 849fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 850fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot using DoneFTSize = SkFunctionWrapper<FT_Error, skstd::remove_pointer_t<FT_Size>, FT_Done_Size>; 851fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot std::unique_ptr<skstd::remove_pointer_t<FT_Size>, DoneFTSize> ftSize([this]() -> FT_Size { 852fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FT_Size size; 853fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FT_Error err = FT_New_Size(fFaceRec->fFace.get(), &size); 854fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (err != 0) { 855fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SK_TRACEFTR(err, "FT_New_Size(%s) failed.", fFaceRec->fFace->family_name); 856fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return nullptr; 857fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 858fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return size; 859fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot }()); 860fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (nullptr == ftSize) { 861fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDEBUGF(("Could not create FT_Size.\n")); 862fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 863fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 864fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 865fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FT_Error err = FT_Activate_Size(ftSize.get()); 866fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (err != 0) { 867fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SK_TRACEFTR(err, "FT_Activate_Size(%s) failed.", fFaceRec->fFace->family_name); 868fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 869fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 870fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 871fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (FT_IS_SCALABLE(fFaceRec->fFace)) { 872fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot err = FT_Set_Char_Size(fFaceRec->fFace.get(), scaleX, scaleY, 72, 72); 873fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (err != 0) { 874fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SK_TRACEFTR(err, "FT_Set_CharSize(%s, %f, %f) failed.", 875fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fFaceRec->fFace->family_name, fScale.fX, fScale.fY); 876fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 877fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 878fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else if (FT_HAS_FIXED_SIZES(fFaceRec->fFace)) { 879fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fStrikeIndex = chooseBitmapStrike(fFaceRec->fFace.get(), scaleY); 880fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (fStrikeIndex == -1) { 881fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDEBUGF(("No glyphs for font \"%s\" size %f.\n", 882fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fFaceRec->fFace->family_name, fScale.fY)); 883fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 884fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 885fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 886fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot err = FT_Select_Size(fFaceRec->fFace.get(), fStrikeIndex); 887fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (err != 0) { 888fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SK_TRACEFTR(err, "FT_Select_Size(%s, %d) failed.", 889fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fFaceRec->fFace->family_name, fStrikeIndex); 890fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fStrikeIndex = -1; 891fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 892fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 893fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 894fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // A non-ideal size was picked, so recompute the matrix. 895fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // This adjusts for the difference between FT_Set_Char_Size and FT_Select_Size. 896fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fMatrix22Scalar.preScale(fScale.x() / fFaceRec->fFace->size->metrics.x_ppem, 897fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fScale.y() / fFaceRec->fFace->size->metrics.y_ppem); 898fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fMatrix22.xx = SkScalarToFixed(fMatrix22Scalar.getScaleX()); 899fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fMatrix22.xy = SkScalarToFixed(-fMatrix22Scalar.getSkewX()); 900fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fMatrix22.yx = SkScalarToFixed(-fMatrix22Scalar.getSkewY()); 901fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fMatrix22.yy = SkScalarToFixed(fMatrix22Scalar.getScaleY()); 902fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 903fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // FreeType does not provide linear metrics for bitmap fonts. 904fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot linearMetrics = false; 905fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 906fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // FreeType documentation says: 907fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // FT_LOAD_NO_BITMAP -- Ignore bitmap strikes when loading. 908fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Bitmap-only fonts ignore this flag. 909fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // 910fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // However, in FreeType 2.5.1 color bitmap only fonts do not ignore this flag. 911fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Force this flag off for bitmap only fonts. 912fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fLoadGlyphFlags &= ~FT_LOAD_NO_BITMAP; 913fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else { 914fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDEBUGF(("Unknown kind of font \"%s\" size %f.\n", fFaceRec->fFace->family_name, fScale.fY)); 915fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 916fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 917fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 918fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fFTSize = ftSize.release(); 919fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fFace = fFaceRec->fFace.get(); 920fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fDoLinearMetrics = linearMetrics; 921fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 922fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 923fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotSkScalerContext_FreeType::~SkScalerContext_FreeType() { 924fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkAutoMutexAcquire ac(gFTMutex); 925fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 926fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (fFTSize != nullptr) { 927fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FT_Done_Size(fFTSize); 928fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 929fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 930fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fFaceRec = nullptr; 931fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 932fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot unref_ft_library(); 933fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 934fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 935fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot/* We call this before each use of the fFace, since we may be sharing 936fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot this face with other context (at different sizes). 937fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot*/ 938fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotFT_Error SkScalerContext_FreeType::setupSize() { 939fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot gFTMutex.assertHeld(); 940fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FT_Error err = FT_Activate_Size(fFTSize); 941fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (err != 0) { 942fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return err; 943fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 944fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FT_Set_Transform(fFace, &fMatrix22, nullptr); 945fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return 0; 946fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 947fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 948fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotunsigned SkScalerContext_FreeType::generateGlyphCount() { 949fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return fFace->num_glyphs; 950fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 951fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 952fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotuint16_t SkScalerContext_FreeType::generateCharToGlyph(SkUnichar uni) { 953fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkAutoMutexAcquire ac(gFTMutex); 954fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return SkToU16(FT_Get_Char_Index( fFace, uni )); 955fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 956fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 957fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotSkUnichar SkScalerContext_FreeType::generateGlyphToChar(uint16_t glyph) { 958fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkAutoMutexAcquire ac(gFTMutex); 959fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // iterate through each cmap entry, looking for matching glyph indices 960fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FT_UInt glyphIndex; 961fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkUnichar charCode = FT_Get_First_Char( fFace, &glyphIndex ); 962fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 963fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot while (glyphIndex != 0) { 964fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (glyphIndex == glyph) { 965fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return charCode; 966fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 967fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot charCode = FT_Get_Next_Char( fFace, charCode, &glyphIndex ); 968fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 969fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 970fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return 0; 971fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 972fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 973fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic SkScalar SkFT_FixedToScalar(FT_Fixed x) { 974fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return SkFixedToScalar(x); 975fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 976fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 977fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkScalerContext_FreeType::generateAdvance(SkGlyph* glyph) { 978fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot /* unhinted and light hinted text have linearly scaled advances 979fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * which are very cheap to compute with some font formats... 980fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot */ 981fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (fDoLinearMetrics) { 982fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkAutoMutexAcquire ac(gFTMutex); 983fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 984fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (this->setupSize()) { 985fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot glyph->zeroMetrics(); 986fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 987fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 988fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 989fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FT_Error error; 990fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FT_Fixed advance; 991fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 992fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot error = FT_Get_Advance( fFace, glyph->getGlyphID(), 993fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fLoadGlyphFlags | FT_ADVANCE_FLAG_FAST_ONLY, 994fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot &advance ); 995fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (0 == error) { 996fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot glyph->fRsbDelta = 0; 997fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot glyph->fLsbDelta = 0; 998fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkScalar advanceScalar = SkFT_FixedToScalar(advance); 999fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot glyph->fAdvanceX = SkScalarToFloat(fMatrix22Scalar.getScaleX() * advanceScalar); 1000fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot glyph->fAdvanceY = SkScalarToFloat(fMatrix22Scalar.getSkewY() * advanceScalar); 1001fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 1002fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1003fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1004fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1005fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot /* otherwise, we need to load/hint the glyph, which is slower */ 1006fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot this->generateMetrics(glyph); 1007fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 1008fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 1009fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1010fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkScalerContext_FreeType::getBBoxForCurrentGlyph(SkGlyph* glyph, 1011fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FT_BBox* bbox, 1012fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bool snapToPixelBoundary) { 1013fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1014fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FT_Outline_Get_CBox(&fFace->glyph->outline, bbox); 1015fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1016fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (fRec.fFlags & SkScalerContext::kSubpixelPositioning_Flag) { 1017fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot int dx = SkFixedToFDot6(glyph->getSubXFixed()); 1018fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot int dy = SkFixedToFDot6(glyph->getSubYFixed()); 1019fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // negate dy since freetype-y-goes-up and skia-y-goes-down 1020fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bbox->xMin += dx; 1021fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bbox->yMin -= dy; 1022fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bbox->xMax += dx; 1023fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bbox->yMax -= dy; 1024fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1025fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1026fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // outset the box to integral boundaries 1027fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (snapToPixelBoundary) { 1028fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bbox->xMin &= ~63; 1029fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bbox->yMin &= ~63; 1030fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bbox->xMax = (bbox->xMax + 63) & ~63; 1031fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bbox->yMax = (bbox->yMax + 63) & ~63; 1032fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1033fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1034fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Must come after snapToPixelBoundary so that the width and height are 1035fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // consistent. Otherwise asserts will fire later on when generating the 1036fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // glyph image. 1037fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (fRec.fFlags & SkScalerContext::kVertical_Flag) { 1038fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FT_Vector vector; 1039fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot vector.x = fFace->glyph->metrics.vertBearingX - fFace->glyph->metrics.horiBearingX; 1040fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot vector.y = -fFace->glyph->metrics.vertBearingY - fFace->glyph->metrics.horiBearingY; 1041fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FT_Vector_Transform(&vector, &fMatrix22); 1042fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bbox->xMin += vector.x; 1043fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bbox->xMax += vector.x; 1044fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bbox->yMin += vector.y; 1045fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bbox->yMax += vector.y; 1046fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1047fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 1048fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1049fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotbool SkScalerContext_FreeType::getCBoxForLetter(char letter, FT_BBox* bbox) { 1050fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const FT_UInt glyph_id = FT_Get_Char_Index(fFace, letter); 1051fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!glyph_id) { 1052fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return false; 1053fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1054fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (FT_Load_Glyph(fFace, glyph_id, fLoadGlyphFlags) != 0) { 1055fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return false; 1056fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1057fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot emboldenIfNeeded(fFace, fFace->glyph, SkTo<SkGlyphID>(glyph_id)); 1058fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FT_Outline_Get_CBox(&fFace->glyph->outline, bbox); 1059fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return true; 1060fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 1061fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1062fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkScalerContext_FreeType::updateGlyphIfLCD(SkGlyph* glyph) { 1063fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (isLCD(fRec)) { 1064fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (fLCDIsVert) { 1065fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot glyph->fHeight += gFTLibrary->lcdExtra(); 1066fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot glyph->fTop -= gFTLibrary->lcdExtra() >> 1; 1067fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else { 1068fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot glyph->fWidth += gFTLibrary->lcdExtra(); 1069fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot glyph->fLeft -= gFTLibrary->lcdExtra() >> 1; 1070fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1071fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1072fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 1073fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1074fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotbool SkScalerContext_FreeType::shouldSubpixelBitmap(const SkGlyph& glyph, const SkMatrix& matrix) { 1075fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // If subpixel rendering of a bitmap *can* be done. 1076fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bool mechanism = fFace->glyph->format == FT_GLYPH_FORMAT_BITMAP && 1077fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fRec.fFlags & SkScalerContext::kSubpixelPositioning_Flag && 1078fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot (glyph.getSubXFixed() || glyph.getSubYFixed()); 1079fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1080fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // If subpixel rendering of a bitmap *should* be done. 1081fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // 1. If the face is not scalable then always allow subpixel rendering. 1082fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Otherwise, if the font has an 8ppem strike 7 will subpixel render but 8 won't. 1083fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // 2. If the matrix is already not identity the bitmap will already be resampled, 1084fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // so resampling slightly differently shouldn't make much difference. 1085fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bool policy = !FT_IS_SCALABLE(fFace) || !matrix.isIdentity(); 1086fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1087fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return mechanism && policy; 1088fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 1089fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1090fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkScalerContext_FreeType::generateMetrics(SkGlyph* glyph) { 1091fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkAutoMutexAcquire ac(gFTMutex); 1092fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1093fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot glyph->fRsbDelta = 0; 1094fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot glyph->fLsbDelta = 0; 1095fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1096fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FT_Error err; 1097fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1098fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (this->setupSize()) { 1099fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot glyph->zeroMetrics(); 1100fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 1101fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1102fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1103fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot err = FT_Load_Glyph( fFace, glyph->getGlyphID(), 1104fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fLoadGlyphFlags | FT_LOAD_BITMAP_METRICS_ONLY ); 1105fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (err != 0) { 1106fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot glyph->zeroMetrics(); 1107fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 1108fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1109fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot emboldenIfNeeded(fFace, fFace->glyph, glyph->getGlyphID()); 1110fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1111fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot switch ( fFace->glyph->format ) { 1112fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot case FT_GLYPH_FORMAT_OUTLINE: 1113fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (0 == fFace->glyph->outline.n_contours) { 1114fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot glyph->fWidth = 0; 1115fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot glyph->fHeight = 0; 1116fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot glyph->fTop = 0; 1117fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot glyph->fLeft = 0; 1118fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else { 1119fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FT_BBox bbox; 1120fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot getBBoxForCurrentGlyph(glyph, &bbox, true); 1121fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1122fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot glyph->fWidth = SkToU16(SkFDot6Floor(bbox.xMax - bbox.xMin)); 1123fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot glyph->fHeight = SkToU16(SkFDot6Floor(bbox.yMax - bbox.yMin)); 1124fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot glyph->fTop = -SkToS16(SkFDot6Floor(bbox.yMax)); 1125fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot glyph->fLeft = SkToS16(SkFDot6Floor(bbox.xMin)); 1126fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1127fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot updateGlyphIfLCD(glyph); 1128fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1129fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot break; 1130fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1131fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot case FT_GLYPH_FORMAT_BITMAP: 1132fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (fRec.fFlags & SkScalerContext::kVertical_Flag) { 1133fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FT_Vector vector; 1134fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot vector.x = fFace->glyph->metrics.vertBearingX - fFace->glyph->metrics.horiBearingX; 1135fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot vector.y = -fFace->glyph->metrics.vertBearingY - fFace->glyph->metrics.horiBearingY; 1136fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FT_Vector_Transform(&vector, &fMatrix22); 1137fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fFace->glyph->bitmap_left += SkFDot6Floor(vector.x); 1138fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fFace->glyph->bitmap_top += SkFDot6Floor(vector.y); 1139fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1140fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1141fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (fFace->glyph->bitmap.pixel_mode == FT_PIXEL_MODE_BGRA) { 1142fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot glyph->fMaskFormat = SkMask::kARGB32_Format; 1143fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1144fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1145fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot { 1146fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkRect rect = SkRect::MakeXYWH(SkIntToScalar(fFace->glyph->bitmap_left), 1147fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot -SkIntToScalar(fFace->glyph->bitmap_top), 1148fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkIntToScalar(fFace->glyph->bitmap.width), 1149fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkIntToScalar(fFace->glyph->bitmap.rows)); 1150fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fMatrix22Scalar.mapRect(&rect); 1151fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (this->shouldSubpixelBitmap(*glyph, fMatrix22Scalar)) { 1152fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot rect.offset(SkFixedToScalar(glyph->getSubXFixed()), 1153fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkFixedToScalar(glyph->getSubYFixed())); 1154fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1155fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkIRect irect = rect.roundOut(); 1156fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot glyph->fWidth = SkToU16(irect.width()); 1157fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot glyph->fHeight = SkToU16(irect.height()); 1158fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot glyph->fTop = SkToS16(irect.top()); 1159fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot glyph->fLeft = SkToS16(irect.left()); 1160fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1161fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot break; 1162fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1163fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot default: 1164fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDEBUGFAIL("unknown glyph format"); 1165fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot glyph->zeroMetrics(); 1166fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 1167fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1168fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1169fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (fRec.fFlags & SkScalerContext::kVertical_Flag) { 1170fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (fDoLinearMetrics) { 1171fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkScalar advanceScalar = SkFT_FixedToScalar(fFace->glyph->linearVertAdvance); 1172fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot glyph->fAdvanceX = SkScalarToFloat(fMatrix22Scalar.getSkewX() * advanceScalar); 1173fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot glyph->fAdvanceY = SkScalarToFloat(fMatrix22Scalar.getScaleY() * advanceScalar); 1174fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else { 1175fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot glyph->fAdvanceX = -SkFDot6ToFloat(fFace->glyph->advance.x); 1176fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot glyph->fAdvanceY = SkFDot6ToFloat(fFace->glyph->advance.y); 1177fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1178fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else { 1179fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (fDoLinearMetrics) { 1180fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkScalar advanceScalar = SkFT_FixedToScalar(fFace->glyph->linearHoriAdvance); 1181fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot glyph->fAdvanceX = SkScalarToFloat(fMatrix22Scalar.getScaleX() * advanceScalar); 1182fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot glyph->fAdvanceY = SkScalarToFloat(fMatrix22Scalar.getSkewY() * advanceScalar); 1183fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else { 1184fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot glyph->fAdvanceX = SkFDot6ToFloat(fFace->glyph->advance.x); 1185fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot glyph->fAdvanceY = -SkFDot6ToFloat(fFace->glyph->advance.y); 1186fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1187fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (fRec.fFlags & kDevKernText_Flag) { 1188fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot glyph->fRsbDelta = SkToS8(fFace->glyph->rsb_delta); 1189fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot glyph->fLsbDelta = SkToS8(fFace->glyph->lsb_delta); 1190fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1191fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1192fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1193fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1194fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#ifdef ENABLE_GLYPH_SPEW 1195fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDEBUGF(("Metrics(glyph:%d flags:0x%x) w:%d\n", glyph->getGlyphID(), fLoadGlyphFlags, glyph->fWidth)); 1196fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif 1197fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 1198fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1199fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic void clear_glyph_image(const SkGlyph& glyph) { 1200fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot sk_bzero(glyph.fImage, glyph.rowBytes() * glyph.fHeight); 1201fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 1202fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1203fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkScalerContext_FreeType::generateImage(const SkGlyph& glyph) { 1204fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkAutoMutexAcquire ac(gFTMutex); 1205fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1206fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (this->setupSize()) { 1207fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot clear_glyph_image(glyph); 1208fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 1209fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1210fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1211fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FT_Error err = FT_Load_Glyph(fFace, glyph.getGlyphID(), fLoadGlyphFlags); 1212fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (err != 0) { 1213fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SK_TRACEFTR(err, "SkScalerContext_FreeType::generateImage: FT_Load_Glyph(glyph:%d " 1214fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot "width:%d height:%d rb:%d flags:%d) failed.", 1215fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot glyph.getGlyphID(), glyph.fWidth, glyph.fHeight, glyph.rowBytes(), 1216fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fLoadGlyphFlags); 1217fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot clear_glyph_image(glyph); 1218fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 1219fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1220fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1221fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot emboldenIfNeeded(fFace, fFace->glyph, glyph.getGlyphID()); 1222fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkMatrix* bitmapMatrix = &fMatrix22Scalar; 1223fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkMatrix subpixelBitmapMatrix; 1224fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (this->shouldSubpixelBitmap(glyph, *bitmapMatrix)) { 1225fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot subpixelBitmapMatrix = fMatrix22Scalar; 1226fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot subpixelBitmapMatrix.postTranslate(SkFixedToScalar(glyph.getSubXFixed()), 1227fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkFixedToScalar(glyph.getSubYFixed())); 1228fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bitmapMatrix = &subpixelBitmapMatrix; 1229fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1230fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot generateGlyphImage(fFace, glyph, *bitmapMatrix); 1231fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 1232fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1233fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1234fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkScalerContext_FreeType::generatePath(SkGlyphID glyphID, SkPath* path) { 1235fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkAutoMutexAcquire ac(gFTMutex); 1236fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1237fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(path); 1238fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1239fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (this->setupSize()) { 1240fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot path->reset(); 1241fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 1242fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1243fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1244fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot uint32_t flags = fLoadGlyphFlags; 1245fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot flags |= FT_LOAD_NO_BITMAP; // ignore embedded bitmaps so we're sure to get the outline 1246fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot flags &= ~FT_LOAD_RENDER; // don't scan convert (we just want the outline) 1247fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1248fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FT_Error err = FT_Load_Glyph(fFace, glyphID, flags); 1249fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1250fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (err != 0) { 1251fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SK_TRACEFTR(err, "SkScalerContext_FreeType::generatePath: FT_Load_Glyph(glyph:%d " 1252fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot "flags:%d) failed.", glyphID, flags); 1253fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot path->reset(); 1254fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 1255fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1256fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot emboldenIfNeeded(fFace, fFace->glyph, glyphID); 1257fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1258fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot generateGlyphPath(fFace, path); 1259fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1260fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // The path's origin from FreeType is always the horizontal layout origin. 1261fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Offset the path so that it is relative to the vertical origin if needed. 1262fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (fRec.fFlags & SkScalerContext::kVertical_Flag) { 1263fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FT_Vector vector; 1264fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot vector.x = fFace->glyph->metrics.vertBearingX - fFace->glyph->metrics.horiBearingX; 1265fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot vector.y = -fFace->glyph->metrics.vertBearingY - fFace->glyph->metrics.horiBearingY; 1266fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FT_Vector_Transform(&vector, &fMatrix22); 1267fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot path->offset(SkFDot6ToScalar(vector.x), -SkFDot6ToScalar(vector.y)); 1268fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1269fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 1270fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1271fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkScalerContext_FreeType::generateFontMetrics(SkPaint::FontMetrics* metrics) { 1272fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (nullptr == metrics) { 1273fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 1274fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1275fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1276fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkAutoMutexAcquire ac(gFTMutex); 1277fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1278fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (this->setupSize()) { 1279fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot sk_bzero(metrics, sizeof(*metrics)); 1280fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 1281fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1282fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1283fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FT_Face face = fFace; 1284fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot metrics->fFlags = 0; 1285fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1286fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // fetch units/EM from "head" table if needed (ie for bitmap fonts) 1287fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkScalar upem = SkIntToScalar(face->units_per_EM); 1288fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!upem) { 1289fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot TT_Header* ttHeader = (TT_Header*)FT_Get_Sfnt_Table(face, ft_sfnt_head); 1290fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (ttHeader) { 1291fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot upem = SkIntToScalar(ttHeader->Units_Per_EM); 1292fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1293fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1294fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1295fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // use the os/2 table as a source of reasonable defaults. 1296fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkScalar x_height = 0.0f; 1297fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkScalar avgCharWidth = 0.0f; 1298fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkScalar cap_height = 0.0f; 1299fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkScalar strikeoutThickness = 0.0f, strikeoutPosition = 0.0f; 1300fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot TT_OS2* os2 = (TT_OS2*) FT_Get_Sfnt_Table(face, ft_sfnt_os2); 1301fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (os2) { 1302fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot x_height = SkIntToScalar(os2->sxHeight) / upem * fScale.y(); 1303fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot avgCharWidth = SkIntToScalar(os2->xAvgCharWidth) / upem; 1304fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot strikeoutThickness = SkIntToScalar(os2->yStrikeoutSize) / upem; 1305fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot strikeoutPosition = -SkIntToScalar(os2->yStrikeoutPosition) / upem; 1306fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot metrics->fFlags |= SkPaint::FontMetrics::kStrikeoutThicknessIsValid_Flag; 1307fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot metrics->fFlags |= SkPaint::FontMetrics::kStrikeoutPositionIsValid_Flag; 1308fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (os2->version != 0xFFFF && os2->version >= 2) { 1309fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot cap_height = SkIntToScalar(os2->sCapHeight) / upem * fScale.y(); 1310fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1311fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1312fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1313fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // pull from format-specific metrics as needed 1314fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkScalar ascent, descent, leading, xmin, xmax, ymin, ymax; 1315fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkScalar underlineThickness, underlinePosition; 1316fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (face->face_flags & FT_FACE_FLAG_SCALABLE) { // scalable outline font 1317fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // FreeType will always use HHEA metrics if they're not zero. 1318fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // It completely ignores the OS/2 fsSelection::UseTypoMetrics bit. 1319fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // It also ignores the VDMX tables, which are also of interest here 1320fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // (and override everything else when they apply). 1321fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot static const int kUseTypoMetricsMask = (1 << 7); 1322fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (os2 && os2->version != 0xFFFF && (os2->fsSelection & kUseTypoMetricsMask)) { 1323fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot ascent = -SkIntToScalar(os2->sTypoAscender) / upem; 1324fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot descent = -SkIntToScalar(os2->sTypoDescender) / upem; 1325fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot leading = SkIntToScalar(os2->sTypoLineGap) / upem; 1326fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else { 1327fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot ascent = -SkIntToScalar(face->ascender) / upem; 1328fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot descent = -SkIntToScalar(face->descender) / upem; 1329fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot leading = SkIntToScalar(face->height + (face->descender - face->ascender)) / upem; 1330fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1331fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot xmin = SkIntToScalar(face->bbox.xMin) / upem; 1332fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot xmax = SkIntToScalar(face->bbox.xMax) / upem; 1333fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot ymin = -SkIntToScalar(face->bbox.yMin) / upem; 1334fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot ymax = -SkIntToScalar(face->bbox.yMax) / upem; 1335fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot underlineThickness = SkIntToScalar(face->underline_thickness) / upem; 1336fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot underlinePosition = -SkIntToScalar(face->underline_position + 1337fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot face->underline_thickness / 2) / upem; 1338fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1339fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot metrics->fFlags |= SkPaint::FontMetrics::kUnderlineThicknessIsValid_Flag; 1340fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot metrics->fFlags |= SkPaint::FontMetrics::kUnderlinePositionIsValid_Flag; 1341fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1342fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // we may be able to synthesize x_height and cap_height from outline 1343fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!x_height) { 1344fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FT_BBox bbox; 1345fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (getCBoxForLetter('x', &bbox)) { 1346fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot x_height = SkIntToScalar(bbox.yMax) / 64.0f; 1347fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1348fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1349fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!cap_height) { 1350fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FT_BBox bbox; 1351fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (getCBoxForLetter('H', &bbox)) { 1352fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot cap_height = SkIntToScalar(bbox.yMax) / 64.0f; 1353fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1354fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1355fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else if (fStrikeIndex != -1) { // bitmap strike metrics 1356fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkScalar xppem = SkIntToScalar(face->size->metrics.x_ppem); 1357fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkScalar yppem = SkIntToScalar(face->size->metrics.y_ppem); 1358fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot ascent = -SkIntToScalar(face->size->metrics.ascender) / (yppem * 64.0f); 1359fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot descent = -SkIntToScalar(face->size->metrics.descender) / (yppem * 64.0f); 1360fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot leading = (SkIntToScalar(face->size->metrics.height) / (yppem * 64.0f)) + ascent - descent; 1361fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot xmin = 0.0f; 1362fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot xmax = SkIntToScalar(face->available_sizes[fStrikeIndex].width) / xppem; 1363fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot ymin = descent + leading; 1364fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot ymax = ascent - descent; 1365fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot underlineThickness = 0; 1366fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot underlinePosition = 0; 1367fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1368fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot metrics->fFlags &= ~SkPaint::FontMetrics::kUnderlineThicknessIsValid_Flag; 1369fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot metrics->fFlags &= ~SkPaint::FontMetrics::kUnderlinePositionIsValid_Flag; 1370fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else { 1371fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot sk_bzero(metrics, sizeof(*metrics)); 1372fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 1373fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1374fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1375fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // synthesize elements that were not provided by the os/2 table or format-specific metrics 1376fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!x_height) { 1377fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot x_height = -ascent * fScale.y(); 1378fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1379fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!avgCharWidth) { 1380fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot avgCharWidth = xmax - xmin; 1381fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1382fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!cap_height) { 1383fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot cap_height = -ascent * fScale.y(); 1384fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1385fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1386fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // disallow negative linespacing 1387fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (leading < 0.0f) { 1388fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot leading = 0.0f; 1389fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1390fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1391fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot metrics->fTop = ymax * fScale.y(); 1392fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot metrics->fAscent = ascent * fScale.y(); 1393fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot metrics->fDescent = descent * fScale.y(); 1394fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot metrics->fBottom = ymin * fScale.y(); 1395fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot metrics->fLeading = leading * fScale.y(); 1396fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot metrics->fAvgCharWidth = avgCharWidth * fScale.y(); 1397fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot metrics->fXMin = xmin * fScale.y(); 1398fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot metrics->fXMax = xmax * fScale.y(); 1399fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot metrics->fMaxCharWidth = metrics->fXMax - metrics->fXMin; 1400fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot metrics->fXHeight = x_height; 1401fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot metrics->fCapHeight = cap_height; 1402fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot metrics->fUnderlineThickness = underlineThickness * fScale.y(); 1403fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot metrics->fUnderlinePosition = underlinePosition * fScale.y(); 1404fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot metrics->fStrikeoutThickness = strikeoutThickness * fScale.y(); 1405fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot metrics->fStrikeoutPosition = strikeoutPosition * fScale.y(); 1406fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 1407fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1408fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot/////////////////////////////////////////////////////////////////////////////// 1409fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1410fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// hand-tuned value to reduce outline embolden strength 1411fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#ifndef SK_OUTLINE_EMBOLDEN_DIVISOR 1412fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot #ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK 1413fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot #define SK_OUTLINE_EMBOLDEN_DIVISOR 34 1414fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot #else 1415fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot #define SK_OUTLINE_EMBOLDEN_DIVISOR 24 1416fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot #endif 1417fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif 1418fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1419fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot/////////////////////////////////////////////////////////////////////////////// 1420fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1421fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkScalerContext_FreeType::emboldenIfNeeded(FT_Face face, FT_GlyphSlot glyph, SkGlyphID gid) { 1422fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // check to see if the embolden bit is set 1423fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (0 == (fRec.fFlags & SkScalerContext::kEmbolden_Flag)) { 1424fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 1425fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1426fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1427fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot switch (glyph->format) { 1428fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot case FT_GLYPH_FORMAT_OUTLINE: 1429fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FT_Pos strength; 1430fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot strength = FT_MulFix(face->units_per_EM, face->size->metrics.y_scale) 1431fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot / SK_OUTLINE_EMBOLDEN_DIVISOR; 1432fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FT_Outline_Embolden(&glyph->outline, strength); 1433fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot break; 1434fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot case FT_GLYPH_FORMAT_BITMAP: 1435fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!fFace->glyph->bitmap.buffer) { 1436fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FT_Load_Glyph(fFace, gid, fLoadGlyphFlags); 1437fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1438fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FT_GlyphSlot_Own_Bitmap(glyph); 1439fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FT_Bitmap_Embolden(glyph->library, &glyph->bitmap, kBitmapEmboldenStrength, 0); 1440fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot break; 1441fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot default: 1442fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDEBUGFAIL("unknown glyph format"); 1443fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1444fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 1445fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1446fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot/////////////////////////////////////////////////////////////////////////////// 1447fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1448fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkUtils.h" 1449fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1450fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic SkUnichar next_utf8(const void** chars) { 1451fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return SkUTF8_NextUnichar((const char**)chars); 1452fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 1453fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1454fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic SkUnichar next_utf16(const void** chars) { 1455fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return SkUTF16_NextUnichar((const uint16_t**)chars); 1456fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 1457fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1458fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic SkUnichar next_utf32(const void** chars) { 1459fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkUnichar** uniChars = (const SkUnichar**)chars; 1460fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkUnichar uni = **uniChars; 1461fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot *uniChars += 1; 1462fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return uni; 1463fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 1464fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1465fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robottypedef SkUnichar (*EncodingProc)(const void**); 1466fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1467fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic EncodingProc find_encoding_proc(SkTypeface::Encoding enc) { 1468fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot static const EncodingProc gProcs[] = { 1469fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot next_utf8, next_utf16, next_utf32 1470fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot }; 1471fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT((size_t)enc < SK_ARRAY_COUNT(gProcs)); 1472fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return gProcs[enc]; 1473fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 1474fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1475fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotint SkTypeface_FreeType::onCharsToGlyphs(const void* chars, Encoding encoding, 1476fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot uint16_t glyphs[], int glyphCount) const 1477fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot{ 1478fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot AutoFTAccess fta(this); 1479fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FT_Face face = fta.face(); 1480fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!face) { 1481fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (glyphs) { 1482fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot sk_bzero(glyphs, glyphCount * sizeof(glyphs[0])); 1483fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1484fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return 0; 1485fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1486fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1487fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot EncodingProc next_uni_proc = find_encoding_proc(encoding); 1488fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1489fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (nullptr == glyphs) { 1490fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot for (int i = 0; i < glyphCount; ++i) { 1491fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (0 == FT_Get_Char_Index(face, next_uni_proc(&chars))) { 1492fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return i; 1493fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1494fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1495fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return glyphCount; 1496fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else { 1497fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot int first = glyphCount; 1498fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot for (int i = 0; i < glyphCount; ++i) { 1499fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot unsigned id = FT_Get_Char_Index(face, next_uni_proc(&chars)); 1500fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot glyphs[i] = SkToU16(id); 1501fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (0 == id && i < first) { 1502fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot first = i; 1503fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1504fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1505fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return first; 1506fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1507fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 1508fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1509fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotint SkTypeface_FreeType::onCountGlyphs() const { 1510fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot AutoFTAccess fta(this); 1511fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FT_Face face = fta.face(); 1512fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return face ? face->num_glyphs : 0; 1513fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 1514fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1515fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotSkTypeface::LocalizedStrings* SkTypeface_FreeType::onCreateFamilyNameIterator() const { 1516fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkTypeface::LocalizedStrings* nameIter = 1517fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkOTUtils::LocalizedStrings_NameTable::CreateForFamilyNames(*this); 1518fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (nullptr == nameIter) { 1519fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkString familyName; 1520fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot this->getFamilyName(&familyName); 1521fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkString language("und"); //undetermined 1522fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot nameIter = new SkOTUtils::LocalizedStrings_SingleName(familyName, language); 1523fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1524fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return nameIter; 1525fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 1526fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1527fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotint SkTypeface_FreeType::onGetVariationDesignPosition( 1528fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkFontArguments::VariationPosition::Coordinate coordinates[], int coordinateCount) const 1529fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot{ 1530fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot AutoFTAccess fta(this); 1531fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FT_Face face = fta.face(); 1532fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1533fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!face || !(face->face_flags & FT_FACE_FLAG_MULTIPLE_MASTERS)) { 1534fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return 0; 1535fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1536fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1537fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FT_MM_Var* variations = nullptr; 1538fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (FT_Get_MM_Var(face, &variations)) { 1539fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return 0; 1540fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1541fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkAutoFree autoFreeVariations(variations); 1542fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1543fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!coordinates || coordinateCount < SkToInt(variations->num_axis)) { 1544fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return variations->num_axis; 1545fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1546fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1547fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkAutoSTMalloc<4, FT_Fixed> coords(variations->num_axis); 1548fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // FT_Get_{MM,Var}_{Blend,Design}_Coordinates were added in FreeType 2.7.1. 1549fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (gFTLibrary->fGetVarDesignCoordinates && 1550fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot !gFTLibrary->fGetVarDesignCoordinates(face, variations->num_axis, coords.get())) 1551fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot { 1552fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot for (FT_UInt i = 0; i < variations->num_axis; ++i) { 1553fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot coordinates[i].axis = variations->axis[i].tag; 1554fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot coordinates[i].value = SkFixedToScalar(coords[i]); 1555fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1556fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else if (static_cast<FT_UInt>(fta.getAxesCount()) == variations->num_axis) { 1557fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot for (FT_UInt i = 0; i < variations->num_axis; ++i) { 1558fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot coordinates[i].axis = variations->axis[i].tag; 1559fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot coordinates[i].value = SkFixedToScalar(fta.getAxes()[i]); 1560fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1561fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else if (fta.isNamedVariationSpecified()) { 1562fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // The font has axes, they cannot be retrieved, and some named axis was specified. 1563fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return -1; 1564fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else { 1565fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // The font has axes, they cannot be retrieved, but no named instance was specified. 1566fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return 0; 1567fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1568fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1569fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return variations->num_axis; 1570fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 1571fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1572fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotint SkTypeface_FreeType::onGetTableTags(SkFontTableTag tags[]) const { 1573fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot AutoFTAccess fta(this); 1574fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FT_Face face = fta.face(); 1575fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1576fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FT_ULong tableCount = 0; 1577fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FT_Error error; 1578fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1579fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // When 'tag' is nullptr, returns number of tables in 'length'. 1580fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot error = FT_Sfnt_Table_Info(face, 0, nullptr, &tableCount); 1581fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (error) { 1582fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return 0; 1583fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1584fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1585fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (tags) { 1586fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot for (FT_ULong tableIndex = 0; tableIndex < tableCount; ++tableIndex) { 1587fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FT_ULong tableTag; 1588fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FT_ULong tablelength; 1589fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot error = FT_Sfnt_Table_Info(face, tableIndex, &tableTag, &tablelength); 1590fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (error) { 1591fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return 0; 1592fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1593fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot tags[tableIndex] = static_cast<SkFontTableTag>(tableTag); 1594fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1595fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1596fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return tableCount; 1597fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 1598fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1599fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotsize_t SkTypeface_FreeType::onGetTableData(SkFontTableTag tag, size_t offset, 1600fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot size_t length, void* data) const 1601fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot{ 1602fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot AutoFTAccess fta(this); 1603fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FT_Face face = fta.face(); 1604fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1605fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FT_ULong tableLength = 0; 1606fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FT_Error error; 1607fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1608fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // When 'length' is 0 it is overwritten with the full table length; 'offset' is ignored. 1609fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot error = FT_Load_Sfnt_Table(face, tag, 0, nullptr, &tableLength); 1610fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (error) { 1611fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return 0; 1612fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1613fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1614fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (offset > tableLength) { 1615fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return 0; 1616fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1617fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FT_ULong size = SkTMin((FT_ULong)length, tableLength - (FT_ULong)offset); 1618fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (data) { 1619fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot error = FT_Load_Sfnt_Table(face, tag, offset, reinterpret_cast<FT_Byte*>(data), &size); 1620fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (error) { 1621fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return 0; 1622fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1623fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1624fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1625fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return size; 1626fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 1627fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1628fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot/////////////////////////////////////////////////////////////////////////////// 1629fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot/////////////////////////////////////////////////////////////////////////////// 1630fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1631fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotSkTypeface_FreeType::Scanner::Scanner() : fLibrary(nullptr) { 1632fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (FT_New_Library(&gFTMemory, &fLibrary)) { 1633fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 1634fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1635fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FT_Add_Default_Modules(fLibrary); 1636fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 1637fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotSkTypeface_FreeType::Scanner::~Scanner() { 1638fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (fLibrary) { 1639fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FT_Done_Library(fLibrary); 1640fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1641fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 1642fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1643fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotFT_Face SkTypeface_FreeType::Scanner::openFace(SkStreamAsset* stream, int ttcIndex, 1644fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FT_Stream ftStream) const 1645fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot{ 1646fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (fLibrary == nullptr) { 1647fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return nullptr; 1648fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1649fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1650fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FT_Open_Args args; 1651fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot memset(&args, 0, sizeof(args)); 1652fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1653fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const void* memoryBase = stream->getMemoryBase(); 1654fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1655fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (memoryBase) { 1656fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot args.flags = FT_OPEN_MEMORY; 1657fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot args.memory_base = (const FT_Byte*)memoryBase; 1658fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot args.memory_size = stream->getLength(); 1659fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else { 1660fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot memset(ftStream, 0, sizeof(*ftStream)); 1661fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot ftStream->size = stream->getLength(); 1662fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot ftStream->descriptor.pointer = stream; 1663fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot ftStream->read = sk_ft_stream_io; 1664fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot ftStream->close = sk_ft_stream_close; 1665fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1666fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot args.flags = FT_OPEN_STREAM; 1667fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot args.stream = ftStream; 1668fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1669fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1670fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FT_Face face; 1671fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (FT_Open_Face(fLibrary, &args, ttcIndex, &face)) { 1672fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return nullptr; 1673fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1674fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return face; 1675fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 1676fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1677fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotbool SkTypeface_FreeType::Scanner::recognizedFont(SkStreamAsset* stream, int* numFaces) const { 1678fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkAutoMutexAcquire libraryLock(fLibraryMutex); 1679fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1680fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FT_StreamRec streamRec; 1681fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FT_Face face = this->openFace(stream, -1, &streamRec); 1682fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (nullptr == face) { 1683fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return false; 1684fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1685fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1686fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot *numFaces = face->num_faces; 1687fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1688fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FT_Done_Face(face); 1689fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return true; 1690fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 1691fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1692fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkTSearch.h" 1693fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotbool SkTypeface_FreeType::Scanner::scanFont( 1694fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkStreamAsset* stream, int ttcIndex, 1695fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkString* name, SkFontStyle* style, bool* isFixedPitch, AxisDefinitions* axes) const 1696fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot{ 1697fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkAutoMutexAcquire libraryLock(fLibraryMutex); 1698fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1699fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FT_StreamRec streamRec; 1700fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FT_Face face = this->openFace(stream, ttcIndex, &streamRec); 1701fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (nullptr == face) { 1702fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return false; 1703fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1704fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1705fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot int weight = SkFontStyle::kNormal_Weight; 1706fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot int width = SkFontStyle::kNormal_Width; 1707fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkFontStyle::Slant slant = SkFontStyle::kUpright_Slant; 1708fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (face->style_flags & FT_STYLE_FLAG_BOLD) { 1709fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot weight = SkFontStyle::kBold_Weight; 1710fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1711fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (face->style_flags & FT_STYLE_FLAG_ITALIC) { 1712fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot slant = SkFontStyle::kItalic_Slant; 1713fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1714fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1715fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot PS_FontInfoRec psFontInfo; 1716fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot TT_OS2* os2 = static_cast<TT_OS2*>(FT_Get_Sfnt_Table(face, ft_sfnt_os2)); 1717fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (os2 && os2->version != 0xffff) { 1718fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot weight = os2->usWeightClass; 1719fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot width = os2->usWidthClass; 1720fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1721fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // OS/2::fsSelection bit 9 indicates oblique. 1722fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (SkToBool(os2->fsSelection & (1u << 9))) { 1723fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot slant = SkFontStyle::kOblique_Slant; 1724fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1725fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else if (0 == FT_Get_PS_Font_Info(face, &psFontInfo) && psFontInfo.weight) { 1726fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot static const struct { 1727fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot char const * const name; 1728fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot int const weight; 1729fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } commonWeights [] = { 1730fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // There are probably more common names, but these are known to exist. 1731fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot { "all", SkFontStyle::kNormal_Weight }, // Multiple Masters usually default to normal. 1732fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot { "black", SkFontStyle::kBlack_Weight }, 1733fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot { "bold", SkFontStyle::kBold_Weight }, 1734fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot { "book", (SkFontStyle::kNormal_Weight + SkFontStyle::kLight_Weight)/2 }, 1735fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot { "demi", SkFontStyle::kSemiBold_Weight }, 1736fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot { "demibold", SkFontStyle::kSemiBold_Weight }, 1737fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot { "extra", SkFontStyle::kExtraBold_Weight }, 1738fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot { "extrabold", SkFontStyle::kExtraBold_Weight }, 1739fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot { "extralight", SkFontStyle::kExtraLight_Weight }, 1740fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot { "hairline", SkFontStyle::kThin_Weight }, 1741fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot { "heavy", SkFontStyle::kBlack_Weight }, 1742fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot { "light", SkFontStyle::kLight_Weight }, 1743fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot { "medium", SkFontStyle::kMedium_Weight }, 1744fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot { "normal", SkFontStyle::kNormal_Weight }, 1745fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot { "plain", SkFontStyle::kNormal_Weight }, 1746fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot { "regular", SkFontStyle::kNormal_Weight }, 1747fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot { "roman", SkFontStyle::kNormal_Weight }, 1748fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot { "semibold", SkFontStyle::kSemiBold_Weight }, 1749fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot { "standard", SkFontStyle::kNormal_Weight }, 1750fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot { "thin", SkFontStyle::kThin_Weight }, 1751fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot { "ultra", SkFontStyle::kExtraBold_Weight }, 1752fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot { "ultrablack", SkFontStyle::kExtraBlack_Weight }, 1753fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot { "ultrabold", SkFontStyle::kExtraBold_Weight }, 1754fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot { "ultraheavy", SkFontStyle::kExtraBlack_Weight }, 1755fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot { "ultralight", SkFontStyle::kExtraLight_Weight }, 1756fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot }; 1757fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot int const index = SkStrLCSearch(&commonWeights[0].name, SK_ARRAY_COUNT(commonWeights), 1758fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot psFontInfo.weight, sizeof(commonWeights[0])); 1759fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (index >= 0) { 1760fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot weight = commonWeights[index].weight; 1761fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else { 1762fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDEBUGF(("Do not know weight for: %s (%s) \n", face->family_name, psFontInfo.weight)); 1763fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1764fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1765fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1766fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (name) { 1767fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot name->set(face->family_name); 1768fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1769fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (style) { 1770fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot *style = SkFontStyle(weight, width, slant); 1771fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1772fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (isFixedPitch) { 1773fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot *isFixedPitch = FT_IS_FIXED_WIDTH(face); 1774fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1775fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1776fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (axes && face->face_flags & FT_FACE_FLAG_MULTIPLE_MASTERS) { 1777fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FT_MM_Var* variations = nullptr; 1778fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FT_Error err = FT_Get_MM_Var(face, &variations); 1779fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (err) { 1780fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDEBUGF(("INFO: font %s claims to have variations, but none found.\n", 1781fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot face->family_name)); 1782fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return false; 1783fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1784fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkAutoFree autoFreeVariations(variations); 1785fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1786fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot axes->reset(variations->num_axis); 1787fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot for (FT_UInt i = 0; i < variations->num_axis; ++i) { 1788fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const FT_Var_Axis& ftAxis = variations->axis[i]; 1789fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot (*axes)[i].fTag = ftAxis.tag; 1790fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot (*axes)[i].fMinimum = ftAxis.minimum; 1791fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot (*axes)[i].fDefault = ftAxis.def; 1792fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot (*axes)[i].fMaximum = ftAxis.maximum; 1793fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1794fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1795fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1796fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot FT_Done_Face(face); 1797fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return true; 1798fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 1799fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1800fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot/*static*/ void SkTypeface_FreeType::Scanner::computeAxisValues( 1801fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot AxisDefinitions axisDefinitions, 1802fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkFontArguments::VariationPosition position, 1803fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkFixed* axisValues, 1804fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkString& name) 1805fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot{ 1806fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot for (int i = 0; i < axisDefinitions.count(); ++i) { 1807fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const Scanner::AxisDefinition& axisDefinition = axisDefinitions[i]; 1808fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkScalar axisMin = SkFixedToScalar(axisDefinition.fMinimum); 1809fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkScalar axisMax = SkFixedToScalar(axisDefinition.fMaximum); 1810fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot axisValues[i] = axisDefinition.fDefault; 1811fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // The position may be over specified. If there are multiple values for a given axis, 1812fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // use the last one since that's what css-fonts-4 requires. 1813fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot for (int j = position.coordinateCount; j --> 0;) { 1814fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const auto& coordinate = position.coordinates[j]; 1815fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (axisDefinition.fTag == coordinate.axis) { 1816fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkScalar axisValue = SkTPin(coordinate.value, axisMin, axisMax); 1817fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (coordinate.value != axisValue) { 1818fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDEBUGF(("Requested font axis value out of range: " 1819fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot "%s '%c%c%c%c' %f; pinned to %f.\n", 1820fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot name.c_str(), 1821fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot (axisDefinition.fTag >> 24) & 0xFF, 1822fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot (axisDefinition.fTag >> 16) & 0xFF, 1823fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot (axisDefinition.fTag >> 8) & 0xFF, 1824fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot (axisDefinition.fTag ) & 0xFF, 1825fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkScalarToDouble(coordinate.value), 1826fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkScalarToDouble(axisValue))); 1827fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1828fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot axisValues[i] = SkScalarToFixed(axisValue); 1829fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot break; 1830fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1831fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1832fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // TODO: warn on defaulted axis? 1833fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1834fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1835fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDEBUGCODE( 1836fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Check for axis specified, but not matched in font. 1837fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot for (int i = 0; i < position.coordinateCount; ++i) { 1838fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkFourByteTag skTag = position.coordinates[i].axis; 1839fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bool found = false; 1840fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot for (int j = 0; j < axisDefinitions.count(); ++j) { 1841fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (skTag == axisDefinitions[j].fTag) { 1842fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot found = true; 1843fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot break; 1844fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1845fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1846fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!found) { 1847fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDEBUGF(("Requested font axis not found: %s '%c%c%c%c'\n", 1848fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot name.c_str(), 1849fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot (skTag >> 24) & 0xFF, 1850fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot (skTag >> 16) & 0xFF, 1851fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot (skTag >> 8) & 0xFF, 1852fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot (skTag) & 0xFF)); 1853fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1854fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1855fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot ) 1856fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 1857