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