int RenderInline::offsetLeft() const { int x = RenderFlow::offsetLeft(); if (firstLineBox()) x += firstLineBox()->xPos(); return x; }
bool LineBoxList::hitTest(LayoutBoxModelObject* renderer, HitTestResult& result, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction hitTestAction) const { if (hitTestAction != HitTestForeground) return false; ASSERT(renderer->isLayoutBlock() || (renderer->isLayoutInline() && renderer->hasLayer())); // The only way an inline could hit test like this is if it has a layer. // If we have no lines then we have no work to do. if (!firstLineBox()) return false; LayoutPoint point = locationInContainer.point(); LayoutRect rect(firstLineBox()->isHorizontal() ? IntRect(point.x(), point.y() - locationInContainer.topPadding(), 1, locationInContainer.topPadding() + locationInContainer.bottomPadding() + 1) : IntRect(point.x() - locationInContainer.leftPadding(), point.y(), locationInContainer.rightPadding() + locationInContainer.leftPadding() + 1, 1)); if (!anyLineIntersectsRect(renderer, rect, accumulatedOffset)) return false; // See if our root lines contain the point. If so, then we hit test // them further. Note that boxes can easily overlap, so we can't make any assumptions // based off positions of our first line box or our last line box. for (InlineFlowBox* curr = lastLineBox(); curr; curr = curr->prevLineBox()) { RootInlineBox& root = curr->root(); if (rangeIntersectsRect(renderer, curr->logicalTopVisualOverflow(root.lineTop()), curr->logicalBottomVisualOverflow(root.lineBottom()), rect, accumulatedOffset)) { bool inside = curr->nodeAtPoint(result, locationInContainer, accumulatedOffset, root.lineTop(), root.lineBottom()); if (inside) { renderer->updateHitTestResult(result, locationInContainer.point() - toLayoutSize(accumulatedOffset)); return true; } } } return false; }
int RenderInline::offsetTop() const { int y = RenderFlow::offsetTop(); if (firstLineBox()) y += firstLineBox()->yPos(); return y; }
bool RenderLineBoxList::hitTest(RenderBoxModelObject* renderer, const HitTestRequest& request, HitTestResult& result, int x, int y, int tx, int ty, HitTestAction hitTestAction) const { if (hitTestAction != HitTestForeground) return false; ASSERT(renderer->isRenderBlock() || (renderer->isRenderInline() && renderer->hasLayer())); // The only way an inline could hit test like this is if it has a layer. // If we have no lines then we have no work to do. if (!firstLineBox()) return false; // We can check the first box and last box and avoid hit testing if we don't // contain the point. This is a quick short-circuit that we can take to avoid walking any lines. // FIXME: This check is flawed in the following extremely obscure way: // if some line in the middle has a huge overflow, it might actually extend below the last line. if ((y >= ty + lastLineBox()->root()->bottomVisibleOverflow()) || (y < ty + firstLineBox()->root()->topVisibleOverflow())) return false; // See if our root lines contain the point. If so, then we hit test // them further. Note that boxes can easily overlap, so we can't make any assumptions // based off positions of our first line box or our last line box. for (InlineFlowBox* curr = lastLineBox(); curr; curr = curr->prevLineBox()) { if (y >= ty + curr->root()->topVisibleOverflow() && y < ty + curr->root()->bottomVisibleOverflow()) { bool inside = curr->nodeAtPoint(request, result, x, y, tx, ty); if (inside) { renderer->updateHitTestResult(result, IntPoint(x - tx, y - ty)); return true; } } } return false; }
int RenderInline::height() const { // See <rdar://problem/5289721>, for an unknown reason the linked list here is sometimes inconsistent, first is non-zero and last is zero. We have been // unable to reproduce this at all (and consequently unable to figure ot why this is happening). The assert will hopefully catch the problem in debug // builds and help us someday figure out why. We also put in a redundant check of lastLineBox() to avoid the crash for now. ASSERT(!firstLineBox() == !lastLineBox()); // Either both are null or both exist. if (firstLineBox() && lastLineBox()) return lastLineBox()->yPos() + lastLineBox()->height() - firstLineBox()->yPos(); return 0; }
bool LineBoxList::anyLineIntersectsRect(LayoutBoxModelObject* renderer, const LayoutRect& rect, const LayoutPoint& offset) const { // We can check the first box and last box and avoid painting/hit testing if we don't // intersect. This is a quick short-circuit that we can take to avoid walking any lines. // FIXME: This check is flawed in the following extremely obscure way: // if some line in the middle has a huge overflow, it might actually extend below the last line. RootInlineBox& firstRootBox = firstLineBox()->root(); RootInlineBox& lastRootBox = lastLineBox()->root(); LayoutUnit firstLineTop = firstLineBox()->logicalTopVisualOverflow(firstRootBox.lineTop()); LayoutUnit lastLineBottom = lastLineBox()->logicalBottomVisualOverflow(lastRootBox.lineBottom()); return rangeIntersectsRect(renderer, firstLineTop, lastLineBottom, rect, offset); }
int RenderInline::width() const { // Return the width of the minimal left side and the maximal right side. int leftSide = 0; int rightSide = 0; for (InlineRunBox* curr = firstLineBox(); curr; curr = curr->nextLineBox()) { if (curr == firstLineBox() || curr->xPos() < leftSide) leftSide = curr->xPos(); if (curr == firstLineBox() || curr->xPos() + curr->width() > rightSide) rightSide = curr->xPos() + curr->width(); } return rightSide - leftSide; }
void LayoutMultiColumnFlowThread::evacuateAndDestroy() { LayoutBlockFlow* multicolContainer = multiColumnBlockFlow(); m_isBeingEvacuated = true; // Remove all sets and spanners. while (LayoutBox* columnBox = firstMultiColumnBox()) { ASSERT(columnBox->isAnonymous()); columnBox->destroy(); } ASSERT(!previousSibling()); ASSERT(!nextSibling()); // Finally we can promote all flow thread's children. Before we move them to the flow thread's // container, we need to unregister the flow thread, so that they aren't just re-added again to // the flow thread that we're trying to empty. multicolContainer->resetMultiColumnFlowThread(); moveAllChildrenTo(multicolContainer, true); // We used to manually nuke the line box tree here, but that should happen automatically when // moving children around (the code above). ASSERT(!firstLineBox()); destroy(); }
FloatRect RenderSVGText::relativeBBox(bool includeStroke) const { FloatRect repaintRect; for (InlineRunBox* runBox = firstLineBox(); runBox; runBox = runBox->nextLineBox()) { ASSERT(runBox->isInlineFlowBox()); InlineFlowBox* flowBox = static_cast<InlineFlowBox*>(runBox); for (InlineBox* box = flowBox->firstChild(); box; box = box->nextOnLine()) repaintRect.unite(FloatRect(box->xPos(), box->yPos(), box->width(), box->height())); } // SVG needs to include the strokeWidth(), not the textStrokeWidth(). if (includeStroke && style()->svgStyle()->hasStroke()) { float strokeWidth = SVGRenderStyle::cssPrimitiveToLength(this, style()->svgStyle()->strokeWidth(), 0.0f); #if ENABLE(SVG_FONTS) const Font& font = style()->font(); if (font.primaryFont()->isSVGFont()) { float scale = font.unitsPerEm() > 0 ? font.size() / font.unitsPerEm() : 0.0f; if (scale != 0.0f) strokeWidth /= scale; } #endif repaintRect.inflate(strokeWidth); } repaintRect.move(xPos(), yPos()); return repaintRect; }
IntRect RenderInline::clippedOverflowRectForRepaint(RenderBox* repaintContainer) { // Only run-ins are allowed in here during layout. ASSERT(!view() || !view()->layoutStateEnabled() || isRunIn()); if (!firstLineBox() && !continuation()) return IntRect(); // Find our leftmost position. IntRect boundingBox(linesBoundingBox()); int left = boundingBox.x(); int top = boundingBox.y(); // Now invalidate a rectangle. int ow = style() ? style()->outlineSize() : 0; // We need to add in the relative position offsets of any inlines (including us) up to our // containing block. RenderBlock* cb = containingBlock(); for (RenderObject* inlineFlow = this; inlineFlow && inlineFlow->isRenderInline() && inlineFlow != cb; inlineFlow = inlineFlow->parent()) { if (inlineFlow->style()->position() == RelativePosition && inlineFlow->hasLayer()) toRenderBox(inlineFlow)->layer()->relativePositionOffset(left, top); } IntRect r(-ow + left, -ow + top, boundingBox.width() + ow * 2, boundingBox.height() + ow * 2); if (cb->hasColumns()) cb->adjustRectForColumns(r); if (cb->hasOverflowClip()) { // cb->height() is inaccurate if we're in the middle of a layout of |cb|, so use the // layer's size instead. Even if the layer's size is wrong, the layer itself will repaint // anyway if its size does change. int x = r.x(); int y = r.y(); IntRect boxRect(0, 0, cb->layer()->width(), cb->layer()->height()); cb->layer()->subtractScrolledContentOffset(x, y); // For overflow:auto/scroll/hidden. IntRect repaintRect(x, y, r.width(), r.height()); r = intersection(repaintRect, boxRect); } ASSERT(repaintContainer != this); cb->computeRectForRepaint(r, repaintContainer); if (ow) { for (RenderObject* curr = firstChild(); curr; curr = curr->nextSibling()) { if (!curr->isText()) { IntRect childRect = curr->rectWithOutlineForRepaint(repaintContainer, ow); r.unite(childRect); } } if (continuation() && !continuation()->isInline()) { IntRect contRect = continuation()->rectWithOutlineForRepaint(repaintContainer, ow); r.unite(contRect); } } return r; }
IntRect RenderInline::linesBoundingBox() const { IntRect result; // See <rdar://problem/5289721>, for an unknown reason the linked list here is sometimes inconsistent, first is non-zero and last is zero. We have been // unable to reproduce this at all (and consequently unable to figure ot why this is happening). The assert will hopefully catch the problem in debug // builds and help us someday figure out why. We also put in a redundant check of lastLineBox() to avoid the crash for now. ASSERT(!firstLineBox() == !lastLineBox()); // Either both are null or both exist. if (firstLineBox() && lastLineBox()) { // Return the width of the minimal left side and the maximal right side. int leftSide = 0; int rightSide = 0; for (InlineRunBox* curr = firstLineBox(); curr; curr = curr->nextLineBox()) { if (curr == firstLineBox() || curr->xPos() < leftSide) leftSide = curr->xPos(); if (curr == firstLineBox() || curr->xPos() + curr->width() > rightSide) rightSide = curr->xPos() + curr->width(); } result.setWidth(rightSide - leftSide); result.setX(leftSide); result.setHeight(lastLineBox()->yPos() + lastLineBox()->height() - firstLineBox()->yPos()); result.setY(firstLineBox()->yPos()); } return result; }
void RenderSVGInline::absoluteQuads(Vector<FloatQuad>& quads, bool* wasFixed) const { auto* textAncestor = RenderSVGText::locateRenderSVGTextAncestor(*this); if (!textAncestor) return; FloatRect textBoundingBox = textAncestor->strokeBoundingBox(); for (InlineFlowBox* box = firstLineBox(); box; box = box->nextLineBox()) quads.append(localToAbsoluteQuad(FloatRect(textBoundingBox.x() + box->x(), textBoundingBox.y() + box->y(), box->logicalWidth(), box->logicalHeight()), UseTransforms, wasFixed)); }
void RenderSVGInline::absoluteQuads(Vector<FloatQuad>& quads) { const RenderObject* object = SVGRenderSupport::findTextRootObject(this); if (!object) return; FloatRect textBoundingBox = object->strokeBoundingBox(); for (InlineFlowBox* box = firstLineBox(); box; box = box->nextLineBox()) quads.append(localToAbsoluteQuad(FloatRect(textBoundingBox.x() + box->x(), textBoundingBox.y() + box->y(), box->width(), box->height()))); }
void RenderSVGInline::absoluteQuads(Vector<FloatQuad>& quads, bool* wasFixed) { RenderObject* object = RenderSVGText::locateRenderSVGTextAncestor(this); if (!object) return; FloatRect textBoundingBox = object->strokeBoundingBox(); for (InlineFlowBox* box = firstLineBox(); box; box = box->nextLineBox()) quads.append(localToAbsoluteQuad(FloatRect(textBoundingBox.x() + box->x(), textBoundingBox.y() + box->y(), box->logicalWidth(), box->logicalHeight()), false, wasFixed)); }
GapRects RenderBlockFlow::inlineSelectionGaps(RenderBlock* rootBlock, const LayoutPoint& rootBlockPhysicalPosition, const LayoutSize& offsetFromRootBlock, LayoutUnit& lastLogicalTop, LayoutUnit& lastLogicalLeft, LayoutUnit& lastLogicalRight, const PaintInfo* paintInfo) { GapRects result; bool containsStart = selectionState() == SelectionStart || selectionState() == SelectionBoth; if (!firstLineBox()) { if (containsStart) { // Go ahead and update our lastLogicalTop to be the bottom of the block. <hr>s or empty blocks with height can trip this // case. lastLogicalTop = rootBlock->blockDirectionOffset(offsetFromRootBlock) + logicalHeight(); lastLogicalLeft = logicalLeftSelectionOffset(rootBlock, logicalHeight()); lastLogicalRight = logicalRightSelectionOffset(rootBlock, logicalHeight()); } return result; } RootInlineBox* lastSelectedLine = 0; RootInlineBox* curr; for (curr = firstRootBox(); curr && !curr->hasSelectedChildren(); curr = curr->nextRootBox()) { } // Now paint the gaps for the lines. for (; curr && curr->hasSelectedChildren(); curr = curr->nextRootBox()) { LayoutUnit selTop = curr->selectionTopAdjustedForPrecedingBlock(); LayoutUnit selHeight = curr->selectionHeightAdjustedForPrecedingBlock(); if (!containsStart && !lastSelectedLine && selectionState() != SelectionStart && selectionState() != SelectionBoth) { result.uniteCenter(blockSelectionGap(rootBlock, rootBlockPhysicalPosition, offsetFromRootBlock, lastLogicalTop, lastLogicalLeft, lastLogicalRight, selTop, paintInfo)); } LayoutRect logicalRect(curr->logicalLeft(), selTop, curr->logicalWidth(), selTop + selHeight); logicalRect.move(offsetFromRootBlock); LayoutRect physicalRect = rootBlock->logicalRectToPhysicalRect(rootBlockPhysicalPosition, logicalRect); if (!paintInfo || (physicalRect.y() < paintInfo->rect.maxY() && physicalRect.maxY() > paintInfo->rect.y())) result.unite(curr->lineSelectionGap(rootBlock, rootBlockPhysicalPosition, offsetFromRootBlock, selTop, selHeight, paintInfo)); lastSelectedLine = curr; } if (containsStart && !lastSelectedLine) { // VisibleSelection must start just after our last line. lastSelectedLine = lastRootBox(); } if (lastSelectedLine && selectionState() != SelectionEnd && selectionState() != SelectionBoth) { // Go ahead and update our lastY to be the bottom of the last selected line. lastLogicalTop = rootBlock->blockDirectionOffset(offsetFromRootBlock) + lastSelectedLine->selectionBottom(); lastLogicalLeft = logicalLeftSelectionOffset(rootBlock, lastSelectedLine->selectionBottom()); lastLogicalRight = logicalRightSelectionOffset(rootBlock, lastSelectedLine->selectionBottom()); } return result; }
FloatRect RenderSVGText::objectBoundingBox() const { FloatRect boundingBox; for (InlineFlowBox* flow = firstLineBox(); flow; flow = flow->nextLineBox()) { for (InlineBox* box = flow->firstChild(); box; box = box->nextOnLine()) boundingBox.unite(FloatRect(box->x(), box->y(), box->width(), box->height())); } boundingBox.move(x(), y()); return boundingBox; }
void RenderLineBoxList::paint(RenderBoxModelObject* renderer, PaintInfo& paintInfo, const LayoutPoint& paintOffset) const { // Only paint during the foreground/selection phases. if (paintInfo.phase != PaintPhaseForeground && paintInfo.phase != PaintPhaseSelection && paintInfo.phase != PaintPhaseOutline && paintInfo.phase != PaintPhaseSelfOutline && paintInfo.phase != PaintPhaseChildOutlines && paintInfo.phase != PaintPhaseTextClip && paintInfo.phase != PaintPhaseMask) return; ASSERT(renderer->isRenderBlock() || (renderer->isRenderInline() && renderer->hasLayer())); // The only way an inline could paint like this is if it has a layer. // If we have no lines then we have no work to do. if (!firstLineBox()) return; if (!anyLineIntersectsRect(renderer, paintInfo.rect, paintOffset)) return; PaintInfo info(paintInfo); ListHashSet<RenderInline*> outlineObjects; info.setOutlineObjects(&outlineObjects); // See if our root lines intersect with the dirty rect. If so, then we paint // them. Note that boxes can easily overlap, so we can't make any assumptions // based off positions of our first line box or our last line box. for (InlineFlowBox* curr = firstLineBox(); curr; curr = curr->nextLineBox()) { if (lineIntersectsDirtyRect(renderer, curr, info, paintOffset)) { RootInlineBox& root = curr->root(); curr->paint(info, paintOffset, root.lineTop(), root.lineBottom()); } } if (info.phase == PaintPhaseOutline || info.phase == PaintPhaseSelfOutline || info.phase == PaintPhaseChildOutlines) { ListHashSet<RenderInline*>::iterator end = info.outlineObjects()->end(); for (ListHashSet<RenderInline*>::iterator it = info.outlineObjects()->begin(); it != end; ++it) { RenderInline* flow = *it; flow->paintOutline(info, paintOffset); } info.outlineObjects()->clear(); } }
void RenderLineBoxList::paint(RenderBoxModelObject* renderer, PaintInfo& paintInfo, const LayoutPoint& paintOffset, Vector<RenderBox*>& layers) const { ASSERT(renderer->isRenderBlock() || (renderer->isRenderInline() && renderer->hasLayer())); // The only way an inline could paint like this is if it has a layer. // If we have no lines then we have no work to do. if (!firstLineBox()) return; if (!anyLineIntersectsRect(renderer, paintInfo.rect, paintOffset)) return; PaintInfo info(paintInfo); // See if our root lines intersect with the dirty rect. If so, then we paint // them. Note that boxes can easily overlap, so we can't make any assumptions // based off positions of our first line box or our last line box. for (InlineFlowBox* curr = firstLineBox(); curr; curr = curr->nextLineBox()) { if (lineIntersectsDirtyRect(renderer, curr, info, paintOffset)) { RootInlineBox& root = curr->root(); curr->paint(info, paintOffset, root.lineTop(), root.lineBottom(), layers); } } }
FloatRect RenderSVGText::objectBoundingBox() const { FloatRect boundingBox; for (InlineRunBox* runBox = firstLineBox(); runBox; runBox = runBox->nextLineBox()) { ASSERT(runBox->isInlineFlowBox()); InlineFlowBox* flowBox = static_cast<InlineFlowBox*>(runBox); for (InlineBox* box = flowBox->firstChild(); box; box = box->nextOnLine()) boundingBox.unite(FloatRect(box->x(), box->y(), box->width(), box->height())); } boundingBox.move(x(), y()); return boundingBox; }
void RenderInline::absoluteQuads(Vector<FloatQuad>& quads, bool topLevel) { for (InlineRunBox* curr = firstLineBox(); curr; curr = curr->nextLineBox()) { FloatRect localRect(curr->xPos(), curr->yPos(), curr->width(), curr->height()); quads.append(localToAbsoluteQuad(localRect)); } for (RenderObject* curr = firstChild(); curr; curr = curr->nextSibling()) { if (!curr->isText()) curr->absoluteQuads(quads, false); } if (continuation() && topLevel) continuation()->absoluteQuads(quads, topLevel); }
void LayoutSVGInline::absoluteQuads(Vector<FloatQuad>& quads) const { const LayoutSVGText* textRoot = LayoutSVGText::locateLayoutSVGTextAncestor(this); if (!textRoot) return; FloatRect textBoundingBox = textRoot->strokeBoundingBox(); for (InlineFlowBox* box = firstLineBox(); box; box = box->nextLineBox()) quads.append( localToAbsoluteQuad(FloatRect(textBoundingBox.x() + box->x().toFloat(), textBoundingBox.y() + box->y().toFloat(), box->logicalWidth().toFloat(), box->logicalHeight().toFloat()), false)); }
void RenderInline::absoluteRects(Vector<IntRect>& rects, int tx, int ty, bool topLevel) { for (InlineRunBox* curr = firstLineBox(); curr; curr = curr->nextLineBox()) rects.append(IntRect(tx + curr->xPos(), ty + curr->yPos(), curr->width(), curr->height())); for (RenderObject* curr = firstChild(); curr; curr = curr->nextSibling()) { if (!curr->isText()) curr->absoluteRects(rects, tx + curr->xPos(), ty + curr->yPos(), false); } if (continuation() && topLevel) continuation()->absoluteRects(rects, tx - containingBlock()->xPos() + continuation()->xPos(), ty - containingBlock()->yPos() + continuation()->yPos(), topLevel); }
void RenderSVGText::absoluteQuads(Vector<FloatQuad>& quads) { RenderSVGRoot* root = findSVGRootObject(parent()); if (!root) return; // Don't use objectBoundingBox here, as it's unites the selection rects. Makes it hard // to spot errors, if there are any using WebInspector. Individually feed them into 'rects'. for (InlineFlowBox* flow = firstLineBox(); flow; flow = flow->nextLineBox()) { for (InlineBox* box = flow->firstChild(); box; box = box->nextOnLine()) { FloatRect boxRect(box->x(), box->y(), box->width(), box->height()); // FIXME: crawling up the parent chain to map each quad is very inefficient // we should compute the absoluteTransform outside this loop first. quads.append(localToAbsoluteQuad(boxRect)); } } }
void RenderSVGTSpan::absoluteRects(Vector<IntRect>& rects, int, int, bool) { InlineRunBox* firstBox = firstLineBox(); SVGRootInlineBox* rootBox = firstBox ? static_cast<SVGInlineTextBox*>(firstBox)->svgRootInlineBox() : 0; RenderObject* object = rootBox ? rootBox->object() : 0; if (!object) return; int xRef = object->xPos() + xPos(); int yRef = object->yPos() + yPos(); for (InlineRunBox* curr = firstBox; curr; curr = curr->nextLineBox()) { FloatRect rect(xRef + curr->xPos(), yRef + curr->yPos(), curr->width(), curr->height()); rects.append(enclosingIntRect(absoluteTransform().mapRect(rect))); } }
void RenderSVGInline::absoluteQuads(Vector<FloatQuad>& quads) { InlineRunBox* firstBox = firstLineBox(); SVGRootInlineBox* rootBox = firstBox ? static_cast<SVGInlineTextBox*>(firstBox)->svgRootInlineBox() : 0; RenderBox* object = rootBox ? rootBox->block() : 0; if (!object) return; int xRef = object->x(); int yRef = object->y(); for (InlineRunBox* curr = firstBox; curr; curr = curr->nextLineBox()) { FloatRect rect(xRef + curr->x(), yRef + curr->y(), curr->width(), curr->height()); quads.append(localToAbsoluteQuad(rect)); } }
FloatRect RenderSVGText::relativeBBox(bool includeStroke) const { FloatRect repaintRect; for (InlineRunBox* runBox = firstLineBox(); runBox; runBox = runBox->nextLineBox()) { ASSERT(runBox->isInlineFlowBox()); InlineFlowBox* flowBox = static_cast<InlineFlowBox*>(runBox); for (InlineBox* box = flowBox->firstChild(); box; box = box->nextOnLine()) repaintRect.unite(FloatRect(box->xPos(), box->yPos(), box->width(), box->height())); } // SVG needs to include the strokeWidth(), not the textStrokeWidth(). if (includeStroke && style()->svgStyle()->hasStroke()) repaintRect.inflate(narrowPrecisionToFloat(KSVGPainterFactory::cssPrimitiveToLength(this, style()->svgStyle()->strokeWidth(), 0.0))); repaintRect.move(xPos(), yPos()); return repaintRect; }
void RenderSVGTextPath::absoluteRects(Vector<IntRect>& rects, int, int) { InlineRunBox* firstBox = firstLineBox(); SVGRootInlineBox* rootBox = firstBox ? static_cast<SVGInlineTextBox*>(firstBox)->svgRootInlineBox() : 0; RenderBlock* object = rootBox ? rootBox->block() : 0; if (!object) return; int xRef = object->x() + x(); int yRef = object->y() + y(); for (InlineRunBox* curr = firstBox; curr; curr = curr->nextLineBox()) { FloatRect rect(xRef + curr->xPos(), yRef + curr->yPos(), curr->width(), curr->height()); // FIXME: broken with CSS transforms rects.append(enclosingIntRect(absoluteTransform().mapRect(rect))); } }
void RenderSVGTextPath::absoluteQuads(Vector<FloatQuad>& quads, bool) { InlineRunBox* firstBox = firstLineBox(); SVGRootInlineBox* rootBox = firstBox ? static_cast<SVGInlineTextBox*>(firstBox)->svgRootInlineBox() : 0; RenderObject* object = rootBox ? rootBox->object() : 0; if (!object) return; int xRef = object->xPos() + xPos(); int yRef = object->yPos() + yPos(); for (InlineRunBox* curr = firstBox; curr; curr = curr->nextLineBox()) { FloatRect rect(xRef + curr->xPos(), yRef + curr->yPos(), curr->width(), curr->height()); // FIXME: broken with CSS transforms quads.append(absoluteTransform().mapRect(rect)); } }
void RenderSVGText::absoluteRects(Vector<IntRect>& rects, int, int) { RenderSVGRoot* root = findSVGRootObject(parent()); if (!root) return; // Don't use objectBoundingBox here, as it's unites the selection rects. Makes it hard // to spot errors, if there are any using WebInspector. Individually feed them into 'rects'. for (InlineRunBox* runBox = firstLineBox(); runBox; runBox = runBox->nextLineBox()) { ASSERT(runBox->isInlineFlowBox()); InlineFlowBox* flowBox = static_cast<InlineFlowBox*>(runBox); for (InlineBox* box = flowBox->firstChild(); box; box = box->nextOnLine()) { FloatRect boxRect(box->x(), box->y(), box->width(), box->height()); // FIXME: crawling up the parent chain to map each rect is very inefficient // we should compute the absoluteTransform outside this loop first. rects.append(enclosingIntRect(localToAbsoluteQuad(boxRect).boundingBox())); } } }
void RenderSVGText::absoluteRects(Vector<IntRect>& rects, int, int, bool) { RenderSVGRoot* root = findSVGRootObject(parent()); if (!root) return; int x, y; absolutePosition(x, y); AffineTransform htmlParentCtm = root->RenderContainer::absoluteTransform(); // Don't use relativeBBox here, as it's unites the selection rects. Makes it hard // to spot errors, if there are any using WebInspector. Individually feed them into 'rects'. for (InlineRunBox* runBox = firstLineBox(); runBox; runBox = runBox->nextLineBox()) { ASSERT(runBox->isInlineFlowBox()); InlineFlowBox* flowBox = static_cast<InlineFlowBox*>(runBox); for (InlineBox* box = flowBox->firstChild(); box; box = box->nextOnLine()) { FloatRect boxRect(box->xPos(), box->yPos(), box->width(), box->height()); boxRect.move(narrowPrecisionToFloat(x - htmlParentCtm.e()), narrowPrecisionToFloat(y - htmlParentCtm.f())); rects.append(enclosingIntRect(absoluteTransform().mapRect(boxRect))); } } }