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