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