1/*
2 * Copyright (C) 2006, 2010, 2013-2015 Apple Inc. All rights reserved.
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public License
15 * along with this library; see the file COPYING.LIB. If not, write to
16 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
18 *
19 */
20
21#ifndef FontCascadeFonts_h
22#define FontCascadeFonts_h
23
24#include "Font.h"
25#include "FontRanges.h"
26#include "FontSelector.h"
27#include "GlyphPage.h"
28#include "WidthCache.h"
29#include <wtf/Forward.h>
30#include <wtf/MainThread.h>
31
32#if PLATFORM(IOS_FAMILY)
33#include "WebCoreThread.h"
34#endif
35
36namespace WebCore {
37
38class FontCascadeDescription;
39class FontPlatformData;
40class FontSelector;
41class GraphicsContext;
42class IntRect;
43class MixedFontGlyphPage;
44
45class FontCascadeFonts : public RefCounted<FontCascadeFonts> {
46 WTF_MAKE_NONCOPYABLE(FontCascadeFonts);
47public:
48 static Ref<FontCascadeFonts> create(RefPtr<FontSelector>&& fontSelector) { return adoptRef(*new FontCascadeFonts(WTFMove(fontSelector))); }
49 static Ref<FontCascadeFonts> createForPlatformFont(const FontPlatformData& platformData) { return adoptRef(*new FontCascadeFonts(platformData)); }
50
51 WEBCORE_EXPORT ~FontCascadeFonts();
52
53 bool isForPlatformFont() const { return m_isForPlatformFont; }
54
55 GlyphData glyphDataForCharacter(UChar32, const FontCascadeDescription&, FontVariant);
56
57 bool isFixedPitch(const FontCascadeDescription&);
58 void determinePitch(const FontCascadeDescription&);
59
60 bool isLoadingCustomFonts() const;
61
62 FontSelector* fontSelector() { return m_fontSelector.get(); }
63 // FIXME: It should be possible to combine fontSelectorVersion and generation.
64 unsigned fontSelectorVersion() const { return m_fontSelectorVersion; }
65 unsigned generation() const { return m_generation; }
66
67 WidthCache& widthCache() { return m_widthCache; }
68 const WidthCache& widthCache() const { return m_widthCache; }
69
70 const Font& primaryFont(const FontCascadeDescription&);
71 WEBCORE_EXPORT const FontRanges& realizeFallbackRangesAt(const FontCascadeDescription&, unsigned fallbackIndex);
72
73 void pruneSystemFallbacks();
74
75private:
76 FontCascadeFonts(RefPtr<FontSelector>&&);
77 FontCascadeFonts(const FontPlatformData&);
78
79 GlyphData glyphDataForSystemFallback(UChar32, const FontCascadeDescription&, FontVariant, bool systemFallbackShouldBeInvisible);
80 GlyphData glyphDataForVariant(UChar32, const FontCascadeDescription&, FontVariant, unsigned fallbackIndex = 0);
81
82 Vector<FontRanges, 1> m_realizedFallbackRanges;
83 unsigned m_lastRealizedFallbackIndex { 0 };
84
85 class GlyphPageCacheEntry {
86 public:
87 GlyphData glyphDataForCharacter(UChar32);
88
89 void setSingleFontPage(RefPtr<GlyphPage>&&);
90 void setGlyphDataForCharacter(UChar32, GlyphData);
91
92 bool isNull() const { return !m_singleFont && !m_mixedFont; }
93 bool isMixedFont() const { return !!m_mixedFont; }
94
95 private:
96 // Only one of these is non-null.
97 RefPtr<GlyphPage> m_singleFont;
98 std::unique_ptr<MixedFontGlyphPage> m_mixedFont;
99 };
100
101 GlyphPageCacheEntry m_cachedPageZero;
102 HashMap<int, GlyphPageCacheEntry> m_cachedPages;
103
104 HashSet<RefPtr<Font>> m_systemFallbackFontSet;
105
106 const Font* m_cachedPrimaryFont;
107 RefPtr<FontSelector> m_fontSelector;
108
109 WidthCache m_widthCache;
110
111 unsigned m_fontSelectorVersion;
112 unsigned short m_generation;
113 Pitch m_pitch { UnknownPitch };
114 bool m_isForPlatformFont { false };
115};
116
117inline bool FontCascadeFonts::isFixedPitch(const FontCascadeDescription& description)
118{
119 if (m_pitch == UnknownPitch)
120 determinePitch(description);
121 return m_pitch == FixedPitch;
122};
123
124inline const Font& FontCascadeFonts::primaryFont(const FontCascadeDescription& description)
125{
126 ASSERT(isMainThread());
127 if (!m_cachedPrimaryFont) {
128 auto& primaryRanges = realizeFallbackRangesAt(description, 0);
129 m_cachedPrimaryFont = primaryRanges.glyphDataForCharacter(' ', ExternalResourceDownloadPolicy::Allow).font;
130 if (!m_cachedPrimaryFont)
131 m_cachedPrimaryFont = &primaryRanges.fontForFirstRange();
132 else if (m_cachedPrimaryFont->isInterstitial()) {
133 for (unsigned index = 1; ; ++index) {
134 auto& localRanges = realizeFallbackRangesAt(description, index);
135 if (localRanges.isNull())
136 break;
137 auto* font = localRanges.glyphDataForCharacter(' ', ExternalResourceDownloadPolicy::Forbid).font;
138 if (font && !font->isInterstitial()) {
139 m_cachedPrimaryFont = font;
140 break;
141 }
142 }
143 }
144 }
145 return *m_cachedPrimaryFont;
146}
147
148}
149
150#endif
151