Home | History | Annotate | Download | only in graphics
      1 /**
      2  * Copyright (C) 2003, 2006, 2010 Apple Inc. All rights reserved.
      3  * Copyright (C) 2008 Holger Hans Peter Freyther
      4  * Copyright (C) 2009 Torch Mobile, Inc.
      5  *
      6  * This library is free software; you can redistribute it and/or
      7  * modify it under the terms of the GNU Library General Public
      8  * License as published by the Free Software Foundation; either
      9  * version 2 of the License, or (at your option) any later version.
     10  *
     11  * This library is distributed in the hope that it will be useful,
     12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     14  * Library General Public License for more details.
     15  *
     16  * You should have received a copy of the GNU Library General Public License
     17  * along with this library; see the file COPYING.LIB.  If not, write to
     18  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
     19  * Boston, MA 02110-1301, USA.
     20  *
     21  */
     22 
     23 #include "config.h"
     24 #include "core/platform/graphics/Font.h"
     25 
     26 #include "core/platform/graphics/FloatRect.h"
     27 #include "core/platform/graphics/FontCache.h"
     28 #include "core/platform/graphics/FontFallbackList.h"
     29 #include "core/platform/graphics/GlyphBuffer.h"
     30 #include "core/platform/graphics/GlyphPageTreeNode.h"
     31 #include "core/platform/graphics/SimpleFontData.h"
     32 #include "core/platform/graphics/TextRun.h"
     33 #include "core/platform/graphics/WidthIterator.h"
     34 #include "wtf/MainThread.h"
     35 #include "wtf/MathExtras.h"
     36 #include "wtf/unicode/CharacterNames.h"
     37 #include "wtf/unicode/Unicode.h"
     38 
     39 using namespace WTF;
     40 using namespace Unicode;
     41 using namespace std;
     42 
     43 namespace WebCore {
     44 
     45 static inline bool isInRange(UChar32 character, UChar32 lowerBound, UChar32 upperBound)
     46 {
     47     return character >= lowerBound && character <= upperBound;
     48 }
     49 
     50 static bool shouldIgnoreRotation(UChar32 character)
     51 {
     52     if (character == 0x000A7 || character == 0x000A9 || character == 0x000AE)
     53         return true;
     54 
     55     if (character == 0x000B6 || character == 0x000BC || character == 0x000BD || character == 0x000BE)
     56         return true;
     57 
     58     if (isInRange(character, 0x002E5, 0x002EB))
     59         return true;
     60 
     61     if (isInRange(character, 0x01100, 0x011FF) || isInRange(character, 0x01401, 0x0167F) || isInRange(character, 0x01800, 0x018FF))
     62         return true;
     63 
     64     if (character == 0x02016 || character == 0x02018 || character == 0x02019 || character == 0x02020 || character == 0x02021
     65         || character == 0x2030 || character == 0x02031)
     66         return true;
     67 
     68     if (isInRange(character, 0x0203B, 0x0203D) || character == 0x02042 || character == 0x02044 || character == 0x02047
     69         || character == 0x02048 || character == 0x02049 || character == 0x2051)
     70         return true;
     71 
     72     if (isInRange(character, 0x02065, 0x02069) || isInRange(character, 0x020DD, 0x020E0)
     73         || isInRange(character, 0x020E2, 0x020E4) || isInRange(character, 0x02100, 0x02117)
     74         || isInRange(character, 0x02119, 0x02131) || isInRange(character, 0x02133, 0x0213F))
     75         return true;
     76 
     77     if (isInRange(character, 0x02145, 0x0214A) || character == 0x0214C || character == 0x0214D
     78         || isInRange(character, 0x0214F, 0x0218F))
     79         return true;
     80 
     81     if (isInRange(character, 0x02300, 0x02307) || isInRange(character, 0x0230C, 0x0231F)
     82         || isInRange(character, 0x02322, 0x0232B) || isInRange(character, 0x0237D, 0x0239A)
     83         || isInRange(character, 0x023B4, 0x023B6) || isInRange(character, 0x023BA, 0x023CF)
     84         || isInRange(character, 0x023D1, 0x023DB) || isInRange(character, 0x023E2, 0x024FF))
     85         return true;
     86 
     87     if (isInRange(character, 0x025A0, 0x02619) || isInRange(character, 0x02620, 0x02767)
     88         || isInRange(character, 0x02776, 0x02793) || isInRange(character, 0x02B12, 0x02B2F)
     89         || isInRange(character, 0x02B4D, 0x02BFF) || isInRange(character, 0x02E80, 0x03007))
     90         return true;
     91 
     92     if (character == 0x03012 || character == 0x03013 || isInRange(character, 0x03020, 0x0302F)
     93         || isInRange(character, 0x03031, 0x0309F) || isInRange(character, 0x030A1, 0x030FB)
     94         || isInRange(character, 0x030FD, 0x0A4CF))
     95         return true;
     96 
     97     if (isInRange(character, 0x0A840, 0x0A87F) || isInRange(character, 0x0A960, 0x0A97F)
     98         || isInRange(character, 0x0AC00, 0x0D7FF) || isInRange(character, 0x0E000, 0x0FAFF))
     99         return true;
    100 
    101     if (isInRange(character, 0x0FE10, 0x0FE1F) || isInRange(character, 0x0FE30, 0x0FE48)
    102         || isInRange(character, 0x0FE50, 0x0FE57) || isInRange(character, 0x0FE5F, 0x0FE62)
    103         || isInRange(character, 0x0FE67, 0x0FE6F))
    104         return true;
    105 
    106     if (isInRange(character, 0x0FF01, 0x0FF07) || isInRange(character, 0x0FF0A, 0x0FF0C)
    107         || isInRange(character, 0x0FF0E, 0x0FF19) ||isInRange (character, 0x0FF1F, 0x0FF3A))
    108         return true;
    109 
    110     if (character == 0x0FF3C || character == 0x0FF3E)
    111         return true;
    112 
    113     if (isInRange(character, 0x0FF40, 0x0FF5A) || isInRange(character, 0x0FFE0, 0x0FFE2)
    114         || isInRange(character, 0x0FFE4, 0x0FFE7) || isInRange(character, 0x0FFF0, 0x0FFF8)
    115         || character == 0x0FFFD)
    116         return true;
    117 
    118     if (isInRange(character, 0x13000, 0x1342F) || isInRange(character, 0x1B000, 0x1B0FF)
    119         || isInRange(character, 0x1D000, 0x1D1FF) || isInRange(character, 0x1D300, 0x1D37F)
    120         || isInRange(character, 0x1F000, 0x1F64F) || isInRange(character, 0x1F680, 0x1F77F))
    121         return true;
    122 
    123     if (isInRange(character, 0x20000, 0x2FFFD) || isInRange(character, 0x30000, 0x3FFFD))
    124         return true;
    125 
    126     return false;
    127 }
    128 
    129 static inline std::pair<GlyphData, GlyphPage*> glyphDataAndPageForNonCJKCharacterWithGlyphOrientation(UChar32 character, NonCJKGlyphOrientation orientation, GlyphData& data, GlyphPage* page, unsigned pageNumber)
    130 {
    131     if (orientation == NonCJKGlyphOrientationUpright || shouldIgnoreRotation(character)) {
    132         RefPtr<SimpleFontData> uprightFontData = data.fontData->uprightOrientationFontData();
    133         GlyphPageTreeNode* uprightNode = GlyphPageTreeNode::getRootChild(uprightFontData.get(), pageNumber);
    134         GlyphPage* uprightPage = uprightNode->page();
    135         if (uprightPage) {
    136             GlyphData uprightData = uprightPage->glyphDataForCharacter(character);
    137             // If the glyphs are the same, then we know we can just use the horizontal glyph rotated vertically to be upright.
    138             if (data.glyph == uprightData.glyph)
    139                 return make_pair(data, page);
    140             // The glyphs are distinct, meaning that the font has a vertical-right glyph baked into it. We can't use that
    141             // glyph, so we fall back to the upright data and use the horizontal glyph.
    142             if (uprightData.fontData)
    143                 return make_pair(uprightData, uprightPage);
    144         }
    145     } else if (orientation == NonCJKGlyphOrientationVerticalRight) {
    146         RefPtr<SimpleFontData> verticalRightFontData = data.fontData->verticalRightOrientationFontData();
    147         GlyphPageTreeNode* verticalRightNode = GlyphPageTreeNode::getRootChild(verticalRightFontData.get(), pageNumber);
    148         GlyphPage* verticalRightPage = verticalRightNode->page();
    149         if (verticalRightPage) {
    150             GlyphData verticalRightData = verticalRightPage->glyphDataForCharacter(character);
    151             // If the glyphs are distinct, we will make the assumption that the font has a vertical-right glyph baked
    152             // into it.
    153             if (data.glyph != verticalRightData.glyph)
    154                 return make_pair(data, page);
    155             // The glyphs are identical, meaning that we should just use the horizontal glyph.
    156             if (verticalRightData.fontData)
    157                 return make_pair(verticalRightData, verticalRightPage);
    158         }
    159     }
    160     return make_pair(data, page);
    161 }
    162 
    163 std::pair<GlyphData, GlyphPage*> Font::glyphDataAndPageForCharacter(UChar32 c, bool mirror, FontDataVariant variant) const
    164 {
    165     ASSERT(isMainThread());
    166 
    167     if (variant == AutoVariant) {
    168         if (m_fontDescription.smallCaps() && !primaryFont()->isSVGFont()) {
    169             UChar32 upperC = toUpper(c);
    170             if (upperC != c) {
    171                 c = upperC;
    172                 variant = SmallCapsVariant;
    173             } else
    174                 variant = NormalVariant;
    175         } else
    176             variant = NormalVariant;
    177     }
    178 
    179     if (mirror)
    180         c = mirroredChar(c);
    181 
    182     unsigned pageNumber = (c / GlyphPage::size);
    183 
    184     GlyphPageTreeNode* node = pageNumber ? m_fontFallbackList->m_pages.get(pageNumber) : m_fontFallbackList->m_pageZero;
    185     if (!node) {
    186         node = GlyphPageTreeNode::getRootChild(fontDataAt(0), pageNumber);
    187         if (pageNumber)
    188             m_fontFallbackList->m_pages.set(pageNumber, node);
    189         else
    190             m_fontFallbackList->m_pageZero = node;
    191     }
    192 
    193     GlyphPage* page = 0;
    194     if (variant == NormalVariant) {
    195         // Fastest loop, for the common case (normal variant).
    196         while (true) {
    197             page = node->page();
    198             if (page) {
    199                 GlyphData data = page->glyphDataForCharacter(c);
    200                 if (data.fontData && (data.fontData->platformData().orientation() == Horizontal || data.fontData->isTextOrientationFallback()))
    201                     return make_pair(data, page);
    202 
    203                 if (data.fontData) {
    204                     if (isCJKIdeographOrSymbol(c)) {
    205                         if (!data.fontData->hasVerticalGlyphs()) {
    206                             // Use the broken ideograph font data. The broken ideograph font will use the horizontal width of glyphs
    207                             // to make sure you get a square (even for broken glyphs like symbols used for punctuation).
    208                             variant = BrokenIdeographVariant;
    209                             break;
    210                         }
    211                     } else
    212                         return glyphDataAndPageForNonCJKCharacterWithGlyphOrientation(c, m_fontDescription.nonCJKGlyphOrientation(), data, page, pageNumber);
    213 
    214                     return make_pair(data, page);
    215                 }
    216 
    217                 if (node->isSystemFallback())
    218                     break;
    219             }
    220 
    221             // Proceed with the fallback list.
    222             node = node->getChild(fontDataAt(node->level()), pageNumber);
    223             if (pageNumber)
    224                 m_fontFallbackList->m_pages.set(pageNumber, node);
    225             else
    226                 m_fontFallbackList->m_pageZero = node;
    227         }
    228     }
    229     if (variant != NormalVariant) {
    230         while (true) {
    231             page = node->page();
    232             if (page) {
    233                 GlyphData data = page->glyphDataForCharacter(c);
    234                 if (data.fontData) {
    235                     // The variantFontData function should not normally return 0.
    236                     // But if it does, we will just render the capital letter big.
    237                     RefPtr<SimpleFontData> variantFontData = data.fontData->variantFontData(m_fontDescription, variant);
    238                     if (!variantFontData)
    239                         return make_pair(data, page);
    240 
    241                     GlyphPageTreeNode* variantNode = GlyphPageTreeNode::getRootChild(variantFontData.get(), pageNumber);
    242                     GlyphPage* variantPage = variantNode->page();
    243                     if (variantPage) {
    244                         GlyphData data = variantPage->glyphDataForCharacter(c);
    245                         if (data.fontData)
    246                             return make_pair(data, variantPage);
    247                     }
    248 
    249                     // Do not attempt system fallback off the variantFontData. This is the very unlikely case that
    250                     // a font has the lowercase character but the small caps font does not have its uppercase version.
    251                     return make_pair(variantFontData->missingGlyphData(), page);
    252                 }
    253 
    254                 if (node->isSystemFallback())
    255                     break;
    256             }
    257 
    258             // Proceed with the fallback list.
    259             node = node->getChild(fontDataAt(node->level()), pageNumber);
    260             if (pageNumber)
    261                 m_fontFallbackList->m_pages.set(pageNumber, node);
    262             else
    263                 m_fontFallbackList->m_pageZero = node;
    264         }
    265     }
    266 
    267     ASSERT(page);
    268     ASSERT(node->isSystemFallback());
    269 
    270     // System fallback is character-dependent. When we get here, we
    271     // know that the character in question isn't in the system fallback
    272     // font's glyph page. Try to lazily create it here.
    273 
    274     // FIXME: Unclear if this should normalizeSpaces above 0xFFFF.
    275     // Doing so changes fast/text/international/plane2-diffs.html
    276     UChar32 characterToRender = c;
    277     if (characterToRender <=  0xFFFF)
    278         characterToRender = Font::normalizeSpaces(characterToRender);
    279     RefPtr<SimpleFontData> characterFontData = fontCache()->getFontDataForCharacter(*this, characterToRender);
    280     if (characterFontData) {
    281         if (characterFontData->platformData().orientation() == Vertical && !characterFontData->hasVerticalGlyphs() && isCJKIdeographOrSymbol(c))
    282             variant = BrokenIdeographVariant;
    283         if (variant != NormalVariant)
    284             characterFontData = characterFontData->variantFontData(m_fontDescription, variant);
    285     }
    286     if (characterFontData) {
    287         // Got the fallback glyph and font.
    288         GlyphPage* fallbackPage = GlyphPageTreeNode::getRootChild(characterFontData.get(), pageNumber)->page();
    289         GlyphData data = fallbackPage && fallbackPage->fontDataForCharacter(c) ? fallbackPage->glyphDataForCharacter(c) : characterFontData->missingGlyphData();
    290         // Cache it so we don't have to do system fallback again next time.
    291         if (variant == NormalVariant) {
    292             page->setGlyphDataForCharacter(c, data.glyph, data.fontData);
    293             data.fontData->setMaxGlyphPageTreeLevel(max(data.fontData->maxGlyphPageTreeLevel(), node->level()));
    294             if (!isCJKIdeographOrSymbol(c) && data.fontData->platformData().orientation() != Horizontal && !data.fontData->isTextOrientationFallback())
    295                 return glyphDataAndPageForNonCJKCharacterWithGlyphOrientation(c, m_fontDescription.nonCJKGlyphOrientation(), data, fallbackPage, pageNumber);
    296         }
    297         return make_pair(data, page);
    298     }
    299 
    300     // Even system fallback can fail; use the missing glyph in that case.
    301     // FIXME: It would be nicer to use the missing glyph from the last resort font instead.
    302     GlyphData data = primaryFont()->missingGlyphData();
    303     if (variant == NormalVariant) {
    304         page->setGlyphDataForCharacter(c, data.glyph, data.fontData);
    305         data.fontData->setMaxGlyphPageTreeLevel(max(data.fontData->maxGlyphPageTreeLevel(), node->level()));
    306     }
    307     return make_pair(data, page);
    308 }
    309 
    310 bool Font::primaryFontHasGlyphForCharacter(UChar32 character) const
    311 {
    312     unsigned pageNumber = (character / GlyphPage::size);
    313 
    314     GlyphPageTreeNode* node = GlyphPageTreeNode::getRootChild(primaryFont(), pageNumber);
    315     GlyphPage* page = node->page();
    316 
    317     return page && page->fontDataForCharacter(character);
    318 }
    319 
    320 // FIXME: This function may not work if the emphasis mark uses a complex script, but none of the
    321 // standard emphasis marks do so.
    322 bool Font::getEmphasisMarkGlyphData(const AtomicString& mark, GlyphData& glyphData) const
    323 {
    324     if (mark.isEmpty())
    325         return false;
    326 
    327     UChar32 character = mark[0];
    328 
    329     if (U16_IS_SURROGATE(character)) {
    330         if (!U16_IS_SURROGATE_LEAD(character))
    331             return false;
    332 
    333         if (mark.length() < 2)
    334             return false;
    335 
    336         UChar low = mark[1];
    337         if (!U16_IS_TRAIL(low))
    338             return false;
    339 
    340         character = U16_GET_SUPPLEMENTARY(character, low);
    341     }
    342 
    343     glyphData = glyphDataForCharacter(character, false, EmphasisMarkVariant);
    344     return true;
    345 }
    346 
    347 int Font::emphasisMarkAscent(const AtomicString& mark) const
    348 {
    349     FontCachePurgePreventer purgePreventer;
    350 
    351     GlyphData markGlyphData;
    352     if (!getEmphasisMarkGlyphData(mark, markGlyphData))
    353         return 0;
    354 
    355     const SimpleFontData* markFontData = markGlyphData.fontData;
    356     ASSERT(markFontData);
    357     if (!markFontData)
    358         return 0;
    359 
    360     return markFontData->fontMetrics().ascent();
    361 }
    362 
    363 int Font::emphasisMarkDescent(const AtomicString& mark) const
    364 {
    365     FontCachePurgePreventer purgePreventer;
    366 
    367     GlyphData markGlyphData;
    368     if (!getEmphasisMarkGlyphData(mark, markGlyphData))
    369         return 0;
    370 
    371     const SimpleFontData* markFontData = markGlyphData.fontData;
    372     ASSERT(markFontData);
    373     if (!markFontData)
    374         return 0;
    375 
    376     return markFontData->fontMetrics().descent();
    377 }
    378 
    379 int Font::emphasisMarkHeight(const AtomicString& mark) const
    380 {
    381     FontCachePurgePreventer purgePreventer;
    382 
    383     GlyphData markGlyphData;
    384     if (!getEmphasisMarkGlyphData(mark, markGlyphData))
    385         return 0;
    386 
    387     const SimpleFontData* markFontData = markGlyphData.fontData;
    388     ASSERT(markFontData);
    389     if (!markFontData)
    390         return 0;
    391 
    392     return markFontData->fontMetrics().height();
    393 }
    394 
    395 float Font::getGlyphsAndAdvancesForSimpleText(const TextRun& run, int from, int to, GlyphBuffer& glyphBuffer, ForTextEmphasisOrNot forTextEmphasis) const
    396 {
    397     float initialAdvance;
    398 
    399     WidthIterator it(this, run, 0, false, forTextEmphasis);
    400     // FIXME: Using separate glyph buffers for the prefix and the suffix is incorrect when kerning or
    401     // ligatures are enabled.
    402     GlyphBuffer localGlyphBuffer;
    403     it.advance(from, &localGlyphBuffer);
    404     float beforeWidth = it.m_runWidthSoFar;
    405     it.advance(to, &glyphBuffer);
    406 
    407     if (glyphBuffer.isEmpty())
    408         return 0;
    409 
    410     float afterWidth = it.m_runWidthSoFar;
    411 
    412     if (run.rtl()) {
    413         float finalRoundingWidth = it.m_finalRoundingWidth;
    414         it.advance(run.length(), &localGlyphBuffer);
    415         initialAdvance = finalRoundingWidth + it.m_runWidthSoFar - afterWidth;
    416     } else
    417         initialAdvance = beforeWidth;
    418 
    419     if (run.rtl())
    420         glyphBuffer.reverse(0, glyphBuffer.size());
    421 
    422     return initialAdvance;
    423 }
    424 
    425 void Font::drawSimpleText(GraphicsContext* context, const TextRunPaintInfo& runInfo, const FloatPoint& point) const
    426 {
    427     // This glyph buffer holds our glyphs+advances+font data for each glyph.
    428     GlyphBuffer glyphBuffer;
    429 
    430     float startX = point.x() + getGlyphsAndAdvancesForSimpleText(runInfo.run, runInfo.from, runInfo.to, glyphBuffer);
    431 
    432     if (glyphBuffer.isEmpty())
    433         return;
    434 
    435     FloatPoint startPoint(startX, point.y());
    436     drawGlyphBuffer(context, runInfo, glyphBuffer, startPoint);
    437 }
    438 
    439 void Font::drawEmphasisMarksForSimpleText(GraphicsContext* context, const TextRunPaintInfo& runInfo, const AtomicString& mark, const FloatPoint& point) const
    440 {
    441     GlyphBuffer glyphBuffer;
    442     float initialAdvance = getGlyphsAndAdvancesForSimpleText(runInfo.run, runInfo.from, runInfo.to, glyphBuffer, ForTextEmphasis);
    443 
    444     if (glyphBuffer.isEmpty())
    445         return;
    446 
    447     drawEmphasisMarks(context, runInfo, glyphBuffer, mark, FloatPoint(point.x() + initialAdvance, point.y()));
    448 }
    449 
    450 void Font::drawGlyphBuffer(GraphicsContext* context, const TextRunPaintInfo& runInfo, const GlyphBuffer& glyphBuffer, const FloatPoint& point) const
    451 {
    452     // Draw each contiguous run of glyphs that use the same font data.
    453     const SimpleFontData* fontData = glyphBuffer.fontDataAt(0);
    454     FloatPoint startPoint(point);
    455     float nextX = startPoint.x() + glyphBuffer.advanceAt(0);
    456     int lastFrom = 0;
    457     int nextGlyph = 1;
    458 #if ENABLE(SVG_FONTS)
    459     TextRun::RenderingContext* renderingContext = runInfo.run.renderingContext();
    460 #endif
    461     while (nextGlyph < glyphBuffer.size()) {
    462         const SimpleFontData* nextFontData = glyphBuffer.fontDataAt(nextGlyph);
    463 
    464         if (nextFontData != fontData) {
    465 #if ENABLE(SVG_FONTS)
    466             if (renderingContext && fontData->isSVGFont())
    467                 renderingContext->drawSVGGlyphs(context, runInfo.run, fontData, glyphBuffer, lastFrom, nextGlyph - lastFrom, startPoint);
    468             else
    469 #endif
    470                 drawGlyphs(context, fontData, glyphBuffer, lastFrom, nextGlyph - lastFrom, startPoint, runInfo.bounds);
    471 
    472             lastFrom = nextGlyph;
    473             fontData = nextFontData;
    474             startPoint.setX(nextX);
    475         }
    476         nextX += glyphBuffer.advanceAt(nextGlyph);
    477         nextGlyph++;
    478     }
    479 
    480 #if ENABLE(SVG_FONTS)
    481     if (renderingContext && fontData->isSVGFont())
    482         renderingContext->drawSVGGlyphs(context, runInfo.run, fontData, glyphBuffer, lastFrom, nextGlyph - lastFrom, startPoint);
    483     else
    484 #endif
    485         drawGlyphs(context, fontData, glyphBuffer, lastFrom, nextGlyph - lastFrom, startPoint, runInfo.bounds);
    486 }
    487 
    488 inline static float offsetToMiddleOfGlyph(const SimpleFontData* fontData, Glyph glyph)
    489 {
    490     if (fontData->platformData().orientation() == Horizontal) {
    491         FloatRect bounds = fontData->boundsForGlyph(glyph);
    492         return bounds.x() + bounds.width() / 2;
    493     }
    494     // FIXME: Use glyph bounds once they make sense for vertical fonts.
    495     return fontData->widthForGlyph(glyph) / 2;
    496 }
    497 
    498 inline static float offsetToMiddleOfGlyphAtIndex(const GlyphBuffer& glyphBuffer, size_t i)
    499 {
    500     return offsetToMiddleOfGlyph(glyphBuffer.fontDataAt(i), glyphBuffer.glyphAt(i));
    501 }
    502 
    503 void Font::drawEmphasisMarks(GraphicsContext* context, const TextRunPaintInfo& runInfo, const GlyphBuffer& glyphBuffer, const AtomicString& mark, const FloatPoint& point) const
    504 {
    505     FontCachePurgePreventer purgePreventer;
    506 
    507     GlyphData markGlyphData;
    508     if (!getEmphasisMarkGlyphData(mark, markGlyphData))
    509         return;
    510 
    511     const SimpleFontData* markFontData = markGlyphData.fontData;
    512     ASSERT(markFontData);
    513     if (!markFontData)
    514         return;
    515 
    516     Glyph markGlyph = markGlyphData.glyph;
    517     Glyph spaceGlyph = markFontData->spaceGlyph();
    518 
    519     float middleOfLastGlyph = offsetToMiddleOfGlyphAtIndex(glyphBuffer, 0);
    520     FloatPoint startPoint(point.x() + middleOfLastGlyph - offsetToMiddleOfGlyph(markFontData, markGlyph), point.y());
    521 
    522     GlyphBuffer markBuffer;
    523     for (int i = 0; i + 1 < glyphBuffer.size(); ++i) {
    524         float middleOfNextGlyph = offsetToMiddleOfGlyphAtIndex(glyphBuffer, i + 1);
    525         float advance = glyphBuffer.advanceAt(i) - middleOfLastGlyph + middleOfNextGlyph;
    526         markBuffer.add(glyphBuffer.glyphAt(i) ? markGlyph : spaceGlyph, markFontData, advance);
    527         middleOfLastGlyph = middleOfNextGlyph;
    528     }
    529     markBuffer.add(glyphBuffer.glyphAt(glyphBuffer.size() - 1) ? markGlyph : spaceGlyph, markFontData, 0);
    530 
    531     drawGlyphBuffer(context, runInfo, markBuffer, startPoint);
    532 }
    533 
    534 float Font::floatWidthForSimpleText(const TextRun& run, HashSet<const SimpleFontData*>* fallbackFonts, GlyphOverflow* glyphOverflow) const
    535 {
    536     WidthIterator it(this, run, fallbackFonts, glyphOverflow);
    537     GlyphBuffer glyphBuffer;
    538     it.advance(run.length(), (typesettingFeatures() & (Kerning | Ligatures)) ? &glyphBuffer : 0);
    539 
    540     if (glyphOverflow) {
    541         glyphOverflow->top = max<int>(glyphOverflow->top, ceilf(-it.minGlyphBoundingBoxY()) - (glyphOverflow->computeBounds ? 0 : fontMetrics().ascent()));
    542         glyphOverflow->bottom = max<int>(glyphOverflow->bottom, ceilf(it.maxGlyphBoundingBoxY()) - (glyphOverflow->computeBounds ? 0 : fontMetrics().descent()));
    543         glyphOverflow->left = ceilf(it.firstGlyphOverflow());
    544         glyphOverflow->right = ceilf(it.lastGlyphOverflow());
    545     }
    546 
    547     return it.m_runWidthSoFar;
    548 }
    549 
    550 FloatRect Font::selectionRectForSimpleText(const TextRun& run, const FloatPoint& point, int h, int from, int to) const
    551 {
    552     GlyphBuffer glyphBuffer;
    553     WidthIterator it(this, run);
    554     it.advance(from, &glyphBuffer);
    555     float beforeWidth = it.m_runWidthSoFar;
    556     it.advance(to, &glyphBuffer);
    557     float afterWidth = it.m_runWidthSoFar;
    558 
    559     // Using roundf() rather than ceilf() for the right edge as a compromise to ensure correct caret positioning.
    560     if (run.rtl()) {
    561         it.advance(run.length(), &glyphBuffer);
    562         float totalWidth = it.m_runWidthSoFar;
    563         return FloatRect(floorf(point.x() + totalWidth - afterWidth), point.y(), roundf(point.x() + totalWidth - beforeWidth) - floorf(point.x() + totalWidth - afterWidth), h);
    564     }
    565 
    566     return FloatRect(floorf(point.x() + beforeWidth), point.y(), roundf(point.x() + afterWidth) - floorf(point.x() + beforeWidth), h);
    567 }
    568 
    569 int Font::offsetForPositionForSimpleText(const TextRun& run, float x, bool includePartialGlyphs) const
    570 {
    571     float delta = x;
    572 
    573     WidthIterator it(this, run);
    574     GlyphBuffer localGlyphBuffer;
    575     unsigned offset;
    576     if (run.rtl()) {
    577         delta -= floatWidthForSimpleText(run);
    578         while (1) {
    579             offset = it.m_currentCharacter;
    580             float w;
    581             if (!it.advanceOneCharacter(w, localGlyphBuffer))
    582                 break;
    583             delta += w;
    584             if (includePartialGlyphs) {
    585                 if (delta - w / 2 >= 0)
    586                     break;
    587             } else {
    588                 if (delta >= 0)
    589                     break;
    590             }
    591         }
    592     } else {
    593         while (1) {
    594             offset = it.m_currentCharacter;
    595             float w;
    596             if (!it.advanceOneCharacter(w, localGlyphBuffer))
    597                 break;
    598             delta -= w;
    599             if (includePartialGlyphs) {
    600                 if (delta + w / 2 <= 0)
    601                     break;
    602             } else {
    603                 if (delta <= 0)
    604                     break;
    605             }
    606         }
    607     }
    608 
    609     return offset;
    610 }
    611 
    612 }
    613