Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(165)

Side by Side Diff: Source/WebCore/platform/graphics/chromium/CrossProcessFontLoading.mm

Issue 7618010: Merge 92269 - [Chromium] Fix OOP font loading to work on 10.6.6 and above. (Closed) Base URL: http://svn.webkit.org/repository/webkit/branches/chromium/835/
Patch Set: Created 9 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * This file is part of the internal font implementation. 2 * This file is part of the internal font implementation.
3 * 3 *
4 * Copyright (c) 2010 Google Inc. All rights reserved. 4 * Copyright (c) 2010 Google Inc. All rights reserved.
5 * 5 *
6 * This library is free software; you can redistribute it and/or 6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public 7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either 8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version. 9 * version 2 of the License, or (at your option) any later version.
10 * 10 *
(...skipping 20 matching lines...) Expand all
31 31
32 #import "../graphics/FontPlatformData.h" 32 #import "../graphics/FontPlatformData.h"
33 #import "PlatformBridge.h" 33 #import "PlatformBridge.h"
34 #import <AppKit/NSFont.h> 34 #import <AppKit/NSFont.h>
35 #import <wtf/HashMap.h> 35 #import <wtf/HashMap.h>
36 36
37 namespace WebCore { 37 namespace WebCore {
38 38
39 namespace { 39 namespace {
40 40
41 typedef HashMap<ATSFontContainerRef, MemoryActivatedFont*> FontContainerRefMemor yFontHash; 41 typedef HashMap<uint32, MemoryActivatedFont*> FontContainerRefMemoryFontHash;
42 typedef HashMap<WTF::String, MemoryActivatedFont*> FontNameMemoryFontHash;
42 43
43 // On 10.5, font loading is not blocked by the sandbox and thus there is no 44 // On 10.5, font loading is not blocked by the sandbox and thus there is no
44 // need for the cross-process font loading mechanim. 45 // need for the cross-process font loading mechanim.
45 // On system versions >=10.6 cross-process font loading is required. 46 // On system versions >=10.6 cross-process font loading is required.
46 bool OutOfProcessFontLoadingEnabled() 47 bool OutOfProcessFontLoadingEnabled()
47 { 48 {
48 static SInt32 systemVersion = 0; 49 static SInt32 systemVersion = 0;
49 if (!systemVersion) { 50 if (!systemVersion) {
50 if (Gestalt(gestaltSystemVersion, &systemVersion) != noErr) 51 if (Gestalt(gestaltSystemVersion, &systemVersion) != noErr)
51 return false; 52 return false;
52 } 53 }
53 54
54 return systemVersion >= 0x1060; 55 return systemVersion >= 0x1060;
55 } 56 }
56 57
57 FontContainerRefMemoryFontHash& fontCacheBySrcFontContainerRef() 58 // Caching:
59 //
60 // Requesting a font from the browser process is expensive and so is
61 // "activating" said font. Caching of loaded fonts is complicated by the fact
62 // that it's impossible to get a unique identifier for the on-disk font file
63 // from inside the sandboxed renderer process.
64 // This means that when loading a font we need to round-trip through the browser
65 // process in order to get the unique font file identifer which we might already
66 // have activated and cached.
67 //
68 // In order to save as much work as we can, we maintain 2 levels of caching
69 // for the font data:
70 // 1. A dumb cache keyed by the font name/style (information we can determine
71 // from inside the sandbox).
72 // 2. A smarter cache keyed by the real "unique font id".
73 //
74 // In order to perform a lookup in #2 we need to consult with the browser to get
75 // us the lookup key. While this doesn't save us the font load, it does save
76 // us font activation.
77 //
78 // It's important to remember that existing FontPlatformData objects are already
79 // cached, so a cache miss in the code in this file isn't necessarily so bad.
80
81 FontContainerRefMemoryFontHash& fontCacheByFontID()
58 { 82 {
59 DEFINE_STATIC_LOCAL(FontContainerRefMemoryFontHash, srcFontRefCache, ()); 83 DEFINE_STATIC_LOCAL(FontContainerRefMemoryFontHash, srcFontIDCache, ());
60 return srcFontRefCache; 84 return srcFontIDCache;
85 }
86
87
88 FontNameMemoryFontHash& fontCacheByFontName()
89 {
90 DEFINE_STATIC_LOCAL(FontNameMemoryFontHash, srcFontNameCache, ());
91 return srcFontNameCache;
92 }
93
94 // Given a font specified by |srcFont|, use the information we can query in
95 // the sandbox to construct a key which we hope will be as unique as possible
96 // to the containing font file.
97 WTF::String hashKeyFromNSFont(NSFont* srcFont)
98 {
99 NSFontDescriptor* desc = [srcFont fontDescriptor];
100 NSFontSymbolicTraits traits = [desc symbolicTraits];
101 return WTF::String::format("%s %x", [[srcFont fontName] UTF8String], traits) ;
61 } 102 }
62 103
63 ATSFontContainerRef fontContainerRefFromNSFont(NSFont* srcFont) 104 ATSFontContainerRef fontContainerRefFromNSFont(NSFont* srcFont)
64 { 105 {
65 ATSFontRef fontRef = CTFontGetPlatformFont(toCTFontRef(srcFont), 0); 106 ATSFontRef fontRef = CTFontGetPlatformFont(toCTFontRef(srcFont), 0);
66 if (!fontRef) 107 if (!fontRef)
67 return kATSFontContainerRefUnspecified; 108 return kATSFontContainerRefUnspecified;
68 ATSFontContainerRef fontContainer = kATSFontContainerRefUnspecified; 109 ATSFontContainerRef fontContainer = kATSFontContainerRefUnspecified;
69 if (ATSFontGetContainer(fontRef, 0, &fontContainer) != noErr) 110 if (ATSFontGetContainer(fontRef, 0, &fontContainer) != noErr)
70 return kATSFontContainerRefUnspecified; 111 return kATSFontContainerRefUnspecified;
71 return fontContainer; 112 return fontContainer;
72 } 113 }
73 114
74 // The only way we can tell that an in-process font has failed to load 115 // The only way we can tell that an in-process font has failed to load
75 // is if CTFontCopyGraphicsFont() returns the LastResort font. 116 // is if CTFontCopyGraphicsFont() returns the LastResort font.
76 bool isLastResortFont(CGFontRef cgFont) 117 bool isLastResortFont(CGFontRef cgFont)
77 { 118 {
78 NSString* fontName = (NSString*)CGFontCopyPostScriptName(cgFont); 119 NSString* fontName = (NSString*)CGFontCopyPostScriptName(cgFont);
79 return [fontName isEqualToString:@"LastResort"]; 120 return [fontName isEqualToString:@"LastResort"];
80 } 121 }
81 122
82 // Given an in-process font which has failed to load, return a 123 // Given an in-process font which has failed to load, return a
83 // MemoryActivatedFont* corresponding to an in-memory representation of the 124 // MemoryActivatedFont* corresponding to an in-memory representation of the
84 // same font loaded from the browser process. 125 // same font loaded from the browser process.
85 // On failure this function returns a PassRefPtr pointing to 0. 126 // On failure this function returns a PassRefPtr pointing to 0.
86 PassRefPtr<MemoryActivatedFont> loadFontFromBrowserProcess(NSFont* nsFont) 127 PassRefPtr<MemoryActivatedFont> loadFontFromBrowserProcess(NSFont* nsFont)
87 { 128 {
88 ATSFontContainerRef container; 129 // First try to lookup in our cache with the limited information we have.
89 // Send cross-process request to load font. 130 WTF::String hashKey = hashKeyFromNSFont(nsFont);
90 if (!PlatformBridge::loadFont(nsFont, &container)) 131 RefPtr<MemoryActivatedFont> font(fontCacheByFontName().get(hashKey));
91 return 0; 132 if (font)
92
93 ATSFontContainerRef srcFontContainerRef = fontContainerRefFromNSFont(nsFont) ;
94 if (!srcFontContainerRef) {
95 ATSFontDeactivate(container, 0, kATSOptionFlagsDefault);
96 return 0;
97 }
98
99 PassRefPtr<MemoryActivatedFont> font = adoptRef(fontCacheBySrcFontContainerR ef().get(srcFontContainerRef));
100 if (font.get())
101 return font; 133 return font;
102 134
103 return MemoryActivatedFont::create(srcFontContainerRef, container); 135 ATSFontContainerRef container;
136 uint32_t fontID;
137 // Send cross-process request to load font.
138 if (!PlatformBridge::loadFont(nsFont, &container, &fontID))
139 return 0;
140
141 // Now that we have the fontID from the browser process, we can consult
142 // the ID cache.
143 font = fontCacheByFontID().get(fontID);
144 if (font) {
145 // We can safely discard the new container since we already have the
146 // font in our cache.
147 // FIXME: PlatformBridge::loadFont() should consult the id cache
148 // before activating the font. Then we can save this activate/deactive
149 // dance altogether.
150 ATSFontDeactivate(container, 0, kATSOptionFlagsDefault);
151 return font;
152 }
153
154 return MemoryActivatedFont::create(fontID, nsFont, container);
104 } 155 }
105 156
106 } // namespace 157 } // namespace
107 158
108 PassRefPtr<MemoryActivatedFont> MemoryActivatedFont::create(ATSFontContainerRef srcFontContainerRef, ATSFontContainerRef container) 159 PassRefPtr<MemoryActivatedFont> MemoryActivatedFont::create(uint32_t fontID, NSF ont* nsFont, ATSFontContainerRef container)
109 { 160 {
110 MemoryActivatedFont* font = new MemoryActivatedFont(srcFontContainerRef, conta iner); 161 MemoryActivatedFont* font = new MemoryActivatedFont(fontID, nsFont, container) ;
111 if (!font->cgFont()) // Object construction failed. 162 if (!font->cgFont()) // Object construction failed.
112 { 163 {
113 delete font; 164 delete font;
114 return 0; 165 return 0;
115 } 166 }
116 return adoptRef(font); 167 return adoptRef(font);
117 } 168 }
118 169
119 MemoryActivatedFont::MemoryActivatedFont(ATSFontContainerRef srcFontContainerRef , ATSFontContainerRef container) 170 MemoryActivatedFont::MemoryActivatedFont(uint32_t fontID, NSFont* nsFont, ATSFon tContainerRef container)
120 : m_fontContainer(container) 171 : m_fontContainer(container)
121 , m_atsFontRef(kATSFontRefUnspecified) 172 , m_atsFontRef(kATSFontRefUnspecified)
122 , m_srcFontContainerRef(srcFontContainerRef) 173 , m_fontID(fontID)
174 , m_inSandboxHashKey(hashKeyFromNSFont(nsFont))
123 { 175 {
124 if (!container) 176 if (!container)
125 return; 177 return;
126 178
127 // Count the number of fonts in the container. 179 // Count the number of fonts in the container.
128 ItemCount fontCount = 0; 180 ItemCount fontCount = 0;
129 OSStatus err = ATSFontFindFromContainer(container, kATSOptionFlagsDefault, 0 , 0, &fontCount); 181 OSStatus err = ATSFontFindFromContainer(container, kATSOptionFlagsDefault, 0 , 0, &fontCount);
130 if (err != noErr || fontCount < 1) 182 if (err != noErr || fontCount < 1)
131 return; 183 return;
132 184
133 // For now always assume that we want the first font in the container. 185 // For now always assume that we want the first font in the container.
134 ATSFontFindFromContainer(container, kATSOptionFlagsDefault, 1, &m_atsFontRef , 0); 186 ATSFontFindFromContainer(container, kATSOptionFlagsDefault, 1, &m_atsFontRef , 0);
135 187
136 if (!m_atsFontRef) 188 if (!m_atsFontRef)
137 return; 189 return;
138 190
139 // Cache CGFont representation of the font. 191 // Cache CGFont representation of the font.
140 m_cgFont.adoptCF(CGFontCreateWithPlatformFont(&m_atsFontRef)); 192 m_cgFont.adoptCF(CGFontCreateWithPlatformFont(&m_atsFontRef));
141 193
142 if (!m_cgFont.get()) 194 if (!m_cgFont)
143 return; 195 return;
144 196
145 // Add ourselves to cache. 197 // Add ourselves to caches.
146 fontCacheBySrcFontContainerRef().add(m_srcFontContainerRef, this); 198 fontCacheByFontID().add(fontID, this);
199 fontCacheByFontName().add(m_inSandboxHashKey, this);
147 } 200 }
148 201
149 // Destructor - Unload font container from memory and remove ourselves 202 // Destructor - Unload font container from memory and remove ourselves
150 // from cache. 203 // from cache.
151 MemoryActivatedFont::~MemoryActivatedFont() 204 MemoryActivatedFont::~MemoryActivatedFont()
152 { 205 {
153 if (m_cgFont.get()) { 206 if (m_cgFont) {
154 // First remove ourselves from the caches. 207 // First remove ourselves from the caches.
155 ASSERT(fontCacheBySrcFontContainerRef().contains(m_srcFontContainerRef)) ; 208 ASSERT(fontCacheByFontID().contains(m_fontID));
209 ASSERT(fontCacheByFontName().contains(m_inSandboxHashKey));
156 210
157 fontCacheBySrcFontContainerRef().remove(m_srcFontContainerRef); 211 fontCacheByFontID().remove(m_fontID);
212 fontCacheByFontName().remove(m_inSandboxHashKey);
158 213
159 // Make sure the CGFont is destroyed before its font container. 214 // Make sure the CGFont is destroyed before its font container.
160 m_cgFont.releaseRef(); 215 m_cgFont.releaseRef();
161 } 216 }
162 217
163 if (m_fontContainer != kATSFontContainerRefUnspecified) 218 if (m_fontContainer != kATSFontContainerRefUnspecified)
164 ATSFontDeactivate(m_fontContainer, 0, kATSOptionFlagsDefault); 219 ATSFontDeactivate(m_fontContainer, 0, kATSOptionFlagsDefault);
165 } 220 }
166 221
167 // Given an NSFont, try to load a representation of that font into the cgFont 222 // Given an NSFont, try to load a representation of that font into the cgFont
(...skipping 17 matching lines...) Expand all
185 { 240 {
186 outNSFont = nsFont; 241 outNSFont = nsFont;
187 cgFont = CTFontCopyGraphicsFont(toCTFontRef(outNSFont), 0); 242 cgFont = CTFontCopyGraphicsFont(toCTFontRef(outNSFont), 0);
188 if (OutOfProcessFontLoadingEnabled() && outNSFont && cgFont && isLastResortF ont(cgFont)) { 243 if (OutOfProcessFontLoadingEnabled() && outNSFont && cgFont && isLastResortF ont(cgFont)) {
189 // Release old CGFontRef since it points at the LastResort font which we don't want. 244 // Release old CGFontRef since it points at the LastResort font which we don't want.
190 CFRelease(cgFont); 245 CFRelease(cgFont);
191 cgFont = 0; 246 cgFont = 0;
192 247
193 // Font loading was blocked by the Sandbox. 248 // Font loading was blocked by the Sandbox.
194 m_inMemoryFont = loadFontFromBrowserProcess(outNSFont); 249 m_inMemoryFont = loadFontFromBrowserProcess(outNSFont);
195 if (m_inMemoryFont.get()) { 250 if (m_inMemoryFont) {
196 cgFont = m_inMemoryFont->cgFont(); 251 cgFont = m_inMemoryFont->cgFont();
197 252
198 // Need to add an extra retain so output semantics of this function 253 // Need to add an extra retain so output semantics of this function
199 // are consistent. 254 // are consistent.
200 CFRetain(cgFont); 255 CFRetain(cgFont);
201 } else { 256 } else {
202 // If we still can't load the font, then return Times, 257 // If we still can't load the font, then return Times,
203 // rather than the LastResort font. 258 // rather than the LastResort font.
204 outNSFont = [NSFont fontWithName:@"Times" size:fontSize]; 259 outNSFont = [NSFont fontWithName:@"Times" size:fontSize];
205 cgFont = CTFontCopyGraphicsFont(toCTFontRef(outNSFont), 0); 260 cgFont = CTFontCopyGraphicsFont(toCTFontRef(outNSFont), 0);
206 } 261 }
207 } 262 }
208 } 263 }
209 264
210 } // namespace WebCore 265 } // namespace WebCore
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698