Index: Source/core/platform/graphics/Font.cpp |
diff --git a/Source/core/platform/graphics/Font.cpp b/Source/core/platform/graphics/Font.cpp |
deleted file mode 100644 |
index c903861a8f1c52bd7aba48e37b76736359d61024..0000000000000000000000000000000000000000 |
--- a/Source/core/platform/graphics/Font.cpp |
+++ /dev/null |
@@ -1,698 +0,0 @@ |
-/* |
- * Copyright (C) 1999 Lars Knoll (knoll@kde.org) |
- * (C) 1999 Antti Koivisto (koivisto@kde.org) |
- * (C) 2000 Dirk Mueller (mueller@kde.org) |
- * Copyright (C) 2003, 2006, 2010, 2011 Apple Inc. All rights reserved. |
- * |
- * This library is free software; you can redistribute it and/or |
- * modify it under the terms of the GNU Library General Public |
- * License as published by the Free Software Foundation; either |
- * version 2 of the License, or (at your option) any later version. |
- * |
- * This library is distributed in the hope that it will be useful, |
- * but WITHOUT ANY WARRANTY; without even the implied warranty of |
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
- * Library General Public License for more details. |
- * |
- * You should have received a copy of the GNU Library General Public License |
- * along with this library; see the file COPYING.LIB. If not, write to |
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
- * Boston, MA 02110-1301, USA. |
- * |
- */ |
- |
-#include "config.h" |
-#include "core/platform/graphics/Font.h" |
- |
-#include "core/platform/graphics/WidthIterator.h" |
-#include "platform/geometry/FloatRect.h" |
-#include "platform/graphics/TextRun.h" |
-#include "wtf/MainThread.h" |
-#include "wtf/StdLibExtras.h" |
-#include "wtf/UnusedParam.h" |
-#include "wtf/text/StringBuilder.h" |
- |
-using namespace WTF; |
-using namespace Unicode; |
- |
-namespace WTF { |
- |
-// allow compilation of OwnPtr<TextLayout> in source files that don't have access to the TextLayout class definition |
-void OwnedPtrDeleter<WebCore::TextLayout>::deletePtr(WebCore::TextLayout* ptr) |
-{ |
- WebCore::Font::deleteLayout(ptr); |
-} |
- |
-} |
- |
-namespace WebCore { |
- |
-const uint8_t Font::s_roundingHackCharacterTable[256] = { |
- 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, |
- 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 /*?*/, |
- 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, |
- 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, |
- 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, |
- 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, |
- 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, |
- 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 |
-}; |
- |
-static const UChar32 cjkIsolatedSymbolsArray[] = { |
- // 0x2C7 Caron, Mandarin Chinese 3rd Tone |
- 0x2C7, |
- // 0x2CA Modifier Letter Acute Accent, Mandarin Chinese 2nd Tone |
- 0x2CA, |
- // 0x2CB Modifier Letter Grave Access, Mandarin Chinese 4th Tone |
- 0x2CB, |
- // 0x2D9 Dot Above, Mandarin Chinese 5th Tone |
- 0x2D9, |
- 0x2020, 0x2021, 0x2030, 0x203B, 0x203C, 0x2042, 0x2047, 0x2048, 0x2049, 0x2051, |
- 0x20DD, 0x20DE, 0x2100, 0x2103, 0x2105, 0x2109, 0x210A, 0x2113, 0x2116, 0x2121, |
- 0x212B, 0x213B, 0x2150, 0x2151, 0x2152, 0x217F, 0x2189, 0x2307, 0x2312, 0x23CE, |
- 0x2423, 0x25A0, 0x25A1, 0x25A2, 0x25AA, 0x25AB, 0x25B1, 0x25B2, 0x25B3, 0x25B6, |
- 0x25B7, 0x25BC, 0x25BD, 0x25C0, 0x25C1, 0x25C6, 0x25C7, 0x25C9, 0x25CB, 0x25CC, |
- 0x25EF, 0x2605, 0x2606, 0x260E, 0x2616, 0x2617, 0x2640, 0x2642, 0x26A0, 0x26BD, |
- 0x26BE, 0x2713, 0x271A, 0x273F, 0x2740, 0x2756, 0x2B1A, 0xFE10, 0xFE11, 0xFE12, |
- 0xFE19, 0xFF1D, |
- // Emoji. |
- 0x1F100 |
-}; |
- |
-Font::CodePath Font::s_codePath = Auto; |
- |
-TypesettingFeatures Font::s_defaultTypesettingFeatures = 0; |
- |
-// ============================================================================================ |
-// Font Implementation (Cross-Platform Portion) |
-// ============================================================================================ |
- |
-Font::Font() |
- : m_letterSpacing(0) |
- , m_wordSpacing(0) |
- , m_isPlatformFont(false) |
- , m_typesettingFeatures(0) |
-{ |
-} |
- |
-Font::Font(const FontDescription& fd, float letterSpacing, float wordSpacing) |
- : m_fontDescription(fd) |
- , m_letterSpacing(letterSpacing) |
- , m_wordSpacing(wordSpacing) |
- , m_isPlatformFont(false) |
- , m_typesettingFeatures(computeTypesettingFeatures()) |
-{ |
-} |
- |
-Font::Font(const FontPlatformData& fontData, bool isPrinterFont, FontSmoothingMode fontSmoothingMode) |
- : m_fontFallbackList(FontFallbackList::create()) |
- , m_letterSpacing(0) |
- , m_wordSpacing(0) |
- , m_isPlatformFont(true) |
- , m_typesettingFeatures(computeTypesettingFeatures()) |
-{ |
- m_fontDescription.setUsePrinterFont(isPrinterFont); |
- m_fontDescription.setFontSmoothing(fontSmoothingMode); |
- m_fontFallbackList->setPlatformFont(fontData); |
-} |
- |
-Font::Font(const Font& other) |
- : m_fontDescription(other.m_fontDescription) |
- , m_fontFallbackList(other.m_fontFallbackList) |
- , m_letterSpacing(other.m_letterSpacing) |
- , m_wordSpacing(other.m_wordSpacing) |
- , m_isPlatformFont(other.m_isPlatformFont) |
- , m_typesettingFeatures(computeTypesettingFeatures()) |
-{ |
-} |
- |
-Font& Font::operator=(const Font& other) |
-{ |
- m_fontDescription = other.m_fontDescription; |
- m_fontFallbackList = other.m_fontFallbackList; |
- m_letterSpacing = other.m_letterSpacing; |
- m_wordSpacing = other.m_wordSpacing; |
- m_isPlatformFont = other.m_isPlatformFont; |
- m_typesettingFeatures = other.m_typesettingFeatures; |
- return *this; |
-} |
- |
-bool Font::operator==(const Font& other) const |
-{ |
- // Our FontData don't have to be checked, since checking the font description will be fine. |
- // FIXME: This does not work if the font was made with the FontPlatformData constructor. |
- if (loadingCustomFonts() || other.loadingCustomFonts()) |
- return false; |
- |
- FontSelector* first = m_fontFallbackList ? m_fontFallbackList->fontSelector() : 0; |
- FontSelector* second = other.m_fontFallbackList ? other.m_fontFallbackList->fontSelector() : 0; |
- |
- return first == second |
- && m_fontDescription == other.m_fontDescription |
- && m_letterSpacing == other.m_letterSpacing |
- && m_wordSpacing == other.m_wordSpacing |
- && (m_fontFallbackList ? m_fontFallbackList->fontSelectorVersion() : 0) == (other.m_fontFallbackList ? other.m_fontFallbackList->fontSelectorVersion() : 0) |
- && (m_fontFallbackList ? m_fontFallbackList->generation() : 0) == (other.m_fontFallbackList ? other.m_fontFallbackList->generation() : 0); |
-} |
- |
-void Font::update(PassRefPtr<FontSelector> fontSelector) const |
-{ |
- // FIXME: It is pretty crazy that we are willing to just poke into a RefPtr, but it ends up |
- // being reasonably safe (because inherited fonts in the render tree pick up the new |
- // style anyway. Other copies are transient, e.g., the state in the GraphicsContext, and |
- // won't stick around long enough to get you in trouble). Still, this is pretty disgusting, |
- // and could eventually be rectified by using RefPtrs for Fonts themselves. |
- if (!m_fontFallbackList) |
- m_fontFallbackList = FontFallbackList::create(); |
- m_fontFallbackList->invalidate(fontSelector); |
- m_typesettingFeatures = computeTypesettingFeatures(); |
-} |
- |
-void Font::drawText(GraphicsContext* context, const TextRunPaintInfo& runInfo, const FloatPoint& point, CustomFontNotReadyAction customFontNotReadyAction) const |
-{ |
- // Don't draw anything while we are using custom fonts that are in the process of loading, |
- // except if the 'force' argument is set to true (in which case it will use a fallback |
- // font). |
- if (loadingCustomFonts() && customFontNotReadyAction == DoNotPaintIfFontNotReady) |
- return; |
- |
- CodePath codePathToUse = codePath(runInfo.run); |
- // FIXME: Use the fast code path once it handles partial runs with kerning and ligatures. See http://webkit.org/b/100050 |
- if (codePathToUse != Complex && typesettingFeatures() && (runInfo.from || runInfo.to != runInfo.run.length())) |
- codePathToUse = Complex; |
- |
- if (codePathToUse != Complex) |
- return drawSimpleText(context, runInfo, point); |
- |
- return drawComplexText(context, runInfo, point); |
-} |
- |
-void Font::drawEmphasisMarks(GraphicsContext* context, const TextRunPaintInfo& runInfo, const AtomicString& mark, const FloatPoint& point) const |
-{ |
- if (loadingCustomFonts()) |
- return; |
- |
- CodePath codePathToUse = codePath(runInfo.run); |
- // FIXME: Use the fast code path once it handles partial runs with kerning and ligatures. See http://webkit.org/b/100050 |
- if (codePathToUse != Complex && typesettingFeatures() && (runInfo.from || runInfo.to != runInfo.run.length())) |
- codePathToUse = Complex; |
- |
- if (codePathToUse != Complex) |
- drawEmphasisMarksForSimpleText(context, runInfo, mark, point); |
- else |
- drawEmphasisMarksForComplexText(context, runInfo, mark, point); |
-} |
- |
-float Font::width(const TextRun& run, HashSet<const SimpleFontData*>* fallbackFonts, GlyphOverflow* glyphOverflow) const |
-{ |
- CodePath codePathToUse = codePath(run); |
- if (codePathToUse != Complex) { |
- // 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. |
- if (!canReturnFallbackFontsForComplexText()) |
- fallbackFonts = 0; |
- // The simple path can optimize the case where glyph overflow is not observable. |
- if (codePathToUse != SimpleWithGlyphOverflow && (glyphOverflow && !glyphOverflow->computeBounds)) |
- glyphOverflow = 0; |
- } |
- |
- bool hasKerningOrLigatures = typesettingFeatures() & (Kerning | Ligatures); |
- bool hasWordSpacingOrLetterSpacing = wordSpacing() || letterSpacing(); |
- float* cacheEntry = m_fontFallbackList->widthCache().add(run, std::numeric_limits<float>::quiet_NaN(), hasKerningOrLigatures, hasWordSpacingOrLetterSpacing, glyphOverflow); |
- if (cacheEntry && !std::isnan(*cacheEntry)) |
- return *cacheEntry; |
- |
- float result; |
- if (codePathToUse == Complex) |
- result = floatWidthForComplexText(run, fallbackFonts, glyphOverflow); |
- else |
- result = floatWidthForSimpleText(run, fallbackFonts, glyphOverflow); |
- |
- if (cacheEntry && (!fallbackFonts || fallbackFonts->isEmpty())) |
- *cacheEntry = result; |
- return result; |
-} |
- |
-float Font::width(const TextRun& run, int& charsConsumed, String& glyphName) const |
-{ |
-#if ENABLE(SVG_FONTS) |
- if (TextRun::RenderingContext* renderingContext = run.renderingContext()) |
- return renderingContext->floatWidthUsingSVGFont(*this, run, charsConsumed, glyphName); |
-#endif |
- |
- charsConsumed = run.length(); |
- glyphName = ""; |
- return width(run); |
-} |
- |
-#if !OS(MACOSX) |
- |
-PassOwnPtr<TextLayout> Font::createLayoutForMacComplexText(const TextRun&, unsigned, float, bool) const |
-{ |
- ASSERT_NOT_REACHED(); |
- return nullptr; |
-} |
- |
-void Font::deleteLayout(TextLayout*) |
-{ |
-} |
- |
-float Font::width(TextLayout&, unsigned, unsigned, HashSet<const SimpleFontData*>*) |
-{ |
- ASSERT_NOT_REACHED(); |
- return 0; |
-} |
- |
-#endif |
- |
-FloatRect Font::selectionRectForText(const TextRun& run, const FloatPoint& point, int h, int from, int to) const |
-{ |
- to = (to == -1 ? run.length() : to); |
- |
- CodePath codePathToUse = codePath(run); |
- // FIXME: Use the fast code path once it handles partial runs with kerning and ligatures. See http://webkit.org/b/100050 |
- if (codePathToUse != Complex && typesettingFeatures() && (from || to != run.length())) |
- codePathToUse = Complex; |
- |
- if (codePathToUse != Complex) |
- return selectionRectForSimpleText(run, point, h, from, to); |
- |
- return selectionRectForComplexText(run, point, h, from, to); |
-} |
- |
-int Font::offsetForPosition(const TextRun& run, float x, bool includePartialGlyphs) const |
-{ |
- // FIXME: Use the fast code path once it handles partial runs with kerning and ligatures. See http://webkit.org/b/100050 |
- if (codePath(run) != Complex && !typesettingFeatures()) |
- return offsetForPositionForSimpleText(run, x, includePartialGlyphs); |
- |
- return offsetForPositionForComplexText(run, x, includePartialGlyphs); |
-} |
- |
-template <typename CharacterType> |
-static inline String normalizeSpacesInternal(const CharacterType* characters, unsigned length) |
-{ |
- StringBuilder normalized; |
- normalized.reserveCapacity(length); |
- |
- for (unsigned i = 0; i < length; ++i) |
- normalized.append(Font::normalizeSpaces(characters[i])); |
- |
- return normalized.toString(); |
-} |
- |
-String Font::normalizeSpaces(const LChar* characters, unsigned length) |
-{ |
- return normalizeSpacesInternal(characters, length); |
-} |
- |
-String Font::normalizeSpaces(const UChar* characters, unsigned length) |
-{ |
- return normalizeSpacesInternal(characters, length); |
-} |
- |
-static bool shouldUseFontSmoothing = true; |
- |
-void Font::setShouldUseSmoothing(bool shouldUseSmoothing) |
-{ |
- ASSERT(isMainThread()); |
- shouldUseFontSmoothing = shouldUseSmoothing; |
-} |
- |
-bool Font::shouldUseSmoothing() |
-{ |
- return shouldUseFontSmoothing; |
-} |
- |
-void Font::setCodePath(CodePath p) |
-{ |
- s_codePath = p; |
-} |
- |
-Font::CodePath Font::codePath() |
-{ |
- return s_codePath; |
-} |
- |
-void Font::setDefaultTypesettingFeatures(TypesettingFeatures typesettingFeatures) |
-{ |
- s_defaultTypesettingFeatures = typesettingFeatures; |
-} |
- |
-TypesettingFeatures Font::defaultTypesettingFeatures() |
-{ |
- return s_defaultTypesettingFeatures; |
-} |
- |
-Font::CodePath Font::codePath(const TextRun& run) const |
-{ |
- if (s_codePath != Auto) |
- return s_codePath; |
- |
-#if ENABLE(SVG_FONTS) |
- if (run.renderingContext()) |
- return Simple; |
-#endif |
- |
- if (m_fontDescription.featureSettings() && m_fontDescription.featureSettings()->size() > 0) |
- return Complex; |
- |
- if (run.length() > 1 && !WidthIterator::supportsTypesettingFeatures(*this)) |
- return Complex; |
- |
- if (!run.characterScanForCodePath()) |
- return Simple; |
- |
- if (run.is8Bit()) |
- return Simple; |
- |
- // Start from 0 since drawing and highlighting also measure the characters before run->from. |
- return characterRangeCodePath(run.characters16(), run.length()); |
-} |
- |
-static inline UChar keyExtractorUChar(const UChar* value) |
-{ |
- return *value; |
-} |
- |
-static inline UChar32 keyExtractorUChar32(const UChar32* value) |
-{ |
- return *value; |
-} |
- |
-Font::CodePath Font::characterRangeCodePath(const UChar* characters, unsigned len) |
-{ |
- static const UChar complexCodePathRanges[] = { |
- // U+02E5 through U+02E9 (Modifier Letters : Tone letters) |
- 0x2E5, 0x2E9, |
- // U+0300 through U+036F Combining diacritical marks |
- 0x300, 0x36F, |
- // U+0591 through U+05CF excluding U+05BE Hebrew combining marks, ... |
- 0x0591, 0x05BD, |
- // ... Hebrew punctuation Paseq, Sof Pasuq and Nun Hafukha |
- 0x05BF, 0x05CF, |
- // U+0600 through U+109F Arabic, Syriac, Thaana, NKo, Samaritan, Mandaic, |
- // Devanagari, Bengali, Gurmukhi, Gujarati, Oriya, Tamil, Telugu, Kannada, |
- // Malayalam, Sinhala, Thai, Lao, Tibetan, Myanmar |
- 0x0600, 0x109F, |
- // U+1100 through U+11FF Hangul Jamo (only Ancient Korean should be left |
- // here if you precompose; Modern Korean will be precomposed as a result of step A) |
- 0x1100, 0x11FF, |
- // U+135D through U+135F Ethiopic combining marks |
- 0x135D, 0x135F, |
- // U+1780 through U+18AF Tagalog, Hanunoo, Buhid, Taghanwa,Khmer, Mongolian |
- 0x1700, 0x18AF, |
- // U+1900 through U+194F Limbu (Unicode 4.0) |
- 0x1900, 0x194F, |
- // U+1980 through U+19DF New Tai Lue |
- 0x1980, 0x19DF, |
- // U+1A00 through U+1CFF Buginese, Tai Tham, Balinese, Batak, Lepcha, Vedic |
- 0x1A00, 0x1CFF, |
- // U+1DC0 through U+1DFF Comining diacritical mark supplement |
- 0x1DC0, 0x1DFF, |
- // U+20D0 through U+20FF Combining marks for symbols |
- 0x20D0, 0x20FF, |
- // U+2CEF through U+2CF1 Combining marks for Coptic |
- 0x2CEF, 0x2CF1, |
- // U+302A through U+302F Ideographic and Hangul Tone marks |
- 0x302A, 0x302F, |
- // U+A67C through U+A67D Combining marks for old Cyrillic |
- 0xA67C, 0xA67D, |
- // U+A6F0 through U+A6F1 Combining mark for Bamum |
- 0xA6F0, 0xA6F1, |
- // U+A800 through U+ABFF Nagri, Phags-pa, Saurashtra, Devanagari Extended, |
- // Hangul Jamo Ext. A, Javanese, Myanmar Extended A, Tai Viet, Meetei Mayek |
- 0xA800, 0xABFF, |
- // U+D7B0 through U+D7FF Hangul Jamo Ext. B |
- 0xD7B0, 0xD7FF, |
- // U+FE00 through U+FE0F Unicode variation selectors |
- 0xFE00, 0xFE0F, |
- // U+FE20 through U+FE2F Combining half marks |
- 0xFE20, 0xFE2F |
- }; |
- static size_t complexCodePathRangesCount = WTF_ARRAY_LENGTH(complexCodePathRanges); |
- |
- CodePath result = Simple; |
- for (unsigned i = 0; i < len; i++) { |
- const UChar c = characters[i]; |
- |
- // Shortcut for common case |
- if (c < 0x2E5) |
- continue; |
- |
- // U+1E00 through U+2000 characters with diacritics and stacked diacritics |
- if (c >= 0x1E00 && c <= 0x2000) { |
- result = SimpleWithGlyphOverflow; |
- continue; |
- } |
- |
- // Surrogate pairs |
- if (c > 0xD7FF && c <= 0xDBFF) { |
- if (i == len - 1) |
- continue; |
- |
- UChar next = characters[++i]; |
- if (!U16_IS_TRAIL(next)) |
- continue; |
- |
- UChar32 supplementaryCharacter = U16_GET_SUPPLEMENTARY(c, next); |
- |
- if (supplementaryCharacter < 0x1F1E6) // U+1F1E6 through U+1F1FF Regional Indicator Symbols |
- continue; |
- if (supplementaryCharacter <= 0x1F1FF) |
- return Complex; |
- |
- if (supplementaryCharacter < 0xE0100) // U+E0100 through U+E01EF Unicode variation selectors. |
- continue; |
- if (supplementaryCharacter <= 0xE01EF) |
- return Complex; |
- |
- // FIXME: Check for Brahmi (U+11000 block), Kaithi (U+11080 block) and other complex scripts |
- // in plane 1 or higher. |
- |
- continue; |
- } |
- |
- // Search for other Complex cases |
- UChar* boundingCharacter = approximateBinarySearch<UChar, UChar>( |
- (UChar*)complexCodePathRanges, complexCodePathRangesCount, c, keyExtractorUChar); |
- // Exact matches are complex |
- if (*boundingCharacter == c) |
- return Complex; |
- bool isEndOfRange = ((boundingCharacter - complexCodePathRanges) % 2); |
- if (*boundingCharacter < c) { |
- // Determine if we are in a range or out |
- if (!isEndOfRange) |
- return Complex; |
- continue; |
- } |
- ASSERT(*boundingCharacter > c); |
- // Determine if we are in a range or out - opposite condition to above |
- if (isEndOfRange) |
- return Complex; |
- } |
- |
- return result; |
-} |
- |
-bool Font::isCJKIdeograph(UChar32 c) |
-{ |
- static const UChar32 cjkIdeographRanges[] = { |
- // CJK Radicals Supplement and Kangxi Radicals. |
- 0x2E80, 0x2FDF, |
- // CJK Strokes. |
- 0x31C0, 0x31EF, |
- // CJK Unified Ideographs Extension A. |
- 0x3400, 0x4DBF, |
- // The basic CJK Unified Ideographs block. |
- 0x4E00, 0x9FFF, |
- // CJK Compatibility Ideographs. |
- 0xF900, 0xFAFF, |
- // CJK Unified Ideographs Extension B. |
- 0x20000, 0x2A6DF, |
- // CJK Unified Ideographs Extension C. |
- // CJK Unified Ideographs Extension D. |
- 0x2A700, 0x2B81F, |
- // CJK Compatibility Ideographs Supplement. |
- 0x2F800, 0x2FA1F |
- }; |
- static size_t cjkIdeographRangesCount = WTF_ARRAY_LENGTH(cjkIdeographRanges); |
- |
- // Early out |
- if (c < cjkIdeographRanges[0] || c > cjkIdeographRanges[cjkIdeographRangesCount - 1]) |
- return false; |
- |
- UChar32* boundingCharacter = approximateBinarySearch<UChar32, UChar32>( |
- (UChar32*)cjkIdeographRanges, cjkIdeographRangesCount, c, keyExtractorUChar32); |
- // Exact matches are CJK |
- if (*boundingCharacter == c) |
- return true; |
- bool isEndOfRange = ((boundingCharacter - cjkIdeographRanges) % 2); |
- if (*boundingCharacter < c) |
- return !isEndOfRange; |
- return isEndOfRange; |
-} |
- |
-bool Font::isCJKIdeographOrSymbol(UChar32 c) |
-{ |
- // Likely common case |
- if (c < 0x2C7) |
- return false; |
- |
- // Hash lookup for isolated symbols (those not part of a contiguous range) |
- static HashSet<UChar32>* cjkIsolatedSymbols = 0; |
- if (!cjkIsolatedSymbols) { |
- cjkIsolatedSymbols = new HashSet<UChar32>(); |
- for (size_t i = 0; i < WTF_ARRAY_LENGTH(cjkIsolatedSymbolsArray); ++i) |
- cjkIsolatedSymbols->add(cjkIsolatedSymbolsArray[i]); |
- } |
- if (cjkIsolatedSymbols->contains(c)) |
- return true; |
- |
- if (isCJKIdeograph(c)) |
- return true; |
- |
- static const UChar32 cjkSymbolRanges[] = { |
- 0x2156, 0x215A, |
- 0x2160, 0x216B, |
- 0x2170, 0x217B, |
- 0x23BE, 0x23CC, |
- 0x2460, 0x2492, |
- 0x249C, 0x24FF, |
- 0x25CE, 0x25D3, |
- 0x25E2, 0x25E6, |
- 0x2600, 0x2603, |
- 0x2660, 0x266F, |
- 0x2672, 0x267D, |
- 0x2776, 0x277F, |
- // Ideographic Description Characters, with CJK Symbols and Punctuation, excluding 0x3030. |
- // Then Hiragana 0x3040 .. 0x309F, Katakana 0x30A0 .. 0x30FF, Bopomofo 0x3100 .. 0x312F |
- 0x2FF0, 0x302F, |
- 0x3031, 0x312F, |
- // More Bopomofo and Bopomofo Extended 0x31A0 .. 0x31BF |
- 0x3190, 0x31BF, |
- // Enclosed CJK Letters and Months (0x3200 .. 0x32FF). |
- // CJK Compatibility (0x3300 .. 0x33FF). |
- 0x3200, 0x33FF, |
- 0xF860, 0xF862, |
- // CJK Compatibility Forms. |
- 0xFE30, 0xFE4F, |
- // Halfwidth and Fullwidth Forms |
- // Usually only used in CJK |
- 0xFF00, 0xFF0C, |
- 0xFF0E, 0xFF1A, |
- 0xFF1F, 0xFFEF, |
- // Emoji. |
- 0x1F110, 0x1F129, |
- 0x1F130, 0x1F149, |
- 0x1F150, 0x1F169, |
- 0x1F170, 0x1F189, |
- 0x1F200, 0x1F6FF |
- }; |
- static size_t cjkSymbolRangesCount = WTF_ARRAY_LENGTH(cjkSymbolRanges); |
- |
- UChar32* boundingCharacter = approximateBinarySearch<UChar32, UChar32>( |
- (UChar32*)cjkSymbolRanges, cjkSymbolRangesCount, c, keyExtractorUChar32); |
- // Exact matches are CJK Symbols |
- if (*boundingCharacter == c) |
- return true; |
- bool isEndOfRange = ((boundingCharacter - cjkSymbolRanges) % 2); |
- if (*boundingCharacter < c) |
- return !isEndOfRange; |
- return isEndOfRange; |
-} |
- |
-unsigned Font::expansionOpportunityCount(const LChar* characters, size_t length, TextDirection direction, bool& isAfterExpansion) |
-{ |
- unsigned count = 0; |
- if (direction == LTR) { |
- for (size_t i = 0; i < length; ++i) { |
- if (treatAsSpace(characters[i])) { |
- count++; |
- isAfterExpansion = true; |
- } else |
- isAfterExpansion = false; |
- } |
- } else { |
- for (size_t i = length; i > 0; --i) { |
- if (treatAsSpace(characters[i - 1])) { |
- count++; |
- isAfterExpansion = true; |
- } else |
- isAfterExpansion = false; |
- } |
- } |
- return count; |
-} |
- |
-unsigned Font::expansionOpportunityCount(const UChar* characters, size_t length, TextDirection direction, bool& isAfterExpansion) |
-{ |
- static bool expandAroundIdeographs = canExpandAroundIdeographsInComplexText(); |
- unsigned count = 0; |
- if (direction == LTR) { |
- for (size_t i = 0; i < length; ++i) { |
- UChar32 character = characters[i]; |
- if (treatAsSpace(character)) { |
- count++; |
- isAfterExpansion = true; |
- continue; |
- } |
- if (U16_IS_LEAD(character) && i + 1 < length && U16_IS_TRAIL(characters[i + 1])) { |
- character = U16_GET_SUPPLEMENTARY(character, characters[i + 1]); |
- i++; |
- } |
- if (expandAroundIdeographs && isCJKIdeographOrSymbol(character)) { |
- if (!isAfterExpansion) |
- count++; |
- count++; |
- isAfterExpansion = true; |
- continue; |
- } |
- isAfterExpansion = false; |
- } |
- } else { |
- for (size_t i = length; i > 0; --i) { |
- UChar32 character = characters[i - 1]; |
- if (treatAsSpace(character)) { |
- count++; |
- isAfterExpansion = true; |
- continue; |
- } |
- if (U16_IS_TRAIL(character) && i > 1 && U16_IS_LEAD(characters[i - 2])) { |
- character = U16_GET_SUPPLEMENTARY(characters[i - 2], character); |
- i--; |
- } |
- if (expandAroundIdeographs && isCJKIdeographOrSymbol(character)) { |
- if (!isAfterExpansion) |
- count++; |
- count++; |
- isAfterExpansion = true; |
- continue; |
- } |
- isAfterExpansion = false; |
- } |
- } |
- return count; |
-} |
- |
-bool Font::canReceiveTextEmphasis(UChar32 c) |
-{ |
- CharCategory category = Unicode::category(c); |
- if (category & (Separator_Space | Separator_Line | Separator_Paragraph | Other_NotAssigned | Other_Control | Other_Format)) |
- return false; |
- |
- // Additional word-separator characters listed in CSS Text Level 3 Editor's Draft 3 November 2010. |
- if (c == ethiopicWordspace || c == aegeanWordSeparatorLine || c == aegeanWordSeparatorDot |
- || c == ugariticWordDivider || c == tibetanMarkIntersyllabicTsheg || c == tibetanMarkDelimiterTshegBstar) |
- return false; |
- |
- return true; |
-} |
- |
-void Font::willUseFontData() const |
-{ |
- const FontFamily& family = fontDescription().family(); |
- if (m_fontFallbackList && m_fontFallbackList->fontSelector() && !family.familyIsEmpty()) |
- m_fontFallbackList->fontSelector()->willUseFontData(fontDescription(), family.family()); |
-} |
- |
-} |