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

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

Issue 1816073002: Optimize the characterNumberAtPositionCallback text query (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@svg-textquery--cleanup-2
Patch Set: Created 4 years, 9 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
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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
(...skipping 275 matching lines...) Expand 10 before | Expand all | Expand 10 after
286 struct StartPositionOfCharacterData : QueryData { 286 struct StartPositionOfCharacterData : QueryData {
287 StartPositionOfCharacterData(unsigned queryPosition) 287 StartPositionOfCharacterData(unsigned queryPosition)
288 : position(queryPosition) 288 : position(queryPosition)
289 { 289 {
290 } 290 }
291 291
292 unsigned position; 292 unsigned position;
293 FloatPoint startPosition; 293 FloatPoint startPosition;
294 }; 294 };
295 295
296 static FloatPoint calculateGlyphPositionWithoutTransform(const QueryData* queryD ata, const SVGTextFragment& fragment, unsigned offsetInFragment) 296 static FloatPoint logicalGlyphPositionToPhysical(const QueryData* queryData, con st SVGTextFragment& fragment, float logicalGlyphOffset)
297 { 297 {
298 float glyphOffsetInDirection = calculateGlyphRange(queryData, fragment, 0, o ffsetInFragment); 298 float physicalGlyphOffset = logicalGlyphOffset;
299
300 if (!queryData->textBox->isLeftToRightDirection()) { 299 if (!queryData->textBox->isLeftToRightDirection()) {
301 float fragmentExtent = queryData->isVerticalText ? fragment.height : fra gment.width; 300 float fragmentExtent = queryData->isVerticalText ? fragment.height : fra gment.width;
302 glyphOffsetInDirection = fragmentExtent - glyphOffsetInDirection; 301 physicalGlyphOffset = fragmentExtent - logicalGlyphOffset;
303 } 302 }
304 303
305 FloatPoint glyphPosition(fragment.x, fragment.y); 304 FloatPoint glyphPosition(fragment.x, fragment.y);
306 if (queryData->isVerticalText) 305 if (queryData->isVerticalText)
307 glyphPosition.move(0, glyphOffsetInDirection); 306 glyphPosition.move(0, physicalGlyphOffset);
308 else 307 else
309 glyphPosition.move(glyphOffsetInDirection, 0); 308 glyphPosition.move(physicalGlyphOffset, 0);
310 309
311 return glyphPosition; 310 return glyphPosition;
312 } 311 }
313 312
314 static FloatPoint calculateGlyphPosition(const QueryData* queryData, const SVGTe xtFragment& fragment, unsigned offsetInFragment) 313 static FloatPoint calculateGlyphPosition(const QueryData* queryData, const SVGTe xtFragment& fragment, unsigned offsetInFragment)
315 { 314 {
316 FloatPoint glyphPosition = calculateGlyphPositionWithoutTransform(queryData, fragment, offsetInFragment); 315 float glyphOffsetInDirection = calculateGlyphRange(queryData, fragment, 0, o ffsetInFragment);
316 FloatPoint glyphPosition = logicalGlyphPositionToPhysical(queryData, fragmen t, glyphOffsetInDirection);
317 if (fragment.isTransformed()) { 317 if (fragment.isTransformed()) {
318 AffineTransform fragmentTransform = fragment.buildFragmentTransform(SVGT extFragment::TransformIgnoringTextLength); 318 AffineTransform fragmentTransform = fragment.buildFragmentTransform(SVGT extFragment::TransformIgnoringTextLength);
319 glyphPosition = fragmentTransform.mapPoint(glyphPosition); 319 glyphPosition = fragmentTransform.mapPoint(glyphPosition);
320 } 320 }
321 return glyphPosition; 321 return glyphPosition;
322 } 322 }
323 323
324 static bool startPositionOfCharacterCallback(QueryData* queryData, const SVGText Fragment& fragment) 324 static bool startPositionOfCharacterCallback(QueryData* queryData, const SVGText Fragment& fragment)
325 { 325 {
326 StartPositionOfCharacterData* data = static_cast<StartPositionOfCharacterDat a*>(queryData); 326 StartPositionOfCharacterData* data = static_cast<StartPositionOfCharacterDat a*>(queryData);
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
414 struct ExtentOfCharacterData : QueryData { 414 struct ExtentOfCharacterData : QueryData {
415 ExtentOfCharacterData(unsigned queryPosition) 415 ExtentOfCharacterData(unsigned queryPosition)
416 : position(queryPosition) 416 : position(queryPosition)
417 { 417 {
418 } 418 }
419 419
420 unsigned position; 420 unsigned position;
421 FloatRect extent; 421 FloatRect extent;
422 }; 422 };
423 423
424 static FloatRect physicalGlyphExtents(const QueryData* queryData, const SVGTextM etrics& metrics, const FloatPoint& glyphPosition)
425 {
426 // TODO(fs): Negative glyph extents seems kind of weird to have, but
427 // presently it can occur in some cases (like Arabic.)
428 FloatRect glyphExtents(
429 glyphPosition,
430 FloatSize(std::max<float>(metrics.width(), 0), std::max<float>(metrics.h eight(), 0)));
431
432 // If RTL, adjust the starting point to align with the LHS of the glyph boun ding box.
433 if (!queryData->textBox->isLeftToRightDirection()) {
434 if (queryData->isVerticalText)
435 glyphExtents.move(0, -glyphExtents.height());
436 else
437 glyphExtents.move(-glyphExtents.width(), 0);
438 }
439 return glyphExtents;
440 }
441
424 static inline FloatRect calculateGlyphBoundaries(const QueryData* queryData, con st SVGTextFragment& fragment, int startPosition) 442 static inline FloatRect calculateGlyphBoundaries(const QueryData* queryData, con st SVGTextFragment& fragment, int startPosition)
425 { 443 {
426 float scalingFactor = queryData->textLineLayout.scalingFactor(); 444 const float scalingFactor = queryData->textLineLayout.scalingFactor();
427 ASSERT(scalingFactor); 445 ASSERT(scalingFactor);
446 const float baseline = queryData->textLineLayout.scaledFont().getFontMetrics ().floatAscent() / scalingFactor;
428 447
429 FloatPoint glyphPosition = calculateGlyphPositionWithoutTransform(queryData, fragment, startPosition); 448 float glyphOffsetInDirection = calculateGlyphRange(queryData, fragment, 0, s tartPosition);
430 glyphPosition.move(0, -queryData->textLineLayout.scaledFont().getFontMetrics ().floatAscent() / scalingFactor); 449 FloatPoint glyphPosition = logicalGlyphPositionToPhysical(queryData, fragmen t, glyphOffsetInDirection);
450 glyphPosition.move(0, -baseline);
431 451
432 // Use the SVGTextMetrics computed by SVGTextMetricsBuilder (which spends 452 // Use the SVGTextMetrics computed by SVGTextMetricsBuilder (which spends
pdr. 2016/03/21 22:55:56 Not your fault but can you clean this comment up?
fs 2016/03/22 10:55:30 Well I think I wrote this comment, so somewhat my
433 // time attempting to compute more correct glyph bounds already, handling 453 // time attempting to compute more correct glyph bounds already, handling
434 // cursive scripts to some degree.) 454 // cursive scripts to some degree.)
435 const MetricsList& textMetricsValues = queryData->textLineLayout.layoutAttri butes()->textMetricsValues(); 455 const MetricsList& metricsList = queryData->textLineLayout.layoutAttributes( )->textMetricsValues();
436 auto metrics = findMetricsForCharacter(textMetricsValues, fragment, startPos ition); 456 auto metrics = findMetricsForCharacter(metricsList, fragment, startPosition) ;
437 457
438 // TODO(fs): Negative glyph extents seems kind of weird to have, but 458 FloatRect extent = physicalGlyphExtents(queryData, *metrics, glyphPosition);
439 // presently it can occur in some cases (like Arabic.)
440 FloatSize glyphSize(std::max<float>(metrics->width(), 0), std::max<float>(me trics->height(), 0));
441
442 // If RTL, adjust the starting point to align with the LHS of the glyph boun ding box.
443 if (!queryData->textBox->isLeftToRightDirection()) {
444 if (queryData->isVerticalText)
445 glyphPosition.move(0, -glyphSize.height());
446 else
447 glyphPosition.move(-glyphSize.width(), 0);
448 }
449
450 FloatRect extent(glyphPosition, glyphSize);
451 if (fragment.isTransformed()) { 459 if (fragment.isTransformed()) {
452 AffineTransform fragmentTransform = fragment.buildFragmentTransform(SVGT extFragment::TransformIgnoringTextLength); 460 AffineTransform fragmentTransform = fragment.buildFragmentTransform(SVGT extFragment::TransformIgnoringTextLength);
453 extent = fragmentTransform.mapRect(extent); 461 extent = fragmentTransform.mapRect(extent);
454 } 462 }
455 return extent; 463 return extent;
456 } 464 }
457 465
458 static inline FloatRect calculateFragmentBoundaries(LineLayoutSVGInlineText text LineLayout, const SVGTextFragment& fragment)
459 {
460 float scalingFactor = textLineLayout.scalingFactor();
461 ASSERT(scalingFactor);
462 float baseline = textLineLayout.scaledFont().getFontMetrics().floatAscent() / scalingFactor;
463 return fragment.boundingBox(baseline);
464 }
465
466 static bool extentOfCharacterCallback(QueryData* queryData, const SVGTextFragmen t& fragment) 466 static bool extentOfCharacterCallback(QueryData* queryData, const SVGTextFragmen t& fragment)
467 { 467 {
468 ExtentOfCharacterData* data = static_cast<ExtentOfCharacterData*>(queryData) ; 468 ExtentOfCharacterData* data = static_cast<ExtentOfCharacterData*>(queryData) ;
469 469
470 int startPosition = data->position; 470 int startPosition = data->position;
471 int endPosition = startPosition + 1; 471 int endPosition = startPosition + 1;
472 if (!mapStartEndPositionsIntoFragmentCoordinates(queryData, fragment, startP osition, endPosition)) 472 if (!mapStartEndPositionsIntoFragmentCoordinates(queryData, fragment, startP osition, endPosition))
473 return false; 473 return false;
474 474
475 data->extent = calculateGlyphBoundaries(queryData, fragment, startPosition); 475 data->extent = calculateGlyphBoundaries(queryData, fragment, startPosition);
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
533 --index; 533 --index;
534 offset += textBoxes[index]->len(); 534 offset += textBoxes[index]->len();
535 } 535 }
536 return offset; 536 return offset;
537 } 537 }
538 538
539 static bool characterNumberAtPositionCallback(QueryData* queryData, const SVGTex tFragment& fragment) 539 static bool characterNumberAtPositionCallback(QueryData* queryData, const SVGTex tFragment& fragment)
540 { 540 {
541 CharacterNumberAtPositionData* data = static_cast<CharacterNumberAtPositionD ata*>(queryData); 541 CharacterNumberAtPositionData* data = static_cast<CharacterNumberAtPositionD ata*>(queryData);
542 542
543 const float scalingFactor = data->textLineLayout.scalingFactor();
544 ASSERT(scalingFactor);
545 const float baseline = data->textLineLayout.scaledFont().getFontMetrics().fl oatAscent() / scalingFactor;
546
543 // Test the query point against the bounds of the entire fragment first. 547 // Test the query point against the bounds of the entire fragment first.
544 FloatRect fragmentExtents = calculateFragmentBoundaries(queryData->textLineL ayout, fragment); 548 if (!fragment.boundingBox(baseline).contains(data->position))
545 if (!fragmentExtents.contains(data->position))
546 return false; 549 return false;
547 550
551 AffineTransform fragmentTransform = fragment.buildFragmentTransform(SVGTextF ragment::TransformIgnoringTextLength);
552
548 // Iterate through the glyphs in this fragment, and check if their extents 553 // Iterate through the glyphs in this fragment, and check if their extents
549 // contain the query point. 554 // contain the query point.
550 const Vector<SVGTextMetrics>& textMetrics = queryData->textLineLayout.layout Attributes()->textMetricsValues(); 555 MetricsList::const_iterator metrics =
551 unsigned textMetricsOffset = fragment.metricsListOffset; 556 data->textLineLayout.layoutAttributes()->textMetricsValues().begin() + f ragment.metricsListOffset;
552 unsigned fragmentOffset = 0; 557 unsigned fragmentOffset = 0;
558 float glyphOffset = 0;
553 while (fragmentOffset < fragment.length) { 559 while (fragmentOffset < fragment.length) {
554 FloatRect extent = calculateGlyphBoundaries(queryData, fragment, fragmen tOffset); 560 FloatPoint glyphPosition = logicalGlyphPositionToPhysical(data, fragment , glyphOffset);
561 glyphPosition.move(0, -baseline);
562
563 FloatRect extent = fragmentTransform.mapRect(physicalGlyphExtents(data, *metrics, glyphPosition));
555 if (extent.contains(data->position)) { 564 if (extent.contains(data->position)) {
556 // Compute the character offset of the glyph within the text node. 565 // Compute the character offset of the glyph within the text node.
557 unsigned offsetInBox = fragment.characterOffset - queryData->textBox ->start() + fragmentOffset; 566 unsigned offsetInBox = fragment.characterOffset - queryData->textBox ->start() + fragmentOffset;
558 data->offsetInTextNode = logicalOffsetInTextNode(queryData->textLine Layout, queryData->textBox, offsetInBox); 567 data->offsetInTextNode = logicalOffsetInTextNode(queryData->textLine Layout, queryData->textBox, offsetInBox);
559 data->hitLayoutItem = LineLayoutItem(data->textLineLayout); 568 data->hitLayoutItem = LineLayoutItem(data->textLineLayout);
560 return true; 569 return true;
561 } 570 }
562 fragmentOffset += textMetrics[textMetricsOffset].length(); 571 fragmentOffset += metrics->length();
563 textMetricsOffset++; 572 glyphOffset += data->isVerticalText ? metrics->height() : metrics->width ();
573 ++metrics;
564 } 574 }
565 return false; 575 return false;
566 } 576 }
567 577
568 int SVGTextQuery::characterNumberAtPosition(const FloatPoint& position) const 578 int SVGTextQuery::characterNumberAtPosition(const FloatPoint& position) const
569 { 579 {
570 CharacterNumberAtPositionData data(position); 580 CharacterNumberAtPositionData data(position);
571 spatialQuery(m_queryRootLayoutObject, &data, characterNumberAtPositionCallba ck); 581 spatialQuery(m_queryRootLayoutObject, &data, characterNumberAtPositionCallba ck);
572 return data.characterNumberWithin(m_queryRootLayoutObject); 582 return data.characterNumberWithin(m_queryRootLayoutObject);
573 } 583 }
574 584
575 } // namespace blink 585 } // namespace blink
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698