FontFastPath.cpp revision 81bc750723a18f21cd17d1b173cd2a4dda9cea6e
1635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project/** 2f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch * Copyright (C) 2003, 2006, 2010 Apple Inc. All rights reserved. 3635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * Copyright (C) 2008 Holger Hans Peter Freyther 40bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch * Copyright (C) 2009 Torch Mobile, Inc. 5635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * 6635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * This library is free software; you can redistribute it and/or 7635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * modify it under the terms of the GNU Library General Public 8635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * License as published by the Free Software Foundation; either 9635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * version 2 of the License, or (at your option) any later version. 10635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * 11635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * This library is distributed in the hope that it will be useful, 12635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * but WITHOUT ANY WARRANTY; without even the implied warranty of 13635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * Library General Public License for more details. 15635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * 16635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * You should have received a copy of the GNU Library General Public License 17635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * along with this library; see the file COPYING.LIB. If not, write to 18635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 19635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * Boston, MA 02110-1301, USA. 20635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * 21635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project */ 22635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 23635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#include "config.h" 24635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#include "Font.h" 25635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 26dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block#include "FloatRect.h" 27635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#include "FontCache.h" 280bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#include "FontFallbackList.h" 29635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#include "GlyphBuffer.h" 30635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#include "GlyphPageTreeNode.h" 31635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#include "SimpleFontData.h" 32ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch#include "TextRun.h" 33635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#include "WidthIterator.h" 34635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#include <wtf/MathExtras.h> 352fc2651226baac27029e38c9d6ef883fa32084dbSteve Block#include <wtf/unicode/CharacterNames.h> 36dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block#include <wtf/unicode/Unicode.h> 37635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 38635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectusing namespace WTF; 39635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectusing namespace Unicode; 40635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 41635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectnamespace WebCore { 42635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 43f05b935882198ccf7d81675736e3aeb089c5113aBen MurdochGlyphData Font::glyphDataForCharacter(UChar32 c, bool mirror, FontDataVariant variant) const 44635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{ 455f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian ASSERT(isMainThread()); 465f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian 47f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if (variant == AutoVariant) { 48f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if (m_fontDescription.smallCaps()) { 49f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch UChar32 upperC = toUpper(c); 50f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if (upperC != c) { 51f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch c = upperC; 52f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch variant = SmallCapsVariant; 53f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch } else 54f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch variant = NormalVariant; 55f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch } else 56f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch variant = NormalVariant; 57635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project } 58635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 59635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (mirror) 60635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project c = mirroredChar(c); 61635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 62635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project unsigned pageNumber = (c / GlyphPage::size); 63635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 640bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch GlyphPageTreeNode* node = pageNumber ? m_fontList->m_pages.get(pageNumber) : m_fontList->m_pageZero; 65635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (!node) { 66635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project node = GlyphPageTreeNode::getRootChild(fontDataAt(0), pageNumber); 67635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (pageNumber) 680bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch m_fontList->m_pages.set(pageNumber, node); 69635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project else 700bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch m_fontList->m_pageZero = node; 71635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project } 72635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 73635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project GlyphPage* page; 74f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if (variant == NormalVariant) { 75f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch // Fastest loop, for the common case (normal variant). 76635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project while (true) { 77635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project page = node->page(); 78635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (page) { 795f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian GlyphData data = page->glyphDataForCharacter(c); 806b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner if (data.fontData) { 81f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if (data.fontData->platformData().orientation() == Vertical && data.fontData->orientation() == Horizontal && Font::isCJKIdeographOrSymbol(c)) { 826b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner const SimpleFontData* ideographFontData = data.fontData->brokenIdeographFontData(); 836b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner GlyphPageTreeNode* ideographNode = GlyphPageTreeNode::getRootChild(ideographFontData, pageNumber); 846b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner const GlyphPage* ideographPage = ideographNode->page(); 856b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner if (ideographPage) { 866b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner GlyphData data = ideographPage->glyphDataForCharacter(c); 876b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner if (data.fontData) 886b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner return data; 896b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner } 906b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner 916b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner // Shouldn't be possible to even reach this point. 926b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner ASSERT_NOT_REACHED(); 936b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner } 94635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project return data; 956b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner } 966b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner 97635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (node->isSystemFallback()) 98635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project break; 99635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project } 100635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 101635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // Proceed with the fallback list. 102635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project node = node->getChild(fontDataAt(node->level()), pageNumber); 103635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (pageNumber) 1040bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch m_fontList->m_pages.set(pageNumber, node); 105635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project else 1060bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch m_fontList->m_pageZero = node; 107635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project } 108635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project } else { 109635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project while (true) { 110635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project page = node->page(); 111635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (page) { 1125f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian GlyphData data = page->glyphDataForCharacter(c); 113635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (data.fontData) { 114f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch // The variantFontData function should not normally return 0. 115635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // But if it does, we will just render the capital letter big. 116f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch const SimpleFontData* variantFontData = data.fontData->variantFontData(m_fontDescription, variant); 117f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if (!variantFontData) 118635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project return data; 119635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 120f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch GlyphPageTreeNode* variantNode = GlyphPageTreeNode::getRootChild(variantFontData, pageNumber); 121f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch const GlyphPage* variantPage = variantNode->page(); 122f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if (variantPage) { 123f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch GlyphData data = variantPage->glyphDataForCharacter(c); 124635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (data.fontData) 125635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project return data; 126635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project } 127635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 128f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch // Do not attempt system fallback off the variantFontData. This is the very unlikely case that 129635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // a font has the lowercase character but the small caps font does not have its uppercase version. 130f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch return variantFontData->missingGlyphData(); 131635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project } 132635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 133635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (node->isSystemFallback()) 134635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project break; 135635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project } 136635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 137635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // Proceed with the fallback list. 138635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project node = node->getChild(fontDataAt(node->level()), pageNumber); 139635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (pageNumber) 1400bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch m_fontList->m_pages.set(pageNumber, node); 141635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project else 1420bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch m_fontList->m_pageZero = node; 143635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project } 144635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project } 145635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 146635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project ASSERT(page); 147635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project ASSERT(node->isSystemFallback()); 148635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 149635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // System fallback is character-dependent. When we get here, we 150635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // know that the character in question isn't in the system fallback 151635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // font's glyph page. Try to lazily create it here. 152635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project UChar codeUnits[2]; 153635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project int codeUnitsLength; 154635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (c <= 0xFFFF) { 155d0825bca7fe65beaee391d30da42e937db621564Steve Block codeUnits[0] = Font::normalizeSpaces(c); 156635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project codeUnitsLength = 1; 157635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project } else { 158635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project codeUnits[0] = U16_LEAD(c); 159635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project codeUnits[1] = U16_TRAIL(c); 160635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project codeUnitsLength = 2; 161635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project } 162635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project const SimpleFontData* characterFontData = fontCache()->getFontDataForCharacters(*this, codeUnits, codeUnitsLength); 163f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if (variant != NormalVariant && characterFontData) 164f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch characterFontData = characterFontData->variantFontData(m_fontDescription, variant); 165635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (characterFontData) { 166635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // Got the fallback glyph and font. 167635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project GlyphPage* fallbackPage = GlyphPageTreeNode::getRootChild(characterFontData, pageNumber)->page(); 1685f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian GlyphData data = fallbackPage && fallbackPage->fontDataForCharacter(c) ? fallbackPage->glyphDataForCharacter(c) : characterFontData->missingGlyphData(); 169635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // Cache it so we don't have to do system fallback again next time. 170f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if (variant == NormalVariant) { 171d0825bca7fe65beaee391d30da42e937db621564Steve Block#if OS(WINCE) 1720bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch // missingGlyphData returns a null character, which is not suitable for GDI to display. 1730bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch // Also, sometimes we cannot map a font for the character on WINCE, but GDI can still 1740bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch // display the character, probably because the font package is not installed correctly. 1750bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch // So we just always set the glyph to be same as the character, and let GDI solve it. 1760bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch page->setGlyphDataForCharacter(c, c, characterFontData); 1770bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return page->glyphDataForCharacter(c); 1780bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#else 179635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project page->setGlyphDataForCharacter(c, data.glyph, data.fontData); 1800bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#endif 1810bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch } 182635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project return data; 183635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project } 184635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 185635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // Even system fallback can fail; use the missing glyph in that case. 186635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // FIXME: It would be nicer to use the missing glyph from the last resort font instead. 1875f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian GlyphData data = primaryFont()->missingGlyphData(); 188f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if (variant == NormalVariant) { 189d0825bca7fe65beaee391d30da42e937db621564Steve Block#if OS(WINCE) 1900bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch // See comment about WINCE GDI handling near setGlyphDataForCharacter above. 1910bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch page->setGlyphDataForCharacter(c, c, data.fontData); 1920bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return page->glyphDataForCharacter(c); 1930bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#else 194635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project page->setGlyphDataForCharacter(c, data.glyph, data.fontData); 1950bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#endif 1960bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch } 197635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project return data; 198635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project} 199635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 200cad810f21b803229eb11403f9209855525a25d57Steve Blockbool Font::primaryFontHasGlyphForCharacter(UChar32 character) const 201cad810f21b803229eb11403f9209855525a25d57Steve Block{ 202cad810f21b803229eb11403f9209855525a25d57Steve Block unsigned pageNumber = (character / GlyphPage::size); 203cad810f21b803229eb11403f9209855525a25d57Steve Block 204cad810f21b803229eb11403f9209855525a25d57Steve Block GlyphPageTreeNode* node = GlyphPageTreeNode::getRootChild(primaryFont(), pageNumber); 205cad810f21b803229eb11403f9209855525a25d57Steve Block GlyphPage* page = node->page(); 206cad810f21b803229eb11403f9209855525a25d57Steve Block 207cad810f21b803229eb11403f9209855525a25d57Steve Block return page && page->fontDataForCharacter(character); 208cad810f21b803229eb11403f9209855525a25d57Steve Block} 209cad810f21b803229eb11403f9209855525a25d57Steve Block 210f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch// FIXME: This function may not work if the emphasis mark uses a complex script, but none of the 211f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch// standard emphasis marks do so. 212f05b935882198ccf7d81675736e3aeb089c5113aBen Murdochbool Font::getEmphasisMarkGlyphData(const AtomicString& mark, GlyphData& glyphData) const 213635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{ 214f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if (mark.isEmpty()) 215f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch return false; 216f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 217f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch#if ENABLE(SVG_FONTS) 218f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch // FIXME: Implement for SVG fonts. 219f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if (primaryFont()->isSVGFont()) 220f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch return false; 221f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch#endif 222f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 223f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch UChar32 character = mark[0]; 224f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 225f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if (U16_IS_SURROGATE(character)) { 226f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if (!U16_IS_SURROGATE_LEAD(character)) 227f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch return false; 228f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 229f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if (mark.length() < 2) 230f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch return false; 231f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 232f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch UChar low = mark[1]; 233f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if (!U16_IS_TRAIL(low)) 234f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch return false; 235f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 236f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch character = U16_GET_SUPPLEMENTARY(character, low); 237f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch } 238f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 239f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch glyphData = glyphDataForCharacter(character, false, EmphasisMarkVariant); 240f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch return true; 241f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch} 242f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 243f05b935882198ccf7d81675736e3aeb089c5113aBen Murdochint Font::emphasisMarkAscent(const AtomicString& mark) const 244f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch{ 245f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch GlyphData markGlyphData; 246f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if (!getEmphasisMarkGlyphData(mark, markGlyphData)) 247f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch return 0; 248f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 249f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch const SimpleFontData* markFontData = markGlyphData.fontData; 250f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch ASSERT(markFontData); 251f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if (!markFontData) 252f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch return 0; 253f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 2542fc2651226baac27029e38c9d6ef883fa32084dbSteve Block return markFontData->fontMetrics().ascent(); 255f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch} 256635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 257f05b935882198ccf7d81675736e3aeb089c5113aBen Murdochint Font::emphasisMarkDescent(const AtomicString& mark) const 258f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch{ 259f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch GlyphData markGlyphData; 260f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if (!getEmphasisMarkGlyphData(mark, markGlyphData)) 261f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch return 0; 262f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 263f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch const SimpleFontData* markFontData = markGlyphData.fontData; 264f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch ASSERT(markFontData); 265f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if (!markFontData) 266f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch return 0; 267f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 2682fc2651226baac27029e38c9d6ef883fa32084dbSteve Block return markFontData->fontMetrics().descent(); 269f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch} 270f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 271f05b935882198ccf7d81675736e3aeb089c5113aBen Murdochint Font::emphasisMarkHeight(const AtomicString& mark) const 272f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch{ 273f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch GlyphData markGlyphData; 274f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if (!getEmphasisMarkGlyphData(mark, markGlyphData)) 275f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch return 0; 276f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 277f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch const SimpleFontData* markFontData = markGlyphData.fontData; 278f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch ASSERT(markFontData); 279f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if (!markFontData) 280f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch return 0; 281f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 2822fc2651226baac27029e38c9d6ef883fa32084dbSteve Block return markFontData->fontMetrics().height(); 283f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch} 284f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 285f05b935882198ccf7d81675736e3aeb089c5113aBen Murdochfloat Font::getGlyphsAndAdvancesForSimpleText(const TextRun& run, int from, int to, GlyphBuffer& glyphBuffer, ForTextEmphasisOrNot forTextEmphasis) const 286f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch{ 287f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch float initialAdvance; 288f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 289f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch WidthIterator it(this, run, 0, false, forTextEmphasis); 290635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project it.advance(from); 291635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project float beforeWidth = it.m_runWidthSoFar; 292635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project it.advance(to, &glyphBuffer); 293f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 294635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (glyphBuffer.isEmpty()) 295f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch return 0; 296f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 297635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project float afterWidth = it.m_runWidthSoFar; 298635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 299635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (run.rtl()) { 300635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project it.advance(run.length()); 30181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch initialAdvance = it.m_runWidthSoFar - afterWidth; 302635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project } else 303f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch initialAdvance = beforeWidth; 304635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 305f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if (run.rtl()) { 306635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project for (int i = 0, end = glyphBuffer.size() - 1; i < glyphBuffer.size() / 2; ++i, --end) 307635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project glyphBuffer.swap(i, end); 308f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch } 309f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 310f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch return initialAdvance; 311f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch} 312f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 313f05b935882198ccf7d81675736e3aeb089c5113aBen Murdochvoid Font::drawSimpleText(GraphicsContext* context, const TextRun& run, const FloatPoint& point, int from, int to) const 314f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch{ 315f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch // This glyph buffer holds our glyphs+advances+font data for each glyph. 316f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch GlyphBuffer glyphBuffer; 317f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 318f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch float startX = point.x() + getGlyphsAndAdvancesForSimpleText(run, from, to, glyphBuffer); 319f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 320f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if (glyphBuffer.isEmpty()) 321f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch return; 322635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 323635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project FloatPoint startPoint(startX, point.y()); 324f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch drawGlyphBuffer(context, glyphBuffer, startPoint); 325f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch} 326f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 327f05b935882198ccf7d81675736e3aeb089c5113aBen Murdochvoid Font::drawEmphasisMarksForSimpleText(GraphicsContext* context, const TextRun& run, const AtomicString& mark, const FloatPoint& point, int from, int to) const 328f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch{ 329f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch GlyphBuffer glyphBuffer; 330f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch float initialAdvance = getGlyphsAndAdvancesForSimpleText(run, from, to, glyphBuffer, ForTextEmphasis); 331f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 332f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if (glyphBuffer.isEmpty()) 333f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch return; 334f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 335f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch drawEmphasisMarks(context, glyphBuffer, mark, FloatPoint(point.x() + initialAdvance, point.y())); 336635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project} 337635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 338f05b935882198ccf7d81675736e3aeb089c5113aBen Murdochvoid Font::drawGlyphBuffer(GraphicsContext* context, const GlyphBuffer& glyphBuffer, const FloatPoint& point) const 339635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{ 340635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // Draw each contiguous run of glyphs that use the same font data. 341635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project const SimpleFontData* fontData = glyphBuffer.fontDataAt(0); 342635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project FloatSize offset = glyphBuffer.offsetAt(0); 343635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project FloatPoint startPoint(point); 344635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project float nextX = startPoint.x(); 345635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project int lastFrom = 0; 346635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project int nextGlyph = 0; 347635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project while (nextGlyph < glyphBuffer.size()) { 348635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project const SimpleFontData* nextFontData = glyphBuffer.fontDataAt(nextGlyph); 349635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project FloatSize nextOffset = glyphBuffer.offsetAt(nextGlyph); 350635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (nextFontData != fontData || nextOffset != offset) { 351635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project drawGlyphs(context, fontData, glyphBuffer, lastFrom, nextGlyph - lastFrom, startPoint); 352635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 353635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project lastFrom = nextGlyph; 354635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project fontData = nextFontData; 355635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project offset = nextOffset; 356635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project startPoint.setX(nextX); 357635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project } 358635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project nextX += glyphBuffer.advanceAt(nextGlyph); 359635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project nextGlyph++; 360635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project } 361635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 362635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project drawGlyphs(context, fontData, glyphBuffer, lastFrom, nextGlyph - lastFrom, startPoint); 363635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project} 364635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 365f05b935882198ccf7d81675736e3aeb089c5113aBen Murdochinline static float offsetToMiddleOfGlyph(const SimpleFontData* fontData, Glyph glyph) 366f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch{ 367f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if (fontData->orientation() == Horizontal) { 368f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch FloatRect bounds = fontData->boundsForGlyph(glyph); 369f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch return bounds.x() + bounds.width() / 2; 370f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch } 371f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch // FIXME: Use glyph bounds once they make sense for vertical fonts. 372f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch return fontData->widthForGlyph(glyph) / 2; 373f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch} 374f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 375f05b935882198ccf7d81675736e3aeb089c5113aBen Murdochinline static float offsetToMiddleOfGlyphAtIndex(const GlyphBuffer& glyphBuffer, size_t i) 376f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch{ 377f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch return offsetToMiddleOfGlyph(glyphBuffer.fontDataAt(i), glyphBuffer.glyphAt(i)); 378f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch} 379f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 380f05b935882198ccf7d81675736e3aeb089c5113aBen Murdochvoid Font::drawEmphasisMarks(GraphicsContext* context, const GlyphBuffer& glyphBuffer, const AtomicString& mark, const FloatPoint& point) const 381f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch{ 382f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch GlyphData markGlyphData; 383f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if (!getEmphasisMarkGlyphData(mark, markGlyphData)) 384f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch return; 385f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 386f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch const SimpleFontData* markFontData = markGlyphData.fontData; 387f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch ASSERT(markFontData); 388f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if (!markFontData) 389f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch return; 390f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 391f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch Glyph markGlyph = markGlyphData.glyph; 392f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch Glyph spaceGlyph = markFontData->spaceGlyph(); 393f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 394f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch float middleOfLastGlyph = offsetToMiddleOfGlyphAtIndex(glyphBuffer, 0); 395f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch FloatPoint startPoint(point.x() + middleOfLastGlyph - offsetToMiddleOfGlyph(markFontData, markGlyph), point.y()); 396f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 397f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch GlyphBuffer markBuffer; 398f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch for (int i = 0; i + 1 < glyphBuffer.size(); ++i) { 399f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch float middleOfNextGlyph = offsetToMiddleOfGlyphAtIndex(glyphBuffer, i + 1); 400f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch float advance = glyphBuffer.advanceAt(i) - middleOfLastGlyph + middleOfNextGlyph; 401f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch markBuffer.add(glyphBuffer.glyphAt(i) ? markGlyph : spaceGlyph, markFontData, advance); 402f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch middleOfLastGlyph = middleOfNextGlyph; 403f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch } 404f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch markBuffer.add(glyphBuffer.glyphAt(glyphBuffer.size() - 1) ? markGlyph : spaceGlyph, markFontData, 0); 405f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 406f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch drawGlyphBuffer(context, markBuffer, startPoint); 407f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch} 408f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 40921939df44de1705786c545cd1bf519d47250322dBen Murdochfloat Font::floatWidthForSimpleText(const TextRun& run, GlyphBuffer* glyphBuffer, HashSet<const SimpleFontData*>* fallbackFonts, GlyphOverflow* glyphOverflow) const 410635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{ 41121939df44de1705786c545cd1bf519d47250322dBen Murdoch WidthIterator it(this, run, fallbackFonts, glyphOverflow); 412635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project it.advance(run.length(), glyphBuffer); 41321939df44de1705786c545cd1bf519d47250322dBen Murdoch 41421939df44de1705786c545cd1bf519d47250322dBen Murdoch if (glyphOverflow) { 4152fc2651226baac27029e38c9d6ef883fa32084dbSteve Block glyphOverflow->top = max<int>(glyphOverflow->top, ceilf(-it.minGlyphBoundingBoxY()) - fontMetrics().ascent()); 4162fc2651226baac27029e38c9d6ef883fa32084dbSteve Block glyphOverflow->bottom = max<int>(glyphOverflow->bottom, ceilf(it.maxGlyphBoundingBoxY()) - fontMetrics().descent()); 41721939df44de1705786c545cd1bf519d47250322dBen Murdoch glyphOverflow->left = ceilf(it.firstGlyphOverflow()); 41821939df44de1705786c545cd1bf519d47250322dBen Murdoch glyphOverflow->right = ceilf(it.lastGlyphOverflow()); 41921939df44de1705786c545cd1bf519d47250322dBen Murdoch } 42021939df44de1705786c545cd1bf519d47250322dBen Murdoch 421635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project return it.m_runWidthSoFar; 422635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project} 423635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 42406ea8e899e48f1f2f396b70e63fae369f2f23232Kristian MonsenFloatRect Font::selectionRectForSimpleText(const TextRun& run, const FloatPoint& point, int h, int from, int to) const 425635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{ 426635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project WidthIterator it(this, run); 427635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project it.advance(from); 428635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project float beforeWidth = it.m_runWidthSoFar; 429635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project it.advance(to); 430635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project float afterWidth = it.m_runWidthSoFar; 431635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 43206ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen // Using roundf() rather than ceilf() for the right edge as a compromise to ensure correct caret positioning. 433635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (run.rtl()) { 434635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project it.advance(run.length()); 435635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project float totalWidth = it.m_runWidthSoFar; 436635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project return FloatRect(point.x() + floorf(totalWidth - afterWidth), point.y(), roundf(totalWidth - beforeWidth) - floorf(totalWidth - afterWidth), h); 437635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project } 43806ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen 43906ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen return FloatRect(point.x() + floorf(beforeWidth), point.y(), roundf(afterWidth) - floorf(beforeWidth), h); 440635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project} 441635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 44206ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsenint Font::offsetForPositionForSimpleText(const TextRun& run, float x, bool includePartialGlyphs) const 443635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{ 44406ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen float delta = x; 445635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 446635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project WidthIterator it(this, run); 447635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project GlyphBuffer localGlyphBuffer; 448635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project unsigned offset; 449635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (run.rtl()) { 450635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project delta -= floatWidthForSimpleText(run, 0); 451635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project while (1) { 452635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project offset = it.m_currentCharacter; 453635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project float w; 454635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (!it.advanceOneCharacter(w, &localGlyphBuffer)) 455635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project break; 456635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project delta += w; 457635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (includePartialGlyphs) { 458635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (delta - w / 2 >= 0) 459635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project break; 460635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project } else { 461635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (delta >= 0) 462635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project break; 463635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project } 464635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project } 465635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project } else { 466635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project while (1) { 467635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project offset = it.m_currentCharacter; 468635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project float w; 469635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (!it.advanceOneCharacter(w, &localGlyphBuffer)) 470635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project break; 471635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project delta -= w; 472635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (includePartialGlyphs) { 473635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (delta + w / 2 <= 0) 474635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project break; 475635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project } else { 476635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (delta <= 0) 477635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project break; 478635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project } 479635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project } 480635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project } 481635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 482635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project return offset; 483635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project} 484635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 485635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project} 486