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