[iOS] Arabic text styled with Georgia is rendered as boxes
[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     float widthForGlyph(Glyph) const;
144     FloatRect platformBoundsForGlyph(Glyph) const;
145     float platformWidthForGlyph(Glyph) const;
146
147     float spaceWidth() const { return m_spaceWidth; }
148     float adjustedSpaceWidth() const { return m_adjustedSpaceWidth; }
149     void setSpaceWidths(float spaceWidth)
150     {
151         m_spaceWidth = spaceWidth;
152         m_adjustedSpaceWidth = spaceWidth;
153     }
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     Glyph zeroGlyph() const { return m_zeroGlyph; }
165     void setZeroGlyph(Glyph zeroGlyph) { m_zeroGlyph = zeroGlyph; }
166
167     GlyphData glyphDataForCharacter(UChar32) const;
168     Glyph glyphForCharacter(UChar32) const;
169
170     RefPtr<Font> systemFallbackFontForCharacter(UChar32, const FontDescription&, bool isForPlatformFont) const;
171
172     const GlyphPage* glyphPage(unsigned pageNumber) const;
173
174     void determinePitch();
175     Pitch pitch() const { return m_treatAsFixedPitch ? FixedPitch : VariablePitch; }
176
177     const SVGData* svgData() const { return m_svgData.get(); }
178     bool isSVGFont() const { return !!m_svgData; }
179
180     bool isCustomFont() const { return m_isCustomFont; }
181     bool isLoading() const { return m_isLoading; }
182
183 #ifndef NDEBUG
184     String description() const;
185 #endif
186
187 #if USE(APPKIT)
188     const Font* compositeFontReferenceFont(NSFont *key) const;
189     NSFont* getNSFont() const { return m_platformData.nsFont(); }
190 #endif
191
192 #if PLATFORM(IOS)
193     CTFontRef getCTFont() const { return m_platformData.font(); }
194     bool shouldNotBeUsedForArabic() const { return m_shouldNotBeUsedForArabic; };
195 #endif
196 #if PLATFORM(COCOA)
197     CFDictionaryRef getCFStringAttributes(TypesettingFeatures, FontOrientation) const;
198     bool hasCustomTracking() const { return isSystemFont(); }
199 #endif
200
201 #if PLATFORM(COCOA) || USE(HARFBUZZ)
202     bool canRenderCombiningCharacterSequence(const UChar*, size_t) const;
203 #endif
204
205     bool applyTransforms(GlyphBufferGlyph*, GlyphBufferAdvance*, size_t glyphCount, TypesettingFeatures) const;
206
207 #if PLATFORM(COCOA) || PLATFORM(WIN)
208     bool isSystemFont() const { return m_isSystemFont; }
209 #endif
210
211 #if PLATFORM(WIN)
212     SCRIPT_FONTPROPERTIES* scriptFontProperties() const;
213     SCRIPT_CACHE* scriptCache() const { return &m_scriptCache; }
214     static void setShouldApplyMacAscentHack(bool);
215     static bool shouldApplyMacAscentHack();
216     static float ascentConsideringMacAscentHack(const WCHAR*, float ascent, float descent);
217 #endif
218
219 private:
220     Font(const FontPlatformData&, bool isCustomFont = false, bool isLoading = false, bool isTextOrientationFallback = false);
221
222     Font(std::unique_ptr<SVGData>, float fontSize, bool syntheticBold, bool syntheticItalic);
223
224     Font(const FontPlatformData&, std::unique_ptr<SVGData>&&, bool isCustomFont = false, bool isLoading = false, bool isTextOrientationFallback = false);
225
226     void platformInit();
227     void platformGlyphInit();
228     void platformCharWidthInit();
229     void platformDestroy();
230
231     void initCharWidths();
232
233     PassRefPtr<Font> createScaledFont(const FontDescription&, float scaleFactor) const;
234     PassRefPtr<Font> platformCreateScaledFont(const FontDescription&, float scaleFactor) const;
235
236     void removeFromSystemFallbackCache();
237
238 #if PLATFORM(WIN)
239     void initGDIFont();
240     void platformCommonDestroy();
241     FloatRect boundsForGDIGlyph(Glyph) const;
242     float widthForGDIGlyph(Glyph) const;
243 #endif
244
245     FontMetrics m_fontMetrics;
246     float m_maxCharWidth;
247     float m_avgCharWidth;
248
249     FontPlatformData m_platformData;
250     std::unique_ptr<SVGData> m_svgData;
251
252     mutable RefPtr<GlyphPage> m_glyphPageZero;
253     mutable HashMap<unsigned, RefPtr<GlyphPage>> m_glyphPages;
254     mutable std::unique_ptr<GlyphMetricsMap<FloatRect>> m_glyphToBoundsMap;
255     mutable GlyphMetricsMap<float> m_glyphToWidthMap;
256
257     mutable RefPtr<OpenTypeMathData> m_mathData;
258 #if ENABLE(OPENTYPE_VERTICAL)
259     RefPtr<OpenTypeVerticalData> m_verticalData;
260 #endif
261
262     Glyph m_spaceGlyph;
263     float m_spaceWidth;
264     Glyph m_zeroGlyph;
265     float m_adjustedSpaceWidth;
266
267     Glyph m_zeroWidthSpaceGlyph;
268
269     struct DerivedFontData {
270         explicit DerivedFontData(bool custom)
271             : forCustomFont(custom)
272         {
273         }
274         ~DerivedFontData();
275
276         bool forCustomFont;
277         RefPtr<Font> smallCaps;
278         RefPtr<Font> emphasisMark;
279         RefPtr<Font> brokenIdeograph;
280         RefPtr<Font> verticalRightOrientation;
281         RefPtr<Font> uprightOrientation;
282         RefPtr<Font> nonSyntheticItalic;
283 #if USE(APPKIT)
284         HashMap<NSFont*, RefPtr<Font>> compositeFontReferences;
285 #endif
286     };
287
288     mutable std::unique_ptr<DerivedFontData> m_derivedFontData;
289
290 #if USE(CG) || USE(CAIRO)
291     float m_syntheticBoldOffset;
292 #endif
293
294 #if PLATFORM(COCOA)
295     mutable HashMap<unsigned, RetainPtr<CFDictionaryRef>> m_CFStringAttributes;
296 #endif
297
298 #if PLATFORM(COCOA) || USE(HARFBUZZ)
299     mutable std::unique_ptr<HashMap<String, bool>> m_combiningCharacterSequenceSupport;
300 #endif
301
302 #if PLATFORM(WIN)
303     mutable SCRIPT_CACHE m_scriptCache;
304     mutable SCRIPT_FONTPROPERTIES* m_scriptFontProperties;
305 #endif
306
307     unsigned m_treatAsFixedPitch : 1;
308     unsigned m_isCustomFont : 1; // Whether or not we are custom font loaded via @font-face
309     unsigned m_isLoading : 1; // Whether or not this custom font is still in the act of loading.
310
311     unsigned m_isTextOrientationFallback : 1;
312     unsigned m_isBrokenIdeographFallback : 1;
313     unsigned m_hasVerticalGlyphs : 1;
314
315     unsigned m_isUsedInSystemFallbackCache : 1;
316
317 #if PLATFORM(COCOA) || PLATFORM(WIN)
318     unsigned m_isSystemFont : 1;
319 #endif
320 #if PLATFORM(IOS)
321     unsigned m_shouldNotBeUsedForArabic : 1;
322 #endif
323 };
324
325 #if PLATFORM(IOS)
326 bool fontFamilyShouldNotBeUsedForArabic(CFStringRef);
327 #endif
328
329 ALWAYS_INLINE FloatRect Font::boundsForGlyph(Glyph glyph) const
330 {
331     if (isZeroWidthSpaceGlyph(glyph))
332         return FloatRect();
333
334     FloatRect bounds;
335     if (m_glyphToBoundsMap) {
336         bounds = m_glyphToBoundsMap->metricsForGlyph(glyph);
337         if (bounds.width() != cGlyphSizeUnknown)
338             return bounds;
339     }
340
341     bounds = platformBoundsForGlyph(glyph);
342     if (!m_glyphToBoundsMap)
343         m_glyphToBoundsMap = std::make_unique<GlyphMetricsMap<FloatRect>>();
344     m_glyphToBoundsMap->setMetricsForGlyph(glyph, bounds);
345     return bounds;
346 }
347
348 ALWAYS_INLINE float Font::widthForGlyph(Glyph glyph) const
349 {
350     if (isZeroWidthSpaceGlyph(glyph))
351         return 0;
352
353     float width = m_glyphToWidthMap.metricsForGlyph(glyph);
354     if (width != cGlyphSizeUnknown)
355         return width;
356
357     if (isSVGFont())
358         width = m_svgData->widthForSVGGlyph(glyph, m_platformData.size());
359 #if ENABLE(OPENTYPE_VERTICAL)
360     else if (m_verticalData)
361 #if USE(CG) || USE(CAIRO)
362         width = m_verticalData->advanceHeight(this, glyph) + m_syntheticBoldOffset;
363 #else
364         width = m_verticalData->advanceHeight(this, glyph);
365 #endif
366 #endif
367     else
368         width = platformWidthForGlyph(glyph);
369
370     m_glyphToWidthMap.setMetricsForGlyph(glyph, width);
371     return width;
372 }
373
374 } // namespace WebCore
375
376 #endif // Font_h