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.
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.
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.
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.
27 #include "FloatRect.h"
28 #include "FontCache.h"
29 #include "FontTranscoder.h"
31 #include "GlyphBuffer.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>
40 using namespace Unicode;
44 const uint8_t Font::s_roundingHackCharacterTable[256] = {
45 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,
46 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 /*?*/,
47 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,
48 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,
49 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,
50 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,
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
55 Font::CodePath Font::s_codePath = Auto;
57 // ============================================================================================
58 // Font Implementation (Cross-Platform Portion)
59 // ============================================================================================
64 , m_isPlatformFont(false)
65 , m_needsTranscoding(false)
69 Font::Font(const FontDescription& fd, short letterSpacing, short wordSpacing)
70 : m_fontDescription(fd)
71 , m_letterSpacing(letterSpacing)
72 , m_wordSpacing(wordSpacing)
73 , m_isPlatformFont(false)
74 , m_needsTranscoding(fontTranscoder().needsTranscoding(fd))
78 Font::Font(const FontPlatformData& fontData, bool isPrinterFont, FontSmoothingMode fontSmoothingMode)
79 : m_fontList(FontFallbackList::create())
82 , m_isPlatformFont(true)
84 m_fontDescription.setUsePrinterFont(isPrinterFont);
85 m_fontDescription.setFontSmoothing(fontSmoothingMode);
86 m_needsTranscoding = fontTranscoder().needsTranscoding(fontDescription());
87 m_fontList->setPlatformFont(fontData);
90 Font::Font(const Font& other)
91 : m_fontDescription(other.m_fontDescription)
92 , m_fontList(other.m_fontList)
93 , m_letterSpacing(other.m_letterSpacing)
94 , m_wordSpacing(other.m_wordSpacing)
95 , m_isPlatformFont(other.m_isPlatformFont)
96 , m_needsTranscoding(other.m_needsTranscoding)
100 Font& Font::operator=(const Font& other)
102 m_fontDescription = other.m_fontDescription;
103 m_fontList = other.m_fontList;
104 m_letterSpacing = other.m_letterSpacing;
105 m_wordSpacing = other.m_wordSpacing;
106 m_isPlatformFont = other.m_isPlatformFont;
107 m_needsTranscoding = other.m_needsTranscoding;
111 bool Font::operator==(const Font& other) const
113 // Our FontData don't have to be checked, since checking the font description will be fine.
114 // FIXME: This does not work if the font was made with the FontPlatformData constructor.
115 if (loadingCustomFonts() || other.loadingCustomFonts())
118 FontSelector* first = m_fontList ? m_fontList->fontSelector() : 0;
119 FontSelector* second = other.m_fontList ? other.m_fontList->fontSelector() : 0;
121 return first == second
122 && m_fontDescription == other.m_fontDescription
123 && m_letterSpacing == other.m_letterSpacing
124 && m_wordSpacing == other.m_wordSpacing
125 && (m_fontList ? m_fontList->fontSelectorVersion() : 0) == (other.m_fontList ? other.m_fontList->fontSelectorVersion() : 0)
126 && (m_fontList ? m_fontList->generation() : 0) == (other.m_fontList ? other.m_fontList->generation() : 0);
129 void Font::update(PassRefPtr<FontSelector> fontSelector) const
131 // FIXME: It is pretty crazy that we are willing to just poke into a RefPtr, but it ends up
132 // being reasonably safe (because inherited fonts in the render tree pick up the new
133 // style anyway. Other copies are transient, e.g., the state in the GraphicsContext, and
134 // won't stick around long enough to get you in trouble). Still, this is pretty disgusting,
135 // and could eventually be rectified by using RefPtrs for Fonts themselves.
137 m_fontList = FontFallbackList::create();
138 m_fontList->invalidate(fontSelector);
141 void Font::drawText(GraphicsContext* context, const TextRun& run, const FloatPoint& point, int from, int to, CustomFontNotReadyAction customFontNotReadyAction) const
143 // Don't draw anything while we are using custom fonts that are in the process of loading,
144 // except if the 'force' argument is set to true (in which case it will use a fallback
146 if (loadingCustomFonts() && customFontNotReadyAction == DoNotPaintIfFontNotReady)
149 to = (to == -1 ? run.length() : to);
151 CodePath codePathToUse = codePath(run);
153 if (codePathToUse != Complex)
154 return drawSimpleText(context, run, point, from, to);
156 return drawComplexText(context, run, point, from, to);
159 void Font::drawEmphasisMarks(GraphicsContext* context, const TextRun& run, const AtomicString& mark, const FloatPoint& point, int from, int to) const
161 if (loadingCustomFonts())
167 if (codePath(run) != Complex)
168 drawEmphasisMarksForSimpleText(context, run, mark, point, from, to);
170 drawEmphasisMarksForComplexText(context, run, mark, point, from, to);
173 float Font::width(const TextRun& run, HashSet<const SimpleFontData*>* fallbackFonts, GlyphOverflow* glyphOverflow) const
175 CodePath codePathToUse = codePath(run);
176 if (codePathToUse != Complex) {
177 // If the complex text implementation cannot return fallback fonts, avoid
178 // returning them for simple text as well.
179 static bool returnFallbackFonts = canReturnFallbackFontsForComplexText();
180 return floatWidthForSimpleText(run, 0, returnFallbackFonts ? fallbackFonts : 0, codePathToUse == SimpleWithGlyphOverflow || (glyphOverflow && glyphOverflow->computeBounds) ? glyphOverflow : 0);
183 return floatWidthForComplexText(run, fallbackFonts, glyphOverflow);
186 float Font::width(const TextRun& run, int& charsConsumed, String& glyphName) const
188 #if ENABLE(SVG_FONTS)
189 if (TextRun::RenderingContext* renderingContext = run.renderingContext())
190 return renderingContext->floatWidthUsingSVGFont(*this, run, charsConsumed, glyphName);
193 charsConsumed = run.length();
196 if (codePath(run) != Complex)
197 return floatWidthForSimpleText(run, 0);
199 return floatWidthForComplexText(run);
202 FloatRect Font::selectionRectForText(const TextRun& run, const FloatPoint& point, int h, int from, int to) const
204 to = (to == -1 ? run.length() : to);
206 if (codePath(run) != Complex)
207 return selectionRectForSimpleText(run, point, h, from, to);
209 return selectionRectForComplexText(run, point, h, from, to);
212 int Font::offsetForPosition(const TextRun& run, float x, bool includePartialGlyphs) const
214 if (codePath(run) != Complex)
215 return offsetForPositionForSimpleText(run, x, includePartialGlyphs);
217 return offsetForPositionForComplexText(run, x, includePartialGlyphs);
220 String Font::normalizeSpaces(const UChar* characters, unsigned length)
222 StringBuilder normalized;
223 normalized.reserveCapacity(length);
225 for (unsigned i = 0; i < length; ++i)
226 normalized.append(normalizeSpaces(characters[i]));
228 return normalized.toString();
231 static bool shouldUseFontSmoothing = true;
233 void Font::setShouldUseSmoothing(bool shouldUseSmoothing)
235 ASSERT(isMainThread());
236 shouldUseFontSmoothing = shouldUseSmoothing;
239 bool Font::shouldUseSmoothing()
241 return shouldUseFontSmoothing;
244 void Font::setCodePath(CodePath p)
249 Font::CodePath Font::codePath()
254 Font::CodePath Font::codePath(const TextRun& run) const
256 if (s_codePath != Auto)
259 #if ENABLE(SVG_FONTS)
260 if (run.renderingContext())
264 #if PLATFORM(QT) && !HAVE(QRAWFONT)
265 if (run.expansion() || run.rtl() || isSmallCaps() || wordSpacing() || letterSpacing())
269 if (m_fontDescription.featureSettings() && m_fontDescription.featureSettings()->size() > 0)
272 if (run.length() > 1 && typesettingFeatures())
275 if (!run.characterScanForCodePath())
278 // Start from 0 since drawing and highlighting also measure the characters before run->from.
279 return characterRangeCodePath(run.characters(), run.length());
282 Font::CodePath Font::characterRangeCodePath(const UChar* characters, unsigned len)
284 // FIXME: Should use a UnicodeSet in ports where ICU is used. Note that we
285 // can't simply use UnicodeCharacter Property/class because some characters
286 // are not 'combining', but still need to go to the complex path.
287 // Alternatively, we may as well consider binary search over a sorted
289 CodePath result = Simple;
290 for (unsigned i = 0; i < len; i++) {
291 const UChar c = characters[i];
292 if (c < 0x2E5) // U+02E5 through U+02E9 (Modifier Letters : Tone letters)
297 if (c < 0x300) // U+0300 through U+036F Combining diacritical marks
302 if (c < 0x0591 || c == 0x05BE) // U+0591 through U+05CF excluding U+05BE Hebrew combining marks, Hebrew punctuation Paseq, Sof Pasuq and Nun Hafukha
307 // U+0600 through U+109F Arabic, Syriac, Thaana, NKo, Samaritan, Mandaic,
308 // Devanagari, Bengali, Gurmukhi, Gujarati, Oriya, Tamil, Telugu, Kannada,
309 // Malayalam, Sinhala, Thai, Lao, Tibetan, Myanmar
315 // U+1100 through U+11FF Hangul Jamo (only Ancient Korean should be left here if you precompose;
316 // Modern Korean will be precomposed as a result of step A)
322 if (c < 0x135D) // U+135D through U+135F Ethiopic combining marks
327 if (c < 0x1700) // U+1780 through U+18AF Tagalog, Hanunoo, Buhid, Taghanwa,Khmer, Mongolian
332 if (c < 0x1900) // U+1900 through U+194F Limbu (Unicode 4.0)
337 if (c < 0x1980) // U+1980 through U+19DF New Tai Lue
342 if (c < 0x1A00) // U+1A00 through U+1CFF Buginese, Tai Tham, Balinese, Batak, Lepcha, Vedic
347 if (c < 0x1DC0) // U+1DC0 through U+1DFF Comining diacritical mark supplement
352 // U+1E00 through U+2000 characters with diacritics and stacked diacritics
354 result = SimpleWithGlyphOverflow;
358 if (c < 0x20D0) // U+20D0 through U+20FF Combining marks for symbols
363 if (c < 0x2CEF) // U+2CEF through U+2CF1 Combining marks for Coptic
368 if (c < 0x302A) // U+302A through U+302F Ideographic and Hangul Tone marks
373 if (c < 0xA67C) // U+A67C through U+A67D Combining marks for old Cyrillic
378 if (c < 0xA6F0) // U+A6F0 through U+A6F1 Combining mark for Bamum
383 // U+A800 through U+ABFF Nagri, Phags-pa, Saurashtra, Devanagari Extended,
384 // Hangul Jamo Ext. A, Javanese, Myanmar Extended A, Tai Viet, Meetei Mayek,
390 if (c < 0xD7B0) // U+D7B0 through U+D7FF Hangul Jamo Ext. B
401 UChar next = characters[++i];
402 if (!U16_IS_TRAIL(next))
405 UChar32 supplementaryCharacter = U16_GET_SUPPLEMENTARY(c, next);
407 if (supplementaryCharacter < 0x1F1E6) // U+1F1E6 through U+1F1FF Regional Indicator Symbols
409 if (supplementaryCharacter <= 0x1F1FF)
412 if (supplementaryCharacter < 0xE0100) // U+E0100 through U+E01EF Unicode variation selectors.
414 if (supplementaryCharacter <= 0xE01EF)
417 // FIXME: Check for Brahmi (U+11000 block), Kaithi (U+11080 block) and other complex scripts
418 // in plane 1 or higher.
423 if (c < 0xFE00) // U+FE00 through U+FE0F Unicode variation selectors
428 if (c < 0xFE20) // U+FE20 through U+FE2F Combining half marks
436 bool Font::isCJKIdeograph(UChar32 c)
438 // The basic CJK Unified Ideographs block.
439 if (c >= 0x4E00 && c <= 0x9FFF)
442 // CJK Unified Ideographs Extension A.
443 if (c >= 0x3400 && c <= 0x4DBF)
446 // CJK Radicals Supplement.
447 if (c >= 0x2E80 && c <= 0x2EFF)
451 if (c >= 0x2F00 && c <= 0x2FDF)
455 if (c >= 0x31C0 && c <= 0x31EF)
458 // CJK Compatibility Ideographs.
459 if (c >= 0xF900 && c <= 0xFAFF)
462 // CJK Unified Ideographs Extension B.
463 if (c >= 0x20000 && c <= 0x2A6DF)
466 // CJK Unified Ideographs Extension C.
467 if (c >= 0x2A700 && c <= 0x2B73F)
470 // CJK Unified Ideographs Extension D.
471 if (c >= 0x2B740 && c <= 0x2B81F)
474 // CJK Compatibility Ideographs Supplement.
475 if (c >= 0x2F800 && c <= 0x2FA1F)
481 bool Font::isCJKIdeographOrSymbol(UChar32 c)
483 // 0x2C7 Caron, Mandarin Chinese 3rd Tone
484 // 0x2CA Modifier Letter Acute Accent, Mandarin Chinese 2nd Tone
485 // 0x2CB Modifier Letter Grave Access, Mandarin Chinese 4th Tone
486 // 0x2D9 Dot Above, Mandarin Chinese 5th Tone
487 if ((c == 0x2C7) || (c == 0x2CA) || (c == 0x2CB) || (c == 0x2D9))
490 // Ideographic Description Characters.
491 if (c >= 0x2FF0 && c <= 0x2FFF)
494 // CJK Symbols and Punctuation.
495 if (c >= 0x3000 && c <= 0x303F)
499 if (c >= 0x3040 && c <= 0x309F)
503 if (c >= 0x30A0 && c <= 0x30FF)
507 if (c >= 0x3100 && c <= 0x312F)
511 if (c >= 0x31A0 && c <= 0x31BF)
514 // Enclosed CJK Letters and Months.
515 if (c >= 0x3200 && c <= 0x32FF)
518 // CJK Compatibility.
519 if (c >= 0x3300 && c <= 0x33FF)
522 // CJK Compatibility Forms.
523 if (c >= 0xFE30 && c <= 0xFE4F)
526 // Halfwidth and Fullwidth Forms
527 // Usually only used in CJK
528 if (c >= 0xFF00 && c <= 0xFFEF)
532 if (c >= 0x1F200 && c <= 0x1F6F)
535 return isCJKIdeograph(c);
538 unsigned Font::expansionOpportunityCount(const UChar* characters, size_t length, TextDirection direction, bool& isAfterExpansion)
540 static bool expandAroundIdeographs = canExpandAroundIdeographsInComplexText();
542 if (direction == LTR) {
543 for (size_t i = 0; i < length; ++i) {
544 UChar32 character = characters[i];
545 if (treatAsSpace(character)) {
547 isAfterExpansion = true;
550 if (U16_IS_LEAD(character) && i + 1 < length && U16_IS_TRAIL(characters[i + 1])) {
551 character = U16_GET_SUPPLEMENTARY(character, characters[i + 1]);
554 if (expandAroundIdeographs && isCJKIdeographOrSymbol(character)) {
555 if (!isAfterExpansion)
558 isAfterExpansion = true;
561 isAfterExpansion = false;
564 for (size_t i = length; i > 0; --i) {
565 UChar32 character = characters[i - 1];
566 if (treatAsSpace(character)) {
568 isAfterExpansion = true;
571 if (U16_IS_TRAIL(character) && i > 1 && U16_IS_LEAD(characters[i - 2])) {
572 character = U16_GET_SUPPLEMENTARY(characters[i - 2], character);
575 if (expandAroundIdeographs && isCJKIdeographOrSymbol(character)) {
576 if (!isAfterExpansion)
579 isAfterExpansion = true;
582 isAfterExpansion = false;
588 bool Font::canReceiveTextEmphasis(UChar32 c)
590 CharCategory category = Unicode::category(c);
591 if (category & (Separator_Space | Separator_Line | Separator_Paragraph | Other_NotAssigned | Other_Control | Other_Format))
594 // Additional word-separator characters listed in CSS Text Level 3 Editor's Draft 3 November 2010.
595 if (c == ethiopicWordspace || c == aegeanWordSeparatorLine || c == aegeanWordSeparatorDot
596 || c == ugariticWordDivider || c == tibetanMarkIntersyllabicTsheg || c == tibetanMarkDelimiterTshegBstar)