Add SPI for telling WebKit to prefer pictograph glyphs over monochrome ones
[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         if (!m_fontSelector)
104             return 0;
105
106         size_t index = cAllFamiliesScanned - m_familyIndex;
107         if (index == m_fontSelector->fallbackFontDataCount())
108             return 0;
109
110         m_familyIndex--;
111         RefPtr<FontData> fallback = m_fontSelector->getFallbackFontData(description, index);
112         if (fallback)
113             m_realizedFontData.append(fallback);
114         return fallback.get();
115     }
116
117     // Ask the font cache for the font data.
118     // We are obtaining this font for the first time. We keep track of the families we've looked at before
119     // in |m_familyIndex|, so that we never scan the same spot in the list twice. getFontData will adjust our
120     // |m_familyIndex| as it scans for the right font to make.
121     ASSERT(fontCache()->generation() == m_generation);
122     RefPtr<FontData> result = fontCache()->getFontData(description, m_familyIndex, m_fontSelector.get());
123     if (result) {
124         m_realizedFontData.append(result);
125         if (result->isLoading())
126             m_loadingCustomFonts = true;
127     }
128     return result.get();
129 }
130
131 static inline bool isInRange(UChar32 character, UChar32 lowerBound, UChar32 upperBound)
132 {
133     return character >= lowerBound && character <= upperBound;
134 }
135
136 static bool shouldIgnoreRotation(UChar32 character)
137 {
138     if (character == 0x000A7 || character == 0x000A9 || character == 0x000AE)
139         return true;
140
141     if (character == 0x000B6 || character == 0x000BC || character == 0x000BD || character == 0x000BE)
142         return true;
143
144     if (isInRange(character, 0x002E5, 0x002EB))
145         return true;
146     
147     if (isInRange(character, 0x01100, 0x011FF) || isInRange(character, 0x01401, 0x0167F) || isInRange(character, 0x01800, 0x018FF))
148         return true;
149
150     if (character == 0x02016 || character == 0x02018 || character == 0x02019 || character == 0x02020 || character == 0x02021
151         || character == 0x2030 || character == 0x02031)
152         return true;
153
154     if (isInRange(character, 0x0203B, 0x0203D) || character == 0x02042 || character == 0x02044 || character == 0x02047
155         || character == 0x02048 || character == 0x02049 || character == 0x2051)
156         return true;
157
158     if (isInRange(character, 0x02065, 0x02069) || isInRange(character, 0x020DD, 0x020E0)
159         || isInRange(character, 0x020E2, 0x020E4) || isInRange(character, 0x02100, 0x02117)
160         || isInRange(character, 0x02119, 0x02131) || isInRange(character, 0x02133, 0x0213F))
161         return true;
162
163     if (isInRange(character, 0x02145, 0x0214A) || character == 0x0214C || character == 0x0214D
164         || isInRange(character, 0x0214F, 0x0218F))
165         return true;
166
167     if (isInRange(character, 0x02300, 0x02307) || isInRange(character, 0x0230C, 0x0231F)
168         || isInRange(character, 0x02322, 0x0232B) || isInRange(character, 0x0237D, 0x0239A)
169         || isInRange(character, 0x023B4, 0x023B6) || isInRange(character, 0x023BA, 0x023CF)
170         || isInRange(character, 0x023D1, 0x023DB) || isInRange(character, 0x023E2, 0x024FF))
171         return true;
172
173     if (isInRange(character, 0x025A0, 0x02619) || isInRange(character, 0x02620, 0x02767)
174         || isInRange(character, 0x02776, 0x02793) || isInRange(character, 0x02B12, 0x02B2F)
175         || isInRange(character, 0x02B4D, 0x02BFF) || isInRange(character, 0x02E80, 0x03007))
176         return true;
177
178     if (character == 0x03012 || character == 0x03013 || isInRange(character, 0x03020, 0x0302F)
179         || isInRange(character, 0x03031, 0x0309F) || isInRange(character, 0x030A1, 0x030FB)
180         || isInRange(character, 0x030FD, 0x0A4CF))
181         return true;
182
183     if (isInRange(character, 0x0A840, 0x0A87F) || isInRange(character, 0x0A960, 0x0A97F)
184         || isInRange(character, 0x0AC00, 0x0D7FF) || isInRange(character, 0x0E000, 0x0FAFF))
185         return true;
186
187     if (isInRange(character, 0x0FE10, 0x0FE1F) || isInRange(character, 0x0FE30, 0x0FE48)
188         || isInRange(character, 0x0FE50, 0x0FE57) || isInRange(character, 0x0FE5F, 0x0FE62)
189         || isInRange(character, 0x0FE67, 0x0FE6F))
190         return true;
191
192     if (isInRange(character, 0x0FF01, 0x0FF07) || isInRange(character, 0x0FF0A, 0x0FF0C)
193         || isInRange(character, 0x0FF0E, 0x0FF19) || isInRange(character, 0x0FF1F, 0x0FF3A))
194         return true;
195
196     if (character == 0x0FF3C || character == 0x0FF3E)
197         return true;
198
199     if (isInRange(character, 0x0FF40, 0x0FF5A) || isInRange(character, 0x0FFE0, 0x0FFE2)
200         || isInRange(character, 0x0FFE4, 0x0FFE7) || isInRange(character, 0x0FFF0, 0x0FFF8)
201         || character == 0x0FFFD)
202         return true;
203
204     if (isInRange(character, 0x13000, 0x1342F) || isInRange(character, 0x1B000, 0x1B0FF)
205         || isInRange(character, 0x1D000, 0x1D1FF) || isInRange(character, 0x1D300, 0x1D37F)
206         || isInRange(character, 0x1F000, 0x1F64F) || isInRange(character, 0x1F680, 0x1F77F))
207         return true;
208     
209     if (isInRange(character, 0x20000, 0x2FFFD) || isInRange(character, 0x30000, 0x3FFFD))
210         return true;
211
212     return false;
213 }
214
215 static inline std::pair<GlyphData, GlyphPage*> glyphDataAndPageForCJKCharacterWithoutSyntheticItalic(UChar32 character, GlyphData& data, GlyphPage* page, unsigned pageNumber)
216 {
217     RefPtr<SimpleFontData> nonItalicFontData = data.fontData->nonSyntheticItalicFontData();
218     GlyphPageTreeNode* nonItalicNode = GlyphPageTreeNode::getRootChild(nonItalicFontData.get(), pageNumber);
219     GlyphPage* nonItalicPage = nonItalicNode->page();
220     if (nonItalicPage) {
221         GlyphData nonItalicData = nonItalicPage->glyphDataForCharacter(character);
222         if (nonItalicData.fontData)
223             return std::make_pair(nonItalicData, nonItalicPage);
224     }
225     return std::make_pair(data, page);
226 }
227     
228 static inline std::pair<GlyphData, GlyphPage*> glyphDataAndPageForNonCJKCharacterWithGlyphOrientation(UChar32 character, NonCJKGlyphOrientation orientation, GlyphData& data, GlyphPage* page, unsigned pageNumber)
229 {
230     if (orientation == NonCJKGlyphOrientationUpright || shouldIgnoreRotation(character)) {
231         RefPtr<SimpleFontData> uprightFontData = data.fontData->uprightOrientationFontData();
232         GlyphPageTreeNode* uprightNode = GlyphPageTreeNode::getRootChild(uprightFontData.get(), pageNumber);
233         GlyphPage* uprightPage = uprightNode->page();
234         if (uprightPage) {
235             GlyphData uprightData = uprightPage->glyphDataForCharacter(character);
236             // If the glyphs are the same, then we know we can just use the horizontal glyph rotated vertically to be upright.
237             if (data.glyph == uprightData.glyph)
238                 return std::make_pair(data, page);
239             // The glyphs are distinct, meaning that the font has a vertical-right glyph baked into it. We can't use that
240             // glyph, so we fall back to the upright data and use the horizontal glyph.
241             if (uprightData.fontData)
242                 return std::make_pair(uprightData, uprightPage);
243         }
244     } else if (orientation == NonCJKGlyphOrientationVerticalRight) {
245         RefPtr<SimpleFontData> verticalRightFontData = data.fontData->verticalRightOrientationFontData();
246         GlyphPageTreeNode* verticalRightNode = GlyphPageTreeNode::getRootChild(verticalRightFontData.get(), pageNumber);
247         GlyphPage* verticalRightPage = verticalRightNode->page();
248         if (verticalRightPage) {
249             GlyphData verticalRightData = verticalRightPage->glyphDataForCharacter(character);
250             // If the glyphs are distinct, we will make the assumption that the font has a vertical-right glyph baked
251             // into it.
252             if (data.glyph != verticalRightData.glyph)
253                 return std::make_pair(data, page);
254             // The glyphs are identical, meaning that we should just use the horizontal glyph.
255             if (verticalRightData.fontData)
256                 return std::make_pair(verticalRightData, verticalRightPage);
257         }
258     }
259     return std::make_pair(data, page);
260 }
261
262 std::pair<GlyphData, GlyphPage*> FontGlyphs::glyphDataAndPageForCharacter(const FontDescription& description, UChar32 c, bool mirror, FontDataVariant variant) const
263 {
264     ASSERT(isMainThread());
265
266     if (variant == AutoVariant) {
267         if (description.smallCaps() && !primarySimpleFontData(description)->isSVGFont()) {
268             UChar32 upperC = WTF::Unicode::toUpper(c);
269             if (upperC != c) {
270                 c = upperC;
271                 variant = SmallCapsVariant;
272             } else
273                 variant = NormalVariant;
274         } else
275             variant = NormalVariant;
276     }
277
278     if (mirror)
279         c = WTF::Unicode::mirroredChar(c);
280
281     unsigned pageNumber = (c / GlyphPage::size);
282
283     GlyphPageTreeNode* node = pageNumber ? m_pages.get(pageNumber) : m_pageZero;
284     if (!node) {
285         node = GlyphPageTreeNode::getRootChild(realizeFontDataAt(description, 0), pageNumber);
286         if (pageNumber)
287             m_pages.set(pageNumber, node);
288         else
289             m_pageZero = node;
290     }
291
292     GlyphPage* page = 0;
293     if (variant == NormalVariant) {
294         // Fastest loop, for the common case (normal variant).
295         while (true) {
296             page = node->page();
297             if (page) {
298                 GlyphData data = page->glyphDataForCharacter(c);
299                 if (data.fontData && (data.fontData->platformData().orientation() == Horizontal || data.fontData->isTextOrientationFallback()))
300                     return std::make_pair(data, page);
301
302                 if (data.fontData) {
303                     if (Font::isCJKIdeographOrSymbol(c)) {
304                         if (!data.fontData->hasVerticalGlyphs()) {
305                             // Use the broken ideograph font data. The broken ideograph font will use the horizontal width of glyphs
306                             // to make sure you get a square (even for broken glyphs like symbols used for punctuation).
307                             variant = BrokenIdeographVariant;
308                             break;
309                         }
310 #if PLATFORM(MAC)
311                         else if (data.fontData->platformData().syntheticOblique())
312                             return glyphDataAndPageForCJKCharacterWithoutSyntheticItalic(c, data, page, pageNumber);
313 #endif
314                     } else
315                         return glyphDataAndPageForNonCJKCharacterWithGlyphOrientation(c, description.nonCJKGlyphOrientation(), data, page, pageNumber);
316
317                     return std::make_pair(data, page);
318                 }
319
320                 if (node->isSystemFallback())
321                     break;
322             }
323
324             node = node->getChild(realizeFontDataAt(description, node->level()), pageNumber);
325             if (pageNumber)
326                 m_pages.set(pageNumber, node);
327             else
328                 m_pageZero = node;
329         }
330     }
331     if (variant != NormalVariant) {
332         while (true) {
333             page = node->page();
334             if (page) {
335                 GlyphData data = page->glyphDataForCharacter(c);
336                 if (data.fontData) {
337                     // The variantFontData function should not normally return 0.
338                     // But if it does, we will just render the capital letter big.
339                     RefPtr<SimpleFontData> variantFontData = data.fontData->variantFontData(description, variant);
340                     if (!variantFontData)
341                         return std::make_pair(data, page);
342
343                     GlyphPageTreeNode* variantNode = GlyphPageTreeNode::getRootChild(variantFontData.get(), pageNumber);
344                     GlyphPage* variantPage = variantNode->page();
345                     if (variantPage) {
346                         GlyphData data = variantPage->glyphDataForCharacter(c);
347                         if (data.fontData)
348                             return std::make_pair(data, variantPage);
349                     }
350
351                     // Do not attempt system fallback off the variantFontData. This is the very unlikely case that
352                     // a font has the lowercase character but the small caps font does not have its uppercase version.
353                     return std::make_pair(variantFontData->missingGlyphData(), page);
354                 }
355
356                 if (node->isSystemFallback())
357                     break;
358             }
359
360             node = node->getChild(realizeFontDataAt(description, node->level()), pageNumber);
361             if (pageNumber)
362                 m_pages.set(pageNumber, node);
363             else
364                 m_pageZero = node;
365         }
366     }
367
368     ASSERT(page);
369     ASSERT(node->isSystemFallback());
370
371     // System fallback is character-dependent. When we get here, we
372     // know that the character in question isn't in the system fallback
373     // font's glyph page. Try to lazily create it here.
374     UChar codeUnits[2];
375     int codeUnitsLength;
376     if (c <= 0xFFFF) {
377         codeUnits[0] = Font::normalizeSpaces(c);
378         codeUnitsLength = 1;
379     } else {
380         codeUnits[0] = U16_LEAD(c);
381         codeUnits[1] = U16_TRAIL(c);
382         codeUnitsLength = 2;
383     }
384     const SimpleFontData* originalFontData = primaryFontData(description)->fontDataForCharacter(c);
385     RefPtr<SimpleFontData> characterFontData = fontCache()->systemFallbackForCharacters(description, originalFontData, m_isForPlatformFont, codeUnits, codeUnitsLength);
386     if (characterFontData) {
387         if (characterFontData->platformData().orientation() == Vertical && !characterFontData->hasVerticalGlyphs() && Font::isCJKIdeographOrSymbol(c))
388             variant = BrokenIdeographVariant;
389         if (variant != NormalVariant)
390             characterFontData = characterFontData->variantFontData(description, variant);
391     }
392     if (characterFontData) {
393         // Got the fallback glyph and font.
394         GlyphPage* fallbackPage = GlyphPageTreeNode::getRootChild(characterFontData.get(), pageNumber)->page();
395         GlyphData data = fallbackPage && fallbackPage->fontDataForCharacter(c) ? fallbackPage->glyphDataForCharacter(c) : characterFontData->missingGlyphData();
396         // Cache it so we don't have to do system fallback again next time.
397         if (variant == NormalVariant) {
398 #if OS(WINCE)
399             // missingGlyphData returns a null character, which is not suitable for GDI to display.
400             // Also, sometimes we cannot map a font for the character on WINCE, but GDI can still
401             // display the character, probably because the font package is not installed correctly.
402             // So we just always set the glyph to be same as the character, and let GDI solve it.
403             page->setGlyphDataForCharacter(c, c, characterFontData.get());
404             characterFontData->setMaxGlyphPageTreeLevel(std::max(characterFontData->maxGlyphPageTreeLevel(), node->level()));
405             return std::make_pair(page->glyphDataForCharacter(c), page);
406 #else
407             page->setGlyphDataForCharacter(c, data.glyph, data.fontData);
408             data.fontData->setMaxGlyphPageTreeLevel(std::max(data.fontData->maxGlyphPageTreeLevel(), node->level()));
409             if (!Font::isCJKIdeographOrSymbol(c) && data.fontData->platformData().orientation() != Horizontal && !data.fontData->isTextOrientationFallback())
410                 return glyphDataAndPageForNonCJKCharacterWithGlyphOrientation(c, description.nonCJKGlyphOrientation(), data, fallbackPage, pageNumber);
411 #endif
412         }
413         return std::make_pair(data, page);
414     }
415
416     // Even system fallback can fail; use the missing glyph in that case.
417     // FIXME: It would be nicer to use the missing glyph from the last resort font instead.
418     GlyphData data = primarySimpleFontData(description)->missingGlyphData();
419     if (variant == NormalVariant) {
420 #if OS(WINCE)
421         // See comment about WINCE GDI handling near setGlyphDataForCharacter above.
422         page->setGlyphDataForCharacter(c, c, data.fontData);
423         data.fontData->setMaxGlyphPageTreeLevel(std::max(data.fontData->maxGlyphPageTreeLevel(), node->level()));
424         return std::make_pair(page->glyphDataForCharacter(c), page);
425 #else
426         page->setGlyphDataForCharacter(c, data.glyph, data.fontData);
427         data.fontData->setMaxGlyphPageTreeLevel(std::max(data.fontData->maxGlyphPageTreeLevel(), node->level()));
428 #endif
429     }
430     return std::make_pair(data, page);
431 }
432
433
434 }