diff options
author | Ben Murdoch <benm@google.com> | 2011-05-05 14:36:32 +0100 |
---|---|---|
committer | Ben Murdoch <benm@google.com> | 2011-05-10 15:38:30 +0100 |
commit | f05b935882198ccf7d81675736e3aeb089c5113a (patch) | |
tree | 4ea0ca838d9ef1b15cf17ddb3928efb427c7e5a1 /WebCore/rendering | |
parent | 60fbdcc62bced8db2cb1fd233cc4d1e4ea17db1b (diff) | |
download | external_webkit-f05b935882198ccf7d81675736e3aeb089c5113a.zip external_webkit-f05b935882198ccf7d81675736e3aeb089c5113a.tar.gz external_webkit-f05b935882198ccf7d81675736e3aeb089c5113a.tar.bz2 |
Merge WebKit at r74534: Initial merge by git.
Change-Id: I6ccd1154fa1b19c2ec2a66878eb675738735f1eb
Diffstat (limited to 'WebCore/rendering')
116 files changed, 2077 insertions, 1689 deletions
diff --git a/WebCore/rendering/HitTestResult.cpp b/WebCore/rendering/HitTestResult.cpp index 1bc238f..579042b 100644 --- a/WebCore/rendering/HitTestResult.cpp +++ b/WebCore/rendering/HitTestResult.cpp @@ -48,6 +48,16 @@ namespace WebCore { using namespace HTMLNames; +HitTestResult::HitTestResult() + : m_isOverWidget(false) + , m_isRectBased(false) + , m_topPadding(0) + , m_rightPadding(0) + , m_bottomPadding(0) + , m_leftPadding(0) +{ +} + HitTestResult::HitTestResult(const IntPoint& point) : m_point(point) , m_isOverWidget(false) diff --git a/WebCore/rendering/HitTestResult.h b/WebCore/rendering/HitTestResult.h index 8d9b18d..1545da9 100644 --- a/WebCore/rendering/HitTestResult.h +++ b/WebCore/rendering/HitTestResult.h @@ -43,6 +43,7 @@ class Scrollbar; class HitTestResult { public: + HitTestResult(); HitTestResult(const IntPoint&); // Pass non-negative padding values to perform a rect-based hit test. HitTestResult(const IntPoint& centerPoint, unsigned topPadding, unsigned rightPadding, unsigned bottomPadding, unsigned leftPadding); diff --git a/WebCore/rendering/InlineBox.h b/WebCore/rendering/InlineBox.h index 991a3ff..5b3f682 100644 --- a/WebCore/rendering/InlineBox.h +++ b/WebCore/rendering/InlineBox.h @@ -131,6 +131,8 @@ public: virtual void paint(PaintInfo&, int tx, int ty); virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, int x, int y, int tx, int ty); + InlineBox* next() const { return m_next; } + // Overloaded new operator. void* operator new(size_t, RenderArena*) throw(); @@ -176,12 +178,7 @@ public: } bool isConstructed() { return m_constructed; } - virtual void setConstructed() - { - m_constructed = true; - if (m_next) - m_next->setConstructed(); - } + virtual void setConstructed() { m_constructed = true; } void setExtracted(bool b = true) { m_extracted = b; } @@ -233,6 +230,8 @@ public: int width() const { return isHorizontal() ? logicalWidth() : logicalHeight(); } int height() const { return isHorizontal() ? logicalHeight() : logicalWidth(); } + IntRect frameRect() const { return IntRect(x(), y(), width(), height()); } + // The logicalLeft position is the left edge of the line box in a horizontal line and the top edge in a vertical line. int logicalLeft() const { return isHorizontal() ? m_x : m_y; } int logicalRight() const { return logicalLeft() + logicalWidth(); } @@ -265,7 +264,6 @@ public: virtual int baselinePosition(FontBaseline baselineType) const { return boxModelObject()->baselinePosition(baselineType, m_firstLine, isHorizontal() ? HorizontalLine : VerticalLine, PositionOnContainingLine); } virtual int lineHeight() const { return boxModelObject()->lineHeight(m_firstLine, isHorizontal() ? HorizontalLine : VerticalLine, PositionOnContainingLine); } - virtual int caretMinOffset() const; virtual int caretMaxOffset() const; virtual unsigned caretMaxRenderedOffset() const; diff --git a/WebCore/rendering/InlineFlowBox.cpp b/WebCore/rendering/InlineFlowBox.cpp index ee9fe9f..de369d1 100644 --- a/WebCore/rendering/InlineFlowBox.cpp +++ b/WebCore/rendering/InlineFlowBox.cpp @@ -259,18 +259,7 @@ int InlineFlowBox::placeBoxesInInlineDirection(int logicalLeft, bool& needsWordS { // Set our x position. setLogicalLeft(logicalLeft); - - int logicalLeftLayoutOverflow = logicalLeft; - int logicalRightLayoutOverflow = logicalLeft; - int logicalLeftVisualOverflow = logicalLeft; - int logicalRightVisualOverflow = logicalLeft; - - int boxShadowLogicalLeft; - int boxShadowLogicalRight; - renderer()->style(m_firstLine)->getBoxShadowInlineDirectionExtent(boxShadowLogicalLeft, boxShadowLogicalRight); - - logicalLeftVisualOverflow = min(logicalLeft + boxShadowLogicalLeft, logicalLeftVisualOverflow); - + int startLogicalLeft = logicalLeft; logicalLeft += borderLogicalLeft() + paddingLogicalLeft(); @@ -284,30 +273,6 @@ int InlineFlowBox::placeBoxesInInlineDirection(int logicalLeft, bool& needsWordS needsWordSpacing = !isSpaceOrNewline(rt->characters()[text->end()]); } text->setLogicalLeft(logicalLeft); - - int strokeOverflow = static_cast<int>(ceilf(rt->style()->textStrokeWidth() / 2.0f)); - - // If letter-spacing is negative, we should factor that into right layout overflow. (Even in RTL, letter-spacing is - // applied to the right, so this is not an issue with left overflow. - int letterSpacing = min(0, (int)rt->style(m_firstLine)->font().letterSpacing()); - logicalRightLayoutOverflow = max(logicalLeft + text->logicalWidth() - letterSpacing, logicalRightLayoutOverflow); - - GlyphOverflowAndFallbackFontsMap::iterator it = textBoxDataMap.find(static_cast<InlineTextBox*>(curr)); - GlyphOverflow* glyphOverflow = it == textBoxDataMap.end() ? 0 : &it->second.second; - - int logicalLeftGlyphOverflow = -strokeOverflow - (glyphOverflow ? glyphOverflow->left : 0); - int logicalRightGlyphOverflow = strokeOverflow - letterSpacing + (glyphOverflow ? glyphOverflow->right : 0); - - int childOverflowLogicalLeft = logicalLeftGlyphOverflow; - int childOverflowLogicalRight = logicalRightGlyphOverflow; - int textShadowLogicalLeft; - int textShadowLogicalRight; - rt->style(m_firstLine)->getTextShadowInlineDirectionExtent(textShadowLogicalLeft, textShadowLogicalRight); - childOverflowLogicalLeft = min(childOverflowLogicalLeft, textShadowLogicalLeft + logicalLeftGlyphOverflow); - childOverflowLogicalRight = max(childOverflowLogicalRight, textShadowLogicalRight + logicalRightGlyphOverflow); - logicalLeftVisualOverflow = min(logicalLeft + childOverflowLogicalLeft, logicalLeftVisualOverflow); - logicalRightVisualOverflow = max(logicalLeft + text->logicalWidth() + childOverflowLogicalRight, logicalRightVisualOverflow); - logicalLeft += text->logicalWidth(); } else { if (curr->renderer()->isPositioned()) { @@ -325,10 +290,6 @@ int InlineFlowBox::placeBoxesInInlineDirection(int logicalLeft, bool& needsWordS logicalLeft += flow->marginLogicalLeft(); logicalLeft = flow->placeBoxesInInlineDirection(logicalLeft, needsWordSpacing, textBoxDataMap); logicalLeft += flow->marginLogicalRight(); - logicalLeftLayoutOverflow = min(logicalLeftLayoutOverflow, flow->logicalLeftLayoutOverflow()); - logicalRightLayoutOverflow = max(logicalRightLayoutOverflow, flow->logicalRightLayoutOverflow()); - logicalLeftVisualOverflow = min(logicalLeftVisualOverflow, flow->logicalLeftVisualOverflow()); - logicalRightVisualOverflow = max(logicalRightVisualOverflow, flow->logicalRightVisualOverflow()); } else if (!curr->renderer()->isListMarker() || toRenderListMarker(curr->renderer())->isInside()) { // The box can have a different writing-mode than the overall line, so this is a bit complicated. // Just get all the physical margin and overflow values by hand based off |isVertical|. @@ -337,18 +298,6 @@ int InlineFlowBox::placeBoxesInInlineDirection(int logicalLeft, bool& needsWordS logicalLeft += logicalLeftMargin; curr->setLogicalLeft(logicalLeft); - - RenderBox* box = toRenderBox(curr->renderer()); - - int childOverflowLogicalLeft = box->hasOverflowClip() ? 0 : (isHorizontal() ? box->leftLayoutOverflow() : box->topLayoutOverflow()); - int childOverflowLogicalRight = box->hasOverflowClip() ? curr->logicalWidth() : (isHorizontal() ? box->rightLayoutOverflow() : box->bottomLayoutOverflow()); - - logicalLeftLayoutOverflow = min(logicalLeft + childOverflowLogicalLeft, logicalLeftLayoutOverflow); - logicalRightLayoutOverflow = max(logicalLeft + childOverflowLogicalRight, logicalRightLayoutOverflow); - - logicalLeftVisualOverflow = min(logicalLeft + (isHorizontal() ? box->leftVisualOverflow() : box->topVisualOverflow()), logicalLeftVisualOverflow); - logicalRightVisualOverflow = max(logicalLeft + (isHorizontal() ? box->rightVisualOverflow() : box->bottomVisualOverflow()), logicalRightVisualOverflow); - logicalLeft += curr->logicalWidth() + logicalRightMargin; } } @@ -356,10 +305,6 @@ int InlineFlowBox::placeBoxesInInlineDirection(int logicalLeft, bool& needsWordS logicalLeft += borderLogicalRight() + paddingLogicalRight(); setLogicalWidth(logicalLeft - startLogicalLeft); - logicalRightVisualOverflow = max(logicalLeft + boxShadowLogicalRight, logicalRightVisualOverflow); - logicalRightLayoutOverflow = max(logicalLeft, logicalRightLayoutOverflow); - - setInlineDirectionOverflowPositions(logicalLeftLayoutOverflow, logicalRightLayoutOverflow, logicalLeftVisualOverflow, logicalRightVisualOverflow); return logicalLeft; } @@ -552,24 +497,27 @@ void InlineFlowBox::computeLogicalBoxHeights(int& maxPositionTop, int& maxPositi usedFonts = it == textBoxDataMap.end() ? 0 : &it->second.first; } - if (usedFonts && curr->renderer()->style(m_firstLine)->lineHeight().isNegative()) { + if (usedFonts && !usedFonts->isEmpty() && curr->renderer()->style(m_firstLine)->lineHeight().isNegative()) { usedFonts->append(curr->renderer()->style(m_firstLine)->font().primaryFont()); - Length parentLineHeight = curr->renderer()->parent()->style()->lineHeight(); bool baselineSet = false; baseline = 0; int baselineToBottom = 0; for (size_t i = 0; i < usedFonts->size(); ++i) { int halfLeading = (usedFonts->at(i)->lineSpacing() - usedFonts->at(i)->height()) / 2; - int usedFontAscent = halfLeading + usedFonts->at(i)->ascent(baselineType); - int usedFontDescent = usedFonts->at(i)->lineSpacing() - usedFontAscent; + int usedFontBaseline = halfLeading + usedFonts->at(i)->ascent(baselineType); + int usedFontBaselineToBottom = usedFonts->at(i)->lineSpacing() - usedFontBaseline; if (!baselineSet) { baselineSet = true; - baseline = usedFontAscent; - baselineToBottom = usedFontDescent; + baseline = usedFontBaseline; + baselineToBottom = usedFontBaselineToBottom; } else { - baseline = max(baseline, usedFontAscent); - baselineToBottom = max(baselineToBottom, usedFontDescent); + baseline = max(baseline, usedFontBaseline); + baselineToBottom = max(baselineToBottom, usedFontBaselineToBottom); } + if (!affectsAscent) + affectsAscent = usedFonts->at(i)->ascent() - curr->logicalTop() > 0; + if (!affectsDescent) + affectsDescent = usedFonts->at(i)->descent() + curr->logicalTop() > 0; } lineHeight = baseline + baselineToBottom; } else { @@ -624,7 +572,7 @@ void InlineFlowBox::computeLogicalBoxHeights(int& maxPositionTop, int& maxPositi } void InlineFlowBox::placeBoxesInBlockDirection(int top, int maxHeight, int maxAscent, bool strictMode, int& lineTop, int& lineBottom, bool& setLineTop, - int& lineTopIncludingMargins, int& lineBottomIncludingMargins, bool& containsRuby, FontBaseline baselineType) + int& lineTopIncludingMargins, int& lineBottomIncludingMargins, bool& hasAnnotationsBefore, bool& hasAnnotationsAfter, FontBaseline baselineType) { if (isRootInlineBox()) setLogicalTop(top + maxAscent - baselinePosition(baselineType)); // Place our root box. @@ -638,7 +586,7 @@ void InlineFlowBox::placeBoxesInBlockDirection(int top, int maxHeight, int maxAs bool isInlineFlow = curr->isInlineFlowBox(); if (isInlineFlow) static_cast<InlineFlowBox*>(curr)->placeBoxesInBlockDirection(top, maxHeight, maxAscent, strictMode, lineTop, lineBottom, setLineTop, - lineTopIncludingMargins, lineBottomIncludingMargins, containsRuby, baselineType); + lineTopIncludingMargins, lineBottomIncludingMargins, hasAnnotationsBefore, hasAnnotationsAfter, baselineType); bool childAffectsTopBottomPos = true; if (curr->logicalTop() == PositionTop) @@ -682,7 +630,11 @@ void InlineFlowBox::placeBoxesInBlockDirection(int top, int maxHeight, int maxAs // Treat the leading on the first and last lines of ruby runs as not being part of the overall lineTop/lineBottom. // Really this is a workaround hack for the fact that ruby should have been done as line layout and not done using // inline-block. - containsRuby = true; + if (!renderer()->style()->isFlippedLinesWritingMode()) + hasAnnotationsBefore = true; + else + hasAnnotationsAfter = true; + RenderRubyRun* rubyRun = static_cast<RenderRubyRun*>(curr->renderer()); if (RenderRubyBase* rubyBase = rubyRun->rubyBase()) { int bottomRubyBaseLeading = (curr->logicalHeight() - rubyBase->logicalBottom()) + rubyBase->logicalHeight() - (rubyBase->lastRootBox() ? rubyBase->lastRootBox()->lineBottom() : 0); @@ -691,7 +643,14 @@ void InlineFlowBox::placeBoxesInBlockDirection(int top, int maxHeight, int maxAs boxHeight -= (topRubyBaseLeading + bottomRubyBaseLeading); } } - + if (curr->isInlineTextBox() && curr->renderer()->style(m_firstLine)->textEmphasisMark() != TextEmphasisMarkNone) { + bool emphasisMarkIsOver = curr->renderer()->style(m_firstLine)->textEmphasisPosition() == TextEmphasisPositionOver; + if (emphasisMarkIsOver != curr->renderer()->style(m_firstLine)->isFlippedLinesWritingMode()) + hasAnnotationsBefore = true; + else + hasAnnotationsAfter = true; + } + if (!setLineTop) { setLineTop = true; lineTop = newLogicalTop; @@ -743,32 +702,121 @@ void InlineFlowBox::flipLinesInBlockDirection(int lineTop, int lineBottom) } } -void InlineFlowBox::computeBlockDirectionOverflow(int lineTop, int lineBottom, bool strictMode, GlyphOverflowAndFallbackFontsMap& textBoxDataMap) +void InlineFlowBox::addBoxShadowVisualOverflow(IntRect& logicalVisualOverflow) +{ + if (!parent()) + return; // Box-shadow doesn't apply to root line boxes. + + int boxShadowLogicalTop; + int boxShadowLogicalBottom; + renderer()->style(m_firstLine)->getBoxShadowBlockDirectionExtent(boxShadowLogicalTop, boxShadowLogicalBottom); + + int logicalTopVisualOverflow = min(logicalTop() + boxShadowLogicalTop, logicalVisualOverflow.y()); + int logicalBottomVisualOverflow = max(logicalBottom() + boxShadowLogicalBottom, logicalVisualOverflow.bottom()); + + int boxShadowLogicalLeft; + int boxShadowLogicalRight; + renderer()->style(m_firstLine)->getBoxShadowInlineDirectionExtent(boxShadowLogicalLeft, boxShadowLogicalRight); + + int logicalLeftVisualOverflow = min(logicalLeft() + boxShadowLogicalLeft, logicalVisualOverflow.x()); + int logicalRightVisualOverflow = max(logicalRight() + boxShadowLogicalRight, logicalVisualOverflow.right()); + + logicalVisualOverflow = IntRect(logicalLeftVisualOverflow, logicalTopVisualOverflow, + logicalRightVisualOverflow - logicalLeftVisualOverflow, logicalBottomVisualOverflow - logicalTopVisualOverflow); +} + +void InlineFlowBox::addTextBoxVisualOverflow(const InlineTextBox* textBox, GlyphOverflowAndFallbackFontsMap& textBoxDataMap, IntRect& logicalVisualOverflow) +{ + RenderStyle* style = renderer()->style(m_firstLine); + int strokeOverflow = static_cast<int>(ceilf(style->textStrokeWidth() / 2.0f)); + + GlyphOverflowAndFallbackFontsMap::iterator it = textBoxDataMap.find(textBox); + GlyphOverflow* glyphOverflow = it == textBoxDataMap.end() ? 0 : &it->second.second; + + bool isFlippedLine = style->isFlippedLinesWritingMode(); + + int topGlyphEdge = glyphOverflow ? (isFlippedLine ? glyphOverflow->bottom : glyphOverflow->top) : 0; + int bottomGlyphEdge = glyphOverflow ? (isFlippedLine ? glyphOverflow->top : glyphOverflow->bottom) : 0; + int leftGlyphEdge = glyphOverflow ? glyphOverflow->left : 0; + int rightGlyphEdge = glyphOverflow ? glyphOverflow->right : 0; + + int topGlyphOverflow = -strokeOverflow - topGlyphEdge; + int bottomGlyphOverflow = strokeOverflow + bottomGlyphEdge; + int leftGlyphOverflow = -strokeOverflow - leftGlyphEdge; + int rightGlyphOverflow = strokeOverflow + rightGlyphEdge; + + if (style->textEmphasisMark() != TextEmphasisMarkNone) { + int emphasisMarkHeight = style->font().emphasisMarkHeight(style->textEmphasisMarkString()); + if ((style->textEmphasisPosition() == TextEmphasisPositionOver) == (!style->isFlippedLinesWritingMode())) + topGlyphOverflow = min(topGlyphOverflow, -emphasisMarkHeight); + else + bottomGlyphOverflow = max(bottomGlyphOverflow, emphasisMarkHeight); + } + + // If letter-spacing is negative, we should factor that into right layout overflow. (Even in RTL, letter-spacing is + // applied to the right, so this is not an issue with left overflow. + int letterSpacing = min(0, (int)style->font().letterSpacing()); + rightGlyphOverflow -= letterSpacing; + + int textShadowLogicalTop; + int textShadowLogicalBottom; + style->getTextShadowBlockDirectionExtent(textShadowLogicalTop, textShadowLogicalBottom); + + int childOverflowLogicalTop = min(textShadowLogicalTop + topGlyphOverflow, topGlyphOverflow); + int childOverflowLogicalBottom = max(textShadowLogicalBottom + bottomGlyphOverflow, bottomGlyphOverflow); + + int textShadowLogicalLeft; + int textShadowLogicalRight; + style->getTextShadowInlineDirectionExtent(textShadowLogicalLeft, textShadowLogicalRight); + + int childOverflowLogicalLeft = min(textShadowLogicalLeft + leftGlyphOverflow, leftGlyphOverflow); + int childOverflowLogicalRight = max(textShadowLogicalRight + rightGlyphOverflow, rightGlyphOverflow); + + int logicalTopVisualOverflow = min(textBox->logicalTop() + childOverflowLogicalTop, logicalVisualOverflow.y()); + int logicalBottomVisualOverflow = max(textBox->logicalBottom() + childOverflowLogicalBottom, logicalVisualOverflow.bottom()); + int logicalLeftVisualOverflow = min(textBox->logicalLeft() + childOverflowLogicalLeft, logicalVisualOverflow.x()); + int logicalRightVisualOverflow = max(textBox->logicalRight() + childOverflowLogicalRight, logicalVisualOverflow.right()); + + logicalVisualOverflow = IntRect(logicalLeftVisualOverflow, logicalTopVisualOverflow, + logicalRightVisualOverflow - logicalLeftVisualOverflow, logicalBottomVisualOverflow - logicalTopVisualOverflow); +} + +void InlineFlowBox::addReplacedChildOverflow(const InlineBox* inlineBox, IntRect& logicalLayoutOverflow, IntRect& logicalVisualOverflow) { - bool isFlippedLine = renderer()->style(m_firstLine)->isFlippedLinesWritingMode(); + RenderBox* box = toRenderBox(inlineBox->renderer()); + + // Visual overflow only propagates if the box doesn't have a self-painting layer. This rectangle does not include + // transforms or relative positioning (since those objects always have self-painting layers), but it does need to be adjusted + // for writing-mode differences. + if (!box->hasSelfPaintingLayer()) { + IntRect childLogicalVisualOverflow = box->logicalVisualOverflowRectForPropagation(renderer()->style()); + childLogicalVisualOverflow.move(inlineBox->logicalLeft(), inlineBox->logicalTop()); + logicalVisualOverflow.unite(childLogicalVisualOverflow); + } - int boxHeight = logicalHeight(); + // Layout overflow internal to the child box only propagates if the child box doesn't have overflow clip set. + // Otherwise the child border box propagates as layout overflow. This rectangle must include transforms and relative positioning + // and be adjusted for writing-mode differences. + IntRect childLogicalLayoutOverflow = box->logicalLayoutOverflowRectForPropagation(renderer()->style()); + childLogicalLayoutOverflow.move(inlineBox->logicalLeft(), inlineBox->logicalTop()); + logicalLayoutOverflow.unite(childLogicalLayoutOverflow); +} +void InlineFlowBox::computeOverflow(int lineTop, int lineBottom, bool strictMode, GlyphOverflowAndFallbackFontsMap& textBoxDataMap) +{ // Any spillage outside of the line top and bottom is not considered overflow. We just ignore this, since it only happens // from the "your ascent/descent don't affect the line" quirk. int topOverflow = max(logicalTop(), lineTop); - int bottomOverflow = min(logicalTop() + boxHeight, lineBottom); + int bottomOverflow = min(logicalBottom(), lineBottom); - int topLayoutOverflow = topOverflow; - int bottomLayoutOverflow = bottomOverflow; - - int topVisualOverflow = topOverflow; - int bottomVisualOverflow = bottomOverflow; + // Visual overflow just includes overflow for stuff we need to repaint ourselves. Self-painting layers are ignored. + // Layout overflow is used to determine scrolling extent, so it still includes child layers and also factors in + // transforms, relative positioning, etc. + IntRect logicalLayoutOverflow(logicalLeft(), topOverflow, logicalWidth(), bottomOverflow - topOverflow); + IntRect logicalVisualOverflow(logicalLayoutOverflow); // box-shadow on root line boxes is applying to the block and not to the lines. - if (parent()) { - int boxShadowTop; - int boxShadowBottom; - renderer()->style(m_firstLine)->getBoxShadowBlockDirectionExtent(boxShadowTop, boxShadowBottom); - - topVisualOverflow = min(logicalTop() + boxShadowTop, topVisualOverflow); - bottomVisualOverflow = max(logicalTop() + boxHeight + boxShadowBottom, bottomVisualOverflow); - } + addBoxShadowVisualOverflow(logicalVisualOverflow); for (InlineBox* curr = firstChild(); curr; curr = curr->nextOnLine()) { if (curr->renderer()->isPositioned()) @@ -779,64 +827,70 @@ void InlineFlowBox::computeBlockDirectionOverflow(int lineTop, int lineBottom, b RenderText* rt = toRenderText(text->renderer()); if (rt->isBR()) continue; + addTextBoxVisualOverflow(text, textBoxDataMap, logicalVisualOverflow); + } else if (curr->renderer()->isRenderInline()) { + InlineFlowBox* flow = static_cast<InlineFlowBox*>(curr); + flow->computeOverflow(lineTop, lineBottom, strictMode, textBoxDataMap); + if (!flow->boxModelObject()->hasSelfPaintingLayer()) + logicalVisualOverflow.unite(flow->logicalVisualOverflowRect()); + IntRect childLayoutOverflow = flow->logicalLayoutOverflowRect(); + childLayoutOverflow.move(flow->boxModelObject()->relativePositionLogicalOffset()); + logicalLayoutOverflow.unite(childLayoutOverflow); + } else + addReplacedChildOverflow(curr, logicalLayoutOverflow, logicalVisualOverflow); + } + + setOverflowFromLogicalRects(logicalLayoutOverflow, logicalVisualOverflow); +} - int strokeOverflow = static_cast<int>(ceilf(rt->style()->textStrokeWidth() / 2.0f)); - - GlyphOverflowAndFallbackFontsMap::iterator it = textBoxDataMap.find(static_cast<InlineTextBox*>(curr)); - GlyphOverflow* glyphOverflow = it == textBoxDataMap.end() ? 0 : &it->second.second; - - int topGlyphEdge = glyphOverflow ? (isFlippedLine ? glyphOverflow->bottom : glyphOverflow->top) : 0; - int bottomGlyphEdge = glyphOverflow ? (isFlippedLine ? glyphOverflow->top : glyphOverflow->bottom) : 0; - - int topGlyphOverflow = -strokeOverflow - topGlyphEdge; - int bottomGlyphOverflow = strokeOverflow + bottomGlyphEdge; +// FIXME: You will notice there is no contains() check here. If the rect is smaller than the frame box it actually +// becomes the new overflow. The reason for this is that in quirks mode we don't let inline flow boxes paint +// outside of the root line box's lineTop and lineBottom values. We accomplish this visual clamping by actually +// insetting the overflow rect so that it's smaller than the frame rect. +// +// The reason we don't just mutate the frameRect in quirks mode is that we'd have to put the m_height member variable +// back into InlineBox. Basically the tradeoff is 4 bytes in all modes (for m_height) added to InlineFlowBox, or +// the allocation of a RenderOverflow struct for InlineFlowBoxes in quirks mode only. For now, we're opting to award +// the smaller memory consumption to strict mode pages. +// +// It might be possible to hash a custom height, or to require that lineTop and lineBottom be passed in to +// all functions that query overflow. +void InlineFlowBox::setLayoutOverflow(const IntRect& rect) +{ + IntRect frameBox = frameRect(); + if (frameBox == rect || rect.isEmpty()) + return; + + if (!m_overflow) + m_overflow.set(new RenderOverflow(frameBox, frameBox)); + + m_overflow->setLayoutOverflow(rect); +} - int textShadowTop; - int textShadowBottom; - curr->renderer()->style(m_firstLine)->getTextShadowBlockDirectionExtent(textShadowTop, textShadowBottom); +void InlineFlowBox::setVisualOverflow(const IntRect& rect) +{ + IntRect frameBox = frameRect(); + if (frameBox == rect || rect.isEmpty()) + return; - int childOverflowTop = min(textShadowTop + topGlyphOverflow, topGlyphOverflow); - int childOverflowBottom = max(textShadowBottom + bottomGlyphOverflow, bottomGlyphOverflow); + if (!m_overflow) + m_overflow.set(new RenderOverflow(frameBox, frameBox)); - topVisualOverflow = min(curr->logicalTop() + childOverflowTop, topVisualOverflow); - bottomVisualOverflow = max(curr->logicalTop() + text->logicalHeight() + childOverflowBottom, bottomVisualOverflow); - } else if (curr->renderer()->isRenderInline()) { - InlineFlowBox* flow = static_cast<InlineFlowBox*>(curr); - flow->computeBlockDirectionOverflow(lineTop, lineBottom, strictMode, textBoxDataMap); - topLayoutOverflow = min(topLayoutOverflow, flow->logicalTopLayoutOverflow()); - bottomLayoutOverflow = max(bottomLayoutOverflow, flow->logicalBottomLayoutOverflow()); - topVisualOverflow = min(topVisualOverflow, flow->logicalTopVisualOverflow()); - bottomVisualOverflow = max(bottomVisualOverflow, flow->logicalBottomVisualOverflow()); - } else if (!curr->boxModelObject()->hasSelfPaintingLayer()){ - // Only include overflow from replaced inlines if they do not paint themselves. - int boxLogicalTop = curr->logicalTop(); - int childTopLayoutOverflow; - int childBottomLayoutOverflow; - int childTopVisualOverflow; - int childBottomVisualOverflow; - - RenderBox* box = toRenderBox(curr->renderer()); - box->blockDirectionOverflow(isHorizontal(), childTopLayoutOverflow, childBottomLayoutOverflow, - childTopVisualOverflow, childBottomVisualOverflow); - - if (box->hasOverflowClip()) { - childTopLayoutOverflow = 0; - childBottomLayoutOverflow = curr->logicalHeight(); - } + m_overflow->setVisualOverflow(rect); +} - topLayoutOverflow = min(boxLogicalTop + childTopLayoutOverflow, topLayoutOverflow); - bottomLayoutOverflow = max(boxLogicalTop + childBottomLayoutOverflow, bottomLayoutOverflow); - topVisualOverflow = min(boxLogicalTop + childTopVisualOverflow, topVisualOverflow); - bottomVisualOverflow = max(boxLogicalTop + childBottomVisualOverflow, bottomVisualOverflow); - } - } +void InlineFlowBox::setOverflowFromLogicalRects(const IntRect& logicalLayoutOverflow, const IntRect& logicalVisualOverflow) +{ + IntRect layoutOverflow(isHorizontal() ? logicalLayoutOverflow : logicalLayoutOverflow.transposedRect()); + setLayoutOverflow(layoutOverflow); - setBlockDirectionOverflowPositions(topLayoutOverflow, bottomLayoutOverflow, topVisualOverflow, bottomVisualOverflow); + IntRect visualOverflow(isHorizontal() ? logicalVisualOverflow : logicalVisualOverflow.transposedRect()); + setVisualOverflow(visualOverflow); } bool InlineFlowBox::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, int x, int y, int tx, int ty) { - IntRect overflowRect(visibleOverflowRect()); + IntRect overflowRect(visualOverflowRect()); flipForWritingMode(overflowRect); overflowRect.move(tx, ty); if (!overflowRect.intersects(result.rectForPoint(x, y))) @@ -865,7 +919,7 @@ bool InlineFlowBox::nodeAtPoint(const HitTestRequest& request, HitTestResult& re void InlineFlowBox::paint(PaintInfo& paintInfo, int tx, int ty) { - IntRect overflowRect(visibleOverflowRect()); + IntRect overflowRect(visualOverflowRect()); overflowRect.inflate(renderer()->maximalOutlineSize(paintInfo.phase)); flipForWritingMode(overflowRect); overflowRect.move(tx, ty); @@ -1205,7 +1259,7 @@ void InlineFlowBox::clearTruncation() box->clearTruncation(); } -int InlineFlowBox::computeBlockDirectionRubyAdjustment(int allowedPosition) const +int InlineFlowBox::computeOverAnnotationAdjustment(int allowedPosition) const { int result = 0; for (InlineBox* curr = firstChild(); curr; curr = curr->nextOnLine()) { @@ -1213,7 +1267,7 @@ int InlineFlowBox::computeBlockDirectionRubyAdjustment(int allowedPosition) cons continue; // Positioned placeholders don't affect calculations. if (curr->isInlineFlowBox()) - result = max(result, static_cast<InlineFlowBox*>(curr)->computeBlockDirectionRubyAdjustment(allowedPosition)); + result = max(result, static_cast<InlineFlowBox*>(curr)->computeOverAnnotationAdjustment(allowedPosition)); if (curr->renderer()->isReplaced() && curr->renderer()->isRubyRun()) { RenderRubyRun* rubyRun = static_cast<RenderRubyRun*>(curr->renderer()); @@ -1235,6 +1289,45 @@ int InlineFlowBox::computeBlockDirectionRubyAdjustment(int allowedPosition) cons result = max(result, bottomOfLastRubyTextLine - allowedPosition); } } + + if (curr->isInlineTextBox()) { + RenderStyle* style = curr->renderer()->style(m_firstLine); + if (style->textEmphasisMark() != TextEmphasisMarkNone && style->textEmphasisPosition() == TextEmphasisPositionOver) { + if (!style->isFlippedLinesWritingMode()) { + int topOfEmphasisMark = curr->logicalTop() - style->font().emphasisMarkHeight(style->textEmphasisMarkString()); + result = max(result, allowedPosition - topOfEmphasisMark); + } else { + int bottomOfEmphasisMark = curr->logicalBottom() + style->font().emphasisMarkHeight(style->textEmphasisMarkString()); + result = max(result, bottomOfEmphasisMark - allowedPosition); + } + } + } + } + return result; +} + +int InlineFlowBox::computeUnderAnnotationAdjustment(int allowedPosition) const +{ + int result = 0; + for (InlineBox* curr = firstChild(); curr; curr = curr->nextOnLine()) { + if (curr->renderer()->isPositioned()) + continue; // Positioned placeholders don't affect calculations. + + if (curr->isInlineFlowBox()) + result = max(result, static_cast<InlineFlowBox*>(curr)->computeUnderAnnotationAdjustment(allowedPosition)); + + if (curr->isInlineTextBox()) { + RenderStyle* style = curr->renderer()->style(m_firstLine); + if (style->textEmphasisMark() != TextEmphasisMarkNone && style->textEmphasisPosition() == TextEmphasisPositionUnder) { + if (!style->isFlippedLinesWritingMode()) { + int bottomOfEmphasisMark = curr->logicalBottom() + style->font().emphasisMarkHeight(style->textEmphasisMarkString()); + result = max(result, bottomOfEmphasisMark - allowedPosition); + } else { + int topOfEmphasisMark = curr->logicalTop() - style->font().emphasisMarkHeight(style->textEmphasisMarkString()); + result = max(result, allowedPosition - topOfEmphasisMark); + } + } + } } return result; } diff --git a/WebCore/rendering/InlineFlowBox.h b/WebCore/rendering/InlineFlowBox.h index 6e06a75..63263fd 100644 --- a/WebCore/rendering/InlineFlowBox.h +++ b/WebCore/rendering/InlineFlowBox.h @@ -76,8 +76,8 @@ public: virtual void setConstructed() { InlineBox::setConstructed(); - if (firstChild()) - firstChild()->setConstructed(); + for (InlineBox* child = firstChild(); child; child = child->next()) + child->setConstructed(); } void addToLine(InlineBox* child); @@ -161,11 +161,14 @@ public: void adjustMaxAscentAndDescent(int& maxAscent, int& maxDescent, int maxPositionTop, int maxPositionBottom); void placeBoxesInBlockDirection(int logicalTop, int maxHeight, int maxAscent, bool strictMode, int& lineTop, int& lineBottom, bool& setLineTop, - int& lineTopIncludingMargins, int& lineBottomIncludingMargins, bool& containsRuby, FontBaseline); + int& lineTopIncludingMargins, int& lineBottomIncludingMargins, bool& hasAnnotationsBefore, bool& hasAnnotationsAfter, FontBaseline); void flipLinesInBlockDirection(int lineTop, int lineBottom); - void computeBlockDirectionOverflow(int lineTop, int lineBottom, bool strictMode, GlyphOverflowAndFallbackFontsMap&); bool requiresIdeographicBaseline(const GlyphOverflowAndFallbackFontsMap&) const; - int computeBlockDirectionRubyAdjustment(int allowedPosition) const; + + int computeOverAnnotationAdjustment(int allowedPosition) const; + int computeUnderAnnotationAdjustment(int allowedPosition) const; + + void computeOverflow(int lineTop, int lineBottom, bool strictMode, GlyphOverflowAndFallbackFontsMap&); void removeChild(InlineBox* child); @@ -183,17 +186,6 @@ public: // top/right/bottom/left in the code - these aren't purely physical directions. For horizontal-tb and vertical-lr they will match physical // directions, but for horizontal-bt and vertical-rl, the top/bottom and left/right respectively are inverted when compared to // their physical counterparts. - int topVisibleOverflow() const { return std::min(topLayoutOverflow(), topVisualOverflow()); } - int bottomVisibleOverflow() const { return std::max(bottomLayoutOverflow(), bottomVisualOverflow()); } - int leftVisibleOverflow() const { return std::min(leftLayoutOverflow(), leftVisualOverflow()); } - int rightVisibleOverflow() const { return std::max(rightLayoutOverflow(), rightVisualOverflow()); } - int logicalLeftVisibleOverflow() const { return std::min(logicalLeftLayoutOverflow(), logicalLeftVisualOverflow()); } - int logicalRightVisibleOverflow() const { return std::max(logicalRightLayoutOverflow(), logicalRightVisualOverflow()); } - int logicalTopVisibleOverflow() const { return std::min(logicalTopLayoutOverflow(), logicalTopVisualOverflow()); } - int logicalBottomVisibleOverflow() const { return std::max(logicalBottomLayoutOverflow(), logicalBottomVisualOverflow()); } - - IntRect visibleOverflowRect() const { return m_overflow ? m_overflow->visibleOverflowRect() : IntRect(m_x, m_y, width(), height()); } - int topLayoutOverflow() const { return m_overflow ? m_overflow->topLayoutOverflow() : m_y; } int bottomLayoutOverflow() const { return m_overflow ? m_overflow->bottomLayoutOverflow() : m_y + height(); } int leftLayoutOverflow() const { return m_overflow ? m_overflow->leftLayoutOverflow() : m_x; } @@ -203,6 +195,13 @@ public: int logicalRightLayoutOverflow() const { return renderer()->style()->isHorizontalWritingMode() ? rightLayoutOverflow() : bottomLayoutOverflow(); } int logicalTopLayoutOverflow() const { return renderer()->style()->isHorizontalWritingMode() ? topVisualOverflow() : leftVisualOverflow(); } int logicalBottomLayoutOverflow() const { return renderer()->style()->isHorizontalWritingMode() ? bottomLayoutOverflow() : rightLayoutOverflow(); } + IntRect logicalLayoutOverflowRect() const + { + IntRect result = layoutOverflowRect(); + if (!renderer()->style()->isHorizontalWritingMode()) + result = result.transposedRect(); + return result; + } int topVisualOverflow() const { return m_overflow ? m_overflow->topVisualOverflow() : m_y; } int bottomVisualOverflow() const { return m_overflow ? m_overflow->bottomVisualOverflow() : m_y + height(); } @@ -213,11 +212,22 @@ public: int logicalRightVisualOverflow() const { return renderer()->style()->isHorizontalWritingMode() ? rightVisualOverflow() : bottomVisualOverflow(); } int logicalTopVisualOverflow() const { return renderer()->style()->isHorizontalWritingMode() ? topVisualOverflow() : leftVisualOverflow(); } int logicalBottomVisualOverflow() const { return renderer()->style()->isHorizontalWritingMode() ? bottomVisualOverflow() : rightVisualOverflow(); } + IntRect logicalVisualOverflowRect() const + { + IntRect result = visualOverflowRect(); + if (!renderer()->style()->isHorizontalWritingMode()) + result = result.transposedRect(); + return result; + } - void setInlineDirectionOverflowPositions(int logicalLeftLayoutOverflow, int logicalRightLayoutOverflow, - int logicalLeftVisualOverflow, int logicalRightVisualOverflow); - void setBlockDirectionOverflowPositions(int logicalTopLayoutOverflow, int logicalBottomLayoutOverflow, - int logicalTopVisualOverflow, int logicalBottomVisualOverflow); + void setOverflowFromLogicalRects(const IntRect& logicalLayoutOverflow, const IntRect& logicalVisualOverflow); + void setLayoutOverflow(const IntRect&); + void setVisualOverflow(const IntRect&); + +private: + void addBoxShadowVisualOverflow(IntRect& logicalVisualOverflow); + void addTextBoxVisualOverflow(const InlineTextBox*, GlyphOverflowAndFallbackFontsMap&, IntRect& logicalVisualOverflow); + void addReplacedChildOverflow(const InlineBox*, IntRect& logicalLayoutOverflow, IntRect& logicalVisualOverflow); protected: OwnPtr<RenderOverflow> m_overflow; @@ -239,52 +249,6 @@ protected: #endif }; -inline void InlineFlowBox::setInlineDirectionOverflowPositions(int logicalLeftLayoutOverflow, int logicalRightLayoutOverflow, - int logicalLeftVisualOverflow, int logicalRightVisualOverflow) -{ - if (!m_overflow) { - if (logicalLeftLayoutOverflow == logicalLeft() && logicalRightLayoutOverflow == logicalRight() - && logicalLeftVisualOverflow == logicalLeft() && logicalRightVisualOverflow == logicalRight()) - return; - m_overflow = adoptPtr(new RenderOverflow(IntRect(m_x, m_y, width(), height()))); - } - - if (isHorizontal()) { - m_overflow->setLeftLayoutOverflow(logicalLeftLayoutOverflow); - m_overflow->setRightLayoutOverflow(logicalRightLayoutOverflow); - m_overflow->setLeftVisualOverflow(logicalLeftVisualOverflow); - m_overflow->setRightVisualOverflow(logicalRightVisualOverflow); - } else { - m_overflow->setTopLayoutOverflow(logicalLeftLayoutOverflow); - m_overflow->setBottomLayoutOverflow(logicalRightLayoutOverflow); - m_overflow->setTopVisualOverflow(logicalLeftVisualOverflow); - m_overflow->setBottomVisualOverflow(logicalRightVisualOverflow); - } -} - -inline void InlineFlowBox::setBlockDirectionOverflowPositions(int logicalTopLayoutOverflow, int logicalBottomLayoutOverflow, - int logicalTopVisualOverflow, int logicalBottomVisualOverflow) -{ - if (!m_overflow) { - if (logicalTopLayoutOverflow == logicalTop() && logicalBottomLayoutOverflow == logicalBottom() - && logicalTopVisualOverflow == logicalTop() && logicalBottomVisualOverflow == logicalBottom()) - return; - m_overflow = adoptPtr(new RenderOverflow(IntRect(m_x, m_y, width(), height()))); - } - - if (isHorizontal()) { - m_overflow->setTopLayoutOverflow(logicalTopLayoutOverflow); - m_overflow->setBottomLayoutOverflow(logicalBottomLayoutOverflow); - m_overflow->setTopVisualOverflow(logicalTopVisualOverflow); - m_overflow->setBottomVisualOverflow(logicalBottomVisualOverflow); - } else { - m_overflow->setLeftLayoutOverflow(logicalTopLayoutOverflow); - m_overflow->setRightLayoutOverflow(logicalBottomLayoutOverflow); - m_overflow->setLeftVisualOverflow(logicalTopVisualOverflow); - m_overflow->setRightVisualOverflow(logicalBottomVisualOverflow); - } -} - #ifdef NDEBUG inline void InlineFlowBox::checkConsistency() const { diff --git a/WebCore/rendering/InlineTextBox.cpp b/WebCore/rendering/InlineTextBox.cpp index 2bec8a1..73107a8 100644 --- a/WebCore/rendering/InlineTextBox.cpp +++ b/WebCore/rendering/InlineTextBox.cpp @@ -291,19 +291,19 @@ Color correctedTextColor(Color textColor, Color backgroundColor) void updateGraphicsContext(GraphicsContext* context, const Color& fillColor, const Color& strokeColor, float strokeThickness, ColorSpace colorSpace) { - int mode = context->textDrawingMode(); + TextDrawingModeFlags mode = context->textDrawingMode(); if (strokeThickness > 0) { - int newMode = mode | cTextStroke; + TextDrawingModeFlags newMode = mode | TextModeStroke; if (mode != newMode) { context->setTextDrawingMode(newMode); mode = newMode; } } - if (mode & cTextFill && (fillColor != context->fillColor() || colorSpace != context->fillColorSpace())) + if (mode & TextModeFill && (fillColor != context->fillColor() || colorSpace != context->fillColorSpace())) context->setFillColor(fillColor, colorSpace); - if (mode & cTextStroke) { + if (mode & TextModeStroke) { if (strokeColor != context->strokeColor()) context->setStrokeColor(strokeColor, colorSpace); if (strokeThickness != context->strokeThickness()) @@ -359,7 +359,7 @@ FloatSize InlineTextBox::applyShadowToGraphicsContext(GraphicsContext* context, return extraOffset; } -static void paintTextWithShadows(GraphicsContext* context, const Font& font, const TextRun& textRun, int startOffset, int endOffset, int truncationPoint, const IntPoint& textOrigin, +static void paintTextWithShadows(GraphicsContext* context, const Font& font, const TextRun& textRun, const AtomicString& emphasisMark, int emphasisMarkOffset, int startOffset, int endOffset, int truncationPoint, const IntPoint& textOrigin, const IntRect& boxRect, const ShadowData* shadow, bool stroked, bool horizontal) { Color fillColor = context->fillColor(); @@ -375,13 +375,23 @@ static void paintTextWithShadows(GraphicsContext* context, const Font& font, con else if (!opaque) context->setFillColor(fillColor, fillColorSpace); - if (startOffset <= endOffset) - context->drawText(font, textRun, textOrigin + extraOffset, startOffset, endOffset); - else { - if (endOffset > 0) - context->drawText(font, textRun, textOrigin + extraOffset, 0, endOffset); - if (startOffset < truncationPoint) - context->drawText(font, textRun, textOrigin + extraOffset, startOffset, truncationPoint); + if (startOffset <= endOffset) { + if (emphasisMark.isEmpty()) + context->drawText(font, textRun, textOrigin + extraOffset, startOffset, endOffset); + else + context->drawEmphasisMarks(font, textRun, emphasisMark, textOrigin + extraOffset + IntSize(0, emphasisMarkOffset), startOffset, endOffset); + } else { + if (endOffset > 0) { + if (emphasisMark.isEmpty()) + context->drawText(font, textRun, textOrigin + extraOffset, 0, endOffset); + else + context->drawEmphasisMarks(font, textRun, emphasisMark, textOrigin + extraOffset + IntSize(0, emphasisMarkOffset), 0, endOffset); + } if (startOffset < truncationPoint) { + if (emphasisMark.isEmpty()) + context->drawText(font, textRun, textOrigin + extraOffset, startOffset, truncationPoint); + else + context->drawEmphasisMarks(font, textRun, emphasisMark, textOrigin + extraOffset + IntSize(0, emphasisMarkOffset), startOffset, truncationPoint); + } } if (!shadow) @@ -495,12 +505,14 @@ void InlineTextBox::paint(PaintInfo& paintInfo, int tx, int ty) // 2. Now paint the foreground, including text and decorations like underline/overline (in quirks mode only). Color textFillColor; Color textStrokeColor; + Color emphasisMarkColor; float textStrokeWidth = styleToUse->textStrokeWidth(); const ShadowData* textShadow = paintInfo.forceBlackText ? 0 : styleToUse->textShadow(); if (paintInfo.forceBlackText) { textFillColor = Color::black; textStrokeColor = Color::black; + emphasisMarkColor = Color::black; } else { textFillColor = styleToUse->visitedDependentColor(CSSPropertyWebkitTextFillColor); @@ -513,6 +525,12 @@ void InlineTextBox::paint(PaintInfo& paintInfo, int tx, int ty) // Make the text stroke color legible against a white background if (styleToUse->forceBackgroundsToWhite()) textStrokeColor = correctedTextColor(textStrokeColor, Color::white); + + emphasisMarkColor = styleToUse->visitedDependentColor(CSSPropertyWebkitTextEmphasisColor); + + // Make the text stroke color legible against a white background + if (styleToUse->forceBackgroundsToWhite()) + emphasisMarkColor = correctedTextColor(emphasisMarkColor, Color::white); } bool paintSelectedTextOnly = (paintInfo.phase == PaintPhaseSelection); @@ -520,6 +538,7 @@ void InlineTextBox::paint(PaintInfo& paintInfo, int tx, int ty) Color selectionFillColor = textFillColor; Color selectionStrokeColor = textStrokeColor; + Color selectionEmphasisMarkColor = emphasisMarkColor; float selectionStrokeWidth = textStrokeWidth; const ShadowData* selectionShadow = textShadow; if (haveSelection) { @@ -531,6 +550,13 @@ void InlineTextBox::paint(PaintInfo& paintInfo, int tx, int ty) selectionFillColor = foreground; } + Color emphasisMarkForeground = paintInfo.forceBlackText ? Color::black : renderer()->selectionEmphasisMarkColor(); + if (emphasisMarkForeground.isValid() && emphasisMarkForeground != selectionEmphasisMarkColor) { + if (!paintSelectedTextOnly) + paintSelectedTextSeparately = true; + selectionEmphasisMarkColor = emphasisMarkForeground; + } + if (RenderStyle* pseudoStyle = renderer()->getCachedPseudoStyle(SELECTION)) { const ShadowData* shadow = paintInfo.forceBlackText ? 0 : pseudoStyle->textShadow(); if (shadow != selectionShadow) { @@ -578,6 +604,15 @@ void InlineTextBox::paint(PaintInfo& paintInfo, int tx, int ty) length = m_truncation; } + int emphasisMarkOffset = 0; + const AtomicString& emphasisMark = styleToUse->textEmphasisMarkString(); + if (!emphasisMark.isEmpty()) { + if (styleToUse->textEmphasisPosition() == TextEmphasisPositionOver) + emphasisMarkOffset = -font.ascent() - font.emphasisMarkDescent(emphasisMark); + else + emphasisMarkOffset = font.descent() + font.emphasisMarkAscent(emphasisMark); + } + if (!paintSelectedTextOnly) { // For stroked painting, we have to change the text drawing mode. It's probably dangerous to leave that mutated as a side // effect, so only when we know we're stroking, do a save/restore. @@ -587,9 +622,18 @@ void InlineTextBox::paint(PaintInfo& paintInfo, int tx, int ty) updateGraphicsContext(context, textFillColor, textStrokeColor, textStrokeWidth, styleToUse->colorSpace()); if (!paintSelectedTextSeparately || ePos <= sPos) { // FIXME: Truncate right-to-left text correctly. - paintTextWithShadows(context, font, textRun, 0, length, length, textOrigin, boxRect, textShadow, textStrokeWidth > 0, isHorizontal()); + paintTextWithShadows(context, font, textRun, nullAtom, 0, 0, length, length, textOrigin, boxRect, textShadow, textStrokeWidth > 0, isHorizontal()); } else - paintTextWithShadows(context, font, textRun, ePos, sPos, length, textOrigin, boxRect, textShadow, textStrokeWidth > 0, isHorizontal()); + paintTextWithShadows(context, font, textRun, nullAtom, 0, ePos, sPos, length, textOrigin, boxRect, textShadow, textStrokeWidth > 0, isHorizontal()); + + if (!emphasisMark.isEmpty()) { + updateGraphicsContext(context, emphasisMarkColor, textStrokeColor, textStrokeWidth, styleToUse->colorSpace()); + if (!paintSelectedTextSeparately || ePos <= sPos) { + // FIXME: Truncate right-to-left text correctly. + paintTextWithShadows(context, font, textRun, emphasisMark, emphasisMarkOffset, 0, length, length, textOrigin, boxRect, textShadow, textStrokeWidth > 0, isHorizontal()); + } else + paintTextWithShadows(context, font, textRun, emphasisMark, emphasisMarkOffset, ePos, sPos, length, textOrigin, boxRect, textShadow, textStrokeWidth > 0, isHorizontal()); + } if (textStrokeWidth > 0) context->restore(); @@ -601,8 +645,11 @@ void InlineTextBox::paint(PaintInfo& paintInfo, int tx, int ty) context->save(); updateGraphicsContext(context, selectionFillColor, selectionStrokeColor, selectionStrokeWidth, styleToUse->colorSpace()); - paintTextWithShadows(context, font, textRun, sPos, ePos, length, textOrigin, boxRect, selectionShadow, selectionStrokeWidth > 0, isHorizontal()); - + paintTextWithShadows(context, font, textRun, nullAtom, 0, sPos, ePos, length, textOrigin, boxRect, selectionShadow, selectionStrokeWidth > 0, isHorizontal()); + if (!emphasisMark.isEmpty()) { + updateGraphicsContext(context, selectionEmphasisMarkColor, textStrokeColor, textStrokeWidth, styleToUse->colorSpace()); + paintTextWithShadows(context, font, textRun, emphasisMark, emphasisMarkOffset, sPos, ePos, length, textOrigin, boxRect, selectionShadow, selectionStrokeWidth > 0, isHorizontal()); + } if (selectionStrokeWidth > 0) context->restore(); } @@ -1124,10 +1171,11 @@ unsigned InlineTextBox::caretMaxRenderedOffset() const int InlineTextBox::textPos() const { + // When computing the width of a text run, RenderBlock::computeInlineDirectionPositionsForLine() doesn't include the actual offset + // from the containing block edge in its measurement. textPos() should be consistent so the text are rendered in the same width. if (logicalLeft() == 0) return 0; - RenderBlock* blockElement = renderer()->containingBlock(); - return logicalLeft() - blockElement->borderStart() - blockElement->paddingStart(); + return logicalLeft() - root()->logicalLeft(); } int InlineTextBox::offsetForPosition(int lineOffset, bool includePartialGlyphs) const @@ -1135,6 +1183,16 @@ int InlineTextBox::offsetForPosition(int lineOffset, bool includePartialGlyphs) if (isLineBreak()) return 0; + int leftOffset = isLeftToRightDirection() ? 0 : m_len; + int rightOffset = isLeftToRightDirection() ? m_len : 0; + if (renderer()->containingBlock()->style()->isLeftToRightDirection() != isLeftToRightDirection()) + swap(leftOffset, rightOffset); + + if (lineOffset - logicalLeft() > logicalWidth()) + return rightOffset; + if (lineOffset - logicalLeft() < 0) + return leftOffset; + RenderText* text = toRenderText(renderer()); RenderStyle* style = text->style(m_firstLine); const Font* f = &style->font(); @@ -1145,8 +1203,12 @@ int InlineTextBox::offsetForPosition(int lineOffset, bool includePartialGlyphs) return f->offsetForPosition(textRun, lineOffset - logicalLeft(), includePartialGlyphs); #else return f->offsetForPosition(TextRun(textRenderer()->text()->characters() + m_start, m_len, textRenderer()->allowTabs(), textPos(), m_toAdd, !isLeftToRightDirection(), m_dirOverride || style->visuallyOrdered()), +<<<<<<< HEAD lineOffset - logicalLeft(), includePartialGlyphs); #endif +======= + lineOffset - logicalLeft(), includePartialGlyphs); +>>>>>>> webkit.org at r74534 (trunk) } int InlineTextBox::positionForOffset(int offset) const diff --git a/WebCore/rendering/InlineTextBox.h b/WebCore/rendering/InlineTextBox.h index e19da2e..5b8d104 100644 --- a/WebCore/rendering/InlineTextBox.h +++ b/WebCore/rendering/InlineTextBox.h @@ -126,7 +126,7 @@ public: private: virtual unsigned caretMaxRenderedOffset() const; - int textPos() const; + int textPos() const; // returns the x position relative to the left start of the text line. public: virtual int offsetForPosition(int x, bool includePartialGlyphs = true) const; diff --git a/WebCore/rendering/LayoutState.cpp b/WebCore/rendering/LayoutState.cpp index 3eea51f..aeba416 100644 --- a/WebCore/rendering/LayoutState.cpp +++ b/WebCore/rendering/LayoutState.cpp @@ -34,7 +34,7 @@ namespace WebCore { -LayoutState::LayoutState(LayoutState* prev, RenderBox* renderer, const IntSize& offset, int pageHeight, bool pageHeightChanged, ColumnInfo* columnInfo) +LayoutState::LayoutState(LayoutState* prev, RenderBox* renderer, const IntSize& offset, int pageLogicalHeight, bool pageLogicalHeightChanged, ColumnInfo* columnInfo) : m_columnInfo(columnInfo) , m_next(prev) #ifndef NDEBUG @@ -82,20 +82,20 @@ LayoutState::LayoutState(LayoutState* prev, RenderBox* renderer, const IntSize& // If we establish a new page height, then cache the offset to the top of the first page. // We can compare this later on to figure out what part of the page we're actually on, - if (pageHeight || m_columnInfo) { - m_pageHeight = pageHeight; + if (pageLogicalHeight || m_columnInfo) { + m_pageLogicalHeight = pageLogicalHeight; m_pageOffset = IntSize(m_layoutOffset.width() + renderer->borderLeft() + renderer->paddingLeft(), m_layoutOffset.height() + renderer->borderTop() + renderer->paddingTop()); - m_pageHeightChanged = pageHeightChanged; + m_pageLogicalHeightChanged = pageLogicalHeightChanged; } else { // If we don't establish a new page height, then propagate the old page height and offset down. - m_pageHeight = m_next->m_pageHeight; - m_pageHeightChanged = m_next->m_pageHeightChanged; + m_pageLogicalHeight = m_next->m_pageLogicalHeight; + m_pageLogicalHeightChanged = m_next->m_pageLogicalHeightChanged; m_pageOffset = m_next->m_pageOffset; // Disable pagination for objects we don't support. For now this includes overflow:scroll/auto and inline blocks. if (renderer->isReplaced() || renderer->scrollsOverflow()) - m_pageHeight = 0; + m_pageLogicalHeight = 0; } if (!m_columnInfo) @@ -108,8 +108,8 @@ LayoutState::LayoutState(LayoutState* prev, RenderBox* renderer, const IntSize& LayoutState::LayoutState(RenderObject* root) : m_clipped(false) - , m_pageHeight(0) - , m_pageHeightChanged(false) + , m_pageLogicalHeight(0) + , m_pageLogicalHeightChanged(false) , m_columnInfo(0) , m_next(0) #ifndef NDEBUG @@ -157,21 +157,21 @@ void LayoutState::operator delete(void* ptr, size_t sz) void LayoutState::clearPaginationInformation() { - m_pageHeight = m_next->m_pageHeight; + m_pageLogicalHeight = m_next->m_pageLogicalHeight; m_pageOffset = m_next->m_pageOffset; m_columnInfo = m_next->m_columnInfo; } -int LayoutState::pageY(int childY) const +int LayoutState::pageLogicalOffset(int childLogicalOffset) const { - return m_layoutOffset.height() + childY - m_pageOffset.height(); + return m_layoutOffset.height() + childLogicalOffset - m_pageOffset.height(); } void LayoutState::addForcedColumnBreak(int childY) { if (!m_columnInfo || m_columnInfo->columnHeight()) return; - m_columnInfo->addForcedBreak(pageY(childY)); + m_columnInfo->addForcedBreak(pageLogicalOffset(childY)); } } // namespace WebCore diff --git a/WebCore/rendering/LayoutState.h b/WebCore/rendering/LayoutState.h index cca3e42..0d06cb1 100644 --- a/WebCore/rendering/LayoutState.h +++ b/WebCore/rendering/LayoutState.h @@ -41,8 +41,8 @@ class LayoutState : public Noncopyable { public: LayoutState() : m_clipped(false) - , m_pageHeight(0) - , m_pageHeightChanged(false) + , m_pageLogicalHeight(0) + , m_pageLogicalHeightChanged(false) , m_columnInfo(0) , m_next(0) #ifndef NDEBUG @@ -64,12 +64,16 @@ public: void clearPaginationInformation(); bool isPaginatingColumns() const { return m_columnInfo; } - bool isPaginated() const { return m_pageHeight || m_columnInfo; } - int pageY(int childY) const; + bool isPaginated() const { return m_pageLogicalHeight || m_columnInfo; } + + // The page logical offset is the object's offset from the top of the page in the page progression + // direction (so an x-offset in vertical text and a y-offset for horizontal text). + int pageLogicalOffset(int childLogicalOffset) const; + void addForcedColumnBreak(int childY); - bool pageHeight() const { return m_pageHeight; } - bool pageHeightChanged() const { return m_pageHeightChanged; } + bool pageLogicalHeight() const { return m_pageLogicalHeight; } + bool pageLogicalHeightChanged() const { return m_pageLogicalHeightChanged; } private: // The normal operator new is disallowed. @@ -84,8 +88,8 @@ public: // used to ensure that repaints happen in the correct place. // This is a total delta accumulated from the root. - int m_pageHeight; // The current page height for the pagination model that encloses us. - bool m_pageHeightChanged; // If our page height has changed, this will force all blocks to relayout. + int m_pageLogicalHeight; // The current page height for the pagination model that encloses us. + bool m_pageLogicalHeightChanged; // If our page height has changed, this will force all blocks to relayout. IntSize m_pageOffset; // The offset of the start of the first page in the nearest enclosing pagination model. ColumnInfo* m_columnInfo; // If the enclosing pagination model is a column model, then this will store column information for easy retrieval/manipulation. diff --git a/WebCore/rendering/MediaControlElements.cpp b/WebCore/rendering/MediaControlElements.cpp index 25b5a12..fcaf368 100644 --- a/WebCore/rendering/MediaControlElements.cpp +++ b/WebCore/rendering/MediaControlElements.cpp @@ -65,8 +65,8 @@ static const float cSeekTime = 0.2f; inline MediaControlShadowRootElement::MediaControlShadowRootElement(HTMLMediaElement* mediaElement) : HTMLDivElement(divTag, mediaElement->document()) - , m_mediaElement(mediaElement) { + setShadowHost(mediaElement); } PassRefPtr<MediaControlShadowRootElement> MediaControlShadowRootElement::create(HTMLMediaElement* mediaElement) @@ -91,11 +91,18 @@ PassRefPtr<MediaControlShadowRootElement> MediaControlShadowRootElement::create( void MediaControlShadowRootElement::updateStyle() { if (renderer()) { - RenderStyle* timelineContainerStyle = m_mediaElement->renderer()->getCachedPseudoStyle(MEDIA_CONTROLS_TIMELINE_CONTAINER); + RenderStyle* timelineContainerStyle = shadowHost()->renderer()->getCachedPseudoStyle(MEDIA_CONTROLS_TIMELINE_CONTAINER); renderer()->setStyle(timelineContainerStyle); } } +void MediaControlShadowRootElement::detach() +{ + HTMLDivElement::detach(); + // FIXME: Remove once shadow DOM uses Element::setShadowRoot(). + setShadowHost(0); +} + // ---------------------------- MediaControlElement::MediaControlElement(HTMLMediaElement* mediaElement, PseudoId pseudo) diff --git a/WebCore/rendering/MediaControlElements.h b/WebCore/rendering/MediaControlElements.h index a9ffb0b..b2d063d 100644 --- a/WebCore/rendering/MediaControlElements.h +++ b/WebCore/rendering/MediaControlElements.h @@ -76,14 +76,10 @@ public: static PassRefPtr<MediaControlShadowRootElement> create(HTMLMediaElement*); void updateStyle(); + virtual void detach(); private: MediaControlShadowRootElement(HTMLMediaElement*); - - virtual bool isShadowNode() const { return true; } - virtual ContainerNode* shadowParentNode() { return m_mediaElement; } - - HTMLMediaElement* m_mediaElement; }; // ---------------------------- diff --git a/WebCore/rendering/RenderBlock.cpp b/WebCore/rendering/RenderBlock.cpp index 22e8afb..a1c2131 100644 --- a/WebCore/rendering/RenderBlock.cpp +++ b/WebCore/rendering/RenderBlock.cpp @@ -117,7 +117,6 @@ RenderBlock::RenderBlock(Node* node) , m_continuation(0) , m_rareData(0) , m_lineHeight(-1) - , m_beingDestroyed(false) { setChildrenInline(true); } @@ -152,9 +151,6 @@ RenderBlock::~RenderBlock() void RenderBlock::destroy() { - // Mark as being destroyed to avoid trouble with merges in removeChild(). - m_beingDestroyed = true; - // Make sure to destroy anonymous children first while they are still connected to the rest of the tree, so that they will // properly dirty line boxes that they are removed from. Effects that do :before/:after only on hover could crash otherwise. children()->destroyLeftoverChildren(); @@ -397,15 +393,10 @@ RenderBlock* RenderBlock::containingColumnsBlock(bool allowAnonymousColumnBlock) RenderBlock* RenderBlock::clone() const { - RenderBlock* cloneBlock; - if (isAnonymousBlock()) - cloneBlock = createAnonymousBlock(); - else { - cloneBlock = new (renderArena()) RenderBlock(node()); - cloneBlock->setStyle(style()); - } - cloneBlock->setChildrenInline(childrenInline()); - return cloneBlock; + RenderBlock* o = new (renderArena()) RenderBlock(node()); + o->setStyle(style()); + o->setChildrenInline(childrenInline()); + return o; } void RenderBlock::splitBlocks(RenderBlock* fromBlock, RenderBlock* toBlock, @@ -413,9 +404,13 @@ void RenderBlock::splitBlocks(RenderBlock* fromBlock, RenderBlock* toBlock, RenderObject* beforeChild, RenderBoxModelObject* oldCont) { // Create a clone of this inline. - RenderBlock* cloneBlock = clone(); - if (!isAnonymousBlock()) + RenderBlock* cloneBlock; + if (isAnonymousBlock()) + cloneBlock = createAnonymousBlock(); + else { + cloneBlock = clone(); cloneBlock->setContinuation(oldCont); + } // Now take all of the children from beforeChild to the end and remove // them from |this| and place them in the clone. @@ -440,7 +435,7 @@ void RenderBlock::splitBlocks(RenderBlock* fromBlock, RenderBlock* toBlock, // Create a new clone. RenderBlock* cloneChild = cloneBlock; - cloneBlock = blockCurr->clone(); + cloneBlock = blockCurr->isAnonymousBlock() ? blockCurr->createAnonymousBlock() : blockCurr->clone(); // Insert our child clone as the first child. cloneBlock->children()->appendChildNode(cloneBlock, cloneChild); @@ -934,8 +929,8 @@ static bool canMergeContiguousAnonymousBlocks(RenderObject* oldChild, RenderObje if (oldChild->documentBeingDestroyed() || oldChild->isInline() || oldChild->virtualContinuation()) return false; - if ((prev && (!prev->isAnonymousBlock() || toRenderBlock(prev)->continuation() || toRenderBlock(prev)->beingDestroyed())) - || (next && (!next->isAnonymousBlock() || toRenderBlock(next)->continuation() || toRenderBlock(next)->beingDestroyed()))) + if ((prev && (!prev->isAnonymousBlock() || toRenderBlock(prev)->continuation())) + || (next && (!next->isAnonymousBlock() || toRenderBlock(next)->continuation()))) return false; // FIXME: This check isn't required when inline run-ins can't be split into continuations. @@ -951,7 +946,7 @@ static bool canMergeContiguousAnonymousBlocks(RenderObject* oldChild, RenderObje // Make sure the types of the anonymous blocks match up. return prev->isAnonymousColumnsBlock() == next->isAnonymousColumnsBlock() - && prev->isAnonymousColumnSpanBlock() == next->isAnonymousColumnSpanBlock(); + && prev->isAnonymousColumnSpanBlock() == prev->isAnonymousColumnSpanBlock(); } void RenderBlock::removeChild(RenderObject* oldChild) @@ -985,32 +980,14 @@ void RenderBlock::removeChild(RenderObject* oldChild) blockChildrenBlock->children()->insertChildNode(blockChildrenBlock, inlineChildrenBlock, prev == inlineChildrenBlock ? blockChildrenBlock->firstChild() : 0, inlineChildrenBlock->hasLayer() || blockChildrenBlock->hasLayer()); next->setNeedsLayoutAndPrefWidthsRecalc(); - - // inlineChildrenBlock got reparented to blockChildrenBlock, so it is no longer a child - // of "this". we null out prev or next so that is not used later in the function. - if (inlineChildrenBlock == prevBlock) - prev = 0; - else - next = 0; } else { // Take all the children out of the |next| block and put them in // the |prev| block. nextBlock->moveAllChildrenTo(prevBlock, nextBlock->hasLayer() || prevBlock->hasLayer()); - - // FIXME: When we destroy nextBlock, it might happen that nextBlock's next sibling block and - // oldChild can get merged. Since oldChild is getting removed, we do not want to move - // nextBlock's next sibling block's children into it. By setting a fake continuation, - // we prevent this from happening. - RenderBlock* oldChildBlock = 0; - if (oldChild->isAnonymous() && oldChild->isRenderBlock() && !toRenderBlock(oldChild)->continuation()) { - oldChildBlock = toRenderBlock(oldChild); - oldChildBlock->setContinuation(oldChildBlock); - } - + // Delete the now-empty block's lines and nuke it. nextBlock->deleteLineBoxTree(); nextBlock->destroy(); - next = 0; } } @@ -1136,7 +1113,7 @@ void RenderBlock::layout() clearLayoutOverflow(); } -void RenderBlock::layoutBlock(bool relayoutChildren, int pageHeight) +void RenderBlock::layoutBlock(bool relayoutChildren, int pageLogicalHeight) { ASSERT(needsLayout()); @@ -1167,31 +1144,31 @@ void RenderBlock::layoutBlock(bool relayoutChildren, int pageHeight) int previousHeight = logicalHeight(); setLogicalHeight(0); - bool hasSpecifiedPageHeight = false; - bool pageHeightChanged = false; + bool hasSpecifiedPageLogicalHeight = false; + bool pageLogicalHeightChanged = false; ColumnInfo* colInfo = columnInfo(); if (hasColumns()) { - if (!pageHeight) { + if (!pageLogicalHeight) { // We need to go ahead and set our explicit page height if one exists, so that we can // avoid doing two layout passes. computeLogicalHeight(); int columnHeight = contentLogicalHeight(); if (columnHeight > 0) { - pageHeight = columnHeight; - hasSpecifiedPageHeight = true; + pageLogicalHeight = columnHeight; + hasSpecifiedPageLogicalHeight = true; } setLogicalHeight(0); } - if (colInfo->columnHeight() != pageHeight && m_everHadLayout) { - colInfo->setColumnHeight(pageHeight); - pageHeightChanged = true; + if (colInfo->columnHeight() != pageLogicalHeight && m_everHadLayout) { + colInfo->setColumnHeight(pageLogicalHeight); + pageLogicalHeightChanged = true; } - if (!hasSpecifiedPageHeight && !pageHeight) + if (!hasSpecifiedPageLogicalHeight && !pageLogicalHeight) colInfo->clearForcedBreaks(); } - LayoutStateMaintainer statePusher(view(), this, IntSize(x(), y()), hasColumns() || hasTransform() || hasReflection() || style()->isFlippedBlocksWritingMode(), pageHeight, pageHeightChanged, colInfo); + LayoutStateMaintainer statePusher(view(), this, IntSize(x(), y()), hasColumns() || hasTransform() || hasReflection() || style()->isFlippedBlocksWritingMode(), pageLogicalHeight, pageLogicalHeightChanged, colInfo); // We use four values, maxTopPos, maxTopNeg, maxBottomPos, and maxBottomNeg, to track // our current maximal positive and negative margins. These values are used when we @@ -1243,11 +1220,12 @@ void RenderBlock::layoutBlock(bool relayoutChildren, int pageHeight) if (lowestFloatLogicalBottom() > (logicalHeight() - toAdd) && expandsToEncloseOverhangingFloats()) setLogicalHeight(lowestFloatLogicalBottom() + toAdd); - if (layoutColumns(hasSpecifiedPageHeight, pageHeight, statePusher)) + if (layoutColumns(hasSpecifiedPageLogicalHeight, pageLogicalHeight, statePusher)) return; // Calculate our new height. int oldHeight = logicalHeight(); + int oldClientAfterEdge = clientLogicalBottom(); computeLogicalHeight(); int newHeight = logicalHeight(); if (oldHeight != newHeight) { @@ -1266,30 +1244,17 @@ void RenderBlock::layoutBlock(bool relayoutChildren, int pageHeight) if (previousHeight != newHeight) relayoutChildren = true; - // Add overflow from children (unless we're multi-column, since in that case all our child overflow is clipped anyway). - if (!hasColumns()) { - // This check is designed to catch anyone - // who wasn't going to propagate float information up to the parent and yet could potentially be painted by its ancestor. - if (isRoot() || expandsToEncloseOverhangingFloats()) - addOverflowFromFloats(); - - if (childrenInline()) - addOverflowFromInlineChildren(); - else - addOverflowFromBlockChildren(); - } - - // Add visual overflow from box-shadow and reflections. - addShadowOverflow(); - layoutPositionedObjects(relayoutChildren || isRoot()); - positionListMarker(); + // Add overflow from children (unless we're multi-column, since in that case all our child overflow is clipped anyway). + computeOverflow(oldClientAfterEdge); statePusher.pop(); - if (view()->layoutState()->m_pageHeight) - setPageY(view()->layoutState()->pageY(y())); + if (view()->layoutState()->m_pageLogicalHeight) + setPageLogicalOffset(view()->layoutState()->pageLogicalOffset(y())); + + updateLayerTransform(); // Update our scroll information if we're overflow:auto/scroll/hidden now that we know if // we overflow or not. @@ -1298,8 +1263,17 @@ void RenderBlock::layoutBlock(bool relayoutChildren, int pageHeight) // Repaint with our new bounds if they are different from our old bounds. bool didFullRepaint = repainter.repaintAfterLayout(); if (!didFullRepaint && repaintLogicalTop != repaintLogicalBottom && (style()->visibility() == VISIBLE || enclosingLayer()->hasVisibleContent())) { - int repaintLogicalLeft = min(logicalLeftVisualOverflow(), logicalLeftLayoutOverflow()); - int repaintLogicalRight = max(logicalRightVisualOverflow(), logicalRightLayoutOverflow()); + // FIXME: We could tighten up the left and right invalidation points if we let layoutInlineChildren fill them in based off the particular lines + // it had to lay out. We wouldn't need the hasOverflowClip() hack in that case either. + int repaintLogicalLeft = logicalLeftVisualOverflow(); + int repaintLogicalRight = logicalRightVisualOverflow(); + if (hasOverflowClip()) { + // If we have clipped overflow, we should use layout overflow as well, since visual overflow from lines didn't propagate to our block's overflow. + // Note the old code did this as well but even for overflow:visible. The addition of hasOverflowClip() at least tightens up the hack a bit. + // layoutInlineChildren should be patched to compute the entire repaint rect. + repaintLogicalLeft = min(repaintLogicalLeft, logicalLeftLayoutOverflow()); + repaintLogicalRight = max(repaintLogicalRight, logicalRightLayoutOverflow()); + } IntRect repaintRect; if (style()->isHorizontalWritingMode()) @@ -1330,6 +1304,53 @@ void RenderBlock::layoutBlock(bool relayoutChildren, int pageHeight) setNeedsLayout(false); } +void RenderBlock::addOverflowFromChildren() +{ + if (!hasColumns()) { + if (childrenInline()) + addOverflowFromInlineChildren(); + else + addOverflowFromBlockChildren(); + } else { + ColumnInfo* colInfo = columnInfo(); + if (columnCount(colInfo)) { + IntRect lastRect = columnRectAt(colInfo, columnCount(colInfo) - 1); + int overflowLeft = !style()->isLeftToRightDirection() ? min(0, lastRect.x()) : 0; + int overflowRight = style()->isLeftToRightDirection() ? max(width(), lastRect.x() + lastRect.width()) : 0; + int overflowHeight = borderTop() + paddingTop() + colInfo->columnHeight(); + addLayoutOverflow(IntRect(overflowLeft, 0, overflowRight - overflowLeft, overflowHeight)); + } + } +} + +void RenderBlock::computeOverflow(int oldClientAfterEdge, bool recomputeFloats) +{ + // Add overflow from children. + addOverflowFromChildren(); + + if (!hasColumns() && (recomputeFloats || isRoot() || expandsToEncloseOverhangingFloats() || hasSelfPaintingLayer())) + addOverflowFromFloats(); + + // Add in the overflow from positioned objects. + addOverflowFromPositionedObjects(); + + if (hasOverflowClip()) { + // When we have overflow clip, propagate the original spillout since it will include collapsed bottom margins + // and bottom padding. Set the axis we don't care about to be 1, since we want this overflow to always + // be considered reachable. + IntRect clientRect(clientBoxRect()); + IntRect rectToApply; + if (style()->isHorizontalWritingMode()) + rectToApply = IntRect(clientRect.x(), clientRect.y(), 1, max(0, oldClientAfterEdge - clientRect.y())); + else + rectToApply = IntRect(clientRect.x(), clientRect.y(), max(0, oldClientAfterEdge - clientRect.x()), 1); + addLayoutOverflow(rectToApply); + } + + // Add visual overflow from box-shadow and reflections. + addShadowOverflow(); +} + void RenderBlock::addOverflowFromBlockChildren() { for (RenderBox* child = firstChildBox(); child; child = child->nextSiblingBox()) { @@ -1346,12 +1367,28 @@ void RenderBlock::addOverflowFromFloats() FloatingObject* r; DeprecatedPtrListIterator<FloatingObject> it(*m_floatingObjects); for (; (r = it.current()); ++it) { - if (r->m_shouldPaint && !r->m_renderer->hasSelfPaintingLayer()) + if (r->m_isDescendant) addOverflowFromChild(r->m_renderer, IntSize(r->left() + r->m_renderer->marginLeft(), r->top() + r->m_renderer->marginTop())); } return; } +void RenderBlock::addOverflowFromPositionedObjects() +{ + if (!m_positionedObjects) + return; + + RenderBox* positionedObject; + Iterator end = m_positionedObjects->end(); + for (Iterator it = m_positionedObjects->begin(); it != end; ++it) { + positionedObject = *it; + + // Fixed positioned elements don't contribute to layout overflow, since they don't scroll with the content. + if (positionedObject->style()->position() != FixedPosition) + addOverflowFromChild(positionedObject); + } +} + bool RenderBlock::expandsToEncloseOverhangingFloats() const { return isInlineBlockOrInlineTable() || isFloatingOrPositioned() || hasOverflowClip() || (parent() && parent()->isFlexibleBox()) @@ -2034,7 +2071,17 @@ bool RenderBlock::layoutOnlyPositionedObjects() // All we have to is lay out our positioned objects. layoutPositionedObjects(false); + // Recompute our overflow information. + // FIXME: We could do better here by computing a temporary overflow object from layoutPositionedObjects and only + // updating our overflow if we either used to have overflow or if the new temporary object has overflow. + // For now just always recompute overflow. This is no worse performance-wise than the old code that called rightmostPosition and + // lowestPosition on every relayout so it's not a regression. + m_overflow.clear(); + computeOverflow(clientLogicalBottom(), true); + statePusher.pop(); + + updateLayerTransform(); updateScrollInfoAfterLayout(); @@ -2051,38 +2098,39 @@ bool RenderBlock::layoutOnlyPositionedObjects() void RenderBlock::layoutPositionedObjects(bool relayoutChildren) { - if (m_positionedObjects) { - if (hasColumns()) - view()->layoutState()->clearPaginationInformation(); // Positioned objects are not part of the column flow, so they don't paginate with the columns. + if (!m_positionedObjects) + return; + + if (hasColumns()) + view()->layoutState()->clearPaginationInformation(); // Positioned objects are not part of the column flow, so they don't paginate with the columns. - RenderBox* r; - Iterator end = m_positionedObjects->end(); - for (Iterator it = m_positionedObjects->begin(); it != end; ++it) { - r = *it; - // When a non-positioned block element moves, it may have positioned children that are implicitly positioned relative to the - // non-positioned block. Rather than trying to detect all of these movement cases, we just always lay out positioned - // objects that are positioned implicitly like this. Such objects are rare, and so in typical DHTML menu usage (where everything is - // positioned explicitly) this should not incur a performance penalty. - if (relayoutChildren || (r->style()->hasStaticY() && r->parent() != this && r->parent()->isBlockFlow())) - r->setChildNeedsLayout(true, false); - - // If relayoutChildren is set and we have percentage padding, we also need to invalidate the child's pref widths. - //if (relayoutChildren && (r->style()->paddingLeft().isPercent() || r->style()->paddingRight().isPercent())) - r->setPreferredLogicalWidthsDirty(true, false); + RenderBox* r; + Iterator end = m_positionedObjects->end(); + for (Iterator it = m_positionedObjects->begin(); it != end; ++it) { + r = *it; + // When a non-positioned block element moves, it may have positioned children that are implicitly positioned relative to the + // non-positioned block. Rather than trying to detect all of these movement cases, we just always lay out positioned + // objects that are positioned implicitly like this. Such objects are rare, and so in typical DHTML menu usage (where everything is + // positioned explicitly) this should not incur a performance penalty. + if (relayoutChildren || (r->style()->hasStaticY() && r->parent() != this && r->parent()->isBlockFlow())) + r->setChildNeedsLayout(true, false); - if (!r->needsLayout()) - r->markForPaginationRelayoutIfNeeded(); - - // We don't have to do a full layout. We just have to update our position. Try that first. If we have shrink-to-fit width - // and we hit the available width constraint, the layoutIfNeeded() will catch it and do a full layout. - if (r->needsPositionedMovementLayoutOnly()) - r->tryLayoutDoingPositionedMovementOnly(); - r->layoutIfNeeded(); - } + // If relayoutChildren is set and we have percentage padding, we also need to invalidate the child's pref widths. + if (relayoutChildren && (r->style()->paddingStart().isPercent() || r->style()->paddingEnd().isPercent())) + r->setPreferredLogicalWidthsDirty(true, false); - if (hasColumns()) - view()->layoutState()->m_columnInfo = columnInfo(); // FIXME: Kind of gross. We just put this back into the layout state so that pop() will work. + if (!r->needsLayout()) + r->markForPaginationRelayoutIfNeeded(); + + // We don't have to do a full layout. We just have to update our position. Try that first. If we have shrink-to-fit width + // and we hit the available width constraint, the layoutIfNeeded() will catch it and do a full layout. + if (r->needsPositionedMovementLayoutOnly()) + r->tryLayoutDoingPositionedMovementOnly(); + r->layoutIfNeeded(); } + + if (hasColumns()) + view()->layoutState()->m_columnInfo = columnInfo(); // FIXME: Kind of gross. We just put this back into the layout state so that pop() will work. } void RenderBlock::markPositionedObjectsForLayout() @@ -2103,7 +2151,7 @@ void RenderBlock::markForPaginationRelayoutIfNeeded() if (needsLayout()) return; - if (view()->layoutState()->pageHeightChanged() || (view()->layoutState()->pageHeight() && view()->layoutState()->pageY(y()) != pageY())) + if (view()->layoutState()->pageLogicalHeightChanged() || (view()->layoutState()->pageLogicalHeight() && view()->layoutState()->pageLogicalOffset(y()) != pageLogicalOffset())) setChildNeedsLayout(true, false); } @@ -2147,7 +2195,7 @@ void RenderBlock::paint(PaintInfo& paintInfo, int tx, int ty) // FIXME: Could eliminate the isRoot() check if we fix background painting so that the RenderView // paints the root's background. if (!isRoot()) { - IntRect overflowBox = visibleOverflowRect(); + IntRect overflowBox = visualOverflowRect(); overflowBox.inflate(maximalOutlineSize(paintInfo.phase)); overflowBox.move(tx, ty); if (!overflowBox.intersects(paintInfo.rect)) @@ -2999,10 +3047,10 @@ RenderBlock::FloatingObject* RenderBlock::insertFloatingObject(RenderBox* o) // Our location is irrelevant if we're unsplittable or no pagination is in effect. // Just go ahead and lay out the float. bool isChildRenderBlock = o->isRenderBlock(); - if (isChildRenderBlock && !o->needsLayout() && view()->layoutState()->pageHeightChanged()) + if (isChildRenderBlock && !o->needsLayout() && view()->layoutState()->pageLogicalHeightChanged()) o->setChildNeedsLayout(true, false); - bool affectedByPagination = isChildRenderBlock && view()->layoutState()->m_pageHeight; + bool affectedByPagination = isChildRenderBlock && view()->layoutState()->m_pageLogicalHeight; if (!affectedByPagination || isWritingModeRoot()) // We are unsplittable if we're a block flow root. o->layoutIfNeeded(); else { @@ -3033,7 +3081,7 @@ void RenderBlock::removeFloatingObject(RenderBox* o) // Special-case zero- and less-than-zero-height floats: those don't touch // the line that they're on, but it still needs to be dirtied. This is // accomplished by pretending they have a height of 1. - logicalBottom = max(logicalBottom, logicalTop == numeric_limits<int>::max() ? logicalTop : logicalTop + 1); + logicalBottom = max(logicalBottom, logicalTop + 1); markLinesDirtyInBlockRange(0, logicalBottom); } m_floatingObjects->removeRef(it.current()); @@ -3388,418 +3436,6 @@ int RenderBlock::lowestFloatLogicalBottom(FloatingObject::Type floatType) const return lowestFloatBottom; } -int RenderBlock::topmostPosition(bool includeOverflowInterior, bool includeSelf, ApplyTransform applyTransform) const -{ - IntRect transformedRect = transformedFrameRect(); - int transformedTop = includeSelf && transformedRect.width() > 0 ? 0 : transformedRect.height(); - - if (!includeOverflowInterior && (hasOverflowClip() || hasControlClip())) - return transformedTop; - - if (!firstChild() && (!transformedRect.width() || !transformedRect.height())) - return transformedTop; - - int top = includeSelf && width() > 0 ? 0 : height(); - - if (!hasColumns()) { - // FIXME: Come up with a way to use the layer tree to avoid visiting all the kids. - // For now, we have to descend into all the children, since we may have a huge abs div inside - // a tiny rel div buried somewhere deep in our child tree. In this case we have to get to - // the abs div. - for (RenderObject* c = firstChild(); c; c = c->nextSibling()) { - if (!c->isFloatingOrPositioned() && c->isBox()) { - RenderBox* childBox = toRenderBox(c); - top = min(top, childBox->transformedFrameRect().y() + childBox->topmostPosition(false)); - } - } - } - - if (includeSelf && isRelPositioned()) - top += relativePositionOffsetY(); - - if (!includeOverflowInterior && hasOverflowClip()) - return top; - - int relativeOffset = includeSelf && isRelPositioned() ? relativePositionOffsetY() : 0; - - if (includeSelf) - top = min(top, topLayoutOverflow() + relativeOffset); - - if (m_positionedObjects) { - RenderBox* r; - Iterator end = m_positionedObjects->end(); - for (Iterator it = m_positionedObjects->begin(); it != end; ++it) { - r = *it; - // Fixed positioned objects do not scroll and thus should not constitute - // part of the topmost position. - if (r->style()->position() != FixedPosition) { - // FIXME: Should work for overflow sections too. - // If a positioned object lies completely to the left of the root it will be unreachable via scrolling. - // Therefore we should not allow it to contribute to the topmost position. - IntRect transformedR = r->transformedFrameRect(); - if (!isRenderView() || transformedR.x() + transformedR.width() > 0 || transformedR.x() + r->rightmostPosition(false) > 0) { - int tp = transformedR.y() + r->topmostPosition(false); - top = min(top, tp + relativeOffset); - } - } - } - } - - if (hasColumns()) { - ColumnInfo* colInfo = columnInfo(); - for (unsigned i = 0; i < columnCount(colInfo); i++) - top = min(top, columnRectAt(colInfo, i).y() + relativeOffset); - return top; - } - - if (m_floatingObjects) { - FloatingObject* r; - DeprecatedPtrListIterator<FloatingObject> it(*m_floatingObjects); - for ( ; (r = it.current()); ++it) { - if (r->m_shouldPaint || r->m_renderer->hasSelfPaintingLayer()) { - int tp = r->top() + r->m_renderer->marginTop() + r->m_renderer->topmostPosition(false); - top = min(top, tp + relativeOffset); - } - } - } - - if (!includeSelf && firstRootBox()) - top = min(top, firstRootBox()->selectionTop() + relativeOffset); - - if (applyTransform == IncludeTransform && includeSelf && layer() && layer()->hasTransform()) { - int bottom = lowestPosition(includeOverflowInterior, includeSelf, ExcludeTransform); - int right = rightmostPosition(includeOverflowInterior, includeSelf, ExcludeTransform); - int left = leftmostPosition(includeOverflowInterior, includeSelf, ExcludeTransform); - IntRect transformRect = applyLayerTransformToRect(IntRect(left, top, right - left, bottom - top)); - return transformRect.y(); - } - - return top; -} - -int RenderBlock::lowestPosition(bool includeOverflowInterior, bool includeSelf, ApplyTransform applyTransform) const -{ - IntRect transformedRect = transformedFrameRect(); - int transformedBottom = includeSelf && transformedRect.width() > 0 ? transformedRect.height() : 0; - - if (!includeOverflowInterior && (hasOverflowClip() || hasControlClip())) - return transformedBottom; - - if (!firstChild() && (!transformedRect.width() || !transformedRect.height())) - return transformedBottom; - - int bottom = includeSelf && width() > 0 ? height() : 0; - - if (!hasColumns()) { - // FIXME: Come up with a way to use the layer tree to avoid visiting all the kids. - // For now, we have to descend into all the children, since we may have a huge abs div inside - // a tiny rel div buried somewhere deep in our child tree. In this case we have to get to - // the abs div. - // See the last test case in https://bugs.webkit.org/show_bug.cgi?id=9314 for why this is a problem. - // For inline children, we miss relative positioned boxes that might be buried inside <span>s. - for (RenderObject* c = firstChild(); c; c = c->nextSibling()) { - if (!c->isFloatingOrPositioned() && c->isBox()) { - RenderBox* childBox = toRenderBox(c); - bottom = max(bottom, childBox->transformedFrameRect().y() + childBox->lowestPosition(false)); - } - } - } - - if (includeSelf && isRelPositioned()) - bottom += relativePositionOffsetY(); - if (!includeOverflowInterior && hasOverflowClip()) - return bottom; - - int relativeOffset = includeSelf && isRelPositioned() ? relativePositionOffsetY() : 0; - - if (includeSelf) - bottom = max(bottom, bottomLayoutOverflow() + relativeOffset); - - if (m_positionedObjects) { - RenderBox* r; - Iterator end = m_positionedObjects->end(); - for (Iterator it = m_positionedObjects->begin(); it != end; ++it) { - r = *it; - // Fixed positioned objects do not scroll and thus should not constitute - // part of the lowest position. - if (r->style()->position() != FixedPosition) { - // FIXME: Should work for overflow sections too. - // If a positioned object lies completely to the left of the root it will be unreachable via scrolling. - // Therefore we should not allow it to contribute to the lowest position. - IntRect transformedR = r->transformedFrameRect(); - if (!isRenderView() || transformedR.x() + transformedR.width() > 0 || transformedR.x() + r->rightmostPosition(false) > 0) { - int lp = transformedR.y() + r->lowestPosition(false); - bottom = max(bottom, lp + relativeOffset); - } - } - } - } - - if (hasColumns()) { - ColumnInfo* colInfo = columnInfo(); - for (unsigned i = 0; i < columnCount(colInfo); i++) - bottom = max(bottom, columnRectAt(colInfo, i).bottom() + relativeOffset); - return bottom; - } - - if (m_floatingObjects) { - FloatingObject* r; - DeprecatedPtrListIterator<FloatingObject> it(*m_floatingObjects); - for ( ; (r = it.current()); ++it ) { - if (r->m_shouldPaint || r->m_renderer->hasSelfPaintingLayer()) { - int lp = r->top() + r->m_renderer->marginTop() + r->m_renderer->lowestPosition(false); - bottom = max(bottom, lp + relativeOffset); - } - } - } - - if (!includeSelf) { - bottom = max(bottom, borderTop() + paddingTop() + paddingBottom() + relativeOffset); - if (childrenInline()) { - if (lastRootBox()) { - int childBottomEdge = lastRootBox()->selectionBottom(); - bottom = max(bottom, childBottomEdge + paddingBottom() + relativeOffset); - } - } else { - // Find the last normal flow child. - RenderBox* currBox = lastChildBox(); - while (currBox && currBox->isFloatingOrPositioned()) - currBox = currBox->previousSiblingBox(); - if (currBox) { - IntRect transformedCurrBox = currBox->transformedFrameRect(); - int childBottomEdge = transformedCurrBox.y() + transformedCurrBox.height() + currBox->collapsedMarginAfter(); // FIXME: "after" is wrong here for lowestPosition. - bottom = max(bottom, childBottomEdge + paddingBottom() + relativeOffset); - } - } - } - - if (applyTransform == IncludeTransform && includeSelf && layer() && layer()->hasTransform()) { - int top = topmostPosition(includeOverflowInterior, includeSelf, ExcludeTransform); - int right = rightmostPosition(includeOverflowInterior, includeSelf, ExcludeTransform); - int left = leftmostPosition(includeOverflowInterior, includeSelf, ExcludeTransform); - IntRect transformRect = applyLayerTransformToRect(IntRect(left, top, right - left, bottom - top)); - return transformRect.height(); - } - - return bottom; -} - -int RenderBlock::rightmostPosition(bool includeOverflowInterior, bool includeSelf, ApplyTransform applyTransform) const -{ - IntRect transformedRect = transformedFrameRect(); - int transformedRight = includeSelf && transformedRect.height() > 0 ? transformedRect.width() : 0; - - if (!includeOverflowInterior && (hasOverflowClip() || hasControlClip())) - return transformedRight; - - if (!firstChild() && (!transformedRect.width() || !transformedRect.height())) - return transformedRight; - - int right = includeSelf && height() > 0 ? width() : 0; - - if (!hasColumns()) { - // FIXME: Come up with a way to use the layer tree to avoid visiting all the kids. - // For now, we have to descend into all the children, since we may have a huge abs div inside - // a tiny rel div buried somewhere deep in our child tree. In this case we have to get to - // the abs div. - for (RenderObject* c = firstChild(); c; c = c->nextSibling()) { - if (!c->isFloatingOrPositioned() && c->isBox()) { - RenderBox* childBox = toRenderBox(c); - right = max(right, childBox->transformedFrameRect().x() + childBox->rightmostPosition(false)); - } - } - } - - if (includeSelf && isRelPositioned()) - right += relativePositionOffsetX(); - - if (!includeOverflowInterior && hasOverflowClip()) - return right; - - int relativeOffset = includeSelf && isRelPositioned() ? relativePositionOffsetX() : 0; - - if (includeSelf) - right = max(right, rightLayoutOverflow() + relativeOffset); - - if (m_positionedObjects) { - RenderBox* r; - Iterator end = m_positionedObjects->end(); - for (Iterator it = m_positionedObjects->begin() ; it != end; ++it) { - r = *it; - // Fixed positioned objects do not scroll and thus should not constitute - // part of the rightmost position. - if (r->style()->position() != FixedPosition) { - // FIXME: Should work for overflow sections too. - // If a positioned object lies completely above the root it will be unreachable via scrolling. - // Therefore we should not allow it to contribute to the rightmost position. - IntRect transformedR = r->transformedFrameRect(); - if (!isRenderView() || transformedR.y() + transformedR.height() > 0 || transformedR.y() + r->lowestPosition(false) > 0) { - int rp = transformedR.x() + r->rightmostPosition(false); - right = max(right, rp + relativeOffset); - } - } - } - } - - if (hasColumns()) { - // This only matters for LTR - if (style()->isLeftToRightDirection()) { - ColumnInfo* colInfo = columnInfo(); - unsigned count = columnCount(colInfo); - if (count) - right = max(columnRectAt(colInfo, count - 1).right() + relativeOffset, right); - } - if (applyTransform == IncludeTransform && includeSelf && layer() && layer()->hasTransform()) { - int top = topmostPosition(includeOverflowInterior, includeSelf, ExcludeTransform); - int bottom = lowestPosition(includeOverflowInterior, includeSelf, ExcludeTransform); - int left = leftmostPosition(includeOverflowInterior, includeSelf, ExcludeTransform); - IntRect transformRect = applyLayerTransformToRect(IntRect(left, top, right - left, bottom - top)); - return transformRect.width(); - } - return right; - } - - if (m_floatingObjects) { - FloatingObject* r; - DeprecatedPtrListIterator<FloatingObject> it(*m_floatingObjects); - for ( ; (r = it.current()); ++it ) { - if (r->m_shouldPaint || r->m_renderer->hasSelfPaintingLayer()) { - int rp = r->left() + r->m_renderer->marginLeft() + r->m_renderer->rightmostPosition(false); - right = max(right, rp + relativeOffset); - } - } - } - - if (!includeSelf) { - right = max(right, borderLeft() + paddingLeft() + paddingRight() + relativeOffset); - if (childrenInline()) { - for (InlineFlowBox* currBox = firstLineBox(); currBox; currBox = currBox->nextLineBox()) { - int childRightEdge = currBox->x() + currBox->logicalWidth(); - - // If this node is a root editable element, then the rightmostPosition should account for a caret at the end. - // FIXME: Need to find another way to do this, since scrollbars could show when we don't want them to. - if (node() && node()->isContentEditable() && node() == node()->rootEditableElement() && style()->isLeftToRightDirection() && !paddingRight()) - childRightEdge += 1; - right = max(right, childRightEdge + paddingRight() + relativeOffset); - } - } else { - // Walk all normal flow children. - for (RenderBox* currBox = firstChildBox(); currBox; currBox = currBox->nextSiblingBox()) { - if (currBox->isFloatingOrPositioned()) - continue; - IntRect transformedChild = currBox->transformedFrameRect(); - int childRightEdge = transformedChild.x() + transformedChild.width() + currBox->marginRight(); - right = max(right, childRightEdge + paddingRight() + relativeOffset); - } - } - } - - if (applyTransform == IncludeTransform && includeSelf && layer() && layer()->hasTransform()) { - int top = topmostPosition(includeOverflowInterior, includeSelf, ExcludeTransform); - int bottom = lowestPosition(includeOverflowInterior, includeSelf, ExcludeTransform); - int left = leftmostPosition(includeOverflowInterior, includeSelf, ExcludeTransform); - IntRect transformRect = applyLayerTransformToRect(IntRect(left, top, right - left, bottom - top)); - return transformRect.width(); - } - - return right; -} - -int RenderBlock::leftmostPosition(bool includeOverflowInterior, bool includeSelf, ApplyTransform applyTransform) const -{ - IntRect transformedRect = transformedFrameRect(); - int transformedLeft = includeSelf && transformedRect.height() > 0 ? 0 : transformedRect.width(); - - if (!includeOverflowInterior && (hasOverflowClip() || hasControlClip())) - return transformedLeft; - - if (!firstChild() && (!transformedRect.width() || !transformedRect.height())) - return transformedLeft; - - int left = includeSelf && height() > 0 ? 0 : width(); - - if (!hasColumns()) { - // FIXME: Come up with a way to use the layer tree to avoid visiting all the kids. - // For now, we have to descend into all the children, since we may have a huge abs div inside - // a tiny rel div buried somewhere deep in our child tree. In this case we have to get to - // the abs div. - for (RenderObject* c = firstChild(); c; c = c->nextSibling()) { - if (!c->isFloatingOrPositioned() && c->isBox()) { - RenderBox* childBox = toRenderBox(c); - left = min(left, childBox->transformedFrameRect().x() + childBox->leftmostPosition(false)); - } - } - } - - if (includeSelf && isRelPositioned()) - left += relativePositionOffsetX(); - - if (!includeOverflowInterior && hasOverflowClip()) - return left; - - int relativeOffset = includeSelf && isRelPositioned() ? relativePositionOffsetX() : 0; - - if (includeSelf) - left = min(left, leftLayoutOverflow() + relativeOffset); - - if (m_positionedObjects) { - RenderBox* r; - Iterator end = m_positionedObjects->end(); - for (Iterator it = m_positionedObjects->begin(); it != end; ++it) { - r = *it; - // Fixed positioned objects do not scroll and thus should not constitute - // part of the leftmost position. - if (r->style()->position() != FixedPosition) { - // FIXME: Should work for overflow sections too. - // If a positioned object lies completely above the root it will be unreachable via scrolling. - // Therefore we should not allow it to contribute to the leftmost position. - IntRect transformedR = r->transformedFrameRect(); - if (!isRenderView() || transformedR.y() + transformedR.height() > 0 || transformedR.y() + r->lowestPosition(false) > 0) { - int lp = transformedR.x() + r->leftmostPosition(false); - left = min(left, lp + relativeOffset); - } - } - } - } - - if (hasColumns()) { - // This only matters for RTL - if (!style()->isLeftToRightDirection()) { - ColumnInfo* colInfo = columnInfo(); - unsigned count = columnCount(colInfo); - if (count) - left = min(columnRectAt(colInfo, count - 1).x() + relativeOffset, left); - } - return left; - } - - if (m_floatingObjects) { - FloatingObject* r; - DeprecatedPtrListIterator<FloatingObject> it(*m_floatingObjects); - for ( ; (r = it.current()); ++it ) { - if (r->m_shouldPaint || r->m_renderer->hasSelfPaintingLayer()) { - int lp = r->left() + r->m_renderer->marginLeft() + r->m_renderer->leftmostPosition(false); - left = min(left, lp + relativeOffset); - } - } - } - - if (!includeSelf && firstLineBox()) { - for (InlineFlowBox* currBox = firstLineBox(); currBox; currBox = currBox->nextLineBox()) - left = min(left, (int)currBox->x() + relativeOffset); - } - - if (applyTransform == IncludeTransform && includeSelf && layer() && layer()->hasTransform()) { - int top = topmostPosition(includeOverflowInterior, includeSelf, ExcludeTransform); - int bottom = lowestPosition(includeOverflowInterior, includeSelf, ExcludeTransform); - int right = rightmostPosition(includeOverflowInterior, includeSelf, ExcludeTransform); - IntRect transformRect = applyLayerTransformToRect(IntRect(left, top, right - left, bottom - top)); - return transformRect.x(); - } - - return left; -} - void RenderBlock::markLinesDirtyInBlockRange(int logicalTop, int logicalBottom, RootInlineBox* highest) { if (logicalTop >= logicalBottom) @@ -3807,7 +3443,7 @@ void RenderBlock::markLinesDirtyInBlockRange(int logicalTop, int logicalBottom, RootInlineBox* lowestDirtyLine = lastRootBox(); RootInlineBox* afterLowest = lowestDirtyLine; - while (lowestDirtyLine && lowestDirtyLine->blockLogicalHeight() >= logicalBottom && logicalBottom < numeric_limits<int>::max()) { + while (lowestDirtyLine && lowestDirtyLine->blockLogicalHeight() >= logicalBottom) { afterLowest = lowestDirtyLine; lowestDirtyLine = lowestDirtyLine->prevRootBox(); } @@ -3945,11 +3581,13 @@ int RenderBlock::addOverhangingFloats(RenderBlock* child, int logicalLeftOffset, // behaves properly). We always want to propagate the desire to paint the float as // far out as we can, to the outermost block that overlaps the float, stopping only // if we hit a self-painting layer boundary. - if (r->m_renderer->enclosingSelfPaintingLayer() == enclosingSelfPaintingLayer()) + if (r->m_renderer->enclosingFloatPaintingLayer() == enclosingFloatPaintingLayer()) r->m_shouldPaint = false; else floatingObj->m_shouldPaint = false; + floatingObj->m_isDescendant = true; + // We create the floating object list lazily. if (!m_floatingObjects) { m_floatingObjects = new DeprecatedPtrList<FloatingObject>; @@ -3957,17 +3595,22 @@ int RenderBlock::addOverhangingFloats(RenderBlock* child, int logicalLeftOffset, } m_floatingObjects->append(floatingObj); } - } else if (makeChildPaintOtherFloats && !r->m_shouldPaint && !r->m_renderer->hasSelfPaintingLayer() && - r->m_renderer->isDescendantOf(child) && r->m_renderer->enclosingLayer() == child->enclosingLayer()) - // The float is not overhanging from this block, so if it is a descendant of the child, the child should - // paint it (the other case is that it is intruding into the child), unless it has its own layer or enclosing - // layer. - // If makeChildPaintOtherFloats is false, it means that the child must already know about all the floats - // it should paint. - r->m_shouldPaint = true; - - if (r->m_shouldPaint && !r->m_renderer->hasSelfPaintingLayer()) - child->addOverflowFromChild(r->m_renderer, IntSize(r->left() + r->m_renderer->marginLeft(), r->top() + r->m_renderer->marginTop())); + } else { + if (makeChildPaintOtherFloats && !r->m_shouldPaint && !r->m_renderer->hasSelfPaintingLayer() && + r->m_renderer->isDescendantOf(child) && r->m_renderer->enclosingFloatPaintingLayer() == child->enclosingFloatPaintingLayer()) { + // The float is not overhanging from this block, so if it is a descendant of the child, the child should + // paint it (the other case is that it is intruding into the child), unless it has its own layer or enclosing + // layer. + // If makeChildPaintOtherFloats is false, it means that the child must already know about all the floats + // it should paint. + r->m_shouldPaint = true; + } + + // Since the float doesn't overhang, it didn't get put into our list. We need to go ahead and add its overflow in to the + // child now. + if (r->m_isDescendant) + child->addOverflowFromChild(r->m_renderer, IntSize(r->left() + r->m_renderer->marginLeft(), r->top() + r->m_renderer->marginTop())); + } } return lowestFloatLogicalBottom; } @@ -4135,7 +3778,7 @@ bool RenderBlock::nodeAtPoint(const HitTestRequest& request, HitTestResult& resu if (!isRenderView()) { // Check if we need to do anything at all. - IntRect overflowBox = visibleOverflowRect(); + IntRect overflowBox = visualOverflowRect(); overflowBox.move(tx, ty); if (!overflowBox.intersects(result.rectForPoint(_x, _y))) return false; @@ -4593,51 +4236,45 @@ IntRect RenderBlock::columnRectAt(ColumnInfo* colInfo, unsigned index) const return IntRect(colLeft, colTop, colWidth, colHeight); } -bool RenderBlock::layoutColumns(bool hasSpecifiedPageHeight, int pageHeight, LayoutStateMaintainer& statePusher) +bool RenderBlock::layoutColumns(bool hasSpecifiedPageLogicalHeight, int pageLogicalHeight, LayoutStateMaintainer& statePusher) { - if (hasColumns()) { - // FIXME: We don't balance properly at all in the presence of forced page breaks. We need to understand what - // the distance between forced page breaks is so that we can avoid making the minimum column height too tall. - ColumnInfo* colInfo = columnInfo(); - int desiredColumnCount = colInfo->desiredColumnCount(); - if (!hasSpecifiedPageHeight) { - int columnHeight = pageHeight; - int minColumnCount = colInfo->forcedBreaks() + 1; - if (minColumnCount >= desiredColumnCount) { - // The forced page breaks are in control of the balancing. Just set the column height to the - // maximum page break distance. - if (!pageHeight) { - int distanceBetweenBreaks = max(colInfo->maximumDistanceBetweenForcedBreaks(), - view()->layoutState()->pageY(borderTop() + paddingTop() + contentHeight()) - colInfo->forcedBreakOffset()); - columnHeight = max(colInfo->minimumColumnHeight(), distanceBetweenBreaks); - } - } else if (contentHeight() > pageHeight * desiredColumnCount) { - // Now that we know the intrinsic height of the columns, we have to rebalance them. - columnHeight = max(colInfo->minimumColumnHeight(), (int)ceilf((float)contentHeight() / desiredColumnCount)); - } - - if (columnHeight && columnHeight != pageHeight) { - statePusher.pop(); - m_everHadLayout = true; - layoutBlock(false, columnHeight); - return true; + if (!hasColumns()) + return false; + + // FIXME: We don't balance properly at all in the presence of forced page breaks. We need to understand what + // the distance between forced page breaks is so that we can avoid making the minimum column height too tall. + ColumnInfo* colInfo = columnInfo(); + int desiredColumnCount = colInfo->desiredColumnCount(); + if (!hasSpecifiedPageLogicalHeight) { + int columnHeight = pageLogicalHeight; + int minColumnCount = colInfo->forcedBreaks() + 1; + if (minColumnCount >= desiredColumnCount) { + // The forced page breaks are in control of the balancing. Just set the column height to the + // maximum page break distance. + if (!pageLogicalHeight) { + int distanceBetweenBreaks = max(colInfo->maximumDistanceBetweenForcedBreaks(), + view()->layoutState()->pageLogicalOffset(borderTop() + paddingTop() + contentHeight()) - colInfo->forcedBreakOffset()); + columnHeight = max(colInfo->minimumColumnHeight(), distanceBetweenBreaks); } - } + } else if (contentHeight() > pageLogicalHeight * desiredColumnCount) { + // Now that we know the intrinsic height of the columns, we have to rebalance them. + columnHeight = max(colInfo->minimumColumnHeight(), (int)ceilf((float)contentHeight() / desiredColumnCount)); + } - if (pageHeight) // FIXME: Should we use lowestPosition (excluding our positioned objects) instead of contentHeight()? - colInfo->setColumnCountAndHeight(ceilf((float)contentHeight() / pageHeight), pageHeight); - - if (columnCount(colInfo)) { - IntRect lastRect = columnRectAt(colInfo, columnCount(colInfo) - 1); - int overflowLeft = !style()->isLeftToRightDirection() ? min(0, lastRect.x()) : 0; - int overflowRight = style()->isLeftToRightDirection() ? max(width(), lastRect.x() + lastRect.width()) : 0; - int overflowHeight = borderTop() + paddingTop() + colInfo->columnHeight(); - - setLogicalHeight(overflowHeight + borderBottom() + paddingBottom() + horizontalScrollbarHeight()); - - m_overflow.clear(); - addLayoutOverflow(IntRect(overflowLeft, 0, overflowRight - overflowLeft, overflowHeight)); + if (columnHeight && columnHeight != pageLogicalHeight) { + statePusher.pop(); + m_everHadLayout = true; + layoutBlock(false, columnHeight); + return true; } + } + + if (pageLogicalHeight) + colInfo->setColumnCountAndHeight(ceilf((float)contentHeight() / pageLogicalHeight), pageLogicalHeight); + + if (columnCount(colInfo)) { + setLogicalHeight(borderTop() + paddingTop() + colInfo->columnHeight() + borderBottom() + paddingBottom() + horizontalScrollbarHeight()); + m_overflow.clear(); } return false; @@ -4772,11 +4409,22 @@ void RenderBlock::computePreferredLogicalWidths() m_minPreferredLogicalWidth = 0; } + int scrollbarWidth = 0; + if (hasOverflowClip() && style()->overflowY() == OSCROLL) { + layer()->setHasVerticalScrollbar(true); + scrollbarWidth = verticalScrollbarWidth(); + m_maxPreferredLogicalWidth += scrollbarWidth; + } + if (isTableCell()) { Length w = toRenderTableCell(this)->styleOrColLogicalWidth(); - if (w.isFixed() && w.value() > 0) + if (w.isFixed() && w.value() > 0) { m_maxPreferredLogicalWidth = max(m_minPreferredLogicalWidth, computeContentBoxLogicalWidth(w.value())); + scrollbarWidth = 0; + } } + + m_minPreferredLogicalWidth += scrollbarWidth; } if (style()->logicalMinWidth().isFixed() && style()->logicalMinWidth().value() > 0) { @@ -4789,14 +4437,9 @@ void RenderBlock::computePreferredLogicalWidths() m_minPreferredLogicalWidth = min(m_minPreferredLogicalWidth, computeContentBoxLogicalWidth(style()->logicalMaxWidth().value())); } - int toAdd = 0; - toAdd = borderAndPaddingLogicalWidth(); - - if (hasOverflowClip() && style()->overflowY() == OSCROLL) - toAdd += verticalScrollbarWidth(); - - m_minPreferredLogicalWidth += toAdd; - m_maxPreferredLogicalWidth += toAdd; + int borderAndPadding = borderAndPaddingLogicalWidth(); + m_minPreferredLogicalWidth += borderAndPadding; + m_maxPreferredLogicalWidth += borderAndPadding; setPreferredLogicalWidthsDirty(false); } @@ -5273,7 +4916,7 @@ bool RenderBlock::hasLineIfEmpty() const if (node()->isContentEditable() && node()->rootEditableElement() == node()) return true; - if (node()->isShadowNode() && (node()->shadowParentNode()->hasTagName(inputTag))) + if (node()->isShadowRoot() && (node()->shadowParentNode()->hasTagName(inputTag))) return true; return false; @@ -5822,14 +5465,14 @@ void RenderBlock::setPaginationStrut(int strut) m_rareData->m_paginationStrut = strut; } -void RenderBlock::setPageY(int y) +void RenderBlock::setPageLogicalOffset(int logicalOffset) { if (!m_rareData) { - if (!y) + if (!logicalOffset) return; m_rareData = new RenderBlockRareData(this); } - m_rareData->m_pageY = y; + m_rareData->m_pageLogicalOffset = logicalOffset; } void RenderBlock::absoluteRects(Vector<IntRect>& rects, int tx, int ty) @@ -6099,12 +5742,12 @@ RenderBlock* RenderBlock::createAnonymousColumnSpanBlock() const int RenderBlock::nextPageTop(int yPos) const { LayoutState* layoutState = view()->layoutState(); - if (!layoutState->m_pageHeight) + if (!layoutState->m_pageLogicalHeight) return yPos; // The yPos is in our coordinate space. We can add in our pushed offset. - int pageHeight = layoutState->m_pageHeight; - int remainingHeight = (pageHeight - ((layoutState->m_layoutOffset - layoutState->m_pageOffset).height() + yPos) % pageHeight) % pageHeight; + int pageLogicalHeight = layoutState->m_pageLogicalHeight; + int remainingHeight = (pageLogicalHeight - ((layoutState->m_layoutOffset - layoutState->m_pageOffset).height() + yPos) % pageLogicalHeight) % pageLogicalHeight; return yPos + remainingHeight; } @@ -6126,7 +5769,7 @@ int RenderBlock::applyBeforeBreak(RenderBox* child, int yPos) { // FIXME: Add page break checking here when we support printing. bool checkColumnBreaks = view()->layoutState()->isPaginatingColumns(); - bool checkPageBreaks = !checkColumnBreaks && view()->layoutState()->m_pageHeight; // FIXME: Once columns can print we have to check this. + bool checkPageBreaks = !checkColumnBreaks && view()->layoutState()->m_pageLogicalHeight; // FIXME: Once columns can print we have to check this. bool checkBeforeAlways = (checkColumnBreaks && child->style()->columnBreakBefore() == PBALWAYS) || (checkPageBreaks && child->style()->pageBreakBefore() == PBALWAYS); if (checkBeforeAlways && inNormalFlow(child)) { if (checkColumnBreaks) @@ -6140,7 +5783,7 @@ int RenderBlock::applyAfterBreak(RenderBox* child, int yPos, MarginInfo& marginI { // FIXME: Add page break checking here when we support printing. bool checkColumnBreaks = view()->layoutState()->isPaginatingColumns(); - bool checkPageBreaks = !checkColumnBreaks && view()->layoutState()->m_pageHeight; // FIXME: Once columns can print we have to check this. + bool checkPageBreaks = !checkColumnBreaks && view()->layoutState()->m_pageLogicalHeight; // FIXME: Once columns can print we have to check this. bool checkAfterAlways = (checkColumnBreaks && child->style()->columnBreakAfter() == PBALWAYS) || (checkPageBreaks && child->style()->pageBreakAfter() == PBALWAYS); if (checkAfterAlways && inNormalFlow(child)) { marginInfo.setMarginAfterQuirk(true); // Cause margins to be discarded for any following content. @@ -6160,10 +5803,10 @@ int RenderBlock::adjustForUnsplittableChild(RenderBox* child, int yPos, bool inc LayoutState* layoutState = view()->layoutState(); if (layoutState->m_columnInfo) layoutState->m_columnInfo->updateMinimumColumnHeight(childHeight); - int pageHeight = layoutState->m_pageHeight; - if (!pageHeight || childHeight > pageHeight) + int pageLogicalHeight = layoutState->m_pageLogicalHeight; + if (!pageLogicalHeight || childHeight > pageLogicalHeight) return yPos; - int remainingHeight = (pageHeight - ((layoutState->m_layoutOffset - layoutState->m_pageOffset).height() + yPos) % pageHeight) % pageHeight; + int remainingHeight = (pageLogicalHeight - ((layoutState->m_layoutOffset - layoutState->m_pageOffset).height() + yPos) % pageLogicalHeight) % pageLogicalHeight; if (remainingHeight < childHeight) return yPos + remainingHeight; return yPos; @@ -6188,19 +5831,19 @@ void RenderBlock::adjustLinePositionForPagination(RootInlineBox* lineBox, int& d // Technically if the location we move the line to has a different line width than our old position, then we need to dirty the // line and all following lines. LayoutState* layoutState = view()->layoutState(); - int pageHeight = layoutState->m_pageHeight; - int yPos = lineBox->topVisibleOverflow(); - int lineHeight = lineBox->bottomVisibleOverflow() - yPos; + int pageLogicalHeight = layoutState->m_pageLogicalHeight; + int yPos = lineBox->topVisualOverflow(); + int lineHeight = lineBox->bottomVisualOverflow() - yPos; if (layoutState->m_columnInfo) layoutState->m_columnInfo->updateMinimumColumnHeight(lineHeight); yPos += delta; lineBox->setPaginationStrut(0); - if (!pageHeight || lineHeight > pageHeight) + if (!pageLogicalHeight || lineHeight > pageLogicalHeight) return; - int remainingHeight = pageHeight - ((layoutState->m_layoutOffset - layoutState->m_pageOffset).height() + yPos) % pageHeight; + int remainingHeight = pageLogicalHeight - ((layoutState->m_layoutOffset - layoutState->m_pageOffset).height() + yPos) % pageLogicalHeight; if (remainingHeight < lineHeight) { int totalHeight = lineHeight + max(0, yPos); - if (lineBox == firstRootBox() && totalHeight < pageHeight && !isPositioned() && !isTableCell()) + if (lineBox == firstRootBox() && totalHeight < pageLogicalHeight && !isPositioned() && !isTableCell()) setPaginationStrut(remainingHeight + max(0, yPos)); else { delta += remainingHeight; diff --git a/WebCore/rendering/RenderBlock.h b/WebCore/rendering/RenderBlock.h index cc06954..5294ad4 100644 --- a/WebCore/rendering/RenderBlock.h +++ b/WebCore/rendering/RenderBlock.h @@ -55,7 +55,6 @@ public: RenderObjectChildList* children() { return &m_children; } virtual void destroy(); - bool beingDestroyed() const { return m_beingDestroyed; } // These two functions are overridden for inline-block. virtual int lineHeight(bool firstLine, LineDirectionMode, LinePositionMode = PositionOnContainingLine) const; @@ -72,7 +71,7 @@ public: virtual void addChild(RenderObject* newChild, RenderObject* beforeChild = 0); virtual void removeChild(RenderObject*); - virtual void layoutBlock(bool relayoutChildren, int pageHeight = 0); + virtual void layoutBlock(bool relayoutChildren, int pageLogicalHeight = 0); void insertPositionedObject(RenderBox*); void removePositionedObject(RenderBox*); @@ -99,11 +98,6 @@ public: int availableLogicalWidthForLine(int position, bool firstLine) const; int logicalRightOffsetForLine(int position, bool firstLine) const { return logicalRightOffsetForLine(position, logicalRightOffsetForContent(), firstLine); } int logicalLeftOffsetForLine(int position, bool firstLine) const { return logicalLeftOffsetForLine(position, logicalLeftOffsetForContent(), firstLine); } - - virtual int topmostPosition(bool includeOverflowInterior = true, bool includeSelf = true, ApplyTransform = IncludeTransform) const; - virtual int lowestPosition(bool includeOverflowInterior = true, bool includeSelf = true, ApplyTransform = IncludeTransform) const; - virtual int rightmostPosition(bool includeOverflowInterior = true, bool includeSelf = true, ApplyTransform = IncludeTransform) const; - virtual int leftmostPosition(bool includeOverflowInterior = true, bool includeSelf = true, ApplyTransform = IncludeTransform) const; virtual VisiblePosition positionForPoint(const IntPoint&); @@ -159,9 +153,12 @@ public: IntRect columnRectAt(ColumnInfo*, unsigned) const; int paginationStrut() const { return m_rareData ? m_rareData->m_paginationStrut : 0; } - int pageY() const { return m_rareData ? m_rareData->m_pageY : 0; } - void setPaginationStrut(int strut); - void setPageY(int y); + void setPaginationStrut(int); + + // The page logical offset is the object's offset from the top of the page in the page progression + // direction (so an x-offset in vertical text and a y-offset for horizontal text). + int pageLogicalOffset() const { return m_rareData ? m_rareData->m_pageLogicalOffset : 0; } + void setPageLogicalOffset(int); // Accessors for logical width/height and margins in the containing block's block-flow direction. enum ApplyLayoutDeltaMode { ApplyLayoutDelta, DoNotApplyLayoutDelta }; @@ -210,6 +207,8 @@ public: }; MarginValues marginValuesForChild(RenderBox* child); + virtual void scrollbarsChanged(bool /*horizontalScrollbarChanged*/, bool /*verticalScrollbarChanged*/) { }; + protected: // These functions are only used internally to manipulate the render tree structure via remove/insert/appendChildNode. // Since they are typically called only to move objects around within anonymous blocks (which only have layers in @@ -287,6 +286,13 @@ protected: virtual bool hasLineIfEmpty() const; bool layoutOnlyPositionedObjects(); + void computeOverflow(int oldClientAfterEdge, bool recomputeFloats = false); + virtual void addOverflowFromChildren(); + void addOverflowFromFloats(); + void addOverflowFromPositionedObjects(); + void addOverflowFromBlockChildren(); + void addOverflowFromInlineChildren(); + #if ENABLE(SVG) protected: @@ -299,8 +305,6 @@ protected: } #endif - void addOverflowFromBlockChildren(); - private: virtual RenderObjectChildList* virtualChildren() { return children(); } virtual const RenderObjectChildList* virtualChildren() const { return children(); } @@ -331,8 +335,6 @@ private: void layoutBlockChildren(bool relayoutChildren, int& maxFloatLogicalBottom); void layoutInlineChildren(bool relayoutChildren, int& repaintLogicalTop, int& repaintLogicalBottom); - virtual void positionListMarker() { } - virtual void borderFitAdjust(int& x, int& w) const; // Shrink the box in which the border paints if border-fit is set. virtual void updateBeforeAfterContent(PseudoId); @@ -464,15 +466,12 @@ private: void computeBlockDirectionPositionsForLine(RootInlineBox*, BidiRun*, GlyphOverflowAndFallbackFontsMap&, VerticalPositionCache&); void deleteEllipsisLineBoxes(); void checkLinesForTextOverflow(); - void addOverflowFromInlineChildren(); - int beforeSideVisibleOverflowForLine(RootInlineBox*) const; - int afterSideVisibleOverflowForLine(RootInlineBox*) const; + int beforeSideVisualOverflowForLine(RootInlineBox*) const; + int afterSideVisualOverflowForLine(RootInlineBox*) const; int beforeSideLayoutOverflowForLine(RootInlineBox*) const; int afterSideLayoutOverflowForLine(RootInlineBox*) const; // End of functions defined in RenderBlockLineLayout.cpp. - void addOverflowFromFloats(); - void paintFloats(PaintInfo&, int tx, int ty, bool preservePhase = false); void paintContents(PaintInfo&, int tx, int ty); void paintColumnContents(PaintInfo&, int tx, int ty, bool paintFloats = false); @@ -571,7 +570,7 @@ private: void offsetForContents(int& tx, int& ty) const; void calcColumnWidth(); - bool layoutColumns(bool hasSpecifiedPageHeight, int pageHeight, LayoutStateMaintainer&); + bool layoutColumns(bool hasSpecifiedPageLogicalHeight, int pageLogicalHeight, LayoutStateMaintainer&); void makeChildrenAnonymousColumnBlocks(RenderObject* beforeChild, RenderBlock* newBlockBox, RenderObject* newChild); bool expandsToEncloseOverhangingFloats() const; @@ -686,7 +685,7 @@ private: RenderBlockRareData(const RenderBlock* block) : m_margins(positiveMarginBeforeDefault(block), negativeMarginBeforeDefault(block), positiveMarginAfterDefault(block), negativeMarginAfterDefault(block)) , m_paginationStrut(0) - , m_pageY(0) + , m_pageLogicalOffset(0) { } @@ -710,7 +709,7 @@ private: MarginValues m_margins; int m_paginationStrut; - int m_pageY; + int m_pageLogicalOffset; }; OwnPtr<RenderBlockRareData> m_rareData; @@ -718,8 +717,7 @@ private: RenderObjectChildList m_children; RenderLineBoxList m_lineBoxes; // All of the root line boxes created for this block flow. For example, <div>Hello<br>world.</div> will have two total lines for the <div>. - mutable int m_lineHeight : 31; - bool m_beingDestroyed : 1; + mutable int m_lineHeight; // RenderRubyBase objects need to be able to split and merge, moving their children around // (calling moveChildTo, moveAllChildrenTo, and makeChildrenNonInline). diff --git a/WebCore/rendering/RenderBlockLineLayout.cpp b/WebCore/rendering/RenderBlockLineLayout.cpp index c722136..d8b11a8 100644 --- a/WebCore/rendering/RenderBlockLineLayout.cpp +++ b/WebCore/rendering/RenderBlockLineLayout.cpp @@ -734,8 +734,8 @@ void RenderBlock::layoutInlineChildren(bool relayoutChildren, int& repaintLogica RenderArena* arena = renderArena(); RootInlineBox* box = startLine; while (box) { - repaintLogicalTop = min(repaintLogicalTop, beforeSideVisibleOverflowForLine(box)); - repaintLogicalBottom = max(repaintLogicalBottom, afterSideVisibleOverflowForLine(box)); + repaintLogicalTop = min(repaintLogicalTop, beforeSideVisualOverflowForLine(box)); + repaintLogicalBottom = max(repaintLogicalBottom, afterSideVisualOverflowForLine(box)); RootInlineBox* next = box->nextRootBox(); box->deleteLine(arena); box = next; @@ -883,6 +883,9 @@ void RenderBlock::layoutInlineChildren(bool relayoutChildren, int& repaintLogica } #endif + // Compute our overflow now. + lineBox->computeOverflow(lineBox->lineTop(), lineBox->lineBottom(), document()->inNoQuirksMode(), textBoxDataMap); + #if PLATFORM(MAC) // Highlight acts as an overflow inflation. if (style()->highlight() != nullAtom) @@ -896,8 +899,8 @@ void RenderBlock::layoutInlineChildren(bool relayoutChildren, int& repaintLogica if (lineBox) { lineBox->setLineBreakInfo(end.obj, end.pos, resolver.status()); if (useRepaintBounds) { - repaintLogicalTop = min(repaintLogicalTop, beforeSideVisibleOverflowForLine(lineBox)); - repaintLogicalBottom = max(repaintLogicalBottom, afterSideVisibleOverflowForLine(lineBox)); + repaintLogicalTop = min(repaintLogicalTop, beforeSideVisualOverflowForLine(lineBox)); + repaintLogicalBottom = max(repaintLogicalBottom, afterSideVisualOverflowForLine(lineBox)); } if (paginated) { @@ -907,7 +910,7 @@ void RenderBlock::layoutInlineChildren(bool relayoutChildren, int& repaintLogica int oldLineWidth = availableLogicalWidthForLine(oldLogicalHeight, firstLine); lineBox->adjustPosition(0, adjustment); if (useRepaintBounds) // This can only be a positive adjustment, so no need to update repaintTop. - repaintLogicalBottom = max(repaintLogicalBottom, afterSideVisibleOverflowForLine(lineBox)); + repaintLogicalBottom = max(repaintLogicalBottom, afterSideVisualOverflowForLine(lineBox)); if (availableLogicalWidthForLine(oldLogicalHeight + adjustment, firstLine) != oldLineWidth) { // We have to delete this line, remove all floats that got added, and let line layout re-run. @@ -961,8 +964,8 @@ void RenderBlock::layoutInlineChildren(bool relayoutChildren, int& repaintLogica adjustLinePositionForPagination(line, delta); } if (delta) { - repaintLogicalTop = min(repaintLogicalTop, beforeSideVisibleOverflowForLine(line) + min(delta, 0)); - repaintLogicalBottom = max(repaintLogicalBottom, afterSideVisibleOverflowForLine(line) + max(delta, 0)); + repaintLogicalTop = min(repaintLogicalTop, beforeSideVisualOverflowForLine(line) + min(delta, 0)); + repaintLogicalBottom = max(repaintLogicalBottom, afterSideVisualOverflowForLine(line) + max(delta, 0)); line->adjustPosition(0, delta); } if (Vector<RenderBox*>* cleanLineFloats = line->floatsPtr()) { @@ -980,8 +983,8 @@ void RenderBlock::layoutInlineChildren(bool relayoutChildren, int& repaintLogica RootInlineBox* line = endLine; RenderArena* arena = renderArena(); while (line) { - repaintLogicalTop = min(repaintLogicalTop, beforeSideVisibleOverflowForLine(line)); - repaintLogicalBottom = max(repaintLogicalBottom, afterSideVisibleOverflowForLine(line)); + repaintLogicalTop = min(repaintLogicalTop, beforeSideVisualOverflowForLine(line)); + repaintLogicalBottom = max(repaintLogicalBottom, afterSideVisualOverflowForLine(line)); RootInlineBox* next = line->nextRootBox(); line->deleteLine(arena); line = next; @@ -993,7 +996,7 @@ void RenderBlock::layoutInlineChildren(bool relayoutChildren, int& repaintLogica // This has to be done before adding in the bottom border/padding, or the float will // include the padding incorrectly. -dwh if (checkForFloatsFromLastLine) { - int bottomVisualOverflow = afterSideVisibleOverflowForLine(lastRootBox()); + int bottomVisualOverflow = afterSideVisualOverflowForLine(lastRootBox()); int bottomLayoutOverflow = afterSideLayoutOverflowForLine(lastRootBox()); TrailingFloatsRootInlineBox* trailingFloatsLineBox = new (renderArena()) TrailingFloatsRootInlineBox(this); m_lineBoxes.appendLineBox(trailingFloatsLineBox); @@ -1001,7 +1004,9 @@ void RenderBlock::layoutInlineChildren(bool relayoutChildren, int& repaintLogica GlyphOverflowAndFallbackFontsMap textBoxDataMap; VerticalPositionCache verticalPositionCache; trailingFloatsLineBox->alignBoxesInBlockDirection(logicalHeight(), textBoxDataMap, verticalPositionCache); - trailingFloatsLineBox->setBlockDirectionOverflowPositions(logicalHeight(), bottomLayoutOverflow, logicalHeight(), bottomVisualOverflow); + IntRect logicalLayoutOverflow(0, logicalHeight(), 1, bottomLayoutOverflow); + IntRect logicalVisualOverflow(0, logicalHeight(), 1, bottomVisualOverflow); + trailingFloatsLineBox->setOverflowFromLogicalRects(logicalLayoutOverflow, logicalVisualOverflow); trailingFloatsLineBox->setBlockLogicalHeight(logicalHeight()); } if (lastFloat) { @@ -1027,16 +1032,18 @@ void RenderBlock::layoutInlineChildren(bool relayoutChildren, int& repaintLogica } } - // Expand the last line to accommodate Ruby in flipped lines writing modes (the Ruby is on - // the after side in this case). - int lastLineRubyAdjustment = 0; - if (lastRootBox() && style()->isFlippedLinesWritingMode()) { + // Expand the last line to accommodate Ruby and emphasis marks. + int lastLineAnnotationsAdjustment = 0; + if (lastRootBox()) { int lowestAllowedPosition = max(lastRootBox()->lineBottom(), logicalHeight() + paddingAfter()); - lastLineRubyAdjustment = lastRootBox()->computeBlockDirectionRubyAdjustment(lowestAllowedPosition); + if (!style()->isFlippedLinesWritingMode()) + lastLineAnnotationsAdjustment = lastRootBox()->computeUnderAnnotationAdjustment(lowestAllowedPosition); + else + lastLineAnnotationsAdjustment = lastRootBox()->computeOverAnnotationAdjustment(lowestAllowedPosition); } - + // Now add in the bottom border/padding. - setLogicalHeight(logicalHeight() + lastLineRubyAdjustment + borderAfter() + paddingAfter() + scrollbarLogicalHeight()); + setLogicalHeight(logicalHeight() + lastLineAnnotationsAdjustment + borderAfter() + paddingAfter() + scrollbarLogicalHeight()); if (!firstLineBox() && hasLineIfEmpty()) setLogicalHeight(logicalHeight() + lineHeight(true, style()->isHorizontalWritingMode() ? HorizontalLine : VerticalLine, PositionOfInteriorLineBoxes)); @@ -1074,8 +1081,8 @@ RootInlineBox* RenderBlock::determineStartPosition(bool& firstLine, bool& fullLa if (!useRepaintBounds) useRepaintBounds = true; - repaintLogicalTop = min(repaintLogicalTop, beforeSideVisibleOverflowForLine(curr) + min(paginationDelta, 0)); - repaintLogicalBottom = max(repaintLogicalBottom, afterSideVisibleOverflowForLine(curr) + max(paginationDelta, 0)); + repaintLogicalTop = min(repaintLogicalTop, beforeSideVisualOverflowForLine(curr) + min(paginationDelta, 0)); + repaintLogicalBottom = max(repaintLogicalBottom, afterSideVisualOverflowForLine(curr) + max(paginationDelta, 0)); curr->adjustPosition(0, paginationDelta); } } @@ -1291,8 +1298,8 @@ bool RenderBlock::matchedEndLine(const InlineBidiResolver& resolver, const Inlin RootInlineBox* boxToDelete = endLine; RenderArena* arena = renderArena(); while (boxToDelete && boxToDelete != result) { - repaintLogicalTop = min(repaintLogicalTop, beforeSideVisibleOverflowForLine(boxToDelete)); - repaintLogicalBottom = max(repaintLogicalBottom, afterSideVisibleOverflowForLine(boxToDelete)); + repaintLogicalTop = min(repaintLogicalTop, beforeSideVisualOverflowForLine(boxToDelete)); + repaintLogicalBottom = max(repaintLogicalBottom, afterSideVisualOverflowForLine(boxToDelete)); RootInlineBox* next = boxToDelete->nextRootBox(); boxToDelete->deleteLine(arena); boxToDelete = next; @@ -2148,29 +2155,33 @@ InlineIterator RenderBlock::findNextLineBreak(InlineBidiResolver& resolver, bool void RenderBlock::addOverflowFromInlineChildren() { + int endPadding = hasOverflowClip() ? paddingEnd() : 0; + // FIXME: Need to find another way to do this, since scrollbars could show when we don't want them to. + if (hasOverflowClip() && !endPadding && node() && node()->isContentEditable() && node() == node()->rootEditableElement() && style()->isLeftToRightDirection()) + endPadding = 1; for (RootInlineBox* curr = firstRootBox(); curr; curr = curr->nextRootBox()) { - addLayoutOverflow(curr->layoutOverflowRect()); + addLayoutOverflow(curr->paddedLayoutOverflowRect(endPadding)); if (!hasOverflowClip()) addVisualOverflow(curr->visualOverflowRect()); } } -int RenderBlock::beforeSideVisibleOverflowForLine(RootInlineBox* line) const +int RenderBlock::beforeSideVisualOverflowForLine(RootInlineBox* line) const { // Overflow is in the block's coordinate space, which means it isn't purely physical. For flipped blocks (rl and bt), // we continue to use top and left overflow even though physically it's bottom and right. if (style()->isHorizontalWritingMode()) - return line->topVisibleOverflow(); - return line->leftVisibleOverflow(); + return line->topVisualOverflow(); + return line->leftVisualOverflow(); } -int RenderBlock::afterSideVisibleOverflowForLine(RootInlineBox* line) const +int RenderBlock::afterSideVisualOverflowForLine(RootInlineBox* line) const { // Overflow is in the block's coordinate space, which means it isn't purely physical. For flipped blocks (rl and bt), // we continue to use bottom and right overflow even though physically it's top and left. if (style()->isHorizontalWritingMode()) - return line->bottomVisibleOverflow(); - return line->rightVisibleOverflow(); + return line->bottomVisualOverflow(); + return line->rightVisualOverflow(); } int RenderBlock::beforeSideLayoutOverflowForLine(RootInlineBox* line) const diff --git a/WebCore/rendering/RenderBox.cpp b/WebCore/rendering/RenderBox.cpp index 0944c37..355d385 100644 --- a/WebCore/rendering/RenderBox.cpp +++ b/WebCore/rendering/RenderBox.cpp @@ -227,28 +227,26 @@ void RenderBox::removeFloatingOrPositionedChildFromBlockLists() return; if (isFloating()) { - RenderBlock* parentBlock = 0; - for (RenderObject* curr = parent(); curr && !curr->isRenderView(); curr = curr->parent()) { - if (curr->isRenderBlock()) { - RenderBlock* currBlock = toRenderBlock(curr); - if (currBlock->containsFloat(this)) - parentBlock = currBlock; - } + RenderBlock* outermostBlock = containingBlock(); + for (RenderBlock* p = outermostBlock; p && !p->isRenderView(); p = p->containingBlock()) { + if (p->containsFloat(this)) + outermostBlock = p; } - if (parentBlock) { - RenderObject* parent = parentBlock->parent(); + if (outermostBlock) { + RenderObject* parent = outermostBlock->parent(); if (parent && parent->isFlexibleBox()) - parentBlock = toRenderBlock(parent); + outermostBlock = toRenderBlock(parent); - parentBlock->markAllDescendantsWithFloatsForLayout(this, false); + outermostBlock->markAllDescendantsWithFloatsForLayout(this, false); } } if (isPositioned()) { - for (RenderObject* curr = parent(); curr; curr = curr->parent()) { - if (curr->isRenderBlock()) - toRenderBlock(curr)->removePositionedObject(this); + RenderObject* p; + for (p = parent(); p; p = p->parent()) { + if (p->isRenderBlock()) + toRenderBlock(p)->removePositionedObject(this); } } } @@ -418,9 +416,10 @@ int RenderBox::scrollWidth() const if (hasOverflowClip()) return layer()->scrollWidth(); // For objects with visible overflow, this matches IE. + // FIXME: Need to work right with writing modes. if (style()->isLeftToRightDirection()) - return max(clientWidth(), rightmostPosition(true, false) - borderLeft()); - return clientWidth() - min(0, leftmostPosition(true, false) - borderLeft()); + return max(clientWidth(), rightLayoutOverflow() - borderLeft()); + return clientWidth() - min(0, leftLayoutOverflow() - borderLeft()); } int RenderBox::scrollHeight() const @@ -428,7 +427,8 @@ int RenderBox::scrollHeight() const if (hasOverflowClip()) return layer()->scrollHeight(); // For objects with visible overflow, this matches IE. - return max(clientHeight(), lowestPosition(true, false) - borderTop()); + // FIXME: Need to work right with writing modes. + return max(clientHeight(), bottomLayoutOverflow() - borderTop()); } int RenderBox::scrollLeft() const @@ -463,22 +463,11 @@ void RenderBox::absoluteQuads(Vector<FloatQuad>& quads) quads.append(localToAbsoluteQuad(FloatRect(0, 0, width(), height()))); } -IntRect RenderBox::applyLayerTransformToRect(const IntRect& rect) const +void RenderBox::updateLayerTransform() { - if (layer() && layer()->hasTransform()) { - TransformationMatrix transform; - transform.makeIdentity(); - transform.translate(rect.x(), rect.y()); + // Transform-origin depends on box size, so we need to update the layer transform after layout. + if (hasLayer()) layer()->updateTransform(); - transform.multLeft(layer()->currentTransform()); - return transform.mapRect(IntRect(0, 0, rect.width(), rect.height())); - } - return rect; -} - -IntRect RenderBox::transformedFrameRect() const -{ - return applyLayerTransformToRect(frameRect()); } IntRect RenderBox::absoluteContentBox() const @@ -606,6 +595,36 @@ bool RenderBox::scroll(ScrollDirection direction, ScrollGranularity granularity, return false; } +bool RenderBox::logicalScroll(ScrollLogicalDirection direction, ScrollGranularity granularity, float multiplier, Node** stopNode) +{ + bool scrolled = false; + + RenderLayer* l = layer(); + if (l) { +#if PLATFORM(MAC) + // On Mac only we reset the inline direction position when doing a document scroll (e.g., hitting Home/End). + if (granularity == ScrollByDocument) + scrolled = l->scroll(logicalToPhysical(ScrollInlineDirectionBackward, style()->isHorizontalWritingMode(), style()->isFlippedBlocksWritingMode()), ScrollByDocument, multiplier); +#endif + if (l->scroll(logicalToPhysical(direction, style()->isHorizontalWritingMode(), style()->isFlippedBlocksWritingMode()), granularity, multiplier)) + scrolled = true; + + if (scrolled) { + if (stopNode) + *stopNode = node(); + return true; + } + } + + if (stopNode && *stopNode && *stopNode == node()) + return true; + + RenderBlock* b = containingBlock(); + if (b && !b->isRenderView()) + return b->logicalScroll(direction, granularity, multiplier, stopNode); + return false; +} + bool RenderBox::canBeScrolledAndHasScrollableArea() const { return canBeProgramaticallyScrolled(false) && (scrollHeight() != clientHeight() || scrollWidth() != clientWidth()); @@ -764,31 +783,12 @@ void RenderBox::paintRootBoxDecorations(PaintInfo& paintInfo, int tx, int ty) } } - int w = width(); - int h = height(); - - int rw; - int rh; - if (view()->frameView()) { - rw = view()->frameView()->contentsWidth(); - rh = view()->frameView()->contentsHeight(); - } else { - rw = view()->width(); - rh = view()->height(); - } - - // CSS2 14.2: - // The background of the box generated by the root element covers the entire canvas including - // its margins. - int bx = tx - marginLeft() + view()->leftLayoutOverflow(); - int by = ty - marginTop(); - int bw = max(w + marginLeft() + marginRight() + borderLeft() + borderRight(), rw); - int bh = max(h + marginTop() + marginBottom() + borderTop() + borderBottom(), rh); - - paintFillLayers(paintInfo, bgColor, bgLayer, bx, by, bw, bh, CompositeSourceOver, bodyObject); + // The background of the box generated by the root element covers the entire canvas, so just use + // the RenderView's docTop/Left/Width/Height accessors. + paintFillLayers(paintInfo, bgColor, bgLayer, view()->docLeft(), view()->docTop(), view()->docWidth(), view()->docHeight(), CompositeSourceOver, bodyObject); if (style()->hasBorder() && style()->display() != INLINE) - paintBorder(paintInfo.context, tx, ty, w, h, style()); + paintBorder(paintInfo.context, tx, ty, width(), height(), style()); } void RenderBox::paintBoxDecorations(PaintInfo& paintInfo, int tx, int ty) @@ -947,6 +947,18 @@ void RenderBox::paintFillLayer(const PaintInfo& paintInfo, const Color& c, const paintFillLayerExtended(paintInfo, c, fillLayer, tx, ty, width, height, 0, op, backgroundObject); } +#if USE(ACCELERATED_COMPOSITING) +static bool layersUseImage(WrappedImagePtr image, const FillLayer* layers) +{ + for (const FillLayer* curLayer = layers; curLayer; curLayer = curLayer->next()) { + if (curLayer->image() && image == curLayer->image()->data()) + return true; + } + + return false; +} +#endif + void RenderBox::imageChanged(WrappedImagePtr image, const IntRect*) { if (!parent()) @@ -961,6 +973,12 @@ void RenderBox::imageChanged(WrappedImagePtr image, const IntRect*) bool didFullRepaint = repaintLayerRectsForImage(image, style()->backgroundLayers(), true); if (!didFullRepaint) repaintLayerRectsForImage(image, style()->maskLayers(), false); + + +#if USE(ACCELERATED_COMPOSITING) + if (hasLayer() && layer()->hasCompositedMask() && layersUseImage(image, style()->maskLayers())) + layer()->contentChanged(RenderLayer::MaskImageChanged); +#endif } bool RenderBox::repaintLayerRectsForImage(WrappedImagePtr image, const FillLayer* layers, bool drawingBackground) @@ -1323,7 +1341,7 @@ IntRect RenderBox::clippedOverflowRectForRepaint(RenderBoxModelObject* repaintCo if (style()->visibility() != VISIBLE && !enclosingLayer()->hasVisibleContent()) return IntRect(); - IntRect r = visibleOverflowRect(); + IntRect r = visualOverflowRect(); RenderView* v = view(); if (v) { @@ -1826,7 +1844,7 @@ void RenderBox::computeLogicalHeight() int margins = collapsedMarginBefore() + collapsedMarginAfter(); int visHeight; if (document()->printing()) - visHeight = static_cast<int>(view()->pageHeight()); + visHeight = static_cast<int>(view()->pageLogicalHeight()); else { if (style()->isHorizontalWritingMode()) visHeight = view()->viewHeight(); @@ -3048,50 +3066,6 @@ IntRect RenderBox::localCaretRect(InlineBox* box, int caretOffset, int* extraWid return rect; } -int RenderBox::topmostPosition(bool /*includeOverflowInterior*/, bool includeSelf, ApplyTransform applyTransform) const -{ - IntRect transformedRect = applyTransform == IncludeTransform && includeSelf ? transformedFrameRect() : frameRect(); - if (!includeSelf || !transformedRect.width()) - return 0; - int top = 0; - if (isRelPositioned()) - top += relativePositionOffsetY(); - return top; -} - -int RenderBox::lowestPosition(bool /*includeOverflowInterior*/, bool includeSelf, ApplyTransform applyTransform) const -{ - IntRect transformedRect = applyTransform == IncludeTransform && includeSelf ? transformedFrameRect() : frameRect(); - if (!includeSelf || !transformedRect.width()) - return 0; - int bottom = transformedRect.height(); - if (isRelPositioned()) - bottom += relativePositionOffsetY(); - return bottom; -} - -int RenderBox::rightmostPosition(bool /*includeOverflowInterior*/, bool includeSelf, ApplyTransform applyTransform) const -{ - IntRect transformedRect = applyTransform == IncludeTransform && includeSelf ? transformedFrameRect() : frameRect(); - if (!includeSelf || !transformedRect.height()) - return 0; - int right = transformedRect.width(); - if (isRelPositioned()) - right += relativePositionOffsetX(); - return right; -} - -int RenderBox::leftmostPosition(bool /*includeOverflowInterior*/, bool includeSelf, ApplyTransform applyTransform) const -{ - IntRect transformedRect = applyTransform == IncludeTransform && includeSelf ? transformedFrameRect() : frameRect(); - if (!includeSelf || !transformedRect.height()) - return transformedRect.width(); - int left = 0; - if (isRelPositioned()) - left += relativePositionOffsetX(); - return left; -} - VisiblePosition RenderBox::positionForPoint(const IntPoint& point) { // no children...return this render object's element, if there is one, and offset 0 @@ -3216,47 +3190,67 @@ void RenderBox::addShadowOverflow() void RenderBox::addOverflowFromChild(RenderBox* child, const IntSize& delta) { - // Update our overflow in case the child spills out the block, but only if we were going to paint - // the child block ourselves. - if (child->hasSelfPaintingLayer()) - return; - // Only propagate layout overflow from the child if the child isn't clipping its overflow. If it is, then - // its overflow is internal to it, and we don't care about it. - IntRect childLayoutOverflowRect = child->hasOverflowClip() ? child->borderBoxRect() : child->layoutOverflowRect(); + // its overflow is internal to it, and we don't care about it. layoutOverflowRectForPropagation takes care of this + // and just propagates the border box rect instead. + IntRect childLayoutOverflowRect = child->layoutOverflowRectForPropagation(style()); childLayoutOverflowRect.move(delta); addLayoutOverflow(childLayoutOverflowRect); // Add in visual overflow from the child. Even if the child clips its overflow, it may still // have visual overflow of its own set from box shadows or reflections. It is unnecessary to propagate this // overflow if we are clipping our own overflow. - if (hasOverflowClip()) + if (child->hasSelfPaintingLayer() || hasOverflowClip()) return; - IntRect childVisualOverflowRect = child->visualOverflowRect(); + IntRect childVisualOverflowRect = child->visualOverflowRectForPropagation(style()); childVisualOverflowRect.move(delta); addVisualOverflow(childVisualOverflowRect); } void RenderBox::addLayoutOverflow(const IntRect& rect) { - IntRect borderBox = borderBoxRect(); - if (borderBox.contains(rect)) + IntRect clientBox = clientBoxRect(); + if (clientBox.contains(rect) || rect.isEmpty()) return; + + // For overflow clip objects, we don't want to propagate overflow into unreachable areas. + IntRect overflowRect(rect); + if (hasOverflowClip() || isRenderView()) { + // Overflow is in the block's coordinate space and thus is flipped for horizontal-bt and vertical-rl + // writing modes. At this stage that is actually a simplification, since we can treat horizontal-tb/bt as the same + // and vertical-lr/rl as the same. + bool hasTopOverflow = !style()->isLeftToRightDirection() && !style()->isHorizontalWritingMode(); + bool hasLeftOverflow = !style()->isLeftToRightDirection() && style()->isHorizontalWritingMode(); + + if (!hasTopOverflow) + overflowRect.shiftTopEdgeTo(max(overflowRect.y(), clientBox.y())); + else + overflowRect.shiftBottomEdgeTo(min(overflowRect.bottom(), clientBox.bottom())); + if (!hasLeftOverflow) + overflowRect.shiftLeftEdgeTo(max(overflowRect.x(), clientBox.x())); + else + overflowRect.shiftRightEdgeTo(min(overflowRect.right(), clientBox.right())); + // Now re-test with the adjusted rectangle and see if it has become unreachable or fully + // contained. + if (clientBox.contains(overflowRect) || overflowRect.isEmpty()) + return; + } + if (!m_overflow) - m_overflow.set(new RenderOverflow(borderBox)); + m_overflow.set(new RenderOverflow(clientBox, borderBoxRect())); - m_overflow->addLayoutOverflow(rect); + m_overflow->addLayoutOverflow(overflowRect); } void RenderBox::addVisualOverflow(const IntRect& rect) { IntRect borderBox = borderBoxRect(); - if (borderBox.contains(rect)) + if (borderBox.contains(rect) || rect.isEmpty()) return; if (!m_overflow) - m_overflow.set(new RenderOverflow(borderBox)); + m_overflow.set(new RenderOverflow(clientBoxRect(), borderBox)); m_overflow->addVisualOverflow(rect); } @@ -3292,20 +3286,89 @@ int RenderBox::baselinePosition(FontBaseline baselineType, bool /*firstLine*/, L return 0; } -void RenderBox::blockDirectionOverflow(bool isLineHorizontal, int& logicalTopLayoutOverflow, int& logicalBottomLayoutOverflow, - int& logicalTopVisualOverflow, int& logicalBottomVisualOverflow) + +RenderLayer* RenderBox::enclosingFloatPaintingLayer() const { - if (isLineHorizontal) { - logicalTopLayoutOverflow = topLayoutOverflow(); - logicalBottomLayoutOverflow = bottomLayoutOverflow(); - logicalTopVisualOverflow = topVisualOverflow(); - logicalBottomVisualOverflow = bottomVisualOverflow(); - } else { - logicalTopLayoutOverflow = leftLayoutOverflow(); - logicalBottomLayoutOverflow = rightLayoutOverflow(); - logicalTopVisualOverflow = leftVisualOverflow(); - logicalBottomVisualOverflow = rightVisualOverflow(); - } + const RenderObject* curr = this; + while (curr) { + RenderLayer* layer = curr->hasLayer() && curr->isBox() ? toRenderBoxModelObject(curr)->layer() : 0; + if (layer && layer->isSelfPaintingLayer()) + return layer; + curr = curr->parent(); + } + return 0; +} + +IntRect RenderBox::logicalVisualOverflowRectForPropagation(RenderStyle* parentStyle) const +{ + IntRect rect = visualOverflowRectForPropagation(parentStyle); + if (!parentStyle->isHorizontalWritingMode()) + return rect.transposedRect(); + return rect; +} + +IntRect RenderBox::visualOverflowRectForPropagation(RenderStyle* parentStyle) const +{ + // If the writing modes of the child and parent match, then we don't have to + // do anything fancy. Just return the result. + IntRect rect = visualOverflowRect(); + if (parentStyle->writingMode() == style()->writingMode()) + return rect; + + // We are putting ourselves into our parent's coordinate space. If there is a flipped block mismatch + // in a particular axis, then we have to flip the rect along that axis. + if (style()->writingMode() == RightToLeftWritingMode || parentStyle->writingMode() == RightToLeftWritingMode) + rect.setX(width() - rect.right()); + else if (style()->writingMode() == BottomToTopWritingMode || parentStyle->writingMode() == BottomToTopWritingMode) + rect.setY(height() - rect.bottom()); + + return rect; +} + +IntRect RenderBox::logicalLayoutOverflowRectForPropagation(RenderStyle* parentStyle) const +{ + IntRect rect = layoutOverflowRectForPropagation(parentStyle); + if (!parentStyle->isHorizontalWritingMode()) + return rect.transposedRect(); + return rect; +} + +IntRect RenderBox::layoutOverflowRectForPropagation(RenderStyle* parentStyle) const +{ + // Only propagate interior layout overflow if we don't clip it. + IntRect rect = borderBoxRect(); + if (!hasOverflowClip()) + rect.unite(layoutOverflowRect()); + + if (isRelPositioned() || hasTransform()) { + // If we are relatively positioned or if we have a transform, then we have to convert + // this rectangle into physical coordinates, apply relative positioning and transforms + // to it, and then convert it back. + flipForWritingMode(rect); + + if (hasTransform()) + rect = layer()->currentTransform().mapRect(rect); + + if (isRelPositioned()) + rect.move(relativePositionOffsetX(), relativePositionOffsetY()); + + // Now we need to flip back. + flipForWritingMode(rect); + } + + // If the writing modes of the child and parent match, then we don't have to + // do anything fancy. Just return the result. + if (parentStyle->writingMode() == style()->writingMode()) + return rect; + + // We are putting ourselves into our parent's coordinate space. If there is a flipped block mismatch + // in a particular axis, then we have to flip the rect along that axis. + if (style()->writingMode() == RightToLeftWritingMode || parentStyle->writingMode() == RightToLeftWritingMode) + rect.setX(width() - rect.right()); + else if (style()->writingMode() == BottomToTopWritingMode || parentStyle->writingMode() == BottomToTopWritingMode) + rect.setY(height() - rect.bottom()); + + return rect; } IntPoint RenderBox::flipForWritingMode(const RenderBox* child, const IntPoint& point, FlippingAdjustment adjustment) const diff --git a/WebCore/rendering/RenderBox.h b/WebCore/rendering/RenderBox.h index 091796b..3dd7c23 100644 --- a/WebCore/rendering/RenderBox.h +++ b/WebCore/rendering/RenderBox.h @@ -106,12 +106,9 @@ public: IntRect frameRect() const { return m_frameRect; } void setFrameRect(const IntRect& rect) { m_frameRect = rect; } - IntRect transformedFrameRect() const; - IntRect applyLayerTransformToRect(const IntRect&) const; - IntRect borderBoxRect() const { return IntRect(0, 0, width(), height()); } virtual IntRect borderBoundingBox() const { return borderBoxRect(); } - + // The content area of the box (excludes padding and border). IntRect contentBoxRect() const { return IntRect(borderLeft() + paddingLeft(), borderTop() + paddingTop(), contentWidth(), contentHeight()); } // The content box in absolute coords. Ignores transforms. @@ -128,17 +125,11 @@ public: RenderBox* nextSiblingBox() const; RenderBox* parentBox() const; - IntRect visibleOverflowRect() const { return hasOverflowClip() ? visualOverflowRect() : (m_overflow ? m_overflow->visibleOverflowRect() : borderBoxRect()); } - int topVisibleOverflow() const { return hasOverflowClip() ? topVisualOverflow() : std::min(topLayoutOverflow(), topVisualOverflow()); } - int bottomVisibleOverflow() const { return hasOverflowClip() ? bottomVisualOverflow() : std::max(bottomLayoutOverflow(), bottomVisualOverflow()); } - int leftVisibleOverflow() const { return hasOverflowClip() ? leftVisualOverflow() : std::min(leftLayoutOverflow(), leftVisualOverflow()); } - int rightVisibleOverflow() const { return hasOverflowClip() ? rightVisualOverflow() : std::max(rightLayoutOverflow(), rightVisualOverflow()); } - - IntRect layoutOverflowRect() const { return m_overflow ? m_overflow->layoutOverflowRect() : borderBoxRect(); } - int topLayoutOverflow() const { return m_overflow? m_overflow->topLayoutOverflow() : 0; } - int bottomLayoutOverflow() const { return m_overflow ? m_overflow->bottomLayoutOverflow() : height(); } - int leftLayoutOverflow() const { return m_overflow ? m_overflow->leftLayoutOverflow() : 0; } - int rightLayoutOverflow() const { return m_overflow ? m_overflow->rightLayoutOverflow() : width(); } + IntRect layoutOverflowRect() const { return m_overflow ? m_overflow->layoutOverflowRect() : clientBoxRect(); } + int topLayoutOverflow() const { return m_overflow? m_overflow->topLayoutOverflow() : borderTop(); } + int bottomLayoutOverflow() const { return m_overflow ? m_overflow->bottomLayoutOverflow() : borderTop() + clientHeight(); } + int leftLayoutOverflow() const { return m_overflow ? m_overflow->leftLayoutOverflow() : borderLeft(); } + int rightLayoutOverflow() const { return m_overflow ? m_overflow->rightLayoutOverflow() : borderLeft() + clientWidth(); } int logicalLeftLayoutOverflow() const { return style()->isHorizontalWritingMode() ? leftLayoutOverflow() : topLayoutOverflow(); } int logicalRightLayoutOverflow() const { return style()->isHorizontalWritingMode() ? rightLayoutOverflow() : bottomLayoutOverflow(); } @@ -157,6 +148,8 @@ public: void addOverflowFromChild(RenderBox* child) { addOverflowFromChild(child, IntSize(child->x(), child->y())); } void addOverflowFromChild(RenderBox* child, const IntSize& delta); void clearLayoutOverflow(); + + void updateLayerTransform(); void blockDirectionOverflow(bool isLineHorizontal, int& logicalTopLayoutOverflow, int& logicalBottomLayoutOverflow, int& logicalTopVisualOverflow, int& logicalBottomVisualOverflow); @@ -177,6 +170,8 @@ public: int clientTop() const { return borderTop(); } int clientWidth() const; int clientHeight() const; + int clientLogicalBottom() const { return style()->isHorizontalWritingMode() ? clientTop() + clientHeight() : clientLeft() + clientWidth(); } + IntRect clientBoxRect() const { return IntRect(clientLeft(), clientTop(), clientWidth(), clientHeight()); } // scrollWidth/scrollHeight will be the same as clientWidth/clientHeight unless the // object has overflow:hidden/scroll/auto specified and also has overflow. @@ -268,12 +263,6 @@ public: void setInlineBoxWrapper(InlineBox* boxWrapper) { m_inlineBoxWrapper = boxWrapper; } void deleteLineBoxWrapper(); - enum ApplyTransform { IncludeTransform, ExcludeTransform }; - virtual int topmostPosition(bool includeOverflowInterior = true, bool includeSelf = true, ApplyTransform = IncludeTransform) const; - virtual int lowestPosition(bool includeOverflowInterior = true, bool includeSelf = true, ApplyTransform = IncludeTransform) const; - virtual int rightmostPosition(bool includeOverflowInterior = true, bool includeSelf = true, ApplyTransform = IncludeTransform) const; - virtual int leftmostPosition(bool includeOverflowInterior = true, bool includeSelf = true, ApplyTransform = IncludeTransform) const; - virtual IntRect clippedOverflowRectForRepaint(RenderBoxModelObject* repaintContainer); virtual void computeRectForRepaint(RenderBoxModelObject* repaintContainer, IntRect&, bool fixed = false); @@ -323,6 +312,7 @@ public: int horizontalScrollbarHeight() const; int scrollbarLogicalHeight() const { return style()->isHorizontalWritingMode() ? horizontalScrollbarHeight() : verticalScrollbarWidth(); } virtual bool scroll(ScrollDirection, ScrollGranularity, float multiplier = 1, Node** stopNode = 0); + virtual bool logicalScroll(ScrollLogicalDirection, ScrollGranularity, float multiplier = 1, Node** stopNode = 0); bool canBeScrolledAndHasScrollableArea() const; virtual bool canBeProgramaticallyScrolled(bool) const; virtual void autoscroll(); @@ -367,6 +357,8 @@ public: void removeFloatingOrPositionedChildFromBlockLists(); + RenderLayer* enclosingFloatPaintingLayer() const; + virtual int firstLineBoxBaseline() const { return -1; } virtual int lastLineBoxBaseline() const { return -1; } @@ -388,9 +380,16 @@ public: void flipForWritingMode(IntRect&) const; IntSize locationOffsetIncludingFlipping() const; +<<<<<<< HEAD #ifdef ANDROID_LAYOUT int getVisibleWidth() const { return m_visibleWidth; } #endif +======= + IntRect logicalVisualOverflowRectForPropagation(RenderStyle*) const; + IntRect visualOverflowRectForPropagation(RenderStyle*) const; + IntRect logicalLayoutOverflowRectForPropagation(RenderStyle*) const; + IntRect layoutOverflowRectForPropagation(RenderStyle*) const; +>>>>>>> webkit.org at r74534 (trunk) protected: virtual void styleWillChange(StyleDifference, const RenderStyle* newStyle); diff --git a/WebCore/rendering/RenderBoxModelObject.cpp b/WebCore/rendering/RenderBoxModelObject.cpp index 143c72c..f985a20 100644 --- a/WebCore/rendering/RenderBoxModelObject.cpp +++ b/WebCore/rendering/RenderBoxModelObject.cpp @@ -671,10 +671,10 @@ void RenderBoxModelObject::paintFillLayerExtended(const PaintInfo& paintInfo, co if (isOpaqueRoot) { Color baseColor = view()->frameView()->baseBackgroundColor(); if (baseColor.alpha() > 0) { - context->save(); + CompositeOperator previousOperator = context->compositeOperation(); context->setCompositeOperation(CompositeCopy); context->fillRect(rect, baseColor, style()->colorSpace()); - context->restore(); + context->setCompositeOperation(previousOperator); } else context->clearRect(rect); } @@ -1064,7 +1064,6 @@ void RenderBoxModelObject::paintBorder(GraphicsContext* graphicsContext, int tx, graphicsContext->addRoundedRectClip(borderRect, topLeft, topRight, bottomLeft, bottomRight); graphicsContext->clipOutRoundedRect(innerBorderRect, innerTopLeft, innerTopRight, innerBottomLeft, innerBottomRight); roundedPath.addRoundedRect(borderRect, topLeft, topRight, bottomLeft, bottomRight); - graphicsContext->addPath(roundedPath); } } @@ -1805,13 +1804,10 @@ void RenderBoxModelObject::paintBoxShadow(GraphicsContext* context, int tx, int } else path.addRect(holeRect); - context->beginPath(); - context->addPath(path); - context->setFillRule(RULE_EVENODD); context->setFillColor(fillColor, s->colorSpace()); context->setShadow(shadowOffset, shadowBlur, shadowColor, s->colorSpace()); - context->fillPath(); + context->fillPath(path); context->restore(); } diff --git a/WebCore/rendering/RenderBoxModelObject.h b/WebCore/rendering/RenderBoxModelObject.h index 988d61a..b697217 100644 --- a/WebCore/rendering/RenderBoxModelObject.h +++ b/WebCore/rendering/RenderBoxModelObject.h @@ -45,6 +45,7 @@ public: int relativePositionOffsetX() const; int relativePositionOffsetY() const; IntSize relativePositionOffset() const { return IntSize(relativePositionOffsetX(), relativePositionOffsetY()); } + IntSize relativePositionLogicalOffset() const { return style()->isHorizontalWritingMode() ? relativePositionOffset() : relativePositionOffset().transposedSize(); } // IE extensions. Used to calculate offsetWidth/Height. Overridden by inlines (RenderFlow) // to return the remaining width on a given line (and the height of a single line). diff --git a/WebCore/rendering/RenderCounter.cpp b/WebCore/rendering/RenderCounter.cpp index c357be1..7e10440 100644 --- a/WebCore/rendering/RenderCounter.cpp +++ b/WebCore/rendering/RenderCounter.cpp @@ -136,11 +136,6 @@ static bool findPlaceForCounter(RenderObject* counterOwner, const AtomicString& RenderObject* currentRenderer = counterOwner->previousInPreOrder(); previousSibling = 0; while (currentRenderer) { - // A sibling without a parent means that the counter node tree was not constructed correctly so we stop - // traversing. In the future RenderCounter should handle RenderObjects that are not connected to the - // render tree at counter node creation. See bug 43812. - if (previousSibling && !previousSibling->parent()) - return false; CounterNode* currentCounter = makeCounterNode(currentRenderer, identifier, false); if (searchEndRenderer == currentRenderer) { // We may be at the end of our search. diff --git a/WebCore/rendering/RenderDetails.cpp b/WebCore/rendering/RenderDetails.cpp new file mode 100644 index 0000000..a1039f9 --- /dev/null +++ b/WebCore/rendering/RenderDetails.cpp @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#include "config.h" +#include "RenderDetails.h" + +namespace WebCore { + +RenderDetails::RenderDetails(Node* element) + : RenderBlock(element) +{ +} + +void RenderDetails::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle) +{ + RenderBlock::styleDidChange(diff, oldStyle); + + // Ensure that if we ended up being inline that we set our replaced flag + // so that we're treated like an inline-block. + setReplaced(isInline()); +} + +} diff --git a/WebCore/rendering/RenderDetails.h b/WebCore/rendering/RenderDetails.h new file mode 100644 index 0000000..b8aebab --- /dev/null +++ b/WebCore/rendering/RenderDetails.h @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef RenderDetails_h +#define RenderDetails_h + +#include "RenderBlock.h" + +namespace WebCore { + +class RenderDetails : public RenderBlock { +public: + explicit RenderDetails(Node*); + +private: + virtual const char* renderName() const { return "RenderDetails"; } + virtual bool isDetails() const { return true; } + virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle); +}; + +inline RenderDetails* toRenderDetails(RenderObject* object) +{ + ASSERT(!object || object->isDetails()); + return static_cast<RenderDetails*>(object); +} + +// This will catch anyone doing an unnecessary cast. +void toRenderDetails(const RenderDetails*); + +} + +#endif // RenderDetails_h diff --git a/WebCore/rendering/RenderDetailsMarker.cpp b/WebCore/rendering/RenderDetailsMarker.cpp new file mode 100644 index 0000000..26e49d9 --- /dev/null +++ b/WebCore/rendering/RenderDetailsMarker.cpp @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#include "config.h" +#include "RenderDetailsMarker.h" + +namespace WebCore { + +RenderDetailsMarker::RenderDetailsMarker(Node* element) + : RenderBlock(element) +{ +} + +} diff --git a/WebCore/rendering/RenderDetailsMarker.h b/WebCore/rendering/RenderDetailsMarker.h new file mode 100644 index 0000000..08bdbd8 --- /dev/null +++ b/WebCore/rendering/RenderDetailsMarker.h @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef RenderDetailsMarker_h +#define RenderDetailsMarker_h + +#include "RenderBlock.h" + +namespace WebCore { + +class RenderDetailsMarker : public RenderBlock { +public: + explicit RenderDetailsMarker(Node*); + +private: + virtual const char* renderName() const { return "RenderDetailsMarker"; } + virtual bool isDetailsMarker() const { return true; } +}; + +inline RenderDetailsMarker* toRenderDetailsMarker(RenderObject* object) +{ + ASSERT(!object || object->isDetails()); + return static_cast<RenderDetailsMarker*>(object); +} + +// This will catch anyone doing an unnecessary cast. +void toRenderDetailsMarker(const RenderDetailsMarker*); + +} + +#endif // RenderDetailsMarker_h + diff --git a/WebCore/rendering/RenderEmbeddedObject.cpp b/WebCore/rendering/RenderEmbeddedObject.cpp index 16613a5..294ffec 100644 --- a/WebCore/rendering/RenderEmbeddedObject.cpp +++ b/WebCore/rendering/RenderEmbeddedObject.cpp @@ -166,11 +166,9 @@ void RenderEmbeddedObject::paintReplaced(PaintInfo& paintInfo, int tx, int ty) context->save(); context->clip(contentRect); - context->beginPath(); - context->addPath(path); context->setAlpha(m_missingPluginIndicatorIsPressed ? replacementTextPressedRoundedRectOpacity : replacementTextRoundedRectOpacity); context->setFillColor(m_missingPluginIndicatorIsPressed ? replacementTextRoundedRectPressedColor() : Color::white, style()->colorSpace()); - context->fillPath(); + context->fillPath(path); float labelX = roundf(replacementTextRect.location().x() + (replacementTextRect.size().width() - textWidth) / 2); float labelY = roundf(replacementTextRect.location().y() + (replacementTextRect.size().height() - font.height()) / 2 + font.ascent()); @@ -223,6 +221,8 @@ void RenderEmbeddedObject::layout() m_overflow.clear(); addShadowOverflow(); + updateLayerTransform(); + if (!widget() && frameView()) frameView()->addWidgetToUpdate(this); diff --git a/WebCore/rendering/RenderFileUploadControl.cpp b/WebCore/rendering/RenderFileUploadControl.cpp index 82bd1fa..3c10f43 100644 --- a/WebCore/rendering/RenderFileUploadControl.cpp +++ b/WebCore/rendering/RenderFileUploadControl.cpp @@ -100,14 +100,14 @@ bool RenderFileUploadControl::allowsMultipleFiles() #endif HTMLInputElement* input = static_cast<HTMLInputElement*>(node()); - return !input->getAttribute(multipleAttr).isNull(); + return input->fastHasAttribute(multipleAttr); } #if ENABLE(DIRECTORY_UPLOAD) bool RenderFileUploadControl::allowsDirectoryUpload() { HTMLInputElement* input = static_cast<HTMLInputElement*>(node()); - return !input->getAttribute(webkitdirectoryAttr).isNull(); + return input->fastHasAttribute(webkitdirectoryAttr); } #endif diff --git a/WebCore/rendering/RenderFlexibleBox.cpp b/WebCore/rendering/RenderFlexibleBox.cpp index 841442b..5d96adb 100644 --- a/WebCore/rendering/RenderFlexibleBox.cpp +++ b/WebCore/rendering/RenderFlexibleBox.cpp @@ -185,6 +185,13 @@ void RenderFlexibleBox::computePreferredLogicalWidths() m_maxPreferredLogicalWidth = max(m_minPreferredLogicalWidth, m_maxPreferredLogicalWidth); } + if (hasOverflowClip() && style()->overflowY() == OSCROLL) { + layer()->setHasVerticalScrollbar(true); + int scrollbarWidth = verticalScrollbarWidth(); + m_maxPreferredLogicalWidth += scrollbarWidth; + m_minPreferredLogicalWidth += scrollbarWidth; + } + if (style()->minWidth().isFixed() && style()->minWidth().value() > 0) { m_maxPreferredLogicalWidth = max(m_maxPreferredLogicalWidth, computeContentBoxLogicalWidth(style()->minWidth().value())); m_minPreferredLogicalWidth = max(m_minPreferredLogicalWidth, computeContentBoxLogicalWidth(style()->minWidth().value())); @@ -195,13 +202,9 @@ void RenderFlexibleBox::computePreferredLogicalWidths() m_minPreferredLogicalWidth = min(m_minPreferredLogicalWidth, computeContentBoxLogicalWidth(style()->maxWidth().value())); } - int toAdd = borderAndPaddingWidth(); - - if (hasOverflowClip() && style()->overflowY() == OSCROLL) - toAdd += verticalScrollbarWidth(); - - m_minPreferredLogicalWidth += toAdd; - m_maxPreferredLogicalWidth += toAdd; + int borderAndPadding = borderAndPaddingLogicalWidth(); + m_minPreferredLogicalWidth += borderAndPadding; + m_maxPreferredLogicalWidth += borderAndPadding; setPreferredLogicalWidthsDirty(false); } @@ -251,6 +254,7 @@ void RenderFlexibleBox::layoutBlock(bool relayoutChildren, int /*pageHeight FIXM else layoutVerticalBox(relayoutChildren); + int oldClientAfterEdge = clientLogicalBottom(); computeLogicalHeight(); if (previousHeight != height()) @@ -276,18 +280,14 @@ void RenderFlexibleBox::layoutBlock(bool relayoutChildren, int /*pageHeight FIXM setMaxMarginAfterValues(0, 0); } - // Add in the overflow from children. - FlexBoxIterator iterator(this); - for (RenderBox* child = iterator.first(); child; child = iterator.next()) - addOverflowFromChild(child); - - // Add visual overflow from box-shadow and reflections. - addShadowOverflow(); + computeOverflow(oldClientAfterEdge); statePusher.pop(); - if (view()->layoutState()->m_pageHeight) - setPageY(view()->layoutState()->pageY(y())); + updateLayerTransform(); + + if (view()->layoutState()->pageLogicalHeight()) + setPageLogicalOffset(view()->layoutState()->pageLogicalOffset(y())); // Update our scrollbars if we're overflow:auto/scroll/hidden now that we know if // we overflow or not. diff --git a/WebCore/rendering/RenderIFrame.cpp b/WebCore/rendering/RenderIFrame.cpp index 19bca49..01b8a17 100644 --- a/WebCore/rendering/RenderIFrame.cpp +++ b/WebCore/rendering/RenderIFrame.cpp @@ -119,6 +119,7 @@ void RenderIFrame::layout() m_overflow.clear(); addShadowOverflow(); + updateLayerTransform(); setNeedsLayout(false); } diff --git a/WebCore/rendering/RenderImage.cpp b/WebCore/rendering/RenderImage.cpp index 282eef3..44e0de7 100644 --- a/WebCore/rendering/RenderImage.cpp +++ b/WebCore/rendering/RenderImage.cpp @@ -215,7 +215,7 @@ void RenderImage::imageDimensionsChanged(bool imageSizeChanged, const IntRect* r #if USE(ACCELERATED_COMPOSITING) if (hasLayer()) { // Tell any potential compositing layers that the image needs updating. - layer()->rendererContentChanged(); + layer()->contentChanged(RenderLayer::ImageChanged); } #endif } @@ -233,7 +233,7 @@ void RenderImage::notifyFinished(CachedResource* newImage) if (newImage == m_imageResource->cachedImage() && hasLayer()) { // tell any potential compositing layers // that the image is done and they can reference it directly. - layer()->rendererContentChanged(); + layer()->contentChanged(RenderLayer::ImageChanged); } #else UNUSED_PARAM(newImage); @@ -367,8 +367,9 @@ void RenderImage::paintFocusRing(PaintInfo& paintInfo, const RenderStyle* style) HTMLAreaElement* areaElement = static_cast<HTMLAreaElement*>(areas->item(k)); if (focusedNode != areaElement) continue; - - paintInfo.context->drawFocusRing(areaElement->getPath(this), style->outlineWidth(), style->outlineOffset(), style->visitedDependentColor(CSSPropertyOutlineColor)); + + RenderStyle* styleToUse = areaElement->computedStyle(); + paintInfo.context->drawFocusRing(areaElement->getPath(this), styleToUse->outlineWidth(), styleToUse->outlineOffset(), styleToUse->visitedDependentColor(CSSPropertyOutlineColor)); break; } } diff --git a/WebCore/rendering/RenderInline.cpp b/WebCore/rendering/RenderInline.cpp index 8f828f9..4b5298c 100644 --- a/WebCore/rendering/RenderInline.cpp +++ b/WebCore/rendering/RenderInline.cpp @@ -579,7 +579,7 @@ IntRect RenderInline::linesBoundingBox() const return result; } -IntRect RenderInline::linesVisibleOverflowBoundingBox() const +IntRect RenderInline::linesVisualOverflowBoundingBox() const { if (!firstLineBox() || !lastLineBox()) return IntRect(); @@ -588,16 +588,16 @@ IntRect RenderInline::linesVisibleOverflowBoundingBox() const int logicalLeftSide = numeric_limits<int>::max(); int logicalRightSide = numeric_limits<int>::min(); for (InlineFlowBox* curr = firstLineBox(); curr; curr = curr->nextLineBox()) { - logicalLeftSide = min(logicalLeftSide, curr->logicalLeftVisibleOverflow()); - logicalRightSide = max(logicalRightSide, curr->logicalRightVisibleOverflow()); + logicalLeftSide = min(logicalLeftSide, curr->logicalLeftVisualOverflow()); + logicalRightSide = max(logicalRightSide, curr->logicalRightVisualOverflow()); } bool isHorizontal = style()->isHorizontalWritingMode(); - int x = isHorizontal ? logicalLeftSide : firstLineBox()->leftVisibleOverflow(); - int y = isHorizontal ? firstLineBox()->topVisibleOverflow() : logicalLeftSide; - int width = isHorizontal ? logicalRightSide - logicalLeftSide : lastLineBox()->rightVisibleOverflow() - firstLineBox()->leftVisibleOverflow(); - int height = isHorizontal ? lastLineBox()->bottomVisibleOverflow() - firstLineBox()->topVisibleOverflow() : logicalRightSide - logicalLeftSide; + int x = isHorizontal ? logicalLeftSide : firstLineBox()->leftVisualOverflow(); + int y = isHorizontal ? firstLineBox()->topVisualOverflow() : logicalLeftSide; + int width = isHorizontal ? logicalRightSide - logicalLeftSide : lastLineBox()->rightVisualOverflow() - firstLineBox()->leftVisualOverflow(); + int height = isHorizontal ? lastLineBox()->bottomVisualOverflow() - firstLineBox()->topVisualOverflow() : logicalRightSide - logicalLeftSide; return IntRect(x, y, width, height); } @@ -610,7 +610,7 @@ IntRect RenderInline::clippedOverflowRectForRepaint(RenderBoxModelObject* repain return IntRect(); // Find our leftmost position. - IntRect boundingBox(linesVisibleOverflowBoundingBox()); + IntRect boundingBox(linesVisualOverflowBoundingBox()); int left = boundingBox.x(); int top = boundingBox.y(); diff --git a/WebCore/rendering/RenderInline.h b/WebCore/rendering/RenderInline.h index 399a167..f6f3908 100644 --- a/WebCore/rendering/RenderInline.h +++ b/WebCore/rendering/RenderInline.h @@ -53,7 +53,7 @@ public: virtual IntSize offsetFromContainer(RenderObject*, const IntPoint&) const; IntRect linesBoundingBox() const; - IntRect linesVisibleOverflowBoundingBox() const; + IntRect linesVisualOverflowBoundingBox() const; InlineFlowBox* createAndAppendInlineFlowBox(); diff --git a/WebCore/rendering/RenderLayer.cpp b/WebCore/rendering/RenderLayer.cpp index 62ddaac..2eab3c6 100644 --- a/WebCore/rendering/RenderLayer.cpp +++ b/WebCore/rendering/RenderLayer.cpp @@ -146,8 +146,8 @@ RenderLayer::RenderLayer(RenderBoxModelObject* renderer) , m_height(0) , m_scrollX(0) , m_scrollY(0) - , m_scrollOriginX(0) , m_scrollLeftOverflow(0) + , m_scrollTopOverflow(0) , m_scrollWidth(0) , m_scrollHeight(0) , m_inResizeMode(false) @@ -235,14 +235,14 @@ RenderLayerCompositor* RenderLayer::compositor() const return renderer()->view()->compositor(); } -void RenderLayer::rendererContentChanged() +void RenderLayer::contentChanged(ContentChangeType changeType) { // This can get called when video becomes accelerated, so the layers may change. - if (compositor()->updateLayerCompositingState(this)) + if ((changeType == CanvasChanged || changeType == VideoChanged) && compositor()->updateLayerCompositingState(this)) compositor()->setCompositingLayersNeedRebuild(); if (m_backing) - m_backing->rendererContentChanged(); + m_backing->contentChanged(changeType); } #endif // USE(ACCELERATED_COMPOSITING) @@ -325,8 +325,6 @@ void RenderLayer::updateLayerPositions(UpdateLayerPositionsFlags flags, IntPoint updateVisibilityStatus(); - updateTransform(); - if (flags & UpdatePagination) updatePagination(); else @@ -684,14 +682,6 @@ void RenderLayer::updateLayerPosition() } else if (RenderBox* box = renderBox()) { setWidth(box->width()); setHeight(box->height()); - - if (!box->hasOverflowClip()) { - if (box->rightLayoutOverflow() > box->width()) - setWidth(box->rightLayoutOverflow()); - if (box->bottomLayoutOverflow() > box->height()) - setHeight(box->bottomLayoutOverflow()); - } - localPoint += box->locationOffsetIncludingFlipping(); } @@ -1356,11 +1346,12 @@ void RenderLayer::scrollToOffset(int x, int y, bool updateScrollbars, bool repai // complicated (since it will involve testing whether our layer // is either occluded by another layer or clipped by an enclosing // layer or contains fixed backgrounds, etc.). - int newScrollX = x - m_scrollOriginX; - if (m_scrollY == y && m_scrollX == newScrollX) + int newScrollX = x - m_scrollOrigin.x(); + int newScrollY = y - m_scrollOrigin.y(); + if (m_scrollY == newScrollY && m_scrollX == newScrollX) return; m_scrollX = newScrollX; - m_scrollY = y; + m_scrollY = newScrollY; // Update the positions of our child layers. Don't have updateLayerPositions() update // compositing layers, because we need to do a deep update from the compositing ancestor. @@ -2012,34 +2003,57 @@ int RenderLayer::scrollHeight() return m_scrollHeight; } +int RenderLayer::overflowTop() const +{ + RenderBox* box = renderBox(); + IntRect overflowRect(box->layoutOverflowRect()); + box->flipForWritingMode(overflowRect); + return overflowRect.y(); +} + +int RenderLayer::overflowBottom() const +{ + RenderBox* box = renderBox(); + IntRect overflowRect(box->layoutOverflowRect()); + box->flipForWritingMode(overflowRect); + return overflowRect.bottom(); +} + +int RenderLayer::overflowLeft() const +{ + RenderBox* box = renderBox(); + IntRect overflowRect(box->layoutOverflowRect()); + box->flipForWritingMode(overflowRect); + return overflowRect.x(); +} + +int RenderLayer::overflowRight() const +{ + RenderBox* box = renderBox(); + IntRect overflowRect(box->layoutOverflowRect()); + box->flipForWritingMode(overflowRect); + return overflowRect.right(); +} + void RenderLayer::computeScrollDimensions(bool* needHBar, bool* needVBar) { RenderBox* box = renderBox(); ASSERT(box); m_scrollDimensionsDirty = false; - - bool ltr = renderer()->style()->isLeftToRightDirection(); - - int clientWidth = box->clientWidth(); - int clientHeight = box->clientHeight(); - m_scrollLeftOverflow = ltr ? 0 : min(0, box->leftmostPosition(true, false) - box->borderLeft()); + m_scrollLeftOverflow = overflowLeft() - box->borderLeft(); + m_scrollTopOverflow = overflowTop() - box->borderTop(); - int rightPos = ltr ? - box->rightmostPosition(true, false) - box->borderLeft() : - clientWidth - m_scrollLeftOverflow; - int bottomPos = box->lowestPosition(true, false) - box->borderTop(); - - m_scrollWidth = max(rightPos, clientWidth); - m_scrollHeight = max(bottomPos, clientHeight); + m_scrollWidth = overflowRight() - overflowLeft(); + m_scrollHeight = overflowBottom() - overflowTop(); - m_scrollOriginX = ltr ? 0 : m_scrollWidth - clientWidth; + m_scrollOrigin = IntPoint(-m_scrollLeftOverflow, -m_scrollTopOverflow); if (needHBar) - *needHBar = rightPos > clientWidth; + *needHBar = m_scrollWidth > box->clientWidth(); if (needVBar) - *needVBar = bottomPos > clientHeight; + *needVBar = m_scrollHeight > box->clientHeight(); } void RenderLayer::updateOverflowStatus(bool horizontalOverflow, bool verticalOverflow) @@ -2048,7 +2062,6 @@ void RenderLayer::updateOverflowStatus(bool horizontalOverflow, bool verticalOve m_horizontalOverflow = horizontalOverflow; m_verticalOverflow = verticalOverflow; m_overflowStatusDirty = false; - return; } @@ -2135,9 +2148,12 @@ RenderLayer::updateScrollInfoAfterLayout() // Our proprietary overflow: overlay value doesn't trigger a layout. m_inOverflowRelayout = true; renderer()->setNeedsLayout(true, false); - if (renderer()->isRenderBlock()) - toRenderBlock(renderer())->layoutBlock(true); - else + if (renderer()->isRenderBlock()) { + RenderBlock* block = toRenderBlock(renderer()); + block->scrollbarsChanged(box->hasAutoHorizontalScrollbar() && haveHorizontalBar != horizontalOverflow, + box->hasAutoVerticalScrollbar() && haveVerticalBar != verticalOverflow); + block->layoutBlock(true); + } else renderer()->layout(); m_inOverflowRelayout = false; } @@ -2161,9 +2177,7 @@ RenderLayer::updateScrollInfoAfterLayout() // top right corner of the content doesn't shift with respect to the top // right corner of the area. Conceptually, right-to-left areas have // their origin at the top-right, but RenderLayer is top-left oriented, - // so this is needed to keep everything working (see how scrollXOffset() - // differs from scrollYOffset() to get an idea of why the horizontal and - // vertical scrollbars need to be treated differently). + // so this is needed to keep everything working. m_hBar->setValue(scrollXOffset(), Scrollbar::NotFromScrollAnimator); } if (m_vBar) { @@ -2171,6 +2185,13 @@ RenderLayer::updateScrollInfoAfterLayout() int pageStep = max(max<int>(clientHeight * Scrollbar::minFractionToStepWhenPaging(), clientHeight - Scrollbar::maxOverlapBetweenPages()), 1); m_vBar->setSteps(Scrollbar::pixelsPerLineStep(), pageStep); m_vBar->setProportion(clientHeight, m_scrollHeight); + // Explicitly set the vertical scroll value. This ensures that when a + // right-to-left vertical writing-mode scrollable area's height (or content height) changes, the + // bottom right corner of the content doesn't shift with respect to the bottom + // right corner of the area. Conceptually, right-to-left vertical writing-mode areas have + // their origin at the bottom-right, but RenderLayer is top-left oriented, + // so this is needed to keep everything working. + m_vBar->setValue(scrollYOffset(), Scrollbar::NotFromScrollAnimator); } if (renderer()->node() && renderer()->document()->hasListenerType(Document::OVERFLOWCHANGED_LISTENER)) @@ -2343,14 +2364,9 @@ bool RenderLayer::scroll(ScrollDirection direction, ScrollGranularity granularit { bool didHorizontalScroll = false; bool didVerticalScroll = false; - - if (m_hBar) { - // Special-case for the ScrollByDocument granularity. A document scroll - // can only be up or down and in both cases the horizontal bar goes all - // the way to the left. - didHorizontalScroll = m_hBar->scroll((granularity == ScrollByDocument) ? ScrollLeft : direction, granularity, multiplier); - } + if (m_hBar) + didHorizontalScroll = m_hBar->scroll(direction, granularity, multiplier); if (m_vBar) didVerticalScroll = m_vBar->scroll(direction, granularity, multiplier); @@ -2381,12 +2397,13 @@ static void restoreClip(GraphicsContext* p, const IntRect& paintDirtyRect, const p->restore(); } -static void performOverlapTests(OverlapTestRequestMap& overlapTestRequests, const IntRect& layerBounds) +static void performOverlapTests(OverlapTestRequestMap& overlapTestRequests, const RenderLayer* rootLayer, const RenderLayer* layer) { Vector<OverlapTestRequestClient*> overlappedRequestClients; OverlapTestRequestMap::iterator end = overlapTestRequests.end(); + IntRect boundingBox = layer->boundingBox(rootLayer); for (OverlapTestRequestMap::iterator it = overlapTestRequests.begin(); it != end; ++it) { - if (!layerBounds.intersects(it->second)) + if (!boundingBox.intersects(it->second)) continue; it->first->setOverlapTestResult(true); @@ -2513,7 +2530,7 @@ void RenderLayer::paintLayer(RenderLayer* rootLayer, GraphicsContext* p, paintingRootForRenderer = paintingRoot; if (overlapTestRequests && isSelfPaintingLayer()) - performOverlapTests(*overlapTestRequests, layerBounds); + performOverlapTests(*overlapTestRequests, rootLayer, this); // We want to paint our layer, but only if we intersect the damage rect. bool shouldPaint = intersectsDamageRect(layerBounds, damageRect, rootLayer) && m_hasVisibleContent && isSelfPaintingLayer(); @@ -2728,11 +2745,11 @@ bool RenderLayer::hitTest(const HitTestRequest& request, HitTestResult& result) { renderer()->document()->updateLayout(); - IntRect boundsRect(m_x, m_y, width(), height()); + IntRect hitTestArea = result.rectForPoint(result.point()); if (!request.ignoreClipping()) - boundsRect.intersect(frameVisibleRect(renderer())); + hitTestArea.intersect(frameVisibleRect(renderer())); - RenderLayer* insideLayer = hitTestLayer(this, 0, request, result, boundsRect, result.point(), false); + RenderLayer* insideLayer = hitTestLayer(this, 0, request, result, hitTestArea, result.point(), false); if (!insideLayer) { // We didn't hit any layer. If we are the root layer and the mouse is -- or just was -- down, // return ourselves. We do this so mouse events continue getting delivered after a drag has @@ -3377,19 +3394,19 @@ void RenderLayer::calculateRects(const RenderLayer* rootLayer, const IntRect& pa IntRect RenderLayer::childrenClipRect() const { - RenderLayer* rootLayer = renderer()->view()->layer(); + RenderView* renderView = renderer()->view(); RenderLayer* clippingRootLayer = clippingRoot(); IntRect layerBounds, backgroundRect, foregroundRect, outlineRect; - calculateRects(clippingRootLayer, rootLayer->boundingBox(rootLayer), layerBounds, backgroundRect, foregroundRect, outlineRect); + calculateRects(clippingRootLayer, renderView->documentRect(), layerBounds, backgroundRect, foregroundRect, outlineRect); return clippingRootLayer->renderer()->localToAbsoluteQuad(FloatQuad(foregroundRect)).enclosingBoundingBox(); } IntRect RenderLayer::selfClipRect() const { - RenderLayer* rootLayer = renderer()->view()->layer(); + RenderView* renderView = renderer()->view(); RenderLayer* clippingRootLayer = clippingRoot(); IntRect layerBounds, backgroundRect, foregroundRect, outlineRect; - calculateRects(clippingRootLayer, rootLayer->boundingBox(rootLayer), layerBounds, backgroundRect, foregroundRect, outlineRect); + calculateRects(clippingRootLayer, renderView->documentRect(), layerBounds, backgroundRect, foregroundRect, outlineRect); return clippingRootLayer->renderer()->localToAbsoluteQuad(FloatQuad(backgroundRect)).enclosingBoundingBox(); } @@ -3465,8 +3482,8 @@ IntRect RenderLayer::localBoundingBox() const InlineFlowBox* firstBox = inlineFlow->firstLineBox(); if (!firstBox) return result; - int top = firstBox->topVisibleOverflow(); - int bottom = inlineFlow->lastLineBox()->bottomVisibleOverflow(); + int top = firstBox->topVisualOverflow(); + int bottom = inlineFlow->lastLineBox()->bottomVisualOverflow(); int left = firstBox->x(); for (InlineFlowBox* curr = firstBox->nextLineBox(); curr; curr = curr->nextLineBox()) left = min(left, curr->x()); @@ -3477,7 +3494,7 @@ IntRect RenderLayer::localBoundingBox() const if (child->isTableCell()) { IntRect bbox = toRenderBox(child)->borderBoxRect(); result.unite(bbox); - IntRect overflowRect = renderBox()->visibleOverflowRect(); + IntRect overflowRect = renderBox()->visualOverflowRect(); if (bbox != overflowRect) result.unite(overflowRect); } @@ -3490,7 +3507,7 @@ IntRect RenderLayer::localBoundingBox() const else { IntRect bbox = box->borderBoxRect(); result = bbox; - IntRect overflowRect = box->visibleOverflowRect(); + IntRect overflowRect = box->visualOverflowRect(); if (bbox != overflowRect) result.unite(overflowRect); } diff --git a/WebCore/rendering/RenderLayer.h b/WebCore/rendering/RenderLayer.h index 711d398..53cfc21 100644 --- a/WebCore/rendering/RenderLayer.h +++ b/WebCore/rendering/RenderLayer.h @@ -260,14 +260,14 @@ public: // Scrolling methods for layers that can scroll their overflow. void scrollByRecursively(int xDelta, int yDelta); - IntSize scrolledContentOffset() const { return IntSize(scrollXOffset() + m_scrollLeftOverflow, scrollYOffset()); } + IntSize scrolledContentOffset() const { return IntSize(scrollXOffset() + m_scrollLeftOverflow, scrollYOffset() + m_scrollTopOverflow); } - int scrollXOffset() const { return m_scrollX + m_scrollOriginX; } - int scrollYOffset() const { return m_scrollY; } + int scrollXOffset() const { return m_scrollX + m_scrollOrigin.x(); } + int scrollYOffset() const { return m_scrollY + m_scrollOrigin.y(); } void scrollToOffset(int x, int y, bool updateScrollbars = true, bool repaint = true); - void scrollToXOffset(int x) { scrollToOffset(x, m_scrollY); } - void scrollToYOffset(int y) { scrollToOffset(m_scrollX + m_scrollOriginX, y); } + void scrollToXOffset(int x) { scrollToOffset(x, m_scrollY + m_scrollOrigin.y()); } + void scrollToYOffset(int y) { scrollToOffset(m_scrollX + m_scrollOrigin.x(), y); } void scrollRectToVisible(const IntRect&, bool scrollToAnchor = false, const ScrollAlignment& alignX = ScrollAlignment::alignCenterIfNeeded, const ScrollAlignment& alignY = ScrollAlignment::alignCenterIfNeeded); IntRect getRectToExpose(const IntRect& visibleRect, const IntRect& exposeRect, const ScrollAlignment& alignX, const ScrollAlignment& alignY); @@ -314,7 +314,8 @@ public: // Notification from the renderer that its content changed (e.g. current frame of image changed). // Allows updates of layer content without repainting. - void rendererContentChanged(); + enum ContentChangeType { ImageChanged, MaskImageChanged, CanvasChanged, VideoChanged }; + void contentChanged(ContentChangeType); #endif // Returns true if the accelerated compositing is enabled @@ -628,6 +629,11 @@ private: // Only safe to call from RenderBoxModelObject::destroyLayer(RenderArena*) void destroy(RenderArena*); + int overflowTop() const; + int overflowBottom() const; + int overflowLeft() const; + int overflowRight() const; + protected: RenderBoxModelObject* m_renderer; @@ -655,9 +661,22 @@ protected: // Our scroll offsets if the view is scrolled. int m_scrollX; int m_scrollY; - int m_scrollOriginX; // only non-zero for rtl content - int m_scrollLeftOverflow; // only non-zero for rtl content - + + // There are 8 possible combinations of writing mode and direction. Scroll origin (and its corresponding left/top overflow) + // will be non-zero in the x or y axis if there is any reversed direction or writing-mode. The combinations are: + // writing-mode / direction scrollOrigin.x() set scrollOrigin.y() set + // horizontal-tb / ltr NO NO + // horizontal-tb / rtl YES NO + // horizontal-bt / ltr NO YES + // horizontal-bt / rtl YES YES + // vertical-lr / ltr NO NO + // vertical-lr / rtl NO YES + // vertical-rl / ltr YES NO + // vertical-rl / rtl YES YES + IntPoint m_scrollOrigin; + int m_scrollLeftOverflow; + int m_scrollTopOverflow; + // The width/height of our scrolled area. int m_scrollWidth; int m_scrollHeight; diff --git a/WebCore/rendering/RenderLayerBacking.cpp b/WebCore/rendering/RenderLayerBacking.cpp index 0d39f7a..a2af9ca 100644 --- a/WebCore/rendering/RenderLayerBacking.cpp +++ b/WebCore/rendering/RenderLayerBacking.cpp @@ -374,7 +374,10 @@ void RenderLayerBacking::updateGraphicsLayerGeometry() } if (m_maskLayer) { - m_maskLayer->setSize(m_graphicsLayer->size()); + if (m_maskLayer->size() != m_graphicsLayer->size()) { + m_maskLayer->setSize(m_graphicsLayer->size()); + m_maskLayer->setNeedsDisplay(); + } m_maskLayer->setPosition(FloatPoint()); } @@ -767,7 +770,8 @@ bool RenderLayerBacking::containsPaintedContent() const if (renderer()->isVideo() && toRenderVideo(renderer())->shouldDisplayVideo()) return hasBoxDecorationsOrBackground(renderer()); #endif -#if ENABLE(3D_CANVAS) || ENABLE(ACCELERATED_2D_CANVAS) +#if PLATFORM(MAC) && PLATFORM(CA) && !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD) +#elif ENABLE(3D_CANVAS) || ENABLE(ACCELERATED_2D_CANVAS) if (isAcceleratedCanvas(renderer())) return hasBoxDecorationsOrBackground(renderer()); #endif @@ -793,15 +797,22 @@ bool RenderLayerBacking::isDirectlyCompositedImage() const return false; } -void RenderLayerBacking::rendererContentChanged() +void RenderLayerBacking::contentChanged(RenderLayer::ContentChangeType changeType) { - if (isDirectlyCompositedImage()) { + if ((changeType == RenderLayer::ImageChanged) && isDirectlyCompositedImage()) { updateImageContents(); return; } + + if ((changeType == RenderLayer::MaskImageChanged) && m_maskLayer) { + // The composited layer bounds relies on box->maskClipRect(), which changes + // when the mask image becomes available. + bool isUpdateRoot = true; + updateAfterLayout(CompositingChildren, isUpdateRoot); + } #if ENABLE(3D_CANVAS) || ENABLE(ACCELERATED_2D_CANVAS) - if (isAcceleratedCanvas(renderer())) { + if ((changeType == RenderLayer::CanvasChanged) && isAcceleratedCanvas(renderer())) { m_graphicsLayer->setContentsNeedsDisplay(); return; } @@ -900,7 +911,7 @@ FloatPoint RenderLayerBacking::contentsToGraphicsLayerCoordinates(const Graphics bool RenderLayerBacking::paintingGoesToWindow() const { if (m_owningLayer->isRootLayer()) - return compositor()->rootLayerAttachment() != RenderLayerCompositor::RootLayerAttachedViaEnclosingIframe; + return !m_owningLayer->hasTransform() && (compositor()->rootLayerAttachment() != RenderLayerCompositor::RootLayerAttachedViaEnclosingIframe); return false; } @@ -1150,20 +1161,20 @@ bool RenderLayerBacking::startAnimation(double timeOffset, const Animation* anim opacityVector.insert(new FloatAnimationValue(key, keyframeStyle->opacity(), tf)); } - bool didAnimateTransform = !hasTransform; - bool didAnimateOpacity = !hasOpacity; + bool didAnimateTransform = false; + bool didAnimateOpacity = false; - if (hasTransform && m_graphicsLayer->addAnimation(transformVector, toRenderBox(renderer())->borderBoxRect().size(), anim, keyframes.animationName(), timeOffset)) + if (hasTransform && m_graphicsLayer->addAnimation(transformVector, toRenderBox(renderer())->borderBoxRect().size(), anim, keyframes.animationName(), timeOffset)) { didAnimateTransform = true; + compositor()->didStartAcceleratedAnimation(CSSPropertyWebkitTransform); + } - if (hasOpacity && m_graphicsLayer->addAnimation(opacityVector, IntSize(), anim, keyframes.animationName(), timeOffset)) + if (hasOpacity && m_graphicsLayer->addAnimation(opacityVector, IntSize(), anim, keyframes.animationName(), timeOffset)) { didAnimateOpacity = true; - - bool runningAcceleratedAnimation = didAnimateTransform && didAnimateOpacity; - if (runningAcceleratedAnimation) - compositor()->didStartAcceleratedAnimation(); + compositor()->didStartAcceleratedAnimation(CSSPropertyOpacity); + } - return runningAcceleratedAnimation; + return didAnimateTransform || didAnimateOpacity; } void RenderLayerBacking::animationPaused(double timeOffset, const String& animationName) @@ -1178,7 +1189,8 @@ void RenderLayerBacking::animationFinished(const String& animationName) bool RenderLayerBacking::startTransition(double timeOffset, int property, const RenderStyle* fromStyle, const RenderStyle* toStyle) { - bool didAnimate = false; + bool didAnimateOpacity = false; + bool didAnimateTransform = false; ASSERT(property != cAnimateAll); if (property == (int)CSSPropertyOpacity) { @@ -1191,7 +1203,7 @@ bool RenderLayerBacking::startTransition(double timeOffset, int property, const if (m_graphicsLayer->addAnimation(opacityVector, IntSize(), opacityAnim, GraphicsLayer::animationNameForTransition(AnimatedPropertyOpacity), timeOffset)) { // To ensure that the correct opacity is visible when the animation ends, also set the final opacity. updateLayerOpacity(toStyle); - didAnimate = true; + didAnimateOpacity = true; } } } @@ -1205,15 +1217,18 @@ bool RenderLayerBacking::startTransition(double timeOffset, int property, const if (m_graphicsLayer->addAnimation(transformVector, toRenderBox(renderer())->borderBoxRect().size(), transformAnim, GraphicsLayer::animationNameForTransition(AnimatedPropertyWebkitTransform), timeOffset)) { // To ensure that the correct transform is visible when the animation ends, also set the final opacity. updateLayerTransform(toStyle); - didAnimate = true; + didAnimateTransform = true; } } } - if (didAnimate) - compositor()->didStartAcceleratedAnimation(); + if (didAnimateOpacity) + compositor()->didStartAcceleratedAnimation(CSSPropertyOpacity); + + if (didAnimateTransform) + compositor()->didStartAcceleratedAnimation(CSSPropertyWebkitTransform); - return didAnimate; + return didAnimateOpacity || didAnimateTransform; } void RenderLayerBacking::transitionPaused(double timeOffset, int property) diff --git a/WebCore/rendering/RenderLayerBacking.h b/WebCore/rendering/RenderLayerBacking.h index fb3ab67..c5489f3 100644 --- a/WebCore/rendering/RenderLayerBacking.h +++ b/WebCore/rendering/RenderLayerBacking.h @@ -101,8 +101,8 @@ public: // r is in the coordinate space of the layer's render object void setContentsNeedDisplayInRect(const IntRect& r); - // Notification from the renderer that its content changed; used by RenderImage. - void rendererContentChanged(); + // Notification from the renderer that its content changed. + void contentChanged(RenderLayer::ContentChangeType); // Interface to start, finish, suspend and resume animations and transitions bool startTransition(double timeOffset, int property, const RenderStyle* fromStyle, const RenderStyle* toStyle); diff --git a/WebCore/rendering/RenderLayerCompositor.cpp b/WebCore/rendering/RenderLayerCompositor.cpp index c0dba6f..7e0a92c 100644 --- a/WebCore/rendering/RenderLayerCompositor.cpp +++ b/WebCore/rendering/RenderLayerCompositor.cpp @@ -310,6 +310,14 @@ bool RenderLayerCompositor::updateBacking(RenderLayer* layer, CompositingChangeR repaintOnCompositingChange(layer); layer->ensureBacking(); + +#if PLATFORM(MAC) && PLATFORM(CA) + if (layer->renderer()->isCanvas()) { + HTMLCanvasElement* canvas = static_cast<HTMLCanvasElement*>(layer->renderer()->node()); + if (canvas->renderingContext() && canvas->renderingContext()->isAccelerated()) + layer->backing()->graphicsLayer()->setAcceleratesDrawing(true); + } +#endif layerChanged = true; } } else { @@ -1108,18 +1116,19 @@ void RenderLayerCompositor::willMoveOffscreen() void RenderLayerCompositor::updateRootLayerPosition() { - // Eventually we will need to account for scrolling here. - // https://bugs.webkit.org/show_bug.cgi?id=38518 - if (m_rootPlatformLayer) - m_rootPlatformLayer->setSize(FloatSize(m_renderView->rightLayoutOverflow(), m_renderView->bottomLayoutOverflow())); + if (m_rootPlatformLayer) { + m_rootPlatformLayer->setSize(FloatSize(m_renderView->docWidth(), m_renderView->docHeight())); + m_rootPlatformLayer->setPosition(FloatPoint(m_renderView->docLeft(), m_renderView->docTop())); + } } -void RenderLayerCompositor::didStartAcceleratedAnimation() +void RenderLayerCompositor::didStartAcceleratedAnimation(CSSPropertyID property) { // If an accelerated animation or transition runs, we have to turn off overlap checking because // we don't do layout for every frame, but we have to ensure that the layering is // correct between the animating object and other objects on the page. - setCompositingConsultsOverlap(false); + if (property == CSSPropertyWebkitTransform) + setCompositingConsultsOverlap(false); } bool RenderLayerCompositor::has3DContent() const diff --git a/WebCore/rendering/RenderLayerCompositor.h b/WebCore/rendering/RenderLayerCompositor.h index a2f51c0..2f01360 100644 --- a/WebCore/rendering/RenderLayerCompositor.h +++ b/WebCore/rendering/RenderLayerCompositor.h @@ -143,7 +143,7 @@ public: void didMoveOnscreen(); void willMoveOffscreen(); - void didStartAcceleratedAnimation(); + void didStartAcceleratedAnimation(CSSPropertyID); #if ENABLE(VIDEO) // Use by RenderVideo to ask if it should try to use accelerated compositing. diff --git a/WebCore/rendering/RenderLineBoxList.cpp b/WebCore/rendering/RenderLineBoxList.cpp index 3139fd5..85d7f18 100644 --- a/WebCore/rendering/RenderLineBoxList.cpp +++ b/WebCore/rendering/RenderLineBoxList.cpp @@ -176,10 +176,10 @@ bool RenderLineBoxList::anyLineIntersectsRect(RenderBoxModelObject* renderer, co // 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. - int firstLineTop = firstLineBox()->logicalTopVisibleOverflow(); + int firstLineTop = firstLineBox()->logicalTopVisualOverflow(); if (usePrintRect && !firstLineBox()->parent()) firstLineTop = min(firstLineTop, firstLineBox()->root()->lineTop()); - int lastLineBottom = lastLineBox()->logicalBottomVisibleOverflow(); + int lastLineBottom = lastLineBox()->logicalBottomVisualOverflow(); if (usePrintRect && !lastLineBox()->parent()) lastLineBottom = max(lastLineBottom, lastLineBox()->root()->lineBottom()); int logicalTop = firstLineTop - outlineSize; @@ -190,8 +190,8 @@ bool RenderLineBoxList::anyLineIntersectsRect(RenderBoxModelObject* renderer, co bool RenderLineBoxList::lineIntersectsDirtyRect(RenderBoxModelObject* renderer, InlineFlowBox* box, const PaintInfo& paintInfo, int tx, int ty) const { - int logicalTop = min(box->logicalTopVisibleOverflow(), box->root()->selectionTop()) - renderer->maximalOutlineSize(paintInfo.phase); - int logicalBottom = box->logicalBottomVisibleOverflow() + renderer->maximalOutlineSize(paintInfo.phase); + int logicalTop = min(box->logicalTopVisualOverflow(), box->root()->selectionTop()) - renderer->maximalOutlineSize(paintInfo.phase); + int logicalBottom = box->logicalBottomVisualOverflow() + renderer->maximalOutlineSize(paintInfo.phase); return rangeIntersectsRect(renderer, logicalTop, logicalBottom, paintInfo.rect, tx, ty); } @@ -230,8 +230,8 @@ void RenderLineBoxList::paint(RenderBoxModelObject* renderer, PaintInfo& paintIn // FIXME: This is the deprecated pagination model that is still needed // for embedded views inside AppKit. AppKit is incapable of paginating vertical // text pages, so we don't have to deal with vertical lines at all here. - int topForPaginationCheck = curr->topVisibleOverflow(); - int bottomForPaginationCheck = curr->bottomVisibleOverflow(); + int topForPaginationCheck = curr->topVisualOverflow(); + int bottomForPaginationCheck = curr->bottomVisualOverflow(); if (!curr->parent()) { // We're a root box. Use lineTop and lineBottom as well here. topForPaginationCheck = min(topForPaginationCheck, curr->root()->lineTop()); @@ -240,7 +240,7 @@ void RenderLineBoxList::paint(RenderBoxModelObject* renderer, PaintInfo& paintIn if (bottomForPaginationCheck - topForPaginationCheck <= v->printRect().height()) { if (ty + bottomForPaginationCheck > v->printRect().bottom()) { if (RootInlineBox* nextRootBox = curr->root()->nextRootBox()) - bottomForPaginationCheck = min(bottomForPaginationCheck, min(nextRootBox->topVisibleOverflow(), nextRootBox->lineTop())); + bottomForPaginationCheck = min(bottomForPaginationCheck, min(nextRootBox->topVisualOverflow(), nextRootBox->lineTop())); } if (ty + bottomForPaginationCheck > v->printRect().bottom()) { if (ty + topForPaginationCheck < v->truncatedAt()) @@ -292,7 +292,7 @@ bool RenderLineBoxList::hitTest(RenderBoxModelObject* renderer, const HitTestReq // 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 (rangeIntersectsRect(renderer, curr->logicalTopVisibleOverflow(), curr->logicalBottomVisibleOverflow(), rect, tx, ty)) { + if (rangeIntersectsRect(renderer, curr->logicalTopVisualOverflow(), curr->logicalBottomVisualOverflow(), rect, tx, ty)) { bool inside = curr->nodeAtPoint(request, result, x, y, tx, ty); if (inside) { renderer->updateHitTestResult(result, IntPoint(x - tx, y - ty)); diff --git a/WebCore/rendering/RenderListBox.cpp b/WebCore/rendering/RenderListBox.cpp index 5717871..ed7f8ee 100644 --- a/WebCore/rendering/RenderListBox.cpp +++ b/WebCore/rendering/RenderListBox.cpp @@ -515,6 +515,11 @@ bool RenderListBox::scroll(ScrollDirection direction, ScrollGranularity granular return m_vBar && m_vBar->scroll(direction, granularity, multiplier); } +bool RenderListBox::logicalScroll(ScrollLogicalDirection direction, ScrollGranularity granularity, float multiplier, Node**) +{ + return m_vBar && m_vBar->scroll(logicalToPhysical(direction, style()->isHorizontalWritingMode(), style()->isFlippedBlocksWritingMode()), granularity, multiplier); +} + void RenderListBox::valueChanged(unsigned listIndex) { Element* element = static_cast<Element*>(node()); diff --git a/WebCore/rendering/RenderListBox.h b/WebCore/rendering/RenderListBox.h index 69acb57..1fbff0d 100644 --- a/WebCore/rendering/RenderListBox.h +++ b/WebCore/rendering/RenderListBox.h @@ -69,6 +69,7 @@ private: virtual bool isPointInOverflowControl(HitTestResult&, int x, int y, int tx, int ty); virtual bool scroll(ScrollDirection, ScrollGranularity, float multiplier = 1, Node** stopNode = 0); + virtual bool logicalScroll(ScrollLogicalDirection, ScrollGranularity, float multiplier = 1, Node** stopNode = 0); virtual void computePreferredLogicalWidths(); virtual int baselinePosition(FontBaseline, bool firstLine, LineDirectionMode, LinePositionMode = PositionOnContainingLine) const; diff --git a/WebCore/rendering/RenderListItem.cpp b/WebCore/rendering/RenderListItem.cpp index ba107064..65606f3 100644 --- a/WebCore/rendering/RenderListItem.cpp +++ b/WebCore/rendering/RenderListItem.cpp @@ -243,6 +243,12 @@ void RenderListItem::layout() RenderBlock::layout(); } +void RenderListItem::addOverflowFromChildren() +{ + RenderBlock::addOverflowFromChildren(); + positionListMarker(); +} + void RenderListItem::positionListMarker() { if (m_marker && m_marker->parent()->isBox() && !m_marker->isInside() && m_marker->inlineBoxWrapper()) { @@ -257,20 +263,31 @@ void RenderListItem::positionListMarker() bool adjustOverflow = false; int markerLogicalLeft; RootInlineBox* root = m_marker->inlineBoxWrapper()->root(); + bool hitSelfPaintingLayer = false; - // FIXME: Inline flows in the line box hierarchy that have self-painting layers should act as cutoff points - // and really shouldn't keep propagating overflow up. This won't really break anything other than repainting - // not being as tight as it could be though. + // FIXME: Need to account for relative positioning in the layout overflow. if (style()->isLeftToRightDirection()) { int leftLineOffset = logicalLeftOffsetForLine(blockOffset, logicalLeftOffsetForLine(blockOffset, false), false); markerLogicalLeft = leftLineOffset - lineOffset - paddingStart() - borderStart() + m_marker->marginStart(); m_marker->inlineBoxWrapper()->adjustLineDirectionPosition(markerLogicalLeft - markerOldLogicalLeft); for (InlineFlowBox* box = m_marker->inlineBoxWrapper()->parent(); box; box = box->parent()) { - if (markerLogicalLeft < box->logicalLeftLayoutOverflow()) { - box->setInlineDirectionOverflowPositions(markerLogicalLeft, box->logicalRightLayoutOverflow(), box->logicalLeftVisualOverflow(), box->logicalRightVisualOverflow()); + IntRect newLogicalVisualOverflowRect = box->logicalVisualOverflowRect(); + IntRect newLogicalLayoutOverflowRect = box->logicalLayoutOverflowRect(); + if (markerLogicalLeft < newLogicalVisualOverflowRect.x() && !hitSelfPaintingLayer) { + newLogicalVisualOverflowRect.setX(markerLogicalLeft); + newLogicalVisualOverflowRect.setWidth(box->logicalRightVisualOverflow() - newLogicalVisualOverflowRect.x()); + if (box == root) + adjustOverflow = true; + } + if (markerLogicalLeft < newLogicalLayoutOverflowRect.x()) { + newLogicalLayoutOverflowRect.setX(markerLogicalLeft); + newLogicalLayoutOverflowRect.setWidth(box->logicalRightLayoutOverflow() - newLogicalLayoutOverflowRect.x()); if (box == root) adjustOverflow = true; } + box->setOverflowFromLogicalRects(newLogicalLayoutOverflowRect, newLogicalVisualOverflowRect); + if (box->boxModelObject()->hasSelfPaintingLayer()) + hitSelfPaintingLayer = true; } } else { markerLogicalLeft = m_marker->logicalLeft() + paddingStart() + borderStart() + m_marker->marginEnd(); @@ -278,11 +295,22 @@ void RenderListItem::positionListMarker() markerLogicalLeft = rightLineOffset - lineOffset + paddingStart() + borderStart() + m_marker->marginEnd(); m_marker->inlineBoxWrapper()->adjustLineDirectionPosition(markerLogicalLeft - markerOldLogicalLeft); for (InlineFlowBox* box = m_marker->inlineBoxWrapper()->parent(); box; box = box->parent()) { - if (markerLogicalLeft + m_marker->logicalWidth() > box->logicalRightLayoutOverflow()) { - box->setInlineDirectionOverflowPositions(box->logicalLeftLayoutOverflow(), markerLogicalLeft + m_marker->logicalWidth(), box->logicalLeftVisualOverflow(), box->logicalRightVisualOverflow()); + IntRect newLogicalVisualOverflowRect = box->logicalVisualOverflowRect(); + IntRect newLogicalLayoutOverflowRect = box->logicalLayoutOverflowRect(); + if (markerLogicalLeft + m_marker->logicalWidth() > newLogicalVisualOverflowRect.right() && !hitSelfPaintingLayer) { + newLogicalVisualOverflowRect.setWidth(markerLogicalLeft + m_marker->logicalWidth() - box->logicalLeftVisualOverflow()); if (box == root) adjustOverflow = true; } + if (markerLogicalLeft + m_marker->logicalWidth() > newLogicalLayoutOverflowRect.right()) { + newLogicalLayoutOverflowRect.setWidth(markerLogicalLeft + m_marker->logicalWidth() - box->logicalLeftLayoutOverflow()); + if (box == root) + adjustOverflow = true; + } + box->setOverflowFromLogicalRects(newLogicalLayoutOverflowRect, newLogicalVisualOverflowRect); + + if (box->boxModelObject()->hasSelfPaintingLayer()) + hitSelfPaintingLayer = true; } } @@ -291,12 +319,24 @@ void RenderListItem::positionListMarker() if (!style()->isHorizontalWritingMode()) markerRect = markerRect.transposedRect(); RenderBox* o = m_marker; + bool propagateVisualOverflow = true; + bool propagateLayoutOverflow = true; do { o = o->parentBox(); - if (o->isRenderBlock()) - toRenderBlock(o)->addLayoutOverflow(markerRect); + if (o->hasOverflowClip()) + propagateVisualOverflow = false; + if (o->isRenderBlock()) { + if (propagateVisualOverflow) + toRenderBlock(o)->addVisualOverflow(markerRect); + if (propagateLayoutOverflow) + toRenderBlock(o)->addLayoutOverflow(markerRect); + } + if (o->hasOverflowClip()) + propagateLayoutOverflow = false; + if (o->hasSelfPaintingLayer()) + propagateVisualOverflow = false; markerRect.move(-o->x(), -o->y()); - } while (o != this && !o->hasSelfPaintingLayer()); + } while (o != this && propagateVisualOverflow && propagateLayoutOverflow); } } } diff --git a/WebCore/rendering/RenderListItem.h b/WebCore/rendering/RenderListItem.h index 2fcb6c4..fe2cb6a 100644 --- a/WebCore/rendering/RenderListItem.h +++ b/WebCore/rendering/RenderListItem.h @@ -62,12 +62,14 @@ private: virtual void layout(); virtual void computePreferredLogicalWidths(); - virtual void positionListMarker(); + void positionListMarker(); virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle); virtual bool requiresForcedStyleRecalcPropagation() const { return true; } + virtual void addOverflowFromChildren(); + void updateMarkerLocation(); inline int calcValue() const; void updateValueNow() const; diff --git a/WebCore/rendering/RenderListMarker.cpp b/WebCore/rendering/RenderListMarker.cpp index 2f33afb..71b1eae 100644 --- a/WebCore/rendering/RenderListMarker.cpp +++ b/WebCore/rendering/RenderListMarker.cpp @@ -467,6 +467,7 @@ static EListStyleType effectiveListMarkerType(EListStyleType type, int value) case Katakana: case KatakanaIroha: case LowerAlpha: + case LowerArmenian: case LowerGreek: case LowerLatin: case LowerNorwegian: @@ -479,6 +480,7 @@ static EListStyleType effectiveListMarkerType(EListStyleType type, int value) case TigrinyaEt: case TigrinyaEtAbegede: case UpperAlpha: + case UpperArmenian: case UpperGreek: case UpperLatin: case UpperNorwegian: @@ -558,6 +560,7 @@ static UChar listMarkerSuffix(EListStyleType type, int value) case Khmer: case Lao: case LowerAlpha: + case LowerArmenian: case LowerGreek: case LowerHexadecimal: case LowerLatin: @@ -573,6 +576,7 @@ static UChar listMarkerSuffix(EListStyleType type, int value) case Thai: case Tibetan: case UpperAlpha: + case UpperArmenian: case UpperGreek: case UpperHexadecimal: case UpperLatin: @@ -1020,10 +1024,13 @@ String listMarkerText(EListStyleType type, int value) return toRoman(value, true); case Armenian: + case UpperArmenian: // CSS3 says "armenian" means "lower-armenian". // But the CSS2.1 test suite contains uppercase test results for "armenian", // so we'll match the test suite. return toArmenian(value, true); + case LowerArmenian: + return toArmenian(value, false); case Georgian: return toGeorgian(value); case Hebrew: @@ -1103,7 +1110,7 @@ void RenderListMarker::paint(PaintInfo& paintInfo, int tx, int ty) return; IntPoint boxOrigin(tx + x(), ty + y()); - IntRect overflowRect(visibleOverflowRect()); + IntRect overflowRect(visualOverflowRect()); overflowRect.move(boxOrigin.x(), boxOrigin.y()); overflowRect.inflate(maximalOutlineSize(paintInfo.phase)); @@ -1207,6 +1214,7 @@ void RenderListMarker::paint(PaintInfo& paintInfo, int tx, int ty) case Khmer: case Lao: case LowerAlpha: + case LowerArmenian: case LowerGreek: case LowerHexadecimal: case LowerLatin: @@ -1230,6 +1238,7 @@ void RenderListMarker::paint(PaintInfo& paintInfo, int tx, int ty) case TigrinyaEt: case TigrinyaEtAbegede: case UpperAlpha: + case UpperArmenian: case UpperGreek: case UpperHexadecimal: case UpperLatin: @@ -1409,6 +1418,7 @@ void RenderListMarker::computePreferredLogicalWidths() case Khmer: case Lao: case LowerAlpha: + case LowerArmenian: case LowerGreek: case LowerHexadecimal: case LowerLatin: @@ -1432,6 +1442,7 @@ void RenderListMarker::computePreferredLogicalWidths() case TigrinyaEt: case TigrinyaEtAbegede: case UpperAlpha: + case UpperArmenian: case UpperGreek: case UpperHexadecimal: case UpperLatin: @@ -1631,6 +1642,7 @@ IntRect RenderListMarker::getRelativeMarkerRect() case Khmer: case Lao: case LowerAlpha: + case LowerArmenian: case LowerGreek: case LowerHexadecimal: case LowerLatin: @@ -1654,6 +1666,7 @@ IntRect RenderListMarker::getRelativeMarkerRect() case TigrinyaEt: case TigrinyaEtAbegede: case UpperAlpha: + case UpperArmenian: case UpperGreek: case UpperHexadecimal: case UpperLatin: diff --git a/WebCore/rendering/RenderMarquee.cpp b/WebCore/rendering/RenderMarquee.cpp index 90383d8..1c08831 100644 --- a/WebCore/rendering/RenderMarquee.cpp +++ b/WebCore/rendering/RenderMarquee.cpp @@ -116,7 +116,7 @@ int RenderMarquee::computePosition(EMarqueeDirection dir, bool stopAtContentEdge if (isHorizontal()) { bool ltr = s->isLeftToRightDirection(); int clientWidth = box->clientWidth(); - int contentWidth = ltr ? box->rightmostPosition(true, false) : box->leftmostPosition(true, false); + int contentWidth = ltr ? box->rightLayoutOverflow() : box->leftLayoutOverflow(); if (ltr) contentWidth += (box->paddingRight() - box->borderLeft()); else { @@ -137,8 +137,7 @@ int RenderMarquee::computePosition(EMarqueeDirection dir, bool stopAtContentEdge } } else { - int contentHeight = box->lowestPosition(true, false) - - box->borderTop() + box->paddingBottom(); + int contentHeight = box->bottomLayoutOverflow() - box->borderTop() + box->paddingBottom(); int clientHeight = box->clientHeight(); if (dir == MUP) { if (stopAtContentEdge) @@ -294,7 +293,7 @@ void RenderMarquee::timerFired(Timer<RenderMarquee>*) } bool positive = range > 0; int clientSize = (isHorizontal() ? m_layer->renderBox()->clientWidth() : m_layer->renderBox()->clientHeight()); - int increment = max(1, abs(m_layer->renderer()->style()->marqueeIncrement().calcValue(clientSize))); + int increment = abs(m_layer->renderer()->style()->marqueeIncrement().calcValue(clientSize)); int currentPos = (isHorizontal() ? m_layer->scrollXOffset() : m_layer->scrollYOffset()); newPos = currentPos + (addIncrement ? increment : -increment); if (positive) diff --git a/WebCore/rendering/RenderMedia.cpp b/WebCore/rendering/RenderMedia.cpp index 6fe0337..f59a995 100644 --- a/WebCore/rendering/RenderMedia.cpp +++ b/WebCore/rendering/RenderMedia.cpp @@ -633,83 +633,6 @@ void RenderMedia::forwardEvent(Event* event) } } -int RenderMedia::topmostPosition(bool includeOverflowInterior, bool includeSelf, ApplyTransform applyTransform) const -{ - int top = RenderImage::topmostPosition(includeOverflowInterior, includeSelf, applyTransform); - if (!m_controlsShadowRoot || !m_controlsShadowRoot->renderer()) - return top; - - top = min(top, m_controlsShadowRoot->renderBox()->transformedFrameRect().y() + m_controlsShadowRoot->renderBox()->topmostPosition(includeOverflowInterior, includeSelf, applyTransform)); - - if (applyTransform == IncludeTransform && includeSelf && layer() && layer()->hasTransform()) { - int bottom = lowestPosition(includeOverflowInterior, includeSelf, ExcludeTransform); - int right = rightmostPosition(includeOverflowInterior, includeSelf, ExcludeTransform); - int left = leftmostPosition(includeOverflowInterior, includeSelf, ExcludeTransform); - IntRect transformRect = applyLayerTransformToRect(IntRect(left, top, right - left, bottom - top)); - return transformRect.y(); - } - - return top; -} - -int RenderMedia::lowestPosition(bool includeOverflowInterior, bool includeSelf, ApplyTransform applyTransform) const -{ - int bottom = RenderImage::lowestPosition(includeOverflowInterior, includeSelf, applyTransform); - if (!m_controlsShadowRoot || !m_controlsShadowRoot->renderer()) - return bottom; - - bottom = max(bottom, m_controlsShadowRoot->renderBox()->transformedFrameRect().y() + m_controlsShadowRoot->renderBox()->lowestPosition(includeOverflowInterior, includeSelf, applyTransform)); - - if (applyTransform == IncludeTransform && includeSelf && layer() && layer()->hasTransform()) { - int top = topmostPosition(includeOverflowInterior, includeSelf, ExcludeTransform); - int right = rightmostPosition(includeOverflowInterior, includeSelf, ExcludeTransform); - int left = leftmostPosition(includeOverflowInterior, includeSelf, ExcludeTransform); - IntRect transformRect = applyLayerTransformToRect(IntRect(left, top, right - left, bottom - top)); - return transformRect.height() + transformRect.y(); - } - - return bottom; -} - -int RenderMedia::rightmostPosition(bool includeOverflowInterior, bool includeSelf, ApplyTransform applyTransform) const -{ - int right = RenderImage::rightmostPosition(includeOverflowInterior, includeSelf, applyTransform); - if (!m_controlsShadowRoot || !m_controlsShadowRoot->renderer()) - return right; - - right = max(right, m_controlsShadowRoot->renderBox()->transformedFrameRect().x() + m_controlsShadowRoot->renderBox()->rightmostPosition(includeOverflowInterior, includeSelf, applyTransform)); - - if (applyTransform == IncludeTransform && includeSelf && layer() && layer()->hasTransform()) { - int top = rightmostPosition(includeOverflowInterior, includeSelf, ExcludeTransform); - int bottom = lowestPosition(includeOverflowInterior, includeSelf, ExcludeTransform); - int left = leftmostPosition(includeOverflowInterior, includeSelf, ExcludeTransform); - IntRect transformRect = applyLayerTransformToRect(IntRect(left, top, right - left, bottom - top)); - return transformRect.width() + transformRect.x(); - } - - return right; -} - -int RenderMedia::leftmostPosition(bool includeOverflowInterior, bool includeSelf, ApplyTransform applyTransform) const -{ - int left = RenderImage::leftmostPosition(includeOverflowInterior, includeSelf, applyTransform); - if (!m_controlsShadowRoot || !m_controlsShadowRoot->renderer()) - return left; - - left = min(left, m_controlsShadowRoot->renderBox()->transformedFrameRect().x() + m_controlsShadowRoot->renderBox()->leftmostPosition(includeOverflowInterior, includeSelf, applyTransform)); - - if (applyTransform == IncludeTransform && includeSelf && layer() && layer()->hasTransform()) { - int top = rightmostPosition(includeOverflowInterior, includeSelf, ExcludeTransform); - int bottom = lowestPosition(includeOverflowInterior, includeSelf, ExcludeTransform); - int right = rightmostPosition(includeOverflowInterior, includeSelf, ExcludeTransform); - IntRect transformRect = applyLayerTransformToRect(IntRect(left, top, right - left, bottom - top)); - return transformRect.x(); - } - - return left; -} - - // We want the timeline slider to be at least 100 pixels wide. static const int minWidthToDisplayTimeDisplays = 16 + 16 + 45 + 100 + 45 + 16 + 1; diff --git a/WebCore/rendering/RenderMedia.h b/WebCore/rendering/RenderMedia.h index a3b5c5c..817252d 100644 --- a/WebCore/rendering/RenderMedia.h +++ b/WebCore/rendering/RenderMedia.h @@ -88,11 +88,6 @@ private: virtual bool isMedia() const { return true; } virtual bool isImage() const { return false; } - virtual int topmostPosition(bool includeOverflowInterior = true, bool includeSelf = true, ApplyTransform = IncludeTransform) const; - virtual int lowestPosition(bool includeOverflowInterior = true, bool includeSelf = true, ApplyTransform = IncludeTransform) const; - virtual int rightmostPosition(bool includeOverflowInterior = true, bool includeSelf = true, ApplyTransform = IncludeTransform) const; - virtual int leftmostPosition(bool includeOverflowInterior = true, bool includeSelf = true, ApplyTransform = IncludeTransform) const; - void createControlsShadowRoot(); void destroyControlsShadowRoot(); void createPanel(); diff --git a/WebCore/rendering/RenderObject.cpp b/WebCore/rendering/RenderObject.cpp index c6c49ec..8888253 100644 --- a/WebCore/rendering/RenderObject.cpp +++ b/WebCore/rendering/RenderObject.cpp @@ -318,7 +318,6 @@ void RenderObject::addChild(RenderObject* newChild, RenderObject* beforeChild) // Just add it... children->insertChildNode(this, newChild, beforeChild); } - RenderCounter::rendererSubtreeAttached(newChild); if (newChild->isText() && newChild->style()->textTransform() == CAPITALIZE) { RefPtr<StringImpl> textToTransform = toRenderText(newChild)->originalText(); if (textToTransform) @@ -541,18 +540,6 @@ RenderLayer* RenderObject::enclosingLayer() const return 0; } -RenderLayer* RenderObject::enclosingSelfPaintingLayer() const -{ - const RenderObject* curr = this; - while (curr) { - RenderLayer* layer = curr->hasLayer() ? toRenderBoxModelObject(curr)->layer() : 0; - if (layer && layer->isSelfPaintingLayer()) - return layer; - curr = curr->parent(); - } - return 0; -} - RenderBox* RenderObject::enclosingBox() const { RenderObject* curr = const_cast<RenderObject*>(this); @@ -959,8 +946,7 @@ void RenderObject::drawBoxSideFromPath(GraphicsContext* graphicsContext, IntRect lineDash.append(patWidth); lineDash.append(whiteSpaceWidth); graphicsContext->setLineDash(lineDash, patWidth); - graphicsContext->addPath(borderPath); - graphicsContext->strokePath(); + graphicsContext->strokePath(borderPath); return; } case DOUBLE: { @@ -1609,7 +1595,7 @@ Color RenderObject::selectionBackgroundColor() const return color; } -Color RenderObject::selectionForegroundColor() const +Color RenderObject::selectionColor(int colorProperty) const { Color color; // If the element is unselectable, or we are only painting the selection, @@ -1619,7 +1605,7 @@ Color RenderObject::selectionForegroundColor() const return color; if (RefPtr<RenderStyle> pseudoStyle = getUncachedPseudoStyle(SELECTION)) { - color = pseudoStyle->visitedDependentColor(CSSPropertyWebkitTextFillColor); + color = pseudoStyle->visitedDependentColor(colorProperty); if (!color.isValid()) color = pseudoStyle->visitedDependentColor(CSSPropertyColor); } else @@ -1630,6 +1616,16 @@ Color RenderObject::selectionForegroundColor() const return color; } +Color RenderObject::selectionForegroundColor() const +{ + return selectionColor(CSSPropertyWebkitTextFillColor); +} + +Color RenderObject::selectionEmphasisMarkColor() const +{ + return selectionColor(CSSPropertyWebkitTextEmphasisColor); +} + #if ENABLE(DRAG_SUPPORT) Node* RenderObject::draggableNode(bool dhtmlOK, bool uaOK, int x, int y, bool& dhtmlWillDrag) const { diff --git a/WebCore/rendering/RenderObject.h b/WebCore/rendering/RenderObject.h index bfc62fe..9cb4e36 100644 --- a/WebCore/rendering/RenderObject.h +++ b/WebCore/rendering/RenderObject.h @@ -159,7 +159,6 @@ public: // properly added and removed. Since containership can be implemented by any subclass, and since a hierarchy // can contain a mixture of boxes and other object types, these functions need to be in the base class. RenderLayer* enclosingLayer() const; - RenderLayer* enclosingSelfPaintingLayer() const; void addLayers(RenderLayer* parentLayer, RenderObject* newObject); void removeLayers(RenderLayer* parentLayer); void moveLayers(RenderLayer* oldParent, RenderLayer* newParent); @@ -240,6 +239,8 @@ public: virtual bool isBlockFlow() const { return false; } virtual bool isBoxModelObject() const { return false; } virtual bool isCounter() const { return false; } + virtual bool isDetails() const { return false; } + virtual bool isDetailsMarker() const { return false; } virtual bool isEmbeddedObject() const { return false; } virtual bool isFieldset() const { return false; } virtual bool isFileUploadControl() const { return false; } @@ -273,6 +274,7 @@ public: virtual bool isRubyText() const { return false; } virtual bool isSlider() const { return false; } + virtual bool isSummary() const { return false; } virtual bool isTable() const { return false; } virtual bool isTableCell() const { return false; } virtual bool isTableCol() const { return false; } @@ -672,6 +674,7 @@ public: // Obtains the selection colors that should be used when painting a selection. Color selectionBackgroundColor() const; Color selectionForegroundColor() const; + Color selectionEmphasisMarkColor() const; // Whether or not a given block needs to paint selection gaps. virtual bool shouldPaintSelectionGaps() const { return false; } @@ -793,6 +796,8 @@ protected: private: RenderStyle* firstLineStyleSlowCase() const; StyleDifference adjustStyleDifference(StyleDifference, unsigned contextSensitiveProperties) const; + + Color selectionColor(int colorProperty) const; RefPtr<RenderStyle> m_style; @@ -1002,14 +1007,6 @@ inline int adjustForAbsoluteZoom(int value, RenderObject* renderer) return adjustForAbsoluteZoom(value, renderer->style()); } -inline void adjustIntRectForAbsoluteZoom(IntRect& rect, RenderObject* renderer) -{ - rect.setX(adjustForAbsoluteZoom(rect.x(), renderer)); - rect.setY(adjustForAbsoluteZoom(rect.y(), renderer)); - rect.setWidth(adjustForAbsoluteZoom(rect.width(), renderer)); - rect.setHeight(adjustForAbsoluteZoom(rect.height(), renderer)); -} - inline FloatPoint adjustFloatPointForAbsoluteZoom(const FloatPoint& point, RenderObject* renderer) { // The result here is in floats, so we don't need the truncation hack from the integer version above. @@ -1027,6 +1024,15 @@ inline void adjustFloatQuadForAbsoluteZoom(FloatQuad& quad, RenderObject* render quad.setP4(adjustFloatPointForAbsoluteZoom(quad.p4(), renderer)); } +inline void adjustFloatRectForAbsoluteZoom(FloatRect& rect, RenderObject* renderer) +{ + RenderStyle* style = renderer->style(); + rect.setX(adjustFloatForAbsoluteZoom(rect.x(), style)); + rect.setY(adjustFloatForAbsoluteZoom(rect.y(), style)); + rect.setWidth(adjustFloatForAbsoluteZoom(rect.width(), style)); + rect.setHeight(adjustFloatForAbsoluteZoom(rect.height(), style)); +} + } // namespace WebCore #ifndef NDEBUG diff --git a/WebCore/rendering/RenderObjectChildList.cpp b/WebCore/rendering/RenderObjectChildList.cpp index c7c8e44..fed5a2e 100644 --- a/WebCore/rendering/RenderObjectChildList.cpp +++ b/WebCore/rendering/RenderObjectChildList.cpp @@ -174,6 +174,7 @@ void RenderObjectChildList::appendChildNode(RenderObject* owner, RenderObject* n owner->dirtyLinesFromChangedChild(newChild); } + RenderCounter::rendererSubtreeAttached(newChild); newChild->setNeedsLayoutAndPrefWidthsRecalc(); // Goes up the containing block hierarchy. if (!owner->normalChildNeedsLayout()) owner->setChildNeedsLayout(true); // We may supply the static position for an absolute positioned child. @@ -233,6 +234,7 @@ void RenderObjectChildList::insertChildNode(RenderObject* owner, RenderObject* c owner->dirtyLinesFromChangedChild(child); } + RenderCounter::rendererSubtreeAttached(child); child->setNeedsLayoutAndPrefWidthsRecalc(); if (!owner->normalChildNeedsLayout()) owner->setChildNeedsLayout(true); // We may supply the static position for an absolute positioned child. diff --git a/WebCore/rendering/RenderOverflow.h b/WebCore/rendering/RenderOverflow.h index 253a672..7dc2bcb 100644 --- a/WebCore/rendering/RenderOverflow.h +++ b/WebCore/rendering/RenderOverflow.h @@ -39,15 +39,15 @@ namespace WebCore // This object is allocated only when some of these fields have non-default values in the owning box. class RenderOverflow : public Noncopyable { public: - RenderOverflow(const IntRect& defaultRect = IntRect()) - : m_topLayoutOverflow(defaultRect.y()) - , m_bottomLayoutOverflow(defaultRect.bottom()) - , m_leftLayoutOverflow(defaultRect.x()) - , m_rightLayoutOverflow(defaultRect.right()) - , m_topVisualOverflow(defaultRect.y()) - , m_bottomVisualOverflow(defaultRect.bottom()) - , m_leftVisualOverflow(defaultRect.x()) - , m_rightVisualOverflow(defaultRect.right()) + RenderOverflow(const IntRect& layoutRect, const IntRect& visualRect) + : m_topLayoutOverflow(layoutRect.y()) + , m_bottomLayoutOverflow(layoutRect.bottom()) + , m_leftLayoutOverflow(layoutRect.x()) + , m_rightLayoutOverflow(layoutRect.right()) + , m_topVisualOverflow(visualRect.y()) + , m_bottomVisualOverflow(visualRect.bottom()) + , m_leftVisualOverflow(visualRect.x()) + , m_rightVisualOverflow(visualRect.right()) { } @@ -63,8 +63,6 @@ public: int rightVisualOverflow() const { return m_rightVisualOverflow; } IntRect visualOverflowRect() const; - IntRect visibleOverflowRect() const; - void setTopLayoutOverflow(int overflow) { m_topLayoutOverflow = overflow; } void setBottomLayoutOverflow(int overflow) { m_bottomLayoutOverflow = overflow; } void setLeftLayoutOverflow(int overflow) { m_leftLayoutOverflow = overflow; } @@ -80,6 +78,9 @@ public: void addLayoutOverflow(const IntRect&); void addVisualOverflow(const IntRect&); + void setLayoutOverflow(const IntRect&); + void setVisualOverflow(const IntRect&); + void resetLayoutOverflow(const IntRect& defaultRect); private: @@ -104,13 +105,6 @@ inline IntRect RenderOverflow::visualOverflowRect() const return IntRect(m_leftVisualOverflow, m_topVisualOverflow, m_rightVisualOverflow - m_leftVisualOverflow, m_bottomVisualOverflow - m_topVisualOverflow); } -inline IntRect RenderOverflow::visibleOverflowRect() const -{ - IntRect combinedRect(layoutOverflowRect()); - combinedRect.unite(visualOverflowRect()); - return combinedRect; -} - inline void RenderOverflow::move(int dx, int dy) { m_topLayoutOverflow += dy; @@ -140,6 +134,22 @@ inline void RenderOverflow::addVisualOverflow(const IntRect& rect) m_rightVisualOverflow = std::max(rect.right(), m_rightVisualOverflow); } +inline void RenderOverflow::setLayoutOverflow(const IntRect& rect) +{ + m_topLayoutOverflow = rect.y(); + m_bottomLayoutOverflow = rect.bottom(); + m_leftLayoutOverflow = rect.x(); + m_rightLayoutOverflow = rect.right(); +} + +inline void RenderOverflow::setVisualOverflow(const IntRect& rect) +{ + m_topVisualOverflow = rect.y(); + m_bottomVisualOverflow = rect.bottom(); + m_leftVisualOverflow = rect.x(); + m_rightVisualOverflow = rect.right(); +} + inline void RenderOverflow::resetLayoutOverflow(const IntRect& rect) { m_topLayoutOverflow = rect.y(); diff --git a/WebCore/rendering/RenderReplaced.cpp b/WebCore/rendering/RenderReplaced.cpp index b1a7711..974a8d0 100644 --- a/WebCore/rendering/RenderReplaced.cpp +++ b/WebCore/rendering/RenderReplaced.cpp @@ -80,6 +80,7 @@ void RenderReplaced::layout() m_overflow.clear(); addShadowOverflow(); + updateLayerTransform(); repainter.repaintAfterLayout(); setNeedsLayout(false); @@ -175,8 +176,8 @@ bool RenderReplaced::shouldPaint(PaintInfo& paintInfo, int& tx, int& ty) int currentTY = ty + y(); // Early exit if the element touches the edges. - int top = currentTY + topVisibleOverflow(); - int bottom = currentTY + bottomVisibleOverflow(); + int top = currentTY + topVisualOverflow(); + int bottom = currentTY + bottomVisualOverflow(); if (isSelected() && m_inlineBoxWrapper) { int selTop = ty + m_inlineBoxWrapper->root()->selectionTop(); int selBottom = ty + selTop + m_inlineBoxWrapper->root()->selectionHeight(); @@ -185,7 +186,7 @@ bool RenderReplaced::shouldPaint(PaintInfo& paintInfo, int& tx, int& ty) } int os = 2 * maximalOutlineSize(paintInfo.phase); - if (currentTX + leftVisibleOverflow() >= paintInfo.rect.right() + os || currentTX + rightVisibleOverflow() <= paintInfo.rect.x() - os) + if (currentTX + leftVisualOverflow() >= paintInfo.rect.right() + os || currentTX + rightVisualOverflow() <= paintInfo.rect.x() - os) return false; if (top >= paintInfo.rect.bottom() + os || bottom <= paintInfo.rect.y() - os) return false; @@ -388,7 +389,7 @@ IntRect RenderReplaced::clippedOverflowRectForRepaint(RenderBoxModelObject* repa // The selectionRect can project outside of the overflowRect, so take their union // for repainting to avoid selection painting glitches. - IntRect r = unionRect(localSelectionRect(false), visibleOverflowRect()); + IntRect r = unionRect(localSelectionRect(false), visualOverflowRect()); RenderView* v = view(); if (v) { diff --git a/WebCore/rendering/RenderReplica.cpp b/WebCore/rendering/RenderReplica.cpp index 4b11f40..c099d9d 100644 --- a/WebCore/rendering/RenderReplica.cpp +++ b/WebCore/rendering/RenderReplica.cpp @@ -49,6 +49,7 @@ RenderReplica::~RenderReplica() void RenderReplica::layout() { setFrameRect(parentBox()->borderBoxRect()); + updateLayerTransform(); setNeedsLayout(false); } diff --git a/WebCore/rendering/RenderRubyRun.cpp b/WebCore/rendering/RenderRubyRun.cpp index 5c92c04..c12e543 100644 --- a/WebCore/rendering/RenderRubyRun.cpp +++ b/WebCore/rendering/RenderRubyRun.cpp @@ -278,7 +278,7 @@ void RenderRubyRun::layout() // Update our overflow to account for the new RenderRubyText position. m_overflow.clear(); - addOverflowFromBlockChildren(); + computeOverflow(clientLogicalBottom()); } } // namespace WebCore diff --git a/WebCore/rendering/RenderSVGContainer.cpp b/WebCore/rendering/RenderSVGContainer.cpp index 0761562..32e0598 100644 --- a/WebCore/rendering/RenderSVGContainer.cpp +++ b/WebCore/rendering/RenderSVGContainer.cpp @@ -38,7 +38,6 @@ namespace WebCore { RenderSVGContainer::RenderSVGContainer(SVGStyledElement* node) : RenderSVGModelObject(node) - , m_drawsContents(true) , m_needsBoundariesUpdate(true) { } @@ -94,7 +93,7 @@ bool RenderSVGContainer::selfWillPaint() void RenderSVGContainer::paint(PaintInfo& paintInfo, int, int) { - if (paintInfo.context->paintingDisabled() || !drawsContents()) + if (paintInfo.context->paintingDisabled()) return; // Spec: groups w/o children still may render filter content. diff --git a/WebCore/rendering/RenderSVGContainer.h b/WebCore/rendering/RenderSVGContainer.h index 5bdbf32..3bd5346 100644 --- a/WebCore/rendering/RenderSVGContainer.h +++ b/WebCore/rendering/RenderSVGContainer.h @@ -39,10 +39,6 @@ public: const RenderObjectChildList* children() const { return &m_children; } RenderObjectChildList* children() { return &m_children; } - // <marker> uses these methods to only allow drawing children during a special marker draw time - void setDrawsContents(bool drawsContents) { m_drawsContents = drawsContents; } - bool drawsContents() const { return m_drawsContents; } - virtual void paint(PaintInfo&, int parentX, int parentY); virtual void setNeedsBoundariesUpdate() { m_needsBoundariesUpdate = true; } @@ -79,7 +75,6 @@ private: FloatRect m_objectBoundingBox; FloatRect m_strokeBoundingBox; FloatRect m_repaintBoundingBox; - bool m_drawsContents : 1; bool m_needsBoundariesUpdate : 1; }; diff --git a/WebCore/rendering/RenderSVGResource.h b/WebCore/rendering/RenderSVGResource.h index 0230e98..6fc2dae 100644 --- a/WebCore/rendering/RenderSVGResource.h +++ b/WebCore/rendering/RenderSVGResource.h @@ -48,6 +48,7 @@ enum RenderSVGResourceMode { class Color; class FloatRect; class GraphicsContext; +class Path; class RenderObject; class RenderStyle; class RenderSVGResourceSolidColor; @@ -61,7 +62,7 @@ public: virtual void removeClientFromCache(RenderObject*, bool markForInvalidation = true) = 0; virtual bool applyResource(RenderObject*, RenderStyle*, GraphicsContext*&, unsigned short resourceMode) = 0; - virtual void postApplyResource(RenderObject*, GraphicsContext*&, unsigned short) { } + virtual void postApplyResource(RenderObject*, GraphicsContext*&, unsigned short, const Path*) { } virtual FloatRect resourceBoundingBox(RenderObject*) = 0; virtual RenderSVGResourceType resourceType() const = 0; diff --git a/WebCore/rendering/RenderSVGResourceClipper.cpp b/WebCore/rendering/RenderSVGResourceClipper.cpp index e7b9fbb..190c1a4 100644 --- a/WebCore/rendering/RenderSVGResourceClipper.cpp +++ b/WebCore/rendering/RenderSVGResourceClipper.cpp @@ -38,6 +38,7 @@ #include "SVGClipPathElement.h" #include "SVGElement.h" #include "SVGImageBufferTools.h" +#include "SVGNames.h" #include "SVGRenderSupport.h" #include "SVGResources.h" #include "SVGStyledElement.h" @@ -151,9 +152,7 @@ bool RenderSVGResourceClipper::pathOnlyClipping(GraphicsContext* context, const // The SVG specification wants us to clip everything, if clip-path doesn't have a child. if (clipPath.isEmpty()) clipPath.addRect(FloatRect()); - context->beginPath(); - context->addPath(clipPath); - context->clipPath(clipRule); + context->clipPath(clipPath, clipRule); return true; } diff --git a/WebCore/rendering/RenderSVGResourceContainer.h b/WebCore/rendering/RenderSVGResourceContainer.h index 08e18d4..4e5e475 100644 --- a/WebCore/rendering/RenderSVGResourceContainer.h +++ b/WebCore/rendering/RenderSVGResourceContainer.h @@ -38,7 +38,6 @@ public: virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle); virtual bool isSVGResourceContainer() const { return true; } - virtual bool drawsContents() { return false; } virtual RenderSVGResourceContainer* toRenderSVGResourceContainer() { return this; } static AffineTransform transformOnNonScalingStroke(RenderObject*, const AffineTransform& resourceTransform); diff --git a/WebCore/rendering/RenderSVGResourceFilter.cpp b/WebCore/rendering/RenderSVGResourceFilter.cpp index 72872f6..8aa9370 100644 --- a/WebCore/rendering/RenderSVGResourceFilter.cpp +++ b/WebCore/rendering/RenderSVGResourceFilter.cpp @@ -41,6 +41,7 @@ #include "SVGFilterElement.h" #include "SVGFilterPrimitiveStandardAttributes.h" #include "SVGImageBufferTools.h" +#include "SVGNames.h" #include "SVGStyledElement.h" #include "SVGUnitTypes.h" #include <wtf/Vector.h> @@ -254,7 +255,7 @@ bool RenderSVGResourceFilter::applyResource(RenderObject* object, RenderStyle*, return true; } -void RenderSVGResourceFilter::postApplyResource(RenderObject* object, GraphicsContext*& context, unsigned short resourceMode) +void RenderSVGResourceFilter::postApplyResource(RenderObject* object, GraphicsContext*& context, unsigned short resourceMode, const Path*) { ASSERT(object); ASSERT(context); @@ -292,14 +293,14 @@ void RenderSVGResourceFilter::postApplyResource(RenderObject* object, GraphicsCo filterData->filter->setSourceImage(filterData->sourceGraphicBuffer.release()); lastEffect->apply(); #if !PLATFORM(CG) - ImageBuffer* resultImage = lastEffect->resultImage(); + ImageBuffer* resultImage = lastEffect->asImageBuffer(); if (resultImage) resultImage->transformColorSpace(ColorSpaceLinearRGB, ColorSpaceDeviceRGB); #endif filterData->builded = true; } - ImageBuffer* resultImage = lastEffect->resultImage(); + ImageBuffer* resultImage = lastEffect->asImageBuffer(); if (resultImage) { context->concatCTM(filterData->shearFreeAbsoluteTransform.inverse()); diff --git a/WebCore/rendering/RenderSVGResourceFilter.h b/WebCore/rendering/RenderSVGResourceFilter.h index 32f61ea..5950c44 100644 --- a/WebCore/rendering/RenderSVGResourceFilter.h +++ b/WebCore/rendering/RenderSVGResourceFilter.h @@ -70,7 +70,7 @@ public: virtual void removeClientFromCache(RenderObject*, bool markForInvalidation = true); virtual bool applyResource(RenderObject*, RenderStyle*, GraphicsContext*&, unsigned short resourceMode); - virtual void postApplyResource(RenderObject*, GraphicsContext*&, unsigned short resourceMode); + virtual void postApplyResource(RenderObject*, GraphicsContext*&, unsigned short resourceMode, const Path*); virtual FloatRect resourceBoundingBox(RenderObject*); diff --git a/WebCore/rendering/RenderSVGResourceGradient.cpp b/WebCore/rendering/RenderSVGResourceGradient.cpp index a757147..7c383d0 100644 --- a/WebCore/rendering/RenderSVGResourceGradient.cpp +++ b/WebCore/rendering/RenderSVGResourceGradient.cpp @@ -209,7 +209,7 @@ bool RenderSVGResourceGradient::applyResource(RenderObject* object, RenderStyle* } #endif - context->setTextDrawingMode(resourceMode & ApplyToFillMode ? cTextFill : cTextStroke); + context->setTextDrawingMode(resourceMode & ApplyToFillMode ? TextModeFill : TextModeStroke); } const SVGRenderStyle* svgStyle = style->svgStyle(); @@ -230,7 +230,7 @@ bool RenderSVGResourceGradient::applyResource(RenderObject* object, RenderStyle* return true; } -void RenderSVGResourceGradient::postApplyResource(RenderObject* object, GraphicsContext*& context, unsigned short resourceMode) +void RenderSVGResourceGradient::postApplyResource(RenderObject* object, GraphicsContext*& context, unsigned short resourceMode, const Path* path) { ASSERT(context); ASSERT(resourceMode != ApplyToDefaultMode); @@ -258,11 +258,11 @@ void RenderSVGResourceGradient::postApplyResource(RenderObject* object, Graphics #else UNUSED_PARAM(object); #endif - } else { + } else if (path) { if (resourceMode & ApplyToFillMode) - context->fillPath(); + context->fillPath(*path); else if (resourceMode & ApplyToStrokeMode) - context->strokePath(); + context->strokePath(*path); } context->restore(); diff --git a/WebCore/rendering/RenderSVGResourceGradient.h b/WebCore/rendering/RenderSVGResourceGradient.h index bc0b864..1c7f52d 100644 --- a/WebCore/rendering/RenderSVGResourceGradient.h +++ b/WebCore/rendering/RenderSVGResourceGradient.h @@ -51,7 +51,7 @@ public: virtual void removeClientFromCache(RenderObject*, bool markForInvalidation = true); virtual bool applyResource(RenderObject*, RenderStyle*, GraphicsContext*&, unsigned short resourceMode); - virtual void postApplyResource(RenderObject*, GraphicsContext*&, unsigned short resourceMode); + virtual void postApplyResource(RenderObject*, GraphicsContext*&, unsigned short resourceMode, const Path*); virtual FloatRect resourceBoundingBox(RenderObject*) { return FloatRect(); } protected: diff --git a/WebCore/rendering/RenderSVGResourcePattern.cpp b/WebCore/rendering/RenderSVGResourcePattern.cpp index d2e4563..cd64183 100644 --- a/WebCore/rendering/RenderSVGResourcePattern.cpp +++ b/WebCore/rendering/RenderSVGResourcePattern.cpp @@ -165,13 +165,13 @@ bool RenderSVGResourcePattern::applyResource(RenderObject* object, RenderStyle* if (resourceMode & ApplyToTextMode) { if (resourceMode & ApplyToFillMode) { - context->setTextDrawingMode(cTextFill); + context->setTextDrawingMode(TextModeFill); #if PLATFORM(CG) context->applyFillPattern(); #endif } else if (resourceMode & ApplyToStrokeMode) { - context->setTextDrawingMode(cTextStroke); + context->setTextDrawingMode(TextModeStroke); #if PLATFORM(CG) context->applyStrokePattern(); @@ -182,16 +182,16 @@ bool RenderSVGResourcePattern::applyResource(RenderObject* object, RenderStyle* return true; } -void RenderSVGResourcePattern::postApplyResource(RenderObject*, GraphicsContext*& context, unsigned short resourceMode) +void RenderSVGResourcePattern::postApplyResource(RenderObject*, GraphicsContext*& context, unsigned short resourceMode, const Path* path) { ASSERT(context); ASSERT(resourceMode != ApplyToDefaultMode); - if (!(resourceMode & ApplyToTextMode)) { + if (path && !(resourceMode & ApplyToTextMode)) { if (resourceMode & ApplyToFillMode) - context->fillPath(); + context->fillPath(*path); else if (resourceMode & ApplyToStrokeMode) - context->strokePath(); + context->strokePath(*path); } context->restore(); diff --git a/WebCore/rendering/RenderSVGResourcePattern.h b/WebCore/rendering/RenderSVGResourcePattern.h index ba4aec4..ee3fb23 100644 --- a/WebCore/rendering/RenderSVGResourcePattern.h +++ b/WebCore/rendering/RenderSVGResourcePattern.h @@ -53,7 +53,7 @@ public: virtual void removeClientFromCache(RenderObject*, bool markForInvalidation = true); virtual bool applyResource(RenderObject*, RenderStyle*, GraphicsContext*&, unsigned short resourceMode); - virtual void postApplyResource(RenderObject*, GraphicsContext*&, unsigned short resourceMode); + virtual void postApplyResource(RenderObject*, GraphicsContext*&, unsigned short resourceMode, const Path*); virtual FloatRect resourceBoundingBox(RenderObject*) { return FloatRect(); } virtual RenderSVGResourceType resourceType() const { return s_resourceType; } diff --git a/WebCore/rendering/RenderSVGResourceSolidColor.cpp b/WebCore/rendering/RenderSVGResourceSolidColor.cpp index 8228c80..105723f 100644 --- a/WebCore/rendering/RenderSVGResourceSolidColor.cpp +++ b/WebCore/rendering/RenderSVGResourceSolidColor.cpp @@ -60,7 +60,7 @@ bool RenderSVGResourceSolidColor::applyResource(RenderObject* object, RenderStyl context->setFillRule(svgStyle ? svgStyle->fillRule() : RULE_NONZERO); if (resourceMode & ApplyToTextMode) - context->setTextDrawingMode(cTextFill); + context->setTextDrawingMode(TextModeFill); } else if (resourceMode & ApplyToStrokeMode) { context->setAlpha(svgStyle ? svgStyle->strokeOpacity() : 1.0f); context->setStrokeColor(m_color, colorSpace); @@ -69,23 +69,24 @@ bool RenderSVGResourceSolidColor::applyResource(RenderObject* object, RenderStyl SVGRenderSupport::applyStrokeStyleToContext(context, style, object); if (resourceMode & ApplyToTextMode) - context->setTextDrawingMode(cTextStroke); + context->setTextDrawingMode(TextModeStroke); } return true; } -void RenderSVGResourceSolidColor::postApplyResource(RenderObject*, GraphicsContext*& context, unsigned short resourceMode) +void RenderSVGResourceSolidColor::postApplyResource(RenderObject*, GraphicsContext*& context, unsigned short resourceMode, const Path* path) { ASSERT(context); ASSERT(resourceMode != ApplyToDefaultMode); - if (!(resourceMode & ApplyToTextMode)) { + if (path && !(resourceMode & ApplyToTextMode)) { if (resourceMode & ApplyToFillMode) - context->fillPath(); + context->fillPath(*path); else if (resourceMode & ApplyToStrokeMode) - context->strokePath(); + context->strokePath(*path); } +<<<<<<< HEAD #if PLATFORM(SKIA) && !PLATFORM(ANDROID) // FIXME: Move this into the GraphicsContext @@ -97,6 +98,8 @@ void RenderSVGResourceSolidColor::postApplyResource(RenderObject*, GraphicsConte context->platformContext()->setFillShader(0); context->platformContext()->setStrokeShader(0); #endif +======= +>>>>>>> webkit.org at r74534 (trunk) } } diff --git a/WebCore/rendering/RenderSVGResourceSolidColor.h b/WebCore/rendering/RenderSVGResourceSolidColor.h index 44109db..72de3b2 100644 --- a/WebCore/rendering/RenderSVGResourceSolidColor.h +++ b/WebCore/rendering/RenderSVGResourceSolidColor.h @@ -37,7 +37,7 @@ public: virtual void removeClientFromCache(RenderObject*, bool = true) { } virtual bool applyResource(RenderObject*, RenderStyle*, GraphicsContext*&, unsigned short resourceMode); - virtual void postApplyResource(RenderObject*, GraphicsContext*&, unsigned short resourceMode); + virtual void postApplyResource(RenderObject*, GraphicsContext*&, unsigned short resourceMode, const Path*); virtual FloatRect resourceBoundingBox(RenderObject*) { return FloatRect(); } virtual RenderSVGResourceType resourceType() const { return s_resourceType; } diff --git a/WebCore/rendering/RenderSVGShadowTreeRootContainer.cpp b/WebCore/rendering/RenderSVGShadowTreeRootContainer.cpp index d3064c6..c5430ed 100644 --- a/WebCore/rendering/RenderSVGShadowTreeRootContainer.cpp +++ b/WebCore/rendering/RenderSVGShadowTreeRootContainer.cpp @@ -36,8 +36,10 @@ RenderSVGShadowTreeRootContainer::RenderSVGShadowTreeRootContainer(SVGUseElement RenderSVGShadowTreeRootContainer::~RenderSVGShadowTreeRootContainer() { - if (m_shadowRoot && m_shadowRoot->attached()) + if (m_shadowRoot && m_shadowRoot->attached()) { m_shadowRoot->detach(); + m_shadowRoot->clearShadowHost(); + } } void RenderSVGShadowTreeRootContainer::updateStyle(Node::StyleChange change) diff --git a/WebCore/rendering/RenderSVGTransformableContainer.cpp b/WebCore/rendering/RenderSVGTransformableContainer.cpp index c7d2029..3c91170 100644 --- a/WebCore/rendering/RenderSVGTransformableContainer.cpp +++ b/WebCore/rendering/RenderSVGTransformableContainer.cpp @@ -24,6 +24,7 @@ #if ENABLE(SVG) #include "RenderSVGTransformableContainer.h" +#include "SVGNames.h" #include "SVGShadowTreeElements.h" #include "SVGStyledTransformableElement.h" diff --git a/WebCore/rendering/RenderSVGViewportContainer.cpp b/WebCore/rendering/RenderSVGViewportContainer.cpp index ccf67fa..8031328 100644 --- a/WebCore/rendering/RenderSVGViewportContainer.cpp +++ b/WebCore/rendering/RenderSVGViewportContainer.cpp @@ -28,6 +28,7 @@ #include "GraphicsContext.h" #include "RenderView.h" +#include "SVGNames.h" #include "SVGSVGElement.h" namespace WebCore { diff --git a/WebCore/rendering/RenderSlider.cpp b/WebCore/rendering/RenderSlider.cpp index f00b586..cf8c29b 100644 --- a/WebCore/rendering/RenderSlider.cpp +++ b/WebCore/rendering/RenderSlider.cpp @@ -36,6 +36,7 @@ #include "RenderTheme.h" #include "RenderView.h" #include "ShadowElement.h" +#include "SliderThumbElement.h" #include "StepRange.h" #include <wtf/MathExtras.h> @@ -60,6 +61,7 @@ static double sliderPosition(HTMLInputElement* element) return range.proportionFromValue(range.valueFromElement(element)); } +<<<<<<< HEAD class SliderThumbElement : public ShadowBlockElement { public: static PassRefPtr<SliderThumbElement> create(HTMLElement* shadowParent); @@ -181,6 +183,8 @@ void SliderThumbElement::detach() ShadowBlockElement::detach(); } +======= +>>>>>>> webkit.org at r74534 (trunk) RenderSlider::RenderSlider(HTMLInputElement* element) : RenderBlock(element) { @@ -314,6 +318,7 @@ void RenderSlider::layout() setSize(baseSize); computeLogicalWidth(); computeLogicalHeight(); + updateLayerTransform(); if (thumb) { if (oldSize != size()) diff --git a/WebCore/rendering/RenderSummary.cpp b/WebCore/rendering/RenderSummary.cpp new file mode 100644 index 0000000..8fccf66 --- /dev/null +++ b/WebCore/rendering/RenderSummary.cpp @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#include "config.h" +#include "RenderSummary.h" + +namespace WebCore { + +RenderSummary::RenderSummary(Node* element) + : RenderBlock(element) +{ +} + +} diff --git a/WebCore/rendering/RenderSummary.h b/WebCore/rendering/RenderSummary.h new file mode 100644 index 0000000..afc18fa --- /dev/null +++ b/WebCore/rendering/RenderSummary.h @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef RenderSummary_h +#define RenderSummary_h + +#include "RenderBlock.h" + +namespace WebCore { + +class RenderSummary : public RenderBlock { +public: + explicit RenderSummary(Node*); + +private: + virtual const char* renderName() const { return "RenderSummary"; } + virtual bool isSummary() const { return true; } +}; + +inline RenderSummary* toRenderSummary(RenderObject* object) +{ + ASSERT(!object || object->isSummary()); + return static_cast<RenderSummary*>(object); +} + +// This will catch anyone doing an unnecessary cast. +void toRenderSummary(const RenderSummary*); + +} + +#endif // RenderSummary_h + diff --git a/WebCore/rendering/RenderTable.cpp b/WebCore/rendering/RenderTable.cpp index 521dea1..b580ef1 100644 --- a/WebCore/rendering/RenderTable.cpp +++ b/WebCore/rendering/RenderTable.cpp @@ -167,7 +167,7 @@ void RenderTable::addChild(RenderObject* child, RenderObject* beforeChild) if (!wrapInAnonymousSection) { // If the next renderer is actually wrapped in an anonymous table section, we need to go up and find that. - while (beforeChild && beforeChild->parent() != this) + while (beforeChild && !beforeChild->isTableSection() && !beforeChild->isTableCol() && beforeChild->style()->display() != TABLE_CAPTION) beforeChild = beforeChild->parent(); RenderBox::addChild(child, beforeChild); @@ -183,8 +183,6 @@ void RenderTable::addChild(RenderObject* child, RenderObject* beforeChild) while (lastBox && lastBox->parent()->isAnonymous() && !lastBox->isTableSection() && lastBox->style()->display() != TABLE_CAPTION && lastBox->style()->display() != TABLE_COLUMN_GROUP) lastBox = lastBox->parent(); if (lastBox && lastBox->isAnonymous() && !isAfterContent(lastBox)) { - if (beforeChild == lastBox) - beforeChild = lastBox->firstChild(); lastBox->addChild(child, beforeChild); return; } @@ -418,7 +416,7 @@ void RenderTable::layout() while (section) { if (!sectionMoved && section->logicalTop() != logicalHeight()) { sectionMoved = true; - movedSectionLogicalTop = min(logicalHeight(), section->logicalTop()) + (style()->isHorizontalWritingMode() ? section->topVisibleOverflow() : section->leftVisibleOverflow()); + movedSectionLogicalTop = min(logicalHeight(), section->logicalTop()) + (style()->isHorizontalWritingMode() ? section->topVisualOverflow() : section->leftVisualOverflow()); } section->setLogicalLocation(sectionLogicalLeft, logicalHeight()); @@ -445,45 +443,57 @@ void RenderTable::layout() // FIXME: Only pass true if width or height changed. layoutPositionedObjects(true); - // Add overflow from borders. - int rightBorderOverflow = width() + (collapsing ? outerBorderRight() - borderRight() : 0); - int leftBorderOverflow = collapsing ? borderLeft() - outerBorderLeft() : 0; - int bottomBorderOverflow = height() + (collapsing ? outerBorderBottom() - borderBottom() : 0); - int topBorderOverflow = collapsing ? borderTop() - outerBorderTop() : 0; - addLayoutOverflow(IntRect(leftBorderOverflow, topBorderOverflow, rightBorderOverflow - leftBorderOverflow, bottomBorderOverflow - topBorderOverflow)); - - // Add visual overflow from box-shadow and reflections. - addShadowOverflow(); - - // Add overflow from our caption. - if (m_caption) - addOverflowFromChild(m_caption); + updateLayerTransform(); - // Add overflow from our sections. - for (RenderObject* child = firstChild(); child; child = child->nextSibling()) { - if (child->isTableSection()) { - RenderTableSection* section = toRenderTableSection(child); - addOverflowFromChild(section); - } - } + computeOverflow(clientLogicalBottom()); statePusher.pop(); - if (view()->layoutState()->m_pageHeight) - setPageY(view()->layoutState()->pageY(y())); + if (view()->layoutState()->pageLogicalHeight()) + setPageLogicalOffset(view()->layoutState()->pageLogicalOffset(y())); bool didFullRepaint = repainter.repaintAfterLayout(); // Repaint with our new bounds if they are different from our old bounds. if (!didFullRepaint && sectionMoved) { if (style()->isHorizontalWritingMode()) - repaintRectangle(IntRect(leftVisibleOverflow(), movedSectionLogicalTop, rightVisibleOverflow() - leftVisibleOverflow(), bottomVisibleOverflow() - movedSectionLogicalTop)); + repaintRectangle(IntRect(leftVisualOverflow(), movedSectionLogicalTop, rightVisualOverflow() - leftVisualOverflow(), bottomVisualOverflow() - movedSectionLogicalTop)); else - repaintRectangle(IntRect(movedSectionLogicalTop, topVisibleOverflow(), rightVisibleOverflow() - movedSectionLogicalTop, bottomVisibleOverflow() - topVisibleOverflow())); + repaintRectangle(IntRect(movedSectionLogicalTop, topVisualOverflow(), rightVisualOverflow() - movedSectionLogicalTop, bottomVisualOverflow() - topVisualOverflow())); } setNeedsLayout(false); } +void RenderTable::addOverflowFromChildren() +{ + // Add overflow from borders. + // Technically it's odd that we are incorporating the borders into layout overflow, which is only supposed to be about overflow from our + // descendant objects, but since tables don't support overflow:auto, this works out fine. + if (collapseBorders()) { + int rightBorderOverflow = width() + outerBorderRight() - borderRight(); + int leftBorderOverflow = borderLeft() - outerBorderLeft(); + int bottomBorderOverflow = height() + outerBorderBottom() - borderBottom(); + int topBorderOverflow = borderTop() - outerBorderTop(); + IntRect borderOverflowRect(leftBorderOverflow, topBorderOverflow, rightBorderOverflow - leftBorderOverflow, bottomBorderOverflow - topBorderOverflow); + if (borderOverflowRect != borderBoxRect()) { + addLayoutOverflow(borderOverflowRect); + addVisualOverflow(borderOverflowRect); + } + } + + // Add overflow from our caption. + if (m_caption) + addOverflowFromChild(m_caption); + + // Add overflow from our sections. + for (RenderObject* child = firstChild(); child; child = child->nextSibling()) { + if (child->isTableSection()) { + RenderTableSection* section = toRenderTableSection(child); + addOverflowFromChild(section); + } + } +} + void RenderTable::setCellLogicalWidths() { for (RenderObject* child = firstChild(); child; child = child->nextSibling()) { @@ -500,9 +510,9 @@ void RenderTable::paint(PaintInfo& paintInfo, int tx, int ty) PaintPhase paintPhase = paintInfo.phase; int os = 2 * maximalOutlineSize(paintPhase); - if (ty + topVisibleOverflow() >= paintInfo.rect.bottom() + os || ty + bottomVisibleOverflow() <= paintInfo.rect.y() - os) + if (ty + topVisualOverflow() >= paintInfo.rect.bottom() + os || ty + bottomVisualOverflow() <= paintInfo.rect.y() - os) return; - if (tx + leftVisibleOverflow() >= paintInfo.rect.right() + os || tx + rightVisibleOverflow() <= paintInfo.rect.x() - os) + if (tx + leftVisualOverflow() >= paintInfo.rect.right() + os || tx + rightVisualOverflow() <= paintInfo.rect.x() - os) return; bool pushedClip = pushContentsClip(paintInfo, tx, ty); @@ -1172,8 +1182,6 @@ int RenderTable::firstLineBoxBaseline() const if (isWritingModeRoot()) return -1; - recalcSectionsIfNeeded(); - RenderTableSection* firstNonEmptySection = m_head ? m_head : (m_firstBody ? m_firstBody : m_foot); if (firstNonEmptySection && !firstNonEmptySection->numRows()) firstNonEmptySection = sectionBelow(firstNonEmptySection, true); diff --git a/WebCore/rendering/RenderTable.h b/WebCore/rendering/RenderTable.h index 5495615..6afb108 100644 --- a/WebCore/rendering/RenderTable.h +++ b/WebCore/rendering/RenderTable.h @@ -237,6 +237,8 @@ private: virtual IntRect overflowClipRect(int tx, int ty); + virtual void addOverflowFromChildren(); + void subtractCaptionRect(IntRect&) const; void recalcSections() const; diff --git a/WebCore/rendering/RenderTableCell.cpp b/WebCore/rendering/RenderTableCell.cpp index 801a362..17789cb 100644 --- a/WebCore/rendering/RenderTableCell.cpp +++ b/WebCore/rendering/RenderTableCell.cpp @@ -275,9 +275,9 @@ IntRect RenderTableCell::clippedOverflowRectForRepaint(RenderBoxModelObject* rep right = max(right, below->borderHalfRight(true)); } } - left = max(left, -leftVisibleOverflow()); - top = max(top, -topVisibleOverflow()); - IntRect r(-left, - top, left + max(width() + right, rightVisibleOverflow()), top + max(height() + bottom, bottomVisibleOverflow())); + left = max(left, -leftVisualOverflow()); + top = max(top, -topVisualOverflow()); + IntRect r(-left, - top, left + max(width() + right, rightVisualOverflow()), top + max(height() + bottom, bottomVisualOverflow())); if (RenderView* v = view()) { // FIXME: layoutDelta needs to be applied in parts before/after transforms and @@ -1042,4 +1042,28 @@ void RenderTableCell::paintMask(PaintInfo& paintInfo, int tx, int ty) paintMaskImages(paintInfo, tx, ty, w, h); } +void RenderTableCell::scrollbarsChanged(bool horizontalScrollbarChanged, bool verticalScrollbarChanged) +{ + int scrollbarHeight = scrollbarLogicalHeight(); + if (!scrollbarHeight) + return; // Not sure if we should be doing something when a scrollbar goes away or not. + + // We only care if the scrollbar that affects our intrinsic padding has been added. + if ((style()->isHorizontalWritingMode() && !horizontalScrollbarChanged) || + (!style()->isHorizontalWritingMode() && !verticalScrollbarChanged)) + return; + + // Shrink our intrinsic padding as much as possible to accommodate the scrollbar. + if (style()->verticalAlign() == MIDDLE) { + int totalHeight = logicalHeight(); + int heightWithoutIntrinsicPadding = totalHeight - intrinsicPaddingBefore() - intrinsicPaddingAfter(); + totalHeight -= scrollbarHeight; + int newBeforePadding = (totalHeight - heightWithoutIntrinsicPadding) / 2; + int newAfterPadding = totalHeight - heightWithoutIntrinsicPadding - newBeforePadding; + setIntrinsicPaddingBefore(newBeforePadding); + setIntrinsicPaddingAfter(newAfterPadding); + } else + setIntrinsicPaddingAfter(intrinsicPaddingAfter() - scrollbarHeight); +} + } // namespace WebCore diff --git a/WebCore/rendering/RenderTableCell.h b/WebCore/rendering/RenderTableCell.h index 281c226..91eddc8 100644 --- a/WebCore/rendering/RenderTableCell.h +++ b/WebCore/rendering/RenderTableCell.h @@ -121,7 +121,9 @@ public: virtual void setOverrideSize(int); - bool hasVisibleOverflow() const { return m_overflow; } + bool hasVisualOverflow() const { return m_overflow && !borderBoxRect().contains(m_overflow->visualOverflowRect()); } + + virtual void scrollbarsChanged(bool horizontalScrollbarChanged, bool verticalScrollbarChanged); protected: virtual void styleWillChange(StyleDifference, const RenderStyle* newStyle); diff --git a/WebCore/rendering/RenderTableRow.cpp b/WebCore/rendering/RenderTableRow.cpp index ec523b0..e5f484b 100644 --- a/WebCore/rendering/RenderTableRow.cpp +++ b/WebCore/rendering/RenderTableRow.cpp @@ -73,9 +73,7 @@ void RenderTableRow::addChild(RenderObject* child, RenderObject* beforeChild) if (!last) last = lastChild(); if (last && last->isAnonymous() && last->isTableCell()) { - if (beforeChild == last) - beforeChild = last->firstChild(); - last->addChild(child, beforeChild); + last->addChild(child, child->isBeforeContent() ? last->firstChild() : 0); return; } @@ -124,7 +122,7 @@ void RenderTableRow::layout() for (RenderObject* child = firstChild(); child; child = child->nextSibling()) { if (child->isTableCell()) { RenderTableCell* cell = toRenderTableCell(child); - if (!cell->needsLayout() && paginated && view()->layoutState()->m_pageHeight && view()->layoutState()->pageY(cell->y()) != cell->pageY()) + if (!cell->needsLayout() && paginated && view()->layoutState()->pageLogicalHeight() && view()->layoutState()->pageLogicalOffset(cell->y()) != cell->pageLogicalOffset()) cell->setChildNeedsLayout(true, false); if (child->needsLayout()) { @@ -147,6 +145,7 @@ void RenderTableRow::layout() } statePusher.pop(); + // RenderTableSection::layoutRows will set our logical height and width later, so it calls updateLayerTransform(). setNeedsLayout(false); } diff --git a/WebCore/rendering/RenderTableSection.cpp b/WebCore/rendering/RenderTableSection.cpp index 3598053..23796e2 100644 --- a/WebCore/rendering/RenderTableSection.cpp +++ b/WebCore/rendering/RenderTableSection.cpp @@ -100,9 +100,7 @@ void RenderTableSection::addChild(RenderObject* child, RenderObject* beforeChild if (!last) last = lastChild(); if (last && last->isAnonymous()) { - if (beforeChild == last) - beforeChild = last->firstChild(); - last->addChild(child, beforeChild); + last->addChild(child); return; } @@ -581,6 +579,7 @@ int RenderTableSection::layoutRows(int toAdd) rowRenderer->setLocation(0, m_rowPos[r]); rowRenderer->setLogicalWidth(logicalWidth()); rowRenderer->setLogicalHeight(m_rowPos[r + 1] - m_rowPos[r] - vspacing); + rowRenderer->updateLayerTransform(); } for (int c = 0; c < nEffCols; c++) { @@ -702,13 +701,13 @@ int RenderTableSection::layoutRows(int toAdd) if (intrinsicPaddingBefore != oldIntrinsicPaddingBefore || intrinsicPaddingAfter != oldIntrinsicPaddingAfter) cell->setNeedsLayout(true, false); - if (!cell->needsLayout() && view()->layoutState()->m_pageHeight && view()->layoutState()->pageY(cell->y()) != cell->pageY()) + if (!cell->needsLayout() && view()->layoutState()->pageLogicalHeight() && view()->layoutState()->pageLogicalOffset(cell->y()) != cell->pageLogicalOffset()) cell->setChildNeedsLayout(true, false); cell->layoutIfNeeded(); // FIXME: Make pagination work with vertical tables. - if (style()->isHorizontalWritingMode() && view()->layoutState()->m_pageHeight && cell->height() != rHeight) + if (style()->isHorizontalWritingMode() && view()->layoutState()->pageLogicalHeight() && cell->height() != rHeight) cell->setHeight(rHeight); // FIXME: Pagination might have made us change size. For now just shrink or grow the cell to fit without doing a relayout. IntSize childOffset(cell->x() - oldCellRect.x(), cell->y() - oldCellRect.y()); @@ -742,7 +741,7 @@ int RenderTableSection::layoutRows(int toAdd) if (r < totalRows - 1 && cell == primaryCellAt(r + 1, c)) continue; addOverflowFromChild(cell); - m_hasOverflowingCell |= cell->hasVisibleOverflow(); + m_hasOverflowingCell |= cell->hasVisualOverflow(); } } @@ -750,78 +749,6 @@ int RenderTableSection::layoutRows(int toAdd) return height(); } -int RenderTableSection::topmostPosition(bool includeOverflowInterior, bool includeSelf, ApplyTransform applyTransform) const -{ - int top = RenderBox::topmostPosition(includeOverflowInterior, includeSelf, applyTransform); - if (!includeOverflowInterior && hasOverflowClip()) - return top; - - for (RenderObject* row = firstChild(); row; row = row->nextSibling()) { - for (RenderObject* curr = row->firstChild(); curr; curr = curr->nextSibling()) { - if (curr->isTableCell()) { - RenderTableCell* cell = toRenderTableCell(curr); - top = min(top, cell->transformedFrameRect().y() + cell->topmostPosition(false)); - } - } - } - - return top; -} - -int RenderTableSection::lowestPosition(bool includeOverflowInterior, bool includeSelf, ApplyTransform applyTransform) const -{ - int bottom = RenderBox::lowestPosition(includeOverflowInterior, includeSelf, applyTransform); - if (!includeOverflowInterior && hasOverflowClip()) - return bottom; - - for (RenderObject* row = firstChild(); row; row = row->nextSibling()) { - for (RenderObject* curr = row->firstChild(); curr; curr = curr->nextSibling()) { - if (curr->isTableCell()) { - RenderTableCell* cell = toRenderTableCell(curr); - bottom = max(bottom, cell->transformedFrameRect().y() + cell->lowestPosition(false)); - } - } - } - - return bottom; -} - -int RenderTableSection::rightmostPosition(bool includeOverflowInterior, bool includeSelf, ApplyTransform applyTransform) const -{ - int right = RenderBox::rightmostPosition(includeOverflowInterior, includeSelf, applyTransform); - if (!includeOverflowInterior && hasOverflowClip()) - return right; - - for (RenderObject* row = firstChild(); row; row = row->nextSibling()) { - for (RenderObject* curr = row->firstChild(); curr; curr = curr->nextSibling()) { - if (curr->isTableCell()) { - RenderTableCell* cell = toRenderTableCell(curr); - right = max(right, cell->transformedFrameRect().x() + cell->rightmostPosition(false)); - } - } - } - - return right; -} - -int RenderTableSection::leftmostPosition(bool includeOverflowInterior, bool includeSelf, ApplyTransform applyTransform) const -{ - int left = RenderBox::leftmostPosition(includeOverflowInterior, includeSelf, applyTransform); - if (!includeOverflowInterior && hasOverflowClip()) - return left; - - for (RenderObject* row = firstChild(); row; row = row->nextSibling()) { - for (RenderObject* curr = row->firstChild(); curr; curr = curr->nextSibling()) { - if (curr->isTableCell()) { - RenderTableCell* cell = toRenderTableCell(curr); - left = min(left, cell->transformedFrameRect().x() + cell->leftmostPosition(false)); - } - } - } - - return left; -} - int RenderTableSection::calcOuterBorderBefore() const { int totalCols = table()->numEffCols(); @@ -1112,10 +1039,6 @@ void RenderTableSection::paintObject(PaintInfo& paintInfo, int tx, int ty) unsigned totalCols = table()->columns().size(); PaintPhase paintPhase = paintInfo.phase; - int x = paintInfo.rect.x(); - int y = paintInfo.rect.y(); - int w = paintInfo.rect.width(); - int h = paintInfo.rect.height(); #ifdef ANDROID_LAYOUT unsigned int startrow = 0; @@ -1137,45 +1060,53 @@ void RenderTableSection::paintObject(PaintInfo& paintInfo, int tx, int ty) int os = 2 * maximalOutlineSize(paintPhase); unsigned startrow = 0; unsigned endrow = totalRows; - + + IntRect localRepaintRect = paintInfo.rect; + localRepaintRect.move(-tx, -ty); + if (style()->isFlippedBlocksWritingMode()) { + if (style()->isHorizontalWritingMode()) + localRepaintRect.setY(height() - localRepaintRect.bottom()); + else + localRepaintRect.setX(width() - localRepaintRect.right()); + } + // If some cell overflows, just paint all of them. if (!m_hasOverflowingCell) { - int relativeY = y - ty; - int top = relativeY - os; + int before = (style()->isHorizontalWritingMode() ? localRepaintRect.y() : localRepaintRect.x()) - os; // binary search to find a row - startrow = std::lower_bound(m_rowPos.begin(), m_rowPos.end(), top) - m_rowPos.begin(); + startrow = std::lower_bound(m_rowPos.begin(), m_rowPos.end(), before) - m_rowPos.begin(); // The binary search above gives us the first row with // a y position >= the top of the paint rect. Thus, the previous // may need to be repainted as well. - if (startrow == m_rowPos.size() || (startrow > 0 && (m_rowPos[startrow] > top))) + if (startrow == m_rowPos.size() || (startrow > 0 && (m_rowPos[startrow] > before))) --startrow; - int bottom = relativeY + h + os; - endrow = std::lower_bound(m_rowPos.begin(), m_rowPos.end(), bottom) - m_rowPos.begin(); + int after = (style()->isHorizontalWritingMode() ? localRepaintRect.bottom() : localRepaintRect.right()) + os; + endrow = std::lower_bound(m_rowPos.begin(), m_rowPos.end(), after) - m_rowPos.begin(); if (endrow == m_rowPos.size()) --endrow; - if (!endrow && ty + m_rowPos[0] - table()->outerBorderTop() <= y + h + os) + if (!endrow && m_rowPos[0] - table()->outerBorderBefore() <= after) ++endrow; } + unsigned startcol = 0; unsigned endcol = totalCols; // FIXME: Implement RTL. if (!m_hasOverflowingCell && style()->isLeftToRightDirection()) { - int relativeX = x - tx; - int left = relativeX - os; + int start = (style()->isHorizontalWritingMode() ? localRepaintRect.x() : localRepaintRect.y()) - os; Vector<int>& columnPos = table()->columnPositions(); - startcol = std::lower_bound(columnPos.begin(), columnPos.end(), left) - columnPos.begin(); - if ((startcol == columnPos.size()) || (startcol > 0 && (columnPos[startcol] > left))) + startcol = std::lower_bound(columnPos.begin(), columnPos.end(), start) - columnPos.begin(); + if ((startcol == columnPos.size()) || (startcol > 0 && (columnPos[startcol] > start))) --startcol; - int right = relativeX + w + os; - endcol = std::lower_bound(columnPos.begin(), columnPos.end(), right) - columnPos.begin(); + int end = (style()->isHorizontalWritingMode() ? localRepaintRect.right() : localRepaintRect.bottom()) + os; + endcol = std::lower_bound(columnPos.begin(), columnPos.end(), end) - columnPos.begin(); if (endcol == columnPos.size()) --endcol; - if (!endcol && tx + table()->columnPositions()[0] - table()->outerBorderLeft() <= y + w + os) + if (!endcol && columnPos[0] - table()->outerBorderStart() <= end) ++endcol; } diff --git a/WebCore/rendering/RenderTableSection.h b/WebCore/rendering/RenderTableSection.h index 0327d59..fac6a84 100644 --- a/WebCore/rendering/RenderTableSection.h +++ b/WebCore/rendering/RenderTableSection.h @@ -136,11 +136,6 @@ private: virtual void removeChild(RenderObject* oldChild); - virtual int topmostPosition(bool includeOverflowInterior, bool includeSelf, ApplyTransform = IncludeTransform) const; - virtual int lowestPosition(bool includeOverflowInterior, bool includeSelf, ApplyTransform = IncludeTransform) const; - virtual int rightmostPosition(bool includeOverflowInterior, bool includeSelf, ApplyTransform = IncludeTransform) const; - virtual int leftmostPosition(bool includeOverflowInterior, bool includeSelf, ApplyTransform = IncludeTransform) const; - virtual void paint(PaintInfo&, int tx, int ty); virtual void paintCell(RenderTableCell*, PaintInfo&, int tx, int ty); virtual void paintObject(PaintInfo&, int tx, int ty); diff --git a/WebCore/rendering/RenderText.cpp b/WebCore/rendering/RenderText.cpp index b1e9413..78c5684 100644 --- a/WebCore/rendering/RenderText.cpp +++ b/WebCore/rendering/RenderText.cpp @@ -429,7 +429,7 @@ VisiblePosition RenderText::positionForPoint(const IntPoint& point) // at the y coordinate of the first line or above // and the x coordinate is to the left of the first text box left edge offset = firstTextBox()->offsetForPosition(pointLineDirection); - return createVisiblePosition(offset + firstTextBox()->start(), DOWNSTREAM); + return createVisiblePosition(offset + firstTextBox()->start(), offset > 0 ? VP_UPSTREAM_IF_POSSIBLE : DOWNSTREAM); } if (lastTextBox() && pointBlockDirection >= lastTextBox()->root()->selectionTop() && pointLineDirection >= lastTextBox()->logicalRight()) { // at the y coordinate of the last line or below diff --git a/WebCore/rendering/RenderTextControl.cpp b/WebCore/rendering/RenderTextControl.cpp index 2040f10..0192ee4 100644 --- a/WebCore/rendering/RenderTextControl.cpp +++ b/WebCore/rendering/RenderTextControl.cpp @@ -607,7 +607,7 @@ void RenderTextControl::paintPlaceholder(PaintInfo& paintInfo, int tx, int ty) RenderBox* textRenderer = innerTextElement() ? innerTextElement()->renderBox() : 0; if (textRenderer) { IntPoint textPoint; - textPoint.setY(ty + borderTop() + paddingTop() + textRenderer->paddingTop() + placeholderStyle->font().ascent()); + textPoint.setY(ty + textBlockInsetTop() + placeholderStyle->font().ascent()); if (placeholderStyle->isLeftToRightDirection()) textPoint.setX(tx + textBlockInsetLeft()); else diff --git a/WebCore/rendering/RenderTextControl.h b/WebCore/rendering/RenderTextControl.h index 4b1d6e3..fdb7fdc 100644 --- a/WebCore/rendering/RenderTextControl.h +++ b/WebCore/rendering/RenderTextControl.h @@ -112,6 +112,7 @@ private: virtual int textBlockInsetLeft() const = 0; virtual int textBlockInsetRight() const = 0; + virtual int textBlockInsetTop() const = 0; void paintPlaceholder(PaintInfo&, int tx, int ty); diff --git a/WebCore/rendering/RenderTextControlMultiLine.cpp b/WebCore/rendering/RenderTextControlMultiLine.cpp index 1a7ba36..d0b0cbc 100644 --- a/WebCore/rendering/RenderTextControlMultiLine.cpp +++ b/WebCore/rendering/RenderTextControlMultiLine.cpp @@ -41,7 +41,7 @@ RenderTextControlMultiLine::RenderTextControlMultiLine(Node* node, bool placehol RenderTextControlMultiLine::~RenderTextControlMultiLine() { - if (node() && node()->inDocument()) + if (node()) static_cast<HTMLTextAreaElement*>(node())->rendererWillBeDestroyed(); } @@ -150,4 +150,14 @@ int RenderTextControlMultiLine::textBlockInsetRight() const return inset; } +int RenderTextControlMultiLine::textBlockInsetTop() const +{ + int inset = borderTop() + paddingTop(); + if (HTMLElement* innerText = innerTextElement()) { + if (RenderBox* innerTextRenderer = innerText->renderBox()) + inset += innerTextRenderer->paddingTop(); + } + return inset; +} + } diff --git a/WebCore/rendering/RenderTextControlMultiLine.h b/WebCore/rendering/RenderTextControlMultiLine.h index 6dc2032..0bb8c8f 100644 --- a/WebCore/rendering/RenderTextControlMultiLine.h +++ b/WebCore/rendering/RenderTextControlMultiLine.h @@ -52,6 +52,7 @@ private: virtual PassRefPtr<RenderStyle> createInnerTextStyle(const RenderStyle* startStyle) const; virtual int textBlockInsetLeft() const; virtual int textBlockInsetRight() const; + virtual int textBlockInsetTop() const; }; inline RenderTextControlMultiLine* toRenderTextControlMultiLine(RenderObject* object) diff --git a/WebCore/rendering/RenderTextControlSingleLine.cpp b/WebCore/rendering/RenderTextControlSingleLine.cpp index 5c8b1e5..29538ce 100644 --- a/WebCore/rendering/RenderTextControlSingleLine.cpp +++ b/WebCore/rendering/RenderTextControlSingleLine.cpp @@ -67,8 +67,10 @@ RenderTextControlSingleLine::~RenderTextControlSingleLine() m_searchPopup = 0; } - if (m_innerBlock) + if (m_innerBlock) { m_innerBlock->detach(); + m_innerBlock = 0; + } if (m_innerSpinButton) m_innerSpinButton->detach(); @@ -669,6 +671,21 @@ void RenderTextControlSingleLine::createSubtreeIfNeeded() } } +#if ENABLE(INPUT_SPEECH) +void RenderTextControlSingleLine::speechAttributeChanged() +{ + // The inner text element of this renderer has different styles depending on whether the + // speech button is visible or not. So when the speech attribute changes, we reset the + // whole thing and recreate to get the right styles and layout. + if (m_speechButton) + m_speechButton->detach(); + setChildrenInline(true); + RenderStyle* parentStyle = m_innerBlock ? m_innerBlock->renderer()->style() : style(); + setStyle(createInnerTextStyle(parentStyle)); + updateFromElement(); +} +#endif + void RenderTextControlSingleLine::updateFromElement() { createSubtreeIfNeeded(); @@ -1073,6 +1090,14 @@ bool RenderTextControlSingleLine::scroll(ScrollDirection direction, ScrollGranul return RenderBlock::scroll(direction, granularity, multiplier, stopNode); } +bool RenderTextControlSingleLine::logicalScroll(ScrollLogicalDirection direction, ScrollGranularity granularity, float multiplier, Node** stopNode) +{ + RenderLayer* layer = innerTextElement()->renderBox()->layer(); + if (layer && layer->scroll(logicalToPhysical(direction, style()->isHorizontalWritingMode(), style()->isFlippedBlocksWritingMode()), granularity, multiplier)) + return true; + return RenderBlock::logicalScroll(direction, granularity, multiplier, stopNode); +} + PassRefPtr<Scrollbar> RenderTextControlSingleLine::createScrollbar(ScrollbarClient* client, ScrollbarOrientation orientation, ScrollbarControlSize controlSize) { RefPtr<Scrollbar> widget; @@ -1109,4 +1134,18 @@ int RenderTextControlSingleLine::textBlockInsetRight() const return inset; } +int RenderTextControlSingleLine::textBlockInsetTop() const +{ + RenderBox* innerRenderer = 0; + if (m_innerBlock) + innerRenderer = m_innerBlock->renderBox(); + else if (HTMLElement* innerText = innerTextElement()) + innerRenderer = innerText->renderBox(); + + if (innerRenderer) + return innerRenderer->y(); + + return borderTop() + paddingTop(); +} + } diff --git a/WebCore/rendering/RenderTextControlSingleLine.h b/WebCore/rendering/RenderTextControlSingleLine.h index 26987fd..51509c0 100644 --- a/WebCore/rendering/RenderTextControlSingleLine.h +++ b/WebCore/rendering/RenderTextControlSingleLine.h @@ -59,6 +59,10 @@ public: // Decoration width outside of the text field. int decorationWidthRight() const; +#if ENABLE(INPUT_SPEECH) + void speechAttributeChanged(); +#endif + private: int preferredDecorationWidthRight() const; virtual bool hasControlClip() const; @@ -83,6 +87,7 @@ private: virtual void setScrollLeft(int); virtual void setScrollTop(int); virtual bool scroll(ScrollDirection, ScrollGranularity, float multiplier = 1, Node** stopNode = 0); + virtual bool logicalScroll(ScrollLogicalDirection, ScrollGranularity, float multiplier = 1, Node** stopNode = 0); int textBlockWidth() const; virtual float getAvgCharWidth(AtomicString family); @@ -145,6 +150,7 @@ private: virtual int textBlockInsetLeft() const; virtual int textBlockInsetRight() const; + virtual int textBlockInsetTop() const; bool m_searchPopupIsVisible; bool m_shouldDrawCapsLockIndicator; diff --git a/WebCore/rendering/RenderThemeChromiumSkia.cpp b/WebCore/rendering/RenderThemeChromiumSkia.cpp index 7f664eb..9824851 100644 --- a/WebCore/rendering/RenderThemeChromiumSkia.cpp +++ b/WebCore/rendering/RenderThemeChromiumSkia.cpp @@ -840,7 +840,8 @@ bool RenderThemeChromiumSkia::paintProgressBar(RenderObject* renderObject, const IntRect valueRect = progressValueRectFor(renderProgress, rect); if (valueRect.width()) { - IntSize valueTileSize(static_cast<int>(valueImage->width() * tileScale), valueRect.height()); + IntSize valueTileSize(std::max(1, static_cast<int>(valueImage->width() * tileScale)), valueRect.height()); + int leftOffset = valueRect.x() - rect.x(); int roundedLeftOffset= (leftOffset / valueTileSize.width()) * valueTileSize.width(); int dstLeftValueWidth = roundedLeftOffset - leftOffset + (leftOffset % valueImage->width()) ? valueTileSize.width() : 0; diff --git a/WebCore/rendering/RenderTreeAsText.cpp b/WebCore/rendering/RenderTreeAsText.cpp index f93cd55..2e64999 100644 --- a/WebCore/rendering/RenderTreeAsText.cpp +++ b/WebCore/rendering/RenderTreeAsText.cpp @@ -616,8 +616,17 @@ static void write(TextStream& ts, RenderLayer& l, } static void writeLayers(TextStream& ts, const RenderLayer* rootLayer, RenderLayer* l, - const IntRect& paintDirtyRect, int indent, RenderAsTextBehavior behavior) + const IntRect& paintRect, int indent, RenderAsTextBehavior behavior) { + // FIXME: Apply overflow to the root layer to not break every test. Complete hack. Sigh. + IntRect paintDirtyRect(paintRect); + if (rootLayer == l) { + paintDirtyRect.setWidth(max(paintDirtyRect.width(), rootLayer->renderBox()->rightLayoutOverflow())); + paintDirtyRect.setHeight(max(paintDirtyRect.height(), rootLayer->renderBox()->bottomLayoutOverflow())); + l->setWidth(max(l->width(), l->renderBox()->rightLayoutOverflow())); + l->setHeight(max(l->height(), l->renderBox()->bottomLayoutOverflow())); + } + // Calculate the clip rects we should use. IntRect layerBounds, damageRect, clipRectToApply, outlineRect; l->calculateRects(rootLayer, paintDirtyRect, layerBounds, damageRect, clipRectToApply, outlineRect, true); @@ -676,9 +685,7 @@ static String nodePosition(Node* node) Element* body = node->document()->body(); Node* parent; for (Node* n = node; n; n = parent) { - parent = n->parentNode(); - if (!parent) - parent = n->shadowParentNode(); + parent = n->parentOrHostNode(); if (n != node) result += " of "; if (parent) { diff --git a/WebCore/rendering/RenderVideo.cpp b/WebCore/rendering/RenderVideo.cpp index 32ba91b..5b82deb 100644 --- a/WebCore/rendering/RenderVideo.cpp +++ b/WebCore/rendering/RenderVideo.cpp @@ -237,7 +237,7 @@ void RenderVideo::updatePlayer() } #if USE(ACCELERATED_COMPOSITING) - layer()->rendererContentChanged(); + layer()->contentChanged(RenderLayer::VideoChanged); #endif IntRect videoBounds = videoBox(); diff --git a/WebCore/rendering/RenderView.cpp b/WebCore/rendering/RenderView.cpp index 951bea1..6820e34 100644 --- a/WebCore/rendering/RenderView.cpp +++ b/WebCore/rendering/RenderView.cpp @@ -53,8 +53,8 @@ RenderView::RenderView(Node* node, FrameView* view) , m_selectionStartPos(-1) , m_selectionEndPos(-1) , m_maximalOutlineSize(0) - , m_pageHeight(0) - , m_pageHeightChanged(false) + , m_pageLogicalHeight(0) + , m_pageLogicalHeightChanged(false) , m_layoutState(0) , m_layoutStateDisableCount(0) { @@ -113,7 +113,7 @@ bool RenderView::isChildAllowed(RenderObject* child, RenderStyle*) const void RenderView::layout() { if (!document()->paginated()) - setPageHeight(0); + setPageLogicalHeight(0); if (printing()) m_minPreferredLogicalWidth = m_maxPreferredLogicalWidth = width(); @@ -132,19 +132,14 @@ void RenderView::layout() LayoutState state; // FIXME: May be better to push a clip and avoid issuing offscreen repaints. state.m_clipped = false; - state.m_pageHeight = m_pageHeight; - state.m_pageHeightChanged = m_pageHeightChanged; - m_pageHeightChanged = false; + state.m_pageLogicalHeight = m_pageLogicalHeight; + state.m_pageLogicalHeightChanged = m_pageLogicalHeightChanged; + m_pageLogicalHeightChanged = false; m_layoutState = &state; if (needsLayout()) RenderBlock::layout(); - // Reset overflow and then replace it with docWidth and docHeight. - m_overflow.clear(); - int leftOverflow = docLeft(); - addLayoutOverflow(IntRect(leftOverflow, 0, docWidth(leftOverflow), docHeight())); - ASSERT(layoutDelta() == IntSize()); ASSERT(m_layoutStateDisableCount == 0); ASSERT(m_layoutState == &state); @@ -237,10 +232,10 @@ void RenderView::paintBoxDecorations(PaintInfo& paintInfo, int, int) else { Color baseColor = frameView()->baseBackgroundColor(); if (baseColor.alpha() > 0) { - paintInfo.context->save(); + CompositeOperator previousOperator = paintInfo.context->compositeOperation(); paintInfo.context->setCompositeOperation(CompositeCopy); paintInfo.context->fillRect(paintInfo.rect, baseColor, style()->colorSpace()); - paintInfo.context->restore(); + paintInfo.context->setCompositeOperation(previousOperator); } else paintInfo.context->clearRect(paintInfo.rect); } @@ -582,15 +577,10 @@ bool RenderView::printing() const return document()->printing(); } -void RenderView::updateWidgetPositions() +size_t RenderView::getRetainedWidgets(Vector<RenderWidget*>& renderWidgets) { - // updateWidgetPosition() can possibly cause layout to be re-entered (via plug-ins running - // scripts in response to NPP_SetWindow, for example), so we need to keep the Widgets - // alive during enumeration. - size_t size = m_widgets.size(); - Vector<RenderWidget*> renderWidgets; renderWidgets.reserveCapacity(size); RenderWidgetSet::const_iterator end = m_widgets.end(); @@ -599,14 +589,33 @@ void RenderView::updateWidgetPositions() (*it)->ref(); } + return size; +} + +void RenderView::releaseWidgets(Vector<RenderWidget*>& renderWidgets) +{ + size_t size = renderWidgets.size(); + + for (size_t i = 0; i < size; ++i) + renderWidgets[i]->deref(renderArena()); +} + +void RenderView::updateWidgetPositions() +{ + // updateWidgetPosition() can possibly cause layout to be re-entered (via plug-ins running + // scripts in response to NPP_SetWindow, for example), so we need to keep the Widgets + // alive during enumeration. + + Vector<RenderWidget*> renderWidgets; + size_t size = getRetainedWidgets(renderWidgets); + for (size_t i = 0; i < size; ++i) renderWidgets[i]->updateWidgetPosition(); for (size_t i = 0; i < size; ++i) renderWidgets[i]->widgetPositionsUpdated(); - for (size_t i = 0; i < size; ++i) - renderWidgets[i]->deref(renderArena()); + releaseWidgets(renderWidgets); } void RenderView::addWidget(RenderWidget* o) @@ -619,6 +628,17 @@ void RenderView::removeWidget(RenderWidget* o) m_widgets.remove(o); } +void RenderView::notifyWidgets(WidgetNotification notification) +{ + Vector<RenderWidget*> renderWidgets; + size_t size = getRetainedWidgets(renderWidgets); + + for (size_t i = 0; i < size; ++i) + renderWidgets[i]->notifyWidget(notification); + + releaseWidgets(renderWidgets); +} + IntRect RenderView::viewRect() const { if (printing()) @@ -628,40 +648,40 @@ IntRect RenderView::viewRect() const return IntRect(); } -int RenderView::docHeight() const +int RenderView::docTop() const { - int h = lowestPosition(); - - // FIXME: This doesn't do any margin collapsing. - // Instead of this dh computation we should keep the result - // when we call RenderBlock::layout. - int dh = 0; - for (RenderBox* c = firstChildBox(); c; c = c->nextSiblingBox()) - dh += c->height() + c->marginTop() + c->marginBottom(); - - if (dh > h) - h = dh; + IntRect overflowRect(0, topLayoutOverflow(), 0, bottomLayoutOverflow() - topLayoutOverflow()); + flipForWritingMode(overflowRect); + if (hasTransform()) + overflowRect = layer()->currentTransform().mapRect(overflowRect); + return overflowRect.y(); +} - return h; +int RenderView::docBottom() const +{ + IntRect overflowRect(layoutOverflowRect()); + flipForWritingMode(overflowRect); + if (hasTransform()) + overflowRect = layer()->currentTransform().mapRect(overflowRect); + return overflowRect.bottom(); } int RenderView::docLeft() const { - // Clip out left overflow in LTR page. - return style()->isLeftToRightDirection() ? 0 : std::min(0, leftmostPosition()); + IntRect overflowRect(layoutOverflowRect()); + flipForWritingMode(overflowRect); + if (hasTransform()) + overflowRect = layer()->currentTransform().mapRect(overflowRect); + return overflowRect.x(); } -int RenderView::docWidth(int leftOverflow) const +int RenderView::docRight() const { - int w = style()->isLeftToRightDirection() ? rightmostPosition() : width() - leftOverflow; - - for (RenderBox* c = firstChildBox(); c; c = c->nextSiblingBox()) { - int dw = c->width() + c->marginLeft() + c->marginRight(); - if (dw > w) - w = dw; - } - - return w; + IntRect overflowRect(layoutOverflowRect()); + flipForWritingMode(overflowRect); + if (hasTransform()) + overflowRect = layer()->currentTransform().mapRect(overflowRect); + return overflowRect.right(); } int RenderView::viewHeight() const diff --git a/WebCore/rendering/RenderView.h b/WebCore/rendering/RenderView.h index 8436762..dc81b63 100644 --- a/WebCore/rendering/RenderView.h +++ b/WebCore/rendering/RenderView.h @@ -97,9 +97,14 @@ public: void updateWidgetPositions(); void addWidget(RenderWidget*); void removeWidget(RenderWidget*); +<<<<<<< HEAD #ifdef ANDROID_PLUGINS const HashSet<RenderWidget*>& widgets() const { return m_widgets; } #endif +======= + + void notifyWidgets(WidgetNotification); +>>>>>>> webkit.org at r74534 (trunk) // layoutDelta is used transiently during layout to store how far an object has moved from its // last layout location, in order to repaint correctly. @@ -135,12 +140,12 @@ public: virtual void updateHitTestResult(HitTestResult&, const IntPoint&); - unsigned pageHeight() const { return m_pageHeight; } - void setPageHeight(unsigned height) + unsigned pageLogicalHeight() const { return m_pageLogicalHeight; } + void setPageLogicalHeight(unsigned height) { - if (m_pageHeight != height) { - m_pageHeight = height; - m_pageHeightChanged = true; + if (m_pageLogicalHeight != height) { + m_pageLogicalHeight = height; + m_pageLogicalHeightChanged = true; } } @@ -169,17 +174,21 @@ public: bool usesCompositing() const; #endif + int docTop() const; + int docBottom() const; + int docHeight() const { return docBottom() - docTop(); } + int docLeft() const; + int docRight() const; + int docWidth() const { return docRight() - docLeft(); } + IntRect documentRect() const { return IntRect(docLeft(), docTop(), docWidth(), docHeight()); } + protected: virtual void mapLocalToContainer(RenderBoxModelObject* repaintContainer, bool useTransforms, bool fixed, TransformState&) const; virtual void mapAbsoluteToLocalPoint(bool fixed, bool useTransforms, TransformState&) const; private: bool shouldRepaint(const IntRect& r) const; - - int docHeight() const; - int docLeft() const; - int docWidth(int leftOverflow) const; - + // These functions may only be accessed by LayoutStateMaintainer. bool pushLayoutState(RenderBox* renderer, const IntSize& offset, int pageHeight = 0, bool pageHeightChanged = false, ColumnInfo* colInfo = 0) { @@ -197,6 +206,9 @@ private: m_layoutState = state->m_next; state->destroy(renderArena()); } + + size_t getRetainedWidgets(Vector<RenderWidget*>&); + void releaseWidgets(Vector<RenderWidget*>&); friend class LayoutStateMaintainer; @@ -232,8 +244,8 @@ protected: RenderWidgetSet m_widgets; private: - unsigned m_pageHeight; - bool m_pageHeightChanged; + unsigned m_pageLogicalHeight; + bool m_pageLogicalHeightChanged; LayoutState* m_layoutState; unsigned m_layoutStateDisableCount; #if USE(ACCELERATED_COMPOSITING) diff --git a/WebCore/rendering/RenderWidget.cpp b/WebCore/rendering/RenderWidget.cpp index 6ea620f..152bb2f 100644 --- a/WebCore/rendering/RenderWidget.cpp +++ b/WebCore/rendering/RenderWidget.cpp @@ -236,6 +236,12 @@ void RenderWidget::showSubstituteImage(PassRefPtr<Image> prpImage) repaint(); } +void RenderWidget::notifyWidget(WidgetNotification notification) +{ + if (m_widget) + m_widget->notifyWidget(notification); +} + void RenderWidget::paint(PaintInfo& paintInfo, int tx, int ty) { if (!shouldPaint(paintInfo, tx, ty)) diff --git a/WebCore/rendering/RenderWidget.h b/WebCore/rendering/RenderWidget.h index b85b951..d2ec096 100644 --- a/WebCore/rendering/RenderWidget.h +++ b/WebCore/rendering/RenderWidget.h @@ -24,11 +24,10 @@ #include "OverlapTestRequestClient.h" #include "RenderReplaced.h" +#include "Widget.h" namespace WebCore { -class Widget; - class RenderWidget : public RenderReplaced, private OverlapTestRequestClient { public: virtual ~RenderWidget(); @@ -44,6 +43,8 @@ public: void showSubstituteImage(PassRefPtr<Image>); + void notifyWidget(WidgetNotification); + static void suspendWidgetHierarchyUpdates(); static void resumeWidgetHierarchyUpdates(); diff --git a/WebCore/rendering/RenderingAllInOne.cpp b/WebCore/rendering/RenderingAllInOne.cpp index 7a3a705..37ba704 100644 --- a/WebCore/rendering/RenderingAllInOne.cpp +++ b/WebCore/rendering/RenderingAllInOne.cpp @@ -47,6 +47,8 @@ #include "RenderButton.cpp" #include "RenderCounter.cpp" #include "RenderDataGrid.cpp" +#include "RenderDetails.cpp" +#include "RenderDetailsMarker.cpp" #include "RenderEmbeddedObject.cpp" #include "RenderFieldset.cpp" #include "RenderFileUploadControl.cpp" @@ -87,6 +89,7 @@ #include "RenderScrollbarPart.cpp" #include "RenderScrollbarTheme.cpp" #include "RenderSlider.cpp" +#include "RenderSummary.cpp" #include "RenderTable.cpp" #include "RenderTableCell.cpp" #include "RenderTableCol.cpp" diff --git a/WebCore/rendering/RootInlineBox.cpp b/WebCore/rendering/RootInlineBox.cpp index da7d037..7c2ac98 100644 --- a/WebCore/rendering/RootInlineBox.cpp +++ b/WebCore/rendering/RootInlineBox.cpp @@ -48,7 +48,8 @@ RootInlineBox::RootInlineBox(RenderBlock* block) , m_paginationStrut(0) , m_blockLogicalHeight(0) , m_baselineType(AlphabeticBaseline) - , m_containsRuby(false) + , m_hasAnnotationsBefore(false) + , m_hasAnnotationsAfter(false) { setIsHorizontal(block->style()->isHorizontalWritingMode()); } @@ -150,8 +151,7 @@ void RootInlineBox::addHighlightOverflow() // Highlight acts as a selection inflation. FloatRect rootRect(0, selectionTop(), logicalWidth(), selectionHeight()); IntRect inflatedRect = enclosingIntRect(page->chrome()->client()->customHighlightRect(renderer()->node(), renderer()->style()->highlight(), rootRect)); - setInlineDirectionOverflowPositions(leftLayoutOverflow(), rightLayoutOverflow(), min(leftVisualOverflow(), inflatedRect.x()), max(rightVisualOverflow(), inflatedRect.right())); - setBlockDirectionOverflowPositions(topLayoutOverflow(), bottomLayoutOverflow(), min(topVisualOverflow(), inflatedRect.y()), max(bottomVisualOverflow(), inflatedRect.bottom())); + setOverflowFromLogicalRects(inflatedRect, inflatedRect); } void RootInlineBox::paintCustomHighlight(PaintInfo& paintInfo, int tx, int ty, const AtomicString& highlightType) @@ -249,20 +249,20 @@ int RootInlineBox::alignBoxesInBlockDirection(int heightOfBlock, GlyphOverflowAn int lineTopIncludingMargins = heightOfBlock; int lineBottomIncludingMargins = heightOfBlock; bool setLineTop = false; - bool containsRuby = false; + bool hasAnnotationsBefore = false; + bool hasAnnotationsAfter = false; placeBoxesInBlockDirection(heightOfBlock, maxHeight, maxAscent, noQuirksMode, lineTop, lineBottom, setLineTop, - lineTopIncludingMargins, lineBottomIncludingMargins, containsRuby, m_baselineType); - computeBlockDirectionOverflow(lineTop, lineBottom, noQuirksMode, textBoxDataMap); + lineTopIncludingMargins, lineBottomIncludingMargins, hasAnnotationsBefore, hasAnnotationsAfter, m_baselineType); + m_hasAnnotationsBefore = hasAnnotationsBefore; + m_hasAnnotationsAfter = hasAnnotationsAfter; setLineTopBottomPositions(lineTop, lineBottom); - m_containsRuby = containsRuby; - - int rubyAdjustment = blockDirectionRubyAdjustment(); - if (rubyAdjustment) { + int annotationsAdjustment = beforeAnnotationsAdjustment(); + if (annotationsAdjustment) { // FIXME: Need to handle pagination here. We might have to move to the next page/column as a result of the // ruby expansion. - adjustBlockDirectionPosition(rubyAdjustment); - heightOfBlock += rubyAdjustment; + adjustBlockDirectionPosition(annotationsAdjustment); + heightOfBlock += annotationsAdjustment; } // Detect integer overflow. @@ -272,19 +272,35 @@ int RootInlineBox::alignBoxesInBlockDirection(int heightOfBlock, GlyphOverflowAn return heightOfBlock + maxHeight; } -int RootInlineBox::blockDirectionRubyAdjustment() const +int RootInlineBox::beforeAnnotationsAdjustment() const { + int result = 0; + if (!renderer()->style()->isFlippedLinesWritingMode()) { - if (!containsRuby()) - return 0; - int highestAllowedPosition = prevRootBox() ? min(prevRootBox()->lineBottom(), lineTop()) : block()->borderBefore(); - return computeBlockDirectionRubyAdjustment(highestAllowedPosition); - } else if (prevRootBox() && prevRootBox()->containsRuby()) { - // We have to compute the Ruby expansion for the previous line to see how much we should move. - int lowestAllowedPosition = max(prevRootBox()->lineBottom(), lineTop()); - return prevRootBox()->computeBlockDirectionRubyAdjustment(lowestAllowedPosition); + // Annotations under the previous line may push us down. + if (prevRootBox() && prevRootBox()->hasAnnotationsAfter()) + result = prevRootBox()->computeUnderAnnotationAdjustment(lineTop()); + + if (!hasAnnotationsBefore()) + return result; + + // Annotations over this line may push us further down. + int highestAllowedPosition = prevRootBox() ? min(prevRootBox()->lineBottom(), lineTop()) + result : block()->borderBefore(); + result = computeOverAnnotationAdjustment(highestAllowedPosition); + } else { + // Annotations under this line may push us up. + if (hasAnnotationsBefore()) + result = computeUnderAnnotationAdjustment(prevRootBox() ? prevRootBox()->lineBottom() : block()->borderBefore()); + + if (!prevRootBox() || !prevRootBox()->hasAnnotationsAfter()) + return result; + + // We have to compute the expansion for annotations over the previous line to see how much we should move. + int lowestAllowedPosition = max(prevRootBox()->lineBottom(), lineTop()) - result; + result = prevRootBox()->computeOverAnnotationAdjustment(lowestAllowedPosition); } - return 0; + + return result; } GapRects RootInlineBox::lineSelectionGap(RenderBlock* rootBlock, const IntPoint& rootBlockPhysicalPosition, const IntSize& offsetFromRootBlock, @@ -389,6 +405,10 @@ InlineBox* RootInlineBox::lastSelectedBox() int RootInlineBox::selectionTop() const { int selectionTop = m_lineTop; + + if (m_hasAnnotationsBefore) + selectionTop -= !renderer()->style()->isFlippedLinesWritingMode() ? computeOverAnnotationAdjustment(m_lineTop) : computeUnderAnnotationAdjustment(m_lineTop); + if (renderer()->style()->isFlippedLinesWritingMode()) return selectionTop; @@ -411,6 +431,10 @@ int RootInlineBox::selectionTop() const int RootInlineBox::selectionBottom() const { int selectionBottom = m_lineBottom; + + if (m_hasAnnotationsAfter) + selectionBottom += !renderer()->style()->isFlippedLinesWritingMode() ? computeUnderAnnotationAdjustment(m_lineBottom) : computeOverAnnotationAdjustment(m_lineBottom); + if (!renderer()->style()->isFlippedLinesWritingMode() || !nextRootBox()) return selectionBottom; @@ -509,4 +533,25 @@ void RootInlineBox::attachLineBoxToRenderObject() block()->lineBoxes()->attachLineBox(this); } +IntRect RootInlineBox::paddedLayoutOverflowRect(int endPadding) const +{ + IntRect lineLayoutOverflow = layoutOverflowRect(); + if (!endPadding) + return lineLayoutOverflow; + + if (isHorizontal()) { + if (isLeftToRightDirection()) + lineLayoutOverflow.shiftRightEdgeTo(max(lineLayoutOverflow.right(), logicalRight() + endPadding)); + else + lineLayoutOverflow.shiftLeftEdgeTo(min(lineLayoutOverflow.x(), logicalLeft() - endPadding)); + } else { + if (isLeftToRightDirection()) + lineLayoutOverflow.shiftBottomEdgeTo(max(lineLayoutOverflow.bottom(), logicalRight() + endPadding)); + else + lineLayoutOverflow.shiftTopEdgeTo(min(lineLayoutOverflow.y(), logicalRight() - endPadding)); + } + + return lineLayoutOverflow; +} + } // namespace WebCore diff --git a/WebCore/rendering/RootInlineBox.h b/WebCore/rendering/RootInlineBox.h index 42ad4da..9fe80a1 100644 --- a/WebCore/rendering/RootInlineBox.h +++ b/WebCore/rendering/RootInlineBox.h @@ -128,13 +128,16 @@ public: FontBaseline baselineType() const { return m_baselineType; } - bool containsRuby() const { return m_containsRuby; } + bool hasAnnotationsBefore() const { return m_hasAnnotationsBefore; } + bool hasAnnotationsAfter() const { return m_hasAnnotationsAfter; } + + IntRect paddedLayoutOverflowRect(int endPadding) const; private: bool hasEllipsisBox() const { return m_hasEllipsisBoxOrHyphen; } void setHasEllipsisBox(bool hasEllipsisBox) { m_hasEllipsisBoxOrHyphen = hasEllipsisBox; } - int blockDirectionRubyAdjustment() const; + int beforeAnnotationsAdjustment() const; // Where this line ended. The exact object and the position within that object are stored so that // we can create an InlineIterator beginning just after the end of this line. @@ -158,7 +161,8 @@ private: FontBaseline m_baselineType; // If the line contains any ruby runs, then this will be true. - bool m_containsRuby : 1; + bool m_hasAnnotationsBefore : 1; + bool m_hasAnnotationsAfter : 1; WTF::Unicode::Direction m_lineBreakBidiStatusEor : 5; WTF::Unicode::Direction m_lineBreakBidiStatusLastStrong : 5; diff --git a/WebCore/rendering/SVGImageBufferTools.cpp b/WebCore/rendering/SVGImageBufferTools.cpp index 20f45b1..2dc0a6f 100644 --- a/WebCore/rendering/SVGImageBufferTools.cpp +++ b/WebCore/rendering/SVGImageBufferTools.cpp @@ -81,14 +81,6 @@ void SVGImageBufferTools::renderSubtreeToImageBuffer(ImageBuffer* image, RenderO PaintInfo info(image->context(), PaintInfo::infiniteRect(), PaintPhaseForeground, 0, 0, 0); - RenderSVGContainer* svgContainer = 0; - if (item && item->isSVGContainer() && !item->isSVGViewportContainer()) - svgContainer = toRenderSVGContainer(item); - - bool drawsContents = svgContainer ? svgContainer->drawsContents() : false; - if (svgContainer && !drawsContents) - svgContainer->setDrawsContents(true); - AffineTransform& contentTransformation = currentContentTransformation(); AffineTransform savedContentTransformation = contentTransformation; contentTransformation.multiply(subtreeContentTransformation); @@ -97,9 +89,6 @@ void SVGImageBufferTools::renderSubtreeToImageBuffer(ImageBuffer* image, RenderO item->paint(info, 0, 0); contentTransformation = savedContentTransformation; - - if (svgContainer && !drawsContents) - svgContainer->setDrawsContents(false); } void SVGImageBufferTools::clipToImageBuffer(GraphicsContext* context, const AffineTransform& absoluteTransform, const FloatRect& clampedAbsoluteTargetRect, OwnPtr<ImageBuffer>& imageBuffer) diff --git a/WebCore/rendering/SVGRenderSupport.cpp b/WebCore/rendering/SVGRenderSupport.cpp index 608cf4d..cbde49b 100644 --- a/WebCore/rendering/SVGRenderSupport.cpp +++ b/WebCore/rendering/SVGRenderSupport.cpp @@ -148,7 +148,7 @@ void SVGRenderSupport::finishRenderSVGContent(RenderObject* object, PaintInfo& p SVGResources* resources = SVGResourcesCache::cachedResourcesForRenderObject(object); if (resources) { if (RenderSVGResourceFilter* filter = resources->filter()) { - filter->postApplyResource(object, paintInfo.context, ApplyToDefaultMode); + filter->postApplyResource(object, paintInfo.context, ApplyToDefaultMode, /* path */0); paintInfo.context = savedContext; } } diff --git a/WebCore/rendering/SVGRenderTreeAsText.cpp b/WebCore/rendering/SVGRenderTreeAsText.cpp index 9393fd6..ea843c2 100644 --- a/WebCore/rendering/SVGRenderTreeAsText.cpp +++ b/WebCore/rendering/SVGRenderTreeAsText.cpp @@ -62,6 +62,7 @@ #include "SVGInlineTextBox.h" #include "SVGLineElement.h" #include "SVGLinearGradientElement.h" +#include "SVGNames.h" #include "SVGPathElement.h" #include "SVGPathParserFactory.h" #include "SVGPatternElement.h" diff --git a/WebCore/rendering/SVGResources.cpp b/WebCore/rendering/SVGResources.cpp index f796f3b..e162f83 100644 --- a/WebCore/rendering/SVGResources.cpp +++ b/WebCore/rendering/SVGResources.cpp @@ -27,6 +27,7 @@ #include "RenderSVGResourceMasker.h" #include "SVGFilterElement.h" #include "SVGGradientElement.h" +#include "SVGNames.h" #include "SVGPaint.h" #include "SVGPatternElement.h" #include "SVGRenderStyle.h" diff --git a/WebCore/rendering/SVGShadowTreeElements.cpp b/WebCore/rendering/SVGShadowTreeElements.cpp index 8a66991..7c5e1a9 100644 --- a/WebCore/rendering/SVGShadowTreeElements.cpp +++ b/WebCore/rendering/SVGShadowTreeElements.cpp @@ -51,8 +51,8 @@ FloatSize SVGShadowTreeContainerElement::containerTranslation() const inline SVGShadowTreeRootElement::SVGShadowTreeRootElement(Document* document, SVGUseElement* shadowParent) : SVGShadowTreeContainerElement(document) - , m_shadowParent(shadowParent) { + setShadowHost(shadowParent); setInDocument(); } @@ -63,7 +63,7 @@ PassRefPtr<SVGShadowTreeRootElement> SVGShadowTreeRootElement::create(Document* void SVGShadowTreeRootElement::attachElement(PassRefPtr<RenderStyle> style, RenderArena* arena) { - ASSERT(m_shadowParent); + ASSERT(shadowHost()); // Create the renderer with the specified style RenderObject* renderer = createRenderer(arena, style.get()); @@ -77,7 +77,12 @@ void SVGShadowTreeRootElement::attachElement(PassRefPtr<RenderStyle> style, Rend // Add the renderer to the render tree if (renderer) - m_shadowParent->renderer()->addChild(renderer); + shadowHost()->renderer()->addChild(renderer); +} + +void SVGShadowTreeRootElement::clearShadowHost() +{ + setShadowHost(0); } } diff --git a/WebCore/rendering/SVGShadowTreeElements.h b/WebCore/rendering/SVGShadowTreeElements.h index d49fbaa..fe25678 100644 --- a/WebCore/rendering/SVGShadowTreeElements.h +++ b/WebCore/rendering/SVGShadowTreeElements.h @@ -55,15 +55,10 @@ public: static PassRefPtr<SVGShadowTreeRootElement> create(Document*, SVGUseElement* shadowParent); void attachElement(PassRefPtr<RenderStyle>, RenderArena*); - - virtual ContainerNode* shadowParentNode() { return m_shadowParent; } + void clearShadowHost(); private: SVGShadowTreeRootElement(Document*, SVGUseElement* shadowParent); - - virtual bool isShadowNode() const { return m_shadowParent; } - - ContainerNode* m_shadowParent; }; } diff --git a/WebCore/rendering/ShadowElement.cpp b/WebCore/rendering/ShadowElement.cpp index 72f48e2..e1b247c 100644 --- a/WebCore/rendering/ShadowElement.cpp +++ b/WebCore/rendering/ShadowElement.cpp @@ -75,7 +75,7 @@ PassRefPtr<ShadowBlockElement> ShadowBlockElement::createForPart(HTMLElement* sh void ShadowBlockElement::initAsPart(PseudoId pseudoId) { - RenderObject* parentRenderer = shadowParent()->renderer(); + RenderObject* parentRenderer = shadowHost()->renderer(); RefPtr<RenderStyle> styleForPart = createStyleForPart(parentRenderer, pseudoId); setRenderer(createRenderer(parentRenderer->renderArena(), styleForPart.get())); renderer()->setStyle(styleForPart.release()); diff --git a/WebCore/rendering/ShadowElement.h b/WebCore/rendering/ShadowElement.h index 72bc207..2c1a69e 100644 --- a/WebCore/rendering/ShadowElement.h +++ b/WebCore/rendering/ShadowElement.h @@ -41,17 +41,24 @@ protected: : BaseElement(name, shadowParent->document()) , m_shadowParent(shadowParent) { + BaseElement::setShadowHost(shadowParent); } - HTMLElement* shadowParent() const { return m_shadowParent.get(); } +public: + virtual void detach(); private: - virtual bool isShadowNode() const { return true; } - virtual ContainerNode* shadowParentNode() { return m_shadowParent.get(); } - RefPtr<HTMLElement> m_shadowParent; }; +template<class BaseElement> +void ShadowElement<BaseElement>::detach() +{ + BaseElement::detach(); + // FIXME: Remove once shadow DOM uses Element::setShadowRoot(). + BaseElement::setShadowHost(0); +} + class ShadowBlockElement : public ShadowElement<HTMLDivElement> { public: static PassRefPtr<ShadowBlockElement> create(HTMLElement*); diff --git a/WebCore/rendering/TextControlInnerElements.cpp b/WebCore/rendering/TextControlInnerElements.cpp index 92c51ee..d6fc7aa 100644 --- a/WebCore/rendering/TextControlInnerElements.cpp +++ b/WebCore/rendering/TextControlInnerElements.cpp @@ -79,6 +79,7 @@ TextControlInnerElement::TextControlInnerElement(Document* document, HTMLElement : HTMLDivElement(divTag, document) , m_shadowParent(shadowParent) { + setShadowHost(shadowParent); } PassRefPtr<TextControlInnerElement> TextControlInnerElement::create(HTMLElement* shadowParent) @@ -102,8 +103,8 @@ void TextControlInnerElement::attachInnerElement(Node* parent, PassRefPtr<Render setAttached(); setInDocument(); - // For elements without a shadow parent, add the node to the DOM normally. - if (!m_shadowParent) { + // For elements not yet in shadow DOM, add the node to the DOM normally. + if (!isShadowRoot()) { // FIXME: This code seems very wrong. Why are we magically adding |this| to the DOM here? // We shouldn't be calling parser API methods outside of the parser! parent->deprecatedParserAddChild(this); @@ -114,6 +115,13 @@ void TextControlInnerElement::attachInnerElement(Node* parent, PassRefPtr<Render parent->renderer()->addChild(renderer); } +void TextControlInnerElement::detach() +{ + HTMLDivElement::detach(); + // FIXME: Remove once shadow DOM uses Element::setShadowRoot(). + setShadowHost(0); +} + // ---------------------------- inline TextControlInnerTextElement::TextControlInnerTextElement(Document* document, HTMLElement* shadowParent) diff --git a/WebCore/rendering/TextControlInnerElements.h b/WebCore/rendering/TextControlInnerElements.h index 5af98ed..bb77dcd 100644 --- a/WebCore/rendering/TextControlInnerElements.h +++ b/WebCore/rendering/TextControlInnerElements.h @@ -39,6 +39,7 @@ class SpeechInput; class TextControlInnerElement : public HTMLDivElement { public: static PassRefPtr<TextControlInnerElement> create(HTMLElement* shadowParent); + virtual void detach(); void attachInnerElement(Node*, PassRefPtr<RenderStyle>, RenderArena*); @@ -46,10 +47,7 @@ protected: TextControlInnerElement(Document*, HTMLElement* shadowParent = 0); private: - virtual bool isMouseFocusable() const { return false; } - virtual bool isShadowNode() const { return m_shadowParent.get(); } - virtual ContainerNode* shadowParentNode() { return m_shadowParent.get(); } - void setShadowParentNode(HTMLElement* shadowParent) { m_shadowParent = shadowParent; } + virtual bool isMouseFocusable() const { return false; } RefPtr<HTMLElement> m_shadowParent; }; diff --git a/WebCore/rendering/style/RenderStyle.cpp b/WebCore/rendering/style/RenderStyle.cpp index 0ea3673..37ed391 100644 --- a/WebCore/rendering/style/RenderStyle.cpp +++ b/WebCore/rendering/style/RenderStyle.cpp @@ -402,7 +402,10 @@ StyleDifference RenderStyle::diff(const RenderStyle* other, unsigned& changedCon rareInheritedData->textSecurity != other->rareInheritedData->textSecurity || rareInheritedData->hyphens != other->rareInheritedData->hyphens || rareInheritedData->hyphenationString != other->rareInheritedData->hyphenationString || - rareInheritedData->hyphenationLocale != other->rareInheritedData->hyphenationLocale) + rareInheritedData->hyphenationLocale != other->rareInheritedData->hyphenationLocale || + rareInheritedData->textEmphasisMark != other->rareInheritedData->textEmphasisMark || + rareInheritedData->textEmphasisPosition != other->rareInheritedData->textEmphasisPosition || + rareInheritedData->textEmphasisCustomMark != other->rareInheritedData->textEmphasisCustomMark) return StyleDifferenceLayout; if (!rareInheritedData->shadowDataEquivalent(*other->rareInheritedData.get())) @@ -553,7 +556,9 @@ StyleDifference RenderStyle::diff(const RenderStyle* other, unsigned& changedCon rareNonInheritedData->userDrag != other->rareNonInheritedData->userDrag || rareNonInheritedData->m_borderFit != other->rareNonInheritedData->m_borderFit || rareInheritedData->textFillColor != other->rareInheritedData->textFillColor || - rareInheritedData->textStrokeColor != other->rareInheritedData->textStrokeColor) + rareInheritedData->textStrokeColor != other->rareInheritedData->textStrokeColor || + rareInheritedData->textEmphasisColor != other->rareInheritedData->textEmphasisColor || + rareInheritedData->textEmphasisFill != other->rareInheritedData->textEmphasisFill) return StyleDifferenceRepaint; #if USE(ACCELERATED_COMPOSITING) @@ -842,6 +847,47 @@ const AtomicString& RenderStyle::hyphenString() const return hyphenMinusString; } +const AtomicString& RenderStyle::textEmphasisMarkString() const +{ + switch (textEmphasisMark()) { + case TextEmphasisMarkNone: + return nullAtom; + case TextEmphasisMarkCustom: + return textEmphasisCustomMark(); + case TextEmphasisMarkDot: { + DEFINE_STATIC_LOCAL(AtomicString, filledDotString, (&bullet, 1)); + DEFINE_STATIC_LOCAL(AtomicString, openDotString, (&whiteBullet, 1)); + return textEmphasisFill() == TextEmphasisFillFilled ? filledDotString : openDotString; + } + case TextEmphasisMarkCircle: { + DEFINE_STATIC_LOCAL(AtomicString, filledCircleString, (&blackCircle, 1)); + DEFINE_STATIC_LOCAL(AtomicString, openCircleString, (&whiteCircle, 1)); + return textEmphasisFill() == TextEmphasisFillFilled ? filledCircleString : openCircleString; + } + case TextEmphasisMarkDoubleCircle: { + DEFINE_STATIC_LOCAL(AtomicString, filledDoubleCircleString, (&fisheye, 1)); + DEFINE_STATIC_LOCAL(AtomicString, openDoubleCircleString, (&bullseye, 1)); + return textEmphasisFill() == TextEmphasisFillFilled ? filledDoubleCircleString : openDoubleCircleString; + } + case TextEmphasisMarkTriangle: { + DEFINE_STATIC_LOCAL(AtomicString, filledTriangleString, (&blackUpPointingTriangle, 1)); + DEFINE_STATIC_LOCAL(AtomicString, openTriangleString, (&whiteUpPointingTriangle, 1)); + return textEmphasisFill() == TextEmphasisFillFilled ? filledTriangleString : openTriangleString; + } + case TextEmphasisMarkSesame: { + DEFINE_STATIC_LOCAL(AtomicString, filledSesameString, (&sesameDot, 1)); + DEFINE_STATIC_LOCAL(AtomicString, openSesameString, (&whiteSesameDot, 1)); + return textEmphasisFill() == TextEmphasisFillFilled ? filledSesameString : openSesameString; + } + case TextEmphasisMarkAuto: + ASSERT_NOT_REACHED(); + return nullAtom; + } + + ASSERT_NOT_REACHED(); + return nullAtom; +} + #if ENABLE(DASHBOARD_SUPPORT) const Vector<StyleDashboardRegion>& RenderStyle::initialDashboardRegions() { @@ -1067,6 +1113,9 @@ const Color RenderStyle::colorIncludingFallback(int colorProperty, EBorderStyle case CSSPropertyWebkitColumnRuleColor: result = columnRuleColor(); break; + case CSSPropertyWebkitTextEmphasisColor: + result = textEmphasisColor(); + break; case CSSPropertyWebkitTextFillColor: result = textFillColor(); break; @@ -1408,4 +1457,16 @@ Length RenderStyle::paddingEnd() const return isLeftToRightDirection() ? paddingBottom() : paddingTop(); } +TextEmphasisMark RenderStyle::textEmphasisMark() const +{ + TextEmphasisMark mark = static_cast<TextEmphasisMark>(rareInheritedData->textEmphasisMark); + if (mark != TextEmphasisMarkAuto) + return mark; + + if (isHorizontalWritingMode()) + return TextEmphasisMarkDot; + + return TextEmphasisMarkSesame; +} + } // namespace WebCore diff --git a/WebCore/rendering/style/RenderStyle.h b/WebCore/rendering/style/RenderStyle.h index e86d595..7e61e46 100644 --- a/WebCore/rendering/style/RenderStyle.h +++ b/WebCore/rendering/style/RenderStyle.h @@ -713,6 +713,12 @@ public: Length transformOriginY() const { return rareNonInheritedData->m_transform->m_y; } float transformOriginZ() const { return rareNonInheritedData->m_transform->m_z; } bool hasTransform() const { return !rareNonInheritedData->m_transform->m_operations.operations().isEmpty(); } + + TextEmphasisFill textEmphasisFill() const { return static_cast<TextEmphasisFill>(rareInheritedData->textEmphasisFill); } + TextEmphasisMark textEmphasisMark() const; + const AtomicString& textEmphasisCustomMark() const { return rareInheritedData->textEmphasisCustomMark; } + TextEmphasisPosition textEmphasisPosition() const { return static_cast<TextEmphasisPosition>(rareInheritedData->textEmphasisPosition); } + const AtomicString& textEmphasisMarkString() const; // Return true if any transform related property (currently transform, transformStyle3D or perspective) // indicates that we are transforming @@ -1080,6 +1086,11 @@ public: void setTransformOriginZ(float f) { SET_VAR(rareNonInheritedData.access()->m_transform, m_z, f); } void setSpeak(ESpeak s) { SET_VAR(rareInheritedData, speak, s); } void setTextCombine(TextCombine v) { SET_VAR(rareNonInheritedData, m_textCombine, v); } + void setTextEmphasisColor(const Color& c) { SET_VAR(rareInheritedData, textEmphasisColor, c) } + void setTextEmphasisFill(TextEmphasisFill fill) { SET_VAR(rareInheritedData, textEmphasisFill, fill); } + void setTextEmphasisMark(TextEmphasisMark mark) { SET_VAR(rareInheritedData, textEmphasisMark, mark); } + void setTextEmphasisCustomMark(const AtomicString& mark) { SET_VAR(rareInheritedData, textEmphasisCustomMark, mark); } + void setTextEmphasisPosition(TextEmphasisPosition position) { SET_VAR(rareInheritedData, textEmphasisPosition, position); } // End CSS3 Setters // Apple-specific property setters @@ -1311,6 +1322,11 @@ public: static Length initialPerspectiveOriginX() { return Length(50.0, Percent); } static Length initialPerspectiveOriginY() { return Length(50.0, Percent); } static Color initialBackgroundColor() { return Color::transparent; } + static Color initialTextEmphasisColor() { return TextEmphasisFillFilled; } + static TextEmphasisFill initialTextEmphasisFill() { return TextEmphasisFillFilled; } + static TextEmphasisMark initialTextEmphasisMark() { return TextEmphasisMarkNone; } + static const AtomicString& initialTextEmphasisCustomMark() { return nullAtom; } + static TextEmphasisPosition initialTextEmphasisPosition() { return TextEmphasisPositionOver; } // Keep these at the end. static LineClampValue initialLineClamp() { return LineClampValue(); } @@ -1358,6 +1374,7 @@ private: const Color& color() const { return inherited->color; } const Color& columnRuleColor() const { return rareNonInheritedData->m_multiCol->m_rule.color(); } const Color& outlineColor() const { return m_background->outline().color(); } + const Color& textEmphasisColor() const { return rareInheritedData->textEmphasisColor; } const Color& textFillColor() const { return rareInheritedData->textFillColor; } const Color& textStrokeColor() const { return rareInheritedData->textStrokeColor; } @@ -1382,6 +1399,11 @@ inline int adjustForAbsoluteZoom(int value, const RenderStyle* style) return roundForImpreciseConversion<int, INT_MAX, INT_MIN>(value / zoomFactor); } +inline float adjustFloatForAbsoluteZoom(float value, const RenderStyle* style) +{ + return value / style->effectiveZoom(); +} + } // namespace WebCore #endif // RenderStyle_h diff --git a/WebCore/rendering/style/RenderStyleConstants.h b/WebCore/rendering/style/RenderStyleConstants.h index b8e2079..0839864 100644 --- a/WebCore/rendering/style/RenderStyleConstants.h +++ b/WebCore/rendering/style/RenderStyleConstants.h @@ -134,7 +134,7 @@ enum WritingMode { }; enum TextCombine { - TextCombineNone, TextCombineCluster, TextCombineUpright + TextCombineNone, TextCombineHorizontal }; enum EFillAttachment { @@ -290,6 +290,8 @@ enum EListStyleType { Footnotes, Hebrew, Armenian, + LowerArmenian, + UpperArmenian, Georgian, CJKIdeographic, Hiragana, @@ -420,7 +422,13 @@ enum ELineClampType { LineClampLineCount, LineClampPercentage }; enum Hyphens { HyphensNone, HyphensManual, HyphensAuto }; enum ESpeak { SpeakNone, SpeakNormal, SpeakSpellOut, SpeakDigits, SpeakLiteralPunctuation, SpeakNoPunctuation }; - + +enum TextEmphasisFill { TextEmphasisFillFilled, TextEmphasisFillOpen }; + +enum TextEmphasisMark { TextEmphasisMarkNone, TextEmphasisMarkAuto, TextEmphasisMarkDot, TextEmphasisMarkCircle, TextEmphasisMarkDoubleCircle, TextEmphasisMarkTriangle, TextEmphasisMarkSesame, TextEmphasisMarkCustom }; + +enum TextEmphasisPosition { TextEmphasisPositionOver, TextEmphasisPositionUnder }; + } // namespace WebCore #endif // RenderStyleConstants_h diff --git a/WebCore/rendering/style/StyleRareInheritedData.cpp b/WebCore/rendering/style/StyleRareInheritedData.cpp index af2b555..1fdf0b2 100644 --- a/WebCore/rendering/style/StyleRareInheritedData.cpp +++ b/WebCore/rendering/style/StyleRareInheritedData.cpp @@ -60,6 +60,9 @@ StyleRareInheritedData::StyleRareInheritedData() , colorSpace(ColorSpaceDeviceRGB) , speak(SpeakNormal) , hyphens(HyphensManual) + , textEmphasisFill(TextEmphasisFillFilled) + , textEmphasisMark(TextEmphasisMarkNone) + , textEmphasisPosition(TextEmphasisPositionOver) { } @@ -68,6 +71,7 @@ StyleRareInheritedData::StyleRareInheritedData(const StyleRareInheritedData& o) , textStrokeColor(o.textStrokeColor) , textStrokeWidth(o.textStrokeWidth) , textFillColor(o.textFillColor) +<<<<<<< HEAD #ifdef ANDROID_CSS_RING , ringFillColor(o.ringFillColor) , ringInnerWidth(o.ringInnerWidth) @@ -82,6 +86,9 @@ StyleRareInheritedData::StyleRareInheritedData(const StyleRareInheritedData& o) #ifdef ANDROID_CSS_TAP_HIGHLIGHT_COLOR , tapHighlightColor(o.tapHighlightColor) #endif +======= + , textEmphasisColor(o.textEmphasisColor) +>>>>>>> webkit.org at r74534 (trunk) , textShadow(o.textShadow ? new ShadowData(*o.textShadow) : 0) , highlight(o.highlight) , cursorData(o.cursorData) @@ -101,8 +108,12 @@ StyleRareInheritedData::StyleRareInheritedData(const StyleRareInheritedData& o) , colorSpace(o.colorSpace) , speak(o.speak) , hyphens(o.hyphens) + , textEmphasisFill(o.textEmphasisFill) + , textEmphasisMark(o.textEmphasisMark) + , textEmphasisPosition(o.textEmphasisPosition) , hyphenationString(o.hyphenationString) , hyphenationLocale(o.hyphenationLocale) + , textEmphasisCustomMark(o.textEmphasisCustomMark) { } @@ -125,6 +136,7 @@ bool StyleRareInheritedData::operator==(const StyleRareInheritedData& o) const return textStrokeColor == o.textStrokeColor && textStrokeWidth == o.textStrokeWidth && textFillColor == o.textFillColor + && textEmphasisColor == o.textEmphasisColor && shadowDataEquivalent(o) && highlight == o.highlight && cursorDataEquivalent(cursorData.get(), o.cursorData.get()) @@ -158,8 +170,12 @@ bool StyleRareInheritedData::operator==(const StyleRareInheritedData& o) const && colorSpace == o.colorSpace && speak == o.speak && hyphens == o.hyphens + && textEmphasisFill == o.textEmphasisFill + && textEmphasisMark == o.textEmphasisMark + && textEmphasisPosition == o.textEmphasisPosition && hyphenationString == o.hyphenationString - && hyphenationLocale == o.hyphenationLocale; + && hyphenationLocale == o.hyphenationLocale + && textEmphasisCustomMark == o.textEmphasisCustomMark; } bool StyleRareInheritedData::shadowDataEquivalent(const StyleRareInheritedData& o) const diff --git a/WebCore/rendering/style/StyleRareInheritedData.h b/WebCore/rendering/style/StyleRareInheritedData.h index 4ebbf88..e488909 100644 --- a/WebCore/rendering/style/StyleRareInheritedData.h +++ b/WebCore/rendering/style/StyleRareInheritedData.h @@ -55,6 +55,7 @@ public: Color textStrokeColor; float textStrokeWidth; Color textFillColor; +<<<<<<< HEAD #ifdef ANDROID_CSS_RING Color ringFillColor; Length ringInnerWidth; @@ -69,6 +70,9 @@ public: #ifdef ANDROID_CSS_TAP_HIGHLIGHT_COLOR Color tapHighlightColor; #endif +======= + Color textEmphasisColor; +>>>>>>> webkit.org at r74534 (trunk) ShadowData* textShadow; // Our text shadow information for shadowed text drawing. AtomicString highlight; // Apple-specific extension for custom highlight rendering. @@ -93,10 +97,15 @@ public: unsigned colorSpace : 1; // ColorSpace unsigned speak : 3; // ESpeak unsigned hyphens : 2; // Hyphens + unsigned textEmphasisFill : 1; // TextEmphasisFill + unsigned textEmphasisMark : 3; // TextEmphasisMark + unsigned textEmphasisPosition : 1; // TextEmphasisPosition AtomicString hyphenationString; AtomicString hyphenationLocale; + AtomicString textEmphasisCustomMark; + private: StyleRareInheritedData(); StyleRareInheritedData(const StyleRareInheritedData&); diff --git a/WebCore/rendering/style/StyleRareNonInheritedData.h b/WebCore/rendering/style/StyleRareNonInheritedData.h index a53eee7..89437f6 100644 --- a/WebCore/rendering/style/StyleRareNonInheritedData.h +++ b/WebCore/rendering/style/StyleRareNonInheritedData.h @@ -103,7 +103,7 @@ public: unsigned matchNearestMailBlockquoteColor : 1; // EMatchNearestMailBlockquoteColor, FIXME: This property needs to be eliminated. It should never have been added. unsigned m_appearance : 6; // EAppearance unsigned m_borderFit : 1; // EBorderFit - unsigned m_textCombine : 2; // CSS3 text-combine properties + unsigned m_textCombine : 1; // CSS3 text-combine properties short m_counterIncrement; short m_counterReset; diff --git a/WebCore/rendering/svg/RenderSVGPath.cpp b/WebCore/rendering/svg/RenderSVGPath.cpp index 483303f..0c8ac0c 100644 --- a/WebCore/rendering/svg/RenderSVGPath.cpp +++ b/WebCore/rendering/svg/RenderSVGPath.cpp @@ -148,19 +148,17 @@ void RenderSVGPath::layout() void RenderSVGPath::fillAndStrokePath(GraphicsContext* context) { - context->beginPath(); RenderStyle* style = this->style(); Color fallbackColor; if (RenderSVGResource* fillPaintingResource = RenderSVGResource::fillPaintingResource(this, style, fallbackColor)) { - context->addPath(m_path); if (fillPaintingResource->applyResource(this, style, context, ApplyToFillMode)) - fillPaintingResource->postApplyResource(this, context, ApplyToFillMode); + fillPaintingResource->postApplyResource(this, context, ApplyToFillMode, &m_path); else if (fallbackColor.isValid()) { RenderSVGResourceSolidColor* fallbackResource = RenderSVGResource::sharedSolidPaintingResource(); fallbackResource->setColor(fallbackColor); if (fallbackResource->applyResource(this, style, context, ApplyToFillMode)) - fallbackResource->postApplyResource(this, context, ApplyToFillMode); + fallbackResource->postApplyResource(this, context, ApplyToFillMode, &m_path); } } @@ -169,30 +167,31 @@ void RenderSVGPath::fillAndStrokePath(GraphicsContext* context) if (!strokePaintingResource) return; + Path path; + + bool nonScalingStroke = style->svgStyle()->vectorEffect() == VE_NON_SCALING_STROKE; bool restoreContext = false; - if (style->svgStyle()->vectorEffect() == VE_NON_SCALING_STROKE) { + if (nonScalingStroke) { SVGStyledTransformableElement* element = static_cast<SVGStyledTransformableElement*>(node()); AffineTransform nonScalingStrokeTransform = element->getScreenCTM(SVGLocatable::DisallowStyleUpdate); if (!nonScalingStrokeTransform.isInvertible()) return; - Path transformedPath = m_path; - transformedPath.transform(nonScalingStrokeTransform); + path = m_path; + path.transform(nonScalingStrokeTransform); context->save(); context->concatCTM(nonScalingStrokeTransform.inverse()); - context->addPath(transformedPath); restoreContext = true; - } else - context->addPath(m_path); + } if (strokePaintingResource->applyResource(this, style, context, ApplyToStrokeMode)) - strokePaintingResource->postApplyResource(this, context, ApplyToStrokeMode); + strokePaintingResource->postApplyResource(this, context, ApplyToStrokeMode, nonScalingStroke ? &path : &m_path); else if (fallbackColor.isValid()) { RenderSVGResourceSolidColor* fallbackResource = RenderSVGResource::sharedSolidPaintingResource(); fallbackResource->setColor(fallbackColor); if (fallbackResource->applyResource(this, style, context, ApplyToStrokeMode)) - fallbackResource->postApplyResource(this, context, ApplyToStrokeMode); + fallbackResource->postApplyResource(this, context, ApplyToStrokeMode, nonScalingStroke ? &path : &m_path); } if (restoreContext) diff --git a/WebCore/rendering/svg/RenderSVGTextPath.cpp b/WebCore/rendering/svg/RenderSVGTextPath.cpp index 64ebc6d..4ba2eeb 100644 --- a/WebCore/rendering/svg/RenderSVGTextPath.cpp +++ b/WebCore/rendering/svg/RenderSVGTextPath.cpp @@ -28,6 +28,7 @@ #include "FloatQuad.h" #include "RenderBlock.h" #include "SVGInlineTextBox.h" +#include "SVGNames.h" #include "SVGPathElement.h" #include "SVGRootInlineBox.h" #include "SVGTextPathElement.h" diff --git a/WebCore/rendering/svg/SVGInlineTextBox.cpp b/WebCore/rendering/svg/SVGInlineTextBox.cpp index d1f660a..5d0278b 100644 --- a/WebCore/rendering/svg/SVGInlineTextBox.cpp +++ b/WebCore/rendering/svg/SVGInlineTextBox.cpp @@ -318,14 +318,14 @@ bool SVGInlineTextBox::acquirePaintingResource(GraphicsContext*& context, Render return true; } -void SVGInlineTextBox::releasePaintingResource(GraphicsContext*& context) +void SVGInlineTextBox::releasePaintingResource(GraphicsContext*& context, const Path* path) { ASSERT(m_paintingResource); RenderObject* parentRenderer = parent()->renderer(); ASSERT(parentRenderer); - m_paintingResource->postApplyResource(parentRenderer, context, m_paintingResourceMode); + m_paintingResource->postApplyResource(parentRenderer, context, m_paintingResourceMode, path); m_paintingResource = 0; } @@ -344,7 +344,7 @@ bool SVGInlineTextBox::prepareGraphicsContextForTextPainting(GraphicsContext*& c void SVGInlineTextBox::restoreGraphicsContextAfterTextPainting(GraphicsContext*& context, TextRun& textRun) { - releasePaintingResource(context); + releasePaintingResource(context, /* path */0); #if ENABLE(SVG_FONTS) textRun.setActivePaintingResource(0); @@ -500,11 +500,9 @@ void SVGInlineTextBox::paintDecorationWithStyle(GraphicsContext* context, ETextD path.addRect(FloatRect(fragment.x, y, fragment.width, thickness)); context->save(); - context->beginPath(); - context->addPath(path); if (acquirePaintingResource(context, decorationRenderer, decorationStyle)) - releasePaintingResource(context); + releasePaintingResource(context, &path); context->restore(); } diff --git a/WebCore/rendering/svg/SVGInlineTextBox.h b/WebCore/rendering/svg/SVGInlineTextBox.h index 8e82dda..acc5e9f 100644 --- a/WebCore/rendering/svg/SVGInlineTextBox.h +++ b/WebCore/rendering/svg/SVGInlineTextBox.h @@ -68,7 +68,7 @@ private: TextRun constructTextRun(RenderStyle*, const SVGTextFragment&) const; bool acquirePaintingResource(GraphicsContext*&, RenderObject*, RenderStyle*); - void releasePaintingResource(GraphicsContext*&); + void releasePaintingResource(GraphicsContext*&, const Path*); bool prepareGraphicsContextForTextPainting(GraphicsContext*&, TextRun&, RenderStyle*); void restoreGraphicsContextAfterTextPainting(GraphicsContext*&, TextRun&); diff --git a/WebCore/rendering/svg/SVGRootInlineBox.cpp b/WebCore/rendering/svg/SVGRootInlineBox.cpp index 7109e1f..49c76de 100644 --- a/WebCore/rendering/svg/SVGRootInlineBox.cpp +++ b/WebCore/rendering/svg/SVGRootInlineBox.cpp @@ -30,6 +30,7 @@ #include "RenderSVGInlineText.h" #include "SVGInlineFlowBox.h" #include "SVGInlineTextBox.h" +#include "SVGNames.h" #include "SVGRenderSupport.h" #include "SVGTextPositioningElement.h" |