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

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

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

Powered by Google App Engine
This is Rietveld 408576698