Add some new emoji with modifiers and new sequence.
[WebKit-https.git] / Source / WebCore / platform / graphics / FontCascade.cpp
1 /*
2  * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3  *           (C) 1999 Antti Koivisto (koivisto@kde.org)
4  *           (C) 2000 Dirk Mueller (mueller@kde.org)
5  * Copyright (C) 2003, 2006, 2010, 2011 Apple Inc. All rights reserved.
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 #include "config.h"
25 #include "FontCascade.h"
26
27 #include "CharacterProperties.h"
28 #include "FloatRect.h"
29 #include "FontCache.h"
30 #include "GlyphBuffer.h"
31 #include "LayoutRect.h"
32 #include "TextRun.h"
33 #include "WidthIterator.h"
34 #include <wtf/MainThread.h>
35 #include <wtf/MathExtras.h>
36 #include <wtf/NeverDestroyed.h>
37 #include <wtf/text/AtomicStringHash.h>
38 #include <wtf/text/StringBuilder.h>
39
40 using namespace WTF;
41 using namespace Unicode;
42
43 namespace WebCore {
44
45 static Ref<FontCascadeFonts> retrieveOrAddCachedFonts(const FontDescription&, RefPtr<FontSelector>&&);
46
47 const uint8_t FontCascade::s_roundingHackCharacterTable[256] = {
48     0, 0, 0, 0, 0, 0, 0, 0, 0, 1 /*\t*/, 1 /*\n*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
49     1 /*space*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 /*-*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 /*?*/,
50     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
51     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
52     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
53     1 /*no-break space*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
54     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
55     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
56 };
57
58 static bool isDrawnWithSVGFont(const TextRun& run)
59 {
60     return run.renderingContext();
61 }
62
63 static bool useBackslashAsYenSignForFamily(const AtomicString& family)
64 {
65     if (family.isEmpty())
66         return false;
67     static HashSet<AtomicString>* set;
68     if (!set) {
69         set = new HashSet<AtomicString>;
70         set->add("MS PGothic");
71         UChar unicodeNameMSPGothic[] = {0xFF2D, 0xFF33, 0x0020, 0xFF30, 0x30B4, 0x30B7, 0x30C3, 0x30AF};
72         set->add(AtomicString(unicodeNameMSPGothic, WTF_ARRAY_LENGTH(unicodeNameMSPGothic)));
73
74         set->add("MS PMincho");
75         UChar unicodeNameMSPMincho[] = {0xFF2D, 0xFF33, 0x0020, 0xFF30, 0x660E, 0x671D};
76         set->add(AtomicString(unicodeNameMSPMincho, WTF_ARRAY_LENGTH(unicodeNameMSPMincho)));
77
78         set->add("MS Gothic");
79         UChar unicodeNameMSGothic[] = {0xFF2D, 0xFF33, 0x0020, 0x30B4, 0x30B7, 0x30C3, 0x30AF};
80         set->add(AtomicString(unicodeNameMSGothic, WTF_ARRAY_LENGTH(unicodeNameMSGothic)));
81
82         set->add("MS Mincho");
83         UChar unicodeNameMSMincho[] = {0xFF2D, 0xFF33, 0x0020, 0x660E, 0x671D};
84         set->add(AtomicString(unicodeNameMSMincho, WTF_ARRAY_LENGTH(unicodeNameMSMincho)));
85
86         set->add("Meiryo");
87         UChar unicodeNameMeiryo[] = {0x30E1, 0x30A4, 0x30EA, 0x30AA};
88         set->add(AtomicString(unicodeNameMeiryo, WTF_ARRAY_LENGTH(unicodeNameMeiryo)));
89     }
90     return set->contains(family);
91 }
92
93 FontCascade::CodePath FontCascade::s_codePath = Auto;
94
95 TypesettingFeatures FontCascade::s_defaultTypesettingFeatures = 0;
96
97 // ============================================================================================
98 // FontCascade Implementation (Cross-Platform Portion)
99 // ============================================================================================
100
101 FontCascade::FontCascade()
102     : m_weakPtrFactory(this)
103     , m_letterSpacing(0)
104     , m_wordSpacing(0)
105     , m_useBackslashAsYenSymbol(false)
106     , m_typesettingFeatures(0)
107 {
108 }
109
110 FontCascade::FontCascade(const FontDescription& fd, float letterSpacing, float wordSpacing)
111     : m_fontDescription(fd)
112     , m_weakPtrFactory(this)
113     , m_letterSpacing(letterSpacing)
114     , m_wordSpacing(wordSpacing)
115     , m_useBackslashAsYenSymbol(useBackslashAsYenSignForFamily(fd.firstFamily()))
116     , m_typesettingFeatures(computeTypesettingFeatures())
117 {
118 }
119
120 // FIXME: We should make this constructor platform-independent.
121 FontCascade::FontCascade(const FontPlatformData& fontData, FontSmoothingMode fontSmoothingMode)
122     : m_fonts(FontCascadeFonts::createForPlatformFont(fontData))
123     , m_weakPtrFactory(this)
124     , m_letterSpacing(0)
125     , m_wordSpacing(0)
126     , m_useBackslashAsYenSymbol(false)
127     , m_typesettingFeatures(computeTypesettingFeatures())
128 {
129     m_fontDescription.setFontSmoothing(fontSmoothingMode);
130 #if PLATFORM(IOS)
131     m_fontDescription.setSpecifiedSize(CTFontGetSize(fontData.font()));
132     m_fontDescription.setComputedSize(CTFontGetSize(fontData.font()));
133     m_fontDescription.setIsItalic(CTFontGetSymbolicTraits(fontData.font()) & kCTFontTraitItalic);
134     m_fontDescription.setWeight((CTFontGetSymbolicTraits(fontData.font()) & kCTFontTraitBold) ? FontWeightBold : FontWeightNormal);
135 #endif
136 }
137
138 FontCascade::FontCascade(const FontCascade& other)
139     : m_fontDescription(other.m_fontDescription)
140     , m_fonts(other.m_fonts)
141     , m_weakPtrFactory(this)
142     , m_letterSpacing(other.m_letterSpacing)
143     , m_wordSpacing(other.m_wordSpacing)
144     , m_useBackslashAsYenSymbol(other.m_useBackslashAsYenSymbol)
145     , m_typesettingFeatures(computeTypesettingFeatures())
146 {
147 }
148
149 FontCascade& FontCascade::operator=(const FontCascade& other)
150 {
151     m_fontDescription = other.m_fontDescription;
152     m_fonts = other.m_fonts;
153     m_letterSpacing = other.m_letterSpacing;
154     m_wordSpacing = other.m_wordSpacing;
155     m_useBackslashAsYenSymbol = other.m_useBackslashAsYenSymbol;
156     m_typesettingFeatures = other.m_typesettingFeatures;
157     return *this;
158 }
159
160 bool FontCascade::operator==(const FontCascade& other) const
161 {
162     if (isLoadingCustomFonts() || other.isLoadingCustomFonts())
163         return false;
164
165     if (m_fontDescription != other.m_fontDescription || m_letterSpacing != other.m_letterSpacing || m_wordSpacing != other.m_wordSpacing)
166         return false;
167     if (m_fonts == other.m_fonts)
168         return true;
169     if (!m_fonts || !other.m_fonts)
170         return false;
171     if (m_fonts->fontSelector() != other.m_fonts->fontSelector())
172         return false;
173     // Can these cases actually somehow occur? All fonts should get wiped out by full style recalc.
174     if (m_fonts->fontSelectorVersion() != other.m_fonts->fontSelectorVersion())
175         return false;
176     if (m_fonts->generation() != other.m_fonts->generation())
177         return false;
178     return true;
179 }
180
181 struct FontCascadeCacheKey {
182     FontDescriptionKey fontDescriptionKey; // Shared with the lower level FontCache (caching Font objects)
183     Vector<AtomicString, 3> families;
184     unsigned fontSelectorId;
185     unsigned fontSelectorVersion;
186 };
187
188 struct FontCascadeCacheEntry {
189     WTF_MAKE_FAST_ALLOCATED;
190 public:
191     FontCascadeCacheEntry(FontCascadeCacheKey&& key, Ref<FontCascadeFonts>&& fonts)
192         : key(WTF::move(key))
193         , fonts(WTF::move(fonts))
194     { }
195     FontCascadeCacheKey key;
196     Ref<FontCascadeFonts> fonts;
197 };
198
199 typedef HashMap<unsigned, std::unique_ptr<FontCascadeCacheEntry>, AlreadyHashed> FontCascadeCache;
200
201 static bool operator==(const FontCascadeCacheKey& a, const FontCascadeCacheKey& b)
202 {
203     if (a.fontDescriptionKey != b.fontDescriptionKey)
204         return false;
205     if (a.fontSelectorId != b.fontSelectorId || a.fontSelectorVersion != b.fontSelectorVersion)
206         return false;
207     if (a.families.size() != b.families.size())
208         return false;
209     for (unsigned i = 0; i < a.families.size(); ++i) {
210         if (!equalIgnoringCase(a.families[i].impl(), b.families[i].impl()))
211             return false;
212     }
213     return true;
214 }
215
216 static FontCascadeCache& fontCascadeCache()
217 {
218     static NeverDestroyed<FontCascadeCache> cache;
219     return cache.get();
220 }
221
222 void invalidateFontCascadeCache()
223 {
224     fontCascadeCache().clear();
225 }
226
227 void clearWidthCaches()
228 {
229     for (auto& value : fontCascadeCache().values())
230         value->fonts.get().widthCache().clear();
231 }
232
233 static FontCascadeCacheKey makeFontCascadeCacheKey(const FontDescription& description, FontSelector* fontSelector)
234 {
235     FontCascadeCacheKey key;
236     key.fontDescriptionKey = FontDescriptionKey(description);
237     for (unsigned i = 0; i < description.familyCount(); ++i)
238         key.families.append(description.familyAt(i));
239     key.fontSelectorId = fontSelector ? fontSelector->uniqueId() : 0;
240     key.fontSelectorVersion = fontSelector ? fontSelector->version() : 0;
241     return key;
242 }
243
244 // FIXME: Why can't we just teach HashMap about FontCascadeCacheKey instead of hashing a hash?
245 static unsigned computeFontCascadeCacheHash(const FontCascadeCacheKey& key)
246 {
247     Vector<unsigned, 7> hashCodes;
248     hashCodes.reserveInitialCapacity(4 + key.families.size());
249
250     hashCodes.uncheckedAppend(key.fontDescriptionKey.computeHash());
251     hashCodes.uncheckedAppend(key.fontSelectorId);
252     hashCodes.uncheckedAppend(key.fontSelectorVersion);
253     for (unsigned i = 0; i < key.families.size(); ++i)
254         hashCodes.uncheckedAppend(key.families[i].impl() ? CaseFoldingHash::hash(key.families[i]) : 0);
255
256     return StringHasher::hashMemory(hashCodes.data(), hashCodes.size() * sizeof(unsigned));
257 }
258
259 void pruneUnreferencedEntriesFromFontCascadeCache()
260 {
261     fontCascadeCache().removeIf([](FontCascadeCache::KeyValuePairType& entry) {
262         return entry.value->fonts.get().hasOneRef();
263     });
264 }
265
266 void pruneSystemFallbackFonts()
267 {
268     for (auto& entry : fontCascadeCache().values())
269         entry->fonts->pruneSystemFallbacks();
270 }
271
272 static Ref<FontCascadeFonts> retrieveOrAddCachedFonts(const FontDescription& fontDescription, RefPtr<FontSelector>&& fontSelector)
273 {
274     auto key = makeFontCascadeCacheKey(fontDescription, fontSelector.get());
275
276     unsigned hash = computeFontCascadeCacheHash(key);
277     auto addResult = fontCascadeCache().add(hash, std::unique_ptr<FontCascadeCacheEntry>());
278     if (!addResult.isNewEntry && addResult.iterator->value->key == key)
279         return addResult.iterator->value->fonts.get();
280
281     auto& newEntry = addResult.iterator->value;
282     newEntry = std::make_unique<FontCascadeCacheEntry>(WTF::move(key), FontCascadeFonts::create(WTF::move(fontSelector)));
283     Ref<FontCascadeFonts> glyphs = newEntry->fonts.get();
284
285     static const unsigned unreferencedPruneInterval = 50;
286     static const int maximumEntries = 400;
287     static unsigned pruneCounter;
288     // Referenced FontCascadeFonts would exist anyway so pruning them saves little memory.
289     if (!(++pruneCounter % unreferencedPruneInterval))
290         pruneUnreferencedEntriesFromFontCascadeCache();
291     // Prevent pathological growth.
292     if (fontCascadeCache().size() > maximumEntries)
293         fontCascadeCache().remove(fontCascadeCache().begin());
294     return glyphs;
295 }
296
297 void FontCascade::update(RefPtr<FontSelector>&& fontSelector) const
298 {
299     m_fonts = retrieveOrAddCachedFonts(m_fontDescription, WTF::move(fontSelector));
300     m_useBackslashAsYenSymbol = useBackslashAsYenSignForFamily(firstFamily());
301     m_typesettingFeatures = computeTypesettingFeatures();
302 }
303
304 float FontCascade::drawText(GraphicsContext* context, const TextRun& run, const FloatPoint& point, int from, int to, CustomFontNotReadyAction customFontNotReadyAction) const
305 {
306     // Don't draw anything while we are using custom fonts that are in the process of loading,
307     // except if the 'force' argument is set to true (in which case it will use a fallback
308     // font).
309     if (isLoadingCustomFonts() && customFontNotReadyAction == DoNotPaintIfFontNotReady)
310         return 0;
311
312     to = (to == -1 ? run.length() : to);
313
314     CodePath codePathToUse = codePath(run);
315     // FIXME: Use the fast code path once it handles partial runs with kerning and ligatures. See http://webkit.org/b/100050
316     if (codePathToUse != Complex && typesettingFeatures() && (from || static_cast<unsigned>(to) != run.length()) && !isDrawnWithSVGFont(run))
317         codePathToUse = Complex;
318
319     if (codePathToUse != Complex)
320         return drawSimpleText(context, run, point, from, to);
321
322     return drawComplexText(context, run, point, from, to);
323 }
324
325 void FontCascade::drawEmphasisMarks(GraphicsContext* context, const TextRun& run, const AtomicString& mark, const FloatPoint& point, int from, int to) const
326 {
327     if (isLoadingCustomFonts())
328         return;
329
330     if (to < 0)
331         to = run.length();
332
333     CodePath codePathToUse = codePath(run);
334     // FIXME: Use the fast code path once it handles partial runs with kerning and ligatures. See http://webkit.org/b/100050
335     if (codePathToUse != Complex && typesettingFeatures() && (from || static_cast<unsigned>(to) != run.length()) && !isDrawnWithSVGFont(run))
336         codePathToUse = Complex;
337
338     if (codePathToUse != Complex)
339         drawEmphasisMarksForSimpleText(context, run, mark, point, from, to);
340     else
341         drawEmphasisMarksForComplexText(context, run, mark, point, from, to);
342 }
343
344 float FontCascade::width(const TextRun& run, HashSet<const Font*>* fallbackFonts, GlyphOverflow* glyphOverflow) const
345 {
346     CodePath codePathToUse = codePath(run);
347     if (codePathToUse != Complex) {
348         // The complex path is more restrictive about returning fallback fonts than the simple path, so we need an explicit test to make their behaviors match.
349         if (!canReturnFallbackFontsForComplexText())
350             fallbackFonts = 0;
351         // The simple path can optimize the case where glyph overflow is not observable.
352         if (codePathToUse != SimpleWithGlyphOverflow && (glyphOverflow && !glyphOverflow->computeBounds))
353             glyphOverflow = 0;
354     }
355
356     bool hasKerningOrLigatures = typesettingFeatures() & (Kerning | Ligatures);
357     bool hasWordSpacingOrLetterSpacing = wordSpacing() || letterSpacing();
358     float* cacheEntry = m_fonts->widthCache().add(run, std::numeric_limits<float>::quiet_NaN(), hasKerningOrLigatures, hasWordSpacingOrLetterSpacing, glyphOverflow);
359     if (cacheEntry && !std::isnan(*cacheEntry))
360         return *cacheEntry;
361
362     HashSet<const Font*> localFallbackFonts;
363     if (!fallbackFonts)
364         fallbackFonts = &localFallbackFonts;
365
366     float result;
367     if (codePathToUse == Complex)
368         result = floatWidthForComplexText(run, fallbackFonts, glyphOverflow);
369     else
370         result = floatWidthForSimpleText(run, fallbackFonts, glyphOverflow);
371
372     if (cacheEntry && fallbackFonts->isEmpty())
373         *cacheEntry = result;
374     return result;
375 }
376
377 float FontCascade::width(const TextRun& run, int& charsConsumed, String& glyphName) const
378 {
379 #if ENABLE(SVG_FONTS)
380     if (isDrawnWithSVGFont(run))
381         return run.renderingContext()->floatWidthUsingSVGFont(*this, run, charsConsumed, glyphName);
382 #endif
383
384     charsConsumed = run.length();
385     glyphName = "";
386     return width(run);
387 }
388
389 GlyphData FontCascade::glyphDataForCharacter(UChar32 c, bool mirror, FontVariant variant) const
390 {
391     if (variant == AutoVariant) {
392         if (m_fontDescription.smallCaps() && !primaryFont().isSVGFont()) {
393             UChar32 upperC = u_toupper(c);
394             if (upperC != c) {
395                 c = upperC;
396                 variant = SmallCapsVariant;
397             } else
398                 variant = NormalVariant;
399         } else
400             variant = NormalVariant;
401     }
402
403     if (mirror)
404         c = u_charMirror(c);
405
406     return m_fonts->glyphDataForCharacter(c, m_fontDescription, variant);
407 }
408
409 #if !PLATFORM(COCOA)
410
411 std::unique_ptr<TextLayout, TextLayoutDeleter> FontCascade::createLayout(RenderText&, float, bool) const
412 {
413     return nullptr;
414 }
415
416 void TextLayoutDeleter::operator()(TextLayout*) const
417 {
418 }
419
420 float FontCascade::width(TextLayout&, unsigned, unsigned, HashSet<const Font*>*)
421 {
422     ASSERT_NOT_REACHED();
423     return 0;
424 }
425
426 #endif
427
428 static const char* fontFamiliesWithInvalidCharWidth[] = {
429     "American Typewriter",
430     "Arial Hebrew",
431     "Chalkboard",
432     "Cochin",
433     "Corsiva Hebrew",
434     "Courier",
435     "Euphemia UCAS",
436     "Geneva",
437     "Gill Sans",
438     "Hei",
439     "Helvetica",
440     "Hoefler Text",
441     "InaiMathi",
442     "Kai",
443     "Lucida Grande",
444     "Marker Felt",
445     "Monaco",
446     "Mshtakan",
447     "New Peninim MT",
448     "Osaka",
449     "Raanana",
450     "STHeiti",
451     "Symbol",
452     "Times",
453     "Apple Braille",
454     "Apple LiGothic",
455     "Apple LiSung",
456     "Apple Symbols",
457     "AppleGothic",
458     "AppleMyungjo",
459     "#GungSeo",
460     "#HeadLineA",
461     "#PCMyungjo",
462     "#PilGi",
463 };
464
465 // For font families where any of the fonts don't have a valid entry in the OS/2 table
466 // for avgCharWidth, fallback to the legacy webkit behavior of getting the avgCharWidth
467 // from the width of a '0'. This only seems to apply to a fixed number of Mac fonts,
468 // but, in order to get similar rendering across platforms, we do this check for
469 // all platforms.
470 bool FontCascade::hasValidAverageCharWidth() const
471 {
472     AtomicString family = firstFamily();
473     if (family.isEmpty())
474         return false;
475
476 #if PLATFORM(MAC) || PLATFORM(IOS)
477     // Internal fonts on OS X and iOS also have an invalid entry in the table for avgCharWidth.
478     if (primaryFontIsSystemFont())
479         return false;
480 #endif
481
482     static HashSet<AtomicString>* fontFamiliesWithInvalidCharWidthMap = 0;
483
484     if (!fontFamiliesWithInvalidCharWidthMap) {
485         fontFamiliesWithInvalidCharWidthMap = new HashSet<AtomicString>;
486
487         for (size_t i = 0; i < WTF_ARRAY_LENGTH(fontFamiliesWithInvalidCharWidth); ++i)
488             fontFamiliesWithInvalidCharWidthMap->add(AtomicString(fontFamiliesWithInvalidCharWidth[i]));
489     }
490
491     return !fontFamiliesWithInvalidCharWidthMap->contains(family);
492 }
493
494 bool FontCascade::fastAverageCharWidthIfAvailable(float& width) const
495 {
496     bool success = hasValidAverageCharWidth();
497     if (success)
498         width = roundf(primaryFont().avgCharWidth()); // FIXME: primaryFont() might not correspond to firstFamily().
499     return success;
500 }
501
502 void FontCascade::adjustSelectionRectForText(const TextRun& run, LayoutRect& selectionRect, int from, int to) const
503 {
504     to = (to == -1 ? run.length() : to);
505
506     CodePath codePathToUse = codePath(run);
507     // FIXME: Use the fast code path once it handles partial runs with kerning and ligatures. See http://webkit.org/b/100050
508     if (codePathToUse != Complex && typesettingFeatures() && (from || static_cast<unsigned>(to) != run.length()) && !isDrawnWithSVGFont(run))
509         codePathToUse = Complex;
510
511     if (codePathToUse != Complex)
512         return adjustSelectionRectForSimpleText(run, selectionRect, from, to);
513
514     return adjustSelectionRectForComplexText(run, selectionRect, from, to);
515 }
516
517 int FontCascade::offsetForPosition(const TextRun& run, float x, bool includePartialGlyphs) const
518 {
519     // FIXME: Use the fast code path once it handles partial runs with kerning and ligatures. See http://webkit.org/b/100050
520     if (codePath(run) != Complex && (!typesettingFeatures() || isDrawnWithSVGFont(run)))
521         return offsetForPositionForSimpleText(run, x, includePartialGlyphs);
522
523     return offsetForPositionForComplexText(run, x, includePartialGlyphs);
524 }
525
526 template <typename CharacterType>
527 static inline String normalizeSpacesInternal(const CharacterType* characters, unsigned length)
528 {
529     StringBuilder normalized;
530     normalized.reserveCapacity(length);
531
532     for (unsigned i = 0; i < length; ++i)
533         normalized.append(FontCascade::normalizeSpaces(characters[i]));
534
535     return normalized.toString();
536 }
537
538 String FontCascade::normalizeSpaces(const LChar* characters, unsigned length)
539 {
540     return normalizeSpacesInternal(characters, length);
541 }
542
543 String FontCascade::normalizeSpaces(const UChar* characters, unsigned length)
544 {
545     return normalizeSpacesInternal(characters, length);
546 }
547
548 static bool shouldUseFontSmoothing = true;
549
550 void FontCascade::setShouldUseSmoothing(bool shouldUseSmoothing)
551 {
552     ASSERT(isMainThread());
553     shouldUseFontSmoothing = shouldUseSmoothing;
554 }
555
556 bool FontCascade::shouldUseSmoothing()
557 {
558     return shouldUseFontSmoothing;
559 }
560
561 static bool antialiasedFontDilationIsEnabled = false;
562
563 void FontCascade::setAntialiasedFontDilationEnabled(bool enabled)
564 {
565     antialiasedFontDilationIsEnabled = enabled;
566 }
567
568 bool FontCascade::antialiasedFontDilationEnabled()
569 {
570     return antialiasedFontDilationIsEnabled;
571 }
572
573 void FontCascade::setCodePath(CodePath p)
574 {
575     s_codePath = p;
576 }
577
578 FontCascade::CodePath FontCascade::codePath()
579 {
580     return s_codePath;
581 }
582
583 void FontCascade::setDefaultTypesettingFeatures(TypesettingFeatures typesettingFeatures)
584 {
585     s_defaultTypesettingFeatures = typesettingFeatures;
586 }
587
588 TypesettingFeatures FontCascade::defaultTypesettingFeatures()
589 {
590     return s_defaultTypesettingFeatures;
591 }
592
593 FontCascade::CodePath FontCascade::codePath(const TextRun& run) const
594 {
595     if (s_codePath != Auto)
596         return s_codePath;
597
598 #if ENABLE(SVG_FONTS)
599     if (isDrawnWithSVGFont(run))
600         return Simple;
601 #endif
602
603     if (m_fontDescription.featureSettings() && m_fontDescription.featureSettings()->size() > 0)
604         return Complex;
605     
606     if (run.length() > 1 && !WidthIterator::supportsTypesettingFeatures(*this))
607         return Complex;
608
609     if (!run.characterScanForCodePath())
610         return Simple;
611
612     if (run.is8Bit())
613         return Simple;
614
615     // Start from 0 since drawing and highlighting also measure the characters before run->from.
616     return characterRangeCodePath(run.characters16(), run.length());
617 }
618
619 FontCascade::CodePath FontCascade::characterRangeCodePath(const UChar* characters, unsigned len)
620 {
621     // FIXME: Should use a UnicodeSet in ports where ICU is used. Note that we 
622     // can't simply use UnicodeCharacter Property/class because some characters
623     // are not 'combining', but still need to go to the complex path.
624     // Alternatively, we may as well consider binary search over a sorted
625     // list of ranges.
626     CodePath result = Simple;
627     bool previousCharacterIsEmojiGroupCandidate = false;
628     for (unsigned i = 0; i < len; i++) {
629         const UChar c = characters[i];
630         if (c == zeroWidthJoiner && previousCharacterIsEmojiGroupCandidate)
631             return Complex;
632         
633         previousCharacterIsEmojiGroupCandidate = false;
634         if (c < 0x2E5) // U+02E5 through U+02E9 (Modifier Letters : Tone letters)  
635             continue;
636         if (c <= 0x2E9) 
637             return Complex;
638
639         if (c < 0x300) // U+0300 through U+036F Combining diacritical marks
640             continue;
641         if (c <= 0x36F)
642             return Complex;
643
644         if (c < 0x0591 || c == 0x05BE) // U+0591 through U+05CF excluding U+05BE Hebrew combining marks, Hebrew punctuation Paseq, Sof Pasuq and Nun Hafukha
645             continue;
646         if (c <= 0x05CF)
647             return Complex;
648
649         // U+0600 through U+109F Arabic, Syriac, Thaana, NKo, Samaritan, Mandaic,
650         // Devanagari, Bengali, Gurmukhi, Gujarati, Oriya, Tamil, Telugu, Kannada, 
651         // Malayalam, Sinhala, Thai, Lao, Tibetan, Myanmar
652         if (c < 0x0600) 
653             continue;
654         if (c <= 0x109F)
655             return Complex;
656
657         // U+1100 through U+11FF Hangul Jamo (only Ancient Korean should be left here if you precompose;
658         // Modern Korean will be precomposed as a result of step A)
659         if (c < 0x1100)
660             continue;
661         if (c <= 0x11FF)
662             return Complex;
663
664         if (c < 0x135D) // U+135D through U+135F Ethiopic combining marks
665             continue;
666         if (c <= 0x135F)
667             return Complex;
668
669         if (c < 0x1700) // U+1780 through U+18AF Tagalog, Hanunoo, Buhid, Taghanwa,Khmer, Mongolian
670             continue;
671         if (c <= 0x18AF)
672             return Complex;
673
674         if (c < 0x1900) // U+1900 through U+194F Limbu (Unicode 4.0)
675             continue;
676         if (c <= 0x194F)
677             return Complex;
678
679         if (c < 0x1980) // U+1980 through U+19DF New Tai Lue
680             continue;
681         if (c <= 0x19DF)
682             return Complex;
683
684         if (c < 0x1A00) // U+1A00 through U+1CFF Buginese, Tai Tham, Balinese, Batak, Lepcha, Vedic
685             continue;
686         if (c <= 0x1CFF)
687             return Complex;
688
689         if (c < 0x1DC0) // U+1DC0 through U+1DFF Comining diacritical mark supplement
690             continue;
691         if (c <= 0x1DFF)
692             return Complex;
693
694         // U+1E00 through U+2000 characters with diacritics and stacked diacritics
695         if (c <= 0x2000) {
696             result = SimpleWithGlyphOverflow;
697             continue;
698         }
699
700         if (c < 0x20D0) // U+20D0 through U+20FF Combining marks for symbols
701             continue;
702         if (c <= 0x20FF)
703             return Complex;
704
705         if (c < 0x2CEF) // U+2CEF through U+2CF1 Combining marks for Coptic
706             continue;
707         if (c <= 0x2CF1)
708             return Complex;
709
710         if (c < 0x302A) // U+302A through U+302F Ideographic and Hangul Tone marks
711             continue;
712         if (c <= 0x302F)
713             return Complex;
714
715         if (c < 0xA67C) // U+A67C through U+A67D Combining marks for old Cyrillic
716             continue;
717         if (c <= 0xA67D)
718             return Complex;
719
720         if (c < 0xA6F0) // U+A6F0 through U+A6F1 Combining mark for Bamum
721             continue;
722         if (c <= 0xA6F1)
723             return Complex;
724
725         // U+A800 through U+ABFF Nagri, Phags-pa, Saurashtra, Devanagari Extended,
726         // Hangul Jamo Ext. A, Javanese, Myanmar Extended A, Tai Viet, Meetei Mayek,
727         if (c < 0xA800) 
728             continue;
729         if (c <= 0xABFF)
730             return Complex;
731
732         if (c < 0xD7B0) // U+D7B0 through U+D7FF Hangul Jamo Ext. B
733             continue;
734         if (c <= 0xD7FF)
735             return Complex;
736
737         if (c <= 0xDBFF) {
738             // High surrogate
739
740             if (i == len - 1)
741                 continue;
742
743             UChar next = characters[++i];
744             if (!U16_IS_TRAIL(next))
745                 continue;
746
747             UChar32 supplementaryCharacter = U16_GET_SUPPLEMENTARY(c, next);
748
749             if (supplementaryCharacter < 0x1F1E6) // U+1F1E6 through U+1F1FF Regional Indicator Symbols
750                 continue;
751             if (supplementaryCharacter <= 0x1F1FF)
752                 return Complex;
753
754             if (supplementaryCharacter == 0x1F441 || supplementaryCharacter == 0x1F5E8 || (supplementaryCharacter >= 0x1F466 && supplementaryCharacter <= 0x1F469)) {
755                 previousCharacterIsEmojiGroupCandidate = true;
756                 continue;
757             }
758             if (isEmojiModifier(supplementaryCharacter))
759                 return Complex;
760             if (supplementaryCharacter < 0xE0100) // U+E0100 through U+E01EF Unicode variation selectors.
761                 continue;
762             if (supplementaryCharacter <= 0xE01EF)
763                 return Complex;
764
765             // FIXME: Check for Brahmi (U+11000 block), Kaithi (U+11080 block) and other complex scripts
766             // in plane 1 or higher.
767
768             continue;
769         }
770
771         if (c < 0xFE00) // U+FE00 through U+FE0F Unicode variation selectors
772             continue;
773         if (c <= 0xFE0F)
774             return Complex;
775
776         if (c < 0xFE20) // U+FE20 through U+FE2F Combining half marks
777             continue;
778         if (c <= 0xFE2F)
779             return Complex;
780     }
781     return result;
782 }
783
784 bool FontCascade::isCJKIdeograph(UChar32 c)
785 {
786     // The basic CJK Unified Ideographs block.
787     if (c >= 0x4E00 && c <= 0x9FFF)
788         return true;
789     
790     // CJK Unified Ideographs Extension A.
791     if (c >= 0x3400 && c <= 0x4DBF)
792         return true;
793     
794     // CJK Radicals Supplement.
795     if (c >= 0x2E80 && c <= 0x2EFF)
796         return true;
797     
798     // Kangxi Radicals.
799     if (c >= 0x2F00 && c <= 0x2FDF)
800         return true;
801     
802     // CJK Strokes.
803     if (c >= 0x31C0 && c <= 0x31EF)
804         return true;
805     
806     // CJK Compatibility Ideographs.
807     if (c >= 0xF900 && c <= 0xFAFF)
808         return true;
809
810     // CJK Unified Ideographs Extension B.
811     if (c >= 0x20000 && c <= 0x2A6DF)
812         return true;
813
814     // CJK Unified Ideographs Extension C.
815     if (c >= 0x2A700 && c <= 0x2B73F)
816         return true;
817     
818     // CJK Unified Ideographs Extension D.
819     if (c >= 0x2B740 && c <= 0x2B81F)
820         return true;
821     
822     // CJK Compatibility Ideographs Supplement.
823     if (c >= 0x2F800 && c <= 0x2FA1F)
824         return true;
825
826     return false;
827 }
828
829 bool FontCascade::isCJKIdeographOrSymbol(UChar32 c)
830 {
831     // 0x2C7 Caron, Mandarin Chinese 3rd Tone
832     // 0x2CA Modifier Letter Acute Accent, Mandarin Chinese 2nd Tone
833     // 0x2CB Modifier Letter Grave Access, Mandarin Chinese 4th Tone 
834     // 0x2D9 Dot Above, Mandarin Chinese 5th Tone 
835     if ((c == 0x2C7) || (c == 0x2CA) || (c == 0x2CB) || (c == 0x2D9))
836         return true;
837
838     if ((c == 0x2020) || (c == 0x2021) || (c == 0x2030) || (c == 0x203B) || (c == 0x203C)
839         || (c == 0x2042) || (c == 0x2047) || (c == 0x2048) || (c == 0x2049) || (c == 0x2051)
840         || (c == 0x20DD) || (c == 0x20DE) || (c == 0x2100) || (c == 0x2103) || (c == 0x2105)
841         || (c == 0x2109) || (c == 0x210A) || (c == 0x2113) || (c == 0x2116) || (c == 0x2121)
842         || (c == 0x212B) || (c == 0x213B) || (c == 0x2150) || (c == 0x2151) || (c == 0x2152))
843         return true;
844
845     if (c >= 0x2156 && c <= 0x215A)
846         return true;
847
848     if (c >= 0x2160 && c <= 0x216B)
849         return true;
850
851     if (c >= 0x2170 && c <= 0x217B)
852         return true;
853
854     if ((c == 0x217F) || (c == 0x2189) || (c == 0x2307) || (c == 0x2312) || (c == 0x23BE) || (c == 0x23BF))
855         return true;
856
857     if (c >= 0x23C0 && c <= 0x23CC)
858         return true;
859
860     if ((c == 0x23CE) || (c == 0x2423))
861         return true;
862
863     if (c >= 0x2460 && c <= 0x2492)
864         return true;
865
866     if (c >= 0x249C && c <= 0x24FF)
867         return true;
868
869     if ((c == 0x25A0) || (c == 0x25A1) || (c == 0x25A2) || (c == 0x25AA) || (c == 0x25AB))
870         return true;
871
872     if ((c == 0x25B1) || (c == 0x25B2) || (c == 0x25B3) || (c == 0x25B6) || (c == 0x25B7) || (c == 0x25BC) || (c == 0x25BD))
873         return true;
874     
875     if ((c == 0x25C0) || (c == 0x25C1) || (c == 0x25C6) || (c == 0x25C7) || (c == 0x25C9) || (c == 0x25CB) || (c == 0x25CC))
876         return true;
877
878     if (c >= 0x25CE && c <= 0x25D3)
879         return true;
880
881     if (c >= 0x25E2 && c <= 0x25E6)
882         return true;
883
884     if (c == 0x25EF)
885         return true;
886
887     if (c >= 0x2600 && c <= 0x2603)
888         return true;
889
890     if ((c == 0x2605) || (c == 0x2606) || (c == 0x260E) || (c == 0x2616) || (c == 0x2617) || (c == 0x2640) || (c == 0x2642))
891         return true;
892
893     if (c >= 0x2660 && c <= 0x266F)
894         return true;
895
896     if (c >= 0x2672 && c <= 0x267D)
897         return true;
898
899     if ((c == 0x26A0) || (c == 0x26BD) || (c == 0x26BE) || (c == 0x2713) || (c == 0x271A) || (c == 0x273F) || (c == 0x2740) || (c == 0x2756))
900         return true;
901
902     if (c >= 0x2776 && c <= 0x277F)
903         return true;
904
905     if (c == 0x2B1A)
906         return true;
907
908     // Ideographic Description Characters.
909     if (c >= 0x2FF0 && c <= 0x2FFF)
910         return true;
911
912     // CJK Symbols and Punctuation, excluding 0x3030.
913     if (c >= 0x3000 && c < 0x3030)
914         return true;
915
916     if (c > 0x3030 && c <= 0x303F)
917         return true;
918
919     // Hiragana
920     if (c >= 0x3040 && c <= 0x309F)
921         return true;
922
923     // Katakana 
924     if (c >= 0x30A0 && c <= 0x30FF)
925         return true;
926
927     // Bopomofo
928     if (c >= 0x3100 && c <= 0x312F)
929         return true;
930
931     if (c >= 0x3190 && c <= 0x319F)
932         return true;
933
934     // Bopomofo Extended
935     if (c >= 0x31A0 && c <= 0x31BF)
936         return true;
937
938     // Enclosed CJK Letters and Months.
939     if (c >= 0x3200 && c <= 0x32FF)
940         return true;
941     
942     // CJK Compatibility.
943     if (c >= 0x3300 && c <= 0x33FF)
944         return true;
945
946     if (c >= 0xF860 && c <= 0xF862)
947         return true;
948
949     // CJK Compatibility Forms.
950     if (c >= 0xFE30 && c <= 0xFE4F)
951         return true;
952
953     if ((c == 0xFE10) || (c == 0xFE11) || (c == 0xFE12) || (c == 0xFE19))
954         return true;
955
956     if ((c == 0xFF0D) || (c == 0xFF1B) || (c == 0xFF1C) || (c == 0xFF1E))
957         return false;
958
959     // Halfwidth and Fullwidth Forms
960     // Usually only used in CJK
961     if (c >= 0xFF00 && c <= 0xFFEF)
962         return true;
963
964     // Emoji.
965     if (c == 0x1F100)
966         return true;
967
968     if (c >= 0x1F110 && c <= 0x1F129)
969         return true;
970
971     if (c >= 0x1F130 && c <= 0x1F149)
972         return true;
973
974     if (c >= 0x1F150 && c <= 0x1F169)
975         return true;
976
977     if (c >= 0x1F170 && c <= 0x1F189)
978         return true;
979
980     if (c >= 0x1F200 && c <= 0x1F6C5)
981         return true;
982
983     return isCJKIdeograph(c);
984 }
985
986 std::pair<unsigned, bool> FontCascade::expansionOpportunityCountInternal(const LChar* characters, size_t length, TextDirection direction, ExpansionBehavior expansionBehavior)
987 {
988     unsigned count = 0;
989     bool isAfterExpansion = (expansionBehavior & LeadingExpansionMask) == ForbidLeadingExpansion;
990     if ((expansionBehavior & LeadingExpansionMask) == ForceLeadingExpansion) {
991         ++count;
992         isAfterExpansion = true;
993     }
994     if (direction == LTR) {
995         for (size_t i = 0; i < length; ++i) {
996             if (treatAsSpace(characters[i])) {
997                 count++;
998                 isAfterExpansion = true;
999             } else
1000                 isAfterExpansion = false;
1001         }
1002     } else {
1003         for (size_t i = length; i > 0; --i) {
1004             if (treatAsSpace(characters[i - 1])) {
1005                 count++;
1006                 isAfterExpansion = true;
1007             } else
1008                 isAfterExpansion = false;
1009         }
1010     }
1011     if (!isAfterExpansion && (expansionBehavior & TrailingExpansionMask) == ForceTrailingExpansion) {
1012         ++count;
1013         isAfterExpansion = true;
1014     } else if (isAfterExpansion && (expansionBehavior & TrailingExpansionMask) == ForbidTrailingExpansion) {
1015         --count;
1016         isAfterExpansion = false;
1017     }
1018     return std::make_pair(count, isAfterExpansion);
1019 }
1020
1021 std::pair<unsigned, bool> FontCascade::expansionOpportunityCountInternal(const UChar* characters, size_t length, TextDirection direction, ExpansionBehavior expansionBehavior)
1022 {
1023     static bool expandAroundIdeographs = canExpandAroundIdeographsInComplexText();
1024     unsigned count = 0;
1025     bool isAfterExpansion = (expansionBehavior & LeadingExpansionMask) == ForbidLeadingExpansion;
1026     if ((expansionBehavior & LeadingExpansionMask) == ForceLeadingExpansion) {
1027         ++count;
1028         isAfterExpansion = true;
1029     }
1030     if (direction == LTR) {
1031         for (size_t i = 0; i < length; ++i) {
1032             UChar32 character = characters[i];
1033             if (treatAsSpace(character)) {
1034                 count++;
1035                 isAfterExpansion = true;
1036                 continue;
1037             }
1038             if (U16_IS_LEAD(character) && i + 1 < length && U16_IS_TRAIL(characters[i + 1])) {
1039                 character = U16_GET_SUPPLEMENTARY(character, characters[i + 1]);
1040                 i++;
1041             }
1042             if (expandAroundIdeographs && isCJKIdeographOrSymbol(character)) {
1043                 if (!isAfterExpansion)
1044                     count++;
1045                 count++;
1046                 isAfterExpansion = true;
1047                 continue;
1048             }
1049             isAfterExpansion = false;
1050         }
1051     } else {
1052         for (size_t i = length; i > 0; --i) {
1053             UChar32 character = characters[i - 1];
1054             if (treatAsSpace(character)) {
1055                 count++;
1056                 isAfterExpansion = true;
1057                 continue;
1058             }
1059             if (U16_IS_TRAIL(character) && i > 1 && U16_IS_LEAD(characters[i - 2])) {
1060                 character = U16_GET_SUPPLEMENTARY(characters[i - 2], character);
1061                 i--;
1062             }
1063             if (expandAroundIdeographs && isCJKIdeographOrSymbol(character)) {
1064                 if (!isAfterExpansion)
1065                     count++;
1066                 count++;
1067                 isAfterExpansion = true;
1068                 continue;
1069             }
1070             isAfterExpansion = false;
1071         }
1072     }
1073     if (!isAfterExpansion && (expansionBehavior & TrailingExpansionMask) == ForceTrailingExpansion) {
1074         ++count;
1075         isAfterExpansion = true;
1076     } else if (isAfterExpansion && (expansionBehavior & TrailingExpansionMask) == ForbidTrailingExpansion) {
1077         --count;
1078         isAfterExpansion = false;
1079     }
1080     return std::make_pair(count, isAfterExpansion);
1081 }
1082
1083 std::pair<unsigned, bool> FontCascade::expansionOpportunityCount(const StringView& stringView, TextDirection direction, ExpansionBehavior expansionBehavior)
1084 {
1085     // For each character, iterating from left to right:
1086     //   If it is recognized as a space, insert an opportunity after it
1087     //   If it is an ideograph, insert one opportunity before it and one opportunity after it
1088     // Do this such a way so that there are not two opportunities next to each other.
1089     if (stringView.is8Bit())
1090         return expansionOpportunityCountInternal(stringView.characters8(), stringView.length(), direction, expansionBehavior);
1091     return expansionOpportunityCountInternal(stringView.characters16(), stringView.length(), direction, expansionBehavior);
1092 }
1093
1094 bool FontCascade::leadingExpansionOpportunity(const StringView& stringView, TextDirection direction)
1095 {
1096     if (!stringView.length())
1097         return false;
1098
1099     UChar32 initialCharacter;
1100     if (direction == LTR) {
1101         initialCharacter = stringView[0];
1102         if (U16_IS_LEAD(initialCharacter) && stringView.length() > 1 && U16_IS_TRAIL(stringView[1]))
1103             initialCharacter = U16_GET_SUPPLEMENTARY(initialCharacter, stringView[1]);
1104     } else {
1105         initialCharacter = stringView[stringView.length() - 1];
1106         if (U16_IS_TRAIL(initialCharacter) && stringView.length() > 1 && U16_IS_LEAD(stringView[stringView.length() - 2]))
1107             initialCharacter = U16_GET_SUPPLEMENTARY(stringView[stringView.length() - 2], initialCharacter);
1108     }
1109
1110     return canExpandAroundIdeographsInComplexText() && isCJKIdeographOrSymbol(initialCharacter);
1111 }
1112
1113 bool FontCascade::trailingExpansionOpportunity(const StringView& stringView, TextDirection direction)
1114 {
1115     if (!stringView.length())
1116         return false;
1117
1118     UChar32 finalCharacter;
1119     if (direction == LTR) {
1120         finalCharacter = stringView[stringView.length() - 1];
1121         if (U16_IS_TRAIL(finalCharacter) && stringView.length() > 1 && U16_IS_LEAD(stringView[stringView.length() - 2]))
1122             finalCharacter = U16_GET_SUPPLEMENTARY(stringView[stringView.length() - 2], finalCharacter);
1123     } else {
1124         finalCharacter = stringView[0];
1125         if (U16_IS_LEAD(finalCharacter) && stringView.length() > 1 && U16_IS_TRAIL(stringView[1]))
1126             finalCharacter = U16_GET_SUPPLEMENTARY(finalCharacter, stringView[1]);
1127     }
1128
1129     return treatAsSpace(finalCharacter) || (canExpandAroundIdeographsInComplexText() && isCJKIdeographOrSymbol(finalCharacter));
1130 }
1131
1132 bool FontCascade::canReceiveTextEmphasis(UChar32 c)
1133 {
1134     if (U_GET_GC_MASK(c) & (U_GC_Z_MASK | U_GC_CN_MASK | U_GC_CC_MASK | U_GC_CF_MASK))
1135         return false;
1136
1137     // Additional word-separator characters listed in CSS Text Level 3 Editor's Draft 3 November 2010.
1138     if (c == ethiopicWordspace || c == aegeanWordSeparatorLine || c == aegeanWordSeparatorDot
1139         || c == ugariticWordDivider || c == tibetanMarkIntersyllabicTsheg || c == tibetanMarkDelimiterTshegBstar)
1140         return false;
1141
1142     return true;
1143 }
1144
1145 bool FontCascade::isLoadingCustomFonts() const
1146 {
1147     return m_fonts && m_fonts->isLoadingCustomFonts();
1148 }
1149     
1150 GlyphToPathTranslator::GlyphUnderlineType computeUnderlineType(const TextRun& textRun, const GlyphBuffer& glyphBuffer, int index)
1151 {
1152     // In general, we want to skip descenders. However, skipping descenders on CJK characters leads to undesirable renderings,
1153     // so we want to draw through CJK characters (on a character-by-character basis).
1154     UChar32 baseCharacter;
1155     unsigned offsetInString = glyphBuffer.offsetInString(index);
1156
1157     if (offsetInString == GlyphBuffer::noOffset) {
1158         // We have no idea which character spawned this glyph. Bail.
1159         return GlyphToPathTranslator::GlyphUnderlineType::DrawOverGlyph;
1160     }
1161     
1162     if (textRun.is8Bit())
1163         baseCharacter = textRun.characters8()[offsetInString];
1164     else
1165         U16_NEXT(textRun.characters16(), offsetInString, textRun.length(), baseCharacter);
1166     
1167     // u_getIntPropertyValue with UCHAR_IDEOGRAPHIC doesn't return true for Japanese or Korean codepoints.
1168     // Instead, we can use the "Unicode allocation block" for the character.
1169     UBlockCode blockCode = ublock_getCode(baseCharacter);
1170     switch (blockCode) {
1171     case UBLOCK_CJK_RADICALS_SUPPLEMENT:
1172     case UBLOCK_CJK_SYMBOLS_AND_PUNCTUATION:
1173     case UBLOCK_ENCLOSED_CJK_LETTERS_AND_MONTHS:
1174     case UBLOCK_CJK_COMPATIBILITY:
1175     case UBLOCK_CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A:
1176     case UBLOCK_CJK_UNIFIED_IDEOGRAPHS:
1177     case UBLOCK_CJK_COMPATIBILITY_IDEOGRAPHS:
1178     case UBLOCK_CJK_COMPATIBILITY_FORMS:
1179     case UBLOCK_CJK_UNIFIED_IDEOGRAPHS_EXTENSION_B:
1180     case UBLOCK_CJK_COMPATIBILITY_IDEOGRAPHS_SUPPLEMENT:
1181     case UBLOCK_CJK_STROKES:
1182     case UBLOCK_CJK_UNIFIED_IDEOGRAPHS_EXTENSION_C:
1183     case UBLOCK_CJK_UNIFIED_IDEOGRAPHS_EXTENSION_D:
1184     case UBLOCK_IDEOGRAPHIC_DESCRIPTION_CHARACTERS:
1185     case UBLOCK_LINEAR_B_IDEOGRAMS:
1186     case UBLOCK_ENCLOSED_IDEOGRAPHIC_SUPPLEMENT:
1187     case UBLOCK_HIRAGANA:
1188     case UBLOCK_KATAKANA:
1189     case UBLOCK_BOPOMOFO:
1190     case UBLOCK_BOPOMOFO_EXTENDED:
1191     case UBLOCK_HANGUL_JAMO:
1192     case UBLOCK_HANGUL_COMPATIBILITY_JAMO:
1193     case UBLOCK_HANGUL_SYLLABLES:
1194     case UBLOCK_HANGUL_JAMO_EXTENDED_A:
1195     case UBLOCK_HANGUL_JAMO_EXTENDED_B:
1196         return GlyphToPathTranslator::GlyphUnderlineType::DrawOverGlyph;
1197     default:
1198         return GlyphToPathTranslator::GlyphUnderlineType::SkipDescenders;
1199     }
1200 }
1201
1202 // FIXME: This function may not work if the emphasis mark uses a complex script, but none of the
1203 // standard emphasis marks do so.
1204 bool FontCascade::getEmphasisMarkGlyphData(const AtomicString& mark, GlyphData& glyphData) const
1205 {
1206     if (mark.isEmpty())
1207         return false;
1208
1209     UChar32 character = mark[0];
1210
1211     if (U16_IS_SURROGATE(character)) {
1212         if (!U16_IS_SURROGATE_LEAD(character))
1213             return false;
1214
1215         if (mark.length() < 2)
1216             return false;
1217
1218         UChar low = mark[1];
1219         if (!U16_IS_TRAIL(low))
1220             return false;
1221
1222         character = U16_GET_SUPPLEMENTARY(character, low);
1223     }
1224
1225     glyphData = glyphDataForCharacter(character, false, EmphasisMarkVariant);
1226     return true;
1227 }
1228
1229 int FontCascade::emphasisMarkAscent(const AtomicString& mark) const
1230 {
1231     GlyphData markGlyphData;
1232     if (!getEmphasisMarkGlyphData(mark, markGlyphData))
1233         return 0;
1234
1235     const Font* markFontData = markGlyphData.font;
1236     ASSERT(markFontData);
1237     if (!markFontData)
1238         return 0;
1239
1240     return markFontData->fontMetrics().ascent();
1241 }
1242
1243 int FontCascade::emphasisMarkDescent(const AtomicString& mark) const
1244 {
1245     GlyphData markGlyphData;
1246     if (!getEmphasisMarkGlyphData(mark, markGlyphData))
1247         return 0;
1248
1249     const Font* markFontData = markGlyphData.font;
1250     ASSERT(markFontData);
1251     if (!markFontData)
1252         return 0;
1253
1254     return markFontData->fontMetrics().descent();
1255 }
1256
1257 int FontCascade::emphasisMarkHeight(const AtomicString& mark) const
1258 {
1259     GlyphData markGlyphData;
1260     if (!getEmphasisMarkGlyphData(mark, markGlyphData))
1261         return 0;
1262
1263     const Font* markFontData = markGlyphData.font;
1264     ASSERT(markFontData);
1265     if (!markFontData)
1266         return 0;
1267
1268     return markFontData->fontMetrics().height();
1269 }
1270
1271 float FontCascade::getGlyphsAndAdvancesForSimpleText(const TextRun& run, int from, int to, GlyphBuffer& glyphBuffer, ForTextEmphasisOrNot forTextEmphasis) const
1272 {
1273     float initialAdvance;
1274
1275     WidthIterator it(this, run, 0, false, forTextEmphasis);
1276     // FIXME: Using separate glyph buffers for the prefix and the suffix is incorrect when kerning or
1277     // ligatures are enabled.
1278     GlyphBuffer localGlyphBuffer;
1279     it.advance(from, &localGlyphBuffer);
1280     float beforeWidth = it.m_runWidthSoFar;
1281     it.advance(to, &glyphBuffer);
1282
1283     if (glyphBuffer.isEmpty())
1284         return 0;
1285
1286     float afterWidth = it.m_runWidthSoFar;
1287
1288     if (run.rtl()) {
1289         float finalRoundingWidth = it.m_finalRoundingWidth;
1290         it.advance(run.length(), &localGlyphBuffer);
1291         initialAdvance = finalRoundingWidth + it.m_runWidthSoFar - afterWidth;
1292     } else
1293         initialAdvance = beforeWidth;
1294
1295     if (run.rtl())
1296         glyphBuffer.reverse(0, glyphBuffer.size());
1297
1298     return initialAdvance;
1299 }
1300
1301 float FontCascade::drawSimpleText(GraphicsContext* context, const TextRun& run, const FloatPoint& point, int from, int to) const
1302 {
1303     // This glyph buffer holds our glyphs+advances+font data for each glyph.
1304     GlyphBuffer glyphBuffer;
1305
1306     float startX = point.x() + getGlyphsAndAdvancesForSimpleText(run, from, to, glyphBuffer);
1307
1308     if (glyphBuffer.isEmpty())
1309         return 0;
1310
1311     FloatPoint startPoint(startX, point.y());
1312     drawGlyphBuffer(context, run, glyphBuffer, startPoint);
1313
1314     return startPoint.x() - startX;
1315 }
1316
1317 void FontCascade::drawEmphasisMarksForSimpleText(GraphicsContext* context, const TextRun& run, const AtomicString& mark, const FloatPoint& point, int from, int to) const
1318 {
1319     GlyphBuffer glyphBuffer;
1320     float initialAdvance = getGlyphsAndAdvancesForSimpleText(run, from, to, glyphBuffer, ForTextEmphasis);
1321
1322     if (glyphBuffer.isEmpty())
1323         return;
1324
1325     drawEmphasisMarks(context, run, glyphBuffer, mark, FloatPoint(point.x() + initialAdvance, point.y()));
1326 }
1327
1328 void FontCascade::drawGlyphBuffer(GraphicsContext* context, const TextRun& run, const GlyphBuffer& glyphBuffer, FloatPoint& point) const
1329 {
1330 #if !ENABLE(SVG_FONTS)
1331     UNUSED_PARAM(run);
1332 #endif
1333
1334     // Draw each contiguous run of glyphs that use the same font data.
1335     const Font* fontData = glyphBuffer.fontAt(0);
1336     FloatSize offset = glyphBuffer.offsetAt(0);
1337     FloatPoint startPoint(point.x(), point.y() - glyphBuffer.initialAdvance().height());
1338     float nextX = startPoint.x() + glyphBuffer.advanceAt(0).width();
1339     float nextY = startPoint.y() + glyphBuffer.advanceAt(0).height();
1340     int lastFrom = 0;
1341     int nextGlyph = 1;
1342 #if ENABLE(SVG_FONTS)
1343     TextRun::RenderingContext* renderingContext = run.renderingContext();
1344 #endif
1345     while (nextGlyph < glyphBuffer.size()) {
1346         const Font* nextFontData = glyphBuffer.fontAt(nextGlyph);
1347         FloatSize nextOffset = glyphBuffer.offsetAt(nextGlyph);
1348
1349         if (nextFontData != fontData || nextOffset != offset) {
1350 #if ENABLE(SVG_FONTS)
1351             if (renderingContext && fontData->isSVGFont())
1352                 renderingContext->drawSVGGlyphs(context, fontData, glyphBuffer, lastFrom, nextGlyph - lastFrom, startPoint);
1353             else
1354 #endif
1355                 drawGlyphs(context, fontData, glyphBuffer, lastFrom, nextGlyph - lastFrom, startPoint);
1356
1357             lastFrom = nextGlyph;
1358             fontData = nextFontData;
1359             offset = nextOffset;
1360             startPoint.setX(nextX);
1361             startPoint.setY(nextY);
1362         }
1363         nextX += glyphBuffer.advanceAt(nextGlyph).width();
1364         nextY += glyphBuffer.advanceAt(nextGlyph).height();
1365         nextGlyph++;
1366     }
1367
1368 #if ENABLE(SVG_FONTS)
1369     if (renderingContext && fontData->isSVGFont())
1370         renderingContext->drawSVGGlyphs(context, fontData, glyphBuffer, lastFrom, nextGlyph - lastFrom, startPoint);
1371     else
1372 #endif
1373     {
1374         drawGlyphs(context, fontData, glyphBuffer, lastFrom, nextGlyph - lastFrom, startPoint);
1375         point.setX(nextX);
1376     }
1377 }
1378
1379 inline static float offsetToMiddleOfGlyph(const Font* fontData, Glyph glyph)
1380 {
1381     if (fontData->platformData().orientation() == Horizontal) {
1382         FloatRect bounds = fontData->boundsForGlyph(glyph);
1383         return bounds.x() + bounds.width() / 2;
1384     }
1385     // FIXME: Use glyph bounds once they make sense for vertical fonts.
1386     return fontData->widthForGlyph(glyph) / 2;
1387 }
1388
1389 inline static float offsetToMiddleOfGlyphAtIndex(const GlyphBuffer& glyphBuffer, size_t i)
1390 {
1391     return offsetToMiddleOfGlyph(glyphBuffer.fontAt(i), glyphBuffer.glyphAt(i));
1392 }
1393
1394 void FontCascade::drawEmphasisMarks(GraphicsContext* context, const TextRun& run, const GlyphBuffer& glyphBuffer, const AtomicString& mark, const FloatPoint& point) const
1395 {
1396     GlyphData markGlyphData;
1397     if (!getEmphasisMarkGlyphData(mark, markGlyphData))
1398         return;
1399
1400     const Font* markFontData = markGlyphData.font;
1401     ASSERT(markFontData);
1402     if (!markFontData)
1403         return;
1404
1405     Glyph markGlyph = markGlyphData.glyph;
1406     Glyph spaceGlyph = markFontData->spaceGlyph();
1407
1408     float middleOfLastGlyph = offsetToMiddleOfGlyphAtIndex(glyphBuffer, 0);
1409     FloatPoint startPoint(point.x() + middleOfLastGlyph - offsetToMiddleOfGlyph(markFontData, markGlyph), point.y());
1410
1411     GlyphBuffer markBuffer;
1412     for (int i = 0; i + 1 < glyphBuffer.size(); ++i) {
1413         float middleOfNextGlyph = offsetToMiddleOfGlyphAtIndex(glyphBuffer, i + 1);
1414         float advance = glyphBuffer.advanceAt(i).width() - middleOfLastGlyph + middleOfNextGlyph;
1415         markBuffer.add(glyphBuffer.glyphAt(i) ? markGlyph : spaceGlyph, markFontData, advance);
1416         middleOfLastGlyph = middleOfNextGlyph;
1417     }
1418     markBuffer.add(glyphBuffer.glyphAt(glyphBuffer.size() - 1) ? markGlyph : spaceGlyph, markFontData, 0);
1419
1420     drawGlyphBuffer(context, run, markBuffer, startPoint);
1421 }
1422
1423 float FontCascade::floatWidthForSimpleText(const TextRun& run, HashSet<const Font*>* fallbackFonts, GlyphOverflow* glyphOverflow) const
1424 {
1425     WidthIterator it(this, run, fallbackFonts, glyphOverflow);
1426     GlyphBuffer glyphBuffer;
1427     it.advance(run.length(), (typesettingFeatures() & (Kerning | Ligatures)) ? &glyphBuffer : 0);
1428
1429     if (glyphOverflow) {
1430         glyphOverflow->top = std::max<int>(glyphOverflow->top, ceilf(-it.minGlyphBoundingBoxY()) - (glyphOverflow->computeBounds ? 0 : fontMetrics().ascent()));
1431         glyphOverflow->bottom = std::max<int>(glyphOverflow->bottom, ceilf(it.maxGlyphBoundingBoxY()) - (glyphOverflow->computeBounds ? 0 : fontMetrics().descent()));
1432         glyphOverflow->left = ceilf(it.firstGlyphOverflow());
1433         glyphOverflow->right = ceilf(it.lastGlyphOverflow());
1434     }
1435
1436     return it.m_runWidthSoFar;
1437 }
1438
1439 void FontCascade::adjustSelectionRectForSimpleText(const TextRun& run, LayoutRect& selectionRect, int from, int to) const
1440 {
1441     GlyphBuffer glyphBuffer;
1442     WidthIterator it(this, run);
1443     it.advance(from, &glyphBuffer);
1444     float beforeWidth = it.m_runWidthSoFar;
1445     it.advance(to, &glyphBuffer);
1446     float afterWidth = it.m_runWidthSoFar;
1447     float totalWidth = -1;
1448
1449     if (run.rtl()) {
1450         it.advance(run.length(), &glyphBuffer);
1451         totalWidth = it.m_runWidthSoFar;
1452         selectionRect.move(totalWidth - afterWidth, 0);
1453     } else
1454         selectionRect.move(beforeWidth, 0);
1455     selectionRect.setWidth(LayoutUnit::fromFloatCeil(afterWidth - beforeWidth));
1456 }
1457
1458 int FontCascade::offsetForPositionForSimpleText(const TextRun& run, float x, bool includePartialGlyphs) const
1459 {
1460     float delta = x;
1461
1462     WidthIterator it(this, run);
1463     GlyphBuffer localGlyphBuffer;
1464     unsigned offset;
1465     if (run.rtl()) {
1466         delta -= floatWidthForSimpleText(run);
1467         while (1) {
1468             offset = it.m_currentCharacter;
1469             float w;
1470             if (!it.advanceOneCharacter(w, localGlyphBuffer))
1471                 break;
1472             delta += w;
1473             if (includePartialGlyphs) {
1474                 if (delta - w / 2 >= 0)
1475                     break;
1476             } else {
1477                 if (delta >= 0)
1478                     break;
1479             }
1480         }
1481     } else {
1482         while (1) {
1483             offset = it.m_currentCharacter;
1484             float w;
1485             if (!it.advanceOneCharacter(w, localGlyphBuffer))
1486                 break;
1487             delta -= w;
1488             if (includePartialGlyphs) {
1489                 if (delta + w / 2 <= 0)
1490                     break;
1491             } else {
1492                 if (delta <= 0)
1493                     break;
1494             }
1495         }
1496     }
1497
1498     return offset;
1499 }
1500
1501
1502 }