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