[iOS] Upstream text autosizing
[WebKit-https.git] / Source / WebCore / platform / graphics / Font.h
1 /*
2  * Copyright (C) 2000 Lars Knoll (knoll@kde.org)
3  *           (C) 2000 Antti Koivisto (koivisto@kde.org)
4  *           (C) 2000 Dirk Mueller (mueller@kde.org)
5  * Copyright (C) 2003, 2006, 2007, 2010, 2011 Apple Inc. All rights reserved.
6  * Copyright (C) 2008 Holger Hans Peter Freyther
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Library General Public
10  * License as published by the Free Software Foundation; either
11  * version 2 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Library General Public License for more details.
17  *
18  * You should have received a copy of the GNU Library General Public License
19  * along with this library; see the file COPYING.LIB.  If not, write to
20  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21  * Boston, MA 02110-1301, USA.
22  *
23  */
24
25 #ifndef Font_h
26 #define Font_h
27
28 #include "FontDescription.h"
29 #include "FontGlyphs.h"
30 #include "SimpleFontData.h"
31 #include "TextDirection.h"
32 #include "TypesettingFeatures.h"
33 #include <wtf/HashMap.h>
34 #include <wtf/HashSet.h>
35 #include <wtf/MathExtras.h>
36 #include <wtf/unicode/CharacterNames.h>
37
38 #if PLATFORM(QT)
39 #include <QRawFont>
40 QT_BEGIN_NAMESPACE
41 class QTextLayout;
42 QT_END_NAMESPACE
43 #endif
44
45 // "X11/X.h" defines Complex to 0 and conflicts
46 // with Complex value in CodePath enum.
47 #ifdef Complex
48 #undef Complex
49 #endif
50
51 namespace WebCore {
52
53 class FloatPoint;
54 class FloatRect;
55 class FontData;
56 class FontMetrics;
57 class FontPlatformData;
58 class FontSelector;
59 class GlyphBuffer;
60 class GraphicsContext;
61 class RenderText;
62 class TextLayout;
63 class TextRun;
64
65 struct GlyphData;
66
67 struct GlyphOverflow {
68     GlyphOverflow()
69         : left(0)
70         , right(0)
71         , top(0)
72         , bottom(0)
73         , computeBounds(false)
74     {
75     }
76
77     int left;
78     int right;
79     int top;
80     int bottom;
81     bool computeBounds;
82 };
83
84
85 class Font {
86 public:
87     Font();
88     Font(const FontDescription&, short letterSpacing, short wordSpacing);
89     // This constructor is only used if the platform wants to start with a native font.
90     Font(const FontPlatformData&, bool isPrinting, FontSmoothingMode = AutoSmoothing);
91     ~Font();
92
93     Font(const Font&);
94     Font& operator=(const Font&);
95
96     bool operator==(const Font& other) const;
97     bool operator!=(const Font& other) const { return !(*this == other); }
98
99     const FontDescription& fontDescription() const { return m_fontDescription; }
100
101     int pixelSize() const { return fontDescription().computedPixelSize(); }
102     float size() const { return fontDescription().computedSize(); }
103
104     void update(PassRefPtr<FontSelector>) const;
105
106     enum CustomFontNotReadyAction { DoNotPaintIfFontNotReady, UseFallbackIfFontNotReady };
107     void drawText(GraphicsContext*, const TextRun&, const FloatPoint&, int from = 0, int to = -1, CustomFontNotReadyAction = DoNotPaintIfFontNotReady) const;
108     void drawEmphasisMarks(GraphicsContext*, const TextRun&, const AtomicString& mark, const FloatPoint&, int from = 0, int to = -1) const;
109
110     float width(const TextRun&, HashSet<const SimpleFontData*>* fallbackFonts = 0, GlyphOverflow* = 0) const;
111     float width(const TextRun&, int& charsConsumed, String& glyphName) const;
112
113     PassOwnPtr<TextLayout> createLayout(RenderText*, float xPos, bool collapseWhiteSpace) const;
114     static void deleteLayout(TextLayout*);
115     static float width(TextLayout&, unsigned from, unsigned len, HashSet<const SimpleFontData*>* fallbackFonts = 0);
116
117     int offsetForPosition(const TextRun&, float position, bool includePartialGlyphs) const;
118     FloatRect selectionRectForText(const TextRun&, const FloatPoint&, int h, int from = 0, int to = -1) const;
119
120     bool isSmallCaps() const { return m_fontDescription.smallCaps(); }
121
122     short wordSpacing() const { return m_wordSpacing; }
123     short letterSpacing() const { return m_letterSpacing; }
124     void setWordSpacing(short s) { m_wordSpacing = s; }
125     void setLetterSpacing(short s) { m_letterSpacing = s; }
126     bool isFixedPitch() const;
127     bool isPrinterFont() const { return m_fontDescription.usePrinterFont(); }
128     
129     FontRenderingMode renderingMode() const { return m_fontDescription.renderingMode(); }
130
131     TypesettingFeatures typesettingFeatures() const { return static_cast<TypesettingFeatures>(m_typesettingFeatures); }
132
133     const AtomicString& firstFamily() const { return m_fontDescription.firstFamily(); }
134     unsigned familyCount() const { return m_fontDescription.familyCount(); }
135     const AtomicString& familyAt(unsigned i) const { return m_fontDescription.familyAt(i); }
136
137     FontItalic italic() const { return m_fontDescription.italic(); }
138     FontWeight weight() const { return m_fontDescription.weight(); }
139     FontWidthVariant widthVariant() const { return m_fontDescription.widthVariant(); }
140
141     bool isPlatformFont() const { return m_glyphs->isForPlatformFont(); }
142
143     const FontMetrics& fontMetrics() const { return primaryFont()->fontMetrics(); }
144     float spaceWidth() const { return primaryFont()->spaceWidth() + m_letterSpacing; }
145     float tabWidth(const SimpleFontData&, unsigned tabSize, float position) const;
146     float tabWidth(unsigned tabSize, float position) const { return tabWidth(*primaryFont(), tabSize, position); }
147
148     int emphasisMarkAscent(const AtomicString&) const;
149     int emphasisMarkDescent(const AtomicString&) const;
150     int emphasisMarkHeight(const AtomicString&) const;
151
152     const SimpleFontData* primaryFont() const;
153     const FontData* fontDataAt(unsigned) const;
154     GlyphData glyphDataForCharacter(UChar32 c, bool mirror, FontDataVariant variant = AutoVariant) const
155     {
156         return glyphDataAndPageForCharacter(c, mirror, variant).first;
157     }
158 #if PLATFORM(MAC)
159     const SimpleFontData* fontDataForCombiningCharacterSequence(const UChar*, size_t length, FontDataVariant) const;
160 #endif
161     std::pair<GlyphData, GlyphPage*> glyphDataAndPageForCharacter(UChar32 c, bool mirror, FontDataVariant variant) const
162     {
163         return m_glyphs->glyphDataAndPageForCharacter(m_fontDescription, c, mirror, variant);
164     }
165     bool primaryFontHasGlyphForCharacter(UChar32) const;
166
167     static bool isCJKIdeograph(UChar32);
168     static bool isCJKIdeographOrSymbol(UChar32);
169
170     static unsigned expansionOpportunityCount(const LChar*, size_t length, TextDirection, bool& isAfterExpansion);
171     static unsigned expansionOpportunityCount(const UChar*, size_t length, TextDirection, bool& isAfterExpansion);
172
173 #if PLATFORM(QT)
174     QRawFont rawFont() const;
175     QFont syntheticFont() const;
176 #endif
177
178     static void setShouldUseSmoothing(bool);
179     static bool shouldUseSmoothing();
180
181     enum CodePath { Auto, Simple, Complex, SimpleWithGlyphOverflow };
182     CodePath codePath(const TextRun&) const;
183     static CodePath characterRangeCodePath(const LChar*, unsigned) { return Simple; }
184     static CodePath characterRangeCodePath(const UChar*, unsigned len);
185
186 private:
187     enum ForTextEmphasisOrNot { NotForTextEmphasis, ForTextEmphasis };
188
189     // Returns the initial in-stream advance.
190     float getGlyphsAndAdvancesForSimpleText(const TextRun&, int from, int to, GlyphBuffer&, ForTextEmphasisOrNot = NotForTextEmphasis) const;
191     void drawSimpleText(GraphicsContext*, const TextRun&, const FloatPoint&, int from, int to) const;
192     void drawEmphasisMarksForSimpleText(GraphicsContext*, const TextRun&, const AtomicString& mark, const FloatPoint&, int from, int to) const;
193     void drawGlyphs(GraphicsContext*, const SimpleFontData*, const GlyphBuffer&, int from, int to, const FloatPoint&) const;
194     void drawGlyphBuffer(GraphicsContext*, const TextRun&, const GlyphBuffer&, const FloatPoint&) const;
195     void drawEmphasisMarks(GraphicsContext*, const TextRun&, const GlyphBuffer&, const AtomicString&, const FloatPoint&) const;
196     float floatWidthForSimpleText(const TextRun&, HashSet<const SimpleFontData*>* fallbackFonts = 0, GlyphOverflow* = 0) const;
197     int offsetForPositionForSimpleText(const TextRun&, float position, bool includePartialGlyphs) const;
198     FloatRect selectionRectForSimpleText(const TextRun&, const FloatPoint&, int h, int from, int to) const;
199
200     bool getEmphasisMarkGlyphData(const AtomicString&, GlyphData&) const;
201
202     static bool canReturnFallbackFontsForComplexText();
203     static bool canExpandAroundIdeographsInComplexText();
204
205     // Returns the initial in-stream advance.
206     float getGlyphsAndAdvancesForComplexText(const TextRun&, int from, int to, GlyphBuffer&, ForTextEmphasisOrNot = NotForTextEmphasis) const;
207     void drawComplexText(GraphicsContext*, const TextRun&, const FloatPoint&, int from, int to) const;
208     void drawEmphasisMarksForComplexText(GraphicsContext*, const TextRun&, const AtomicString& mark, const FloatPoint&, int from, int to) const;
209     float floatWidthForComplexText(const TextRun&, HashSet<const SimpleFontData*>* fallbackFonts = 0, GlyphOverflow* = 0) const;
210     int offsetForPositionForComplexText(const TextRun&, float position, bool includePartialGlyphs) const;
211     FloatRect selectionRectForComplexText(const TextRun&, const FloatPoint&, int h, int from, int to) const;
212
213     friend struct WidthIterator;
214     friend class SVGTextRunRenderingContext;
215
216 public:
217 #if ENABLE(IOS_TEXT_AUTOSIZING)
218     bool equalForTextAutoSizing(const Font& other) const
219     {
220         return m_fontDescription.equalForTextAutoSizing(other.m_fontDescription)
221             && m_letterSpacing == other.m_letterSpacing
222             && m_wordSpacing == other.m_wordSpacing;
223     }
224 #endif
225
226     // Useful for debugging the different font rendering code paths.
227     static void setCodePath(CodePath);
228     static CodePath codePath();
229     static CodePath s_codePath;
230
231     static void setDefaultTypesettingFeatures(TypesettingFeatures);
232     static TypesettingFeatures defaultTypesettingFeatures();
233
234     static const uint8_t s_roundingHackCharacterTable[256];
235     static bool isRoundingHackCharacter(UChar32 c)
236     {
237         return !(c & ~0xFF) && s_roundingHackCharacterTable[c];
238     }
239
240     FontSelector* fontSelector() const;
241     static bool treatAsSpace(UChar c) { return c == ' ' || c == '\t' || c == '\n' || c == noBreakSpace; }
242     static bool treatAsZeroWidthSpace(UChar c) { return treatAsZeroWidthSpaceInComplexScript(c) || c == 0x200c || c == 0x200d; }
243     static bool treatAsZeroWidthSpaceInComplexScript(UChar c) { return c < 0x20 || (c >= 0x7F && c < 0xA0) || c == softHyphen || c == zeroWidthSpace || (c >= 0x200e && c <= 0x200f) || (c >= 0x202a && c <= 0x202e) || c == zeroWidthNoBreakSpace || c == objectReplacementCharacter; }
244     static bool canReceiveTextEmphasis(UChar32 c);
245
246     static inline UChar normalizeSpaces(UChar character)
247     {
248         if (treatAsSpace(character))
249             return space;
250
251         if (treatAsZeroWidthSpace(character))
252             return zeroWidthSpace;
253
254         return character;
255     }
256
257     static String normalizeSpaces(const LChar*, unsigned length);
258     static String normalizeSpaces(const UChar*, unsigned length);
259
260     bool needsTranscoding() const { return m_needsTranscoding; }
261     FontGlyphs* glyphs() const { return m_glyphs.get(); }
262
263 private:
264     bool loadingCustomFonts() const
265     {
266         return m_glyphs && m_glyphs->loadingCustomFonts();
267     }
268
269     TypesettingFeatures computeTypesettingFeatures() const
270     {
271         TextRenderingMode textRenderingMode = m_fontDescription.textRenderingMode();
272         TypesettingFeatures features = s_defaultTypesettingFeatures;
273
274         switch (textRenderingMode) {
275         case AutoTextRendering:
276             break;
277         case OptimizeSpeed:
278             features &= ~(Kerning | Ligatures);
279             break;
280         case GeometricPrecision:
281         case OptimizeLegibility:
282             features |= Kerning | Ligatures;
283             break;
284         }
285
286         switch (m_fontDescription.kerning()) {
287         case FontDescription::NoneKerning:
288             features &= ~Kerning;
289             break;
290         case FontDescription::NormalKerning:
291             features |= Kerning;
292             break;
293         case FontDescription::AutoKerning:
294             break;
295         }
296
297         switch (m_fontDescription.commonLigaturesState()) {
298         case FontDescription::DisabledLigaturesState:
299             features &= ~Ligatures;
300             break;
301         case FontDescription::EnabledLigaturesState:
302             features |= Ligatures;
303             break;
304         case FontDescription::NormalLigaturesState:
305             break;
306         }
307
308         return features;
309     }
310
311 #if PLATFORM(QT)
312     void initFormatForTextLayout(QTextLayout*, const TextRun&) const;
313 #endif
314
315     static TypesettingFeatures s_defaultTypesettingFeatures;
316
317     FontDescription m_fontDescription;
318     mutable RefPtr<FontGlyphs> m_glyphs;
319     short m_letterSpacing;
320     short m_wordSpacing;
321     bool m_needsTranscoding;
322     mutable unsigned m_typesettingFeatures : 2; // (TypesettingFeatures) Caches values computed from m_fontDescription.
323 };
324
325 void invalidateFontGlyphsCache();
326 void pruneUnreferencedEntriesFromFontGlyphsCache();
327
328 inline Font::~Font()
329 {
330 }
331
332 inline const SimpleFontData* Font::primaryFont() const
333 {
334     ASSERT(m_glyphs);
335     return m_glyphs->primarySimpleFontData(m_fontDescription);
336 }
337
338 inline const FontData* Font::fontDataAt(unsigned index) const
339 {
340     ASSERT(m_glyphs);
341     return m_glyphs->realizeFontDataAt(m_fontDescription, index);
342 }
343
344 inline bool Font::isFixedPitch() const
345 {
346     ASSERT(m_glyphs);
347     return m_glyphs->isFixedPitch(m_fontDescription);
348 }
349
350 inline FontSelector* Font::fontSelector() const
351 {
352     return m_glyphs ? m_glyphs->fontSelector() : 0;
353 }
354
355 inline float Font::tabWidth(const SimpleFontData& fontData, unsigned tabSize, float position) const
356 {
357     if (!tabSize)
358         return letterSpacing();
359     float tabWidth = tabSize * fontData.spaceWidth() + letterSpacing();
360     return tabWidth - fmodf(position, tabWidth);
361 }
362
363 }
364
365 namespace WTF {
366
367 template <> void deleteOwnedPtr<WebCore::TextLayout>(WebCore::TextLayout*);
368
369 }
370
371 #endif