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

Side by Side Diff: content/child/dwrite_font_proxy/dwrite_font_proxy_win.cc

Issue 1378353006: Implementation of dwrite font proxy and removal of dwrite font cache (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rename locals to match style guide Created 5 years, 1 month 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
(Empty)
1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "content/child/dwrite_font_proxy/dwrite_font_proxy_win.h"
6
7 #include <utility>
8
9 #include "base/logging.h"
10 #include "base/metrics/histogram_macros.h"
11 #include "base/strings/utf_string_conversions.h"
12 #include "base/win/scoped_handle.h"
13 #include "content/child/dwrite_font_proxy/dwrite_localized_strings_win.h"
14 #include "content/common/dwrite_font_proxy_messages.h"
15 #include "ipc/ipc_sender.h"
16
17 namespace content {
18
19 // This enum is used to define the buckets for an enumerated UMA histogram.
20 // Hence,
21 // (a) existing enumerated constants should never be deleted or reordered, and
22 // (b) new constants should only be appended at the end of the enumeration.
23 enum DWriteLoadFamilyResult {
24 LOAD_FAMILY_SUCCESS_SINGLE_FAMILY = 0,
25 LOAD_FAMILY_SUCCESS_MATCHED_FAMILY = 1,
26 LOAD_FAMILY_ERROR_MULTIPLE_FAMILIES = 2,
27 LOAD_FAMILY_ERROR_NO_FAMILIES = 3,
28 LOAD_FAMILY_ERROR_NO_COLLECTION = 4,
29
30 LOAD_FAMILY_MAX_VALUE
31 };
32
33 HRESULT DWriteFontCollectionProxy::FindFamilyName(const WCHAR* familyName,
34 UINT32* index,
35 BOOL* exists) {
36 DCHECK(familyName != nullptr);
37 DCHECK(index != nullptr);
38 DCHECK(exists != nullptr);
39 TRACE_EVENT0("dwrite", "FontProxy::FindFamilyName");
40
41 uint32 family_index = 0;
42 base::string16 name;
43 base::WideToUTF16(familyName, wcslen(familyName), &name);
44
45 auto iter = family_names_.find(name);
46 if (iter != family_names_.end()) {
47 *index = iter->second;
48 *exists = iter->second != UINT_MAX;
49 return S_OK;
50 }
51
52 if (!sender_.Run()->Send(
53 new DWriteFontProxyMsg_FindFamily(name, &family_index))) {
54 return E_FAIL;
55 }
56
57 if (family_index != UINT32_MAX) {
58 if (!CreateFamily(family_index))
59 return E_FAIL;
60 *exists = TRUE;
61 *index = family_index;
62 families_[family_index]->SetName(name);
63 } else {
64 *exists = FALSE;
65 *index = UINT32_MAX;
66 }
67
68 family_names_[name] = *index;
69 return S_OK;
70 }
71
72 HRESULT DWriteFontCollectionProxy::GetFontFamily(
73 UINT32 index,
74 IDWriteFontFamily** fontFamily) {
75 DCHECK(fontFamily != nullptr);
76
77 if (index < families_.size() && families_[index] != nullptr) {
78 families_[index].CopyTo(fontFamily);
79 return S_OK;
80 }
81
82 if (!CreateFamily(index))
83 return E_FAIL;
84
85 families_[index].CopyTo(fontFamily);
86 return S_OK;
87 }
88
89 UINT32 DWriteFontCollectionProxy::GetFontFamilyCount() {
90 if (family_count_ != UINT_MAX)
91 return family_count_;
92
93 TRACE_EVENT0("dwrite", "FontProxy::GetFontFamilyCount");
94
95 uint32 family_count = 0;
96 if (!sender_.Run()->Send(
97 new DWriteFontProxyMsg_GetFamilyCount(&family_count))) {
98 return 0;
99 }
100 family_count_ = family_count;
101 return family_count;
102 }
103
104 HRESULT DWriteFontCollectionProxy::GetFontFromFontFace(
105 IDWriteFontFace* fontFace,
106 IDWriteFont** font) {
107 DCHECK(fontFace != nullptr);
108 DCHECK(font != nullptr);
109
110 for (auto& family : families_) {
111 if (family != nullptr && family->GetFontFromFontFace(fontFace, font))
112 return S_OK;
113 }
114 return E_FAIL;
115 }
116
117 HRESULT DWriteFontCollectionProxy::CreateEnumeratorFromKey(
118 IDWriteFactory* factory,
119 const void* collectionKey,
120 UINT32 collectionKeySize,
121 IDWriteFontFileEnumerator** fontFileEnumerator) {
122 if (collectionKey == nullptr || collectionKeySize != sizeof(uint32)) {
123 return E_INVALIDARG;
124 }
125
126 TRACE_EVENT0("dwrite", "FontProxy::LoadingFontFiles");
127
128 const uint32* family_index = reinterpret_cast<const uint32*>(collectionKey);
129
130 if (*family_index >= GetFontFamilyCount()) {
131 return E_INVALIDARG;
132 }
133
134 // If we already loaded the family we should reuse the existing collection.
135 DCHECK(!families_[*family_index]->IsLoaded());
136
137 std::vector<base::string16> file_names;
138 if (!sender_.Run()->Send(
139 new DWriteFontProxyMsg_GetFontFiles(*family_index, &file_names))) {
140 return E_FAIL;
141 }
142
143 HRESULT hr = mswr::MakeAndInitialize<FontFileEnumerator>(
144 fontFileEnumerator, factory, this, &file_names);
145
146 if (!SUCCEEDED(hr))
147 return E_FAIL;
148
149 return S_OK;
150 }
151
152 HRESULT DWriteFontCollectionProxy::CreateStreamFromKey(
153 const void* fontFileReferenceKey,
154 uint32 fontFileReferenceKeySize,
155 IDWriteFontFileStream** fontFileStream) {
156 if (fontFileReferenceKey == nullptr)
157 return E_FAIL;
158
159 const base::char16* file_name =
160 reinterpret_cast<const base::char16*>(fontFileReferenceKey);
161 DCHECK_EQ(fontFileReferenceKeySize % sizeof(base::char16), 0u);
162 uint32 file_name_length = fontFileReferenceKeySize / sizeof(base::char16);
163 file_name_length--; // Don't count the terminating null.
164
165 if (file_name[file_name_length] != L'\0')
166 return E_FAIL;
167
168 TRACE_EVENT0("dwrite", "FontFileEnumerator::CreateStreamFromKey");
169
170 mswr::ComPtr<IDWriteFontFileStream> stream;
171 if (!SUCCEEDED(mswr::MakeAndInitialize<FontFileStream>(&stream, file_name)))
172 return E_FAIL;
173 *fontFileStream = stream.Detach();
174 return S_OK;
175 }
176
177 HRESULT DWriteFontCollectionProxy::RuntimeClassInitialize(
178 IDWriteFactory* factory,
179 const base::Callback<IPC::Sender*(void)>& sender) {
180 DCHECK(factory != nullptr);
181
182 factory_ = factory;
183 sender_ = sender;
184
185 HRESULT hr = factory->RegisterFontCollectionLoader(this);
186 DCHECK(SUCCEEDED(hr));
187 hr = factory_->RegisterFontFileLoader(this);
188 DCHECK(SUCCEEDED(hr));
189 return S_OK;
190 }
191
192 void DWriteFontCollectionProxy::Unregister() {
193 factory_->UnregisterFontCollectionLoader(this);
194 factory_->UnregisterFontFileLoader(this);
195 }
196
197 bool DWriteFontCollectionProxy::LoadFamily(
198 unsigned int family_index,
199 IDWriteFontCollection** containing_collection) {
200 TRACE_EVENT0("dwrite", "FontProxy::LoadFamily");
201
202 uint32 index = family_index;
203 HRESULT hr = factory_->CreateCustomFontCollection(
204 this /*collectonLoader*/, reinterpret_cast<const void*>(&index),
205 sizeof(index), containing_collection);
206
207 return SUCCEEDED(hr);
208 }
209
210 bool DWriteFontCollectionProxy::LoadFamilyNames(
211 unsigned int family_index,
212 IDWriteLocalizedStrings** localized_strings) {
213 TRACE_EVENT0("dwrite", "FontProxy::LoadFamilyNames");
214
215 std::vector<std::pair<base::string16, base::string16>> strings;
216 if (!sender_.Run()->Send(
217 new DWriteFontProxyMsg_GetFamilyNames(family_index, &strings))) {
218 return false;
219 }
220
221 HRESULT hr = mswr::MakeAndInitialize<DWriteLocalizedStrings>(
222 localized_strings, &strings);
223
224 return SUCCEEDED(hr);
225 }
226
227 bool DWriteFontCollectionProxy::CreateFamily(unsigned int family_index) {
228 if (family_index < families_.size() && families_[family_index] != nullptr)
229 return true;
230
231 uint32 family_count = GetFontFamilyCount();
232 if (family_index >= family_count)
233 return false;
234
235 if (families_.size() < family_count)
236 families_.resize(family_count);
237
238 mswr::ComPtr<DWriteFontFamilyProxy> family;
239 HRESULT hr = mswr::MakeAndInitialize<DWriteFontFamilyProxy>(&family, this,
240 family_index);
241 DCHECK(SUCCEEDED(hr));
242 DCHECK(family_index < families_.size());
243
244 families_[family_index] = family;
245 return true;
246 }
247
248 HRESULT DWriteFontFamilyProxy::GetFontCollection(
249 IDWriteFontCollection** fontCollection) {
250 DCHECK(fontCollection != nullptr);
251
252 proxy_collection_.CopyTo(fontCollection);
253 return S_OK;
254 }
255
256 UINT32 DWriteFontFamilyProxy::GetFontCount() {
257 // We could conceivably proxy just the font count. However, calling
258 // GetFontCount is almost certain to be followed by a series of GetFont
259 // calls which will need to load all the fonts anyway, so we might as
260 // well save an IPC here.
261 if (!LoadFamily())
262 return 0;
263
264 return family_->GetFontCount();
265 }
266
267 HRESULT DWriteFontFamilyProxy::GetFont(UINT32 index, IDWriteFont** font) {
268 DCHECK(font != nullptr);
269
270 if (index >= GetFontCount()) {
271 return E_INVALIDARG;
272 }
273 if (!LoadFamily()) {
274 return E_FAIL;
275 }
276
277 return family_->GetFont(index, font);
278 }
279
280 HRESULT DWriteFontFamilyProxy::GetFamilyNames(IDWriteLocalizedStrings** names) {
281 DCHECK(names != nullptr);
282
283 // Prefer the real thing, if available.
284 if (family_ != nullptr) {
285 family_names_ = nullptr; // Release cached data.
286 return family_->GetFamilyNames(names);
287 }
288
289 // If already cached, use the cache.
290 if (family_names_ != nullptr) {
291 family_names_.CopyTo(names);
292 return S_OK;
293 }
294
295 TRACE_EVENT0("dwrite", "FontProxy::GetFamilyNames");
296
297 // Otherwise, do the IPC.
298 if (!proxy_collection_->LoadFamilyNames(family_index_, &family_names_)) {
299 return E_FAIL;
300 }
301
302 family_names_.CopyTo(names);
303 return S_OK;
304 }
305
306 HRESULT DWriteFontFamilyProxy::GetFirstMatchingFont(
307 DWRITE_FONT_WEIGHT weight,
308 DWRITE_FONT_STRETCH stretch,
309 DWRITE_FONT_STYLE style,
310 IDWriteFont** matchingFont) {
311 DCHECK(matchingFont != nullptr);
312
313 if (!LoadFamily()) {
314 return E_FAIL;
315 }
316
317 return family_->GetFirstMatchingFont(weight, stretch, style, matchingFont);
318 }
319
320 HRESULT DWriteFontFamilyProxy::GetMatchingFonts(
321 DWRITE_FONT_WEIGHT weight,
322 DWRITE_FONT_STRETCH stretch,
323 DWRITE_FONT_STYLE style,
324 IDWriteFontList** matchingFonts) {
325 DCHECK(matchingFonts != nullptr);
326
327 if (!LoadFamily()) {
328 return E_FAIL;
329 }
330
331 return family_->GetMatchingFonts(weight, stretch, style, matchingFonts);
332 }
333
334 HRESULT DWriteFontFamilyProxy::RuntimeClassInitialize(
335 DWriteFontCollectionProxy* collection,
336 unsigned int index) {
337 DCHECK(collection != nullptr);
338
339 proxy_collection_ = collection;
340 family_index_ = index;
341 return S_OK;
342 }
343
344 bool DWriteFontFamilyProxy::GetFontFromFontFace(IDWriteFontFace* font_face,
345 IDWriteFont** font) {
346 DCHECK(font_face != nullptr);
347 DCHECK(font != nullptr);
348
349 if (family_ == nullptr)
350 return false;
351
352 mswr::ComPtr<IDWriteFontCollection> collection;
353 HRESULT hr = family_->GetFontCollection(&collection);
354 DCHECK(SUCCEEDED(hr));
355 hr = collection->GetFontFromFontFace(font_face, font);
356
357 return SUCCEEDED(hr);
358 }
359
360 bool DWriteFontFamilyProxy::LoadFamily() {
361 if (family_ != nullptr)
362 return true;
363
364 mswr::ComPtr<IDWriteFontCollection> collection;
365 if (!proxy_collection_->LoadFamily(family_index_, &collection)) {
366 UMA_HISTOGRAM_ENUMERATION("DWriteFontProxy.LoadFamily",
367 LOAD_FAMILY_ERROR_NO_COLLECTION,
368 LOAD_FAMILY_MAX_VALUE);
369 return false;
370 }
371
372 UINT32 family_count = collection->GetFontFamilyCount();
373
374 HRESULT hr;
375 if (family_count > 1) {
376 // Some fonts are packaged in a single file containing multiple families. In
377 // such a case we can find the right family by family name.
378 DCHECK(!family_name_.empty());
379 uint32 family_index = 0;
380 BOOL found = FALSE;
381 hr =
382 collection->FindFamilyName(family_name_.c_str(), &family_index, &found);
383 if (SUCCEEDED(hr) && found) {
384 hr = collection->GetFontFamily(family_index, &family_);
385 UMA_HISTOGRAM_ENUMERATION("DWriteFontProxy.LoadFamily",
386 LOAD_FAMILY_SUCCESS_MATCHED_FAMILY,
387 LOAD_FAMILY_MAX_VALUE);
388 return SUCCEEDED(hr);
389 }
390 }
391
392 DCHECK(family_count <= 1);
393
394 if (family_count == 0) {
395 // This is really strange, we successfully loaded no fonts?!
396 UMA_HISTOGRAM_ENUMERATION("DWriteFontProxy.LoadFamily",
397 LOAD_FAMILY_ERROR_NO_FAMILIES,
398 LOAD_FAMILY_MAX_VALUE);
399 return false;
400 }
401
402 UMA_HISTOGRAM_ENUMERATION("DWriteFontProxy.LoadFamily",
403 family_count == 1
404 ? LOAD_FAMILY_SUCCESS_SINGLE_FAMILY
405 : LOAD_FAMILY_ERROR_MULTIPLE_FAMILIES,
406 LOAD_FAMILY_MAX_VALUE);
407
408 hr = collection->GetFontFamily(0, &family_);
409
410 return SUCCEEDED(hr);
411 }
412
413 HRESULT FontFileEnumerator::GetCurrentFontFile(IDWriteFontFile** file) {
414 DCHECK(file != nullptr);
415 if (current_file_ >= file_names_.size()) {
416 return E_FAIL;
417 }
418
419 TRACE_EVENT0("dwrite", "FontFileEnumerator::GetCurrentFontFile (memmap)");
420 return factory_->CreateCustomFontFileReference(
421 reinterpret_cast<const void*>(file_names_[current_file_].c_str()),
422 (file_names_[current_file_].size() + 1) * sizeof(base::char16),
423 loader_.Get() /*IDWriteFontFileLoader*/, file);
424 }
425
426 HRESULT FontFileEnumerator::MoveNext(BOOL* hasCurrentFile) {
427 DCHECK(hasCurrentFile);
428
429 TRACE_EVENT0("dwrite", "FontFileEnumerator::MoveNext");
430 if (next_file_ >= file_names_.size()) {
431 *hasCurrentFile = FALSE;
432 current_file_ = UINT_MAX;
433 return S_OK;
434 }
435
436 current_file_ = next_file_;
437 next_file_++;
438 *hasCurrentFile = TRUE;
439 return S_OK;
440 }
441
442 HRESULT FontFileEnumerator::RuntimeClassInitialize(
443 IDWriteFactory* factory,
444 IDWriteFontFileLoader* loader,
445 std::vector<base::string16>* file_names) {
446 factory_ = factory;
447 loader_ = loader;
448 file_names_.swap(*file_names);
449 file_streams_.resize(file_names_.size());
450 return S_OK;
451 }
452
453 HRESULT FontFileStream::GetFileSize(UINT64* fileSize) {
454 *fileSize = data_.length();
455 return S_OK;
456 }
457 HRESULT FontFileStream::GetLastWriteTime(UINT64* lastWriteTime) {
458 return S_OK;
459 }
460 HRESULT FontFileStream::ReadFileFragment(const void** fragmentStart,
461 UINT64 fileOffset,
462 UINT64 fragmentSize,
463 void** fragmentContext) {
464 if (fileOffset + fragmentSize < fileOffset)
465 return E_FAIL;
466 if (fileOffset + fragmentSize > data_.length())
467 return E_FAIL;
468 *fragmentStart = data_.data() + fileOffset;
469 *fragmentContext = nullptr;
470 return S_OK;
471 }
472 HRESULT FontFileStream::RuntimeClassInitialize(const base::string16& fileName) {
473 data_.Initialize(base::FilePath(fileName));
474 if (!data_.IsValid())
475 return E_FAIL;
476 return S_OK;
477 }
478
479 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698