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