Add WTF::move()
[WebKit-https.git] / Source / WebCore / platform / graphics / SimpleFontData.cpp
1 /*
2  * Copyright (C) 2005, 2008, 2010 Apple Inc. All rights reserved.
3  * Copyright (C) 2006 Alexey Proskuryakov
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * 1.  Redistributions of source code must retain the above copyright
10  *     notice, this list of conditions and the following disclaimer. 
11  * 2.  Redistributions in binary form must reproduce the above copyright
12  *     notice, this list of conditions and the following disclaimer in the
13  *     documentation and/or other materials provided with the distribution. 
14  * 3.  Neither the name of Apple Inc. ("Apple") nor the names of
15  *     its contributors may be used to endorse or promote products derived
16  *     from this software without specific prior written permission. 
17  *
18  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
19  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
22  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  */
29
30 #include "config.h"
31 #include "SimpleFontData.h"
32
33 #include "Font.h"
34 #include "FontCache.h"
35 #include "OpenTypeMathData.h"
36 #include <wtf/MathExtras.h>
37
38 #if ENABLE(OPENTYPE_VERTICAL)
39 #include "OpenTypeVerticalData.h"
40 #endif
41
42 namespace WebCore {
43
44 const float smallCapsFontSizeMultiplier = 0.7f;
45 const float emphasisMarkFontSizeMultiplier = 0.5f;
46
47 SimpleFontData::SimpleFontData(const FontPlatformData& platformData, bool isCustomFont, bool isLoading, bool isTextOrientationFallback)
48     : m_maxCharWidth(-1)
49     , m_avgCharWidth(-1)
50     , m_platformData(platformData)
51     , m_treatAsFixedPitch(false)
52     , m_isCustomFont(isCustomFont)
53     , m_isLoading(isLoading)
54     , m_isTextOrientationFallback(isTextOrientationFallback)
55     , m_isBrokenIdeographFallback(false)
56     , m_mathData(nullptr)
57 #if ENABLE(OPENTYPE_VERTICAL)
58     , m_verticalData(0)
59 #endif
60     , m_hasVerticalGlyphs(false)
61 {
62     platformInit();
63     platformGlyphInit();
64     platformCharWidthInit();
65 #if ENABLE(OPENTYPE_VERTICAL)
66     if (platformData.orientation() == Vertical && !isTextOrientationFallback) {
67         m_verticalData = platformData.verticalData();
68         m_hasVerticalGlyphs = m_verticalData.get() && m_verticalData->hasVerticalMetrics();
69     }
70 #endif
71 }
72
73 SimpleFontData::SimpleFontData(std::unique_ptr<AdditionalFontData> fontData, float fontSize, bool syntheticBold, bool syntheticItalic)
74     : m_platformData(FontPlatformData(fontSize, syntheticBold, syntheticItalic))
75     , m_fontData(WTF::move(fontData))
76     , m_treatAsFixedPitch(false)
77     , m_isCustomFont(true)
78     , m_isLoading(false)
79     , m_isTextOrientationFallback(false)
80     , m_isBrokenIdeographFallback(false)
81     , m_mathData(nullptr)
82 #if ENABLE(OPENTYPE_VERTICAL)
83     , m_verticalData(0)
84 #endif
85     , m_hasVerticalGlyphs(false)
86 #if PLATFORM(IOS)
87     , m_shouldNotBeUsedForArabic(false)
88 #endif
89 {
90     m_fontData->initializeFontData(this, fontSize);
91 }
92
93 // Estimates of avgCharWidth and maxCharWidth for platforms that don't support accessing these values from the font.
94 void SimpleFontData::initCharWidths()
95 {
96     GlyphPage* glyphPageZero = GlyphPageTreeNode::getRootChild(this, 0)->page();
97
98     // Treat the width of a '0' as the avgCharWidth.
99     if (m_avgCharWidth <= 0.f && glyphPageZero) {
100         static const UChar32 digitZeroChar = '0';
101         Glyph digitZeroGlyph = glyphPageZero->glyphDataForCharacter(digitZeroChar).glyph;
102         if (digitZeroGlyph)
103             m_avgCharWidth = widthForGlyph(digitZeroGlyph);
104     }
105
106     // If we can't retrieve the width of a '0', fall back to the x height.
107     if (m_avgCharWidth <= 0.f)
108         m_avgCharWidth = m_fontMetrics.xHeight();
109
110     if (m_maxCharWidth <= 0.f)
111         m_maxCharWidth = std::max(m_avgCharWidth, m_fontMetrics.floatAscent());
112 }
113
114 void SimpleFontData::platformGlyphInit()
115 {
116     GlyphPage* glyphPageZero = GlyphPageTreeNode::getRootChild(this, 0)->page();
117     if (!glyphPageZero) {
118         LOG_ERROR("Failed to get glyph page zero.");
119         m_spaceGlyph = 0;
120         m_spaceWidth = 0;
121         m_zeroGlyph = 0;
122         m_adjustedSpaceWidth = 0;
123         determinePitch();
124         m_zeroWidthSpaceGlyph = 0;
125         m_missingGlyphData.fontData = this;
126         m_missingGlyphData.glyph = 0;
127         return;
128     }
129
130     m_zeroWidthSpaceGlyph = glyphPageZero->glyphDataForCharacter(0).glyph;
131
132     // Nasty hack to determine if we should round or ceil space widths.
133     // If the font is monospace or fake monospace we ceil to ensure that 
134     // every character and the space are the same width.  Otherwise we round.
135     m_spaceGlyph = glyphPageZero->glyphDataForCharacter(' ').glyph;
136     float width = widthForGlyph(m_spaceGlyph);
137     m_spaceWidth = width;
138     m_zeroGlyph = glyphPageZero->glyphDataForCharacter('0').glyph;
139     m_fontMetrics.setZeroWidth(widthForGlyph(m_zeroGlyph));
140     determinePitch();
141     m_adjustedSpaceWidth = m_treatAsFixedPitch ? ceilf(width) : roundf(width);
142
143     // Force the glyph for ZERO WIDTH SPACE to have zero width, unless it is shared with SPACE.
144     // Helvetica is an example of a non-zero width ZERO WIDTH SPACE glyph.
145     // See <http://bugs.webkit.org/show_bug.cgi?id=13178>
146     // Ask for the glyph for 0 to avoid paging in ZERO WIDTH SPACE. Control characters, including 0,
147     // are mapped to the ZERO WIDTH SPACE glyph.
148     if (m_zeroWidthSpaceGlyph == m_spaceGlyph) {
149         m_zeroWidthSpaceGlyph = 0;
150         LOG_ERROR("Font maps SPACE and ZERO WIDTH SPACE to the same glyph. Glyph width will not be overridden.");
151     }
152
153     m_missingGlyphData.fontData = this;
154     m_missingGlyphData.glyph = 0;
155 }
156
157 SimpleFontData::~SimpleFontData()
158 {
159     if (!m_fontData)
160         platformDestroy();
161
162     if (isCustomFont())
163         GlyphPageTreeNode::pruneTreeCustomFontData(this);
164     else
165         GlyphPageTreeNode::pruneTreeFontData(this);
166 }
167
168 const SimpleFontData* SimpleFontData::fontDataForCharacter(UChar32) const
169 {
170     return this;
171 }
172
173 Glyph SimpleFontData::glyphForCharacter(UChar32 character) const
174 {
175     GlyphPageTreeNode* node = GlyphPageTreeNode::getRootChild(this, character / GlyphPage::size);
176     return node->page() ? node->page()->glyphAt(character % GlyphPage::size) : 0;
177 }
178
179 bool SimpleFontData::isSegmented() const
180 {
181     return false;
182 }
183
184 PassRefPtr<SimpleFontData> SimpleFontData::verticalRightOrientationFontData() const
185 {
186     if (!m_derivedFontData)
187         m_derivedFontData = DerivedFontData::create(isCustomFont());
188     if (!m_derivedFontData->verticalRightOrientation) {
189         FontPlatformData verticalRightPlatformData(m_platformData);
190         verticalRightPlatformData.setOrientation(Horizontal);
191         m_derivedFontData->verticalRightOrientation = create(verticalRightPlatformData, isCustomFont(), false, true);
192     }
193     return m_derivedFontData->verticalRightOrientation;
194 }
195
196 PassRefPtr<SimpleFontData> SimpleFontData::uprightOrientationFontData() const
197 {
198     if (!m_derivedFontData)
199         m_derivedFontData = DerivedFontData::create(isCustomFont());
200     if (!m_derivedFontData->uprightOrientation)
201         m_derivedFontData->uprightOrientation = create(m_platformData, isCustomFont(), false, true);
202     return m_derivedFontData->uprightOrientation;
203 }
204
205 PassRefPtr<SimpleFontData> SimpleFontData::smallCapsFontData(const FontDescription& fontDescription) const
206 {
207     if (!m_derivedFontData)
208         m_derivedFontData = DerivedFontData::create(isCustomFont());
209     if (!m_derivedFontData->smallCaps)
210         m_derivedFontData->smallCaps = createScaledFontData(fontDescription, smallCapsFontSizeMultiplier);
211
212     return m_derivedFontData->smallCaps;
213 }
214
215 PassRefPtr<SimpleFontData> SimpleFontData::emphasisMarkFontData(const FontDescription& fontDescription) const
216 {
217     if (!m_derivedFontData)
218         m_derivedFontData = DerivedFontData::create(isCustomFont());
219     if (!m_derivedFontData->emphasisMark)
220         m_derivedFontData->emphasisMark = createScaledFontData(fontDescription, emphasisMarkFontSizeMultiplier);
221
222     return m_derivedFontData->emphasisMark;
223 }
224
225 PassRefPtr<SimpleFontData> SimpleFontData::brokenIdeographFontData() const
226 {
227     if (!m_derivedFontData)
228         m_derivedFontData = DerivedFontData::create(isCustomFont());
229     if (!m_derivedFontData->brokenIdeograph) {
230         m_derivedFontData->brokenIdeograph = create(m_platformData, isCustomFont(), false);
231         m_derivedFontData->brokenIdeograph->m_isBrokenIdeographFallback = true;
232     }
233     return m_derivedFontData->brokenIdeograph;
234 }
235
236 PassRefPtr<SimpleFontData> SimpleFontData::nonSyntheticItalicFontData() const
237 {
238     if (!m_derivedFontData)
239         m_derivedFontData = DerivedFontData::create(isCustomFont());
240     if (!m_derivedFontData->nonSyntheticItalic) {
241         FontPlatformData nonSyntheticItalicFontPlatformData(m_platformData);
242 #if PLATFORM(COCOA)
243         nonSyntheticItalicFontPlatformData.m_syntheticOblique = false;
244 #endif
245         m_derivedFontData->nonSyntheticItalic = create(nonSyntheticItalicFontPlatformData, isCustomFont(), false, true);
246     }
247     return m_derivedFontData->nonSyntheticItalic;
248 }
249
250 #ifndef NDEBUG
251 String SimpleFontData::description() const
252 {
253     if (isSVGFont())
254         return "[SVG font]";
255     if (isCustomFont())
256         return "[custom font]";
257
258     return platformData().description();
259 }
260 #endif
261
262 const OpenTypeMathData* SimpleFontData::mathData() const
263 {
264     if (m_isLoading)
265         return nullptr;
266     if (!m_mathData) {
267         m_mathData = OpenTypeMathData::create(m_platformData);
268         if (!m_mathData->hasMathData())
269             m_mathData.clear();
270     }
271     return m_mathData.get();
272 }
273
274 PassOwnPtr<SimpleFontData::DerivedFontData> SimpleFontData::DerivedFontData::create(bool forCustomFont)
275 {
276     return adoptPtr(new DerivedFontData(forCustomFont));
277 }
278
279 SimpleFontData::DerivedFontData::~DerivedFontData()
280 {
281     if (!forCustomFont)
282         return;
283
284     if (smallCaps)
285         GlyphPageTreeNode::pruneTreeCustomFontData(smallCaps.get());
286     if (emphasisMark)
287         GlyphPageTreeNode::pruneTreeCustomFontData(emphasisMark.get());
288     if (brokenIdeograph)
289         GlyphPageTreeNode::pruneTreeCustomFontData(brokenIdeograph.get());
290     if (verticalRightOrientation)
291         GlyphPageTreeNode::pruneTreeCustomFontData(verticalRightOrientation.get());
292     if (uprightOrientation)
293         GlyphPageTreeNode::pruneTreeCustomFontData(uprightOrientation.get());
294 #if PLATFORM(COCOA)
295     if (compositeFontReferences) {
296         CFDictionaryRef dictionary = CFDictionaryRef(compositeFontReferences.get());
297         CFIndex count = CFDictionaryGetCount(dictionary);
298         if (count > 0) {
299             Vector<SimpleFontData*, 2> stash(count);
300             SimpleFontData** fonts = stash.data();
301             CFDictionaryGetKeysAndValues(dictionary, 0, (const void **)fonts);
302             while (count-- > 0 && *fonts) {
303                 RefPtr<SimpleFontData> afont = adoptRef(*fonts++);
304                 GlyphPageTreeNode::pruneTreeCustomFontData(afont.get());
305             }
306         }
307     }
308 #endif
309 }
310
311 PassRefPtr<SimpleFontData> SimpleFontData::createScaledFontData(const FontDescription& fontDescription, float scaleFactor) const
312 {
313     // FIXME: Support scaled fonts that used AdditionalFontData.
314     if (m_fontData)
315         return 0;
316
317     return platformCreateScaledFontData(fontDescription, scaleFactor);
318 }
319
320 } // namespace WebCore