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