| Index: third_party/WebKit/Source/core/layout/svg/SVGTextQuery.cpp
|
| diff --git a/third_party/WebKit/Source/core/layout/svg/SVGTextQuery.cpp b/third_party/WebKit/Source/core/layout/svg/SVGTextQuery.cpp
|
| index 8c3173e3171fb19055ac71e968374813c92f7cd8..d1670c7da4a082ffa86ecd56be4db95cc6898b2f 100644
|
| --- a/third_party/WebKit/Source/core/layout/svg/SVGTextQuery.cpp
|
| +++ b/third_party/WebKit/Source/core/layout/svg/SVGTextQuery.cpp
|
| @@ -293,27 +293,27 @@ struct StartPositionOfCharacterData : QueryData {
|
| FloatPoint startPosition;
|
| };
|
|
|
| -static FloatPoint calculateGlyphPositionWithoutTransform(const QueryData* queryData, const SVGTextFragment& fragment, unsigned offsetInFragment)
|
| +static FloatPoint logicalGlyphPositionToPhysical(const QueryData* queryData, const SVGTextFragment& fragment, float logicalGlyphOffset)
|
| {
|
| - float glyphOffsetInDirection = calculateGlyphRange(queryData, fragment, 0, offsetInFragment);
|
| -
|
| + float physicalGlyphOffset = logicalGlyphOffset;
|
| if (!queryData->textBox->isLeftToRightDirection()) {
|
| float fragmentExtent = queryData->isVerticalText ? fragment.height : fragment.width;
|
| - glyphOffsetInDirection = fragmentExtent - glyphOffsetInDirection;
|
| + physicalGlyphOffset = fragmentExtent - logicalGlyphOffset;
|
| }
|
|
|
| FloatPoint glyphPosition(fragment.x, fragment.y);
|
| if (queryData->isVerticalText)
|
| - glyphPosition.move(0, glyphOffsetInDirection);
|
| + glyphPosition.move(0, physicalGlyphOffset);
|
| else
|
| - glyphPosition.move(glyphOffsetInDirection, 0);
|
| + glyphPosition.move(physicalGlyphOffset, 0);
|
|
|
| return glyphPosition;
|
| }
|
|
|
| static FloatPoint calculateGlyphPosition(const QueryData* queryData, const SVGTextFragment& fragment, unsigned offsetInFragment)
|
| {
|
| - FloatPoint glyphPosition = calculateGlyphPositionWithoutTransform(queryData, fragment, offsetInFragment);
|
| + float glyphOffsetInDirection = calculateGlyphRange(queryData, fragment, 0, offsetInFragment);
|
| + FloatPoint glyphPosition = logicalGlyphPositionToPhysical(queryData, fragment, glyphOffsetInDirection);
|
| if (fragment.isTransformed()) {
|
| AffineTransform fragmentTransform = fragment.buildFragmentTransform(SVGTextFragment::TransformIgnoringTextLength);
|
| glyphPosition = fragmentTransform.mapPoint(glyphPosition);
|
| @@ -421,33 +421,39 @@ struct ExtentOfCharacterData : QueryData {
|
| FloatRect extent;
|
| };
|
|
|
| -static inline FloatRect calculateGlyphBoundaries(const QueryData* queryData, const SVGTextFragment& fragment, int startPosition)
|
| +static FloatRect physicalGlyphExtents(const QueryData* queryData, const SVGTextMetrics& metrics, const FloatPoint& glyphPosition)
|
| {
|
| - float scalingFactor = queryData->textLineLayout.scalingFactor();
|
| - ASSERT(scalingFactor);
|
| -
|
| - FloatPoint glyphPosition = calculateGlyphPositionWithoutTransform(queryData, fragment, startPosition);
|
| - glyphPosition.move(0, -queryData->textLineLayout.scaledFont().getFontMetrics().floatAscent() / scalingFactor);
|
| -
|
| - // Use the SVGTextMetrics computed by SVGTextMetricsBuilder (which spends
|
| - // time attempting to compute more correct glyph bounds already, handling
|
| - // cursive scripts to some degree.)
|
| - const MetricsList& textMetricsValues = queryData->textLineLayout.layoutAttributes()->textMetricsValues();
|
| - auto metrics = findMetricsForCharacter(textMetricsValues, fragment, startPosition);
|
| -
|
| // TODO(fs): Negative glyph extents seems kind of weird to have, but
|
| // presently it can occur in some cases (like Arabic.)
|
| - FloatSize glyphSize(std::max<float>(metrics->width(), 0), std::max<float>(metrics->height(), 0));
|
| + FloatRect glyphExtents(
|
| + glyphPosition,
|
| + FloatSize(std::max<float>(metrics.width(), 0), std::max<float>(metrics.height(), 0)));
|
|
|
| // If RTL, adjust the starting point to align with the LHS of the glyph bounding box.
|
| if (!queryData->textBox->isLeftToRightDirection()) {
|
| if (queryData->isVerticalText)
|
| - glyphPosition.move(0, -glyphSize.height());
|
| + glyphExtents.move(0, -glyphExtents.height());
|
| else
|
| - glyphPosition.move(-glyphSize.width(), 0);
|
| + glyphExtents.move(-glyphExtents.width(), 0);
|
| }
|
| + return glyphExtents;
|
| +}
|
| +
|
| +static inline FloatRect calculateGlyphBoundaries(const QueryData* queryData, const SVGTextFragment& fragment, int startPosition)
|
| +{
|
| + const float scalingFactor = queryData->textLineLayout.scalingFactor();
|
| + ASSERT(scalingFactor);
|
| + const float baseline = queryData->textLineLayout.scaledFont().getFontMetrics().floatAscent() / scalingFactor;
|
|
|
| - FloatRect extent(glyphPosition, glyphSize);
|
| + float glyphOffsetInDirection = calculateGlyphRange(queryData, fragment, 0, startPosition);
|
| + FloatPoint glyphPosition = logicalGlyphPositionToPhysical(queryData, fragment, glyphOffsetInDirection);
|
| + glyphPosition.move(0, -baseline);
|
| +
|
| + // Use the SVGTextMetrics computed by SVGTextMetricsBuilder.
|
| + const MetricsList& metricsList = queryData->textLineLayout.layoutAttributes()->textMetricsValues();
|
| + auto metrics = findMetricsForCharacter(metricsList, fragment, startPosition);
|
| +
|
| + FloatRect extent = physicalGlyphExtents(queryData, *metrics, glyphPosition);
|
| if (fragment.isTransformed()) {
|
| AffineTransform fragmentTransform = fragment.buildFragmentTransform(SVGTextFragment::TransformIgnoringTextLength);
|
| extent = fragmentTransform.mapRect(extent);
|
| @@ -455,14 +461,6 @@ static inline FloatRect calculateGlyphBoundaries(const QueryData* queryData, con
|
| return extent;
|
| }
|
|
|
| -static inline FloatRect calculateFragmentBoundaries(LineLayoutSVGInlineText textLineLayout, const SVGTextFragment& fragment)
|
| -{
|
| - float scalingFactor = textLineLayout.scalingFactor();
|
| - ASSERT(scalingFactor);
|
| - float baseline = textLineLayout.scaledFont().getFontMetrics().floatAscent() / scalingFactor;
|
| - return fragment.boundingBox(baseline);
|
| -}
|
| -
|
| static bool extentOfCharacterCallback(QueryData* queryData, const SVGTextFragment& fragment)
|
| {
|
| ExtentOfCharacterData* data = static_cast<ExtentOfCharacterData*>(queryData);
|
| @@ -540,18 +538,27 @@ static bool characterNumberAtPositionCallback(QueryData* queryData, const SVGTex
|
| {
|
| CharacterNumberAtPositionData* data = static_cast<CharacterNumberAtPositionData*>(queryData);
|
|
|
| + const float scalingFactor = data->textLineLayout.scalingFactor();
|
| + ASSERT(scalingFactor);
|
| + const float baseline = data->textLineLayout.scaledFont().getFontMetrics().floatAscent() / scalingFactor;
|
| +
|
| // Test the query point against the bounds of the entire fragment first.
|
| - FloatRect fragmentExtents = calculateFragmentBoundaries(queryData->textLineLayout, fragment);
|
| - if (!fragmentExtents.contains(data->position))
|
| + if (!fragment.boundingBox(baseline).contains(data->position))
|
| return false;
|
|
|
| + AffineTransform fragmentTransform = fragment.buildFragmentTransform(SVGTextFragment::TransformIgnoringTextLength);
|
| +
|
| // Iterate through the glyphs in this fragment, and check if their extents
|
| // contain the query point.
|
| - const Vector<SVGTextMetrics>& textMetrics = queryData->textLineLayout.layoutAttributes()->textMetricsValues();
|
| - unsigned textMetricsOffset = fragment.metricsListOffset;
|
| + MetricsList::const_iterator metrics =
|
| + data->textLineLayout.layoutAttributes()->textMetricsValues().begin() + fragment.metricsListOffset;
|
| unsigned fragmentOffset = 0;
|
| + float glyphOffset = 0;
|
| while (fragmentOffset < fragment.length) {
|
| - FloatRect extent = calculateGlyphBoundaries(queryData, fragment, fragmentOffset);
|
| + FloatPoint glyphPosition = logicalGlyphPositionToPhysical(data, fragment, glyphOffset);
|
| + glyphPosition.move(0, -baseline);
|
| +
|
| + FloatRect extent = fragmentTransform.mapRect(physicalGlyphExtents(data, *metrics, glyphPosition));
|
| if (extent.contains(data->position)) {
|
| // Compute the character offset of the glyph within the text node.
|
| unsigned offsetInBox = fragment.characterOffset - queryData->textBox->start() + fragmentOffset;
|
| @@ -559,8 +566,9 @@ static bool characterNumberAtPositionCallback(QueryData* queryData, const SVGTex
|
| data->hitLayoutItem = LineLayoutItem(data->textLineLayout);
|
| return true;
|
| }
|
| - fragmentOffset += textMetrics[textMetricsOffset].length();
|
| - textMetricsOffset++;
|
| + fragmentOffset += metrics->length();
|
| + glyphOffset += data->isVerticalText ? metrics->height() : metrics->width();
|
| + ++metrics;
|
| }
|
| return false;
|
| }
|
|
|