Cache glyph widths to GlyphPages
[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 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 "FontBaseline.h"
29 #include "FontMetrics.h"
30 #include "FontPlatformData.h"
31 #include "GlyphBuffer.h"
32 #include "GlyphMetricsMap.h"
33 #include "GlyphPage.h"
34 #include "OpenTypeMathData.h"
35 #if ENABLE(OPENTYPE_VERTICAL)
36 #include "OpenTypeVerticalData.h"
37 #endif
38 #include "TypesettingFeatures.h"
39 #include <wtf/TypeCasts.h>
40 #include <wtf/text/StringHash.h>
41
42 #if PLATFORM(COCOA)
43 #include "WebCoreSystemInterface.h"
44 #include <wtf/RetainPtr.h>
45 #endif
46
47 #if PLATFORM(WIN)
48 #include <usp10.h>
49 #endif
50
51 #if USE(CAIRO)
52 #include <cairo.h>
53 #endif
54
55 #if USE(CG)
56 #include <WebCore/CoreGraphicsSPI.h>
57 #endif
58
59 namespace WebCore {
60
61 class GlyphPage;
62 class FontDescription;
63 class SharedBuffer;
64 struct GlyphData;
65 struct WidthIterator;
66
67 enum FontVariant { AutoVariant, NormalVariant, SmallCapsVariant, EmphasisMarkVariant, BrokenIdeographVariant };
68 enum Pitch { UnknownPitch, FixedPitch, VariablePitch };
69
70 class Font : public RefCounted<Font> {
71 public:
72     class SVGData {
73         WTF_MAKE_FAST_ALLOCATED;
74     public:
75         virtual ~SVGData() { }
76
77         virtual void initializeFont(Font*, float fontSize) = 0;
78         virtual float widthForSVGGlyph(Glyph, float fontSize) const = 0;
79         virtual bool fillSVGGlyphPage(GlyphPage*, unsigned offset, unsigned length, UChar* buffer, unsigned bufferLength, const Font*) const = 0;
80     };
81
82     // Used to create platform fonts.
83     static Ref<Font> create(const FontPlatformData& platformData, bool isCustomFont = false, bool isLoading = false, bool isTextOrientationFallback = false)
84     {
85         return adoptRef(*new Font(platformData, isCustomFont, isLoading, isTextOrientationFallback));
86     }
87
88     // Used to create SVG Fonts.
89     static Ref<Font> create(std::unique_ptr<SVGData> svgData, float fontSize, bool syntheticBold, bool syntheticItalic)
90     {
91         return adoptRef(*new Font(WTF::move(svgData), fontSize, syntheticBold, syntheticItalic));
92     }
93
94     WEBCORE_EXPORT ~Font();
95
96     static const Font* systemFallback() { return reinterpret_cast<const Font*>(-1); }
97
98     const FontPlatformData& platformData() const { return m_platformData; }
99     const OpenTypeMathData* mathData() const;
100 #if ENABLE(OPENTYPE_VERTICAL)
101     const OpenTypeVerticalData* verticalData() const { return m_verticalData.get(); }
102 #endif
103
104     PassRefPtr<Font> smallCapsFont(const FontDescription&) const;
105     PassRefPtr<Font> emphasisMarkFont(const FontDescription&) const;
106     PassRefPtr<Font> brokenIdeographFont() const;
107     PassRefPtr<Font> nonSyntheticItalicFont() const;
108
109     PassRefPtr<Font> variantFont(const FontDescription& description, FontVariant variant) const
110     {
111         switch (variant) {
112         case SmallCapsVariant:
113             return smallCapsFont(description);
114         case EmphasisMarkVariant:
115             return emphasisMarkFont(description);
116         case BrokenIdeographVariant:
117             return brokenIdeographFont();
118         case AutoVariant:
119         case NormalVariant:
120             break;
121         }
122         ASSERT_NOT_REACHED();
123         return const_cast<Font*>(this);
124     }
125
126     PassRefPtr<Font> verticalRightOrientationFont() const;
127     PassRefPtr<Font> uprightOrientationFont() const;
128
129     bool hasVerticalGlyphs() const { return m_hasVerticalGlyphs; }
130     bool isTextOrientationFallback() const { return m_isTextOrientationFallback; }
131
132     FontMetrics& fontMetrics() { return m_fontMetrics; }
133     const FontMetrics& fontMetrics() const { return m_fontMetrics; }
134     float sizePerUnit() const { return platformData().size() / (fontMetrics().unitsPerEm() ? fontMetrics().unitsPerEm() : 1); }
135
136     float maxCharWidth() const { return m_maxCharWidth; }
137     void setMaxCharWidth(float maxCharWidth) { m_maxCharWidth = maxCharWidth; }
138
139     float avgCharWidth() const { return m_avgCharWidth; }
140     void setAvgCharWidth(float avgCharWidth) { m_avgCharWidth = avgCharWidth; }
141
142     FloatRect boundsForGlyph(Glyph) const;
143
144     float computeWidthForGlyph(Glyph) const;
145
146     float spaceWidth() const { return m_spaceWidth; }
147     float adjustedSpaceWidth() const { return m_adjustedSpaceWidth; }
148     void setSpaceWidths(float spaceWidth)
149     {
150         m_spaceWidth = spaceWidth;
151         m_adjustedSpaceWidth = spaceWidth;
152     }
153     float glyphZeroWidth() const { return m_glyphZeroWidth; }
154
155 #if USE(CG) || USE(CAIRO)
156     float syntheticBoldOffset() const { return m_syntheticBoldOffset; }
157 #endif
158
159     Glyph spaceGlyph() const { return m_spaceGlyph; }
160     void setSpaceGlyph(Glyph spaceGlyph) { m_spaceGlyph = spaceGlyph; }
161     Glyph zeroWidthSpaceGlyph() const { return m_zeroWidthSpaceGlyph; }
162     void setZeroWidthSpaceGlyph(Glyph spaceGlyph) { m_zeroWidthSpaceGlyph = spaceGlyph; }
163     bool isZeroWidthSpaceGlyph(Glyph glyph) const { return glyph == m_zeroWidthSpaceGlyph && glyph; }
164
165     GlyphData glyphDataForCharacter(UChar32) const;
166     Glyph glyphForCharacter(UChar32) const;
167
168     RefPtr<Font> systemFallbackFontForCharacter(UChar32, const FontDescription&, bool isForPlatformFont) const;
169
170     const GlyphPage* glyphPage(unsigned pageNumber) const;
171
172     void determinePitch();
173     Pitch pitch() const { return m_treatAsFixedPitch ? FixedPitch : VariablePitch; }
174
175     const SVGData* svgData() const { return m_svgData.get(); }
176     bool isSVGFont() const { return !!m_svgData; }
177
178     bool isCustomFont() const { return m_isCustomFont; }
179     bool isLoading() const { return m_isLoading; }
180
181 #ifndef NDEBUG
182     String description() const;
183 #endif
184
185 #if USE(APPKIT)
186     const Font* compositeFontReferenceFont(NSFont *key) const;
187     NSFont* getNSFont() const { return m_platformData.nsFont(); }
188 #endif
189
190 #if PLATFORM(IOS)
191     CTFontRef getCTFont() const { return m_platformData.font(); }
192     bool shouldNotBeUsedForArabic() const { return m_shouldNotBeUsedForArabic; };
193 #endif
194 #if PLATFORM(COCOA)
195     CFDictionaryRef getCFStringAttributes(TypesettingFeatures, FontOrientation) const;
196 #endif
197
198 #if PLATFORM(COCOA) || USE(HARFBUZZ)
199     bool canRenderCombiningCharacterSequence(const UChar*, size_t) const;
200 #endif
201
202     bool applyTransforms(GlyphBufferGlyph*, GlyphBufferAdvance*, size_t glyphCount, TypesettingFeatures) const;
203
204 #if PLATFORM(WIN)
205     bool isSystemFont() const { return m_isSystemFont; }
206     SCRIPT_FONTPROPERTIES* scriptFontProperties() const;
207     SCRIPT_CACHE* scriptCache() const { return &m_scriptCache; }
208     static void setShouldApplyMacAscentHack(bool);
209     static bool shouldApplyMacAscentHack();
210     static float ascentConsideringMacAscentHack(const WCHAR*, float ascent, float descent);
211 #endif
212
213 private:
214     Font(const FontPlatformData&, bool isCustomFont = false, bool isLoading = false, bool isTextOrientationFallback = false);
215
216     Font(std::unique_ptr<SVGData>, float fontSize, bool syntheticBold, bool syntheticItalic);
217
218     void platformInit();
219     void platformGlyphInit();
220     void platformCharWidthInit();
221     void platformDestroy();
222
223     void initCharWidths();
224
225     PassRefPtr<Font> createScaledFont(const FontDescription&, float scaleFactor) const;
226     PassRefPtr<Font> platformCreateScaledFont(const FontDescription&, float scaleFactor) const;
227
228     float platformWidthForGlyph(Glyph) const;
229     FloatRect platformBoundsForGlyph(Glyph) const;
230
231     void removeFromSystemFallbackCache();
232
233     friend RefPtr<GlyphPage> createAndFillGlyphPage(unsigned pageNumber, const Font*);
234
235 #if PLATFORM(WIN)
236     void initGDIFont();
237     void platformCommonDestroy();
238     FloatRect boundsForGDIGlyph(Glyph) const;
239     float widthForGDIGlyph(Glyph) const;
240 #endif
241
242     FontMetrics m_fontMetrics;
243     float m_maxCharWidth;
244     float m_avgCharWidth;
245
246     FontPlatformData m_platformData;
247     std::unique_ptr<SVGData> m_svgData;
248
249     mutable RefPtr<GlyphPage> m_glyphPageZero;
250     mutable HashMap<unsigned, RefPtr<GlyphPage>> m_glyphPages;
251     mutable std::unique_ptr<GlyphMetricsMap<FloatRect>> m_glyphToBoundsMap;
252
253     bool m_treatAsFixedPitch { false };
254     bool m_isCustomFont { false }; // Whether or not we are custom font loaded via @font-face
255     bool m_isLoading { false }; // Whether or not this custom font is still in the act of loading.
256
257     bool m_isTextOrientationFallback { false };
258     bool m_isBrokenIdeographFallback { false };
259
260     bool m_isUsedInSystemFallbackCache { false };
261
262     mutable RefPtr<OpenTypeMathData> m_mathData;
263 #if ENABLE(OPENTYPE_VERTICAL)
264     RefPtr<OpenTypeVerticalData> m_verticalData;
265 #endif
266     bool m_hasVerticalGlyphs { false };
267
268     Glyph m_spaceGlyph { 0 };
269     float m_spaceWidth { 0 };
270     float m_adjustedSpaceWidth { 0 };
271
272     Glyph m_zeroWidthSpaceGlyph { 0 };
273
274     float m_glyphZeroWidth { 0 };
275
276     struct DerivedFontData {
277         explicit DerivedFontData(bool custom)
278             : forCustomFont(custom)
279         {
280         }
281         ~DerivedFontData();
282
283         bool forCustomFont;
284         RefPtr<Font> smallCaps;
285         RefPtr<Font> emphasisMark;
286         RefPtr<Font> brokenIdeograph;
287         RefPtr<Font> verticalRightOrientation;
288         RefPtr<Font> uprightOrientation;
289         RefPtr<Font> nonSyntheticItalic;
290 #if USE(APPKIT)
291         HashMap<NSFont*, RefPtr<Font>> compositeFontReferences;
292 #endif
293     };
294
295     mutable std::unique_ptr<DerivedFontData> m_derivedFontData;
296
297 #if USE(CG) || USE(CAIRO)
298     float m_syntheticBoldOffset;
299 #endif
300
301 #if PLATFORM(COCOA)
302     mutable HashMap<unsigned, RetainPtr<CFDictionaryRef>> m_CFStringAttributes;
303 #endif
304
305 #if PLATFORM(COCOA) || USE(HARFBUZZ)
306     mutable std::unique_ptr<HashMap<String, bool>> m_combiningCharacterSequenceSupport;
307 #endif
308
309 #if PLATFORM(WIN)
310     bool m_isSystemFont;
311     mutable SCRIPT_CACHE m_scriptCache;
312     mutable SCRIPT_FONTPROPERTIES* m_scriptFontProperties;
313 #endif
314 #if PLATFORM(IOS)
315     bool m_shouldNotBeUsedForArabic { false };
316 #endif
317 };
318
319 ALWAYS_INLINE FloatRect Font::boundsForGlyph(Glyph glyph) const
320 {
321     if (isZeroWidthSpaceGlyph(glyph))
322         return FloatRect();
323
324     FloatRect bounds;
325     if (m_glyphToBoundsMap) {
326         bounds = m_glyphToBoundsMap->metricsForGlyph(glyph);
327         if (bounds.width() != cGlyphSizeUnknown)
328             return bounds;
329     }
330
331     bounds = platformBoundsForGlyph(glyph);
332     if (!m_glyphToBoundsMap)
333         m_glyphToBoundsMap = std::make_unique<GlyphMetricsMap<FloatRect>>();
334     m_glyphToBoundsMap->setMetricsForGlyph(glyph, bounds);
335     return bounds;
336 }
337
338 } // namespace WebCore
339
340 #endif // Font_h