Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(449)

Side by Side Diff: Source/core/platform/graphics/Font.cpp

Issue 99103006: Moving GraphicsContext and dependencies from core to platform. (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Final patch - fixes Android Created 7 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « Source/core/platform/graphics/Font.h ('k') | Source/core/platform/graphics/FontCache.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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 "core/platform/graphics/Font.h"
26
27 #include "core/platform/graphics/WidthIterator.h"
28 #include "platform/geometry/FloatRect.h"
29 #include "platform/graphics/TextRun.h"
30 #include "wtf/MainThread.h"
31 #include "wtf/StdLibExtras.h"
32 #include "wtf/UnusedParam.h"
33 #include "wtf/text/StringBuilder.h"
34
35 using namespace WTF;
36 using namespace Unicode;
37
38 namespace WTF {
39
40 // allow compilation of OwnPtr<TextLayout> in source files that don't have acces s to the TextLayout class definition
41 void OwnedPtrDeleter<WebCore::TextLayout>::deletePtr(WebCore::TextLayout* ptr)
42 {
43 WebCore::Font::deleteLayout(ptr);
44 }
45
46 }
47
48 namespace WebCore {
49
50 const uint8_t Font::s_roundingHackCharacterTable[256] = {
51 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,
52 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 /*?*/,
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 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,
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 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,
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 };
60
61 static const UChar32 cjkIsolatedSymbolsArray[] = {
62 // 0x2C7 Caron, Mandarin Chinese 3rd Tone
63 0x2C7,
64 // 0x2CA Modifier Letter Acute Accent, Mandarin Chinese 2nd Tone
65 0x2CA,
66 // 0x2CB Modifier Letter Grave Access, Mandarin Chinese 4th Tone
67 0x2CB,
68 // 0x2D9 Dot Above, Mandarin Chinese 5th Tone
69 0x2D9,
70 0x2020, 0x2021, 0x2030, 0x203B, 0x203C, 0x2042, 0x2047, 0x2048, 0x2049, 0x20 51,
71 0x20DD, 0x20DE, 0x2100, 0x2103, 0x2105, 0x2109, 0x210A, 0x2113, 0x2116, 0x21 21,
72 0x212B, 0x213B, 0x2150, 0x2151, 0x2152, 0x217F, 0x2189, 0x2307, 0x2312, 0x23 CE,
73 0x2423, 0x25A0, 0x25A1, 0x25A2, 0x25AA, 0x25AB, 0x25B1, 0x25B2, 0x25B3, 0x25 B6,
74 0x25B7, 0x25BC, 0x25BD, 0x25C0, 0x25C1, 0x25C6, 0x25C7, 0x25C9, 0x25CB, 0x25 CC,
75 0x25EF, 0x2605, 0x2606, 0x260E, 0x2616, 0x2617, 0x2640, 0x2642, 0x26A0, 0x26 BD,
76 0x26BE, 0x2713, 0x271A, 0x273F, 0x2740, 0x2756, 0x2B1A, 0xFE10, 0xFE11, 0xFE 12,
77 0xFE19, 0xFF1D,
78 // Emoji.
79 0x1F100
80 };
81
82 Font::CodePath Font::s_codePath = Auto;
83
84 TypesettingFeatures Font::s_defaultTypesettingFeatures = 0;
85
86 // ============================================================================= ===============
87 // Font Implementation (Cross-Platform Portion)
88 // ============================================================================= ===============
89
90 Font::Font()
91 : m_letterSpacing(0)
92 , m_wordSpacing(0)
93 , m_isPlatformFont(false)
94 , m_typesettingFeatures(0)
95 {
96 }
97
98 Font::Font(const FontDescription& fd, float letterSpacing, float wordSpacing)
99 : m_fontDescription(fd)
100 , m_letterSpacing(letterSpacing)
101 , m_wordSpacing(wordSpacing)
102 , m_isPlatformFont(false)
103 , m_typesettingFeatures(computeTypesettingFeatures())
104 {
105 }
106
107 Font::Font(const FontPlatformData& fontData, bool isPrinterFont, FontSmoothingMo de fontSmoothingMode)
108 : m_fontFallbackList(FontFallbackList::create())
109 , m_letterSpacing(0)
110 , m_wordSpacing(0)
111 , m_isPlatformFont(true)
112 , m_typesettingFeatures(computeTypesettingFeatures())
113 {
114 m_fontDescription.setUsePrinterFont(isPrinterFont);
115 m_fontDescription.setFontSmoothing(fontSmoothingMode);
116 m_fontFallbackList->setPlatformFont(fontData);
117 }
118
119 Font::Font(const Font& other)
120 : m_fontDescription(other.m_fontDescription)
121 , m_fontFallbackList(other.m_fontFallbackList)
122 , m_letterSpacing(other.m_letterSpacing)
123 , m_wordSpacing(other.m_wordSpacing)
124 , m_isPlatformFont(other.m_isPlatformFont)
125 , m_typesettingFeatures(computeTypesettingFeatures())
126 {
127 }
128
129 Font& Font::operator=(const Font& other)
130 {
131 m_fontDescription = other.m_fontDescription;
132 m_fontFallbackList = other.m_fontFallbackList;
133 m_letterSpacing = other.m_letterSpacing;
134 m_wordSpacing = other.m_wordSpacing;
135 m_isPlatformFont = other.m_isPlatformFont;
136 m_typesettingFeatures = other.m_typesettingFeatures;
137 return *this;
138 }
139
140 bool Font::operator==(const Font& other) const
141 {
142 // Our FontData don't have to be checked, since checking the font descriptio n will be fine.
143 // FIXME: This does not work if the font was made with the FontPlatformData constructor.
144 if (loadingCustomFonts() || other.loadingCustomFonts())
145 return false;
146
147 FontSelector* first = m_fontFallbackList ? m_fontFallbackList->fontSelector( ) : 0;
148 FontSelector* second = other.m_fontFallbackList ? other.m_fontFallbackList-> fontSelector() : 0;
149
150 return first == second
151 && m_fontDescription == other.m_fontDescription
152 && m_letterSpacing == other.m_letterSpacing
153 && m_wordSpacing == other.m_wordSpacing
154 && (m_fontFallbackList ? m_fontFallbackList->fontSelectorVersion() : 0) == (other.m_fontFallbackList ? other.m_fontFallbackList->fontSelectorVersion() : 0)
155 && (m_fontFallbackList ? m_fontFallbackList->generation() : 0) == (other .m_fontFallbackList ? other.m_fontFallbackList->generation() : 0);
156 }
157
158 void Font::update(PassRefPtr<FontSelector> fontSelector) const
159 {
160 // FIXME: It is pretty crazy that we are willing to just poke into a RefPtr, but it ends up
161 // being reasonably safe (because inherited fonts in the render tree pick up the new
162 // style anyway. Other copies are transient, e.g., the state in the Graphics Context, and
163 // won't stick around long enough to get you in trouble). Still, this is pre tty disgusting,
164 // and could eventually be rectified by using RefPtrs for Fonts themselves.
165 if (!m_fontFallbackList)
166 m_fontFallbackList = FontFallbackList::create();
167 m_fontFallbackList->invalidate(fontSelector);
168 m_typesettingFeatures = computeTypesettingFeatures();
169 }
170
171 void Font::drawText(GraphicsContext* context, const TextRunPaintInfo& runInfo, c onst FloatPoint& point, CustomFontNotReadyAction customFontNotReadyAction) const
172 {
173 // Don't draw anything while we are using custom fonts that are in the proce ss of loading,
174 // except if the 'force' argument is set to true (in which case it will use a fallback
175 // font).
176 if (loadingCustomFonts() && customFontNotReadyAction == DoNotPaintIfFontNotR eady)
177 return;
178
179 CodePath codePathToUse = codePath(runInfo.run);
180 // FIXME: Use the fast code path once it handles partial runs with kerning a nd ligatures. See http://webkit.org/b/100050
181 if (codePathToUse != Complex && typesettingFeatures() && (runInfo.from || ru nInfo.to != runInfo.run.length()))
182 codePathToUse = Complex;
183
184 if (codePathToUse != Complex)
185 return drawSimpleText(context, runInfo, point);
186
187 return drawComplexText(context, runInfo, point);
188 }
189
190 void Font::drawEmphasisMarks(GraphicsContext* context, const TextRunPaintInfo& r unInfo, const AtomicString& mark, const FloatPoint& point) const
191 {
192 if (loadingCustomFonts())
193 return;
194
195 CodePath codePathToUse = codePath(runInfo.run);
196 // FIXME: Use the fast code path once it handles partial runs with kerning a nd ligatures. See http://webkit.org/b/100050
197 if (codePathToUse != Complex && typesettingFeatures() && (runInfo.from || ru nInfo.to != runInfo.run.length()))
198 codePathToUse = Complex;
199
200 if (codePathToUse != Complex)
201 drawEmphasisMarksForSimpleText(context, runInfo, mark, point);
202 else
203 drawEmphasisMarksForComplexText(context, runInfo, mark, point);
204 }
205
206 float Font::width(const TextRun& run, HashSet<const SimpleFontData*>* fallbackFo nts, GlyphOverflow* glyphOverflow) const
207 {
208 CodePath codePathToUse = codePath(run);
209 if (codePathToUse != Complex) {
210 // The complex path is more restrictive about returning fallback fonts t han the simple path, so we need an explicit test to make their behaviors match.
211 if (!canReturnFallbackFontsForComplexText())
212 fallbackFonts = 0;
213 // The simple path can optimize the case where glyph overflow is not obs ervable.
214 if (codePathToUse != SimpleWithGlyphOverflow && (glyphOverflow && !glyph Overflow->computeBounds))
215 glyphOverflow = 0;
216 }
217
218 bool hasKerningOrLigatures = typesettingFeatures() & (Kerning | Ligatures);
219 bool hasWordSpacingOrLetterSpacing = wordSpacing() || letterSpacing();
220 float* cacheEntry = m_fontFallbackList->widthCache().add(run, std::numeric_l imits<float>::quiet_NaN(), hasKerningOrLigatures, hasWordSpacingOrLetterSpacing, glyphOverflow);
221 if (cacheEntry && !std::isnan(*cacheEntry))
222 return *cacheEntry;
223
224 float result;
225 if (codePathToUse == Complex)
226 result = floatWidthForComplexText(run, fallbackFonts, glyphOverflow);
227 else
228 result = floatWidthForSimpleText(run, fallbackFonts, glyphOverflow);
229
230 if (cacheEntry && (!fallbackFonts || fallbackFonts->isEmpty()))
231 *cacheEntry = result;
232 return result;
233 }
234
235 float Font::width(const TextRun& run, int& charsConsumed, String& glyphName) con st
236 {
237 #if ENABLE(SVG_FONTS)
238 if (TextRun::RenderingContext* renderingContext = run.renderingContext())
239 return renderingContext->floatWidthUsingSVGFont(*this, run, charsConsume d, glyphName);
240 #endif
241
242 charsConsumed = run.length();
243 glyphName = "";
244 return width(run);
245 }
246
247 #if !OS(MACOSX)
248
249 PassOwnPtr<TextLayout> Font::createLayoutForMacComplexText(const TextRun&, unsig ned, float, bool) const
250 {
251 ASSERT_NOT_REACHED();
252 return nullptr;
253 }
254
255 void Font::deleteLayout(TextLayout*)
256 {
257 }
258
259 float Font::width(TextLayout&, unsigned, unsigned, HashSet<const SimpleFontData* >*)
260 {
261 ASSERT_NOT_REACHED();
262 return 0;
263 }
264
265 #endif
266
267 FloatRect Font::selectionRectForText(const TextRun& run, const FloatPoint& point , int h, int from, int to) const
268 {
269 to = (to == -1 ? run.length() : to);
270
271 CodePath codePathToUse = codePath(run);
272 // FIXME: Use the fast code path once it handles partial runs with kerning a nd ligatures. See http://webkit.org/b/100050
273 if (codePathToUse != Complex && typesettingFeatures() && (from || to != run. length()))
274 codePathToUse = Complex;
275
276 if (codePathToUse != Complex)
277 return selectionRectForSimpleText(run, point, h, from, to);
278
279 return selectionRectForComplexText(run, point, h, from, to);
280 }
281
282 int Font::offsetForPosition(const TextRun& run, float x, bool includePartialGlyp hs) const
283 {
284 // FIXME: Use the fast code path once it handles partial runs with kerning a nd ligatures. See http://webkit.org/b/100050
285 if (codePath(run) != Complex && !typesettingFeatures())
286 return offsetForPositionForSimpleText(run, x, includePartialGlyphs);
287
288 return offsetForPositionForComplexText(run, x, includePartialGlyphs);
289 }
290
291 template <typename CharacterType>
292 static inline String normalizeSpacesInternal(const CharacterType* characters, un signed length)
293 {
294 StringBuilder normalized;
295 normalized.reserveCapacity(length);
296
297 for (unsigned i = 0; i < length; ++i)
298 normalized.append(Font::normalizeSpaces(characters[i]));
299
300 return normalized.toString();
301 }
302
303 String Font::normalizeSpaces(const LChar* characters, unsigned length)
304 {
305 return normalizeSpacesInternal(characters, length);
306 }
307
308 String Font::normalizeSpaces(const UChar* characters, unsigned length)
309 {
310 return normalizeSpacesInternal(characters, length);
311 }
312
313 static bool shouldUseFontSmoothing = true;
314
315 void Font::setShouldUseSmoothing(bool shouldUseSmoothing)
316 {
317 ASSERT(isMainThread());
318 shouldUseFontSmoothing = shouldUseSmoothing;
319 }
320
321 bool Font::shouldUseSmoothing()
322 {
323 return shouldUseFontSmoothing;
324 }
325
326 void Font::setCodePath(CodePath p)
327 {
328 s_codePath = p;
329 }
330
331 Font::CodePath Font::codePath()
332 {
333 return s_codePath;
334 }
335
336 void Font::setDefaultTypesettingFeatures(TypesettingFeatures typesettingFeatures )
337 {
338 s_defaultTypesettingFeatures = typesettingFeatures;
339 }
340
341 TypesettingFeatures Font::defaultTypesettingFeatures()
342 {
343 return s_defaultTypesettingFeatures;
344 }
345
346 Font::CodePath Font::codePath(const TextRun& run) const
347 {
348 if (s_codePath != Auto)
349 return s_codePath;
350
351 #if ENABLE(SVG_FONTS)
352 if (run.renderingContext())
353 return Simple;
354 #endif
355
356 if (m_fontDescription.featureSettings() && m_fontDescription.featureSettings ()->size() > 0)
357 return Complex;
358
359 if (run.length() > 1 && !WidthIterator::supportsTypesettingFeatures(*this))
360 return Complex;
361
362 if (!run.characterScanForCodePath())
363 return Simple;
364
365 if (run.is8Bit())
366 return Simple;
367
368 // Start from 0 since drawing and highlighting also measure the characters b efore run->from.
369 return characterRangeCodePath(run.characters16(), run.length());
370 }
371
372 static inline UChar keyExtractorUChar(const UChar* value)
373 {
374 return *value;
375 }
376
377 static inline UChar32 keyExtractorUChar32(const UChar32* value)
378 {
379 return *value;
380 }
381
382 Font::CodePath Font::characterRangeCodePath(const UChar* characters, unsigned le n)
383 {
384 static const UChar complexCodePathRanges[] = {
385 // U+02E5 through U+02E9 (Modifier Letters : Tone letters)
386 0x2E5, 0x2E9,
387 // U+0300 through U+036F Combining diacritical marks
388 0x300, 0x36F,
389 // U+0591 through U+05CF excluding U+05BE Hebrew combining marks, ...
390 0x0591, 0x05BD,
391 // ... Hebrew punctuation Paseq, Sof Pasuq and Nun Hafukha
392 0x05BF, 0x05CF,
393 // U+0600 through U+109F Arabic, Syriac, Thaana, NKo, Samaritan, Mandaic ,
394 // Devanagari, Bengali, Gurmukhi, Gujarati, Oriya, Tamil, Telugu, Kannad a,
395 // Malayalam, Sinhala, Thai, Lao, Tibetan, Myanmar
396 0x0600, 0x109F,
397 // U+1100 through U+11FF Hangul Jamo (only Ancient Korean should be left
398 // here if you precompose; Modern Korean will be precomposed as a result of step A)
399 0x1100, 0x11FF,
400 // U+135D through U+135F Ethiopic combining marks
401 0x135D, 0x135F,
402 // U+1780 through U+18AF Tagalog, Hanunoo, Buhid, Taghanwa,Khmer, Mongol ian
403 0x1700, 0x18AF,
404 // U+1900 through U+194F Limbu (Unicode 4.0)
405 0x1900, 0x194F,
406 // U+1980 through U+19DF New Tai Lue
407 0x1980, 0x19DF,
408 // U+1A00 through U+1CFF Buginese, Tai Tham, Balinese, Batak, Lepcha, Ve dic
409 0x1A00, 0x1CFF,
410 // U+1DC0 through U+1DFF Comining diacritical mark supplement
411 0x1DC0, 0x1DFF,
412 // U+20D0 through U+20FF Combining marks for symbols
413 0x20D0, 0x20FF,
414 // U+2CEF through U+2CF1 Combining marks for Coptic
415 0x2CEF, 0x2CF1,
416 // U+302A through U+302F Ideographic and Hangul Tone marks
417 0x302A, 0x302F,
418 // U+A67C through U+A67D Combining marks for old Cyrillic
419 0xA67C, 0xA67D,
420 // U+A6F0 through U+A6F1 Combining mark for Bamum
421 0xA6F0, 0xA6F1,
422 // U+A800 through U+ABFF Nagri, Phags-pa, Saurashtra, Devanagari Extende d,
423 // Hangul Jamo Ext. A, Javanese, Myanmar Extended A, Tai Viet, Meetei Ma yek
424 0xA800, 0xABFF,
425 // U+D7B0 through U+D7FF Hangul Jamo Ext. B
426 0xD7B0, 0xD7FF,
427 // U+FE00 through U+FE0F Unicode variation selectors
428 0xFE00, 0xFE0F,
429 // U+FE20 through U+FE2F Combining half marks
430 0xFE20, 0xFE2F
431 };
432 static size_t complexCodePathRangesCount = WTF_ARRAY_LENGTH(complexCodePathR anges);
433
434 CodePath result = Simple;
435 for (unsigned i = 0; i < len; i++) {
436 const UChar c = characters[i];
437
438 // Shortcut for common case
439 if (c < 0x2E5)
440 continue;
441
442 // U+1E00 through U+2000 characters with diacritics and stacked diacriti cs
443 if (c >= 0x1E00 && c <= 0x2000) {
444 result = SimpleWithGlyphOverflow;
445 continue;
446 }
447
448 // Surrogate pairs
449 if (c > 0xD7FF && c <= 0xDBFF) {
450 if (i == len - 1)
451 continue;
452
453 UChar next = characters[++i];
454 if (!U16_IS_TRAIL(next))
455 continue;
456
457 UChar32 supplementaryCharacter = U16_GET_SUPPLEMENTARY(c, next);
458
459 if (supplementaryCharacter < 0x1F1E6) // U+1F1E6 through U+1F1FF Reg ional Indicator Symbols
460 continue;
461 if (supplementaryCharacter <= 0x1F1FF)
462 return Complex;
463
464 if (supplementaryCharacter < 0xE0100) // U+E0100 through U+E01EF Uni code variation selectors.
465 continue;
466 if (supplementaryCharacter <= 0xE01EF)
467 return Complex;
468
469 // FIXME: Check for Brahmi (U+11000 block), Kaithi (U+11080 block) a nd other complex scripts
470 // in plane 1 or higher.
471
472 continue;
473 }
474
475 // Search for other Complex cases
476 UChar* boundingCharacter = approximateBinarySearch<UChar, UChar>(
477 (UChar*)complexCodePathRanges, complexCodePathRangesCount, c, keyExt ractorUChar);
478 // Exact matches are complex
479 if (*boundingCharacter == c)
480 return Complex;
481 bool isEndOfRange = ((boundingCharacter - complexCodePathRanges) % 2);
482 if (*boundingCharacter < c) {
483 // Determine if we are in a range or out
484 if (!isEndOfRange)
485 return Complex;
486 continue;
487 }
488 ASSERT(*boundingCharacter > c);
489 // Determine if we are in a range or out - opposite condition to above
490 if (isEndOfRange)
491 return Complex;
492 }
493
494 return result;
495 }
496
497 bool Font::isCJKIdeograph(UChar32 c)
498 {
499 static const UChar32 cjkIdeographRanges[] = {
500 // CJK Radicals Supplement and Kangxi Radicals.
501 0x2E80, 0x2FDF,
502 // CJK Strokes.
503 0x31C0, 0x31EF,
504 // CJK Unified Ideographs Extension A.
505 0x3400, 0x4DBF,
506 // The basic CJK Unified Ideographs block.
507 0x4E00, 0x9FFF,
508 // CJK Compatibility Ideographs.
509 0xF900, 0xFAFF,
510 // CJK Unified Ideographs Extension B.
511 0x20000, 0x2A6DF,
512 // CJK Unified Ideographs Extension C.
513 // CJK Unified Ideographs Extension D.
514 0x2A700, 0x2B81F,
515 // CJK Compatibility Ideographs Supplement.
516 0x2F800, 0x2FA1F
517 };
518 static size_t cjkIdeographRangesCount = WTF_ARRAY_LENGTH(cjkIdeographRanges) ;
519
520 // Early out
521 if (c < cjkIdeographRanges[0] || c > cjkIdeographRanges[cjkIdeographRangesCo unt - 1])
522 return false;
523
524 UChar32* boundingCharacter = approximateBinarySearch<UChar32, UChar32>(
525 (UChar32*)cjkIdeographRanges, cjkIdeographRangesCount, c, keyExtractorUC har32);
526 // Exact matches are CJK
527 if (*boundingCharacter == c)
528 return true;
529 bool isEndOfRange = ((boundingCharacter - cjkIdeographRanges) % 2);
530 if (*boundingCharacter < c)
531 return !isEndOfRange;
532 return isEndOfRange;
533 }
534
535 bool Font::isCJKIdeographOrSymbol(UChar32 c)
536 {
537 // Likely common case
538 if (c < 0x2C7)
539 return false;
540
541 // Hash lookup for isolated symbols (those not part of a contiguous range)
542 static HashSet<UChar32>* cjkIsolatedSymbols = 0;
543 if (!cjkIsolatedSymbols) {
544 cjkIsolatedSymbols = new HashSet<UChar32>();
545 for (size_t i = 0; i < WTF_ARRAY_LENGTH(cjkIsolatedSymbolsArray); ++i)
546 cjkIsolatedSymbols->add(cjkIsolatedSymbolsArray[i]);
547 }
548 if (cjkIsolatedSymbols->contains(c))
549 return true;
550
551 if (isCJKIdeograph(c))
552 return true;
553
554 static const UChar32 cjkSymbolRanges[] = {
555 0x2156, 0x215A,
556 0x2160, 0x216B,
557 0x2170, 0x217B,
558 0x23BE, 0x23CC,
559 0x2460, 0x2492,
560 0x249C, 0x24FF,
561 0x25CE, 0x25D3,
562 0x25E2, 0x25E6,
563 0x2600, 0x2603,
564 0x2660, 0x266F,
565 0x2672, 0x267D,
566 0x2776, 0x277F,
567 // Ideographic Description Characters, with CJK Symbols and Punctuation, excluding 0x3030.
568 // Then Hiragana 0x3040 .. 0x309F, Katakana 0x30A0 .. 0x30FF, Bopomofo 0 x3100 .. 0x312F
569 0x2FF0, 0x302F,
570 0x3031, 0x312F,
571 // More Bopomofo and Bopomofo Extended 0x31A0 .. 0x31BF
572 0x3190, 0x31BF,
573 // Enclosed CJK Letters and Months (0x3200 .. 0x32FF).
574 // CJK Compatibility (0x3300 .. 0x33FF).
575 0x3200, 0x33FF,
576 0xF860, 0xF862,
577 // CJK Compatibility Forms.
578 0xFE30, 0xFE4F,
579 // Halfwidth and Fullwidth Forms
580 // Usually only used in CJK
581 0xFF00, 0xFF0C,
582 0xFF0E, 0xFF1A,
583 0xFF1F, 0xFFEF,
584 // Emoji.
585 0x1F110, 0x1F129,
586 0x1F130, 0x1F149,
587 0x1F150, 0x1F169,
588 0x1F170, 0x1F189,
589 0x1F200, 0x1F6FF
590 };
591 static size_t cjkSymbolRangesCount = WTF_ARRAY_LENGTH(cjkSymbolRanges);
592
593 UChar32* boundingCharacter = approximateBinarySearch<UChar32, UChar32>(
594 (UChar32*)cjkSymbolRanges, cjkSymbolRangesCount, c, keyExtractorUChar32) ;
595 // Exact matches are CJK Symbols
596 if (*boundingCharacter == c)
597 return true;
598 bool isEndOfRange = ((boundingCharacter - cjkSymbolRanges) % 2);
599 if (*boundingCharacter < c)
600 return !isEndOfRange;
601 return isEndOfRange;
602 }
603
604 unsigned Font::expansionOpportunityCount(const LChar* characters, size_t length, TextDirection direction, bool& isAfterExpansion)
605 {
606 unsigned count = 0;
607 if (direction == LTR) {
608 for (size_t i = 0; i < length; ++i) {
609 if (treatAsSpace(characters[i])) {
610 count++;
611 isAfterExpansion = true;
612 } else
613 isAfterExpansion = false;
614 }
615 } else {
616 for (size_t i = length; i > 0; --i) {
617 if (treatAsSpace(characters[i - 1])) {
618 count++;
619 isAfterExpansion = true;
620 } else
621 isAfterExpansion = false;
622 }
623 }
624 return count;
625 }
626
627 unsigned Font::expansionOpportunityCount(const UChar* characters, size_t length, TextDirection direction, bool& isAfterExpansion)
628 {
629 static bool expandAroundIdeographs = canExpandAroundIdeographsInComplexText( );
630 unsigned count = 0;
631 if (direction == LTR) {
632 for (size_t i = 0; i < length; ++i) {
633 UChar32 character = characters[i];
634 if (treatAsSpace(character)) {
635 count++;
636 isAfterExpansion = true;
637 continue;
638 }
639 if (U16_IS_LEAD(character) && i + 1 < length && U16_IS_TRAIL(charact ers[i + 1])) {
640 character = U16_GET_SUPPLEMENTARY(character, characters[i + 1]);
641 i++;
642 }
643 if (expandAroundIdeographs && isCJKIdeographOrSymbol(character)) {
644 if (!isAfterExpansion)
645 count++;
646 count++;
647 isAfterExpansion = true;
648 continue;
649 }
650 isAfterExpansion = false;
651 }
652 } else {
653 for (size_t i = length; i > 0; --i) {
654 UChar32 character = characters[i - 1];
655 if (treatAsSpace(character)) {
656 count++;
657 isAfterExpansion = true;
658 continue;
659 }
660 if (U16_IS_TRAIL(character) && i > 1 && U16_IS_LEAD(characters[i - 2 ])) {
661 character = U16_GET_SUPPLEMENTARY(characters[i - 2], character);
662 i--;
663 }
664 if (expandAroundIdeographs && isCJKIdeographOrSymbol(character)) {
665 if (!isAfterExpansion)
666 count++;
667 count++;
668 isAfterExpansion = true;
669 continue;
670 }
671 isAfterExpansion = false;
672 }
673 }
674 return count;
675 }
676
677 bool Font::canReceiveTextEmphasis(UChar32 c)
678 {
679 CharCategory category = Unicode::category(c);
680 if (category & (Separator_Space | Separator_Line | Separator_Paragraph | Oth er_NotAssigned | Other_Control | Other_Format))
681 return false;
682
683 // Additional word-separator characters listed in CSS Text Level 3 Editor's Draft 3 November 2010.
684 if (c == ethiopicWordspace || c == aegeanWordSeparatorLine || c == aegeanWor dSeparatorDot
685 || c == ugariticWordDivider || c == tibetanMarkIntersyllabicTsheg || c = = tibetanMarkDelimiterTshegBstar)
686 return false;
687
688 return true;
689 }
690
691 void Font::willUseFontData() const
692 {
693 const FontFamily& family = fontDescription().family();
694 if (m_fontFallbackList && m_fontFallbackList->fontSelector() && !family.fami lyIsEmpty())
695 m_fontFallbackList->fontSelector()->willUseFontData(fontDescription(), f amily.family());
696 }
697
698 }
OLDNEW
« no previous file with comments | « Source/core/platform/graphics/Font.h ('k') | Source/core/platform/graphics/FontCache.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698