bug 467669 - pt 5 - expose WOFF metadata (if present) for downloaded fonts. r=roc

--HG--
extra : rebase_source : 91e7f231b281e1949997996d7308aceb4935247b
This commit is contained in:
Jonathan Kew 2011-06-15 20:17:52 +01:00
parent 42b0ff4b45
commit 08274c4304
2 changed files with 89 additions and 8 deletions

View File

@ -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 {

View File

@ -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;
}