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 |
(...skipping 23 matching lines...) Expand all Loading... |
34 , m_isComplexText(false) | 34 , m_isComplexText(false) |
35 , m_totalWidth(0) | 35 , m_totalWidth(0) |
36 { | 36 { |
37 } | 37 } |
38 | 38 |
39 inline bool SVGTextMetricsBuilder::currentCharacterStartsSurrogatePair() const | 39 inline bool SVGTextMetricsBuilder::currentCharacterStartsSurrogatePair() const |
40 { | 40 { |
41 return U16_IS_LEAD(m_run[m_textPosition]) && int(m_textPosition + 1) < m_run
.charactersLength() && U16_IS_TRAIL(m_run[m_textPosition + 1]); | 41 return U16_IS_LEAD(m_run[m_textPosition]) && int(m_textPosition + 1) < m_run
.charactersLength() && U16_IS_TRAIL(m_run[m_textPosition + 1]); |
42 } | 42 } |
43 | 43 |
44 bool SVGTextMetricsBuilder::advance() | 44 SVGTextMetrics SVGTextMetricsBuilder::computeMetricsForCurrentCharacterSimple() |
45 { | |
46 m_textPosition += m_currentMetrics.length(); | |
47 if (int(m_textPosition) >= m_run.charactersLength()) | |
48 return false; | |
49 | |
50 if (m_isComplexText) | |
51 advanceComplexText(); | |
52 else | |
53 advanceSimpleText(); | |
54 | |
55 return m_currentMetrics.length() > 0; | |
56 } | |
57 | |
58 void SVGTextMetricsBuilder::advanceSimpleText() | |
59 { | 45 { |
60 GlyphBuffer glyphBuffer; | 46 GlyphBuffer glyphBuffer; |
61 unsigned metricsLength = m_simpleWidthIterator->advance(m_textPosition + 1,
&glyphBuffer); | 47 unsigned metricsLength = m_simpleWidthIterator->advance(m_textPosition + 1,
&glyphBuffer); |
62 if (!metricsLength) { | 48 if (!metricsLength) |
63 m_currentMetrics = SVGTextMetrics(); | 49 return SVGTextMetrics(); |
64 return; | |
65 } | |
66 | 50 |
67 float currentWidth = m_simpleWidthIterator->runWidthSoFar() - m_totalWidth; | 51 float currentWidth = m_simpleWidthIterator->runWidthSoFar() - m_totalWidth; |
68 m_totalWidth = m_simpleWidthIterator->runWidthSoFar(); | 52 m_totalWidth = m_simpleWidthIterator->runWidthSoFar(); |
69 | 53 |
70 Glyph glyphId = glyphBuffer.glyphAt(0); | 54 Glyph glyphId = glyphBuffer.glyphAt(0); |
71 m_currentMetrics = SVGTextMetrics(m_text, m_textPosition, metricsLength, cur
rentWidth, glyphId); | 55 return SVGTextMetrics(m_text, m_textPosition, metricsLength, currentWidth, g
lyphId); |
72 } | 56 } |
73 | 57 |
74 void SVGTextMetricsBuilder::advanceComplexText() | 58 SVGTextMetrics SVGTextMetricsBuilder::computeMetricsForCurrentCharacterComplex() |
75 { | 59 { |
76 unsigned metricsLength = currentCharacterStartsSurrogatePair() ? 2 : 1; | 60 unsigned metricsLength = currentCharacterStartsSurrogatePair() ? 2 : 1; |
77 m_currentMetrics = SVGTextMetrics::measureCharacterRange(m_text, m_textPosit
ion, metricsLength); | 61 SVGTextMetrics metrics = SVGTextMetrics::measureCharacterRange(m_text, m_tex
tPosition, metricsLength); |
78 m_complexStartToCurrentMetrics = SVGTextMetrics::measureCharacterRange(m_tex
t, 0, m_textPosition + metricsLength); | 62 ASSERT(metrics.length() == metricsLength); |
79 ASSERT(m_currentMetrics.length() == metricsLength); | |
80 | 63 |
| 64 SVGTextMetrics complexStartToCurrentMetrics = SVGTextMetrics::measureCharact
erRange(m_text, 0, m_textPosition + metricsLength); |
81 // Frequent case for Arabic text: when measuring a single character the arab
ic isolated form is taken | 65 // Frequent case for Arabic text: when measuring a single character the arab
ic isolated form is taken |
82 // when rendering the glyph "in context" (with it's surrounding characters)
it changes due to shaping. | 66 // when rendering the glyph "in context" (with it's surrounding characters)
it changes due to shaping. |
83 // So whenever currentWidth != currentMetrics.width(), we are processing a t
ext run whose length is | 67 // So whenever currentWidth != currentMetrics.width(), we are processing a t
ext run whose length is |
84 // not equal to the sum of the individual lengths of the glyphs, when measur
ing them isolated. | 68 // not equal to the sum of the individual lengths of the glyphs, when measur
ing them isolated. |
85 float currentWidth = m_complexStartToCurrentMetrics.width() - m_totalWidth; | 69 float currentWidth = complexStartToCurrentMetrics.width() - m_totalWidth; |
86 if (currentWidth != m_currentMetrics.width()) | 70 if (currentWidth != metrics.width()) |
87 m_currentMetrics.setWidth(currentWidth); | 71 metrics.setWidth(currentWidth); |
88 | 72 |
89 m_totalWidth = m_complexStartToCurrentMetrics.width(); | 73 m_totalWidth = complexStartToCurrentMetrics.width(); |
| 74 return metrics; |
| 75 } |
| 76 |
| 77 SVGTextMetrics SVGTextMetricsBuilder::computeMetricsForCurrentCharacter() |
| 78 { |
| 79 if (m_isComplexText) |
| 80 return computeMetricsForCurrentCharacterComplex(); |
| 81 |
| 82 return computeMetricsForCurrentCharacterSimple(); |
90 } | 83 } |
91 | 84 |
92 void SVGTextMetricsBuilder::initializeMeasurementWithTextRenderer(RenderSVGInlin
eText* text) | 85 void SVGTextMetricsBuilder::initializeMeasurementWithTextRenderer(RenderSVGInlin
eText* text) |
93 { | 86 { |
94 m_text = text; | 87 m_text = text; |
95 m_textPosition = 0; | 88 m_textPosition = 0; |
96 m_currentMetrics = SVGTextMetrics(); | |
97 m_complexStartToCurrentMetrics = SVGTextMetrics(); | |
98 m_totalWidth = 0; | 89 m_totalWidth = 0; |
99 | 90 |
100 const Font& scaledFont = text->scaledFont(); | 91 const Font& scaledFont = text->scaledFont(); |
101 m_run = SVGTextMetrics::constructTextRun(text, 0, text->textLength()); | 92 m_run = SVGTextMetrics::constructTextRun(text, 0, text->textLength()); |
102 CodePath codePath = scaledFont.codePath(m_run); | 93 CodePath codePath = scaledFont.codePath(m_run); |
103 m_isComplexText = codePath == ComplexPath; | 94 m_isComplexText = codePath == ComplexPath; |
104 m_run.setCharacterScanForCodePath(!m_isComplexText); | 95 m_run.setCharacterScanForCodePath(!m_isComplexText); |
105 | 96 |
106 if (m_isComplexText) | 97 if (m_isComplexText) |
107 m_simpleWidthIterator.clear(); | 98 m_simpleWidthIterator.clear(); |
(...skipping 24 matching lines...) Expand all Loading... |
132 if (data->allCharactersMap) | 123 if (data->allCharactersMap) |
133 attributes->clear(); | 124 attributes->clear(); |
134 else | 125 else |
135 textMetricsValues->clear(); | 126 textMetricsValues->clear(); |
136 } | 127 } |
137 | 128 |
138 initializeMeasurementWithTextRenderer(text); | 129 initializeMeasurementWithTextRenderer(text); |
139 bool preserveWhiteSpace = text->style()->whiteSpace() == PRE; | 130 bool preserveWhiteSpace = text->style()->whiteSpace() == PRE; |
140 unsigned surrogatePairCharacters = 0; | 131 unsigned surrogatePairCharacters = 0; |
141 unsigned skippedCharacters = 0; | 132 unsigned skippedCharacters = 0; |
| 133 unsigned textLength = static_cast<unsigned>(m_run.charactersLength()); |
142 | 134 |
143 while (advance()) { | 135 SVGTextMetrics currentMetrics; |
| 136 for (; m_textPosition < textLength; m_textPosition += currentMetrics.length(
)) { |
| 137 currentMetrics = computeMetricsForCurrentCharacter(); |
| 138 if (!currentMetrics.length()) |
| 139 break; |
| 140 |
144 bool characterIsWhiteSpace = m_run[m_textPosition] == ' '; | 141 bool characterIsWhiteSpace = m_run[m_textPosition] == ' '; |
145 if (characterIsWhiteSpace && !preserveWhiteSpace && data->lastCharacterW
asWhiteSpace) { | 142 if (characterIsWhiteSpace && !preserveWhiteSpace && data->lastCharacterW
asWhiteSpace) { |
146 if (processRenderer) | 143 if (processRenderer) |
147 textMetricsValues->append(SVGTextMetrics(SVGTextMetrics::Skipped
SpaceMetrics)); | 144 textMetricsValues->append(SVGTextMetrics(SVGTextMetrics::Skipped
SpaceMetrics)); |
148 if (data->allCharactersMap) | 145 if (data->allCharactersMap) |
149 skippedCharacters += m_currentMetrics.length(); | 146 skippedCharacters += currentMetrics.length(); |
150 continue; | 147 continue; |
151 } | 148 } |
152 | 149 |
153 if (processRenderer) { | 150 if (processRenderer) { |
154 if (data->allCharactersMap) { | 151 if (data->allCharactersMap) { |
155 const SVGCharacterDataMap::const_iterator it = data->allCharacte
rsMap->find(data->valueListPosition + m_textPosition - skippedCharacters - surro
gatePairCharacters + 1); | 152 const SVGCharacterDataMap::const_iterator it = data->allCharacte
rsMap->find(data->valueListPosition + m_textPosition - skippedCharacters - surro
gatePairCharacters + 1); |
156 if (it != data->allCharactersMap->end()) | 153 if (it != data->allCharactersMap->end()) |
157 attributes->characterDataMap().set(m_textPosition + 1, it->v
alue); | 154 attributes->characterDataMap().set(m_textPosition + 1, it->v
alue); |
158 } | 155 } |
159 textMetricsValues->append(m_currentMetrics); | 156 textMetricsValues->append(currentMetrics); |
160 } | 157 } |
161 | 158 |
162 if (data->allCharactersMap && currentCharacterStartsSurrogatePair()) | 159 if (data->allCharactersMap && currentCharacterStartsSurrogatePair()) |
163 surrogatePairCharacters++; | 160 surrogatePairCharacters++; |
164 | 161 |
165 data->lastCharacterWasWhiteSpace = characterIsWhiteSpace; | 162 data->lastCharacterWasWhiteSpace = characterIsWhiteSpace; |
166 } | 163 } |
167 | 164 |
168 if (!data->allCharactersMap) | 165 if (!data->allCharactersMap) |
169 return; | 166 return; |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
204 } | 201 } |
205 | 202 |
206 void SVGTextMetricsBuilder::buildMetricsAndLayoutAttributes(RenderSVGText* textR
oot, RenderSVGInlineText* stopAtLeaf, SVGCharacterDataMap& allCharactersMap) | 203 void SVGTextMetricsBuilder::buildMetricsAndLayoutAttributes(RenderSVGText* textR
oot, RenderSVGInlineText* stopAtLeaf, SVGCharacterDataMap& allCharactersMap) |
207 { | 204 { |
208 ASSERT(textRoot); | 205 ASSERT(textRoot); |
209 MeasureTextData data(&allCharactersMap); | 206 MeasureTextData data(&allCharactersMap); |
210 walkTree(textRoot, stopAtLeaf, &data); | 207 walkTree(textRoot, stopAtLeaf, &data); |
211 } | 208 } |
212 | 209 |
213 } | 210 } |
OLD | NEW |