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 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
144 int fragmentStartInBox = fragment.characterOffset - queryData->textBox->star
t(); | 144 int fragmentStartInBox = fragment.characterOffset - queryData->textBox->star
t(); |
145 int fragmentEndInBox = fragmentStartInBox + fragment.length; | 145 int fragmentEndInBox = fragmentStartInBox + fragment.length; |
146 | 146 |
147 // Check if the ranges intersect. | 147 // Check if the ranges intersect. |
148 startPosition = std::max(startPosition, fragmentStartInBox); | 148 startPosition = std::max(startPosition, fragmentStartInBox); |
149 endPosition = std::min(endPosition, fragmentEndInBox); | 149 endPosition = std::min(endPosition, fragmentEndInBox); |
150 | 150 |
151 if (startPosition >= endPosition) | 151 if (startPosition >= endPosition) |
152 return false; | 152 return false; |
153 | 153 |
154 modifyStartEndPositionsRespectingLigatures(queryData, startPosition, endPosi
tion); | 154 modifyStartEndPositionsRespectingLigatures(queryData, fragment, startPositio
n, endPosition); |
155 if (!queryData->textBox->mapStartEndPositionsIntoFragmentCoordinates(fragmen
t, startPosition, endPosition)) | 155 if (!queryData->textBox->mapStartEndPositionsIntoFragmentCoordinates(fragmen
t, startPosition, endPosition)) |
156 return false; | 156 return false; |
157 | 157 |
158 ASSERT(startPosition < endPosition); | 158 ASSERT(startPosition < endPosition); |
159 return true; | 159 return true; |
160 } | 160 } |
161 | 161 |
162 void SVGTextQuery::modifyStartEndPositionsRespectingLigatures(Data* queryData, i
nt& startPosition, int& endPosition) const | 162 void SVGTextQuery::modifyStartEndPositionsRespectingLigatures(Data* queryData, c
onst SVGTextFragment& fragment, int& startPosition, int& endPosition) const |
163 { | 163 { |
164 SVGTextLayoutAttributes* layoutAttributes = queryData->textRenderer->layoutA
ttributes(); | 164 SVGTextLayoutAttributes* layoutAttributes = queryData->textRenderer->layoutA
ttributes(); |
165 Vector<SVGTextMetrics>& textMetricsValues = layoutAttributes->textMetricsVal
ues(); | 165 Vector<SVGTextMetrics>& textMetricsValues = layoutAttributes->textMetricsVal
ues(); |
166 unsigned boxStart = queryData->textBox->start(); | |
167 unsigned boxLength = queryData->textBox->len(); | |
168 | 166 |
169 unsigned textMetricsOffset = 0; | 167 unsigned textMetricsOffset = fragment.metricsListOffset; |
170 unsigned textMetricsSize = textMetricsValues.size(); | |
171 | 168 |
172 unsigned positionOffset = 0; | 169 // Compute the offset of the fragment within the box, since that's the |
173 unsigned positionSize = layoutAttributes->context()->textLength(); | 170 // space <startPosition, endPosition> is in (and that's what we need). |
| 171 int fragmentOffsetInBox = fragment.characterOffset - queryData->textBox->sta
rt(); |
| 172 int fragmentEndInBox = fragmentOffsetInBox + fragment.length; |
174 | 173 |
175 bool alterStartPosition = true; | 174 // Find the text metrics cell that start at or contain the character startPo
sition. |
176 bool alterEndPosition = true; | 175 while (fragmentOffsetInBox < fragmentEndInBox) { |
177 | |
178 int lastPositionOffset = -1; | |
179 for (; textMetricsOffset < textMetricsSize && positionOffset < positionSize;
++textMetricsOffset) { | |
180 SVGTextMetrics& metrics = textMetricsValues[textMetricsOffset]; | 176 SVGTextMetrics& metrics = textMetricsValues[textMetricsOffset]; |
181 | 177 int glyphEnd = fragmentOffsetInBox + metrics.length(); |
182 // Advance to text box start location. | 178 if (startPosition < glyphEnd) |
183 if (positionOffset < boxStart) { | |
184 positionOffset += metrics.length(); | |
185 continue; | |
186 } | |
187 | |
188 // Stop if we've finished processing this text box. | |
189 if (positionOffset >= boxStart + boxLength) | |
190 break; | 179 break; |
191 | 180 fragmentOffsetInBox = glyphEnd; |
192 // If the start position maps to a character in the metrics list, we don
't need to modify it. | 181 textMetricsOffset++; |
193 if (startPosition == static_cast<int>(positionOffset)) | |
194 alterStartPosition = false; | |
195 | |
196 // If the start position maps to a character in the metrics list, we don
't need to modify it. | |
197 if (endPosition == static_cast<int>(positionOffset)) | |
198 alterEndPosition = false; | |
199 | |
200 // Detect ligatures. | |
201 if (lastPositionOffset != -1 && lastPositionOffset - positionOffset > 1)
{ | |
202 if (alterStartPosition && startPosition > lastPositionOffset && star
tPosition < static_cast<int>(positionOffset)) { | |
203 startPosition = lastPositionOffset; | |
204 alterStartPosition = false; | |
205 } | |
206 | |
207 if (alterEndPosition && endPosition > lastPositionOffset && endPosit
ion < static_cast<int>(positionOffset)) { | |
208 endPosition = positionOffset; | |
209 alterEndPosition = false; | |
210 } | |
211 } | |
212 | |
213 if (!alterStartPosition && !alterEndPosition) | |
214 break; | |
215 | |
216 lastPositionOffset = positionOffset; | |
217 positionOffset += metrics.length(); | |
218 } | 182 } |
219 | 183 |
220 if (!alterStartPosition && !alterEndPosition) | 184 startPosition = fragmentOffsetInBox; |
221 return; | |
222 | 185 |
223 if (lastPositionOffset != -1 && lastPositionOffset - positionOffset > 1) { | 186 // Find the text metrics cell that contain or ends at the character endPosit
ion. |
224 if (alterStartPosition && startPosition > lastPositionOffset && startPos
ition < static_cast<int>(positionOffset)) | 187 while (fragmentOffsetInBox < fragmentEndInBox) { |
225 startPosition = lastPositionOffset; | 188 SVGTextMetrics& metrics = textMetricsValues[textMetricsOffset]; |
| 189 fragmentOffsetInBox += metrics.length(); |
| 190 if (fragmentOffsetInBox >= endPosition) |
| 191 break; |
| 192 textMetricsOffset++; |
| 193 } |
226 | 194 |
227 if (alterEndPosition && endPosition > lastPositionOffset && endPosition
< static_cast<int>(positionOffset)) | 195 endPosition = fragmentOffsetInBox; |
228 endPosition = positionOffset; | |
229 } | |
230 } | 196 } |
231 | 197 |
232 // numberOfCharacters() implementation | 198 // numberOfCharacters() implementation |
233 bool SVGTextQuery::numberOfCharactersCallback(Data*, const SVGTextFragment&) con
st | 199 bool SVGTextQuery::numberOfCharactersCallback(Data*, const SVGTextFragment&) con
st |
234 { | 200 { |
235 // no-op | 201 // no-op |
236 return false; | 202 return false; |
237 } | 203 } |
238 | 204 |
239 unsigned SVGTextQuery::numberOfCharacters() const | 205 unsigned SVGTextQuery::numberOfCharacters() const |
(...skipping 286 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
526 int SVGTextQuery::characterNumberAtPosition(const FloatPoint& position) const | 492 int SVGTextQuery::characterNumberAtPosition(const FloatPoint& position) const |
527 { | 493 { |
528 CharacterNumberAtPositionData data(position); | 494 CharacterNumberAtPositionData data(position); |
529 if (!executeQuery(&data, &SVGTextQuery::characterNumberAtPositionCallback)) | 495 if (!executeQuery(&data, &SVGTextQuery::characterNumberAtPositionCallback)) |
530 return -1; | 496 return -1; |
531 | 497 |
532 return data.processedCharacters; | 498 return data.processedCharacters; |
533 } | 499 } |
534 | 500 |
535 } | 501 } |
OLD | NEW |