| 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 |