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); 802bde8e466a4451c7319e3a072d118917957d6554Steve Block if (data.fontData && (data.fontData->platformData().orientation() == Horizontal || data.fontData->isTextOrientationFallback())) 812bde8e466a4451c7319e3a072d118917957d6554Steve Block return data; 822bde8e466a4451c7319e3a072d118917957d6554Steve Block 836b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner if (data.fontData) { 842bde8e466a4451c7319e3a072d118917957d6554Steve Block if (isCJKIdeographOrSymbol(c)) { 852bde8e466a4451c7319e3a072d118917957d6554Steve Block if (!data.fontData->hasVerticalGlyphs()) { 862bde8e466a4451c7319e3a072d118917957d6554Steve Block // Use the broken ideograph font data. The broken ideograph font will use the horizontal width of glyphs 872bde8e466a4451c7319e3a072d118917957d6554Steve Block // to make sure you get a square (even for broken glyphs like symbols used for punctuation). 882bde8e466a4451c7319e3a072d118917957d6554Steve Block const SimpleFontData* brokenIdeographFontData = data.fontData->brokenIdeographFontData(); 892bde8e466a4451c7319e3a072d118917957d6554Steve Block GlyphPageTreeNode* brokenIdeographNode = GlyphPageTreeNode::getRootChild(brokenIdeographFontData, pageNumber); 902bde8e466a4451c7319e3a072d118917957d6554Steve Block const GlyphPage* brokenIdeographPage = brokenIdeographNode->page(); 912bde8e466a4451c7319e3a072d118917957d6554Steve Block if (brokenIdeographPage) { 922bde8e466a4451c7319e3a072d118917957d6554Steve Block GlyphData brokenIdeographData = brokenIdeographPage->glyphDataForCharacter(c); 932bde8e466a4451c7319e3a072d118917957d6554Steve Block if (brokenIdeographData.fontData) 942bde8e466a4451c7319e3a072d118917957d6554Steve Block return brokenIdeographData; 952bde8e466a4451c7319e3a072d118917957d6554Steve Block } 962bde8e466a4451c7319e3a072d118917957d6554Steve Block 972bde8e466a4451c7319e3a072d118917957d6554Steve Block // Shouldn't be possible to even reach this point. 982bde8e466a4451c7319e3a072d118917957d6554Steve Block ASSERT_NOT_REACHED(); 992bde8e466a4451c7319e3a072d118917957d6554Steve Block } 1002bde8e466a4451c7319e3a072d118917957d6554Steve Block } else { 1012bde8e466a4451c7319e3a072d118917957d6554Steve Block if (m_fontDescription.textOrientation() == TextOrientationVerticalRight) { 1022bde8e466a4451c7319e3a072d118917957d6554Steve Block const SimpleFontData* verticalRightFontData = data.fontData->verticalRightOrientationFontData(); 1032bde8e466a4451c7319e3a072d118917957d6554Steve Block GlyphPageTreeNode* verticalRightNode = GlyphPageTreeNode::getRootChild(verticalRightFontData, pageNumber); 1042bde8e466a4451c7319e3a072d118917957d6554Steve Block const GlyphPage* verticalRightPage = verticalRightNode->page(); 1052bde8e466a4451c7319e3a072d118917957d6554Steve Block if (verticalRightPage) { 1062bde8e466a4451c7319e3a072d118917957d6554Steve Block GlyphData verticalRightData = verticalRightPage->glyphDataForCharacter(c); 1072bde8e466a4451c7319e3a072d118917957d6554Steve Block // If the glyphs are distinct, we will make the assumption that the font has a vertical-right glyph baked 1082bde8e466a4451c7319e3a072d118917957d6554Steve Block // into it. 1092bde8e466a4451c7319e3a072d118917957d6554Steve Block if (data.glyph != verticalRightData.glyph) 1102bde8e466a4451c7319e3a072d118917957d6554Steve Block return data; 1112bde8e466a4451c7319e3a072d118917957d6554Steve Block // The glyphs are identical, meaning that we should just use the horizontal glyph. 1122bde8e466a4451c7319e3a072d118917957d6554Steve Block if (verticalRightData.fontData) 1132bde8e466a4451c7319e3a072d118917957d6554Steve Block return verticalRightData; 1142bde8e466a4451c7319e3a072d118917957d6554Steve Block } 1152bde8e466a4451c7319e3a072d118917957d6554Steve Block } else if (m_fontDescription.textOrientation() == TextOrientationUpright) { 1162bde8e466a4451c7319e3a072d118917957d6554Steve Block const SimpleFontData* uprightFontData = data.fontData->uprightOrientationFontData(); 1172bde8e466a4451c7319e3a072d118917957d6554Steve Block GlyphPageTreeNode* uprightNode = GlyphPageTreeNode::getRootChild(uprightFontData, pageNumber); 1182bde8e466a4451c7319e3a072d118917957d6554Steve Block const GlyphPage* uprightPage = uprightNode->page(); 1192bde8e466a4451c7319e3a072d118917957d6554Steve Block if (uprightPage) { 1202bde8e466a4451c7319e3a072d118917957d6554Steve Block GlyphData uprightData = uprightPage->glyphDataForCharacter(c); 1212bde8e466a4451c7319e3a072d118917957d6554Steve Block // If the glyphs are the same, then we know we can just use the horizontal glyph rotated vertically to be upright. 1222bde8e466a4451c7319e3a072d118917957d6554Steve Block if (data.glyph == uprightData.glyph) 1232bde8e466a4451c7319e3a072d118917957d6554Steve Block return data; 1242bde8e466a4451c7319e3a072d118917957d6554Steve Block // The glyphs are distinct, meaning that the font has a vertical-right glyph baked into it. We can't use that 1252bde8e466a4451c7319e3a072d118917957d6554Steve Block // glyph, so we fall back to the upright data and use the horizontal glyph. 1262bde8e466a4451c7319e3a072d118917957d6554Steve Block if (uprightData.fontData) 1272bde8e466a4451c7319e3a072d118917957d6554Steve Block return uprightData; 1282bde8e466a4451c7319e3a072d118917957d6554Steve Block } 1296b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner } 1302bde8e466a4451c7319e3a072d118917957d6554Steve Block 1316b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner // Shouldn't be possible to even reach this point. 1326b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner ASSERT_NOT_REACHED(); 1336b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner } 134635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project return data; 1356b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner } 1366b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner 137635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (node->isSystemFallback()) 138635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project break; 139635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project } 140635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 141635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // Proceed with the fallback list. 142635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project node = node->getChild(fontDataAt(node->level()), pageNumber); 143635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (pageNumber) 1440bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch m_fontList->m_pages.set(pageNumber, node); 145635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project else 1460bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch m_fontList->m_pageZero = node; 147635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project } 148635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project } else { 149635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project while (true) { 150635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project page = node->page(); 151635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (page) { 1525f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian GlyphData data = page->glyphDataForCharacter(c); 153635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (data.fontData) { 154f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch // The variantFontData function should not normally return 0. 155635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // But if it does, we will just render the capital letter big. 156f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch const SimpleFontData* variantFontData = data.fontData->variantFontData(m_fontDescription, variant); 157f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if (!variantFontData) 158635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project return data; 159635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 160f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch GlyphPageTreeNode* variantNode = GlyphPageTreeNode::getRootChild(variantFontData, pageNumber); 161f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch const GlyphPage* variantPage = variantNode->page(); 162f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if (variantPage) { 163f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch GlyphData data = variantPage->glyphDataForCharacter(c); 164635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (data.fontData) 165635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project return data; 166635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project } 167635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 168f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch // Do not attempt system fallback off the variantFontData. This is the very unlikely case that 169635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // a font has the lowercase character but the small caps font does not have its uppercase version. 170f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch return variantFontData->missingGlyphData(); 171635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project } 172635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 173635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (node->isSystemFallback()) 174635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project break; 175635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project } 176635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 177635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // Proceed with the fallback list. 178635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project node = node->getChild(fontDataAt(node->level()), pageNumber); 179635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (pageNumber) 1800bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch m_fontList->m_pages.set(pageNumber, node); 181635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project else 1820bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch m_fontList->m_pageZero = node; 183635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project } 184635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project } 185635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 186635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project ASSERT(page); 187635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project ASSERT(node->isSystemFallback()); 188635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 189635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // System fallback is character-dependent. When we get here, we 190635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // know that the character in question isn't in the system fallback 191635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // font's glyph page. Try to lazily create it here. 192635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project UChar codeUnits[2]; 193635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project int codeUnitsLength; 194635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (c <= 0xFFFF) { 195d0825bca7fe65beaee391d30da42e937db621564Steve Block codeUnits[0] = Font::normalizeSpaces(c); 196635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project codeUnitsLength = 1; 197635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project } else { 198635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project codeUnits[0] = U16_LEAD(c); 199635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project codeUnits[1] = U16_TRAIL(c); 200635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project codeUnitsLength = 2; 201635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project } 202635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project const SimpleFontData* characterFontData = fontCache()->getFontDataForCharacters(*this, codeUnits, codeUnitsLength); 203f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if (variant != NormalVariant && characterFontData) 204f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch characterFontData = characterFontData->variantFontData(m_fontDescription, variant); 205635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (characterFontData) { 206635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // Got the fallback glyph and font. 207635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project GlyphPage* fallbackPage = GlyphPageTreeNode::getRootChild(characterFontData, pageNumber)->page(); 2085f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian GlyphData data = fallbackPage && fallbackPage->fontDataForCharacter(c) ? fallbackPage->glyphDataForCharacter(c) : characterFontData->missingGlyphData(); 209635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // Cache it so we don't have to do system fallback again next time. 210f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if (variant == NormalVariant) { 211d0825bca7fe65beaee391d30da42e937db621564Steve Block#if OS(WINCE) 2120bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch // missingGlyphData returns a null character, which is not suitable for GDI to display. 2130bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch // Also, sometimes we cannot map a font for the character on WINCE, but GDI can still 2140bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch // display the character, probably because the font package is not installed correctly. 2150bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch // So we just always set the glyph to be same as the character, and let GDI solve it. 2160bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch page->setGlyphDataForCharacter(c, c, characterFontData); 2170bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return page->glyphDataForCharacter(c); 2180bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#else 219635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project page->setGlyphDataForCharacter(c, data.glyph, data.fontData); 2200bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#endif 2210bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch } 222635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project return data; 223635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project } 224635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 225635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // Even system fallback can fail; use the missing glyph in that case. 226635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // FIXME: It would be nicer to use the missing glyph from the last resort font instead. 2275f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian GlyphData data = primaryFont()->missingGlyphData(); 228f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if (variant == NormalVariant) { 229d0825bca7fe65beaee391d30da42e937db621564Steve Block#if OS(WINCE) 2300bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch // See comment about WINCE GDI handling near setGlyphDataForCharacter above. 2310bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch page->setGlyphDataForCharacter(c, c, data.fontData); 2320bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return page->glyphDataForCharacter(c); 2330bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#else 234635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project page->setGlyphDataForCharacter(c, data.glyph, data.fontData); 2350bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#endif 2360bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch } 237635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project return data; 238635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project} 239635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 240cad810f21b803229eb11403f9209855525a25d57Steve Blockbool Font::primaryFontHasGlyphForCharacter(UChar32 character) const 241cad810f21b803229eb11403f9209855525a25d57Steve Block{ 242cad810f21b803229eb11403f9209855525a25d57Steve Block unsigned pageNumber = (character / GlyphPage::size); 243cad810f21b803229eb11403f9209855525a25d57Steve Block 244cad810f21b803229eb11403f9209855525a25d57Steve Block GlyphPageTreeNode* node = GlyphPageTreeNode::getRootChild(primaryFont(), pageNumber); 245cad810f21b803229eb11403f9209855525a25d57Steve Block GlyphPage* page = node->page(); 246cad810f21b803229eb11403f9209855525a25d57Steve Block 247cad810f21b803229eb11403f9209855525a25d57Steve Block return page && page->fontDataForCharacter(character); 248cad810f21b803229eb11403f9209855525a25d57Steve Block} 249cad810f21b803229eb11403f9209855525a25d57Steve Block 250f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch// FIXME: This function may not work if the emphasis mark uses a complex script, but none of the 251f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch// standard emphasis marks do so. 252f05b935882198ccf7d81675736e3aeb089c5113aBen Murdochbool Font::getEmphasisMarkGlyphData(const AtomicString& mark, GlyphData& glyphData) const 253635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{ 254f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if (mark.isEmpty()) 255f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch return false; 256f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 257f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch#if ENABLE(SVG_FONTS) 258f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch // FIXME: Implement for SVG fonts. 259f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if (primaryFont()->isSVGFont()) 260f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch return false; 261f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch#endif 262f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 263f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch UChar32 character = mark[0]; 264f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 265f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if (U16_IS_SURROGATE(character)) { 266f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if (!U16_IS_SURROGATE_LEAD(character)) 267f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch return false; 268f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 269f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if (mark.length() < 2) 270f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch return false; 271f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 272f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch UChar low = mark[1]; 273f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if (!U16_IS_TRAIL(low)) 274f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch return false; 275f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 276f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch character = U16_GET_SUPPLEMENTARY(character, low); 277f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch } 278f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 279f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch glyphData = glyphDataForCharacter(character, false, EmphasisMarkVariant); 280f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch return true; 281f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch} 282f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 283f05b935882198ccf7d81675736e3aeb089c5113aBen Murdochint Font::emphasisMarkAscent(const AtomicString& mark) const 284f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch{ 285f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch GlyphData markGlyphData; 286f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if (!getEmphasisMarkGlyphData(mark, markGlyphData)) 287f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch return 0; 288f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 289f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch const SimpleFontData* markFontData = markGlyphData.fontData; 290f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch ASSERT(markFontData); 291f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if (!markFontData) 292f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch return 0; 293f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 2942fc2651226baac27029e38c9d6ef883fa32084dbSteve Block return markFontData->fontMetrics().ascent(); 295f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch} 296635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 297f05b935882198ccf7d81675736e3aeb089c5113aBen Murdochint Font::emphasisMarkDescent(const AtomicString& mark) const 298f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch{ 299f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch GlyphData markGlyphData; 300f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if (!getEmphasisMarkGlyphData(mark, markGlyphData)) 301f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch return 0; 302f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 303f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch const SimpleFontData* markFontData = markGlyphData.fontData; 304f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch ASSERT(markFontData); 305f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if (!markFontData) 306f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch return 0; 307f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 3082fc2651226baac27029e38c9d6ef883fa32084dbSteve Block return markFontData->fontMetrics().descent(); 309f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch} 310f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 311f05b935882198ccf7d81675736e3aeb089c5113aBen Murdochint Font::emphasisMarkHeight(const AtomicString& mark) const 312f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch{ 313f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch GlyphData markGlyphData; 314f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if (!getEmphasisMarkGlyphData(mark, markGlyphData)) 315f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch return 0; 316f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 317f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch const SimpleFontData* markFontData = markGlyphData.fontData; 318f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch ASSERT(markFontData); 319f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if (!markFontData) 320f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch return 0; 321f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 3222fc2651226baac27029e38c9d6ef883fa32084dbSteve Block return markFontData->fontMetrics().height(); 323f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch} 324f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 325f05b935882198ccf7d81675736e3aeb089c5113aBen Murdochfloat Font::getGlyphsAndAdvancesForSimpleText(const TextRun& run, int from, int to, GlyphBuffer& glyphBuffer, ForTextEmphasisOrNot forTextEmphasis) const 326f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch{ 327f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch float initialAdvance; 328f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 329f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch WidthIterator it(this, run, 0, false, forTextEmphasis); 330635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project it.advance(from); 331635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project float beforeWidth = it.m_runWidthSoFar; 332635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project it.advance(to, &glyphBuffer); 333f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 334635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (glyphBuffer.isEmpty()) 335f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch return 0; 336f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 337635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project float afterWidth = it.m_runWidthSoFar; 338635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 339635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (run.rtl()) { 340635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project it.advance(run.length()); 34181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch initialAdvance = it.m_runWidthSoFar - afterWidth; 342635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project } else 343f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch initialAdvance = beforeWidth; 344635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 345f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if (run.rtl()) { 346635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project for (int i = 0, end = glyphBuffer.size() - 1; i < glyphBuffer.size() / 2; ++i, --end) 347635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project glyphBuffer.swap(i, end); 348f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch } 349f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 350f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch return initialAdvance; 351f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch} 352f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 353f05b935882198ccf7d81675736e3aeb089c5113aBen Murdochvoid Font::drawSimpleText(GraphicsContext* context, const TextRun& run, const FloatPoint& point, int from, int to) const 354f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch{ 355f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch // This glyph buffer holds our glyphs+advances+font data for each glyph. 356f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch GlyphBuffer glyphBuffer; 357f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 358f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch float startX = point.x() + getGlyphsAndAdvancesForSimpleText(run, from, to, glyphBuffer); 359f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 360f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if (glyphBuffer.isEmpty()) 361f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch return; 362635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 363635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project FloatPoint startPoint(startX, point.y()); 364f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch drawGlyphBuffer(context, glyphBuffer, startPoint); 365f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch} 366f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 367f05b935882198ccf7d81675736e3aeb089c5113aBen Murdochvoid Font::drawEmphasisMarksForSimpleText(GraphicsContext* context, const TextRun& run, const AtomicString& mark, const FloatPoint& point, int from, int to) const 368f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch{ 369f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch GlyphBuffer glyphBuffer; 370f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch float initialAdvance = getGlyphsAndAdvancesForSimpleText(run, from, to, glyphBuffer, ForTextEmphasis); 371f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 372f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if (glyphBuffer.isEmpty()) 373f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch return; 374f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 375f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch drawEmphasisMarks(context, glyphBuffer, mark, FloatPoint(point.x() + initialAdvance, point.y())); 376635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project} 377635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 378f05b935882198ccf7d81675736e3aeb089c5113aBen Murdochvoid Font::drawGlyphBuffer(GraphicsContext* context, const GlyphBuffer& glyphBuffer, const FloatPoint& point) const 379635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{ 380635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // Draw each contiguous run of glyphs that use the same font data. 381635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project const SimpleFontData* fontData = glyphBuffer.fontDataAt(0); 382635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project FloatSize offset = glyphBuffer.offsetAt(0); 383635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project FloatPoint startPoint(point); 384635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project float nextX = startPoint.x(); 385635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project int lastFrom = 0; 386635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project int nextGlyph = 0; 387635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project while (nextGlyph < glyphBuffer.size()) { 388635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project const SimpleFontData* nextFontData = glyphBuffer.fontDataAt(nextGlyph); 389635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project FloatSize nextOffset = glyphBuffer.offsetAt(nextGlyph); 390635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (nextFontData != fontData || nextOffset != offset) { 391635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project drawGlyphs(context, fontData, glyphBuffer, lastFrom, nextGlyph - lastFrom, startPoint); 392635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 393635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project lastFrom = nextGlyph; 394635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project fontData = nextFontData; 395635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project offset = nextOffset; 396635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project startPoint.setX(nextX); 397635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project } 398635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project nextX += glyphBuffer.advanceAt(nextGlyph); 399635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project nextGlyph++; 400635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project } 401635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 402635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project drawGlyphs(context, fontData, glyphBuffer, lastFrom, nextGlyph - lastFrom, startPoint); 403635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project} 404635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 405f05b935882198ccf7d81675736e3aeb089c5113aBen Murdochinline static float offsetToMiddleOfGlyph(const SimpleFontData* fontData, Glyph glyph) 406f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch{ 4072bde8e466a4451c7319e3a072d118917957d6554Steve Block if (fontData->platformData().orientation() == Horizontal) { 408f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch FloatRect bounds = fontData->boundsForGlyph(glyph); 409f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch return bounds.x() + bounds.width() / 2; 410f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch } 411f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch // FIXME: Use glyph bounds once they make sense for vertical fonts. 412f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch return fontData->widthForGlyph(glyph) / 2; 413f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch} 414f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 415f05b935882198ccf7d81675736e3aeb089c5113aBen Murdochinline static float offsetToMiddleOfGlyphAtIndex(const GlyphBuffer& glyphBuffer, size_t i) 416f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch{ 417f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch return offsetToMiddleOfGlyph(glyphBuffer.fontDataAt(i), glyphBuffer.glyphAt(i)); 418f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch} 419f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 420f05b935882198ccf7d81675736e3aeb089c5113aBen Murdochvoid Font::drawEmphasisMarks(GraphicsContext* context, const GlyphBuffer& glyphBuffer, const AtomicString& mark, const FloatPoint& point) const 421f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch{ 422f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch GlyphData markGlyphData; 423f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if (!getEmphasisMarkGlyphData(mark, markGlyphData)) 424f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch return; 425f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 426f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch const SimpleFontData* markFontData = markGlyphData.fontData; 427f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch ASSERT(markFontData); 428f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if (!markFontData) 429f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch return; 430f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 431f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch Glyph markGlyph = markGlyphData.glyph; 432f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch Glyph spaceGlyph = markFontData->spaceGlyph(); 433f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 434f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch float middleOfLastGlyph = offsetToMiddleOfGlyphAtIndex(glyphBuffer, 0); 435f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch FloatPoint startPoint(point.x() + middleOfLastGlyph - offsetToMiddleOfGlyph(markFontData, markGlyph), point.y()); 436f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 437f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch GlyphBuffer markBuffer; 438f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch for (int i = 0; i + 1 < glyphBuffer.size(); ++i) { 439f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch float middleOfNextGlyph = offsetToMiddleOfGlyphAtIndex(glyphBuffer, i + 1); 440f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch float advance = glyphBuffer.advanceAt(i) - middleOfLastGlyph + middleOfNextGlyph; 441f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch markBuffer.add(glyphBuffer.glyphAt(i) ? markGlyph : spaceGlyph, markFontData, advance); 442f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch middleOfLastGlyph = middleOfNextGlyph; 443f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch } 444f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch markBuffer.add(glyphBuffer.glyphAt(glyphBuffer.size() - 1) ? markGlyph : spaceGlyph, markFontData, 0); 445f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 446f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch drawGlyphBuffer(context, markBuffer, startPoint); 447f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch} 448f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 44921939df44de1705786c545cd1bf519d47250322dBen Murdochfloat Font::floatWidthForSimpleText(const TextRun& run, GlyphBuffer* glyphBuffer, HashSet<const SimpleFontData*>* fallbackFonts, GlyphOverflow* glyphOverflow) const 450635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{ 45121939df44de1705786c545cd1bf519d47250322dBen Murdoch WidthIterator it(this, run, fallbackFonts, glyphOverflow); 452635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project it.advance(run.length(), glyphBuffer); 45321939df44de1705786c545cd1bf519d47250322dBen Murdoch 45421939df44de1705786c545cd1bf519d47250322dBen Murdoch if (glyphOverflow) { 4552bde8e466a4451c7319e3a072d118917957d6554Steve Block glyphOverflow->top = max<int>(glyphOverflow->top, ceilf(-it.minGlyphBoundingBoxY()) - (glyphOverflow->computeBounds ? 0 : fontMetrics().ascent())); 4562bde8e466a4451c7319e3a072d118917957d6554Steve Block glyphOverflow->bottom = max<int>(glyphOverflow->bottom, ceilf(it.maxGlyphBoundingBoxY()) - (glyphOverflow->computeBounds ? 0 : fontMetrics().descent())); 45721939df44de1705786c545cd1bf519d47250322dBen Murdoch glyphOverflow->left = ceilf(it.firstGlyphOverflow()); 45821939df44de1705786c545cd1bf519d47250322dBen Murdoch glyphOverflow->right = ceilf(it.lastGlyphOverflow()); 45921939df44de1705786c545cd1bf519d47250322dBen Murdoch } 46021939df44de1705786c545cd1bf519d47250322dBen Murdoch 461635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project return it.m_runWidthSoFar; 462635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project} 463635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 46406ea8e899e48f1f2f396b70e63fae369f2f23232Kristian MonsenFloatRect Font::selectionRectForSimpleText(const TextRun& run, const FloatPoint& point, int h, int from, int to) const 465635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{ 466635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project WidthIterator it(this, run); 467635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project it.advance(from); 468635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project float beforeWidth = it.m_runWidthSoFar; 469635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project it.advance(to); 470635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project float afterWidth = it.m_runWidthSoFar; 471635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 47206ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen // Using roundf() rather than ceilf() for the right edge as a compromise to ensure correct caret positioning. 473635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (run.rtl()) { 474635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project it.advance(run.length()); 475635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project float totalWidth = it.m_runWidthSoFar; 476635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project return FloatRect(point.x() + floorf(totalWidth - afterWidth), point.y(), roundf(totalWidth - beforeWidth) - floorf(totalWidth - afterWidth), h); 477635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project } 47806ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen 47906ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen return FloatRect(point.x() + floorf(beforeWidth), point.y(), roundf(afterWidth) - floorf(beforeWidth), h); 480635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project} 481635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 48206ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsenint Font::offsetForPositionForSimpleText(const TextRun& run, float x, bool includePartialGlyphs) const 483635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{ 48406ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen float delta = x; 485635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 486635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project WidthIterator it(this, run); 487635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project GlyphBuffer localGlyphBuffer; 488635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project unsigned offset; 489635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (run.rtl()) { 490635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project delta -= floatWidthForSimpleText(run, 0); 491635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project while (1) { 492635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project offset = it.m_currentCharacter; 493635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project float w; 494635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (!it.advanceOneCharacter(w, &localGlyphBuffer)) 495635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project break; 496635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project delta += w; 497635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (includePartialGlyphs) { 498635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (delta - w / 2 >= 0) 499635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project break; 500635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project } else { 501635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (delta >= 0) 502635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project break; 503635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project } 504635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project } 505635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project } else { 506635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project while (1) { 507635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project offset = it.m_currentCharacter; 508635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project float w; 509635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (!it.advanceOneCharacter(w, &localGlyphBuffer)) 510635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project break; 511635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project delta -= w; 512635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (includePartialGlyphs) { 513635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (delta + w / 2 <= 0) 514635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project break; 515635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project } else { 516635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (delta <= 0) 517635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project break; 518635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project } 519635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project } 520635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project } 521635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 522635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project return offset; 523635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project} 524635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 525635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project} 526