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