mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-09 03:15:11 +00:00
bug 467669 - pt 6 - provide the real font name rather than our internal identifier. r=roc
--HG-- extra : rebase_source : d548ab2be329058bde101b142607abf14dce7191
This commit is contained in:
parent
08274c4304
commit
34ebc89623
@ -260,31 +260,42 @@ FontEntry::ReadCMAP()
|
||||
// attempt this once, if errors occur leave a blank cmap
|
||||
mCmapInitialized = PR_TRUE;
|
||||
|
||||
AutoFallibleTArray<PRUint8,16384> buffer;
|
||||
nsresult rv = GetFontTable(TTAG_cmap, buffer);
|
||||
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
PRPackedBool unicodeFont;
|
||||
PRPackedBool symbolFont;
|
||||
rv = gfxFontUtils::ReadCMAP(buffer.Elements(), buffer.Length(),
|
||||
mCharacterMap, mUVSOffset,
|
||||
unicodeFont, symbolFont);
|
||||
}
|
||||
|
||||
mHasCmapTable = NS_SUCCEEDED(rv);
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult
|
||||
FontEntry::GetFontTable(PRUint32 aTableTag, FallibleTArray<PRUint8>& aBuffer)
|
||||
{
|
||||
// Ensure existence of mFTFace
|
||||
CairoFontFace();
|
||||
NS_ENSURE_TRUE(mFTFace, NS_ERROR_FAILURE);
|
||||
|
||||
FT_Error status;
|
||||
FT_ULong len = 0;
|
||||
status = FT_Load_Sfnt_Table(mFTFace, TTAG_cmap, 0, nsnull, &len);
|
||||
status = FT_Load_Sfnt_Table(mFTFace, aTableTag, 0, nsnull, &len);
|
||||
NS_ENSURE_TRUE(status == 0, NS_ERROR_FAILURE);
|
||||
NS_ENSURE_TRUE(len != 0, NS_ERROR_FAILURE);
|
||||
|
||||
AutoFallibleTArray<PRUint8,16384> buffer;
|
||||
if (!buffer.AppendElements(len)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
if (!aBuffer.SetLength(len)) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
PRUint8 *buf = buffer.Elements();
|
||||
|
||||
status = FT_Load_Sfnt_Table(mFTFace, TTAG_cmap, 0, buf, &len);
|
||||
PRUint8 *buf = aBuffer.Elements();
|
||||
status = FT_Load_Sfnt_Table(mFTFace, aTableTag, 0, buf, &len);
|
||||
NS_ENSURE_TRUE(status == 0, NS_ERROR_FAILURE);
|
||||
|
||||
PRPackedBool unicodeFont;
|
||||
PRPackedBool symbolFont;
|
||||
nsresult rv = gfxFontUtils::ReadCMAP(buf, len, mCharacterMap, mUVSOffset,
|
||||
unicodeFont, symbolFont);
|
||||
mHasCmapTable = NS_SUCCEEDED(rv);
|
||||
return rv;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
FontEntry *
|
||||
|
@ -112,6 +112,8 @@ public:
|
||||
cairo_font_face_t *CairoFontFace();
|
||||
nsresult ReadCMAP();
|
||||
|
||||
nsresult GetFontTable(PRUint32 aTableTag, FallibleTArray<PRUint8>& aBuffer);
|
||||
|
||||
FT_Face mFTFace;
|
||||
cairo_font_face_t *mFontFace;
|
||||
|
||||
|
@ -175,6 +175,21 @@ nsString gfxFontEntry::FamilyName() const
|
||||
}
|
||||
}
|
||||
|
||||
nsString
|
||||
gfxFontEntry::RealFaceName()
|
||||
{
|
||||
FallibleTArray<PRUint8> nameTable;
|
||||
nsresult rv = GetFontTable(TRUETYPE_TAG('n','a','m','e'), nameTable);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
nsAutoString name;
|
||||
rv = gfxFontUtils::GetFullNameFromTable(nameTable, name);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
return name;
|
||||
}
|
||||
}
|
||||
return Name();
|
||||
}
|
||||
|
||||
already_AddRefed<gfxFont>
|
||||
gfxFontEntry::FindOrMakeFont(const gfxFontStyle *aStyle, PRBool aNeedsBold)
|
||||
{
|
||||
|
@ -221,9 +221,14 @@ public:
|
||||
|
||||
virtual ~gfxFontEntry();
|
||||
|
||||
// unique name for the face, *not* the family
|
||||
// unique name for the face, *not* the family; not necessarily the
|
||||
// "real" or user-friendly name, may be an internal identifier
|
||||
const nsString& Name() const { return mName; }
|
||||
|
||||
// the "real" name of the face, if available from the font resource
|
||||
// (may be expensive); returns Name() if nothing better is available
|
||||
virtual nsString RealFaceName();
|
||||
|
||||
gfxFontFamily* Family() const { return mFamily; }
|
||||
|
||||
PRUint16 Weight() const { return mWeight; }
|
||||
|
@ -1434,6 +1434,80 @@ gfxFontUtils::RenameFont(const nsAString& aName, const PRUint8 *aFontData,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// This is only called after the basic validity of the downloaded sfnt
|
||||
// data has been checked, so it should never fail to find the name table
|
||||
// (though it might fail to read it, if memory isn't available);
|
||||
// other checks here are just for extra paranoia.
|
||||
nsresult
|
||||
gfxFontUtils::GetFullNameFromSFNT(const PRUint8* aFontData, PRUint32 aLength,
|
||||
nsAString& aFullName)
|
||||
{
|
||||
aFullName.AssignLiteral("(MISSING NAME)"); // should always get replaced
|
||||
|
||||
NS_ENSURE_TRUE(aLength >= sizeof(SFNTHeader), NS_ERROR_UNEXPECTED);
|
||||
const SFNTHeader *sfntHeader =
|
||||
reinterpret_cast<const SFNTHeader*>(aFontData);
|
||||
const TableDirEntry *dirEntry =
|
||||
reinterpret_cast<const TableDirEntry*>(aFontData + sizeof(SFNTHeader));
|
||||
PRUint32 numTables = sfntHeader->numTables;
|
||||
NS_ENSURE_TRUE(aLength >=
|
||||
sizeof(SFNTHeader) + numTables * sizeof(TableDirEntry),
|
||||
NS_ERROR_UNEXPECTED);
|
||||
PRBool foundName = PR_FALSE;
|
||||
for (PRUint32 i = 0; i < numTables; i++, dirEntry++) {
|
||||
if (dirEntry->tag == TRUETYPE_TAG('n','a','m','e')) {
|
||||
foundName = PR_TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// should never fail, as we're only called after font validation succeeded
|
||||
NS_ENSURE_TRUE(foundName, NS_ERROR_NOT_AVAILABLE);
|
||||
|
||||
PRUint32 len = dirEntry->length;
|
||||
NS_ENSURE_TRUE(aLength > len && aLength - len >= dirEntry->offset,
|
||||
NS_ERROR_UNEXPECTED);
|
||||
FallibleTArray<PRUint8> nameTable;
|
||||
if (!nameTable.SetLength(len)) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
memcpy(nameTable.Elements(), aFontData + dirEntry->offset, len);
|
||||
|
||||
return GetFullNameFromTable(nameTable, aFullName);
|
||||
}
|
||||
|
||||
nsresult
|
||||
gfxFontUtils::GetFullNameFromTable(FallibleTArray<PRUint8>& aNameTable,
|
||||
nsAString& aFullName)
|
||||
{
|
||||
nsAutoString name;
|
||||
nsresult rv =
|
||||
gfxFontUtils::ReadCanonicalName(aNameTable,
|
||||
gfxFontUtils::NAME_ID_FULL,
|
||||
name);
|
||||
if (NS_SUCCEEDED(rv) && !name.IsEmpty()) {
|
||||
aFullName = name;
|
||||
return NS_OK;
|
||||
}
|
||||
rv = gfxFontUtils::ReadCanonicalName(aNameTable,
|
||||
gfxFontUtils::NAME_ID_FAMILY,
|
||||
name);
|
||||
if (NS_SUCCEEDED(rv) && !name.IsEmpty()) {
|
||||
nsAutoString styleName;
|
||||
rv = gfxFontUtils::ReadCanonicalName(aNameTable,
|
||||
gfxFontUtils::NAME_ID_STYLE,
|
||||
styleName);
|
||||
if (NS_SUCCEEDED(rv) && !styleName.IsEmpty()) {
|
||||
name.AppendLiteral(" ");
|
||||
name.Append(styleName);
|
||||
aFullName = name;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
enum {
|
||||
#if defined(XP_MACOSX)
|
||||
CANONICAL_LANG_ID = gfxFontUtils::LANG_ID_MAC_ENGLISH,
|
||||
|
@ -706,10 +706,26 @@ public:
|
||||
DetermineFontDataType(const PRUint8 *aFontData, PRUint32 aFontDataLength);
|
||||
|
||||
// checks for valid SFNT table structure, returns true if valid
|
||||
// does *not* guarantee that all font data is 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 PRBool
|
||||
ValidateSFNTHeaders(const PRUint8 *aFontData, PRUint32 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,
|
||||
// so it should always succeed in finding the name table.
|
||||
static nsresult
|
||||
GetFullNameFromSFNT(const PRUint8* aFontData, PRUint32 aLength,
|
||||
nsAString& aFullName);
|
||||
|
||||
// helper to get fullname from name table
|
||||
static nsresult
|
||||
GetFullNameFromTable(FallibleTArray<PRUint8>& aNameTable,
|
||||
nsAString& aFullName);
|
||||
|
||||
// create a new name table and build a new font with that name table
|
||||
// appended on the end, returns true on success
|
||||
static nsresult
|
||||
|
@ -194,6 +194,11 @@ public:
|
||||
// gfxFcFontEntries in families; just read the name from fontconfig
|
||||
virtual nsString FamilyName() const;
|
||||
|
||||
// override the gfxFontEntry impl to read the name from fontconfig
|
||||
// instead of trying to get the 'name' table, as we don't implement
|
||||
// GetFontTable() here
|
||||
virtual nsString RealFaceName();
|
||||
|
||||
protected:
|
||||
gfxFcFontEntry(const nsAString& aName)
|
||||
: gfxFontEntry(aName),
|
||||
@ -229,6 +234,29 @@ gfxFcFontEntry::FamilyName() const
|
||||
return gfxFontEntry::FamilyName();
|
||||
}
|
||||
|
||||
nsString
|
||||
gfxFcFontEntry::RealFaceName()
|
||||
{
|
||||
FcChar8 *name;
|
||||
if (!mPatterns.IsEmpty()) {
|
||||
if (FcPatternGetString(mPatterns[0],
|
||||
FC_FULLNAME, 0, &name) == FcResultMatch) {
|
||||
return NS_ConvertUTF8toUTF16((const char*)name);
|
||||
}
|
||||
if (FcPatternGetString(mPatterns[0],
|
||||
FC_FAMILY, 0, &name) == FcResultMatch) {
|
||||
NS_ConvertUTF8toUTF16 result((const char*)name);
|
||||
if (FcPatternGetString(mPatterns[0],
|
||||
FC_STYLE, 0, &name) == FcResultMatch) {
|
||||
result.AppendLiteral(" ");
|
||||
AppendUTF8toUTF16((const char*)name, result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
return gfxFontEntry::RealFaceName();
|
||||
}
|
||||
|
||||
PRBool
|
||||
gfxFcFontEntry::ShouldUseHarfBuzz(PRInt32 aRunScript) {
|
||||
if (mSkipHarfBuzz ||
|
||||
|
@ -374,6 +374,7 @@ SanitizeOpenTypeData(const PRUint8* aData, PRUint32 aLength,
|
||||
|
||||
static void
|
||||
StoreUserFontData(gfxFontEntry* aFontEntry, gfxProxyFontEntry* aProxy,
|
||||
const nsAString& aOriginalName,
|
||||
nsTArray<PRUint8>* aMetadata, PRUint32 aMetaOrigLen)
|
||||
{
|
||||
if (!aFontEntry->mUserFontData) {
|
||||
@ -388,6 +389,7 @@ StoreUserFontData(gfxFontEntry* aFontEntry, gfxProxyFontEntry* aProxy,
|
||||
userFontData->mURI = src.mURI;
|
||||
}
|
||||
userFontData->mFormat = src.mFormatFlags;
|
||||
userFontData->mRealName = aOriginalName;
|
||||
if (aMetadata) {
|
||||
userFontData->mMetadata.SwapElements(*aMetadata);
|
||||
userFontData->mMetaOrigLen = aMetaOrigLen;
|
||||
@ -468,6 +470,11 @@ gfxUserFontSet::OnLoadComplete(gfxProxyFontEntry *aProxy,
|
||||
// Unwrap/decompress/sanitize or otherwise munge the downloaded data
|
||||
// to make a usable sfnt structure.
|
||||
|
||||
// Because platform font activation code may replace the name table
|
||||
// in the font with a synthetic one, we save the original name so that
|
||||
// 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.
|
||||
@ -484,6 +491,12 @@ gfxUserFontSet::OnLoadComplete(gfxProxyFontEntry *aProxy,
|
||||
}
|
||||
#endif
|
||||
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,
|
||||
@ -501,6 +514,10 @@ gfxUserFontSet::OnLoadComplete(gfxProxyFontEntry *aProxy,
|
||||
|
||||
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,
|
||||
@ -525,7 +542,8 @@ gfxUserFontSet::OnLoadComplete(gfxProxyFontEntry *aProxy,
|
||||
// newly-created font entry
|
||||
fe->mFeatureSettings.AppendElements(aProxy->mFeatureSettings);
|
||||
fe->mLanguageOverride = aProxy->mLanguageOverride;
|
||||
StoreUserFontData(fe, aProxy, &metadata, metaOrigLen);
|
||||
StoreUserFontData(fe, aProxy, originalFullName,
|
||||
&metadata, metaOrigLen);
|
||||
#ifdef PR_LOGGING
|
||||
// must do this before ReplaceFontEntry() because that will
|
||||
// clear the proxy's mFamily pointer!
|
||||
@ -617,7 +635,7 @@ gfxUserFontSet::LoadNext(gfxProxyFontEntry *aProxyEntry)
|
||||
PRUint32(mGeneration)));
|
||||
fe->mFeatureSettings.AppendElements(aProxyEntry->mFeatureSettings);
|
||||
fe->mLanguageOverride = aProxyEntry->mLanguageOverride;
|
||||
StoreUserFontData(fe, aProxyEntry, nsnull, 0);
|
||||
StoreUserFontData(fe, aProxyEntry, nsString(), nsnull, 0);
|
||||
ReplaceFontEntry(aProxyEntry, fe);
|
||||
return STATUS_LOADED;
|
||||
} else {
|
||||
|
@ -87,6 +87,7 @@ public:
|
||||
nsTArray<PRUint8> mMetadata; // woff metadata block (compressed), if any
|
||||
nsCOMPtr<nsIURI> mURI; // URI of the source, if it was url()
|
||||
nsString mLocalName; // font name used for the source, if local()
|
||||
nsString mRealName; // original fullname from the font resource
|
||||
PRUint32 mSrcIndex; // index in the rule's source list
|
||||
PRUint32 mFormat; // format hint for the source used, if any
|
||||
PRUint32 mMetaOrigLen; // length needed to decompress metadata
|
||||
|
@ -94,7 +94,12 @@ nsFontFace::GetFromSystemFallback(PRBool * aFromSystemFallback)
|
||||
NS_IMETHODIMP
|
||||
nsFontFace::GetName(nsAString & aName)
|
||||
{
|
||||
aName = mFontEntry->Name();
|
||||
if (mFontEntry->IsUserFont() && !mFontEntry->IsLocalUserFont()) {
|
||||
NS_ASSERTION(mFontEntry->mUserFontData, "missing userFontData");
|
||||
aName = mFontEntry->mUserFontData->mRealName;
|
||||
} else {
|
||||
aName = mFontEntry->RealFaceName();
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user