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