void RenderInline::paintOutlines(QPainter *p, int _tx, int _ty) { if(style()->outlineWidth() == 0 || style()->outlineStyle() <= BHIDDEN) return; int offset = style()->outlineOffset(); // We may have to draw more than one outline path as they may be // disjoint. for(InlineRunBox *curr = firstLineBox(); curr; curr = curr->nextLineBox()) { QValueVector< QPoint > path; // collect topmost outline collectHorizontalBoxCoordinates(curr, path, false, offset); // collect right outline collectVerticalBoxCoordinates(curr, path, false, offset, &curr); // collect bottommost outline collectHorizontalBoxCoordinates(curr, path, true, offset); // collect left outline collectVerticalBoxCoordinates(curr, path, true, offset); if(path.size() < 3) continue; const QPoint *begin = linkEndToBegin(path); // paint the outline paintOutlinePath(p, _tx, _ty, begin, path.end(), BSLeft, -1, BSTop); } }
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; }
/** * Traverses the vertical outer borders of the given render flow's line * boxes and appends the point coordinates to the given point array. * @param line line box to begin traversal * @param pointArray point array * @param left \c true, traverse the left vertical coordinates, * \c false, traverse the right vertical coordinates. * @param lastline if not 0, returns the pointer to the last line box traversed */ static void collectVerticalBoxCoordinates(InlineRunBox *line, QValueVector< QPoint > &pointArray, bool left, int offset, InlineRunBox **lastline = 0) { InlineRunBox *last = 0; offset = left ? -offset : offset; for(InlineRunBox *curr = line; curr && !last; curr = left ? curr->prevLineBox() : curr->nextLineBox()) { InlineBox *root = curr; bool isLast = lineBoxesDisjoint(curr, kAbs(offset), left); if(isLast) last = curr; if(root != line && !isLast) while(root->parent()) root = root->parent(); QPoint newPnt(curr->xPos() + !left * curr->width() + offset, (left ? root->topOverflow() : root->bottomOverflow()) + offset); if(!pointArray.isEmpty()) { QPoint lastPnt = pointArray.back(); if(newPnt.x() > lastPnt.x() && !left) pointArray.back().setY(kMin(lastPnt.y(), root->topOverflow() - offset)); else if(newPnt.x() < lastPnt.x() && left) pointArray.back().setY(kMax(lastPnt.y(), root->bottomOverflow() + offset)); QPoint insPnt(newPnt.x(), pointArray.back().y()); // kdDebug(6040) << "left: " << lastPnt << " == " << insPnt << ": " << (insPnt == lastPnt) << endl; appendPoint(pointArray, insPnt); } appendPoint(pointArray, newPnt); } if(lastline) *lastline = last; }
inline int minXPos(const RenderInline *o) { int retval = 6666666; if(!o->firstLineBox()) return 0; for(InlineRunBox *curr = o->firstLineBox(); curr; curr = curr->nextLineBox()) retval = kMin(retval, int(curr->m_x)); return retval; }
void RenderFlow::extractLineBox(InlineFlowBox* box) { m_lastLineBox = box->prevFlowBox(); if (box == m_firstLineBox) m_firstLineBox = 0; if (box->prevLineBox()) box->prevLineBox()->setNextLineBox(0); box->setPreviousLineBox(0); for (InlineRunBox* curr = box; curr; curr = curr->nextLineBox()) curr->setExtracted(); }
void RenderFlow::dirtyLineBoxes(bool fullLayout, bool isRootLineBox) { if (!isRootLineBox && isReplaced()) return RenderContainer::dirtyLineBoxes(fullLayout, isRootLineBox); if (fullLayout) deleteLineBoxes(); else { for (InlineRunBox* curr = firstLineBox(); curr; curr = curr->nextLineBox()) curr->dirtyLineBoxes(); } }
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; }
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; }
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 RenderFlow::repaint(Priority prior) { if (isInlineFlow()) { // Find our leftmost position. int left = 0; // root inline box not reliably availabe during relayout int top = firstLineBox() ? ( needsLayout() ? firstLineBox()->xPos() : firstLineBox()->root()->topOverflow() ) : 0; for (InlineRunBox* curr = firstLineBox(); curr; curr = curr->nextLineBox()) if (curr == firstLineBox() || curr->xPos() < left) left = curr->xPos(); // 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->isInlineFlow() && inlineFlow != cb; inlineFlow = inlineFlow->parent()) { if (inlineFlow->style() && inlineFlow->style()->position() == RELATIVE && inlineFlow->layer()) { KHTMLAssert(inlineFlow->isBox()); static_cast<RenderBox*>(inlineFlow)->relativePositionOffset(left, top); } } RootInlineBox *lastRoot = lastLineBox() && !needsLayout() ? lastLineBox()->root() : 0; containingBlock()->repaintRectangle(-ow+left, -ow+top, width()+ow*2, (lastRoot ? lastRoot->bottomOverflow() - top : height())+ow*2, prior); } else { if (firstLineBox() && firstLineBox()->topOverflow() < 0) { int ow = style() ? style()->outlineSize() : 0; repaintRectangle(-ow, -ow+firstLineBox()->topOverflow(), effectiveWidth()+ow*2, effectiveHeight()+ow*2, prior); } else return RenderBox::repaint(prior); } }
bool RenderInline::nodeAtPoint(NodeInfo& info, int _x, int _y, int _tx, int _ty, HitTestAction hitTestAction, bool inside) { // Check our kids if our HitTestAction says to. if (hitTestAction != HitTestSelfOnly) { for (RenderObject* child = lastChild(); child; child = child->previousSibling()) if (!child->layer() && !child->isFloating() && child->nodeAtPoint(info, _x, _y, _tx, _ty)) inside = true; } // Check our line boxes if we're still not inside. if (hitTestAction != HitTestChildrenOnly && !inside && style()->visibility() != HIDDEN) { // See if we're inside one of our line boxes. for (InlineRunBox* curr = firstLineBox(); curr; curr = curr->nextLineBox()) { if((_y >=_ty + curr->m_y) && (_y < _ty + curr->m_y + curr->m_height) && (_x >= _tx + curr->m_x) && (_x <_tx + curr->m_x + curr->m_width) ) { inside = true; break; } } } if (inside && element()) { if (info.innerNode() && info.innerNode()->renderer() && !info.innerNode()->renderer()->isInline()) { // Within the same layer, inlines are ALWAYS fully above blocks. Change inner node. info.setInnerNode(element()); // Clear everything else. info.setInnerNonSharedNode(0); info.setURLElement(0); } if (!info.innerNode()) info.setInnerNode(element()); if(!info.innerNonSharedNode()) info.setInnerNonSharedNode(element()); } return inside; }
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 (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 quad is very inefficient // we should compute the absoluteTransform outside this loop first. quads.append(localToAbsoluteQuad(boxRect)); } } }
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 RenderFlow::addFocusRingRects(QPainter *p, int _tx, int _ty) { // Only paint focus ring around outermost contenteditable element. // But skip the body element if it is outermost. if (element() && element()->isContentEditable()) { if (element()->parentNode() && !element()->parentNode()->isContentEditable() && element()->id() != ID_BODY) p->addFocusRingRect(_tx, _ty, width(), height()); return; } for (InlineRunBox* curr = firstLineBox(); curr; curr = curr->nextLineBox()) { p->addFocusRingRect(_tx + curr->xPos(), _ty + curr->yPos(), curr->width(), curr->height()); } for (RenderObject* curr = firstChild(); curr; curr = curr->nextSibling()) { if (!curr->isText()) curr->addFocusRingRects(p, _tx + curr->xPos(), _ty + curr->yPos()); } if (continuation()) continuation()->addFocusRingRects(p, _tx - containingBlock()->xPos() + continuation()->xPos(), _ty - containingBlock()->yPos() + continuation()->yPos()); }
void InlineFlowBox::paintBackground(QPainter* p, const QColor& c, const BackgroundLayer* bgLayer, int my, int mh, int _tx, int _ty, int w, int h) { CachedImage* bg = bgLayer->backgroundImage(); bool hasBackgroundImage = bg && (bg->pixmap_size() == bg->valid_rect().size()) && !bg->isTransparent() && !bg->isErrorImage(); if (!hasBackgroundImage || (!prevLineBox() && !nextLineBox()) || !parent()) object()->paintBackgroundExtended(p, c, bgLayer, my, mh, _tx, _ty, w, h, borderLeft(), borderRight(), paddingLeft(), paddingRight()); else { // We have a background image that spans multiple lines. // We need to adjust _tx and _ty by the width of all previous lines. // Think of background painting on inlines as though you had one long line, a single continuous // strip. Even though that strip has been broken up across multiple lines, you still paint it // as though you had one single line. This means each line has to pick up the background where // the previous line left off. // FIXME: What the heck do we do with RTL here? The math we're using is obviously not right, // but it isn't even clear how this should work at all. int xOffsetOnLine = 0; for (InlineRunBox* curr = prevLineBox(); curr; curr = curr->prevLineBox()) xOffsetOnLine += curr->width(); int startX = _tx - xOffsetOnLine; int totalWidth = xOffsetOnLine; for (InlineRunBox* curr = this; curr; curr = curr->nextLineBox()) totalWidth += curr->width(); p->save(); p->setClipRect(QRect(_tx, _ty, width(), height()), QPainter::CoordPainter); object()->paintBackgroundExtended(p, c, bgLayer, my, mh, startX, _ty, totalWidth, h, borderLeft(), borderRight(), paddingLeft(), paddingRight()); p->restore(); } }
void RenderFlow::detach() { if (!documentBeingDestroyed()) { if (m_firstLineBox) { // We can't wait for RenderContainer::detach to clear the selection, // because by then we will have nuked the line boxes. if (isSelectionBorder()) canvas()->clearSelection(); // If line boxes are contained inside a root, that means we're an inline. // In that case, we need to remove all the line boxes so that the parent // lines aren't pointing to deleted children. If the first line box does // not have a parent that means they are either already disconnected or // root lines that can just be destroyed without disconnecting. if (m_firstLineBox->parent()) { for (InlineRunBox* box = m_firstLineBox; box; box = box->nextLineBox()) box->remove(); } // If we are an anonymous block, then our line boxes might have children // that will outlast this block. In the non-anonymous block case those // children will be destroyed by the time we return from this function. if (isAnonymousBlock()) { for (InlineFlowBox* box = m_firstLineBox; box; box = box->nextFlowBox()) { while (InlineBox *childBox = box->firstChild()) { childBox->remove(); } } } } else if (isInline() && parent()) parent()->dirtyLinesFromChangedChild(this, false); } deleteLineBoxes(); RenderContainer::detach(); }
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))); } } }
void RenderInline::absoluteRects(QValueList<QRect>& rects, int _tx, int _ty) { for (InlineRunBox* curr = firstLineBox(); curr; curr = curr->nextLineBox()) rects.append(QRect(_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()); if (continuation()) continuation()->absoluteRects(rects, _tx - containingBlock()->xPos() + continuation()->xPos(), _ty - containingBlock()->yPos() + continuation()->yPos()); }
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 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 RenderFlow::paintOutlines(QPainter *p, int _tx, int _ty) { if (style()->outlineStyle() <= BHIDDEN) return; QPtrList <QRect> rects; rects.setAutoDelete(true); rects.append(new QRect(0,0,0,0)); for (InlineRunBox* curr = firstLineBox(); curr; curr = curr->nextLineBox()) { rects.append(new QRect(curr->xPos(), curr->yPos(), curr->width(), curr->height())); } rects.append(new QRect(0,0,0,0)); for (unsigned int i = 1; i < rects.count() - 1; i++) paintOutlineForLine(p, _tx, _ty, *rects.at(i-1), *rects.at(i), *rects.at(i+1)); }
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)); } }
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 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 RenderInline::addFocusRingRects(QPainter *p, int _tx, int _ty) { for (InlineRunBox* curr = firstLineBox(); curr; curr = curr->nextLineBox()) { p->addFocusRingRect(_tx + curr->xPos(), _ty + curr->yPos(), curr->width(), curr->height()); } for (RenderObject* curr = firstChild(); curr; curr = curr->nextSibling()) { if (!curr->isText()) curr->addFocusRingRects(p, _tx + curr->xPos(), _ty + curr->yPos()); } if (continuation()) continuation()->addFocusRingRects(p, _tx - containingBlock()->xPos() + continuation()->xPos(), _ty - containingBlock()->yPos() + continuation()->yPos()); }
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))); } }
/** * Checks whether the given line box' extents and the following line box' * extents are disjount (i. e. do not share the same x-coordinate range). * @param line line box * @param toBegin \c true, compare with preceding line box, \c false, with * succeeding * @return \c true if this and the next box are disjoint */ inline static bool lineBoxesDisjoint(InlineRunBox *line, int offset, bool toBegin) { InlineRunBox *next = toBegin ? line->prevLineBox() : line->nextLineBox(); return !next || next->xPos() + next->width() + 2 * offset < line->xPos() || next->xPos() > line->xPos() + line->width() + 2 * offset; }
void RenderFlow::dirtyLinesFromChangedChild(RenderObject* child, bool adding) { if (!parent() || selfNeedsLayout() || isTable()) return; // For an empty inline, go ahead and propagate the check up to our parent. if (isInline() && !firstLineBox()) return parent()->dirtyLinesFromChangedChild(this); // Try to figure out which line box we belong in. First try to find a previous // line box by examining our siblings. If we didn't find a line box, then use our // parent's first line box. RootInlineBox* box = 0; RenderObject* curr = 0; for (curr = child->previousSibling(); curr; curr = curr->previousSibling()) { if (curr->isFloatingOrPositioned()) continue; if (curr->isReplaced()) { InlineBox* wrapper = curr->inlineBoxWrapper(); if (wrapper) box = wrapper->root(); } else if (curr->isText()) { InlineTextBox* textBox = static_cast<RenderText*>(curr)->lastTextBox(); if (textBox) box = textBox->root(); } else if (curr->isInlineFlow()) { InlineRunBox* runBox = static_cast<RenderFlow*>(curr)->lastLineBox(); if (runBox) box = runBox->root(); } if (box) break; } if (!box && firstLineBox()) box = firstLineBox()->root(); // If we found a line box, then dirty it. if (box) { RootInlineBox* adjacentBox; box->markDirty(); // dirty the adjacent lines that might be affected // NOTE: we dirty the previous line because RootInlineBox objects cache // the address of the first object on the next line after a BR, which we may be // invalidating here. For more info, see how RenderBlock::layoutInlineChildren // calls setLineBreakInfo with the result of findNextLineBreak. findNextLineBreak, // despite the name, actually returns the first RenderObject after the BR. // <rdar://problem/3849947> "Typing after pasting line does not appear until after window resize." adjacentBox = box->prevRootBox(); if (adjacentBox) adjacentBox->markDirty(); if (child->isBR() || (curr && curr->isBR())) { adjacentBox = box->nextRootBox(); if (adjacentBox) adjacentBox->markDirty(); } } }
QRect RenderFlow::getAbsoluteRepaintRect() { if (isInlineFlow()) { // Find our leftmost position. int left = 0; int top = firstLineBox() ? firstLineBox()->yPos() : 0; for (InlineRunBox* curr = firstLineBox(); curr; curr = curr->nextLineBox()) if (curr == firstLineBox() || curr->xPos() < left) left = curr->xPos(); // Now invalidate a rectangle. int ow = style() ? style()->outlineSize() : 0; if (isCompact()) left -= m_x; // 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->isInlineFlow() && inlineFlow != cb; inlineFlow = inlineFlow->parent()) { if (inlineFlow->style()->position() == RELATIVE && inlineFlow->layer()) inlineFlow->layer()->relativePositionOffset(left, top); } QRect r(-ow+left, -ow+top, width()+ow*2, height()+ow*2); 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.left(); int y = r.top(); QRect boxRect(0, 0, cb->layer()->width(), cb->layer()->height()); cb->layer()->subtractScrollOffset(x,y); // For overflow:auto/scroll/hidden. QRect repaintRect(x, y, r.width(), r.height()); r = repaintRect.intersect(boxRect); } cb->computeAbsoluteRepaintRect(r); if (ow) { for (RenderObject* curr = firstChild(); curr; curr = curr->nextSibling()) { if (!curr->isText()) { QRect childRect = curr->getAbsoluteRepaintRectWithOutline(ow); r = r.unite(childRect); } } if (continuation() && !continuation()->isInline()) { QRect contRect = continuation()->getAbsoluteRepaintRectWithOutline(ow); r = r.unite(contRect); } } return r; } else { if (firstLineBox() && firstLineBox()->topOverflow() < 0) { int ow = style() ? style()->outlineSize() : 0; QRect r(-ow, -ow+firstLineBox()->topOverflow(), overflowWidth(false)+ow*2, overflowHeight(false)+ow*2-firstLineBox()->topOverflow()); computeAbsoluteRepaintRect(r); return r; } } return RenderContainer::getAbsoluteRepaintRect(); }