3c2119492f5e0b06c4209c4b82f9c3afd6ee5b1e
[WebKit-https.git] / Source / WebCore / platform / graphics / FontGlyphs.cpp
1 /*
2  * Copyright (C) 2006, 2013 Apple Inc.  All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *
8  * 1.  Redistributions of source code must retain the above copyright
9  *     notice, this list of conditions and the following disclaimer. 
10  * 2.  Redistributions in binary form must reproduce the above copyright
11  *     notice, this list of conditions and the following disclaimer in the
12  *     documentation and/or other materials provided with the distribution. 
13  * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
14  *     its contributors may be used to endorse or promote products derived
15  *     from this software without specific prior written permission. 
16  *
17  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
18  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
21  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28
29 #include "config.h"
30 #include "FontGlyphs.h"
31
32 #include "Font.h"
33 #include "FontCache.h"
34 #include "SegmentedFontData.h"
35 #include <wtf/unicode/Unicode.h>
36
37 namespace WebCore {
38
39
40 FontGlyphs::FontGlyphs(PassRefPtr<FontSelector> fontSelector)
41     : m_pageZero(0)
42     , m_cachedPrimarySimpleFontData(0)
43     , m_fontSelector(fontSelector)
44     , m_fontSelectorVersion(m_fontSelector ? m_fontSelector->version() : 0)
45     , m_familyIndex(0)
46     , m_generation(fontCache()->generation())
47     , m_pitch(UnknownPitch)
48     , m_loadingCustomFonts(false)
49     , m_isForPlatformFont(false)
50 {
51 }
52
53 FontGlyphs::FontGlyphs(const FontPlatformData& platformData)
54     : m_pageZero(0)
55     , m_cachedPrimarySimpleFontData(0)
56     , m_fontSelector(0)
57     , m_fontSelectorVersion(0)
58     , m_familyIndex(cAllFamiliesScanned)
59     , m_generation(fontCache()->generation())
60     , m_pitch(UnknownPitch)
61     , m_loadingCustomFonts(false)
62     , m_isForPlatformFont(true)
63 {
64     RefPtr<FontData> fontData = fontCache()->getCachedFontData(&platformData);
65     m_realizedFontData.append(fontData.release());
66 }
67
68 void FontGlyphs::releaseFontData()
69 {
70     unsigned numFonts = m_realizedFontData.size();
71     for (unsigned i = 0; i < numFonts; ++i) {
72         if (m_realizedFontData[i]->isCustomFont())
73             continue;
74         ASSERT(!m_realizedFontData[i]->isSegmented());
75         fontCache()->releaseFontData(static_cast<const SimpleFontData*>(m_realizedFontData[i].get()));
76     }
77 }
78
79 void FontGlyphs::determinePitch(const FontDescription& description) const
80 {
81     const FontData* fontData = primaryFontData(description);
82     if (!fontData->isSegmented())
83         m_pitch = static_cast<const SimpleFontData*>(fontData)->pitch();
84     else {
85         const SegmentedFontData* segmentedFontData = static_cast<const SegmentedFontData*>(fontData);
86         unsigned numRanges = segmentedFontData->numRanges();
87         if (numRanges == 1)
88             m_pitch = segmentedFontData->rangeAt(0).fontData()->pitch();
89         else
90             m_pitch = VariablePitch;
91     }
92 }
93
94 const FontData* FontGlyphs::realizeFontDataAt(const FontDescription& description, unsigned realizedFontIndex) const
95 {
96     if (realizedFontIndex < m_realizedFontData.size())
97         return m_realizedFontData[realizedFontIndex].get(); // This fallback font is already in our list.
98
99     // Make sure we're not passing in some crazy value here.
100     ASSERT(realizedFontIndex == m_realizedFontData.size());
101
102     if (m_familyIndex == cAllFamiliesScanned)
103         return 0;
104
105     // Ask the font cache for the font data.
106     // We are obtaining this font for the first time. We keep track of the families we've looked at before
107     // in |m_familyIndex|, so that we never scan the same spot in the list twice. getFontData will adjust our
108     // |m_familyIndex| as it scans for the right font to make.
109     ASSERT(fontCache()->generation() == m_generation);
110     RefPtr<FontData> result = fontCache()->getFontData(description, m_familyIndex, m_fontSelector.get());
111     if (result) {
112         m_realizedFontData.append(result);
113         if (result->isLoading())
114             m_loadingCustomFonts = true;
115     }
116     return result.get();
117 }
118
119 static inline bool isInRange(UChar32 character, UChar32 lowerBound, UChar32 upperBound)
120 {
121     return character >= lowerBound && character <= upperBound;
122 }
123
124 static bool shouldIgnoreRotation(UChar32 character)
125 {
126     if (character == 0x000A7 || character == 0x000A9 || character == 0x000AE)
127         return true;
128
129     if (character == 0x000B6 || character == 0x000BC || character == 0x000BD || character == 0x000BE)
130         return true;
131
132     if (isInRange(character, 0x002E5, 0x002EB))
133         return true;
134     
135     if (isInRange(character, 0x01100, 0x011FF) || isInRange(character, 0x01401, 0x0167F) || isInRange(character, 0x01800, 0x018FF))
136         return true;
137
138     if (character == 0x02016 || character == 0x02018 || character == 0x02019 || character == 0x02020 || character == 0x02021
139         || character == 0x2030 || character == 0x02031)
140         return true;
141
142     if (isInRange(character, 0x0203B, 0x0203D) || character == 0x02042 || character == 0x02044 || character == 0x02047
143         || character == 0x02048 || character == 0x02049 || character == 0x2051)
144         return true;
145
146     if (isInRange(character, 0x02065, 0x02069) || isInRange(character, 0x020DD, 0x020E0)
147         || isInRange(character, 0x020E2, 0x020E4) || isInRange(character, 0x02100, 0x02117)
148         || isInRange(character, 0x02119, 0x02131) || isInRange(character, 0x02133, 0x0213F))
149         return true;
150
151     if (isInRange(character, 0x02145, 0x0214A) || character == 0x0214C || character == 0x0214D
152         || isInRange(character, 0x0214F, 0x0218F))
153         return true;
154
155     if (isInRange(character, 0x02300, 0x02307) || isInRange(character, 0x0230C, 0x0231F)
156         || isInRange(character, 0x02322, 0x0232B) || isInRange(character, 0x0237D, 0x0239A)
157         || isInRange(character, 0x023B4, 0x023B6) || isInRange(character, 0x023BA, 0x023CF)
158         || isInRange(character, 0x023D1, 0x023DB) || isInRange(character, 0x023E2, 0x024FF))
159         return true;
160
161     if (isInRange(character, 0x025A0, 0x02619) || isInRange(character, 0x02620, 0x02767)
162         || isInRange(character, 0x02776, 0x02793) || isInRange(character, 0x02B12, 0x02B2F)
163         || isInRange(character, 0x02B4D, 0x02BFF) || isInRange(character, 0x02E80, 0x03007))
164         return true;
165
166     if (character == 0x03012 || character == 0x03013 || isInRange(character, 0x03020, 0x0302F)
167         || isInRange(character, 0x03031, 0x0309F) || isInRange(character, 0x030A1, 0x030FB)
168         || isInRange(character, 0x030FD, 0x0A4CF))
169         return true;
170
171     if (isInRange(character, 0x0A840, 0x0A87F) || isInRange(character, 0x0A960, 0x0A97F)
172         || isInRange(character, 0x0AC00, 0x0D7FF) || isInRange(character, 0x0E000, 0x0FAFF))
173         return true;
174
175     if (isInRange(character, 0x0FE10, 0x0FE1F) || isInRange(character, 0x0FE30, 0x0FE48)
176         || isInRange(character, 0x0FE50, 0x0FE57) || isInRange(character, 0x0FE5F, 0x0FE62)
177         || isInRange(character, 0x0FE67, 0x0FE6F))
178         return true;
179
180     if (isInRange(character, 0x0FF01, 0x0FF07) || isInRange(character, 0x0FF0A, 0x0FF0C)
181         || isInRange(character, 0x0FF0E, 0x0FF19) || isInRange(character, 0x0FF1F, 0x0FF3A))
182         return true;
183
184     if (character == 0x0FF3C || character == 0x0FF3E)
185         return true;
186
187     if (isInRange(character, 0x0FF40, 0x0FF5A) || isInRange(character, 0x0FFE0, 0x0FFE2)
188         || isInRange(character, 0x0FFE4, 0x0FFE7) || isInRange(character, 0x0FFF0, 0x0FFF8)
189         || character == 0x0FFFD)
190         return true;
191
192     if (isInRange(character, 0x13000, 0x1342F) || isInRange(character, 0x1B000, 0x1B0FF)
193         || isInRange(character, 0x1D000, 0x1D1FF) || isInRange(character, 0x1D300, 0x1D37F)
194         || isInRange(character, 0x1F000, 0x1F64F) || isInRange(character, 0x1F680, 0x1F77F))
195         return true;
196     
197     if (isInRange(character, 0x20000, 0x2FFFD) || isInRange(character, 0x30000, 0x3FFFD))
198         return true;
199
200     return false;
201 }
202
203 static inline std::pair<GlyphData, GlyphPage*> glyphDataAndPageForCJKCharacterWithoutSyntheticItalic(UChar32 character, GlyphData& data, GlyphPage* page, unsigned pageNumber)
204 {
205     RefPtr<SimpleFontData> nonItalicFontData = data.fontData->nonSyntheticItalicFontData();
206     GlyphPageTreeNode* nonItalicNode = GlyphPageTreeNode::getRootChild(nonItalicFontData.get(), pageNumber);
207     GlyphPage* nonItalicPage = nonItalicNode->page();
208     if (nonItalicPage) {
209         GlyphData nonItalicData = nonItalicPage->glyphDataForCharacter(character);
210         if (nonItalicData.fontData)
211             return std::make_pair(nonItalicData, nonItalicPage);
212     }
213     return std::make_pair(data, page);
214 }
215     
216 static inline std::pair<GlyphData, GlyphPage*> glyphDataAndPageForNonCJKCharacterWithGlyphOrientation(UChar32 character, NonCJKGlyphOrientation orientation, GlyphData& data, GlyphPage* page, unsigned pageNumber)
217 {
218     if (orientation == NonCJKGlyphOrientationUpright || shouldIgnoreRotation(character)) {
219         RefPtr<SimpleFontData> uprightFontData = data.fontData->uprightOrientationFontData();
220         GlyphPageTreeNode* uprightNode = GlyphPageTreeNode::getRootChild(uprightFontData.get(), pageNumber);
221         GlyphPage* uprightPage = uprightNode->page();
222         if (uprightPage) {
223             GlyphData uprightData = uprightPage->glyphDataForCharacter(character);
224             // If the glyphs are the same, then we know we can just use the horizontal glyph rotated vertically to be upright.
225             if (data.glyph == uprightData.glyph)
226                 return std::make_pair(data, page);
227             // The glyphs are distinct, meaning that the font has a vertical-right glyph baked into it. We can't use that
228             // glyph, so we fall back to the upright data and use the horizontal glyph.
229             if (uprightData.fontData)
230                 return std::make_pair(uprightData, uprightPage);
231         }
232     } else if (orientation == NonCJKGlyphOrientationVerticalRight) {
233         RefPtr<SimpleFontData> verticalRightFontData = data.fontData->verticalRightOrientationFontData();
234         GlyphPageTreeNode* verticalRightNode = GlyphPageTreeNode::getRootChild(verticalRightFontData.get(), pageNumber);
235         GlyphPage* verticalRightPage = verticalRightNode->page();
236         if (verticalRightPage) {
237             GlyphData verticalRightData = verticalRightPage->glyphDataForCharacter(character);
238             // If the glyphs are distinct, we will make the assumption that the font has a vertical-right glyph baked
239             // into it.
240             if (data.glyph != verticalRightData.glyph)
241                 return std::make_pair(data, page);
242             // The glyphs are identical, meaning that we should just use the horizontal glyph.
243             if (verticalRightData.fontData)
244                 return std::make_pair(verticalRightData, verticalRightPage);
245         }
246     }
247     return std::make_pair(data, page);
248 }
249
250 std::pair<GlyphData, GlyphPage*> FontGlyphs::glyphDataAndPageForCharacter(const FontDescription& description, UChar32 c, bool mirror, FontDataVariant variant) const
251 {
252     ASSERT(isMainThread());
253
254     if (variant == AutoVariant) {
255         if (description.smallCaps() && !primarySimpleFontData(description)->isSVGFont()) {
256             UChar32 upperC = WTF::Unicode::toUpper(c);
257             if (upperC != c) {
258                 c = upperC;
259                 variant = SmallCapsVariant;
260             } else
261                 variant = NormalVariant;
262         } else
263             variant = NormalVariant;
264     }
265
266     if (mirror)
267         c = WTF::Unicode::mirroredChar(c);
268
269     unsigned pageNumber = (c / GlyphPage::size);
270
271     GlyphPageTreeNode* node = pageNumber ? m_pages.get(pageNumber) : m_pageZero;
272     if (!node) {
273         node = GlyphPageTreeNode::getRootChild(realizeFontDataAt(description, 0), pageNumber);
274         if (pageNumber)
275             m_pages.set(pageNumber, node);
276         else
277             m_pageZero = node;
278     }
279
280     GlyphPage* page = 0;
281     if (variant == NormalVariant) {
282         // Fastest loop, for the common case (normal variant).
283         while (true) {
284             page = node->page();
285             if (page) {
286                 GlyphData data = page->glyphDataForCharacter(c);
287                 if (data.fontData && (data.fontData->platformData().orientation() == Horizontal || data.fontData->isTextOrientationFallback()))
288                     return std::make_pair(data, page);
289
290                 if (data.fontData) {
291                     if (Font::isCJKIdeographOrSymbol(c)) {
292                         if (!data.fontData->hasVerticalGlyphs()) {
293                             // Use the broken ideograph font data. The broken ideograph font will use the horizontal width of glyphs
294                             // to make sure you get a square (even for broken glyphs like symbols used for punctuation).
295                             variant = BrokenIdeographVariant;
296                             break;
297                         }
298 #if PLATFORM(MAC)
299                         else if (data.fontData->platformData().syntheticOblique())
300                             return glyphDataAndPageForCJKCharacterWithoutSyntheticItalic(c, data, page, pageNumber);
301 #endif
302                     } else
303                         return glyphDataAndPageForNonCJKCharacterWithGlyphOrientation(c, description.nonCJKGlyphOrientation(), data, page, pageNumber);
304
305                     return std::make_pair(data, page);
306                 }
307
308                 if (node->isSystemFallback())
309                     break;
310             }
311
312             node = node->getChild(realizeFontDataAt(description, node->level()), pageNumber);
313             if (pageNumber)
314                 m_pages.set(pageNumber, node);
315             else
316                 m_pageZero = node;
317         }
318     }
319     if (variant != NormalVariant) {
320         while (true) {
321             page = node->page();
322             if (page) {
323                 GlyphData data = page->glyphDataForCharacter(c);
324                 if (data.fontData) {
325                     // The variantFontData function should not normally return 0.
326                     // But if it does, we will just render the capital letter big.
327                     RefPtr<SimpleFontData> variantFontData = data.fontData->variantFontData(description, variant);
328                     if (!variantFontData)
329                         return std::make_pair(data, page);
330
331                     GlyphPageTreeNode* variantNode = GlyphPageTreeNode::getRootChild(variantFontData.get(), pageNumber);
332                     GlyphPage* variantPage = variantNode->page();
333                     if (variantPage) {
334                         GlyphData data = variantPage->glyphDataForCharacter(c);
335                         if (data.fontData)
336                             return std::make_pair(data, variantPage);
337                     }
338
339                     // Do not attempt system fallback off the variantFontData. This is the very unlikely case that
340                     // a font has the lowercase character but the small caps font does not have its uppercase version.
341                     return std::make_pair(variantFontData->missingGlyphData(), page);
342                 }
343
344                 if (node->isSystemFallback())
345                     break;
346             }
347
348             node = node->getChild(realizeFontDataAt(description, node->level()), pageNumber);
349             if (pageNumber)
350                 m_pages.set(pageNumber, node);
351             else
352                 m_pageZero = node;
353         }
354     }
355
356     ASSERT(page);
357     ASSERT(node->isSystemFallback());
358
359     // System fallback is character-dependent. When we get here, we
360     // know that the character in question isn't in the system fallback
361     // font's glyph page. Try to lazily create it here.
362     UChar codeUnits[2];
363     int codeUnitsLength;
364     if (c <= 0xFFFF) {
365         codeUnits[0] = Font::normalizeSpaces(c);
366         codeUnitsLength = 1;
367     } else {
368         codeUnits[0] = U16_LEAD(c);
369         codeUnits[1] = U16_TRAIL(c);
370         codeUnitsLength = 2;
371     }
372     const SimpleFontData* originalFontData = primaryFontData(description)->fontDataForCharacter(c);
373     RefPtr<SimpleFontData> characterFontData = fontCache()->systemFallbackForCharacters(description, originalFontData, m_isForPlatformFont, codeUnits, codeUnitsLength);
374     if (characterFontData) {
375         if (characterFontData->platformData().orientation() == Vertical && !characterFontData->hasVerticalGlyphs() && Font::isCJKIdeographOrSymbol(c))
376             variant = BrokenIdeographVariant;
377         if (variant != NormalVariant)
378             characterFontData = characterFontData->variantFontData(description, variant);
379     }
380     if (characterFontData) {
381         // Got the fallback glyph and font.
382         GlyphPage* fallbackPage = GlyphPageTreeNode::getRootChild(characterFontData.get(), pageNumber)->page();
383         GlyphData data = fallbackPage && fallbackPage->fontDataForCharacter(c) ? fallbackPage->glyphDataForCharacter(c) : characterFontData->missingGlyphData();
384         // Cache it so we don't have to do system fallback again next time.
385         if (variant == NormalVariant) {
386 #if OS(WINCE)
387             // missingGlyphData returns a null character, which is not suitable for GDI to display.
388             // Also, sometimes we cannot map a font for the character on WINCE, but GDI can still
389             // display the character, probably because the font package is not installed correctly.
390             // So we just always set the glyph to be same as the character, and let GDI solve it.
391             page->setGlyphDataForCharacter(c, c, characterFontData.get());
392             characterFontData->setMaxGlyphPageTreeLevel(std::max(characterFontData->maxGlyphPageTreeLevel(), node->level()));
393             return std::make_pair(page->glyphDataForCharacter(c), page);
394 #else
395             page->setGlyphDataForCharacter(c, data.glyph, data.fontData);
396             data.fontData->setMaxGlyphPageTreeLevel(std::max(data.fontData->maxGlyphPageTreeLevel(), node->level()));
397             if (!Font::isCJKIdeographOrSymbol(c) && data.fontData->platformData().orientation() != Horizontal && !data.fontData->isTextOrientationFallback())
398                 return glyphDataAndPageForNonCJKCharacterWithGlyphOrientation(c, description.nonCJKGlyphOrientation(), data, fallbackPage, pageNumber);
399 #endif
400         }
401         return std::make_pair(data, page);
402     }
403
404     // Even system fallback can fail; use the missing glyph in that case.
405     // FIXME: It would be nicer to use the missing glyph from the last resort font instead.
406     GlyphData data = primarySimpleFontData(description)->missingGlyphData();
407     if (variant == NormalVariant) {
408 #if OS(WINCE)
409         // See comment about WINCE GDI handling near setGlyphDataForCharacter above.
410         page->setGlyphDataForCharacter(c, c, data.fontData);
411         data.fontData->setMaxGlyphPageTreeLevel(std::max(data.fontData->maxGlyphPageTreeLevel(), node->level()));
412         return std::make_pair(page->glyphDataForCharacter(c), page);
413 #else
414         page->setGlyphDataForCharacter(c, data.glyph, data.fontData);
415         data.fontData->setMaxGlyphPageTreeLevel(std::max(data.fontData->maxGlyphPageTreeLevel(), node->level()));
416 #endif
417     }
418     return std::make_pair(data, page);
419 }
420
421
422 }