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.
25 #include "platform/fonts/Font.h"
27 #include "platform/LayoutUnit.h"
28 #include "platform/fonts/Character.h"
29 #include "platform/fonts/FontCache.h"
30 #include "platform/fonts/FontFallbackList.h"
31 #include "platform/fonts/FontPlatformFeatures.h"
32 #include "platform/fonts/GlyphBuffer.h"
33 #include "platform/fonts/GlyphPageTreeNode.h"
34 #include "platform/fonts/SimpleFontData.h"
35 #include "platform/fonts/WidthIterator.h"
36 #include "platform/geometry/FloatRect.h"
37 #include "platform/text/TextRun.h"
38 #include "wtf/MainThread.h"
39 #include "wtf/StdLibExtras.h"
40 #include "wtf/unicode/CharacterNames.h"
41 #include "wtf/unicode/Unicode.h"
44 using namespace Unicode;
49 CodePath Font::s_codePath = AutoPath;
51 // ============================================================================================
52 // Font Implementation (Cross-Platform Portion)
53 // ============================================================================================
59 Font::Font(const FontDescription& fd)
60 : m_fontDescription(fd)
64 Font::Font(const Font& other)
65 : m_fontDescription(other.m_fontDescription)
66 , m_fontFallbackList(other.m_fontFallbackList)
70 Font& Font::operator=(const Font& other)
72 m_fontDescription = other.m_fontDescription;
73 m_fontFallbackList = other.m_fontFallbackList;
77 bool Font::operator==(const Font& other) const
79 // Our FontData don't have to be checked, since checking the font description will be fine.
80 // FIXME: This does not work if the font was made with the FontPlatformData constructor.
81 if (loadingCustomFonts() || other.loadingCustomFonts())
84 FontSelector* first = m_fontFallbackList ? m_fontFallbackList->fontSelector() : 0;
85 FontSelector* second = other.m_fontFallbackList ? other.m_fontFallbackList->fontSelector() : 0;
87 return first == second
88 && m_fontDescription == other.m_fontDescription
89 && (m_fontFallbackList ? m_fontFallbackList->fontSelectorVersion() : 0) == (other.m_fontFallbackList ? other.m_fontFallbackList->fontSelectorVersion() : 0)
90 && (m_fontFallbackList ? m_fontFallbackList->generation() : 0) == (other.m_fontFallbackList ? other.m_fontFallbackList->generation() : 0);
93 void Font::update(PassRefPtr<FontSelector> fontSelector) const
95 // FIXME: It is pretty crazy that we are willing to just poke into a RefPtr, but it ends up
96 // being reasonably safe (because inherited fonts in the render tree pick up the new
97 // style anyway. Other copies are transient, e.g., the state in the GraphicsContext, and
98 // won't stick around long enough to get you in trouble). Still, this is pretty disgusting,
99 // and could eventually be rectified by using RefPtrs for Fonts themselves.
100 if (!m_fontFallbackList)
101 m_fontFallbackList = FontFallbackList::create();
102 m_fontFallbackList->invalidate(fontSelector);
105 void Font::drawText(GraphicsContext* context, const TextRunPaintInfo& runInfo, const FloatPoint& point, CustomFontNotReadyAction customFontNotReadyAction) const
107 // Don't draw anything while we are using custom fonts that are in the process of loading,
108 // except if the 'force' argument is set to true (in which case it will use a fallback
110 if (loadingCustomFonts() && customFontNotReadyAction == DoNotPaintIfFontNotReady)
113 CodePath codePathToUse = codePath(runInfo.run);
114 // FIXME: Use the fast code path once it handles partial runs with kerning and ligatures. See http://webkit.org/b/100050
115 if (codePathToUse != ComplexPath && fontDescription().typesettingFeatures() && (runInfo.from || runInfo.to != runInfo.run.length()))
116 codePathToUse = ComplexPath;
118 if (codePathToUse != ComplexPath)
119 return drawSimpleText(context, runInfo, point);
121 return drawComplexText(context, runInfo, point);
124 void Font::drawEmphasisMarks(GraphicsContext* context, const TextRunPaintInfo& runInfo, const AtomicString& mark, const FloatPoint& point) const
126 if (loadingCustomFonts())
129 CodePath codePathToUse = codePath(runInfo.run);
130 // FIXME: Use the fast code path once it handles partial runs with kerning and ligatures. See http://webkit.org/b/100050
131 if (codePathToUse != ComplexPath && fontDescription().typesettingFeatures() && (runInfo.from || runInfo.to != runInfo.run.length()))
132 codePathToUse = ComplexPath;
134 if (codePathToUse != ComplexPath)
135 drawEmphasisMarksForSimpleText(context, runInfo, mark, point);
137 drawEmphasisMarksForComplexText(context, runInfo, mark, point);
140 float Font::width(const TextRun& run, HashSet<const SimpleFontData*>* fallbackFonts, GlyphOverflow* glyphOverflow) const
142 CodePath codePathToUse = codePath(run);
143 if (codePathToUse != ComplexPath) {
144 // 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.
145 if (!FontPlatformFeatures::canReturnFallbackFontsForComplexText())
147 // The simple path can optimize the case where glyph overflow is not observable.
148 if (codePathToUse != SimpleWithGlyphOverflowPath && (glyphOverflow && !glyphOverflow->computeBounds))
152 bool hasKerningOrLigatures = fontDescription().typesettingFeatures() & (Kerning | Ligatures);
153 bool hasWordSpacingOrLetterSpacing = fontDescription().wordSpacing() || fontDescription().letterSpacing();
154 float* cacheEntry = m_fontFallbackList->widthCache().add(run, std::numeric_limits<float>::quiet_NaN(), hasKerningOrLigatures, hasWordSpacingOrLetterSpacing, glyphOverflow);
155 if (cacheEntry && !std::isnan(*cacheEntry))
159 if (codePathToUse == ComplexPath)
160 result = floatWidthForComplexText(run, fallbackFonts, glyphOverflow);
162 result = floatWidthForSimpleText(run, fallbackFonts, glyphOverflow);
164 if (cacheEntry && (!fallbackFonts || fallbackFonts->isEmpty()))
165 *cacheEntry = result;
169 float Font::width(const TextRun& run, int& charsConsumed, String& glyphName) const
171 #if ENABLE(SVG_FONTS)
172 if (TextRun::RenderingContext* renderingContext = run.renderingContext())
173 return renderingContext->floatWidthUsingSVGFont(*this, run, charsConsumed, glyphName);
176 charsConsumed = run.length();
181 FloatRect Font::selectionRectForText(const TextRun& run, const FloatPoint& point, int h, int from, int to) const
183 to = (to == -1 ? run.length() : to);
185 CodePath codePathToUse = codePath(run);
186 // FIXME: Use the fast code path once it handles partial runs with kerning and ligatures. See http://webkit.org/b/100050
187 if (codePathToUse != ComplexPath && fontDescription().typesettingFeatures() && (from || to != run.length()))
188 codePathToUse = ComplexPath;
190 if (codePathToUse != ComplexPath)
191 return selectionRectForSimpleText(run, point, h, from, to);
193 return selectionRectForComplexText(run, point, h, from, to);
196 int Font::offsetForPosition(const TextRun& run, float x, bool includePartialGlyphs) const
198 // FIXME: Use the fast code path once it handles partial runs with kerning and ligatures. See http://webkit.org/b/100050
199 if (codePath(run) != ComplexPath && !fontDescription().typesettingFeatures())
200 return offsetForPositionForSimpleText(run, x, includePartialGlyphs);
202 return offsetForPositionForComplexText(run, x, includePartialGlyphs);
205 void Font::setCodePath(CodePath p)
210 CodePath Font::codePath()
215 CodePath Font::codePath(const TextRun& run) const
217 if (s_codePath != AutoPath)
220 #if ENABLE(SVG_FONTS)
221 if (run.renderingContext())
225 if (m_fontDescription.featureSettings() && m_fontDescription.featureSettings()->size() > 0)
228 if (run.length() > 1 && !WidthIterator::supportsTypesettingFeatures(*this))
231 if (!run.characterScanForCodePath())
237 // Start from 0 since drawing and highlighting also measure the characters before run->from.
238 return Character::characterRangeCodePath(run.characters16(), run.length());
241 void Font::willUseFontData() const
243 const FontFamily& family = fontDescription().family();
244 if (m_fontFallbackList && m_fontFallbackList->fontSelector() && !family.familyIsEmpty())
245 m_fontFallbackList->fontSelector()->willUseFontData(fontDescription(), family.family());
248 static inline bool isInRange(UChar32 character, UChar32 lowerBound, UChar32 upperBound)
250 return character >= lowerBound && character <= upperBound;
253 static bool shouldIgnoreRotation(UChar32 character)
255 if (character == 0x000A7 || character == 0x000A9 || character == 0x000AE)
258 if (character == 0x000B6 || character == 0x000BC || character == 0x000BD || character == 0x000BE)
261 if (isInRange(character, 0x002E5, 0x002EB))
264 if (isInRange(character, 0x01100, 0x011FF) || isInRange(character, 0x01401, 0x0167F) || isInRange(character, 0x01800, 0x018FF))
267 if (character == 0x02016 || character == 0x02018 || character == 0x02019 || character == 0x02020 || character == 0x02021
268 || character == 0x2030 || character == 0x02031)
271 if (isInRange(character, 0x0203B, 0x0203D) || character == 0x02042 || character == 0x02044 || character == 0x02047
272 || character == 0x02048 || character == 0x02049 || character == 0x2051)
275 if (isInRange(character, 0x02065, 0x02069) || isInRange(character, 0x020DD, 0x020E0)
276 || isInRange(character, 0x020E2, 0x020E4) || isInRange(character, 0x02100, 0x02117)
277 || isInRange(character, 0x02119, 0x02131) || isInRange(character, 0x02133, 0x0213F))
280 if (isInRange(character, 0x02145, 0x0214A) || character == 0x0214C || character == 0x0214D
281 || isInRange(character, 0x0214F, 0x0218F))
284 if (isInRange(character, 0x02300, 0x02307) || isInRange(character, 0x0230C, 0x0231F)
285 || isInRange(character, 0x02322, 0x0232B) || isInRange(character, 0x0237D, 0x0239A)
286 || isInRange(character, 0x023B4, 0x023B6) || isInRange(character, 0x023BA, 0x023CF)
287 || isInRange(character, 0x023D1, 0x023DB) || isInRange(character, 0x023E2, 0x024FF))
290 if (isInRange(character, 0x025A0, 0x02619) || isInRange(character, 0x02620, 0x02767)
291 || isInRange(character, 0x02776, 0x02793) || isInRange(character, 0x02B12, 0x02B2F)
292 || isInRange(character, 0x02B4D, 0x02BFF) || isInRange(character, 0x02E80, 0x03007))
295 if (character == 0x03012 || character == 0x03013 || isInRange(character, 0x03020, 0x0302F)
296 || isInRange(character, 0x03031, 0x0309F) || isInRange(character, 0x030A1, 0x030FB)
297 || isInRange(character, 0x030FD, 0x0A4CF))
300 if (isInRange(character, 0x0A840, 0x0A87F) || isInRange(character, 0x0A960, 0x0A97F)
301 || isInRange(character, 0x0AC00, 0x0D7FF) || isInRange(character, 0x0E000, 0x0FAFF))
304 if (isInRange(character, 0x0FE10, 0x0FE1F) || isInRange(character, 0x0FE30, 0x0FE48)
305 || isInRange(character, 0x0FE50, 0x0FE57) || isInRange(character, 0x0FE5F, 0x0FE62)
306 || isInRange(character, 0x0FE67, 0x0FE6F))
309 if (isInRange(character, 0x0FF01, 0x0FF07) || isInRange(character, 0x0FF0A, 0x0FF0C)
310 || isInRange(character, 0x0FF0E, 0x0FF19) || isInRange(character, 0x0FF1F, 0x0FF3A))
313 if (character == 0x0FF3C || character == 0x0FF3E)
316 if (isInRange(character, 0x0FF40, 0x0FF5A) || isInRange(character, 0x0FFE0, 0x0FFE2)
317 || isInRange(character, 0x0FFE4, 0x0FFE7) || isInRange(character, 0x0FFF0, 0x0FFF8)
318 || character == 0x0FFFD)
321 if (isInRange(character, 0x13000, 0x1342F) || isInRange(character, 0x1B000, 0x1B0FF)
322 || isInRange(character, 0x1D000, 0x1D1FF) || isInRange(character, 0x1D300, 0x1D37F)
323 || isInRange(character, 0x1F000, 0x1F64F) || isInRange(character, 0x1F680, 0x1F77F))
326 if (isInRange(character, 0x20000, 0x2FFFD) || isInRange(character, 0x30000, 0x3FFFD))
332 static inline std::pair<GlyphData, GlyphPage*> glyphDataAndPageForNonCJKCharacterWithGlyphOrientation(UChar32 character, NonCJKGlyphOrientation orientation, GlyphData& data, GlyphPage* page, unsigned pageNumber)
334 if (orientation == NonCJKGlyphOrientationUpright || shouldIgnoreRotation(character)) {
335 RefPtr<SimpleFontData> uprightFontData = data.fontData->uprightOrientationFontData();
336 GlyphPageTreeNode* uprightNode = GlyphPageTreeNode::getRootChild(uprightFontData.get(), pageNumber);
337 GlyphPage* uprightPage = uprightNode->page();
339 GlyphData uprightData = uprightPage->glyphDataForCharacter(character);
340 // If the glyphs are the same, then we know we can just use the horizontal glyph rotated vertically to be upright.
341 if (data.glyph == uprightData.glyph)
342 return make_pair(data, page);
343 // The glyphs are distinct, meaning that the font has a vertical-right glyph baked into it. We can't use that
344 // glyph, so we fall back to the upright data and use the horizontal glyph.
345 if (uprightData.fontData)
346 return make_pair(uprightData, uprightPage);
348 } else if (orientation == NonCJKGlyphOrientationVerticalRight) {
349 RefPtr<SimpleFontData> verticalRightFontData = data.fontData->verticalRightOrientationFontData();
350 GlyphPageTreeNode* verticalRightNode = GlyphPageTreeNode::getRootChild(verticalRightFontData.get(), pageNumber);
351 GlyphPage* verticalRightPage = verticalRightNode->page();
352 if (verticalRightPage) {
353 GlyphData verticalRightData = verticalRightPage->glyphDataForCharacter(character);
354 // If the glyphs are distinct, we will make the assumption that the font has a vertical-right glyph baked
356 if (data.glyph != verticalRightData.glyph)
357 return make_pair(data, page);
358 // The glyphs are identical, meaning that we should just use the horizontal glyph.
359 if (verticalRightData.fontData)
360 return make_pair(verticalRightData, verticalRightPage);
363 return make_pair(data, page);
366 std::pair<GlyphData, GlyphPage*> Font::glyphDataAndPageForCharacter(UChar32 c, bool mirror, FontDataVariant variant) const
368 ASSERT(isMainThread());
370 if (variant == AutoVariant) {
371 if (m_fontDescription.smallCaps() && !primaryFont()->isSVGFont()) {
372 UChar32 upperC = toUpper(c);
375 variant = SmallCapsVariant;
377 variant = NormalVariant;
380 variant = NormalVariant;
387 unsigned pageNumber = (c / GlyphPage::size);
389 GlyphPageTreeNode* node = pageNumber ? m_fontFallbackList->m_pages.get(pageNumber) : m_fontFallbackList->m_pageZero;
391 node = GlyphPageTreeNode::getRootChild(fontDataAt(0), pageNumber);
393 m_fontFallbackList->m_pages.set(pageNumber, node);
395 m_fontFallbackList->m_pageZero = node;
399 if (variant == NormalVariant) {
400 // Fastest loop, for the common case (normal variant).
404 GlyphData data = page->glyphDataForCharacter(c);
405 if (data.fontData && (data.fontData->platformData().orientation() == Horizontal || data.fontData->isTextOrientationFallback()))
406 return make_pair(data, page);
409 if (Character::isCJKIdeographOrSymbol(c)) {
410 if (!data.fontData->hasVerticalGlyphs()) {
411 // Use the broken ideograph font data. The broken ideograph font will use the horizontal width of glyphs
412 // to make sure you get a square (even for broken glyphs like symbols used for punctuation).
413 variant = BrokenIdeographVariant;
417 return glyphDataAndPageForNonCJKCharacterWithGlyphOrientation(c, m_fontDescription.nonCJKGlyphOrientation(), data, page, pageNumber);
420 return make_pair(data, page);
423 if (node->isSystemFallback())
427 // Proceed with the fallback list.
428 node = node->getChild(fontDataAt(node->level()), pageNumber);
430 m_fontFallbackList->m_pages.set(pageNumber, node);
432 m_fontFallbackList->m_pageZero = node;
435 if (variant != NormalVariant) {
439 GlyphData data = page->glyphDataForCharacter(c);
441 // The variantFontData function should not normally return 0.
442 // But if it does, we will just render the capital letter big.
443 RefPtr<SimpleFontData> variantFontData = data.fontData->variantFontData(m_fontDescription, variant);
444 if (!variantFontData)
445 return make_pair(data, page);
447 GlyphPageTreeNode* variantNode = GlyphPageTreeNode::getRootChild(variantFontData.get(), pageNumber);
448 GlyphPage* variantPage = variantNode->page();
450 GlyphData data = variantPage->glyphDataForCharacter(c);
452 return make_pair(data, variantPage);
455 // Do not attempt system fallback off the variantFontData. This is the very unlikely case that
456 // a font has the lowercase character but the small caps font does not have its uppercase version.
457 return make_pair(variantFontData->missingGlyphData(), page);
460 if (node->isSystemFallback())
464 // Proceed with the fallback list.
465 node = node->getChild(fontDataAt(node->level()), pageNumber);
467 m_fontFallbackList->m_pages.set(pageNumber, node);
469 m_fontFallbackList->m_pageZero = node;
474 ASSERT(node->isSystemFallback());
476 // System fallback is character-dependent. When we get here, we
477 // know that the character in question isn't in the system fallback
478 // font's glyph page. Try to lazily create it here.
480 // FIXME: Unclear if this should normalizeSpaces above 0xFFFF.
481 // Doing so changes fast/text/international/plane2-diffs.html
482 UChar32 characterToRender = c;
483 if (characterToRender <= 0xFFFF)
484 characterToRender = Character::normalizeSpaces(characterToRender);
485 const SimpleFontData* fontDataToSubstitute = fontDataAt(0)->fontDataForCharacter(characterToRender);
486 RefPtr<SimpleFontData> characterFontData = FontCache::fontCache()->platformFallbackForCharacter(m_fontDescription, characterToRender, fontDataToSubstitute);
487 if (characterFontData) {
488 if (characterFontData->platformData().orientation() == Vertical && !characterFontData->hasVerticalGlyphs() && Character::isCJKIdeographOrSymbol(c))
489 variant = BrokenIdeographVariant;
490 if (variant != NormalVariant)
491 characterFontData = characterFontData->variantFontData(m_fontDescription, variant);
493 if (characterFontData) {
494 // Got the fallback glyph and font.
495 GlyphPage* fallbackPage = GlyphPageTreeNode::getRootChild(characterFontData.get(), pageNumber)->page();
496 GlyphData data = fallbackPage && fallbackPage->fontDataForCharacter(c) ? fallbackPage->glyphDataForCharacter(c) : characterFontData->missingGlyphData();
497 // Cache it so we don't have to do system fallback again next time.
498 if (variant == NormalVariant) {
499 page->setGlyphDataForCharacter(c, data.glyph, data.fontData);
500 data.fontData->setMaxGlyphPageTreeLevel(max(data.fontData->maxGlyphPageTreeLevel(), node->level()));
501 if (!Character::isCJKIdeographOrSymbol(c) && data.fontData->platformData().orientation() != Horizontal && !data.fontData->isTextOrientationFallback())
502 return glyphDataAndPageForNonCJKCharacterWithGlyphOrientation(c, m_fontDescription.nonCJKGlyphOrientation(), data, fallbackPage, pageNumber);
504 return make_pair(data, page);
507 // Even system fallback can fail; use the missing glyph in that case.
508 // FIXME: It would be nicer to use the missing glyph from the last resort font instead.
509 GlyphData data = primaryFont()->missingGlyphData();
510 if (variant == NormalVariant) {
511 page->setGlyphDataForCharacter(c, data.glyph, data.fontData);
512 data.fontData->setMaxGlyphPageTreeLevel(max(data.fontData->maxGlyphPageTreeLevel(), node->level()));
514 return make_pair(data, page);
517 bool Font::primaryFontHasGlyphForCharacter(UChar32 character) const
519 unsigned pageNumber = (character / GlyphPage::size);
521 GlyphPageTreeNode* node = GlyphPageTreeNode::getRootChild(primaryFont(), pageNumber);
522 GlyphPage* page = node->page();
524 return page && page->fontDataForCharacter(character);
527 // FIXME: This function may not work if the emphasis mark uses a complex script, but none of the
528 // standard emphasis marks do so.
529 bool Font::getEmphasisMarkGlyphData(const AtomicString& mark, GlyphData& glyphData) const
534 UChar32 character = mark[0];
536 if (U16_IS_SURROGATE(character)) {
537 if (!U16_IS_SURROGATE_LEAD(character))
540 if (mark.length() < 2)
544 if (!U16_IS_TRAIL(low))
547 character = U16_GET_SUPPLEMENTARY(character, low);
550 glyphData = glyphDataForCharacter(character, false, EmphasisMarkVariant);
554 int Font::emphasisMarkAscent(const AtomicString& mark) const
556 FontCachePurgePreventer purgePreventer;
558 GlyphData markGlyphData;
559 if (!getEmphasisMarkGlyphData(mark, markGlyphData))
562 const SimpleFontData* markFontData = markGlyphData.fontData;
563 ASSERT(markFontData);
567 return markFontData->fontMetrics().ascent();
570 int Font::emphasisMarkDescent(const AtomicString& mark) const
572 FontCachePurgePreventer purgePreventer;
574 GlyphData markGlyphData;
575 if (!getEmphasisMarkGlyphData(mark, markGlyphData))
578 const SimpleFontData* markFontData = markGlyphData.fontData;
579 ASSERT(markFontData);
583 return markFontData->fontMetrics().descent();
586 int Font::emphasisMarkHeight(const AtomicString& mark) const
588 FontCachePurgePreventer purgePreventer;
590 GlyphData markGlyphData;
591 if (!getEmphasisMarkGlyphData(mark, markGlyphData))
594 const SimpleFontData* markFontData = markGlyphData.fontData;
595 ASSERT(markFontData);
599 return markFontData->fontMetrics().height();
602 float Font::getGlyphsAndAdvancesForSimpleText(const TextRun& run, int from, int to, GlyphBuffer& glyphBuffer, ForTextEmphasisOrNot forTextEmphasis) const
604 float initialAdvance;
606 WidthIterator it(this, run, 0, false, forTextEmphasis);
607 // FIXME: Using separate glyph buffers for the prefix and the suffix is incorrect when kerning or
608 // ligatures are enabled.
609 GlyphBuffer localGlyphBuffer;
610 it.advance(from, &localGlyphBuffer);
611 float beforeWidth = it.m_runWidthSoFar;
612 it.advance(to, &glyphBuffer);
614 if (glyphBuffer.isEmpty())
617 float afterWidth = it.m_runWidthSoFar;
620 float finalRoundingWidth = it.m_finalRoundingWidth;
621 it.advance(run.length(), &localGlyphBuffer);
622 initialAdvance = finalRoundingWidth + it.m_runWidthSoFar - afterWidth;
624 initialAdvance = beforeWidth;
628 glyphBuffer.reverse(0, glyphBuffer.size());
630 return initialAdvance;
633 void Font::drawSimpleText(GraphicsContext* context, const TextRunPaintInfo& runInfo, const FloatPoint& point) const
635 // This glyph buffer holds our glyphs+advances+font data for each glyph.
636 GlyphBuffer glyphBuffer;
638 float startX = point.x() + getGlyphsAndAdvancesForSimpleText(runInfo.run, runInfo.from, runInfo.to, glyphBuffer);
640 if (glyphBuffer.isEmpty())
643 FloatPoint startPoint(startX, point.y());
644 drawGlyphBuffer(context, runInfo, glyphBuffer, startPoint);
647 void Font::drawEmphasisMarksForSimpleText(GraphicsContext* context, const TextRunPaintInfo& runInfo, const AtomicString& mark, const FloatPoint& point) const
649 GlyphBuffer glyphBuffer;
650 float initialAdvance = getGlyphsAndAdvancesForSimpleText(runInfo.run, runInfo.from, runInfo.to, glyphBuffer, ForTextEmphasis);
652 if (glyphBuffer.isEmpty())
655 drawEmphasisMarks(context, runInfo, glyphBuffer, mark, FloatPoint(point.x() + initialAdvance, point.y()));
658 void Font::drawGlyphBuffer(GraphicsContext* context, const TextRunPaintInfo& runInfo, const GlyphBuffer& glyphBuffer, const FloatPoint& point) const
660 // Draw each contiguous run of glyphs that use the same font data.
661 const SimpleFontData* fontData = glyphBuffer.fontDataAt(0);
662 FloatPoint startPoint(point);
663 float nextX = startPoint.x() + glyphBuffer.advanceAt(0);
664 unsigned lastFrom = 0;
665 unsigned nextGlyph = 1;
666 #if ENABLE(SVG_FONTS)
667 TextRun::RenderingContext* renderingContext = runInfo.run.renderingContext();
669 while (nextGlyph < glyphBuffer.size()) {
670 const SimpleFontData* nextFontData = glyphBuffer.fontDataAt(nextGlyph);
672 if (nextFontData != fontData) {
673 #if ENABLE(SVG_FONTS)
674 if (renderingContext && fontData->isSVGFont())
675 renderingContext->drawSVGGlyphs(context, runInfo.run, fontData, glyphBuffer, lastFrom, nextGlyph - lastFrom, startPoint);
678 drawGlyphs(context, fontData, glyphBuffer, lastFrom, nextGlyph - lastFrom, startPoint, runInfo.bounds);
680 lastFrom = nextGlyph;
681 fontData = nextFontData;
682 startPoint.setX(nextX);
684 nextX += glyphBuffer.advanceAt(nextGlyph);
688 #if ENABLE(SVG_FONTS)
689 if (renderingContext && fontData->isSVGFont())
690 renderingContext->drawSVGGlyphs(context, runInfo.run, fontData, glyphBuffer, lastFrom, nextGlyph - lastFrom, startPoint);
693 drawGlyphs(context, fontData, glyphBuffer, lastFrom, nextGlyph - lastFrom, startPoint, runInfo.bounds);
696 inline static float offsetToMiddleOfGlyph(const SimpleFontData* fontData, Glyph glyph)
698 if (fontData->platformData().orientation() == Horizontal) {
699 FloatRect bounds = fontData->boundsForGlyph(glyph);
700 return bounds.x() + bounds.width() / 2;
702 // FIXME: Use glyph bounds once they make sense for vertical fonts.
703 return fontData->widthForGlyph(glyph) / 2;
706 inline static float offsetToMiddleOfAdvanceAtIndex(const GlyphBuffer& glyphBuffer, size_t i)
708 return glyphBuffer.advanceAt(i) / 2;
711 void Font::drawEmphasisMarks(GraphicsContext* context, const TextRunPaintInfo& runInfo, const GlyphBuffer& glyphBuffer, const AtomicString& mark, const FloatPoint& point) const
713 FontCachePurgePreventer purgePreventer;
715 GlyphData markGlyphData;
716 if (!getEmphasisMarkGlyphData(mark, markGlyphData))
719 const SimpleFontData* markFontData = markGlyphData.fontData;
720 ASSERT(markFontData);
724 Glyph markGlyph = markGlyphData.glyph;
725 Glyph spaceGlyph = markFontData->spaceGlyph();
727 float middleOfLastGlyph = offsetToMiddleOfAdvanceAtIndex(glyphBuffer, 0);
728 FloatPoint startPoint(point.x() + middleOfLastGlyph - offsetToMiddleOfGlyph(markFontData, markGlyph), point.y());
730 GlyphBuffer markBuffer;
731 for (unsigned i = 0; i + 1 < glyphBuffer.size(); ++i) {
732 float middleOfNextGlyph = offsetToMiddleOfAdvanceAtIndex(glyphBuffer, i + 1);
733 float advance = glyphBuffer.advanceAt(i) - middleOfLastGlyph + middleOfNextGlyph;
734 markBuffer.add(glyphBuffer.glyphAt(i) ? markGlyph : spaceGlyph, markFontData, advance);
735 middleOfLastGlyph = middleOfNextGlyph;
737 markBuffer.add(glyphBuffer.glyphAt(glyphBuffer.size() - 1) ? markGlyph : spaceGlyph, markFontData, 0);
739 drawGlyphBuffer(context, runInfo, markBuffer, startPoint);
742 float Font::floatWidthForSimpleText(const TextRun& run, HashSet<const SimpleFontData*>* fallbackFonts, GlyphOverflow* glyphOverflow) const
744 WidthIterator it(this, run, fallbackFonts, glyphOverflow);
745 GlyphBuffer glyphBuffer;
746 it.advance(run.length(), (fontDescription().typesettingFeatures() & (Kerning | Ligatures)) ? &glyphBuffer : 0);
749 glyphOverflow->top = max<int>(glyphOverflow->top, ceilf(-it.minGlyphBoundingBoxY()) - (glyphOverflow->computeBounds ? 0 : fontMetrics().ascent()));
750 glyphOverflow->bottom = max<int>(glyphOverflow->bottom, ceilf(it.maxGlyphBoundingBoxY()) - (glyphOverflow->computeBounds ? 0 : fontMetrics().descent()));
751 glyphOverflow->left = ceilf(it.firstGlyphOverflow());
752 glyphOverflow->right = ceilf(it.lastGlyphOverflow());
755 return it.m_runWidthSoFar;
758 FloatRect Font::selectionRectForSimpleText(const TextRun& run, const FloatPoint& point, int h, int from, int to) const
760 GlyphBuffer glyphBuffer;
761 WidthIterator it(this, run);
762 it.advance(from, &glyphBuffer);
763 float beforeWidth = it.m_runWidthSoFar;
764 it.advance(to, &glyphBuffer);
765 float afterWidth = it.m_runWidthSoFar;
767 // Using roundf() rather than ceilf() for the right edge as a compromise to
768 // ensure correct caret positioning.
769 // Use LayoutUnit::epsilon() to ensure that values that cannot be stored as
770 // an integer are floored to n and not n-1 due to floating point imprecision.
772 it.advance(run.length(), &glyphBuffer);
773 float totalWidth = it.m_runWidthSoFar;
774 float pixelAlignedX = floorf(point.x() + totalWidth - afterWidth + LayoutUnit::epsilon());
775 return FloatRect(pixelAlignedX, point.y(),
776 roundf(point.x() + totalWidth - beforeWidth) - pixelAlignedX, h);
779 float pixelAlignedX = floorf(point.x() + beforeWidth + LayoutUnit::epsilon());
780 return FloatRect(pixelAlignedX, point.y(),
781 roundf(point.x() + afterWidth) - pixelAlignedX, h);
784 int Font::offsetForPositionForSimpleText(const TextRun& run, float x, bool includePartialGlyphs) const
788 WidthIterator it(this, run);
789 GlyphBuffer localGlyphBuffer;
792 delta -= floatWidthForSimpleText(run);
794 offset = it.m_currentCharacter;
796 if (!it.advanceOneCharacter(w, localGlyphBuffer))
799 if (includePartialGlyphs) {
800 if (delta - w / 2 >= 0)
809 offset = it.m_currentCharacter;
811 if (!it.advanceOneCharacter(w, localGlyphBuffer))
814 if (includePartialGlyphs) {
815 if (delta + w / 2 <= 0)