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