Remove WebCoreSystemInterface
[WebKit-https.git] / Source / WebCore / platform / graphics / Font.h
1 /*
2  * This file is part of the internal font implementation.
3  *
4  * Copyright (C) 2006, 2008, 2010, 2015-2016 Apple Inc. All rights reserved.
5  * Copyright (C) 2007-2008 Torch Mobile, Inc.
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Library General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Library General Public License for more details.
16  *
17  * You should have received a copy of the GNU Library General Public License
18  * along with this library; see the file COPYING.LIB.  If not, write to
19  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20  * Boston, MA 02110-1301, USA.
21  *
22  */
23
24 #ifndef Font_h
25 #define Font_h
26
27 #include "FloatRect.h"
28 #include "FontMetrics.h"
29 #include "FontPlatformData.h"
30 #include "GlyphBuffer.h"
31 #include "GlyphMetricsMap.h"
32 #include "GlyphPage.h"
33 #include "OpenTypeMathData.h"
34 #if ENABLE(OPENTYPE_VERTICAL)
35 #include "OpenTypeVerticalData.h"
36 #endif
37 #include <wtf/BitVector.h>
38 #include <wtf/Optional.h>
39 #include <wtf/text/StringHash.h>
40
41 #if PLATFORM(COCOA)
42 #include <wtf/RetainPtr.h>
43 #endif
44
45 #if PLATFORM(WIN)
46 #include <usp10.h>
47 #endif
48
49 #if USE(CG)
50 #include <pal/spi/cg/CoreGraphicsSPI.h>
51 #endif
52
53 #if USE(DIRECT2D)
54 interface IDWriteFactory;
55 interface IDWriteGdiInterop;
56 #endif
57
58 namespace WebCore {
59
60 class GlyphPage;
61 class FontDescription;
62 class SharedBuffer;
63 struct GlyphData;
64 struct WidthIterator;
65
66 enum FontVariant { AutoVariant, NormalVariant, SmallCapsVariant, EmphasisMarkVariant, BrokenIdeographVariant };
67 enum Pitch { UnknownPitch, FixedPitch, VariablePitch };
68
69 class Font : public RefCounted<Font> {
70 public:
71     // Used to create platform fonts.
72     enum class Origin {
73         Remote,
74         Local
75     };
76     enum class Interstitial {
77         Yes,
78         No
79     };
80     enum class Visibility {
81         Visible,
82         Invisible
83     };
84     enum class OrientationFallback {
85         Yes,
86         No
87     };
88     static Ref<Font> create(const FontPlatformData& platformData, Origin origin = Origin::Local, Interstitial interstitial = Interstitial::No, Visibility visibility = Visibility::Visible, OrientationFallback orientationFallback = OrientationFallback::No)
89     {
90         return adoptRef(*new Font(platformData, origin, interstitial, visibility, orientationFallback));
91     }
92
93     WEBCORE_EXPORT ~Font();
94
95     static const Font* systemFallback() { return reinterpret_cast<const Font*>(-1); }
96
97     const FontPlatformData& platformData() const { return m_platformData; }
98     const OpenTypeMathData* mathData() const;
99 #if ENABLE(OPENTYPE_VERTICAL)
100     const OpenTypeVerticalData* verticalData() const { return m_verticalData.get(); }
101 #endif
102
103     const Font* smallCapsFont(const FontDescription&) const;
104     const Font& noSynthesizableFeaturesFont() const;
105     const Font* emphasisMarkFont(const FontDescription&) const;
106     const Font& brokenIdeographFont() const;
107
108     const Font* variantFont(const FontDescription& description, FontVariant variant) const
109     {
110 #if PLATFORM(COCOA)
111         ASSERT(variant != SmallCapsVariant);
112 #endif
113         switch (variant) {
114         case SmallCapsVariant:
115             return smallCapsFont(description);
116         case EmphasisMarkVariant:
117             return emphasisMarkFont(description);
118         case BrokenIdeographVariant:
119             return &brokenIdeographFont();
120         case AutoVariant:
121         case NormalVariant:
122             break;
123         }
124         ASSERT_NOT_REACHED();
125         return const_cast<Font*>(this);
126     }
127
128     bool variantCapsSupportsCharacterForSynthesis(FontVariantCaps, UChar32) const;
129
130     const Font& verticalRightOrientationFont() const;
131     const Font& uprightOrientationFont() const;
132     const Font& invisibleFont() const;
133
134     bool hasVerticalGlyphs() const { return m_hasVerticalGlyphs; }
135     bool isTextOrientationFallback() const { return m_isTextOrientationFallback; }
136
137     FontMetrics& fontMetrics() { return m_fontMetrics; }
138     const FontMetrics& fontMetrics() const { return m_fontMetrics; }
139     float sizePerUnit() const { return platformData().size() / (fontMetrics().unitsPerEm() ? fontMetrics().unitsPerEm() : 1); }
140
141     float maxCharWidth() const { return m_maxCharWidth; }
142     void setMaxCharWidth(float maxCharWidth) { m_maxCharWidth = maxCharWidth; }
143
144     float avgCharWidth() const { return m_avgCharWidth; }
145     void setAvgCharWidth(float avgCharWidth) { m_avgCharWidth = avgCharWidth; }
146
147     FloatRect boundsForGlyph(Glyph) const;
148     float widthForGlyph(Glyph) const;
149     FloatRect platformBoundsForGlyph(Glyph) const;
150     float platformWidthForGlyph(Glyph) const;
151
152     float spaceWidth() const { return m_spaceWidth; }
153     float adjustedSpaceWidth() const { return m_adjustedSpaceWidth; }
154     void setSpaceWidths(float spaceWidth)
155     {
156         m_spaceWidth = spaceWidth;
157         m_adjustedSpaceWidth = spaceWidth;
158     }
159
160 #if USE(CG) || USE(DIRECT2D) || USE(CAIRO)
161     float syntheticBoldOffset() const { return m_syntheticBoldOffset; }
162 #endif
163
164     Glyph spaceGlyph() const { return m_spaceGlyph; }
165     void setSpaceGlyph(Glyph spaceGlyph) { m_spaceGlyph = spaceGlyph; }
166     Glyph zeroWidthSpaceGlyph() const { return m_zeroWidthSpaceGlyph; }
167     void setZeroWidthSpaceGlyph(Glyph spaceGlyph) { m_zeroWidthSpaceGlyph = spaceGlyph; }
168     bool isZeroWidthSpaceGlyph(Glyph glyph) const { return glyph == m_zeroWidthSpaceGlyph && glyph; }
169     Glyph zeroGlyph() const { return m_zeroGlyph; }
170     void setZeroGlyph(Glyph zeroGlyph) { m_zeroGlyph = zeroGlyph; }
171
172     GlyphData glyphDataForCharacter(UChar32) const;
173     Glyph glyphForCharacter(UChar32) const;
174
175     RefPtr<Font> systemFallbackFontForCharacter(UChar32, const FontDescription&, bool isForPlatformFont) const;
176
177     const GlyphPage* glyphPage(unsigned pageNumber) const;
178
179     void determinePitch();
180     Pitch pitch() const { return m_treatAsFixedPitch ? FixedPitch : VariablePitch; }
181
182     Origin origin() const { return m_origin; }
183     bool isInterstitial() const { return m_isInterstitial; }
184     Visibility visibility() const { return m_visibility; }
185
186 #ifndef NDEBUG
187     String description() const;
188 #endif
189
190 #if PLATFORM(IOS)
191     bool shouldNotBeUsedForArabic() const { return m_shouldNotBeUsedForArabic; };
192 #endif
193 #if PLATFORM(COCOA)
194     CTFontRef getCTFont() const { return m_platformData.font(); }
195     CFDictionaryRef getCFStringAttributes(bool enableKerning, FontOrientation) const;
196     const BitVector& glyphsSupportedBySmallCaps() const;
197     const BitVector& glyphsSupportedByAllSmallCaps() const;
198     const BitVector& glyphsSupportedByPetiteCaps() const;
199     const BitVector& glyphsSupportedByAllPetiteCaps() const;
200 #endif
201
202 #if PLATFORM(COCOA) || USE(HARFBUZZ)
203     bool canRenderCombiningCharacterSequence(const UChar*, size_t) const;
204 #endif
205
206     bool applyTransforms(GlyphBufferGlyph*, GlyphBufferAdvance*, size_t glyphCount, bool enableKerning, bool requiresShaping) const;
207
208 #if PLATFORM(WIN)
209     SCRIPT_FONTPROPERTIES* scriptFontProperties() const;
210     SCRIPT_CACHE* scriptCache() const { return &m_scriptCache; }
211     static void setShouldApplyMacAscentHack(bool);
212     static bool shouldApplyMacAscentHack();
213     static float ascentConsideringMacAscentHack(const WCHAR*, float ascent, float descent);
214 #endif
215
216 #if USE(DIRECT2D)
217     WEBCORE_EXPORT static IDWriteFactory* systemDWriteFactory();
218     WEBCORE_EXPORT static IDWriteGdiInterop* systemDWriteGdiInterop();
219 #endif
220
221 private:
222     Font(const FontPlatformData&, Origin, Interstitial, Visibility, OrientationFallback);
223
224     void platformInit();
225     void platformGlyphInit();
226     void platformCharWidthInit();
227     void platformDestroy();
228
229     void initCharWidths();
230
231     RefPtr<Font> createFontWithoutSynthesizableFeatures() const;
232     RefPtr<Font> createScaledFont(const FontDescription&, float scaleFactor) const;
233     RefPtr<Font> platformCreateScaledFont(const FontDescription&, float scaleFactor) const;
234
235     void removeFromSystemFallbackCache();
236     
237     struct DerivedFonts;
238     DerivedFonts& ensureDerivedFontData() const;
239
240 #if PLATFORM(WIN)
241     void initGDIFont();
242     void platformCommonDestroy();
243     FloatRect boundsForGDIGlyph(Glyph) const;
244     float widthForGDIGlyph(Glyph) const;
245 #endif
246
247     FontMetrics m_fontMetrics;
248     float m_maxCharWidth;
249     float m_avgCharWidth;
250
251     const FontPlatformData m_platformData;
252
253     mutable RefPtr<GlyphPage> m_glyphPageZero;
254     mutable HashMap<unsigned, RefPtr<GlyphPage>> m_glyphPages;
255     mutable std::unique_ptr<GlyphMetricsMap<FloatRect>> m_glyphToBoundsMap;
256     mutable GlyphMetricsMap<float> m_glyphToWidthMap;
257
258     mutable RefPtr<OpenTypeMathData> m_mathData;
259 #if ENABLE(OPENTYPE_VERTICAL)
260     RefPtr<OpenTypeVerticalData> m_verticalData;
261 #endif
262
263     Glyph m_spaceGlyph { 0 };
264     float m_spaceWidth { 0 };
265     Glyph m_zeroGlyph { 0 };
266     float m_adjustedSpaceWidth { 0 };
267
268     Glyph m_zeroWidthSpaceGlyph { 0 };
269
270     struct DerivedFonts {
271 #if !COMPILER(MSVC)
272         WTF_MAKE_FAST_ALLOCATED;
273 #endif
274     public:
275
276         RefPtr<Font> smallCapsFont;
277         RefPtr<Font> noSynthesizableFeaturesFont;
278         RefPtr<Font> emphasisMarkFont;
279         RefPtr<Font> brokenIdeographFont;
280         RefPtr<Font> verticalRightOrientationFont;
281         RefPtr<Font> uprightOrientationFont;
282         RefPtr<Font> invisibleFont;
283     };
284
285     mutable std::unique_ptr<DerivedFonts> m_derivedFontData;
286
287 #if USE(CG) || USE(DIRECT2D) || USE(CAIRO)
288     float m_syntheticBoldOffset;
289 #endif
290
291 #if PLATFORM(COCOA)
292     mutable RetainPtr<CFDictionaryRef> m_nonKernedCFStringAttributes;
293     mutable RetainPtr<CFDictionaryRef> m_kernedCFStringAttributes;
294     mutable std::optional<BitVector> m_glyphsSupportedBySmallCaps;
295     mutable std::optional<BitVector> m_glyphsSupportedByAllSmallCaps;
296     mutable std::optional<BitVector> m_glyphsSupportedByPetiteCaps;
297     mutable std::optional<BitVector> m_glyphsSupportedByAllPetiteCaps;
298 #endif
299
300 #if PLATFORM(COCOA) || USE(HARFBUZZ)
301     mutable std::unique_ptr<HashMap<String, bool>> m_combiningCharacterSequenceSupport;
302 #endif
303
304 #if PLATFORM(WIN)
305     mutable SCRIPT_CACHE m_scriptCache;
306     mutable SCRIPT_FONTPROPERTIES* m_scriptFontProperties;
307 #endif
308
309     Origin m_origin; // Whether or not we are custom font loaded via @font-face
310     Visibility m_visibility; // @font-face's internal timer can cause us to show fonts even when a font is being downloaded.
311
312     unsigned m_treatAsFixedPitch : 1;
313     unsigned m_isInterstitial : 1; // Whether or not this custom font is the last resort placeholder for a loading font
314
315     unsigned m_isTextOrientationFallback : 1;
316     unsigned m_isBrokenIdeographFallback : 1;
317     unsigned m_hasVerticalGlyphs : 1;
318
319     unsigned m_isUsedInSystemFallbackCache : 1;
320
321 #if PLATFORM(IOS)
322     unsigned m_shouldNotBeUsedForArabic : 1;
323 #endif
324 };
325
326 #if PLATFORM(IOS)
327 bool fontFamilyShouldNotBeUsedForArabic(CFStringRef);
328 #endif
329
330 ALWAYS_INLINE FloatRect Font::boundsForGlyph(Glyph glyph) const
331 {
332     if (isZeroWidthSpaceGlyph(glyph))
333         return FloatRect();
334
335     FloatRect bounds;
336     if (m_glyphToBoundsMap) {
337         bounds = m_glyphToBoundsMap->metricsForGlyph(glyph);
338         if (bounds.width() != cGlyphSizeUnknown)
339             return bounds;
340     }
341
342     bounds = platformBoundsForGlyph(glyph);
343     if (!m_glyphToBoundsMap)
344         m_glyphToBoundsMap = std::make_unique<GlyphMetricsMap<FloatRect>>();
345     m_glyphToBoundsMap->setMetricsForGlyph(glyph, bounds);
346     return bounds;
347 }
348
349 ALWAYS_INLINE float Font::widthForGlyph(Glyph glyph) const
350 {
351     // The optimization of returning 0 for the zero-width-space glyph is incorrect for the LastResort font,
352     // used in place of the actual font when isLoading() is true on both macOS and iOS.
353     // The zero-width-space glyph in that font does not have a width of zero and, further, that glyph is used
354     // for many other characters and must not be zero width when used for them.
355     if (isZeroWidthSpaceGlyph(glyph) && !isInterstitial())
356         return 0;
357
358     float width = m_glyphToWidthMap.metricsForGlyph(glyph);
359     if (width != cGlyphSizeUnknown)
360         return width;
361
362 #if ENABLE(OPENTYPE_VERTICAL)
363     if (m_verticalData) {
364 #if USE(CG) || USE(DIRECT2D) || USE(CAIRO)
365         width = m_verticalData->advanceHeight(this, glyph) + m_syntheticBoldOffset;
366 #else
367         width = m_verticalData->advanceHeight(this, glyph);
368 #endif
369     } else
370 #endif
371         width = platformWidthForGlyph(glyph);
372
373     m_glyphToWidthMap.setMetricsForGlyph(glyph, width);
374     return width;
375 }
376
377 } // namespace WebCore
378
379 #endif // Font_h