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