Laying out a TextRun using an SVG font is O(n^2)
[WebKit-https.git] / Source / WebCore / platform / graphics / SimpleFontData.h
1 /*
2  * This file is part of the internal font implementation.
3  *
4  * Copyright (C) 2006, 2008, 2010 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 SimpleFontData_h
25 #define SimpleFontData_h
26
27 #include "FontBaseline.h"
28 #include "FontData.h"
29 #include "FontMetrics.h"
30 #include "FontPlatformData.h"
31 #include "FloatRect.h"
32 #include "GlyphBuffer.h"
33 #include "GlyphMetricsMap.h"
34 #include "GlyphPageTreeNode.h"
35 #include "OpenTypeMathData.h"
36 #if ENABLE(OPENTYPE_VERTICAL)
37 #include "OpenTypeVerticalData.h"
38 #endif
39 #include "TypesettingFeatures.h"
40 #include <wtf/OwnPtr.h>
41 #include <wtf/PassOwnPtr.h>
42 #include <wtf/text/StringHash.h>
43
44 #if PLATFORM(COCOA)
45 #include "WebCoreSystemInterface.h"
46 #include <wtf/RetainPtr.h>
47 #endif
48
49 #if (PLATFORM(WIN) && !OS(WINCE))
50 #include <usp10.h>
51 #endif
52
53 #if USE(CAIRO)
54 #include <cairo.h>
55 #endif
56
57 #if USE(CG)
58 #if defined(__has_include) && __has_include(<CoreGraphics/CGFontRendering.h>)
59 #include <CoreGraphics/CGFontRendering.h>
60 #else
61 enum {
62     kCGFontRenderingStyleAntialiasing = (1 << 0),
63     kCGFontRenderingStyleSmoothing = (1 << 1),
64     kCGFontRenderingStyleSubpixelPositioning = (1 << 2),
65     kCGFontRenderingStyleSubpixelQuantization = (1 << 3),
66     kCGFontRenderingStylePlatformNative = (1 << 9),
67     kCGFontRenderingStyleMask = 0x20F
68 };
69 #endif
70 typedef uint32_t CGFontRenderingStyle;
71 #endif
72
73 namespace WebCore {
74
75 class FontDescription;
76 class SharedBuffer;
77 struct WidthIterator;
78
79 enum FontDataVariant { AutoVariant, NormalVariant, SmallCapsVariant, EmphasisMarkVariant, BrokenIdeographVariant };
80 enum Pitch { UnknownPitch, FixedPitch, VariablePitch };
81
82 class SimpleFontData final : public FontData {
83 public:
84     class AdditionalFontData {
85         WTF_MAKE_FAST_ALLOCATED;
86     public:
87         virtual ~AdditionalFontData() { }
88
89         virtual void initializeFontData(SimpleFontData*, float fontSize) = 0;
90         virtual float widthForSVGGlyph(Glyph, float fontSize) const = 0;
91         virtual bool fillSVGGlyphPage(GlyphPage*, unsigned offset, unsigned length, UChar* buffer, unsigned bufferLength, const SimpleFontData*) const = 0;
92         virtual bool applySVGGlyphSelection(WidthIterator&, GlyphData&, bool mirror, int currentCharacter, unsigned& advanceLength, String& normalizedSpacesStringCache) const = 0;
93     };
94
95     // Used to create platform fonts.
96     static PassRefPtr<SimpleFontData> create(const FontPlatformData& platformData, bool isCustomFont = false, bool isLoading = false, bool isTextOrientationFallback = false)
97     {
98         return adoptRef(new SimpleFontData(platformData, isCustomFont, isLoading, isTextOrientationFallback));
99     }
100
101     // Used to create SVG Fonts.
102     static PassRefPtr<SimpleFontData> create(std::unique_ptr<AdditionalFontData> fontData, float fontSize, bool syntheticBold, bool syntheticItalic)
103     {
104         return adoptRef(new SimpleFontData(WTF::move(fontData), fontSize, syntheticBold, syntheticItalic));
105     }
106
107     virtual ~SimpleFontData();
108
109     static const SimpleFontData* systemFallback() { return reinterpret_cast<const SimpleFontData*>(-1); }
110
111     const FontPlatformData& platformData() const { return m_platformData; }
112     const OpenTypeMathData* mathData() const;
113 #if ENABLE(OPENTYPE_VERTICAL)
114     const OpenTypeVerticalData* verticalData() const { return m_verticalData.get(); }
115 #endif
116
117     PassRefPtr<SimpleFontData> smallCapsFontData(const FontDescription&) const;
118     PassRefPtr<SimpleFontData> emphasisMarkFontData(const FontDescription&) const;
119     PassRefPtr<SimpleFontData> brokenIdeographFontData() const;
120     PassRefPtr<SimpleFontData> nonSyntheticItalicFontData() const;
121
122     PassRefPtr<SimpleFontData> variantFontData(const FontDescription& description, FontDataVariant variant) const
123     {
124         switch (variant) {
125         case SmallCapsVariant:
126             return smallCapsFontData(description);
127         case EmphasisMarkVariant:
128             return emphasisMarkFontData(description);
129         case BrokenIdeographVariant:
130             return brokenIdeographFontData();
131         case AutoVariant:
132         case NormalVariant:
133             break;
134         }
135         ASSERT_NOT_REACHED();
136         return const_cast<SimpleFontData*>(this);
137     }
138
139     PassRefPtr<SimpleFontData> verticalRightOrientationFontData() const;
140     PassRefPtr<SimpleFontData> uprightOrientationFontData() const;
141
142     bool hasVerticalGlyphs() const { return m_hasVerticalGlyphs; }
143     bool isTextOrientationFallback() const { return m_isTextOrientationFallback; }
144
145     FontMetrics& fontMetrics() { return m_fontMetrics; }
146     const FontMetrics& fontMetrics() const { return m_fontMetrics; }
147     float sizePerUnit() const { return platformData().size() / (fontMetrics().unitsPerEm() ? fontMetrics().unitsPerEm() : 1); }
148
149     float maxCharWidth() const { return m_maxCharWidth; }
150     void setMaxCharWidth(float maxCharWidth) { m_maxCharWidth = maxCharWidth; }
151
152     float avgCharWidth() const { return m_avgCharWidth; }
153     void setAvgCharWidth(float avgCharWidth) { m_avgCharWidth = avgCharWidth; }
154
155     FloatRect boundsForGlyph(Glyph) const;
156     float widthForGlyph(Glyph glyph) const;
157     FloatRect platformBoundsForGlyph(Glyph) const;
158     float platformWidthForGlyph(Glyph) const;
159
160     float spaceWidth() const { return m_spaceWidth; }
161     float adjustedSpaceWidth() const { return m_adjustedSpaceWidth; }
162     void setSpaceWidth(float spaceWidth) { m_spaceWidth = spaceWidth; }
163
164 #if USE(CG) || USE(CAIRO)
165     float syntheticBoldOffset() const { return m_syntheticBoldOffset; }
166 #endif
167
168     Glyph spaceGlyph() const { return m_spaceGlyph; }
169     void setSpaceGlyph(Glyph spaceGlyph) { m_spaceGlyph = spaceGlyph; }
170     Glyph zeroWidthSpaceGlyph() const { return m_zeroWidthSpaceGlyph; }
171     void setZeroWidthSpaceGlyph(Glyph spaceGlyph) { m_zeroWidthSpaceGlyph = spaceGlyph; }
172     bool isZeroWidthSpaceGlyph(Glyph glyph) const { return glyph == m_zeroWidthSpaceGlyph && glyph; }
173     Glyph zeroGlyph() const { return m_zeroGlyph; }
174     void setZeroGlyph(Glyph zeroGlyph) { m_zeroGlyph = zeroGlyph; }
175
176     virtual const SimpleFontData* fontDataForCharacter(UChar32) const override;
177     virtual bool containsCharacters(const UChar*, int length) const override;
178
179     Glyph glyphForCharacter(UChar32) const;
180
181     void determinePitch();
182     Pitch pitch() const { return m_treatAsFixedPitch ? FixedPitch : VariablePitch; }
183
184     AdditionalFontData* fontData() const { return m_fontData.get(); }
185     bool isSVGFont() const { return m_fontData != nullptr; }
186
187     virtual bool isCustomFont() const override { return m_isCustomFont; }
188     virtual bool isLoading() const override { return m_isLoading; }
189     virtual bool isSegmented() const override;
190
191     const GlyphData& missingGlyphData() const { return m_missingGlyphData; }
192     void setMissingGlyphData(const GlyphData& glyphData) { m_missingGlyphData = glyphData; }
193
194 #ifndef NDEBUG
195     virtual String description() const override;
196 #endif
197
198 #if USE(APPKIT)
199     const SimpleFontData* getCompositeFontReferenceFontData(NSFont *key) const;
200     NSFont* getNSFont() const { return m_platformData.font(); }
201 #endif
202
203 #if PLATFORM(IOS)
204     CTFontRef getCTFont() const { return m_platformData.font(); }
205     bool shouldNotBeUsedForArabic() const { return m_shouldNotBeUsedForArabic; };
206 #endif
207 #if PLATFORM(COCOA)
208     CFDictionaryRef getCFStringAttributes(TypesettingFeatures, FontOrientation) const;
209 #endif
210
211 #if PLATFORM(COCOA) || USE(HARFBUZZ)
212     bool canRenderCombiningCharacterSequence(const UChar*, size_t) const;
213 #endif
214
215     bool applyTransforms(GlyphBufferGlyph* glyphs, GlyphBufferAdvance* advances, size_t glyphCount, TypesettingFeatures typesettingFeatures) const
216     {
217         if (isSVGFont())
218             return false;
219 #if PLATFORM(IOS) || (PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED > 1080)
220         wkCTFontTransformOptions options = (typesettingFeatures & Kerning ? wkCTFontTransformApplyPositioning : 0) | (typesettingFeatures & Ligatures ? wkCTFontTransformApplyShaping : 0);
221         return wkCTFontTransformGlyphs(m_platformData.ctFont(), glyphs, reinterpret_cast<CGSize*>(advances), glyphCount, options);
222 #else
223         UNUSED_PARAM(glyphs);
224         UNUSED_PARAM(advances);
225         UNUSED_PARAM(glyphCount);
226         UNUSED_PARAM(typesettingFeatures);
227         return false;
228 #endif
229     }
230
231 #if PLATFORM(WIN)
232     bool isSystemFont() const { return m_isSystemFont; }
233 #if !OS(WINCE) // disable unused members to save space
234     SCRIPT_FONTPROPERTIES* scriptFontProperties() const;
235     SCRIPT_CACHE* scriptCache() const { return &m_scriptCache; }
236 #endif
237     static void setShouldApplyMacAscentHack(bool);
238     static bool shouldApplyMacAscentHack();
239     static float ascentConsideringMacAscentHack(const WCHAR*, float ascent, float descent);
240 #endif
241
242 private:
243     SimpleFontData(const FontPlatformData&, bool isCustomFont = false, bool isLoading = false, bool isTextOrientationFallback = false);
244
245     SimpleFontData(std::unique_ptr<AdditionalFontData>, float fontSize, bool syntheticBold, bool syntheticItalic);
246
247     void platformInit();
248     void platformGlyphInit();
249     void platformCharWidthInit();
250     void platformDestroy();
251
252     void initCharWidths();
253
254     PassRefPtr<SimpleFontData> createScaledFontData(const FontDescription&, float scaleFactor) const;
255     PassRefPtr<SimpleFontData> platformCreateScaledFontData(const FontDescription&, float scaleFactor) const;
256
257 #if (PLATFORM(WIN) && !OS(WINCE))
258     void initGDIFont();
259     void platformCommonDestroy();
260     FloatRect boundsForGDIGlyph(Glyph glyph) const;
261     float widthForGDIGlyph(Glyph glyph) const;
262 #endif
263
264 #if USE(CG)
265     bool canUseFastGlyphAdvanceGetter(Glyph glyph, CGSize& advance, bool& populatedAdvance) const;
266     CGFontRenderingStyle renderingStyle() const;
267     bool advanceForColorBitmapFont(Glyph, CGSize& result) const; // Returns true if the font is a color bitmap font
268 #endif
269
270     FontMetrics m_fontMetrics;
271     float m_maxCharWidth;
272     float m_avgCharWidth;
273
274     FontPlatformData m_platformData;
275     std::unique_ptr<AdditionalFontData> m_fontData;
276
277     mutable OwnPtr<GlyphMetricsMap<FloatRect>> m_glyphToBoundsMap;
278     mutable GlyphMetricsMap<float> m_glyphToWidthMap;
279
280     bool m_treatAsFixedPitch;
281     bool m_isCustomFont;  // Whether or not we are custom font loaded via @font-face
282     bool m_isLoading; // Whether or not this custom font is still in the act of loading.
283
284     bool m_isTextOrientationFallback;
285     bool m_isBrokenIdeographFallback;
286     mutable RefPtr<OpenTypeMathData> m_mathData;
287 #if ENABLE(OPENTYPE_VERTICAL)
288     RefPtr<OpenTypeVerticalData> m_verticalData;
289 #endif
290     bool m_hasVerticalGlyphs;
291
292     Glyph m_spaceGlyph;
293     float m_spaceWidth;
294     Glyph m_zeroGlyph;
295     float m_adjustedSpaceWidth;
296
297     Glyph m_zeroWidthSpaceGlyph;
298
299     GlyphData m_missingGlyphData;
300
301     struct DerivedFontData {
302         static PassOwnPtr<DerivedFontData> create(bool forCustomFont);
303         ~DerivedFontData();
304
305         bool forCustomFont;
306         RefPtr<SimpleFontData> smallCaps;
307         RefPtr<SimpleFontData> emphasisMark;
308         RefPtr<SimpleFontData> brokenIdeograph;
309         RefPtr<SimpleFontData> verticalRightOrientation;
310         RefPtr<SimpleFontData> uprightOrientation;
311         RefPtr<SimpleFontData> nonSyntheticItalic;
312 #if PLATFORM(COCOA)
313         mutable RetainPtr<CFMutableDictionaryRef> compositeFontReferences;
314 #endif
315
316     private:
317         DerivedFontData(bool custom)
318             : forCustomFont(custom)
319         {
320         }
321     };
322
323     mutable OwnPtr<DerivedFontData> m_derivedFontData;
324
325 #if USE(CG) || USE(CAIRO)
326     float m_syntheticBoldOffset;
327 #endif
328
329 #if PLATFORM(COCOA)
330     mutable HashMap<unsigned, RetainPtr<CFDictionaryRef>> m_CFStringAttributes;
331 #endif
332
333 #if PLATFORM(COCOA) || USE(HARFBUZZ)
334     mutable OwnPtr<HashMap<String, bool>> m_combiningCharacterSequenceSupport;
335 #endif
336
337 #if PLATFORM(WIN)
338     bool m_isSystemFont;
339 #if !OS(WINCE) // disable unused members to save space
340     mutable SCRIPT_CACHE m_scriptCache;
341     mutable SCRIPT_FONTPROPERTIES* m_scriptFontProperties;
342 #endif
343 #endif
344 #if PLATFORM(IOS)
345     bool m_shouldNotBeUsedForArabic;
346 #endif
347 };
348
349 ALWAYS_INLINE FloatRect SimpleFontData::boundsForGlyph(Glyph glyph) const
350 {
351     if (isZeroWidthSpaceGlyph(glyph))
352         return FloatRect();
353
354     FloatRect bounds;
355     if (m_glyphToBoundsMap) {
356         bounds = m_glyphToBoundsMap->metricsForGlyph(glyph);
357         if (bounds.width() != cGlyphSizeUnknown)
358             return bounds;
359     }
360
361     bounds = platformBoundsForGlyph(glyph);
362     if (!m_glyphToBoundsMap)
363         m_glyphToBoundsMap = adoptPtr(new GlyphMetricsMap<FloatRect>);
364     m_glyphToBoundsMap->setMetricsForGlyph(glyph, bounds);
365     return bounds;
366 }
367
368 ALWAYS_INLINE float SimpleFontData::widthForGlyph(Glyph glyph) const
369 {
370     if (isZeroWidthSpaceGlyph(glyph))
371         return 0;
372
373     float width = m_glyphToWidthMap.metricsForGlyph(glyph);
374     if (width != cGlyphSizeUnknown)
375         return width;
376
377     if (m_fontData)
378         width = m_fontData->widthForSVGGlyph(glyph, m_platformData.size());
379 #if ENABLE(OPENTYPE_VERTICAL)
380     else if (m_verticalData)
381 #if USE(CG) || USE(CAIRO)
382         width = m_verticalData->advanceHeight(this, glyph) + m_syntheticBoldOffset;
383 #else
384         width = m_verticalData->advanceHeight(this, glyph);
385 #endif
386 #endif
387     else
388         width = platformWidthForGlyph(glyph);
389
390     m_glyphToWidthMap.setMetricsForGlyph(glyph, width);
391     return width;
392 }
393
394 } // namespace WebCore
395 #endif // SimpleFontData_h