| Index: Source/WebCore/platform/graphics/chromium/CrossProcessFontLoading.mm
|
| ===================================================================
|
| --- Source/WebCore/platform/graphics/chromium/CrossProcessFontLoading.mm (revision 92838)
|
| +++ Source/WebCore/platform/graphics/chromium/CrossProcessFontLoading.mm (working copy)
|
| @@ -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
|
|
|