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 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
112 continue; | 112 continue; |
113 } | 113 } |
114 | 114 |
115 if (child->isSVGInlineTextBox()) | 115 if (child->isSVGInlineTextBox()) |
116 m_textBoxes.append(toSVGInlineTextBox(child)); | 116 m_textBoxes.append(toSVGInlineTextBox(child)); |
117 } | 117 } |
118 } | 118 } |
119 | 119 |
120 bool SVGTextQuery::executeQuery(Data* queryData, ProcessTextFragmentCallback fra
gmentCallback) const | 120 bool SVGTextQuery::executeQuery(Data* queryData, ProcessTextFragmentCallback fra
gmentCallback) const |
121 { | 121 { |
122 ASSERT(!m_textBoxes.isEmpty()); | |
123 | |
124 unsigned processedCharacters = 0; | 122 unsigned processedCharacters = 0; |
125 unsigned textBoxCount = m_textBoxes.size(); | 123 unsigned textBoxCount = m_textBoxes.size(); |
126 | 124 |
127 // Loop over all text boxes | 125 // Loop over all text boxes |
128 for (unsigned textBoxPosition = 0; textBoxPosition < textBoxCount; ++textBox
Position) { | 126 for (unsigned textBoxPosition = 0; textBoxPosition < textBoxCount; ++textBox
Position) { |
129 queryData->textBox = m_textBoxes.at(textBoxPosition); | 127 queryData->textBox = m_textBoxes.at(textBoxPosition); |
130 queryData->textRenderer = &toRenderSVGInlineText(queryData->textBox->tex
tRenderer()); | 128 queryData->textRenderer = &toRenderSVGInlineText(queryData->textBox->tex
tRenderer()); |
131 ASSERT(queryData->textRenderer->style()); | 129 ASSERT(queryData->textRenderer->style()); |
132 ASSERT(queryData->textRenderer->style()->svgStyle()); | 130 ASSERT(queryData->textRenderer->style()->svgStyle()); |
133 | 131 |
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
253 | 251 |
254 // numberOfCharacters() implementation | 252 // numberOfCharacters() implementation |
255 bool SVGTextQuery::numberOfCharactersCallback(Data*, const SVGTextFragment&) con
st | 253 bool SVGTextQuery::numberOfCharactersCallback(Data*, const SVGTextFragment&) con
st |
256 { | 254 { |
257 // no-op | 255 // no-op |
258 return false; | 256 return false; |
259 } | 257 } |
260 | 258 |
261 unsigned SVGTextQuery::numberOfCharacters() const | 259 unsigned SVGTextQuery::numberOfCharacters() const |
262 { | 260 { |
263 if (m_textBoxes.isEmpty()) | |
264 return 0; | |
265 | |
266 Data data; | 261 Data data; |
267 executeQuery(&data, &SVGTextQuery::numberOfCharactersCallback); | 262 executeQuery(&data, &SVGTextQuery::numberOfCharactersCallback); |
268 return data.processedCharacters; | 263 return data.processedCharacters; |
269 } | 264 } |
270 | 265 |
271 // textLength() implementation | 266 // textLength() implementation |
272 struct TextLengthData : SVGTextQuery::Data { | 267 struct TextLengthData : SVGTextQuery::Data { |
273 TextLengthData() | 268 TextLengthData() |
274 : textLength(0) | 269 : textLength(0) |
275 { | 270 { |
276 } | 271 } |
277 | 272 |
278 float textLength; | 273 float textLength; |
279 }; | 274 }; |
280 | 275 |
281 bool SVGTextQuery::textLengthCallback(Data* queryData, const SVGTextFragment& fr
agment) const | 276 bool SVGTextQuery::textLengthCallback(Data* queryData, const SVGTextFragment& fr
agment) const |
282 { | 277 { |
283 TextLengthData* data = static_cast<TextLengthData*>(queryData); | 278 TextLengthData* data = static_cast<TextLengthData*>(queryData); |
284 data->textLength += queryData->isVerticalText ? fragment.height : fragment.w
idth; | 279 data->textLength += queryData->isVerticalText ? fragment.height : fragment.w
idth; |
285 return false; | 280 return false; |
286 } | 281 } |
287 | 282 |
288 float SVGTextQuery::textLength() const | 283 float SVGTextQuery::textLength() const |
289 { | 284 { |
290 if (m_textBoxes.isEmpty()) | |
291 return 0; | |
292 | |
293 TextLengthData data; | 285 TextLengthData data; |
294 executeQuery(&data, &SVGTextQuery::textLengthCallback); | 286 executeQuery(&data, &SVGTextQuery::textLengthCallback); |
295 return data.textLength; | 287 return data.textLength; |
296 } | 288 } |
297 | 289 |
298 // subStringLength() implementation | 290 // subStringLength() implementation |
299 struct SubStringLengthData : SVGTextQuery::Data { | 291 struct SubStringLengthData : SVGTextQuery::Data { |
300 SubStringLengthData(unsigned queryStartPosition, unsigned queryLength) | 292 SubStringLengthData(unsigned queryStartPosition, unsigned queryLength) |
301 : startPosition(queryStartPosition) | 293 : startPosition(queryStartPosition) |
302 , length(queryLength) | 294 , length(queryLength) |
(...skipping 16 matching lines...) Expand all Loading... |
319 if (!mapStartEndPositionsIntoFragmentCoordinates(queryData, fragment, startP
osition, endPosition)) | 311 if (!mapStartEndPositionsIntoFragmentCoordinates(queryData, fragment, startP
osition, endPosition)) |
320 return false; | 312 return false; |
321 | 313 |
322 SVGTextMetrics metrics = SVGTextMetrics::measureCharacterRange(queryData->te
xtRenderer, fragment.characterOffset + startPosition, endPosition - startPositio
n); | 314 SVGTextMetrics metrics = SVGTextMetrics::measureCharacterRange(queryData->te
xtRenderer, fragment.characterOffset + startPosition, endPosition - startPositio
n); |
323 data->subStringLength += queryData->isVerticalText ? metrics.height() : metr
ics.width(); | 315 data->subStringLength += queryData->isVerticalText ? metrics.height() : metr
ics.width(); |
324 return false; | 316 return false; |
325 } | 317 } |
326 | 318 |
327 float SVGTextQuery::subStringLength(unsigned startPosition, unsigned length) con
st | 319 float SVGTextQuery::subStringLength(unsigned startPosition, unsigned length) con
st |
328 { | 320 { |
329 if (m_textBoxes.isEmpty()) | |
330 return 0; | |
331 | |
332 SubStringLengthData data(startPosition, length); | 321 SubStringLengthData data(startPosition, length); |
333 executeQuery(&data, &SVGTextQuery::subStringLengthCallback); | 322 executeQuery(&data, &SVGTextQuery::subStringLengthCallback); |
334 return data.subStringLength; | 323 return data.subStringLength; |
335 } | 324 } |
336 | 325 |
337 // startPositionOfCharacter() implementation | 326 // startPositionOfCharacter() implementation |
338 struct StartPositionOfCharacterData : SVGTextQuery::Data { | 327 struct StartPositionOfCharacterData : SVGTextQuery::Data { |
339 StartPositionOfCharacterData(unsigned queryPosition) | 328 StartPositionOfCharacterData(unsigned queryPosition) |
340 : position(queryPosition) | 329 : position(queryPosition) |
341 { | 330 { |
(...skipping 26 matching lines...) Expand all Loading... |
368 fragment.buildFragmentTransform(fragmentTransform, SVGTextFragment::Transfor
mIgnoringTextLength); | 357 fragment.buildFragmentTransform(fragmentTransform, SVGTextFragment::Transfor
mIgnoringTextLength); |
369 if (fragmentTransform.isIdentity()) | 358 if (fragmentTransform.isIdentity()) |
370 return true; | 359 return true; |
371 | 360 |
372 data->startPosition = fragmentTransform.mapPoint(data->startPosition); | 361 data->startPosition = fragmentTransform.mapPoint(data->startPosition); |
373 return true; | 362 return true; |
374 } | 363 } |
375 | 364 |
376 FloatPoint SVGTextQuery::startPositionOfCharacter(unsigned position) const | 365 FloatPoint SVGTextQuery::startPositionOfCharacter(unsigned position) const |
377 { | 366 { |
378 if (m_textBoxes.isEmpty()) | |
379 return FloatPoint(); | |
380 | |
381 StartPositionOfCharacterData data(position); | 367 StartPositionOfCharacterData data(position); |
382 executeQuery(&data, &SVGTextQuery::startPositionOfCharacterCallback); | 368 executeQuery(&data, &SVGTextQuery::startPositionOfCharacterCallback); |
383 return data.startPosition; | 369 return data.startPosition; |
384 } | 370 } |
385 | 371 |
386 // endPositionOfCharacter() implementation | 372 // endPositionOfCharacter() implementation |
387 struct EndPositionOfCharacterData : SVGTextQuery::Data { | 373 struct EndPositionOfCharacterData : SVGTextQuery::Data { |
388 EndPositionOfCharacterData(unsigned queryPosition) | 374 EndPositionOfCharacterData(unsigned queryPosition) |
389 : position(queryPosition) | 375 : position(queryPosition) |
390 { | 376 { |
(...skipping 24 matching lines...) Expand all Loading... |
415 fragment.buildFragmentTransform(fragmentTransform, SVGTextFragment::Transfor
mIgnoringTextLength); | 401 fragment.buildFragmentTransform(fragmentTransform, SVGTextFragment::Transfor
mIgnoringTextLength); |
416 if (fragmentTransform.isIdentity()) | 402 if (fragmentTransform.isIdentity()) |
417 return true; | 403 return true; |
418 | 404 |
419 data->endPosition = fragmentTransform.mapPoint(data->endPosition); | 405 data->endPosition = fragmentTransform.mapPoint(data->endPosition); |
420 return true; | 406 return true; |
421 } | 407 } |
422 | 408 |
423 FloatPoint SVGTextQuery::endPositionOfCharacter(unsigned position) const | 409 FloatPoint SVGTextQuery::endPositionOfCharacter(unsigned position) const |
424 { | 410 { |
425 if (m_textBoxes.isEmpty()) | |
426 return FloatPoint(); | |
427 | |
428 EndPositionOfCharacterData data(position); | 411 EndPositionOfCharacterData data(position); |
429 executeQuery(&data, &SVGTextQuery::endPositionOfCharacterCallback); | 412 executeQuery(&data, &SVGTextQuery::endPositionOfCharacterCallback); |
430 return data.endPosition; | 413 return data.endPosition; |
431 } | 414 } |
432 | 415 |
433 // rotationOfCharacter() implementation | 416 // rotationOfCharacter() implementation |
434 struct RotationOfCharacterData : SVGTextQuery::Data { | 417 struct RotationOfCharacterData : SVGTextQuery::Data { |
435 RotationOfCharacterData(unsigned queryPosition) | 418 RotationOfCharacterData(unsigned queryPosition) |
436 : position(queryPosition) | 419 : position(queryPosition) |
437 , rotation(0) | 420 , rotation(0) |
(...skipping 20 matching lines...) Expand all Loading... |
458 else { | 441 else { |
459 fragmentTransform.scale(1 / fragmentTransform.xScale(), 1 / fragmentTran
sform.yScale()); | 442 fragmentTransform.scale(1 / fragmentTransform.xScale(), 1 / fragmentTran
sform.yScale()); |
460 data->rotation = narrowPrecisionToFloat(rad2deg(atan2(fragmentTransform.
b(), fragmentTransform.a()))); | 443 data->rotation = narrowPrecisionToFloat(rad2deg(atan2(fragmentTransform.
b(), fragmentTransform.a()))); |
461 } | 444 } |
462 | 445 |
463 return true; | 446 return true; |
464 } | 447 } |
465 | 448 |
466 float SVGTextQuery::rotationOfCharacter(unsigned position) const | 449 float SVGTextQuery::rotationOfCharacter(unsigned position) const |
467 { | 450 { |
468 if (m_textBoxes.isEmpty()) | |
469 return 0; | |
470 | |
471 RotationOfCharacterData data(position); | 451 RotationOfCharacterData data(position); |
472 executeQuery(&data, &SVGTextQuery::rotationOfCharacterCallback); | 452 executeQuery(&data, &SVGTextQuery::rotationOfCharacterCallback); |
473 return data.rotation; | 453 return data.rotation; |
474 } | 454 } |
475 | 455 |
476 // extentOfCharacter() implementation | 456 // extentOfCharacter() implementation |
477 struct ExtentOfCharacterData : SVGTextQuery::Data { | 457 struct ExtentOfCharacterData : SVGTextQuery::Data { |
478 ExtentOfCharacterData(unsigned queryPosition) | 458 ExtentOfCharacterData(unsigned queryPosition) |
479 : position(queryPosition) | 459 : position(queryPosition) |
480 { | 460 { |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
516 int endPosition = startPosition + 1; | 496 int endPosition = startPosition + 1; |
517 if (!mapStartEndPositionsIntoFragmentCoordinates(queryData, fragment, startP
osition, endPosition)) | 497 if (!mapStartEndPositionsIntoFragmentCoordinates(queryData, fragment, startP
osition, endPosition)) |
518 return false; | 498 return false; |
519 | 499 |
520 calculateGlyphBoundaries(queryData, fragment, startPosition, data->extent); | 500 calculateGlyphBoundaries(queryData, fragment, startPosition, data->extent); |
521 return true; | 501 return true; |
522 } | 502 } |
523 | 503 |
524 FloatRect SVGTextQuery::extentOfCharacter(unsigned position) const | 504 FloatRect SVGTextQuery::extentOfCharacter(unsigned position) const |
525 { | 505 { |
526 if (m_textBoxes.isEmpty()) | |
527 return FloatRect(); | |
528 | |
529 ExtentOfCharacterData data(position); | 506 ExtentOfCharacterData data(position); |
530 executeQuery(&data, &SVGTextQuery::extentOfCharacterCallback); | 507 executeQuery(&data, &SVGTextQuery::extentOfCharacterCallback); |
531 return data.extent; | 508 return data.extent; |
532 } | 509 } |
533 | 510 |
534 // characterNumberAtPosition() implementation | 511 // characterNumberAtPosition() implementation |
535 struct CharacterNumberAtPositionData : SVGTextQuery::Data { | 512 struct CharacterNumberAtPositionData : SVGTextQuery::Data { |
536 CharacterNumberAtPositionData(const FloatPoint& queryPosition) | 513 CharacterNumberAtPositionData(const FloatPoint& queryPosition) |
537 : position(queryPosition) | 514 : position(queryPosition) |
538 { | 515 { |
(...skipping 22 matching lines...) Expand all Loading... |
561 return true; | 538 return true; |
562 } | 539 } |
563 fragmentOffset += textMetrics[textMetricsOffset].length(); | 540 fragmentOffset += textMetrics[textMetricsOffset].length(); |
564 textMetricsOffset++; | 541 textMetricsOffset++; |
565 } | 542 } |
566 return false; | 543 return false; |
567 } | 544 } |
568 | 545 |
569 int SVGTextQuery::characterNumberAtPosition(const FloatPoint& position) const | 546 int SVGTextQuery::characterNumberAtPosition(const FloatPoint& position) const |
570 { | 547 { |
571 if (m_textBoxes.isEmpty()) | |
572 return -1; | |
573 | |
574 CharacterNumberAtPositionData data(position); | 548 CharacterNumberAtPositionData data(position); |
575 if (!executeQuery(&data, &SVGTextQuery::characterNumberAtPositionCallback)) | 549 if (!executeQuery(&data, &SVGTextQuery::characterNumberAtPositionCallback)) |
576 return -1; | 550 return -1; |
577 | 551 |
578 return data.processedCharacters; | 552 return data.processedCharacters; |
579 } | 553 } |
580 | 554 |
581 } | 555 } |
OLD | NEW |