e67c5ec4ea59ebe0a19574192681fd5ff639e8d1
[WebKit-https.git] / Source / WebCore / platform / graphics / Font.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 "Font.h"
26
27 #include "FloatRect.h"
28 #include "FontCache.h"
29 #include "FontTranscoder.h"
30 #include "IntPoint.h"
31 #include "GlyphBuffer.h"
32 #include "TextRun.h"
33 #include "WidthIterator.h"
34 #include <wtf/MainThread.h>
35 #include <wtf/MathExtras.h>
36 #include <wtf/text/StringBuilder.h>
37
38 using namespace WTF;
39 using namespace Unicode;
40
41 namespace WTF {
42
43 // allow compilation of OwnPtr<TextLayout> in source files that don't have access to the TextLayout class definition
44 template <> void deleteOwnedPtr<WebCore::TextLayout>(WebCore::TextLayout* ptr)
45 {
46     WebCore::Font::deleteLayout(ptr);
47 }
48
49 }
50
51 namespace WebCore {
52
53 const uint8_t Font::s_roundingHackCharacterTable[256] = {
54     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,
55     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 /*?*/,
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     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,
58     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,
59     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,
60     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,
61     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
62 };
63
64 Font::CodePath Font::s_codePath = Auto;
65
66 TypesettingFeatures Font::s_defaultTypesettingFeatures = 0;
67
68 // ============================================================================================
69 // Font Implementation (Cross-Platform Portion)
70 // ============================================================================================
71
72 Font::Font()
73     : m_letterSpacing(0)
74     , m_wordSpacing(0)
75     , m_needsTranscoding(false)
76     , m_typesettingFeatures(0)
77 {
78 }
79
80 Font::Font(const FontDescription& fd, short letterSpacing, short wordSpacing) 
81     : m_fontDescription(fd)
82     , m_letterSpacing(letterSpacing)
83     , m_wordSpacing(wordSpacing)
84     , m_needsTranscoding(fontTranscoder().needsTranscoding(fd))
85     , m_typesettingFeatures(computeTypesettingFeatures())
86 {
87 }
88
89 Font::Font(const FontPlatformData& fontData, bool isPrinterFont, FontSmoothingMode fontSmoothingMode)
90     : m_glyphs(FontGlyphs::createForPlatformFont(fontData))
91     , m_letterSpacing(0)
92     , m_wordSpacing(0)
93     , m_typesettingFeatures(computeTypesettingFeatures())
94 {
95     m_fontDescription.setUsePrinterFont(isPrinterFont);
96     m_fontDescription.setFontSmoothing(fontSmoothingMode);
97     m_needsTranscoding = fontTranscoder().needsTranscoding(fontDescription());
98 }
99
100 Font::Font(const Font& other)
101     : m_fontDescription(other.m_fontDescription)
102     , m_glyphs(other.m_glyphs)
103     , m_letterSpacing(other.m_letterSpacing)
104     , m_wordSpacing(other.m_wordSpacing)
105     , m_needsTranscoding(other.m_needsTranscoding)
106     , m_typesettingFeatures(computeTypesettingFeatures())
107 {
108 }
109
110 Font& Font::operator=(const Font& other)
111 {
112     m_fontDescription = other.m_fontDescription;
113     m_glyphs = other.m_glyphs;
114     m_letterSpacing = other.m_letterSpacing;
115     m_wordSpacing = other.m_wordSpacing;
116     m_needsTranscoding = other.m_needsTranscoding;
117     m_typesettingFeatures = other.m_typesettingFeatures;
118     return *this;
119 }
120
121 bool Font::operator==(const Font& other) const
122 {
123     // Our FontData don't have to be checked, since checking the font description will be fine.
124     // FIXME: This does not work if the font was made with the FontPlatformData constructor.
125     if (loadingCustomFonts() || other.loadingCustomFonts())
126         return false;
127
128     if (m_fontDescription != other.m_fontDescription || m_letterSpacing != other.m_letterSpacing || m_wordSpacing != other.m_wordSpacing)
129         return false;
130     if (m_glyphs == other.m_glyphs)
131         return true;
132     if (!m_glyphs || !other.m_glyphs)
133         return false;
134     if (m_glyphs->fontSelector() != other.m_glyphs->fontSelector())
135         return false;
136     // Can these cases actually somehow occur? All fonts should get wiped out by full style recalc.
137     if (m_glyphs->fontSelectorVersion() != other.m_glyphs->fontSelectorVersion())
138         return false;
139     if (m_glyphs->generation() != other.m_glyphs->generation())
140         return false;
141     return true;
142 }
143
144 struct FontGlyphsCacheKey {
145     // This part of the key is shared with the lower level FontCache (caching FontData objects).
146     FontDescriptionFontDataCacheKey fontDescriptionCacheKey;
147     Vector<AtomicString, 3> families;
148     unsigned fontSelectorId;
149     unsigned fontSelectorVersion;
150     unsigned fontSelectorFlags;
151 };
152
153 struct FontGlyphsCacheEntry {
154     WTF_MAKE_FAST_ALLOCATED;
155 public:
156     FontGlyphsCacheKey key;
157     RefPtr<FontGlyphs> glyphs;
158 };
159
160 typedef HashMap<unsigned, OwnPtr<FontGlyphsCacheEntry>, AlreadyHashed> FontGlyphsCache;
161
162 static bool operator==(const FontGlyphsCacheKey& a, const FontGlyphsCacheKey& b)
163 {
164     if (a.fontDescriptionCacheKey != b.fontDescriptionCacheKey)
165         return false;
166     if (a.families != b.families)
167         return false;
168     if (a.fontSelectorId != b.fontSelectorId || a.fontSelectorVersion != b.fontSelectorVersion || a.fontSelectorFlags != b.fontSelectorFlags)
169         return false;
170     return true;
171 }
172
173 static FontGlyphsCache& fontGlyphsCache()
174 {
175     DEFINE_STATIC_LOCAL(FontGlyphsCache, cache, ());
176     return cache;
177 }
178
179 void invalidateFontGlyphsCache()
180 {
181     fontGlyphsCache().clear();
182 }
183
184 static unsigned makeFontSelectorFlags(const FontDescription& description)
185 {
186     return static_cast<unsigned>(description.script()) << 1 | static_cast<unsigned>(description.smallCaps());
187 }
188
189 static void makeFontGlyphsCacheKey(FontGlyphsCacheKey& key, const FontDescription& description, FontSelector* fontSelector)
190 {
191     key.fontDescriptionCacheKey = FontDescriptionFontDataCacheKey(description);
192     for (unsigned i = 0; i < description.familyCount(); ++i)
193         key.families.append(description.familyAt(i).lower());
194     key.fontSelectorId = fontSelector ? fontSelector->uniqueId() : 0;
195     key.fontSelectorVersion = fontSelector ? fontSelector->version() : 0;
196     key.fontSelectorFlags = fontSelector && fontSelector->resolvesFamilyFor(description) ? makeFontSelectorFlags(description) : 0;
197 }
198
199 static unsigned computeFontGlyphsCacheHash(const FontGlyphsCacheKey& key)
200 {
201     unsigned hashCodes[5] = {
202         StringHasher::hashMemory(key.families.data(), key.families.size() * sizeof(key.families[0])),
203         key.fontDescriptionCacheKey.computeHash(),
204         key.fontSelectorId,
205         key.fontSelectorVersion,
206         key.fontSelectorFlags
207     };
208     return StringHasher::hashMemory<sizeof(hashCodes)>(hashCodes);
209 }
210
211 void pruneUnreferencedEntriesFromFontGlyphsCache()
212 {
213     Vector<unsigned, 50> toRemove;
214     FontGlyphsCache::iterator end = fontGlyphsCache().end();
215     for (FontGlyphsCache::iterator it = fontGlyphsCache().begin(); it != end; ++it) {
216         if (it->value->glyphs->hasOneRef())
217             toRemove.append(it->key);
218     }
219     for (unsigned i = 0; i < toRemove.size(); ++i)
220         fontGlyphsCache().remove(toRemove[i]);
221 }
222
223 static PassRefPtr<FontGlyphs> retrieveOrAddCachedFontGlyphs(const FontDescription& fontDescription, PassRefPtr<FontSelector> fontSelector)
224 {
225     FontGlyphsCacheKey key;
226     makeFontGlyphsCacheKey(key, fontDescription, fontSelector.get());
227
228     unsigned hash = computeFontGlyphsCacheHash(key);
229     FontGlyphsCache::AddResult addResult = fontGlyphsCache().add(hash, PassOwnPtr<FontGlyphsCacheEntry>());
230     if (!addResult.isNewEntry && addResult.iterator->value->key == key)
231         return addResult.iterator->value->glyphs;
232
233     OwnPtr<FontGlyphsCacheEntry>& newEntry = addResult.iterator->value;
234     newEntry = adoptPtr(new FontGlyphsCacheEntry);
235     newEntry->glyphs = FontGlyphs::create(fontSelector);
236     newEntry->key = key;
237     RefPtr<FontGlyphs> glyphs = newEntry->glyphs;
238
239     static const unsigned unreferencedPruneInterval = 50;
240     static const int maximumEntries = 400;
241     static unsigned pruneCounter;
242     // Referenced FontGlyphs would exist anyway so pruning them saves little memory.
243     if (!(++pruneCounter % unreferencedPruneInterval))
244         pruneUnreferencedEntriesFromFontGlyphsCache();
245     // Prevent pathological growth.
246     if (fontGlyphsCache().size() > maximumEntries)
247         fontGlyphsCache().remove(fontGlyphsCache().begin());
248     return glyphs;
249 }
250
251 void Font::update(PassRefPtr<FontSelector> fontSelector) const
252 {
253     m_glyphs = retrieveOrAddCachedFontGlyphs(m_fontDescription, fontSelector.get());
254     m_typesettingFeatures = computeTypesettingFeatures();
255 }
256
257 void Font::drawText(GraphicsContext* context, const TextRun& run, const FloatPoint& point, int from, int to, CustomFontNotReadyAction customFontNotReadyAction) const
258 {
259     // Don't draw anything while we are using custom fonts that are in the process of loading,
260     // except if the 'force' argument is set to true (in which case it will use a fallback
261     // font).
262     if (loadingCustomFonts() && customFontNotReadyAction == DoNotPaintIfFontNotReady)
263         return;
264     
265     to = (to == -1 ? run.length() : to);
266
267     CodePath codePathToUse = codePath(run);
268     // FIXME: Use the fast code path once it handles partial runs with kerning and ligatures. See http://webkit.org/b/100050
269     if (codePathToUse != Complex && typesettingFeatures() && (from || to != run.length()))
270         codePathToUse = Complex;
271
272     if (codePathToUse != Complex)
273         return drawSimpleText(context, run, point, from, to);
274
275     return drawComplexText(context, run, point, from, to);
276 }
277
278 void Font::drawEmphasisMarks(GraphicsContext* context, const TextRun& run, const AtomicString& mark, const FloatPoint& point, int from, int to) const
279 {
280     if (loadingCustomFonts())
281         return;
282
283     if (to < 0)
284         to = run.length();
285
286     CodePath codePathToUse = codePath(run);
287     // FIXME: Use the fast code path once it handles partial runs with kerning and ligatures. See http://webkit.org/b/100050
288     if (codePathToUse != Complex && typesettingFeatures() && (from || to != run.length()))
289         codePathToUse = Complex;
290
291     if (codePathToUse != Complex)
292         drawEmphasisMarksForSimpleText(context, run, mark, point, from, to);
293     else
294         drawEmphasisMarksForComplexText(context, run, mark, point, from, to);
295 }
296
297 float Font::width(const TextRun& run, HashSet<const SimpleFontData*>* fallbackFonts, GlyphOverflow* glyphOverflow) const
298 {
299     CodePath codePathToUse = codePath(run);
300     if (codePathToUse != Complex) {
301         // 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.
302         if (!canReturnFallbackFontsForComplexText())
303             fallbackFonts = 0;
304         // The simple path can optimize the case where glyph overflow is not observable.
305         if (codePathToUse != SimpleWithGlyphOverflow && (glyphOverflow && !glyphOverflow->computeBounds))
306             glyphOverflow = 0;
307     }
308
309     bool hasKerningOrLigatures = typesettingFeatures() & (Kerning | Ligatures);
310     bool hasWordSpacingOrLetterSpacing = wordSpacing() | letterSpacing();
311     float* cacheEntry = m_glyphs->widthCache().add(run, std::numeric_limits<float>::quiet_NaN(), hasKerningOrLigatures, hasWordSpacingOrLetterSpacing, glyphOverflow);
312     if (cacheEntry && !std::isnan(*cacheEntry))
313         return *cacheEntry;
314
315     float result;
316     if (codePathToUse == Complex)
317         result = floatWidthForComplexText(run, fallbackFonts, glyphOverflow);
318     else
319         result = floatWidthForSimpleText(run, fallbackFonts, glyphOverflow);
320
321     if (cacheEntry && (!fallbackFonts || fallbackFonts->isEmpty()))
322         *cacheEntry = result;
323     return result;
324 }
325
326 float Font::width(const TextRun& run, int& charsConsumed, String& glyphName) const
327 {
328 #if ENABLE(SVG_FONTS)
329     if (TextRun::RenderingContext* renderingContext = run.renderingContext())
330         return renderingContext->floatWidthUsingSVGFont(*this, run, charsConsumed, glyphName);
331 #endif
332
333     charsConsumed = run.length();
334     glyphName = "";
335     return width(run);
336 }
337
338 #if !PLATFORM(MAC)
339 PassOwnPtr<TextLayout> Font::createLayout(RenderText*, float, bool) const
340 {
341     return nullptr;
342 }
343
344 void Font::deleteLayout(TextLayout*)
345 {
346 }
347
348 float Font::width(TextLayout&, unsigned, unsigned, HashSet<const SimpleFontData*>*)
349 {
350     ASSERT_NOT_REACHED();
351     return 0;
352 }
353 #endif
354
355 FloatRect Font::selectionRectForText(const TextRun& run, const FloatPoint& point, int h, int from, int to) const
356 {
357     to = (to == -1 ? run.length() : to);
358
359     CodePath codePathToUse = codePath(run);
360     // FIXME: Use the fast code path once it handles partial runs with kerning and ligatures. See http://webkit.org/b/100050
361     if (codePathToUse != Complex && typesettingFeatures() && (from || to != run.length()))
362         codePathToUse = Complex;
363
364     if (codePathToUse != Complex)
365         return selectionRectForSimpleText(run, point, h, from, to);
366
367     return selectionRectForComplexText(run, point, h, from, to);
368 }
369
370 int Font::offsetForPosition(const TextRun& run, float x, bool includePartialGlyphs) const
371 {
372     // FIXME: Use the fast code path once it handles partial runs with kerning and ligatures. See http://webkit.org/b/100050
373     if (codePath(run) != Complex && !typesettingFeatures())
374         return offsetForPositionForSimpleText(run, x, includePartialGlyphs);
375
376     return offsetForPositionForComplexText(run, x, includePartialGlyphs);
377 }
378
379 template <typename CharacterType>
380 static inline String normalizeSpacesInternal(const CharacterType* characters, unsigned length)
381 {
382     StringBuilder normalized;
383     normalized.reserveCapacity(length);
384
385     for (unsigned i = 0; i < length; ++i)
386         normalized.append(Font::normalizeSpaces(characters[i]));
387
388     return normalized.toString();
389 }
390
391 String Font::normalizeSpaces(const LChar* characters, unsigned length)
392 {
393     return normalizeSpacesInternal(characters, length);
394 }
395
396 String Font::normalizeSpaces(const UChar* characters, unsigned length)
397 {
398     return normalizeSpacesInternal(characters, length);
399 }
400
401 static bool shouldUseFontSmoothing = true;
402
403 void Font::setShouldUseSmoothing(bool shouldUseSmoothing)
404 {
405     ASSERT(isMainThread());
406     shouldUseFontSmoothing = shouldUseSmoothing;
407 }
408
409 bool Font::shouldUseSmoothing()
410 {
411     return shouldUseFontSmoothing;
412 }
413
414 void Font::setCodePath(CodePath p)
415 {
416     s_codePath = p;
417 }
418
419 Font::CodePath Font::codePath()
420 {
421     return s_codePath;
422 }
423
424 void Font::setDefaultTypesettingFeatures(TypesettingFeatures typesettingFeatures)
425 {
426     s_defaultTypesettingFeatures = typesettingFeatures;
427 }
428
429 TypesettingFeatures Font::defaultTypesettingFeatures()
430 {
431     return s_defaultTypesettingFeatures;
432 }
433
434 Font::CodePath Font::codePath(const TextRun& run) const
435 {
436     if (s_codePath != Auto)
437         return s_codePath;
438
439 #if ENABLE(SVG_FONTS)
440     if (run.renderingContext())
441         return Simple;
442 #endif
443
444     if (m_fontDescription.featureSettings() && m_fontDescription.featureSettings()->size() > 0)
445         return Complex;
446     
447     if (run.length() > 1 && !WidthIterator::supportsTypesettingFeatures(*this))
448         return Complex;
449
450     if (!run.characterScanForCodePath())
451         return Simple;
452
453     if (run.is8Bit())
454         return Simple;
455
456     // Start from 0 since drawing and highlighting also measure the characters before run->from.
457     return characterRangeCodePath(run.characters16(), run.length());
458 }
459
460 Font::CodePath Font::characterRangeCodePath(const UChar* characters, unsigned len)
461 {
462     // FIXME: Should use a UnicodeSet in ports where ICU is used. Note that we 
463     // can't simply use UnicodeCharacter Property/class because some characters
464     // are not 'combining', but still need to go to the complex path.
465     // Alternatively, we may as well consider binary search over a sorted
466     // list of ranges.
467     CodePath result = Simple;
468     for (unsigned i = 0; i < len; i++) {
469         const UChar c = characters[i];
470         if (c < 0x2E5) // U+02E5 through U+02E9 (Modifier Letters : Tone letters)  
471             continue;
472         if (c <= 0x2E9) 
473             return Complex;
474
475         if (c < 0x300) // U+0300 through U+036F Combining diacritical marks
476             continue;
477         if (c <= 0x36F)
478             return Complex;
479
480         if (c < 0x0591 || c == 0x05BE) // U+0591 through U+05CF excluding U+05BE Hebrew combining marks, Hebrew punctuation Paseq, Sof Pasuq and Nun Hafukha
481             continue;
482         if (c <= 0x05CF)
483             return Complex;
484
485         // U+0600 through U+109F Arabic, Syriac, Thaana, NKo, Samaritan, Mandaic,
486         // Devanagari, Bengali, Gurmukhi, Gujarati, Oriya, Tamil, Telugu, Kannada, 
487         // Malayalam, Sinhala, Thai, Lao, Tibetan, Myanmar
488         if (c < 0x0600) 
489             continue;
490         if (c <= 0x109F)
491             return Complex;
492
493         // U+1100 through U+11FF Hangul Jamo (only Ancient Korean should be left here if you precompose;
494         // Modern Korean will be precomposed as a result of step A)
495         if (c < 0x1100)
496             continue;
497         if (c <= 0x11FF)
498             return Complex;
499
500         if (c < 0x135D) // U+135D through U+135F Ethiopic combining marks
501             continue;
502         if (c <= 0x135F)
503             return Complex;
504
505         if (c < 0x1700) // U+1780 through U+18AF Tagalog, Hanunoo, Buhid, Taghanwa,Khmer, Mongolian
506             continue;
507         if (c <= 0x18AF)
508             return Complex;
509
510         if (c < 0x1900) // U+1900 through U+194F Limbu (Unicode 4.0)
511             continue;
512         if (c <= 0x194F)
513             return Complex;
514
515         if (c < 0x1980) // U+1980 through U+19DF New Tai Lue
516             continue;
517         if (c <= 0x19DF)
518             return Complex;
519
520         if (c < 0x1A00) // U+1A00 through U+1CFF Buginese, Tai Tham, Balinese, Batak, Lepcha, Vedic
521             continue;
522         if (c <= 0x1CFF)
523             return Complex;
524
525         if (c < 0x1DC0) // U+1DC0 through U+1DFF Comining diacritical mark supplement
526             continue;
527         if (c <= 0x1DFF)
528             return Complex;
529
530         // U+1E00 through U+2000 characters with diacritics and stacked diacritics
531         if (c <= 0x2000) {
532             result = SimpleWithGlyphOverflow;
533             continue;
534         }
535
536         if (c < 0x20D0) // U+20D0 through U+20FF Combining marks for symbols
537             continue;
538         if (c <= 0x20FF)
539             return Complex;
540
541         if (c < 0x2CEF) // U+2CEF through U+2CF1 Combining marks for Coptic
542             continue;
543         if (c <= 0x2CF1)
544             return Complex;
545
546         if (c < 0x302A) // U+302A through U+302F Ideographic and Hangul Tone marks
547             continue;
548         if (c <= 0x302F)
549             return Complex;
550
551         if (c < 0xA67C) // U+A67C through U+A67D Combining marks for old Cyrillic
552             continue;
553         if (c <= 0xA67D)
554             return Complex;
555
556         if (c < 0xA6F0) // U+A6F0 through U+A6F1 Combining mark for Bamum
557             continue;
558         if (c <= 0xA6F1)
559             return Complex;
560
561        // U+A800 through U+ABFF Nagri, Phags-pa, Saurashtra, Devanagari Extended,
562        // Hangul Jamo Ext. A, Javanese, Myanmar Extended A, Tai Viet, Meetei Mayek,
563         if (c < 0xA800) 
564             continue;
565         if (c <= 0xABFF)
566             return Complex;
567
568         if (c < 0xD7B0) // U+D7B0 through U+D7FF Hangul Jamo Ext. B
569             continue;
570         if (c <= 0xD7FF)
571             return Complex;
572
573         if (c <= 0xDBFF) {
574             // High surrogate
575
576             if (i == len - 1)
577                 continue;
578
579             UChar next = characters[++i];
580             if (!U16_IS_TRAIL(next))
581                 continue;
582
583             UChar32 supplementaryCharacter = U16_GET_SUPPLEMENTARY(c, next);
584
585             if (supplementaryCharacter < 0x1F1E6) // U+1F1E6 through U+1F1FF Regional Indicator Symbols
586                 continue;
587             if (supplementaryCharacter <= 0x1F1FF)
588                 return Complex;
589
590             if (supplementaryCharacter < 0xE0100) // U+E0100 through U+E01EF Unicode variation selectors.
591                 continue;
592             if (supplementaryCharacter <= 0xE01EF)
593                 return Complex;
594
595             // FIXME: Check for Brahmi (U+11000 block), Kaithi (U+11080 block) and other complex scripts
596             // in plane 1 or higher.
597
598             continue;
599         }
600
601         if (c < 0xFE00) // U+FE00 through U+FE0F Unicode variation selectors
602             continue;
603         if (c <= 0xFE0F)
604             return Complex;
605
606         if (c < 0xFE20) // U+FE20 through U+FE2F Combining half marks
607             continue;
608         if (c <= 0xFE2F)
609             return Complex;
610     }
611     return result;
612 }
613
614 bool Font::isCJKIdeograph(UChar32 c)
615 {
616     // The basic CJK Unified Ideographs block.
617     if (c >= 0x4E00 && c <= 0x9FFF)
618         return true;
619     
620     // CJK Unified Ideographs Extension A.
621     if (c >= 0x3400 && c <= 0x4DBF)
622         return true;
623     
624     // CJK Radicals Supplement.
625     if (c >= 0x2E80 && c <= 0x2EFF)
626         return true;
627     
628     // Kangxi Radicals.
629     if (c >= 0x2F00 && c <= 0x2FDF)
630         return true;
631     
632     // CJK Strokes.
633     if (c >= 0x31C0 && c <= 0x31EF)
634         return true;
635     
636     // CJK Compatibility Ideographs.
637     if (c >= 0xF900 && c <= 0xFAFF)
638         return true;
639     
640     // CJK Unified Ideographs Extension B.
641     if (c >= 0x20000 && c <= 0x2A6DF)
642         return true;
643         
644     // CJK Unified Ideographs Extension C.
645     if (c >= 0x2A700 && c <= 0x2B73F)
646         return true;
647     
648     // CJK Unified Ideographs Extension D.
649     if (c >= 0x2B740 && c <= 0x2B81F)
650         return true;
651     
652     // CJK Compatibility Ideographs Supplement.
653     if (c >= 0x2F800 && c <= 0x2FA1F)
654         return true;
655
656     return false;
657 }
658
659 bool Font::isCJKIdeographOrSymbol(UChar32 c)
660 {
661     // 0x2C7 Caron, Mandarin Chinese 3rd Tone
662     // 0x2CA Modifier Letter Acute Accent, Mandarin Chinese 2nd Tone
663     // 0x2CB Modifier Letter Grave Access, Mandarin Chinese 4th Tone 
664     // 0x2D9 Dot Above, Mandarin Chinese 5th Tone 
665     if ((c == 0x2C7) || (c == 0x2CA) || (c == 0x2CB) || (c == 0x2D9))
666         return true;
667
668     if ((c == 0x2020) || (c == 0x2021) || (c == 0x2030) || (c == 0x203B) || (c == 0x203C)
669         || (c == 0x2042) || (c == 0x2047) || (c == 0x2048) || (c == 0x2049) || (c == 0x2051)
670         || (c == 0x20DD) || (c == 0x20DE) || (c == 0x2100) || (c == 0x2103) || (c == 0x2105)
671         || (c == 0x2109) || (c == 0x210A) || (c == 0x2113) || (c == 0x2116) || (c == 0x2121)
672         || (c == 0x212B) || (c == 0x213B) || (c == 0x2150) || (c == 0x2151) || (c == 0x2152))
673         return true;
674
675     if (c >= 0x2156 && c <= 0x215A)
676         return true;
677
678     if (c >= 0x2160 && c <= 0x216B)
679         return true;
680
681     if (c >= 0x2170 && c <= 0x217B)
682         return true;
683
684     if ((c == 0x217F) || (c == 0x2189) || (c == 0x2307) || (c == 0x2312) || (c == 0x23BE) || (c == 0x23BF))
685         return true;
686
687     if (c >= 0x23C0 && c <= 0x23CC)
688         return true;
689
690     if ((c == 0x23CE) || (c == 0x2423))
691         return true;
692
693     if (c >= 0x2460 && c <= 0x2492)
694         return true;
695
696     if (c >= 0x249C && c <= 0x24FF)
697         return true;
698
699     if ((c == 0x25A0) || (c == 0x25A1) || (c == 0x25A2) || (c == 0x25AA) || (c == 0x25AB))
700         return true;
701
702     if ((c == 0x25B1) || (c == 0x25B2) || (c == 0x25B3) || (c == 0x25B6) || (c == 0x25B7) || (c == 0x25BC) || (c == 0x25BD))
703         return true;
704     
705     if ((c == 0x25C0) || (c == 0x25C1) || (c == 0x25C6) || (c == 0x25C7) || (c == 0x25C9) || (c == 0x25CB) || (c == 0x25CC))
706         return true;
707
708     if (c >= 0x25CE && c <= 0x25D3)
709         return true;
710
711     if (c >= 0x25E2 && c <= 0x25E6)
712         return true;
713
714     if (c == 0x25EF)
715         return true;
716
717     if (c >= 0x2600 && c <= 0x2603)
718         return true;
719
720     if ((c == 0x2605) || (c == 0x2606) || (c == 0x260E) || (c == 0x2616) || (c == 0x2617) || (c == 0x2640) || (c == 0x2642))
721         return true;
722
723     if (c >= 0x2660 && c <= 0x266F)
724         return true;
725
726     if (c >= 0x2672 && c <= 0x267D)
727         return true;
728
729     if ((c == 0x26A0) || (c == 0x26BD) || (c == 0x26BE) || (c == 0x2713) || (c == 0x271A) || (c == 0x273F) || (c == 0x2740) || (c == 0x2756))
730         return true;
731
732     if (c >= 0x2776 && c <= 0x277F)
733         return true;
734
735     if (c == 0x2B1A)
736         return true;
737
738     // Ideographic Description Characters.
739     if (c >= 0x2FF0 && c <= 0x2FFF)
740         return true;
741     
742     // CJK Symbols and Punctuation, excluding 0x3030.
743     if (c >= 0x3000 && c < 0x3030)
744         return true;
745
746     if (c > 0x3030 && c <= 0x303F)
747         return true;
748
749     // Hiragana
750     if (c >= 0x3040 && c <= 0x309F)
751         return true;
752
753     // Katakana 
754     if (c >= 0x30A0 && c <= 0x30FF)
755         return true;
756
757     // Bopomofo
758     if (c >= 0x3100 && c <= 0x312F)
759         return true;
760
761     if (c >= 0x3190 && c <= 0x319F)
762         return true;
763
764     // Bopomofo Extended
765     if (c >= 0x31A0 && c <= 0x31BF)
766         return true;
767  
768     // Enclosed CJK Letters and Months.
769     if (c >= 0x3200 && c <= 0x32FF)
770         return true;
771     
772     // CJK Compatibility.
773     if (c >= 0x3300 && c <= 0x33FF)
774         return true;
775
776     if (c >= 0xF860 && c <= 0xF862)
777         return true;
778
779     // CJK Compatibility Forms.
780     if (c >= 0xFE30 && c <= 0xFE4F)
781         return true;
782
783     if ((c == 0xFE10) || (c == 0xFE11) || (c == 0xFE12) || (c == 0xFE19))
784         return true;
785
786     if ((c == 0xFF0D) || (c == 0xFF1B) || (c == 0xFF1C) || (c == 0xFF1E))
787         return false;
788
789     // Halfwidth and Fullwidth Forms
790     // Usually only used in CJK
791     if (c >= 0xFF00 && c <= 0xFFEF)
792         return true;
793
794     // Emoji.
795     if (c == 0x1F100)
796         return true;
797
798     if (c >= 0x1F110 && c <= 0x1F129)
799         return true;
800
801     if (c >= 0x1F130 && c <= 0x1F149)
802         return true;
803
804     if (c >= 0x1F150 && c <= 0x1F169)
805         return true;
806
807     if (c >= 0x1F170 && c <= 0x1F189)
808         return true;
809
810     if (c >= 0x1F200 && c <= 0x1F6F)
811         return true;
812
813     return isCJKIdeograph(c);
814 }
815
816 unsigned Font::expansionOpportunityCount(const LChar* characters, size_t length, TextDirection direction, bool& isAfterExpansion)
817 {
818     unsigned count = 0;
819     if (direction == LTR) {
820         for (size_t i = 0; i < length; ++i) {
821             if (treatAsSpace(characters[i])) {
822                 count++;
823                 isAfterExpansion = true;
824             } else
825                 isAfterExpansion = false;
826         }
827     } else {
828         for (size_t i = length; i > 0; --i) {
829             if (treatAsSpace(characters[i - 1])) {
830                 count++;
831                 isAfterExpansion = true;
832             } else
833                 isAfterExpansion = false;
834         }
835     }
836     return count;
837 }
838
839 unsigned Font::expansionOpportunityCount(const UChar* characters, size_t length, TextDirection direction, bool& isAfterExpansion)
840 {
841     static bool expandAroundIdeographs = canExpandAroundIdeographsInComplexText();
842     unsigned count = 0;
843     if (direction == LTR) {
844         for (size_t i = 0; i < length; ++i) {
845             UChar32 character = characters[i];
846             if (treatAsSpace(character)) {
847                 count++;
848                 isAfterExpansion = true;
849                 continue;
850             }
851             if (U16_IS_LEAD(character) && i + 1 < length && U16_IS_TRAIL(characters[i + 1])) {
852                 character = U16_GET_SUPPLEMENTARY(character, characters[i + 1]);
853                 i++;
854             }
855             if (expandAroundIdeographs && isCJKIdeographOrSymbol(character)) {
856                 if (!isAfterExpansion)
857                     count++;
858                 count++;
859                 isAfterExpansion = true;
860                 continue;
861             }
862             isAfterExpansion = false;
863         }
864     } else {
865         for (size_t i = length; i > 0; --i) {
866             UChar32 character = characters[i - 1];
867             if (treatAsSpace(character)) {
868                 count++;
869                 isAfterExpansion = true;
870                 continue;
871             }
872             if (U16_IS_TRAIL(character) && i > 1 && U16_IS_LEAD(characters[i - 2])) {
873                 character = U16_GET_SUPPLEMENTARY(characters[i - 2], character);
874                 i--;
875             }
876             if (expandAroundIdeographs && isCJKIdeographOrSymbol(character)) {
877                 if (!isAfterExpansion)
878                     count++;
879                 count++;
880                 isAfterExpansion = true;
881                 continue;
882             }
883             isAfterExpansion = false;
884         }
885     }
886     return count;
887 }
888
889 bool Font::canReceiveTextEmphasis(UChar32 c)
890 {
891     CharCategory category = Unicode::category(c);
892     if (category & (Separator_Space | Separator_Line | Separator_Paragraph | Other_NotAssigned | Other_Control | Other_Format))
893         return false;
894
895     // Additional word-separator characters listed in CSS Text Level 3 Editor's Draft 3 November 2010.
896     if (c == ethiopicWordspace || c == aegeanWordSeparatorLine || c == aegeanWordSeparatorDot
897         || c == ugariticWordDivider || c == tibetanMarkIntersyllabicTsheg || c == tibetanMarkDelimiterTshegBstar)
898         return false;
899
900     return true;
901 }
902
903 }