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 |