mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-09 03:15:11 +00:00
bug 467669 - pt 5 - expose WOFF metadata (if present) for downloaded fonts. r=roc
--HG-- extra : rebase_source : 91e7f231b281e1949997996d7308aceb4935247b
This commit is contained in:
parent
42b0ff4b45
commit
08274c4304
@ -373,7 +373,8 @@ SanitizeOpenTypeData(const PRUint8* aData, PRUint32 aLength,
|
||||
}
|
||||
|
||||
static void
|
||||
StoreUserFontData(gfxFontEntry* aFontEntry, gfxProxyFontEntry* aProxy)
|
||||
StoreUserFontData(gfxFontEntry* aFontEntry, gfxProxyFontEntry* aProxy,
|
||||
nsTArray<PRUint8>* aMetadata, PRUint32 aMetaOrigLen)
|
||||
{
|
||||
if (!aFontEntry->mUserFontData) {
|
||||
aFontEntry->mUserFontData = new gfxUserFontData;
|
||||
@ -387,6 +388,54 @@ StoreUserFontData(gfxFontEntry* aFontEntry, gfxProxyFontEntry* aProxy)
|
||||
userFontData->mURI = src.mURI;
|
||||
}
|
||||
userFontData->mFormat = src.mFormatFlags;
|
||||
if (aMetadata) {
|
||||
userFontData->mMetadata.SwapElements(*aMetadata);
|
||||
userFontData->mMetaOrigLen = aMetaOrigLen;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
CopyWOFFMetadata(const PRUint8* aFontData, PRUint32 aLength,
|
||||
nsTArray<PRUint8>* aMetadata, PRUint32* aMetaOrigLen)
|
||||
{
|
||||
// This function may be called with arbitrary, unvalidated "font" data
|
||||
// from @font-face, so it needs to be careful to bounds-check, etc.,
|
||||
// before trying to read anything.
|
||||
// This just saves a copy of the compressed data block; it does NOT check
|
||||
// that the block can be successfully decompressed, or that it contains
|
||||
// well-formed/valid XML metadata.
|
||||
struct WOFFHeader {
|
||||
AutoSwap_PRUint32 signature;
|
||||
AutoSwap_PRUint32 flavor;
|
||||
AutoSwap_PRUint32 length;
|
||||
AutoSwap_PRUint16 numTables;
|
||||
AutoSwap_PRUint16 reserved;
|
||||
AutoSwap_PRUint32 totalSfntSize;
|
||||
AutoSwap_PRUint16 majorVersion;
|
||||
AutoSwap_PRUint16 minorVersion;
|
||||
AutoSwap_PRUint32 metaOffset;
|
||||
AutoSwap_PRUint32 metaCompLen;
|
||||
AutoSwap_PRUint32 metaOrigLen;
|
||||
AutoSwap_PRUint32 privOffset;
|
||||
AutoSwap_PRUint32 privLen;
|
||||
};
|
||||
if (aLength < sizeof(WOFFHeader)) {
|
||||
return;
|
||||
}
|
||||
const WOFFHeader* woff = reinterpret_cast<const WOFFHeader*>(aFontData);
|
||||
PRUint32 metaOffset = woff->metaOffset;
|
||||
PRUint32 metaCompLen = woff->metaCompLen;
|
||||
if (!metaOffset || !metaCompLen || !woff->metaOrigLen) {
|
||||
return;
|
||||
}
|
||||
if (metaOffset >= aLength || metaCompLen > aLength - metaOffset) {
|
||||
return;
|
||||
}
|
||||
if (!aMetadata->SetLength(woff->metaCompLen)) {
|
||||
return;
|
||||
}
|
||||
memcpy(aMetadata->Elements(), aFontData + metaOffset, metaCompLen);
|
||||
*aMetaOrigLen = woff->metaOrigLen;
|
||||
}
|
||||
|
||||
// This is called when a font download finishes.
|
||||
@ -401,14 +450,26 @@ gfxUserFontSet::OnLoadComplete(gfxProxyFontEntry *aProxy,
|
||||
if (NS_SUCCEEDED(aDownloadStatus)) {
|
||||
gfxFontEntry *fe = nsnull;
|
||||
|
||||
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<PRUint8> metadata;
|
||||
PRUint32 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.
|
||||
|
||||
if (gfxPlatform::GetPlatform()->SanitizeDownloadedFonts()) {
|
||||
gfxUserFontType fontType =
|
||||
gfxFontUtils::DetermineFontDataType(aFontData, aLength);
|
||||
|
||||
// Call the OTS sanitizer; this will also decode WOFF to sfnt
|
||||
// Call the OTS sanitizer; this will also decode WOFF to sfnt
|
||||
// if necessary. The original data in aFontData is left unchanged.
|
||||
PRUint32 saneLen;
|
||||
const PRUint8* saneData =
|
||||
@ -464,7 +525,7 @@ gfxUserFontSet::OnLoadComplete(gfxProxyFontEntry *aProxy,
|
||||
// newly-created font entry
|
||||
fe->mFeatureSettings.AppendElements(aProxy->mFeatureSettings);
|
||||
fe->mLanguageOverride = aProxy->mLanguageOverride;
|
||||
StoreUserFontData(fe, aProxy);
|
||||
StoreUserFontData(fe, aProxy, &metadata, metaOrigLen);
|
||||
#ifdef PR_LOGGING
|
||||
// must do this before ReplaceFontEntry() because that will
|
||||
// clear the proxy's mFamily pointer!
|
||||
@ -556,7 +617,7 @@ gfxUserFontSet::LoadNext(gfxProxyFontEntry *aProxyEntry)
|
||||
PRUint32(mGeneration)));
|
||||
fe->mFeatureSettings.AppendElements(aProxyEntry->mFeatureSettings);
|
||||
fe->mLanguageOverride = aProxyEntry->mLanguageOverride;
|
||||
StoreUserFontData(fe, aProxyEntry);
|
||||
StoreUserFontData(fe, aProxyEntry, nsnull, 0);
|
||||
ReplaceFontEntry(aProxyEntry, fe);
|
||||
return STATUS_LOADED;
|
||||
} else {
|
||||
|
@ -40,6 +40,7 @@
|
||||
#include "nsIDOMCSSFontFaceRule.h"
|
||||
#include "nsCSSRules.h"
|
||||
#include "gfxUserFontSet.h"
|
||||
#include "zlib.h"
|
||||
|
||||
nsFontFace::nsFontFace(gfxFontEntry* aFontEntry,
|
||||
PRUint8 aMatchType,
|
||||
@ -198,5 +199,24 @@ nsFontFace::GetFormat(nsAString & aFormat)
|
||||
NS_IMETHODIMP
|
||||
nsFontFace::GetMetadata(nsAString & aMetadata)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
aMetadata.Truncate();
|
||||
if (mFontEntry->IsUserFont() && !mFontEntry->IsLocalUserFont()) {
|
||||
NS_ASSERTION(mFontEntry->mUserFontData, "missing userFontData");
|
||||
const gfxUserFontData* userFontData = mFontEntry->mUserFontData;
|
||||
if (userFontData->mMetadata.Length() && userFontData->mMetaOrigLen) {
|
||||
nsCAutoString str;
|
||||
str.SetLength(userFontData->mMetaOrigLen);
|
||||
if (str.Length() == userFontData->mMetaOrigLen) {
|
||||
uLongf destLen = userFontData->mMetaOrigLen;
|
||||
if (uncompress((Bytef *)(str.BeginWriting()), &destLen,
|
||||
(const Bytef *)(userFontData->mMetadata.Elements()),
|
||||
userFontData->mMetadata.Length()) == Z_OK &&
|
||||
destLen == userFontData->mMetaOrigLen)
|
||||
{
|
||||
AppendUTF8toUTF16(str, aMetadata);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user