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

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

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

Powered by Google App Engine
This is Rietveld 408576698