bool SVGInlineTextBox::nodeAtPoint(HitTestResult& result, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, LayoutUnit, LayoutUnit) { // FIXME: integrate with InlineTextBox::nodeAtPoint better. ASSERT(!isLineBreak()); PointerEventsHitRules hitRules(PointerEventsHitRules::SVG_TEXT_HITTESTING, result.hitTestRequest(), getLineLayoutItem().style()->pointerEvents()); bool isVisible = getLineLayoutItem().style()->visibility() == EVisibility::Visible; if (isVisible || !hitRules.requireVisible) { if (hitRules.canHitBoundingBox || (hitRules.canHitStroke && (getLineLayoutItem().style()->svgStyle().hasStroke() || !hitRules.requireStroke)) || (hitRules.canHitFill && (getLineLayoutItem().style()->svgStyle().hasFill() || !hitRules.requireFill))) { LayoutRect rect(topLeft(), LayoutSize(logicalWidth(), logicalHeight())); rect.moveBy(accumulatedOffset); if (locationInContainer.intersects(rect)) { LineLayoutSVGInlineText lineLayoutItem = LineLayoutSVGInlineText(this->getLineLayoutItem()); const SimpleFontData* fontData = lineLayoutItem.scaledFont().primaryFont(); DCHECK(fontData); if (!fontData) return false; DCHECK(lineLayoutItem.scalingFactor()); float baseline = fontData->getFontMetrics().floatAscent() / lineLayoutItem.scalingFactor(); FloatPoint floatLocation = FloatPoint(locationInContainer.point()); for (const SVGTextFragment& fragment : m_textFragments) { FloatQuad fragmentQuad = fragment.boundingQuad(baseline); if (fragmentQuad.containsPoint(floatLocation)) { lineLayoutItem.updateHitTestResult( result, locationInContainer.point() - toLayoutSize(accumulatedOffset)); if (result.addNodeToListBasedTestResult(lineLayoutItem.node(), locationInContainer, rect) == StopHitTesting) return true; } } } } } return false; }
bool SVGInlineTextBox::nodeAtPoint(HitTestResult& result, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, LayoutUnit, LayoutUnit) { // FIXME: integrate with InlineTextBox::nodeAtPoint better. ASSERT(!isLineBreak()); PointerEventsHitRules hitRules(PointerEventsHitRules::SVG_TEXT_HITTESTING, result.hitTestRequest(), lineLayoutItem().style()->pointerEvents()); bool isVisible = lineLayoutItem().style()->visibility() == VISIBLE; if (isVisible || !hitRules.requireVisible) { if (hitRules.canHitBoundingBox || (hitRules.canHitStroke && (lineLayoutItem().style()->svgStyle().hasStroke() || !hitRules.requireStroke)) || (hitRules.canHitFill && (lineLayoutItem().style()->svgStyle().hasFill() || !hitRules.requireFill))) { LayoutPoint boxOrigin(x(), y()); boxOrigin.moveBy(accumulatedOffset); LayoutRect rect(boxOrigin, size()); if (locationInContainer.intersects(rect)) { LineLayoutSVGInlineText lineLayoutItem = LineLayoutSVGInlineText(this->lineLayoutItem()); ASSERT(lineLayoutItem.scalingFactor()); float baseline = lineLayoutItem.scaledFont().fontMetrics().floatAscent() / lineLayoutItem.scalingFactor(); FloatPoint floatLocation = FloatPoint(locationInContainer.point()); for (const SVGTextFragment& fragment : m_textFragments) { FloatQuad fragmentQuad = fragment.boundingQuad(baseline); if (fragmentQuad.containsPoint(floatLocation)) { lineLayoutItem.updateHitTestResult(result, locationInContainer.point() - toLayoutSize(accumulatedOffset)); if (!result.addNodeToListBasedTestResult(lineLayoutItem.node(), locationInContainer, rect)) return true; } } } } } return false; }
static inline FloatRect calculateFragmentBoundaries(LineLayoutSVGInlineText textLineLayout, const SVGTextFragment& fragment) { float scalingFactor = textLineLayout.scalingFactor(); ASSERT(scalingFactor); float baseline = textLineLayout.scaledFont().fontMetrics().floatAscent() / scalingFactor; return fragment.boundingBox(baseline); }
int SVGInlineTextBox::offsetForPositionInFragment( const SVGTextFragment& fragment, LayoutUnit position, bool includePartialGlyphs) const { LineLayoutSVGInlineText lineLayoutItem = LineLayoutSVGInlineText(this->getLineLayoutItem()); float scalingFactor = lineLayoutItem.scalingFactor(); ASSERT(scalingFactor); const ComputedStyle& style = lineLayoutItem.styleRef(); TextRun textRun = constructTextRun(style, fragment); // Eventually handle lengthAdjust="spacingAndGlyphs". // FIXME: Handle vertical text. if (fragment.isTransformed()) { AffineTransform fragmentTransform = fragment.buildFragmentTransform(); textRun.setHorizontalGlyphStretch( clampTo<float>(fragmentTransform.xScale())); } return fragment.characterOffset - start() + lineLayoutItem.scaledFont().offsetForPosition( textRun, position * scalingFactor, includePartialGlyphs); }
FloatRect SVGInlineTextBox::selectionRectForTextFragment( const SVGTextFragment& fragment, int startPosition, int endPosition, const ComputedStyle& style) const { ASSERT(startPosition < endPosition); LineLayoutSVGInlineText lineLayoutItem = LineLayoutSVGInlineText(this->getLineLayoutItem()); float scalingFactor = lineLayoutItem.scalingFactor(); ASSERT(scalingFactor); const Font& scaledFont = lineLayoutItem.scaledFont(); const SimpleFontData* fontData = scaledFont.primaryFont(); DCHECK(fontData); if (!fontData) return FloatRect(); const FontMetrics& scaledFontMetrics = fontData->getFontMetrics(); FloatPoint textOrigin(fragment.x, fragment.y); if (scalingFactor != 1) textOrigin.scale(scalingFactor, scalingFactor); textOrigin.move(0, -scaledFontMetrics.floatAscent()); FloatRect selectionRect = scaledFont.selectionRectForText( constructTextRun(style, fragment), textOrigin, fragment.height * scalingFactor, startPosition, endPosition); if (scalingFactor == 1) return selectionRect; selectionRect.scale(1 / scalingFactor); return selectionRect; }
static inline FloatRect calculateFragmentBoundaries(LineLayoutSVGInlineText textLineLayout, const SVGTextFragment& fragment) { float scalingFactor = textLineLayout.scalingFactor(); ASSERT(scalingFactor); float baseline = textLineLayout.scaledFont().fontMetrics().floatAscent() / scalingFactor; AffineTransform fragmentTransform; FloatRect fragmentRect(fragment.x, fragment.y - baseline, fragment.width, fragment.height); fragment.buildFragmentTransform(fragmentTransform); return fragmentTransform.mapRect(fragmentRect); }
SVGTextMetrics::SVGTextMetrics(LineLayoutSVGInlineText textLayoutItem, unsigned length, float width) { ASSERT(textLayoutItem); float scalingFactor = textLayoutItem.scalingFactor(); ASSERT(scalingFactor); m_width = width / scalingFactor; m_height = textLayoutItem.scaledFont().fontMetrics().floatHeight() / scalingFactor; m_length = length; }
LayoutRect SVGInlineTextBox::calculateBoundaries() const { LineLayoutSVGInlineText lineLayoutItem = LineLayoutSVGInlineText(this->lineLayoutItem()); float scalingFactor = lineLayoutItem.scalingFactor(); ASSERT(scalingFactor); LayoutUnit baseline = lineLayoutItem.scaledFont().fontMetrics().floatAscent() / scalingFactor; LayoutRect textBoundingRect; for (const SVGTextFragment& fragment : m_textFragments) textBoundingRect.unite(LayoutRect(fragment.overflowBoundingBox(baseline))); return textBoundingRect; }
SVGTextMetrics::SVGTextMetrics(LineLayoutSVGInlineText textLayoutItem, const TextRun& run) { ASSERT(textLayoutItem); float scalingFactor = textLayoutItem.scalingFactor(); ASSERT(scalingFactor); const Font& scaledFont = textLayoutItem.scaledFont(); // Calculate width/height using the scaled font, divide this result by the scalingFactor afterwards. m_width = scaledFont.width(run) / scalingFactor; m_height = scaledFont.fontMetrics().floatHeight() / scalingFactor; ASSERT(run.length() >= 0); m_length = static_cast<unsigned>(run.length()); }
LayoutRect SVGInlineTextBox::calculateBoundaries() const { LineLayoutSVGInlineText lineLayoutItem = LineLayoutSVGInlineText(this->getLineLayoutItem()); const SimpleFontData* fontData = lineLayoutItem.scaledFont().primaryFont(); DCHECK(fontData); if (!fontData) return LayoutRect(); float scalingFactor = lineLayoutItem.scalingFactor(); ASSERT(scalingFactor); LayoutUnit baseline(fontData->getFontMetrics().floatAscent() / scalingFactor); LayoutRect textBoundingRect; for (const SVGTextFragment& fragment : m_textFragments) textBoundingRect.unite(LayoutRect(fragment.overflowBoundingBox(baseline))); return textBoundingRect; }