OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) Research In Motion Limited 2010-2012. All rights reserved. | 2 * Copyright (C) Research In Motion Limited 2010-2012. All rights reserved. |
3 * | 3 * |
4 * This library is free software; you can redistribute it and/or | 4 * This library is free software; you can redistribute it and/or |
5 * modify it under the terms of the GNU Library General Public | 5 * modify it under the terms of the GNU Library General Public |
6 * License as published by the Free Software Foundation; either | 6 * License as published by the Free Software Foundation; either |
7 * version 2 of the License, or (at your option) any later version. | 7 * version 2 of the License, or (at your option) any later version. |
8 * | 8 * |
9 * This library is distributed in the hope that it will be useful, | 9 * This library is distributed in the hope that it will be useful, |
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of | 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
12 * Library General Public License for more details. | 12 * Library General Public License for more details. |
13 * | 13 * |
14 * You should have received a copy of the GNU Library General Public License | 14 * You should have received a copy of the GNU Library General Public License |
15 * along with this library; see the file COPYING.LIB. If not, write to | 15 * along with this library; see the file COPYING.LIB. If not, write to |
16 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | 16 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
17 * Boston, MA 02110-1301, USA. | 17 * Boston, MA 02110-1301, USA. |
18 */ | 18 */ |
19 | 19 |
20 #include "config.h" | 20 #include "config.h" |
21 | 21 |
22 #include "core/rendering/svg/SVGTextMetricsBuilder.h" | 22 #include "core/rendering/svg/SVGTextMetricsBuilder.h" |
23 | 23 |
24 #include "core/rendering/svg/RenderSVGInlineText.h" | 24 #include "core/rendering/svg/RenderSVGInlineText.h" |
25 #include "core/rendering/svg/RenderSVGText.h" | 25 #include "core/rendering/svg/RenderSVGText.h" |
26 #include "core/rendering/svg/SVGTextMetrics.h" | 26 #include "core/rendering/svg/SVGTextMetrics.h" |
27 #include "platform/fonts/WidthIterator.h" | 27 #include "platform/fonts/WidthIterator.h" |
| 28 #include "platform/text/BidiCharacterRun.h" |
| 29 #include "platform/text/BidiResolver.h" |
| 30 #include "platform/text/TextDirection.h" |
28 #include "platform/text/TextPath.h" | 31 #include "platform/text/TextPath.h" |
29 #include "platform/text/TextRun.h" | 32 #include "platform/text/TextRun.h" |
| 33 #include "platform/text/TextRunIterator.h" |
30 #include "wtf/Vector.h" | 34 #include "wtf/Vector.h" |
31 | 35 |
32 namespace WebCore { | 36 namespace WebCore { |
33 | 37 |
34 class SVGTextMetricsCalculator { | 38 class SVGTextMetricsCalculator { |
35 public: | 39 public: |
36 SVGTextMetricsCalculator(RenderSVGInlineText*); | 40 SVGTextMetricsCalculator(RenderSVGInlineText*); |
| 41 ~SVGTextMetricsCalculator(); |
37 | 42 |
38 SVGTextMetrics computeMetricsForCharacter(unsigned textPosition); | 43 SVGTextMetrics computeMetricsForCharacter(unsigned textPosition); |
39 unsigned textLength() const { return static_cast<unsigned>(m_run.charactersL
ength()); } | 44 unsigned textLength() const { return static_cast<unsigned>(m_run.charactersL
ength()); } |
40 | 45 |
41 bool characterStartsSurrogatePair(unsigned textPosition) const | 46 bool characterStartsSurrogatePair(unsigned textPosition) const |
42 { | 47 { |
43 return U16_IS_LEAD(m_run[textPosition]) && textPosition + 1 < textLength
() && U16_IS_TRAIL(m_run[textPosition + 1]); | 48 return U16_IS_LEAD(m_run[textPosition]) && textPosition + 1 < textLength
() && U16_IS_TRAIL(m_run[textPosition + 1]); |
44 } | 49 } |
45 bool characterIsWhiteSpace(unsigned textPosition) const | 50 bool characterIsWhiteSpace(unsigned textPosition) const |
46 { | 51 { |
47 return m_run[textPosition] == ' '; | 52 return m_run[textPosition] == ' '; |
48 } | 53 } |
49 | 54 |
50 private: | 55 private: |
| 56 void setupBidiRuns(); |
51 SVGTextMetrics computeMetricsForCharacterSimple(unsigned textPosition); | 57 SVGTextMetrics computeMetricsForCharacterSimple(unsigned textPosition); |
52 SVGTextMetrics computeMetricsForCharacterComplex(unsigned textPosition); | 58 SVGTextMetrics computeMetricsForCharacterComplex(unsigned textPosition); |
53 | 59 |
54 RenderSVGInlineText* m_text; | 60 RenderSVGInlineText* m_text; |
| 61 BidiCharacterRun* m_bidiRun; |
55 TextRun m_run; | 62 TextRun m_run; |
| 63 BidiResolver<TextRunIterator, BidiCharacterRun> m_bidiResolver; |
56 bool m_isComplexText; | 64 bool m_isComplexText; |
57 float m_totalWidth; | 65 float m_totalWidth; |
| 66 TextDirection m_textDirection; |
58 | 67 |
59 // Simple text only. | 68 // Simple text only. |
60 OwnPtr<WidthIterator> m_simpleWidthIterator; | 69 OwnPtr<WidthIterator> m_simpleWidthIterator; |
61 }; | 70 }; |
62 | 71 |
63 SVGTextMetricsCalculator::SVGTextMetricsCalculator(RenderSVGInlineText* text) | 72 SVGTextMetricsCalculator::SVGTextMetricsCalculator(RenderSVGInlineText* text) |
64 : m_text(text) | 73 : m_text(text) |
| 74 , m_bidiRun(0) |
65 , m_run(SVGTextMetrics::constructTextRun(text, 0, text->textLength())) | 75 , m_run(SVGTextMetrics::constructTextRun(text, 0, text->textLength())) |
66 , m_isComplexText(false) | 76 , m_isComplexText(false) |
67 , m_totalWidth(0) | 77 , m_totalWidth(0) |
68 { | 78 { |
69 const Font& scaledFont = text->scaledFont(); | 79 const Font& scaledFont = text->scaledFont(); |
70 CodePath codePath = scaledFont.codePath(m_run); | 80 CodePath codePath = scaledFont.codePath(m_run); |
71 m_isComplexText = codePath == ComplexPath; | 81 m_isComplexText = codePath == ComplexPath; |
72 m_run.setCharacterScanForCodePath(!m_isComplexText); | 82 m_run.setCharacterScanForCodePath(!m_isComplexText); |
73 | 83 |
74 if (!m_isComplexText) | 84 if (!m_isComplexText) |
75 m_simpleWidthIterator = adoptPtr(new WidthIterator(&scaledFont, m_run)); | 85 m_simpleWidthIterator = adoptPtr(new WidthIterator(&scaledFont, m_run)); |
| 86 else |
| 87 setupBidiRuns(); |
| 88 } |
| 89 |
| 90 SVGTextMetricsCalculator::~SVGTextMetricsCalculator() |
| 91 { |
| 92 if (m_bidiRun) |
| 93 m_bidiResolver.runs().deleteRuns(); |
| 94 } |
| 95 |
| 96 void SVGTextMetricsCalculator::setupBidiRuns() |
| 97 { |
| 98 RenderStyle* style = m_text->style(); |
| 99 m_textDirection = style->direction(); |
| 100 if (isOverride(style->unicodeBidi())) |
| 101 return; |
| 102 |
| 103 BidiStatus status(LTR, false); |
| 104 status.last = status.lastStrong = WTF::Unicode::OtherNeutral; |
| 105 m_bidiResolver.setStatus(status); |
| 106 m_bidiResolver.setPositionIgnoringNestedIsolates(TextRunIterator(&m_run, 0))
; |
| 107 const bool hardLineBreak = false; |
| 108 const bool reorderRuns = false; |
| 109 m_bidiResolver.createBidiRunsForLine(TextRunIterator(&m_run, m_run.length())
, NoVisualOverride, hardLineBreak, reorderRuns); |
| 110 BidiRunList<BidiCharacterRun>& bidiRuns = m_bidiResolver.runs(); |
| 111 m_bidiRun = bidiRuns.firstRun(); |
76 } | 112 } |
77 | 113 |
78 SVGTextMetrics SVGTextMetricsCalculator::computeMetricsForCharacterSimple(unsign
ed textPosition) | 114 SVGTextMetrics SVGTextMetricsCalculator::computeMetricsForCharacterSimple(unsign
ed textPosition) |
79 { | 115 { |
80 GlyphBuffer glyphBuffer; | 116 GlyphBuffer glyphBuffer; |
81 unsigned metricsLength = m_simpleWidthIterator->advance(textPosition + 1, &g
lyphBuffer); | 117 unsigned metricsLength = m_simpleWidthIterator->advance(textPosition + 1, &g
lyphBuffer); |
82 if (!metricsLength) | 118 if (!metricsLength) |
83 return SVGTextMetrics(); | 119 return SVGTextMetrics(); |
84 | 120 |
85 float currentWidth = m_simpleWidthIterator->runWidthSoFar() - m_totalWidth; | 121 float currentWidth = m_simpleWidthIterator->runWidthSoFar() - m_totalWidth; |
86 m_totalWidth = m_simpleWidthIterator->runWidthSoFar(); | 122 m_totalWidth = m_simpleWidthIterator->runWidthSoFar(); |
87 | 123 |
88 Glyph glyphId = glyphBuffer.glyphAt(0); | 124 Glyph glyphId = glyphBuffer.glyphAt(0); |
89 return SVGTextMetrics(m_text, textPosition, metricsLength, currentWidth, gly
phId); | 125 return SVGTextMetrics(m_text, textPosition, metricsLength, currentWidth, gly
phId); |
90 } | 126 } |
91 | 127 |
92 SVGTextMetrics SVGTextMetricsCalculator::computeMetricsForCharacterComplex(unsig
ned textPosition) | 128 SVGTextMetrics SVGTextMetricsCalculator::computeMetricsForCharacterComplex(unsig
ned textPosition) |
93 { | 129 { |
94 unsigned metricsLength = characterStartsSurrogatePair(textPosition) ? 2 : 1; | 130 unsigned metricsLength = characterStartsSurrogatePair(textPosition) ? 2 : 1; |
95 SVGTextMetrics metrics = SVGTextMetrics::measureCharacterRange(m_text, textP
osition, metricsLength); | 131 SVGTextMetrics metrics = SVGTextMetrics::measureCharacterRange(m_text, textP
osition, metricsLength, m_textDirection); |
96 ASSERT(metrics.length() == metricsLength); | 132 ASSERT(metrics.length() == metricsLength); |
97 | 133 |
98 SVGTextMetrics complexStartToCurrentMetrics = SVGTextMetrics::measureCharact
erRange(m_text, 0, textPosition + metricsLength); | 134 unsigned startPosition = m_bidiRun ? m_bidiRun->start() : 0; |
| 135 ASSERT(startPosition <= textPosition); |
| 136 SVGTextMetrics complexStartToCurrentMetrics = SVGTextMetrics::measureCharact
erRange(m_text, startPosition, textPosition - startPosition + metricsLength, m_t
extDirection); |
99 // Frequent case for Arabic text: when measuring a single character the arab
ic isolated form is taken | 137 // Frequent case for Arabic text: when measuring a single character the arab
ic isolated form is taken |
100 // when rendering the glyph "in context" (with it's surrounding characters)
it changes due to shaping. | 138 // when rendering the glyph "in context" (with it's surrounding characters)
it changes due to shaping. |
101 // So whenever currentWidth != currentMetrics.width(), we are processing a t
ext run whose length is | 139 // So whenever currentWidth != currentMetrics.width(), we are processing a t
ext run whose length is |
102 // not equal to the sum of the individual lengths of the glyphs, when measur
ing them isolated. | 140 // not equal to the sum of the individual lengths of the glyphs, when measur
ing them isolated. |
103 float currentWidth = complexStartToCurrentMetrics.width() - m_totalWidth; | 141 float currentWidth = complexStartToCurrentMetrics.width() - m_totalWidth; |
104 if (currentWidth != metrics.width()) | 142 if (currentWidth != metrics.width()) |
105 metrics.setWidth(currentWidth); | 143 metrics.setWidth(currentWidth); |
106 | 144 |
107 m_totalWidth = complexStartToCurrentMetrics.width(); | 145 m_totalWidth = complexStartToCurrentMetrics.width(); |
108 return metrics; | 146 return metrics; |
109 } | 147 } |
110 | 148 |
111 SVGTextMetrics SVGTextMetricsCalculator::computeMetricsForCharacter(unsigned tex
tPosition) | 149 SVGTextMetrics SVGTextMetricsCalculator::computeMetricsForCharacter(unsigned tex
tPosition) |
112 { | 150 { |
| 151 if (m_bidiRun) { |
| 152 if (textPosition >= static_cast<unsigned>(m_bidiRun->stop())) { |
| 153 m_bidiRun = m_bidiRun->next(); |
| 154 // New BiDi run means new reference position for measurements, so re
set |m_totalWidth|. |
| 155 m_totalWidth = 0; |
| 156 } |
| 157 ASSERT(m_bidiRun); |
| 158 ASSERT(static_cast<int>(textPosition) < m_bidiRun->stop()); |
| 159 m_textDirection = m_bidiRun->direction(); |
| 160 } |
| 161 |
113 if (m_isComplexText) | 162 if (m_isComplexText) |
114 return computeMetricsForCharacterComplex(textPosition); | 163 return computeMetricsForCharacterComplex(textPosition); |
115 | 164 |
116 return computeMetricsForCharacterSimple(textPosition); | 165 return computeMetricsForCharacterSimple(textPosition); |
117 } | 166 } |
118 | 167 |
119 struct MeasureTextData { | 168 struct MeasureTextData { |
120 MeasureTextData(SVGCharacterDataMap* characterDataMap) | 169 MeasureTextData(SVGCharacterDataMap* characterDataMap) |
121 : allCharactersMap(characterDataMap) | 170 : allCharactersMap(characterDataMap) |
122 , lastCharacterWasWhiteSpace(true) | 171 , lastCharacterWasWhiteSpace(true) |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
218 } | 267 } |
219 | 268 |
220 void SVGTextMetricsBuilder::buildMetricsAndLayoutAttributes(RenderSVGText* textR
oot, RenderSVGInlineText* stopAtLeaf, SVGCharacterDataMap& allCharactersMap) | 269 void SVGTextMetricsBuilder::buildMetricsAndLayoutAttributes(RenderSVGText* textR
oot, RenderSVGInlineText* stopAtLeaf, SVGCharacterDataMap& allCharactersMap) |
221 { | 270 { |
222 ASSERT(textRoot); | 271 ASSERT(textRoot); |
223 MeasureTextData data(&allCharactersMap); | 272 MeasureTextData data(&allCharactersMap); |
224 walkTree(textRoot, stopAtLeaf, &data); | 273 walkTree(textRoot, stopAtLeaf, &data); |
225 } | 274 } |
226 | 275 |
227 } | 276 } |
OLD | NEW |