PositionWithAffinity RenderReplaced::positionForPoint(const LayoutPoint& point) { // FIXME: This code is buggy if the replaced element is relative positioned. InlineBox* box = inlineBoxWrapper(); RootInlineBox* rootBox = box ? &box->root() : 0; LayoutUnit top = rootBox ? rootBox->selectionTop() : logicalTop(); LayoutUnit bottom = rootBox ? rootBox->selectionBottom() : logicalBottom(); LayoutUnit blockDirectionPosition = isHorizontalWritingMode() ? point.y() + y() : point.x() + x(); LayoutUnit lineDirectionPosition = isHorizontalWritingMode() ? point.x() + x() : point.y() + y(); if (blockDirectionPosition < top) return createPositionWithAffinity(caretMinOffset(), DOWNSTREAM); // coordinates are above if (blockDirectionPosition >= bottom) return createPositionWithAffinity(caretMaxOffset(), DOWNSTREAM); // coordinates are below if (node()) { if (lineDirectionPosition <= logicalLeft() + (logicalWidth() / 2)) return createPositionWithAffinity(0, DOWNSTREAM); return createPositionWithAffinity(1, DOWNSTREAM); } return RenderBox::positionForPoint(point); }
PositionWithAffinity LayoutSVGInlineText::positionForPoint(const LayoutPoint& point) { if (!firstTextBox() || !textLength()) return createPositionWithAffinity(0, DOWNSTREAM); ASSERT(m_scalingFactor); float baseline = m_scaledFont.fontMetrics().floatAscent() / m_scalingFactor; LayoutBlock* containingBlock = this->containingBlock(); ASSERT(containingBlock); // Map local point to absolute point, as the character origins stored in the text fragments use absolute coordinates. FloatPoint absolutePoint(point); absolutePoint.moveBy(containingBlock->location()); float closestDistance = std::numeric_limits<float>::max(); float closestDistancePosition = 0; const SVGTextFragment* closestDistanceFragment = 0; SVGInlineTextBox* closestDistanceBox = 0; AffineTransform fragmentTransform; for (InlineTextBox* box = firstTextBox(); box; box = box->nextTextBox()) { if (!box->isSVGInlineTextBox()) continue; SVGInlineTextBox* textBox = toSVGInlineTextBox(box); Vector<SVGTextFragment>& fragments = textBox->textFragments(); unsigned textFragmentsSize = fragments.size(); for (unsigned i = 0; i < textFragmentsSize; ++i) { const SVGTextFragment& fragment = fragments.at(i); FloatRect fragmentRect(fragment.x, fragment.y - baseline, fragment.width, fragment.height); fragment.buildFragmentTransform(fragmentTransform); if (!fragmentTransform.isIdentity()) fragmentRect = fragmentTransform.mapRect(fragmentRect); float distance = 0; if (!fragmentRect.contains(absolutePoint)) distance = squaredDistanceToClosestPoint(fragmentRect, absolutePoint); if (distance <= closestDistance) { closestDistance = distance; closestDistanceBox = textBox; closestDistanceFragment = &fragment; closestDistancePosition = fragmentRect.x(); } } } if (!closestDistanceFragment) return createPositionWithAffinity(0, DOWNSTREAM); int offset = closestDistanceBox->offsetForPositionInFragment(*closestDistanceFragment, absolutePoint.x() - closestDistancePosition, true); return createPositionWithAffinity(offset + closestDistanceBox->start(), offset > 0 ? VP_UPSTREAM_IF_POSSIBLE : DOWNSTREAM); }
PositionWithAffinity RenderSVGText::positionForPoint(const LayoutPoint& pointInContents) { RootInlineBox* rootBox = firstRootBox(); if (!rootBox) return createPositionWithAffinity(0, DOWNSTREAM); ASSERT(!rootBox->nextRootBox()); ASSERT(childrenInline()); InlineBox* closestBox = toSVGRootInlineBox(rootBox)->closestLeafChildForPosition(pointInContents); if (!closestBox) return createPositionWithAffinity(0, DOWNSTREAM); return closestBox->renderer().positionForPoint(LayoutPoint(pointInContents.x(), closestBox->y())); }
PositionWithAffinity RenderSVGText::positionForPoint(const LayoutPoint& pointInContents) { RootInlineBox* rootBox = firstRootBox(); if (!rootBox) return createPositionWithAffinity(0, DOWNSTREAM); ASSERT_WITH_SECURITY_IMPLICATION(rootBox->isSVGRootInlineBox()); ASSERT(!rootBox->nextRootBox()); ASSERT(childrenInline()); InlineBox* closestBox = static_cast<SVGRootInlineBox*>(rootBox)->closestLeafChildForPosition(pointInContents); if (!closestBox) return createPositionWithAffinity(0, DOWNSTREAM); return closestBox->renderer()->positionForPoint(LayoutPoint(pointInContents.x(), closestBox->y())); }
PositionWithAffinity LayoutSVGInlineText::positionForPoint(const LayoutPoint& point) { if (!hasTextBoxes() || !textLength()) return createPositionWithAffinity(0); ASSERT(m_scalingFactor); float baseline = m_scaledFont.getFontMetrics().floatAscent() / m_scalingFactor; LayoutBlock* containingBlock = this->containingBlock(); ASSERT(containingBlock); // Map local point to absolute point, as the character origins stored in the text fragments use absolute coordinates. FloatPoint absolutePoint(point); absolutePoint.moveBy(containingBlock->location()); float closestDistance = std::numeric_limits<float>::max(); float closestDistancePosition = 0; const SVGTextFragment* closestDistanceFragment = nullptr; SVGInlineTextBox* closestDistanceBox = nullptr; for (InlineTextBox* box = firstTextBox(); box; box = box->nextTextBox()) { if (!box->isSVGInlineTextBox()) continue; SVGInlineTextBox* textBox = toSVGInlineTextBox(box); for (const SVGTextFragment& fragment : textBox->textFragments()) { FloatRect fragmentRect = fragment.boundingBox(baseline); float distance = 0; if (!fragmentRect.contains(absolutePoint)) distance = fragmentRect.squaredDistanceTo(absolutePoint); if (distance <= closestDistance) { closestDistance = distance; closestDistanceBox = textBox; closestDistanceFragment = &fragment; closestDistancePosition = fragmentRect.x(); } } } if (!closestDistanceFragment) return createPositionWithAffinity(0); int offset = closestDistanceBox->offsetForPositionInFragment(*closestDistanceFragment, LayoutUnit(absolutePoint.x() - closestDistancePosition), true); return createPositionWithAffinity(offset + closestDistanceBox->start(), offset > 0 ? VP_UPSTREAM_IF_POSSIBLE : TextAffinity::Downstream); }
PositionWithAffinity LayoutBR::positionForPoint(const LayoutPoint&) { return createPositionWithAffinity(0); }