1 /*
2  * Copyright (C) 2006, 2008 Apple Computer, Inc.  All rights reserved.
3  * Copyright (C) 2007-2008 Torch Mobile, Inc.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * 1.  Redistributions of source code must retain the above copyright
10  *     notice, this list of conditions and the following disclaimer.
11  * 2.  Redistributions in binary form must reproduce the above copyright
12  *     notice, this list of conditions and the following disclaimer in the
13  *     documentation and/or other materials provided with the distribution.
14  * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
15  *     its contributors may be used to endorse or promote products derived
16  *     from this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
19  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
22  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  */
29 
30 #ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_FONT_CACHE_H_
31 #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_FONT_CACHE_H_
32 
33 #include <limits.h>
34 
35 #include <memory>
36 #include <string>
37 
38 #include "base/memory/scoped_refptr.h"
39 #include "build/build_config.h"
40 #include "mojo/public/cpp/bindings/remote.h"
41 #include "third_party/blink/renderer/platform/fonts/fallback_list_composite_key.h"
42 #include "third_party/blink/renderer/platform/fonts/font_cache_client.h"
43 #include "third_party/blink/renderer/platform/fonts/font_cache_key.h"
44 #include "third_party/blink/renderer/platform/fonts/font_data_cache.h"
45 #include "third_party/blink/renderer/platform/fonts/font_face_creation_params.h"
46 #include "third_party/blink/renderer/platform/fonts/font_fallback_priority.h"
47 #include "third_party/blink/renderer/platform/fonts/font_platform_data.h"
48 #include "third_party/blink/renderer/platform/fonts/shaping/shape_cache.h"
49 #include "third_party/blink/renderer/platform/heap/heap_allocator.h"
50 #include "third_party/blink/renderer/platform/heap/persistent.h"
51 #include "third_party/blink/renderer/platform/platform_export.h"
52 #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
53 #include "third_party/blink/renderer/platform/wtf/forward.h"
54 #include "third_party/blink/renderer/platform/wtf/hash_map.h"
55 #include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
56 #include "third_party/blink/renderer/platform/wtf/text/unicode.h"
57 #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
58 #include "third_party/skia/include/core/SkFontMgr.h"
59 #include "third_party/skia/include/core/SkRefCnt.h"
60 
61 #if defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_BSD)
62 #include "ui/gfx/font_fallback_linux.h"
63 #endif
64 
65 #if defined(OS_WIN)
66 #include "third_party/blink/public/mojom/dwrite_font_proxy/dwrite_font_proxy.mojom-blink.h"
67 #include "third_party/blink/renderer/platform/fonts/win/fallback_family_style_cache_win.h"
68 #endif
69 
70 class SkString;
71 class SkTypeface;
72 
73 namespace base {
74 namespace trace_event {
75 class ProcessMemoryDump;
76 }
77 }
78 
79 namespace blink {
80 
81 class FontDescription;
82 class FontFaceCreationParams;
83 class FontFallbackMap;
84 class FontGlobalContext;
85 class SimpleFontData;
86 
87 enum class AlternateFontName {
88   kAllowAlternate,
89   kNoAlternate,
90   kLocalUniqueFace,
91   kLastResort
92 };
93 
94 enum CreateIfNeeded { kDoNotCreate, kCreate };
95 
96 typedef HashMap<unsigned,
97                 std::unique_ptr<FontPlatformData>,
98                 WTF::IntHash<unsigned>,
99                 WTF::UnsignedWithZeroKeyHashTraits<unsigned>>
100     SizedFontPlatformDataSet;
101 typedef HashMap<FontCacheKey, SizedFontPlatformDataSet> FontPlatformDataCache;
102 typedef HashMap<FallbackListCompositeKey,
103                 std::unique_ptr<ShapeCache>,
104                 FallbackListCompositeKeyHash,
105                 FallbackListCompositeKeyTraits>
106     FallbackListShaperCache;
107 
108 // "und-Zsye", the special locale for retrieving the color emoji font defined
109 // in UTS #51: https://unicode.org/reports/tr51/#Emoji_Script
110 extern const char kColorEmojiLocale[];
111 
112 class PLATFORM_EXPORT FontCache {
113   friend class FontCachePurgePreventer;
114 
115   USING_FAST_MALLOC(FontCache);
116 
117  public:
118   // FontCache initialisation on Windows depends on a global FontMgr being
119   // configured through a call from the browser process. CreateIfNeeded helps
120   // avoid early creation of a font cache when these globals have not yet
121   // been set.
122   static FontCache* GetFontCache(CreateIfNeeded = kCreate);
123 
124   void ReleaseFontData(const SimpleFontData*);
125 
126   scoped_refptr<SimpleFontData> FallbackFontForCharacter(
127       const FontDescription&,
128       UChar32,
129       const SimpleFontData* font_data_to_substitute,
130       FontFallbackPriority = FontFallbackPriority::kText);
131 
132   // Also implemented by the platform.
133   void PlatformInit();
134 
135   scoped_refptr<SimpleFontData> GetFontData(
136       const FontDescription&,
137       const AtomicString&,
138       AlternateFontName = AlternateFontName::kAllowAlternate,
139       ShouldRetain = kRetain);
140   scoped_refptr<SimpleFontData> GetLastResortFallbackFont(const FontDescription&,
141                                                    ShouldRetain = kRetain);
142   SimpleFontData* GetNonRetainedLastResortFallbackFont(const FontDescription&);
143 
144   // Should be used in determining whether family names listed in font-family:
145   // ... are available locally. Only returns true if family name matches.
146   bool IsPlatformFamilyMatchAvailable(const FontDescription&,
147                                       const AtomicString& family);
148 
149   // Should be used in determining whether the <abc> argument to local in
150   // @font-face { ... src: local(<abc>) } are available locally, which should
151   // match Postscript name or full font name. Compare
152   // https://drafts.csswg.org/css-fonts-3/#src-desc
153   // TODO crbug.com/627143 complete this and actually look at the right
154   // namerecords.
155   bool IsPlatformFontUniqueNameMatchAvailable(
156       const FontDescription&,
157       const AtomicString& unique_font_name);
158 
159   static String FirstAvailableOrFirst(const String&);
160 
161   // Returns the ShapeCache instance associated with the given cache key.
162   // Creates a new instance as needed and as such is guaranteed not to return
163   // a nullptr. Instances are managed by FontCache and are only guaranteed to
164   // be valid for the duration of the current session, as controlled by
165   // disable/enablePurging.
166   ShapeCache* GetShapeCache(const FallbackListCompositeKey&);
167 
168   void AddClient(FontCacheClient*);
169 
170   uint16_t Generation();
171   void Invalidate();
172 
FontManager()173   sk_sp<SkFontMgr> FontManager() { return font_manager_; }
174   static void SetFontManager(sk_sp<SkFontMgr>);
175 
176 #if defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_BSD)
177   // These are needed for calling QueryRenderStyleForStrike, since
178   // gfx::GetFontRenderParams makes distinctions based on DSF.
DeviceScaleFactor()179   static float DeviceScaleFactor() { return device_scale_factor_; }
SetDeviceScaleFactor(float device_scale_factor)180   static void SetDeviceScaleFactor(float device_scale_factor) {
181     device_scale_factor_ = device_scale_factor;
182   }
183 #endif
184 
185 #if !defined(OS_MAC)
186   static const AtomicString& SystemFontFamily();
187 #else
188   static const AtomicString& LegacySystemFontFamily();
189 #endif
190 
191 #if !defined(OS_MAC)
192   static void SetSystemFontFamily(const AtomicString&);
193 #endif
194 
195 #if defined(OS_WIN)
196   // TODO(https://crbug.com/808221) System font style configuration is not
197   // related to FontCache. Move it somewhere else, e.g. to WebThemeEngine.
AntialiasedTextEnabled()198   static bool AntialiasedTextEnabled() { return antialiased_text_enabled_; }
LcdTextEnabled()199   static bool LcdTextEnabled() { return lcd_text_enabled_; }
SetAntialiasedTextEnabled(bool enabled)200   static void SetAntialiasedTextEnabled(bool enabled) {
201     antialiased_text_enabled_ = enabled;
202   }
SetLCDTextEnabled(bool enabled)203   static void SetLCDTextEnabled(bool enabled) { lcd_text_enabled_ = enabled; }
204   static void AddSideloadedFontForTesting(sk_sp<SkTypeface>);
205   // Functions to cache and retrieve the system font metrics.
206   static void SetMenuFontMetrics(const wchar_t* family_name,
207                                  int32_t font_height);
208   static void SetSmallCaptionFontMetrics(const wchar_t* family_name,
209                                          int32_t font_height);
210   static void SetStatusFontMetrics(const wchar_t* family_name,
211                                    int32_t font_height);
MenuFontHeight()212   static int32_t MenuFontHeight() { return menu_font_height_; }
MenuFontFamily()213   static const AtomicString& MenuFontFamily() {
214     return *menu_font_family_name_;
215   }
SmallCaptionFontHeight()216   static int32_t SmallCaptionFontHeight() { return small_caption_font_height_; }
SmallCaptionFontFamily()217   static const AtomicString& SmallCaptionFontFamily() {
218     return *small_caption_font_family_name_;
219   }
StatusFontHeight()220   static int32_t StatusFontHeight() { return status_font_height_; }
StatusFontFamily()221   static const AtomicString& StatusFontFamily() {
222     return *status_font_family_name_;
223   }
SetUseSkiaFontFallback(bool use_skia_font_fallback)224   static void SetUseSkiaFontFallback(bool use_skia_font_fallback) {
225     use_skia_font_fallback_ = use_skia_font_fallback;
226   }
227 
228   // On Windows pre 8.1 establish a connection to the DWriteFontProxy service in
229   // order to retrieve family names for fallback lookup.
230   void EnsureServiceConnected();
231 
232   scoped_refptr<SimpleFontData> GetFallbackFamilyNameFromHardcodedChoices(
233       const FontDescription&,
234       UChar32 codepoint,
235       FontFallbackPriority fallback_priority);
236 
237   scoped_refptr<SimpleFontData> GetDWriteFallbackFamily(
238       const FontDescription&,
239       UChar32 codepoint,
240       FontFallbackPriority fallback_priority);
241 #endif  // defined(OS_WIN)
242 
243   static void AcceptLanguagesChanged(const String&);
244 
245 #if defined(OS_ANDROID)
246   static AtomicString GetGenericFamilyNameForScript(
247       const AtomicString& family_name,
248       const FontDescription&);
249 #endif  // defined(OS_ANDROID)
250 
251 #if defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_BSD)
252   static bool GetFontForCharacter(UChar32,
253                                   const char* preferred_locale,
254                                   gfx::FallbackFontData*);
255 #endif  // defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_BSD)
256 
257   scoped_refptr<SimpleFontData> FontDataFromFontPlatformData(
258       const FontPlatformData*,
259       ShouldRetain = kRetain,
260       bool subpixel_ascent_descent = false);
261 
262   void InvalidateShapeCache();
263 
264   static void CrashWithFontInfo(const FontDescription*);
265 
266   // Memory reporting
267   void DumpFontPlatformDataCache(base::trace_event::ProcessMemoryDump*);
268   void DumpShapeResultCache(base::trace_event::ProcessMemoryDump*);
269 
270   FontFallbackMap& GetFontFallbackMap();
271 
272   ~FontCache() = default;
273 
274  private:
275   // BCP47 list used when requesting fallback font for a character.
276   // inlineCapacity is set to 4: the array vector not need to hold more than 4
277   // elements.
278   using Bcp47Vector = WTF::Vector<const char*, 4>;
279 
280   scoped_refptr<SimpleFontData> PlatformFallbackFontForCharacter(
281       const FontDescription&,
282       UChar32,
283       const SimpleFontData* font_data_to_substitute,
284       FontFallbackPriority = FontFallbackPriority::kText);
285   sk_sp<SkTypeface> CreateTypefaceFromUniqueName(
286       const FontFaceCreationParams& creation_params);
287 
288   static Bcp47Vector GetBcp47LocaleForRequest(
289       const FontDescription& font_description,
290       FontFallbackPriority fallback_priority);
291 
292   friend class FontGlobalContext;
293   FontCache();
294 
295   void Purge(PurgeSeverity = kPurgeIfNeeded);
296 
DisablePurging()297   void DisablePurging() { purge_prevent_count_++; }
EnablePurging()298   void EnablePurging() {
299     DCHECK(purge_prevent_count_);
300     if (!--purge_prevent_count_)
301       Purge(kPurgeIfNeeded);
302   }
303 
304   // FIXME: This method should eventually be removed.
305   FontPlatformData* GetFontPlatformData(
306       const FontDescription&,
307       const FontFaceCreationParams&,
308       AlternateFontName = AlternateFontName::kAllowAlternate);
309 #if !defined(OS_MAC)
310   FontPlatformData* SystemFontPlatformData(const FontDescription&);
311 #endif  // !defined(OS_MAC)
312 
313   // These methods are implemented by each platform.
314   std::unique_ptr<FontPlatformData> CreateFontPlatformData(
315       const FontDescription&,
316       const FontFaceCreationParams&,
317       float font_size,
318       AlternateFontName = AlternateFontName::kAllowAlternate);
319   std::unique_ptr<FontPlatformData> ScaleFontPlatformData(
320       const FontPlatformData&,
321       const FontDescription&,
322       const FontFaceCreationParams&,
323       float font_size);
324 
325   sk_sp<SkTypeface> CreateTypeface(const FontDescription&,
326                                    const FontFaceCreationParams&,
327                                    std::string& name);
328 
329 #if defined(OS_ANDROID) || defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_BSD)
330   static AtomicString GetFamilyNameForCharacter(SkFontMgr*,
331                                                 UChar32,
332                                                 const FontDescription&,
333                                                 FontFallbackPriority);
334 #endif  // defined(OS_ANDROID) || defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_BSD)
335 
336   scoped_refptr<SimpleFontData> FallbackOnStandardFontStyle(
337       const FontDescription&,
338       UChar32);
339 
340   // When true, the font size is removed from primary keys in
341   // |font_platform_data_cache_|. The font size is not necessary in the primary
342   // key, because per-size FontPlatformData are held in a nested map. This is
343   // controlled by a base::Feature to assess impact with an experiment.
344   const bool no_size_in_key_;
345 
346   // Don't purge if this count is > 0;
347   int purge_prevent_count_;
348 
349   sk_sp<SkFontMgr> font_manager_;
350 
351   // A leaky owning bare pointer.
352   static SkFontMgr* static_font_manager_;
353 
354 #if defined(OS_WIN)
355   static bool antialiased_text_enabled_;
356   static bool lcd_text_enabled_;
357   static HashMap<String, sk_sp<SkTypeface>, CaseFoldingHash>* sideloaded_fonts_;
358   // The system font metrics cache.
359   static AtomicString* menu_font_family_name_;
360   static int32_t menu_font_height_;
361   static AtomicString* small_caption_font_family_name_;
362   static int32_t small_caption_font_height_;
363   static AtomicString* status_font_family_name_;
364   static int32_t status_font_height_;
365   static bool use_skia_font_fallback_;
366 
367   // Windows creates an SkFontMgr for unit testing automatically. This flag is
368   // to ensure it's not happening in the production from the crash log.
369   bool is_test_font_mgr_ = false;
370   mojo::Remote<mojom::blink::DWriteFontProxy> service_;
371   std::unique_ptr<FallbackFamilyStyleCache> fallback_params_cache_;
372 #endif  // defined(OS_WIN)
373 
374 #if defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_BSD)
375   static float device_scale_factor_;
376 #endif
377 
378   uint16_t generation_ = 0;
379   bool platform_init_ = false;
380   Persistent<HeapHashSet<WeakMember<FontCacheClient>>> font_cache_clients_;
381   FontPlatformDataCache font_platform_data_cache_;
382   FallbackListShaperCache fallback_list_shaper_cache_;
383   FontDataCache font_data_cache_;
384 
385   Persistent<FontFallbackMap> font_fallback_map_;
386 
387   void PurgePlatformFontDataCache();
388   void PurgeFallbackListShaperCache();
389 
390   // A maximum float value to which we limit incoming font sizes. This is the
391   // smallest float so that multiplying it by
392   // FontCacheKey::PrecisionMultiplier() is still smaller than
393   // std::numeric_limits<unsigned>::max() - 1 in order to avoid hitting HashMap
394   // sentinel values (placed at std::numeric_limits<unsigned>::max() and
395   // std::numeric_limits<unsigned>::max() - 1) for SizedFontPlatformDataSet and
396   // FontPlatformDataCache.
397   const float font_size_limit_;
398 
399   friend class SimpleFontData;  // For fontDataFromFontPlatformData
400   friend class FontFallbackList;
401 
402   DISALLOW_COPY_AND_ASSIGN(FontCache);
403 };
404 
405 class PLATFORM_EXPORT FontCachePurgePreventer {
406   USING_FAST_MALLOC(FontCachePurgePreventer);
407 
408  public:
FontCachePurgePreventer()409   FontCachePurgePreventer() { FontCache::GetFontCache()->DisablePurging(); }
~FontCachePurgePreventer()410   ~FontCachePurgePreventer() { FontCache::GetFontCache()->EnablePurging(); }
411 
412  private:
413   DISALLOW_COPY_AND_ASSIGN(FontCachePurgePreventer);
414 };
415 
416 AtomicString ToAtomicString(const SkString&);
417 
418 }  // namespace blink
419 
420 #endif  // THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_FONT_CACHE_H_
421