From e091da21917242466db4e4b53da59af649ae201d Mon Sep 17 00:00:00 2001 From: Jonathan Kew Date: Wed, 23 Jan 2013 16:41:18 +0000 Subject: [PATCH] bug 833283 - remove the option to bypass OTS for downloaded fonts. r=jdaggett --- gfx/thebes/Makefile.in | 4 +- gfx/thebes/gfxFontUtils.cpp | 224 ------ gfx/thebes/gfxFontUtils.h | 12 +- gfx/thebes/gfxPlatform.cpp | 15 - gfx/thebes/gfxPlatform.h | 6 - gfx/thebes/gfxUserFontSet.cpp | 159 +--- gfx/thebes/woff-private.h | 127 --- gfx/thebes/woff.c | 1297 ------------------------------- gfx/thebes/woff.h | 187 ----- modules/libpref/src/init/all.js | 1 - 10 files changed, 39 insertions(+), 1993 deletions(-) delete mode 100644 gfx/thebes/woff-private.h delete mode 100644 gfx/thebes/woff.c delete mode 100644 gfx/thebes/woff.h diff --git a/gfx/thebes/Makefile.in b/gfx/thebes/Makefile.in index 3cb7978e5e9..1df0748dcf0 100644 --- a/gfx/thebes/Makefile.in +++ b/gfx/thebes/Makefile.in @@ -345,9 +345,7 @@ CMMSRCS = \ endif -CSRCS += woff.c - -DEFINES += -DIMPL_THEBES -DWOFF_MOZILLA_CLIENT -DHB_DONT_DEFINE_STDINT +DEFINES += -DIMPL_THEBES -DHB_DONT_DEFINE_STDINT DEFINES += -DMOZ_OTS_REPORT_ERRORS ifeq (WINNT,$(OS_TARGET)) diff --git a/gfx/thebes/gfxFontUtils.cpp b/gfx/thebes/gfxFontUtils.cpp index ece483f3455..1cf0550428b 100644 --- a/gfx/thebes/gfxFontUtils.cpp +++ b/gfx/thebes/gfxFontUtils.cpp @@ -24,8 +24,6 @@ #include "plbase64.h" #include "prlog.h" -#include "woff.h" - #ifdef XP_MACOSX #include #endif @@ -1118,228 +1116,6 @@ gfxFontUtils::DetermineFontDataType(const uint8_t *aFontData, uint32_t aFontData return GFX_USERFONT_UNKNOWN; } -bool -gfxFontUtils::ValidateSFNTHeaders(const uint8_t *aFontData, - uint32_t aFontDataLength) -{ - NS_ASSERTION(aFontData, "null font data"); - - uint64_t dataLength(aFontDataLength); - - // read in the sfnt header - if (sizeof(SFNTHeader) > aFontDataLength) { - NS_WARNING("invalid font (insufficient data)"); - return false; - } - - const SFNTHeader *sfntHeader = reinterpret_cast(aFontData); - uint32_t sfntVersion = sfntHeader->sfntVersion; - if (!IsValidSFNTVersion(sfntVersion)) { - NS_WARNING("invalid font (SFNT version)"); - return false; - } - - // iterate through the table headers to find the head, name and OS/2 tables -#ifdef XP_WIN - bool foundOS2 = false; -#endif - bool foundHead = false, foundName = false; - bool foundGlyphs = false, foundCFF = false, foundKern = false; - bool foundLoca = false, foundMaxp = false; - uint32_t headOffset = 0, headLen, nameOffset = 0, kernOffset = 0, - kernLen = 0, glyfLen = 0, locaOffset = 0, locaLen = 0, - maxpOffset = 0, maxpLen; - uint32_t i, numTables; - - numTables = sfntHeader->numTables; - uint32_t headerLen = sizeof(SFNTHeader) + sizeof(TableDirEntry) * numTables; - if (headerLen > aFontDataLength) { - NS_WARNING("invalid font (table directory)"); - return false; - } - - // table directory entries begin immediately following SFNT header - const TableDirEntry *dirEntry = - reinterpret_cast(aFontData + sizeof(SFNTHeader)); - uint32_t checksum = 0; - - // checksum for font = (checksum of header) + (checksum of tables) - const AutoSwap_PRUint32 *headerData = - reinterpret_cast(aFontData); - - // header length is in bytes, checksum calculated in longwords - for (i = 0; i < (headerLen >> 2); i++, headerData++) { - checksum += *headerData; - } - - for (i = 0; i < numTables; i++, dirEntry++) { - - // sanity check on offset, length values - if (uint64_t(dirEntry->offset) + uint64_t(dirEntry->length) > dataLength) { - NS_WARNING("invalid font (table directory entry)"); - return false; - } - - checksum += dirEntry->checkSum; - - switch (dirEntry->tag) { - - case TRUETYPE_TAG('h','e','a','d'): - foundHead = true; - headOffset = dirEntry->offset; - headLen = dirEntry->length; - if (headLen < sizeof(HeadTable)) { - NS_WARNING("invalid font (head table length)"); - return false; - } - break; - - case TRUETYPE_TAG('k','e','r','n'): - foundKern = true; - kernOffset = dirEntry->offset; - kernLen = dirEntry->length; - break; - - case TRUETYPE_TAG('n','a','m','e'): - foundName = true; - nameOffset = dirEntry->offset; - break; - - case TRUETYPE_TAG('O','S','/','2'): -#ifdef XP_WIN - foundOS2 = true; -#endif - break; - - case TRUETYPE_TAG('g','l','y','f'): // TrueType-style quadratic glyph table - foundGlyphs = true; - glyfLen = dirEntry->length; - break; - - case TRUETYPE_TAG('l','o','c','a'): // glyph location table - foundLoca = true; - locaOffset = dirEntry->offset; - locaLen = dirEntry->length; - break; - - case TRUETYPE_TAG('m','a','x','p'): // max profile - foundMaxp = true; - maxpOffset = dirEntry->offset; - maxpLen = dirEntry->length; - if (maxpLen < sizeof(MaxpTableHeader)) { - NS_WARNING("invalid font (maxp table length)"); - return false; - } - break; - - case TRUETYPE_TAG('C','F','F',' '): // PS-style cubic glyph table - foundCFF = true; - break; - - default: - break; - } - - } - - // simple sanity checks - - // -- fonts need head, name, maxp tables - if (!foundHead || !foundName || !foundMaxp) { - NS_WARNING("invalid font (missing head/name/maxp table)"); - return false; - } - - // -- on Windows need OS/2 table -#ifdef XP_WIN - if (!foundOS2) { - NS_WARNING("invalid font (missing OS/2 table)"); - return false; - } -#endif - - // -- head table data - const HeadTable *headData = reinterpret_cast(aFontData + headOffset); - - if (headData->tableVersionNumber != HeadTable::HEAD_VERSION) { - NS_WARNING("invalid font (head table version)"); - return false; - } - - if (headData->magicNumber != HeadTable::HEAD_MAGIC_NUMBER) { - NS_WARNING("invalid font (head magic number)"); - return false; - } - - if (headData->checkSumAdjustment != (HeadTable::HEAD_CHECKSUM_CALC_CONST - checksum)) { - NS_WARNING("invalid font (bad checksum)"); - // Bug 483459 - warn about a bad checksum but allow the font to be - // used, since a small percentage of fonts don't calculate this - // correctly and font systems aren't fussy about this - // return false; - } - - // need glyf or CFF table based on sfnt version - if (sfntVersion == TRUETYPE_TAG('O','T','T','O')) { - if (!foundCFF) { - NS_WARNING("invalid font (missing CFF table)"); - return false; - } - } else { - if (!foundGlyphs || !foundLoca) { - NS_WARNING("invalid font (missing glyf or loca table)"); - return false; - } - - // sanity-check 'loca' offsets - const MaxpTableHeader *maxpData = - reinterpret_cast(aFontData + maxpOffset); - if (!ValidateLocaTable(aFontData + locaOffset, locaLen, glyfLen, - headData->indexToLocFormat, - maxpData->numGlyphs)) { - NS_WARNING("invalid font (loca table offsets)"); - return false; - } - } - - // -- name table data - const NameHeader *nameHeader = reinterpret_cast(aFontData + nameOffset); - - uint32_t nameCount = nameHeader->count; - - // -- sanity check the number of name records - if (uint64_t(nameCount) * sizeof(NameRecord) + uint64_t(nameOffset) > dataLength) { - NS_WARNING("invalid font (name records)"); - return false; - } - - // -- iterate through name records - const NameRecord *nameRecord = reinterpret_cast - (aFontData + nameOffset + sizeof(NameHeader)); - uint64_t nameStringsBase = uint64_t(nameOffset) + uint64_t(nameHeader->stringOffset); - - for (i = 0; i < nameCount; i++, nameRecord++) { - uint32_t namelen = nameRecord->length; - uint32_t nameoff = nameRecord->offset; // offset from base of string storage - - if (nameStringsBase + uint64_t(nameoff) + uint64_t(namelen) > dataLength) { - NS_WARNING("invalid font (name table strings)"); - return false; - } - } - - // -- sanity-check the kern table, if present (see bug 487549) - if (foundKern) { - if (!ValidateKernTable(aFontData + kernOffset, kernLen)) { - NS_WARNING("invalid font (kern table)"); - return false; - } - } - - // everything seems consistent - return true; -} - nsresult gfxFontUtils::RenameFont(const nsAString& aName, const uint8_t *aFontData, uint32_t aFontDataLength, FallibleTArray *aNewFont) diff --git a/gfx/thebes/gfxFontUtils.h b/gfx/thebes/gfxFontUtils.h index 8ca31ee6361..314bf0176df 100644 --- a/gfx/thebes/gfxFontUtils.h +++ b/gfx/thebes/gfxFontUtils.h @@ -740,8 +740,8 @@ public: MakeEOTHeader(const uint8_t *aFontData, uint32_t aFontDataLength, FallibleTArray *aHeader, FontDataOverlay *aOverlay); - // determine whether a font (which has already passed ValidateSFNTHeaders) - // is CFF format rather than TrueType + // determine whether a font (which has already been sanitized, so is known + // to be a valid sfnt) is CFF format rather than TrueType static bool IsCffFont(const uint8_t* aFontData, bool& hasVertical); @@ -751,14 +751,6 @@ public: static gfxUserFontType DetermineFontDataType(const uint8_t *aFontData, uint32_t aFontDataLength); - // checks for valid SFNT table structure, returns true if valid - // does *not* guarantee that all font data is valid, though it does - // check that key tables such as 'name' are present and readable. - // XXX to be removed if/when we eliminate the option to disable OTS, - // which does more thorough validation. - static bool - ValidateSFNTHeaders(const uint8_t *aFontData, uint32_t aFontDataLength); - // Read the fullname from the sfnt data (used to save the original name // prior to renaming the font for installation). // This is called with sfnt data that has already been validated, diff --git a/gfx/thebes/gfxPlatform.cpp b/gfx/thebes/gfxPlatform.cpp index 0a5f0e50790..813f9760638 100644 --- a/gfx/thebes/gfxPlatform.cpp +++ b/gfx/thebes/gfxPlatform.cpp @@ -129,7 +129,6 @@ SRGBOverrideObserver::Observe(nsISupports *aSubject, } #define GFX_DOWNLOADABLE_FONTS_ENABLED "gfx.downloadable_fonts.enabled" -#define GFX_DOWNLOADABLE_FONTS_SANITIZE "gfx.downloadable_fonts.sanitize" #define GFX_PREF_HARFBUZZ_SCRIPTS "gfx.font_rendering.harfbuzz.scripts" #define HARFBUZZ_SCRIPTS_DEFAULT mozilla::unicode::SHAPING_DEFAULT @@ -240,7 +239,6 @@ gfxPlatform::gfxPlatform() { mUseHarfBuzzScripts = UNINITIALIZED_VALUE; mAllowDownloadableFonts = UNINITIALIZED_VALUE; - mDownloadableFontsSanitize = UNINITIALIZED_VALUE; mFallbackUsesCmaps = UNINITIALIZED_VALUE; #ifdef MOZ_GRAPHITE @@ -819,17 +817,6 @@ gfxPlatform::DownloadableFontsEnabled() return mAllowDownloadableFonts; } -bool -gfxPlatform::SanitizeDownloadedFonts() -{ - if (mDownloadableFontsSanitize == UNINITIALIZED_VALUE) { - mDownloadableFontsSanitize = - Preferences::GetBool(GFX_DOWNLOADABLE_FONTS_SANITIZE, true); - } - - return mDownloadableFontsSanitize; -} - bool gfxPlatform::UseCmapsDuringSystemFallback() { @@ -1619,8 +1606,6 @@ gfxPlatform::FontsPrefsChanged(const char *aPref) NS_ASSERTION(aPref != nullptr, "null preference"); if (!strcmp(GFX_DOWNLOADABLE_FONTS_ENABLED, aPref)) { mAllowDownloadableFonts = UNINITIALIZED_VALUE; - } else if (!strcmp(GFX_DOWNLOADABLE_FONTS_SANITIZE, aPref)) { - mDownloadableFontsSanitize = UNINITIALIZED_VALUE; } else if (!strcmp(GFX_PREF_FALLBACK_USE_CMAPS, aPref)) { mFallbackUsesCmaps = UNINITIALIZED_VALUE; #ifdef MOZ_GRAPHITE diff --git a/gfx/thebes/gfxPlatform.h b/gfx/thebes/gfxPlatform.h index 894d204621c..fd7978425ee 100644 --- a/gfx/thebes/gfxPlatform.h +++ b/gfx/thebes/gfxPlatform.h @@ -315,11 +315,6 @@ public: */ bool DownloadableFontsEnabled(); - /** - * Whether to sanitize downloaded fonts using the OTS library - */ - bool SanitizeDownloadedFonts(); - /** * True when hinting should be enabled. This setting shouldn't * change per gecko process, while the process is live. If so the @@ -570,7 +565,6 @@ protected: } int8_t mAllowDownloadableFonts; - int8_t mDownloadableFontsSanitize; #ifdef MOZ_GRAPHITE int8_t mGraphiteShapingEnabled; #endif diff --git a/gfx/thebes/gfxUserFontSet.cpp b/gfx/thebes/gfxUserFontSet.cpp index 4c85fe56947..50fca4eb248 100644 --- a/gfx/thebes/gfxUserFontSet.cpp +++ b/gfx/thebes/gfxUserFontSet.cpp @@ -18,8 +18,6 @@ #include "nsIPrincipal.h" #include "mozilla/Telemetry.h" -#include "woff.h" - #include "opentype-sanitiser.h" #include "ots-memory-stream.h" @@ -203,58 +201,6 @@ gfxUserFontSet::FindFontEntry(gfxFontFamily *aFamily, return nullptr; } -// Given a buffer of downloaded font data, do any necessary preparation -// to make it into usable OpenType. -// May return the original pointer unchanged, or a newly-allocated -// block (in which case the passed-in block is NS_Free'd). -// aLength is updated if necessary to the new length of the data. -// Returns NULL and NS_Free's the incoming data in case of errors. -static const uint8_t* -PrepareOpenTypeData(const uint8_t* aData, uint32_t* aLength) -{ - switch(gfxFontUtils::DetermineFontDataType(aData, *aLength)) { - - case GFX_USERFONT_OPENTYPE: - // nothing to do - return aData; - - case GFX_USERFONT_WOFF: { - uint32_t status = eWOFF_ok; - uint32_t bufferSize = woffGetDecodedSize(aData, *aLength, &status); - if (WOFF_FAILURE(status)) { - break; - } - uint8_t* decodedData = static_cast(NS_Alloc(bufferSize)); - if (!decodedData) { - break; - } - woffDecodeToBuffer(aData, *aLength, - decodedData, bufferSize, - aLength, &status); - // replace original data with the decoded version - NS_Free((void*)aData); - aData = decodedData; - if (WOFF_FAILURE(status)) { - // something went wrong, discard the data and return NULL - break; - } - // success, return the decoded data - return aData; - } - - // xxx - add support for other wrappers here - - default: - NS_WARNING("unknown font format"); - break; - } - - // discard downloaded data that couldn't be used - NS_Free((void*)aData); - - return nullptr; -} - // Based on ots::ExpandingMemoryStream from ots-memory-stream.h, // adapted to use Mozilla allocators and to allow the final // memory buffer to be adopted by the client. @@ -666,18 +612,6 @@ gfxUserFontSet::LoadFont(gfxMixedFontFamily *aFamily, gfxUserFontType fontType = gfxFontUtils::DetermineFontDataType(aFontData, aLength); - // Save a copy of the metadata block (if present) for nsIDOMFontFace - // to use if required. Ownership of the metadata block will be passed - // to the gfxUserFontData record below. - // NOTE: after the non-OTS codepath using PrepareOpenTypeData is - // removed, we should defer this until after we've created the new - // fontEntry. - nsTArray metadata; - uint32_t metaOrigLen = 0; - if (fontType == GFX_USERFONT_WOFF) { - CopyWOFFMetadata(aFontData, aLength, &metadata, &metaOrigLen); - } - // Unwrap/decompress/sanitize or otherwise munge the downloaded data // to make a usable sfnt structure. @@ -686,67 +620,42 @@ gfxUserFontSet::LoadFont(gfxMixedFontFamily *aFamily, // it can be reported via the nsIDOMFontFace API. nsAutoString originalFullName; - if (gfxPlatform::GetPlatform()->SanitizeDownloadedFonts()) { - // Call the OTS sanitizer; this will also decode WOFF to sfnt - // if necessary. The original data in aFontData is left unchanged. - uint32_t saneLen; - const uint8_t* saneData = - SanitizeOpenTypeData(aFamily, aProxy, aFontData, aLength, saneLen, - fontType == GFX_USERFONT_WOFF); - if (!saneData) { - LogMessage(aFamily, aProxy, "rejected by sanitizer"); - } - if (saneData) { - // The sanitizer ensures that we have a valid sfnt and a usable - // name table, so this should never fail unless we're out of - // memory, and GetFullNameFromSFNT is not directly exposed to - // arbitrary/malicious data from the web. - gfxFontUtils::GetFullNameFromSFNT(saneData, saneLen, - originalFullName); - // Here ownership of saneData is passed to the platform, - // which will delete it when no longer required - fe = gfxPlatform::GetPlatform()->MakePlatformFont(aProxy, - saneData, - saneLen); - if (!fe) { - LogMessage(aFamily, aProxy, "not usable by platform"); - } - } - } else { - // FIXME: this code can be removed once we remove the pref to - // disable the sanitizer; the PrepareOpenTypeData and - // ValidateSFNTHeaders functions will then be obsolete. - aFontData = PrepareOpenTypeData(aFontData, &aLength); - - if (aFontData) { - if (gfxFontUtils::ValidateSFNTHeaders(aFontData, aLength)) { - // ValidateSFNTHeaders has checked that we have a valid - // sfnt structure and a usable 'name' table - gfxFontUtils::GetFullNameFromSFNT(aFontData, aLength, - originalFullName); - // Here ownership of aFontData is passed to the platform, - // which will delete it when no longer required - fe = gfxPlatform::GetPlatform()->MakePlatformFont(aProxy, - aFontData, - aLength); - if (!fe) { - LogMessage(aFamily, aProxy, "not usable by platform"); - } - aFontData = nullptr; // we must NOT free this! - } else { - // the data was unusable, so just discard it - // (error will be reported below, if logging is enabled) - LogMessage(aFamily, aProxy, "SFNT header or tables invalid"); - } - } + // Call the OTS sanitizer; this will also decode WOFF to sfnt + // if necessary. The original data in aFontData is left unchanged. + uint32_t saneLen; + const uint8_t* saneData = + SanitizeOpenTypeData(aFamily, aProxy, aFontData, aLength, saneLen, + fontType == GFX_USERFONT_WOFF); + if (!saneData) { + LogMessage(aFamily, aProxy, "rejected by sanitizer"); } - - if (aFontData) { - NS_Free((void*)aFontData); - aFontData = nullptr; + if (saneData) { + // The sanitizer ensures that we have a valid sfnt and a usable + // name table, so this should never fail unless we're out of + // memory, and GetFullNameFromSFNT is not directly exposed to + // arbitrary/malicious data from the web. + gfxFontUtils::GetFullNameFromSFNT(saneData, saneLen, + originalFullName); + // Here ownership of saneData is passed to the platform, + // which will delete it when no longer required + fe = gfxPlatform::GetPlatform()->MakePlatformFont(aProxy, + saneData, + saneLen); + if (!fe) { + LogMessage(aFamily, aProxy, "not usable by platform"); + } } if (fe) { + // Save a copy of the metadata block (if present) for nsIDOMFontFace + // to use if required. Ownership of the metadata block will be passed + // to the gfxUserFontData record below. + nsTArray metadata; + uint32_t metaOrigLen = 0; + if (fontType == GFX_USERFONT_WOFF) { + CopyWOFFMetadata(aFontData, aLength, &metadata, &metaOrigLen); + } + // copy OpenType feature/language settings from the proxy to the // newly-created font entry fe->mFeatureSettings.AppendElements(aProxy->mFeatureSettings); @@ -778,6 +687,10 @@ gfxUserFontSet::LoadFont(gfxMixedFontFamily *aFamily, #endif } + // The downloaded data can now be discarded; the font entry is using the + // sanitized copy + NS_Free((void*)aFontData); + return fe; } diff --git a/gfx/thebes/woff-private.h b/gfx/thebes/woff-private.h deleted file mode 100644 index f9323a64b67..00000000000 --- a/gfx/thebes/woff-private.h +++ /dev/null @@ -1,127 +0,0 @@ -/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#ifndef WOFF_PRIVATE_H_ -#define WOFF_PRIVATE_H_ - -#include "woff.h" - -/* private definitions used in the WOFF encoder/decoder functions */ - -/* create an OT tag from 4 characters */ -#define TAG(a,b,c,d) ((a)<<24 | (b)<<16 | (c)<<8 | (d)) - -#define WOFF_SIGNATURE TAG('w','O','F','F') - -#define SFNT_VERSION_CFF TAG('O','T','T','O') -#define SFNT_VERSION_TT 0x00010000 -#define SFNT_VERSION_true TAG('t','r','u','e') - -#define TABLE_TAG_DSIG TAG('D','S','I','G') -#define TABLE_TAG_head TAG('h','e','a','d') -#define TABLE_TAG_bhed TAG('b','h','e','d') - -#define SFNT_CHECKSUM_CALC_CONST 0xB1B0AFBAU /* from the TT/OT spec */ - -#ifdef WOFF_MOZILLA_CLIENT/* Copies of the NS_SWAP16 and NS_SWAP32 macros; they are defined in - a C++ header in mozilla, so we cannot include that here */ -# include "prtypes.h" /* defines IS_LITTLE_ENDIAN / IS_BIG_ENDIAN */ -# if defined IS_LITTLE_ENDIAN -# define READ16BE(x) ((((x) & 0xff) << 8) | (((x) >> 8) & 0xff)) -# define READ32BE(x) ((READ16BE((x) & 0xffff) << 16) | (READ16BE((x) >> 16))) -# elif defined IS_BIG_ENDIAN -# define READ16BE(x) (x) -# define READ32BE(x) (x) -# else -# error "Unknown byte order" -# endif -#else -/* These macros to read values as big-endian only work on "real" variables, - not general expressions, because of the use of &(x), but they are - designed to work on both BE and LE machines without the need for a - configure check. For production code, we might want to replace this - with something more efficient. */ -/* read a 32-bit BigEndian value */ -# define READ32BE(x) ( ( (uint32_t) ((uint8_t*)&(x))[0] << 24 ) + \ - ( (uint32_t) ((uint8_t*)&(x))[1] << 16 ) + \ - ( (uint32_t) ((uint8_t*)&(x))[2] << 8 ) + \ - (uint32_t) ((uint8_t*)&(x))[3] ) -/* read a 16-bit BigEndian value */ -# define READ16BE(x) ( ( (uint16_t) ((uint8_t*)&(x))[0] << 8 ) + \ - (uint16_t) ((uint8_t*)&(x))[1] ) -#endif - -#pragma pack(push,1) - -typedef struct { - uint32_t version; - uint16_t numTables; - uint16_t searchRange; - uint16_t entrySelector; - uint16_t rangeShift; -} sfntHeader; - -typedef struct { - uint32_t tag; - uint32_t checksum; - uint32_t offset; - uint32_t length; -} sfntDirEntry; - -typedef struct { - uint32_t signature; - uint32_t flavor; - uint32_t length; - uint16_t numTables; - uint16_t reserved; - uint32_t totalSfntSize; - uint16_t majorVersion; - uint16_t minorVersion; - uint32_t metaOffset; - uint32_t metaCompLen; - uint32_t metaOrigLen; - uint32_t privOffset; - uint32_t privLen; -} woffHeader; - -typedef struct { - uint32_t tag; - uint32_t offset; - uint32_t compLen; - uint32_t origLen; - uint32_t checksum; -} woffDirEntry; - -typedef struct { - uint32_t version; - uint32_t fontRevision; - uint32_t checkSumAdjustment; - uint32_t magicNumber; - uint16_t flags; - uint16_t unitsPerEm; - uint32_t created[2]; - uint32_t modified[2]; - int16_t xMin; - int16_t yMin; - int16_t xMax; - int16_t yMax; - uint16_t macStyle; - uint16_t lowestRecPpem; - int16_t fontDirectionHint; - int16_t indexToLocFormat; - int16_t glyphDataFormat; -} sfntHeadTable; - -#define HEAD_TABLE_SIZE 54 /* sizeof(sfntHeadTable) may report 56 because of alignment */ - -typedef struct { - uint32_t offset; - uint16_t oldIndex; - uint16_t newIndex; -} tableOrderRec; - -#pragma pack(pop) - -#endif diff --git a/gfx/thebes/woff.c b/gfx/thebes/woff.c deleted file mode 100644 index a3a33fcc801..00000000000 --- a/gfx/thebes/woff.c +++ /dev/null @@ -1,1297 +0,0 @@ -/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "woff-private.h" - -#include -#include -#include -#include "zlib.h" - -#ifdef WOFF_MOZILLA_CLIENT /* define this when building as part of Gecko */ -# include "mozilla/mozalloc.h" -# define malloc moz_malloc -# define realloc moz_realloc -# define free moz_free -#endif - -/* - * Just simple whole-file encoding and decoding functions; a more extensive - * WOFF library could provide support for accessing individual tables from a - * compressed font, alternative options for memory allocation/ownership and - * error handling, etc. - */ - -/* on errors, each function sets a status variable and jumps to failure: */ -#undef FAIL -#define FAIL(err) do { status |= err; goto failure; } while (0) - -/* adjust an offset for longword alignment */ -#define LONGALIGN(x) (((x) + 3) & ~3) - -static int -compareOffsets(const void * lhs, const void * rhs) -{ - const tableOrderRec * a = (const tableOrderRec *) lhs; - const tableOrderRec * b = (const tableOrderRec *) rhs; - /* don't simply return a->offset - b->offset because these are unsigned - offset values; could convert to int, but possible integer overflow */ - return a->offset > b->offset ? 1 : - a->offset < b->offset ? -1 : - 0; -} - -#ifndef WOFF_MOZILLA_CLIENT - -/******************************************************************/ -/* * * * * * * * * * * * * * ENCODING * * * * * * * * * * * * * * */ -/******************************************************************/ - -static uint32_t -calcChecksum(const sfntDirEntry * dirEntry, - const uint8_t * sfntData, uint32_t sfntLen) -{ - /* just returns zero on errors, they will be detected again elsewhere */ - const uint32_t * csumPtr; - const uint32_t * csumEnd; - uint32_t csum = 0; - uint32_t length = READ32BE(dirEntry->length); - uint32_t offset = READ32BE(dirEntry->offset); - uint32_t tag; - if (LONGALIGN(length) < length) { /* overflow */ - return csum; - } else { - length = LONGALIGN(length); - } - if ((offset & 3) != 0) { /* invalid - not properly aligned */ - return csum; - } - if (length > sfntLen || offset > sfntLen - length) { - return csum; - } - csumPtr = (const uint32_t *) (sfntData + offset); - csumEnd = csumPtr + length / 4; - while (csumPtr < csumEnd) { - csum += READ32BE(*csumPtr); - csumPtr++; - } - tag = READ32BE(dirEntry->tag); - if (tag == TABLE_TAG_head || tag == TABLE_TAG_bhed) { - const sfntHeadTable * head; - if (length < HEAD_TABLE_SIZE) { - return 0; - } - head = (const sfntHeadTable *)(sfntData + offset); - csum -= READ32BE(head->checkSumAdjustment); - } - return csum; -} - -const uint8_t * -woffEncode(const uint8_t * sfntData, uint32_t sfntLen, - uint16_t majorVersion, uint16_t minorVersion, - uint32_t * woffLen, uint32_t * pStatus) -{ - uint8_t * woffData = NULL; - tableOrderRec * tableOrder = NULL; - - uint32_t tableOffset; - uint32_t totalSfntSize; - - uint16_t numOrigTables; - uint16_t numTables; - uint16_t tableIndex; - uint16_t order; - const sfntDirEntry * sfntDir; - uint32_t tableBase; - uint32_t checkSumAdjustment = 0; - woffHeader * newHeader; - uint32_t tag = 0; - uint32_t removedDsigSize = 0; - uint32_t status = eWOFF_ok; - - const sfntHeader * header = (const sfntHeader *) (sfntData); - const sfntHeadTable * head = NULL; - - if (pStatus && WOFF_FAILURE(*pStatus)) { - return NULL; - } - - if (READ32BE(header->version) != SFNT_VERSION_TT && - READ32BE(header->version) != SFNT_VERSION_CFF && - READ32BE(header->version) != SFNT_VERSION_true) { - status |= eWOFF_warn_unknown_version; - } - - numOrigTables = READ16BE(header->numTables); - sfntDir = (const sfntDirEntry *) (sfntData + sizeof(sfntHeader)); - - for (tableIndex = 0; tableIndex < numOrigTables; ++tableIndex) { - /* validate table checksums, to figure out if we need to drop DSIG; - also check that table directory is correctly sorted */ - uint32_t prevTag = tag; - uint32_t csum = calcChecksum(&sfntDir[tableIndex], sfntData, sfntLen); - if (csum != READ32BE(sfntDir[tableIndex].checksum)) { - status |= eWOFF_warn_checksum_mismatch; - } - checkSumAdjustment += csum; - tag = READ32BE(sfntDir[tableIndex].tag); - if (tag <= prevTag) { - FAIL(eWOFF_invalid); - } - if (tag == TABLE_TAG_head || tag == TABLE_TAG_bhed) { - if (READ32BE(sfntDir[tableIndex].length) < HEAD_TABLE_SIZE) { - FAIL(eWOFF_invalid); - } - head = (const sfntHeadTable *)(sfntData + - READ32BE(sfntDir[tableIndex].offset)); - } - } - if (!head) { - FAIL(eWOFF_invalid); - } - if ((status & eWOFF_warn_checksum_mismatch) == 0) { - /* no point even checking if we already have an error, - as fixing that will change the overall checksum too */ - const uint32_t * csumPtr = (const uint32_t *) sfntData; - const uint32_t * csumEnd = csumPtr + 3 + 4 * numOrigTables; - while (csumPtr < csumEnd) { - checkSumAdjustment += READ32BE(*csumPtr); - ++csumPtr; - } - checkSumAdjustment = 0xB1B0AFBA - checkSumAdjustment; - if (checkSumAdjustment != READ32BE(head->checkSumAdjustment)) { - status |= eWOFF_warn_checksum_mismatch; - } - } - - /* Fixing checkSumAdjustment is tricky, because if there's a DSIG table, - we're going to have to remove that, which in turn means that table - offsets in the directory will all change. - And recalculating checkSumAdjustment requires taking account of any - individual table checksum corrections, but they have not actually been - applied to the sfnt data at this point. - And finally, we'd need to get the corrected checkSumAdjustment into the - encoded head table (but we can't modify the original sfnt data). - An easier way out seems to be to go ahead and encode the font, knowing - that checkSumAdjustment will be wrong; then (if the status flag - eWOFF_warn_checksum_mismatch is set) we'll decode the font back to - sfnt format. This will fix up the checkSumAdjustment (and return a - warning status). We'll ignore that warning, and then re-encode the - new, cleaned-up sfnt to get the final WOFF data. Perhaps not the most - efficient approach, but it seems simpler than trying to predict the - correct final checkSumAdjustment and incorporate it into the head - table on the fly. */ - - tableOrder = (tableOrderRec *) malloc(numOrigTables * sizeof(tableOrderRec)); - if (!tableOrder) { - FAIL(eWOFF_out_of_memory); - } - for (tableIndex = 0, numTables = 0; - tableIndex < numOrigTables; ++tableIndex) { - if ((status & eWOFF_warn_checksum_mismatch) != 0) { - /* check for DSIG table that we must drop if we're fixing checksums */ - tag = READ32BE(sfntDir[tableIndex].tag); - if (tag == TABLE_TAG_DSIG) { - status |= eWOFF_warn_removed_DSIG; - removedDsigSize = READ32BE(sfntDir[tableIndex].length); - if (LONGALIGN(removedDsigSize) < removedDsigSize) { - FAIL(eWOFF_invalid); - } - continue; - } - } - tableOrder[numTables].offset = READ32BE(sfntDir[tableIndex].offset); - tableOrder[numTables].oldIndex = tableIndex; - tableOrder[numTables].newIndex = numTables; - ++numTables; - } - qsort(tableOrder, numTables, sizeof(tableOrderRec), compareOffsets); - - /* initially, allocate space for header and directory */ - /* cannot be too big because numTables is 16-bit */ - tableOffset = sizeof(woffHeader) + numTables * sizeof(woffDirEntry); - woffData = (uint8_t *) malloc(tableOffset); - if (!woffData) { - FAIL(eWOFF_out_of_memory); - } - - /* accumulator for total expected size of decoded font */ - totalSfntSize = sizeof(sfntHeader) + numTables * sizeof(sfntDirEntry); - -/* - * We use a macro for this rather than creating a variable because woffData - * will get reallocated during encoding. The macro avoids the risk of using a - * stale pointer, and the compiler should optimize multiple successive uses. - */ -#define WOFFDIR ((woffDirEntry *) (woffData + sizeof(woffHeader))) - - for (order = 0; order < numTables; ++order) { - uLong sourceLen, destLen; - uint32_t sourceOffset; - - uint16_t oldIndex = tableOrder[order].oldIndex; - uint16_t newIndex = tableOrder[order].newIndex; - - WOFFDIR[newIndex].tag = sfntDir[oldIndex].tag; - if ((status & eWOFF_warn_checksum_mismatch) != 0) { - uint32_t csum = calcChecksum(&sfntDir[oldIndex], sfntData, sfntLen); - WOFFDIR[newIndex].checksum = READ32BE(csum); - } else { - WOFFDIR[newIndex].checksum = sfntDir[oldIndex].checksum; - } - WOFFDIR[newIndex].origLen = sfntDir[oldIndex].length; - - /* we always realloc woffData to a long-aligned size, so this is safe */ - while ((tableOffset & 3) != 0) { - woffData[tableOffset++] = 0; - } - WOFFDIR[newIndex].offset = READ32BE(tableOffset); - - /* allocate enough space for upper bound of compressed size */ - sourceOffset = READ32BE(sfntDir[oldIndex].offset); - if ((sourceOffset & 3) != 0) { - status |= eWOFF_warn_misaligned_table; - } - sourceLen = READ32BE(sfntDir[oldIndex].length); - if (sourceLen > sfntLen || sourceOffset > sfntLen - sourceLen) { - FAIL(eWOFF_invalid); - } - destLen = compressBound(sourceLen); - if (LONGALIGN(destLen) < destLen) { - /* something weird is going on if this overflows! */ - FAIL(eWOFF_invalid); - } - destLen = LONGALIGN(destLen); - if (tableOffset + destLen < tableOffset) { - FAIL(eWOFF_invalid); - } - woffData = (uint8_t *) realloc(woffData, tableOffset + destLen); - if (!woffData) { - FAIL(eWOFF_out_of_memory); - } - - /* do the compression directly into the WOFF data block */ - if (compress2((Bytef *) (woffData + tableOffset), &destLen, - (const Bytef *) (sfntData + sourceOffset), - sourceLen, 9) != Z_OK) { - FAIL(eWOFF_compression_failure); - } - if (destLen < sourceLen) { - /* compressed table was smaller */ - tableOffset += destLen; /* checked for potential overflow above */ - WOFFDIR[newIndex].compLen = READ32BE(destLen); - } else { - /* compression didn't make it smaller, so store original data instead */ - if (LONGALIGN(sourceLen) < sourceLen) { - FAIL(eWOFF_invalid); /* overflow, bail out */ - } - destLen = sourceLen; - /* reallocate to ensure enough space for the table, - plus potential padding after it */ - if (tableOffset + LONGALIGN(sourceLen) < tableOffset) { - FAIL(eWOFF_invalid); /* overflow, bail out */ - } - woffData = (uint8_t *) realloc(woffData, - tableOffset + LONGALIGN(sourceLen)); - if (!woffData) { - FAIL(eWOFF_out_of_memory); - } - /* copy the original data into place */ - memcpy(woffData + tableOffset, - sfntData + READ32BE(sfntDir[oldIndex].offset), sourceLen); - if (tableOffset + sourceLen < tableOffset) { - FAIL(eWOFF_invalid); /* overflow, bail out */ - } - tableOffset += sourceLen; - WOFFDIR[newIndex].compLen = WOFFDIR[newIndex].origLen; - } - - /* update total size of uncompressed OpenType with table size */ - if (totalSfntSize + sourceLen < totalSfntSize) { - FAIL(eWOFF_invalid); /* overflow, bail out */ - } - totalSfntSize += sourceLen; - if (LONGALIGN(totalSfntSize) < totalSfntSize) { - FAIL(eWOFF_invalid); - } - totalSfntSize = LONGALIGN(totalSfntSize); - } - - if (totalSfntSize > sfntLen) { - if (totalSfntSize > LONGALIGN(sfntLen)) { - FAIL(eWOFF_invalid); - } else { - status |= eWOFF_warn_unpadded_table; - } - } else if (totalSfntSize < sfntLen) { - /* check if the remaining data is a DSIG we're removing; - if so, we're already warning about that */ - if ((status & eWOFF_warn_removed_DSIG) != 0 || - sfntLen - totalSfntSize > - LONGALIGN(removedDsigSize) + sizeof(sfntDirEntry)) { - status |= eWOFF_warn_trailing_data; - } - } - - /* write the header */ - newHeader = (woffHeader *) (woffData); - newHeader->signature = WOFF_SIGNATURE; - newHeader->signature = READ32BE(newHeader->signature); - newHeader->flavor = header->version; - newHeader->length = READ32BE(tableOffset); - newHeader->numTables = READ16BE(numTables); - newHeader->reserved = 0; - newHeader->totalSfntSize = READ32BE(totalSfntSize); - newHeader->majorVersion = READ16BE(majorVersion); - newHeader->minorVersion = READ16BE(minorVersion); - newHeader->metaOffset = 0; - newHeader->metaCompLen = 0; - newHeader->metaOrigLen = 0; - newHeader->privOffset = 0; - newHeader->privLen = 0; - - free(tableOrder); - - if ((status & eWOFF_warn_checksum_mismatch) != 0) { - /* The original font had checksum errors, so we now decode our WOFF data - back to sfnt format (which fixes checkSumAdjustment), then re-encode - to get a clean copy. */ - const uint8_t * cleanSfnt = woffDecode(woffData, tableOffset, - &sfntLen, &status); - if (WOFF_FAILURE(status)) { - FAIL(status); - } - free(woffData); - woffData = (uint8_t *) woffEncode(cleanSfnt, sfntLen, - majorVersion, minorVersion, - &tableOffset, &status); - free((void *) cleanSfnt); - if (WOFF_FAILURE(status)) { - FAIL(status); - } - } - - if (woffLen) { - *woffLen = tableOffset; - } - if (pStatus) { - *pStatus |= status; - } - return woffData; - -failure: - if (tableOrder) { - free(tableOrder); - } - if (woffData) { - free(woffData); - } - if (pStatus) { - *pStatus = status; - } - return NULL; -} - -static const uint8_t * -rebuildWoff(const uint8_t * woffData, uint32_t * woffLen, - const uint8_t * metaData, uint32_t metaCompLen, uint32_t metaOrigLen, - const uint8_t * privData, uint32_t privLen, uint32_t * pStatus) -{ - const woffHeader * origHeader; - const woffDirEntry * woffDir; - uint8_t * newData = NULL; - uint8_t * tableData = NULL; - woffHeader * newHeader; - uint16_t numTables; - uint32_t tableLimit, totalSize, offset; - uint16_t i; - uint32_t status = eWOFF_ok; - - if (*woffLen < sizeof(woffHeader)) { - FAIL(eWOFF_invalid); - } - origHeader = (const woffHeader *) (woffData); - - if (READ32BE(origHeader->signature) != WOFF_SIGNATURE) { - FAIL(eWOFF_bad_signature); - } - - numTables = READ16BE(origHeader->numTables); - woffDir = (const woffDirEntry *) (woffData + sizeof(woffHeader)); - tableLimit = 0; - for (i = 0; i < numTables; ++i) { - uint32_t end = READ32BE(woffDir[i].offset) + READ32BE(woffDir[i].compLen); - if (end > tableLimit) { - tableLimit = end; - } - } - tableLimit = LONGALIGN(tableLimit); - - /* check for broken input (meta/priv data before sfnt tables) */ - offset = READ32BE(origHeader->metaOffset); - if (offset != 0 && offset < tableLimit) { - FAIL(eWOFF_illegal_order); - } - offset = READ32BE(origHeader->privOffset); - if (offset != 0 && offset < tableLimit) { - FAIL(eWOFF_illegal_order); - } - - totalSize = tableLimit; /* already long-aligned */ - if (metaCompLen) { - if (totalSize + metaCompLen < totalSize) { - FAIL(eWOFF_invalid); - } - totalSize += metaCompLen; - } - if (privLen) { - if (LONGALIGN(totalSize) < totalSize) { - FAIL(eWOFF_invalid); - } - totalSize = LONGALIGN(totalSize); - if (totalSize + privLen < totalSize) { - FAIL(eWOFF_invalid); - } - totalSize += privLen; - } - newData = malloc(totalSize); - if (!newData) { - FAIL(eWOFF_out_of_memory); - } - - /* copy the header, directory, and sfnt tables */ - memcpy(newData, woffData, tableLimit); - - /* then overwrite the header fields that should be changed */ - newHeader = (woffHeader *) newData; - newHeader->length = READ32BE(totalSize); - newHeader->metaOffset = 0; - newHeader->metaCompLen = 0; - newHeader->metaOrigLen = 0; - newHeader->privOffset = 0; - newHeader->privLen = 0; - - offset = tableLimit; - if (metaData && metaCompLen > 0 && metaOrigLen > 0) { - newHeader->metaOffset = READ32BE(offset); - newHeader->metaCompLen = READ32BE(metaCompLen); - newHeader->metaOrigLen = READ32BE(metaOrigLen); - memcpy(newData + offset, metaData, metaCompLen); - offset += metaCompLen; - } - - if (privData && privLen > 0) { - while ((offset & 3) != 0) { - newData[offset++] = 0; - } - newHeader->privOffset = READ32BE(offset); - newHeader->privLen = READ32BE(privLen); - memcpy(newData + offset, privData, privLen); - offset += privLen; - } - - *woffLen = offset; - free((void *) woffData); - - if (pStatus) { - *pStatus |= status; - } - return newData; - -failure: - if (newData) { - free(newData); - } - if (pStatus) { - *pStatus = status; - } - return NULL; -} - -const uint8_t * -woffSetMetadata(const uint8_t * woffData, uint32_t * woffLen, - const uint8_t * metaData, uint32_t metaLen, - uint32_t * pStatus) -{ - const woffHeader * header; - uLong compLen = 0; - uint8_t * compData = NULL; - const uint8_t * privData = NULL; - uint32_t privLen = 0; - uint32_t status = eWOFF_ok; - - if (pStatus && WOFF_FAILURE(*pStatus)) { - return NULL; - } - - if (!woffData || !woffLen) { - FAIL(eWOFF_bad_parameter); - } - - if (*woffLen < sizeof(woffHeader)) { - FAIL(eWOFF_invalid); - } - header = (const woffHeader *) (woffData); - - if (READ32BE(header->signature) != WOFF_SIGNATURE) { - FAIL(eWOFF_bad_signature); - } - - if (header->privOffset != 0 && header->privLen != 0) { - privData = woffData + READ32BE(header->privOffset); - privLen = READ32BE(header->privLen); - if (privData + privLen > woffData + *woffLen) { - FAIL(eWOFF_invalid); - } - } - - if (metaData && metaLen > 0) { - compLen = compressBound(metaLen); - compData = malloc(compLen); - if (!compData) { - FAIL(eWOFF_out_of_memory); - } - - if (compress2((Bytef *) compData, &compLen, - (const Bytef *) metaData, metaLen, 9) != Z_OK) { - FAIL(eWOFF_compression_failure); - } - } - - woffData = rebuildWoff(woffData, woffLen, - compData, compLen, metaLen, - privData, privLen, pStatus); - free(compData); - return woffData; - -failure: - if (compData) { - free(compData); - } - if (pStatus) { - *pStatus = status; - } - return NULL; -} - -const uint8_t * -woffSetPrivateData(const uint8_t * woffData, uint32_t * woffLen, - const uint8_t * privData, uint32_t privLen, - uint32_t * pStatus) -{ - const woffHeader * header; - const uint8_t * metaData = NULL; - uint32_t metaLen = 0; - uint32_t status = eWOFF_ok; - - if (pStatus && WOFF_FAILURE(*pStatus)) { - return NULL; - } - - if (!woffData || !woffLen) { - FAIL(eWOFF_bad_parameter); - } - - if (*woffLen < sizeof(woffHeader)) { - FAIL(eWOFF_invalid); - } - header = (const woffHeader *) (woffData); - - if (READ32BE(header->signature) != WOFF_SIGNATURE) { - FAIL(eWOFF_bad_signature); - } - - if (header->metaOffset != 0 && header->metaCompLen != 0) { - metaData = woffData + READ32BE(header->metaOffset); - metaLen = READ32BE(header->metaCompLen); - if (metaData + metaLen > woffData + *woffLen) { - FAIL(eWOFF_invalid); - } - } - - woffData = rebuildWoff(woffData, woffLen, - metaData, metaLen, READ32BE(header->metaOrigLen), - privData, privLen, pStatus); - return woffData; - -failure: - if (pStatus) { - *pStatus = status; - } - return NULL; -} - -#endif /* WOFF_MOZILLA_CLIENT */ - -/******************************************************************/ -/* * * * * * * * * * * * * * DECODING * * * * * * * * * * * * * * */ -/******************************************************************/ - -static uint32_t -sanityCheck(const uint8_t * woffData, uint32_t woffLen) -{ - const woffHeader * header; - uint16_t numTables, i; - const woffDirEntry * dirEntry; - uint64_t tableTotal = 0; - - if (!woffData || !woffLen) { - return eWOFF_bad_parameter; - } - - if (woffLen < sizeof(woffHeader)) { - return eWOFF_invalid; - } - - header = (const woffHeader *) (woffData); - if (READ32BE(header->signature) != WOFF_SIGNATURE) { - return eWOFF_bad_signature; - } - - if (READ32BE(header->length) != woffLen || header->reserved != 0) { - return eWOFF_invalid; - } - - numTables = READ16BE(header->numTables); - if (woffLen < sizeof(woffHeader) + numTables * sizeof(woffDirEntry)) { - return eWOFF_invalid; - } - - dirEntry = (const woffDirEntry *) (woffData + sizeof(woffHeader)); - for (i = 0; i < numTables; ++i) { - uint64_t offs = READ32BE(dirEntry->offset); - uint64_t orig = READ32BE(dirEntry->origLen); - uint64_t comp = READ32BE(dirEntry->compLen); - if (comp > orig || comp > woffLen || offs > woffLen - comp) { - return eWOFF_invalid; - } - orig = (orig + 3) & ~3; - tableTotal += orig; - if (tableTotal > 0xffffffffU) { - return eWOFF_invalid; - } - ++dirEntry; - } - - if (tableTotal > 0xffffffffU - sizeof(sfntHeader) - - numTables * sizeof(sfntDirEntry) || - READ32BE(header->totalSfntSize) != - tableTotal + sizeof(sfntHeader) + numTables * sizeof(sfntDirEntry)) { - return eWOFF_invalid; - } - - return eWOFF_ok; -} - -uint32_t -woffGetDecodedSize(const uint8_t * woffData, uint32_t woffLen, - uint32_t * pStatus) -{ - uint32_t status = eWOFF_ok; - uint32_t totalLen = 0; - - if (pStatus && WOFF_FAILURE(*pStatus)) { - return 0; - } - - status = sanityCheck(woffData, woffLen); - if (WOFF_FAILURE(status)) { - FAIL(status); - } - - totalLen = READ32BE(((const woffHeader *) (woffData))->totalSfntSize); - /* totalLen must be correctly rounded up to 4-byte alignment, otherwise - sanityCheck would have failed */ - -failure: - if (pStatus) { - *pStatus = status; - } - return totalLen; -} - -static void -woffDecodeToBufferInternal(const uint8_t * woffData, uint32_t woffLen, - uint8_t * sfntData, uint32_t bufferLen, - uint32_t * pActualSfntLen, uint32_t * pStatus) -{ - /* this is only called after sanityCheck has verified that - (a) basic header fields are ok - (b) all the WOFF table offset/length pairs are valid (within the data) - (c) the sum of original sizes + header/directory matches totalSfntSize - so we don't have to re-check those overflow conditions here */ - tableOrderRec * tableOrder = NULL; - const woffHeader * header; - uint16_t numTables; - uint16_t tableIndex; - uint16_t order; - const woffDirEntry * woffDir; - uint32_t totalLen; - sfntHeader * newHeader; - uint16_t searchRange, rangeShift, entrySelector; - uint32_t offset; - sfntDirEntry * sfntDir; - uint32_t headOffset = 0, headLength = 0; - sfntHeadTable * head; - uint32_t csum = 0; - const uint32_t * csumPtr; - uint32_t oldCheckSumAdjustment; - uint32_t status = eWOFF_ok; - - if (pStatus && WOFF_FAILURE(*pStatus)) { - return; - } - - /* check basic header fields */ - header = (const woffHeader *) (woffData); - if (READ32BE(header->flavor) != SFNT_VERSION_TT && - READ32BE(header->flavor) != SFNT_VERSION_CFF && - READ32BE(header->flavor) != SFNT_VERSION_true) { - status |= eWOFF_warn_unknown_version; - } - - numTables = READ16BE(header->numTables); - woffDir = (const woffDirEntry *) (woffData + sizeof(woffHeader)); - - totalLen = READ32BE(header->totalSfntSize); - - /* construct the sfnt header */ - newHeader = (sfntHeader *) (sfntData); - newHeader->version = header->flavor; - newHeader->numTables = READ16BE(numTables); - - /* calculate header fields for binary search */ - searchRange = numTables; - searchRange |= (searchRange >> 1); - searchRange |= (searchRange >> 2); - searchRange |= (searchRange >> 4); - searchRange |= (searchRange >> 8); - searchRange &= ~(searchRange >> 1); - searchRange *= 16; - newHeader->searchRange = READ16BE(searchRange); - rangeShift = numTables * 16 - searchRange; - newHeader->rangeShift = READ16BE(rangeShift); - entrySelector = 0; - while (searchRange > 16) { - ++entrySelector; - searchRange >>= 1; - } - newHeader->entrySelector = READ16BE(entrySelector); - - /* cannot be too big because numTables is 16-bit */ - tableOrder = (tableOrderRec *) malloc(numTables * sizeof(tableOrderRec)); - if (!tableOrder) { - FAIL(eWOFF_out_of_memory); - } - for (tableIndex = 0; tableIndex < numTables; ++tableIndex) { - tableOrder[tableIndex].offset = READ32BE(woffDir[tableIndex].offset); - tableOrder[tableIndex].oldIndex = tableIndex; - } - qsort(tableOrder, numTables, sizeof(tableOrderRec), compareOffsets); - - /* process each table, filling in the sfnt directory */ - offset = sizeof(sfntHeader) + numTables * sizeof(sfntDirEntry); - sfntDir = (sfntDirEntry *) (sfntData + sizeof(sfntHeader)); - for (order = 0; order < numTables; ++order) { - uint32_t origLen, compLen, tag, sourceOffset; - tableIndex = tableOrder[order].oldIndex; - - /* validity of these was confirmed by sanityCheck */ - origLen = READ32BE(woffDir[tableIndex].origLen); - compLen = READ32BE(woffDir[tableIndex].compLen); - sourceOffset = READ32BE(woffDir[tableIndex].offset); - - sfntDir[tableIndex].tag = woffDir[tableIndex].tag; - sfntDir[tableIndex].offset = READ32BE(offset); - sfntDir[tableIndex].length = woffDir[tableIndex].origLen; - sfntDir[tableIndex].checksum = woffDir[tableIndex].checksum; - csum += READ32BE(sfntDir[tableIndex].checksum); - - if (compLen < origLen) { - uLongf destLen = origLen; - if (uncompress((Bytef *)(sfntData + offset), &destLen, - (const Bytef *)(woffData + sourceOffset), - compLen) != Z_OK || destLen != origLen) { - FAIL(eWOFF_compression_failure); - } - } else { - memcpy(sfntData + offset, woffData + sourceOffset, origLen); - } - - /* note that old Mac bitmap-only fonts have no 'head' table - (eg NISC18030.ttf) but a 'bhed' table instead */ - tag = READ32BE(sfntDir[tableIndex].tag); - if (tag == TABLE_TAG_head || tag == TABLE_TAG_bhed) { - headOffset = offset; - headLength = origLen; - } - - offset += origLen; - - while (offset < totalLen && (offset & 3) != 0) { - sfntData[offset++] = 0; - } - } - - if (headOffset > 0) { - /* the font checksum in the 'head' table depends on all the individual - table checksums (collected above), plus the header and directory - which are added in here */ - if (headLength < HEAD_TABLE_SIZE) { - FAIL(eWOFF_invalid); - } - head = (sfntHeadTable *)(sfntData + headOffset); - oldCheckSumAdjustment = READ32BE(head->checkSumAdjustment); - head->checkSumAdjustment = 0; - csumPtr = (const uint32_t *)sfntData; - while (csumPtr < (const uint32_t *)(sfntData + sizeof(sfntHeader) + - numTables * sizeof(sfntDirEntry))) { - csum += READ32BE(*csumPtr); - csumPtr++; - } - csum = SFNT_CHECKSUM_CALC_CONST - csum; - - if (oldCheckSumAdjustment != csum) { - /* if the checksum doesn't match, we fix it; but this will invalidate - any DSIG that may be present */ - status |= eWOFF_warn_checksum_mismatch; - } - head->checkSumAdjustment = READ32BE(csum); - } - - if (pActualSfntLen) { - *pActualSfntLen = totalLen; - } - if (pStatus) { - *pStatus |= status; - } - free(tableOrder); - return; - -failure: - if (tableOrder) { - free(tableOrder); - } - if (pActualSfntLen) { - *pActualSfntLen = 0; - } - if (pStatus) { - *pStatus = status; - } -} - -void -woffDecodeToBuffer(const uint8_t * woffData, uint32_t woffLen, - uint8_t * sfntData, uint32_t bufferLen, - uint32_t * pActualSfntLen, uint32_t * pStatus) -{ - uint32_t status = eWOFF_ok; - uint32_t totalLen; - - if (pStatus && WOFF_FAILURE(*pStatus)) { - return; - } - - status = sanityCheck(woffData, woffLen); - if (WOFF_FAILURE(status)) { - FAIL(status); - } - - if (!sfntData) { - FAIL(eWOFF_bad_parameter); - } - - totalLen = READ32BE(((const woffHeader *) (woffData))->totalSfntSize); - if (bufferLen < totalLen) { - FAIL(eWOFF_buffer_too_small); - } - - woffDecodeToBufferInternal(woffData, woffLen, sfntData, bufferLen, - pActualSfntLen, pStatus); - return; - -failure: - if (pActualSfntLen) { - *pActualSfntLen = 0; - } - if (pStatus) { - *pStatus = status; - } -} - -const uint8_t * -woffDecode(const uint8_t * woffData, uint32_t woffLen, - uint32_t * sfntLen, uint32_t * pStatus) -{ - uint32_t status = eWOFF_ok; - uint8_t * sfntData = NULL; - uint32_t bufLen; - - if (pStatus && WOFF_FAILURE(*pStatus)) { - return NULL; - } - - status = sanityCheck(woffData, woffLen); - if (WOFF_FAILURE(status)) { - FAIL(status); - } - - bufLen = READ32BE(((const woffHeader *) (woffData))->totalSfntSize); - sfntData = (uint8_t *) malloc(bufLen); - if (!sfntData) { - FAIL(eWOFF_out_of_memory); - } - - woffDecodeToBufferInternal(woffData, woffLen, sfntData, bufLen, - sfntLen, &status); - if (WOFF_FAILURE(status)) { - FAIL(status); - } - - if (pStatus) { - *pStatus |= status; - } - return sfntData; - -failure: - if (sfntData) { - free(sfntData); - } - if (pStatus) { - *pStatus = status; - } - return NULL; -} - -/* functions to get size and data of a single table */ - -uint32_t woffGetTableSize(const uint8_t * woffData, uint32_t woffLen, - uint32_t tag, uint32_t * pStatus) -{ - uint32_t status = eWOFF_ok; - const woffHeader * header; - uint16_t numTables; - uint16_t tableIndex; - const woffDirEntry * woffDir; - - if (pStatus && WOFF_FAILURE(*pStatus)) { - return 0; - } - - status = sanityCheck(woffData, woffLen); - if (WOFF_FAILURE(status)) { - FAIL(status); - } - - header = (const woffHeader *) (woffData); - - numTables = READ16BE(header->numTables); - woffDir = (const woffDirEntry *) (woffData + sizeof(woffHeader)); - - for (tableIndex = 0; tableIndex < numTables; ++tableIndex) { - uint32_t thisTag; - thisTag = READ32BE(woffDir[tableIndex].tag); - if (thisTag < tag) { - continue; - } - if (thisTag > tag) { - break; - } - return READ32BE(woffDir[tableIndex].origLen); - } - - status = eWOFF_warn_no_such_table; - -failure: - if (pStatus) { - *pStatus = status; - } - return 0; -} - -void woffGetTableToBuffer(const uint8_t * woffData, uint32_t woffLen, - uint32_t tag, uint8_t * buffer, uint32_t bufferLen, - uint32_t * pTableLen, uint32_t * pStatus) -{ - uint32_t status = eWOFF_ok; - const woffHeader * header; - uint16_t numTables; - uint16_t tableIndex; - const woffDirEntry * woffDir; - - if (pStatus && WOFF_FAILURE(*pStatus)) { - return; - } - - status = sanityCheck(woffData, woffLen); - if (WOFF_FAILURE(status)) { - FAIL(status); - } - - header = (const woffHeader *) (woffData); - - numTables = READ16BE(header->numTables); - woffDir = (const woffDirEntry *) (woffData + sizeof(woffHeader)); - - for (tableIndex = 0; tableIndex < numTables; ++tableIndex) { - uint32_t thisTag, origLen, compLen, sourceOffset; - thisTag = READ32BE(woffDir[tableIndex].tag); - if (thisTag < tag) { - continue; - } - if (thisTag > tag) { - break; - } - - /* found the required table: decompress it (checking for overflow) */ - origLen = READ32BE(woffDir[tableIndex].origLen); - if (origLen > bufferLen) { - FAIL(eWOFF_buffer_too_small); - } - - compLen = READ32BE(woffDir[tableIndex].compLen); - sourceOffset = READ32BE(woffDir[tableIndex].offset); - - if (compLen < origLen) { - uLongf destLen = origLen; - if (uncompress((Bytef *)(buffer), &destLen, - (const Bytef *)(woffData + sourceOffset), - compLen) != Z_OK || destLen != origLen) { - FAIL(eWOFF_compression_failure); - } - } else { - memcpy(buffer, woffData + sourceOffset, origLen); - } - - if (pTableLen) { - *pTableLen = origLen; - } - - return; - } - - status = eWOFF_warn_no_such_table; - -failure: - if (pStatus) { - *pStatus = status; - } -} - - -#ifndef WOFF_MOZILLA_CLIENT - -const uint8_t * -woffGetMetadata(const uint8_t * woffData, uint32_t woffLen, - uint32_t * metaLen, uint32_t * pStatus) -{ - const woffHeader * header; - uint32_t offset, compLen; - uLong origLen; - uint8_t * data = NULL; - uint32_t status = eWOFF_ok; - - if (pStatus && WOFF_FAILURE(*pStatus)) { - return NULL; - } - - status = sanityCheck(woffData, woffLen); - if (WOFF_FAILURE(status)) { - FAIL(status); - } - - header = (const woffHeader *) (woffData); - - offset = READ32BE(header->metaOffset); - compLen = READ32BE(header->metaCompLen); - origLen = READ32BE(header->metaOrigLen); - if (offset == 0 || compLen == 0 || origLen == 0) { - return NULL; - } - - if (compLen > woffLen || offset > woffLen - compLen) { - FAIL(eWOFF_invalid); - } - - data = malloc(origLen); - if (!data) { - FAIL(eWOFF_out_of_memory); - } - - if (uncompress((Bytef *)data, &origLen, - (const Bytef *)woffData + offset, compLen) != Z_OK || - origLen != READ32BE(header->metaOrigLen)) { - FAIL(eWOFF_compression_failure); - } - - if (metaLen) { - *metaLen = origLen; - } - if (pStatus) { - *pStatus |= status; - } - return data; - -failure: - if (data) { - free(data); - } - if (pStatus) { - *pStatus = status; - } - return NULL; -} - -const uint8_t * -woffGetPrivateData(const uint8_t * woffData, uint32_t woffLen, - uint32_t * privLen, uint32_t * pStatus) -{ - const woffHeader * header; - uint32_t offset, length; - uint8_t * data = NULL; - uint32_t status = eWOFF_ok; - - if (pStatus && WOFF_FAILURE(*pStatus)) { - return NULL; - } - - status = sanityCheck(woffData, woffLen); - if (WOFF_FAILURE(status)) { - FAIL(status); - } - - header = (const woffHeader *) (woffData); - - offset = READ32BE(header->privOffset); - length = READ32BE(header->privLen); - if (offset == 0 || length == 0) { - return NULL; - } - - if (length > woffLen || offset > woffLen - length) { - FAIL(eWOFF_invalid); - } - - data = malloc(length); - if (!data) { - FAIL(eWOFF_out_of_memory); - } - - memcpy(data, woffData + offset, length); - - if (privLen) { - *privLen = length; - } - if (pStatus) { - *pStatus |= status; - } - return data; - -failure: - if (data) { - free(data); - } - if (pStatus) { - *pStatus = status; - } - return NULL; -} - -void -woffGetFontVersion(const uint8_t * woffData, uint32_t woffLen, - uint16_t * major, uint16_t * minor, uint32_t * pStatus) -{ - const woffHeader * header; - uint32_t status = eWOFF_ok; - - if (pStatus && WOFF_FAILURE(*pStatus)) { - return; - } - - status = sanityCheck(woffData, woffLen); - if (WOFF_FAILURE(status)) { - FAIL(status); - } - - if (!major || !minor) { - FAIL(eWOFF_bad_parameter); - } - - *major = *minor = 0; - - header = (const woffHeader *) (woffData); - - *major = READ16BE(header->majorVersion); - *minor = READ16BE(header->minorVersion); - -failure: - if (pStatus) { - *pStatus = status; - } -} - -/* utility to print messages corresponding to WOFF encoder/decoder errors */ -void -woffPrintStatus(FILE * f, uint32_t status, const char * prefix) -{ - if (!prefix) { - prefix = ""; - } - if (WOFF_WARNING(status)) { - const char * template = "%sWOFF warning: %s\n"; - if (status & eWOFF_warn_unknown_version) { - fprintf(f, template, prefix, "unrecognized sfnt version"); - } - if (status & eWOFF_warn_checksum_mismatch) { - fprintf(f, template, prefix, "checksum mismatch (corrected)"); - } - if (status & eWOFF_warn_misaligned_table) { - fprintf(f, template, prefix, "misaligned font table"); - } - if (status & eWOFF_warn_trailing_data) { - fprintf(f, template, prefix, "extraneous input data discarded"); - } - if (status & eWOFF_warn_unpadded_table) { - fprintf(f, template, prefix, "final table not correctly padded"); - } - if (status & eWOFF_warn_removed_DSIG) { - fprintf(f, template, prefix, "digital signature (DSIG) table removed"); - } - } - if (WOFF_FAILURE(status)) { - const char * template = "%sWOFF error: %s\n"; - const char * msg; - switch (status & 0xff) { - case eWOFF_out_of_memory: - msg = "memory allocation failure"; - break; - case eWOFF_invalid: - msg = "invalid input font"; - break; - case eWOFF_compression_failure: - msg = "zlib compression/decompression failure"; - break; - case eWOFF_bad_signature: - msg = "incorrect WOFF file signature"; - break; - case eWOFF_buffer_too_small: - msg = "buffer too small"; - break; - case eWOFF_bad_parameter: - msg = "bad parameter to WOFF function"; - break; - case eWOFF_illegal_order: - msg = "incorrect table directory order"; - break; - default: - msg = "unknown internal error"; - break; - } - fprintf(f, template, prefix, msg); - } -} - -#endif /* not WOFF_MOZILLA_CLIENT */ diff --git a/gfx/thebes/woff.h b/gfx/thebes/woff.h deleted file mode 100644 index 56eb89349e6..00000000000 --- a/gfx/thebes/woff.h +++ /dev/null @@ -1,187 +0,0 @@ -/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#ifndef WOFF_H_ -#define WOFF_H_ - -/* API for the WOFF encoder and decoder */ - -#include "mozilla/StandardInteger.h" - -#include /* only for FILE, needed for woffPrintStatus */ - -/* error codes returned in the status parameter of WOFF functions */ -enum { - /* Success */ - eWOFF_ok = 0, - - /* Errors: no valid result returned */ - eWOFF_out_of_memory = 1, /* malloc or realloc failed */ - eWOFF_invalid = 2, /* invalid input file (e.g., bad offset) */ - eWOFF_compression_failure = 3, /* error in zlib call */ - eWOFF_bad_signature = 4, /* unrecognized file signature */ - eWOFF_buffer_too_small = 5, /* the provided buffer is too small */ - eWOFF_bad_parameter = 6, /* bad parameter (e.g., null source ptr) */ - eWOFF_illegal_order = 7, /* improperly ordered chunks in WOFF font */ - - /* Warnings: call succeeded but something odd was noticed. - Multiple warnings may be OR'd together. */ - eWOFF_warn_unknown_version = 0x0100, /* unrecognized version of sfnt, - not standard TrueType or CFF */ - eWOFF_warn_checksum_mismatch = 0x0200, /* bad checksum, use with caution; - any DSIG will be invalid */ - eWOFF_warn_misaligned_table = 0x0400, /* table not long-aligned; fixing, - but DSIG will be invalid */ - eWOFF_warn_trailing_data = 0x0800, /* trailing junk discarded, - any DSIG may be invalid */ - eWOFF_warn_unpadded_table = 0x1000, /* sfnt not correctly padded, - any DSIG may be invalid */ - eWOFF_warn_removed_DSIG = 0x2000, /* removed digital signature - while fixing checksum errors */ - eWOFF_warn_no_such_table = 0x4000 /* specified table not present */ -}; - -/* Note: status parameters must be initialized to eWOFF_ok before calling - WOFF functions. If the status parameter contains an error code, - functions will return immediately. */ - -#define WOFF_SUCCESS(status) (((uint32_t)(status) & 0xff) == eWOFF_ok) -#define WOFF_FAILURE(status) (!WOFF_SUCCESS(status)) -#define WOFF_WARNING(status) ((uint32_t)(status) & ~0xff) - -#ifdef __cplusplus -extern "C" { -#endif - -#ifndef WOFF_DISABLE_ENCODING - -/***************************************************************************** - * Returns a new malloc() block containing the encoded data, or NULL on error; - * caller should free() this when finished with it. - * Returns length of the encoded data in woffLen. - * The new WOFF has no metadata or private block; - * see the following functions to update these elements. - */ -const uint8_t * woffEncode(const uint8_t * sfntData, uint32_t sfntLen, - uint16_t majorVersion, uint16_t minorVersion, - uint32_t * woffLen, uint32_t * status); - - -/***************************************************************************** - * Add the given metadata block to the WOFF font, replacing any existing - * metadata block. The block will be zlib-compressed. - * Metadata is required to be valid XML (use of UTF-8 is recommended), - * though this function does not currently check this. - * The woffData pointer must be a malloc() block (typically from woffEncode); - * it will be freed by this function and a new malloc() block will be returned. - * Returns NULL if an error occurs, in which case the original WOFF is NOT freed. - */ -const uint8_t * woffSetMetadata(const uint8_t * woffData, uint32_t * woffLen, - const uint8_t * metaData, uint32_t metaLen, - uint32_t * status); - - -/***************************************************************************** - * Add the given private data block to the WOFF font, replacing any existing - * private block. The block will NOT be zlib-compressed. - * Private data may be any arbitrary block of bytes; it may be externally - * compressed by the client if desired. - * The woffData pointer must be a malloc() block (typically from woffEncode); - * it will be freed by this function and a new malloc() block will be returned. - * Returns NULL if an error occurs, in which case the original WOFF is NOT freed. - */ -const uint8_t * woffSetPrivateData(const uint8_t * woffData, uint32_t * woffLen, - const uint8_t * privData, uint32_t privLen, - uint32_t * status); - -#endif /* WOFF_DISABLE_ENCODING */ - -/***************************************************************************** - * Returns the size of buffer needed to decode the font (or zero on error). - */ -uint32_t woffGetDecodedSize(const uint8_t * woffData, uint32_t woffLen, - uint32_t * pStatus); - - -/***************************************************************************** - * Decodes WOFF font to a caller-supplied buffer of size bufferLen. - * Returns the actual size of the decoded sfnt data in pActualSfntLen - * (must be <= bufferLen, otherwise an error will be returned). - */ -void woffDecodeToBuffer(const uint8_t * woffData, uint32_t woffLen, - uint8_t * sfntData, uint32_t bufferLen, - uint32_t * pActualSfntLen, uint32_t * pStatus); - - -/***************************************************************************** - * Returns a new malloc() block containing the decoded data, or NULL on error; - * caller should free() this when finished with it. - * Returns length of the decoded data in sfntLen. - */ -const uint8_t * woffDecode(const uint8_t * woffData, uint32_t woffLen, - uint32_t * sfntLen, uint32_t * status); - - -/***************************************************************************** - * Returns the size of buffer needed for a specific table (or zero on error). - */ -uint32_t woffGetTableSize(const uint8_t * woffData, uint32_t woffLen, - uint32_t tag, uint32_t * pStatus); - - -/***************************************************************************** - * Gets a table from a WOFF font to a caller-supplied buffer of size bufferLen. - * Returns the actual size of the decoded table in pTableLen - * (must be <= bufferLen, otherwise an error will be returned). - */ -void woffGetTableToBuffer(const uint8_t * woffData, uint32_t woffLen, - uint32_t tag, uint8_t * buffer, uint32_t bufferLen, - uint32_t * pTableLen, uint32_t * pStatus); - - -/***************************************************************************** - * Returns a new malloc() block containing the metadata from the WOFF font, - * or NULL if an error occurs or no metadata is present. - * Length of the metadata is returned in metaLen. - * The metadata is decompressed before returning. - */ -const uint8_t * woffGetMetadata(const uint8_t * woffData, uint32_t woffLen, - uint32_t * metaLen, uint32_t * status); - - -/***************************************************************************** - * Returns a new malloc() block containing the private data from the WOFF font, - * or NULL if an error occurs or no private data is present. - * Length of the private data is returned in privLen. - */ -const uint8_t * woffGetPrivateData(const uint8_t * woffData, uint32_t woffLen, - uint32_t * privLen, uint32_t * status); - - -/***************************************************************************** - * Returns the font version numbers from the WOFF font in the major and minor - * parameters. - * Check the status result to know if the function succeeded. - */ -void woffGetFontVersion(const uint8_t * woffData, uint32_t woffLen, - uint16_t * major, uint16_t * minor, - uint32_t * status); - - -/***************************************************************************** - * Utility to print warning and/or error status to the specified FILE*. - * The prefix string will be prepended to each line (ok to pass NULL if no - * prefix is wanted). - * (Provides terse English messages only, not intended for end-user display; - * user-friendly tools should map the status codes to their own messages.) - */ -void woffPrintStatus(FILE * f, uint32_t status, const char * prefix); - - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/modules/libpref/src/init/all.js b/modules/libpref/src/init/all.js index e7c63fdb3e4..f14cb47f943 100644 --- a/modules/libpref/src/init/all.js +++ b/modules/libpref/src/init/all.js @@ -211,7 +211,6 @@ pref("gfx.color_management.enablev4", false); pref("gfx.downloadable_fonts.enabled", true); pref("gfx.downloadable_fonts.fallback_delay", 3000); -pref("gfx.downloadable_fonts.sanitize", true); pref("gfx.filter.nearest.force-enabled", false);