Diff
Modified: branches/chromium/835/Source/WebCore/platform/chromium/PlatformBridge.h (92839 => 92840)
--- branches/chromium/835/Source/WebCore/platform/chromium/PlatformBridge.h 2011-08-11 12:40:57 UTC (rev 92839)
+++ branches/chromium/835/Source/WebCore/platform/chromium/PlatformBridge.h 2011-08-11 12:44:15 UTC (rev 92840)
@@ -151,7 +151,7 @@
static bool ensureFontLoaded(HFONT);
#endif
#if OS(DARWIN)
- static bool loadFont(NSFont* srcFont, ATSFontContainerRef* out);
+ static bool loadFont(NSFont* srcFont, ATSFontContainerRef*, uint32_t* fontID);
#elif OS(UNIX)
static void getRenderStyleForStrike(const char* family, int sizeAndStyle, FontRenderStyle* result);
static String getFontFamilyForCharacters(const UChar*, size_t numCharacters, const char* preferredLocale);
Modified: branches/chromium/835/Source/WebCore/platform/graphics/chromium/CrossProcessFontLoading.h (92839 => 92840)
--- branches/chromium/835/Source/WebCore/platform/graphics/chromium/CrossProcessFontLoading.h 2011-08-11 12:40:57 UTC (rev 92839)
+++ branches/chromium/835/Source/WebCore/platform/graphics/chromium/CrossProcessFontLoading.h 2011-08-11 12:44:15 UTC (rev 92840)
@@ -33,6 +33,7 @@
#import <wtf/RefCounted.h>
#import <wtf/RetainPtr.h>
+#import <wtf/text/WTFString.h>
typedef struct CGFont* CGFontRef;
typedef UInt32 ATSFontContainerRef;
@@ -73,7 +74,7 @@
class MemoryActivatedFont : public RefCounted<MemoryActivatedFont> {
public:
// Use to create a new object, see docs on constructor below.
- static PassRefPtr<MemoryActivatedFont> create(ATSFontContainerRef srcFontContainerRef, ATSFontContainerRef container);
+ static PassRefPtr<MemoryActivatedFont> create(uint32_t fontID, NSFont*, ATSFontContainerRef);
~MemoryActivatedFont();
// Get cached CGFontRef corresponding to the in-memory font.
@@ -87,12 +88,13 @@
// load in-process.
// container - a font container corresponding to an identical font that
// we loaded cross-process.
- MemoryActivatedFont(ATSFontContainerRef srcFontContainerRef, ATSFontContainerRef container);
+ MemoryActivatedFont(uint32_t fontID, NSFont*, ATSFontContainerRef);
ATSFontContainerRef m_fontContainer;
WTF::RetainPtr<CGFontRef> m_cgFont;
ATSFontRef m_atsFontRef;
- ATSFontContainerRef m_srcFontContainerRef;
+ uint32_t m_fontID;
+ WTF::String m_inSandboxHashKey;
};
} // namespace WebCore
Modified: branches/chromium/835/Source/WebCore/platform/graphics/chromium/CrossProcessFontLoading.mm (92839 => 92840)
--- branches/chromium/835/Source/WebCore/platform/graphics/chromium/CrossProcessFontLoading.mm 2011-08-11 12:40:57 UTC (rev 92839)
+++ branches/chromium/835/Source/WebCore/platform/graphics/chromium/CrossProcessFontLoading.mm 2011-08-11 12:44:15 UTC (rev 92840)
@@ -38,7 +38,8 @@
namespace {
-typedef HashMap<ATSFontContainerRef, MemoryActivatedFont*> FontContainerRefMemoryFontHash;
+typedef HashMap<uint32, MemoryActivatedFont*> FontContainerRefMemoryFontHash;
+typedef HashMap<WTF::String, MemoryActivatedFont*> FontNameMemoryFontHash;
// On 10.5, font loading is not blocked by the sandbox and thus there is no
// need for the cross-process font loading mechanim.
@@ -54,12 +55,52 @@
return systemVersion >= 0x1060;
}
-FontContainerRefMemoryFontHash& fontCacheBySrcFontContainerRef()
+// Caching:
+//
+// Requesting a font from the browser process is expensive and so is
+// "activating" said font. Caching of loaded fonts is complicated by the fact
+// that it's impossible to get a unique identifier for the on-disk font file
+// from inside the sandboxed renderer process.
+// This means that when loading a font we need to round-trip through the browser
+// process in order to get the unique font file identifer which we might already
+// have activated and cached.
+//
+// In order to save as much work as we can, we maintain 2 levels of caching
+// for the font data:
+// 1. A dumb cache keyed by the font name/style (information we can determine
+// from inside the sandbox).
+// 2. A smarter cache keyed by the real "unique font id".
+//
+// In order to perform a lookup in #2 we need to consult with the browser to get
+// us the lookup key. While this doesn't save us the font load, it does save
+// us font activation.
+//
+// It's important to remember that existing FontPlatformData objects are already
+// cached, so a cache miss in the code in this file isn't necessarily so bad.
+
+FontContainerRefMemoryFontHash& fontCacheByFontID()
{
- DEFINE_STATIC_LOCAL(FontContainerRefMemoryFontHash, srcFontRefCache, ());
- return srcFontRefCache;
+ DEFINE_STATIC_LOCAL(FontContainerRefMemoryFontHash, srcFontIDCache, ());
+ return srcFontIDCache;
}
+
+FontNameMemoryFontHash& fontCacheByFontName()
+{
+ DEFINE_STATIC_LOCAL(FontNameMemoryFontHash, srcFontNameCache, ());
+ return srcFontNameCache;
+}
+
+// Given a font specified by |srcFont|, use the information we can query in
+// the sandbox to construct a key which we hope will be as unique as possible
+// to the containing font file.
+WTF::String hashKeyFromNSFont(NSFont* srcFont)
+{
+ NSFontDescriptor* desc = [srcFont fontDescriptor];
+ NSFontSymbolicTraits traits = [desc symbolicTraits];
+ return WTF::String::format("%s %x", [[srcFont fontName] UTF8String], traits);
+}
+
ATSFontContainerRef fontContainerRefFromNSFont(NSFont* srcFont)
{
ATSFontRef fontRef = CTFontGetPlatformFont(toCTFontRef(srcFont), 0);
@@ -85,29 +126,39 @@
// On failure this function returns a PassRefPtr pointing to 0.
PassRefPtr<MemoryActivatedFont> loadFontFromBrowserProcess(NSFont* nsFont)
{
+ // First try to lookup in our cache with the limited information we have.
+ WTF::String hashKey = hashKeyFromNSFont(nsFont);
+ RefPtr<MemoryActivatedFont> font(fontCacheByFontName().get(hashKey));
+ if (font)
+ return font;
+
ATSFontContainerRef container;
+ uint32_t fontID;
// Send cross-process request to load font.
- if (!PlatformBridge::loadFont(nsFont, &container))
+ if (!PlatformBridge::loadFont(nsFont, &container, &fontID))
return 0;
-
- ATSFontContainerRef srcFontContainerRef = fontContainerRefFromNSFont(nsFont);
- if (!srcFontContainerRef) {
+
+ // Now that we have the fontID from the browser process, we can consult
+ // the ID cache.
+ font = fontCacheByFontID().get(fontID);
+ if (font) {
+ // We can safely discard the new container since we already have the
+ // font in our cache.
+ // FIXME: PlatformBridge::loadFont() should consult the id cache
+ // before activating the font. Then we can save this activate/deactive
+ // dance altogether.
ATSFontDeactivate(container, 0, kATSOptionFlagsDefault);
- return 0;
+ return font;
}
-
- PassRefPtr<MemoryActivatedFont> font = adoptRef(fontCacheBySrcFontContainerRef().get(srcFontContainerRef));
- if (font.get())
- return font;
- return MemoryActivatedFont::create(srcFontContainerRef, container);
+ return MemoryActivatedFont::create(fontID, nsFont, container);
}
} // namespace
-PassRefPtr<MemoryActivatedFont> MemoryActivatedFont::create(ATSFontContainerRef srcFontContainerRef, ATSFontContainerRef container)
+PassRefPtr<MemoryActivatedFont> MemoryActivatedFont::create(uint32_t fontID, NSFont* nsFont, ATSFontContainerRef container)
{
- MemoryActivatedFont* font = new MemoryActivatedFont(srcFontContainerRef, container);
+ MemoryActivatedFont* font = new MemoryActivatedFont(fontID, nsFont, container);
if (!font->cgFont()) // Object construction failed.
{
delete font;
@@ -116,10 +167,11 @@
return adoptRef(font);
}
-MemoryActivatedFont::MemoryActivatedFont(ATSFontContainerRef srcFontContainerRef, ATSFontContainerRef container)
+MemoryActivatedFont::MemoryActivatedFont(uint32_t fontID, NSFont* nsFont, ATSFontContainerRef container)
: m_fontContainer(container)
, m_atsFontRef(kATSFontRefUnspecified)
- , m_srcFontContainerRef(srcFontContainerRef)
+ , m_fontID(fontID)
+ , m_inSandboxHashKey(hashKeyFromNSFont(nsFont))
{
if (!container)
return;
@@ -139,22 +191,25 @@
// Cache CGFont representation of the font.
m_cgFont.adoptCF(CGFontCreateWithPlatformFont(&m_atsFontRef));
- if (!m_cgFont.get())
+ if (!m_cgFont)
return;
- // Add ourselves to cache.
- fontCacheBySrcFontContainerRef().add(m_srcFontContainerRef, this);
+ // Add ourselves to caches.
+ fontCacheByFontID().add(fontID, this);
+ fontCacheByFontName().add(m_inSandboxHashKey, this);
}
// Destructor - Unload font container from memory and remove ourselves
// from cache.
MemoryActivatedFont::~MemoryActivatedFont()
{
- if (m_cgFont.get()) {
+ if (m_cgFont) {
// First remove ourselves from the caches.
- ASSERT(fontCacheBySrcFontContainerRef().contains(m_srcFontContainerRef));
+ ASSERT(fontCacheByFontID().contains(m_fontID));
+ ASSERT(fontCacheByFontName().contains(m_inSandboxHashKey));
- fontCacheBySrcFontContainerRef().remove(m_srcFontContainerRef);
+ fontCacheByFontID().remove(m_fontID);
+ fontCacheByFontName().remove(m_inSandboxHashKey);
// Make sure the CGFont is destroyed before its font container.
m_cgFont.releaseRef();
@@ -192,7 +247,7 @@
// Font loading was blocked by the Sandbox.
m_inMemoryFont = loadFontFromBrowserProcess(outNSFont);
- if (m_inMemoryFont.get()) {
+ if (m_inMemoryFont) {
cgFont = m_inMemoryFont->cgFont();
// Need to add an extra retain so output semantics of this function
Modified: branches/chromium/835/Source/WebKit/chromium/public/mac/WebSandboxSupport.h (92839 => 92840)
--- branches/chromium/835/Source/WebKit/chromium/public/mac/WebSandboxSupport.h 2011-08-11 12:40:57 UTC (rev 92839)
+++ branches/chromium/835/Source/WebKit/chromium/public/mac/WebSandboxSupport.h 2011-08-11 12:44:15 UTC (rev 92840)
@@ -46,7 +46,8 @@
public:
// Given an input font - |srcFont| [which can't be loaded due to sandbox
// restrictions]. Return a font container belonging to an equivalent
- // font file that can be used to access the font.
+ // font file that can be used to access the font and a unique identifier
+ // corresponding to the on-disk font file.
//
// Note that a font container may contain multiple fonts, the caller is
// responsible for retreiving the appropriate font from the container.
@@ -55,7 +56,7 @@
// parameter and must call ATSFontDeactivate() to unload it when done.
//
// Returns: true on success, false on error.
- virtual bool loadFont(NSFont* srcFont, ATSFontContainerRef* out) = 0;
+ virtual bool loadFont(NSFont* srcFont, ATSFontContainerRef*, uint32_t* fontID) = 0;
};
} // namespace WebKit
Modified: branches/chromium/835/Source/WebKit/chromium/src/PlatformBridge.cpp (92839 => 92840)
--- branches/chromium/835/Source/WebKit/chromium/src/PlatformBridge.cpp 2011-08-11 12:40:57 UTC (rev 92839)
+++ branches/chromium/835/Source/WebKit/chromium/src/PlatformBridge.cpp 2011-08-11 12:44:15 UTC (rev 92840)
@@ -444,17 +444,18 @@
#endif
#if OS(DARWIN)
-bool PlatformBridge::loadFont(NSFont* srcFont, ATSFontContainerRef* out)
+bool PlatformBridge::loadFont(NSFont* srcFont, ATSFontContainerRef* container, uint32_t* fontID)
{
WebSandboxSupport* ss = webKitClient()->sandboxSupport();
if (ss)
- return ss->loadFont(srcFont, out);
+ return ss->loadFont(srcFont, container, fontID);
// This function should only be called in response to an error loading a
// font due to being blocked by the sandbox.
// This by definition shouldn't happen if there is no sandbox support.
ASSERT_NOT_REACHED();
- *out = 0;
+ *container = 0;
+ *fontID = 0;
return false;
}
#elif OS(UNIX)