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/. */
6 #ifndef GFX_OTS_UTILS_H
7 #define GFX_OTS_UTILS_H
9 #include "gfxFontUtils.h"
11 #include "opentype-sanitiser.h"
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
);
18 void Free(void* aPtr
) { free(aPtr
); }
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
{
27 // limit output/expansion to 256MB by default
28 enum { DEFAULT_LIMIT
= 256 * 1024 * 1024 };
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
);
36 ~gfxOTSExpandingMemoryStream() { mAlloc
.Free(mPtr
); }
38 size_t size() override
{ return mLimit
; }
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.
44 auto p
= mAlloc
.ShrinkToFit(mPtr
, mOff
);
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
) {
55 size_t newLength
= (mLength
+ 1) * 2;
56 if (newLength
< mLength
) {
59 if (newLength
> mLimit
) {
62 mPtr
= mAlloc
.Grow(mPtr
, newLength
);
64 return WriteRaw(data
, length
);
66 std::memcpy(static_cast<char*>(mPtr
) + mOff
, data
, length
);
71 bool Seek(off_t position
) override
{
75 if (static_cast<size_t>(position
) > mLength
) {
82 off_t
Tell() const override
{ return mOff
; }
92 class MOZ_STACK_CLASS gfxOTSContext
: public ots::OTSContext
{
95 using namespace mozilla
;
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
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();
110 virtual ots::TableAction
GetTableAction(uint32_t aTag
) override
{
111 // Pass through or validate OTL and Variation tables, depending on prefs.
112 if ((!mCheckOTLTables
&& (aTag
== TRUETYPE_TAG('G', 'D', 'E', 'F') ||
113 aTag
== TRUETYPE_TAG('G', 'P', 'O', 'S') ||
114 aTag
== TRUETYPE_TAG('G', 'S', 'U', 'B')))) {
115 return ots::TABLE_ACTION_PASSTHRU
;
117 auto isVariationTable
= [](uint32_t aTag
) -> bool {
118 return aTag
== TRUETYPE_TAG('a', 'v', 'a', 'r') ||
119 aTag
== TRUETYPE_TAG('c', 'v', 'a', 'r') ||
120 aTag
== TRUETYPE_TAG('f', 'v', 'a', 'r') ||
121 aTag
== TRUETYPE_TAG('g', 'v', 'a', 'r') ||
122 aTag
== TRUETYPE_TAG('H', 'V', 'A', 'R') ||
123 aTag
== TRUETYPE_TAG('M', 'V', 'A', 'R') ||
124 aTag
== TRUETYPE_TAG('S', 'T', 'A', 'T') ||
125 aTag
== TRUETYPE_TAG('V', 'V', 'A', 'R');
127 if (!mCheckVariationTables
&& isVariationTable(aTag
)) {
128 return ots::TABLE_ACTION_PASSTHRU
;
130 if (!gfxPlatform::HasVariationFontSupport() && isVariationTable(aTag
)) {
131 return ots::TABLE_ACTION_DROP
;
133 // Preserve SVG table if OpenType-SVG rendering is enabled.
134 if (aTag
== TRUETYPE_TAG('S', 'V', 'G', ' ')) {
135 return mKeepSVG
? ots::TABLE_ACTION_PASSTHRU
: ots::TABLE_ACTION_DROP
;
137 // Preserve BASE table; harfbuzz will sanitize it before using.
138 if (aTag
== TRUETYPE_TAG('B', 'A', 'S', 'E')) {
139 return ots::TABLE_ACTION_PASSTHRU
;
141 if (mKeepColorBitmaps
&& (aTag
== TRUETYPE_TAG('C', 'B', 'D', 'T') ||
142 aTag
== TRUETYPE_TAG('C', 'B', 'L', 'C'))) {
143 return ots::TABLE_ACTION_PASSTHRU
;
145 return ots::TABLE_ACTION_DEFAULT
;
148 static size_t GuessSanitizedFontSize(size_t aLength
,
149 gfxUserFontType aFontType
,
150 bool aStrict
= true) {
152 case GFX_USERFONT_UNKNOWN
:
153 // If being permissive of unknown types, make a reasonable guess
154 // at how much room the sanitized font may take, if it passes. Just
155 // enough extra space to accomodate some growth without excessive
156 // bloat in case of large fonts. 1.5x is a reasonable compromise
157 // for growable vectors in general.
158 return aStrict
|| !aLength
? 0 : (aLength
* 3) / 2;
159 case GFX_USERFONT_WOFF
:
161 case GFX_USERFONT_WOFF2
:
168 static size_t GuessSanitizedFontSize(const uint8_t* aData
, size_t aLength
,
169 bool aStrict
= true) {
170 gfxUserFontType fontType
=
171 gfxFontUtils::DetermineFontDataType(aData
, aLength
);
172 return GuessSanitizedFontSize(aLength
, fontType
, aStrict
);
176 bool mCheckOTLTables
;
177 bool mCheckVariationTables
;
178 bool mKeepColorBitmaps
;
182 #endif /* GFX_OTS_UTILS_H */