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; }
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); }
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); }
float Font::floatWidthForSimpleText(const TextRun& run, HashSet<const SimpleFontData*>* fallbackFonts, GlyphOverflow* glyphOverflow) const { WidthIterator it(this, run, fallbackFonts, glyphOverflow); GlyphBuffer glyphBuffer; it.advance(run.length(), (typesettingFeatures() & (Kerning | Ligatures)) ? &glyphBuffer : 0); if (glyphOverflow) { glyphOverflow->top = std::max<int>(glyphOverflow->top, ceilf(-it.minGlyphBoundingBoxY()) - (glyphOverflow->computeBounds ? 0 : fontMetrics().ascent())); glyphOverflow->bottom = std::max<int>(glyphOverflow->bottom, ceilf(it.maxGlyphBoundingBoxY()) - (glyphOverflow->computeBounds ? 0 : fontMetrics().descent())); glyphOverflow->left = ceilf(it.firstGlyphOverflow()); glyphOverflow->right = ceilf(it.lastGlyphOverflow()); } return it.m_runWidthSoFar; }
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); }
void Font::drawText(GraphicsContext* context, const TextRun& run, const FloatPoint& point, int from, int to) const { // Don't draw anything while we are using custom fonts that are in the process of loading. if (loadingCustomFonts()) return; 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 drawSimpleText(context, run, point, from, to); return drawComplexText(context, run, point, from, to); }
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); }
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 && typesettingFeatures()) return Complex; if (!run.characterScanForCodePath()) return Simple; // Start from 0 since drawing and highlighting also measure the characters before run->from. return characterRangeCodePath(run.characters(), run.length()); }
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 PLATFORM(QT) && !HAVE(QRAWFONT) if (run.expansion() || run.rtl() || isSmallCaps() || wordSpacing() || letterSpacing()) return Complex; #endif if (m_fontDescription.featureSettings() && m_fontDescription.featureSettings()->size() > 0) return Complex; CodePath result = Simple; // Start from 0 since drawing and highlighting also measure the characters before run->from // FIXME: Should use a UnicodeSet in ports where ICU is used. Note that we // can't simply use UnicodeCharacter Property/class because some characters // are not 'combining', but still need to go to the complex path. // Alternatively, we may as well consider binary search over a sorted // list of ranges. for (int i = 0; i < run.length(); i++) { const UChar c = run[i]; if (c < 0x2E5) // U+02E5 through U+02E9 (Modifier Letters : Tone letters) continue; if (c <= 0x2E9) return Complex; if (c < 0x300) // U+0300 through U+036F Combining diacritical marks continue; if (c <= 0x36F) return Complex; if (c < 0x0591 || c == 0x05BE) // U+0591 through U+05CF excluding U+05BE Hebrew combining marks, Hebrew punctuation Paseq, Sof Pasuq and Nun Hafukha continue; if (c <= 0x05CF) return Complex; // 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 if (c < 0x0600) continue; if (c <= 0x109F) return Complex; // 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) if (c < 0x1100) continue; if (c <= 0x11FF) return Complex; if (c < 0x135D) // U+135D through U+135F Ethiopic combining marks continue; if (c <= 0x135F) return Complex; if (c < 0x1700) // U+1780 through U+18AF Tagalog, Hanunoo, Buhid, Taghanwa,Khmer, Mongolian continue; if (c <= 0x18AF) return Complex; if (c < 0x1900) // U+1900 through U+194F Limbu (Unicode 4.0) continue; if (c <= 0x194F) return Complex; if (c < 0x1980) // U+1980 through U+19DF New Tai Lue continue; if (c <= 0x19DF) return Complex; if (c < 0x1A00) // U+1A00 through U+1CFF Buginese, Tai Tham, Balinese, Batak, Lepcha, Vedic continue; if (c <= 0x1CFF) return Complex; if (c < 0x1DC0) // U+1DC0 through U+1DFF Comining diacritical mark supplement continue; if (c <= 0x1DFF) return Complex; // U+1E00 through U+2000 characters with diacritics and stacked diacritics if (c <= 0x2000) { result = SimpleWithGlyphOverflow; continue; } if (c < 0x20D0) // U+20D0 through U+20FF Combining marks for symbols continue; if (c <= 0x20FF) return Complex; if (c < 0x2CEF) // U+2CEF through U+2CF1 Combining marks for Coptic continue; if (c <= 0x2CF1) return Complex; if (c < 0x302A) // U+302A through U+302F Ideographic and Hangul Tone marks continue; if (c <= 0x302F) return Complex; if (c < 0xA67C) // U+A67C through U+A67D Combining marks for old Cyrillic continue; if (c <= 0xA67D) return Complex; if (c < 0xA6F0) // U+A6F0 through U+A6F1 Combining mark for Bamum continue; if (c <= 0xA6F1) return Complex; // U+A800 through U+ABFF Nagri, Phags-pa, Saurashtra, Devanagari Extended, // Hangul Jamo Ext. A, Javanese, Myanmar Extended A, Tai Viet, Meetei Mayek, if (c < 0xA800) continue; if (c <= 0xABFF) return Complex; if (c < 0xD7B0) // U+D7B0 through U+D7FF Hangul Jamo Ext. B continue; if (c <= 0xD7FF) return Complex; if (c <= 0xDBFF) { // High surrogate if (i == run.length() - 1) continue; UChar next = run[++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; } if (c < 0xFE00) // U+FE00 through U+FE0F Unicode variation selectors continue; if (c <= 0xFE0F) return Complex; if (c < 0xFE20) // U+FE20 through U+FE2F Combining half marks continue; if (c <= 0xFE2F) return Complex; } if (run.length() > 1 && typesettingFeatures()) return Complex; return result; }
Font::CodePath Font::codePath(const TextRun& run) const { if (s_codePath != Auto) return s_codePath; #if PLATFORM(QT) if (run.expansion() || run.rtl() || isSmallCaps() || wordSpacing() || letterSpacing()) return Complex; #endif CodePath result = Simple; // Start from 0 since drawing and highlighting also measure the characters before run->from for (int i = 0; i < run.length(); i++) { const UChar c = run[i]; if (c < 0x300) // U+0300 through U+036F Combining diacritical marks continue; if (c <= 0x36F) return Complex; if (c < 0x0591 || c == 0x05BE) // U+0591 through U+05CF excluding U+05BE Hebrew combining marks, Hebrew punctuation Paseq, Sof Pasuq and Nun Hafukha continue; if (c <= 0x05CF) return Complex; if (c < 0x0600) // U+0600 through U+1059 Arabic, Syriac, Thaana, Devanagari, Bengali, Gurmukhi, Gujarati, Oriya, Tamil, Telugu, Kannada, Malayalam, Sinhala, Thai, Lao, Tibetan, Myanmar continue; if (c <= 0x1059) return Complex; if (c < 0x1100) // 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) continue; if (c <= 0x11FF) return Complex; if (c < 0x1780) // U+1780 through U+18AF Khmer, Mongolian continue; if (c <= 0x18AF) return Complex; if (c < 0x1900) // U+1900 through U+194F Limbu (Unicode 4.0) continue; if (c <= 0x194F) return Complex; if (c < 0x1E00) // U+1E00 through U+2000 characters with diacritics and stacked diacritics continue; if (c <= 0x2000) { result = SimpleWithGlyphOverflow; continue; } if (c < 0x20D0) // U+20D0 through U+20FF Combining marks for symbols continue; if (c <= 0x20FF) return Complex; if (c < 0xFE20) // U+FE20 through U+FE2F Combining half marks continue; if (c <= 0xFE2F) return Complex; } #if ENABLE(SAMSUNG_WEBKIT_PERFORMANCE_PATCH) // SAMSUNG CHANGE : Webkit Performance Patch Merge + r94303 if (run.length() > 1 && typesettingFeatures()) #else if (typesettingFeatures()) // SAMSUNG CHANGE : Webkit Performance Patch Merge - #endif return Complex; return result; }
bool Font::canUseGlyphCache(const TextRun& run) const { switch (s_codePath) { case Auto: break; case Simple: return true; case Complex: return false; } // Start from 0 since drawing and highlighting also measure the characters before run->from for (int i = 0; i < run.length(); i++) { const UChar c = run[i]; if (c < 0x300) // U+0300 through U+036F Combining diacritical marks continue; if (c <= 0x36F) return false; if (c < 0x0591 || c == 0x05BE) // U+0591 through U+05CF excluding U+05BE Hebrew combining marks, Hebrew punctuation Paseq, Sof Pasuq and Nun Hafukha continue; if (c <= 0x05CF) return false; if (c < 0x0600) // U+0600 through U+1059 Arabic, Syriac, Thaana, Devanagari, Bengali, Gurmukhi, Gujarati, Oriya, Tamil, Telugu, Kannada, Malayalam, Sinhala, Thai, Lao, Tibetan, Myanmar continue; if (c <= 0x1059) return false; if (c < 0x1100) // 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) continue; if (c <= 0x11FF) return false; if (c < 0x1780) // U+1780 through U+18AF Khmer, Mongolian continue; if (c <= 0x18AF) return false; if (c < 0x1900) // U+1900 through U+194F Limbu (Unicode 4.0) continue; if (c <= 0x194F) return false; if (c < 0x20D0) // U+20D0 through U+20FF Combining marks for symbols continue; if (c <= 0x20FF) return false; if (c < 0xFE20) // U+FE20 through U+FE2F Combining half marks continue; if (c <= 0xFE2F) return false; } if (typesettingFeatures()) return false; return true; }