gfxOTSUtils.h (6693B)
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 #ifndef GFX_OTS_UTILS_H 7 #define GFX_OTS_UTILS_H 8 9 #include "gfxFontUtils.h" 10 11 #include "opentype-sanitiser.h" 12 13 struct gfxOTSMozAlloc { 14 void* Grow(void* aPtr, size_t aLength) { return moz_xrealloc(aPtr, aLength); } 15 void* ShrinkToFit(void* aPtr, size_t aLength) { 16 return moz_xrealloc(aPtr, aLength); 17 } 18 void Free(void* aPtr) { free(aPtr); } 19 }; 20 21 // Based on ots::ExpandingMemoryStream from ots-memory-stream.h, 22 // adapted to use Mozilla allocators and to allow the final 23 // memory buffer to be adopted by the client. 24 template <typename AllocT = gfxOTSMozAlloc> 25 class gfxOTSExpandingMemoryStream : public ots::OTSStream { 26 public: 27 // limit output/expansion to 256MB by default 28 enum { DEFAULT_LIMIT = 256 * 1024 * 1024 }; 29 30 explicit gfxOTSExpandingMemoryStream(size_t initial, 31 size_t limit = DEFAULT_LIMIT) 32 : mLength(initial), mLimit(limit), mOff(0) { 33 mPtr = mAlloc.Grow(nullptr, mLength); 34 } 35 36 ~gfxOTSExpandingMemoryStream() { mAlloc.Free(mPtr); } 37 38 size_t size() override { return mLimit; } 39 40 // Return the buffer, resized to fit its contents (as it may have been 41 // over-allocated during growth), and give up ownership of it so the 42 // caller becomes responsible to call free() when finished with it. 43 auto forget() { 44 auto p = mAlloc.ShrinkToFit(mPtr, mOff); 45 mPtr = nullptr; 46 return p; 47 } 48 49 bool WriteRaw(const void* data, size_t length) override { 50 if ((mOff + length > mLength) || 51 (mLength > std::numeric_limits<size_t>::max() - mOff)) { 52 if (mLength == mLimit) { 53 return false; 54 } 55 size_t newLength = (mLength + 1) * 2; 56 if (newLength < mLength) { 57 return false; 58 } 59 if (newLength > mLimit) { 60 newLength = mLimit; 61 } 62 mPtr = mAlloc.Grow(mPtr, newLength); 63 mLength = newLength; 64 return WriteRaw(data, length); 65 } 66 std::memcpy(static_cast<char*>(mPtr) + mOff, data, length); 67 mOff += length; 68 return true; 69 } 70 71 bool Seek(off_t position) override { 72 if (position < 0) { 73 return false; 74 } 75 if (static_cast<size_t>(position) > mLength) { 76 return false; 77 } 78 mOff = position; 79 return true; 80 } 81 82 off_t Tell() const override { return mOff; } 83 84 private: 85 AllocT mAlloc; 86 void* mPtr; 87 size_t mLength; 88 const size_t mLimit; 89 off_t mOff; 90 }; 91 92 class MOZ_STACK_CLASS gfxOTSContext : public ots::OTSContext { 93 public: 94 gfxOTSContext() { 95 using namespace mozilla; 96 97 // Whether to apply OTS validation to OpenType Layout tables 98 mCheckOTLTables = StaticPrefs::gfx_downloadable_fonts_otl_validation(); 99 // Whether to preserve Variation tables in downloaded fonts 100 mCheckVariationTables = 101 StaticPrefs::gfx_downloadable_fonts_validate_variation_tables(); 102 // Whether to preserve color bitmap glyphs 103 mKeepColorBitmaps = 104 StaticPrefs::gfx_downloadable_fonts_keep_color_bitmaps(); 105 // Whether to preserve SVG glyphs (which can be expensive in Core Text, 106 // so better to drop them if we're not going to render them anyhow). 107 mKeepSVG = StaticPrefs::gfx_font_rendering_opentype_svg_enabled(); 108 } 109 110 virtual ots::TableAction GetTableAction(uint32_t aTag) override { 111 // Pass through or validate OTL and Variation tables, depending on prefs. 112 if (aTag == TRUETYPE_TAG('G', 'D', 'E', 'F') || 113 aTag == TRUETYPE_TAG('G', 'P', 'O', 'S') || 114 aTag == TRUETYPE_TAG('G', 'S', 'U', 'B')) { 115 switch (mCheckOTLTables) { 116 case 0: // no validation 117 return ots::TABLE_ACTION_PASSTHRU; 118 case 1: // validate, logging errors, but do not reject font 119 return ots::TABLE_ACTION_SANITIZE_SOFT; 120 case 2: // validate, and reject font if errors are found 121 default: 122 return ots::TABLE_ACTION_SANITIZE; 123 } 124 } 125 auto isVariationTable = [](uint32_t aTag) -> bool { 126 return aTag == TRUETYPE_TAG('a', 'v', 'a', 'r') || 127 aTag == TRUETYPE_TAG('c', 'v', 'a', 'r') || 128 aTag == TRUETYPE_TAG('f', 'v', 'a', 'r') || 129 aTag == TRUETYPE_TAG('g', 'v', 'a', 'r') || 130 aTag == TRUETYPE_TAG('H', 'V', 'A', 'R') || 131 aTag == TRUETYPE_TAG('M', 'V', 'A', 'R') || 132 aTag == TRUETYPE_TAG('S', 'T', 'A', 'T') || 133 aTag == TRUETYPE_TAG('V', 'V', 'A', 'R'); 134 }; 135 if (!mCheckVariationTables && isVariationTable(aTag)) { 136 return ots::TABLE_ACTION_PASSTHRU; 137 } 138 if (!gfxPlatform::HasVariationFontSupport() && isVariationTable(aTag)) { 139 return ots::TABLE_ACTION_DROP; 140 } 141 // Preserve SVG table if OpenType-SVG rendering is enabled. 142 if (aTag == TRUETYPE_TAG('S', 'V', 'G', ' ')) { 143 return mKeepSVG ? ots::TABLE_ACTION_PASSTHRU : ots::TABLE_ACTION_DROP; 144 } 145 // Preserve BASE table; harfbuzz will sanitize it before using. 146 if (aTag == TRUETYPE_TAG('B', 'A', 'S', 'E')) { 147 return ots::TABLE_ACTION_PASSTHRU; 148 } 149 if (mKeepColorBitmaps && (aTag == TRUETYPE_TAG('C', 'B', 'D', 'T') || 150 aTag == TRUETYPE_TAG('C', 'B', 'L', 'C'))) { 151 return ots::TABLE_ACTION_PASSTHRU; 152 } 153 return ots::TABLE_ACTION_DEFAULT; 154 } 155 156 static size_t GuessSanitizedFontSize(size_t aLength, 157 gfxUserFontType aFontType, 158 bool aStrict = true) { 159 switch (aFontType) { 160 case GFX_USERFONT_UNKNOWN: 161 // If being permissive of unknown types, make a reasonable guess 162 // at how much room the sanitized font may take, if it passes. Just 163 // enough extra space to accomodate some growth without excessive 164 // bloat in case of large fonts. 1.5x is a reasonable compromise 165 // for growable vectors in general. 166 return aStrict || !aLength ? 0 : (aLength * 3) / 2; 167 case GFX_USERFONT_WOFF: 168 return aLength * 2; 169 case GFX_USERFONT_WOFF2: 170 return aLength * 3; 171 default: 172 return aLength; 173 } 174 } 175 176 static size_t GuessSanitizedFontSize(const uint8_t* aData, size_t aLength, 177 bool aStrict = true) { 178 gfxUserFontType fontType = 179 gfxFontUtils::DetermineFontDataType(aData, aLength); 180 return GuessSanitizedFontSize(aLength, fontType, aStrict); 181 } 182 183 private: 184 uint8_t mCheckOTLTables; 185 bool mCheckVariationTables; 186 bool mKeepColorBitmaps; 187 bool mKeepSVG; 188 }; 189 190 #endif /* GFX_OTS_UTILS_H */