| 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 441 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 452 struct ExtentOfCharacterData : QueryData { | 452 struct ExtentOfCharacterData : QueryData { |
| 453 ExtentOfCharacterData(unsigned queryPosition) | 453 ExtentOfCharacterData(unsigned queryPosition) |
| 454 : position(queryPosition) | 454 : position(queryPosition) |
| 455 { | 455 { |
| 456 } | 456 } |
| 457 | 457 |
| 458 unsigned position; | 458 unsigned position; |
| 459 FloatRect extent; | 459 FloatRect extent; |
| 460 }; | 460 }; |
| 461 | 461 |
| 462 static inline void calculateGlyphBoundaries(const QueryData* queryData, const SV
GTextFragment& fragment, int startPosition, FloatRect& extent) | 462 static inline FloatRect calculateGlyphBoundaries(const QueryData* queryData, con
st SVGTextFragment& fragment, int startPosition) |
| 463 { | 463 { |
| 464 float scalingFactor = queryData->textLineLayout.scalingFactor(); | 464 float scalingFactor = queryData->textLineLayout.scalingFactor(); |
| 465 ASSERT(scalingFactor); | 465 ASSERT(scalingFactor); |
| 466 | 466 |
| 467 FloatPoint glyphPosition = calculateGlyphPositionWithoutTransform(queryData,
fragment, startPosition); | 467 FloatPoint glyphPosition = calculateGlyphPositionWithoutTransform(queryData,
fragment, startPosition); |
| 468 glyphPosition.move(0, -queryData->textLineLayout.scaledFont().getFontMetrics
().floatAscent() / scalingFactor); | 468 glyphPosition.move(0, -queryData->textLineLayout.scaledFont().getFontMetrics
().floatAscent() / scalingFactor); |
| 469 extent.setLocation(glyphPosition); | |
| 470 | 469 |
| 471 // Use the SVGTextMetrics computed by SVGTextMetricsBuilder (which spends | 470 // Use the SVGTextMetrics computed by SVGTextMetricsBuilder (which spends |
| 472 // time attempting to compute more correct glyph bounds already, handling | 471 // time attempting to compute more correct glyph bounds already, handling |
| 473 // cursive scripts to some degree.) | 472 // cursive scripts to some degree.) |
| 474 const Vector<SVGTextMetrics>& textMetricsValues = queryData->textLineLayout.
layoutAttributes()->textMetricsValues(); | 473 const Vector<SVGTextMetrics>& textMetricsValues = queryData->textLineLayout.
layoutAttributes()->textMetricsValues(); |
| 475 const SVGTextMetrics& metrics = findMetricsForCharacter(textMetricsValues, f
ragment, startPosition); | 474 const SVGTextMetrics& metrics = findMetricsForCharacter(textMetricsValues, f
ragment, startPosition); |
| 476 | 475 |
| 477 // TODO(fs): Negative glyph extents seems kind of weird to have, but | 476 // TODO(fs): Negative glyph extents seems kind of weird to have, but |
| 478 // presently it can occur in some cases (like Arabic.) | 477 // presently it can occur in some cases (like Arabic.) |
| 479 FloatSize glyphSize(std::max<float>(metrics.width(), 0), std::max<float>(met
rics.height(), 0)); | 478 FloatSize glyphSize(std::max<float>(metrics.width(), 0), std::max<float>(met
rics.height(), 0)); |
| 480 extent.setSize(glyphSize); | |
| 481 | 479 |
| 482 // If RTL, adjust the starting point to align with the LHS of the glyph boun
ding box. | 480 // If RTL, adjust the starting point to align with the LHS of the glyph boun
ding box. |
| 483 if (!queryData->textBox->isLeftToRightDirection()) { | 481 if (!queryData->textBox->isLeftToRightDirection()) { |
| 484 if (queryData->isVerticalText) | 482 if (queryData->isVerticalText) |
| 485 extent.move(0, -glyphSize.height()); | 483 glyphPosition.move(0, -glyphSize.height()); |
| 486 else | 484 else |
| 487 extent.move(-glyphSize.width(), 0); | 485 glyphPosition.move(-glyphSize.width(), 0); |
| 488 } | 486 } |
| 489 | 487 |
| 488 FloatRect extent(glyphPosition, glyphSize); |
| 490 if (fragment.isTransformed()) { | 489 if (fragment.isTransformed()) { |
| 491 AffineTransform fragmentTransform = fragment.buildFragmentTransform(SVGT
extFragment::TransformIgnoringTextLength); | 490 AffineTransform fragmentTransform = fragment.buildFragmentTransform(SVGT
extFragment::TransformIgnoringTextLength); |
| 492 extent = fragmentTransform.mapRect(extent); | 491 extent = fragmentTransform.mapRect(extent); |
| 493 } | 492 } |
| 493 return extent; |
| 494 } | 494 } |
| 495 | 495 |
| 496 static inline FloatRect calculateFragmentBoundaries(LineLayoutSVGInlineText text
LineLayout, const SVGTextFragment& fragment) | 496 static inline FloatRect calculateFragmentBoundaries(LineLayoutSVGInlineText text
LineLayout, const SVGTextFragment& fragment) |
| 497 { | 497 { |
| 498 float scalingFactor = textLineLayout.scalingFactor(); | 498 float scalingFactor = textLineLayout.scalingFactor(); |
| 499 ASSERT(scalingFactor); | 499 ASSERT(scalingFactor); |
| 500 float baseline = textLineLayout.scaledFont().getFontMetrics().floatAscent()
/ scalingFactor; | 500 float baseline = textLineLayout.scaledFont().getFontMetrics().floatAscent()
/ scalingFactor; |
| 501 return fragment.boundingBox(baseline); | 501 return fragment.boundingBox(baseline); |
| 502 } | 502 } |
| 503 | 503 |
| 504 static bool extentOfCharacterCallback(QueryData* queryData, const SVGTextFragmen
t& fragment) | 504 static bool extentOfCharacterCallback(QueryData* queryData, const SVGTextFragmen
t& fragment) |
| 505 { | 505 { |
| 506 ExtentOfCharacterData* data = static_cast<ExtentOfCharacterData*>(queryData)
; | 506 ExtentOfCharacterData* data = static_cast<ExtentOfCharacterData*>(queryData)
; |
| 507 | 507 |
| 508 int startPosition = data->position; | 508 int startPosition = data->position; |
| 509 int endPosition = startPosition + 1; | 509 int endPosition = startPosition + 1; |
| 510 if (!mapStartEndPositionsIntoFragmentCoordinates(queryData, fragment, startP
osition, endPosition)) | 510 if (!mapStartEndPositionsIntoFragmentCoordinates(queryData, fragment, startP
osition, endPosition)) |
| 511 return false; | 511 return false; |
| 512 | 512 |
| 513 calculateGlyphBoundaries(queryData, fragment, startPosition, data->extent); | 513 data->extent = calculateGlyphBoundaries(queryData, fragment, startPosition); |
| 514 return true; | 514 return true; |
| 515 } | 515 } |
| 516 | 516 |
| 517 FloatRect SVGTextQuery::extentOfCharacter(unsigned position) const | 517 FloatRect SVGTextQuery::extentOfCharacter(unsigned position) const |
| 518 { | 518 { |
| 519 ExtentOfCharacterData data(position); | 519 ExtentOfCharacterData data(position); |
| 520 logicalQuery(m_queryRootLayoutObject, &data, extentOfCharacterCallback); | 520 logicalQuery(m_queryRootLayoutObject, &data, extentOfCharacterCallback); |
| 521 return data.extent; | 521 return data.extent; |
| 522 } | 522 } |
| 523 | 523 |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 578 { | 578 { |
| 579 CharacterNumberAtPositionData* data = static_cast<CharacterNumberAtPositionD
ata*>(queryData); | 579 CharacterNumberAtPositionData* data = static_cast<CharacterNumberAtPositionD
ata*>(queryData); |
| 580 | 580 |
| 581 // Test the query point against the bounds of the entire fragment first. | 581 // Test the query point against the bounds of the entire fragment first. |
| 582 FloatRect fragmentExtents = calculateFragmentBoundaries(queryData->textLineL
ayout, fragment); | 582 FloatRect fragmentExtents = calculateFragmentBoundaries(queryData->textLineL
ayout, fragment); |
| 583 if (!fragmentExtents.contains(data->position)) | 583 if (!fragmentExtents.contains(data->position)) |
| 584 return false; | 584 return false; |
| 585 | 585 |
| 586 // Iterate through the glyphs in this fragment, and check if their extents | 586 // Iterate through the glyphs in this fragment, and check if their extents |
| 587 // contain the query point. | 587 // contain the query point. |
| 588 FloatRect extent; | |
| 589 const Vector<SVGTextMetrics>& textMetrics = queryData->textLineLayout.layout
Attributes()->textMetricsValues(); | 588 const Vector<SVGTextMetrics>& textMetrics = queryData->textLineLayout.layout
Attributes()->textMetricsValues(); |
| 590 unsigned textMetricsOffset = fragment.metricsListOffset; | 589 unsigned textMetricsOffset = fragment.metricsListOffset; |
| 591 unsigned fragmentOffset = 0; | 590 unsigned fragmentOffset = 0; |
| 592 while (fragmentOffset < fragment.length) { | 591 while (fragmentOffset < fragment.length) { |
| 593 calculateGlyphBoundaries(queryData, fragment, fragmentOffset, extent); | 592 FloatRect extent = calculateGlyphBoundaries(queryData, fragment, fragmen
tOffset); |
| 594 if (extent.contains(data->position)) { | 593 if (extent.contains(data->position)) { |
| 595 // Compute the character offset of the glyph within the text node. | 594 // Compute the character offset of the glyph within the text node. |
| 596 unsigned offsetInBox = fragment.characterOffset - queryData->textBox
->start() + fragmentOffset; | 595 unsigned offsetInBox = fragment.characterOffset - queryData->textBox
->start() + fragmentOffset; |
| 597 data->offsetInTextNode = logicalOffsetInTextNode(queryData->textLine
Layout, queryData->textBox, offsetInBox); | 596 data->offsetInTextNode = logicalOffsetInTextNode(queryData->textLine
Layout, queryData->textBox, offsetInBox); |
| 598 data->hitLayoutItem = LineLayoutItem(data->textLineLayout); | 597 data->hitLayoutItem = LineLayoutItem(data->textLineLayout); |
| 599 return true; | 598 return true; |
| 600 } | 599 } |
| 601 fragmentOffset += textMetrics[textMetricsOffset].length(); | 600 fragmentOffset += textMetrics[textMetricsOffset].length(); |
| 602 textMetricsOffset++; | 601 textMetricsOffset++; |
| 603 } | 602 } |
| 604 return false; | 603 return false; |
| 605 } | 604 } |
| 606 | 605 |
| 607 int SVGTextQuery::characterNumberAtPosition(const FloatPoint& position) const | 606 int SVGTextQuery::characterNumberAtPosition(const FloatPoint& position) const |
| 608 { | 607 { |
| 609 CharacterNumberAtPositionData data(position); | 608 CharacterNumberAtPositionData data(position); |
| 610 spatialQuery(m_queryRootLayoutObject, &data, characterNumberAtPositionCallba
ck); | 609 spatialQuery(m_queryRootLayoutObject, &data, characterNumberAtPositionCallba
ck); |
| 611 return data.characterNumberWithin(m_queryRootLayoutObject); | 610 return data.characterNumberWithin(m_queryRootLayoutObject); |
| 612 } | 611 } |
| 613 | 612 |
| 614 } // namespace blink | 613 } // namespace blink |
| OLD | NEW |