Bug 465452 - better handling of format hints for downloadable fonts. r=dbaron.
authorJohn Daggett <jdaggett@mozilla.com>
Tue, 13 Jan 2009 14:16:58 +0900
changeset 23576 2bed74c80db848d374d81143721aebbbb029e67d
parent 23575 526ceb7dd261f289380c4ff0d8065fff9bc21093
child 23577 cfcb51bdb85201f86cbf94cca5c87151499ddecc
push id4617
push userjdaggett@mozilla.com
push dateTue, 13 Jan 2009 05:17:14 +0000
treeherdermozilla-central@2bed74c80db8 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdbaron
bugs465452
milestone1.9.2a1pre
Bug 465452 - better handling of format hints for downloadable fonts. r=dbaron.
gfx/thebes/public/gfxUserFontSet.h
gfx/thebes/src/gfxPlatformGtk.cpp
gfx/thebes/src/gfxPlatformMac.cpp
gfx/thebes/src/gfxUserFontSet.cpp
gfx/thebes/src/gfxWindowsPlatform.cpp
layout/base/nsPresContext.cpp
layout/reftests/font-face/reftest.list
layout/reftests/font-face/src-list-format-7.html
--- a/gfx/thebes/public/gfxUserFontSet.h
+++ b/gfx/thebes/public/gfxUserFontSet.h
@@ -146,22 +146,27 @@ class THEBES_API gfxUserFontSet {
 public:
 
     THEBES_INLINE_DECL_REFCOUNTING(gfxUserFontSet)
 
     gfxUserFontSet();
     virtual ~gfxUserFontSet();
 
     enum {
-        // no flags ==> unknown
-        FLAG_FORMAT_OPENTYPE       = 1,
-        FLAG_FORMAT_TRUETYPE       = 2,
-        FLAG_FORMAT_TRUETYPE_AAT   = 4,
-        FLAG_FORMAT_EOT            = 8,
-        FLAG_FORMAT_SVG            = 16
+        // no flags ==> no hint set
+        // unknown ==> unknown format hint set
+        FLAG_FORMAT_UNKNOWN        = 1,
+        FLAG_FORMAT_OPENTYPE       = 1 << 1,
+        FLAG_FORMAT_TRUETYPE       = 1 << 2,
+        FLAG_FORMAT_TRUETYPE_AAT   = 1 << 3,
+        FLAG_FORMAT_EOT            = 1 << 4,
+        FLAG_FORMAT_SVG            = 1 << 5,
+        
+        // mask of all unused bits, update when adding new formats
+        FLAG_FORMAT_NOT_USED       = ~((1 << 6)-1)
     };
 
     enum LoadStatus {
         STATUS_LOADING = 0,
         STATUS_LOADED,
         STATUS_FORMAT_NOT_SUPPORTED,
         STATUS_ERROR,
         STATUS_END_OF_LIST
--- a/gfx/thebes/src/gfxPlatformGtk.cpp
+++ b/gfx/thebes/src/gfxPlatformGtk.cpp
@@ -303,30 +303,35 @@ gfxPlatformGtk::MakePlatformFont(const g
 
     return gfxPangoFontGroup::NewFontEntry(*aProxyEntry, aLoader,
                                            aFontData, aLength);
 }
 
 PRBool
 gfxPlatformGtk::IsFontFormatSupported(nsIURI *aFontURI, PRUint32 aFormatFlags)
 {
-    // reject based on format flags
-    if (aFormatFlags & (gfxUserFontSet::FLAG_FORMAT_EOT | gfxUserFontSet::FLAG_FORMAT_SVG)) {
+    // check for strange format flags
+    NS_ASSERTION(!(aFormatFlags & gfxUserFontSet::FLAG_FORMAT_NOT_USED),
+                 "strange font format hint set");
+
+    // accept supported formats
+    // Pango doesn't apply features from AAT TrueType extensions.
+    // Assume that if this is the only SFNT format specified,
+    // then AAT extensions are required for complex script support.
+    if (aFormatFlags & (gfxUserFontSet::FLAG_FORMAT_OPENTYPE | 
+                        gfxUserFontSet::FLAG_FORMAT_TRUETYPE)) {
+        return PR_TRUE;
+    }
+
+    // reject all other formats, known and unknown
+    if (aFormatFlags != 0) {
         return PR_FALSE;
     }
 
-    // Pango doesn't apply features from AAT TrueType extensions.
-    // Assume that if this is the only SFNT format specified,
-    // then AAT extensions are required for complex script support.
-    if ((aFormatFlags & gfxUserFontSet::FLAG_FORMAT_TRUETYPE_AAT) 
-         && !(aFormatFlags & (gfxUserFontSet::FLAG_FORMAT_OPENTYPE | gfxUserFontSet::FLAG_FORMAT_TRUETYPE))) {
-        return PR_FALSE;
-    }
-
-    // otherwise, return true
+    // no format hint set, need to look at data
     return PR_TRUE;
 }
 
 #else
 
 nsresult
 gfxPlatformGtk::GetFontList(const nsACString& aLangGroup,
                             const nsACString& aGenericFamily,
--- a/gfx/thebes/src/gfxPlatformMac.cpp
+++ b/gfx/thebes/src/gfxPlatformMac.cpp
@@ -135,24 +135,33 @@ gfxPlatformMac::MakePlatformFont(const g
                                  const PRUint8 *aFontData, PRUint32 aLength)
 {
     return gfxQuartzFontCache::SharedFontCache()->MakePlatformFont(aProxyEntry, aFontData, aLength);
 }
 
 PRBool
 gfxPlatformMac::IsFontFormatSupported(nsIURI *aFontURI, PRUint32 aFormatFlags)
 {
-    // reject based on format flags
-    if (aFormatFlags & (gfxUserFontSet::FLAG_FORMAT_EOT | gfxUserFontSet::FLAG_FORMAT_SVG)) {
+    // check for strange format flags
+    NS_ASSERTION(!(aFormatFlags & gfxUserFontSet::FLAG_FORMAT_NOT_USED),
+                 "strange font format hint set");
+
+    // accept supported formats
+    if (aFormatFlags & (gfxUserFontSet::FLAG_FORMAT_OPENTYPE | 
+                        gfxUserFontSet::FLAG_FORMAT_TRUETYPE | 
+                        gfxUserFontSet::FLAG_FORMAT_TRUETYPE_AAT)) {
+        return PR_TRUE;
+    }
+
+    // reject all other formats, known and unknown
+    if (aFormatFlags != 0) {
         return PR_FALSE;
     }
 
-    // reject based on filetype in URI
-
-    // otherwise, return true
+    // no format hint set, need to look at data
     return PR_TRUE;
 }
 
 nsresult
 gfxPlatformMac::GetFontList(const nsACString& aLangGroup,
                             const nsACString& aGenericFamily,
                             nsStringArray& aListOfFonts)
 {
--- a/gfx/thebes/src/gfxUserFontSet.cpp
+++ b/gfx/thebes/src/gfxUserFontSet.cpp
@@ -288,22 +288,22 @@ gfxUserFontSet::LoadNext(gfxProxyFontEnt
 
         // src local ==> lookup and load   
 
         if (currSrc.mIsLocal) {
             gfxFontEntry *fe =
                 gfxPlatform::GetPlatform()->LookupLocalFont(aProxyEntry,
                                                             currSrc.mLocalName);
             if (fe) {
-                aProxyEntry->mFamily->ReplaceFontEntry(aProxyEntry, fe);
                 LOG(("userfonts (%p) [src %d] loaded local: (%s) for (%s) gen: %8.8x\n", 
                      this, aProxyEntry->mSrcIndex, 
                      NS_ConvertUTF16toUTF8(currSrc.mLocalName).get(), 
                      NS_ConvertUTF16toUTF8(aProxyEntry->mFamily->Name()).get(), 
                      PRUint32(mGeneration)));
+                aProxyEntry->mFamily->ReplaceFontEntry(aProxyEntry, fe);
                 return STATUS_LOADED;
             } else {
                 LOG(("userfonts (%p) [src %d] failed local: (%s) for (%s)\n", 
                      this, aProxyEntry->mSrcIndex, 
                      NS_ConvertUTF16toUTF8(currSrc.mLocalName).get(), 
                      NS_ConvertUTF16toUTF8(aProxyEntry->mFamily->Name()).get()));            
             }
         } 
--- a/gfx/thebes/src/gfxWindowsPlatform.cpp
+++ b/gfx/thebes/src/gfxWindowsPlatform.cpp
@@ -873,32 +873,32 @@ gfxWindowsPlatform::MakePlatformFont(con
         fe->mForceGDI = PR_TRUE;
 
     return fe;
 }
 
 PRBool
 gfxWindowsPlatform::IsFontFormatSupported(nsIURI *aFontURI, PRUint32 aFormatFlags)
 {
-    // reject based on format flags
-    if (aFormatFlags & (gfxUserFontSet::FLAG_FORMAT_EOT | gfxUserFontSet::FLAG_FORMAT_SVG)) {
+    // check for strange format flags
+    NS_ASSERTION(!(aFormatFlags & gfxUserFontSet::FLAG_FORMAT_NOT_USED),
+                 "strange font format hint set");
+
+    // accept supported formats
+    if (aFormatFlags & (gfxUserFontSet::FLAG_FORMAT_OPENTYPE | 
+                        gfxUserFontSet::FLAG_FORMAT_TRUETYPE)) {
+        return PR_TRUE;
+    }
+
+    // reject all other formats, known and unknown
+    if (aFormatFlags != 0) {
         return PR_FALSE;
     }
 
-    // exclude AAT fonts on platforms other than Mac OS X, this allows
-    // fonts for complex scripts which require AAT tables to be omitted
-    // on other platforms
-    if ((aFormatFlags & gfxUserFontSet::FLAG_FORMAT_TRUETYPE_AAT) 
-         && !(aFormatFlags & (gfxUserFontSet::FLAG_FORMAT_OPENTYPE | gfxUserFontSet::FLAG_FORMAT_TRUETYPE))) {
-        return PR_FALSE;
-    }
-
-    // reject based on filetype in URI
-
-    // otherwise, return true
+    // no format hint set, need to look at data
     return PR_TRUE;
 }
 
 FontFamily *
 gfxWindowsPlatform::FindFontFamily(const nsAString& aName)
 {
     nsAutoString name(aName);
     BuildKeyNameFromFontName(name);
--- a/layout/base/nsPresContext.cpp
+++ b/layout/base/nsPresContext.cpp
@@ -1710,16 +1710,20 @@ InsertFontFaceRule(nsCSSFontFaceRule *aR
           } else if (valueString.LowerCaseEqualsASCII("truetype")) {
             face->mFormatFlags |= gfxUserFontSet::FLAG_FORMAT_TRUETYPE; 
           } else if (valueString.LowerCaseEqualsASCII("truetype-aat")) {
             face->mFormatFlags |= gfxUserFontSet::FLAG_FORMAT_TRUETYPE_AAT; 
           } else if (valueString.LowerCaseEqualsASCII("embedded-opentype")) {
             face->mFormatFlags |= gfxUserFontSet::FLAG_FORMAT_EOT;   
           } else if (valueString.LowerCaseEqualsASCII("svg")) {
             face->mFormatFlags |= gfxUserFontSet::FLAG_FORMAT_SVG;   
+          } else {
+            // unknown format specified, mark to distinguish from the 
+            // case where no format hints are specified
+            face->mFormatFlags |= gfxUserFontSet::FLAG_FORMAT_UNKNOWN;
           }
           i++;
         }
         break;
       default:
         NS_ASSERTION(unit == eCSSUnit_Local_Font || unit == eCSSUnit_URL,
                      "strange unit type in font-face src array");
         break;
--- a/layout/reftests/font-face/reftest.list
+++ b/layout/reftests/font-face/reftest.list
@@ -11,22 +11,25 @@ HTTP(..) == fallback-to-system-1.html fa
 HTTP(..) == name-override-simple-1.html name-override-simple-1-ref.html
 HTTP(..) != name-override-simple-1.html download-1-notref.html
 fails HTTP(..) == name-override-1.html name-override-1-ref.html
 HTTP(..) == multiple-descriptor-1.html multiple-descriptor-1-ref.html
 HTTP(..) != multiple-descriptor-1.html multiple-descriptor-1-notref.html
 HTTP(..) == src-list-1.html src-list-1-ref.html
 HTTP(..) == src-list-2.html src-list-2-ref.html
 fails-if(MOZ_WIDGET_TOOLKIT=="windows") HTTP(..) == src-list-2-big-otf.html src-list-2-big-ref.html # bug 470713
-fails HTTP(..) == src-list-format-1.html src-list-format-1-ref.html # bug 465452
-fails HTTP(..) == src-list-format-2.html src-list-format-2-ref.html # bug 465452
+HTTP(..) == src-list-format-1.html src-list-format-1-ref.html
+HTTP(..) == src-list-format-2.html src-list-format-2-ref.html
 HTTP(..) == src-list-format-3.html src-list-format-3-ref.html
 HTTP(..) == src-list-format-4.html src-list-format-1-ref.html
 HTTP(..) == src-list-format-5.html src-list-format-2-ref.html
-fails HTTP(..) == src-list-format-6.html src-list-format-3-ref.html # bug 465452
+HTTP(..) == src-list-format-6.html src-list-format-3-ref.html
+# assumes AAT fonts are only supported on MacOS
+skip-if(MOZ_WIDGET_TOOLKIT=="cocoa") HTTP(..) == src-list-format-7.html src-list-format-2-ref.html
+skip-if(MOZ_WIDGET_TOOLKIT!="cocoa") HTTP(..) == src-list-format-7.html src-list-format-3-ref.html
 # FIXME: The behavior here is neither mandated nor specified by the spec, but
 # it really ought to be.
 HTTP(..) == order-1.html order-1-ref.html
 fails HTTP(..) == order-2.html order-2-ref.html # bug 465414
 fails HTTP(..) == order-3.html order-3-ref.html # bug 465414
 HTTP(..) == multiple-in-family-1.html multiple-in-family-1-ref.html
 HTTP(..) == multiple-in-family-1b.html multiple-in-family-1-ref.html
 HTTP(..) != multiple-in-family-1.html multiple-in-family-1-notref.html
new file mode 100644
--- /dev/null
+++ b/layout/reftests/font-face/src-list-format-7.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
+	"http://www.w3.org/TR/html4/strict.dtd">
+<html lang="en-US">
+<head>
+	<title></title>
+	<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+	<style type="text/css">
+
+	@font-face {
+		font-family: "One";
+		src: url(../fonts/markA.ttf) format("truetype-aat"), url(../fonts/mark2A.ttf);
+	}
+
+	body { font-family: "One"; }
+
+	</style>
+</head>
+<body>
+
+<p>ABC</p>
+
+</body>
+</html>