1dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch/*
28e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Copyright (C) 2007, 2008 Nikolas Zimmermann <zimmermann@kde.org>
3dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block * Copyright (C) Research In Motion Limited 2010. All rights reserved.
48e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *
58e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * This library is free software; you can redistribute it and/or
68e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * modify it under the terms of the GNU Library General Public
78e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * License as published by the Free Software Foundation; either
88e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * version 2 of the License, or (at your option) any later version.
98e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *
108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * This library is distributed in the hope that it will be useful,
118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * but WITHOUT ANY WARRANTY; without even the implied warranty of
128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Library General Public License for more details.
148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *
158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * You should have received a copy of the GNU Library General Public License
168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * along with this library; see the file COPYING.LIB.  If not, write to
178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Boston, MA 02110-1301, USA.
198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project */
208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "config.h"
228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#if ENABLE(SVG_FONTS)
248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "Font.h"
258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "CSSFontSelector.h"
278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "GraphicsContext.h"
288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "RenderObject.h"
292fc2651226baac27029e38c9d6ef883fa32084dbSteve Block#include "RenderSVGInlineText.h"
3021939df44de1705786c545cd1bf519d47250322dBen Murdoch#include "RenderSVGResourceSolidColor.h"
318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "SVGAltGlyphElement.h"
328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "SVGFontData.h"
338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "SVGFontElement.h"
348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "SVGFontFaceElement.h"
35f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch#include "SVGGlyphElement.h"
36f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch#include "SVGGlyphMap.h"
378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "SVGMissingGlyphElement.h"
38f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch#include "SVGNames.h"
39f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch#include "SimpleFontData.h"
40ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch#include "TextRun.h"
418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "XMLNames.h"
428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectusing namespace WTF::Unicode;
448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectnamespace WebCore {
468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic inline float convertEmUnitToPixel(float fontSize, float unitsPerEm, float value)
488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
49f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    if (!unitsPerEm)
508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return 0.0f;
518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return value * fontSize / unitsPerEm;
538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic inline bool isVerticalWritingMode(const SVGRenderStyle* style)
568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return style->writingMode() == WM_TBRL || style->writingMode() == WM_TB;
588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// Helper functions to determine the arabic character forms (initial, medial, terminal, isolated)
618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectenum ArabicCharShapingMode {
628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    SNone = 0,
638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    SRight = 1,
648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    SDual = 2
658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project};
668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic const ArabicCharShapingMode s_arabicCharShapingMode[222] = {
688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    SRight, SRight, SRight, SRight, SDual , SRight, SDual , SRight, SDual , SDual , SDual , SDual , SDual , SRight,                 /* 0x0622 - 0x062F */
698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    SRight, SRight, SRight, SDual , SDual , SDual , SDual , SDual , SDual , SDual , SDual , SNone , SNone , SNone , SNone , SNone , /* 0x0630 - 0x063F */
708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    SNone , SDual , SDual , SDual , SDual , SDual , SDual , SRight, SDual , SDual , SNone , SNone , SNone , SNone , SNone , SNone , /* 0x0640 - 0x064F */
718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    SNone , SNone , SNone , SNone , SNone , SNone , SNone , SNone , SNone , SNone , SNone , SNone , SNone , SNone , SNone , SNone , /* 0x0650 - 0x065F */
728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    SNone , SNone , SNone , SNone , SNone , SNone , SNone , SNone , SNone , SNone , SNone , SNone , SNone , SNone , SNone , SNone , /* 0x0660 - 0x066F */
738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    SNone , SRight, SRight, SRight, SNone , SRight, SRight, SRight, SDual , SDual , SDual , SDual , SDual , SDual , SDual , SDual , /* 0x0670 - 0x067F */
748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    SDual , SDual , SDual , SDual , SDual , SDual , SDual , SDual , SRight, SRight, SRight, SRight, SRight, SRight, SRight, SRight, /* 0x0680 - 0x068F */
758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    SRight, SRight, SRight, SRight, SRight, SRight, SRight, SRight, SRight, SRight, SDual , SDual , SDual , SDual , SDual , SDual , /* 0x0690 - 0x069F */
768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    SDual , SDual , SDual , SDual , SDual , SDual , SDual , SDual , SDual , SDual , SDual , SDual , SDual , SDual , SDual , SDual , /* 0x06A0 - 0x06AF */
778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    SDual , SDual , SDual , SDual , SDual , SDual , SDual , SDual , SDual , SDual , SDual , SDual , SDual , SDual , SDual , SDual , /* 0x06B0 - 0x06BF */
788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    SRight, SDual , SRight, SRight, SRight, SRight, SRight, SRight, SRight, SRight, SRight, SRight, SDual , SRight, SDual , SRight, /* 0x06C0 - 0x06CF */
798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    SDual , SDual , SRight, SRight, SNone , SNone , SNone , SNone , SNone , SNone , SNone , SNone , SNone , SNone , SNone , SNone , /* 0x06D0 - 0x06DF */
808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    SNone , SNone , SNone , SNone , SNone , SNone , SNone , SNone , SNone , SNone , SNone , SNone , SNone , SNone , SNone , SNone , /* 0x06E0 - 0x06EF */
818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    SNone , SNone , SNone , SNone , SNone , SNone , SNone , SNone , SNone , SNone , SDual , SDual , SDual , SNone , SNone , SNone   /* 0x06F0 - 0x06FF */
828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project};
838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic inline SVGGlyphIdentifier::ArabicForm processArabicFormDetection(const UChar& curChar, bool& lastCharShapesRight, SVGGlyphIdentifier::ArabicForm* prevForm)
858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    SVGGlyphIdentifier::ArabicForm curForm;
878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ArabicCharShapingMode shapingMode = SNone;
898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (curChar >= 0x0622 && curChar <= 0x06FF)
908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        shapingMode = s_arabicCharShapingMode[curChar - 0x0622];
918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Use a simple state machine to identify the actual arabic form
938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // It depends on the order of the arabic form enum:
948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // enum ArabicForm { None = 0, Isolated, Terminal, Initial, Medial };
958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (lastCharShapesRight && shapingMode == SDual) {
978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (prevForm) {
988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            int correctedForm = (int) *prevForm + 1;
998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            ASSERT(correctedForm >= SVGGlyphIdentifier::None && correctedForm <= SVGGlyphIdentifier::Medial);
1008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            *prevForm = static_cast<SVGGlyphIdentifier::ArabicForm>(correctedForm);
1018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
1028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        curForm = SVGGlyphIdentifier::Initial;
1048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    } else
1058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        curForm = shapingMode == SNone ? SVGGlyphIdentifier::None : SVGGlyphIdentifier::Isolated;
1068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    lastCharShapesRight = shapingMode != SNone;
1088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return curForm;
1098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic Vector<SVGGlyphIdentifier::ArabicForm> charactersWithArabicForm(const String& input, bool rtl)
1128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
1138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Vector<SVGGlyphIdentifier::ArabicForm> forms;
1148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    unsigned length = input.length();
1158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    bool containsArabic = false;
1178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    for (unsigned i = 0; i < length; ++i) {
1188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (isArabicChar(input[i])) {
1198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            containsArabic = true;
1208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            break;
1218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
1228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
1238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!containsArabic)
1258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return forms;
1268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    bool lastCharShapesRight = false;
1288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Start identifying arabic forms
1308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (rtl) {
1318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        for (int i = length - 1; i >= 0; --i)
1328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            forms.prepend(processArabicFormDetection(input[i], lastCharShapesRight, forms.isEmpty() ? 0 : &forms.first()));
1338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    } else {
1348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        for (unsigned i = 0; i < length; ++i)
1358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            forms.append(processArabicFormDetection(input[i], lastCharShapesRight, forms.isEmpty() ? 0 : &forms.last()));
1368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
1378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return forms;
1398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic inline bool isCompatibleArabicForm(const SVGGlyphIdentifier& identifier, const Vector<SVGGlyphIdentifier::ArabicForm>& chars, unsigned startPosition, unsigned endPosition)
1428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
1438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (chars.isEmpty())
1448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return true;
1458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Vector<SVGGlyphIdentifier::ArabicForm>::const_iterator it = chars.begin() + startPosition;
1478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Vector<SVGGlyphIdentifier::ArabicForm>::const_iterator end = chars.begin() + endPosition;
1488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ASSERT(end <= chars.end());
1508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    for (; it != end; ++it) {
1518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (*it != static_cast<SVGGlyphIdentifier::ArabicForm>(identifier.arabicForm) && *it != SVGGlyphIdentifier::None)
1528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return false;
1538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
1548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return true;
1568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic inline bool isCompatibleGlyph(const SVGGlyphIdentifier& identifier, bool isVerticalText, const String& language,
1598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                                     const Vector<SVGGlyphIdentifier::ArabicForm>& chars, unsigned startPosition, unsigned endPosition)
1608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
1618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    bool valid = true;
1628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Check wheter orientation if glyph fits within the request
1648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    switch (identifier.orientation) {
1658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    case SVGGlyphIdentifier::Vertical:
1668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        valid = isVerticalText;
1678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        break;
1688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    case SVGGlyphIdentifier::Horizontal:
1698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        valid = !isVerticalText;
1708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        break;
1718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    case SVGGlyphIdentifier::Both:
1728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        break;
1738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
1748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!valid)
1768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return false;
1778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Check wheter languages are compatible
1798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!identifier.languages.isEmpty()) {
1808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // This glyph exists only in certain languages, if we're not specifying a
1818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // language on the referencing element we're unable to use this glyph.
1828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (language.isEmpty())
1838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return false;
1848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // Split subcode from language, if existant.
1868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        String languagePrefix;
1878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
188f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick        size_t subCodeSeparator = language.find('-');
189f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick        if (subCodeSeparator != notFound)
1908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            languagePrefix = language.left(subCodeSeparator);
1918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        Vector<String>::const_iterator it = identifier.languages.begin();
1938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        Vector<String>::const_iterator end = identifier.languages.end();
1948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        bool found = false;
1968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        for (; it != end; ++it) {
1978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            const String& cur = *it;
1988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            if (cur == language || cur == languagePrefix) {
1998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                found = true;
2008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                break;
2018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            }
2028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
2038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (!found)
2058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return false;
2068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
2078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Check wheter arabic form is compatible
2098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return isCompatibleArabicForm(identifier, chars, startPosition, endPosition);
2108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
2118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic inline const SVGFontData* svgFontAndFontFaceElementForFontData(const SimpleFontData* fontData, SVGFontFaceElement*& fontFace, SVGFontElement*& font)
2138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
2148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ASSERT(fontData->isCustomFont());
2158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ASSERT(fontData->isSVGFont());
2168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    const SVGFontData* svgFontData = static_cast<const SVGFontData*>(fontData->svgFontData());
2188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    fontFace = svgFontData->svgFontFaceElement();
2208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ASSERT(fontFace);
2218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    font = fontFace->associatedFontElement();
2238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return svgFontData;
2248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
2258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// Helper class to walk a text run. Lookup a SVGGlyphIdentifier for each character
2278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// - also respecting possibly defined ligatures - and invoke a callback for each found glyph.
2288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projecttemplate<typename SVGTextRunData>
2298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstruct SVGTextRunWalker {
2308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    typedef bool (*SVGTextRunWalkerCallback)(const SVGGlyphIdentifier&, SVGTextRunData&);
2318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    typedef void (*SVGTextRunWalkerMissingGlyphCallback)(const TextRun&, SVGTextRunData&);
2328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    SVGTextRunWalker(const SVGFontData* fontData, SVGFontElement* fontElement, SVGTextRunData& data,
2348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                     SVGTextRunWalkerCallback callback, SVGTextRunWalkerMissingGlyphCallback missingGlyphCallback)
2358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        : m_fontData(fontData)
2368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        , m_fontElement(fontElement)
2378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        , m_walkerData(data)
2388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        , m_walkerCallback(callback)
2398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        , m_walkerMissingGlyphCallback(missingGlyphCallback)
2408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    {
2418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
2428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    void walk(const TextRun& run, bool isVerticalText, const String& language, int from, int to)
2448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    {
2458a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block        ASSERT(0 <= from && from <= to && to - from <= run.length());
2468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2472fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        const String text = Font::normalizeSpaces(run.data(from), to - from);
248d0825bca7fe65beaee391d30da42e937db621564Steve Block        Vector<SVGGlyphIdentifier::ArabicForm> chars(charactersWithArabicForm(text, run.rtl()));
2498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        SVGGlyphIdentifier identifier;
2518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        bool foundGlyph = false;
2528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        int characterLookupRange;
2538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        int endOfScanRange = to + m_walkerData.extraCharsAvailable;
2548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        bool haveAltGlyph = false;
2568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        SVGGlyphIdentifier altGlyphIdentifier;
2578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (RenderObject* renderObject = run.referencingRenderObject()) {
2582fc2651226baac27029e38c9d6ef883fa32084dbSteve Block            RenderObject* parentRenderer = renderObject->parent();
2592fc2651226baac27029e38c9d6ef883fa32084dbSteve Block            ASSERT(parentRenderer);
2602fc2651226baac27029e38c9d6ef883fa32084dbSteve Block            if (parentRenderer->node() && parentRenderer->node()->hasTagName(SVGNames::altGlyphTag)) {
2612fc2651226baac27029e38c9d6ef883fa32084dbSteve Block                SVGGlyphElement* glyphElement = static_cast<SVGAltGlyphElement*>(parentRenderer->node())->glyphElement();
2628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                if (glyphElement) {
2638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    haveAltGlyph = true;
2648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    altGlyphIdentifier = glyphElement->buildGlyphIdentifier();
2658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    altGlyphIdentifier.isValid = true;
2668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    altGlyphIdentifier.nameLength = to - from;
2678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                }
2688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            }
2698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
2708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        for (int i = from; i < to; ++i) {
2728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            // If characterLookupRange is > 0, then the font defined ligatures (length of unicode property value > 1).
2738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            // We have to check wheter the current character & the next character define a ligature. This needs to be
2748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            // extended to the n-th next character (where n is 'characterLookupRange'), to check for any possible ligature.
2758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            characterLookupRange = endOfScanRange - i;
2768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2772fc2651226baac27029e38c9d6ef883fa32084dbSteve Block            String lookupString = Font::normalizeSpaces(run.data(i), characterLookupRange);
278d0825bca7fe65beaee391d30da42e937db621564Steve Block
2798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            Vector<SVGGlyphIdentifier> glyphs;
2808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            if (haveAltGlyph)
2818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                glyphs.append(altGlyphIdentifier);
2828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            else
2838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                m_fontElement->getGlyphIdentifiersForString(lookupString, glyphs);
2848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            Vector<SVGGlyphIdentifier>::iterator it = glyphs.begin();
2868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            Vector<SVGGlyphIdentifier>::iterator end = glyphs.end();
2878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            for (; it != end; ++it) {
2898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                identifier = *it;
2908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                if (identifier.isValid && isCompatibleGlyph(identifier, isVerticalText, language, chars, i, i + identifier.nameLength)) {
2918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    ASSERT(characterLookupRange > 0);
2928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    i += identifier.nameLength - 1;
2938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    m_walkerData.charsConsumed += identifier.nameLength;
2948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    m_walkerData.glyphName = identifier.glyphName;
2958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    foundGlyph = true;
2978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    SVGGlyphElement::inheritUnspecifiedAttributes(identifier, m_fontData);
2988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    break;
2998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                }
3008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            }
3018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            if (!foundGlyph) {
3038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                ++m_walkerData.charsConsumed;
3048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                if (SVGMissingGlyphElement* element = m_fontElement->firstMissingGlyphElement()) {
3058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    // <missing-glyph> element support
3068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    identifier = SVGGlyphElement::buildGenericGlyphIdentifier(element);
3078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    SVGGlyphElement::inheritUnspecifiedAttributes(identifier, m_fontData);
3088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    identifier.isValid = true;
3098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                } else {
3108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    // Fallback to system font fallback
3118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    TextRun subRun(run);
3128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    subRun.setText(subRun.data(i), 1);
3138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    (*m_walkerMissingGlyphCallback)(subRun, m_walkerData);
3158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    continue;
3168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                }
3178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            }
3188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            if (!(*m_walkerCallback)(identifier, m_walkerData))
3208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                break;
3218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            foundGlyph = false;
3238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
3248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
3258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectprivate:
3278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    const SVGFontData* m_fontData;
3288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    SVGFontElement* m_fontElement;
3298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    SVGTextRunData& m_walkerData;
3308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    SVGTextRunWalkerCallback m_walkerCallback;
3318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    SVGTextRunWalkerMissingGlyphCallback m_walkerMissingGlyphCallback;
3328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project};
3338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// Callback & data structures to compute the width of text using SVG Fonts
3358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstruct SVGTextRunWalkerMeasuredLengthData {
3368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    int at;
3378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    int from;
3388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    int to;
3398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    int extraCharsAvailable;
3408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    int charsConsumed;
3418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    String glyphName;
3428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    float scale;
3448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    float length;
3458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    const Font* font;
3468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project};
3478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
348635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectstatic bool floatWidthUsingSVGFontCallback(const SVGGlyphIdentifier& identifier, SVGTextRunWalkerMeasuredLengthData& data)
3498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
3508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (data.at >= data.from && data.at < data.to)
3518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        data.length += identifier.horizontalAdvanceX * data.scale;
3528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    data.at++;
3548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return data.at < data.to;
3558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
3568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
357635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectstatic void floatWidthMissingGlyphCallback(const TextRun& run, SVGTextRunWalkerMeasuredLengthData& data)
3588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
3598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Handle system font fallback
3608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    FontDescription fontDescription(data.font->fontDescription());
3618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    fontDescription.setFamily(FontFamily());
3628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Font font(fontDescription, 0, 0); // spacing handled by SVG text code.
3638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    font.update(data.font->fontSelector());
3648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
36581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    data.length += font.width(run);
3668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
3678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectSVGFontElement* Font::svgFont() const
3708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
3718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!isSVGFont())
3728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return 0;
3738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    SVGFontElement* fontElement = 0;
3758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    SVGFontFaceElement* fontFaceElement = 0;
3768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (svgFontAndFontFaceElementForFontData(primaryFont(), fontFaceElement, fontElement))
3778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return fontElement;
3788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return 0;
3808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
3818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic float floatWidthOfSubStringUsingSVGFont(const Font* font, const TextRun& run, int extraCharsAvailable, int from, int to, int& charsConsumed, String& glyphName)
3838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
3848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    int newFrom = to > from ? from : to;
3858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    int newTo = to > from ? to : from;
3868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    from = newFrom;
3888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    to = newTo;
3898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    SVGFontElement* fontElement = 0;
3918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    SVGFontFaceElement* fontFaceElement = 0;
3928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (const SVGFontData* fontData = svgFontAndFontFaceElementForFontData(font->primaryFont(), fontFaceElement, fontElement)) {
3948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (!fontElement)
3958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return 0.0f;
3968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        SVGTextRunWalkerMeasuredLengthData data;
3988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        data.font = font;
4008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        data.at = from;
4018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        data.from = from;
4028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        data.to = to;
4038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        data.extraCharsAvailable = extraCharsAvailable;
4048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        data.charsConsumed = 0;
4058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        data.scale = convertEmUnitToPixel(font->size(), fontFaceElement->unitsPerEm(), 1.0f);
4068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        data.length = 0.0f;
4078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        String language;
4098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        bool isVerticalText = false; // Holds true for HTML text
4108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // TODO: language matching & svg glyphs should be possible for HTML text, too.
4128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (RenderObject* renderObject = run.referencingRenderObject()) {
4132fc2651226baac27029e38c9d6ef883fa32084dbSteve Block            RenderObject* parentRenderer = renderObject->parent();
4142fc2651226baac27029e38c9d6ef883fa32084dbSteve Block            ASSERT(parentRenderer);
4152fc2651226baac27029e38c9d6ef883fa32084dbSteve Block            isVerticalText = isVerticalWritingMode(parentRenderer->style()->svgStyle());
4168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4172fc2651226baac27029e38c9d6ef883fa32084dbSteve Block            if (SVGElement* element = static_cast<SVGElement*>(parentRenderer->node()))
4188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                language = element->getAttribute(XMLNames::langAttr);
4198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
4208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        SVGTextRunWalker<SVGTextRunWalkerMeasuredLengthData> runWalker(fontData, fontElement, data, floatWidthUsingSVGFontCallback, floatWidthMissingGlyphCallback);
422967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch        runWalker.walk(run, isVerticalText, language, from, to);
4238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        charsConsumed = data.charsConsumed;
4248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        glyphName = data.glyphName;
4258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return data.length;
4268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
4278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return 0.0f;
4298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
4308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectfloat Font::floatWidthUsingSVGFont(const TextRun& run) const
4328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
4338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    int charsConsumed;
4348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    String glyphName;
4358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return floatWidthOfSubStringUsingSVGFont(this, run, 0, 0, run.length(), charsConsumed, glyphName);
4368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
4378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectfloat Font::floatWidthUsingSVGFont(const TextRun& run, int extraCharsAvailable, int& charsConsumed, String& glyphName) const
4398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
4408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return floatWidthOfSubStringUsingSVGFont(this, run, extraCharsAvailable, 0, run.length(), charsConsumed, glyphName);
4418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
4428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// Callback & data structures to draw text using SVG Fonts
4448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstruct SVGTextRunWalkerDrawTextData {
4458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    int extraCharsAvailable;
4468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    int charsConsumed;
4478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    String glyphName;
4488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Vector<SVGGlyphIdentifier> glyphIdentifiers;
4498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Vector<UChar> fallbackCharacters;
4508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project};
4518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
452635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectstatic bool drawTextUsingSVGFontCallback(const SVGGlyphIdentifier& identifier, SVGTextRunWalkerDrawTextData& data)
4538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
4548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    data.glyphIdentifiers.append(identifier);
4558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return true;
4568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
4578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
458635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectstatic void drawTextMissingGlyphCallback(const TextRun& run, SVGTextRunWalkerDrawTextData& data)
4598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
4608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ASSERT(run.length() == 1);
4618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    data.glyphIdentifiers.append(SVGGlyphIdentifier());
4628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    data.fallbackCharacters.append(run[0]);
4638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
4648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid Font::drawTextUsingSVGFont(GraphicsContext* context, const TextRun& run,
4668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                                const FloatPoint& point, int from, int to) const
4678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
4688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    SVGFontElement* fontElement = 0;
4698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    SVGFontFaceElement* fontFaceElement = 0;
4708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (const SVGFontData* fontData = svgFontAndFontFaceElementForFontData(primaryFont(), fontFaceElement, fontElement)) {
4728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (!fontElement)
4738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return;
4748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        SVGTextRunWalkerDrawTextData data;
4768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        FloatPoint currentPoint = point;
4778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        float scale = convertEmUnitToPixel(size(), fontFaceElement->unitsPerEm(), 1.0f);
4788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
47921939df44de1705786c545cd1bf519d47250322dBen Murdoch        RenderSVGResource* activePaintingResource = run.activePaintingResource();
4808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // If renderObject is not set, we're dealing for HTML text rendered using SVG Fonts.
4828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (!run.referencingRenderObject()) {
48321939df44de1705786c545cd1bf519d47250322dBen Murdoch            ASSERT(!activePaintingResource);
4848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            // TODO: We're only supporting simple filled HTML text so far.
48621939df44de1705786c545cd1bf519d47250322dBen Murdoch            RenderSVGResourceSolidColor* solidPaintingResource = RenderSVGResource::sharedSolidPaintingResource();
48721939df44de1705786c545cd1bf519d47250322dBen Murdoch            solidPaintingResource->setColor(context->fillColor());
4888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
48921939df44de1705786c545cd1bf519d47250322dBen Murdoch            activePaintingResource = solidPaintingResource;
4908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
4918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
49221939df44de1705786c545cd1bf519d47250322dBen Murdoch        ASSERT(activePaintingResource);
4938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        int charsConsumed;
4958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        String glyphName;
4968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        bool isVerticalText = false;
4978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        float xStartOffset = floatWidthOfSubStringUsingSVGFont(this, run, 0, run.rtl() ? to : 0, run.rtl() ? run.length() : from, charsConsumed, glyphName);
4988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        FloatPoint glyphOrigin;
4998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        String language;
5018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // TODO: language matching & svg glyphs should be possible for HTML text, too.
5032fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        RenderObject* referencingRenderObject = run.referencingRenderObject();
5042fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        RenderObject* referencingRenderObjectParent = referencingRenderObject ? referencingRenderObject->parent() : 0;
5052fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        RenderStyle* referencingRenderObjectParentStyle = 0;
5062fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        if (referencingRenderObject) {
5072fc2651226baac27029e38c9d6ef883fa32084dbSteve Block            ASSERT(referencingRenderObjectParent);
5082fc2651226baac27029e38c9d6ef883fa32084dbSteve Block            referencingRenderObjectParentStyle = referencingRenderObjectParent->style();
5092fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
5102fc2651226baac27029e38c9d6ef883fa32084dbSteve Block            isVerticalText = isVerticalWritingMode(referencingRenderObjectParentStyle->svgStyle());
5112fc2651226baac27029e38c9d6ef883fa32084dbSteve Block            if (SVGElement* element = static_cast<SVGElement*>(referencingRenderObjectParent->node()))
5128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                language = element->getAttribute(XMLNames::langAttr);
5138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
5148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (!isVerticalText) {
5168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            glyphOrigin.setX(fontData->horizontalOriginX() * scale);
5178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            glyphOrigin.setY(fontData->horizontalOriginY() * scale);
5188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
5198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        data.extraCharsAvailable = 0;
521635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        data.charsConsumed = 0;
5228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        SVGTextRunWalker<SVGTextRunWalkerDrawTextData> runWalker(fontData, fontElement, data, drawTextUsingSVGFontCallback, drawTextMissingGlyphCallback);
5248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        runWalker.walk(run, isVerticalText, language, from, to);
5258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
526f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        RenderSVGResourceMode resourceMode = context->textDrawingMode() == TextModeStroke ? ApplyToStrokeMode : ApplyToFillMode;
5278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        unsigned numGlyphs = data.glyphIdentifiers.size();
5298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        unsigned fallbackCharacterIndex = 0;
5308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        for (unsigned i = 0; i < numGlyphs; ++i) {
5318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            const SVGGlyphIdentifier& identifier = data.glyphIdentifiers[run.rtl() ? numGlyphs - i - 1 : i];
5328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            if (identifier.isValid) {
5338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                // FIXME: Support arbitary SVG content as glyph (currently limited to <glyph d="..."> situations).
5348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                if (!identifier.pathData.isEmpty()) {
5358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    context->save();
5368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    if (isVerticalText) {
5388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                        glyphOrigin.setX(identifier.verticalOriginX * scale);
5398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                        glyphOrigin.setY(identifier.verticalOriginY * scale);
5408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    }
5418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
542dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                    AffineTransform glyphPathTransform;
543dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                    glyphPathTransform.translate(xStartOffset + currentPoint.x() + glyphOrigin.x(), currentPoint.y() + glyphOrigin.y());
544dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                    glyphPathTransform.scale(scale, -scale);
5458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
546dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                    Path glyphPath = identifier.pathData;
547dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                    glyphPath.transform(glyphPathTransform);
5488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5492fc2651226baac27029e38c9d6ef883fa32084dbSteve Block                    if (activePaintingResource->applyResource(referencingRenderObjectParent, referencingRenderObjectParentStyle, context, resourceMode)) {
5502fc2651226baac27029e38c9d6ef883fa32084dbSteve Block                        if (referencingRenderObject) {
5512fc2651226baac27029e38c9d6ef883fa32084dbSteve Block                            RenderSVGInlineText* textRenderer = toRenderSVGInlineText(referencingRenderObject);
5522fc2651226baac27029e38c9d6ef883fa32084dbSteve Block                            context->setStrokeThickness(context->strokeThickness() * textRenderer->scalingFactor());
5532fc2651226baac27029e38c9d6ef883fa32084dbSteve Block                        }
5542fc2651226baac27029e38c9d6ef883fa32084dbSteve Block                        activePaintingResource->postApplyResource(referencingRenderObjectParent, context, resourceMode, &glyphPath);
5552fc2651226baac27029e38c9d6ef883fa32084dbSteve Block                    }
5568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    context->restore();
5588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                }
5598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                if (isVerticalText)
5618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    currentPoint.move(0.0f, identifier.verticalAdvanceY * scale);
5628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                else
5638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    currentPoint.move(identifier.horizontalAdvanceX * scale, 0.0f);
5648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            } else {
5658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                // Handle system font fallback
566635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project                FontDescription fontDescription(m_fontDescription);
5678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                fontDescription.setFamily(FontFamily());
5688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                Font font(fontDescription, 0, 0); // spacing handled by SVG text code.
569635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project                font.update(fontSelector());
5708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                TextRun fallbackCharacterRun(run);
5728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                fallbackCharacterRun.setText(&data.fallbackCharacters[run.rtl() ? data.fallbackCharacters.size() - fallbackCharacterIndex - 1 : fallbackCharacterIndex], 1);
5738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                font.drawText(context, fallbackCharacterRun, currentPoint);
5748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                if (isVerticalText)
57681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch                    currentPoint.move(0.0f, font.width(fallbackCharacterRun));
5778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                else
57881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch                    currentPoint.move(font.width(fallbackCharacterRun), 0.0f);
5798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                fallbackCharacterIndex++;
5818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            }
5828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
5838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
5848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
5858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
58606ea8e899e48f1f2f396b70e63fae369f2f23232Kristian MonsenFloatRect Font::selectionRectForTextUsingSVGFont(const TextRun& run, const FloatPoint& point, int height, int from, int to) const
5878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
5888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    int charsConsumed;
5898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    String glyphName;
5908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return FloatRect(point.x() + floatWidthOfSubStringUsingSVGFont(this, run, 0, run.rtl() ? to : 0, run.rtl() ? run.length() : from, charsConsumed, glyphName),
5928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                     point.y(), floatWidthOfSubStringUsingSVGFont(this, run, 0, from, to, charsConsumed, glyphName), height);
5938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
5948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
59506ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsenint Font::offsetForPositionForTextUsingSVGFont(const TextRun&, float, bool) const
5968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
5978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // TODO: Fix text selection when HTML text is drawn using a SVG Font
5988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // We need to integrate the SVG text selection code in the offsetForPosition() framework.
5998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // This will also fix a major issue, that SVG Text code can't select arabic strings properly.
6008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return 0;
6018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
6028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
6038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
6048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
6058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#endif
606