OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "content/common/dwrite_font_platform_win.h" | 5 #include "content/public/common/dwrite_font_platform_win.h" |
6 | 6 |
7 #include <dwrite.h> | 7 #include <dwrite.h> |
8 #include <map> | 8 #include <map> |
9 #include <string> | 9 #include <string> |
10 #include <utility> | 10 #include <utility> |
11 #include <vector> | 11 #include <vector> |
12 #include <wrl/implements.h> | 12 #include <wrl/implements.h> |
13 #include <wrl/wrappers/corewrappers.h> | 13 #include <wrl/wrappers/corewrappers.h> |
14 | 14 |
15 #include "base/command_line.h" | 15 #include "base/command_line.h" |
(...skipping 10 matching lines...) Expand all Loading... |
26 #include "base/path_service.h" | 26 #include "base/path_service.h" |
27 #include "base/process/process_handle.h" | 27 #include "base/process/process_handle.h" |
28 #include "base/stl_util.h" | 28 #include "base/stl_util.h" |
29 #include "base/strings/string_number_conversions.h" | 29 #include "base/strings/string_number_conversions.h" |
30 #include "base/strings/utf_string_conversions.h" | 30 #include "base/strings/utf_string_conversions.h" |
31 #include "base/synchronization/lock.h" | 31 #include "base/synchronization/lock.h" |
32 #include "base/time/time.h" | 32 #include "base/time/time.h" |
33 #include "base/win/registry.h" | 33 #include "base/win/registry.h" |
34 #include "base/win/scoped_comptr.h" | 34 #include "base/win/scoped_comptr.h" |
35 #include "content/public/common/content_switches.h" | 35 #include "content/public/common/content_switches.h" |
36 #include "content/public/common/dwrite_font_cache_win.h" | |
37 | 36 |
38 namespace { | 37 namespace { |
39 | 38 |
40 // Font Cache implementation short story: | 39 // Font Cache implementation short story: |
41 // Due to our sandboxing restrictions, we cannot connect to Windows font cache | 40 // Due to our sandboxing restrictions, we cannot connect to Windows font cache |
42 // service from Renderer and need to use DirectWrite isolated font loading | 41 // service from Renderer and need to use DirectWrite isolated font loading |
43 // mechanism. | 42 // mechanism. |
44 // DirectWrite needs to be initialized before any of the API could be used. | 43 // DirectWrite needs to be initialized before any of the API could be used. |
45 // During initialization DirectWrite loads all font files and populates | 44 // During initialization DirectWrite loads all font files and populates |
46 // internal cache, we refer this phase as enumeration and we are trying | 45 // internal cache, we refer this phase as enumeration and we are trying |
(...skipping 16 matching lines...) Expand all Loading... |
63 namespace mswr = Microsoft::WRL; | 62 namespace mswr = Microsoft::WRL; |
64 | 63 |
65 const char kFontKeyName[] = "font_key_name"; | 64 const char kFontKeyName[] = "font_key_name"; |
66 | 65 |
67 // We use this value to determine whether to cache file fragments | 66 // We use this value to determine whether to cache file fragments |
68 // or not. In our trials we observed that for some font files | 67 // or not. In our trials we observed that for some font files |
69 // direct write ends up reading almost entire file during enumeration | 68 // direct write ends up reading almost entire file during enumeration |
70 // phase. If we don't use this percentile formula we will end up | 69 // phase. If we don't use this percentile formula we will end up |
71 // increasing significant cache size by caching entire file contents | 70 // increasing significant cache size by caching entire file contents |
72 // for some of the font files. | 71 // for some of the font files. |
73 const double kMaxPercentileOfFontFileSizeToCache = 0.7; | 72 const double kMaxPercentileOfFontFileSizeToCache = 0.5; |
| 73 |
| 74 // With current implementation we map entire shared section into memory during |
| 75 // renderer startup. This causes increase in working set of Chrome. As first |
| 76 // step we want to see if caching is really improving any performance for our |
| 77 // users, so we are putting arbitrary limit on cache file size. There are |
| 78 // multiple ways we can tune our working size, like mapping only required part |
| 79 // of section at any given time. |
| 80 const double kArbitraryCacheFileSizeLimit = (20 * 1024 * 1024); |
74 | 81 |
75 // We have chosen current font file length arbitrarily. In our logic | 82 // We have chosen current font file length arbitrarily. In our logic |
76 // if we don't find file we are looking for in cache we end up loading | 83 // if we don't find file we are looking for in cache we end up loading |
77 // that file directly from system fonts folder. | 84 // that file directly from system fonts folder. |
78 const unsigned int kMaxFontFileNameLength = 34; | 85 const unsigned int kMaxFontFileNameLength = 34; |
79 | 86 |
80 const DWORD kCacheFileVersion = 101; | 87 const DWORD kCacheFileVersion = 101; |
81 const DWORD kFileSignature = 0x4D4F5243; // CROM | 88 const DWORD kFileSignature = 0x4D4F5243; // CROM |
82 const DWORD kMagicCompletionSignature = 0x454E4F44; // DONE | 89 const DWORD kMagicCompletionSignature = 0x454E4F44; // DONE |
83 | 90 |
(...skipping 277 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
361 regions.push_back(region); | 368 regions.push_back(region); |
362 return true; | 369 return true; |
363 } | 370 } |
364 | 371 |
365 // Function which commits after merging all collected regions into cache file. | 372 // Function which commits after merging all collected regions into cache file. |
366 bool CommitFontEntry(UINT cookie) { | 373 bool CommitFontEntry(UINT cookie) { |
367 base::AutoLock lock(lock_); | 374 base::AutoLock lock(lock_); |
368 if (cookie_map_.find(cookie) == cookie_map_.end()) | 375 if (cookie_map_.find(cookie) == cookie_map_.end()) |
369 return false; | 376 return false; |
370 | 377 |
| 378 // We will skip writing entries beyond allowed limit. Following condition |
| 379 // doesn't enforce hard file size. We need to write complete font entry. |
| 380 int64 length = static_cache_->GetLength(); |
| 381 if (length == -1 || length >= kArbitraryCacheFileSizeLimit) { |
| 382 count_font_entries_ignored_++; |
| 383 return false; |
| 384 } |
| 385 |
371 FontEntryInternal* font_entry = cookie_map_[cookie].get(); | 386 FontEntryInternal* font_entry = cookie_map_[cookie].get(); |
372 RegionVector& regions = font_entry->regions; | 387 RegionVector& regions = font_entry->regions; |
373 std::sort(regions.begin(), regions.end(), SortCacheRegions); | 388 std::sort(regions.begin(), regions.end(), SortCacheRegions); |
374 | 389 |
375 // At this point, we have collected all regions to be cached. These regions | 390 // At this point, we have collected all regions to be cached. These regions |
376 // are tuples of start, length, data for particular data segment. | 391 // are tuples of start, length, data for particular data segment. |
377 // These tuples can overlap. | 392 // These tuples can overlap. |
378 // e.g. (0, 12, data), (0, 117, data), (21, 314, data), (335, 15, data) | 393 // e.g. (0, 12, data), (0, 117, data), (21, 314, data), (335, 15, data) |
379 // In this case as you can see first three segments overlap and | 394 // In this case as you can see first three segments overlap and |
380 // 4th is adjacent. If we cache them individually then we will end up | 395 // 4th is adjacent. If we cache them individually then we will end up |
(...skipping 734 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1115 base::TimeDelta time_delta = base::TimeTicks::Now() - start_tick; | 1130 base::TimeDelta time_delta = base::TimeTicks::Now() - start_tick; |
1116 int64 delta = time_delta.ToInternalValue(); | 1131 int64 delta = time_delta.ToInternalValue(); |
1117 base::debug::Alias(&delta); | 1132 base::debug::Alias(&delta); |
1118 UINT32 size = g_font_loader->GetFontMapSize(); | 1133 UINT32 size = g_font_loader->GetFontMapSize(); |
1119 base::debug::Alias(&size); | 1134 base::debug::Alias(&size); |
1120 base::debug::Alias(&loading_restricted); | 1135 base::debug::Alias(&loading_restricted); |
1121 | 1136 |
1122 CHECK(SUCCEEDED(hr)); | 1137 CHECK(SUCCEEDED(hr)); |
1123 CHECK(font_collection.Get() != NULL); | 1138 CHECK(font_collection.Get() != NULL); |
1124 | 1139 |
1125 UMA_HISTOGRAM_TIMES("DirectWrite.Fonts.LoadTime", time_delta); | |
1126 | |
1127 base::debug::ClearCrashKey(kFontKeyName); | 1140 base::debug::ClearCrashKey(kFontKeyName); |
1128 | 1141 |
1129 return true; | 1142 return true; |
1130 } | 1143 } |
1131 | 1144 |
1132 bool ValidateFontCacheFile(base::File* file) { | 1145 bool ValidateFontCacheFile(base::File* file) { |
1133 DCHECK(file != NULL); | 1146 DCHECK(file != NULL); |
1134 CacheFileHeader file_header; | 1147 CacheFileHeader file_header; |
1135 if (file->Read(0, reinterpret_cast<char*>(&file_header), sizeof(file_header)) | 1148 if (file->Read(0, reinterpret_cast<char*>(&file_header), sizeof(file_header)) |
1136 == -1) { | 1149 == -1) { |
(...skipping 29 matching lines...) Expand all Loading... |
1166 CHECK(false); | 1179 CHECK(false); |
1167 return false; | 1180 return false; |
1168 } | 1181 } |
1169 | 1182 |
1170 DCHECK(!g_shared_font_cache.IsValid()); | 1183 DCHECK(!g_shared_font_cache.IsValid()); |
1171 g_shared_font_cache.Set(mapping); | 1184 g_shared_font_cache.Set(mapping); |
1172 | 1185 |
1173 return true; | 1186 return true; |
1174 } | 1187 } |
1175 | 1188 |
1176 // Assumption for this function is that it will get called through a posted task | 1189 bool BuildFontCache(const base::FilePath& file) { |
1177 // on FILE thread. | 1190 return BuildFontCacheInternal(file.value().c_str()); |
1178 bool BuildAndLoadFontCache(const base::FilePath& file) { | |
1179 if (BuildFontCacheInternal(file.value().c_str())) | |
1180 return LoadFontCache(file); | |
1181 return false; | |
1182 } | 1191 } |
1183 | 1192 |
1184 } // namespace content | 1193 } // namespace content |
OLD | NEW |