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