Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(464)

Side by Side Diff: Source/core/layout/svg/SVGTextQuery.cpp

Issue 1057853002: Hide the SVGTextQuery implementation in the .cpp file (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Created 5 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 #include "core/layout/svg/SVGTextQuery.h" 21 #include "core/layout/svg/SVGTextQuery.h"
22 22
23 #include "core/layout/LayoutBlockFlow.h" 23 #include "core/layout/LayoutBlockFlow.h"
24 #include "core/layout/LayoutInline.h" 24 #include "core/layout/LayoutInline.h"
25 #include "core/layout/line/InlineFlowBox.h" 25 #include "core/layout/line/InlineFlowBox.h"
26 #include "core/layout/svg/LayoutSVGInlineText.h" 26 #include "core/layout/svg/LayoutSVGInlineText.h"
27 #include "core/layout/svg/SVGTextFragment.h"
27 #include "core/layout/svg/SVGTextMetrics.h" 28 #include "core/layout/svg/SVGTextMetrics.h"
28 #include "core/layout/svg/line/SVGInlineTextBox.h" 29 #include "core/layout/svg/line/SVGInlineTextBox.h"
29 #include "platform/FloatConversion.h" 30 #include "platform/FloatConversion.h"
30 #include "wtf/MathExtras.h" 31 #include "wtf/MathExtras.h"
32 #include "wtf/Vector.h"
31 33
32 namespace blink { 34 namespace blink {
33 35
34 // Base structure for callback user data 36 // Base structure for callback user data
35 struct SVGTextQuery::Data { 37 struct QueryData {
36 Data() 38 QueryData()
37 : isVerticalText(false) 39 : isVerticalText(false)
38 , processedCharacters(0) 40 , processedCharacters(0)
39 , textLayoutObject(0) 41 , textLayoutObject(0)
40 , textBox(0) 42 , textBox(0)
41 { 43 {
42 } 44 }
43 45
44 bool isVerticalText; 46 bool isVerticalText;
45 unsigned processedCharacters; 47 unsigned processedCharacters;
46 LayoutSVGInlineText* textLayoutObject; 48 LayoutSVGInlineText* textLayoutObject;
(...skipping 23 matching lines...) Expand all
70 // LayoutSVGInline only ever contains a single line box. 72 // LayoutSVGInline only ever contains a single line box.
71 InlineFlowBox* flowBox = layoutInline->firstLineBox(); 73 InlineFlowBox* flowBox = layoutInline->firstLineBox();
72 ASSERT(flowBox == layoutInline->lastLineBox()); 74 ASSERT(flowBox == layoutInline->lastLineBox());
73 return flowBox; 75 return flowBox;
74 } 76 }
75 77
76 ASSERT_NOT_REACHED(); 78 ASSERT_NOT_REACHED();
77 return 0; 79 return 0;
78 } 80 }
79 81
80 SVGTextQuery::SVGTextQuery(LayoutObject* layoutObject) 82 static void collectTextBoxesInFlowBox(InlineFlowBox* flowBox, Vector<SVGInlineTe xtBox*>& textBoxes)
81 {
82 collectTextBoxesInFlowBox(flowBoxForLayoutObject(layoutObject));
83 }
84
85 void SVGTextQuery::collectTextBoxesInFlowBox(InlineFlowBox* flowBox)
86 { 83 {
87 if (!flowBox) 84 if (!flowBox)
88 return; 85 return;
89 86
90 for (InlineBox* child = flowBox->firstChild(); child; child = child->nextOnL ine()) { 87 for (InlineBox* child = flowBox->firstChild(); child; child = child->nextOnL ine()) {
91 if (child->isInlineFlowBox()) { 88 if (child->isInlineFlowBox()) {
92 // Skip generated content. 89 // Skip generated content.
93 if (!child->layoutObject().node()) 90 if (!child->layoutObject().node())
94 continue; 91 continue;
95 92
96 collectTextBoxesInFlowBox(toInlineFlowBox(child)); 93 collectTextBoxesInFlowBox(toInlineFlowBox(child), textBoxes);
97 continue; 94 continue;
98 } 95 }
99 96
100 if (child->isSVGInlineTextBox()) 97 if (child->isSVGInlineTextBox())
101 m_textBoxes.append(toSVGInlineTextBox(child)); 98 textBoxes.append(toSVGInlineTextBox(child));
102 } 99 }
103 } 100 }
104 101
105 bool SVGTextQuery::executeQuery(Data* queryData, ProcessTextFragmentCallback fra gmentCallback) const 102 typedef bool ProcessTextFragmentCallback(QueryData*, const SVGTextFragment&);
103
104 static bool executeQuery(LayoutObject* queryRoot, QueryData* queryData, ProcessT extFragmentCallback fragmentCallback)
106 { 105 {
106 Vector<SVGInlineTextBox*> textBoxes;
107 collectTextBoxesInFlowBox(flowBoxForLayoutObject(queryRoot), textBoxes);
108
107 unsigned processedCharacters = 0; 109 unsigned processedCharacters = 0;
108 unsigned textBoxCount = m_textBoxes.size(); 110 unsigned textBoxCount = textBoxes.size();
109 111
110 // Loop over all text boxes 112 // Loop over all text boxes
111 for (unsigned textBoxPosition = 0; textBoxPosition < textBoxCount; ++textBox Position) { 113 for (unsigned textBoxPosition = 0; textBoxPosition < textBoxCount; ++textBox Position) {
112 queryData->textBox = m_textBoxes.at(textBoxPosition); 114 queryData->textBox = textBoxes[textBoxPosition];
113 queryData->textLayoutObject = &toLayoutSVGInlineText(queryData->textBox- >layoutObject()); 115 queryData->textLayoutObject = &toLayoutSVGInlineText(queryData->textBox- >layoutObject());
114 ASSERT(queryData->textLayoutObject->style()); 116 ASSERT(queryData->textLayoutObject->style());
115 117
116 queryData->isVerticalText = queryData->textLayoutObject->style()->svgSty le().isVerticalWritingMode(); 118 queryData->isVerticalText = queryData->textLayoutObject->style()->svgSty le().isVerticalWritingMode();
117 const Vector<SVGTextFragment>& fragments = queryData->textBox->textFragm ents(); 119 const Vector<SVGTextFragment>& fragments = queryData->textBox->textFragm ents();
118 120
119 // Loop over all text fragments in this text box, firing a callback for each. 121 // Loop over all text fragments in this text box, firing a callback for each.
120 unsigned fragmentCount = fragments.size(); 122 unsigned fragmentCount = fragments.size();
121 for (unsigned i = 0; i < fragmentCount; ++i) { 123 for (unsigned i = 0; i < fragmentCount; ++i) {
122 const SVGTextFragment& fragment = fragments.at(i); 124 const SVGTextFragment& fragment = fragments.at(i);
123 if ((this->*fragmentCallback)(queryData, fragment)) 125 if (fragmentCallback(queryData, fragment))
124 return true; 126 return true;
125 127
126 processedCharacters += fragment.length; 128 processedCharacters += fragment.length;
127 } 129 }
128 130
129 queryData->processedCharacters = processedCharacters; 131 queryData->processedCharacters = processedCharacters;
130 } 132 }
131
132 return false; 133 return false;
133 } 134 }
134 135
135 bool SVGTextQuery::mapStartEndPositionsIntoFragmentCoordinates(Data* queryData, const SVGTextFragment& fragment, int& startPosition, int& endPosition) const 136 static void modifyStartEndPositionsRespectingLigatures(const QueryData* queryDat a, const SVGTextFragment& fragment, int& startPosition, int& endPosition)
136 {
137 // Make <startPosition, endPosition> offsets relative to the current text bo x.
138 startPosition -= queryData->processedCharacters;
139 endPosition -= queryData->processedCharacters;
140
141 // Reuse the same logic used for text selection & painting, to map our
142 // query start/length into start/endPositions of the current text fragment.
143 if (!queryData->textBox->mapStartEndPositionsIntoFragmentCoordinates(fragmen t, startPosition, endPosition))
144 return false;
145
146 modifyStartEndPositionsRespectingLigatures(queryData, fragment, startPositio n, endPosition);
147 ASSERT(startPosition < endPosition);
148 return true;
149 }
150
151 void SVGTextQuery::modifyStartEndPositionsRespectingLigatures(Data* queryData, c onst SVGTextFragment& fragment, int& startPosition, int& endPosition) const
152 { 137 {
153 const Vector<SVGTextMetrics>& textMetricsValues = queryData->textLayoutObjec t->layoutAttributes()->textMetricsValues(); 138 const Vector<SVGTextMetrics>& textMetricsValues = queryData->textLayoutObjec t->layoutAttributes()->textMetricsValues();
154 139
155 unsigned textMetricsOffset = fragment.metricsListOffset; 140 unsigned textMetricsOffset = fragment.metricsListOffset;
156 int fragmentOffset = 0; 141 int fragmentOffset = 0;
157 int fragmentEnd = static_cast<int>(fragment.length); 142 int fragmentEnd = static_cast<int>(fragment.length);
158 143
159 // Find the text metrics cell that start at or contain the character startPo sition. 144 // Find the text metrics cell that start at or contain the character startPo sition.
160 while (fragmentOffset < fragmentEnd) { 145 while (fragmentOffset < fragmentEnd) {
161 const SVGTextMetrics& metrics = textMetricsValues[textMetricsOffset]; 146 const SVGTextMetrics& metrics = textMetricsValues[textMetricsOffset];
(...skipping 11 matching lines...) Expand all
173 const SVGTextMetrics& metrics = textMetricsValues[textMetricsOffset]; 158 const SVGTextMetrics& metrics = textMetricsValues[textMetricsOffset];
174 fragmentOffset += metrics.length(); 159 fragmentOffset += metrics.length();
175 if (fragmentOffset >= endPosition) 160 if (fragmentOffset >= endPosition)
176 break; 161 break;
177 textMetricsOffset++; 162 textMetricsOffset++;
178 } 163 }
179 164
180 endPosition = fragmentOffset; 165 endPosition = fragmentOffset;
181 } 166 }
182 167
168 static bool mapStartEndPositionsIntoFragmentCoordinates(const QueryData* queryDa ta, const SVGTextFragment& fragment, int& startPosition, int& endPosition)
169 {
170 // Make <startPosition, endPosition> offsets relative to the current text bo x.
171 startPosition -= queryData->processedCharacters;
172 endPosition -= queryData->processedCharacters;
173
174 // Reuse the same logic used for text selection & painting, to map our
175 // query start/length into start/endPositions of the current text fragment.
176 if (!queryData->textBox->mapStartEndPositionsIntoFragmentCoordinates(fragmen t, startPosition, endPosition))
177 return false;
178
179 modifyStartEndPositionsRespectingLigatures(queryData, fragment, startPositio n, endPosition);
180 ASSERT(startPosition < endPosition);
181 return true;
182 }
183
183 // numberOfCharacters() implementation 184 // numberOfCharacters() implementation
184 bool SVGTextQuery::numberOfCharactersCallback(Data*, const SVGTextFragment&) con st 185 static bool numberOfCharactersCallback(QueryData*, const SVGTextFragment&)
185 { 186 {
186 // no-op 187 // no-op
187 return false; 188 return false;
188 } 189 }
189 190
190 unsigned SVGTextQuery::numberOfCharacters() const 191 unsigned SVGTextQuery::numberOfCharacters() const
191 { 192 {
192 Data data; 193 QueryData data;
193 executeQuery(&data, &SVGTextQuery::numberOfCharactersCallback); 194 executeQuery(m_queryRootLayoutObject, &data, numberOfCharactersCallback);
194 return data.processedCharacters; 195 return data.processedCharacters;
195 } 196 }
196 197
197 // textLength() implementation 198 // textLength() implementation
198 struct TextLengthData : SVGTextQuery::Data { 199 struct TextLengthData : QueryData {
199 TextLengthData() 200 TextLengthData()
200 : textLength(0) 201 : textLength(0)
201 { 202 {
202 } 203 }
203 204
204 float textLength; 205 float textLength;
205 }; 206 };
206 207
207 bool SVGTextQuery::textLengthCallback(Data* queryData, const SVGTextFragment& fr agment) const 208 static bool textLengthCallback(QueryData* queryData, const SVGTextFragment& frag ment)
208 { 209 {
209 TextLengthData* data = static_cast<TextLengthData*>(queryData); 210 TextLengthData* data = static_cast<TextLengthData*>(queryData);
210 data->textLength += queryData->isVerticalText ? fragment.height : fragment.w idth; 211 data->textLength += queryData->isVerticalText ? fragment.height : fragment.w idth;
211 return false; 212 return false;
212 } 213 }
213 214
214 float SVGTextQuery::textLength() const 215 float SVGTextQuery::textLength() const
215 { 216 {
216 TextLengthData data; 217 TextLengthData data;
217 executeQuery(&data, &SVGTextQuery::textLengthCallback); 218 executeQuery(m_queryRootLayoutObject, &data, textLengthCallback);
218 return data.textLength; 219 return data.textLength;
219 } 220 }
220 221
221 // subStringLength() implementation 222 // subStringLength() implementation
222 struct SubStringLengthData : SVGTextQuery::Data { 223 struct SubStringLengthData : QueryData {
223 SubStringLengthData(unsigned queryStartPosition, unsigned queryLength) 224 SubStringLengthData(unsigned queryStartPosition, unsigned queryLength)
224 : startPosition(queryStartPosition) 225 : startPosition(queryStartPosition)
225 , length(queryLength) 226 , length(queryLength)
226 , subStringLength(0) 227 , subStringLength(0)
227 { 228 {
228 } 229 }
229 230
230 unsigned startPosition; 231 unsigned startPosition;
231 unsigned length; 232 unsigned length;
232 233
233 float subStringLength; 234 float subStringLength;
234 }; 235 };
235 236
236 bool SVGTextQuery::subStringLengthCallback(Data* queryData, const SVGTextFragmen t& fragment) const 237 static bool subStringLengthCallback(QueryData* queryData, const SVGTextFragment& fragment)
237 { 238 {
238 SubStringLengthData* data = static_cast<SubStringLengthData*>(queryData); 239 SubStringLengthData* data = static_cast<SubStringLengthData*>(queryData);
239 240
240 int startPosition = data->startPosition; 241 int startPosition = data->startPosition;
241 int endPosition = startPosition + data->length; 242 int endPosition = startPosition + data->length;
242 if (!mapStartEndPositionsIntoFragmentCoordinates(queryData, fragment, startP osition, endPosition)) 243 if (!mapStartEndPositionsIntoFragmentCoordinates(queryData, fragment, startP osition, endPosition))
243 return false; 244 return false;
244 245
245 SVGTextMetrics metrics = SVGTextMetrics::measureCharacterRange(queryData->te xtLayoutObject, fragment.characterOffset + startPosition, endPosition - startPos ition, queryData->textBox->direction()); 246 SVGTextMetrics metrics = SVGTextMetrics::measureCharacterRange(queryData->te xtLayoutObject, fragment.characterOffset + startPosition, endPosition - startPos ition, queryData->textBox->direction());
246 data->subStringLength += queryData->isVerticalText ? metrics.height() : metr ics.width(); 247 data->subStringLength += queryData->isVerticalText ? metrics.height() : metr ics.width();
247 return false; 248 return false;
248 } 249 }
249 250
250 float SVGTextQuery::subStringLength(unsigned startPosition, unsigned length) con st 251 float SVGTextQuery::subStringLength(unsigned startPosition, unsigned length) con st
251 { 252 {
252 SubStringLengthData data(startPosition, length); 253 SubStringLengthData data(startPosition, length);
253 executeQuery(&data, &SVGTextQuery::subStringLengthCallback); 254 executeQuery(m_queryRootLayoutObject, &data, subStringLengthCallback);
254 return data.subStringLength; 255 return data.subStringLength;
255 } 256 }
256 257
257 // startPositionOfCharacter() implementation 258 // startPositionOfCharacter() implementation
258 struct StartPositionOfCharacterData : SVGTextQuery::Data { 259 struct StartPositionOfCharacterData : QueryData {
259 StartPositionOfCharacterData(unsigned queryPosition) 260 StartPositionOfCharacterData(unsigned queryPosition)
260 : position(queryPosition) 261 : position(queryPosition)
261 { 262 {
262 } 263 }
263 264
264 unsigned position; 265 unsigned position;
265 FloatPoint startPosition; 266 FloatPoint startPosition;
266 }; 267 };
267 268
268 static FloatPoint calculateGlyphPositionWithoutTransform(const SVGTextQuery::Dat a* queryData, const SVGTextFragment& fragment, int offsetInFragment) 269 static FloatPoint calculateGlyphPositionWithoutTransform(const QueryData* queryD ata, const SVGTextFragment& fragment, int offsetInFragment)
269 { 270 {
270 float glyphOffsetInDirection = 0; 271 float glyphOffsetInDirection = 0;
271 if (offsetInFragment) { 272 if (offsetInFragment) {
272 SVGTextMetrics metrics = SVGTextMetrics::measureCharacterRange(queryData ->textLayoutObject, fragment.characterOffset, offsetInFragment, queryData->textB ox->direction()); 273 SVGTextMetrics metrics = SVGTextMetrics::measureCharacterRange(queryData ->textLayoutObject, fragment.characterOffset, offsetInFragment, queryData->textB ox->direction());
273 if (queryData->isVerticalText) 274 if (queryData->isVerticalText)
274 glyphOffsetInDirection = metrics.height(); 275 glyphOffsetInDirection = metrics.height();
275 else 276 else
276 glyphOffsetInDirection = metrics.width(); 277 glyphOffsetInDirection = metrics.width();
277 } 278 }
278 279
279 if (!queryData->textBox->isLeftToRightDirection()) { 280 if (!queryData->textBox->isLeftToRightDirection()) {
280 float fragmentExtent = queryData->isVerticalText ? fragment.height : fra gment.width; 281 float fragmentExtent = queryData->isVerticalText ? fragment.height : fra gment.width;
281 glyphOffsetInDirection = fragmentExtent - glyphOffsetInDirection; 282 glyphOffsetInDirection = fragmentExtent - glyphOffsetInDirection;
282 } 283 }
283 284
284 FloatPoint glyphPosition(fragment.x, fragment.y); 285 FloatPoint glyphPosition(fragment.x, fragment.y);
285 if (queryData->isVerticalText) 286 if (queryData->isVerticalText)
286 glyphPosition.move(0, glyphOffsetInDirection); 287 glyphPosition.move(0, glyphOffsetInDirection);
287 else 288 else
288 glyphPosition.move(glyphOffsetInDirection, 0); 289 glyphPosition.move(glyphOffsetInDirection, 0);
289 290
290 return glyphPosition; 291 return glyphPosition;
291 } 292 }
292 293
293 static FloatPoint calculateGlyphPosition(const SVGTextQuery::Data* queryData, co nst SVGTextFragment& fragment, int offsetInFragment) 294 static FloatPoint calculateGlyphPosition(const QueryData* queryData, const SVGTe xtFragment& fragment, int offsetInFragment)
294 { 295 {
295 FloatPoint glyphPosition = calculateGlyphPositionWithoutTransform(queryData, fragment, offsetInFragment); 296 FloatPoint glyphPosition = calculateGlyphPositionWithoutTransform(queryData, fragment, offsetInFragment);
296 AffineTransform fragmentTransform; 297 AffineTransform fragmentTransform;
297 fragment.buildFragmentTransform(fragmentTransform, SVGTextFragment::Transfor mIgnoringTextLength); 298 fragment.buildFragmentTransform(fragmentTransform, SVGTextFragment::Transfor mIgnoringTextLength);
298 if (!fragmentTransform.isIdentity()) 299 if (!fragmentTransform.isIdentity())
299 glyphPosition = fragmentTransform.mapPoint(glyphPosition); 300 glyphPosition = fragmentTransform.mapPoint(glyphPosition);
300 301
301 return glyphPosition; 302 return glyphPosition;
302 } 303 }
303 304
304 bool SVGTextQuery::startPositionOfCharacterCallback(Data* queryData, const SVGTe xtFragment& fragment) const 305 static bool startPositionOfCharacterCallback(QueryData* queryData, const SVGText Fragment& fragment)
305 { 306 {
306 StartPositionOfCharacterData* data = static_cast<StartPositionOfCharacterDat a*>(queryData); 307 StartPositionOfCharacterData* data = static_cast<StartPositionOfCharacterDat a*>(queryData);
307 308
308 int startPosition = data->position; 309 int startPosition = data->position;
309 int endPosition = startPosition + 1; 310 int endPosition = startPosition + 1;
310 if (!mapStartEndPositionsIntoFragmentCoordinates(queryData, fragment, startP osition, endPosition)) 311 if (!mapStartEndPositionsIntoFragmentCoordinates(queryData, fragment, startP osition, endPosition))
311 return false; 312 return false;
312 313
313 data->startPosition = calculateGlyphPosition(queryData, fragment, startPosit ion); 314 data->startPosition = calculateGlyphPosition(queryData, fragment, startPosit ion);
314 return true; 315 return true;
315 } 316 }
316 317
317 FloatPoint SVGTextQuery::startPositionOfCharacter(unsigned position) const 318 FloatPoint SVGTextQuery::startPositionOfCharacter(unsigned position) const
318 { 319 {
319 StartPositionOfCharacterData data(position); 320 StartPositionOfCharacterData data(position);
320 executeQuery(&data, &SVGTextQuery::startPositionOfCharacterCallback); 321 executeQuery(m_queryRootLayoutObject, &data, startPositionOfCharacterCallbac k);
321 return data.startPosition; 322 return data.startPosition;
322 } 323 }
323 324
324 // endPositionOfCharacter() implementation 325 // endPositionOfCharacter() implementation
325 struct EndPositionOfCharacterData : SVGTextQuery::Data { 326 struct EndPositionOfCharacterData : QueryData {
326 EndPositionOfCharacterData(unsigned queryPosition) 327 EndPositionOfCharacterData(unsigned queryPosition)
327 : position(queryPosition) 328 : position(queryPosition)
328 { 329 {
329 } 330 }
330 331
331 unsigned position; 332 unsigned position;
332 FloatPoint endPosition; 333 FloatPoint endPosition;
333 }; 334 };
334 335
335 bool SVGTextQuery::endPositionOfCharacterCallback(Data* queryData, const SVGText Fragment& fragment) const 336 static bool endPositionOfCharacterCallback(QueryData* queryData, const SVGTextFr agment& fragment)
336 { 337 {
337 EndPositionOfCharacterData* data = static_cast<EndPositionOfCharacterData*>( queryData); 338 EndPositionOfCharacterData* data = static_cast<EndPositionOfCharacterData*>( queryData);
338 339
339 int startPosition = data->position; 340 int startPosition = data->position;
340 int endPosition = startPosition + 1; 341 int endPosition = startPosition + 1;
341 if (!mapStartEndPositionsIntoFragmentCoordinates(queryData, fragment, startP osition, endPosition)) 342 if (!mapStartEndPositionsIntoFragmentCoordinates(queryData, fragment, startP osition, endPosition))
342 return false; 343 return false;
343 344
344 // TODO(fs): mapStartEndPositionsIntoFragmentCoordinates(...) above applies 345 // TODO(fs): mapStartEndPositionsIntoFragmentCoordinates(...) above applies
345 // some heuristics for ligatures, so why not just use endPosition here? 346 // some heuristics for ligatures, so why not just use endPosition here?
346 // (rather than startPosition+1) 347 // (rather than startPosition+1)
347 data->endPosition = calculateGlyphPosition(queryData, fragment, startPositio n + 1); 348 data->endPosition = calculateGlyphPosition(queryData, fragment, startPositio n + 1);
348 return true; 349 return true;
349 } 350 }
350 351
351 FloatPoint SVGTextQuery::endPositionOfCharacter(unsigned position) const 352 FloatPoint SVGTextQuery::endPositionOfCharacter(unsigned position) const
352 { 353 {
353 EndPositionOfCharacterData data(position); 354 EndPositionOfCharacterData data(position);
354 executeQuery(&data, &SVGTextQuery::endPositionOfCharacterCallback); 355 executeQuery(m_queryRootLayoutObject, &data, endPositionOfCharacterCallback) ;
355 return data.endPosition; 356 return data.endPosition;
356 } 357 }
357 358
358 // rotationOfCharacter() implementation 359 // rotationOfCharacter() implementation
359 struct RotationOfCharacterData : SVGTextQuery::Data { 360 struct RotationOfCharacterData : QueryData {
360 RotationOfCharacterData(unsigned queryPosition) 361 RotationOfCharacterData(unsigned queryPosition)
361 : position(queryPosition) 362 : position(queryPosition)
362 , rotation(0) 363 , rotation(0)
363 { 364 {
364 } 365 }
365 366
366 unsigned position; 367 unsigned position;
367 float rotation; 368 float rotation;
368 }; 369 };
369 370
370 bool SVGTextQuery::rotationOfCharacterCallback(Data* queryData, const SVGTextFra gment& fragment) const 371 static bool rotationOfCharacterCallback(QueryData* queryData, const SVGTextFragm ent& fragment)
371 { 372 {
372 RotationOfCharacterData* data = static_cast<RotationOfCharacterData*>(queryD ata); 373 RotationOfCharacterData* data = static_cast<RotationOfCharacterData*>(queryD ata);
373 374
374 int startPosition = data->position; 375 int startPosition = data->position;
375 int endPosition = startPosition + 1; 376 int endPosition = startPosition + 1;
376 if (!mapStartEndPositionsIntoFragmentCoordinates(queryData, fragment, startP osition, endPosition)) 377 if (!mapStartEndPositionsIntoFragmentCoordinates(queryData, fragment, startP osition, endPosition))
377 return false; 378 return false;
378 379
379 AffineTransform fragmentTransform; 380 AffineTransform fragmentTransform;
380 fragment.buildFragmentTransform(fragmentTransform, SVGTextFragment::Transfor mIgnoringTextLength); 381 fragment.buildFragmentTransform(fragmentTransform, SVGTextFragment::Transfor mIgnoringTextLength);
381 if (fragmentTransform.isIdentity()) { 382 if (fragmentTransform.isIdentity()) {
382 data->rotation = 0; 383 data->rotation = 0;
383 } else { 384 } else {
384 fragmentTransform.scale(1 / fragmentTransform.xScale(), 1 / fragmentTran sform.yScale()); 385 fragmentTransform.scale(1 / fragmentTransform.xScale(), 1 / fragmentTran sform.yScale());
385 data->rotation = narrowPrecisionToFloat(rad2deg(atan2(fragmentTransform. b(), fragmentTransform.a()))); 386 data->rotation = narrowPrecisionToFloat(rad2deg(atan2(fragmentTransform. b(), fragmentTransform.a())));
386 } 387 }
387 388
388 return true; 389 return true;
389 } 390 }
390 391
391 float SVGTextQuery::rotationOfCharacter(unsigned position) const 392 float SVGTextQuery::rotationOfCharacter(unsigned position) const
392 { 393 {
393 RotationOfCharacterData data(position); 394 RotationOfCharacterData data(position);
394 executeQuery(&data, &SVGTextQuery::rotationOfCharacterCallback); 395 executeQuery(m_queryRootLayoutObject, &data, rotationOfCharacterCallback);
395 return data.rotation; 396 return data.rotation;
396 } 397 }
397 398
398 // extentOfCharacter() implementation 399 // extentOfCharacter() implementation
399 struct ExtentOfCharacterData : SVGTextQuery::Data { 400 struct ExtentOfCharacterData : QueryData {
400 ExtentOfCharacterData(unsigned queryPosition) 401 ExtentOfCharacterData(unsigned queryPosition)
401 : position(queryPosition) 402 : position(queryPosition)
402 { 403 {
403 } 404 }
404 405
405 unsigned position; 406 unsigned position;
406 FloatRect extent; 407 FloatRect extent;
407 }; 408 };
408 409
409 const SVGTextMetrics& findMetricsForCharacter(const Vector<SVGTextMetrics>& text MetricsValues, const SVGTextFragment& fragment, unsigned startInFragment) 410 const SVGTextMetrics& findMetricsForCharacter(const Vector<SVGTextMetrics>& text MetricsValues, const SVGTextFragment& fragment, unsigned startInFragment)
410 { 411 {
411 // Find the text metrics cell that start at or contain the character at |sta rtInFragment|. 412 // Find the text metrics cell that start at or contain the character at |sta rtInFragment|.
412 unsigned textMetricsOffset = fragment.metricsListOffset; 413 unsigned textMetricsOffset = fragment.metricsListOffset;
413 unsigned fragmentOffset = 0; 414 unsigned fragmentOffset = 0;
414 while (fragmentOffset < fragment.length) { 415 while (fragmentOffset < fragment.length) {
415 const SVGTextMetrics& metrics = textMetricsValues[textMetricsOffset++]; 416 const SVGTextMetrics& metrics = textMetricsValues[textMetricsOffset++];
416 unsigned glyphEnd = fragmentOffset + metrics.length(); 417 unsigned glyphEnd = fragmentOffset + metrics.length();
417 if (startInFragment < glyphEnd) 418 if (startInFragment < glyphEnd)
418 break; 419 break;
419 fragmentOffset = glyphEnd; 420 fragmentOffset = glyphEnd;
420 } 421 }
421 return textMetricsValues[textMetricsOffset - 1]; 422 return textMetricsValues[textMetricsOffset - 1];
422 } 423 }
423 424
424 static inline void calculateGlyphBoundaries(SVGTextQuery::Data* queryData, const SVGTextFragment& fragment, int startPosition, FloatRect& extent) 425 static inline void calculateGlyphBoundaries(const QueryData* queryData, const SV GTextFragment& fragment, int startPosition, FloatRect& extent)
425 { 426 {
426 float scalingFactor = queryData->textLayoutObject->scalingFactor(); 427 float scalingFactor = queryData->textLayoutObject->scalingFactor();
427 ASSERT(scalingFactor); 428 ASSERT(scalingFactor);
428 429
429 FloatPoint glyphPosition = calculateGlyphPositionWithoutTransform(queryData, fragment, startPosition); 430 FloatPoint glyphPosition = calculateGlyphPositionWithoutTransform(queryData, fragment, startPosition);
430 glyphPosition.move(0, -queryData->textLayoutObject->scaledFont().fontMetrics ().floatAscent() / scalingFactor); 431 glyphPosition.move(0, -queryData->textLayoutObject->scaledFont().fontMetrics ().floatAscent() / scalingFactor);
431 extent.setLocation(glyphPosition); 432 extent.setLocation(glyphPosition);
432 433
433 // Use the SVGTextMetrics computed by SVGTextMetricsBuilder (which spends 434 // Use the SVGTextMetrics computed by SVGTextMetricsBuilder (which spends
434 // time attempting to compute more correct glyph bounds already, handling 435 // time attempting to compute more correct glyph bounds already, handling
(...skipping 25 matching lines...) Expand all
460 float scalingFactor = textLayoutObject.scalingFactor(); 461 float scalingFactor = textLayoutObject.scalingFactor();
461 ASSERT(scalingFactor); 462 ASSERT(scalingFactor);
462 float baseline = textLayoutObject.scaledFont().fontMetrics().floatAscent() / scalingFactor; 463 float baseline = textLayoutObject.scaledFont().fontMetrics().floatAscent() / scalingFactor;
463 464
464 AffineTransform fragmentTransform; 465 AffineTransform fragmentTransform;
465 FloatRect fragmentRect(fragment.x, fragment.y - baseline, fragment.width, fr agment.height); 466 FloatRect fragmentRect(fragment.x, fragment.y - baseline, fragment.width, fr agment.height);
466 fragment.buildFragmentTransform(fragmentTransform); 467 fragment.buildFragmentTransform(fragmentTransform);
467 return fragmentTransform.mapRect(fragmentRect); 468 return fragmentTransform.mapRect(fragmentRect);
468 } 469 }
469 470
470 bool SVGTextQuery::extentOfCharacterCallback(Data* queryData, const SVGTextFragm ent& fragment) const 471 static bool extentOfCharacterCallback(QueryData* queryData, const SVGTextFragmen t& fragment)
471 { 472 {
472 ExtentOfCharacterData* data = static_cast<ExtentOfCharacterData*>(queryData) ; 473 ExtentOfCharacterData* data = static_cast<ExtentOfCharacterData*>(queryData) ;
473 474
474 int startPosition = data->position; 475 int startPosition = data->position;
475 int endPosition = startPosition + 1; 476 int endPosition = startPosition + 1;
476 if (!mapStartEndPositionsIntoFragmentCoordinates(queryData, fragment, startP osition, endPosition)) 477 if (!mapStartEndPositionsIntoFragmentCoordinates(queryData, fragment, startP osition, endPosition))
477 return false; 478 return false;
478 479
479 calculateGlyphBoundaries(queryData, fragment, startPosition, data->extent); 480 calculateGlyphBoundaries(queryData, fragment, startPosition, data->extent);
480 return true; 481 return true;
481 } 482 }
482 483
483 FloatRect SVGTextQuery::extentOfCharacter(unsigned position) const 484 FloatRect SVGTextQuery::extentOfCharacter(unsigned position) const
484 { 485 {
485 ExtentOfCharacterData data(position); 486 ExtentOfCharacterData data(position);
486 executeQuery(&data, &SVGTextQuery::extentOfCharacterCallback); 487 executeQuery(m_queryRootLayoutObject, &data, extentOfCharacterCallback);
487 return data.extent; 488 return data.extent;
488 } 489 }
489 490
490 // characterNumberAtPosition() implementation 491 // characterNumberAtPosition() implementation
491 struct CharacterNumberAtPositionData : SVGTextQuery::Data { 492 struct CharacterNumberAtPositionData : QueryData {
492 CharacterNumberAtPositionData(const FloatPoint& queryPosition) 493 CharacterNumberAtPositionData(const FloatPoint& queryPosition)
493 : position(queryPosition) 494 : position(queryPosition)
494 { 495 {
495 } 496 }
496 497
497 FloatPoint position; 498 FloatPoint position;
498 }; 499 };
499 500
500 bool SVGTextQuery::characterNumberAtPositionCallback(Data* queryData, const SVGT extFragment& fragment) const 501 static bool characterNumberAtPositionCallback(QueryData* queryData, const SVGTex tFragment& fragment)
501 { 502 {
502 CharacterNumberAtPositionData* data = static_cast<CharacterNumberAtPositionD ata*>(queryData); 503 CharacterNumberAtPositionData* data = static_cast<CharacterNumberAtPositionD ata*>(queryData);
503 504
504 // Test the query point against the bounds of the entire fragment first. 505 // Test the query point against the bounds of the entire fragment first.
505 FloatRect fragmentExtents = calculateFragmentBoundaries(*queryData->textLayo utObject, fragment); 506 FloatRect fragmentExtents = calculateFragmentBoundaries(*queryData->textLayo utObject, fragment);
506 if (!fragmentExtents.contains(data->position)) 507 if (!fragmentExtents.contains(data->position))
507 return false; 508 return false;
508 509
509 // Iterate through the glyphs in this fragment, and check if their extents 510 // Iterate through the glyphs in this fragment, and check if their extents
510 // contain the query point. 511 // contain the query point.
(...skipping 12 matching lines...) Expand all
523 } 524 }
524 fragmentOffset += textMetrics[textMetricsOffset].length(); 525 fragmentOffset += textMetrics[textMetricsOffset].length();
525 textMetricsOffset++; 526 textMetricsOffset++;
526 } 527 }
527 return false; 528 return false;
528 } 529 }
529 530
530 int SVGTextQuery::characterNumberAtPosition(const FloatPoint& position) const 531 int SVGTextQuery::characterNumberAtPosition(const FloatPoint& position) const
531 { 532 {
532 CharacterNumberAtPositionData data(position); 533 CharacterNumberAtPositionData data(position);
533 if (!executeQuery(&data, &SVGTextQuery::characterNumberAtPositionCallback)) 534 if (!executeQuery(m_queryRootLayoutObject, &data, characterNumberAtPositionC allback))
534 return -1; 535 return -1;
535 536
536 return data.processedCharacters; 537 return data.processedCharacters;
537 } 538 }
538 539
539 } 540 }
OLDNEW
« Source/core/layout/svg/SVGTextQuery.h ('K') | « Source/core/layout/svg/SVGTextQuery.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698