gfxFT2Utils.cpp (5304B)
1 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- 2 * This Source Code Form is subject to the terms of the Mozilla Public 3 * License, v. 2.0. If a copy of the MPL was not distributed with this 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 5 6 #include "gfxFT2FontBase.h" 7 #include "gfxFT2Utils.h" 8 #include "mozilla/Likely.h" 9 10 #ifdef USE_FC_FREETYPE 11 # include <fontconfig/fcfreetype.h> 12 #endif 13 14 #include "ft2build.h" 15 #include FT_MULTIPLE_MASTERS_H 16 17 #include "prlink.h" 18 19 uint32_t gfxFT2LockedFace::GetGlyph(uint32_t aCharCode) { 20 if (MOZ_UNLIKELY(!mFace)) return 0; 21 22 #ifdef USE_FC_FREETYPE 23 // FcFreeTypeCharIndex will search starting from the most recently 24 // selected charmap. This can cause non-determistic behavior when more 25 // than one charmap supports a character but with different glyphs, as 26 // with older versions of MS Gothic, for example. Always prefer a Unicode 27 // charmap, if there is one; failing that, try MS_SYMBOL. 28 // (FcFreeTypeCharIndex usually does the appropriate Unicode conversion, 29 // but some fonts have non-Roman glyphs for FT_ENCODING_APPLE_ROMAN 30 // characters.) 31 if (!mFace->charmap || (mFace->charmap->encoding != FT_ENCODING_UNICODE && 32 mFace->charmap->encoding != FT_ENCODING_MS_SYMBOL)) { 33 if (FT_Err_Ok != FT_Select_Charmap(mFace, FT_ENCODING_UNICODE) && 34 FT_Err_Ok != FT_Select_Charmap(mFace, FT_ENCODING_MS_SYMBOL)) { 35 NS_WARNING("failed to select Unicode or symbol charmap"); 36 } 37 } 38 39 uint32_t gid = FcFreeTypeCharIndex(mFace, aCharCode); 40 #else 41 uint32_t gid = FT_Get_Char_Index(mFace, aCharCode); 42 #endif 43 if (!gid && mFace->charmap && 44 mFace->charmap->encoding == FT_ENCODING_MS_SYMBOL) { 45 if (auto pua = gfxFontUtils::MapLegacySymbolFontCharToPUA(aCharCode)) { 46 gid = FT_Get_Char_Index(mFace, pua); 47 } 48 } 49 return gid; 50 } 51 52 typedef FT_UInt (*GetCharVariantFunction)(FT_Face face, FT_ULong charcode, 53 FT_ULong variantSelector); 54 55 uint32_t gfxFT2LockedFace::GetUVSGlyph(uint32_t aCharCode, 56 uint32_t aVariantSelector) { 57 MOZ_ASSERT(aVariantSelector, "aVariantSelector should not be NULL"); 58 59 if (MOZ_UNLIKELY(!mFace)) return 0; 60 61 // This function is available from FreeType 2.3.6 (June 2008). 62 static CharVariantFunction sGetCharVariantPtr = FindCharVariantFunction(); 63 if (!sGetCharVariantPtr) return 0; 64 65 #ifdef USE_FC_FREETYPE 66 // FcFreeTypeCharIndex may have changed the selected charmap. 67 // FT_Face_GetCharVariantIndex needs a unicode charmap. 68 if (!mFace->charmap || mFace->charmap->encoding != FT_ENCODING_UNICODE) { 69 FT_Select_Charmap(mFace, FT_ENCODING_UNICODE); 70 } 71 #endif 72 73 return (*sGetCharVariantPtr)(mFace, aCharCode, aVariantSelector); 74 } 75 76 gfxFT2LockedFace::CharVariantFunction 77 gfxFT2LockedFace::FindCharVariantFunction() { 78 // This function is available from FreeType 2.3.6 (June 2008). 79 PRLibrary* lib = nullptr; 80 CharVariantFunction function = reinterpret_cast<CharVariantFunction>( 81 PR_FindFunctionSymbolAndLibrary("FT_Face_GetCharVariantIndex", &lib)); 82 if (!lib) { 83 return nullptr; 84 } 85 86 FT_Int major; 87 FT_Int minor; 88 FT_Int patch; 89 FT_Library_Version(mFace->glyph->library, &major, &minor, &patch); 90 91 // Versions 2.4.0 to 2.4.3 crash if configured with 92 // FT_CONFIG_OPTION_OLD_INTERNALS. Presence of the symbol FT_Alloc 93 // indicates FT_CONFIG_OPTION_OLD_INTERNALS. 94 if (major == 2 && minor == 4 && patch < 4 && 95 PR_FindFunctionSymbol(lib, "FT_Alloc")) { 96 function = nullptr; 97 } 98 99 // Decrement the reference count incremented in 100 // PR_FindFunctionSymbolAndLibrary. 101 PR_UnloadLibrary(lib); 102 103 return function; 104 } 105 106 /*static*/ 107 void gfxFT2Utils::GetVariationAxes(const FT_MM_Var* aMMVar, 108 nsTArray<gfxFontVariationAxis>& aAxes) { 109 MOZ_ASSERT(aAxes.IsEmpty()); 110 if (!aMMVar) { 111 return; 112 } 113 aAxes.SetCapacity(aMMVar->num_axis); 114 for (unsigned i = 0; i < aMMVar->num_axis; i++) { 115 const auto& a = aMMVar->axis[i]; 116 gfxFontVariationAxis axis; 117 axis.mMinValue = a.minimum / 65536.0; 118 axis.mMaxValue = a.maximum / 65536.0; 119 axis.mDefaultValue = a.def / 65536.0; 120 axis.mTag = a.tag; 121 axis.mName = a.name; 122 aAxes.AppendElement(axis); 123 } 124 } 125 126 /*static*/ 127 void gfxFT2Utils::GetVariationInstances( 128 gfxFontEntry* aFontEntry, const FT_MM_Var* aMMVar, 129 nsTArray<gfxFontVariationInstance>& aInstances) { 130 MOZ_ASSERT(aInstances.IsEmpty()); 131 if (!aMMVar) { 132 return; 133 } 134 gfxFontUtils::AutoHBBlob nameTable( 135 aFontEntry->GetFontTable(TRUETYPE_TAG('n', 'a', 'm', 'e'))); 136 if (!nameTable) { 137 return; 138 } 139 aInstances.SetCapacity(aMMVar->num_namedstyles); 140 for (unsigned i = 0; i < aMMVar->num_namedstyles; i++) { 141 const auto& ns = aMMVar->namedstyle[i]; 142 gfxFontVariationInstance inst; 143 nsresult rv = 144 gfxFontUtils::ReadCanonicalName(nameTable, ns.strid, inst.mName); 145 if (NS_FAILED(rv)) { 146 continue; 147 } 148 inst.mValues.SetCapacity(aMMVar->num_axis); 149 for (unsigned j = 0; j < aMMVar->num_axis; j++) { 150 gfxFontVariationValue value; 151 value.mAxis = aMMVar->axis[j].tag; 152 value.mValue = ns.coords[j] / 65536.0; 153 inst.mValues.AppendElement(value); 154 } 155 aInstances.AppendElement(inst); 156 } 157 }