summaryrefslogtreecommitdiffstats
path: root/Source/WebCore/rendering
diff options
context:
space:
mode:
authorBen Murdoch <benm@google.com>2011-06-02 12:07:03 +0100
committerBen Murdoch <benm@google.com>2011-06-10 10:47:21 +0100
commit2daae5fd11344eaa88a0d92b0f6d65f8d2255c00 (patch)
treee4964fbd1cb70599f7718ff03e50ea1dab33890b /Source/WebCore/rendering
parent87bdf0060a247bfbe668342b87e0874182e0ffa9 (diff)
downloadexternal_webkit-2daae5fd11344eaa88a0d92b0f6d65f8d2255c00.zip
external_webkit-2daae5fd11344eaa88a0d92b0f6d65f8d2255c00.tar.gz
external_webkit-2daae5fd11344eaa88a0d92b0f6d65f8d2255c00.tar.bz2
Merge WebKit at r84325: Initial merge by git.
Change-Id: Ic1a909300ecc0a13ddc6b4e784371d2ac6e3d59b
Diffstat (limited to 'Source/WebCore/rendering')
-rw-r--r--Source/WebCore/rendering/EllipsisBox.cpp8
-rw-r--r--Source/WebCore/rendering/EllipsisBox.h4
-rw-r--r--Source/WebCore/rendering/HitTestResult.cpp29
-rw-r--r--Source/WebCore/rendering/InlineBox.cpp11
-rw-r--r--Source/WebCore/rendering/InlineBox.h14
-rw-r--r--Source/WebCore/rendering/InlineFlowBox.cpp177
-rw-r--r--Source/WebCore/rendering/InlineFlowBox.h95
-rw-r--r--Source/WebCore/rendering/InlineIterator.h55
-rw-r--r--Source/WebCore/rendering/InlineTextBox.cpp49
-rw-r--r--Source/WebCore/rendering/InlineTextBox.h13
-rw-r--r--Source/WebCore/rendering/MediaControlElements.cpp1130
-rw-r--r--Source/WebCore/rendering/MediaControlElements.h492
-rw-r--r--Source/WebCore/rendering/RenderBlock.cpp122
-rw-r--r--Source/WebCore/rendering/RenderBlock.h26
-rw-r--r--Source/WebCore/rendering/RenderBlockLineLayout.cpp697
-rw-r--r--Source/WebCore/rendering/RenderBox.cpp2
-rw-r--r--Source/WebCore/rendering/RenderBox.h10
-rw-r--r--Source/WebCore/rendering/RenderBoxModelObject.cpp884
-rw-r--r--Source/WebCore/rendering/RenderBoxModelObject.h23
-rw-r--r--Source/WebCore/rendering/RenderDetails.cpp176
-rw-r--r--Source/WebCore/rendering/RenderDetails.h25
-rw-r--r--Source/WebCore/rendering/RenderDetailsMarker.cpp87
-rw-r--r--Source/WebCore/rendering/RenderDetailsMarker.h17
-rw-r--r--Source/WebCore/rendering/RenderFileUploadControl.cpp13
-rw-r--r--Source/WebCore/rendering/RenderFileUploadControl.h1
-rw-r--r--Source/WebCore/rendering/RenderFlexibleBox.cpp2
-rw-r--r--Source/WebCore/rendering/RenderFullScreen.cpp4
-rw-r--r--Source/WebCore/rendering/RenderIFrame.cpp3
-rw-r--r--Source/WebCore/rendering/RenderIFrame.h7
-rw-r--r--Source/WebCore/rendering/RenderImage.cpp7
-rw-r--r--Source/WebCore/rendering/RenderIndicator.cpp102
-rw-r--r--Source/WebCore/rendering/RenderIndicator.h66
-rw-r--r--Source/WebCore/rendering/RenderInline.cpp418
-rw-r--r--Source/WebCore/rendering/RenderInline.h17
-rw-r--r--Source/WebCore/rendering/RenderInputSpeech.cpp6
-rw-r--r--Source/WebCore/rendering/RenderLayer.cpp169
-rw-r--r--Source/WebCore/rendering/RenderLayer.h38
-rw-r--r--Source/WebCore/rendering/RenderLayerBacking.cpp166
-rw-r--r--Source/WebCore/rendering/RenderLayerBacking.h14
-rw-r--r--Source/WebCore/rendering/RenderLayerCompositor.cpp323
-rw-r--r--Source/WebCore/rendering/RenderLayerCompositor.h44
-rw-r--r--Source/WebCore/rendering/RenderLineBoxList.cpp46
-rw-r--r--Source/WebCore/rendering/RenderListBox.cpp22
-rw-r--r--Source/WebCore/rendering/RenderListBox.h7
-rw-r--r--Source/WebCore/rendering/RenderListItem.cpp24
-rw-r--r--Source/WebCore/rendering/RenderMedia.cpp24
-rw-r--r--Source/WebCore/rendering/RenderMedia.h15
-rw-r--r--Source/WebCore/rendering/RenderMediaControls.cpp1
-rw-r--r--Source/WebCore/rendering/RenderMediaControlsChromium.cpp22
-rw-r--r--Source/WebCore/rendering/RenderMediaControlsChromium.h1
-rw-r--r--Source/WebCore/rendering/RenderMeter.cpp199
-rw-r--r--Source/WebCore/rendering/RenderMeter.h26
-rw-r--r--Source/WebCore/rendering/RenderObject.cpp349
-rw-r--r--Source/WebCore/rendering/RenderObject.h65
-rw-r--r--Source/WebCore/rendering/RenderObjectChildList.cpp6
-rw-r--r--Source/WebCore/rendering/RenderPart.cpp34
-rw-r--r--Source/WebCore/rendering/RenderPart.h9
-rw-r--r--Source/WebCore/rendering/RenderProgress.cpp53
-rw-r--r--Source/WebCore/rendering/RenderProgress.h17
-rw-r--r--Source/WebCore/rendering/RenderRuby.cpp144
-rw-r--r--Source/WebCore/rendering/RenderRuby.h4
-rw-r--r--Source/WebCore/rendering/RenderRubyRun.cpp37
-rw-r--r--Source/WebCore/rendering/RenderRubyRun.h16
-rw-r--r--Source/WebCore/rendering/RenderSlider.cpp12
-rw-r--r--Source/WebCore/rendering/RenderSlider.h4
-rw-r--r--Source/WebCore/rendering/RenderTableRow.cpp14
-rw-r--r--Source/WebCore/rendering/RenderTableRow.h2
-rw-r--r--Source/WebCore/rendering/RenderTableSection.cpp1
-rw-r--r--Source/WebCore/rendering/RenderText.cpp46
-rw-r--r--Source/WebCore/rendering/RenderText.h3
-rw-r--r--Source/WebCore/rendering/RenderTextControlSingleLine.cpp4
-rw-r--r--Source/WebCore/rendering/RenderTheme.cpp29
-rw-r--r--Source/WebCore/rendering/RenderTheme.h7
-rw-r--r--Source/WebCore/rendering/RenderThemeChromiumLinux.cpp3
-rw-r--r--Source/WebCore/rendering/RenderThemeChromiumMac.h8
-rw-r--r--Source/WebCore/rendering/RenderThemeChromiumMac.mm13
-rw-r--r--Source/WebCore/rendering/RenderThemeChromiumSkia.cpp7
-rw-r--r--Source/WebCore/rendering/RenderThemeChromiumSkia.h2
-rw-r--r--Source/WebCore/rendering/RenderThemeMac.h6
-rw-r--r--Source/WebCore/rendering/RenderThemeMac.mm44
-rw-r--r--Source/WebCore/rendering/RenderThemeWin.cpp12
-rw-r--r--Source/WebCore/rendering/RenderThemeWin.h2
-rw-r--r--Source/WebCore/rendering/RenderTreeAsText.cpp5
-rw-r--r--Source/WebCore/rendering/RenderView.cpp10
-rw-r--r--Source/WebCore/rendering/RenderWidget.cpp4
-rw-r--r--Source/WebCore/rendering/RenderingAllInOne.cpp2
-rw-r--r--Source/WebCore/rendering/RootInlineBox.cpp24
-rw-r--r--Source/WebCore/rendering/RootInlineBox.h37
-rw-r--r--Source/WebCore/rendering/ShadowElement.cpp79
-rw-r--r--Source/WebCore/rendering/ShadowElement.h15
-rw-r--r--Source/WebCore/rendering/style/RenderStyle.cpp319
-rw-r--r--Source/WebCore/rendering/style/RenderStyle.h50
-rw-r--r--Source/WebCore/rendering/style/RenderStyleConstants.h7
-rw-r--r--Source/WebCore/rendering/svg/RenderSVGInline.cpp1
-rw-r--r--Source/WebCore/rendering/svg/RenderSVGInlineText.cpp10
-rw-r--r--Source/WebCore/rendering/svg/RenderSVGPath.cpp4
-rw-r--r--Source/WebCore/rendering/svg/RenderSVGResourceFilter.cpp4
-rw-r--r--Source/WebCore/rendering/svg/RenderSVGResourceFilterPrimitive.cpp27
-rw-r--r--Source/WebCore/rendering/svg/RenderSVGResourceFilterPrimitive.h2
-rw-r--r--Source/WebCore/rendering/svg/RenderSVGResourceGradient.cpp10
-rw-r--r--Source/WebCore/rendering/svg/RenderSVGResourceGradient.h2
-rw-r--r--Source/WebCore/rendering/svg/RenderSVGResourceMasker.cpp2
-rw-r--r--Source/WebCore/rendering/svg/RenderSVGResourcePattern.cpp4
-rw-r--r--Source/WebCore/rendering/svg/RenderSVGShadowTreeRootContainer.cpp4
-rw-r--r--Source/WebCore/rendering/svg/RenderSVGText.cpp5
-rw-r--r--Source/WebCore/rendering/svg/RenderSVGText.h2
-rw-r--r--Source/WebCore/rendering/svg/SVGInlineFlowBox.cpp14
-rw-r--r--Source/WebCore/rendering/svg/SVGInlineFlowBox.h2
-rw-r--r--Source/WebCore/rendering/svg/SVGInlineTextBox.cpp35
-rw-r--r--Source/WebCore/rendering/svg/SVGInlineTextBox.h2
-rw-r--r--Source/WebCore/rendering/svg/SVGMarkerLayoutInfo.cpp9
-rw-r--r--Source/WebCore/rendering/svg/SVGMarkerLayoutInfo.h1
-rw-r--r--Source/WebCore/rendering/svg/SVGRenderTreeAsText.cpp6
-rw-r--r--Source/WebCore/rendering/svg/SVGResourcesCache.cpp4
-rw-r--r--Source/WebCore/rendering/svg/SVGRootInlineBox.cpp23
-rw-r--r--Source/WebCore/rendering/svg/SVGRootInlineBox.h2
-rw-r--r--Source/WebCore/rendering/svg/SVGShadowTreeElements.cpp16
-rw-r--r--Source/WebCore/rendering/svg/SVGShadowTreeElements.h8
-rw-r--r--Source/WebCore/rendering/svg/SVGTextChunkBuilder.cpp28
-rw-r--r--Source/WebCore/rendering/svg/SVGTextFragment.h62
-rw-r--r--Source/WebCore/rendering/svg/SVGTextLayoutAttributes.cpp53
-rw-r--r--Source/WebCore/rendering/svg/SVGTextLayoutAttributes.h41
-rw-r--r--Source/WebCore/rendering/svg/SVGTextLayoutAttributesBuilder.cpp227
-rw-r--r--Source/WebCore/rendering/svg/SVGTextLayoutAttributesBuilder.h39
-rw-r--r--Source/WebCore/rendering/svg/SVGTextLayoutEngine.cpp87
-rw-r--r--Source/WebCore/rendering/svg/SVGTextQuery.cpp53
126 files changed, 3815 insertions, 4412 deletions
diff --git a/Source/WebCore/rendering/EllipsisBox.cpp b/Source/WebCore/rendering/EllipsisBox.cpp
index db66b43..1641ee5 100644
--- a/Source/WebCore/rendering/EllipsisBox.cpp
+++ b/Source/WebCore/rendering/EllipsisBox.cpp
@@ -29,7 +29,7 @@
namespace WebCore {
-void EllipsisBox::paint(PaintInfo& paintInfo, int tx, int ty)
+void EllipsisBox::paint(PaintInfo& paintInfo, int tx, int ty, int lineTop, int lineBottom)
{
GraphicsContext* context = paintInfo.context;
RenderStyle* style = m_renderer->style(m_firstLine);
@@ -66,7 +66,7 @@ void EllipsisBox::paint(PaintInfo& paintInfo, int tx, int ty)
// Paint the markup box
tx += m_x + m_logicalWidth - m_markupBox->x();
ty += m_y + style->fontMetrics().ascent() - (m_markupBox->y() + m_markupBox->renderer()->style(m_firstLine)->fontMetrics().ascent());
- m_markupBox->paint(paintInfo, tx, ty);
+ m_markupBox->paint(paintInfo, tx, ty, lineTop, lineBottom);
}
}
@@ -99,7 +99,7 @@ void EllipsisBox::paintSelection(GraphicsContext* context, int tx, int ty, Rende
context->restore();
}
-bool EllipsisBox::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, int x, int y, int tx, int ty)
+bool EllipsisBox::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, int x, int y, int tx, int ty, int lineTop, int lineBottom)
{
tx += m_x;
ty += m_y;
@@ -109,7 +109,7 @@ bool EllipsisBox::nodeAtPoint(const HitTestRequest& request, HitTestResult& resu
RenderStyle* style = m_renderer->style(m_firstLine);
int mtx = tx + m_logicalWidth - m_markupBox->x();
int mty = ty + style->fontMetrics().ascent() - (m_markupBox->y() + m_markupBox->renderer()->style(m_firstLine)->fontMetrics().ascent());
- if (m_markupBox->nodeAtPoint(request, result, x, y, mtx, mty)) {
+ if (m_markupBox->nodeAtPoint(request, result, x, y, mtx, mty, lineTop, lineBottom)) {
renderer()->updateHitTestResult(result, IntPoint(x - mtx, y - mty));
return true;
}
diff --git a/Source/WebCore/rendering/EllipsisBox.h b/Source/WebCore/rendering/EllipsisBox.h
index ec1b00b..c178cba 100644
--- a/Source/WebCore/rendering/EllipsisBox.h
+++ b/Source/WebCore/rendering/EllipsisBox.h
@@ -39,8 +39,8 @@ public:
{
}
- virtual void paint(PaintInfo&, int tx, int ty);
- virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, int x, int y, int tx, int ty);
+ virtual void paint(PaintInfo&, int tx, int ty, int lineTop, int lineBottom);
+ virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, int x, int y, int tx, int ty, int lineTop, int lineBottom);
void setSelectionState(RenderObject::SelectionState s) { m_selectionState = s; }
IntRect selectionRect(int tx, int ty);
diff --git a/Source/WebCore/rendering/HitTestResult.cpp b/Source/WebCore/rendering/HitTestResult.cpp
index e5638c9..77ccc4b 100644
--- a/Source/WebCore/rendering/HitTestResult.cpp
+++ b/Source/WebCore/rendering/HitTestResult.cpp
@@ -32,6 +32,7 @@
#include "HTMLNames.h"
#include "HTMLParserIdioms.h"
#include "RenderImage.h"
+#include "RenderInline.h"
#include "Scrollbar.h"
#include "SelectionController.h"
@@ -544,6 +545,20 @@ bool HitTestResult::addNodeToRectBasedTestResult(Node* node, int x, int y, const
node = node->shadowAncestorNode();
mutableRectBasedTestResult().add(node);
+ if (node->renderer()->isInline()) {
+ for (RenderObject* curr = node->renderer()->parent(); curr; curr = curr->parent()) {
+ if (!curr->isRenderInline())
+ break;
+
+ // We need to make sure the nodes for culled inlines get included.
+ RenderInline* currInline = toRenderInline(curr);
+ if (currInline->alwaysCreateLineBoxes())
+ break;
+
+ if (currInline->visibleToHitTesting() && currInline->node())
+ mutableRectBasedTestResult().add(currInline->node()->shadowAncestorNode());
+ }
+ }
return !rect.contains(rectForPoint(x, y));
}
@@ -561,6 +576,20 @@ bool HitTestResult::addNodeToRectBasedTestResult(Node* node, int x, int y, const
node = node->shadowAncestorNode();
mutableRectBasedTestResult().add(node);
+ if (node->renderer()->isInline()) {
+ for (RenderObject* curr = node->renderer()->parent(); curr; curr = curr->parent()) {
+ if (!curr->isRenderInline())
+ break;
+
+ // We need to make sure the nodes for culled inlines get included.
+ RenderInline* currInline = toRenderInline(curr);
+ if (currInline->alwaysCreateLineBoxes())
+ break;
+
+ if (currInline->visibleToHitTesting() && currInline->node())
+ mutableRectBasedTestResult().add(currInline->node()->shadowAncestorNode());
+ }
+ }
return !rect.contains(rectForPoint(x, y));
}
diff --git a/Source/WebCore/rendering/InlineBox.cpp b/Source/WebCore/rendering/InlineBox.cpp
index 930071e..f3d3a2d 100644
--- a/Source/WebCore/rendering/InlineBox.cpp
+++ b/Source/WebCore/rendering/InlineBox.cpp
@@ -159,7 +159,7 @@ void InlineBox::adjustPosition(float dx, float dy)
toRenderBox(m_renderer)->move(dx, dy);
}
-void InlineBox::paint(PaintInfo& paintInfo, int tx, int ty)
+void InlineBox::paint(PaintInfo& paintInfo, int tx, int ty, int /* lineTop */, int /*lineBottom*/)
{
if (!paintInfo.shouldPaintWithinRoot(renderer()) || (paintInfo.phase != PaintPhaseForeground && paintInfo.phase != PaintPhaseSelection))
return;
@@ -187,7 +187,7 @@ void InlineBox::paint(PaintInfo& paintInfo, int tx, int ty)
}
}
-bool InlineBox::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, int x, int y, int tx, int ty)
+bool InlineBox::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, int x, int y, int tx, int ty, int /* lineTop */, int /*lineBottom*/)
{
// Hit test all phases of replaced elements atomically, as though the replaced element established its
// own stacking context. (See Appendix E.2, section 6.4 on inline block/table elements in the CSS2.1
@@ -283,6 +283,13 @@ float InlineBox::placeEllipsisBox(bool, float, float, float, bool&)
return -1;
}
+void InlineBox::clearKnownToHaveNoOverflow()
+{
+ m_knownToHaveNoOverflow = false;
+ if (parent() && parent()->knownToHaveNoOverflow())
+ parent()->clearKnownToHaveNoOverflow();
+}
+
FloatPoint InlineBox::locationIncludingFlipping()
{
if (!renderer()->style()->isFlippedBlocksWritingMode())
diff --git a/Source/WebCore/rendering/InlineBox.h b/Source/WebCore/rendering/InlineBox.h
index 9335970..8989a77 100644
--- a/Source/WebCore/rendering/InlineBox.h
+++ b/Source/WebCore/rendering/InlineBox.h
@@ -54,6 +54,7 @@ public:
, m_isHorizontal(true)
, m_endsWithBreak(false)
, m_hasSelectedChildrenOrCanHaveLeadingExpansion(false)
+ , m_knownToHaveNoOverflow(true)
, m_hasEllipsisBoxOrHyphen(false)
, m_dirOverride(false)
, m_isText(false)
@@ -87,7 +88,8 @@ public:
#endif
, m_isHorizontal(isHorizontal)
, m_endsWithBreak(false)
- , m_hasSelectedChildrenOrCanHaveLeadingExpansion(false)
+ , m_hasSelectedChildrenOrCanHaveLeadingExpansion(false)
+ , m_knownToHaveNoOverflow(true)
, m_hasEllipsisBoxOrHyphen(false)
, m_dirOverride(false)
, m_isText(false)
@@ -128,8 +130,8 @@ public:
adjustPosition(delta, 0);
}
- virtual void paint(PaintInfo&, int tx, int ty);
- virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, int x, int y, int tx, int ty);
+ virtual void paint(PaintInfo&, int tx, int ty, int lineTop, int lineBottom);
+ virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, int x, int y, int tx, int ty, int lineTop, int lineBottom);
InlineBox* next() const { return m_next; }
@@ -261,6 +263,8 @@ public:
// The logical height is our extent in the block flow direction, i.e., height for horizontal text and width for vertical text.
int logicalHeight() const;
+ FloatRect logicalFrameRect() const { return isHorizontal() ? IntRect(m_x, m_y, m_logicalWidth, logicalHeight()) : IntRect(m_y, m_x, m_logicalWidth, logicalHeight()); }
+
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); }
@@ -310,6 +314,9 @@ public:
void flipForWritingMode(IntRect&);
IntPoint flipForWritingMode(const IntPoint&);
+ bool knownToHaveNoOverflow() const { return m_knownToHaveNoOverflow; }
+ void clearKnownToHaveNoOverflow();
+
private:
InlineBox* m_next; // The next element on the same line as us.
InlineBox* m_prev; // The previous element on the same line as us.
@@ -342,6 +349,7 @@ protected:
bool m_endsWithBreak : 1; // Whether the line ends with a <br>.
// shared between RootInlineBox and InlineTextBox
bool m_hasSelectedChildrenOrCanHaveLeadingExpansion : 1; // Whether we have any children selected (this bit will also be set if the <br> that terminates our line is selected).
+ bool m_knownToHaveNoOverflow : 1;
bool m_hasEllipsisBoxOrHyphen : 1;
// for InlineTextBox
diff --git a/Source/WebCore/rendering/InlineFlowBox.cpp b/Source/WebCore/rendering/InlineFlowBox.cpp
index b58a30e..045edff 100644
--- a/Source/WebCore/rendering/InlineFlowBox.cpp
+++ b/Source/WebCore/rendering/InlineFlowBox.cpp
@@ -97,7 +97,8 @@ void InlineFlowBox::addToLine(InlineBox* child)
child->setFirstLineStyleBit(m_firstLine);
child->setIsHorizontal(isHorizontal());
if (child->isText()) {
- m_hasTextChildren = true;
+ if (child->renderer()->parent() == renderer())
+ m_hasTextChildren = true;
m_hasTextDescendants = true;
} else if (child->isInlineFlowBox()) {
if (static_cast<InlineFlowBox*>(child)->hasTextDescendants())
@@ -111,12 +112,13 @@ void InlineFlowBox::addToLine(InlineBox* child)
if (child->renderer()->isReplaced())
shouldClearDescendantsHaveSameLineHeightAndBaseline = true;
else if (child->isText()) {
- if (child->renderer()->isBR()) {
- if (parentStyle->font().fontMetrics().ascent() != childStyle->font().fontMetrics().ascent()
- || parentStyle->font().fontMetrics().descent() != childStyle->font().fontMetrics().descent() || parentStyle->lineHeight() != childStyle->lineHeight()
+ if (child->renderer()->isBR() || child->renderer()->parent() != renderer()) {
+ if (!parentStyle->font().fontMetrics().hasIdenticalAscentDescentAndLineGap(childStyle->font().fontMetrics())
+ || parentStyle->lineHeight() != childStyle->lineHeight()
|| (parentStyle->verticalAlign() != BASELINE && !isRootInlineBox()) || childStyle->verticalAlign() != BASELINE)
shouldClearDescendantsHaveSameLineHeightAndBaseline = true;
- } else if (childStyle->hasTextCombine() || childStyle->textEmphasisMark() != TextEmphasisMarkNone)
+ }
+ if (childStyle->hasTextCombine() || childStyle->textEmphasisMark() != TextEmphasisMarkNone)
shouldClearDescendantsHaveSameLineHeightAndBaseline = true;
} else {
if (child->renderer()->isBR()) {
@@ -127,8 +129,9 @@ void InlineFlowBox::addToLine(InlineBox* child)
ASSERT(isInlineFlowBox());
InlineFlowBox* childFlowBox = static_cast<InlineFlowBox*>(child);
// Check the child's bit, and then also check for differences in font, line-height, vertical-align
- if (!childFlowBox->descendantsHaveSameLineHeightAndBaseline() || parentStyle->font().fontMetrics().ascent() != childStyle->font().fontMetrics().ascent()
- || parentStyle->font().fontMetrics().descent() != childStyle->font().fontMetrics().descent() || parentStyle->lineHeight() != childStyle->lineHeight()
+ if (!childFlowBox->descendantsHaveSameLineHeightAndBaseline()
+ || !parentStyle->font().fontMetrics().hasIdenticalAscentDescentAndLineGap(childStyle->font().fontMetrics())
+ || parentStyle->lineHeight() != childStyle->lineHeight()
|| (parentStyle->verticalAlign() != BASELINE && !isRootInlineBox()) || childStyle->verticalAlign() != BASELINE
|| childStyle->hasBorder() || childStyle->hasPadding() || childStyle->hasTextCombine())
shouldClearDescendantsHaveSameLineHeightAndBaseline = true;
@@ -139,6 +142,23 @@ void InlineFlowBox::addToLine(InlineBox* child)
clearDescendantsHaveSameLineHeightAndBaseline();
}
+ if (!child->renderer()->isPositioned()) {
+ if (child->isText()) {
+ RenderStyle* childStyle = child->renderer()->style(m_firstLine);
+ if (childStyle->letterSpacing() < 0 || childStyle->textShadow() || childStyle->textEmphasisMark() != TextEmphasisMarkNone || childStyle->textStrokeWidth())
+ child->clearKnownToHaveNoOverflow();
+ } else if (child->renderer()->isReplaced()) {
+ RenderBox* box = toRenderBox(child->renderer());
+ if (box->hasRenderOverflow() || box->hasSelfPaintingLayer())
+ child->clearKnownToHaveNoOverflow();
+ } else if (!child->renderer()->isBR() && (child->renderer()->style(m_firstLine)->boxShadow() || child->boxModelObject()->hasSelfPaintingLayer()
+ || (child->renderer()->isListMarker() && !toRenderListMarker(child->renderer())->isInside())))
+ child->clearKnownToHaveNoOverflow();
+
+ if (knownToHaveNoOverflow() && child->isInlineFlowBox() && !static_cast<InlineFlowBox*>(child)->knownToHaveNoOverflow())
+ clearKnownToHaveNoOverflow();
+ }
+
checkConsistency();
}
@@ -232,19 +252,21 @@ RenderLineBoxList* InlineFlowBox::rendererLineBoxes() const
return toRenderInline(renderer())->lineBoxes();
}
-bool InlineFlowBox::onEndChain(RenderObject* endObject)
+static inline bool isLastChildForRenderer(RenderObject* ancestor, RenderObject* child)
{
- if (!endObject)
+ if (!child)
return false;
- if (endObject == renderer())
+ if (child == ancestor)
return true;
- RenderObject* curr = endObject;
+ RenderObject* curr = child;
RenderObject* parent = curr->parent();
- while (parent && !parent->isRenderBlock()) {
- if (parent->lastChild() != curr || parent == renderer())
+ while (parent && (!parent->isRenderBlock() || parent->isInline())) {
+ if (parent->lastChild() != curr)
return false;
+ if (parent == ancestor)
+ return true;
curr = parent;
parent = curr->parent();
@@ -256,7 +278,7 @@ bool InlineFlowBox::onEndChain(RenderObject* endObject)
static bool isAnsectorAndWithinBlock(RenderObject* ancestor, RenderObject* child)
{
RenderObject* object = child;
- while (object && !object->isRenderBlock()) {
+ while (object && (!object->isRenderBlock() || object->isInline())) {
if (object == ancestor)
return true;
object = object->parent();
@@ -264,7 +286,7 @@ static bool isAnsectorAndWithinBlock(RenderObject* ancestor, RenderObject* child
return false;
}
-void InlineFlowBox::determineSpacingForFlowBoxes(bool lastLine, RenderObject* endObject, RenderObject* logicallyLastRunRenderer)
+void InlineFlowBox::determineSpacingForFlowBoxes(bool lastLine, bool isLogicallyLastRunWrapped, RenderObject* logicallyLastRunRenderer)
{
// All boxes start off open. They will not apply any margins/border/padding on
// any side.
@@ -287,8 +309,13 @@ void InlineFlowBox::determineSpacingForFlowBoxes(bool lastLine, RenderObject* en
if (!lineBoxList->lastLineBox()->isConstructed()) {
RenderInline* inlineFlow = toRenderInline(renderer());
- bool isLastObjectOnLine = (endObject && endObject->isText()) ? !isAnsectorAndWithinBlock(renderer(), logicallyLastRunRenderer->parent()) : onEndChain(logicallyLastRunRenderer);
+ bool isLastObjectOnLine = !isAnsectorAndWithinBlock(renderer(), logicallyLastRunRenderer) || (isLastChildForRenderer(renderer(), logicallyLastRunRenderer) && !isLogicallyLastRunWrapped);
+ // We include the border under these conditions:
+ // (1) The next line was not created, or it is constructed. We check the previous line for rtl.
+ // (2) The logicallyLastRun is not a descendant of this renderer.
+ // (3) The logicallyLastRun is a descendant of this renderer, but it is the last child of this renderer and it does not wrap to the next line.
+
if (ltr) {
if (!nextLineBox()
&& ((lastLine || isLastObjectOnLine) && !inlineFlow->continuation()))
@@ -307,7 +334,7 @@ void InlineFlowBox::determineSpacingForFlowBoxes(bool lastLine, RenderObject* en
for (InlineBox* currChild = firstChild(); currChild; currChild = currChild->nextOnLine()) {
if (currChild->isInlineFlowBox()) {
InlineFlowBox* currFlow = static_cast<InlineFlowBox*>(currChild);
- currFlow->determineSpacingForFlowBoxes(lastLine, endObject, logicallyLastRunRenderer);
+ currFlow->determineSpacingForFlowBoxes(lastLine, isLogicallyLastRunWrapped, logicallyLastRunRenderer);
}
}
}
@@ -319,7 +346,10 @@ float InlineFlowBox::placeBoxesInInlineDirection(float logicalLeft, bool& needsW
float startLogicalLeft = logicalLeft;
logicalLeft += borderLogicalLeft() + paddingLogicalLeft();
-
+
+ float minLogicalLeft = startLogicalLeft;
+ float maxLogicalRight = logicalLeft;
+
for (InlineBox* curr = firstChild(); curr; curr = curr->nextOnLine()) {
if (curr->renderer()->isText()) {
InlineTextBox* text = static_cast<InlineTextBox*>(curr);
@@ -330,7 +360,11 @@ float InlineFlowBox::placeBoxesInInlineDirection(float logicalLeft, bool& needsW
needsWordSpacing = !isSpaceOrNewline(rt->characters()[text->end()]);
}
text->setLogicalLeft(logicalLeft);
+ if (knownToHaveNoOverflow())
+ minLogicalLeft = min(logicalLeft, minLogicalLeft);
logicalLeft += text->logicalWidth();
+ if (knownToHaveNoOverflow())
+ maxLogicalRight = max(logicalLeft, maxLogicalRight);
} else {
if (curr->renderer()->isPositioned()) {
if (curr->renderer()->parent()->style()->isLeftToRightDirection())
@@ -345,7 +379,11 @@ float InlineFlowBox::placeBoxesInInlineDirection(float logicalLeft, bool& needsW
if (curr->renderer()->isRenderInline()) {
InlineFlowBox* flow = static_cast<InlineFlowBox*>(curr);
logicalLeft += flow->marginLogicalLeft();
+ if (knownToHaveNoOverflow())
+ minLogicalLeft = min(logicalLeft, minLogicalLeft);
logicalLeft = flow->placeBoxesInInlineDirection(logicalLeft, needsWordSpacing, textBoxDataMap);
+ if (knownToHaveNoOverflow())
+ maxLogicalRight = max(logicalLeft, maxLogicalRight);
logicalLeft += flow->marginLogicalRight();
} 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.
@@ -355,13 +393,20 @@ float InlineFlowBox::placeBoxesInInlineDirection(float logicalLeft, bool& needsW
logicalLeft += logicalLeftMargin;
curr->setLogicalLeft(logicalLeft);
- logicalLeft += curr->logicalWidth() + logicalRightMargin;
+ if (knownToHaveNoOverflow())
+ minLogicalLeft = min(logicalLeft, minLogicalLeft);
+ logicalLeft += curr->logicalWidth();
+ if (knownToHaveNoOverflow())
+ maxLogicalRight = max(logicalLeft, maxLogicalRight);
+ logicalLeft += logicalRightMargin;
}
}
}
logicalLeft += borderLogicalRight() + paddingLogicalRight();
setLogicalWidth(logicalLeft - startLogicalLeft);
+ if (knownToHaveNoOverflow() && (minLogicalLeft < startLogicalLeft || maxLogicalRight > logicalLeft))
+ clearKnownToHaveNoOverflow();
return logicalLeft;
}
@@ -631,7 +676,7 @@ void InlineFlowBox::placeBoxesInBlockDirection(int top, int maxHeight, int maxAs
lineBottom = max(lineBottom, newLogicalTop + boxHeight);
lineBottomIncludingMargins = max(lineBottom, max(lineBottomIncludingMargins, newLogicalTopIncludingMargins + boxHeightIncludingMargins));
}
-
+
// Adjust boxes to use their real box y/height and not the logical height (as dictated by
// line-height).
if (inlineFlowBox)
@@ -674,7 +719,7 @@ void InlineFlowBox::flipLinesInBlockDirection(int lineTop, int lineBottom)
}
}
-void InlineFlowBox::addBoxShadowVisualOverflow(IntRect& logicalVisualOverflow)
+inline void InlineFlowBox::addBoxShadowVisualOverflow(IntRect& logicalVisualOverflow)
{
if (!parent())
return; // Box-shadow doesn't apply to root line boxes.
@@ -697,14 +742,15 @@ void InlineFlowBox::addBoxShadowVisualOverflow(IntRect& logicalVisualOverflow)
logicalRightVisualOverflow - logicalLeftVisualOverflow, logicalBottomVisualOverflow - logicalTopVisualOverflow);
}
-void InlineFlowBox::addTextBoxVisualOverflow(const InlineTextBox* textBox, GlyphOverflowAndFallbackFontsMap& textBoxDataMap, IntRect& logicalVisualOverflow)
+inline void InlineFlowBox::addTextBoxVisualOverflow(InlineTextBox* textBox, GlyphOverflowAndFallbackFontsMap& textBoxDataMap, IntRect& logicalVisualOverflow)
{
- RenderStyle* style = renderer()->style(m_firstLine);
- int strokeOverflow = static_cast<int>(ceilf(style->textStrokeWidth() / 2.0f));
+ if (textBox->knownToHaveNoOverflow())
+ return;
+ RenderStyle* style = textBox->renderer()->style(m_firstLine);
+
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;
@@ -712,6 +758,7 @@ void InlineFlowBox::addTextBoxVisualOverflow(const InlineTextBox* textBox, Glyph
int leftGlyphEdge = glyphOverflow ? glyphOverflow->left : 0;
int rightGlyphEdge = glyphOverflow ? glyphOverflow->right : 0;
+ int strokeOverflow = static_cast<int>(ceilf(style->textStrokeWidth() / 2.0f));
int topGlyphOverflow = -strokeOverflow - topGlyphEdge;
int bottomGlyphOverflow = strokeOverflow + bottomGlyphEdge;
int leftGlyphOverflow = -strokeOverflow - leftGlyphEdge;
@@ -728,8 +775,7 @@ void InlineFlowBox::addTextBoxVisualOverflow(const InlineTextBox* textBox, Glyph
// 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;
+ rightGlyphOverflow -= min(0, (int)style->font().letterSpacing());
int textShadowLogicalTop;
int textShadowLogicalBottom;
@@ -752,9 +798,11 @@ void InlineFlowBox::addTextBoxVisualOverflow(const InlineTextBox* textBox, Glyph
logicalVisualOverflow = IntRect(logicalLeftVisualOverflow, logicalTopVisualOverflow,
logicalRightVisualOverflow - logicalLeftVisualOverflow, logicalBottomVisualOverflow - logicalTopVisualOverflow);
+
+ textBox->setLogicalOverflowRect(logicalVisualOverflow);
}
-void InlineFlowBox::addReplacedChildOverflow(const InlineBox* inlineBox, IntRect& logicalLayoutOverflow, IntRect& logicalVisualOverflow)
+inline void InlineFlowBox::addReplacedChildOverflow(const InlineBox* inlineBox, IntRect& logicalLayoutOverflow, IntRect& logicalVisualOverflow)
{
RenderBox* box = toRenderBox(inlineBox->renderer());
@@ -775,17 +823,16 @@ void InlineFlowBox::addReplacedChildOverflow(const InlineBox* inlineBox, IntRect
logicalLayoutOverflow.unite(childLogicalLayoutOverflow);
}
-void InlineFlowBox::computeOverflow(int lineTop, int lineBottom, bool strictMode, GlyphOverflowAndFallbackFontsMap& textBoxDataMap)
+void InlineFlowBox::computeOverflow(int lineTop, int lineBottom, 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(logicalBottom(), lineBottom);
-
+ // If we know we have no overflow, we can just bail.
+ if (knownToHaveNoOverflow())
+ return;
+
// 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(enclosingIntRect(FloatRect(logicalLeft(), topOverflow, logicalWidth(), bottomOverflow - topOverflow)));
+ IntRect logicalLayoutOverflow(enclosingIntRect(logicalFrameRectIncludingLineHeight(lineTop, lineBottom)));
IntRect logicalVisualOverflow(logicalLayoutOverflow);
// box-shadow on root line boxes is applying to the block and not to the lines.
@@ -800,50 +847,40 @@ void InlineFlowBox::computeOverflow(int lineTop, int lineBottom, bool strictMode
RenderText* rt = toRenderText(text->renderer());
if (rt->isBR())
continue;
- addTextBoxVisualOverflow(text, textBoxDataMap, logicalVisualOverflow);
+ IntRect textBoxOverflow(enclosingIntRect(text->logicalFrameRect()));
+ addTextBoxVisualOverflow(text, textBoxDataMap, textBoxOverflow);
+ logicalVisualOverflow.unite(textBoxOverflow);
} else if (curr->renderer()->isRenderInline()) {
InlineFlowBox* flow = static_cast<InlineFlowBox*>(curr);
- flow->computeOverflow(lineTop, lineBottom, strictMode, textBoxDataMap);
+ flow->computeOverflow(lineTop, lineBottom, textBoxDataMap);
if (!flow->boxModelObject()->hasSelfPaintingLayer())
- logicalVisualOverflow.unite(flow->logicalVisualOverflowRect());
- IntRect childLayoutOverflow = flow->logicalLayoutOverflowRect();
+ logicalVisualOverflow.unite(flow->logicalVisualOverflowRect(lineTop, lineBottom));
+ IntRect childLayoutOverflow = flow->logicalLayoutOverflowRect(lineTop, lineBottom);
childLayoutOverflow.move(flow->boxModelObject()->relativePositionLogicalOffset());
logicalLayoutOverflow.unite(childLayoutOverflow);
} else
addReplacedChildOverflow(curr, logicalLayoutOverflow, logicalVisualOverflow);
}
- setOverflowFromLogicalRects(logicalLayoutOverflow, logicalVisualOverflow);
+ setOverflowFromLogicalRects(logicalLayoutOverflow, logicalVisualOverflow, lineTop, lineBottom);
}
-// 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)
+void InlineFlowBox::setLayoutOverflow(const IntRect& rect, int lineTop, int lineBottom)
{
- IntRect frameBox = enclosingIntRect(FloatRect(x(), y(), width(), height()));
- if (frameBox == rect || rect.isEmpty())
+ IntRect frameBox = enclosingIntRect(frameRectIncludingLineHeight(lineTop, lineBottom));
+ if (frameBox.contains(rect) || rect.isEmpty())
return;
-
+
if (!m_overflow)
m_overflow.set(new RenderOverflow(frameBox, frameBox));
m_overflow->setLayoutOverflow(rect);
}
-void InlineFlowBox::setVisualOverflow(const IntRect& rect)
+void InlineFlowBox::setVisualOverflow(const IntRect& rect, int lineTop, int lineBottom)
{
- IntRect frameBox = enclosingIntRect(FloatRect(x(), y(), width(), height()));
- if (frameBox == rect || rect.isEmpty())
+ IntRect frameBox = enclosingIntRect(frameRectIncludingLineHeight(lineTop, lineBottom));
+ if (frameBox.contains(rect) || rect.isEmpty())
return;
if (!m_overflow)
@@ -852,18 +889,18 @@ void InlineFlowBox::setVisualOverflow(const IntRect& rect)
m_overflow->setVisualOverflow(rect);
}
-void InlineFlowBox::setOverflowFromLogicalRects(const IntRect& logicalLayoutOverflow, const IntRect& logicalVisualOverflow)
+void InlineFlowBox::setOverflowFromLogicalRects(const IntRect& logicalLayoutOverflow, const IntRect& logicalVisualOverflow, int lineTop, int lineBottom)
{
IntRect layoutOverflow(isHorizontal() ? logicalLayoutOverflow : logicalLayoutOverflow.transposedRect());
- setLayoutOverflow(layoutOverflow);
+ setLayoutOverflow(layoutOverflow, lineTop, lineBottom);
IntRect visualOverflow(isHorizontal() ? logicalVisualOverflow : logicalVisualOverflow.transposedRect());
- setVisualOverflow(visualOverflow);
+ setVisualOverflow(visualOverflow, lineTop, lineBottom);
}
-bool InlineFlowBox::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, int x, int y, int tx, int ty)
+bool InlineFlowBox::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, int x, int y, int tx, int ty, int lineTop, int lineBottom)
{
- IntRect overflowRect(visualOverflowRect());
+ IntRect overflowRect(visualOverflowRect(lineTop, lineBottom));
flipForWritingMode(overflowRect);
overflowRect.move(tx, ty);
if (!overflowRect.intersects(result.rectForPoint(x, y)))
@@ -871,7 +908,7 @@ bool InlineFlowBox::nodeAtPoint(const HitTestRequest& request, HitTestResult& re
// Check children first.
for (InlineBox* curr = lastChild(); curr; curr = curr->prevOnLine()) {
- if ((curr->renderer()->isText() || !curr->boxModelObject()->hasSelfPaintingLayer()) && curr->nodeAtPoint(request, result, x, y, tx, ty)) {
+ if ((curr->renderer()->isText() || !curr->boxModelObject()->hasSelfPaintingLayer()) && curr->nodeAtPoint(request, result, x, y, tx, ty, lineTop, lineBottom)) {
renderer()->updateHitTestResult(result, IntPoint(x - tx, y - ty));
return true;
}
@@ -909,9 +946,9 @@ bool InlineFlowBox::nodeAtPoint(const HitTestRequest& request, HitTestResult& re
return false;
}
-void InlineFlowBox::paint(PaintInfo& paintInfo, int tx, int ty)
+void InlineFlowBox::paint(PaintInfo& paintInfo, int tx, int ty, int lineTop, int lineBottom)
{
- IntRect overflowRect(visualOverflowRect());
+ IntRect overflowRect(visualOverflowRect(lineTop, lineBottom));
overflowRect.inflate(renderer()->maximalOutlineSize(paintInfo.phase));
flipForWritingMode(overflowRect);
overflowRect.move(tx, ty);
@@ -974,7 +1011,7 @@ void InlineFlowBox::paint(PaintInfo& paintInfo, int tx, int ty)
if (paintPhase != PaintPhaseSelfOutline) {
for (InlineBox* curr = firstChild(); curr; curr = curr->nextOnLine()) {
if (curr->renderer()->isText() || !curr->boxModelObject()->hasSelfPaintingLayer())
- curr->paint(childInfo, tx, ty);
+ curr->paint(childInfo, tx, ty, lineTop, lineBottom);
}
}
}
@@ -992,7 +1029,7 @@ void InlineFlowBox::paintFillLayer(const PaintInfo& paintInfo, const Color& c, c
StyleImage* img = fillLayer->image();
bool hasFillImage = img && img->canRender(renderer()->style()->effectiveZoom());
if ((!hasFillImage && !renderer()->style()->hasBorderRadius()) || (!prevLineBox() && !nextLineBox()) || !parent())
- boxModelObject()->paintFillLayerExtended(paintInfo, c, fillLayer, tx, ty, w, h, this, op);
+ boxModelObject()->paintFillLayerExtended(paintInfo, c, fillLayer, tx, ty, w, h, this, w, h, op);
else {
// We have a fill image that spans multiple lines.
// We need to adjust tx and ty by the width of all previous lines.
@@ -1021,7 +1058,7 @@ void InlineFlowBox::paintFillLayer(const PaintInfo& paintInfo, const Color& c, c
int stripHeight = isHorizontal() ? height() : totalLogicalWidth;
paintInfo.context->save();
paintInfo.context->clip(IntRect(tx, ty, width(), height()));
- boxModelObject()->paintFillLayerExtended(paintInfo, c, fillLayer, stripX, stripY, stripWidth, stripHeight, this, op);
+ boxModelObject()->paintFillLayerExtended(paintInfo, c, fillLayer, stripX, stripY, stripWidth, stripHeight, this, w, h, op);
paintInfo.context->restore();
}
}
diff --git a/Source/WebCore/rendering/InlineFlowBox.h b/Source/WebCore/rendering/InlineFlowBox.h
index 9b6f8e4..9b34e9d 100644
--- a/Source/WebCore/rendering/InlineFlowBox.h
+++ b/Source/WebCore/rendering/InlineFlowBox.h
@@ -105,8 +105,8 @@ public:
void paintFillLayers(const PaintInfo&, const Color&, const FillLayer*, int tx, int ty, int w, int h, CompositeOperator = CompositeSourceOver);
void paintFillLayer(const PaintInfo&, const Color&, const FillLayer*, int tx, int ty, int w, int h, CompositeOperator = CompositeSourceOver);
void paintBoxShadow(GraphicsContext*, RenderStyle*, ShadowStyle, int tx, int ty, int w, int h);
- virtual void paint(PaintInfo&, int tx, int ty);
- virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, int x, int y, int tx, int ty);
+ virtual void paint(PaintInfo&, int tx, int ty, int lineTop, int lineBottom);
+ virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, int x, int y, int tx, int ty, int lineTop, int lineBottom);
virtual RenderLineBoxList* rendererLineBoxes() const;
@@ -159,9 +159,8 @@ public:
}
// Helper functions used during line construction and placement.
- void determineSpacingForFlowBoxes(bool lastLine, RenderObject* endObject, RenderObject* logicallyLastRunRenderer);
+ void determineSpacingForFlowBoxes(bool lastLine, bool isLogicallyLastRunWrapped, RenderObject* logicallyLastRunRenderer);
int getFlowSpacingLogicalWidth();
- bool onEndChain(RenderObject* endObject);
float placeBoxesInInlineDirection(float logicalLeft, bool& needsWordSpacing, GlyphOverflowAndFallbackFontsMap&);
void computeLogicalBoxHeights(RootInlineBox*, int& maxPositionTop, int& maxPositionBottom,
int& maxAscent, int& maxDescent, bool& setMaxAscent, bool& setMaxDescent,
@@ -176,7 +175,7 @@ public:
int computeOverAnnotationAdjustment(int allowedPosition) const;
int computeUnderAnnotationAdjustment(int allowedPosition) const;
- void computeOverflow(int lineTop, int lineBottom, bool strictMode, GlyphOverflowAndFallbackFontsMap&);
+ void computeOverflow(int lineTop, int lineBottom, GlyphOverflowAndFallbackFontsMap&);
void removeChild(InlineBox* child);
@@ -194,44 +193,74 @@ public:
// Line visual and layout overflow are in the coordinate space of the block. This means that they 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 flipped when compared to their physical counterparts. For example minX is on the left in vertical-lr, but it is on the right in vertical-rl.
- int minYLayoutOverflow() const { return m_overflow ? m_overflow->minYLayoutOverflow() : m_y; }
- int maxYLayoutOverflow() const { return m_overflow ? m_overflow->maxYLayoutOverflow() : ceilf(m_y + height()); }
- int minXLayoutOverflow() const { return m_overflow ? m_overflow->minXLayoutOverflow() : m_x; }
- int maxXLayoutOverflow() const { return m_overflow ? m_overflow->maxXLayoutOverflow() : ceilf(m_x + width()); }
- IntRect layoutOverflowRect() const { return m_overflow ? m_overflow->layoutOverflowRect() : enclosingIntRect(FloatRect(m_x, m_y, width(), height())); }
- int logicalLeftLayoutOverflow() const { return renderer()->style()->isHorizontalWritingMode() ? minXLayoutOverflow() : minYLayoutOverflow(); }
- int logicalRightLayoutOverflow() const { return renderer()->style()->isHorizontalWritingMode() ? maxXLayoutOverflow() : maxYLayoutOverflow(); }
- int logicalTopLayoutOverflow() const { return renderer()->style()->isHorizontalWritingMode() ? minYVisualOverflow() : minXVisualOverflow(); }
- int logicalBottomLayoutOverflow() const { return renderer()->style()->isHorizontalWritingMode() ? maxYLayoutOverflow() : maxXLayoutOverflow(); }
- IntRect logicalLayoutOverflowRect() const
+ IntRect layoutOverflowRect(int lineTop, int lineBottom) const
+ {
+ return m_overflow ? m_overflow->layoutOverflowRect() : enclosingIntRect(frameRectIncludingLineHeight(lineTop, lineBottom));
+ }
+ int logicalLeftLayoutOverflow() const { return m_overflow ? (isHorizontal() ? m_overflow->minXLayoutOverflow() : m_overflow->minYLayoutOverflow()) : logicalLeft(); }
+ int logicalRightLayoutOverflow() const { return m_overflow ? (isHorizontal() ? m_overflow->maxXLayoutOverflow() : m_overflow->maxYLayoutOverflow()) : ceilf(logicalRight()); }
+ int logicalTopLayoutOverflow(int lineTop) const
{
- IntRect result = layoutOverflowRect();
- if (!renderer()->style()->isHorizontalWritingMode())
+ if (m_overflow)
+ return isHorizontal() ? m_overflow->minYLayoutOverflow() : m_overflow->minXLayoutOverflow();
+ return lineTop;
+ }
+ int logicalBottomLayoutOverflow(int lineBottom) const
+ {
+ if (m_overflow)
+ return isHorizontal() ? m_overflow->maxYLayoutOverflow() : m_overflow->maxXLayoutOverflow();
+ return lineBottom;
+ }
+ IntRect logicalLayoutOverflowRect(int lineTop, int lineBottom) const
+ {
+ IntRect result = layoutOverflowRect(lineTop, lineBottom);
+ if (!renderer()->isHorizontalWritingMode())
result = result.transposedRect();
return result;
}
- int minYVisualOverflow() const { return m_overflow ? m_overflow->minYVisualOverflow() : m_y; }
- int maxYVisualOverflow() const { return m_overflow ? m_overflow->maxYVisualOverflow() : ceilf(m_y + height()); }
- int minXVisualOverflow() const { return m_overflow ? m_overflow->minXVisualOverflow() : m_x; }
- int maxXVisualOverflow() const { return m_overflow ? m_overflow->maxXVisualOverflow() : ceilf(m_x + width()); }
- IntRect visualOverflowRect() const { return m_overflow ? m_overflow->visualOverflowRect() : enclosingIntRect(FloatRect(m_x, m_y, width(), height())); }
- int logicalLeftVisualOverflow() const { return renderer()->style()->isHorizontalWritingMode() ? minXVisualOverflow() : minYVisualOverflow(); }
- int logicalRightVisualOverflow() const { return renderer()->style()->isHorizontalWritingMode() ? maxXVisualOverflow() : maxYVisualOverflow(); }
- int logicalTopVisualOverflow() const { return renderer()->style()->isHorizontalWritingMode() ? minYVisualOverflow() : minXVisualOverflow(); }
- int logicalBottomVisualOverflow() const { return renderer()->style()->isHorizontalWritingMode() ? maxYVisualOverflow() : maxXVisualOverflow(); }
- IntRect logicalVisualOverflowRect() const
+ IntRect visualOverflowRect(int lineTop, int lineBottom) const
+ {
+ return m_overflow ? m_overflow->visualOverflowRect() : enclosingIntRect(frameRectIncludingLineHeight(lineTop, lineBottom));
+ }
+ int logicalLeftVisualOverflow() const { return m_overflow ? (isHorizontal() ? m_overflow->minXVisualOverflow() : m_overflow->minYVisualOverflow()) : logicalLeft(); }
+ int logicalRightVisualOverflow() const { return m_overflow ? (isHorizontal() ? m_overflow->maxXVisualOverflow() : m_overflow->maxYVisualOverflow()) : ceilf(logicalRight()); }
+ int logicalTopVisualOverflow(int lineTop) const
+ {
+ if (m_overflow)
+ return isHorizontal() ? m_overflow->minYVisualOverflow() : m_overflow->minXVisualOverflow();
+ return lineTop;
+ }
+ int logicalBottomVisualOverflow(int lineBottom) const
+ {
+ if (m_overflow)
+ return isHorizontal() ? m_overflow->maxYVisualOverflow() : m_overflow->maxXVisualOverflow();
+ return lineBottom;
+ }
+ IntRect logicalVisualOverflowRect(int lineTop, int lineBottom) const
{
- IntRect result = visualOverflowRect();
- if (!renderer()->style()->isHorizontalWritingMode())
+ IntRect result = visualOverflowRect(lineTop, lineBottom);
+ if (!renderer()->isHorizontalWritingMode())
result = result.transposedRect();
return result;
}
- void setOverflowFromLogicalRects(const IntRect& logicalLayoutOverflow, const IntRect& logicalVisualOverflow);
- void setLayoutOverflow(const IntRect&);
- void setVisualOverflow(const IntRect&);
+ void setOverflowFromLogicalRects(const IntRect& logicalLayoutOverflow, const IntRect& logicalVisualOverflow, int lineTop, int lineBottom);
+ void setLayoutOverflow(const IntRect&, int lineTop, int lineBottom);
+ void setVisualOverflow(const IntRect&, int lineTop, int lineBottom);
+ FloatRect frameRectIncludingLineHeight(int lineTop, int lineBottom) const
+ {
+ if (isHorizontal())
+ return FloatRect(m_x, lineTop, width(), lineBottom - lineTop);
+ return FloatRect(lineTop, m_y, lineBottom - lineTop, height());
+ }
+
+ FloatRect logicalFrameRectIncludingLineHeight(int lineTop, int lineBottom) const
+ {
+ return FloatRect(logicalLeft(), lineTop, logicalWidth(), lineBottom - lineTop);
+ }
+
bool descendantsHaveSameLineHeightAndBaseline() const { return m_descendantsHaveSameLineHeightAndBaseline; }
void clearDescendantsHaveSameLineHeightAndBaseline()
{
@@ -242,7 +271,7 @@ public:
private:
void addBoxShadowVisualOverflow(IntRect& logicalVisualOverflow);
- void addTextBoxVisualOverflow(const InlineTextBox*, GlyphOverflowAndFallbackFontsMap&, IntRect& logicalVisualOverflow);
+ void addTextBoxVisualOverflow(InlineTextBox*, GlyphOverflowAndFallbackFontsMap&, IntRect& logicalVisualOverflow);
void addReplacedChildOverflow(const InlineBox*, IntRect& logicalLayoutOverflow, IntRect& logicalVisualOverflow);
protected:
diff --git a/Source/WebCore/rendering/InlineIterator.h b/Source/WebCore/rendering/InlineIterator.h
index 75d9763..1f6b21c 100644
--- a/Source/WebCore/rendering/InlineIterator.h
+++ b/Source/WebCore/rendering/InlineIterator.h
@@ -34,15 +34,15 @@ namespace WebCore {
class InlineIterator {
public:
InlineIterator()
- : m_block(0)
+ : m_root(0)
, m_obj(0)
, m_pos(0)
, m_nextBreakablePosition(-1)
{
}
- InlineIterator(RenderBlock* b, RenderObject* o, unsigned p)
- : m_block(b)
+ InlineIterator(RenderObject* root, RenderObject* o, unsigned p)
+ : m_root(root)
, m_obj(o)
, m_pos(p)
, m_nextBreakablePosition(-1)
@@ -63,13 +63,30 @@ public:
m_nextBreakablePosition = nextBreak;
}
- void increment(InlineBidiResolver* resolver = 0);
+ RenderObject* root() const { return m_root; }
+
+ void increment(InlineBidiResolver* = 0);
bool atEnd() const;
+ inline bool atTextParagraphSeparator()
+ {
+ return m_obj && m_obj->preservesNewline() && m_obj->isText() && toRenderText(m_obj)->textLength()
+ && !toRenderText(m_obj)->isWordBreak() && toRenderText(m_obj)->characters()[m_pos] == '\n';
+ }
+
+ inline bool atParagraphSeparator()
+ {
+ return (m_obj && m_obj->isBR()) || atTextParagraphSeparator();
+ }
+
UChar current() const;
ALWAYS_INLINE WTF::Unicode::Direction direction() const;
- RenderBlock* m_block;
+private:
+ RenderObject* m_root;
+
+ // FIXME: These should be private.
+public:
RenderObject* m_obj;
unsigned m_pos;
int m_nextBreakablePosition;
@@ -117,7 +134,7 @@ static inline void notifyResolverWillExitObject(InlineBidiResolver* resolver, Re
// FIXME: This function is misleadingly named. It has little to do with bidi.
// This function will iterate over inlines within a block, optionally notifying
// a bidi resolver as it enters/exits inlines (so it can push/pop embedding levels).
-static inline RenderObject* bidiNext(RenderBlock* block, RenderObject* current, InlineBidiResolver* resolver = 0, bool skipInlines = true, bool* endOfInlinePtr = 0)
+static inline RenderObject* bidiNext(RenderObject* root, RenderObject* current, InlineBidiResolver* resolver = 0, bool skipInlines = true, bool* endOfInlinePtr = 0)
{
RenderObject* next = 0;
bool oldEndOfInline = endOfInlinePtr ? *endOfInlinePtr : false;
@@ -137,7 +154,7 @@ static inline RenderObject* bidiNext(RenderBlock* block, RenderObject* current,
break;
}
- while (current && current != block) {
+ while (current && current != root) {
notifyResolverWillExitObject(resolver, current);
next = current->nextSibling();
@@ -147,7 +164,7 @@ static inline RenderObject* bidiNext(RenderBlock* block, RenderObject* current,
}
current = current->parent();
- if (!skipInlines && current && current != block && current->isRenderInline()) {
+ if (!skipInlines && current && current != root && current->isRenderInline()) {
next = current;
endOfInline = true;
break;
@@ -171,16 +188,16 @@ static inline RenderObject* bidiNext(RenderBlock* block, RenderObject* current,
return next;
}
-static inline RenderObject* bidiFirst(RenderBlock* block, InlineBidiResolver* resolver, bool skipInlines = true)
+static inline RenderObject* bidiFirst(RenderObject* root, InlineBidiResolver* resolver, bool skipInlines = true)
{
- if (!block->firstChild())
+ if (!root->firstChild())
return 0;
- RenderObject* o = block->firstChild();
+ RenderObject* o = root->firstChild();
if (o->isRenderInline()) {
notifyResolverEnteredObject(resolver, o);
if (skipInlines && o->firstChild())
- o = bidiNext(block, o, resolver, skipInlines);
+ o = bidiNext(root, o, resolver, skipInlines);
else {
// Never skip empty inlines.
if (resolver)
@@ -190,7 +207,7 @@ static inline RenderObject* bidiFirst(RenderBlock* block, InlineBidiResolver* re
}
if (o && !o->isText() && !o->isReplaced() && !o->isFloating() && !o->isPositioned())
- o = bidiNext(block, o, resolver, skipInlines);
+ o = bidiNext(root, o, resolver, skipInlines);
if (resolver)
resolver->commitExplicitEmbedding();
@@ -207,7 +224,7 @@ inline void InlineIterator::increment(InlineBidiResolver* resolver)
return;
}
// bidiNext can return 0, so use moveTo instead of moveToStartOf
- moveTo(bidiNext(m_block, m_obj, resolver), 0);
+ moveTo(bidiNext(m_root, m_obj, resolver), 0);
}
inline bool InlineIterator::atEnd() const
@@ -247,13 +264,13 @@ inline void InlineBidiResolver::increment()
template <>
inline void InlineBidiResolver::appendRun()
{
- if (!emptyRun && !m_eor.atEnd()) {
+ if (!m_emptyRun && !m_eor.atEnd()) {
int start = m_sor.m_pos;
RenderObject* obj = m_sor.m_obj;
while (obj && obj != m_eor.m_obj && obj != endOfLine.m_obj) {
- RenderBlock::appendRunsForObject(start, obj->length(), obj, *this);
+ RenderBlock::appendRunsForObject(m_runs, start, obj->length(), obj, *this);
start = 0;
- obj = bidiNext(m_sor.m_block, obj);
+ obj = bidiNext(m_sor.root(), obj);
}
if (obj) {
unsigned pos = obj == m_eor.m_obj ? m_eor.m_pos : UINT_MAX;
@@ -263,9 +280,9 @@ inline void InlineBidiResolver::appendRun()
}
// It's OK to add runs for zero-length RenderObjects, just don't make the run larger than it should be
int end = obj->length() ? pos + 1 : 0;
- RenderBlock::appendRunsForObject(start, end, obj, *this);
+ RenderBlock::appendRunsForObject(m_runs, start, end, obj, *this);
}
-
+
m_eor.increment();
m_sor = m_eor;
}
diff --git a/Source/WebCore/rendering/InlineTextBox.cpp b/Source/WebCore/rendering/InlineTextBox.cpp
index b614f0f..5815b8b 100644
--- a/Source/WebCore/rendering/InlineTextBox.cpp
+++ b/Source/WebCore/rendering/InlineTextBox.cpp
@@ -48,20 +48,49 @@ using namespace std;
namespace WebCore {
+typedef WTF::HashMap<const InlineTextBox*, IntRect> InlineTextBoxOverflowMap;
+static InlineTextBoxOverflowMap* gTextBoxesWithOverflow;
+
+void InlineTextBox::destroy(RenderArena* arena)
+{
+ if (!m_knownToHaveNoOverflow && gTextBoxesWithOverflow)
+ gTextBoxesWithOverflow->remove(this);
+ InlineBox::destroy(arena);
+}
+
+IntRect InlineTextBox::logicalOverflowRect() const
+{
+ if (m_knownToHaveNoOverflow || !gTextBoxesWithOverflow)
+ return enclosingIntRect(logicalFrameRect());
+ return gTextBoxesWithOverflow->get(this);
+}
+
+void InlineTextBox::setLogicalOverflowRect(const IntRect& rect)
+{
+ ASSERT(!m_knownToHaveNoOverflow);
+ if (!gTextBoxesWithOverflow)
+ gTextBoxesWithOverflow = new InlineTextBoxOverflowMap;
+ gTextBoxesWithOverflow->add(this, rect);
+}
+
int InlineTextBox::baselinePosition(FontBaseline baselineType) const
{
if (!isText() || !parent())
return 0;
- return parent()->baselinePosition(baselineType);
+ if (parent()->renderer() == renderer()->parent())
+ return parent()->baselinePosition(baselineType);
+ return toRenderBoxModelObject(renderer()->parent())->baselinePosition(baselineType, m_firstLine, isHorizontal() ? HorizontalLine : VerticalLine, PositionOnContainingLine);
}
int InlineTextBox::lineHeight() const
{
- if (!isText() || !parent())
+ if (!isText() || !renderer()->parent())
return 0;
if (m_renderer->isBR())
return toRenderBR(m_renderer)->lineHeight(m_firstLine);
- return parent()->lineHeight();
+ if (parent()->renderer() == renderer()->parent())
+ return parent()->lineHeight();
+ return toRenderBoxModelObject(renderer()->parent())->lineHeight(m_firstLine, isHorizontal() ? HorizontalLine : VerticalLine, PositionOnContainingLine);
}
int InlineTextBox::selectionTop()
@@ -314,7 +343,7 @@ bool InlineTextBox::isLineBreak() const
return renderer()->isBR() || (renderer()->style()->preserveNewline() && len() == 1 && (*textRenderer()->text())[start()] == '\n');
}
-bool InlineTextBox::nodeAtPoint(const HitTestRequest&, HitTestResult& result, int x, int y, int tx, int ty)
+bool InlineTextBox::nodeAtPoint(const HitTestRequest&, HitTestResult& result, int x, int y, int tx, int ty, int /* lineTop */, int /*lineBottom*/)
{
if (isLineBreak())
return false;
@@ -435,7 +464,7 @@ static inline AffineTransform rotation(const FloatRect& boxRect, RotationDirecti
: AffineTransform(0, -1, 1, 0, boxRect.x() - boxRect.maxY(), boxRect.x() + boxRect.maxY());
}
-void InlineTextBox::paint(PaintInfo& paintInfo, int tx, int ty)
+void InlineTextBox::paint(PaintInfo& paintInfo, int tx, int ty, int /*lineTop*/, int /*lineBottom*/)
{
if (isLineBreak() || !paintInfo.shouldPaintWithinRoot(renderer()) || renderer()->style()->visibility() != VISIBLE ||
m_truncation == cFullTruncation || paintInfo.phase == PaintPhaseOutline || !m_len)
@@ -443,12 +472,10 @@ void InlineTextBox::paint(PaintInfo& paintInfo, int tx, int ty)
ASSERT(paintInfo.phase != PaintPhaseSelfOutline && paintInfo.phase != PaintPhaseChildOutlines);
- // FIXME: Technically we're potentially incorporating other visual overflow that had nothing to do with us.
- // Would it be simpler to just check our own shadow and stroke overflow by hand here?
- int logicalLeftOverflow = parent()->logicalLeft() - parent()->logicalLeftVisualOverflow();
- int logicalRightOverflow = parent()->logicalRightVisualOverflow() - (parent()->logicalLeft() + parent()->logicalWidth());
- int logicalStart = logicalLeft() - logicalLeftOverflow + (isHorizontal() ? tx : ty);
- int logicalExtent = logicalWidth() + logicalLeftOverflow + logicalRightOverflow;
+ int logicalLeftSide = logicalLeftVisualOverflow();
+ int logicalRightSide = logicalRightVisualOverflow();
+ int logicalStart = logicalLeftSide + (isHorizontal() ? tx : ty);
+ int logicalExtent = logicalRightSide - logicalLeftSide;
int paintEnd = isHorizontal() ? paintInfo.rect.maxX() : paintInfo.rect.maxY();
int paintStart = isHorizontal() ? paintInfo.rect.x() : paintInfo.rect.y();
diff --git a/Source/WebCore/rendering/InlineTextBox.h b/Source/WebCore/rendering/InlineTextBox.h
index 98a1b78..1878c9f 100644
--- a/Source/WebCore/rendering/InlineTextBox.h
+++ b/Source/WebCore/rendering/InlineTextBox.h
@@ -51,6 +51,8 @@ public:
{
}
+ virtual void destroy(RenderArena*);
+
InlineTextBox* prevTextBox() const { return m_prevTextBox; }
InlineTextBox* nextTextBox() const { return m_nextTextBox; }
void setNextTextBox(InlineTextBox* n) { m_nextTextBox = n; }
@@ -80,6 +82,13 @@ public:
bool getEmphasisMarkPosition(RenderStyle*, TextEmphasisPosition&) const;
+ IntRect logicalOverflowRect() const;
+ void setLogicalOverflowRect(const IntRect&);
+ int logicalTopVisualOverflow() const { return logicalOverflowRect().y(); }
+ int logicalBottomVisualOverflow() const { return logicalOverflowRect().maxY(); }
+ int logicalLeftVisualOverflow() const { return logicalOverflowRect().x(); }
+ int logicalRightVisualOverflow() const { return logicalOverflowRect().maxX(); }
+
private:
int selectionTop();
int selectionBottom();
@@ -93,8 +102,8 @@ public:
void selectionStartEnd(int& sPos, int& ePos);
protected:
- virtual void paint(PaintInfo&, int tx, int ty);
- virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, int x, int y, int tx, int ty);
+ virtual void paint(PaintInfo&, int tx, int ty, int lineTop, int lineBottom);
+ virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, int x, int y, int tx, int ty, int lineTop, int lineBottom);
public:
RenderText* textRenderer() const;
diff --git a/Source/WebCore/rendering/MediaControlElements.cpp b/Source/WebCore/rendering/MediaControlElements.cpp
deleted file mode 100644
index 07df4d9..0000000
--- a/Source/WebCore/rendering/MediaControlElements.cpp
+++ /dev/null
@@ -1,1130 +0,0 @@
-/*
- * Copyright (C) 2008, 2009, 2010 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
- * its contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-
-#if ENABLE(VIDEO)
-
-#include "MediaControlElements.h"
-
-#include "CSSStyleSelector.h"
-#include "EventNames.h"
-#include "FloatConversion.h"
-#include "Frame.h"
-#include "HTMLNames.h"
-#include "LocalizedStrings.h"
-#include "MediaControls.h"
-#include "MouseEvent.h"
-#include "Page.h"
-#include "RenderFlexibleBox.h"
-#include "RenderMedia.h"
-#include "RenderSlider.h"
-#include "RenderTheme.h"
-#include "RenderView.h"
-#include "Settings.h"
-
-namespace WebCore {
-
-using namespace HTMLNames;
-
-HTMLMediaElement* toParentMediaElement(RenderObject* o)
-{
- Node* node = o->node();
- Node* mediaNode = node ? node->shadowAncestorNode() : 0;
- if (!mediaNode || (!mediaNode->hasTagName(HTMLNames::videoTag) && !mediaNode->hasTagName(HTMLNames::audioTag)))
- return 0;
-
- return static_cast<HTMLMediaElement*>(mediaNode);
-}
-
-// FIXME: These constants may need to be tweaked to better match the seeking in the QuickTime plug-in.
-static const float cSeekRepeatDelay = 0.1f;
-static const float cStepTime = 0.07f;
-static const float cSeekTime = 0.2f;
-
-inline MediaControlShadowRootElement::MediaControlShadowRootElement(HTMLMediaElement* mediaElement)
- : HTMLDivElement(divTag, mediaElement->document())
-{
- setShadowHost(mediaElement);
-}
-
-PassRefPtr<MediaControlShadowRootElement> MediaControlShadowRootElement::create(HTMLMediaElement* mediaElement)
-{
- RefPtr<MediaControlShadowRootElement> element = adoptRef(new MediaControlShadowRootElement(mediaElement));
-
- RefPtr<RenderStyle> rootStyle = RenderStyle::create();
- rootStyle->inheritFrom(mediaElement->renderer()->style());
- rootStyle->setDisplay(BLOCK);
- rootStyle->setPosition(RelativePosition);
-
- RenderMediaControlShadowRoot* renderer = new (mediaElement->renderer()->renderArena()) RenderMediaControlShadowRoot(element.get());
- renderer->setStyle(rootStyle.release());
-
- element->setRenderer(renderer);
- element->setAttached();
- element->setInDocument();
-
- return element.release();
-}
-
-void MediaControlShadowRootElement::detach()
-{
- HTMLDivElement::detach();
- // FIXME: Remove once shadow DOM uses Element::setShadowRoot().
- setShadowHost(0);
-}
-
-// ----------------------------
-
-MediaControlElement::MediaControlElement(HTMLMediaElement* mediaElement)
- : HTMLDivElement(divTag, mediaElement->document())
- , m_mediaElement(mediaElement)
-{
- setInDocument();
-}
-
-void MediaControlElement::attachToParent(Element* parent)
-{
- // 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->parserAddChild(this);
-}
-
-void MediaControlElement::update()
-{
- if (renderer())
- renderer()->updateFromElement();
- updateStyle();
-}
-
-PassRefPtr<RenderStyle> MediaControlElement::styleForElement()
-{
- ASSERT(m_mediaElement->renderer());
- RefPtr<RenderStyle> style = document()->styleSelector()->styleForElement(this, m_mediaElement->renderer()->style(), true);
- if (!style)
- return 0;
-
- // text-decoration can't be overrided from CSS. So we do it here.
- // See https://bugs.webkit.org/show_bug.cgi?id=27015
- style->setTextDecoration(TDNONE);
- style->setTextDecorationsInEffect(TDNONE);
-
- return style;
-}
-
-bool MediaControlElement::rendererIsNeeded(RenderStyle* style)
-{
- ASSERT(document()->page());
-
- return HTMLDivElement::rendererIsNeeded(style) && parentNode() && parentNode()->renderer()
- && (!style->hasAppearance() || document()->page()->theme()->shouldRenderMediaControlPart(style->appearance(), m_mediaElement));
-}
-
-void MediaControlElement::attach()
-{
- RefPtr<RenderStyle> style = styleForElement();
- if (!style)
- return;
- bool needsRenderer = rendererIsNeeded(style.get());
- if (!needsRenderer)
- return;
- RenderObject* renderer = createRenderer(m_mediaElement->renderer()->renderArena(), style.get());
- if (!renderer)
- return;
- renderer->setStyle(style.get());
- setRenderer(renderer);
- if (parentNode() && parentNode()->renderer()) {
- // Find next sibling with a renderer to determine where to insert.
- Node* sibling = nextSibling();
- while (sibling && !sibling->renderer())
- sibling = sibling->nextSibling();
- parentNode()->renderer()->addChild(renderer, sibling ? sibling->renderer() : 0);
- }
- ContainerNode::attach();
-}
-
-void MediaControlElement::updateStyle()
-{
- if (!m_mediaElement || !m_mediaElement->renderer())
- return;
-
- RefPtr<RenderStyle> style = styleForElement();
- if (!style)
- return;
-
- bool needsRenderer = rendererIsNeeded(style.get()) && parentNode() && parentNode()->renderer();
- if (renderer() && !needsRenderer)
- detach();
- else if (!renderer() && needsRenderer)
- attach();
- else if (renderer()) {
- renderer()->setStyle(style.get());
-
- // Make sure that if there is any innerText renderer, it is updated as well.
- if (firstChild() && firstChild()->renderer())
- firstChild()->renderer()->setStyle(style.get());
- }
-}
-
-// ----------------------------
-
-inline MediaControlPanelElement::MediaControlPanelElement(HTMLMediaElement* mediaElement)
- : MediaControlElement(mediaElement)
-{
-}
-
-PassRefPtr<MediaControlPanelElement> MediaControlPanelElement::create(HTMLMediaElement* mediaElement)
-{
- return adoptRef(new MediaControlPanelElement(mediaElement));
-}
-
-MediaControlElementType MediaControlPanelElement::displayType() const
-{
- return MediaControlsPanel;
-}
-
-const AtomicString& MediaControlPanelElement::shadowPseudoId() const
-{
- DEFINE_STATIC_LOCAL(AtomicString, id, ("-webkit-media-controls-panel"));
- return id;
-}
-
-// ----------------------------
-
-inline MediaControlTimelineContainerElement::MediaControlTimelineContainerElement(HTMLMediaElement* mediaElement)
- : MediaControlElement(mediaElement)
-{
-}
-
-PassRefPtr<MediaControlTimelineContainerElement> MediaControlTimelineContainerElement::create(HTMLMediaElement* mediaElement)
-{
- return adoptRef(new MediaControlTimelineContainerElement(mediaElement));
-}
-
-bool MediaControlTimelineContainerElement::rendererIsNeeded(RenderStyle* style)
-{
- if (!MediaControlElement::rendererIsNeeded(style))
- return false;
-
- // Always show the timeline if the theme doesn't use status display (MediaControllerThemeClassic, for instance).
- if (!document()->page()->theme()->usesMediaControlStatusDisplay())
- return true;
-
- float duration = mediaElement()->duration();
- return !isnan(duration) && !isinf(duration);
-}
-
-MediaControlElementType MediaControlTimelineContainerElement::displayType() const
-{
- return MediaTimelineContainer;
-}
-
-const AtomicString& MediaControlTimelineContainerElement::shadowPseudoId() const
-{
- DEFINE_STATIC_LOCAL(AtomicString, id, ("-webkit-media-controls-timeline-container"));
- return id;
-}
-
-// ----------------------------
-
-class RenderMediaVolumeSliderContainer : public RenderBlock {
-public:
- RenderMediaVolumeSliderContainer(Node*);
-
-private:
- virtual void layout();
-};
-
-RenderMediaVolumeSliderContainer::RenderMediaVolumeSliderContainer(Node* node)
- : RenderBlock(node)
-{
-}
-
-void RenderMediaVolumeSliderContainer::layout()
-{
- RenderBlock::layout();
- if (style()->display() == NONE || !previousSibling() || !previousSibling()->isBox())
- return;
-
- RenderBox* buttonBox = toRenderBox(previousSibling());
-
- if (view())
- view()->disableLayoutState();
-
- IntPoint offset = theme()->volumeSliderOffsetFromMuteButton(buttonBox, IntSize(width(), height()));
- setX(offset.x() + buttonBox->offsetLeft());
- setY(offset.y() + buttonBox->offsetTop());
-
- if (view())
- view()->enableLayoutState();
-}
-
-inline MediaControlVolumeSliderContainerElement::MediaControlVolumeSliderContainerElement(HTMLMediaElement* mediaElement)
- : MediaControlElement(mediaElement)
- , m_isVisible(false)
-{
-}
-
-PassRefPtr<MediaControlVolumeSliderContainerElement> MediaControlVolumeSliderContainerElement::create(HTMLMediaElement* mediaElement)
-{
- return adoptRef(new MediaControlVolumeSliderContainerElement(mediaElement));
-}
-
-RenderObject* MediaControlVolumeSliderContainerElement::createRenderer(RenderArena* arena, RenderStyle*)
-{
- return new (arena) RenderMediaVolumeSliderContainer(this);
-}
-
-PassRefPtr<RenderStyle> MediaControlVolumeSliderContainerElement::styleForElement()
-{
- RefPtr<RenderStyle> style = MediaControlElement::styleForElement();
- style->setPosition(AbsolutePosition);
- style->setDisplay(m_isVisible ? BLOCK : NONE);
- return style;
-}
-
-void MediaControlVolumeSliderContainerElement::setVisible(bool visible)
-{
- if (visible == m_isVisible)
- return;
- m_isVisible = visible;
-}
-
-bool MediaControlVolumeSliderContainerElement::hitTest(const IntPoint& absPoint)
-{
- if (renderer() && renderer()->style()->hasAppearance())
- return renderer()->theme()->hitTestMediaControlPart(renderer(), absPoint);
-
- return false;
-}
-
-MediaControlElementType MediaControlVolumeSliderContainerElement::displayType() const
-{
- return MediaVolumeSliderContainer;
-}
-
-const AtomicString& MediaControlVolumeSliderContainerElement::shadowPseudoId() const
-{
- DEFINE_STATIC_LOCAL(AtomicString, id, ("-webkit-media-controls-volume-slider-container"));
- return id;
-}
-
-// ----------------------------
-
-inline MediaControlStatusDisplayElement::MediaControlStatusDisplayElement(HTMLMediaElement* mediaElement)
- : MediaControlElement(mediaElement)
- , m_stateBeingDisplayed(Nothing)
-{
-}
-
-PassRefPtr<MediaControlStatusDisplayElement> MediaControlStatusDisplayElement::create(HTMLMediaElement* mediaElement)
-{
- return adoptRef(new MediaControlStatusDisplayElement(mediaElement));
-}
-
-void MediaControlStatusDisplayElement::update()
-{
- MediaControlElement::update();
-
- // Get the new state that we'll have to display.
- StateBeingDisplayed newStateToDisplay = Nothing;
-
- if (mediaElement()->readyState() != HTMLMediaElement::HAVE_ENOUGH_DATA && !mediaElement()->currentSrc().isEmpty())
- newStateToDisplay = Loading;
- else if (mediaElement()->movieLoadType() == MediaPlayer::LiveStream)
- newStateToDisplay = LiveBroadcast;
-
- // Propagate only if needed.
- if (newStateToDisplay == m_stateBeingDisplayed)
- return;
- m_stateBeingDisplayed = newStateToDisplay;
-
- ExceptionCode e;
- switch (m_stateBeingDisplayed) {
- case Nothing:
- setInnerText("", e);
- break;
- case Loading:
- setInnerText(mediaElementLoadingStateText(), e);
- break;
- case LiveBroadcast:
- setInnerText(mediaElementLiveBroadcastStateText(), e);
- break;
- }
-}
-
-bool MediaControlStatusDisplayElement::rendererIsNeeded(RenderStyle* style)
-{
- if (!MediaControlElement::rendererIsNeeded(style) || !document()->page()->theme()->usesMediaControlStatusDisplay())
- return false;
- float duration = mediaElement()->duration();
- return (isnan(duration) || isinf(duration));
-}
-
-MediaControlElementType MediaControlStatusDisplayElement::displayType() const
-{
- return MediaStatusDisplay;
-}
-
-const AtomicString& MediaControlStatusDisplayElement::shadowPseudoId() const
-{
- DEFINE_STATIC_LOCAL(AtomicString, id, ("-webkit-media-controls-status-display"));
- return id;
-}
-
-// ----------------------------
-
-MediaControlInputElement::MediaControlInputElement(HTMLMediaElement* mediaElement, MediaControlElementType displayType)
- : HTMLInputElement(inputTag, mediaElement->document(), 0, false)
- , m_mediaElement(mediaElement)
- , m_displayType(displayType)
-{
-}
-
-void MediaControlInputElement::attachToParent(Element* parent)
-{
- // 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->parserAddChild(this);
-}
-
-void MediaControlInputElement::update()
-{
- updateDisplayType();
- if (renderer())
- renderer()->updateFromElement();
- updateStyle();
-}
-
-PassRefPtr<RenderStyle> MediaControlInputElement::styleForElement()
-{
- return document()->styleSelector()->styleForElement(this, 0, true);
-}
-
-bool MediaControlInputElement::rendererIsNeeded(RenderStyle* style)
-{
- ASSERT(document()->page());
-
- return HTMLInputElement::rendererIsNeeded(style) && parentNode() && parentNode()->renderer()
- && (!style->hasAppearance() || document()->page()->theme()->shouldRenderMediaControlPart(style->appearance(), mediaElement()));
-}
-
-void MediaControlInputElement::attach()
-{
- RefPtr<RenderStyle> style = styleForElement();
- if (!style)
- return;
-
- bool needsRenderer = rendererIsNeeded(style.get());
- if (!needsRenderer)
- return;
- RenderObject* renderer = createRenderer(mediaElement()->renderer()->renderArena(), style.get());
- if (!renderer)
- return;
- renderer->setStyle(style.get());
- setRenderer(renderer);
- if (parentNode() && parentNode()->renderer()) {
- // Find next sibling with a renderer to determine where to insert.
- Node* sibling = nextSibling();
- while (sibling && !sibling->renderer())
- sibling = sibling->nextSibling();
- parentNode()->renderer()->addChild(renderer, sibling ? sibling->renderer() : 0);
- }
- ContainerNode::attach();
- // FIXME: Currently, MeidaControlInput circumvents the normal attachment
- // and style recalc cycle and thus we need to add extra logic to be aware of
- // the shadow DOM. Remove this once all media controls are transitioned to use the regular
- // style calculation.
- if (Node* shadowNode = shadowRoot())
- shadowNode->attach();
-}
-
-void MediaControlInputElement::updateStyle()
-{
- if (!mediaElement() || !mediaElement()->renderer())
- return;
-
- RefPtr<RenderStyle> style = styleForElement();
- if (!style)
- return;
-
- bool needsRenderer = rendererIsNeeded(style.get()) && parentNode() && parentNode()->renderer();
- if (renderer() && !needsRenderer)
- detach();
- else if (!renderer() && needsRenderer)
- attach();
- else if (renderer())
- renderer()->setStyle(style.get());
-
- // FIXME: Currently, MeidaControlInput circumvents the normal attachment
- // and style recalc cycle and thus we need to add extra logic to be aware of
- // the shadow DOM. Remove this once all media controls are transitioned to use
- // the new shadow DOM.
- if (Node* shadowNode = shadowRoot())
- shadowNode->recalcStyle(Node::Force);
-}
-
-bool MediaControlInputElement::hitTest(const IntPoint& absPoint)
-{
- if (renderer() && renderer()->style()->hasAppearance())
- return renderer()->theme()->hitTestMediaControlPart(renderer(), absPoint);
-
- return false;
-}
-
-void MediaControlInputElement::setDisplayType(MediaControlElementType displayType)
-{
- if (displayType == m_displayType)
- return;
-
- m_displayType = displayType;
- if (RenderObject* object = renderer())
- object->repaint();
-}
-
-// ----------------------------
-
-inline MediaControlMuteButtonElement::MediaControlMuteButtonElement(HTMLMediaElement* mediaElement, MediaControlElementType displayType)
- : MediaControlInputElement(mediaElement, displayType)
-{
-}
-
-void MediaControlMuteButtonElement::defaultEventHandler(Event* event)
-{
- if (event->type() == eventNames().clickEvent) {
- mediaElement()->setMuted(!mediaElement()->muted());
- event->setDefaultHandled();
- }
- HTMLInputElement::defaultEventHandler(event);
-}
-
-void MediaControlMuteButtonElement::updateDisplayType()
-{
- setDisplayType(mediaElement()->muted() ? MediaUnMuteButton : MediaMuteButton);
-}
-
-// ----------------------------
-
-inline MediaControlPanelMuteButtonElement::MediaControlPanelMuteButtonElement(HTMLMediaElement* mediaElement)
- : MediaControlMuteButtonElement(mediaElement, MediaMuteButton)
-{
-}
-
-PassRefPtr<MediaControlPanelMuteButtonElement> MediaControlPanelMuteButtonElement::create(HTMLMediaElement* mediaElement)
-{
- RefPtr<MediaControlPanelMuteButtonElement> button = adoptRef(new MediaControlPanelMuteButtonElement(mediaElement));
- button->setType("button");
- return button.release();
-}
-
-const AtomicString& MediaControlPanelMuteButtonElement::shadowPseudoId() const
-{
- DEFINE_STATIC_LOCAL(AtomicString, id, ("-webkit-media-controls-mute-button"));
- return id;
-}
-
-// ----------------------------
-
-inline MediaControlVolumeSliderMuteButtonElement::MediaControlVolumeSliderMuteButtonElement(HTMLMediaElement* mediaElement)
- : MediaControlMuteButtonElement(mediaElement, MediaVolumeSliderMuteButton)
-{
-}
-
-PassRefPtr<MediaControlVolumeSliderMuteButtonElement> MediaControlVolumeSliderMuteButtonElement::create(HTMLMediaElement* mediaElement)
-{
- RefPtr<MediaControlVolumeSliderMuteButtonElement> button = adoptRef(new MediaControlVolumeSliderMuteButtonElement(mediaElement));
- button->setType("button");
- return button.release();
-}
-
-const AtomicString& MediaControlVolumeSliderMuteButtonElement::shadowPseudoId() const
-{
- DEFINE_STATIC_LOCAL(AtomicString, id, ("-webkit-media-controls-volume-slider-mute-button"));
- return id;
-}
-
-// ----------------------------
-
-inline MediaControlPlayButtonElement::MediaControlPlayButtonElement(HTMLMediaElement* mediaElement)
- : MediaControlInputElement(mediaElement, MediaPlayButton)
-{
-}
-
-PassRefPtr<MediaControlPlayButtonElement> MediaControlPlayButtonElement::create(HTMLMediaElement* mediaElement)
-{
- RefPtr<MediaControlPlayButtonElement> button = adoptRef(new MediaControlPlayButtonElement(mediaElement));
- button->setType("button");
- return button.release();
-}
-
-void MediaControlPlayButtonElement::defaultEventHandler(Event* event)
-{
- if (event->type() == eventNames().clickEvent) {
- mediaElement()->togglePlayState();
- event->setDefaultHandled();
- }
- HTMLInputElement::defaultEventHandler(event);
-}
-
-void MediaControlPlayButtonElement::updateDisplayType()
-{
- setDisplayType(mediaElement()->canPlay() ? MediaPlayButton : MediaPauseButton);
-}
-
-const AtomicString& MediaControlPlayButtonElement::shadowPseudoId() const
-{
- DEFINE_STATIC_LOCAL(AtomicString, id, ("-webkit-media-controls-play-button"));
- return id;
-}
-
-// ----------------------------
-
-inline MediaControlSeekButtonElement::MediaControlSeekButtonElement(HTMLMediaElement* mediaElement, MediaControlElementType displayType)
- : MediaControlInputElement(mediaElement, displayType)
- , m_seeking(false)
- , m_capturing(false)
- , m_seekTimer(this, &MediaControlSeekButtonElement::seekTimerFired)
-{
-}
-
-void MediaControlSeekButtonElement::defaultEventHandler(Event* event)
-{
- if (event->type() == eventNames().mousedownEvent) {
- if (Frame* frame = document()->frame()) {
- m_capturing = true;
- frame->eventHandler()->setCapturingMouseEventsNode(this);
- }
- mediaElement()->pause(event->fromUserGesture());
- m_seekTimer.startRepeating(cSeekRepeatDelay);
- event->setDefaultHandled();
- } else if (event->type() == eventNames().mouseupEvent) {
- if (m_capturing)
- if (Frame* frame = document()->frame()) {
- m_capturing = false;
- frame->eventHandler()->setCapturingMouseEventsNode(0);
- }
- ExceptionCode ec;
- if (m_seeking || m_seekTimer.isActive()) {
- if (!m_seeking) {
- float stepTime = isForwardButton() ? cStepTime : -cStepTime;
- mediaElement()->setCurrentTime(mediaElement()->currentTime() + stepTime, ec);
- }
- m_seekTimer.stop();
- m_seeking = false;
- event->setDefaultHandled();
- }
- }
- HTMLInputElement::defaultEventHandler(event);
-}
-
-void MediaControlSeekButtonElement::seekTimerFired(Timer<MediaControlSeekButtonElement>*)
-{
- ExceptionCode ec;
- m_seeking = true;
- float seekTime = isForwardButton() ? cSeekTime : -cSeekTime;
- mediaElement()->setCurrentTime(mediaElement()->currentTime() + seekTime, ec);
-}
-
-void MediaControlSeekButtonElement::detach()
-{
- if (m_capturing) {
- if (Frame* frame = document()->frame())
- frame->eventHandler()->setCapturingMouseEventsNode(0);
- }
- MediaControlInputElement::detach();
-}
-
-// ----------------------------
-
-inline MediaControlSeekForwardButtonElement::MediaControlSeekForwardButtonElement(HTMLMediaElement* mediaElement)
- : MediaControlSeekButtonElement(mediaElement, MediaSeekForwardButton)
-{
-}
-
-PassRefPtr<MediaControlSeekForwardButtonElement> MediaControlSeekForwardButtonElement::create(HTMLMediaElement* mediaElement)
-{
- RefPtr<MediaControlSeekForwardButtonElement> button = adoptRef(new MediaControlSeekForwardButtonElement(mediaElement));
- button->setType("button");
- return button.release();
-}
-
-const AtomicString& MediaControlSeekForwardButtonElement::shadowPseudoId() const
-{
- DEFINE_STATIC_LOCAL(AtomicString, id, ("-webkit-media-controls-seek-forward-button"));
- return id;
-}
-
-// ----------------------------
-
-inline MediaControlSeekBackButtonElement::MediaControlSeekBackButtonElement(HTMLMediaElement* mediaElement)
- : MediaControlSeekButtonElement(mediaElement, MediaSeekBackButton)
-{
-}
-
-PassRefPtr<MediaControlSeekBackButtonElement> MediaControlSeekBackButtonElement::create(HTMLMediaElement* mediaElement)
-{
- RefPtr<MediaControlSeekBackButtonElement> button = adoptRef(new MediaControlSeekBackButtonElement(mediaElement));
- button->setType("button");
- return button.release();
-}
-
-const AtomicString& MediaControlSeekBackButtonElement::shadowPseudoId() const
-{
- DEFINE_STATIC_LOCAL(AtomicString, id, ("-webkit-media-controls-seek-back-button"));
- return id;
-}
-
-// ----------------------------
-
-inline MediaControlRewindButtonElement::MediaControlRewindButtonElement(HTMLMediaElement* element)
- : MediaControlInputElement(element, MediaRewindButton)
-{
-}
-
-PassRefPtr<MediaControlRewindButtonElement> MediaControlRewindButtonElement::create(HTMLMediaElement* mediaElement)
-{
- RefPtr<MediaControlRewindButtonElement> button = adoptRef(new MediaControlRewindButtonElement(mediaElement));
- button->setType("button");
- return button.release();
-}
-
-void MediaControlRewindButtonElement::defaultEventHandler(Event* event)
-{
- if (event->type() == eventNames().clickEvent) {
- mediaElement()->rewind(30);
- event->setDefaultHandled();
- }
- HTMLInputElement::defaultEventHandler(event);
-}
-
-const AtomicString& MediaControlRewindButtonElement::shadowPseudoId() const
-{
- DEFINE_STATIC_LOCAL(AtomicString, id, ("-webkit-media-controls-rewind-button"));
- return id;
-}
-
-// ----------------------------
-
-inline MediaControlReturnToRealtimeButtonElement::MediaControlReturnToRealtimeButtonElement(HTMLMediaElement* mediaElement)
- : MediaControlInputElement(mediaElement, MediaReturnToRealtimeButton)
-{
-}
-
-PassRefPtr<MediaControlReturnToRealtimeButtonElement> MediaControlReturnToRealtimeButtonElement::create(HTMLMediaElement* mediaElement)
-{
- RefPtr<MediaControlReturnToRealtimeButtonElement> button = adoptRef(new MediaControlReturnToRealtimeButtonElement(mediaElement));
- button->setType("button");
- return button.release();
-}
-
-void MediaControlReturnToRealtimeButtonElement::defaultEventHandler(Event* event)
-{
- if (event->type() == eventNames().clickEvent) {
- mediaElement()->returnToRealtime();
- event->setDefaultHandled();
- }
- HTMLInputElement::defaultEventHandler(event);
-}
-
-const AtomicString& MediaControlReturnToRealtimeButtonElement::shadowPseudoId() const
-{
- DEFINE_STATIC_LOCAL(AtomicString, id, ("-webkit-media-controls-return-to-realtime-button"));
- return id;
-}
-
-// ----------------------------
-
-inline MediaControlToggleClosedCaptionsButtonElement::MediaControlToggleClosedCaptionsButtonElement(HTMLMediaElement* mediaElement)
- : MediaControlInputElement(mediaElement, MediaShowClosedCaptionsButton)
-{
-}
-
-PassRefPtr<MediaControlToggleClosedCaptionsButtonElement> MediaControlToggleClosedCaptionsButtonElement::create(HTMLMediaElement* mediaElement)
-{
- RefPtr<MediaControlToggleClosedCaptionsButtonElement> button = adoptRef(new MediaControlToggleClosedCaptionsButtonElement(mediaElement));
- button->setType("button");
- return button.release();
-}
-
-void MediaControlToggleClosedCaptionsButtonElement::defaultEventHandler(Event* event)
-{
- if (event->type() == eventNames().clickEvent) {
- mediaElement()->setClosedCaptionsVisible(!mediaElement()->closedCaptionsVisible());
- setChecked(mediaElement()->closedCaptionsVisible());
- event->setDefaultHandled();
- }
- HTMLInputElement::defaultEventHandler(event);
-}
-
-void MediaControlToggleClosedCaptionsButtonElement::updateDisplayType()
-{
- setDisplayType(mediaElement()->closedCaptionsVisible() ? MediaHideClosedCaptionsButton : MediaShowClosedCaptionsButton);
-}
-
-const AtomicString& MediaControlToggleClosedCaptionsButtonElement::shadowPseudoId() const
-{
- DEFINE_STATIC_LOCAL(AtomicString, id, ("-webkit-media-controls-toggle-closed-captions-button"));
- return id;
-}
-
-// ----------------------------
-
-MediaControlTimelineElement::MediaControlTimelineElement(HTMLMediaElement* mediaElement)
- : MediaControlInputElement(mediaElement, MediaSlider)
-{
-}
-
-PassRefPtr<MediaControlTimelineElement> MediaControlTimelineElement::create(HTMLMediaElement* mediaElement)
-{
- RefPtr<MediaControlTimelineElement> timeline = adoptRef(new MediaControlTimelineElement(mediaElement));
- timeline->setType("range");
- timeline->setAttribute(precisionAttr, "float");
- return timeline.release();
-}
-
-void MediaControlTimelineElement::defaultEventHandler(Event* event)
-{
- // Left button is 0. Rejects mouse events not from left button.
- if (event->isMouseEvent() && static_cast<MouseEvent*>(event)->button())
- return;
-
- if (!attached())
- return;
-
- if (event->type() == eventNames().mousedownEvent)
- mediaElement()->beginScrubbing();
-
- MediaControlInputElement::defaultEventHandler(event);
-
- if (event->type() == eventNames().mouseoverEvent || event->type() == eventNames().mouseoutEvent || event->type() == eventNames().mousemoveEvent)
- return;
-
- float time = narrowPrecisionToFloat(value().toDouble());
- if (time != mediaElement()->currentTime()) {
- ExceptionCode ec;
- mediaElement()->setCurrentTime(time, ec);
- }
-
- RenderSlider* slider = toRenderSlider(renderer());
- if (slider && slider->inDragMode()) {
- toRenderMedia(mediaElement()->renderer())->controls()->updateTimeDisplay();
-#if PLATFORM(ANDROID)
- toRenderMedia(mediaElement()->renderer())->controls()->updateLastTouch();
-#endif
- }
-
- if (event->type() == eventNames().mouseupEvent)
- mediaElement()->endScrubbing();
-}
-
-void MediaControlTimelineElement::update(bool updateDuration)
-{
- if (updateDuration) {
- float duration = mediaElement()->duration();
- setAttribute(maxAttr, String::number(isfinite(duration) ? duration : 0));
- }
- setValue(String::number(mediaElement()->currentTime()));
- MediaControlInputElement::update();
-}
-
-const AtomicString& MediaControlTimelineElement::shadowPseudoId() const
-{
- DEFINE_STATIC_LOCAL(AtomicString, id, ("-webkit-media-controls-timeline"));
- return id;
-}
-
-// ----------------------------
-
-inline MediaControlVolumeSliderElement::MediaControlVolumeSliderElement(HTMLMediaElement* mediaElement)
- : MediaControlInputElement(mediaElement, MediaVolumeSlider)
-{
-}
-
-PassRefPtr<MediaControlVolumeSliderElement> MediaControlVolumeSliderElement::create(HTMLMediaElement* mediaElement)
-{
- RefPtr<MediaControlVolumeSliderElement> slider = adoptRef(new MediaControlVolumeSliderElement(mediaElement));
- slider->setType("range");
- slider->setAttribute(precisionAttr, "float");
- slider->setAttribute(maxAttr, "1");
- slider->setAttribute(valueAttr, String::number(mediaElement->volume()));
- return slider.release();
-}
-
-void MediaControlVolumeSliderElement::defaultEventHandler(Event* event)
-{
- // Left button is 0. Rejects mouse events not from left button.
- if (event->isMouseEvent() && static_cast<MouseEvent*>(event)->button())
- return;
-
- if (!attached())
- return;
-
- MediaControlInputElement::defaultEventHandler(event);
-
- if (event->type() == eventNames().mouseoverEvent || event->type() == eventNames().mouseoutEvent || event->type() == eventNames().mousemoveEvent)
- return;
-
- float volume = narrowPrecisionToFloat(value().toDouble());
- if (volume != mediaElement()->volume()) {
- ExceptionCode ec = 0;
- mediaElement()->setVolume(volume, ec);
- ASSERT(!ec);
- }
-}
-
-void MediaControlVolumeSliderElement::update()
-{
- float volume = mediaElement()->volume();
- if (value().toFloat() != volume)
- setValue(String::number(volume));
- MediaControlInputElement::update();
-}
-
-const AtomicString& MediaControlVolumeSliderElement::shadowPseudoId() const
-{
- DEFINE_STATIC_LOCAL(AtomicString, id, ("-webkit-media-controls-volume-slider"));
- return id;
-}
-
-// ----------------------------
-
-inline MediaControlFullscreenVolumeSliderElement::MediaControlFullscreenVolumeSliderElement(HTMLMediaElement* mediaElement)
-: MediaControlVolumeSliderElement(mediaElement)
-{
-}
-
-PassRefPtr<MediaControlFullscreenVolumeSliderElement> MediaControlFullscreenVolumeSliderElement::create(HTMLMediaElement* mediaElement)
-{
- RefPtr<MediaControlFullscreenVolumeSliderElement> slider = adoptRef(new MediaControlFullscreenVolumeSliderElement(mediaElement));
- slider->setType("range");
- slider->setAttribute(precisionAttr, "float");
- slider->setAttribute(maxAttr, "1");
- slider->setAttribute(valueAttr, String::number(mediaElement->volume()));
- return slider.release();
-}
-
-const AtomicString& MediaControlFullscreenVolumeSliderElement::shadowPseudoId() const
-{
- DEFINE_STATIC_LOCAL(AtomicString, id, ("-webkit-media-controls-fullscreen-volume-slider"));
- return id;
-}
-
-// ----------------------------
-
-inline MediaControlFullscreenButtonElement::MediaControlFullscreenButtonElement(HTMLMediaElement* mediaElement)
- : MediaControlInputElement(mediaElement, MediaFullscreenButton)
-{
-}
-
-PassRefPtr<MediaControlFullscreenButtonElement> MediaControlFullscreenButtonElement::create(HTMLMediaElement* mediaElement)
-{
- RefPtr<MediaControlFullscreenButtonElement> button = adoptRef(new MediaControlFullscreenButtonElement(mediaElement));
- button->setType("button");
- return button.release();
-}
-
-void MediaControlFullscreenButtonElement::defaultEventHandler(Event* event)
-{
- if (event->type() == eventNames().clickEvent) {
-#if ENABLE(FULLSCREEN_API)
- // Only use the new full screen API if the fullScreenEnabled setting has
- // been explicitly enabled. Otherwise, use the old fullscreen API. This
- // allows apps which embed a WebView to retain the existing full screen
- // video implementation without requiring them to implement their own full
- // screen behavior.
- if (document()->settings() && document()->settings()->fullScreenEnabled()) {
- if (document()->webkitIsFullScreen() && document()->webkitCurrentFullScreenElement() == mediaElement())
- document()->webkitCancelFullScreen();
- else
- mediaElement()->webkitRequestFullScreen(0);
- } else
-#endif
- mediaElement()->enterFullscreen();
- event->setDefaultHandled();
- }
- HTMLInputElement::defaultEventHandler(event);
-}
-
-const AtomicString& MediaControlFullscreenButtonElement::shadowPseudoId() const
-{
- DEFINE_STATIC_LOCAL(AtomicString, id, ("-webkit-media-controls-fullscreen-button"));
- return id;
-}
-
-// ----------------------------
-
-inline MediaControlFullscreenVolumeMinButtonElement::MediaControlFullscreenVolumeMinButtonElement(HTMLMediaElement* mediaElement)
-: MediaControlInputElement(mediaElement, MediaUnMuteButton)
-{
-}
-
-PassRefPtr<MediaControlFullscreenVolumeMinButtonElement> MediaControlFullscreenVolumeMinButtonElement::create(HTMLMediaElement* mediaElement)
-{
- RefPtr<MediaControlFullscreenVolumeMinButtonElement> button = adoptRef(new MediaControlFullscreenVolumeMinButtonElement(mediaElement));
- button->setType("button");
- return button.release();
-}
-
-void MediaControlFullscreenVolumeMinButtonElement::defaultEventHandler(Event* event)
-{
- if (event->type() == eventNames().clickEvent) {
- ExceptionCode code = 0;
- mediaElement()->setVolume(0, code);
- event->setDefaultHandled();
- }
- HTMLInputElement::defaultEventHandler(event);
-}
-
-const AtomicString& MediaControlFullscreenVolumeMinButtonElement::shadowPseudoId() const
-{
- DEFINE_STATIC_LOCAL(AtomicString, id, ("-webkit-media-controls-fullscreen-volume-min-button"));
- return id;
-}
-
-// ----------------------------
-
-inline MediaControlFullscreenVolumeMaxButtonElement::MediaControlFullscreenVolumeMaxButtonElement(HTMLMediaElement* mediaElement)
-: MediaControlInputElement(mediaElement, MediaMuteButton)
-{
-}
-
-PassRefPtr<MediaControlFullscreenVolumeMaxButtonElement> MediaControlFullscreenVolumeMaxButtonElement::create(HTMLMediaElement* mediaElement)
-{
- RefPtr<MediaControlFullscreenVolumeMaxButtonElement> button = adoptRef(new MediaControlFullscreenVolumeMaxButtonElement(mediaElement));
- button->setType("button");
- return button.release();
-}
-
-void MediaControlFullscreenVolumeMaxButtonElement::defaultEventHandler(Event* event)
-{
- if (event->type() == eventNames().clickEvent) {
- ExceptionCode code = 0;
- mediaElement()->setVolume(1, code);
- event->setDefaultHandled();
- }
- HTMLInputElement::defaultEventHandler(event);
-}
-
-const AtomicString& MediaControlFullscreenVolumeMaxButtonElement::shadowPseudoId() const
-{
- DEFINE_STATIC_LOCAL(AtomicString, id, ("-webkit-media-controls-fullscreen-volume-max-button"));
- return id;
-}
-
-// ----------------------------
-
-class RenderMediaControlTimeDisplay : public RenderFlexibleBox {
-public:
- RenderMediaControlTimeDisplay(Node*);
-
-private:
- virtual void layout();
-};
-
-RenderMediaControlTimeDisplay::RenderMediaControlTimeDisplay(Node* node)
- : RenderFlexibleBox(node)
-{
-}
-
-// We want the timeline slider to be at least 100 pixels wide.
-// FIXME: Eliminate hard-coded widths altogether.
-static const int minWidthToDisplayTimeDisplays = 45 + 100 + 45;
-
-void RenderMediaControlTimeDisplay::layout()
-{
- RenderFlexibleBox::layout();
- RenderBox* timelineContainerBox = parentBox();
- if (timelineContainerBox && timelineContainerBox->width() < minWidthToDisplayTimeDisplays)
- setWidth(0);
-}
-
-inline MediaControlTimeDisplayElement::MediaControlTimeDisplayElement(HTMLMediaElement* mediaElement)
- : MediaControlElement(mediaElement)
- , m_currentValue(0)
-{
-}
-
-void MediaControlTimeDisplayElement::setCurrentValue(float time)
-{
- m_currentValue = time;
-}
-
-RenderObject* MediaControlTimeDisplayElement::createRenderer(RenderArena* arena, RenderStyle*)
-{
- return new (arena) RenderMediaControlTimeDisplay(this);
-}
-
-// ----------------------------
-
-PassRefPtr<MediaControlTimeRemainingDisplayElement> MediaControlTimeRemainingDisplayElement::create(HTMLMediaElement* mediaElement)
-{
- return adoptRef(new MediaControlTimeRemainingDisplayElement(mediaElement));
-}
-
-MediaControlTimeRemainingDisplayElement::MediaControlTimeRemainingDisplayElement(HTMLMediaElement* mediaElement)
- : MediaControlTimeDisplayElement(mediaElement)
-{
-}
-
-MediaControlElementType MediaControlTimeRemainingDisplayElement::displayType() const
-{
- return MediaTimeRemainingDisplay;
-}
-
-const AtomicString& MediaControlTimeRemainingDisplayElement::shadowPseudoId() const
-{
- DEFINE_STATIC_LOCAL(AtomicString, id, ("-webkit-media-controls-time-remaining-display"));
- return id;
-}
-
-// ----------------------------
-
-PassRefPtr<MediaControlCurrentTimeDisplayElement> MediaControlCurrentTimeDisplayElement::create(HTMLMediaElement* mediaElement)
-{
- return adoptRef(new MediaControlCurrentTimeDisplayElement(mediaElement));
-}
-
-MediaControlCurrentTimeDisplayElement::MediaControlCurrentTimeDisplayElement(HTMLMediaElement* mediaElement)
- : MediaControlTimeDisplayElement(mediaElement)
-{
-}
-
-MediaControlElementType MediaControlCurrentTimeDisplayElement::displayType() const
-{
- return MediaCurrentTimeDisplay;
-}
-
-const AtomicString& MediaControlCurrentTimeDisplayElement::shadowPseudoId() const
-{
- DEFINE_STATIC_LOCAL(AtomicString, id, ("-webkit-media-controls-current-time-display"));
- return id;
-}
-
-} // namespace WebCore
-
-#endif // ENABLE(VIDEO)
diff --git a/Source/WebCore/rendering/MediaControlElements.h b/Source/WebCore/rendering/MediaControlElements.h
deleted file mode 100644
index 77116e3..0000000
--- a/Source/WebCore/rendering/MediaControlElements.h
+++ /dev/null
@@ -1,492 +0,0 @@
-/*
- * Copyright (C) 2008, 2009, 2010 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
- * its contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef MediaControlElements_h
-#define MediaControlElements_h
-
-#if ENABLE(VIDEO)
-
-#include "HTMLDivElement.h"
-#include "HTMLInputElement.h"
-#include "HTMLMediaElement.h"
-#include "RenderBlock.h"
-
-// These are the shadow elements used in RenderMedia
-
-namespace WebCore {
-
-class Event;
-class Frame;
-
-// Must match WebKitSystemInterface.h
-enum MediaControlElementType {
- MediaFullscreenButton = 0,
- MediaMuteButton,
- MediaPlayButton,
- MediaSeekBackButton,
- MediaSeekForwardButton,
- MediaSlider,
- MediaSliderThumb,
- MediaRewindButton,
- MediaReturnToRealtimeButton,
- MediaShowClosedCaptionsButton,
- MediaHideClosedCaptionsButton,
- MediaUnMuteButton,
- MediaPauseButton,
- MediaTimelineContainer,
- MediaCurrentTimeDisplay,
- MediaTimeRemainingDisplay,
- MediaStatusDisplay,
- MediaControlsPanel,
- MediaVolumeSliderContainer,
- MediaVolumeSlider,
- MediaVolumeSliderThumb,
- MediaVolumeSliderMuteButton,
-};
-
-HTMLMediaElement* toParentMediaElement(RenderObject*);
-
-class MediaControlShadowRootElement : public HTMLDivElement {
-public:
- static PassRefPtr<MediaControlShadowRootElement> create(HTMLMediaElement*);
-
- virtual void detach();
-
-private:
- MediaControlShadowRootElement(HTMLMediaElement*);
-};
-
-// ----------------------------
-
-class MediaControlElement : public HTMLDivElement {
-public:
- virtual void attach();
- void attachToParent(Element*);
- void update();
- void updateStyle();
-
- virtual MediaControlElementType displayType() const = 0;
-
- HTMLMediaElement* mediaElement() const { return m_mediaElement; }
-
-protected:
- MediaControlElement(HTMLMediaElement*);
-
- virtual bool rendererIsNeeded(RenderStyle*);
-
- virtual PassRefPtr<RenderStyle> styleForElement();
-
-private:
- virtual bool isMediaControlElement() const { return true; }
-
- HTMLMediaElement* m_mediaElement;
-};
-
-// ----------------------------
-
-class MediaControlPanelElement : public MediaControlElement {
-public:
- static PassRefPtr<MediaControlPanelElement> create(HTMLMediaElement*);
-
-private:
- MediaControlPanelElement(HTMLMediaElement*);
- virtual MediaControlElementType displayType() const;
- virtual const AtomicString& shadowPseudoId() const;
-};
-
-
-// ----------------------------
-
-class MediaControlTimelineContainerElement : public MediaControlElement {
-public:
- static PassRefPtr<MediaControlTimelineContainerElement> create(HTMLMediaElement*);
-
-private:
- MediaControlTimelineContainerElement(HTMLMediaElement*);
- virtual MediaControlElementType displayType() const;
- virtual bool rendererIsNeeded(RenderStyle*);
- virtual const AtomicString& shadowPseudoId() const;
-};
-
-// ----------------------------
-
-class MediaControlVolumeSliderContainerElement : public MediaControlElement {
-public:
- static PassRefPtr<MediaControlVolumeSliderContainerElement> create(HTMLMediaElement*);
-
- virtual PassRefPtr<RenderStyle> styleForElement();
- void setVisible(bool);
- bool isVisible() { return m_isVisible; }
- bool hitTest(const IntPoint& absPoint);
-
-private:
- MediaControlVolumeSliderContainerElement(HTMLMediaElement*);
-
- virtual RenderObject* createRenderer(RenderArena*, RenderStyle*);
- virtual MediaControlElementType displayType() const;
- virtual const AtomicString& shadowPseudoId() const;
-
- bool m_isVisible;
-};
-
-// ----------------------------
-
-class MediaControlStatusDisplayElement : public MediaControlElement {
-public:
- static PassRefPtr<MediaControlStatusDisplayElement> create(HTMLMediaElement*);
-
- void update();
-
-private:
- MediaControlStatusDisplayElement(HTMLMediaElement*);
-
- virtual MediaControlElementType displayType() const;
- virtual bool rendererIsNeeded(RenderStyle*);
- virtual const AtomicString& shadowPseudoId() const;
-
- enum StateBeingDisplayed { Nothing, Loading, LiveBroadcast };
- StateBeingDisplayed m_stateBeingDisplayed;
-};
-
-// ----------------------------
-
-class MediaControlInputElement : public HTMLInputElement {
-public:
- void attachToParent(Element*);
- void update();
- void updateStyle();
-
- bool hitTest(const IntPoint& absPoint);
-
- MediaControlElementType displayType() const { return m_displayType; }
-
- HTMLMediaElement* mediaElement() const { return m_mediaElement; }
-
-protected:
- MediaControlInputElement(HTMLMediaElement*, MediaControlElementType);
-
- void setDisplayType(MediaControlElementType);
-
-private:
- virtual void attach();
- virtual bool rendererIsNeeded(RenderStyle*);
-
- virtual PassRefPtr<RenderStyle> styleForElement();
-
- virtual bool isMediaControlElement() const { return true; }
-
- virtual void updateDisplayType() { }
-
- HTMLMediaElement* m_mediaElement;
- MediaControlElementType m_displayType;
-};
-
-// ----------------------------
-
-class MediaControlMuteButtonElement : public MediaControlInputElement {
-public:
- virtual void defaultEventHandler(Event*);
-
-protected:
- MediaControlMuteButtonElement(HTMLMediaElement*, MediaControlElementType);
-
-private:
- virtual void updateDisplayType();
-};
-
-// ----------------------------
-
-class MediaControlPanelMuteButtonElement : public MediaControlMuteButtonElement {
-public:
- static PassRefPtr<MediaControlPanelMuteButtonElement> create(HTMLMediaElement*);
-
-private:
- MediaControlPanelMuteButtonElement(HTMLMediaElement*);
-
- virtual const AtomicString& shadowPseudoId() const;
-};
-
-// ----------------------------
-
-class MediaControlVolumeSliderMuteButtonElement : public MediaControlMuteButtonElement {
-public:
- static PassRefPtr<MediaControlVolumeSliderMuteButtonElement> create(HTMLMediaElement*);
-
-private:
- MediaControlVolumeSliderMuteButtonElement(HTMLMediaElement*);
-
- virtual const AtomicString& shadowPseudoId() const;
-};
-
-
-// ----------------------------
-
-class MediaControlPlayButtonElement : public MediaControlInputElement {
-public:
- static PassRefPtr<MediaControlPlayButtonElement> create(HTMLMediaElement*);
-
- virtual void defaultEventHandler(Event*);
-
-private:
- MediaControlPlayButtonElement(HTMLMediaElement*);
-
- virtual void updateDisplayType();
- virtual const AtomicString& shadowPseudoId() const;
-};
-
-// ----------------------------
-
-class MediaControlSeekButtonElement : public MediaControlInputElement {
-public:
- virtual void defaultEventHandler(Event*);
-
-protected:
- MediaControlSeekButtonElement(HTMLMediaElement*, MediaControlElementType);
-
-private:
- virtual bool isForwardButton() const = 0;
-
- virtual void detach();
- void seekTimerFired(Timer<MediaControlSeekButtonElement>*);
-
- bool m_seeking;
- bool m_capturing;
- Timer<MediaControlSeekButtonElement> m_seekTimer;
-};
-
-// ----------------------------
-
-class MediaControlSeekForwardButtonElement : public MediaControlSeekButtonElement {
-public:
- static PassRefPtr<MediaControlSeekForwardButtonElement> create(HTMLMediaElement*);
-
-private:
- MediaControlSeekForwardButtonElement(HTMLMediaElement*);
-
- virtual bool isForwardButton() const { return true; }
- virtual const AtomicString& shadowPseudoId() const;
-};
-
-// ----------------------------
-
-class MediaControlSeekBackButtonElement : public MediaControlSeekButtonElement {
-public:
- static PassRefPtr<MediaControlSeekBackButtonElement> create(HTMLMediaElement*);
-
-private:
- MediaControlSeekBackButtonElement(HTMLMediaElement*);
-
- virtual bool isForwardButton() const { return false; }
- virtual const AtomicString& shadowPseudoId() const;
-};
-
-// ----------------------------
-
-class MediaControlRewindButtonElement : public MediaControlInputElement {
-public:
- static PassRefPtr<MediaControlRewindButtonElement> create(HTMLMediaElement*);
-
- virtual void defaultEventHandler(Event*);
-
-private:
- MediaControlRewindButtonElement(HTMLMediaElement*);
-
- virtual const AtomicString& shadowPseudoId() const;
-};
-
-// ----------------------------
-
-class MediaControlReturnToRealtimeButtonElement : public MediaControlInputElement {
-public:
- static PassRefPtr<MediaControlReturnToRealtimeButtonElement> create(HTMLMediaElement*);
-
- virtual void defaultEventHandler(Event*);
-
-private:
- MediaControlReturnToRealtimeButtonElement(HTMLMediaElement*);
-
- virtual const AtomicString& shadowPseudoId() const;
-};
-
-// ----------------------------
-
-class MediaControlToggleClosedCaptionsButtonElement : public MediaControlInputElement {
-public:
- static PassRefPtr<MediaControlToggleClosedCaptionsButtonElement> create(HTMLMediaElement*);
-
- virtual void defaultEventHandler(Event*);
-
-private:
- MediaControlToggleClosedCaptionsButtonElement(HTMLMediaElement*);
-
- virtual void updateDisplayType();
- virtual const AtomicString& shadowPseudoId() const;
-};
-
-// ----------------------------
-
-class MediaControlTimelineElement : public MediaControlInputElement {
-public:
- static PassRefPtr<MediaControlTimelineElement> create(HTMLMediaElement*);
-
- virtual void defaultEventHandler(Event*);
- void update(bool updateDuration = true);
-
-private:
- MediaControlTimelineElement(HTMLMediaElement*);
-
- virtual const AtomicString& shadowPseudoId() const;
-};
-
-// ----------------------------
-
-class MediaControlVolumeSliderElement : public MediaControlInputElement {
-public:
- static PassRefPtr<MediaControlVolumeSliderElement> create(HTMLMediaElement*);
-
- virtual void defaultEventHandler(Event*);
- void update();
-
-protected:
- MediaControlVolumeSliderElement(HTMLMediaElement*);
-
-private:
- virtual const AtomicString& shadowPseudoId() const;
-};
-
-// ----------------------------
-
-class MediaControlFullscreenButtonElement : public MediaControlInputElement {
-public:
- static PassRefPtr<MediaControlFullscreenButtonElement> create(HTMLMediaElement*);
-
- virtual void defaultEventHandler(Event*);
-
-private:
- MediaControlFullscreenButtonElement(HTMLMediaElement*);
-
- virtual const AtomicString& shadowPseudoId() const;
-};
-
-// ----------------------------
-
-class MediaControlFullscreenVolumeSliderElement : public MediaControlVolumeSliderElement {
-public:
- static PassRefPtr<MediaControlFullscreenVolumeSliderElement> create(HTMLMediaElement*);
-
-private:
- MediaControlFullscreenVolumeSliderElement(HTMLMediaElement*);
-
- virtual const AtomicString& shadowPseudoId() const;
-};
-
-// ----------------------------
-
-class MediaControlFullscreenVolumeMinButtonElement : public MediaControlInputElement {
-public:
- static PassRefPtr<MediaControlFullscreenVolumeMinButtonElement> create(HTMLMediaElement*);
-
- virtual void defaultEventHandler(Event*);
-
-private:
- MediaControlFullscreenVolumeMinButtonElement(HTMLMediaElement*);
-
- virtual const AtomicString& shadowPseudoId() const;
-};
-
-// ----------------------------
-
-class MediaControlFullscreenVolumeMaxButtonElement : public MediaControlInputElement {
-public:
- static PassRefPtr<MediaControlFullscreenVolumeMaxButtonElement> create(HTMLMediaElement*);
-
- virtual void defaultEventHandler(Event*);
-
-private:
- MediaControlFullscreenVolumeMaxButtonElement(HTMLMediaElement*);
-
- virtual const AtomicString& shadowPseudoId() const;
-};
-
-// ----------------------------
-
-class MediaControlTimeDisplayElement : public MediaControlElement {
-public:
- void setCurrentValue(float);
- float currentValue() const { return m_currentValue; }
-
-protected:
- MediaControlTimeDisplayElement(HTMLMediaElement*);
-
-private:
- virtual RenderObject* createRenderer(RenderArena*, RenderStyle*);
-
- float m_currentValue;
-};
-
-// ----------------------------
-
-class MediaControlTimeRemainingDisplayElement : public MediaControlTimeDisplayElement {
-public:
- static PassRefPtr<MediaControlTimeRemainingDisplayElement> create(HTMLMediaElement*);
-
-private:
- MediaControlTimeRemainingDisplayElement(HTMLMediaElement*);
-
- virtual MediaControlElementType displayType() const;
- virtual const AtomicString& shadowPseudoId() const;
-};
-
-// ----------------------------
-
-class MediaControlCurrentTimeDisplayElement : public MediaControlTimeDisplayElement {
-public:
- static PassRefPtr<MediaControlCurrentTimeDisplayElement> create(HTMLMediaElement*);
-
-private:
- MediaControlCurrentTimeDisplayElement(HTMLMediaElement*);
-
- virtual MediaControlElementType displayType() const;
- virtual const AtomicString& shadowPseudoId() const;
-};
-
-// ----------------------------
-
-class RenderMediaControlShadowRoot : public RenderBlock {
-public:
- RenderMediaControlShadowRoot(Element* e) : RenderBlock(e) { }
- void setParent(RenderObject* p) { RenderObject::setParent(p); }
-};
-
-// ----------------------------
-
-} //namespace WebCore
-
-#endif // ENABLE(VIDEO)
-
-#endif // MediaControlElements_h
diff --git a/Source/WebCore/rendering/RenderBlock.cpp b/Source/WebCore/rendering/RenderBlock.cpp
index 919e23b..de3af60 100644
--- a/Source/WebCore/rendering/RenderBlock.cpp
+++ b/Source/WebCore/rendering/RenderBlock.cpp
@@ -52,7 +52,6 @@
#include "Settings.h"
#include "TextRun.h"
#include "TransformState.h"
-#include "visible_units.h"
#include <wtf/StdLibExtras.h>
#ifdef ANDROID_LAYOUT
@@ -1550,8 +1549,9 @@ bool RenderBlock::handleRunInChild(RenderBox* child)
runInChild = nextSibling;
}
- // Now insert the new child under |currBlock|.
- currBlock->children()->insertChildNode(currBlock, inlineRunIn, currBlock->firstChild());
+ // Now insert the new child under |currBlock|. Use addChild instead of insertChildNode since it handles correct placement of the children, esp where we cannot insert
+ // anything before the first child. e.g. details tag. See https://bugs.webkit.org/show_bug.cgi?id=58228.
+ currBlock->addChild(inlineRunIn, currBlock->firstChild());
// If the run-in had an element, we need to set the new renderer.
if (runInNode)
@@ -2106,7 +2106,7 @@ void RenderBlock::simplifiedNormalFlowLayout()
GlyphOverflowAndFallbackFontsMap textBoxDataMap;
for (ListHashSet<RootInlineBox*>::const_iterator it = lineBoxes.begin(); it != lineBoxes.end(); ++it) {
RootInlineBox* box = *it;
- box->computeOverflow(box->lineTop(), box->lineBottom(), document()->inNoQuirksMode(), textBoxDataMap);
+ box->computeOverflow(box->lineTop(), box->lineBottom(), textBoxDataMap);
}
} else {
for (RenderBox* box = firstChildBox(); box; box = box->nextSiblingBox()) {
@@ -2123,11 +2123,8 @@ bool RenderBlock::simplifiedLayout()
LayoutStateMaintainer statePusher(view(), this, IntSize(x(), y()), hasColumns() || hasTransform() || hasReflection() || style()->isFlippedBlocksWritingMode());
- if (needsPositionedMovementLayout()) {
- tryLayoutDoingPositionedMovementOnly();
- if (needsLayout())
- return false;
- }
+ if (needsPositionedMovementLayout() && !tryLayoutDoingPositionedMovementOnly())
+ return false;
// Lay out positioned descendants or objects that just need to recompute overflow.
if (needsSimplifiedNormalFlowLayout())
@@ -2190,8 +2187,8 @@ void RenderBlock::layoutPositionedObjects(bool relayoutChildren)
// 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();
+ if (r->needsPositionedMovementLayoutOnly() && r->tryLayoutDoingPositionedMovementOnly())
+ r->setNeedsLayout(false);
r->layoutIfNeeded();
}
@@ -2376,7 +2373,7 @@ void RenderBlock::paintContents(PaintInfo& paintInfo, int tx, int ty)
// Avoid painting descendants of the root element when stylesheets haven't loaded. This eliminates FOUC.
// It's ok not to draw, because later on, when all the stylesheets do load, updateStyleSelector on the Document
// will do a full repaint().
- if (document()->mayCauseFlashOfUnstyledContent() && !isRenderView())
+ if (document()->didLayoutWithPendingStylesheets() && !isRenderView())
return;
if (childrenInline())
@@ -2606,7 +2603,7 @@ void RenderBlock::paintEllipsisBoxes(PaintInfo& paintInfo, int tx, int ty)
yPos = ty + curr->y();
h = curr->logicalHeight();
if (curr->ellipsisBox() && yPos < paintInfo.rect.maxY() && yPos + h > paintInfo.rect.y())
- curr->paintEllipsisBox(paintInfo, tx, ty);
+ curr->paintEllipsisBox(paintInfo, tx, ty, curr->lineTop(), curr->lineBottom());
}
}
}
@@ -3336,59 +3333,6 @@ bool RenderBlock::positionNewFloats()
return true;
}
-bool RenderBlock::positionNewFloatOnLine(FloatingObject* newFloat, FloatingObject* lastFloatFromPreviousLine, bool firstLine, int& lineLeftOffset, int& lineRightOffset)
-{
- bool didPosition = positionNewFloats();
- if (!didPosition)
- return didPosition;
-
- int blockOffset = logicalHeight();
- if (blockOffset >= logicalTopForFloat(newFloat) && blockOffset < logicalBottomForFloat(newFloat)) {
- if (newFloat->type() == FloatingObject::FloatLeft)
- lineLeftOffset = logicalRightForFloat(newFloat);
- else
- lineRightOffset = logicalLeftForFloat(newFloat);
- }
-
- if (!newFloat->m_paginationStrut)
- return didPosition;
-
- FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();
- ASSERT(floatingObjectSet.last() == newFloat);
-
- int floatLogicalTop = logicalTopForFloat(newFloat);
- int paginationStrut = newFloat->m_paginationStrut;
-
- if (floatLogicalTop - paginationStrut != logicalHeight())
- return didPosition;
-
- FloatingObjectSetIterator it = floatingObjectSet.end();
- --it; // Last float is newFloat, skip that one.
- FloatingObjectSetIterator begin = floatingObjectSet.begin();
- while (it != begin) {
- --it;
- FloatingObject* f = *it;
- if (f == lastFloatFromPreviousLine)
- break;
- if (logicalTopForFloat(f) == logicalHeight()) {
- ASSERT(!f->m_paginationStrut);
- f->m_paginationStrut = paginationStrut;
- RenderBox* o = f->m_renderer;
- setLogicalTopForChild(o, logicalTopForChild(o) + marginBeforeForChild(o) + paginationStrut);
- if (o->isRenderBlock())
- toRenderBlock(o)->setChildNeedsLayout(true, false);
- o->layoutIfNeeded();
- setLogicalTopForFloat(f, logicalTopForFloat(f) + f->m_paginationStrut);
- }
- }
-
- setLogicalHeight(blockOffset + paginationStrut);
- lineLeftOffset = logicalLeftOffsetForLine(logicalHeight(), firstLine);
- lineRightOffset = logicalRightOffsetForLine(logicalHeight(), firstLine);
-
- return didPosition;
-}
-
void RenderBlock::newLine(EClear clear)
{
positionNewFloats();
@@ -3721,6 +3665,7 @@ int RenderBlock::addOverhangingFloats(RenderBlock* child, int logicalLeftOffset,
if (child->hasOverflowClip() || !child->containsFloats() || child->isRoot() || child->hasColumns() || child->isWritingModeRoot())
return 0;
+ int childLogicalTop = child->logicalTop();
int lowestFloatLogicalBottom = 0;
// Floats that will remain the child's responsibility to paint should factor into its
@@ -3728,7 +3673,8 @@ int RenderBlock::addOverhangingFloats(RenderBlock* child, int logicalLeftOffset,
FloatingObjectSetIterator childEnd = child->m_floatingObjects->set().end();
for (FloatingObjectSetIterator childIt = child->m_floatingObjects->set().begin(); childIt != childEnd; ++childIt) {
FloatingObject* r = *childIt;
- int logicalBottom = child->logicalTop() + logicalBottomForFloat(r);
+ int logicalBottomForFloat = min(this->logicalBottomForFloat(r), numeric_limits<int>::max() - childLogicalTop);
+ int logicalBottom = childLogicalTop + logicalBottomForFloat;
lowestFloatLogicalBottom = max(lowestFloatLogicalBottom, logicalBottom);
if (logicalBottom > logicalHeight()) {
@@ -4277,34 +4223,15 @@ void RenderBlock::calcColumnWidth()
int colWidth = max(1, static_cast<int>(style()->columnWidth()));
int colCount = max(1, static_cast<int>(style()->columnCount()));
- if (style()->hasAutoColumnWidth()) {
- if ((colCount - 1) * colGap < availWidth) {
- desiredColumnCount = colCount;
- desiredColumnWidth = (availWidth - (desiredColumnCount - 1) * colGap) / desiredColumnCount;
- } else if (colGap < availWidth) {
- desiredColumnCount = availWidth / colGap;
- if (desiredColumnCount < 1)
- desiredColumnCount = 1;
- desiredColumnWidth = (availWidth - (desiredColumnCount - 1) * colGap) / desiredColumnCount;
- }
- } else if (style()->hasAutoColumnCount()) {
- if (colWidth < availWidth) {
- desiredColumnCount = (availWidth + colGap) / (colWidth + colGap);
- if (desiredColumnCount < 1)
- desiredColumnCount = 1;
- desiredColumnWidth = (availWidth - (desiredColumnCount - 1) * colGap) / desiredColumnCount;
- }
+ if (style()->hasAutoColumnWidth() && !style()->hasAutoColumnCount()) {
+ desiredColumnCount = colCount;
+ desiredColumnWidth = max<int>(0, (availWidth - ((desiredColumnCount - 1) * colGap)) / desiredColumnCount);
+ } else if (!style()->hasAutoColumnWidth() && style()->hasAutoColumnCount()) {
+ desiredColumnCount = max<int>(1, (float)(availWidth + colGap) / (colWidth + colGap));
+ desiredColumnWidth = ((availWidth + colGap) / desiredColumnCount) - colGap;
} else {
- // Both are set.
- if (colCount * colWidth + (colCount - 1) * colGap <= availWidth) {
- desiredColumnCount = colCount;
- desiredColumnWidth = colWidth;
- } else if (colWidth < availWidth) {
- desiredColumnCount = (availWidth + colGap) / (colWidth + colGap);
- if (desiredColumnCount < 1)
- desiredColumnCount = 1;
- desiredColumnWidth = (availWidth - (desiredColumnCount - 1) * colGap) / desiredColumnCount;
- }
+ desiredColumnCount = max(min<int>(colCount, (float)(availWidth + colGap) / (colWidth + colGap)), 1);
+ desiredColumnWidth = ((availWidth + colGap) / desiredColumnCount) - colGap;
}
setDesiredColumnCountAndWidth(desiredColumnCount, desiredColumnWidth);
}
@@ -5395,7 +5322,7 @@ void RenderBlock::updateFirstLetter()
view()->disableLayoutState();
while (RenderObject* child = firstLetter->firstChild()) {
if (child->isText())
- toRenderText(child)->dirtyLineBoxes(true);
+ toRenderText(child)->removeAndDestroyTextBoxes();
firstLetter->removeChild(child);
newFirstLetter->addChild(child, 0);
}
@@ -6081,8 +6008,9 @@ void RenderBlock::adjustLinePositionForPagination(RootInlineBox* lineBox, int& d
// line and all following lines.
LayoutState* layoutState = view()->layoutState();
int pageLogicalHeight = layoutState->m_pageLogicalHeight;
- int logicalOffset = lineBox->logicalTopVisualOverflow();
- int lineHeight = lineBox->logicalBottomVisualOverflow() - logicalOffset;
+ IntRect logicalVisualOverflow = lineBox->logicalVisualOverflowRect(lineBox->lineTop(), lineBox->lineBottom());
+ int logicalOffset = logicalVisualOverflow.y();
+ int lineHeight = logicalVisualOverflow.maxY() - logicalOffset;
if (layoutState->m_columnInfo)
layoutState->m_columnInfo->updateMinimumColumnHeight(lineHeight);
logicalOffset += delta;
diff --git a/Source/WebCore/rendering/RenderBlock.h b/Source/WebCore/rendering/RenderBlock.h
index 74751e1..75d93e9 100644
--- a/Source/WebCore/rendering/RenderBlock.h
+++ b/Source/WebCore/rendering/RenderBlock.h
@@ -32,16 +32,19 @@
namespace WebCore {
+class BidiContext;
class ColumnInfo;
class InlineIterator;
class LayoutStateMaintainer;
class LazyLineBreakIterator;
+class LineWidth;
class RenderInline;
struct BidiRun;
struct PaintInfo;
template <class Iterator, class Run> class BidiResolver;
+template <class Run> class BidiRunList;
template <class Iterator> struct MidpointState;
typedef BidiResolver<InlineIterator, BidiRun> InlineBidiResolver;
typedef MidpointState<InlineIterator> LineMidpointState;
@@ -151,7 +154,7 @@ public:
RenderBlock* createAnonymousColumnSpanBlock() const;
RenderBlock* createAnonymousBlockWithSameTypeAs(RenderBlock* otherAnonymousBlock) const;
- static void appendRunsForObject(int start, int end, RenderObject*, InlineBidiResolver&);
+ static void appendRunsForObject(BidiRunList<BidiRun>&, int start, int end, RenderObject*, InlineBidiResolver&);
static bool requiresLineBox(const InlineIterator&, bool isLineEmpty = true, bool previousLineBrokeCleanly = true);
ColumnInfo* columnInfo() const;
@@ -349,6 +352,7 @@ private:
void layoutBlockChildren(bool relayoutChildren, int& maxFloatLogicalBottom);
void layoutInlineChildren(bool relayoutChildren, int& repaintLogicalTop, int& repaintLogicalBottom);
+ BidiRun* handleTrailingSpaces(BidiRunList<BidiRun>&, BidiContext*);
virtual void borderFitAdjust(int& x, int& w) const; // Shrink the box in which the border paints if border-fit is set.
@@ -492,22 +496,23 @@ private:
RootInlineBox*& endLine, int& endYPos, int& repaintBottom, int& repaintTop);
void skipTrailingWhitespace(InlineIterator&, bool isLineEmpty, bool previousLineBrokeCleanly);
- void skipLeadingWhitespace(InlineBidiResolver&, bool firstLine, bool isLineEmpty, bool previousLineBrokeCleanly, FloatingObject* lastFloatFromPreviousLine, int& lineLeftOffset, int& lineRightOffset);
- void fitBelowFloats(float widthToFit, bool firstLine, float& availableWidth);
+ void skipLeadingWhitespace(InlineBidiResolver&, bool isLineEmpty, bool previousLineBrokeCleanly, FloatingObject* lastFloatFromPreviousLine, LineWidth&);
typedef std::pair<RenderText*, LazyLineBreakIterator> LineBreakIteratorInfo;
InlineIterator findNextLineBreak(InlineBidiResolver&, bool firstLine, bool& isLineEmpty, LineBreakIteratorInfo&, bool& previousLineBrokeCleanly, bool& hyphenated,
EClear*, FloatingObject* lastFloatFromPreviousLine, Vector<RenderBox*>& positionedObjects);
- RootInlineBox* constructLine(unsigned runCount, BidiRun* firstRun, BidiRun* lastRun, bool firstLine, bool lastLine, RenderObject* endObject, RenderObject* logicallyLastRunRenderer);
+ RootInlineBox* constructLine(BidiRunList<BidiRun>&, bool firstLine, bool lastLine);
InlineFlowBox* createLineBoxes(RenderObject*, bool firstLine, InlineBox* childBox);
void computeInlineDirectionPositionsForLine(RootInlineBox*, bool firstLine, BidiRun* firstRun, BidiRun* trailingSpaceRun, bool reachedEnd, GlyphOverflowAndFallbackFontsMap&, VerticalPositionCache&);
void computeBlockDirectionPositionsForLine(RootInlineBox*, BidiRun*, GlyphOverflowAndFallbackFontsMap&, VerticalPositionCache&);
void deleteEllipsisLineBoxes();
void checkLinesForTextOverflow();
- int beforeSideVisualOverflowForLine(RootInlineBox*) const;
- int afterSideVisualOverflowForLine(RootInlineBox*) const;
- int beforeSideLayoutOverflowForLine(RootInlineBox*) const;
- int afterSideLayoutOverflowForLine(RootInlineBox*) const;
+
+ // Positions new floats and also adjust all floats encountered on the line if any of them
+ // have to move to the next page/column.
+ bool positionNewFloatOnLine(FloatingObject* newFloat, FloatingObject* lastFloatFromPreviousLine, LineWidth&);
+ void appendFloatingObjectToLastLine(FloatingObject*);
+
// End of functions defined in RenderBlockLineLayout.cpp.
void paintFloats(PaintInfo&, int tx, int ty, bool preservePhase = false);
@@ -526,10 +531,6 @@ private:
// Called from lineWidth, to position the floats added in the last line.
// Returns true if and only if it has positioned any floats.
bool positionNewFloats();
-
- // Positions new floats and also adjust all floats encountered on the line if any of them
- // have to move to the next page/column.
- bool positionNewFloatOnLine(FloatingObject* newFloat, FloatingObject* lastFloatFromPreviousLine, bool firstLine, int& lineLeftOffset, int& lineRightOffset);
void clearFloats();
int getClearDelta(RenderBox* child, int yPos);
@@ -785,6 +786,7 @@ private:
// RenderRubyBase objects need to be able to split and merge, moving their children around
// (calling moveChildTo, moveAllChildrenTo, and makeChildrenNonInline).
friend class RenderRubyBase;
+ friend class LineWidth; // Needs to know FloatingObject
};
inline RenderBlock* toRenderBlock(RenderObject* object)
diff --git a/Source/WebCore/rendering/RenderBlockLineLayout.cpp b/Source/WebCore/rendering/RenderBlockLineLayout.cpp
index 3a0f016..06cbf90 100644
--- a/Source/WebCore/rendering/RenderBlockLineLayout.cpp
+++ b/Source/WebCore/rendering/RenderBlockLineLayout.cpp
@@ -32,6 +32,7 @@
#include "RenderInline.h"
#include "RenderLayer.h"
#include "RenderListMarker.h"
+#include "RenderRubyRun.h"
#include "RenderView.h"
#include "Settings.h"
#include "TextBreakIterator.h"
@@ -67,23 +68,27 @@ namespace WebCore {
// We don't let our line box tree for a single line get any deeper than this.
const unsigned cMaxLineDepth = 200;
-static int getBorderPaddingMargin(RenderBoxModelObject* child, bool endOfInline)
+static inline int borderPaddingMarginStart(RenderInline* child)
{
- if (endOfInline)
- return child->marginEnd() + child->paddingEnd() + child->borderEnd();
return child->marginStart() + child->paddingStart() + child->borderStart();
}
+static inline int borderPaddingMarginEnd(RenderInline* child)
+{
+ return child->marginEnd() + child->paddingEnd() + child->borderEnd();
+}
+
static int inlineLogicalWidth(RenderObject* child, bool start = true, bool end = true)
{
unsigned lineDepth = 1;
int extraWidth = 0;
RenderObject* parent = child->parent();
- while (parent->isInline() && !parent->isInlineBlockOrInlineTable() && lineDepth++ < cMaxLineDepth) {
+ while (parent->isRenderInline() && lineDepth++ < cMaxLineDepth) {
+ RenderInline* parentAsRenderInline = toRenderInline(parent);
if (start && !child->previousSibling())
- extraWidth += getBorderPaddingMargin(toRenderBoxModelObject(parent), false);
+ extraWidth += borderPaddingMarginStart(parentAsRenderInline);
if (end && !child->nextSibling())
- extraWidth += getBorderPaddingMargin(toRenderBoxModelObject(parent), true);
+ extraWidth += borderPaddingMarginEnd(parentAsRenderInline);
child = parent;
parent = child->parent();
}
@@ -120,10 +125,15 @@ static void addMidpoint(LineMidpointState& lineMidpointState, const InlineIterat
midpoints[lineMidpointState.numMidpoints++] = midpoint;
}
-void RenderBlock::appendRunsForObject(int start, int end, RenderObject* obj, InlineBidiResolver& resolver)
+static inline BidiRun* createRun(int start, int end, RenderObject* obj, InlineBidiResolver& resolver)
+{
+ return new (obj->renderArena()) BidiRun(start, end, obj, resolver.context(), resolver.dir());
+}
+
+void RenderBlock::appendRunsForObject(BidiRunList<BidiRun>& runs, int start, int end, RenderObject* obj, InlineBidiResolver& resolver)
{
if (start > end || obj->isFloating() ||
- (obj->isPositioned() && !obj->style()->hasAutoLeftAndRight() && !obj->style()->hasAutoTopAndBottom() && !obj->container()->isRenderInline()))
+ (obj->isPositioned() && !obj->style()->isOriginalDisplayInlineType() && !obj->container()->isRenderInline()))
return;
LineMidpointState& lineMidpointState = resolver.midpointState();
@@ -140,10 +150,10 @@ void RenderBlock::appendRunsForObject(int start, int end, RenderObject* obj, Inl
start = nextMidpoint.m_pos;
lineMidpointState.currentMidpoint++;
if (start < end)
- return appendRunsForObject(start, end, obj, resolver);
+ return appendRunsForObject(runs, start, end, obj, resolver);
} else {
if (!haveNextMidpoint || (obj != nextMidpoint.m_obj)) {
- resolver.addRun(new (obj->renderArena()) BidiRun(start, end, obj, resolver.context(), resolver.dir()));
+ runs.addRun(createRun(start, end, obj, resolver));
return;
}
@@ -154,12 +164,11 @@ void RenderBlock::appendRunsForObject(int start, int end, RenderObject* obj, Inl
lineMidpointState.currentMidpoint++;
if (nextMidpoint.m_pos != UINT_MAX) { // UINT_MAX means stop at the object and don't include any of it.
if (static_cast<int>(nextMidpoint.m_pos + 1) > start)
- resolver.addRun(new (obj->renderArena())
- BidiRun(start, nextMidpoint.m_pos + 1, obj, resolver.context(), resolver.dir()));
- return appendRunsForObject(nextMidpoint.m_pos + 1, end, obj, resolver);
+ runs.addRun(createRun(start, nextMidpoint.m_pos + 1, obj, resolver));
+ return appendRunsForObject(runs, nextMidpoint.m_pos + 1, end, obj, resolver);
}
} else
- resolver.addRun(new (obj->renderArena()) BidiRun(start, end, obj, resolver.context(), resolver.dir()));
+ runs.addRun(createRun(start, end, obj, resolver));
}
}
@@ -214,8 +223,10 @@ InlineFlowBox* RenderBlock::createLineBoxes(RenderObject* obj, bool firstLine, I
do {
ASSERT(obj->isRenderInline() || obj == this);
+ RenderInline* inlineFlow = (obj != this) ? toRenderInline(obj) : 0;
+
// Get the last box we made for this render object.
- parentBox = obj->isRenderInline() ? toRenderInline(obj)->lastLineBox() : toRenderBlock(obj)->lastLineBox();
+ parentBox = inlineFlow ? inlineFlow->lastLineBox() : toRenderBlock(obj)->lastLineBox();
// If this box or its ancestor is constructed then it is from a previous line, and we need
// to make a new box for our line. If this box or its ancestor is unconstructed but it has
@@ -223,7 +234,9 @@ InlineFlowBox* RenderBlock::createLineBoxes(RenderObject* obj, bool firstLine, I
// as well. In this situation our inline has actually been split in two on
// the same line (this can happen with very fancy language mixtures).
bool constructedNewBox = false;
- if (!parentBox || parentIsConstructedOrHaveNext(parentBox)) {
+ bool allowedToConstructNewBox = !hasDefaultLineBoxContain || !inlineFlow || inlineFlow->alwaysCreateLineBoxes();
+ bool canUseExistingParentBox = parentBox && !parentIsConstructedOrHaveNext(parentBox);
+ if (allowedToConstructNewBox && !canUseExistingParentBox) {
// We need to make a new box for this render object. Once
// made, we need to place it at the end of the current line.
InlineBox* newBox = createInlineBoxForRenderer(obj, obj == this);
@@ -236,19 +249,21 @@ InlineFlowBox* RenderBlock::createLineBoxes(RenderObject* obj, bool firstLine, I
constructedNewBox = true;
}
- if (!result)
- result = parentBox;
+ if (constructedNewBox || canUseExistingParentBox) {
+ if (!result)
+ result = parentBox;
- // If we have hit the block itself, then |box| represents the root
- // inline box for the line, and it doesn't have to be appended to any parent
- // inline.
- if (childBox)
- parentBox->addToLine(childBox);
+ // If we have hit the block itself, then |box| represents the root
+ // inline box for the line, and it doesn't have to be appended to any parent
+ // inline.
+ if (childBox)
+ parentBox->addToLine(childBox);
- if (!constructedNewBox || obj == this)
- break;
+ if (!constructedNewBox || obj == this)
+ break;
- childBox = parentBox;
+ childBox = parentBox;
+ }
// If we've exceeded our line depth, then jump straight to the root and skip all the remaining
// intermediate inline flows.
@@ -259,17 +274,38 @@ InlineFlowBox* RenderBlock::createLineBoxes(RenderObject* obj, bool firstLine, I
return result;
}
-RootInlineBox* RenderBlock::constructLine(unsigned runCount, BidiRun* firstRun, BidiRun* lastRun, bool firstLine, bool lastLine, RenderObject* endObject, RenderObject* logicallyLastRunRenderer)
+static bool reachedEndOfTextRenderer(const BidiRunList<BidiRun>& bidiRuns)
+{
+ BidiRun* run = bidiRuns.logicallyLastRun();
+ if (!run)
+ return true;
+ unsigned int pos = run->stop();
+ RenderObject* r = run->m_object;
+ if (!r->isText() || r->isBR())
+ return false;
+ RenderText* renderText = toRenderText(r);
+ if (pos >= renderText->textLength())
+ return true;
+
+ while (isASCIISpace(renderText->characters()[pos])) {
+ pos++;
+ if (pos >= renderText->textLength())
+ return true;
+ }
+ return false;
+}
+
+RootInlineBox* RenderBlock::constructLine(BidiRunList<BidiRun>& bidiRuns, bool firstLine, bool lastLine)
{
- ASSERT(firstRun);
+ ASSERT(bidiRuns.firstRun());
bool rootHasSelectedChildren = false;
InlineFlowBox* parentBox = 0;
- for (BidiRun* r = firstRun; r; r = r->next()) {
+ for (BidiRun* r = bidiRuns.firstRun(); r; r = r->next()) {
// Create a box for our object.
- bool isOnlyRun = (runCount == 1);
- if (runCount == 2 && !r->m_object->isListMarker())
- isOnlyRun = (!style()->isLeftToRightDirection() ? lastRun : firstRun)->m_object->isListMarker();
+ bool isOnlyRun = (bidiRuns.runCount() == 1);
+ if (bidiRuns.runCount() == 2 && !r->m_object->isListMarker())
+ isOnlyRun = (!style()->isLeftToRightDirection() ? bidiRuns.lastRun() : bidiRuns.firstRun())->m_object->isListMarker();
InlineBox* box = createInlineBoxForRenderer(r->m_object, false, isOnlyRun);
r->m_box = box;
@@ -318,7 +354,8 @@ RootInlineBox* RenderBlock::constructLine(unsigned runCount, BidiRun* firstRun,
// paint borders/margins/padding. This knowledge will ultimately be used when
// we determine the horizontal positions and widths of all the inline boxes on
// the line.
- lastLineBox()->determineSpacingForFlowBoxes(lastLine, endObject, logicallyLastRunRenderer);
+ bool isLogicallyLastRunWrapped = bidiRuns.logicallyLastRun()->m_object && bidiRuns.logicallyLastRun()->m_object->isText() ? !reachedEndOfTextRenderer(bidiRuns) : true;
+ lastLineBox()->determineSpacingForFlowBoxes(lastLine, isLogicallyLastRunWrapped, bidiRuns.logicallyLastRun()->m_object);
// Now mark the line boxes as being constructed.
lastLineBox()->setConstructed();
@@ -400,6 +437,7 @@ void RenderBlock::computeInlineDirectionPositionsForLine(RootInlineBox* lineBox,
unsigned expansionOpportunityCount = 0;
bool isAfterExpansion = true;
Vector<unsigned, 16> expansionOpportunities;
+ RenderObject* previousObject = 0;
for (BidiRun* r = firstRun; r; r = r->next()) {
if (!r->m_box || r->m_object->isPositioned() || r->m_box->isLineBreak())
@@ -456,18 +494,33 @@ void RenderBlock::computeInlineDirectionPositionsForLine(RootInlineBox* lineBox,
ASSERT(r->m_box->isText());
GlyphOverflowAndFallbackFontsMap::iterator it = textBoxDataMap.add(static_cast<InlineTextBox*>(r->m_box), make_pair(Vector<const SimpleFontData*>(), GlyphOverflow())).first;
it->second.second = glyphOverflow;
+ r->m_box->clearKnownToHaveNoOverflow();
}
} else {
isAfterExpansion = false;
if (!r->m_object->isRenderInline()) {
RenderBox* renderBox = toRenderBox(r->m_object);
- renderBox->computeLogicalWidth();
+ if (renderBox->isRubyRun()) {
+ int startOverhang;
+ int endOverhang;
+ RenderObject* nextObject = 0;
+ for (BidiRun* runWithNextObject = r->next(); runWithNextObject; runWithNextObject = runWithNextObject->next()) {
+ if (!runWithNextObject->m_object->isPositioned() && !runWithNextObject->m_box->isLineBreak()) {
+ nextObject = runWithNextObject->m_object;
+ break;
+ }
+ }
+ toRenderRubyRun(renderBox)->getOverhang(firstLine, renderBox->style()->isLeftToRightDirection() ? previousObject : nextObject, renderBox->style()->isLeftToRightDirection() ? nextObject : previousObject, startOverhang, endOverhang);
+ setMarginStartForChild(renderBox, -startOverhang);
+ setMarginEndForChild(renderBox, -endOverhang);
+ }
r->m_box->setLogicalWidth(logicalWidthForChild(renderBox));
totalLogicalWidth += marginStartForChild(renderBox) + marginEndForChild(renderBox);
}
}
totalLogicalWidth += r->m_box->logicalWidth();
+ previousObject = r->m_object;
}
if (isAfterExpansion && !expansionOpportunities.isEmpty()) {
@@ -616,27 +669,70 @@ static void setStaticPositions(RenderBlock* block, RenderBox* child)
child->layer()->setStaticBlockPosition(blockHeight);
}
-static bool reachedEndOfTextRenderer(InlineBidiResolver& resolver)
+inline BidiRun* RenderBlock::handleTrailingSpaces(BidiRunList<BidiRun>& bidiRuns, BidiContext* currentContext)
{
- BidiRun* run = resolver.logicallyLastRun();
- if (!run)
- return true;
- unsigned int pos = run->stop();
- RenderObject* r = run->m_object;
- if (!r->isText() || r->isBR())
- return false;
- RenderText* renderText = toRenderText(r);
- if (pos >= renderText->textLength())
- return true;
+ if (!bidiRuns.runCount()
+ || !bidiRuns.logicallyLastRun()->m_object->style()->breakOnlyAfterWhiteSpace()
+ || !bidiRuns.logicallyLastRun()->m_object->style()->autoWrap())
+ return 0;
- while (isASCIISpace(renderText->characters()[pos])) {
- pos++;
- if (pos >= renderText->textLength())
- return true;
+ BidiRun* trailingSpaceRun = bidiRuns.logicallyLastRun();
+ RenderObject* lastObject = trailingSpaceRun->m_object;
+ if (!lastObject->isText())
+ return 0;
+
+ RenderText* lastText = toRenderText(lastObject);
+ const UChar* characters = lastText->characters();
+ int firstSpace = trailingSpaceRun->stop();
+ while (firstSpace > trailingSpaceRun->start()) {
+ UChar current = characters[firstSpace - 1];
+ if (!isCollapsibleSpace(current, lastText))
+ break;
+ firstSpace--;
}
- return false;
+ if (firstSpace == trailingSpaceRun->stop())
+ return 0;
+
+ TextDirection direction = style()->direction();
+ bool shouldReorder = trailingSpaceRun != (direction == LTR ? bidiRuns.lastRun() : bidiRuns.firstRun());
+ if (firstSpace != trailingSpaceRun->start()) {
+ BidiContext* baseContext = currentContext;
+ while (BidiContext* parent = baseContext->parent())
+ baseContext = parent;
+
+ BidiRun* newTrailingRun = new (renderArena()) BidiRun(firstSpace, trailingSpaceRun->m_stop, trailingSpaceRun->m_object, baseContext, OtherNeutral);
+ trailingSpaceRun->m_stop = firstSpace;
+ if (direction == LTR)
+ bidiRuns.addRun(newTrailingRun);
+ else
+ bidiRuns.prependRun(newTrailingRun);
+ trailingSpaceRun = newTrailingRun;
+ return trailingSpaceRun;
+ }
+ if (!shouldReorder)
+ return trailingSpaceRun;
+
+ if (direction == LTR) {
+ bidiRuns.moveRunToEnd(trailingSpaceRun);
+ trailingSpaceRun->m_level = 0;
+ } else {
+ bidiRuns.moveRunToBeginning(trailingSpaceRun);
+ trailingSpaceRun->m_level = 1;
+ }
+ return trailingSpaceRun;
}
-
+
+void RenderBlock::appendFloatingObjectToLastLine(FloatingObject* floatingObject)
+{
+ // Ensure that the float touches the line.
+ if (RootInlineBox* previousLine = lastRootBox()->prevRootBox()) {
+ if (logicalBottomForFloat(floatingObject) < previousLine->blockLogicalHeight())
+ setLogicalHeightForFloat(floatingObject, previousLine->blockLogicalHeight() - logicalTopForFloat(floatingObject));
+ }
+
+ lastRootBox()->appendFloat(floatingObject->renderer());
+}
+
void RenderBlock::layoutInlineChildren(bool relayoutChildren, int& repaintLogicalTop, int& repaintLogicalBottom)
{
bool useRepaintBounds = false;
@@ -741,6 +837,8 @@ void RenderBlock::layoutInlineChildren(bool relayoutChildren, int& repaintLogica
}
#endif // PLATFORM(ANDROID)
} else if (o->isText() || (o->isRenderInline() && !endOfInline)) {
+ if (!o->isText())
+ toRenderInline(o)->updateAlwaysCreateLineBoxes();
if (fullLayout || o->selfNeedsLayout())
dirtyLineBoxesForRenderer(o, fullLayout);
o->setNeedsLayout(false);
@@ -853,8 +951,8 @@ void RenderBlock::layoutInlineChildren(bool relayoutChildren, int& repaintLogica
RenderArena* arena = renderArena();
RootInlineBox* box = startLine;
while (box) {
- repaintLogicalTop = min(repaintLogicalTop, beforeSideVisualOverflowForLine(box));
- repaintLogicalBottom = max(repaintLogicalBottom, afterSideVisualOverflowForLine(box));
+ repaintLogicalTop = min(repaintLogicalTop, box->logicalTopVisualOverflow());
+ repaintLogicalBottom = max(repaintLogicalBottom, box->logicalBottomVisualOverflow());
RootInlineBox* next = box->nextRootBox();
box->deleteLine(arena);
box = next;
@@ -906,7 +1004,10 @@ void RenderBlock::layoutInlineChildren(bool relayoutChildren, int& repaintLogica
FloatingObject* lastFloatFromPreviousLine = (m_floatingObjects && !m_floatingObjects->set().isEmpty()) ? m_floatingObjects->set().last() : 0;
end = findNextLineBreak(resolver, firstLine, isLineEmpty, lineBreakIteratorInfo, previousLineBrokeCleanly, hyphenated, &clear, lastFloatFromPreviousLine, positionedObjects);
if (resolver.position().atEnd()) {
- resolver.deleteRuns();
+ // FIXME: We shouldn't be creating any runs in findNextLineBreak to begin with!
+ // Once BidiRunList is separated from BidiResolver this will not be needed.
+ resolver.runs().deleteRuns();
+ resolver.markCurrentRunEmpty(); // FIXME: This can probably be replaced by an ASSERT (or just removed).
checkForFloatsFromLastLine = true;
break;
}
@@ -917,56 +1018,12 @@ void RenderBlock::layoutInlineChildren(bool relayoutChildren, int& repaintLogica
lastRootBox()->setLineBreakInfo(end.m_obj, end.m_pos, resolver.status());
} else {
VisualDirectionOverride override = (style()->visuallyOrdered() ? (style()->direction() == LTR ? VisualLeftToRightOverride : VisualRightToLeftOverride) : NoVisualOverride);
+ // FIXME: This ownership is reversed. We should own the BidiRunList and pass it to createBidiRunsForLine.
+ BidiRunList<BidiRun>& bidiRuns = resolver.runs();
resolver.createBidiRunsForLine(end, override, previousLineBrokeCleanly);
ASSERT(resolver.position() == end);
- BidiRun* trailingSpaceRun = 0;
- if (!previousLineBrokeCleanly && resolver.runCount() && resolver.logicallyLastRun()->m_object->style()->breakOnlyAfterWhiteSpace()
- && resolver.logicallyLastRun()->m_object->style()->autoWrap()) {
- trailingSpaceRun = resolver.logicallyLastRun();
- RenderObject* lastObject = trailingSpaceRun->m_object;
- if (lastObject->isText()) {
- RenderText* lastText = toRenderText(lastObject);
- const UChar* characters = lastText->characters();
- int firstSpace = trailingSpaceRun->stop();
- while (firstSpace > trailingSpaceRun->start()) {
- UChar current = characters[firstSpace - 1];
- if (!isCollapsibleSpace(current, lastText))
- break;
- firstSpace--;
- }
- if (firstSpace == trailingSpaceRun->stop())
- trailingSpaceRun = 0;
- else {
- TextDirection direction = style()->direction();
- bool shouldReorder = trailingSpaceRun != (direction == LTR ? resolver.lastRun() : resolver.firstRun());
- if (firstSpace != trailingSpaceRun->start()) {
- BidiContext* baseContext = resolver.context();
- while (BidiContext* parent = baseContext->parent())
- baseContext = parent;
-
- BidiRun* newTrailingRun = new (renderArena()) BidiRun(firstSpace, trailingSpaceRun->m_stop, trailingSpaceRun->m_object, baseContext, OtherNeutral);
- trailingSpaceRun->m_stop = firstSpace;
- if (direction == LTR)
- resolver.addRun(newTrailingRun);
- else
- resolver.prependRun(newTrailingRun);
- trailingSpaceRun = newTrailingRun;
- shouldReorder = false;
- }
- if (shouldReorder) {
- if (direction == LTR) {
- resolver.moveRunToEnd(trailingSpaceRun);
- trailingSpaceRun->m_level = 0;
- } else {
- resolver.moveRunToBeginning(trailingSpaceRun);
- trailingSpaceRun->m_level = 1;
- }
- }
- }
- } else
- trailingSpaceRun = 0;
- }
+ BidiRun* trailingSpaceRun = !previousLineBrokeCleanly ? handleTrailingSpaces(bidiRuns, resolver.context()) : 0;
// Now that the runs have been ordered, we create the line boxes.
// At the same time we figure out where border/padding/margin should be applied for
@@ -974,11 +1031,10 @@ void RenderBlock::layoutInlineChildren(bool relayoutChildren, int& repaintLogica
RootInlineBox* lineBox = 0;
int oldLogicalHeight = logicalHeight();
- if (resolver.runCount()) {
+ if (bidiRuns.runCount()) {
if (hyphenated)
- resolver.logicallyLastRun()->m_hasHyphen = true;
- bool lastLine = end.m_obj && end.m_obj->isText() ? reachedEndOfTextRenderer(resolver) : !end.m_obj;
- lineBox = constructLine(resolver.runCount(), resolver.firstRun(), resolver.lastRun(), firstLine, lastLine, end.m_obj && !end.m_pos ? end.m_obj : 0, resolver.logicallyLastRun()->m_object);
+ bidiRuns.logicallyLastRun()->m_hasHyphen = true;
+ lineBox = constructLine(bidiRuns, firstLine, !end.m_obj);
if (lineBox) {
lineBox->setEndsWithBreak(previousLineBrokeCleanly);
@@ -992,10 +1048,10 @@ void RenderBlock::layoutInlineChildren(bool relayoutChildren, int& repaintLogica
// Now we position all of our text runs horizontally.
if (!isSVGRootInlineBox)
- computeInlineDirectionPositionsForLine(lineBox, firstLine, resolver.firstRun(), trailingSpaceRun, end.atEnd(), textBoxDataMap, verticalPositionCache);
+ computeInlineDirectionPositionsForLine(lineBox, firstLine, bidiRuns.firstRun(), trailingSpaceRun, end.atEnd(), textBoxDataMap, verticalPositionCache);
// Now position our text runs vertically.
- computeBlockDirectionPositionsForLine(lineBox, resolver.firstRun(), textBoxDataMap, verticalPositionCache);
+ computeBlockDirectionPositionsForLine(lineBox, bidiRuns.firstRun(), textBoxDataMap, verticalPositionCache);
#if ENABLE(SVG)
// SVG text layout code computes vertical & horizontal positions on its own.
@@ -1010,7 +1066,7 @@ void RenderBlock::layoutInlineChildren(bool relayoutChildren, int& repaintLogica
#endif
// Compute our overflow now.
- lineBox->computeOverflow(lineBox->lineTop(), lineBox->lineBottom(), document()->inNoQuirksMode(), textBoxDataMap);
+ lineBox->computeOverflow(lineBox->lineTop(), lineBox->lineBottom(), textBoxDataMap);
#if PLATFORM(MAC)
// Highlight acts as an overflow inflation.
@@ -1020,13 +1076,14 @@ void RenderBlock::layoutInlineChildren(bool relayoutChildren, int& repaintLogica
}
}
- resolver.deleteRuns();
+ bidiRuns.deleteRuns();
+ resolver.markCurrentRunEmpty(); // FIXME: This can probably be replaced by an ASSERT (or just removed).
if (lineBox) {
lineBox->setLineBreakInfo(end.m_obj, end.m_pos, resolver.status());
if (useRepaintBounds) {
- repaintLogicalTop = min(repaintLogicalTop, beforeSideVisualOverflowForLine(lineBox));
- repaintLogicalBottom = max(repaintLogicalBottom, afterSideVisualOverflowForLine(lineBox));
+ repaintLogicalTop = min(repaintLogicalTop, lineBox->logicalTopVisualOverflow());
+ repaintLogicalBottom = max(repaintLogicalBottom, lineBox->logicalBottomVisualOverflow());
}
if (paginated) {
@@ -1036,7 +1093,7 @@ void RenderBlock::layoutInlineChildren(bool relayoutChildren, int& repaintLogica
int oldLineWidth = availableLogicalWidthForLine(oldLogicalHeight, firstLine);
lineBox->adjustBlockDirectionPosition(adjustment);
if (useRepaintBounds) // This can only be a positive adjustment, so no need to update repaintTop.
- repaintLogicalBottom = max(repaintLogicalBottom, afterSideVisualOverflowForLine(lineBox));
+ repaintLogicalBottom = max(repaintLogicalBottom, lineBox->logicalBottomVisualOverflow());
if (availableLogicalWidthForLine(oldLogicalHeight + adjustment, firstLine) != oldLineWidth) {
// We have to delete this line, remove all floats that got added, and let line layout re-run.
@@ -1072,7 +1129,7 @@ void RenderBlock::layoutInlineChildren(bool relayoutChildren, int& repaintLogica
}
for (; it != end; ++it) {
FloatingObject* f = *it;
- lastRootBox()->floats().append(f->m_renderer);
+ appendFloatingObjectToLastLine(f);
ASSERT(f->m_renderer == floats[floatIndex].object);
// If a float's geometry has changed, give up on syncing with clean lines.
if (floats[floatIndex].rect != f->frameRect())
@@ -1097,8 +1154,8 @@ void RenderBlock::layoutInlineChildren(bool relayoutChildren, int& repaintLogica
adjustLinePositionForPagination(line, delta);
}
if (delta) {
- repaintLogicalTop = min(repaintLogicalTop, beforeSideVisualOverflowForLine(line) + min(delta, 0));
- repaintLogicalBottom = max(repaintLogicalBottom, afterSideVisualOverflowForLine(line) + max(delta, 0));
+ repaintLogicalTop = min(repaintLogicalTop, line->logicalTopVisualOverflow() + min(delta, 0));
+ repaintLogicalBottom = max(repaintLogicalBottom, line->logicalBottomVisualOverflow() + max(delta, 0));
line->adjustBlockDirectionPosition(delta);
}
if (Vector<RenderBox*>* cleanLineFloats = line->floatsPtr()) {
@@ -1116,8 +1173,8 @@ void RenderBlock::layoutInlineChildren(bool relayoutChildren, int& repaintLogica
RootInlineBox* line = endLine;
RenderArena* arena = renderArena();
while (line) {
- repaintLogicalTop = min(repaintLogicalTop, beforeSideVisualOverflowForLine(line));
- repaintLogicalBottom = max(repaintLogicalBottom, afterSideVisualOverflowForLine(line));
+ repaintLogicalTop = min(repaintLogicalTop, line->logicalTopVisualOverflow());
+ repaintLogicalBottom = max(repaintLogicalBottom, line->logicalBottomVisualOverflow());
RootInlineBox* next = line->nextRootBox();
line->deleteLine(arena);
line = next;
@@ -1129,17 +1186,18 @@ 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 = afterSideVisualOverflowForLine(lastRootBox());
- int bottomLayoutOverflow = afterSideLayoutOverflowForLine(lastRootBox());
+ int bottomVisualOverflow = lastRootBox()->logicalBottomVisualOverflow();
+ int bottomLayoutOverflow = lastRootBox()->logicalBottomLayoutOverflow();
TrailingFloatsRootInlineBox* trailingFloatsLineBox = new (renderArena()) TrailingFloatsRootInlineBox(this);
m_lineBoxes.appendLineBox(trailingFloatsLineBox);
trailingFloatsLineBox->setConstructed();
GlyphOverflowAndFallbackFontsMap textBoxDataMap;
VerticalPositionCache verticalPositionCache;
trailingFloatsLineBox->alignBoxesInBlockDirection(logicalHeight(), textBoxDataMap, verticalPositionCache);
- IntRect logicalLayoutOverflow(0, logicalHeight(), 1, bottomLayoutOverflow);
- IntRect logicalVisualOverflow(0, logicalHeight(), 1, bottomVisualOverflow);
- trailingFloatsLineBox->setOverflowFromLogicalRects(logicalLayoutOverflow, logicalVisualOverflow);
+ int blockLogicalHeight = logicalHeight();
+ IntRect logicalLayoutOverflow(0, blockLogicalHeight, 1, bottomLayoutOverflow - blockLogicalHeight);
+ IntRect logicalVisualOverflow(0, blockLogicalHeight, 1, bottomVisualOverflow - blockLogicalHeight);
+ trailingFloatsLineBox->setOverflowFromLogicalRects(logicalLayoutOverflow, logicalVisualOverflow, trailingFloatsLineBox->lineTop(), trailingFloatsLineBox->lineBottom());
trailingFloatsLineBox->setBlockLogicalHeight(logicalHeight());
}
@@ -1153,7 +1211,7 @@ void RenderBlock::layoutInlineChildren(bool relayoutChildren, int& repaintLogica
it = lastFloatIterator;
}
for (; it != end; ++it)
- lastRootBox()->floats().append((*it)->m_renderer);
+ appendFloatingObjectToLastLine(*it);
lastFloat = !floatingObjectSet.isEmpty() ? floatingObjectSet.last() : 0;
}
size_t floatCount = floats.size();
@@ -1211,6 +1269,7 @@ void RenderBlock::checkFloatsInCleanLine(RootInlineBox* line, Vector<FloatWithRe
int floatTop = isHorizontalWritingMode() ? floats[floatIndex].rect.y() : floats[floatIndex].rect.x();
int floatHeight = isHorizontalWritingMode() ? max(floats[floatIndex].rect.height(), newSize.height())
: max(floats[floatIndex].rect.width(), newSize.width());
+ floatHeight = min(floatHeight, numeric_limits<int>::max() - floatTop);
line->markDirty();
markLinesDirtyInBlockRange(line->blockLogicalHeight(), floatTop + floatHeight, line);
floats[floatIndex].rect.setSize(newSize);
@@ -1247,8 +1306,8 @@ RootInlineBox* RenderBlock::determineStartPosition(bool& firstLine, bool& fullLa
if (!useRepaintBounds)
useRepaintBounds = true;
- repaintLogicalTop = min(repaintLogicalTop, beforeSideVisualOverflowForLine(curr) + min(paginationDelta, 0));
- repaintLogicalBottom = max(repaintLogicalBottom, afterSideVisualOverflowForLine(curr) + max(paginationDelta, 0));
+ repaintLogicalTop = min(repaintLogicalTop, curr->logicalTopVisualOverflow() + min(paginationDelta, 0));
+ repaintLogicalBottom = max(repaintLogicalBottom, curr->logicalBottomVisualOverflow() + max(paginationDelta, 0));
curr->adjustBlockDirectionPosition(paginationDelta);
}
}
@@ -1448,8 +1507,8 @@ bool RenderBlock::matchedEndLine(const InlineBidiResolver& resolver, const Inlin
RootInlineBox* boxToDelete = endLine;
RenderArena* arena = renderArena();
while (boxToDelete && boxToDelete != result) {
- repaintLogicalTop = min(repaintLogicalTop, beforeSideVisualOverflowForLine(boxToDelete));
- repaintLogicalBottom = max(repaintLogicalBottom, afterSideVisualOverflowForLine(boxToDelete));
+ repaintLogicalTop = min(repaintLogicalTop, boxToDelete->logicalTopVisualOverflow());
+ repaintLogicalBottom = max(repaintLogicalBottom, boxToDelete->logicalBottomVisualOverflow());
RootInlineBox* next = boxToDelete->nextRootBox();
boxToDelete->deleteLine(arena);
boxToDelete = next;
@@ -1484,16 +1543,6 @@ static inline bool shouldCollapseWhiteSpace(const RenderStyle* style, bool isLin
return style->collapseWhiteSpace() || (style->whiteSpace() == PRE_WRAP && (!isLineEmpty || !previousLineBrokeCleanly));
}
-static inline bool shouldPreserveNewline(RenderObject* object)
-{
-#if ENABLE(SVG)
- if (object->isSVGInlineText())
- return false;
-#endif
-
- return object->style()->preserveNewline();
-}
-
static bool inlineFlowRequiresLineBox(RenderInline* flow)
{
// FIXME: Right now, we only allow line boxes for inlines that are truly empty.
@@ -1514,7 +1563,7 @@ bool RenderBlock::requiresLineBox(const InlineIterator& it, bool isLineEmpty, bo
return true;
UChar current = it.current();
- return current != ' ' && current != '\t' && current != softHyphen && (current != '\n' || shouldPreserveNewline(it.m_obj))
+ return current != ' ' && current != '\t' && current != softHyphen && (current != '\n' || it.m_obj->preservesNewline())
&& !skipNonBreakingSpace(it, isLineEmpty, previousLineBrokeCleanly);
}
@@ -1547,13 +1596,13 @@ void RenderBlock::skipTrailingWhitespace(InlineIterator& iterator, bool isLineEm
}
}
-void RenderBlock::skipLeadingWhitespace(InlineBidiResolver& resolver, bool firstLine, bool isLineEmpty, bool previousLineBrokeCleanly,
- FloatingObject* lastFloatFromPreviousLine, int& lineLeftOffset, int& lineRightOffset)
+void RenderBlock::skipLeadingWhitespace(InlineBidiResolver& resolver, bool isLineEmpty, bool previousLineBrokeCleanly,
+ FloatingObject* lastFloatFromPreviousLine, LineWidth& width)
{
while (!resolver.position().atEnd() && !requiresLineBox(resolver.position(), isLineEmpty, previousLineBrokeCleanly)) {
RenderObject* object = resolver.position().m_obj;
if (object->isFloating())
- positionNewFloatOnLine(insertFloatingObject(toRenderBox(object)), lastFloatFromPreviousLine, firstLine, lineLeftOffset, lineRightOffset);
+ positionNewFloatOnLine(insertFloatingObject(toRenderBox(object)), lastFloatFromPreviousLine, width);
else if (object->isPositioned())
setStaticPositions(this, toRenderBox(object));
resolver.increment();
@@ -1578,30 +1627,6 @@ static bool shouldSkipWhitespaceAfterStartObject(RenderBlock* block, RenderObjec
return false;
}
-void RenderBlock::fitBelowFloats(float widthToFit, bool firstLine, float& availableWidth)
-{
- ASSERT(widthToFit > availableWidth);
-
- int floatLogicalBottom;
- int lastFloatLogicalBottom = logicalHeight();
- float newLineWidth = availableWidth;
- while (true) {
- floatLogicalBottom = nextFloatLogicalBottomBelow(lastFloatLogicalBottom);
- if (!floatLogicalBottom)
- break;
-
- newLineWidth = availableLogicalWidthForLine(floatLogicalBottom, firstLine);
- lastFloatLogicalBottom = floatLogicalBottom;
- if (newLineWidth >= widthToFit)
- break;
- }
-
- if (newLineWidth > availableWidth) {
- setLogicalHeight(lastFloatLogicalBottom);
- availableWidth = newLineWidth;
- }
-}
-
static inline float textWidth(RenderText* text, unsigned from, unsigned len, const Font& font, float xPos, bool isFixedPitch, bool collapseWhiteSpace)
{
if (isFixedPitch || (!from && len == text->textLength()) || text->style()->hasTextCombine())
@@ -1654,23 +1679,131 @@ static void tryHyphenating(RenderText* text, const Font& font, const AtomicStrin
hyphenated = true;
}
+class LineWidth {
+public:
+ LineWidth(RenderBlock* block, bool isFirstLine)
+ : m_block(block)
+ , m_uncommittedWidth(0)
+ , m_committedWidth(0)
+ , m_overhangWidth(0)
+ , m_left(0)
+ , m_right(0)
+ , m_availableWidth(0)
+ , m_isFirstLine(isFirstLine)
+ {
+ ASSERT(block);
+ updateAvailableWidth();
+ }
+ bool fitsOnLine() const { return currentWidth() <= m_availableWidth; }
+ bool fitsOnLine(float extra) const { return currentWidth() + extra <= m_availableWidth; }
+ float currentWidth() const { return m_committedWidth + m_uncommittedWidth; }
+
+ // FIXME: We should eventually replace these three functions by ones that work on a higher abstraction.
+ float uncommittedWidth() const { return m_uncommittedWidth; }
+ float committedWidth() const { return m_committedWidth; }
+ float availableWidth() const { return m_availableWidth; }
+
+ void updateAvailableWidth();
+ void shrinkAvailableWidthForNewFloatIfNeeded(RenderBlock::FloatingObject*);
+ void addUncommittedWidth(float delta) { m_uncommittedWidth += delta; }
+ void commit()
+ {
+ m_committedWidth += m_uncommittedWidth;
+ m_uncommittedWidth = 0;
+ }
+ void applyOverhang(RenderRubyRun*, RenderObject* startRenderer, RenderObject* endRenderer);
+ void fitBelowFloats();
+
+private:
+ void computeAvailableWidthFromLeftAndRight()
+ {
+ m_availableWidth = max(0, m_right - m_left) + m_overhangWidth;
+ }
+
+private:
+ RenderBlock* m_block;
+ float m_uncommittedWidth;
+ float m_committedWidth;
+ float m_overhangWidth; // The amount by which |m_availableWidth| has been inflated to account for possible contraction due to ruby overhang.
+ int m_left;
+ int m_right;
+ float m_availableWidth;
+ bool m_isFirstLine;
+};
+
+inline void LineWidth::updateAvailableWidth()
+{
+ int height = m_block->logicalHeight();
+ m_left = m_block->logicalLeftOffsetForLine(height, m_isFirstLine);
+ m_right = m_block->logicalRightOffsetForLine(height, m_isFirstLine);
+
+ computeAvailableWidthFromLeftAndRight();
+}
+
+inline void LineWidth::shrinkAvailableWidthForNewFloatIfNeeded(RenderBlock::FloatingObject* newFloat)
+{
+ int height = m_block->logicalHeight();
+ if (height < m_block->logicalTopForFloat(newFloat) || height >= m_block->logicalBottomForFloat(newFloat))
+ return;
+
+ if (newFloat->type() == RenderBlock::FloatingObject::FloatLeft)
+ m_left = m_block->logicalRightForFloat(newFloat);
+ else
+ m_right = m_block->logicalLeftForFloat(newFloat);
+
+ computeAvailableWidthFromLeftAndRight();
+}
+
+void LineWidth::applyOverhang(RenderRubyRun* rubyRun, RenderObject* startRenderer, RenderObject* endRenderer)
+{
+ int startOverhang;
+ int endOverhang;
+ rubyRun->getOverhang(m_isFirstLine, startRenderer, endRenderer, startOverhang, endOverhang);
+
+ startOverhang = min<int>(startOverhang, m_committedWidth);
+ m_availableWidth += startOverhang;
+
+ endOverhang = max(min<int>(endOverhang, m_availableWidth - currentWidth()), 0);
+ m_availableWidth += endOverhang;
+ m_overhangWidth += startOverhang + endOverhang;
+}
+
+void LineWidth::fitBelowFloats()
+{
+ ASSERT(!m_committedWidth);
+ ASSERT(!fitsOnLine());
+
+ int floatLogicalBottom;
+ int lastFloatLogicalBottom = m_block->logicalHeight();
+ float newLineWidth = m_availableWidth;
+ while (true) {
+ floatLogicalBottom = m_block->nextFloatLogicalBottomBelow(lastFloatLogicalBottom);
+ if (!floatLogicalBottom)
+ break;
+
+ newLineWidth = m_block->availableLogicalWidthForLine(floatLogicalBottom, m_isFirstLine);
+ lastFloatLogicalBottom = floatLogicalBottom;
+ if (newLineWidth >= m_uncommittedWidth)
+ break;
+ }
+
+ if (newLineWidth > m_availableWidth) {
+ m_block->setLogicalHeight(lastFloatLogicalBottom);
+ m_availableWidth = newLineWidth + m_overhangWidth;
+ }
+}
+
InlineIterator RenderBlock::findNextLineBreak(InlineBidiResolver& resolver, bool firstLine, bool& isLineEmpty, LineBreakIteratorInfo& lineBreakIteratorInfo, bool& previousLineBrokeCleanly,
bool& hyphenated, EClear* clear, FloatingObject* lastFloatFromPreviousLine, Vector<RenderBox*>& positionedBoxes)
{
- ASSERT(resolver.position().m_block == this);
+ ASSERT(resolver.position().root() == this);
bool appliedStartWidth = resolver.position().m_pos > 0;
LineMidpointState& lineMidpointState = resolver.midpointState();
-
- int blockOffset = logicalHeight();
- int lineLeftOffset = logicalLeftOffsetForLine(blockOffset, firstLine);
- int lineRightOffset = logicalRightOffsetForLine(blockOffset, firstLine);
-
- skipLeadingWhitespace(resolver, firstLine, isLineEmpty, previousLineBrokeCleanly, lastFloatFromPreviousLine, lineLeftOffset, lineRightOffset);
- float width = max(0, lineRightOffset - lineLeftOffset);
- float w = 0;
- float tmpW = 0;
+ LineWidth width(this, firstLine);
+
+ skipLeadingWhitespace(resolver, isLineEmpty, previousLineBrokeCleanly, lastFloatFromPreviousLine, width);
if (resolver.position().atEnd())
return resolver.position();
@@ -1714,6 +1847,8 @@ InlineIterator RenderBlock::findNextLineBreak(InlineBidiResolver& resolver, bool
EWhiteSpace currWS = style()->whiteSpace();
EWhiteSpace lastWS = currWS;
while (o) {
+ RenderObject* next = bidiNext(this, o);
+
currWS = o->isReplaced() ? o->parent()->style()->whiteSpace() : o->style()->whiteSpace();
lastWS = last->isReplaced() ? last->parent()->style()->whiteSpace() : last->style()->whiteSpace();
@@ -1729,7 +1864,7 @@ InlineIterator RenderBlock::findNextLineBreak(InlineBidiResolver& resolver, bool
bool collapseWhiteSpace = RenderStyle::collapseWhiteSpace(currWS);
if (o->isBR()) {
- if (w + tmpW <= width) {
+ if (width.fitsOnLine()) {
lBreak.moveToStartOf(o);
lBreak.increment();
@@ -1757,9 +1892,8 @@ InlineIterator RenderBlock::findNextLineBreak(InlineBidiResolver& resolver, bool
// check if it fits in the current line.
// If it does, position it now, otherwise, position
// it after moving to next line (in newLine() func)
- if (floatsFitOnLine && logicalWidthForFloat(f) + w + tmpW <= width) {
- positionNewFloatOnLine(f, lastFloatFromPreviousLine, firstLine, lineLeftOffset, lineRightOffset);
- width = max(0, lineRightOffset - lineLeftOffset);
+ if (floatsFitOnLine && width.fitsOnLine(logicalWidthForFloat(f))) {
+ positionNewFloatOnLine(f, lastFloatFromPreviousLine, width);
if (lBreak.m_obj == o) {
ASSERT(!lBreak.m_pos);
lBreak.increment();
@@ -1820,15 +1954,13 @@ InlineIterator RenderBlock::findNextLineBreak(InlineBidiResolver& resolver, bool
}
}
- tmpW += flowBox->marginStart() + flowBox->borderStart() + flowBox->paddingStart() +
- flowBox->marginEnd() + flowBox->borderEnd() + flowBox->paddingEnd();
+ width.addUncommittedWidth(borderPaddingMarginStart(flowBox) + borderPaddingMarginEnd(flowBox));
} else if (o->isReplaced()) {
RenderBox* replacedBox = toRenderBox(o);
// Break on replaced elements if either has normal white-space.
if ((autoWrap || RenderStyle::autoWrap(lastWS)) && (!o->isImage() || allowImagesToBreak)) {
- w += tmpW;
- tmpW = 0;
+ width.commit();
lBreak.moveToStartOf(o);
}
@@ -1854,9 +1986,11 @@ InlineIterator RenderBlock::findNextLineBreak(InlineBidiResolver& resolver, bool
ignoringSpaces = true;
}
if (toRenderListMarker(o)->isInside())
- tmpW += replacedLogicalWidth;
+ width.addUncommittedWidth(replacedLogicalWidth);
} else
- tmpW += replacedLogicalWidth;
+ width.addUncommittedWidth(replacedLogicalWidth);
+ if (o->isRubyRun())
+ width.applyOverhang(toRenderRubyRun(o), last, next);
} else if (o->isText()) {
if (!pos)
appliedStartWidth = false;
@@ -1887,19 +2021,18 @@ InlineIterator RenderBlock::findNextLineBreak(InlineBidiResolver& resolver, bool
// space, then subtract its width.
float wordTrailingSpaceWidth = f.typesettingFeatures() & Kerning ? f.width(TextRun(&space, 1)) + wordSpacing : 0;
- float wrapW = tmpW + inlineLogicalWidth(o, !appliedStartWidth, true);
+ float wrapW = width.uncommittedWidth() + inlineLogicalWidth(o, !appliedStartWidth, true);
float charWidth = 0;
bool breakNBSP = autoWrap && o->style()->nbspMode() == SPACE;
// Auto-wrapping text should wrap in the middle of a word only if it could not wrap before the word,
// which is only possible if the word is the first thing on the line, that is, if |w| is zero.
- bool breakWords = o->style()->breakWords() && ((autoWrap && !w) || currWS == PRE);
+ bool breakWords = o->style()->breakWords() && ((autoWrap && !width.committedWidth()) || currWS == PRE);
bool midWordBreak = false;
bool breakAll = o->style()->wordBreak() == BreakAllWordBreak && autoWrap;
float hyphenWidth = 0;
if (t->isWordBreak()) {
- w += tmpW;
- tmpW = 0;
+ width.commit();
lBreak.moveToStartOf(o);
ASSERT(!len);
}
@@ -1916,29 +2049,17 @@ InlineIterator RenderBlock::findNextLineBreak(InlineBidiResolver& resolver, bool
if (c == softHyphen && autoWrap && !hyphenWidth && style->hyphens() != HyphensNone) {
const AtomicString& hyphenString = style->hyphenString();
hyphenWidth = f.width(TextRun(hyphenString.characters(), hyphenString.length()));
- tmpW += hyphenWidth;
+ width.addUncommittedWidth(hyphenWidth);
}
-#if ENABLE(SVG)
- if (isSVGText) {
- RenderSVGInlineText* svgInlineText = static_cast<RenderSVGInlineText*>(t);
- if (pos > 0) {
- if (svgInlineText->characterStartsNewTextChunk(pos)) {
- addMidpoint(lineMidpointState, InlineIterator(0, o, pos - 1));
- addMidpoint(lineMidpointState, InlineIterator(0, o, pos));
- }
- }
- }
-#endif
-
bool applyWordSpacing = false;
currentCharacterIsWS = currentCharacterIsSpace || (breakNBSP && c == noBreakSpace);
if ((breakAll || breakWords) && !midWordBreak) {
wrapW += charWidth;
- charWidth = textWidth(t, pos, 1, f, w + wrapW, isFixedPitch, collapseWhiteSpace);
- midWordBreak = w + wrapW + charWidth > width;
+ charWidth = textWidth(t, pos, 1, f, width.committedWidth() + wrapW, isFixedPitch, collapseWhiteSpace);
+ midWordBreak = width.committedWidth() + wrapW + charWidth > width.availableWidth();
}
if (lineBreakIteratorInfo.first != t) {
@@ -1969,44 +2090,44 @@ InlineIterator RenderBlock::findNextLineBreak(InlineBidiResolver& resolver, bool
float additionalTmpW;
if (wordTrailingSpaceWidth && currentCharacterIsSpace)
- additionalTmpW = textWidth(t, lastSpace, pos + 1 - lastSpace, f, w + tmpW, isFixedPitch, collapseWhiteSpace) - wordTrailingSpaceWidth + lastSpaceWordSpacing;
+ additionalTmpW = textWidth(t, lastSpace, pos + 1 - lastSpace, f, width.currentWidth(), isFixedPitch, collapseWhiteSpace) - wordTrailingSpaceWidth + lastSpaceWordSpacing;
else
- additionalTmpW = textWidth(t, lastSpace, pos - lastSpace, f, w + tmpW, isFixedPitch, collapseWhiteSpace) + lastSpaceWordSpacing;
- tmpW += additionalTmpW;
+ additionalTmpW = textWidth(t, lastSpace, pos - lastSpace, f, width.currentWidth(), isFixedPitch, collapseWhiteSpace) + lastSpaceWordSpacing;
+ width.addUncommittedWidth(additionalTmpW);
if (!appliedStartWidth) {
- tmpW += inlineLogicalWidth(o, true, false);
+ width.addUncommittedWidth(inlineLogicalWidth(o, true, false));
appliedStartWidth = true;
}
applyWordSpacing = wordSpacing && currentCharacterIsSpace && !previousCharacterIsSpace;
- if (!w && autoWrap && tmpW > width)
- fitBelowFloats(tmpW, firstLine, width);
+ if (!width.committedWidth() && autoWrap && !width.fitsOnLine())
+ width.fitBelowFloats();
if (autoWrap || breakWords) {
// If we break only after white-space, consider the current character
// as candidate width for this line.
bool lineWasTooWide = false;
- if (w + tmpW <= width && currentCharacterIsWS && o->style()->breakOnlyAfterWhiteSpace() && !midWordBreak) {
- int charWidth = textWidth(t, pos, 1, f, w + tmpW, isFixedPitch, collapseWhiteSpace) + (applyWordSpacing ? wordSpacing : 0);
+ if (width.fitsOnLine() && currentCharacterIsWS && o->style()->breakOnlyAfterWhiteSpace() && !midWordBreak) {
+ int charWidth = textWidth(t, pos, 1, f, width.currentWidth(), isFixedPitch, collapseWhiteSpace) + (applyWordSpacing ? wordSpacing : 0);
// Check if line is too big even without the extra space
// at the end of the line. If it is not, do nothing.
// If the line needs the extra whitespace to be too long,
// then move the line break to the space and skip all
// additional whitespace.
- if (w + tmpW + charWidth > width) {
+ if (!width.fitsOnLine(charWidth)) {
lineWasTooWide = true;
lBreak.moveTo(o, pos, nextBreakable);
skipTrailingWhitespace(lBreak, isLineEmpty, previousLineBrokeCleanly);
}
}
- if (lineWasTooWide || w + tmpW > width) {
- if (canHyphenate && w + tmpW > width) {
- tryHyphenating(t, f, style->locale(), style->hyphenationLimitBefore(), style->hyphenationLimitAfter(), lastSpace, pos, w + tmpW - additionalTmpW, width, isFixedPitch, collapseWhiteSpace, lastSpaceWordSpacing, lBreak, nextBreakable, hyphenated);
+ if (lineWasTooWide || !width.fitsOnLine()) {
+ if (canHyphenate && !width.fitsOnLine()) {
+ tryHyphenating(t, f, style->locale(), style->hyphenationLimitBefore(), style->hyphenationLimitAfter(), lastSpace, pos, width.currentWidth() - additionalTmpW, width.availableWidth(), isFixedPitch, collapseWhiteSpace, lastSpaceWordSpacing, lBreak, nextBreakable, hyphenated);
if (hyphenated)
goto end;
}
- if (lBreak.m_obj && shouldPreserveNewline(lBreak.m_obj) && lBreak.m_obj->isText() && toRenderText(lBreak.m_obj)->textLength() && !toRenderText(lBreak.m_obj)->isWordBreak() && toRenderText(lBreak.m_obj)->characters()[lBreak.m_pos] == '\n') {
+ if (lBreak.atTextParagraphSeparator()) {
if (!stoppedIgnoringSpaces && pos > 0) {
// We need to stop right before the newline and then start up again.
addMidpoint(lineMidpointState, InlineIterator(0, o, pos - 1)); // Stop
@@ -2020,10 +2141,10 @@ InlineIterator RenderBlock::findNextLineBreak(InlineBidiResolver& resolver, bool
goto end; // Didn't fit. Jump to the end.
} else {
if (!betweenWords || (midWordBreak && !autoWrap))
- tmpW -= additionalTmpW;
+ width.addUncommittedWidth(-additionalTmpW);
if (hyphenWidth) {
// Subtract the width of the soft hyphen out since we fit on a line.
- tmpW -= hyphenWidth;
+ width.addUncommittedWidth(-hyphenWidth);
hyphenWidth = 0;
}
}
@@ -2042,9 +2163,8 @@ InlineIterator RenderBlock::findNextLineBreak(InlineBidiResolver& resolver, bool
}
if (autoWrap && betweenWords) {
- w += tmpW;
+ width.commit();
wrapW = 0;
- tmpW = 0;
lBreak.moveTo(o, pos, nextBreakable);
// Auto-wrapping text should not wrap in the middle of a word once it has had an
// opportunity to break after a word.
@@ -2085,6 +2205,16 @@ InlineIterator RenderBlock::findNextLineBreak(InlineBidiResolver& resolver, bool
addMidpoint(lineMidpointState, InlineIterator(0, o, pos));
}
+#if ENABLE(SVG)
+ if (isSVGText && pos > 0) {
+ // Force creation of new InlineBoxes for each absolute positioned character (those that start new text chunks).
+ if (static_cast<RenderSVGInlineText*>(t)->characterStartsNewTextChunk(pos)) {
+ addMidpoint(lineMidpointState, InlineIterator(0, o, pos - 1));
+ addMidpoint(lineMidpointState, InlineIterator(0, o, pos));
+ }
+ }
+#endif
+
if (currentCharacterIsSpace && !previousCharacterIsSpace) {
ignoreStart.m_obj = o;
ignoreStart.m_pos = pos;
@@ -2108,26 +2238,24 @@ InlineIterator RenderBlock::findNextLineBreak(InlineBidiResolver& resolver, bool
}
// IMPORTANT: pos is > length here!
- float additionalTmpW = ignoringSpaces ? 0 : textWidth(t, lastSpace, pos - lastSpace, f, w + tmpW, isFixedPitch, collapseWhiteSpace) + lastSpaceWordSpacing;
- tmpW += additionalTmpW;
- tmpW += inlineLogicalWidth(o, !appliedStartWidth, true);
+ float additionalTmpW = ignoringSpaces ? 0 : textWidth(t, lastSpace, pos - lastSpace, f, width.currentWidth(), isFixedPitch, collapseWhiteSpace) + lastSpaceWordSpacing;
+ width.addUncommittedWidth(additionalTmpW + inlineLogicalWidth(o, !appliedStartWidth, true));
- if (w + tmpW > width) {
+ if (!width.fitsOnLine()) {
if (canHyphenate)
- tryHyphenating(t, f, style->locale(), style->hyphenationLimitBefore(), style->hyphenationLimitAfter(), lastSpace, pos, w + tmpW - additionalTmpW, width, isFixedPitch, collapseWhiteSpace, lastSpaceWordSpacing, lBreak, nextBreakable, hyphenated);
-
+ tryHyphenating(t, f, style->locale(), style->hyphenationLimitBefore(), style->hyphenationLimitAfter(), lastSpace, pos, width.currentWidth() - additionalTmpW, width.availableWidth(), isFixedPitch, collapseWhiteSpace, lastSpaceWordSpacing, lBreak, nextBreakable, hyphenated);
+
if (!hyphenated && lBreak.m_obj && lBreak.m_pos && lBreak.m_obj->isText() && toRenderText(lBreak.m_obj)->textLength() && toRenderText(lBreak.m_obj)->characters()[lBreak.m_pos - 1] == softHyphen && style->hyphens() != HyphensNone)
hyphenated = true;
-
+
if (hyphenated)
goto end;
}
} else
ASSERT_NOT_REACHED();
- RenderObject* next = bidiNext(this, o);
bool checkForBreak = autoWrap;
- if (w && w + tmpW > width && lBreak.m_obj && currWS == NOWRAP)
+ if (width.committedWidth() && !width.fitsOnLine() && lBreak.m_obj && currWS == NOWRAP)
checkForBreak = true;
else if (next && o->isText() && next->isText() && !next->isBR()) {
if (autoWrap || (next->style()->autoWrap())) {
@@ -2138,52 +2266,49 @@ InlineIterator RenderBlock::findNextLineBreak(InlineBidiResolver& resolver, bool
RenderText* nextText = toRenderText(next);
if (nextText->textLength()) {
UChar c = nextText->characters()[0];
- if (c == ' ' || c == '\t' || (c == '\n' && !shouldPreserveNewline(next)))
+ if (c == ' ' || c == '\t' || (c == '\n' && !next->preservesNewline()))
// If the next item on the line is text, and if we did not end with
// a space, then the next text run continues our word (and so it needs to
// keep adding to |tmpW|. Just update and continue.
checkForBreak = true;
} else if (nextText->isWordBreak())
checkForBreak = true;
- bool willFitOnLine = w + tmpW <= width;
- if (!willFitOnLine && !w) {
- fitBelowFloats(tmpW, firstLine, width);
- willFitOnLine = tmpW <= width;
- }
- bool canPlaceOnLine = willFitOnLine || !autoWrapWasEverTrueOnLine;
+
+ if (!width.fitsOnLine() && !width.committedWidth())
+ width.fitBelowFloats();
+
+ bool canPlaceOnLine = width.fitsOnLine() || !autoWrapWasEverTrueOnLine;
if (canPlaceOnLine && checkForBreak) {
- w += tmpW;
- tmpW = 0;
+ width.commit();
lBreak.moveToStartOf(next);
}
}
}
}
- if (checkForBreak && (w + tmpW > width)) {
+ if (checkForBreak && !width.fitsOnLine()) {
// if we have floats, try to get below them.
if (currentCharacterIsSpace && !ignoringSpaces && o->style()->collapseWhiteSpace()) {
trailingSpaceObject = 0;
trailingPositionedBoxes.clear();
}
- if (w)
+ if (width.committedWidth())
goto end;
- fitBelowFloats(tmpW, firstLine, width);
+ width.fitBelowFloats();
// |width| may have been adjusted because we got shoved down past a float (thus
// giving us more room), so we need to retest, and only jump to
// the end label if we still don't fit on the line. -dwh
- if (w + tmpW > width)
+ if (!width.fitsOnLine())
goto end;
}
if (!o->isFloatingOrPositioned()) {
last = o;
if (last->isReplaced() && autoWrap && (!last->isImage() || allowImagesToBreak) && (!last->isListMarker() || toRenderListMarker(last)->isInside())) {
- w += tmpW;
- tmpW = 0;
+ width.commit();
lBreak.moveToStartOf(next);
}
}
@@ -2199,9 +2324,8 @@ InlineIterator RenderBlock::findNextLineBreak(InlineBidiResolver& resolver, bool
pos = 0;
atStart = false;
}
-
- if (w + tmpW <= width || lastWS == NOWRAP)
+ if (width.fitsOnLine() || lastWS == NOWRAP)
lBreak.clear();
end:
@@ -2294,42 +2418,10 @@ void RenderBlock::addOverflowFromInlineChildren()
for (RootInlineBox* curr = firstRootBox(); curr; curr = curr->nextRootBox()) {
addLayoutOverflow(curr->paddedLayoutOverflowRect(endPadding));
if (!hasOverflowClip())
- addVisualOverflow(curr->visualOverflowRect());
+ addVisualOverflow(curr->visualOverflowRect(curr->lineTop(), curr->lineBottom()));
}
}
-int RenderBlock::beforeSideVisualOverflowForLine(RootInlineBox* line) const
-{
- // Overflow is in the block's coordinate space, which means it isn't purely physical.
- if (isHorizontalWritingMode())
- return line->minYVisualOverflow();
- return line->minXVisualOverflow();
-}
-
-int RenderBlock::afterSideVisualOverflowForLine(RootInlineBox* line) const
-{
- // Overflow is in the block's coordinate space, which means it isn't purely physical.
- if (isHorizontalWritingMode())
- return line->maxYVisualOverflow();
- return line->maxXVisualOverflow();
-}
-
-int RenderBlock::beforeSideLayoutOverflowForLine(RootInlineBox* line) const
-{
- // Overflow is in the block's coordinate space, which means it isn't purely physical.
- if (isHorizontalWritingMode())
- return line->minYLayoutOverflow();
- return line->minXLayoutOverflow();
-}
-
-int RenderBlock::afterSideLayoutOverflowForLine(RootInlineBox* line) const
-{
- // Overflow is in the block's coordinate space, which means it isn't purely physical.
- if (isHorizontalWritingMode())
- return line->maxYLayoutOverflow();
- return line->maxXLayoutOverflow();
-}
-
void RenderBlock::deleteEllipsisLineBoxes()
{
for (RootInlineBox* curr = firstRootBox(); curr; curr = curr->nextRootBox())
@@ -2369,4 +2461,49 @@ void RenderBlock::checkLinesForTextOverflow()
}
}
+bool RenderBlock::positionNewFloatOnLine(FloatingObject* newFloat, FloatingObject* lastFloatFromPreviousLine, LineWidth& width)
+{
+ if (!positionNewFloats())
+ return false;
+
+ width.shrinkAvailableWidthForNewFloatIfNeeded(newFloat);
+
+ if (!newFloat->m_paginationStrut)
+ return true;
+
+ FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();
+ ASSERT(floatingObjectSet.last() == newFloat);
+
+ int floatLogicalTop = logicalTopForFloat(newFloat);
+ int paginationStrut = newFloat->m_paginationStrut;
+
+ if (floatLogicalTop - paginationStrut != logicalHeight())
+ return true;
+
+ FloatingObjectSetIterator it = floatingObjectSet.end();
+ --it; // Last float is newFloat, skip that one.
+ FloatingObjectSetIterator begin = floatingObjectSet.begin();
+ while (it != begin) {
+ --it;
+ FloatingObject* f = *it;
+ if (f == lastFloatFromPreviousLine)
+ break;
+ if (logicalTopForFloat(f) == logicalHeight()) {
+ ASSERT(!f->m_paginationStrut);
+ f->m_paginationStrut = paginationStrut;
+ RenderBox* o = f->m_renderer;
+ setLogicalTopForChild(o, logicalTopForChild(o) + marginBeforeForChild(o) + paginationStrut);
+ if (o->isRenderBlock())
+ toRenderBlock(o)->setChildNeedsLayout(true, false);
+ o->layoutIfNeeded();
+ setLogicalTopForFloat(f, logicalTopForFloat(f) + f->m_paginationStrut);
+ }
+ }
+
+ setLogicalHeight(logicalHeight() + paginationStrut);
+ width.updateAvailableWidth();
+
+ return true;
+}
+
}
diff --git a/Source/WebCore/rendering/RenderBox.cpp b/Source/WebCore/rendering/RenderBox.cpp
index 7b32f07..11c0306 100644
--- a/Source/WebCore/rendering/RenderBox.cpp
+++ b/Source/WebCore/rendering/RenderBox.cpp
@@ -966,7 +966,7 @@ void RenderBox::paintFillLayers(const PaintInfo& paintInfo, const Color& c, cons
void RenderBox::paintFillLayer(const PaintInfo& paintInfo, const Color& c, const FillLayer* fillLayer, int tx, int ty, int width, int height, CompositeOperator op, RenderObject* backgroundObject)
{
- paintFillLayerExtended(paintInfo, c, fillLayer, tx, ty, width, height, 0, op, backgroundObject);
+ paintFillLayerExtended(paintInfo, c, fillLayer, tx, ty, width, height, 0, 0, 0, op, backgroundObject);
}
#if USE(ACCELERATED_COMPOSITING)
diff --git a/Source/WebCore/rendering/RenderBox.h b/Source/WebCore/rendering/RenderBox.h
index ccedc66..f8aee06 100644
--- a/Source/WebCore/rendering/RenderBox.h
+++ b/Source/WebCore/rendering/RenderBox.h
@@ -350,15 +350,15 @@ public:
// Called when a positioned object moves but doesn't necessarily change size. A simplified layout is attempted
// that just updates the object's position. If the size does change, the object remains dirty.
- void tryLayoutDoingPositionedMovementOnly()
+ bool tryLayoutDoingPositionedMovementOnly()
{
int oldWidth = width();
computeLogicalWidth();
// If we shrink to fit our width may have changed, so we still need full layout.
if (oldWidth != width())
- return;
+ return false;
computeLogicalHeight();
- setNeedsLayout(false);
+ return true;
}
IntRect maskClipRect();
@@ -398,9 +398,13 @@ public:
IntRect logicalLayoutOverflowRectForPropagation(RenderStyle*) const;
IntRect layoutOverflowRectForPropagation(RenderStyle*) const;
+<<<<<<< HEAD
#ifdef ANDROID_LAYOUT
int getVisibleWidth() const { return m_visibleWidth; }
#endif
+=======
+ RenderOverflow* hasRenderOverflow() const { return m_overflow.get(); }
+>>>>>>> WebKit.org at r84325
protected:
virtual void styleWillChange(StyleDifference, const RenderStyle* newStyle);
diff --git a/Source/WebCore/rendering/RenderBoxModelObject.cpp b/Source/WebCore/rendering/RenderBoxModelObject.cpp
index 3e2974d..52196e3 100644
--- a/Source/WebCore/rendering/RenderBoxModelObject.cpp
+++ b/Source/WebCore/rendering/RenderBoxModelObject.cpp
@@ -559,7 +559,20 @@ int RenderBoxModelObject::paddingEnd(bool) const
return padding.calcMinValue(w);
}
-void RenderBoxModelObject::paintFillLayerExtended(const PaintInfo& paintInfo, const Color& c, const FillLayer* bgLayer, int tx, int ty, int w, int h, InlineFlowBox* box, CompositeOperator op, RenderObject* backgroundObject)
+RoundedIntRect RenderBoxModelObject::getBackgroundRoundedRect(const IntRect& borderRect, InlineFlowBox* box, int inlineBoxWidth, int inlineBoxHeight,
+ bool includeLogicalLeftEdge, bool includeLogicalRightEdge)
+{
+ RoundedIntRect border = style()->getRoundedBorderFor(borderRect, includeLogicalLeftEdge, includeLogicalRightEdge);
+ if (box && (box->nextLineBox() || box->prevLineBox())) {
+ RoundedIntRect segmentBorder = style()->getRoundedBorderFor(IntRect(0, 0, inlineBoxWidth, inlineBoxHeight), includeLogicalLeftEdge, includeLogicalRightEdge);
+ border.setRadii(segmentBorder.radii());
+ }
+
+ return border;
+}
+
+void RenderBoxModelObject::paintFillLayerExtended(const PaintInfo& paintInfo, const Color& color, const FillLayer* bgLayer, int tx, int ty, int w, int h,
+ InlineFlowBox* box, int inlineBoxWidth, int inlineBoxHeight, CompositeOperator op, RenderObject* backgroundObject)
{
GraphicsContext* context = paintInfo.context;
if (context->paintingDisabled())
@@ -567,13 +580,53 @@ void RenderBoxModelObject::paintFillLayerExtended(const PaintInfo& paintInfo, co
bool includeLeftEdge = box ? box->includeLogicalLeftEdge() : true;
bool includeRightEdge = box ? box->includeLogicalRightEdge() : true;
- int bLeft = includeLeftEdge ? borderLeft() : 0;
- int bRight = includeRightEdge ? borderRight() : 0;
- int pLeft = includeLeftEdge ? paddingLeft() : 0;
- int pRight = includeRightEdge ? paddingRight() : 0;
+
+ bool hasRoundedBorder = style()->hasBorderRadius() && (includeLeftEdge || includeRightEdge);
+ bool clippedWithLocalScrolling = hasOverflowClip() && bgLayer->attachment() == LocalBackgroundAttachment;
+ bool isBorderFill = bgLayer->clip() == BorderFillBox;
+ bool isRoot = this->isRoot();
+
+ Color bgColor = color;
+ StyleImage* bgImage = bgLayer->image();
+ bool shouldPaintBackgroundImage = bgImage && bgImage->canRender(style()->effectiveZoom());
+
+ // When this style flag is set, change existing background colors and images to a solid white background.
+ // If there's no bg color or image, leave it untouched to avoid affecting transparency.
+ // We don't try to avoid loading the background images, because this style flag is only set
+ // when printing, and at that point we've already loaded the background images anyway. (To avoid
+ // loading the background images we'd have to do this check when applying styles rather than
+ // while rendering.)
+ if (style()->forceBackgroundsToWhite()) {
+ // Note that we can't reuse this variable below because the bgColor might be changed
+ bool shouldPaintBackgroundColor = !bgLayer->next() && bgColor.isValid() && bgColor.alpha() > 0;
+ if (shouldPaintBackgroundImage || shouldPaintBackgroundColor) {
+ bgColor = Color::white;
+ shouldPaintBackgroundImage = false;
+ }
+ }
+
+ bool colorVisible = bgColor.isValid() && bgColor.alpha() > 0;
+
+ // Fast path for drawing simple color backgrounds.
+ if (!isRoot && !clippedWithLocalScrolling && !shouldPaintBackgroundImage && isBorderFill) {
+ if (!colorVisible)
+ return;
+
+ IntRect borderRect(tx, ty, w, h);
+ if (borderRect.isEmpty())
+ return;
+
+ if (hasRoundedBorder) {
+ RoundedIntRect border = getBackgroundRoundedRect(borderRect, box, inlineBoxWidth, inlineBoxHeight, includeLeftEdge, includeRightEdge);
+ context->fillRoundedRect(border, bgColor, style()->colorSpace());
+ } else
+ context->fillRect(borderRect, bgColor, style()->colorSpace());
+
+ return;
+ }
bool clippedToBorderRadius = false;
- if (style()->hasBorderRadius() && (includeLeftEdge || includeRightEdge)) {
+ if (hasRoundedBorder) {
IntRect borderRect(tx, ty, w, h);
if (borderRect.isEmpty())
@@ -581,13 +634,16 @@ void RenderBoxModelObject::paintFillLayerExtended(const PaintInfo& paintInfo, co
context->save();
- RoundedIntRect border = style()->getRoundedBorderFor(borderRect);
- border.excludeLogicalEdges(box && box->isHorizontal(), !includeLeftEdge, !includeRightEdge);
+ RoundedIntRect border = getBackgroundRoundedRect(borderRect, box, inlineBoxWidth, inlineBoxHeight, includeLeftEdge, includeRightEdge);
context->addRoundedRectClip(border);
clippedToBorderRadius = true;
}
+
+ int bLeft = includeLeftEdge ? borderLeft() : 0;
+ int bRight = includeRightEdge ? borderRight() : 0;
+ int pLeft = includeLeftEdge ? paddingLeft() : 0;
+ int pRight = includeRightEdge ? paddingRight() : 0;
- bool clippedWithLocalScrolling = hasOverflowClip() && bgLayer->attachment() == LocalBackgroundAttachment;
if (clippedWithLocalScrolling) {
// Clip to the overflow area.
context->save();
@@ -628,9 +684,10 @@ void RenderBoxModelObject::paintFillLayerExtended(const PaintInfo& paintInfo, co
// Now add the text to the clip. We do this by painting using a special paint phase that signals to
// InlineTextBoxes that they should just add their contents to the clip.
PaintInfo info(maskImageContext, maskRect, PaintPhaseTextClip, true, 0, 0);
- if (box)
- box->paint(info, tx - box->x(), ty - box->y());
- else {
+ if (box) {
+ RootInlineBox* root = box->root();
+ box->paint(info, tx - box->x(), ty - box->y(), root->lineTop(), root->lineBottom());
+ } else {
int x = isBox() ? toRenderBox(this)->x() : 0;
int y = isBox() ? toRenderBox(this)->y() : 0;
paint(info, tx - x, ty - y);
@@ -641,27 +698,6 @@ void RenderBoxModelObject::paintFillLayerExtended(const PaintInfo& paintInfo, co
context->clipToImageBuffer(maskImage.get(), maskRect);
}
- StyleImage* bg = bgLayer->image();
- bool shouldPaintBackgroundImage = bg && bg->canRender(style()->effectiveZoom());
- Color bgColor = c;
-
- // When this style flag is set, change existing background colors and images to a solid white background.
- // If there's no bg color or image, leave it untouched to avoid affecting transparency.
- // We don't try to avoid loading the background images, because this style flag is only set
- // when printing, and at that point we've already loaded the background images anyway. (To avoid
- // loading the background images we'd have to do this check when applying styles rather than
- // while rendering.)
- if (style()->forceBackgroundsToWhite()) {
- // Note that we can't reuse this variable below because the bgColor might be changed
- bool shouldPaintBackgroundColor = !bgLayer->next() && bgColor.isValid() && bgColor.alpha() > 0;
- if (shouldPaintBackgroundImage || shouldPaintBackgroundColor) {
- bgColor = Color::white;
- shouldPaintBackgroundImage = false;
- }
- }
-
- bool isRoot = this->isRoot();
-
// Only fill with a base color (e.g., white) if we're the root document, since iframes/frames with
// no background in the child document should show the parent's background.
bool isOpaqueRoot = false;
@@ -726,18 +762,16 @@ void RenderBoxModelObject::paintFillLayerExtended(const PaintInfo& paintInfo, co
phase += destRect.location() - destOrigin;
CompositeOperator compositeOp = op == CompositeSourceOver ? bgLayer->composite() : op;
RenderObject* clientForBackgroundImage = backgroundObject ? backgroundObject : this;
- RefPtr<Image> image = bg->image(clientForBackgroundImage, tileSize);
+ RefPtr<Image> image = bgImage->image(clientForBackgroundImage, tileSize);
bool useLowQualityScaling = shouldPaintAtLowQuality(context, image.get(), bgLayer, tileSize);
context->drawTiledImage(image.get(), style()->colorSpace(), destRect, phase, tileSize, compositeOp, useLowQualityScaling);
}
}
- if (bgLayer->clip() != BorderFillBox)
- // Undo the background clip
+ if (!isBorderFill) // Undo the background clip
context->restore();
- if (clippedToBorderRadius)
- // Undo the border radius clip
+ if (clippedToBorderRadius) // Undo the border radius clip
context->restore();
if (clippedWithLocalScrolling) // Undo the clip for local background attachments.
@@ -1001,170 +1035,560 @@ bool RenderBoxModelObject::paintNinePieceImage(GraphicsContext* graphicsContext,
}
#if HAVE(PATH_BASED_BORDER_RADIUS_DRAWING)
-static bool borderWillArcInnerEdge(const IntSize& firstRadius, const IntSize& secondRadius, int firstBorderWidth, int secondBorderWidth, int middleBorderWidth)
+static bool borderWillArcInnerEdge(const IntSize& firstRadius, const IntSize& secondRadius)
{
- // FIXME: This test is insufficient. We need to take border style into account.
- return (!firstRadius.width() || firstRadius.width() >= firstBorderWidth)
- && (!firstRadius.height() || firstRadius.height() >= middleBorderWidth)
- && (!secondRadius.width() || secondRadius.width() >= secondBorderWidth)
- && (!secondRadius.height() || secondRadius.height() >= middleBorderWidth);
+ return !firstRadius.isZero() || !secondRadius.isZero();
}
-void RenderBoxModelObject::paintBorder(GraphicsContext* graphicsContext, int tx, int ty, int w, int h,
- const RenderStyle* style, bool includeLogicalLeftEdge, bool includeLogicalRightEdge)
+enum BorderEdgeFlag {
+ TopBorderEdge = 1 << BSTop,
+ RightBorderEdge = 1 << BSRight,
+ BottomBorderEdge = 1 << BSBottom,
+ LeftBorderEdge = 1 << BSLeft,
+ AllBorderEdges = TopBorderEdge | BottomBorderEdge | LeftBorderEdge | RightBorderEdge
+};
+
+static inline BorderEdgeFlag edgeFlagForSide(BoxSide side)
{
- if (paintNinePieceImage(graphicsContext, tx, ty, w, h, style, style->borderImage()))
- return;
+ return static_cast<BorderEdgeFlag>(1 << side);
+}
- if (graphicsContext->paintingDisabled())
- return;
+static inline bool includesEdge(BorderEdgeFlags flags, BoxSide side)
+{
+ return flags & edgeFlagForSide(side);
+}
- const Color& topColor = style->visitedDependentColor(CSSPropertyBorderTopColor);
- const Color& bottomColor = style->visitedDependentColor(CSSPropertyBorderBottomColor);
- const Color& leftColor = style->visitedDependentColor(CSSPropertyBorderLeftColor);
- const Color& rightColor = style->visitedDependentColor(CSSPropertyBorderRightColor);
+class BorderEdge {
+public:
+ BorderEdge(int edgeWidth, const Color& edgeColor, EBorderStyle edgeStyle, bool edgeIsTransparent, bool edgeIsPresent)
+ : width(edgeWidth)
+ , color(edgeColor)
+ , style(edgeStyle)
+ , isTransparent(edgeIsTransparent)
+ , isPresent(edgeIsPresent)
+ {
+ if (style == DOUBLE && edgeWidth < 3)
+ style = SOLID;
+ }
+
+ bool hasVisibleColorAndStyle() const { return style > BHIDDEN && !isTransparent; }
+ bool shouldRender() const { return isPresent && hasVisibleColorAndStyle(); }
+ bool presentButInvisible() const { return usedWidth() && !hasVisibleColorAndStyle(); }
- bool topTransparent = style->borderTopIsTransparent();
- bool bottomTransparent = style->borderBottomIsTransparent();
- bool rightTransparent = style->borderRightIsTransparent();
- bool leftTransparent = style->borderLeftIsTransparent();
+ int usedWidth() const { return isPresent ? width : 0; }
+
+ void getDoubleBorderStripeWidths(int& outerWidth, int& innerWidth) const
+ {
+ int fullWidth = usedWidth();
+ outerWidth = fullWidth / 3;
+ innerWidth = fullWidth * 2 / 3;
+
+ // We need certain integer rounding results
+ if (fullWidth % 3 == 2)
+ outerWidth += 1;
+
+ if (fullWidth % 3 == 1)
+ innerWidth += 1;
+ }
+
+ int width;
+ Color color;
+ EBorderStyle style;
+ bool isTransparent;
+ bool isPresent;
+};
- EBorderStyle topStyle = style->borderTopStyle();
- EBorderStyle bottomStyle = style->borderBottomStyle();
- EBorderStyle leftStyle = style->borderLeftStyle();
- EBorderStyle rightStyle = style->borderRightStyle();
+inline bool edgesShareColor(const BorderEdge& firstEdge, const BorderEdge& secondEdge)
+{
+ return firstEdge.color == secondEdge.color;
+}
- bool horizontal = style->isHorizontalWritingMode();
+inline bool styleRequiresClipPolygon(EBorderStyle style)
+{
+ return style == DOTTED || style == DASHED; // These are drawn with a stroke, so we have to clip to get corner miters.
+}
- bool renderTop = topStyle > BHIDDEN && !topTransparent && (horizontal || includeLogicalLeftEdge);
- bool renderLeft = leftStyle > BHIDDEN && !leftTransparent && (!horizontal || includeLogicalLeftEdge);
- bool renderRight = rightStyle > BHIDDEN && !rightTransparent && (!horizontal || includeLogicalRightEdge);
- bool renderBottom = bottomStyle > BHIDDEN && !bottomTransparent && (horizontal || includeLogicalRightEdge);
+static bool borderStyleFillsBorderArea(EBorderStyle style)
+{
+ return !(style == DOTTED || style == DASHED || style == DOUBLE);
+}
- Path roundedPath;
- RoundedIntRect border(tx, ty, w, h);
+static bool borderStyleHasInnerDetail(EBorderStyle style)
+{
+ return style == GROOVE || style == RIDGE || style == DOUBLE;
+}
- if (style->hasBorderRadius()) {
- border.includeLogicalEdges(style->getRoundedBorderFor(border.rect()).radii(),
- horizontal, includeLogicalLeftEdge, includeLogicalRightEdge);
+static bool borderStyleIsDottedOrDashed(EBorderStyle style)
+{
+ return style == DOTTED || style == DASHED;
+}
- int leftWidth = (!horizontal || includeLogicalLeftEdge) ? style->borderLeftWidth() : 0;
- int rightWidth = (!horizontal || includeLogicalRightEdge) ? style->borderRightWidth() : 0;
- int topWidth = (horizontal || includeLogicalLeftEdge) ? style->borderTopWidth() : 0;
- int bottomWidth = (horizontal || includeLogicalRightEdge) ? style->borderBottomWidth() : 0;
+// OUTSET darkens the bottom and right (and maybe lightens the top and left)
+// INSET darkens the top and left (and maybe lightens the bottom and right)
+static inline bool borderStyleHasUnmatchedColorsAtCorner(EBorderStyle style, BoxSide side, BoxSide adjacentSide)
+{
+ // These styles match at the top/left and bottom/right.
+ if (style == INSET || style == GROOVE || style == RIDGE || style == OUTSET) {
+ const BorderEdgeFlags topRightFlags = edgeFlagForSide(BSTop) | edgeFlagForSide(BSRight);
+ const BorderEdgeFlags bottomLeftFlags = edgeFlagForSide(BSBottom) | edgeFlagForSide(BSLeft);
- RoundedIntRect inner(borderInnerRect(border.rect(), topWidth, bottomWidth, leftWidth, rightWidth));
- inner.includeLogicalEdges(style->getRoundedInnerBorderWithBorderWidths(inner.rect(), topWidth, bottomWidth, leftWidth, rightWidth).radii(),
- horizontal, includeLogicalLeftEdge, includeLogicalRightEdge);
+ BorderEdgeFlags flags = edgeFlagForSide(side) | edgeFlagForSide(adjacentSide);
+ return flags == topRightFlags || flags == bottomLeftFlags;
+ }
+ return false;
+}
- if (border.isRounded()) {
- // Clip to the inner and outer radii rects.
- graphicsContext->save();
- graphicsContext->addRoundedRectClip(border);
- graphicsContext->clipOutRoundedRect(inner);
- roundedPath.addRoundedRect(border.rect(), border.radii().topLeft(), border.radii().topRight(), border.radii().bottomLeft(), border.radii().bottomRight());
- }
+static inline bool colorsMatchAtCorner(BoxSide side, BoxSide adjacentSide, const BorderEdge edges[])
+{
+ if (edges[side].shouldRender() != edges[adjacentSide].shouldRender())
+ return false;
+
+ if (!edgesShareColor(edges[side], edges[adjacentSide]))
+ return false;
+
+ return !borderStyleHasUnmatchedColorsAtCorner(edges[side].style, side, adjacentSide);
+}
+
+// This assumes that we draw in order: top, bottom, left, right.
+static inline bool willBeOverdrawn(BoxSide side, BoxSide adjacentSide, const BorderEdge edges[])
+{
+ switch (side) {
+ case BSTop:
+ case BSBottom:
+ if (edges[adjacentSide].presentButInvisible())
+ return false;
+
+ if (!edgesShareColor(edges[side], edges[adjacentSide]) && edges[adjacentSide].color.hasAlpha())
+ return false;
+
+ if (!borderStyleFillsBorderArea(edges[adjacentSide].style))
+ return false;
+
+ return true;
+
+ case BSLeft:
+ case BSRight:
+ // These draw last, so are never overdrawn.
+ return false;
}
+ return false;
+}
- bool renderRadii = border.isRounded();
- bool upperLeftBorderStylesMatch = renderLeft && (topStyle == leftStyle) && (topColor == leftColor);
- bool upperRightBorderStylesMatch = renderRight && (topStyle == rightStyle) && (topColor == rightColor) && (topStyle != OUTSET) && (topStyle != RIDGE) && (topStyle != INSET) && (topStyle != GROOVE);
- bool lowerLeftBorderStylesMatch = renderLeft && (bottomStyle == leftStyle) && (bottomColor == leftColor) && (bottomStyle != OUTSET) && (bottomStyle != RIDGE) && (bottomStyle != INSET) && (bottomStyle != GROOVE);
- bool lowerRightBorderStylesMatch = renderRight && (bottomStyle == rightStyle) && (bottomColor == rightColor);
+static inline bool borderStylesRequireMitre(BoxSide side, BoxSide adjacentSide, EBorderStyle style, EBorderStyle adjacentStyle)
+{
+ if (style == DOUBLE || adjacentStyle == DOUBLE || adjacentStyle == GROOVE || adjacentStyle == RIDGE)
+ return true;
- if (renderTop) {
- int x = tx;
- int x2 = tx + w;
+ if (borderStyleIsDottedOrDashed(style) != borderStyleIsDottedOrDashed(adjacentStyle))
+ return true;
+
+ if (style != adjacentStyle)
+ return true;
- if (renderRadii && borderWillArcInnerEdge(border.radii().topLeft(), border.radii().topRight(), style->borderLeftWidth(), style->borderRightWidth(), style->borderTopWidth())) {
+ return borderStyleHasUnmatchedColorsAtCorner(style, side, adjacentSide);
+}
+
+static bool joinRequiresMitre(BoxSide side, BoxSide adjacentSide, const BorderEdge edges[], bool allowOverdraw)
+{
+ if ((edges[side].isTransparent && edges[adjacentSide].isTransparent) || !edges[adjacentSide].isPresent)
+ return false;
+
+ if (allowOverdraw && willBeOverdrawn(side, adjacentSide, edges))
+ return false;
+
+ if (!edgesShareColor(edges[side], edges[adjacentSide]))
+ return true;
+
+ if (borderStylesRequireMitre(side, adjacentSide, edges[side].style, edges[adjacentSide].style))
+ return true;
+
+ return false;
+}
+
+void RenderBoxModelObject::paintOneBorderSide(GraphicsContext* graphicsContext, const RenderStyle* style, const RoundedIntRect& outerBorder, const RoundedIntRect& innerBorder,
+ const IntRect& sideRect, BoxSide side, BoxSide adjacentSide1, BoxSide adjacentSide2, const BorderEdge edges[], const Path* path,
+ bool includeLogicalLeftEdge, bool includeLogicalRightEdge, bool antialias, const Color* overrideColor)
+{
+ const BorderEdge& edgeToRender = edges[side];
+ const BorderEdge& adjacentEdge1 = edges[adjacentSide1];
+ const BorderEdge& adjacentEdge2 = edges[adjacentSide2];
+
+ bool mitreAdjacentSide1 = joinRequiresMitre(side, adjacentSide1, edges, !antialias);
+ bool mitreAdjacentSide2 = joinRequiresMitre(side, adjacentSide2, edges, !antialias);
+
+ bool adjacentSide1StylesMatch = colorsMatchAtCorner(side, adjacentSide1, edges);
+ bool adjacentSide2StylesMatch = colorsMatchAtCorner(side, adjacentSide2, edges);
+
+ const Color& colorToPaint = overrideColor ? *overrideColor : edgeToRender.color;
+
+ if (path) {
+ graphicsContext->save();
+ clipBorderSidePolygon(graphicsContext, outerBorder, innerBorder, side, adjacentSide1StylesMatch, adjacentSide2StylesMatch);
+ float thickness = max(max(edgeToRender.width, adjacentEdge1.width), adjacentEdge2.width);
+ drawBoxSideFromPath(graphicsContext, outerBorder.rect(), *path, edges, edgeToRender.width, thickness, side, style, colorToPaint, edgeToRender.style, includeLogicalLeftEdge, includeLogicalRightEdge);
+ graphicsContext->restore();
+ } else {
+ bool didClip = false;
+
+ if (styleRequiresClipPolygon(edgeToRender.style) && (mitreAdjacentSide1 || mitreAdjacentSide2)) {
graphicsContext->save();
- clipBorderSidePolygon(graphicsContext, border, BSTop, upperLeftBorderStylesMatch, upperRightBorderStylesMatch, style, includeLogicalLeftEdge, includeLogicalRightEdge);
- float thickness = max(max(style->borderTopWidth(), style->borderLeftWidth()), style->borderRightWidth());
- drawBoxSideFromPath(graphicsContext, border.rect(), roundedPath, style->borderTopWidth(), thickness, BSTop, style, topColor, topStyle);
+ clipBorderSidePolygon(graphicsContext, outerBorder, innerBorder, side, !mitreAdjacentSide1, !mitreAdjacentSide2);
+ didClip = true;
+ // Since we clipped, no need to draw with a mitre.
+ mitreAdjacentSide1 = false;
+ mitreAdjacentSide2 = false;
+ }
+
+ drawLineForBoxSide(graphicsContext, sideRect.x(), sideRect.y(), sideRect.maxX(), sideRect.maxY(), side, colorToPaint, edgeToRender.style,
+ mitreAdjacentSide1 ? adjacentEdge1.width : 0, mitreAdjacentSide2 ? adjacentEdge2.width : 0, antialias);
+
+ if (didClip)
graphicsContext->restore();
- } else {
- bool ignoreLeft = (topColor == leftColor && topTransparent == leftTransparent && topStyle >= OUTSET
- && (leftStyle == DOTTED || leftStyle == DASHED || leftStyle == SOLID || leftStyle == OUTSET));
- bool ignoreRight = (topColor == rightColor && topTransparent == rightTransparent && topStyle >= OUTSET
- && (rightStyle == DOTTED || rightStyle == DASHED || rightStyle == SOLID || rightStyle == INSET));
+ }
+}
- drawLineForBoxSide(graphicsContext, x, ty, x2, ty + style->borderTopWidth(), BSTop, topColor, topStyle,
- ignoreLeft ? 0 : style->borderLeftWidth(), ignoreRight ? 0 : style->borderRightWidth());
- }
+void RenderBoxModelObject::paintBorderSides(GraphicsContext* graphicsContext, const RenderStyle* style, const RoundedIntRect& outerBorder, const RoundedIntRect& innerBorder,
+ const BorderEdge edges[], BorderEdgeFlags edgeSet, bool includeLogicalLeftEdge, bool includeLogicalRightEdge, bool antialias, const Color* overrideColor)
+{
+ bool renderRadii = outerBorder.isRounded();
+
+ Path roundedPath;
+ if (renderRadii)
+ roundedPath.addRoundedRect(outerBorder);
+
+ if (edges[BSTop].shouldRender() && includesEdge(edgeSet, BSTop)) {
+ IntRect sideRect = outerBorder.rect();
+ sideRect.setHeight(edges[BSTop].width);
+
+ bool usePath = renderRadii && (borderStyleHasInnerDetail(edges[BSTop].style) || borderWillArcInnerEdge(innerBorder.radii().topLeft(), innerBorder.radii().topRight()));
+ paintOneBorderSide(graphicsContext, style, outerBorder, innerBorder, sideRect, BSTop, BSLeft, BSRight, edges, usePath ? &roundedPath : 0, includeLogicalLeftEdge, includeLogicalRightEdge, antialias, overrideColor);
}
- if (renderBottom) {
- int x = tx;
- int x2 = tx + w;
+ if (edges[BSBottom].shouldRender() && includesEdge(edgeSet, BSBottom)) {
+ IntRect sideRect = outerBorder.rect();
+ sideRect.shiftYEdgeTo(sideRect.maxY() - edges[BSBottom].width);
- if (renderRadii && borderWillArcInnerEdge(border.radii().bottomLeft(), border.radii().bottomRight(), style->borderLeftWidth(), style->borderRightWidth(), style->borderBottomWidth())) {
- graphicsContext->save();
- clipBorderSidePolygon(graphicsContext, border, BSBottom, lowerLeftBorderStylesMatch, lowerRightBorderStylesMatch, style, includeLogicalLeftEdge, includeLogicalRightEdge);
- float thickness = max(max(style->borderBottomWidth(), style->borderLeftWidth()), style->borderRightWidth());
- drawBoxSideFromPath(graphicsContext, border.rect(), roundedPath, style->borderBottomWidth(), thickness, BSBottom, style, bottomColor, bottomStyle);
- graphicsContext->restore();
- } else {
- bool ignoreLeft = (bottomColor == leftColor && bottomTransparent == leftTransparent && bottomStyle >= OUTSET
- && (leftStyle == DOTTED || leftStyle == DASHED || leftStyle == SOLID || leftStyle == OUTSET));
+ bool usePath = renderRadii && (borderStyleHasInnerDetail(edges[BSBottom].style) || borderWillArcInnerEdge(innerBorder.radii().bottomLeft(), innerBorder.radii().bottomRight()));
+ paintOneBorderSide(graphicsContext, style, outerBorder, innerBorder, sideRect, BSBottom, BSLeft, BSRight, edges, usePath ? &roundedPath : 0, includeLogicalLeftEdge, includeLogicalRightEdge, antialias, overrideColor);
+ }
- bool ignoreRight = (bottomColor == rightColor && bottomTransparent == rightTransparent && bottomStyle >= OUTSET
- && (rightStyle == DOTTED || rightStyle == DASHED || rightStyle == SOLID || rightStyle == INSET));
+ if (edges[BSLeft].shouldRender() && includesEdge(edgeSet, BSLeft)) {
+ IntRect sideRect = outerBorder.rect();
+ sideRect.setWidth(edges[BSLeft].width);
+
+ bool usePath = renderRadii && (borderStyleHasInnerDetail(edges[BSLeft].style) || borderWillArcInnerEdge(innerBorder.radii().bottomLeft(), innerBorder.radii().topLeft()));
+ paintOneBorderSide(graphicsContext, style, outerBorder, innerBorder, sideRect, BSLeft, BSTop, BSBottom, edges, usePath ? &roundedPath : 0, includeLogicalLeftEdge, includeLogicalRightEdge, antialias, overrideColor);
+ }
+
+ if (edges[BSRight].shouldRender() && includesEdge(edgeSet, BSRight)) {
+ IntRect sideRect = outerBorder.rect();
+ sideRect.shiftXEdgeTo(sideRect.maxX() - edges[BSRight].width);
+
+ bool usePath = renderRadii && (borderStyleHasInnerDetail(edges[BSRight].style) || borderWillArcInnerEdge(innerBorder.radii().bottomRight(), innerBorder.radii().topRight()));
+ paintOneBorderSide(graphicsContext, style, outerBorder, innerBorder, sideRect, BSRight, BSTop, BSBottom, edges, usePath ? &roundedPath : 0, includeLogicalLeftEdge, includeLogicalRightEdge, antialias, overrideColor);
+ }
+}
- drawLineForBoxSide(graphicsContext, x, ty + h - style->borderBottomWidth(), x2, ty + h, BSBottom, bottomColor,
- bottomStyle, ignoreLeft ? 0 : style->borderLeftWidth(),
- ignoreRight ? 0 : style->borderRightWidth());
+void RenderBoxModelObject::paintTranslucentBorderSides(GraphicsContext* graphicsContext, const RenderStyle* style, const RoundedIntRect& outerBorder, const RoundedIntRect& innerBorder,
+ const BorderEdge edges[], bool includeLogicalLeftEdge, bool includeLogicalRightEdge, bool antialias)
+{
+ BorderEdgeFlags edgesToDraw = AllBorderEdges;
+ while (edgesToDraw) {
+ // Find undrawn edges sharing a color.
+ Color commonColor;
+
+ BorderEdgeFlags commonColorEdgeSet = 0;
+ for (int i = BSTop; i <= BSLeft; ++i) {
+ BoxSide currSide = static_cast<BoxSide>(i);
+ if (!includesEdge(edgesToDraw, currSide))
+ continue;
+
+ bool includeEdge;
+ if (!commonColorEdgeSet) {
+ commonColor = edges[currSide].color;
+ includeEdge = true;
+ } else
+ includeEdge = edges[currSide].color == commonColor;
+
+ if (includeEdge)
+ commonColorEdgeSet |= edgeFlagForSide(currSide);
}
+
+ bool useTransparencyLayer = commonColor.hasAlpha();
+ if (useTransparencyLayer) {
+ graphicsContext->beginTransparencyLayer(static_cast<float>(commonColor.alpha()) / 255);
+ commonColor = Color(commonColor.red(), commonColor.green(), commonColor.blue());
+ }
+
+ paintBorderSides(graphicsContext, style, outerBorder, innerBorder, edges, commonColorEdgeSet, includeLogicalLeftEdge, includeLogicalRightEdge, antialias, &commonColor);
+
+ if (useTransparencyLayer)
+ graphicsContext->endTransparencyLayer();
+
+ edgesToDraw &= ~commonColorEdgeSet;
}
+}
- if (renderLeft) {
- int y = ty;
- int y2 = ty + h;
+void RenderBoxModelObject::paintBorder(GraphicsContext* graphicsContext, int tx, int ty, int w, int h,
+ const RenderStyle* style, bool includeLogicalLeftEdge, bool includeLogicalRightEdge)
+{
+ if (paintNinePieceImage(graphicsContext, tx, ty, w, h, style, style->borderImage()))
+ return;
- if (renderRadii && borderWillArcInnerEdge(border.radii().bottomLeft(), border.radii().topLeft(), style->borderBottomWidth(), style->borderTopWidth(), style->borderLeftWidth())) {
- graphicsContext->save();
- clipBorderSidePolygon(graphicsContext, border, BSLeft, upperLeftBorderStylesMatch, lowerLeftBorderStylesMatch, style, includeLogicalLeftEdge, includeLogicalRightEdge);
- float thickness = max(max(style->borderLeftWidth(), style->borderTopWidth()), style->borderBottomWidth());
- drawBoxSideFromPath(graphicsContext, border.rect(), roundedPath, style->borderLeftWidth(), thickness, BSLeft, style, leftColor, leftStyle);
- graphicsContext->restore();
- } else {
- bool ignoreTop = (topColor == leftColor && topTransparent == leftTransparent && leftStyle >= OUTSET
- && (topStyle == DOTTED || topStyle == DASHED || topStyle == SOLID || topStyle == OUTSET));
+ if (graphicsContext->paintingDisabled())
+ return;
- bool ignoreBottom = (bottomColor == leftColor && bottomTransparent == leftTransparent && leftStyle >= OUTSET
- && (bottomStyle == DOTTED || bottomStyle == DASHED || bottomStyle == SOLID || bottomStyle == INSET));
+ bool horizontal = style->isHorizontalWritingMode();
- drawLineForBoxSide(graphicsContext, tx, y, tx + style->borderLeftWidth(), y2, BSLeft, leftColor,
- leftStyle, ignoreTop ? 0 : style->borderTopWidth(), ignoreBottom ? 0 : style->borderBottomWidth());
+ BorderEdge edges[4] = {
+ // BSTop
+ BorderEdge(style->borderTopWidth(),
+ style->visitedDependentColor(CSSPropertyBorderTopColor),
+ style->borderTopStyle(),
+ style->borderTopIsTransparent(),
+ horizontal || includeLogicalLeftEdge),
+ // BSRight
+ BorderEdge(style->borderRightWidth(),
+ style->visitedDependentColor(CSSPropertyBorderRightColor),
+ style->borderRightStyle(),
+ style->borderRightIsTransparent(),
+ !horizontal || includeLogicalRightEdge),
+ // BSBottom
+ BorderEdge(style->borderBottomWidth(),
+ style->visitedDependentColor(CSSPropertyBorderBottomColor),
+ style->borderBottomStyle(),
+ style->borderBottomIsTransparent(),
+ horizontal || includeLogicalRightEdge),
+ // BSLeft
+ BorderEdge(style->borderLeftWidth(),
+ style->visitedDependentColor(CSSPropertyBorderLeftColor),
+ style->borderLeftStyle(),
+ style->borderLeftIsTransparent(),
+ !horizontal || includeLogicalLeftEdge)
+ };
+
+ IntRect borderRect(tx, ty, w, h);
+ RoundedIntRect outerBorder = style->getRoundedBorderFor(borderRect, includeLogicalLeftEdge, includeLogicalRightEdge);
+ RoundedIntRect innerBorder = style->getRoundedInnerBorderFor(borderRect, includeLogicalLeftEdge, includeLogicalRightEdge);
+
+ const AffineTransform& currentCTM = graphicsContext->getCTM();
+ // FIXME: this isn't quite correct. We may want to antialias when scaled by a non-integral value, or when the translation is non-integral.
+ bool antialias = !currentCTM.isIdentityOrTranslationOrFlipped();
+
+ bool haveAlphaColor = false;
+ bool haveAllSolidEdges = true;
+ bool allEdgesVisible = true;
+ bool allEdgesShareColor = true;
+ int firstVisibleEdge = -1;
+
+ for (int i = BSTop; i <= BSLeft; ++i) {
+ const BorderEdge& currEdge = edges[i];
+ if (currEdge.presentButInvisible()) {
+ allEdgesVisible = false;
+ continue;
}
+
+ if (!currEdge.width)
+ continue;
+
+ if (firstVisibleEdge == -1)
+ firstVisibleEdge = i;
+ else if (currEdge.color != edges[firstVisibleEdge].color)
+ allEdgesShareColor = false;
+
+ if (currEdge.color.hasAlpha())
+ haveAlphaColor = true;
+
+ if (currEdge.style != SOLID)
+ haveAllSolidEdges = false;
}
+
+ // isRenderable() check avoids issue described in https://bugs.webkit.org/show_bug.cgi?id=38787
+ if (haveAllSolidEdges && allEdgesVisible && allEdgesShareColor && innerBorder.isRenderable()) {
+ // Fast path for drawing all solid edges.
+ if (outerBorder.isRounded() || haveAlphaColor) {
+ Path path;
+
+ // FIXME: Path should take a RoundedIntRect directly.
+ if (outerBorder.isRounded())
+ path.addRoundedRect(outerBorder);
+ else
+ path.addRect(outerBorder.rect());
- if (renderRight) {
- if (renderRadii && borderWillArcInnerEdge(border.radii().bottomRight(), border.radii().topRight(), style->borderBottomWidth(), style->borderTopWidth(), style->borderRightWidth())) {
- graphicsContext->save();
- clipBorderSidePolygon(graphicsContext, border, BSRight, upperRightBorderStylesMatch, lowerRightBorderStylesMatch, style, includeLogicalLeftEdge, includeLogicalRightEdge);
- float thickness = max(max(style->borderRightWidth(), style->borderTopWidth()), style->borderBottomWidth());
- drawBoxSideFromPath(graphicsContext, border.rect(), roundedPath, style->borderRightWidth(), thickness, BSRight, style, rightColor, rightStyle);
- graphicsContext->restore();
- } else {
- bool ignoreTop = ((topColor == rightColor) && (topTransparent == rightTransparent)
- && (rightStyle >= DOTTED || rightStyle == INSET)
- && (topStyle == DOTTED || topStyle == DASHED || topStyle == SOLID || topStyle == OUTSET));
+ if (innerBorder.isRounded())
+ path.addRoundedRect(innerBorder);
+ else
+ path.addRect(innerBorder.rect());
+
+ graphicsContext->setFillRule(RULE_EVENODD);
+ graphicsContext->setFillColor(edges[firstVisibleEdge].color, style->colorSpace());
+ graphicsContext->fillPath(path);
+ } else
+ paintBorderSides(graphicsContext, style, outerBorder, innerBorder, edges, AllBorderEdges, includeLogicalLeftEdge, includeLogicalRightEdge, antialias);
+
+ return;
+ }
- bool ignoreBottom = ((bottomColor == rightColor) && (bottomTransparent == rightTransparent)
- && (rightStyle >= DOTTED || rightStyle == INSET)
- && (bottomStyle == DOTTED || bottomStyle == DASHED || bottomStyle == SOLID || bottomStyle == INSET));
+ if (outerBorder.isRounded()) {
+ // Clip to the inner and outer radii rects.
+ graphicsContext->save();
+ graphicsContext->addRoundedRectClip(outerBorder);
+ graphicsContext->clipOutRoundedRect(innerBorder);
+ }
+
+ if (haveAlphaColor)
+ paintTranslucentBorderSides(graphicsContext, style, outerBorder, innerBorder, edges, includeLogicalLeftEdge, includeLogicalRightEdge, antialias);
+ else
+ paintBorderSides(graphicsContext, style, outerBorder, innerBorder, edges, AllBorderEdges, includeLogicalLeftEdge, includeLogicalRightEdge, antialias);
+
+ if (outerBorder.isRounded())
+ graphicsContext->restore();
+}
+
+void RenderBoxModelObject::drawBoxSideFromPath(GraphicsContext* graphicsContext, const IntRect& borderRect, const Path& borderPath, const BorderEdge edges[],
+ float thickness, float drawThickness, BoxSide side, const RenderStyle* style,
+ Color color, EBorderStyle borderStyle, bool includeLogicalLeftEdge, bool includeLogicalRightEdge)
+{
+ if (thickness <= 0)
+ return;
- int y = ty;
- int y2 = ty + h;
+ if (borderStyle == DOUBLE && thickness < 3)
+ borderStyle = SOLID;
- drawLineForBoxSide(graphicsContext, tx + w - style->borderRightWidth(), y, tx + w, y2, BSRight, rightColor,
- rightStyle, ignoreTop ? 0 : style->borderTopWidth(),
- ignoreBottom ? 0 : style->borderBottomWidth());
+ switch (borderStyle) {
+ case BNONE:
+ case BHIDDEN:
+ return;
+ case DOTTED:
+ case DASHED: {
+ graphicsContext->setStrokeColor(color, style->colorSpace());
+
+ // The stroke is doubled here because the provided path is the
+ // outside edge of the border so half the stroke is clipped off.
+ // The extra multiplier is so that the clipping mask can antialias
+ // the edges to prevent jaggies.
+ graphicsContext->setStrokeThickness(drawThickness * 2 * 1.1f);
+ graphicsContext->setStrokeStyle(borderStyle == DASHED ? DashedStroke : DottedStroke);
+
+ // If the number of dashes that fit in the path is odd and non-integral then we
+ // will have an awkwardly-sized dash at the end of the path. To try to avoid that
+ // here, we simply make the whitespace dashes ever so slightly bigger.
+ // FIXME: This could be even better if we tried to manipulate the dash offset
+ // and possibly the gapLength to get the corners dash-symmetrical.
+ float dashLength = thickness * ((borderStyle == DASHED) ? 3.0f : 1.0f);
+ float gapLength = dashLength;
+ float numberOfDashes = borderPath.length() / dashLength;
+ // Don't try to show dashes if we have less than 2 dashes + 2 gaps.
+ // FIXME: should do this test per side.
+ if (numberOfDashes >= 4) {
+ bool evenNumberOfFullDashes = !((int)numberOfDashes % 2);
+ bool integralNumberOfDashes = !(numberOfDashes - (int)numberOfDashes);
+ if (!evenNumberOfFullDashes && !integralNumberOfDashes) {
+ float numberOfGaps = numberOfDashes / 2;
+ gapLength += (dashLength / numberOfGaps);
+ }
+
+ DashArray lineDash;
+ lineDash.append(dashLength);
+ lineDash.append(gapLength);
+ graphicsContext->setLineDash(lineDash, dashLength);
}
+
+ // FIXME: stroking the border path causes issues with tight corners:
+ // https://bugs.webkit.org/show_bug.cgi?id=58711
+ // Also, to get the best appearance we should stroke a path between the two borders.
+ graphicsContext->strokePath(borderPath);
+ return;
}
+ case DOUBLE: {
+ // Get the inner border rects for both the outer border line and the inner border line
+ int outerBorderTopWidth;
+ int innerBorderTopWidth;
+ edges[BSTop].getDoubleBorderStripeWidths(outerBorderTopWidth, innerBorderTopWidth);
+
+ int outerBorderRightWidth;
+ int innerBorderRightWidth;
+ edges[BSRight].getDoubleBorderStripeWidths(outerBorderRightWidth, innerBorderRightWidth);
+
+ int outerBorderBottomWidth;
+ int innerBorderBottomWidth;
+ edges[BSBottom].getDoubleBorderStripeWidths(outerBorderBottomWidth, innerBorderBottomWidth);
+
+ int outerBorderLeftWidth;
+ int innerBorderLeftWidth;
+ edges[BSLeft].getDoubleBorderStripeWidths(outerBorderLeftWidth, innerBorderLeftWidth);
+
+ // Draw inner border line
+ graphicsContext->save();
+
+ RoundedIntRect innerClip = style->getRoundedInnerBorderFor(borderRect,
+ innerBorderTopWidth, innerBorderBottomWidth, innerBorderLeftWidth, innerBorderRightWidth,
+ includeLogicalLeftEdge, includeLogicalRightEdge);
+
+ graphicsContext->addRoundedRectClip(innerClip);
+ drawBoxSideFromPath(graphicsContext, borderRect, borderPath, edges, thickness, drawThickness, side, style, color, SOLID, includeLogicalLeftEdge, includeLogicalRightEdge);
+ graphicsContext->restore();
- if (renderRadii)
+ // Draw outer border line
+ graphicsContext->save();
+
+ RoundedIntRect outerClip = style->getRoundedInnerBorderFor(borderRect,
+ outerBorderTopWidth, outerBorderBottomWidth, outerBorderLeftWidth, outerBorderRightWidth,
+ includeLogicalLeftEdge, includeLogicalRightEdge);
+
+ graphicsContext->clipOutRoundedRect(outerClip);
+ drawBoxSideFromPath(graphicsContext, borderRect, borderPath, edges, thickness, drawThickness, side, style, color, SOLID, includeLogicalLeftEdge, includeLogicalRightEdge);
+ graphicsContext->restore();
+ return;
+ }
+ case RIDGE:
+ case GROOVE:
+ {
+ EBorderStyle s1;
+ EBorderStyle s2;
+ if (borderStyle == GROOVE) {
+ s1 = INSET;
+ s2 = OUTSET;
+ } else {
+ s1 = OUTSET;
+ s2 = INSET;
+ }
+
+ // Paint full border
+ drawBoxSideFromPath(graphicsContext, borderRect, borderPath, edges, thickness, drawThickness, side, style, color, s1, includeLogicalLeftEdge, includeLogicalRightEdge);
+
+ // Paint inner only
+ graphicsContext->save();
+
+ int topWidth = edges[BSTop].usedWidth() / 2;
+ int bottomWidth = edges[BSBottom].usedWidth() / 2;
+ int leftWidth = edges[BSLeft].usedWidth() / 2;
+ int rightWidth = edges[BSRight].usedWidth() / 2;
+
+ RoundedIntRect clipRect = style->getRoundedInnerBorderFor(borderRect,
+ topWidth, bottomWidth, leftWidth, rightWidth,
+ includeLogicalLeftEdge, includeLogicalRightEdge);
+
+ graphicsContext->addRoundedRectClip(clipRect);
+ drawBoxSideFromPath(graphicsContext, borderRect, borderPath, edges, thickness, drawThickness, side, style, color, s2, includeLogicalLeftEdge, includeLogicalRightEdge);
graphicsContext->restore();
+ return;
+ }
+ case INSET:
+ if (side == BSTop || side == BSLeft)
+ color = color.dark();
+ break;
+ case OUTSET:
+ if (side == BSBottom || side == BSRight)
+ color = color.dark();
+ break;
+ default:
+ break;
+ }
+
+ graphicsContext->setStrokeStyle(NoStroke);
+ graphicsContext->setFillColor(color, style->colorSpace());
+ graphicsContext->drawRect(borderRect);
}
#else
void RenderBoxModelObject::paintBorder(GraphicsContext* graphicsContext, int tx, int ty, int w, int h,
@@ -1507,50 +1931,92 @@ void RenderBoxModelObject::paintBorder(GraphicsContext* graphicsContext, int tx,
}
#endif
-void RenderBoxModelObject::clipBorderSidePolygon(GraphicsContext* graphicsContext, const RoundedIntRect& border,
- const BoxSide side, bool firstEdgeMatches, bool secondEdgeMatches, const RenderStyle* style,
- bool includeLogicalLeftEdge, bool includeLogicalRightEdge)
+static void findInnerVertex(const FloatPoint& outerCorner, const FloatPoint& innerCorner, const FloatPoint& centerPoint, FloatPoint& result)
{
- FloatPoint quad[4];
- int tx = border.rect().x();
- int ty = border.rect().y();
- int w = border.rect().width();
- int h = border.rect().height();
+ // If the line between outer and inner corner is towards the horizontal, intersect with a vertical line through the center,
+ // otherwise with a horizontal line through the center. The points that form this line are arbitrary (we use 0, 100).
+ // Note that if findIntersection fails, it will leave result untouched.
+ if (fabs(outerCorner.x() - innerCorner.x()) > fabs(outerCorner.y() - innerCorner.y()))
+ findIntersection(outerCorner, innerCorner, FloatPoint(centerPoint.x(), 0), FloatPoint(centerPoint.x(), 100), result);
+ else
+ findIntersection(outerCorner, innerCorner, FloatPoint(0, centerPoint.y()), FloatPoint(100, centerPoint.y()), result);
+}
- bool horizontal = style->isHorizontalWritingMode();
- int leftWidth = (!horizontal || includeLogicalLeftEdge) ? style->borderLeftWidth() : 0;
- int rightWidth = (!horizontal || includeLogicalRightEdge) ? style->borderRightWidth() : 0;
- int topWidth = (horizontal || includeLogicalLeftEdge) ? style->borderTopWidth() : 0;
- int bottomWidth = (horizontal || includeLogicalRightEdge) ? style->borderBottomWidth() : 0;
+void RenderBoxModelObject::clipBorderSidePolygon(GraphicsContext* graphicsContext, const RoundedIntRect& outerBorder, const RoundedIntRect& innerBorder,
+ BoxSide side, bool firstEdgeMatches, bool secondEdgeMatches)
+{
+ FloatPoint quad[4];
- // For each side, create an array of FloatPoints where each point is based on whichever value in each corner
- // is larger -- the radius width/height or the border width/height -- as appropriate.
+ const IntRect& outerRect = outerBorder.rect();
+ const IntRect& innerRect = innerBorder.rect();
+
+ FloatPoint centerPoint(innerRect.location().x() + static_cast<float>(innerRect.width()) / 2, innerRect.location().y() + static_cast<float>(innerRect.height()) / 2);
+
+ // For each side, create a quad that encompasses all parts of that side that may draw,
+ // including areas inside the innerBorder.
+ //
+ // 0----------------3
+ // 0 \ / 0
+ // |\ 1----------- 2 /|
+ // | 1 1 |
+ // | | | |
+ // | | | |
+ // | 2 2 |
+ // |/ 1------------2 \|
+ // 3 / \ 3
+ // 0----------------3
+ //
switch (side) {
case BSTop:
- quad[0] = FloatPoint(tx, ty);
- quad[1] = FloatPoint(tx + max(border.radii().topLeft().width(), leftWidth), ty + max(border.radii().topLeft().height(), topWidth));
- quad[2] = FloatPoint(tx + w - max(border.radii().topRight().width(), rightWidth), ty + max(border.radii().topRight().height(), topWidth));
- quad[3] = FloatPoint(tx + w, ty);
+ quad[0] = outerRect.minXMinYCorner();
+ quad[1] = innerRect.minXMinYCorner();
+ quad[2] = innerRect.maxXMinYCorner();
+ quad[3] = outerRect.maxXMinYCorner();
+
+ if (!innerBorder.radii().topLeft().isZero())
+ findInnerVertex(outerRect.minXMinYCorner(), innerRect.minXMinYCorner(), centerPoint, quad[1]);
+
+ if (!innerBorder.radii().topRight().isZero())
+ findInnerVertex(outerRect.maxXMinYCorner(), innerRect.maxXMinYCorner(), centerPoint, quad[2]);
break;
+
case BSLeft:
- quad[0] = FloatPoint(tx, ty);
- quad[1] = FloatPoint(tx + max(border.radii().topLeft().width(), leftWidth), ty + max(border.radii().topLeft().height(), topWidth));
- quad[2] = FloatPoint(tx + max(border.radii().bottomLeft().width(), leftWidth), ty + h - max(border.radii().bottomLeft().height(), bottomWidth));
- quad[3] = FloatPoint(tx, ty + h);
+ quad[0] = outerRect.minXMinYCorner();
+ quad[1] = innerRect.minXMinYCorner();
+ quad[2] = innerRect.minXMaxYCorner();
+ quad[3] = outerRect.minXMaxYCorner();
+
+ if (!innerBorder.radii().topLeft().isZero())
+ findInnerVertex(outerRect.minXMinYCorner(), innerRect.minXMinYCorner(), centerPoint, quad[1]);
+
+ if (!innerBorder.radii().bottomLeft().isZero())
+ findInnerVertex(outerRect.minXMaxYCorner(), innerRect.minXMaxYCorner(), centerPoint, quad[2]);
break;
+
case BSBottom:
- quad[0] = FloatPoint(tx, ty + h);
- quad[1] = FloatPoint(tx + max(border.radii().bottomLeft().width(), leftWidth), ty + h - max(border.radii().bottomLeft().height(), bottomWidth));
- quad[2] = FloatPoint(tx + w - max(border.radii().bottomRight().width(), rightWidth), ty + h - max(border.radii().bottomRight().height(), bottomWidth));
- quad[3] = FloatPoint(tx + w, ty + h);
+ quad[0] = outerRect.minXMaxYCorner();
+ quad[1] = innerRect.minXMaxYCorner();
+ quad[2] = innerRect.maxXMaxYCorner();
+ quad[3] = outerRect.maxXMaxYCorner();
+
+ if (!innerBorder.radii().bottomLeft().isZero())
+ findInnerVertex(outerRect.minXMaxYCorner(), innerRect.minXMaxYCorner(), centerPoint, quad[1]);
+
+ if (!innerBorder.radii().bottomRight().isZero())
+ findInnerVertex(outerRect.maxXMaxYCorner(), innerRect.maxXMaxYCorner(), centerPoint, quad[2]);
break;
+
case BSRight:
- quad[0] = FloatPoint(tx + w, ty);
- quad[1] = FloatPoint(tx + w - max(border.radii().topRight().width(), rightWidth), ty + max(border.radii().topRight().height(), topWidth));
- quad[2] = FloatPoint(tx + w - max(border.radii().bottomRight().width(), rightWidth), ty + h - max(border.radii().bottomRight().height(), bottomWidth));
- quad[3] = FloatPoint(tx + w, ty + h);
- break;
- default:
+ quad[0] = outerRect.maxXMinYCorner();
+ quad[1] = innerRect.maxXMinYCorner();
+ quad[2] = innerRect.maxXMaxYCorner();
+ quad[3] = outerRect.maxXMaxYCorner();
+
+ if (!innerBorder.radii().topRight().isZero())
+ findInnerVertex(outerRect.maxXMinYCorner(), innerRect.maxXMinYCorner(), centerPoint, quad[1]);
+
+ if (!innerBorder.radii().bottomRight().isZero())
+ findInnerVertex(outerRect.maxXMaxYCorner(), innerRect.maxXMaxYCorner(), centerPoint, quad[2]);
break;
}
@@ -1561,6 +2027,7 @@ void RenderBoxModelObject::clipBorderSidePolygon(GraphicsContext* graphicsContex
return;
}
+ // Square off the end which shouldn't be affected by antialiasing, and clip.
FloatPoint firstQuad[4];
firstQuad[0] = quad[0];
firstQuad[1] = quad[1];
@@ -1575,6 +2042,7 @@ void RenderBoxModelObject::clipBorderSidePolygon(GraphicsContext* graphicsContex
: FloatPoint(quad[1].x(), quad[0].y());
secondQuad[2] = quad[2];
secondQuad[3] = quad[3];
+ // Antialiasing affects the second side.
graphicsContext->clipConvexPolygon(4, secondQuad, !secondEdgeMatches);
}
@@ -1599,21 +2067,13 @@ void RenderBoxModelObject::paintBoxShadow(GraphicsContext* context, int tx, int
if (context->paintingDisabled() || !s->boxShadow())
return;
- RoundedIntRect border(tx, ty, w, h);
+ IntRect borderRect(tx, ty, w, h);
+ RoundedIntRect border = (shadowStyle == Inset) ? s->getRoundedInnerBorderFor(borderRect, includeLogicalLeftEdge, includeLogicalRightEdge)
+ : s->getRoundedBorderFor(borderRect, includeLogicalLeftEdge, includeLogicalRightEdge);
+
bool hasBorderRadius = s->hasBorderRadius();
bool isHorizontal = s->isHorizontalWritingMode();
-
- if (shadowStyle == Inset)
- border.setRect(IntRect(border.rect().x() + (includeLogicalLeftEdge || !isHorizontal ? borderLeft() : 0),
- border.rect().y() + (includeLogicalLeftEdge || isHorizontal ? borderTop() : 0),
- border.rect().width() - ((includeLogicalLeftEdge || !isHorizontal) ? borderLeft() : 0) - ((includeLogicalRightEdge || !isHorizontal) ? borderRight() : 0),
- border.rect().height() - ((includeLogicalLeftEdge || isHorizontal) ? borderTop() : 0) - ((includeLogicalRightEdge || isHorizontal) ? borderBottom() : 0)));
-
- if (hasBorderRadius && (includeLogicalLeftEdge || includeLogicalRightEdge)) {
- RoundedIntRect::Radii radii = ((shadowStyle == Inset) ? s->getRoundedInnerBorderWithBorderWidths(border.rect(), borderTop(), borderBottom(), borderLeft(), borderRight()) : s->getRoundedBorderFor(border.rect())).radii();
- border.includeLogicalEdges(radii, isHorizontal, includeLogicalLeftEdge, includeLogicalRightEdge);
- }
-
+
bool hasOpaqueBackground = s->visitedDependentColor(CSSPropertyBackgroundColor).isValid() && s->visitedDependentColor(CSSPropertyBackgroundColor).alpha() == 255;
for (const ShadowData* shadow = s->boxShadow(); shadow; shadow = shadow->next()) {
if (shadow->style() != shadowStyle)
@@ -1661,9 +2121,7 @@ void RenderBoxModelObject::paintBoxShadow(GraphicsContext* context, int tx, int
if (!rectToClipOut.isEmpty())
context->clipOutRoundedRect(rectToClipOut);
- if (shadowSpread < 0)
- fillRect.expandRadii(shadowSpread);
-
+ fillRect.expandRadii(shadowSpread);
context->fillRoundedRect(fillRect, Color::black, s->colorSpace());
} else {
IntRect rectToClipOut = border.rect();
@@ -1717,13 +2175,15 @@ void RenderBoxModelObject::paintBoxShadow(GraphicsContext* context, int tx, int
Color fillColor(shadowColor.red(), shadowColor.green(), shadowColor.blue(), 255);
IntRect outerRect = areaCastingShadowInHole(border.rect(), shadowBlur, shadowSpread, shadowOffset);
+ RoundedIntRect roundedHole(holeRect, border.radii());
+
context->save();
- Path path;
if (hasBorderRadius) {
Path path;
- path.addRoundedRect(border.rect(), border.radii().topLeft(), border.radii().topRight(), border.radii().bottomLeft(), border.radii().bottomRight());
+ path.addRoundedRect(border);
context->clip(path);
+ roundedHole.shrinkRadii(shadowSpread);
} else
context->clip(border.rect());
@@ -1731,15 +2191,11 @@ void RenderBoxModelObject::paintBoxShadow(GraphicsContext* context, int tx, int
context->translate(extraOffset.width(), extraOffset.height());
shadowOffset -= extraOffset;
- if (hasBorderRadius && shadowSpread > 0)
- border.shrinkRadii(shadowSpread);
-
if (shadow->isWebkitBoxShadow())
context->setLegacyShadow(shadowOffset, shadowBlur, shadowColor, s->colorSpace());
else
context->setShadow(shadowOffset, shadowBlur, shadowColor, s->colorSpace());
- RoundedIntRect roundedHole(holeRect, border.radii());
context->fillRectWithRoundedHole(outerRect, roundedHole, fillColor, s->colorSpace());
context->restore();
diff --git a/Source/WebCore/rendering/RenderBoxModelObject.h b/Source/WebCore/rendering/RenderBoxModelObject.h
index 2e0bdda..d2f5972 100644
--- a/Source/WebCore/rendering/RenderBoxModelObject.h
+++ b/Source/WebCore/rendering/RenderBoxModelObject.h
@@ -32,6 +32,7 @@ namespace WebCore {
// Modes for some of the line-related functions.
enum LinePositionMode { PositionOnContainingLine, PositionOfInteriorLineBoxes };
enum LineDirectionMode { HorizontalLine, VerticalLine };
+typedef unsigned BorderEdgeFlags;
// This class is the base for all objects that adhere to the CSS box model as described
// at http://www.w3.org/TR/CSS21/box.html
@@ -114,7 +115,7 @@ public:
void paintBorder(GraphicsContext*, int tx, int ty, int w, int h, const RenderStyle*, bool includeLogicalLeftEdge = true, bool includeLogicalRightEdge = true);
bool paintNinePieceImage(GraphicsContext*, int tx, int ty, int w, int h, const RenderStyle*, const NinePieceImage&, CompositeOperator = CompositeSourceOver);
void paintBoxShadow(GraphicsContext*, int tx, int ty, int w, int h, const RenderStyle*, ShadowStyle, bool includeLogicalLeftEdge = true, bool includeLogicalRightEdge = true);
- void paintFillLayerExtended(const PaintInfo&, const Color&, const FillLayer*, int tx, int ty, int width, int height, InlineFlowBox* = 0, CompositeOperator = CompositeSourceOver, RenderObject* backgroundObject = 0);
+ void paintFillLayerExtended(const PaintInfo&, const Color&, const FillLayer*, int tx, int ty, int width, int height, InlineFlowBox* = 0, int inlineBoxWidth = 0, int inlineBoxHeight = 0, CompositeOperator = CompositeSourceOver, RenderObject* backgroundObject = 0);
// Overridden by subclasses to determine line height and baseline position.
virtual int lineHeight(bool firstLine, LineDirectionMode, LinePositionMode = PositionOnContainingLine) const = 0;
@@ -133,15 +134,27 @@ protected:
RenderBoxModelObject* continuation() const;
void setContinuation(RenderBoxModelObject*);
-
+
private:
virtual bool isBoxModelObject() const { return true; }
IntSize calculateFillTileSize(const FillLayer*, IntSize scaledSize) const;
- void clipBorderSidePolygon(GraphicsContext*, const RoundedIntRect& border,
- const BoxSide, bool firstEdgeMatches, bool secondEdgeMatches, const RenderStyle*,
- bool includeLogicalLeftEdge, bool includeLogicalRightEdge);
+ RoundedIntRect getBackgroundRoundedRect(const IntRect&, InlineFlowBox*, int inlineBoxWidth, int inlineBoxHeight,
+ bool includeLogicalLeftEdge, bool includeLogicalRightEdge);
+
+ void clipBorderSidePolygon(GraphicsContext*, const RoundedIntRect& outerBorder, const RoundedIntRect& innerBorder,
+ BoxSide, bool firstEdgeMatches, bool secondEdgeMatches);
+ void paintOneBorderSide(GraphicsContext*, const RenderStyle*, const RoundedIntRect& outerBorder, const RoundedIntRect& innerBorder,
+ const IntRect& sideRect, BoxSide, BoxSide adjacentSide1, BoxSide adjacentSide2, const class BorderEdge[],
+ const Path*, bool includeLogicalLeftEdge, bool includeLogicalRightEdge, bool antialias, const Color* overrideColor = 0);
+ void paintTranslucentBorderSides(GraphicsContext*, const RenderStyle*, const RoundedIntRect& outerBorder, const RoundedIntRect& innerBorder,
+ const class BorderEdge[], bool includeLogicalLeftEdge, bool includeLogicalRightEdge, bool antialias = false);
+ void paintBorderSides(GraphicsContext*, const RenderStyle*, const RoundedIntRect& outerBorder, const RoundedIntRect& innerBorder,
+ const class BorderEdge[], BorderEdgeFlags, bool includeLogicalLeftEdge, bool includeLogicalRightEdge, bool antialias = false, const Color* overrideColor = 0);
+ void drawBoxSideFromPath(GraphicsContext*, const IntRect&, const Path&, const class BorderEdge[],
+ float thickness, float drawThickness, BoxSide, const RenderStyle*,
+ Color, EBorderStyle, bool includeLogicalLeftEdge, bool includeLogicalRightEdge);
friend class RenderView;
diff --git a/Source/WebCore/rendering/RenderDetails.cpp b/Source/WebCore/rendering/RenderDetails.cpp
index be2b435..6b5a1b2 100644
--- a/Source/WebCore/rendering/RenderDetails.cpp
+++ b/Source/WebCore/rendering/RenderDetails.cpp
@@ -24,10 +24,6 @@
#include "CSSStyleSelector.h"
#include "HTMLDetailsElement.h"
#include "HTMLNames.h"
-#include "LocalizedStrings.h"
-#include "RenderDetailsMarker.h"
-#include "RenderTextFragment.h"
-#include "RenderView.h"
namespace WebCore {
@@ -37,23 +33,10 @@ RenderDetails::RenderDetails(Node* node)
: RenderBlock(node)
, m_summaryBlock(0)
, m_contentBlock(0)
- , m_defaultSummaryBlock(0)
- , m_defaultSummaryText(0)
- , m_marker(0)
, m_mainSummary(0)
{
}
-void RenderDetails::destroy()
-{
- if (m_marker) {
- m_marker->destroy();
- m_marker = 0;
- }
-
- RenderBlock::destroy();
-}
-
RenderBlock* RenderDetails::summaryBlock()
{
if (!m_summaryBlock) {
@@ -106,26 +89,9 @@ void RenderDetails::removeChild(RenderObject* oldChild)
ASSERT_NOT_REACHED();
}
-void RenderDetails::setMarkerStyle()
-{
- if (m_marker) {
- RefPtr<RenderStyle> markerStyle = RenderStyle::create();
- markerStyle->inheritFrom(style());
- m_marker->setStyle(markerStyle.release());
- }
-}
-
void RenderDetails::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
{
RenderBlock::styleDidChange(diff, oldStyle);
-
- if (m_defaultSummaryBlock) {
- m_defaultSummaryBlock->setStyle(createSummaryStyle());
- m_defaultSummaryText->setStyle(m_defaultSummaryBlock->style());
- }
-
- setMarkerStyle();
-
// 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());
@@ -144,11 +110,6 @@ RenderObject* RenderDetails::getRenderPosition(RenderObject* object)
return element ? element->renderer() : 0;
}
-void RenderDetails::markerDestroyed()
-{
- m_marker = 0;
-}
-
void RenderDetails::summaryDestroyed(RenderObject* summary)
{
if (summary == m_mainSummary)
@@ -157,14 +118,6 @@ void RenderDetails::summaryDestroyed(RenderObject* summary)
void RenderDetails::moveSummaryToContents()
{
- if (m_defaultSummaryBlock) {
- ASSERT(!m_mainSummary);
- m_defaultSummaryBlock->destroy();
- m_defaultSummaryBlock = 0;
- m_defaultSummaryText = 0;
- return;
- }
-
if (!m_mainSummary)
return;
@@ -173,12 +126,6 @@ void RenderDetails::moveSummaryToContents()
m_mainSummary = 0;
}
-PassRefPtr<RenderStyle> RenderDetails::createSummaryStyle()
-{
- RefPtr<HTMLElement> summary(HTMLElement::create(summaryTag, document()));
- return document()->styleSelector()->styleForElement(summary.get(), style(), true);
-}
-
void RenderDetails::replaceMainSummary(RenderObject* newSummary)
{
ASSERT(newSummary);
@@ -191,68 +138,20 @@ void RenderDetails::replaceMainSummary(RenderObject* newSummary)
m_mainSummary = newSummary;
}
-void RenderDetails::createDefaultSummary()
-{
- if (m_defaultSummaryBlock)
- return;
-
- moveSummaryToContents();
-
- m_defaultSummaryBlock = summaryBlock()->createAnonymousBlock();
- m_defaultSummaryBlock->setStyle(createSummaryStyle());
-
- m_defaultSummaryText = new (renderArena()) RenderTextFragment(document(), defaultDetailsSummaryText().impl());
- m_defaultSummaryText->setStyle(m_defaultSummaryBlock->style());
- m_defaultSummaryBlock->addChild(m_defaultSummaryText);
-
- summaryBlock()->addChild(m_defaultSummaryBlock);
-}
-
void RenderDetails::checkMainSummary()
{
if (!node() || !node()->hasTagName(detailsTag))
return;
Node* mainSummaryNode = static_cast<HTMLDetailsElement*>(node())->mainSummary();
-
- if (!mainSummaryNode || !mainSummaryNode->renderer() || mainSummaryNode->renderer()->isFloatingOrPositioned())
- createDefaultSummary();
- else
+ if (mainSummaryNode && mainSummaryNode->renderer())
replaceMainSummary(mainSummaryNode->renderer());
-
}
void RenderDetails::layout()
{
- ASSERT(needsLayout());
-
checkMainSummary();
- ASSERT(m_summaryBlock);
-
- if (!m_marker) {
- m_marker = new (renderArena()) RenderDetailsMarker(this);
- setMarkerStyle();
- }
- updateMarkerLocation();
-
RenderBlock::layout();
-
- m_interactiveArea = m_summaryBlock->frameRect();
-
- // FIXME: the following code will not be needed once absoluteToLocal get patched to handle flipped blocks writing modes.
- switch (style()->writingMode()) {
- case TopToBottomWritingMode:
- case LeftToRightWritingMode:
- break;
- case RightToLeftWritingMode: {
- m_interactiveArea.setX(width() - m_interactiveArea.x() - m_interactiveArea.width());
- break;
- }
- case BottomToTopWritingMode: {
- m_interactiveArea.setY(height() - m_interactiveArea.y() - m_interactiveArea.height());
- break;
- }
- }
}
bool RenderDetails::isOpen() const
@@ -260,77 +159,4 @@ bool RenderDetails::isOpen() const
return node() && node()->isElementNode() ? !static_cast<Element*>(node())->getAttribute(openAttr).isNull() : false;
}
-RenderObject* RenderDetails::getParentOfFirstLineBox(RenderBlock* curr)
-{
- RenderObject* firstChild = curr->firstChild();
- if (!firstChild)
- return 0;
-
- for (RenderObject* currChild = firstChild; currChild; currChild = currChild->nextSibling()) {
- if (currChild == m_marker)
- continue;
-
- if (currChild->isInline() && (!currChild->isRenderInline() || curr->generatesLineBoxesForInlineChild(currChild)))
- return curr;
-
- if (currChild->isFloating() || currChild->isPositioned())
- continue;
-
- if (currChild->isTable() || !currChild->isRenderBlock() || (currChild->isBox() && toRenderBox(currChild)->isWritingModeRoot()))
- break;
-
- if (currChild->isDetails())
- break;
-
- RenderObject* lineBox = getParentOfFirstLineBox(toRenderBlock(currChild));
- if (lineBox)
- return lineBox;
- }
-
- return 0;
-}
-
-RenderObject* RenderDetails::firstNonMarkerChild(RenderObject* parent)
-{
- RenderObject* result = parent->firstChild();
- while (result && result->isDetailsMarker())
- result = result->nextSibling();
- return result;
-}
-
-void RenderDetails::updateMarkerLocation()
-{
- // Sanity check the location of our marker.
- if (m_marker) {
- RenderObject* markerPar = m_marker->parent();
- RenderObject* lineBoxParent = getParentOfFirstLineBox(m_summaryBlock);
- if (!lineBoxParent) {
- // If the marker is currently contained inside an anonymous box,
- // then we are the only item in that anonymous box (since no line box
- // parent was found). It's ok to just leave the marker where it is
- // in this case.
- if (markerPar && markerPar->isAnonymousBlock())
- lineBoxParent = markerPar;
- else
- lineBoxParent = m_summaryBlock;
- }
-
- if (markerPar != lineBoxParent || m_marker->preferredLogicalWidthsDirty()) {
- // Removing and adding the marker can trigger repainting in
- // containers other than ourselves, so we need to disable LayoutState.
- view()->disableLayoutState();
- m_marker->remove();
- if (!lineBoxParent)
- lineBoxParent = m_summaryBlock;
- lineBoxParent->addChild(m_marker, firstNonMarkerChild(lineBoxParent));
-
- if (m_marker->preferredLogicalWidthsDirty())
- m_marker->computePreferredLogicalWidths();
-
- view()->enableLayoutState();
- }
- }
-}
-
} // namespace WebCore
-
diff --git a/Source/WebCore/rendering/RenderDetails.h b/Source/WebCore/rendering/RenderDetails.h
index 0b56c13..974c174 100644
--- a/Source/WebCore/rendering/RenderDetails.h
+++ b/Source/WebCore/rendering/RenderDetails.h
@@ -27,21 +27,17 @@
namespace WebCore {
-class RenderDetailsMarker;
-
class RenderDetails : public RenderBlock {
public:
explicit RenderDetails(Node*);
- virtual const char* renderName() const { return "RenderDetails"; }
- virtual bool isDetails() const { return true; }
-
bool isOpen() const;
- IntRect interactiveArea() const { return m_interactiveArea; }
- void markerDestroyed();
void summaryDestroyed(RenderObject*);
private:
+ virtual const char* renderName() const { return "RenderDetails"; }
+ virtual bool isDetails() const { return true; }
+
virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
virtual void addChild(RenderObject* newChild, RenderObject *beforeChild = 0);
@@ -52,33 +48,18 @@ private:
virtual bool requiresForcedStyleRecalcPropagation() const { return true; }
virtual void layout();
- virtual void destroy();
- void createDefaultSummary();
void replaceMainSummary(RenderObject*);
void moveSummaryToContents();
void checkMainSummary();
RenderObject* getRenderPosition(RenderObject*);
- PassRefPtr<RenderStyle> createSummaryStyle();
- void setMarkerStyle();
RenderBlock* summaryBlock();
RenderBlock* contentBlock();
- RenderObject* getParentOfFirstLineBox(RenderBlock* curr);
- RenderObject* firstNonMarkerChild(RenderObject* parent);
- void updateMarkerLocation();
-
RenderBlock* m_summaryBlock;
RenderBlock* m_contentBlock;
- RenderObject* m_defaultSummaryBlock;
- RenderObject* m_defaultSummaryText;
-
- IntRect m_interactiveArea;
-
- RenderDetailsMarker* m_marker;
-
RenderObject* m_mainSummary;
};
diff --git a/Source/WebCore/rendering/RenderDetailsMarker.cpp b/Source/WebCore/rendering/RenderDetailsMarker.cpp
index e040eb3..0347e7f 100644
--- a/Source/WebCore/rendering/RenderDetailsMarker.cpp
+++ b/Source/WebCore/rendering/RenderDetailsMarker.cpp
@@ -25,79 +25,21 @@
#include "HTMLNames.h"
#include "PaintInfo.h"
#include "RenderDetails.h"
-#include "RenderSummary.h"
namespace WebCore {
using namespace HTMLNames;
-RenderDetailsMarker::RenderDetailsMarker(RenderDetails* item)
- : RenderBox(item->document())
- , m_details(item)
+RenderDetailsMarker::RenderDetailsMarker(Node* node)
+ : RenderBlock(node)
{
- setInline(true);
- setReplaced(true);
-}
-
-void RenderDetailsMarker::destroy()
-{
- if (m_details)
- m_details->markerDestroyed();
-
- RenderBox::destroy();
-}
-
-int RenderDetailsMarker::lineHeight(bool firstLine, LineDirectionMode direction, LinePositionMode) const
-{
- return m_details->lineHeight(firstLine, direction, PositionOfInteriorLineBoxes);
-}
-
-int RenderDetailsMarker::baselinePosition(FontBaseline baselineType, bool firstLine, LineDirectionMode direction, LinePositionMode) const
-{
- return m_details->baselinePosition(baselineType, firstLine, direction, PositionOfInteriorLineBoxes);
-}
-
-void RenderDetailsMarker::computePreferredLogicalWidths()
-{
- ASSERT(preferredLogicalWidthsDirty());
-
- m_minPreferredLogicalWidth = 2 * style()->fontMetrics().ascent() / 3;
- m_maxPreferredLogicalWidth = m_minPreferredLogicalWidth;
-
- setPreferredLogicalWidthsDirty(false);
-}
-
-void RenderDetailsMarker::layout()
-{
- ASSERT(needsLayout());
-
- setLogicalWidth(minPreferredLogicalWidth());
- setLogicalHeight(style()->fontMetrics().height());
-
- setMarginStart(0);
- setMarginEnd(style()->fontMetrics().ascent() - minPreferredLogicalWidth() + 1);
-
- setNeedsLayout(false);
-}
-
-IntRect RenderDetailsMarker::getRelativeMarkerRect() const
-{
- IntRect relativeRect;
-
- int bulletWidth = minPreferredLogicalWidth();
- relativeRect = IntRect((logicalWidth() - bulletWidth) / 2, (logicalHeight() - bulletWidth) / 2, bulletWidth, bulletWidth);
-
- if (!style()->isHorizontalWritingMode()) {
- relativeRect = relativeRect.transposedRect();
- relativeRect.setX(width() - relativeRect.x() - relativeRect.width());
- }
-
- return relativeRect;
}
bool RenderDetailsMarker::isOpen() const
{
- return m_details && m_details->isOpen();
+ if (RenderDetails* owner = details())
+ return owner->isOpen();
+ return false;
}
static Path createPath(const FloatPoint* path)
@@ -170,17 +112,18 @@ Path RenderDetailsMarker::getCanonicalPath() const
Path RenderDetailsMarker::getPath(const IntPoint& origin) const
{
- IntRect rect = getRelativeMarkerRect();
Path result = getCanonicalPath();
- result.transform(AffineTransform().scale(rect.width()));
- result.translate(FloatSize(origin.x() + rect.x(), origin.y() + rect.y()));
+ result.transform(AffineTransform().scale(logicalHeight()));
+ result.translate(FloatSize(origin.x(), origin.y()));
return result;
}
void RenderDetailsMarker::paint(PaintInfo& paintInfo, int tx, int ty)
{
- if (paintInfo.phase != PaintPhaseForeground || style()->visibility() != VISIBLE)
+ if (paintInfo.phase != PaintPhaseForeground || style()->visibility() != VISIBLE) {
+ RenderBlock::paint(paintInfo, tx, ty);
return;
+ }
IntPoint boxOrigin(tx + x(), ty + y());
IntRect overflowRect(visualOverflowRect());
@@ -199,4 +142,14 @@ void RenderDetailsMarker::paint(PaintInfo& paintInfo, int tx, int ty)
paintInfo.context->fillPath(getPath(boxOrigin));
}
+RenderDetails* RenderDetailsMarker::details() const
+{
+ for (RenderObject* renderer = parent(); renderer; renderer = renderer->parent()) {
+ if (renderer->isDetails())
+ return toRenderDetails(renderer);
+ }
+
+ return 0;
+}
+
}
diff --git a/Source/WebCore/rendering/RenderDetailsMarker.h b/Source/WebCore/rendering/RenderDetailsMarker.h
index de8f60b..f53a0c3 100644
--- a/Source/WebCore/rendering/RenderDetailsMarker.h
+++ b/Source/WebCore/rendering/RenderDetailsMarker.h
@@ -21,38 +21,29 @@
#ifndef RenderDetailsMarker_h
#define RenderDetailsMarker_h
-#include "RenderBox.h"
+#include "RenderBlock.h"
namespace WebCore {
class RenderDetails;
-class RenderDetailsMarker : public RenderBox {
+class RenderDetailsMarker : public RenderBlock {
public:
- RenderDetailsMarker(RenderDetails*);
+ RenderDetailsMarker(Node*);
enum Orientation { Up, Down, Left, Right };
Orientation orientation() const;
- virtual void computePreferredLogicalWidths();
- virtual void destroy();
-
private:
virtual const char* renderName() const { return "RenderDetailsMarker"; }
virtual bool isDetailsMarker() const { return true; }
virtual void paint(PaintInfo&, int tx, int ty);
- virtual void layout();
- virtual int lineHeight(bool firstLine, LineDirectionMode, LinePositionMode = PositionOnContainingLine) const;
- virtual int baselinePosition(FontBaseline, bool firstLine, LineDirectionMode, LinePositionMode = PositionOnContainingLine) const;
-
- IntRect getRelativeMarkerRect() const;
bool isOpen() const;
Path getCanonicalPath() const;
Path getPath(const IntPoint& origin) const;
-
- RenderDetails* m_details;
+ RenderDetails* details() const;
};
inline RenderDetailsMarker* toRenderDetailsMarker(RenderObject* object)
diff --git a/Source/WebCore/rendering/RenderFileUploadControl.cpp b/Source/WebCore/rendering/RenderFileUploadControl.cpp
index b50b2ad..8056662 100644
--- a/Source/WebCore/rendering/RenderFileUploadControl.cpp
+++ b/Source/WebCore/rendering/RenderFileUploadControl.cpp
@@ -109,6 +109,12 @@ bool RenderFileUploadControl::allowsDirectoryUpload()
HTMLInputElement* input = static_cast<HTMLInputElement*>(node());
return input->fastHasAttribute(webkitdirectoryAttr);
}
+
+void RenderFileUploadControl::receiveDropForDirectoryUpload(const Vector<String>& paths)
+{
+ if (Chrome* chromePointer = chrome())
+ chromePointer->enumerateChosenDirectory(paths[0], m_fileChooser.get());
+}
#endif
String RenderFileUploadControl::acceptTypes()
@@ -304,6 +310,13 @@ VisiblePosition RenderFileUploadControl::positionForPoint(const IntPoint&)
void RenderFileUploadControl::receiveDroppedFiles(const Vector<String>& paths)
{
+#if ENABLE(DIRECTORY_UPLOAD)
+ if (allowsDirectoryUpload()) {
+ receiveDropForDirectoryUpload(paths);
+ return;
+ }
+#endif
+
if (allowsMultipleFiles())
m_fileChooser->chooseFiles(paths);
else
diff --git a/Source/WebCore/rendering/RenderFileUploadControl.h b/Source/WebCore/rendering/RenderFileUploadControl.h
index 22974fe..e9fb7f0 100644
--- a/Source/WebCore/rendering/RenderFileUploadControl.h
+++ b/Source/WebCore/rendering/RenderFileUploadControl.h
@@ -64,6 +64,7 @@ private:
bool allowsMultipleFiles();
#if ENABLE(DIRECTORY_UPLOAD)
bool allowsDirectoryUpload();
+ void receiveDropForDirectoryUpload(const Vector<String>&);
#endif
String acceptTypes();
void chooseIconForFiles(FileChooser*, const Vector<String>&);
diff --git a/Source/WebCore/rendering/RenderFlexibleBox.cpp b/Source/WebCore/rendering/RenderFlexibleBox.cpp
index 4d97da0..dc5c171 100644
--- a/Source/WebCore/rendering/RenderFlexibleBox.cpp
+++ b/Source/WebCore/rendering/RenderFlexibleBox.cpp
@@ -978,7 +978,7 @@ void RenderFlexibleBox::applyLineClamp(FlexBoxIterator& iterator, bool relayoutC
// Get ellipsis width, and if the last child is an anchor, it will go after the ellipsis, so add in a space and the anchor width too
int totalWidth;
InlineBox* anchorBox = lastLine->lastChild();
- if (anchorBox && anchorBox->renderer()->node() && anchorBox->renderer()->node()->isLink())
+ if (anchorBox && anchorBox->renderer()->style()->isLink())
totalWidth = anchorBox->logicalWidth() + font.width(TextRun(ellipsisAndSpace, 2));
else {
anchorBox = 0;
diff --git a/Source/WebCore/rendering/RenderFullScreen.cpp b/Source/WebCore/rendering/RenderFullScreen.cpp
index a685064..476727d 100644
--- a/Source/WebCore/rendering/RenderFullScreen.cpp
+++ b/Source/WebCore/rendering/RenderFullScreen.cpp
@@ -46,7 +46,7 @@ PassRefPtr<RenderStyle> RenderFullScreen::createFullScreenStyle()
RefPtr<RenderStyle> fullscreenStyle = RenderStyle::createDefaultStyle();
// Create a stacking context:
- fullscreenStyle->setZIndex(0);
+ fullscreenStyle->setZIndex(INT_MAX);
fullscreenStyle->setFontDescription(FontDescription());
fullscreenStyle->font().update(0);
@@ -54,7 +54,7 @@ PassRefPtr<RenderStyle> RenderFullScreen::createFullScreenStyle()
fullscreenStyle->setDisplay(BOX);
fullscreenStyle->setBoxPack(BCENTER);
fullscreenStyle->setBoxAlign(BCENTER);
- fullscreenStyle->setBoxOrient(HORIZONTAL);
+ fullscreenStyle->setBoxOrient(VERTICAL);
fullscreenStyle->setPosition(FixedPosition);
fullscreenStyle->setWidth(Length(100.0, Percent));
diff --git a/Source/WebCore/rendering/RenderIFrame.cpp b/Source/WebCore/rendering/RenderIFrame.cpp
index 01b8a17..1468acd 100644
--- a/Source/WebCore/rendering/RenderIFrame.cpp
+++ b/Source/WebCore/rendering/RenderIFrame.cpp
@@ -124,6 +124,7 @@ void RenderIFrame::layout()
setNeedsLayout(false);
}
+<<<<<<< HEAD
#if USE(ACCELERATED_COMPOSITING)
bool RenderIFrame::requiresLayer() const
{
@@ -156,4 +157,6 @@ bool RenderIFrame::requiresAcceleratedCompositing() const
}
#endif
+=======
+>>>>>>> WebKit.org at r84325
}
diff --git a/Source/WebCore/rendering/RenderIFrame.h b/Source/WebCore/rendering/RenderIFrame.h
index 0bb3182..b6b30c9 100644
--- a/Source/WebCore/rendering/RenderIFrame.h
+++ b/Source/WebCore/rendering/RenderIFrame.h
@@ -34,19 +34,12 @@ class RenderIFrame : public RenderFrameBase {
public:
explicit RenderIFrame(Element*);
-#if USE(ACCELERATED_COMPOSITING)
- bool requiresAcceleratedCompositing() const;
-#endif
-
private:
virtual void computeLogicalHeight();
virtual void computeLogicalWidth();
virtual void layout();
-#if USE(ACCELERATED_COMPOSITING)
- virtual bool requiresLayer() const;
-#endif
virtual bool isRenderIFrame() const { return true; }
virtual const char* renderName() const { return "RenderPartObject"; } // Lying for now to avoid breaking tests
diff --git a/Source/WebCore/rendering/RenderImage.cpp b/Source/WebCore/rendering/RenderImage.cpp
index 9500aeb..1ea4e09 100644
--- a/Source/WebCore/rendering/RenderImage.cpp
+++ b/Source/WebCore/rendering/RenderImage.cpp
@@ -362,7 +362,12 @@ void RenderImage::paintAreaElementFocusRing(PaintInfo& paintInfo)
// FIXME: Do we need additional code to clip the path to the image's bounding box?
RenderStyle* areaElementStyle = areaElement->computedStyle();
- paintInfo.context->drawFocusRing(path, areaElementStyle->outlineWidth(), areaElementStyle->outlineOffset(),
+ unsigned short outlineWidth = areaElementStyle->outlineWidth();
+ if (!outlineWidth)
+ return;
+
+ paintInfo.context->drawFocusRing(path, outlineWidth,
+ areaElementStyle->outlineOffset(),
areaElementStyle->visitedDependentColor(CSSPropertyOutlineColor));
}
diff --git a/Source/WebCore/rendering/RenderIndicator.cpp b/Source/WebCore/rendering/RenderIndicator.cpp
deleted file mode 100644
index 8f34a40..0000000
--- a/Source/WebCore/rendering/RenderIndicator.cpp
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * 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"
-
-#if ENABLE(PROGRESS_TAG) || ENABLE(METER_TAG)
-
-#include "RenderIndicator.h"
-
-#include "RenderTheme.h"
-#include "RenderView.h"
-
-using namespace std;
-
-namespace WebCore {
-
-RenderIndicatorPart::RenderIndicatorPart(Node* node)
- : RenderBlock(node)
- , m_originalVisibility(HIDDEN)
-{
-}
-
-RenderIndicatorPart::~RenderIndicatorPart()
-{
-}
-
-void RenderIndicatorPart::layout()
-{
- RenderBox* parentRenderer = toRenderBox(parent());
- IntRect oldRect = frameRect();
- IntRect newRect = preferredFrameRect();
-
- LayoutStateMaintainer statePusher(parentRenderer->view(), parentRenderer, parentRenderer->size(), parentRenderer->style()->isFlippedBlocksWritingMode());
-
- if (oldRect.size() != newRect.size())
- setChildNeedsLayout(true, false);
- if (needsLayout())
- RenderBlock::layout();
- setFrameRect(newRect);
-
- if (checkForRepaintDuringLayout())
- repaintDuringLayoutIfMoved(oldRect);
-
- statePusher.pop();
- parentRenderer->addOverflowFromChild(this);
- style()->setVisibility(shouldBeHidden() ? HIDDEN : originalVisibility());
-}
-
-void RenderIndicatorPart::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
-{
- m_originalVisibility = style()->visibility();
- RenderBlock::styleDidChange(diff, oldStyle);
-}
-
-
-RenderIndicator::RenderIndicator(Node* node)
- : RenderBlock(node)
-{
-}
-
-RenderIndicator::~RenderIndicator()
-{
-}
-
-void RenderIndicator::layout()
-{
- ASSERT(needsLayout());
-
- LayoutRepainter repainter(*this, checkForRepaintDuringLayout());
- computeLogicalWidth();
- computeLogicalHeight();
- layoutParts();
- repainter.repaintAfterLayout();
- setNeedsLayout(false);
-}
-
-void RenderIndicator::updateFromElement()
-{
- setNeedsLayout(true);
- repaint();
-}
-
-} // namespace WebCore
-
-#endif
diff --git a/Source/WebCore/rendering/RenderIndicator.h b/Source/WebCore/rendering/RenderIndicator.h
deleted file mode 100644
index 7c2a346..0000000
--- a/Source/WebCore/rendering/RenderIndicator.h
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright (C) 2009 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 RenderIndicator_h
-#define RenderIndicator_h
-
-#if ENABLE(PROGRESS_TAG) || ENABLE(METER_TAG)
-#include "RenderBlock.h"
-
-namespace WebCore {
-
-class RenderIndicatorPart : public RenderBlock {
-public:
- RenderIndicatorPart(Node*);
- virtual ~RenderIndicatorPart();
-
-protected:
- EVisibility originalVisibility() const { return m_originalVisibility; }
- virtual IntRect preferredFrameRect() = 0;
- virtual bool shouldBeHidden() = 0;
-private:
- virtual void layout();
- virtual bool requiresForcedStyleRecalcPropagation() const { return true; }
- virtual bool canHaveChildren() const { return false; }
- virtual void styleDidChange(StyleDifference, const RenderStyle*);
-
- EVisibility m_originalVisibility;
-};
-
-class RenderIndicator : public RenderBlock {
-public:
- RenderIndicator(Node*);
- virtual ~RenderIndicator();
-
-protected:
- virtual void layout();
- virtual void updateFromElement();
- virtual bool requiresForcedStyleRecalcPropagation() const { return true; }
- virtual bool canHaveChildren() const { return false; }
-
- virtual void layoutParts() = 0;
-};
-
-} // namespace WebCore
-
-#endif
-
-#endif // RenderIndicator_h
-
diff --git a/Source/WebCore/rendering/RenderInline.cpp b/Source/WebCore/rendering/RenderInline.cpp
index 3a27307..ae18514 100644
--- a/Source/WebCore/rendering/RenderInline.cpp
+++ b/Source/WebCore/rendering/RenderInline.cpp
@@ -27,6 +27,7 @@
#include "FloatQuad.h"
#include "GraphicsContext.h"
#include "HitTestResult.h"
+#include "InlineTextBox.h"
#include "Page.h"
#include "RenderArena.h"
#include "RenderBlock.h"
@@ -47,6 +48,7 @@ namespace WebCore {
RenderInline::RenderInline(Node* node)
: RenderBoxModelObject(node)
, m_lineHeight(-1)
+ , m_alwaysCreateLineBoxes(false)
{
setChildrenInline(true);
}
@@ -144,6 +146,15 @@ void RenderInline::styleDidChange(StyleDifference diff, const RenderStyle* oldSt
m_lineHeight = -1;
+ if (!m_alwaysCreateLineBoxes) {
+ bool alwaysCreateLineBoxes = hasSelfPaintingLayer() || hasBoxDecorations() || style()->hasPadding() || style()->hasMargin() || style()->hasOutline();
+ if (oldStyle && alwaysCreateLineBoxes) {
+ dirtyLineBoxes(false);
+ setNeedsLayout(true);
+ }
+ m_alwaysCreateLineBoxes = alwaysCreateLineBoxes;
+ }
+
// Update pseudos for :before and :after now.
if (!isAnonymous() && document()->usesBeforeAfterRules()) {
children()->updateBeforeAfterContent(this, BEFORE);
@@ -151,6 +162,38 @@ void RenderInline::styleDidChange(StyleDifference diff, const RenderStyle* oldSt
}
}
+void RenderInline::updateAlwaysCreateLineBoxes()
+{
+ // Once we have been tainted once, just assume it will happen again. This way effects like hover highlighting that change the
+ // background color will only cause a layout on the first rollover.
+ if (m_alwaysCreateLineBoxes)
+ return;
+
+ RenderStyle* parentStyle = parent()->style();
+ RenderInline* parentRenderInline = parent()->isRenderInline() ? toRenderInline(parent()) : 0;
+ bool checkFonts = document()->inNoQuirksMode();
+ bool alwaysCreateLineBoxes = (parentRenderInline && parentRenderInline->alwaysCreateLineBoxes())
+ || (parentRenderInline && parentStyle->verticalAlign() != BASELINE)
+ || style()->verticalAlign() != BASELINE
+ || style()->textEmphasisMark() != TextEmphasisMarkNone
+ || (checkFonts && (!parentStyle->font().fontMetrics().hasIdenticalAscentDescentAndLineGap(style()->font().fontMetrics())
+ || parentStyle->lineHeight() != style()->lineHeight()));
+
+ if (!alwaysCreateLineBoxes && checkFonts && document()->usesFirstLineRules()) {
+ // Have to check the first line style as well.
+ parentStyle = parent()->style(true);
+ RenderStyle* childStyle = style(true);
+ alwaysCreateLineBoxes = !parentStyle->font().fontMetrics().hasIdenticalAscentDescentAndLineGap(childStyle->font().fontMetrics())
+ || childStyle->verticalAlign() != BASELINE
+ || parentStyle->lineHeight() != childStyle->lineHeight();
+ }
+
+ if (alwaysCreateLineBoxes) {
+ dirtyLineBoxes(false);
+ m_alwaysCreateLineBoxes = true;
+ }
+}
+
void RenderInline::addChild(RenderObject* newChild, RenderObject* beforeChild)
{
if (continuation())
@@ -424,9 +467,11 @@ void RenderInline::paint(PaintInfo& paintInfo, int tx, int ty)
void RenderInline::absoluteRects(Vector<IntRect>& rects, int tx, int ty)
{
- if (InlineFlowBox* curr = firstLineBox()) {
+ if (!alwaysCreateLineBoxes())
+ culledInlineAbsoluteRects(this, rects, IntSize(tx, ty));
+ else if (InlineFlowBox* curr = firstLineBox()) {
for (; curr; curr = curr->nextLineBox())
- rects.append(IntRect(tx + curr->x(), ty + curr->y(), curr->logicalWidth(), curr->logicalHeight()));
+ rects.append(enclosingIntRect(FloatRect(tx + curr->x(), ty + curr->y(), curr->width(), curr->height())));
} else
rects.append(IntRect(tx, ty, 0, 0));
@@ -441,11 +486,76 @@ void RenderInline::absoluteRects(Vector<IntRect>& rects, int tx, int ty)
}
}
+void RenderInline::culledInlineAbsoluteRects(const RenderInline* container, Vector<IntRect>& rects, const IntSize& offset)
+{
+ bool isHorizontal = style()->isHorizontalWritingMode();
+ for (RenderObject* curr = firstChild(); curr; curr = curr->nextSibling()) {
+ if (curr->isFloatingOrPositioned())
+ continue;
+
+ // We want to get the margin box in the inline direction, and then use our font ascent/descent in the block
+ // direction (aligned to the root box's baseline).
+ if (curr->isBox()) {
+ RenderBox* currBox = toRenderBox(curr);
+ if (currBox->inlineBoxWrapper()) {
+ RootInlineBox* rootBox = currBox->inlineBoxWrapper()->root();
+ int logicalTop = rootBox->logicalTop() + (rootBox->renderer()->style(rootBox->isFirstLineStyle())->font().fontMetrics().ascent() - container->style(rootBox->isFirstLineStyle())->font().fontMetrics().ascent());
+ int logicalHeight = container->style(rootBox->isFirstLineStyle())->font().fontMetrics().height();
+ FloatRect result;
+ if (isHorizontal)
+ result = FloatRect(offset.width() + currBox->inlineBoxWrapper()->x() - currBox->marginLeft(), offset.height() + logicalTop, currBox->width() + currBox->marginLeft() + currBox->marginRight(), logicalHeight);
+ else
+ result = FloatRect(offset.width() + logicalTop, offset.height() + currBox->inlineBoxWrapper()->y() - currBox->marginTop(), logicalHeight, currBox->height() + currBox->marginTop() + currBox->marginBottom());
+ rects.append(enclosingIntRect(result));
+ }
+ } else if (curr->isRenderInline()) {
+ // If the child doesn't need line boxes either, then we can recur.
+ RenderInline* currInline = toRenderInline(curr);
+ if (!currInline->alwaysCreateLineBoxes())
+ currInline->culledInlineAbsoluteRects(container, rects, offset);
+ else {
+ for (InlineFlowBox* childLine = currInline->firstLineBox(); childLine; childLine = childLine->nextLineBox()) {
+ RootInlineBox* rootBox = childLine->root();
+ int logicalTop = rootBox->logicalTop() + (rootBox->renderer()->style(rootBox->isFirstLineStyle())->font().fontMetrics().ascent() - container->style(rootBox->isFirstLineStyle())->font().fontMetrics().ascent());
+ int logicalHeight = container->style(rootBox->isFirstLineStyle())->font().fontMetrics().height();
+ FloatRect result;
+ if (isHorizontal)
+ result = FloatRect(offset.width() + childLine->x() - childLine->marginLogicalLeft(),
+ offset.height() + logicalTop,
+ childLine->logicalWidth() + childLine->marginLogicalLeft() + childLine->marginLogicalRight(),
+ logicalHeight);
+ else
+ result = FloatRect(offset.width() + logicalTop,
+ offset.height() + childLine->y() - childLine->marginLogicalLeft(),
+ logicalHeight,
+ childLine->logicalWidth() + childLine->marginLogicalLeft() + childLine->marginLogicalRight());
+ rects.append(enclosingIntRect(result));
+ }
+ }
+ } else if (curr->isText()) {
+ RenderText* currText = toRenderText(curr);
+ for (InlineTextBox* childText = currText->firstTextBox(); childText; childText = childText->nextTextBox()) {
+ RootInlineBox* rootBox = childText->root();
+ int logicalTop = rootBox->logicalTop() + (rootBox->renderer()->style(rootBox->isFirstLineStyle())->font().fontMetrics().ascent() - container->style(rootBox->isFirstLineStyle())->font().fontMetrics().ascent());
+ int logicalHeight = container->style(rootBox->isFirstLineStyle())->font().fontMetrics().height();
+ FloatRect result;
+ if (isHorizontal)
+ result = FloatRect(offset.width() + childText->x(), offset.height() + logicalTop, childText->logicalWidth(), logicalHeight);
+ else
+ result = FloatRect(offset.width() + logicalTop, offset.height() + childText->y(), logicalHeight, childText->logicalWidth());
+ rects.append(enclosingIntRect(result));
+ }
+ }
+ }
+}
+
void RenderInline::absoluteQuads(Vector<FloatQuad>& quads)
{
- if (InlineFlowBox* curr = firstLineBox()) {
+ if (!alwaysCreateLineBoxes())
+ culledInlineAbsoluteQuads(this, quads);
+ else if (InlineFlowBox* curr = firstLineBox()) {
for (; curr; curr = curr->nextLineBox()) {
- FloatRect localRect(curr->x(), curr->y(), curr->logicalWidth(), curr->logicalHeight());
+ FloatRect localRect(curr->x(), curr->y(), curr->width(), curr->height());
quads.append(localToAbsoluteQuad(localRect));
}
} else
@@ -455,19 +565,82 @@ void RenderInline::absoluteQuads(Vector<FloatQuad>& quads)
continuation()->absoluteQuads(quads);
}
+void RenderInline::culledInlineAbsoluteQuads(const RenderInline* container, Vector<FloatQuad>& quads)
+{
+ bool isHorizontal = style()->isHorizontalWritingMode();
+ for (RenderObject* curr = firstChild(); curr; curr = curr->nextSibling()) {
+ if (curr->isFloatingOrPositioned())
+ continue;
+
+ // We want to get the margin box in the inline direction, and then use our font ascent/descent in the block
+ // direction (aligned to the root box's baseline).
+ if (curr->isBox()) {
+ RenderBox* currBox = toRenderBox(curr);
+ if (currBox->inlineBoxWrapper()) {
+ RootInlineBox* rootBox = currBox->inlineBoxWrapper()->root();
+ int logicalTop = rootBox->logicalTop() + (rootBox->renderer()->style(rootBox->isFirstLineStyle())->font().fontMetrics().ascent() - container->style(rootBox->isFirstLineStyle())->font().fontMetrics().ascent());
+ int logicalHeight = container->style(rootBox->isFirstLineStyle())->font().fontMetrics().height();
+ FloatRect result;
+ if (isHorizontal)
+ result = FloatRect(currBox->inlineBoxWrapper()->x() - currBox->marginLeft(), logicalTop, currBox->width() + currBox->marginLeft() + currBox->marginRight(), logicalHeight);
+ else
+ result = FloatRect(logicalTop, currBox->inlineBoxWrapper()->y() - currBox->marginTop(), logicalHeight, currBox->height() + currBox->marginTop() + currBox->marginBottom());
+ quads.append(localToAbsoluteQuad(result));
+ }
+ } else if (curr->isRenderInline()) {
+ // If the child doesn't need line boxes either, then we can recur.
+ RenderInline* currInline = toRenderInline(curr);
+ if (!currInline->alwaysCreateLineBoxes())
+ currInline->culledInlineAbsoluteQuads(container, quads);
+ else {
+ for (InlineFlowBox* childLine = currInline->firstLineBox(); childLine; childLine = childLine->nextLineBox()) {
+ RootInlineBox* rootBox = childLine->root();
+ int logicalTop = rootBox->logicalTop() + (rootBox->renderer()->style(rootBox->isFirstLineStyle())->font().fontMetrics().ascent() - container->style(rootBox->isFirstLineStyle())->font().fontMetrics().ascent());
+ int logicalHeight = container->style(rootBox->isFirstLineStyle())->font().fontMetrics().height();
+ FloatRect result;
+ if (isHorizontal)
+ result = FloatRect(childLine->x() - childLine->marginLogicalLeft(),
+ logicalTop,
+ childLine->logicalWidth() + childLine->marginLogicalLeft() + childLine->marginLogicalRight(),
+ logicalHeight);
+ else
+ result = FloatRect(logicalTop,
+ childLine->y() - childLine->marginLogicalLeft(),
+ logicalHeight,
+ childLine->logicalWidth() + childLine->marginLogicalLeft() + childLine->marginLogicalRight());
+ quads.append(localToAbsoluteQuad(result));
+ }
+ }
+ } else if (curr->isText()) {
+ RenderText* currText = toRenderText(curr);
+ for (InlineTextBox* childText = currText->firstTextBox(); childText; childText = childText->nextTextBox()) {
+ RootInlineBox* rootBox = childText->root();
+ int logicalTop = rootBox->logicalTop() + (rootBox->renderer()->style(rootBox->isFirstLineStyle())->font().fontMetrics().ascent() - container->style(rootBox->isFirstLineStyle())->font().fontMetrics().ascent());
+ int logicalHeight = container->style(rootBox->isFirstLineStyle())->font().fontMetrics().height();
+ FloatRect result;
+ if (isHorizontal)
+ result = FloatRect(childText->x(), logicalTop, childText->logicalWidth(), logicalHeight);
+ else
+ result = FloatRect(logicalTop, childText->y(), logicalHeight, childText->logicalWidth());
+ quads.append(localToAbsoluteQuad(result));
+ }
+ }
+ }
+}
+
int RenderInline::offsetLeft() const
{
int x = RenderBoxModelObject::offsetLeft();
- if (firstLineBox())
- x += firstLineBox()->x();
+ if (InlineBox* firstBox = firstLineBoxIncludingCulling())
+ x += firstBox->x();
return x;
}
int RenderInline::offsetTop() const
{
int y = RenderBoxModelObject::offsetTop();
- if (firstLineBox())
- y += firstLineBox()->y();
+ if (InlineBox* firstBox = firstLineBoxIncludingCulling())
+ y += firstBox->y();
return y;
}
@@ -565,6 +738,11 @@ VisiblePosition RenderInline::positionForPoint(const IntPoint& point)
IntRect RenderInline::linesBoundingBox() const
{
+ if (!alwaysCreateLineBoxes()) {
+ ASSERT(!firstLineBox());
+ return enclosingIntRect(culledInlineBoundingBox(this));
+ }
+
IntRect result;
// See <rdar://problem/5289721>, for an unknown reason the linked list here is sometimes inconsistent, first is non-zero and last is zero. We have been
@@ -594,26 +772,183 @@ IntRect RenderInline::linesBoundingBox() const
return result;
}
+FloatRect RenderInline::culledInlineBoundingBox(const RenderInline* container) const
+{
+ FloatRect result;
+ bool isHorizontal = style()->isHorizontalWritingMode();
+ for (RenderObject* curr = firstChild(); curr; curr = curr->nextSibling()) {
+ if (curr->isFloatingOrPositioned())
+ continue;
+
+ // We want to get the margin box in the inline direction, and then use our font ascent/descent in the block
+ // direction (aligned to the root box's baseline).
+ if (curr->isBox()) {
+ RenderBox* currBox = toRenderBox(curr);
+ if (currBox->inlineBoxWrapper()) {
+ RootInlineBox* rootBox = currBox->inlineBoxWrapper()->root();
+ int logicalTop = rootBox->logicalTop() + (rootBox->renderer()->style(rootBox->isFirstLineStyle())->font().fontMetrics().ascent() - container->style(rootBox->isFirstLineStyle())->font().fontMetrics().ascent());
+ int logicalHeight = container->style(rootBox->isFirstLineStyle())->font().fontMetrics().height();
+ if (isHorizontal)
+ result.uniteIfNonZero(FloatRect(currBox->inlineBoxWrapper()->x() - currBox->marginLeft(), logicalTop, currBox->width() + currBox->marginLeft() + currBox->marginRight(), logicalHeight));
+ else
+ result.uniteIfNonZero(FloatRect(logicalTop, currBox->inlineBoxWrapper()->y() - currBox->marginTop(), logicalHeight, currBox->height() + currBox->marginTop() + currBox->marginBottom()));
+ }
+ } else if (curr->isRenderInline()) {
+ // If the child doesn't need line boxes either, then we can recur.
+ RenderInline* currInline = toRenderInline(curr);
+ if (!currInline->alwaysCreateLineBoxes())
+ result.uniteIfNonZero(currInline->culledInlineBoundingBox(container));
+ else {
+ for (InlineFlowBox* childLine = currInline->firstLineBox(); childLine; childLine = childLine->nextLineBox()) {
+ RootInlineBox* rootBox = childLine->root();
+ int logicalTop = rootBox->logicalTop() + (rootBox->renderer()->style(rootBox->isFirstLineStyle())->font().fontMetrics().ascent() - container->style(rootBox->isFirstLineStyle())->font().fontMetrics().ascent());
+ int logicalHeight = container->style(rootBox->isFirstLineStyle())->font().fontMetrics().height();
+ if (isHorizontal)
+ result.uniteIfNonZero(FloatRect(childLine->x() - childLine->marginLogicalLeft(),
+ logicalTop,
+ childLine->logicalWidth() + childLine->marginLogicalLeft() + childLine->marginLogicalRight(),
+ logicalHeight));
+ else
+ result.uniteIfNonZero(FloatRect(logicalTop,
+ childLine->y() - childLine->marginLogicalLeft(),
+ logicalHeight,
+ childLine->logicalWidth() + childLine->marginLogicalLeft() + childLine->marginLogicalRight()));
+
+ }
+ }
+ } else if (curr->isText()) {
+ RenderText* currText = toRenderText(curr);
+ for (InlineTextBox* childText = currText->firstTextBox(); childText; childText = childText->nextTextBox()) {
+ RootInlineBox* rootBox = childText->root();
+ int logicalTop = rootBox->logicalTop() + (rootBox->renderer()->style(rootBox->isFirstLineStyle())->font().fontMetrics().ascent() - container->style(rootBox->isFirstLineStyle())->font().fontMetrics().ascent());
+ int logicalHeight = container->style(rootBox->isFirstLineStyle())->font().fontMetrics().height();
+ if (isHorizontal)
+ result.uniteIfNonZero(FloatRect(childText->x(), logicalTop, childText->logicalWidth(), logicalHeight));
+ else
+ result.uniteIfNonZero(FloatRect(logicalTop, childText->y(), logicalHeight, childText->logicalWidth()));
+ }
+ }
+ }
+ return enclosingIntRect(result);
+}
+
+InlineBox* RenderInline::culledInlineFirstLineBox() const
+{
+ for (RenderObject* curr = firstChild(); curr; curr = curr->nextSibling()) {
+ if (curr->isFloatingOrPositioned())
+ continue;
+
+ // We want to get the margin box in the inline direction, and then use our font ascent/descent in the block
+ // direction (aligned to the root box's baseline).
+ if (curr->isBox()) {
+ RenderBox* currBox = toRenderBox(curr);
+ if (currBox->inlineBoxWrapper())
+ return currBox->inlineBoxWrapper();
+ } else if (curr->isRenderInline()) {
+ RenderInline* currInline = toRenderInline(curr);
+ InlineBox* result = currInline->firstLineBoxIncludingCulling();
+ if (result)
+ return result;
+ } else if (curr->isText()) {
+ RenderText* currText = toRenderText(curr);
+ if (currText->firstTextBox())
+ return currText->firstTextBox();
+ }
+ }
+ return 0;
+}
+
+InlineBox* RenderInline::culledInlineLastLineBox() const
+{
+ for (RenderObject* curr = lastChild(); curr; curr = curr->previousSibling()) {
+ if (curr->isFloatingOrPositioned())
+ continue;
+
+ // We want to get the margin box in the inline direction, and then use our font ascent/descent in the block
+ // direction (aligned to the root box's baseline).
+ if (curr->isBox()) {
+ RenderBox* currBox = toRenderBox(curr);
+ if (currBox->inlineBoxWrapper())
+ return currBox->inlineBoxWrapper();
+ } else if (curr->isRenderInline()) {
+ RenderInline* currInline = toRenderInline(curr);
+ InlineBox* result = currInline->lastLineBoxIncludingCulling();
+ if (result)
+ return result;
+ } else if (curr->isText()) {
+ RenderText* currText = toRenderText(curr);
+ if (currText->lastTextBox())
+ return currText->lastTextBox();
+ }
+ }
+ return 0;
+}
+
+IntRect RenderInline::culledInlineVisualOverflowBoundingBox() const
+{
+ IntRect result(culledInlineBoundingBox(this));
+ bool isHorizontal = style()->isHorizontalWritingMode();
+ for (RenderObject* curr = firstChild(); curr; curr = curr->nextSibling()) {
+ if (curr->isFloatingOrPositioned())
+ continue;
+
+ // For overflow we just have to propagate by hand and recompute it all.
+ if (curr->isBox()) {
+ RenderBox* currBox = toRenderBox(curr);
+ if (!currBox->hasSelfPaintingLayer() && currBox->inlineBoxWrapper()) {
+ IntRect logicalRect = currBox->logicalVisualOverflowRectForPropagation(style());
+ if (isHorizontal) {
+ logicalRect.move(currBox->x(), currBox->y());
+ result.uniteIfNonZero(logicalRect);
+ } else {
+ logicalRect.move(currBox->y(), currBox->x());
+ result.uniteIfNonZero(logicalRect.transposedRect());
+ }
+ }
+ } else if (curr->isRenderInline()) {
+ // If the child doesn't need line boxes either, then we can recur.
+ RenderInline* currInline = toRenderInline(curr);
+ if (!currInline->alwaysCreateLineBoxes())
+ result.uniteIfNonZero(currInline->culledInlineVisualOverflowBoundingBox());
+ else if (!currInline->hasSelfPaintingLayer())
+ result.uniteIfNonZero(currInline->linesVisualOverflowBoundingBox());
+ } else if (curr->isText()) {
+ // FIXME; Overflow from text boxes is lost. We will need to cache this information in
+ // InlineTextBoxes.
+ RenderText* currText = toRenderText(curr);
+ result.uniteIfNonZero(currText->linesVisualOverflowBoundingBox());
+ }
+ }
+ return result;
+}
+
IntRect RenderInline::linesVisualOverflowBoundingBox() const
{
+ if (!alwaysCreateLineBoxes())
+ return culledInlineVisualOverflowBoundingBox();
+
if (!firstLineBox() || !lastLineBox())
return IntRect();
// Return the width of the minimal left side and the maximal right side.
- float logicalLeftSide = numeric_limits<int>::max();
- float logicalRightSide = numeric_limits<int>::min();
+ int logicalLeftSide = numeric_limits<int>::max();
+ int logicalRightSide = numeric_limits<int>::min();
for (InlineFlowBox* curr = firstLineBox(); curr; curr = curr->nextLineBox()) {
- logicalLeftSide = min(logicalLeftSide, static_cast<float>(curr->logicalLeftVisualOverflow()));
- logicalRightSide = max(logicalRightSide, static_cast<float>(curr->logicalRightVisualOverflow()));
+ logicalLeftSide = min(logicalLeftSide, curr->logicalLeftVisualOverflow());
+ logicalRightSide = max(logicalRightSide, curr->logicalRightVisualOverflow());
}
- bool isHorizontal = style()->isHorizontalWritingMode();
-
- float x = isHorizontal ? logicalLeftSide : firstLineBox()->minXVisualOverflow();
- float y = isHorizontal ? firstLineBox()->minYVisualOverflow() : logicalLeftSide;
- float width = isHorizontal ? logicalRightSide - logicalLeftSide : lastLineBox()->maxXVisualOverflow() - firstLineBox()->minXVisualOverflow();
- float height = isHorizontal ? lastLineBox()->maxYVisualOverflow() - firstLineBox()->minYVisualOverflow() : logicalRightSide - logicalLeftSide;
- return enclosingIntRect(FloatRect(x, y, width, height));
+ RootInlineBox* firstRootBox = firstLineBox()->root();
+ RootInlineBox* lastRootBox = lastLineBox()->root();
+
+ int logicalTop = firstLineBox()->logicalTopVisualOverflow(firstRootBox->lineTop());
+ int logicalWidth = logicalRightSide - logicalLeftSide;
+ int logicalHeight = lastLineBox()->logicalBottomVisualOverflow(lastRootBox->lineBottom()) - logicalTop;
+
+ IntRect rect(logicalLeftSide, logicalTop, logicalWidth, logicalHeight);
+ if (!style()->isHorizontalWritingMode())
+ rect = rect.transposedRect();
+ return rect;
}
IntRect RenderInline::clippedOverflowRectForRepaint(RenderBoxModelObject* repaintContainer)
@@ -621,7 +956,7 @@ IntRect RenderInline::clippedOverflowRectForRepaint(RenderBoxModelObject* repain
// Only run-ins are allowed in here during layout.
ASSERT(!view() || !view()->layoutStateEnabled() || isRunIn());
- if (!firstLineBox() && !continuation())
+ if (!firstLineBoxIncludingCulling() && !continuation())
return IntRect();
// Find our leftmost position.
@@ -889,9 +1224,33 @@ void RenderInline::updateHitTestResult(HitTestResult& result, const IntPoint& po
void RenderInline::dirtyLineBoxes(bool fullLayout)
{
- if (fullLayout)
+ if (fullLayout) {
m_lineBoxes.deleteLineBoxes(renderArena());
- else
+ return;
+ }
+
+ if (!alwaysCreateLineBoxes()) {
+ // We have to grovel into our children in order to dirty the appropriate lines.
+ for (RenderObject* curr = firstChild(); curr; curr = curr->nextSibling()) {
+ if (curr->isFloatingOrPositioned())
+ continue;
+ if (curr->isBox() && !curr->needsLayout()) {
+ RenderBox* currBox = toRenderBox(curr);
+ if (currBox->inlineBoxWrapper())
+ currBox->inlineBoxWrapper()->root()->markDirty();
+ } else if (!curr->selfNeedsLayout()) {
+ if (curr->isRenderInline()) {
+ RenderInline* currInline = toRenderInline(curr);
+ for (InlineFlowBox* childLine = currInline->firstLineBox(); childLine; childLine = childLine->nextLineBox())
+ childLine->root()->markDirty();
+ } else if (curr->isText()) {
+ RenderText* currText = toRenderText(curr);
+ for (InlineTextBox* childText = currText->firstTextBox(); childText; childText = childText->nextTextBox())
+ childText->root()->markDirty();
+ }
+ }
+ }
+ } else
m_lineBoxes.dirtyLineBoxes();
}
@@ -902,6 +1261,7 @@ InlineFlowBox* RenderInline::createInlineFlowBox()
InlineFlowBox* RenderInline::createAndAppendInlineFlowBox()
{
+ setAlwaysCreateLineBoxes();
InlineFlowBox* flowBox = createInlineFlowBox();
m_lineBoxes.appendLineBox(flowBox);
return flowBox;
@@ -978,13 +1338,11 @@ void RenderInline::imageChanged(WrappedImagePtr, const IntRect*)
void RenderInline::addFocusRingRects(Vector<IntRect>& rects, int tx, int ty)
{
- for (InlineFlowBox* curr = firstLineBox(); curr; curr = curr->nextLineBox()) {
- RootInlineBox* root = curr->root();
- int top = max(root->lineTop(), curr->logicalTop());
- int bottom = min(root->lineBottom(), curr->logicalBottom());
- IntRect rect(tx + curr->x(), ty + top, curr->logicalWidth(), bottom - top);
- if (!rect.isEmpty())
- rects.append(rect);
+ if (!alwaysCreateLineBoxes())
+ culledInlineAbsoluteRects(this, rects, IntSize(tx, ty));
+ else {
+ for (InlineFlowBox* curr = firstLineBox(); curr; curr = curr->nextLineBox())
+ rects.append(enclosingIntRect(FloatRect(tx + curr->x(), ty + curr->y(), curr->width(), curr->height())));
}
for (RenderObject* curr = firstChild(); curr; curr = curr->nextSibling()) {
@@ -995,7 +1353,7 @@ void RenderInline::addFocusRingRects(Vector<IntRect>& rects, int tx, int ty)
pos = curr->localToAbsolute();
else if (curr->isBox())
pos.move(toRenderBox(curr)->x(), toRenderBox(curr)->y());
- curr->addFocusRingRects(rects, pos.x(), pos.y());
+ curr->addFocusRingRects(rects, pos.x(), pos.y());
}
}
diff --git a/Source/WebCore/rendering/RenderInline.h b/Source/WebCore/rendering/RenderInline.h
index 08ac002..dc3eaea 100644
--- a/Source/WebCore/rendering/RenderInline.h
+++ b/Source/WebCore/rendering/RenderInline.h
@@ -23,6 +23,7 @@
#ifndef RenderInline_h
#define RenderInline_h
+#include "InlineFlowBox.h"
#include "RenderBoxModelObject.h"
#include "RenderLineBoxList.h"
@@ -64,6 +65,8 @@ public:
InlineFlowBox* firstLineBox() const { return m_lineBoxes.firstLineBox(); }
InlineFlowBox* lastLineBox() const { return m_lineBoxes.lastLineBox(); }
+ InlineBox* firstLineBoxIncludingCulling() const { return alwaysCreateLineBoxes() ? firstLineBox() : culledInlineFirstLineBox(); }
+ InlineBox* lastLineBoxIncludingCulling() const { return alwaysCreateLineBoxes() ? lastLineBox() : culledInlineLastLineBox(); }
virtual RenderBoxModelObject* virtualContinuation() const { return continuation(); }
RenderInline* inlineElementContinuation() const;
@@ -78,6 +81,10 @@ public:
using RenderBoxModelObject::continuation;
using RenderBoxModelObject::setContinuation;
+ bool alwaysCreateLineBoxes() const { return m_alwaysCreateLineBoxes; }
+ void setAlwaysCreateLineBoxes() { m_alwaysCreateLineBoxes = true; }
+ void updateAlwaysCreateLineBoxes();
+
protected:
virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
@@ -91,6 +98,13 @@ private:
virtual bool isRenderInline() const { return true; }
+ FloatRect culledInlineBoundingBox(const RenderInline* container) const;
+ IntRect culledInlineVisualOverflowBoundingBox() const;
+ InlineBox* culledInlineFirstLineBox() const;
+ InlineBox* culledInlineLastLineBox() const;
+ void culledInlineAbsoluteRects(const RenderInline* container, Vector<IntRect>&, const IntSize&);
+ void culledInlineAbsoluteQuads(const RenderInline* container, Vector<FloatQuad>&);
+
void addChildToContinuation(RenderObject* newChild, RenderObject* beforeChild);
virtual void addChildIgnoringContinuation(RenderObject* newChild, RenderObject* beforeChild = 0);
@@ -154,7 +168,8 @@ private:
RenderObjectChildList m_children;
RenderLineBoxList m_lineBoxes; // All of the line boxes created for this inline flow. For example, <i>Hello<br>world.</i> will have two <i> line boxes.
- mutable int m_lineHeight;
+ mutable int m_lineHeight : 31;
+ bool m_alwaysCreateLineBoxes : 1;
};
inline RenderInline* toRenderInline(RenderObject* object)
diff --git a/Source/WebCore/rendering/RenderInputSpeech.cpp b/Source/WebCore/rendering/RenderInputSpeech.cpp
index 8a1e73f..e5dba78 100644
--- a/Source/WebCore/rendering/RenderInputSpeech.cpp
+++ b/Source/WebCore/rendering/RenderInputSpeech.cpp
@@ -57,6 +57,10 @@ void RenderInputSpeech::adjustInputFieldSpeechButtonStyle(CSSStyleSelector*, Ren
bool RenderInputSpeech::paintInputFieldSpeechButton(RenderObject* object, const PaintInfo& paintInfo, const IntRect& rect)
{
+ Element* element = object->node()->isElementNode() ? toElement(object->node()) : 0;
+ if (!element || !element->isInputFieldSpeechButtonElement())
+ return false;
+
// Get the renderer of <input> element.
Node* input = object->node()->shadowAncestorNode();
if (!input->renderer()->isBox())
@@ -84,7 +88,7 @@ bool RenderInputSpeech::paintInputFieldSpeechButton(RenderObject* object, const
DEFINE_STATIC_LOCAL(RefPtr<Image>, imageStateRecording, (Image::loadPlatformResource("inputSpeechRecording")));
DEFINE_STATIC_LOCAL(RefPtr<Image>, imageStateWaiting, (Image::loadPlatformResource("inputSpeechWaiting")));
- InputFieldSpeechButtonElement* speechButton = reinterpret_cast<InputFieldSpeechButtonElement*>(object->node());
+ InputFieldSpeechButtonElement* speechButton = toInputFieldSpeechButtonElement(element);
Image* image = imageStateNormal.get();
if (speechButton->state() == InputFieldSpeechButtonElement::Recording)
image = imageStateRecording.get();
diff --git a/Source/WebCore/rendering/RenderLayer.cpp b/Source/WebCore/rendering/RenderLayer.cpp
index 3c6bc31..da82996 100644
--- a/Source/WebCore/rendering/RenderLayer.cpp
+++ b/Source/WebCore/rendering/RenderLayer.cpp
@@ -1420,7 +1420,7 @@ void RenderLayer::scrollTo(int x, int y)
renderer()->repaintUsingContainer(repaintContainer, rectForRepaint);
// Schedule the scroll DOM event.
- renderer()->node()->document()->eventQueue()->enqueueScrollEvent(renderer()->node(), EventQueue::ScrollEventElementTarget);
+ renderer()->node()->document()->eventQueue()->enqueueOrDispatchScrollEvent(renderer()->node(), EventQueue::ScrollEventElementTarget);
}
void RenderLayer::scrollRectToVisible(const IntRect& rect, bool scrollToAnchor, const ScrollAlignment& alignX, const ScrollAlignment& alignY)
@@ -1716,17 +1716,17 @@ static IntRect cornerRect(const RenderLayer* layer, const IntRect& bounds)
horizontalThickness, verticalThickness);
}
-static IntRect scrollCornerRect(const RenderLayer* layer, const IntRect& bounds)
+IntRect RenderLayer::scrollCornerRect() const
{
// We have a scrollbar corner when a scrollbar is visible and not filling the entire length of the box.
// This happens when:
// (a) A resizer is present and at least one scrollbar is present
// (b) Both scrollbars are present.
- bool hasHorizontalBar = layer->horizontalScrollbar();
- bool hasVerticalBar = layer->verticalScrollbar();
- bool hasResizer = layer->renderer()->style()->resize() != RESIZE_NONE;
+ bool hasHorizontalBar = horizontalScrollbar();
+ bool hasVerticalBar = verticalScrollbar();
+ bool hasResizer = renderer()->style()->resize() != RESIZE_NONE;
if ((hasHorizontalBar && hasVerticalBar) || (hasResizer && (hasHorizontalBar || hasVerticalBar)))
- return cornerRect(layer, bounds);
+ return cornerRect(this, renderBox()->borderBoxRect());
return IntRect();
}
@@ -1738,10 +1738,21 @@ static IntRect resizerCornerRect(const RenderLayer* layer, const IntRect& bounds
return cornerRect(layer, bounds);
}
-bool RenderLayer::scrollbarCornerPresent() const
+IntRect RenderLayer::scrollCornerAndResizerRect() const
+{
+ RenderBox* box = renderBox();
+ if (!box)
+ return IntRect();
+ IntRect scrollCornerAndResizer = scrollCornerRect();
+ if (scrollCornerAndResizer.isEmpty())
+ scrollCornerAndResizer = resizerCornerRect(this, box->borderBoxRect());
+ return scrollCornerAndResizer;
+}
+
+bool RenderLayer::isScrollCornerVisible() const
{
ASSERT(renderer()->isBox());
- return !scrollCornerRect(this, renderBox()->borderBoxRect()).isEmpty();
+ return !scrollCornerRect().isEmpty();
}
IntRect RenderLayer::convertFromScrollbarToContainingView(const Scrollbar* scrollbar, const IntRect& scrollbarRect) const
@@ -1834,6 +1845,19 @@ IntSize RenderLayer::scrollbarOffset(const Scrollbar* scrollbar) const
void RenderLayer::invalidateScrollbarRect(Scrollbar* scrollbar, const IntRect& rect)
{
+#if USE(ACCELERATED_COMPOSITING)
+ if (scrollbar == m_vBar.get()) {
+ if (GraphicsLayer* layer = layerForVerticalScrollbar()) {
+ layer->setNeedsDisplayInRect(rect);
+ return;
+ }
+ } else {
+ if (GraphicsLayer* layer = layerForHorizontalScrollbar()) {
+ layer->setNeedsDisplayInRect(rect);
+ return;
+ }
+ }
+#endif
IntRect scrollRect = rect;
RenderBox* box = renderBox();
ASSERT(box);
@@ -1844,6 +1868,20 @@ void RenderLayer::invalidateScrollbarRect(Scrollbar* scrollbar, const IntRect& r
renderer()->repaintRectangle(scrollRect);
}
+void RenderLayer::invalidateScrollCornerRect(const IntRect& rect)
+{
+#if USE(ACCELERATED_COMPOSITING)
+ if (GraphicsLayer* layer = layerForScrollCorner()) {
+ layer->setNeedsDisplayInRect(rect);
+ return;
+ }
+#endif
+ if (m_scrollCorner)
+ m_scrollCorner->repaintRectangle(rect);
+ if (m_resizer)
+ m_resizer->repaintRectangle(rect);
+}
+
PassRefPtr<Scrollbar> RenderLayer::createScrollbar(ScrollbarOrientation orientation)
{
RefPtr<Scrollbar> widget;
@@ -1972,8 +2010,8 @@ void RenderLayer::positionOverflowControls(int tx, int ty)
if (!box)
return;
- IntRect borderBox = box->borderBoxRect();
- IntRect scrollCorner(scrollCornerRect(this, borderBox));
+ const IntRect& borderBox = box->borderBoxRect();
+ const IntRect& scrollCorner = scrollCornerRect();
IntRect absBounds(borderBox.x() + tx, borderBox.y() + ty, borderBox.width(), borderBox.height());
if (m_vBar)
m_vBar->setFrameRect(IntRect(absBounds.maxX() - box->borderRight() - m_vBar->width(),
@@ -1986,7 +2024,31 @@ void RenderLayer::positionOverflowControls(int tx, int ty)
absBounds.maxY() - box->borderBottom() - m_hBar->height(),
absBounds.width() - (box->borderLeft() + box->borderRight()) - scrollCorner.width(),
m_hBar->height()));
-
+
+#if USE(ACCELERATED_COMPOSITING)
+ if (GraphicsLayer* layer = layerForHorizontalScrollbar()) {
+ if (m_hBar) {
+ layer->setPosition(IntPoint(m_hBar->frameRect().x() - tx, m_hBar->frameRect().y() - ty));
+ layer->setSize(m_hBar->frameRect().size());
+ }
+ layer->setDrawsContent(m_hBar);
+ }
+ if (GraphicsLayer* layer = layerForVerticalScrollbar()) {
+ if (m_vBar) {
+ layer->setPosition(IntPoint(m_vBar->frameRect().x() - tx, m_vBar->frameRect().y() - ty));
+ layer->setSize(m_vBar->frameRect().size());
+ }
+ layer->setDrawsContent(m_vBar);
+ }
+
+ if (GraphicsLayer* layer = layerForScrollCorner()) {
+ const IntRect& scrollCornerAndResizer = scrollCornerAndResizerRect();
+ layer->setPosition(scrollCornerAndResizer.location());
+ layer->setSize(scrollCornerAndResizer.size());
+ layer->setDrawsContent(!scrollCornerAndResizer.isEmpty());
+ }
+#endif
+
if (m_scrollCorner)
m_scrollCorner->setFrameRect(scrollCorner);
if (m_resizer)
@@ -2239,9 +2301,10 @@ void RenderLayer::paintOverflowControls(GraphicsContext* context, int tx, int ty
// and we'll paint the scrollbars then. In the meantime, cache tx and ty so that the
// second pass doesn't need to re-enter the RenderTree to get it right.
if (hasOverlayScrollbars() && !paintingOverlayControls) {
- RenderLayer* rootLayer = renderer()->view()->layer();
- rootLayer->setContainsDirtyOverlayScrollbars(true);
+ RenderView* renderView = renderer()->view();
+ renderView->layer()->setContainsDirtyOverlayScrollbars(true);
m_cachedOverlayScrollbarOffset = IntPoint(tx, ty);
+ renderView->frameView()->setContainsScrollableAreaWithOverlayScrollbars(true);
return;
}
@@ -2258,11 +2321,24 @@ void RenderLayer::paintOverflowControls(GraphicsContext* context, int tx, int ty
positionOverflowControls(offsetX, offsetY);
// Now that we're sure the scrollbars are in the right place, paint them.
- if (m_hBar)
+ if (m_hBar
+#if USE(ACCELERATED_COMPOSITING)
+ && !layerForHorizontalScrollbar()
+#endif
+ )
m_hBar->paint(context, damageRect);
- if (m_vBar)
+ if (m_vBar
+#if USE(ACCELERATED_COMPOSITING)
+ && !layerForVerticalScrollbar()
+#endif
+ )
m_vBar->paint(context, damageRect);
+#if USE(ACCELERATED_COMPOSITING)
+ if (layerForScrollCorner())
+ return;
+#endif
+
// We fill our scroll corner with white if we have a scrollbar that doesn't run all the way up to the
// edge of the box.
paintScrollCorner(context, offsetX, offsetY, damageRect);
@@ -2276,7 +2352,7 @@ void RenderLayer::paintScrollCorner(GraphicsContext* context, int tx, int ty, co
RenderBox* box = renderBox();
ASSERT(box);
- IntRect cornerRect = scrollCornerRect(this, box->borderBoxRect());
+ IntRect cornerRect = scrollCornerRect();
IntRect absRect = IntRect(cornerRect.x() + tx, cornerRect.y() + ty, cornerRect.width(), cornerRect.height());
if (!absRect.intersects(damageRect))
return;
@@ -2327,7 +2403,7 @@ void RenderLayer::paintResizer(GraphicsContext* context, int tx, int ty, const I
// Draw a frame around the resizer (1px grey line) if there are any scrollbars present.
// Clipping will exclude the right and bottom edges of this frame.
- if (m_hBar || m_vBar) {
+ if (!hasOverlayScrollbars() && (m_vBar || m_hBar)) {
context->save();
context->clip(absRect);
IntRect largerCorner = absRect;
@@ -2479,7 +2555,7 @@ void RenderLayer::paintLayer(RenderLayer* rootLayer, GraphicsContext* p,
// Avoid painting layers when stylesheets haven't loaded. This eliminates FOUC.
// It's ok not to draw, because later on, when all the stylesheets do load, updateStyleSelector on the Document
// will do a full repaint().
- if (renderer()->document()->mayCauseFlashOfUnstyledContent() && !renderer()->isRenderView() && !renderer()->isRoot())
+ if (renderer()->document()->didLayoutWithPendingStylesheets() && !renderer()->isRenderView() && !renderer()->isRoot())
return;
// If this layer is totally invisible then there is nothing to paint.
@@ -2921,6 +2997,7 @@ RenderLayer* RenderLayer::hitTestLayer(RenderLayer* rootLayer, RenderLayer* cont
#if USE(ACCELERATED_COMPOSITING)
useTemporaryClipRects = compositor()->inCompositingMode();
#endif
+ useTemporaryClipRects |= renderer()->view()->frameView()->containsScrollableAreaWithOverlayScrollbars();
IntRect hitTestArea = result.rectForPoint(hitTestPoint);
@@ -2928,7 +3005,7 @@ RenderLayer* RenderLayer::hitTestLayer(RenderLayer* rootLayer, RenderLayer* cont
if (transform() && !appliedTransform) {
// Make sure the parent's clip rects have been calculated.
if (parent()) {
- IntRect clipRect = backgroundClipRect(rootLayer, useTemporaryClipRects);
+ IntRect clipRect = backgroundClipRect(rootLayer, useTemporaryClipRects, IncludeOverlayScrollbarSize);
// Go ahead and test the enclosing clip now.
if (!clipRect.intersects(hitTestArea))
return 0;
@@ -2996,7 +3073,7 @@ RenderLayer* RenderLayer::hitTestLayer(RenderLayer* rootLayer, RenderLayer* cont
IntRect bgRect;
IntRect fgRect;
IntRect outlineRect;
- calculateRects(rootLayer, hitTestRect, layerBounds, bgRect, fgRect, outlineRect, useTemporaryClipRects);
+ calculateRects(rootLayer, hitTestRect, layerBounds, bgRect, fgRect, outlineRect, useTemporaryClipRects, IncludeOverlayScrollbarSize);
// The following are used for keeping track of the z-depth of the hit point of 3d-transformed
// descendants.
@@ -3265,7 +3342,7 @@ RenderLayer* RenderLayer::hitTestChildLayerColumns(RenderLayer* childLayer, Rend
return 0;
}
-void RenderLayer::updateClipRects(const RenderLayer* rootLayer)
+void RenderLayer::updateClipRects(const RenderLayer* rootLayer, OverlayScrollbarSizeRelevancy relevancy)
{
if (m_clipRects) {
ASSERT(rootLayer == m_clipRectsRoot);
@@ -3276,10 +3353,10 @@ void RenderLayer::updateClipRects(const RenderLayer* rootLayer)
// examine the parent. We want to cache clip rects with us as the root.
RenderLayer* parentLayer = rootLayer != this ? parent() : 0;
if (parentLayer)
- parentLayer->updateClipRects(rootLayer);
+ parentLayer->updateClipRects(rootLayer, relevancy);
ClipRects clipRects;
- calculateClipRects(rootLayer, clipRects, true);
+ calculateClipRects(rootLayer, clipRects, true, relevancy);
if (parentLayer && parentLayer->clipRects() && clipRects == *parentLayer->clipRects())
m_clipRects = parentLayer->clipRects();
@@ -3291,7 +3368,7 @@ void RenderLayer::updateClipRects(const RenderLayer* rootLayer)
#endif
}
-void RenderLayer::calculateClipRects(const RenderLayer* rootLayer, ClipRects& clipRects, bool useCached) const
+void RenderLayer::calculateClipRects(const RenderLayer* rootLayer, ClipRects& clipRects, bool useCached, OverlayScrollbarSizeRelevancy relevancy) const
{
if (!parent()) {
// The root layer's clip rect is always infinite.
@@ -3339,6 +3416,7 @@ void RenderLayer::calculateClipRects(const RenderLayer* rootLayer, ClipRects& cl
}
if (renderer()->hasOverflowClip()) {
+<<<<<<< HEAD
IntRect newOverflowClip = toRenderBox(renderer())->overflowClipRect(x, y);
#if ENABLE(ANDROID_OVERFLOW_SCROLL)
clipRects.setHitTestClip(intersection(clipRects.fixed() ? clipRects.fixedClipRect()
@@ -3350,6 +3428,9 @@ void RenderLayer::calculateClipRects(const RenderLayer* rootLayer, ClipRects& cl
m_scrollWidth, m_scrollHeight);
}
#endif
+=======
+ IntRect newOverflowClip = toRenderBox(renderer())->overflowClipRect(x, y, relevancy);
+>>>>>>> WebKit.org at r84325
clipRects.setOverflowClipRect(intersection(newOverflowClip, clipRects.overflowClipRect()));
if (renderer()->isPositioned() || renderer()->isRelPositioned())
clipRects.setPosClipRect(intersection(newOverflowClip, clipRects.posClipRect()));
@@ -3363,24 +3444,24 @@ void RenderLayer::calculateClipRects(const RenderLayer* rootLayer, ClipRects& cl
}
}
-void RenderLayer::parentClipRects(const RenderLayer* rootLayer, ClipRects& clipRects, bool temporaryClipRects) const
+void RenderLayer::parentClipRects(const RenderLayer* rootLayer, ClipRects& clipRects, bool temporaryClipRects, OverlayScrollbarSizeRelevancy relevancy) const
{
ASSERT(parent());
if (temporaryClipRects) {
- parent()->calculateClipRects(rootLayer, clipRects);
+ parent()->calculateClipRects(rootLayer, clipRects, false, relevancy);
return;
}
- parent()->updateClipRects(rootLayer);
+ parent()->updateClipRects(rootLayer, relevancy);
clipRects = *parent()->clipRects();
}
-IntRect RenderLayer::backgroundClipRect(const RenderLayer* rootLayer, bool temporaryClipRects) const
+IntRect RenderLayer::backgroundClipRect(const RenderLayer* rootLayer, bool temporaryClipRects, OverlayScrollbarSizeRelevancy relevancy) const
{
IntRect backgroundRect;
if (parent()) {
ClipRects parentRects;
- parentClipRects(rootLayer, parentRects, temporaryClipRects);
+ parentClipRects(rootLayer, parentRects, temporaryClipRects, relevancy);
backgroundRect = renderer()->style()->position() == FixedPosition ? parentRects.fixedClipRect() :
(renderer()->isPositioned() ? parentRects.posClipRect() :
parentRects.overflowClipRect());
@@ -3393,10 +3474,11 @@ IntRect RenderLayer::backgroundClipRect(const RenderLayer* rootLayer, bool tempo
}
void RenderLayer::calculateRects(const RenderLayer* rootLayer, const IntRect& paintDirtyRect, IntRect& layerBounds,
- IntRect& backgroundRect, IntRect& foregroundRect, IntRect& outlineRect, bool temporaryClipRects) const
+ IntRect& backgroundRect, IntRect& foregroundRect, IntRect& outlineRect, bool temporaryClipRects,
+ OverlayScrollbarSizeRelevancy relevancy) const
{
if (rootLayer != this && parent()) {
- backgroundRect = backgroundClipRect(rootLayer, temporaryClipRects);
+ backgroundRect = backgroundClipRect(rootLayer, temporaryClipRects, relevancy);
backgroundRect.intersect(paintDirtyRect);
} else
backgroundRect = paintDirtyRect;
@@ -3422,7 +3504,7 @@ void RenderLayer::calculateRects(const RenderLayer* rootLayer, const IntRect& pa
} else
#endif
if (renderer()->hasOverflowClip())
- foregroundRect.intersect(toRenderBox(renderer())->overflowClipRect(x, y));
+ foregroundRect.intersect(toRenderBox(renderer())->overflowClipRect(x, y, relevancy));
if (renderer()->hasClip()) {
// Clip applies to *us* as well, so go ahead and update the damageRect.
IntRect newPosClip = toRenderBox(renderer())->clipRect(x, y);
@@ -3629,6 +3711,21 @@ bool RenderLayer::hasCompositedMask() const
{
return m_backing && m_backing->hasMaskLayer();
}
+
+GraphicsLayer* RenderLayer::layerForHorizontalScrollbar() const
+{
+ return m_backing ? m_backing->layerForHorizontalScrollbar() : 0;
+}
+
+GraphicsLayer* RenderLayer::layerForVerticalScrollbar() const
+{
+ return m_backing ? m_backing->layerForVerticalScrollbar() : 0;
+}
+
+GraphicsLayer* RenderLayer::layerForScrollCorner() const
+{
+ return m_backing ? m_backing->layerForScrollCorner() : 0;
+}
#endif
bool RenderLayer::paintsWithTransform(PaintBehavior paintBehavior) const
@@ -3957,7 +4054,7 @@ bool RenderLayer::isSelfPaintingLayer() const
|| renderer()->isRenderIFrame();
}
-void RenderLayer::styleChanged(StyleDifference diff, const RenderStyle*)
+void RenderLayer::styleChanged(StyleDifference diff, const RenderStyle* oldStyle)
{
bool isNormalFlowOnly = shouldBeNormalFlowOnly();
if (isNormalFlowOnly != m_isNormalFlowOnly) {
@@ -4002,7 +4099,11 @@ void RenderLayer::styleChanged(StyleDifference diff, const RenderStyle*)
compositor()->setCompositingLayersNeedRebuild();
else if (m_backing)
m_backing->updateGraphicsLayerGeometry();
-
+ else if (oldStyle && oldStyle->overflowX() != renderer()->style()->overflowX()) {
+ if (stackingContext()->hasCompositingDescendant())
+ compositor()->setCompositingLayersNeedRebuild();
+ }
+
if (m_backing && diff >= StyleDifferenceRepaint)
m_backing->setContentsNeedDisplay();
#else
diff --git a/Source/WebCore/rendering/RenderLayer.h b/Source/WebCore/rendering/RenderLayer.h
index 17ba99e..4cf96ce 100644
--- a/Source/WebCore/rendering/RenderLayer.h
+++ b/Source/WebCore/rendering/RenderLayer.h
@@ -207,7 +207,7 @@ public:
void repaintIncludingNonCompositingDescendants(RenderBoxModelObject* repaintContainer);
#endif
- void styleChanged(StyleDifference, const RenderStyle*);
+ void styleChanged(StyleDifference, const RenderStyle* oldStyle);
RenderMarquee* marquee() const { return m_marquee; }
@@ -279,18 +279,22 @@ public:
PassRefPtr<Scrollbar> createScrollbar(ScrollbarOrientation);
void destroyScrollbar(ScrollbarOrientation);
- Scrollbar* horizontalScrollbar() const { return m_hBar.get(); }
- Scrollbar* verticalScrollbar() const { return m_vBar.get(); }
+ // ScrollableArea overrides
+ virtual Scrollbar* horizontalScrollbar() const { return m_hBar.get(); }
+ virtual Scrollbar* verticalScrollbar() const { return m_vBar.get(); }
- int verticalScrollbarWidth(OverlayScrollbarSizeRelevancy relevancy = IgnoreOverlayScrollbarSize) const;
- int horizontalScrollbarHeight(OverlayScrollbarSizeRelevancy relevancy = IgnoreOverlayScrollbarSize) const;
+ int verticalScrollbarWidth(OverlayScrollbarSizeRelevancy = IgnoreOverlayScrollbarSize) const;
+ int horizontalScrollbarHeight(OverlayScrollbarSizeRelevancy = IgnoreOverlayScrollbarSize) const;
bool hasOverflowControls() const;
+<<<<<<< HEAD
#if ENABLE(ANDROID_OVERFLOW_SCROLL)
bool hasOverflowScroll() const { return m_hasOverflowScroll; }
bool hasOverflowParent() const;
#endif
void positionOverflowControls(int tx, int ty);
+=======
+>>>>>>> WebKit.org at r84325
bool isPointInResizeControl(const IntPoint& absolutePoint) const;
bool hitTestOverflowControls(HitTestResult&, const IntPoint& localPoint);
IntSize offsetFromResizeCorner(const IntPoint& absolutePoint) const;
@@ -414,13 +418,14 @@ public:
// |rootLayer}. It also computes our background and foreground clip rects
// for painting/event handling.
void calculateRects(const RenderLayer* rootLayer, const IntRect& paintDirtyRect, IntRect& layerBounds,
- IntRect& backgroundRect, IntRect& foregroundRect, IntRect& outlineRect, bool temporaryClipRects = false) const;
+ IntRect& backgroundRect, IntRect& foregroundRect, IntRect& outlineRect, bool temporaryClipRects = false,
+ OverlayScrollbarSizeRelevancy = IgnoreOverlayScrollbarSize) const;
// Compute and cache clip rects computed with the given layer as the root
- void updateClipRects(const RenderLayer* rootLayer);
+ void updateClipRects(const RenderLayer* rootLayer, OverlayScrollbarSizeRelevancy = IgnoreOverlayScrollbarSize);
// Compute and return the clip rects. If useCached is true, will used previously computed clip rects on ancestors
// (rather than computing them all from scratch up the parent chain).
- void calculateClipRects(const RenderLayer* rootLayer, ClipRects&, bool useCached = false) const;
+ void calculateClipRects(const RenderLayer* rootLayer, ClipRects&, bool useCached = false, OverlayScrollbarSizeRelevancy = IgnoreOverlayScrollbarSize) const;
ClipRects* clipRects() const { return m_clipRects; }
IntRect childrenClipRect() const; // Returns the foreground clip rect of the layer in the document's coordinate space.
@@ -479,6 +484,9 @@ public:
RenderLayerBacking* backing() const { return m_backing.get(); }
RenderLayerBacking* ensureBacking();
void clearBacking();
+ virtual GraphicsLayer* layerForHorizontalScrollbar() const;
+ virtual GraphicsLayer* layerForVerticalScrollbar() const;
+ virtual GraphicsLayer* layerForScrollCorner() const;
#else
bool isComposited() const { return false; }
bool hasCompositedMask() const { return false; }
@@ -568,8 +576,10 @@ private:
virtual void setScrollOffset(const IntPoint&);
virtual int scrollPosition(Scrollbar*) const;
virtual void invalidateScrollbarRect(Scrollbar*, const IntRect&);
+ virtual void invalidateScrollCornerRect(const IntRect&);
virtual bool isActive() const;
- virtual bool scrollbarCornerPresent() const;
+ virtual bool isScrollCornerVisible() const;
+ virtual IntRect scrollCornerRect() const;
virtual IntRect convertFromScrollbarToContainingView(const Scrollbar*, const IntRect&) const;
virtual IntRect convertFromContainingViewToScrollbar(const Scrollbar*, const IntRect&) const;
virtual IntPoint convertFromScrollbarToContainingView(const Scrollbar*, const IntPoint&) const;
@@ -580,6 +590,9 @@ private:
virtual IntPoint currentMousePosition() const;
virtual bool shouldSuspendScrollAnimations() const;
+ // Rectangle encompassing the scroll corner and resizer rect.
+ IntRect scrollCornerAndResizerRect() const;
+
virtual void disconnectFromPage() { m_page = 0; }
// NOTE: This should only be called by the overriden setScrollOffset from ScrollableArea.
@@ -610,14 +623,15 @@ private:
bool paintingInsideReflection() const { return m_paintingInsideReflection; }
void setPaintingInsideReflection(bool b) { m_paintingInsideReflection = b; }
- void parentClipRects(const RenderLayer* rootLayer, ClipRects&, bool temporaryClipRects = false) const;
- IntRect backgroundClipRect(const RenderLayer* rootLayer, bool temporaryClipRects) const;
+ void parentClipRects(const RenderLayer* rootLayer, ClipRects&, bool temporaryClipRects = false, OverlayScrollbarSizeRelevancy = IgnoreOverlayScrollbarSize) const;
+ IntRect backgroundClipRect(const RenderLayer* rootLayer, bool temporaryClipRects, OverlayScrollbarSizeRelevancy = IgnoreOverlayScrollbarSize) const;
RenderLayer* enclosingTransformedAncestor() const;
// Convert a point in absolute coords into layer coords, taking transforms into account
IntPoint absoluteToContents(const IntPoint&) const;
+ void positionOverflowControls(int tx, int ty);
void updateScrollCornerStyle();
void updateResizerStyle();
@@ -730,7 +744,7 @@ protected:
bool m_has3DTransformedDescendant : 1; // Set on a stacking context layer that has 3D descendants anywhere
// in a preserves3D hierarchy. Hint to do 3D-aware hit testing.
#if USE(ACCELERATED_COMPOSITING)
- bool m_hasCompositingDescendant : 1;
+ bool m_hasCompositingDescendant : 1; // In the z-order tree.
bool m_mustOverlapCompositedLayers : 1;
#endif
diff --git a/Source/WebCore/rendering/RenderLayerBacking.cpp b/Source/WebCore/rendering/RenderLayerBacking.cpp
index 26a10dd..63b1d20 100644
--- a/Source/WebCore/rendering/RenderLayerBacking.cpp
+++ b/Source/WebCore/rendering/RenderLayerBacking.cpp
@@ -94,6 +94,7 @@ RenderLayerBacking::RenderLayerBacking(RenderLayer* layer)
RenderLayerBacking::~RenderLayerBacking()
{
updateClippingLayers(false, false);
+ updateOverflowControlsLayers(false, false, false);
updateForegroundLayer(false);
updateMaskLayer(false);
destroyGraphicsLayer();
@@ -225,9 +226,11 @@ void RenderLayerBacking::updateCompositedBounds()
void RenderLayerBacking::updateAfterWidgetResize()
{
- if (renderer()->isRenderIFrame()) {
- if (RenderLayerCompositor* innerCompositor = RenderLayerCompositor::iframeContentsCompositor(toRenderIFrame(renderer())))
- innerCompositor->frameViewDidChangeSize(contentsBox().location());
+ if (renderer()->isRenderPart()) {
+ if (RenderLayerCompositor* innerCompositor = RenderLayerCompositor::frameContentsCompositor(toRenderPart(renderer()))) {
+ innerCompositor->frameViewDidChangeSize();
+ innerCompositor->frameViewDidChangeLocation(contentsBox().location());
+ }
}
}
@@ -264,6 +267,12 @@ bool RenderLayerBacking::updateGraphicsLayerConfiguration()
if (updateClippingLayers(compositor->clippedByAncestor(m_owningLayer), compositor->clipsCompositingDescendants(m_owningLayer)))
layerConfigChanged = true;
+ if (updateOverflowControlsLayers(requiresHorizontalScrollbarLayer(), requiresVerticalScrollbarLayer(), requiresScrollCornerLayer()))
+ layerConfigChanged = true;
+
+ if (layerConfigChanged)
+ updateInternalHierarchy();
+
if (updateMaskLayer(renderer->hasMask()))
m_graphicsLayer->setMaskLayer(m_maskLayer.get());
@@ -298,8 +307,8 @@ bool RenderLayerBacking::updateGraphicsLayerConfiguration()
}
#endif
- if (renderer->isRenderIFrame())
- layerConfigChanged = RenderLayerCompositor::parentIFrameContentLayers(toRenderIFrame(renderer));
+ if (renderer->isRenderPart())
+ layerConfigChanged = RenderLayerCompositor::parentFrameContentLayers(toRenderPart(renderer));
return layerConfigChanged;
}
@@ -365,6 +374,7 @@ void RenderLayerBacking::updateGraphicsLayerGeometry()
// layer. Note that we call it with temporaryClipRects = true because normally when computing clip rects
// for a compositing layer, rootLayer is the layer itself.
IntRect parentClipRect = m_owningLayer->backgroundClipRect(compAncestor, true);
+ ASSERT(parentClipRect != PaintInfo::infiniteRect());
m_ancestorClippingLayer->setPosition(FloatPoint() + (parentClipRect.location() - graphicsLayerParentLocation));
m_ancestorClippingLayer->setSize(parentClipRect.size());
@@ -491,6 +501,22 @@ void RenderLayerBacking::updateInternalHierarchy()
if (m_clippingLayer) {
m_clippingLayer->removeFromParent();
m_graphicsLayer->addChild(m_clippingLayer.get());
+
+ // The clip for child layers does not include space for overflow controls, so they exist as
+ // siblings of the clipping layer if we have one. Normal children of this layer are set as
+ // children of the clipping layer.
+ if (m_layerForHorizontalScrollbar) {
+ m_layerForHorizontalScrollbar->removeFromParent();
+ m_graphicsLayer->addChild(m_layerForHorizontalScrollbar.get());
+ }
+ if (m_layerForVerticalScrollbar) {
+ m_layerForVerticalScrollbar->removeFromParent();
+ m_graphicsLayer->addChild(m_layerForVerticalScrollbar.get());
+ }
+ if (m_layerForScrollCorner) {
+ m_layerForScrollCorner->removeFromParent();
+ m_graphicsLayer->addChild(m_layerForScrollCorner.get());
+ }
}
}
@@ -534,8 +560,77 @@ bool RenderLayerBacking::updateClippingLayers(bool needsAncestorClip, bool needs
layersChanged = true;
}
- if (layersChanged)
- updateInternalHierarchy();
+ return layersChanged;
+}
+
+bool RenderLayerBacking::requiresHorizontalScrollbarLayer() const
+{
+#if !PLATFORM(CHROMIUM)
+ if (!m_owningLayer->hasOverlayScrollbars())
+ return false;
+#endif
+ return m_owningLayer->horizontalScrollbar();
+}
+
+bool RenderLayerBacking::requiresVerticalScrollbarLayer() const
+{
+#if !PLATFORM(CHROMIUM)
+ if (!m_owningLayer->hasOverlayScrollbars())
+ return false;
+#endif
+ return m_owningLayer->verticalScrollbar();
+}
+
+bool RenderLayerBacking::requiresScrollCornerLayer() const
+{
+#if !PLATFORM(CHROMIUM)
+ if (!m_owningLayer->hasOverlayScrollbars())
+ return false;
+#endif
+ return !m_owningLayer->scrollCornerAndResizerRect().isEmpty();
+}
+
+bool RenderLayerBacking::updateOverflowControlsLayers(bool needsHorizontalScrollbarLayer, bool needsVerticalScrollbarLayer, bool needsScrollCornerLayer)
+{
+ bool layersChanged = false;
+ if (needsHorizontalScrollbarLayer) {
+ if (!m_layerForHorizontalScrollbar) {
+ m_layerForHorizontalScrollbar = GraphicsLayer::create(this);
+#ifndef NDEBUG
+ m_layerForHorizontalScrollbar ->setName("horizontal scrollbar");
+#endif
+ layersChanged = true;
+ }
+ } else if (m_layerForHorizontalScrollbar) {
+ m_layerForHorizontalScrollbar.clear();
+ layersChanged = true;
+ }
+
+ if (needsVerticalScrollbarLayer) {
+ if (!m_layerForVerticalScrollbar) {
+ m_layerForVerticalScrollbar = GraphicsLayer::create(this);
+#ifndef NDEBUG
+ m_layerForVerticalScrollbar->setName("vertical scrollbar");
+#endif
+ layersChanged = true;
+ }
+ } else if (m_layerForVerticalScrollbar) {
+ m_layerForVerticalScrollbar.clear();
+ layersChanged = true;
+ }
+
+ if (needsScrollCornerLayer) {
+ if (!m_layerForScrollCorner) {
+ m_layerForScrollCorner = GraphicsLayer::create(this);
+#ifndef NDEBUG
+ m_layerForScrollCorner->setName("scroll corner");
+#endif
+ layersChanged = true;
+ }
+ } else if (m_layerForScrollCorner) {
+ m_layerForScrollCorner.clear();
+ layersChanged = true;
+ }
return layersChanged;
}
@@ -804,7 +899,7 @@ bool RenderLayerBacking::containsPaintedContent() const
if (renderer()->isVideo() && toRenderVideo(renderer())->shouldDisplayVideo())
return hasBoxDecorationsOrBackground(renderer());
#endif
-#if PLATFORM(MAC) && PLATFORM(CA) && !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD)
+#if PLATFORM(MAC) && USE(CA) && !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD)
#elif ENABLE(WEBGL) || ENABLE(ACCELERATED_2D_CANVAS)
if (isAcceleratedCanvas(renderer()))
return hasBoxDecorationsOrBackground(renderer());
@@ -933,7 +1028,7 @@ IntRect RenderLayerBacking::contentsBox() const
bool RenderLayerBacking::paintingGoesToWindow() const
{
if (m_owningLayer->isRootLayer())
- return compositor()->rootLayerAttachment() != RenderLayerCompositor::RootLayerAttachedViaEnclosingIframe;
+ return compositor()->rootLayerAttachment() != RenderLayerCompositor::RootLayerAttachedViaEnclosingFrame;
return false;
}
@@ -1110,9 +1205,9 @@ void RenderLayerBacking::paintIntoLayer(RenderLayer* rootLayer, GraphicsContext*
ASSERT(!m_owningLayer->m_usedTransparency);
}
-// Up-call from compositing layer drawing callback.
-void RenderLayerBacking::paintContents(const GraphicsLayer* graphicsLayer, GraphicsContext& context, GraphicsLayerPaintingPhase paintingPhase, const IntRect& clip)
+static void paintScrollbar(Scrollbar* scrollbar, GraphicsContext& context, const IntRect& clip)
{
+<<<<<<< HEAD
InspectorInstrumentationCookie cookie = InspectorInstrumentation::willPaint(m_owningLayer->renderer()->frame(), clip);
IntSize offset = graphicsLayer->offsetFromRenderer();
@@ -1130,11 +1225,54 @@ void RenderLayerBacking::paintContents(const GraphicsLayer* graphicsLayer, Graph
dirtyRect.setSize(clip.size());
#endif
dirtyRect.intersect(clipRect);
+=======
+ if (!scrollbar)
+ return;
+>>>>>>> WebKit.org at r84325
- // We have to use the same root as for hit testing, because both methods can compute and cache clipRects.
- paintIntoLayer(m_owningLayer, &context, dirtyRect, PaintBehaviorNormal, paintingPhase, renderer());
+ context.save();
+ const IntRect& scrollbarRect = scrollbar->frameRect();
+ context.translate(-scrollbarRect.x(), -scrollbarRect.y());
+ IntRect transformedClip = clip;
+ transformedClip.move(scrollbarRect.x(), scrollbarRect.y());
+ scrollbar->paint(&context, transformedClip);
+ context.restore();
+}
- InspectorInstrumentation::didPaint(cookie);
+// Up-call from compositing layer drawing callback.
+void RenderLayerBacking::paintContents(const GraphicsLayer* graphicsLayer, GraphicsContext& context, GraphicsLayerPaintingPhase paintingPhase, const IntRect& clip)
+{
+ if (graphicsLayer == m_graphicsLayer.get() || graphicsLayer == m_foregroundLayer.get() || graphicsLayer == m_maskLayer.get()) {
+ InspectorInstrumentationCookie cookie = InspectorInstrumentation::willPaint(m_owningLayer->renderer()->frame(), clip);
+
+ IntSize offset = graphicsLayer->offsetFromRenderer();
+ context.translate(-offset);
+
+ IntRect clipRect(clip);
+ clipRect.move(offset);
+
+ // The dirtyRect is in the coords of the painting root.
+ IntRect dirtyRect = compositedBounds();
+ dirtyRect.intersect(clipRect);
+
+ // We have to use the same root as for hit testing, because both methods can compute and cache clipRects.
+ paintIntoLayer(m_owningLayer, &context, dirtyRect, PaintBehaviorNormal, paintingPhase, renderer());
+
+ InspectorInstrumentation::didPaint(cookie);
+ } else if (graphicsLayer == layerForHorizontalScrollbar()) {
+ paintScrollbar(m_owningLayer->horizontalScrollbar(), context, clip);
+ } else if (graphicsLayer == layerForVerticalScrollbar()) {
+ paintScrollbar(m_owningLayer->verticalScrollbar(), context, clip);
+ } else if (graphicsLayer == layerForScrollCorner()) {
+ const IntRect& scrollCornerAndResizer = m_owningLayer->scrollCornerAndResizerRect();
+ context.save();
+ context.translate(-scrollCornerAndResizer.x(), -scrollCornerAndResizer.y());
+ IntRect transformedClip = clip;
+ transformedClip.move(scrollCornerAndResizer.x(), scrollCornerAndResizer.y());
+ m_owningLayer->paintScrollCorner(&context, 0, 0, transformedClip);
+ m_owningLayer->paintResizer(&context, 0, 0, transformedClip);
+ context.restore();
+ }
}
bool RenderLayerBacking::showDebugBorders() const
diff --git a/Source/WebCore/rendering/RenderLayerBacking.h b/Source/WebCore/rendering/RenderLayerBacking.h
index 8f0927d..f1b8972 100644
--- a/Source/WebCore/rendering/RenderLayerBacking.h
+++ b/Source/WebCore/rendering/RenderLayerBacking.h
@@ -69,7 +69,6 @@ public:
// Update graphics layer position and bounds.
void updateGraphicsLayerGeometry(); // make private
// Update contents and clipping structure.
- void updateInternalHierarchy(); // make private
void updateDrawsContent();
GraphicsLayer* graphicsLayer() const { return m_graphicsLayer.get(); }
@@ -139,6 +138,10 @@ public:
void updateContentsScale(float);
+ GraphicsLayer* layerForHorizontalScrollbar() const { return m_layerForHorizontalScrollbar.get(); }
+ GraphicsLayer* layerForVerticalScrollbar() const { return m_layerForVerticalScrollbar.get(); }
+ GraphicsLayer* layerForScrollCorner() const { return m_layerForScrollCorner.get(); }
+
private:
void createGraphicsLayer();
void destroyGraphicsLayer();
@@ -146,9 +149,14 @@ private:
RenderBoxModelObject* renderer() const { return m_owningLayer->renderer(); }
RenderLayerCompositor* compositor() const { return m_owningLayer->compositor(); }
+ void updateInternalHierarchy();
bool updateClippingLayers(bool needsAncestorClip, bool needsDescendantClip);
+ bool updateOverflowControlsLayers(bool needsHorizontalScrollbarLayer, bool needsVerticalScrollbarLayer, bool needsScrollCornerLayer);
bool updateForegroundLayer(bool needsForegroundLayer);
bool updateMaskLayer(bool needsMaskLayer);
+ bool requiresHorizontalScrollbarLayer() const;
+ bool requiresVerticalScrollbarLayer() const;
+ bool requiresScrollCornerLayer() const;
GraphicsLayerPaintingPhase paintingPhaseForPrimaryLayer() const;
@@ -196,6 +204,10 @@ private:
OwnPtr<GraphicsLayer> m_clippingLayer; // only used if we have clipping on a stacking context, with compositing children
OwnPtr<GraphicsLayer> m_maskLayer; // only used if we have a mask
+ OwnPtr<GraphicsLayer> m_layerForHorizontalScrollbar;
+ OwnPtr<GraphicsLayer> m_layerForVerticalScrollbar;
+ OwnPtr<GraphicsLayer> m_layerForScrollCorner;
+
IntRect m_compositedBounds;
bool m_artificiallyInflatedBounds; // bounds had to be made non-zero to make transform-origin work
diff --git a/Source/WebCore/rendering/RenderLayerCompositor.cpp b/Source/WebCore/rendering/RenderLayerCompositor.cpp
index 6542ffd..03ae579 100644
--- a/Source/WebCore/rendering/RenderLayerCompositor.cpp
+++ b/Source/WebCore/rendering/RenderLayerCompositor.cpp
@@ -253,7 +253,7 @@ void RenderLayerCompositor::updateCompositingLayers(CompositingUpdateType update
bool checkForHierarchyUpdate = m_compositingDependsOnGeometry;
bool needGeometryUpdate = false;
-
+
switch (updateType) {
case CompositingUpdateAfterLayoutOrStyleChange:
case CompositingUpdateOnPaitingOrHitTest:
@@ -354,7 +354,7 @@ bool RenderLayerCompositor::updateBacking(RenderLayer* layer, CompositingChangeR
layer->ensureBacking();
-#if PLATFORM(MAC) && PLATFORM(CA)
+#if PLATFORM(MAC) && USE(CA)
if (m_renderView->document()->settings()->acceleratedDrawingEnabled())
layer->backing()->graphicsLayer()->setAcceleratesDrawing(true);
else if (layer->renderer()->isCanvas()) {
@@ -399,8 +399,8 @@ bool RenderLayerCompositor::updateBacking(RenderLayer* layer, CompositingChangeR
}
#endif
- if (layerChanged && layer->renderer()->isRenderIFrame()) {
- RenderLayerCompositor* innerCompositor = iframeContentsCompositor(toRenderIFrame(layer->renderer()));
+ if (layerChanged && layer->renderer()->isRenderPart()) {
+ RenderLayerCompositor* innerCompositor = frameContentsCompositor(toRenderPart(layer->renderer()));
if (innerCompositor && innerCompositor->inCompositingMode())
innerCompositor->updateRootLayerAttachment();
}
@@ -915,9 +915,28 @@ void RenderLayerCompositor::rebuildCompositingLayerTree(RenderLayer* layer, cons
if (layerBacking) {
bool parented = false;
- if (layer->renderer()->isRenderIFrame())
- parented = parentIFrameContentLayers(toRenderIFrame(layer->renderer()));
-
+ if (layer->renderer()->isRenderPart())
+ parented = parentFrameContentLayers(toRenderPart(layer->renderer()));
+
+ // If the layer has a clipping layer the overflow controls layers will be siblings of the clipping layer.
+ // Otherwise, the overflow control layers are normal children.
+ if (!layerBacking->hasClippingLayer()) {
+ if (GraphicsLayer* overflowControlLayer = layerBacking->layerForHorizontalScrollbar()) {
+ overflowControlLayer->removeFromParent();
+ layerChildren.append(overflowControlLayer);
+ }
+
+ if (GraphicsLayer* overflowControlLayer = layerBacking->layerForVerticalScrollbar()) {
+ overflowControlLayer->removeFromParent();
+ layerChildren.append(overflowControlLayer);
+ }
+
+ if (GraphicsLayer* overflowControlLayer = layerBacking->layerForScrollCorner()) {
+ overflowControlLayer->removeFromParent();
+ layerChildren.append(overflowControlLayer);
+ }
+ }
+
if (!parented)
layerBacking->parentForSublayers()->setChildren(layerChildren);
@@ -932,15 +951,21 @@ void RenderLayerCompositor::rebuildCompositingLayerTree(RenderLayer* layer, cons
}
}
-void RenderLayerCompositor::frameViewDidChangeSize(const IntPoint& contentsOffset)
+void RenderLayerCompositor::frameViewDidChangeLocation(const IntPoint& contentsOffset)
+{
+ if (m_overflowControlsHostLayer)
+ m_overflowControlsHostLayer->setPosition(contentsOffset);
+}
+
+void RenderLayerCompositor::frameViewDidChangeSize()
{
if (m_clipLayer) {
FrameView* frameView = m_renderView->frameView();
- m_clipLayer->setPosition(contentsOffset);
- m_clipLayer->setSize(FloatSize(frameView->layoutWidth(), frameView->layoutHeight()));
+ m_clipLayer->setSize(frameView->visibleContentRect(false /* exclude scrollbars */).size());
IntPoint scrollPosition = frameView->scrollPosition();
m_scrollLayer->setPosition(FloatPoint(-scrollPosition.x(), -scrollPosition.y()));
+ updateOverflowControlsLayers();
}
}
@@ -963,9 +988,12 @@ String RenderLayerCompositor::layerTreeAsText(bool showDebugInfo)
return m_rootPlatformLayer->layerTreeAsText(showDebugInfo ? LayerTreeAsTextDebug : LayerTreeAsTextBehaviorNormal);
}
-RenderLayerCompositor* RenderLayerCompositor::iframeContentsCompositor(RenderIFrame* renderer)
+RenderLayerCompositor* RenderLayerCompositor::frameContentsCompositor(RenderPart* renderer)
{
- HTMLIFrameElement* element = static_cast<HTMLIFrameElement*>(renderer->node());
+ if (!renderer->node()->isFrameOwnerElement())
+ return 0;
+
+ HTMLFrameOwnerElement* element = static_cast<HTMLFrameOwnerElement*>(renderer->node());
if (Document* contentDocument = element->contentDocument()) {
if (RenderView* view = contentDocument->renderView())
return view->compositor();
@@ -973,10 +1001,10 @@ RenderLayerCompositor* RenderLayerCompositor::iframeContentsCompositor(RenderIFr
return 0;
}
-bool RenderLayerCompositor::parentIFrameContentLayers(RenderIFrame* renderer)
+bool RenderLayerCompositor::parentFrameContentLayers(RenderPart* renderer)
{
- RenderLayerCompositor* innerCompositor = iframeContentsCompositor(renderer);
- if (!innerCompositor || !innerCompositor->inCompositingMode() || innerCompositor->rootLayerAttachment() != RootLayerAttachedViaEnclosingIframe)
+ RenderLayerCompositor* innerCompositor = frameContentsCompositor(renderer);
+ if (!innerCompositor || !innerCompositor->inCompositingMode() || innerCompositor->rootLayerAttachment() != RootLayerAttachedViaEnclosingFrame)
return false;
RenderLayer* layer = renderer->layer();
@@ -1146,7 +1174,9 @@ RenderLayer* RenderLayerCompositor::rootRenderLayer() const
GraphicsLayer* RenderLayerCompositor::rootPlatformLayer() const
{
- return m_clipLayer ? m_clipLayer.get() : m_rootPlatformLayer.get();
+ if (m_overflowControlsHostLayer)
+ return m_overflowControlsHostLayer.get();
+ return m_rootPlatformLayer.get();
}
void RenderLayerCompositor::didMoveOnscreen()
@@ -1154,7 +1184,7 @@ void RenderLayerCompositor::didMoveOnscreen()
if (!inCompositingMode() || m_rootLayerAttachment != RootLayerUnattached)
return;
- RootLayerAttachment attachment = shouldPropagateCompositingToEnclosingIFrame() ? RootLayerAttachedViaEnclosingIframe : RootLayerAttachedViaChromeClient;
+ RootLayerAttachment attachment = shouldPropagateCompositingToEnclosingFrame() ? RootLayerAttachedViaEnclosingFrame : RootLayerAttachedViaChromeClient;
attachRootPlatformLayer(attachment);
}
@@ -1174,7 +1204,7 @@ void RenderLayerCompositor::updateRootLayerPosition()
}
if (m_clipLayer) {
FrameView* frameView = m_renderView->frameView();
- m_clipLayer->setSize(FloatSize(frameView->layoutWidth(), frameView->layoutHeight()));
+ m_clipLayer->setSize(frameView->visibleContentRect(false /* exclude scrollbars */).size());
}
}
@@ -1192,43 +1222,52 @@ bool RenderLayerCompositor::has3DContent() const
return layerHas3DContent(rootRenderLayer());
}
-bool RenderLayerCompositor::allowsIndependentlyCompositedIFrames(const FrameView* view)
+bool RenderLayerCompositor::allowsIndependentlyCompositedFrames(const FrameView* view)
{
#if PLATFORM(MAC)
- // iframes are only independently composited in Mac pre-WebKit2.
+ // frames are only independently composited in Mac pre-WebKit2.
return view->platformWidget();
#endif
return false;
}
-bool RenderLayerCompositor::shouldPropagateCompositingToEnclosingIFrame() const
+bool RenderLayerCompositor::shouldPropagateCompositingToEnclosingFrame() const
{
+<<<<<<< HEAD
#if PLATFORM(ANDROID)
if (enclosingIFrameElement() && !allowsIndependentlyCompositedIFrames(m_renderView->frameView()))
return true;
#endif
// Parent document content needs to be able to render on top of a composited iframe, so correct behavior
+=======
+ // Parent document content needs to be able to render on top of a composited frame, so correct behavior
+>>>>>>> WebKit.org at r84325
// is to have the parent document become composited too. However, this can cause problems on platforms that
// use native views for frames (like Mac), so disable that behavior on those platforms for now.
- HTMLFrameOwnerElement* ownerElement = enclosingIFrameElement();
+ HTMLFrameOwnerElement* ownerElement = enclosingFrameElement();
RenderObject* renderer = ownerElement ? ownerElement->renderer() : 0;
- if (!renderer || !renderer->isRenderIFrame())
+
+ // If we are the top-level frame, don't propagate.
+ if (!ownerElement)
return false;
- if (!allowsIndependentlyCompositedIFrames(m_renderView->frameView()))
+ if (!allowsIndependentlyCompositedFrames(m_renderView->frameView()))
return true;
- // On Mac, only propagate compositing if the iframe is overlapped in the parent
+ if (!renderer || !renderer->isRenderPart())
+ return false;
+
+ // On Mac, only propagate compositing if the frame is overlapped in the parent
// document, or the parent is already compositing, or the main frame is scaled.
Frame* frame = m_renderView->frameView()->frame();
Page* page = frame ? frame->page() : 0;
if (page->mainFrame()->pageScaleFactor() != 1)
return true;
- RenderIFrame* iframeRenderer = toRenderIFrame(renderer);
- if (iframeRenderer->widget()) {
- ASSERT(iframeRenderer->widget()->isFrameView());
- FrameView* view = static_cast<FrameView*>(iframeRenderer->widget());
+ RenderPart* frameRenderer = toRenderPart(renderer);
+ if (frameRenderer->widget()) {
+ ASSERT(frameRenderer->widget()->isFrameView());
+ FrameView* view = static_cast<FrameView*>(frameRenderer->widget());
if (view->isOverlappedIncludingAncestors() || view->hasCompositingAncestor())
return true;
}
@@ -1236,10 +1275,10 @@ bool RenderLayerCompositor::shouldPropagateCompositingToEnclosingIFrame() const
return false;
}
-HTMLFrameOwnerElement* RenderLayerCompositor::enclosingIFrameElement() const
+HTMLFrameOwnerElement* RenderLayerCompositor::enclosingFrameElement() const
{
if (HTMLFrameOwnerElement* ownerElement = m_renderView->document()->ownerElement())
- return ownerElement->hasTagName(iframeTag) ? ownerElement : 0;
+ return (ownerElement->hasTagName(iframeTag) || ownerElement->hasTagName(frameTag) || ownerElement->hasTagName(objectTag)) ? ownerElement : 0;
return 0;
}
@@ -1290,7 +1329,7 @@ bool RenderLayerCompositor::requiresCompositingLayer(const RenderLayer* layer) c
|| requiresCompositingForVideo(renderer)
|| requiresCompositingForCanvas(renderer)
|| requiresCompositingForPlugin(renderer)
- || requiresCompositingForIFrame(renderer)
+ || requiresCompositingForFrame(renderer)
|| (canRender3DTransforms() && renderer->style()->backfaceVisibility() == BackfaceVisibilityHidden)
|| clipsCompositingDescendants(layer)
|| requiresCompositingForAnimation(renderer)
@@ -1423,28 +1462,28 @@ bool RenderLayerCompositor::requiresCompositingForPlugin(RenderObject* renderer)
return contentBox.height() * contentBox.width() > 1;
}
-bool RenderLayerCompositor::requiresCompositingForIFrame(RenderObject* renderer) const
+bool RenderLayerCompositor::requiresCompositingForFrame(RenderObject* renderer) const
{
- if (!renderer->isRenderIFrame())
+ if (!renderer->isRenderPart())
return false;
- RenderIFrame* iframeRenderer = toRenderIFrame(renderer);
+ RenderPart* frameRenderer = toRenderPart(renderer);
- if (!iframeRenderer->requiresAcceleratedCompositing())
+ if (!frameRenderer->requiresAcceleratedCompositing())
return false;
m_compositingDependsOnGeometry = true;
- RenderLayerCompositor* innerCompositor = iframeContentsCompositor(iframeRenderer);
- if (!innerCompositor->shouldPropagateCompositingToEnclosingIFrame())
+ RenderLayerCompositor* innerCompositor = frameContentsCompositor(frameRenderer);
+ if (!innerCompositor || !innerCompositor->shouldPropagateCompositingToEnclosingFrame())
return false;
// If we can't reliably know the size of the iframe yet, don't change compositing state.
if (renderer->needsLayout())
- return iframeRenderer->hasLayer() && iframeRenderer->layer()->isComposited();
+ return frameRenderer->hasLayer() && frameRenderer->layer()->isComposited();
// Don't go into compositing mode if height or width are zero.
- IntRect contentBox = iframeRenderer->contentBoxRect();
+ IntRect contentBox = frameRenderer->contentBoxRect();
return contentBox.height() * contentBox.width() > 0;
}
@@ -1487,12 +1526,119 @@ bool RenderLayerCompositor::requiresScrollLayer(RootLayerAttachment attachment)
{
// We need to handle our own scrolling if we're:
return !m_renderView->frameView()->platformWidget() // viewless (i.e. non-Mac, or Mac in WebKit2)
- || attachment == RootLayerAttachedViaEnclosingIframe; // a composited iframe on Mac
+ || attachment == RootLayerAttachedViaEnclosingFrame; // a composited frame on Mac
+}
+
+static void paintScrollbar(Scrollbar* scrollbar, GraphicsContext& context, const IntRect& clip)
+{
+ if (!scrollbar)
+ return;
+
+ context.save();
+ const IntRect& scrollbarRect = scrollbar->frameRect();
+ context.translate(-scrollbarRect.x(), -scrollbarRect.y());
+ IntRect transformedClip = clip;
+ transformedClip.move(scrollbarRect.x(), scrollbarRect.y());
+ scrollbar->paint(&context, transformedClip);
+ context.restore();
+}
+
+void RenderLayerCompositor::paintContents(const GraphicsLayer* graphicsLayer, GraphicsContext& context, GraphicsLayerPaintingPhase, const IntRect& clip)
+{
+ if (graphicsLayer == layerForHorizontalScrollbar())
+ paintScrollbar(m_renderView->frameView()->horizontalScrollbar(), context, clip);
+ else if (graphicsLayer == layerForVerticalScrollbar())
+ paintScrollbar(m_renderView->frameView()->verticalScrollbar(), context, clip);
+ else if (graphicsLayer == layerForScrollCorner()) {
+ const IntRect& scrollCorner = m_renderView->frameView()->scrollCornerRect();
+ context.save();
+ context.translate(-scrollCorner.x(), -scrollCorner.y());
+ IntRect transformedClip = clip;
+ transformedClip.move(scrollCorner.x(), scrollCorner.y());
+ m_renderView->frameView()->paintScrollCorner(&context, transformedClip);
+ context.restore();
+ }
+}
+
+static bool shouldCompositeOverflowControls(ScrollView* view)
+{
+ if (view->platformWidget())
+ return false;
+#if !PLATFORM(CHROMIUM)
+ if (!view->hasOverlayScrollbars())
+ return false;
+#endif
+ return true;
+}
+
+bool RenderLayerCompositor::requiresHorizontalScrollbarLayer() const
+{
+ ScrollView* view = m_renderView->frameView();
+ return shouldCompositeOverflowControls(view) && view->horizontalScrollbar();
+}
+
+bool RenderLayerCompositor::requiresVerticalScrollbarLayer() const
+{
+ ScrollView* view = m_renderView->frameView();
+ return shouldCompositeOverflowControls(view) && view->verticalScrollbar();
+}
+
+bool RenderLayerCompositor::requiresScrollCornerLayer() const
+{
+ ScrollView* view = m_renderView->frameView();
+ return shouldCompositeOverflowControls(view) && view->isScrollCornerVisible();
+}
+
+void RenderLayerCompositor::updateOverflowControlsLayers()
+{
+ bool layersChanged = false;
+
+ if (requiresHorizontalScrollbarLayer()) {
+ m_layerForHorizontalScrollbar = GraphicsLayer::create(this);
+#ifndef NDEBUG
+ m_layerForHorizontalScrollbar->setName("horizontal scrollbar");
+#endif
+ m_overflowControlsHostLayer->addChild(m_layerForHorizontalScrollbar.get());
+ layersChanged = true;
+ } else if (m_layerForHorizontalScrollbar) {
+ m_layerForHorizontalScrollbar->removeFromParent();
+ m_layerForHorizontalScrollbar = 0;
+ layersChanged = true;
+ }
+
+ if (requiresVerticalScrollbarLayer()) {
+ m_layerForVerticalScrollbar = GraphicsLayer::create(this);
+#ifndef NDEBUG
+ m_layerForVerticalScrollbar->setName("vertical scrollbar");
+#endif
+ m_overflowControlsHostLayer->addChild(m_layerForVerticalScrollbar.get());
+ layersChanged = true;
+ } else if (m_layerForVerticalScrollbar) {
+ m_layerForVerticalScrollbar->removeFromParent();
+ m_layerForVerticalScrollbar = 0;
+ layersChanged = true;
+ }
+
+ if (requiresScrollCornerLayer()) {
+ m_layerForScrollCorner = GraphicsLayer::create(this);
+#ifndef NDEBUG
+ m_layerForScrollCorner->setName("scroll corner");
+#endif
+ m_overflowControlsHostLayer->addChild(m_layerForScrollCorner.get());
+ layersChanged = true;
+ } else if (m_layerForScrollCorner) {
+ m_layerForScrollCorner->removeFromParent();
+ m_layerForScrollCorner = 0;
+ layersChanged = true;
+ }
+
+ if (layersChanged)
+ m_renderView->frameView()->positionScrollbarLayers();
}
void RenderLayerCompositor::ensureRootPlatformLayer()
{
- RootLayerAttachment expectedAttachment = shouldPropagateCompositingToEnclosingIFrame() ? RootLayerAttachedViaEnclosingIframe : RootLayerAttachedViaChromeClient;
+ RootLayerAttachment expectedAttachment = shouldPropagateCompositingToEnclosingFrame() ? RootLayerAttachedViaEnclosingFrame : RootLayerAttachedViaChromeClient;
if (expectedAttachment == m_rootLayerAttachment)
return;
@@ -1509,8 +1655,16 @@ void RenderLayerCompositor::ensureRootPlatformLayer()
}
if (requiresScrollLayer(expectedAttachment)) {
- if (!m_clipLayer) {
+ if (!m_overflowControlsHostLayer) {
ASSERT(!m_scrollLayer);
+ ASSERT(!m_clipLayer);
+
+ // Create a layer to host the clipping layer and the overflow controls layers.
+ m_overflowControlsHostLayer = GraphicsLayer::create(0);
+#ifndef NDEBUG
+ m_overflowControlsHostLayer->setName("overflow controls host");
+#endif
+
// Create a clipping layer if this is an iframe
m_clipLayer = GraphicsLayer::create(this);
#ifndef NDEBUG
@@ -1522,20 +1676,19 @@ void RenderLayerCompositor::ensureRootPlatformLayer()
#ifndef NDEBUG
m_scrollLayer->setName("iframe scrolling");
#endif
+
// Hook them up
+ m_overflowControlsHostLayer->addChild(m_clipLayer.get());
m_clipLayer->addChild(m_scrollLayer.get());
m_scrollLayer->addChild(m_rootPlatformLayer.get());
-
+
frameViewDidChangeSize();
frameViewDidScroll(m_renderView->frameView()->scrollPosition());
}
} else {
- if (m_clipLayer) {
- m_clipLayer->removeAllChildren();
- m_clipLayer->removeFromParent();
+ if (m_overflowControlsHostLayer) {
+ m_overflowControlsHostLayer = 0;
m_clipLayer = 0;
-
- m_scrollLayer->removeAllChildren();
m_scrollLayer = 0;
}
}
@@ -1553,11 +1706,29 @@ void RenderLayerCompositor::destroyRootPlatformLayer()
return;
detachRootPlatformLayer();
- if (m_clipLayer) {
- m_clipLayer->removeAllChildren();
+
+ if (m_layerForHorizontalScrollbar) {
+ m_layerForHorizontalScrollbar->removeFromParent();
+ m_layerForHorizontalScrollbar = 0;
+ if (Scrollbar* horizontalScrollbar = m_renderView->frameView()->verticalScrollbar())
+ m_renderView->frameView()->invalidateScrollbar(horizontalScrollbar, IntRect(IntPoint(0, 0), horizontalScrollbar->frameRect().size()));
+ }
+
+ if (m_layerForVerticalScrollbar) {
+ m_layerForVerticalScrollbar->removeFromParent();
+ m_layerForVerticalScrollbar = 0;
+ if (Scrollbar* verticalScrollbar = m_renderView->frameView()->verticalScrollbar())
+ m_renderView->frameView()->invalidateScrollbar(verticalScrollbar, IntRect(IntPoint(0, 0), verticalScrollbar->frameRect().size()));
+ }
+
+ if (m_layerForScrollCorner) {
+ m_layerForScrollCorner = 0;
+ m_renderView->frameView()->invalidateScrollCorner();
+ }
+
+ if (m_overflowControlsHostLayer) {
+ m_overflowControlsHostLayer = 0;
m_clipLayer = 0;
-
- m_scrollLayer->removeAllChildren();
m_scrollLayer = 0;
}
ASSERT(!m_scrollLayer);
@@ -1582,9 +1753,9 @@ void RenderLayerCompositor::attachRootPlatformLayer(RootLayerAttachment attachme
page->chrome()->client()->attachRootGraphicsLayer(frame, rootPlatformLayer());
break;
}
- case RootLayerAttachedViaEnclosingIframe: {
+ case RootLayerAttachedViaEnclosingFrame: {
// The layer will get hooked up via RenderLayerBacking::updateGraphicsLayerConfiguration()
- // for the iframe's renderer in the parent document.
+ // for the frame's renderer in the parent document.
scheduleNeedsStyleRecalc(m_renderView->document()->ownerElement());
break;
}
@@ -1600,29 +1771,29 @@ void RenderLayerCompositor::detachRootPlatformLayer()
return;
switch (m_rootLayerAttachment) {
- case RootLayerAttachedViaEnclosingIframe: {
- // The layer will get unhooked up via RenderLayerBacking::updateGraphicsLayerConfiguration()
- // for the iframe's renderer in the parent document.
- if (m_clipLayer)
- m_clipLayer->removeFromParent();
- else
- m_rootPlatformLayer->removeFromParent();
-
- if (HTMLFrameOwnerElement* ownerElement = m_renderView->document()->ownerElement())
- scheduleNeedsStyleRecalc(ownerElement);
- break;
- }
- case RootLayerAttachedViaChromeClient: {
- Frame* frame = m_renderView->frameView()->frame();
- Page* page = frame ? frame->page() : 0;
- if (!page)
- return;
+ case RootLayerAttachedViaEnclosingFrame: {
+ // The layer will get unhooked up via RenderLayerBacking::updateGraphicsLayerConfiguration()
+ // for the frame's renderer in the parent document.
+ if (m_overflowControlsHostLayer)
+ m_overflowControlsHostLayer->removeFromParent();
+ else
+ m_rootPlatformLayer->removeFromParent();
+
+ if (HTMLFrameOwnerElement* ownerElement = m_renderView->document()->ownerElement())
+ scheduleNeedsStyleRecalc(ownerElement);
+ break;
+ }
+ case RootLayerAttachedViaChromeClient: {
+ Frame* frame = m_renderView->frameView()->frame();
+ Page* page = frame ? frame->page() : 0;
+ if (!page)
+ return;
- page->chrome()->client()->attachRootGraphicsLayer(frame, 0);
- }
+ page->chrome()->client()->attachRootGraphicsLayer(frame, 0);
+ }
+ break;
+ case RootLayerUnattached:
break;
- case RootLayerUnattached:
- break;
}
m_rootLayerAttachment = RootLayerUnattached;
diff --git a/Source/WebCore/rendering/RenderLayerCompositor.h b/Source/WebCore/rendering/RenderLayerCompositor.h
index c3deb3f..0315050 100644
--- a/Source/WebCore/rendering/RenderLayerCompositor.h
+++ b/Source/WebCore/rendering/RenderLayerCompositor.h
@@ -36,7 +36,7 @@ namespace WebCore {
class GraphicsLayer;
class RenderEmbeddedObject;
-class RenderIFrame;
+class RenderPart;
#if ENABLE(VIDEO)
class RenderVideo;
#endif
@@ -138,7 +138,7 @@ public:
enum RootLayerAttachment {
RootLayerUnattached,
RootLayerAttachedViaChromeClient,
- RootLayerAttachedViaEnclosingIframe
+ RootLayerAttachedViaEnclosingFrame
};
RootLayerAttachment rootLayerAttachment() const { return m_rootLayerAttachment; }
@@ -161,18 +161,18 @@ public:
// Most platforms connect compositing layer trees between iframes and their parent document.
// Some (currently just Mac) allow iframes to do their own compositing.
- static bool allowsIndependentlyCompositedIFrames(const FrameView*);
- bool shouldPropagateCompositingToEnclosingIFrame() const;
+ static bool allowsIndependentlyCompositedFrames(const FrameView*);
+ bool shouldPropagateCompositingToEnclosingFrame() const;
- // FIXME: This should be a RenderIFrame*
- HTMLFrameOwnerElement* enclosingIFrameElement() const;
+ HTMLFrameOwnerElement* enclosingFrameElement() const;
- static RenderLayerCompositor* iframeContentsCompositor(RenderIFrame*);
+ static RenderLayerCompositor* frameContentsCompositor(RenderPart*);
// Return true if the layers changed.
- static bool parentIFrameContentLayers(RenderIFrame*);
+ static bool parentFrameContentLayers(RenderPart*);
// Update the geometry of the layers used for clipping and scrolling in frames.
- void frameViewDidChangeSize(const IntPoint& contentsOffset = IntPoint());
+ void frameViewDidChangeLocation(const IntPoint& contentsOffset);
+ void frameViewDidChangeSize();
void frameViewDidScroll(const IntPoint& = IntPoint());
String layerTreeAsText(bool showDebugInfo = false);
@@ -184,11 +184,15 @@ public:
void updateContentsScale(float, RenderLayer* = 0);
+ GraphicsLayer* layerForHorizontalScrollbar() const { return m_layerForHorizontalScrollbar.get(); }
+ GraphicsLayer* layerForVerticalScrollbar() const { return m_layerForVerticalScrollbar.get(); }
+ GraphicsLayer* layerForScrollCorner() const { return m_layerForScrollCorner.get(); }
+
private:
// GraphicsLayerClient Implementation
virtual void notifyAnimationStarted(const GraphicsLayer*, double) { }
virtual void notifySyncRequired(const GraphicsLayer*) { scheduleLayerFlush(); }
- virtual void paintContents(const GraphicsLayer*, GraphicsContext&, GraphicsLayerPaintingPhase, const IntRect&) { }
+ virtual void paintContents(const GraphicsLayer*, GraphicsContext&, GraphicsLayerPaintingPhase, const IntRect&);
// These calls return false always. They are saying that the layers associated with this client
// (the clipLayer and scrollLayer) should never show debugging info.
@@ -236,7 +240,9 @@ private:
void detachRootPlatformLayer();
void rootLayerAttachmentChanged();
-
+
+ void updateOverflowControlsLayers();
+
void scheduleNeedsStyleRecalc(Element*);
void notifyIFramesOfCompositingChange();
@@ -246,7 +252,7 @@ private:
bool requiresCompositingForVideo(RenderObject*) const;
bool requiresCompositingForCanvas(RenderObject*) const;
bool requiresCompositingForPlugin(RenderObject*) const;
- bool requiresCompositingForIFrame(RenderObject*) const;
+ bool requiresCompositingForFrame(RenderObject*) const;
bool requiresCompositingWhenDescendantsAreCompositing(RenderObject*) const;
bool requiresCompositingForFullScreen(RenderObject*) const;
@@ -256,7 +262,10 @@ private:
#endif
bool requiresScrollLayer(RootLayerAttachment) const;
-
+ bool requiresHorizontalScrollbarLayer() const;
+ bool requiresVerticalScrollbarLayer() const;
+ bool requiresScrollCornerLayer() const;
+
private:
RenderView* m_renderView;
OwnPtr<GraphicsLayer> m_rootPlatformLayer;
@@ -284,7 +293,14 @@ private:
// Enclosing clipping layer for iframe content
OwnPtr<GraphicsLayer> m_clipLayer;
OwnPtr<GraphicsLayer> m_scrollLayer;
-
+
+ // Enclosing layer for overflow controls and the clipping layer
+ OwnPtr<GraphicsLayer> m_overflowControlsHostLayer;
+
+ // Layers for overflow controls
+ OwnPtr<GraphicsLayer> m_layerForHorizontalScrollbar;
+ OwnPtr<GraphicsLayer> m_layerForVerticalScrollbar;
+ OwnPtr<GraphicsLayer> m_layerForScrollCorner;
#if PROFILE_LAYER_REBUILD
int m_rootLayerUpdateCount;
#endif
diff --git a/Source/WebCore/rendering/RenderLineBoxList.cpp b/Source/WebCore/rendering/RenderLineBoxList.cpp
index 9a40baf..32f133c 100644
--- a/Source/WebCore/rendering/RenderLineBoxList.cpp
+++ b/Source/WebCore/rendering/RenderLineBoxList.cpp
@@ -177,10 +177,12 @@ 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()->logicalTopVisualOverflow();
+ RootInlineBox* firstRootBox = firstLineBox()->root();
+ RootInlineBox* lastRootBox = lastLineBox()->root();
+ int firstLineTop = firstLineBox()->logicalTopVisualOverflow(firstRootBox->lineTop());
if (usePrintRect && !firstLineBox()->parent())
firstLineTop = min(firstLineTop, firstLineBox()->root()->lineTop());
- int lastLineBottom = lastLineBox()->logicalBottomVisualOverflow();
+ int lastLineBottom = lastLineBox()->logicalBottomVisualOverflow(lastRootBox->lineBottom());
if (usePrintRect && !lastLineBox()->parent())
lastLineBottom = max(lastLineBottom, lastLineBox()->root()->lineBottom());
int logicalTop = firstLineTop - outlineSize;
@@ -191,8 +193,9 @@ 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->logicalTopVisualOverflow(), box->root()->selectionTop()) - renderer->maximalOutlineSize(paintInfo.phase);
- int logicalBottom = box->logicalBottomVisualOverflow() + renderer->maximalOutlineSize(paintInfo.phase);
+ RootInlineBox* root = box->root();
+ int logicalTop = min(box->logicalTopVisualOverflow(root->lineTop()), root->selectionTop()) - renderer->maximalOutlineSize(paintInfo.phase);
+ int logicalBottom = box->logicalBottomVisualOverflow(root->lineBottom()) + renderer->maximalOutlineSize(paintInfo.phase);
return rangeIntersectsRect(renderer, logicalTop, logicalBottom, paintInfo.rect, tx, ty);
}
@@ -231,17 +234,18 @@ 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->minYVisualOverflow();
- int bottomForPaginationCheck = curr->maxYVisualOverflow();
+ RootInlineBox* root = curr->root();
+ int topForPaginationCheck = curr->logicalTopVisualOverflow(root->lineTop());
+ int bottomForPaginationCheck = curr->logicalLeftVisualOverflow();
if (!curr->parent()) {
// We're a root box. Use lineTop and lineBottom as well here.
- topForPaginationCheck = min(topForPaginationCheck, curr->root()->lineTop());
- bottomForPaginationCheck = max(bottomForPaginationCheck, curr->root()->lineBottom());
+ topForPaginationCheck = min(topForPaginationCheck, root->lineTop());
+ bottomForPaginationCheck = max(bottomForPaginationCheck, root->lineBottom());
}
if (bottomForPaginationCheck - topForPaginationCheck <= v->printRect().height()) {
if (ty + bottomForPaginationCheck > v->printRect().maxY()) {
if (RootInlineBox* nextRootBox = curr->root()->nextRootBox())
- bottomForPaginationCheck = min(bottomForPaginationCheck, min(nextRootBox->minYVisualOverflow(), nextRootBox->lineTop()));
+ bottomForPaginationCheck = min(bottomForPaginationCheck, min(nextRootBox->logicalTopVisualOverflow(), nextRootBox->lineTop()));
}
if (ty + bottomForPaginationCheck > v->printRect().maxY()) {
if (ty + topForPaginationCheck < v->truncatedAt())
@@ -253,8 +257,10 @@ void RenderLineBoxList::paint(RenderBoxModelObject* renderer, PaintInfo& paintIn
}
}
- if (lineIntersectsDirtyRect(renderer, curr, info, tx, ty))
- curr->paint(info, tx, ty);
+ if (lineIntersectsDirtyRect(renderer, curr, info, tx, ty)) {
+ RootInlineBox* root = curr->root();
+ curr->paint(info, tx, ty, root->lineTop(), root->lineBottom());
+ }
}
if (info.phase == PaintPhaseOutline || info.phase == PaintPhaseSelfOutline || info.phase == PaintPhaseChildOutlines) {
@@ -293,8 +299,9 @@ 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->logicalTopVisualOverflow(), curr->logicalBottomVisualOverflow(), rect, tx, ty)) {
- bool inside = curr->nodeAtPoint(request, result, x, y, tx, ty);
+ RootInlineBox* root = curr->root();
+ if (rangeIntersectsRect(renderer, curr->logicalTopVisualOverflow(root->lineTop()), curr->logicalBottomVisualOverflow(root->lineBottom()), rect, tx, ty)) {
+ bool inside = curr->nodeAtPoint(request, result, x, y, tx, ty, root->lineTop(), root->lineBottom());
if (inside) {
renderer->updateHitTestResult(result, IntPoint(x - tx, y - ty));
return true;
@@ -310,8 +317,11 @@ void RenderLineBoxList::dirtyLinesFromChangedChild(RenderObject* container, Rend
if (!container->parent() || (container->isRenderBlock() && (container->selfNeedsLayout() || !container->isBlockFlow())))
return;
+ RenderInline* inlineContainer = container->isRenderInline() ? toRenderInline(container) : 0;
+ InlineBox* firstBox = inlineContainer ? inlineContainer->firstLineBoxIncludingCulling() : firstLineBox();
+
// If we have no first line box, then just bail early.
- if (!firstLineBox()) {
+ if (!firstBox) {
// For an empty inline, go ahead and propagate the check up to our parent, unless the parent
// is already dirty.
if (container->isInline() && !container->parent()->selfNeedsLayout())
@@ -337,16 +347,16 @@ void RenderLineBoxList::dirtyLinesFromChangedChild(RenderObject* container, Rend
if (textBox)
box = textBox->root();
} else if (curr->isRenderInline()) {
- InlineFlowBox* flowBox = toRenderInline(curr)->lastLineBox();
- if (flowBox)
- box = flowBox->root();
+ InlineBox* lastSiblingBox = toRenderInline(curr)->lastLineBoxIncludingCulling();
+ if (lastSiblingBox)
+ box = lastSiblingBox->root();
}
if (box)
break;
}
if (!box)
- box = firstLineBox()->root();
+ box = firstBox->root();
// If we found a line box, then dirty it.
if (box) {
diff --git a/Source/WebCore/rendering/RenderListBox.cpp b/Source/WebCore/rendering/RenderListBox.cpp
index ab3a832..d7798d5 100644
--- a/Source/WebCore/rendering/RenderListBox.cpp
+++ b/Source/WebCore/rendering/RenderListBox.cpp
@@ -273,14 +273,28 @@ void RenderListBox::paintObject(PaintInfo& paintInfo, int tx, int ty)
// Paint the children.
RenderBlock::paintObject(paintInfo, tx, ty);
- if (paintInfo.phase == PaintPhaseBlockBackground)
- paintScrollbar(paintInfo, tx, ty);
- else if (paintInfo.phase == PaintPhaseChildBlockBackground || paintInfo.phase == PaintPhaseChildBlockBackgrounds) {
+ switch (paintInfo.phase) {
+ // Depending on whether we have overlay scrollbars they
+ // get rendered in the foreground or background phases
+ case PaintPhaseForeground:
+ if (m_vBar->isOverlayScrollbar())
+ paintScrollbar(paintInfo, tx, ty);
+ break;
+ case PaintPhaseBlockBackground:
+ if (!m_vBar->isOverlayScrollbar())
+ paintScrollbar(paintInfo, tx, ty);
+ break;
+ case PaintPhaseChildBlockBackground:
+ case PaintPhaseChildBlockBackgrounds: {
int index = m_indexOffset;
while (index < listItemsSize && index <= m_indexOffset + numVisibleItems()) {
paintItemBackground(paintInfo, tx, ty, index);
index++;
}
+ break;
+ }
+ default:
+ break;
}
}
@@ -599,7 +613,7 @@ void RenderListBox::scrollTo(int newOffset)
m_indexOffset = newOffset;
repaint();
- node()->document()->eventQueue()->enqueueScrollEvent(node(), EventQueue::ScrollEventElementTarget);
+ node()->document()->eventQueue()->enqueueOrDispatchScrollEvent(node(), EventQueue::ScrollEventElementTarget);
}
int RenderListBox::itemHeight() const
diff --git a/Source/WebCore/rendering/RenderListBox.h b/Source/WebCore/rendering/RenderListBox.h
index 0e2cfd6..d2de4a5 100644
--- a/Source/WebCore/rendering/RenderListBox.h
+++ b/Source/WebCore/rendering/RenderListBox.h
@@ -53,6 +53,8 @@ public:
int scrollToward(const IntPoint&); // Returns the new index or -1 if no scroll occurred
+ int size() const;
+
private:
virtual const char* renderName() const { return "RenderListBox"; }
@@ -102,7 +104,9 @@ private:
virtual void setScrollOffset(const IntPoint&);
virtual void invalidateScrollbarRect(Scrollbar*, const IntRect&);
virtual bool isActive() const;
- virtual bool scrollbarCornerPresent() const { return false; } // We don't support resize on list boxes yet. If we did this would have to change.
+ virtual bool isScrollCornerVisible() const { return false; } // We don't support resize on list boxes yet. If we did these would have to change.
+ virtual IntRect scrollCornerRect() const { return IntRect(); }
+ virtual void invalidateScrollCornerRect(const IntRect&) { }
virtual IntRect convertFromScrollbarToContainingView(const Scrollbar*, const IntRect&) const;
virtual IntRect convertFromContainingViewToScrollbar(const Scrollbar*, const IntRect&) const;
virtual IntPoint convertFromScrollbarToContainingView(const Scrollbar*, const IntPoint&) const;
@@ -125,7 +129,6 @@ private:
int itemHeight() const;
void valueChanged(unsigned listIndex);
- int size() const;
int numVisibleItems() const;
int numItems() const;
int listHeight() const;
diff --git a/Source/WebCore/rendering/RenderListItem.cpp b/Source/WebCore/rendering/RenderListItem.cpp
index 5cfb522..eaf68e6 100644
--- a/Source/WebCore/rendering/RenderListItem.cpp
+++ b/Source/WebCore/rendering/RenderListItem.cpp
@@ -264,6 +264,10 @@ void RenderListItem::positionListMarker()
int markerLogicalLeft;
RootInlineBox* root = m_marker->inlineBoxWrapper()->root();
bool hitSelfPaintingLayer = false;
+
+ RootInlineBox* rootBox = m_marker->inlineBoxWrapper()->root();
+ int lineTop = rootBox->lineTop();
+ int lineBottom = rootBox->lineBottom();
// FIXME: Need to account for relative positioning in the layout overflow.
if (style()->isLeftToRightDirection()) {
@@ -271,21 +275,21 @@ void RenderListItem::positionListMarker()
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()) {
- IntRect newLogicalVisualOverflowRect = box->logicalVisualOverflowRect();
- IntRect newLogicalLayoutOverflowRect = box->logicalLayoutOverflowRect();
+ IntRect newLogicalVisualOverflowRect = box->logicalVisualOverflowRect(lineTop, lineBottom);
+ IntRect newLogicalLayoutOverflowRect = box->logicalLayoutOverflowRect(lineTop, lineBottom);
if (markerLogicalLeft < newLogicalVisualOverflowRect.x() && !hitSelfPaintingLayer) {
+ newLogicalVisualOverflowRect.setWidth(newLogicalVisualOverflowRect.maxX() - markerLogicalLeft);
newLogicalVisualOverflowRect.setX(markerLogicalLeft);
- newLogicalVisualOverflowRect.setWidth(box->logicalRightVisualOverflow() - newLogicalVisualOverflowRect.x());
if (box == root)
adjustOverflow = true;
}
if (markerLogicalLeft < newLogicalLayoutOverflowRect.x()) {
+ newLogicalLayoutOverflowRect.setWidth(newLogicalLayoutOverflowRect.maxX() - markerLogicalLeft);
newLogicalLayoutOverflowRect.setX(markerLogicalLeft);
- newLogicalLayoutOverflowRect.setWidth(box->logicalRightLayoutOverflow() - newLogicalLayoutOverflowRect.x());
if (box == root)
adjustOverflow = true;
}
- box->setOverflowFromLogicalRects(newLogicalLayoutOverflowRect, newLogicalVisualOverflowRect);
+ box->setOverflowFromLogicalRects(newLogicalLayoutOverflowRect, newLogicalVisualOverflowRect, lineTop, lineBottom);
if (box->boxModelObject()->hasSelfPaintingLayer())
hitSelfPaintingLayer = true;
}
@@ -295,19 +299,19 @@ 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()) {
- IntRect newLogicalVisualOverflowRect = box->logicalVisualOverflowRect();
- IntRect newLogicalLayoutOverflowRect = box->logicalLayoutOverflowRect();
+ IntRect newLogicalVisualOverflowRect = box->logicalVisualOverflowRect(lineTop, lineBottom);
+ IntRect newLogicalLayoutOverflowRect = box->logicalLayoutOverflowRect(lineTop, lineBottom);
if (markerLogicalLeft + m_marker->logicalWidth() > newLogicalVisualOverflowRect.maxX() && !hitSelfPaintingLayer) {
- newLogicalVisualOverflowRect.setWidth(markerLogicalLeft + m_marker->logicalWidth() - box->logicalLeftVisualOverflow());
+ newLogicalVisualOverflowRect.setWidth(markerLogicalLeft + m_marker->logicalWidth() - newLogicalVisualOverflowRect.x());
if (box == root)
adjustOverflow = true;
}
if (markerLogicalLeft + m_marker->logicalWidth() > newLogicalLayoutOverflowRect.maxX()) {
- newLogicalLayoutOverflowRect.setWidth(markerLogicalLeft + m_marker->logicalWidth() - box->logicalLeftLayoutOverflow());
+ newLogicalLayoutOverflowRect.setWidth(markerLogicalLeft + m_marker->logicalWidth() - newLogicalLayoutOverflowRect.x());
if (box == root)
adjustOverflow = true;
}
- box->setOverflowFromLogicalRects(newLogicalLayoutOverflowRect, newLogicalVisualOverflowRect);
+ box->setOverflowFromLogicalRects(newLogicalLayoutOverflowRect, newLogicalVisualOverflowRect, lineTop, lineBottom);
if (box->boxModelObject()->hasSelfPaintingLayer())
hitSelfPaintingLayer = true;
diff --git a/Source/WebCore/rendering/RenderMedia.cpp b/Source/WebCore/rendering/RenderMedia.cpp
index 69d71ec..3f56865 100644
--- a/Source/WebCore/rendering/RenderMedia.cpp
+++ b/Source/WebCore/rendering/RenderMedia.cpp
@@ -29,22 +29,18 @@
#include "RenderMedia.h"
#include "HTMLMediaElement.h"
-#include "MediaControlElements.h"
-#include "MediaControls.h"
#include "RenderView.h"
namespace WebCore {
RenderMedia::RenderMedia(HTMLMediaElement* video)
: RenderImage(video)
- , m_controls(new MediaControls(video))
{
setImageResource(RenderImageResource::create());
}
RenderMedia::RenderMedia(HTMLMediaElement* video, const IntSize& intrinsicSize)
: RenderImage(video)
- , m_controls(new MediaControls(video))
{
setImageResource(RenderImageResource::create());
setIntrinsicSize(intrinsicSize);
@@ -54,32 +50,21 @@ RenderMedia::~RenderMedia()
{
}
-void RenderMedia::destroy()
-{
- m_controls->destroy();
- RenderImage::destroy();
-}
-
HTMLMediaElement* RenderMedia::mediaElement() const
{
return static_cast<HTMLMediaElement*>(node());
}
-void RenderMedia::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
-{
- RenderImage::styleDidChange(diff, oldStyle);
- m_controls->updateStyle();
-}
-
void RenderMedia::layout()
{
IntSize oldSize = contentBoxRect().size();
RenderImage::layout();
- RenderBox* controlsRenderer = m_controls->renderBox();
+ RenderBox* controlsRenderer = toRenderBox(m_children.firstChild());
if (!controlsRenderer)
return;
+
IntSize newSize = contentBoxRect().size();
if (newSize == oldSize && !controlsRenderer->needsLayout())
return;
@@ -99,11 +84,6 @@ void RenderMedia::layout()
statePusher.pop();
}
-void RenderMedia::updateFromElement()
-{
- m_controls->update();
-}
-
} // namespace WebCore
#endif
diff --git a/Source/WebCore/rendering/RenderMedia.h b/Source/WebCore/rendering/RenderMedia.h
index 7658ef6..78e36c4 100644
--- a/Source/WebCore/rendering/RenderMedia.h
+++ b/Source/WebCore/rendering/RenderMedia.h
@@ -33,7 +33,6 @@
namespace WebCore {
class HTMLMediaElement;
-class MediaControls;
class RenderMedia : public RenderImage {
public:
@@ -45,9 +44,6 @@ public:
RenderObjectChildList* children() { return &m_children; }
HTMLMediaElement* mediaElement() const;
- MediaControls* controls() const;
-
- virtual void updateFromElement();
protected:
virtual void layout();
@@ -56,18 +52,12 @@ private:
virtual RenderObjectChildList* virtualChildren() { return children(); }
virtual const RenderObjectChildList* virtualChildren() const { return children(); }
- virtual void destroy();
-
virtual const char* renderName() const { return "RenderMedia"; }
virtual bool isMedia() const { return true; }
virtual bool isImage() const { return false; }
-
- virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
-
virtual bool requiresForcedStyleRecalcPropagation() const { return true; }
- OwnPtr<MediaControls> m_controls;
RenderObjectChildList m_children;
};
@@ -77,11 +67,6 @@ inline RenderMedia* toRenderMedia(RenderObject* object)
return static_cast<RenderMedia*>(object);
}
-inline MediaControls* RenderMedia::controls() const
-{
- return m_controls.get();
-}
-
// This will catch anyone doing an unnecessary cast.
void toRenderMedia(const RenderMedia*);
diff --git a/Source/WebCore/rendering/RenderMediaControls.cpp b/Source/WebCore/rendering/RenderMediaControls.cpp
index dd58cd2..928b5b8 100644
--- a/Source/WebCore/rendering/RenderMediaControls.cpp
+++ b/Source/WebCore/rendering/RenderMediaControls.cpp
@@ -32,6 +32,7 @@
#include "GraphicsContext.h"
#include "HTMLMediaElement.h"
#include "HTMLNames.h"
+#include "PaintInfo.h"
#include "RenderTheme.h"
// FIXME: Unify more of the code for Mac and Win.
diff --git a/Source/WebCore/rendering/RenderMediaControlsChromium.cpp b/Source/WebCore/rendering/RenderMediaControlsChromium.cpp
index 71fca91..40ee9b0 100644
--- a/Source/WebCore/rendering/RenderMediaControlsChromium.cpp
+++ b/Source/WebCore/rendering/RenderMediaControlsChromium.cpp
@@ -242,28 +242,6 @@ static bool paintMediaTimelineContainer(RenderObject* object, const PaintInfo& p
return true;
}
-bool RenderMediaControlsChromium::shouldRenderMediaControlPart(ControlPart part, Element* e)
-{
- UNUSED_PARAM(e);
-
- switch (part) {
- case MediaMuteButtonPart:
- case MediaPlayButtonPart:
- case MediaSliderPart:
- case MediaSliderThumbPart:
- case MediaVolumeSliderContainerPart:
- case MediaVolumeSliderPart:
- case MediaVolumeSliderThumbPart:
- case MediaControlsBackgroundPart:
- case MediaCurrentTimePart:
- case MediaTimeRemainingPart:
- return true;
- default:
- ;
- }
- return false;
-}
-
bool RenderMediaControlsChromium::paintMediaControlsPart(MediaControlElementType part, RenderObject* object, const PaintInfo& paintInfo, const IntRect& rect)
{
switch (part) {
diff --git a/Source/WebCore/rendering/RenderMediaControlsChromium.h b/Source/WebCore/rendering/RenderMediaControlsChromium.h
index 060a9d4..895ac43 100644
--- a/Source/WebCore/rendering/RenderMediaControlsChromium.h
+++ b/Source/WebCore/rendering/RenderMediaControlsChromium.h
@@ -36,7 +36,6 @@ namespace WebCore {
class HTMLMediaElement;
class RenderMediaControlsChromium {
public:
- static bool shouldRenderMediaControlPart(ControlPart, Element*);
static bool paintMediaControlsPart(MediaControlElementType, RenderObject*, const PaintInfo&, const IntRect&);
static void adjustMediaSliderThumbSize(RenderObject*);
};
diff --git a/Source/WebCore/rendering/RenderMeter.cpp b/Source/WebCore/rendering/RenderMeter.cpp
index f3ada0b..683bcc4 100644
--- a/Source/WebCore/rendering/RenderMeter.cpp
+++ b/Source/WebCore/rendering/RenderMeter.cpp
@@ -35,98 +35,13 @@ namespace WebCore {
using namespace HTMLNames;
-class MeterPartElement : public ShadowBlockElement {
-public:
- static PassRefPtr<MeterPartElement> createForPart(HTMLElement*, PseudoId);
-
- void hide();
- void restoreVisibility();
-
- virtual void updateStyleForPart(PseudoId);
-
-private:
- MeterPartElement(HTMLElement*);
- void saveVisibility();
-
- EVisibility m_originalVisibility;
-};
-
-MeterPartElement::MeterPartElement(HTMLElement* shadowParent)
- : ShadowBlockElement(shadowParent)
-{
-}
-
-PassRefPtr<MeterPartElement> MeterPartElement::createForPart(HTMLElement* shadowParent, PseudoId pseudoId)
-{
- RefPtr<MeterPartElement> ret = adoptRef(new MeterPartElement(shadowParent));
- ret->initAsPart(pseudoId);
- ret->saveVisibility();
- return ret;
-}
-
-void MeterPartElement::hide()
-{
- if (renderer())
- renderer()->style()->setVisibility(HIDDEN);
-}
-
-void MeterPartElement::restoreVisibility()
-{
- if (renderer())
- renderer()->style()->setVisibility(m_originalVisibility);
-}
-
-void MeterPartElement::updateStyleForPart(PseudoId pseudoId)
-{
- if (renderer()->style()->styleType() == pseudoId)
- return;
-
- ShadowBlockElement::updateStyleForPart(pseudoId);
- saveVisibility();
-}
-
-void MeterPartElement::saveVisibility()
-{
- m_originalVisibility = renderer()->style()->visibility();
-}
-
RenderMeter::RenderMeter(HTMLMeterElement* element)
- : RenderIndicator(element)
+ : RenderBlock(element)
{
}
RenderMeter::~RenderMeter()
{
- if (shadowAttached()) {
- m_verticalValuePart->detach();
- m_verticalBarPart->detach();
- m_horizontalValuePart->detach();
- m_horizontalBarPart->detach();
- }
-}
-
-PassRefPtr<MeterPartElement> RenderMeter::createPart(PseudoId pseudoId)
-{
- RefPtr<MeterPartElement> element = MeterPartElement::createForPart(toHTMLElement(node()), pseudoId);
- if (element->renderer())
- addChild(element->renderer());
- return element;
-}
-
-void RenderMeter::updateFromElement()
-{
- if (!shadowAttached()) {
- m_horizontalBarPart = createPart(barPseudoId(HORIZONTAL));
- m_horizontalValuePart = createPart(valuePseudoId(HORIZONTAL));
- m_verticalBarPart = createPart(barPseudoId(VERTICAL));
- m_verticalValuePart = createPart(valuePseudoId(VERTICAL));
- }
-
- m_horizontalBarPart->updateStyleForPart(barPseudoId(HORIZONTAL));
- m_horizontalValuePart->updateStyleForPart(valuePseudoId(HORIZONTAL));
- m_verticalBarPart->updateStyleForPart(barPseudoId(VERTICAL));
- m_verticalValuePart->updateStyleForPart(valuePseudoId(VERTICAL));
- RenderIndicator::updateFromElement();
}
void RenderMeter::computeLogicalWidth()
@@ -141,119 +56,9 @@ void RenderMeter::computeLogicalHeight()
setHeight(theme()->meterSizeForBounds(this, frameRect()).height());
}
-void RenderMeter::layoutParts()
-{
- m_horizontalBarPart->layoutAsPart(barPartRect());
- m_horizontalValuePart->layoutAsPart(valuePartRect(HORIZONTAL));
- m_verticalBarPart->layoutAsPart(barPartRect());
- m_verticalValuePart->layoutAsPart(valuePartRect(VERTICAL));
-
- if (shouldHaveParts()) {
- if (HORIZONTAL == orientation()) {
- m_verticalBarPart->hide();
- m_verticalValuePart->hide();
- m_horizontalBarPart->restoreVisibility();
- m_horizontalValuePart->restoreVisibility();
- } else {
- m_verticalBarPart->restoreVisibility();
- m_verticalValuePart->restoreVisibility();
- m_horizontalBarPart->hide();
- m_horizontalValuePart->hide();
- }
- } else {
- m_verticalBarPart->hide();
- m_verticalValuePart->hide();
- m_horizontalBarPart->hide();
- m_horizontalValuePart->hide();
- }
-}
-
-bool RenderMeter::shouldHaveParts() const
-{
- EBoxOrient currentOrientation = orientation();
- bool hasTheme = theme()->supportsMeter(style()->appearance(), HORIZONTAL == currentOrientation);
- if (!hasTheme)
- return true;
- bool shadowsHaveStyle = ShadowBlockElement::partShouldHaveStyle(this, barPseudoId(currentOrientation)) || ShadowBlockElement::partShouldHaveStyle(this, valuePseudoId(currentOrientation));
- if (shadowsHaveStyle)
- return true;
- return false;
-}
-
double RenderMeter::valueRatio() const
{
- HTMLMeterElement* element = static_cast<HTMLMeterElement*>(node());
- double min = element->min();
- double max = element->max();
- double value = element->value();
-
- if (max <= min)
- return 0;
- return (value - min) / (max - min);
-}
-
-IntRect RenderMeter::barPartRect() const
-{
- return IntRect(borderLeft() + paddingLeft(), borderTop() + paddingTop(), lround(width() - borderLeft() - paddingLeft() - borderRight() - paddingRight()), height() - borderTop() - paddingTop() - borderBottom() - paddingBottom());
-}
-
-IntRect RenderMeter::valuePartRect(EBoxOrient asOrientation) const
-{
- IntRect rect = barPartRect();
-
- if (HORIZONTAL == asOrientation) {
- int width = static_cast<int>(rect.width()*valueRatio());
- if (!style()->isLeftToRightDirection()) {
- rect.setX(rect.x() + (rect.width() - width));
- rect.setWidth(width);
- } else
- rect.setWidth(width);
- } else {
- int height = static_cast<int>(rect.height()*valueRatio());
- rect.setY(rect.y() + (rect.height() - height));
- rect.setHeight(height);
- }
-
- return rect;
-}
-
-EBoxOrient RenderMeter::orientation() const
-{
- IntRect rect = barPartRect();
- return rect.height() <= rect.width() ? HORIZONTAL : VERTICAL;
-}
-
-PseudoId RenderMeter::valuePseudoId(EBoxOrient asOrientation) const
-{
- HTMLMeterElement* element = static_cast<HTMLMeterElement*>(node());
-
- if (HORIZONTAL == asOrientation) {
- switch (element->gaugeRegion()) {
- case HTMLMeterElement::GaugeRegionOptimum:
- return METER_HORIZONTAL_OPTIMUM;
- case HTMLMeterElement::GaugeRegionSuboptimal:
- return METER_HORIZONTAL_SUBOPTIMAL;
- case HTMLMeterElement::GaugeRegionEvenLessGood:
- return METER_HORIZONTAL_EVEN_LESS_GOOD;
- }
- } else {
- switch (element->gaugeRegion()) {
- case HTMLMeterElement::GaugeRegionOptimum:
- return METER_VERTICAL_OPTIMUM;
- case HTMLMeterElement::GaugeRegionSuboptimal:
- return METER_VERTICAL_SUBOPTIMAL;
- case HTMLMeterElement::GaugeRegionEvenLessGood:
- return METER_VERTICAL_EVEN_LESS_GOOD;
- }
- }
-
- ASSERT_NOT_REACHED();
- return NOPSEUDO;
-}
-
-PseudoId RenderMeter::barPseudoId(EBoxOrient asOrientation) const
-{
- return HORIZONTAL == asOrientation ? METER_HORIZONTAL_BAR : METER_VERTICAL_BAR;
+ return static_cast<HTMLMeterElement*>(node())->valueRatio();
}
} // namespace WebCore
diff --git a/Source/WebCore/rendering/RenderMeter.h b/Source/WebCore/rendering/RenderMeter.h
index 2f5f5f5..12ab6ba 100644
--- a/Source/WebCore/rendering/RenderMeter.h
+++ b/Source/WebCore/rendering/RenderMeter.h
@@ -23,44 +23,28 @@
#if ENABLE(METER_TAG)
#include "RenderBlock.h"
-#include "RenderIndicator.h"
#include "RenderWidget.h"
namespace WebCore {
class HTMLMeterElement;
-class MeterPartElement;
-class RenderMeter : public RenderIndicator {
+class RenderMeter : public RenderBlock {
public:
RenderMeter(HTMLMeterElement*);
virtual ~RenderMeter();
private:
- virtual const char* renderName() const { return "RenderMeter"; }
- virtual bool isMeter() const { return true; }
- virtual void updateFromElement();
virtual void computeLogicalWidth();
virtual void computeLogicalHeight();
- virtual void layoutParts();
-
- bool shadowAttached() const { return m_horizontalBarPart; }
- IntRect valuePartRect(EBoxOrient) const;
- PseudoId valuePseudoId(EBoxOrient) const;
- IntRect barPartRect() const;
- PseudoId barPseudoId(EBoxOrient) const;
- EBoxOrient orientation() const;
+ virtual const char* renderName() const { return "RenderMeter"; }
+ virtual bool isMeter() const { return true; }
+ virtual bool requiresForcedStyleRecalcPropagation() const { return true; }
+ virtual bool canHaveChildren() const { return false; }
double valueRatio() const;
- bool shouldHaveParts() const;
- PassRefPtr<MeterPartElement> createPart(PseudoId);
-
- RefPtr<MeterPartElement> m_horizontalBarPart;
- RefPtr<MeterPartElement> m_horizontalValuePart;
- RefPtr<MeterPartElement> m_verticalBarPart;
- RefPtr<MeterPartElement> m_verticalValuePart;
};
inline RenderMeter* toRenderMeter(RenderObject* object)
diff --git a/Source/WebCore/rendering/RenderObject.cpp b/Source/WebCore/rendering/RenderObject.cpp
index 7cc6f1f..b050539 100644
--- a/Source/WebCore/rendering/RenderObject.cpp
+++ b/Source/WebCore/rendering/RenderObject.cpp
@@ -707,10 +707,10 @@ bool RenderObject::mustRepaintBackgroundOrBorder() const
}
void RenderObject::drawLineForBoxSide(GraphicsContext* graphicsContext, int x1, int y1, int x2, int y2,
- BoxSide s, Color c, EBorderStyle style,
- int adjbw1, int adjbw2)
+ BoxSide side, Color color, EBorderStyle style,
+ int adjacentWidth1, int adjacentWidth2, bool antialias)
{
- int width = (s == BSTop || s == BSBottom ? y2 - y1 : x2 - x1);
+ int width = (side == BSTop || side == BSBottom ? y2 - y1 : x2 - x1);
if (style == DOUBLE && width < 3)
style = SOLID;
@@ -721,12 +721,15 @@ void RenderObject::drawLineForBoxSide(GraphicsContext* graphicsContext, int x1,
return;
case DOTTED:
case DASHED:
- graphicsContext->setStrokeColor(c, m_style->colorSpace());
+ graphicsContext->setStrokeColor(color, m_style->colorSpace());
graphicsContext->setStrokeThickness(width);
graphicsContext->setStrokeStyle(style == DASHED ? DashedStroke : DottedStroke);
- if (width > 0)
- switch (s) {
+ if (width > 0) {
+ bool wasAntialiased = graphicsContext->shouldAntialias();
+ graphicsContext->setShouldAntialias(antialias);
+
+ switch (side) {
case BSBottom:
case BSTop:
graphicsContext->drawLine(IntPoint(x1, (y1 + y2) / 2), IntPoint(x2, (y1 + y2) / 2));
@@ -736,14 +739,20 @@ void RenderObject::drawLineForBoxSide(GraphicsContext* graphicsContext, int x1,
graphicsContext->drawLine(IntPoint((x1 + x2) / 2, y1), IntPoint((x1 + x2) / 2, y2));
break;
}
+ graphicsContext->setShouldAntialias(wasAntialiased);
+ }
break;
case DOUBLE: {
int third = (width + 1) / 3;
- if (adjbw1 == 0 && adjbw2 == 0) {
+ if (adjacentWidth1 == 0 && adjacentWidth2 == 0) {
graphicsContext->setStrokeStyle(NoStroke);
- graphicsContext->setFillColor(c, m_style->colorSpace());
- switch (s) {
+ graphicsContext->setFillColor(color, m_style->colorSpace());
+
+ bool wasAntialiased = graphicsContext->shouldAntialias();
+ graphicsContext->setShouldAntialias(antialias);
+
+ switch (side) {
case BSTop:
case BSBottom:
graphicsContext->drawRect(IntRect(x1, y1, x2 - x1, third));
@@ -758,42 +767,44 @@ void RenderObject::drawLineForBoxSide(GraphicsContext* graphicsContext, int x1,
graphicsContext->drawRect(IntRect(x2 - third, y1 + 1, third, y2 - y1 - 1));
break;
}
+
+ graphicsContext->setShouldAntialias(wasAntialiased);
} else {
- int adjbw1bigthird = ((adjbw1 > 0) ? adjbw1 + 1 : adjbw1 - 1) / 3;
- int adjbw2bigthird = ((adjbw2 > 0) ? adjbw2 + 1 : adjbw2 - 1) / 3;
+ int adjacent1BigThird = ((adjacentWidth1 > 0) ? adjacentWidth1 + 1 : adjacentWidth1 - 1) / 3;
+ int adjacent2BigThird = ((adjacentWidth2 > 0) ? adjacentWidth2 + 1 : adjacentWidth2 - 1) / 3;
- switch (s) {
+ switch (side) {
case BSTop:
- drawLineForBoxSide(graphicsContext, x1 + max((-adjbw1 * 2 + 1) / 3, 0),
- y1, x2 - max((-adjbw2 * 2 + 1) / 3, 0), y1 + third,
- s, c, SOLID, adjbw1bigthird, adjbw2bigthird);
- drawLineForBoxSide(graphicsContext, x1 + max((adjbw1 * 2 + 1) / 3, 0),
- y2 - third, x2 - max((adjbw2 * 2 + 1) / 3, 0), y2,
- s, c, SOLID, adjbw1bigthird, adjbw2bigthird);
+ drawLineForBoxSide(graphicsContext, x1 + max((-adjacentWidth1 * 2 + 1) / 3, 0),
+ y1, x2 - max((-adjacentWidth2 * 2 + 1) / 3, 0), y1 + third,
+ side, color, SOLID, adjacent1BigThird, adjacent2BigThird, antialias);
+ drawLineForBoxSide(graphicsContext, x1 + max((adjacentWidth1 * 2 + 1) / 3, 0),
+ y2 - third, x2 - max((adjacentWidth2 * 2 + 1) / 3, 0), y2,
+ side, color, SOLID, adjacent1BigThird, adjacent2BigThird, antialias);
break;
case BSLeft:
- drawLineForBoxSide(graphicsContext, x1, y1 + max((-adjbw1 * 2 + 1) / 3, 0),
- x1 + third, y2 - max((-adjbw2 * 2 + 1) / 3, 0),
- s, c, SOLID, adjbw1bigthird, adjbw2bigthird);
- drawLineForBoxSide(graphicsContext, x2 - third, y1 + max((adjbw1 * 2 + 1) / 3, 0),
- x2, y2 - max((adjbw2 * 2 + 1) / 3, 0),
- s, c, SOLID, adjbw1bigthird, adjbw2bigthird);
+ drawLineForBoxSide(graphicsContext, x1, y1 + max((-adjacentWidth1 * 2 + 1) / 3, 0),
+ x1 + third, y2 - max((-adjacentWidth2 * 2 + 1) / 3, 0),
+ side, color, SOLID, adjacent1BigThird, adjacent2BigThird, antialias);
+ drawLineForBoxSide(graphicsContext, x2 - third, y1 + max((adjacentWidth1 * 2 + 1) / 3, 0),
+ x2, y2 - max((adjacentWidth2 * 2 + 1) / 3, 0),
+ side, color, SOLID, adjacent1BigThird, adjacent2BigThird, antialias);
break;
case BSBottom:
- drawLineForBoxSide(graphicsContext, x1 + max((adjbw1 * 2 + 1) / 3, 0),
- y1, x2 - max((adjbw2 * 2 + 1) / 3, 0), y1 + third,
- s, c, SOLID, adjbw1bigthird, adjbw2bigthird);
- drawLineForBoxSide(graphicsContext, x1 + max((-adjbw1 * 2 + 1) / 3, 0),
- y2 - third, x2 - max((-adjbw2 * 2 + 1) / 3, 0), y2,
- s, c, SOLID, adjbw1bigthird, adjbw2bigthird);
+ drawLineForBoxSide(graphicsContext, x1 + max((adjacentWidth1 * 2 + 1) / 3, 0),
+ y1, x2 - max((adjacentWidth2 * 2 + 1) / 3, 0), y1 + third,
+ side, color, SOLID, adjacent1BigThird, adjacent2BigThird, antialias);
+ drawLineForBoxSide(graphicsContext, x1 + max((-adjacentWidth1 * 2 + 1) / 3, 0),
+ y2 - third, x2 - max((-adjacentWidth2 * 2 + 1) / 3, 0), y2,
+ side, color, SOLID, adjacent1BigThird, adjacent2BigThird, antialias);
break;
case BSRight:
- drawLineForBoxSide(graphicsContext, x1, y1 + max((adjbw1 * 2 + 1) / 3, 0),
- x1 + third, y2 - max((adjbw2 * 2 + 1) / 3, 0),
- s, c, SOLID, adjbw1bigthird, adjbw2bigthird);
- drawLineForBoxSide(graphicsContext, x2 - third, y1 + max((-adjbw1 * 2 + 1) / 3, 0),
- x2, y2 - max((-adjbw2 * 2 + 1) / 3, 0),
- s, c, SOLID, adjbw1bigthird, adjbw2bigthird);
+ drawLineForBoxSide(graphicsContext, x1, y1 + max((adjacentWidth1 * 2 + 1) / 3, 0),
+ x1 + third, y2 - max((adjacentWidth2 * 2 + 1) / 3, 0),
+ side, color, SOLID, adjacent1BigThird, adjacent2BigThird, antialias);
+ drawLineForBoxSide(graphicsContext, x2 - third, y1 + max((-adjacentWidth1 * 2 + 1) / 3, 0),
+ x2, y2 - max((-adjacentWidth2 * 2 + 1) / 3, 0),
+ side, color, SOLID, adjacent1BigThird, adjacent2BigThird, antialias);
break;
default:
break;
@@ -802,8 +813,7 @@ void RenderObject::drawLineForBoxSide(GraphicsContext* graphicsContext, int x1,
break;
}
case RIDGE:
- case GROOVE:
- {
+ case GROOVE: {
EBorderStyle s1;
EBorderStyle s2;
if (style == GROOVE) {
@@ -814,82 +824,90 @@ void RenderObject::drawLineForBoxSide(GraphicsContext* graphicsContext, int x1,
s2 = INSET;
}
- int adjbw1bighalf = ((adjbw1 > 0) ? adjbw1 + 1 : adjbw1 - 1) / 2;
- int adjbw2bighalf = ((adjbw2 > 0) ? adjbw2 + 1 : adjbw2 - 1) / 2;
+ int adjacent1BigHalf = ((adjacentWidth1 > 0) ? adjacentWidth1 + 1 : adjacentWidth1 - 1) / 2;
+ int adjacent2BigHalf = ((adjacentWidth2 > 0) ? adjacentWidth2 + 1 : adjacentWidth2 - 1) / 2;
- switch (s) {
+ switch (side) {
case BSTop:
- drawLineForBoxSide(graphicsContext, x1 + max(-adjbw1, 0) / 2, y1, x2 - max(-adjbw2, 0) / 2, (y1 + y2 + 1) / 2,
- s, c, s1, adjbw1bighalf, adjbw2bighalf);
- drawLineForBoxSide(graphicsContext, x1 + max(adjbw1 + 1, 0) / 2, (y1 + y2 + 1) / 2, x2 - max(adjbw2 + 1, 0) / 2, y2,
- s, c, s2, adjbw1 / 2, adjbw2 / 2);
+ drawLineForBoxSide(graphicsContext, x1 + max(-adjacentWidth1, 0) / 2, y1, x2 - max(-adjacentWidth2, 0) / 2, (y1 + y2 + 1) / 2,
+ side, color, s1, adjacent1BigHalf, adjacent2BigHalf, antialias);
+ drawLineForBoxSide(graphicsContext, x1 + max(adjacentWidth1 + 1, 0) / 2, (y1 + y2 + 1) / 2, x2 - max(adjacentWidth2 + 1, 0) / 2, y2,
+ side, color, s2, adjacentWidth1 / 2, adjacentWidth2 / 2, antialias);
break;
case BSLeft:
- drawLineForBoxSide(graphicsContext, x1, y1 + max(-adjbw1, 0) / 2, (x1 + x2 + 1) / 2, y2 - max(-adjbw2, 0) / 2,
- s, c, s1, adjbw1bighalf, adjbw2bighalf);
- drawLineForBoxSide(graphicsContext, (x1 + x2 + 1) / 2, y1 + max(adjbw1 + 1, 0) / 2, x2, y2 - max(adjbw2 + 1, 0) / 2,
- s, c, s2, adjbw1 / 2, adjbw2 / 2);
+ drawLineForBoxSide(graphicsContext, x1, y1 + max(-adjacentWidth1, 0) / 2, (x1 + x2 + 1) / 2, y2 - max(-adjacentWidth2, 0) / 2,
+ side, color, s1, adjacent1BigHalf, adjacent2BigHalf, antialias);
+ drawLineForBoxSide(graphicsContext, (x1 + x2 + 1) / 2, y1 + max(adjacentWidth1 + 1, 0) / 2, x2, y2 - max(adjacentWidth2 + 1, 0) / 2,
+ side, color, s2, adjacentWidth1 / 2, adjacentWidth2 / 2, antialias);
break;
case BSBottom:
- drawLineForBoxSide(graphicsContext, x1 + max(adjbw1, 0) / 2, y1, x2 - max(adjbw2, 0) / 2, (y1 + y2 + 1) / 2,
- s, c, s2, adjbw1bighalf, adjbw2bighalf);
- drawLineForBoxSide(graphicsContext, x1 + max(-adjbw1 + 1, 0) / 2, (y1 + y2 + 1) / 2, x2 - max(-adjbw2 + 1, 0) / 2, y2,
- s, c, s1, adjbw1 / 2, adjbw2 / 2);
+ drawLineForBoxSide(graphicsContext, x1 + max(adjacentWidth1, 0) / 2, y1, x2 - max(adjacentWidth2, 0) / 2, (y1 + y2 + 1) / 2,
+ side, color, s2, adjacent1BigHalf, adjacent2BigHalf, antialias);
+ drawLineForBoxSide(graphicsContext, x1 + max(-adjacentWidth1 + 1, 0) / 2, (y1 + y2 + 1) / 2, x2 - max(-adjacentWidth2 + 1, 0) / 2, y2,
+ side, color, s1, adjacentWidth1 / 2, adjacentWidth2 / 2, antialias);
break;
case BSRight:
- drawLineForBoxSide(graphicsContext, x1, y1 + max(adjbw1, 0) / 2, (x1 + x2 + 1) / 2, y2 - max(adjbw2, 0) / 2,
- s, c, s2, adjbw1bighalf, adjbw2bighalf);
- drawLineForBoxSide(graphicsContext, (x1 + x2 + 1) / 2, y1 + max(-adjbw1 + 1, 0) / 2, x2, y2 - max(-adjbw2 + 1, 0) / 2,
- s, c, s1, adjbw1 / 2, adjbw2 / 2);
+ drawLineForBoxSide(graphicsContext, x1, y1 + max(adjacentWidth1, 0) / 2, (x1 + x2 + 1) / 2, y2 - max(adjacentWidth2, 0) / 2,
+ side, color, s2, adjacent1BigHalf, adjacent2BigHalf, antialias);
+ drawLineForBoxSide(graphicsContext, (x1 + x2 + 1) / 2, y1 + max(-adjacentWidth1 + 1, 0) / 2, x2, y2 - max(-adjacentWidth2 + 1, 0) / 2,
+ side, color, s1, adjacentWidth1 / 2, adjacentWidth2 / 2, antialias);
break;
}
break;
}
case INSET:
- if (s == BSTop || s == BSLeft)
- c = c.dark();
+ // FIXME: Maybe we should lighten the colors on one side like Firefox.
+ // https://bugs.webkit.org/show_bug.cgi?id=58608
+ if (side == BSTop || side == BSLeft)
+ color = color.dark();
// fall through
case OUTSET:
- if (style == OUTSET && (s == BSBottom || s == BSRight))
- c = c.dark();
+ if (style == OUTSET && (side == BSBottom || side == BSRight))
+ color = color.dark();
// fall through
case SOLID: {
graphicsContext->setStrokeStyle(NoStroke);
- graphicsContext->setFillColor(c, m_style->colorSpace());
+ graphicsContext->setFillColor(color, m_style->colorSpace());
ASSERT(x2 >= x1);
ASSERT(y2 >= y1);
- if (!adjbw1 && !adjbw2) {
+ if (!adjacentWidth1 && !adjacentWidth2) {
+ // Turn off antialiasing to match the behavior of drawConvexPolygon();
+ // this matters for rects in transformed contexts.
+ bool wasAntialiased = graphicsContext->shouldAntialias();
+ graphicsContext->setShouldAntialias(antialias);
graphicsContext->drawRect(IntRect(x1, y1, x2 - x1, y2 - y1));
+ graphicsContext->setShouldAntialias(wasAntialiased);
return;
}
FloatPoint quad[4];
- switch (s) {
+ switch (side) {
case BSTop:
- quad[0] = FloatPoint(x1 + max(-adjbw1, 0), y1);
- quad[1] = FloatPoint(x1 + max(adjbw1, 0), y2);
- quad[2] = FloatPoint(x2 - max(adjbw2, 0), y2);
- quad[3] = FloatPoint(x2 - max(-adjbw2, 0), y1);
+ quad[0] = FloatPoint(x1 + max(-adjacentWidth1, 0), y1);
+ quad[1] = FloatPoint(x1 + max(adjacentWidth1, 0), y2);
+ quad[2] = FloatPoint(x2 - max(adjacentWidth2, 0), y2);
+ quad[3] = FloatPoint(x2 - max(-adjacentWidth2, 0), y1);
break;
case BSBottom:
- quad[0] = FloatPoint(x1 + max(adjbw1, 0), y1);
- quad[1] = FloatPoint(x1 + max(-adjbw1, 0), y2);
- quad[2] = FloatPoint(x2 - max(-adjbw2, 0), y2);
- quad[3] = FloatPoint(x2 - max(adjbw2, 0), y1);
+ quad[0] = FloatPoint(x1 + max(adjacentWidth1, 0), y1);
+ quad[1] = FloatPoint(x1 + max(-adjacentWidth1, 0), y2);
+ quad[2] = FloatPoint(x2 - max(-adjacentWidth2, 0), y2);
+ quad[3] = FloatPoint(x2 - max(adjacentWidth2, 0), y1);
break;
case BSLeft:
- quad[0] = FloatPoint(x1, y1 + max(-adjbw1, 0));
- quad[1] = FloatPoint(x1, y2 - max(-adjbw2, 0));
- quad[2] = FloatPoint(x2, y2 - max(adjbw2, 0));
- quad[3] = FloatPoint(x2, y1 + max(adjbw1, 0));
+ quad[0] = FloatPoint(x1, y1 + max(-adjacentWidth1, 0));
+ quad[1] = FloatPoint(x1, y2 - max(-adjacentWidth2, 0));
+ quad[2] = FloatPoint(x2, y2 - max(adjacentWidth2, 0));
+ quad[3] = FloatPoint(x2, y1 + max(adjacentWidth1, 0));
break;
case BSRight:
- quad[0] = FloatPoint(x1, y1 + max(adjbw1, 0));
- quad[1] = FloatPoint(x1, y2 - max(adjbw2, 0));
- quad[2] = FloatPoint(x2, y2 - max(-adjbw2, 0));
- quad[3] = FloatPoint(x2, y1 + max(-adjbw1, 0));
+ quad[0] = FloatPoint(x1, y1 + max(adjacentWidth1, 0));
+ quad[1] = FloatPoint(x1, y2 - max(adjacentWidth2, 0));
+ quad[2] = FloatPoint(x2, y2 - max(-adjacentWidth2, 0));
+ quad[3] = FloatPoint(x2, y1 + max(-adjacentWidth1, 0));
break;
}
- graphicsContext->drawConvexPolygon(4, quad);
+
+ graphicsContext->drawConvexPolygon(4, quad, antialias);
break;
}
}
@@ -904,156 +922,9 @@ IntRect RenderObject::borderInnerRect(const IntRect& borderRect, unsigned short
borderRect.height() - topWidth - bottomWidth);
}
-#if HAVE(PATH_BASED_BORDER_RADIUS_DRAWING)
-void RenderObject::drawBoxSideFromPath(GraphicsContext* graphicsContext, const IntRect& borderRect, const Path& borderPath,
- float thickness, float drawThickness, BoxSide s, const RenderStyle* style,
- Color c, EBorderStyle borderStyle)
-{
- if (thickness <= 0)
- return;
-
- if (borderStyle == DOUBLE && thickness < 3)
- borderStyle = SOLID;
-
- switch (borderStyle) {
- case BNONE:
- case BHIDDEN:
- return;
- case DOTTED:
- case DASHED: {
- graphicsContext->setStrokeColor(c, style->colorSpace());
-
- // The stroke is doubled here because the provided path is the
- // outside edge of the border so half the stroke is clipped off.
- // The extra multiplier is so that the clipping mask can antialias
- // the edges to prevent jaggies.
- graphicsContext->setStrokeThickness(drawThickness * 2 * 1.1f);
- graphicsContext->setStrokeStyle(borderStyle == DASHED ? DashedStroke : DottedStroke);
-
- // If the number of dashes that fit in the path is odd and non-integral then we
- // will have an awkwardly-sized dash at the end of the path. To try to avoid that
- // here, we simply make the whitespace dashes ever so slightly bigger.
- // FIXME: This could be even better if we tried to manipulate the dash offset
- // and possibly the whiteSpaceWidth to get the corners dash-symmetrical.
- float patWidth = thickness * ((borderStyle == DASHED) ? 3.0f : 1.0f);
- float whiteSpaceWidth = patWidth;
- float numberOfDashes = borderPath.length() / patWidth;
- bool evenNumberOfFullDashes = !((int)numberOfDashes % 2);
- bool integralNumberOfDashes = !(numberOfDashes - (int)numberOfDashes);
- if (!evenNumberOfFullDashes && !integralNumberOfDashes) {
- float numberOfWhitespaceDashes = numberOfDashes / 2;
- whiteSpaceWidth += (patWidth / numberOfWhitespaceDashes);
- }
-
- DashArray lineDash;
- lineDash.append(patWidth);
- lineDash.append(whiteSpaceWidth);
- graphicsContext->setLineDash(lineDash, patWidth);
- graphicsContext->strokePath(borderPath);
- return;
- }
- case DOUBLE: {
- int outerBorderTopWidth = style->borderTopWidth() / 3;
- int outerBorderRightWidth = style->borderRightWidth() / 3;
- int outerBorderBottomWidth = style->borderBottomWidth() / 3;
- int outerBorderLeftWidth = style->borderLeftWidth() / 3;
-
- int innerBorderTopWidth = style->borderTopWidth() * 2 / 3;
- int innerBorderRightWidth = style->borderRightWidth() * 2 / 3;
- int innerBorderBottomWidth = style->borderBottomWidth() * 2 / 3;
- int innerBorderLeftWidth = style->borderLeftWidth() * 2 / 3;
-
- // We need certain integer rounding results
- if (style->borderTopWidth() % 3 == 2)
- outerBorderTopWidth += 1;
- if (style->borderRightWidth() % 3 == 2)
- outerBorderRightWidth += 1;
- if (style->borderBottomWidth() % 3 == 2)
- outerBorderBottomWidth += 1;
- if (style->borderLeftWidth() % 3 == 2)
- outerBorderLeftWidth += 1;
-
- if (style->borderTopWidth() % 3 == 1)
- innerBorderTopWidth += 1;
- if (style->borderRightWidth() % 3 == 1)
- innerBorderRightWidth += 1;
- if (style->borderBottomWidth() % 3 == 1)
- innerBorderBottomWidth += 1;
- if (style->borderLeftWidth() % 3 == 1)
- innerBorderLeftWidth += 1;
-
- // Get the inner border rects for both the outer border line and the inner border line
-
- // Draw inner border line
- graphicsContext->save();
- IntRect innerBorderInnerRect = borderInnerRect(borderRect, innerBorderTopWidth, innerBorderBottomWidth,
- innerBorderLeftWidth, innerBorderRightWidth);
- RoundedIntRect innerClip = style->getRoundedInnerBorderWithBorderWidths(innerBorderInnerRect, innerBorderTopWidth, innerBorderBottomWidth,
- innerBorderLeftWidth, innerBorderRightWidth);
- graphicsContext->addRoundedRectClip(innerClip);
- drawBoxSideFromPath(graphicsContext, borderRect, borderPath, thickness, drawThickness, s, style, c, SOLID);
- graphicsContext->restore();
-
- // Draw outer border line
- graphicsContext->save();
- IntRect outerBorderInnerRect = borderInnerRect(borderRect, outerBorderTopWidth, outerBorderBottomWidth,
- outerBorderLeftWidth, outerBorderRightWidth);
- RoundedIntRect outerClip = style->getRoundedInnerBorderWithBorderWidths(outerBorderInnerRect, outerBorderTopWidth, outerBorderBottomWidth,
- outerBorderLeftWidth, outerBorderRightWidth);
- graphicsContext->clipOutRoundedRect(outerClip);
- drawBoxSideFromPath(graphicsContext, borderRect, borderPath, thickness, drawThickness, s, style, c, SOLID);
- graphicsContext->restore();
-
- return;
- }
- case RIDGE:
- case GROOVE:
- {
- EBorderStyle s1;
- EBorderStyle s2;
- if (borderStyle == GROOVE) {
- s1 = INSET;
- s2 = OUTSET;
- } else {
- s1 = OUTSET;
- s2 = INSET;
- }
-
- IntRect halfBorderRect = borderInnerRect(borderRect, style->borderLeftWidth() / 2, style->borderBottomWidth() / 2,
- style->borderLeftWidth() / 2, style->borderRightWidth() / 2);
-
- // Paint full border
- drawBoxSideFromPath(graphicsContext, borderRect, borderPath, thickness, drawThickness, s, style, c, s1);
-
- // Paint inner only
- graphicsContext->save();
- RoundedIntRect clipRect = style->getRoundedInnerBorderWithBorderWidths(halfBorderRect, style->borderLeftWidth() / 2, style->borderBottomWidth() / 2,
- style->borderLeftWidth() / 2, style->borderRightWidth() / 2);
- graphicsContext->addRoundedRectClip(clipRect);
- drawBoxSideFromPath(graphicsContext, borderRect, borderPath, thickness, drawThickness, s, style, c, s2);
- graphicsContext->restore();
-
- return;
- }
- case INSET:
- if (s == BSTop || s == BSLeft)
- c = c.dark();
- break;
- case OUTSET:
- if (s == BSBottom || s == BSRight)
- c = c.dark();
- break;
- default:
- break;
- }
-
- graphicsContext->setStrokeStyle(NoStroke);
- graphicsContext->setFillColor(c, style->colorSpace());
- graphicsContext->drawRect(borderRect);
-}
-#else
+#if !HAVE(PATH_BASED_BORDER_RADIUS_DRAWING)
void RenderObject::drawArcForBoxSide(GraphicsContext* graphicsContext, int x, int y, float thickness, const IntSize& radius,
- int angleStart, int angleSpan, BoxSide s, Color c,
+ int angleStart, int angleSpan, BoxSide s, Color color,
EBorderStyle style, bool firstCorner)
{
// FIXME: This function should be removed when all ports implement GraphicsContext::clipConvexPolygon()!!
@@ -1067,7 +938,7 @@ void RenderObject::drawArcForBoxSide(GraphicsContext* graphicsContext, int x, in
return;
case DOTTED:
case DASHED:
- graphicsContext->setStrokeColor(c, m_style->colorSpace());
+ graphicsContext->setStrokeColor(color, m_style->colorSpace());
graphicsContext->setStrokeStyle(style == DOTTED ? DottedStroke : DashedStroke);
graphicsContext->setStrokeThickness(thickness);
graphicsContext->strokeArc(IntRect(x, y, radius.width() * 2, radius.height() * 2), angleStart, angleSpan);
@@ -1089,7 +960,7 @@ void RenderObject::drawArcForBoxSide(GraphicsContext* graphicsContext, int x, in
}
graphicsContext->setStrokeStyle(SolidStroke);
- graphicsContext->setStrokeColor(c, m_style->colorSpace());
+ graphicsContext->setStrokeColor(color, m_style->colorSpace());
graphicsContext->setStrokeThickness(third);
graphicsContext->strokeArc(IntRect(x, outerY, radius.width() * 2, outerHeight), angleStart, angleSpan);
graphicsContext->setStrokeThickness(innerThird > 2 ? innerThird - 1 : innerThird);
@@ -1101,14 +972,14 @@ void RenderObject::drawArcForBoxSide(GraphicsContext* graphicsContext, int x, in
Color c2;
if ((style == RIDGE && (s == BSTop || s == BSLeft)) ||
(style == GROOVE && (s == BSBottom || s == BSRight)))
- c2 = c.dark();
+ c2 = color.dark();
else {
- c2 = c;
- c = c.dark();
+ c2 = color;
+ color = color.dark();
}
graphicsContext->setStrokeStyle(SolidStroke);
- graphicsContext->setStrokeColor(c, m_style->colorSpace());
+ graphicsContext->setStrokeColor(color, m_style->colorSpace());
graphicsContext->setStrokeThickness(thickness);
graphicsContext->strokeArc(IntRect(x, y, radius.width() * 2, radius.height() * 2), angleStart, angleSpan);
@@ -1122,13 +993,13 @@ void RenderObject::drawArcForBoxSide(GraphicsContext* graphicsContext, int x, in
}
case INSET:
if (s == BSTop || s == BSLeft)
- c = c.dark();
+ color = color.dark();
case OUTSET:
if (style == OUTSET && (s == BSBottom || s == BSRight))
- c = c.dark();
+ color = color.dark();
case SOLID:
graphicsContext->setStrokeStyle(SolidStroke);
- graphicsContext->setStrokeColor(c, m_style->colorSpace());
+ graphicsContext->setStrokeColor(color, m_style->colorSpace());
graphicsContext->setStrokeThickness(thickness);
graphicsContext->strokeArc(IntRect(x, y, radius.width() * 2, radius.height() * 2), angleStart, angleSpan);
break;
diff --git a/Source/WebCore/rendering/RenderObject.h b/Source/WebCore/rendering/RenderObject.h
index 41564dd..cf4d61b 100644
--- a/Source/WebCore/rendering/RenderObject.h
+++ b/Source/WebCore/rendering/RenderObject.h
@@ -37,7 +37,7 @@
#include "TransformationMatrix.h"
#include <wtf/UnusedParam.h>
-#if PLATFORM(CG) || PLATFORM(CAIRO) || PLATFORM(QT)
+#if USE(CG) || USE(CAIRO) || PLATFORM(QT)
#define HAVE_PATH_BASED_BORDER_RADIUS_DRAWING 1
#endif
@@ -79,13 +79,12 @@ enum HitTestAction {
HitTestForeground
};
-// Sides used when drawing borders and outlines. This is in RenderObject rather than RenderBoxModelObject since outlines can
-// be drawn by SVG around bounding boxes.
+// Sides used when drawing borders and outlines. The values should run clockwise from top.
enum BoxSide {
BSTop,
+ BSRight,
BSBottom,
- BSLeft,
- BSRight
+ BSLeft
};
const int caretWidth = 1;
@@ -433,13 +432,9 @@ public:
bool hasTransform() const { return m_hasTransform; }
bool hasMask() const { return style() && style()->hasMask(); }
- void drawLineForBoxSide(GraphicsContext*, int x1, int y1, int x2, int y2, BoxSide,
- Color, EBorderStyle, int adjbw1, int adjbw2);
-#if HAVE(PATH_BASED_BORDER_RADIUS_DRAWING)
- void drawBoxSideFromPath(GraphicsContext*, const IntRect&, const Path&,
- float thickness, float drawThickness, BoxSide, const RenderStyle*,
- Color, EBorderStyle);
-#else
+ inline bool preservesNewline() const;
+
+#if !HAVE(PATH_BASED_BORDER_RADIUS_DRAWING)
// FIXME: This function should be removed when all ports implement GraphicsContext::clipConvexPolygon()!!
// At that time, everyone can use RenderObject::drawBoxSideFromPath() instead. This should happen soon.
void drawArcForBoxSide(GraphicsContext*, int x, int y, float thickness, const IntSize& radius, int angleStart,
@@ -782,6 +777,9 @@ protected:
// Overrides should call the superclass at the start
virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
+ void drawLineForBoxSide(GraphicsContext*, int x1, int y1, int x2, int y2, BoxSide,
+ Color, EBorderStyle, int adjbw1, int adjbw2, bool antialias = false);
+
void paintFocusRing(GraphicsContext*, int tx, int ty, RenderStyle*);
void paintOutline(GraphicsContext*, int tx, int ty, int w, int h);
void addPDFURLRect(GraphicsContext*, const IntRect&);
@@ -958,8 +956,9 @@ inline void RenderObject::setChildNeedsLayout(bool b, bool markParents)
inline void RenderObject::setNeedsPositionedMovementLayout()
{
- bool alreadyNeededLayout = needsLayout();
+ bool alreadyNeededLayout = m_needsPositionedMovementLayout;
m_needsPositionedMovementLayout = true;
+ ASSERT(!isSetNeedsLayoutForbidden());
if (!alreadyNeededLayout) {
markContainingBlocksForLayout();
if (hasLayer())
@@ -969,8 +968,9 @@ inline void RenderObject::setNeedsPositionedMovementLayout()
inline void RenderObject::setNeedsSimplifiedNormalFlowLayout()
{
- bool alreadyNeededLayout = needsLayout();
+ bool alreadyNeededLayout = m_needsSimplifiedNormalFlowLayout;
m_needsSimplifiedNormalFlowLayout = true;
+ ASSERT(!isSetNeedsLayoutForbidden());
if (!alreadyNeededLayout) {
markContainingBlocksForLayout();
if (hasLayer())
@@ -1037,6 +1037,16 @@ inline void RenderObject::markContainingBlocksForLayout(bool scheduleRelayout, R
last->scheduleRelayout();
}
+inline bool RenderObject::preservesNewline() const
+{
+#if ENABLE(SVG)
+ if (isSVGInlineText())
+ return false;
+#endif
+
+ return style()->preserveNewline();
+}
+
inline void makeMatrixRenderable(TransformationMatrix& matrix, bool has3DRendering)
{
#if !ENABLE(3D_RENDERING)
@@ -1079,6 +1089,33 @@ inline void adjustFloatRectForAbsoluteZoom(FloatRect& rect, RenderObject* render
rect.setHeight(adjustFloatForAbsoluteZoom(rect.height(), style));
}
+inline FloatPoint adjustFloatPointForPageScale(const FloatPoint& point, float pageScale)
+{
+ if (pageScale == 1)
+ return point;
+ return FloatPoint(point.x() / pageScale, point.y() / pageScale);
+}
+
+inline void adjustFloatQuadForPageScale(FloatQuad& quad, float pageScale)
+{
+ if (pageScale == 1)
+ return;
+ quad.setP1(adjustFloatPointForPageScale(quad.p1(), pageScale));
+ quad.setP2(adjustFloatPointForPageScale(quad.p2(), pageScale));
+ quad.setP3(adjustFloatPointForPageScale(quad.p3(), pageScale));
+ quad.setP4(adjustFloatPointForPageScale(quad.p4(), pageScale));
+}
+
+inline void adjustFloatRectForPageScale(FloatRect& rect, float pageScale)
+{
+ if (pageScale == 1)
+ return;
+ rect.setX(rect.x() / pageScale);
+ rect.setY(rect.y() / pageScale);
+ rect.setWidth(rect.width() / pageScale);
+ rect.setHeight(rect.height() / pageScale);
+}
+
} // namespace WebCore
#ifndef NDEBUG
diff --git a/Source/WebCore/rendering/RenderObjectChildList.cpp b/Source/WebCore/rendering/RenderObjectChildList.cpp
index 617067a..e26f221 100644
--- a/Source/WebCore/rendering/RenderObjectChildList.cpp
+++ b/Source/WebCore/rendering/RenderObjectChildList.cpp
@@ -456,6 +456,12 @@ void RenderObjectChildList::updateBeforeAfterContent(RenderObject* owner, Pseudo
ASSERT(styledObject->node()); // The styled object cannot be anonymous or else it could not have ':before' or ':after' pseudo elements.
generatedContentContainer->setNode(styledObject->node()); // This allows access to the generatingNode.
generatedContentContainer->setStyle(pseudoElementStyle);
+ if (!owner->isChildAllowed(generatedContentContainer, pseudoElementStyle)) {
+ // The generated content container is not allowed here -> abort.
+ generatedContentContainer->destroy();
+ renderer->destroy();
+ return;
+ }
owner->addChild(generatedContentContainer, insertBefore);
}
if (generatedContentContainer->isChildAllowed(renderer, pseudoElementStyle))
diff --git a/Source/WebCore/rendering/RenderPart.cpp b/Source/WebCore/rendering/RenderPart.cpp
index 3262961..59b9795 100644
--- a/Source/WebCore/rendering/RenderPart.cpp
+++ b/Source/WebCore/rendering/RenderPart.cpp
@@ -24,10 +24,11 @@
#include "config.h"
#include "RenderPart.h"
-#include "RenderView.h"
#include "Frame.h"
#include "FrameView.h"
#include "HTMLFrameElementBase.h"
+#include "PluginViewBase.h"
+#include "RenderView.h"
namespace WebCore {
@@ -58,4 +59,35 @@ void RenderPart::viewCleared()
{
}
+#if USE(ACCELERATED_COMPOSITING)
+bool RenderPart::requiresLayer() const
+{
+ if (RenderWidget::requiresLayer())
+ return true;
+
+ return requiresAcceleratedCompositing();
+}
+
+bool RenderPart::requiresAcceleratedCompositing() const
+{
+ // There are two general cases in which we can return true. First, if this is a plugin
+ // renderer and the plugin has a layer, then we need a layer. Second, if this is
+ // a renderer with a contentDocument and that document needs a layer, then we need
+ // a layer.
+ if (widget() && widget()->isPluginViewBase() && static_cast<PluginViewBase*>(widget())->platformLayer())
+ return true;
+
+ if (!node() || !node()->isFrameOwnerElement())
+ return false;
+
+ HTMLFrameOwnerElement* element = static_cast<HTMLFrameOwnerElement*>(node());
+ if (Document* contentDocument = element->contentDocument()) {
+ if (RenderView* view = contentDocument->renderView())
+ return view->usesCompositing();
+ }
+
+ return false;
+}
+#endif
+
}
diff --git a/Source/WebCore/rendering/RenderPart.h b/Source/WebCore/rendering/RenderPart.h
index 18f2346..9a22b30 100644
--- a/Source/WebCore/rendering/RenderPart.h
+++ b/Source/WebCore/rendering/RenderPart.h
@@ -36,6 +36,15 @@ public:
virtual void setWidget(PassRefPtr<Widget>);
virtual void viewCleared();
+#if USE(ACCELERATED_COMPOSITING)
+ bool requiresAcceleratedCompositing() const;
+#endif
+
+protected:
+#if USE(ACCELERATED_COMPOSITING)
+ virtual bool requiresLayer() const;
+#endif
+
private:
virtual bool isRenderPart() const { return true; }
virtual const char* renderName() const { return "RenderPart"; }
diff --git a/Source/WebCore/rendering/RenderProgress.cpp b/Source/WebCore/rendering/RenderProgress.cpp
index 2a8e6f3..f687589 100644
--- a/Source/WebCore/rendering/RenderProgress.cpp
+++ b/Source/WebCore/rendering/RenderProgress.cpp
@@ -36,19 +36,9 @@ using namespace std;
namespace WebCore {
-IntRect RenderProgressBarValuePart::preferredFrameRect()
-{
- return toRenderProgress(parent())->valuePartRect();
-}
-
-bool RenderProgressBarValuePart::shouldBeHidden()
-{
- return !toRenderProgress(parent())->shouldHaveParts();
-}
-
RenderProgress::RenderProgress(HTMLProgressElement* element)
- : RenderIndicator(element)
- , m_position(-1)
+ : RenderBlock(element)
+ , m_position(HTMLProgressElement::InvalidPosition)
, m_animationStartTime(0)
, m_animationRepeatInterval(0)
, m_animationDuration(0)
@@ -69,7 +59,7 @@ void RenderProgress::updateFromElement()
m_position = element->position();
updateAnimationState();
- RenderIndicator::updateFromElement();
+ RenderBlock::updateFromElement();
}
double RenderProgress::animationProgress() const
@@ -79,36 +69,15 @@ double RenderProgress::animationProgress() const
bool RenderProgress::isDeterminate() const
{
- return 0 <= position();
+ return (HTMLProgressElement::IndeterminatePosition != position()
+ && HTMLProgressElement::InvalidPosition != position());
}
void RenderProgress::animationTimerFired(Timer<RenderProgress>*)
{
repaint();
-}
-
-void RenderProgress::paint(PaintInfo& paintInfo, int tx, int ty)
-{
- if (paintInfo.phase == PaintPhaseBlockBackground) {
- if (!m_animationTimer.isActive() && m_animating)
- m_animationTimer.startOneShot(m_animationRepeatInterval);
- }
-
- RenderIndicator::paint(paintInfo, tx, ty);
-}
-
-void RenderProgress::layoutParts()
-{
- for (RenderObject* child = firstChild(); child; child = child->nextSibling())
- child->layout();
- updateAnimationState();
-}
-
-bool RenderProgress::shouldHaveParts() const
-{
- if (!style()->hasAppearance())
- return true;
- return false;
+ if (!m_animationTimer.isActive() && m_animating)
+ m_animationTimer.startOneShot(m_animationRepeatInterval);
}
void RenderProgress::updateAnimationState()
@@ -128,14 +97,6 @@ void RenderProgress::updateAnimationState()
m_animationTimer.stop();
}
-IntRect RenderProgress::valuePartRect() const
-{
- IntRect rect(borderLeft() + paddingLeft(), borderTop() + paddingTop(), lround((width() - borderLeft() - paddingLeft() - borderRight() - paddingRight()) * position()), height() - borderTop() - paddingTop() - borderBottom() - paddingBottom());
- if (!style()->isLeftToRightDirection())
- rect.setX(width() - borderRight() - paddingRight() - rect.width());
- return rect;
-}
-
HTMLProgressElement* RenderProgress::progressElement() const
{
return static_cast<HTMLProgressElement*>(node());
diff --git a/Source/WebCore/rendering/RenderProgress.h b/Source/WebCore/rendering/RenderProgress.h
index 78cf359..62436fd 100644
--- a/Source/WebCore/rendering/RenderProgress.h
+++ b/Source/WebCore/rendering/RenderProgress.h
@@ -23,21 +23,12 @@
#if ENABLE(PROGRESS_TAG)
#include "RenderBlock.h"
-#include "RenderIndicator.h"
namespace WebCore {
class HTMLProgressElement;
-class RenderProgressBarValuePart : public RenderIndicatorPart {
-public:
- RenderProgressBarValuePart(Node* node) : RenderIndicatorPart(node) {}
-private:
- virtual IntRect preferredFrameRect();
- virtual bool shouldBeHidden();
-};
-
-class RenderProgress : public RenderIndicator {
+class RenderProgress : public RenderBlock {
public:
RenderProgress(HTMLProgressElement*);
virtual ~RenderProgress();
@@ -47,17 +38,15 @@ public:
double animationStartTime() const { return m_animationStartTime; }
bool isDeterminate() const;
- IntRect valuePartRect() const;
- bool shouldHaveParts() const;
HTMLProgressElement* progressElement() const;
private:
virtual const char* renderName() const { return "RenderProgress"; }
virtual bool isProgress() const { return true; }
+ virtual bool requiresForcedStyleRecalcPropagation() const { return true; }
+ virtual bool canHaveChildren() const { return false; }
virtual void updateFromElement();
- virtual void paint(PaintInfo&, int tx, int ty);
- virtual void layoutParts();
void animationTimerFired(Timer<RenderProgress>*);
void updateAnimationState();
diff --git a/Source/WebCore/rendering/RenderRuby.cpp b/Source/WebCore/rendering/RenderRuby.cpp
index 1c5cfaf..0b51384 100644
--- a/Source/WebCore/rendering/RenderRuby.cpp
+++ b/Source/WebCore/rendering/RenderRuby.cpp
@@ -33,17 +33,51 @@
#include "RenderRuby.h"
#include "RenderRubyRun.h"
+#include "RenderStyle.h"
+#include <wtf/RefPtr.h>
namespace WebCore {
//=== generic helper functions to avoid excessive code duplication ===
+static inline bool isAnonymousRubyInlineBlock(RenderObject* object)
+{
+ ASSERT(!object->parent()->isRuby()
+ || object->isRubyRun()
+ || (object->isInline() && (object->isBeforeContent() || object->isAfterContent()))
+ || (object->isAnonymous() && object->isRenderBlock() && object->style()->display() == INLINE_BLOCK));
+ return object->parent()->isRuby() && object->isRenderBlock() && !object->isRubyRun();
+}
+
+static inline RenderBlock* rubyBeforeBlock(const RenderObject* ruby)
+{
+ RenderObject* child = ruby->firstChild();
+ return child && !child->isRubyRun() && child->isRenderBlock() && child->style()->styleType() == BEFORE ? static_cast<RenderBlock*>(child) : 0;
+}
+
+static inline RenderBlock* rubyAfterBlock(const RenderObject* ruby)
+{
+ RenderObject* child = ruby->lastChild();
+ return child && !child->isRubyRun() && child->isRenderBlock() && child->style()->styleType() == AFTER ? static_cast<RenderBlock*>(child) : 0;
+}
+
+static RenderBlock* createAnonymousRubyInlineBlock(RenderObject* ruby, PseudoId styleType)
+{
+ RefPtr<RenderStyle> newStyle = RenderStyle::createAnonymousStyle(ruby->style());
+ newStyle->setDisplay(INLINE_BLOCK);
+ newStyle->setStyleType(styleType);
+
+ RenderBlock* newBlock = new (ruby->renderArena()) RenderBlock(ruby->document() /* anonymous box */);
+ newBlock->setStyle(newStyle.release());
+ return newBlock;
+}
+
static RenderRubyRun* lastRubyRun(const RenderObject* ruby)
{
RenderObject* child = ruby->lastChild();
- if (child && ruby->isAfterContent(child))
+ if (child && !child->isRubyRun())
child = child->previousSibling();
- ASSERT(!child || child->isRubyRun() || child->isBeforeContent());
+ ASSERT(!child || child->isRubyRun() || child->isBeforeContent() || child == rubyBeforeBlock(ruby));
return child && child->isRubyRun() ? static_cast<RenderRubyRun*>(child) : 0;
}
@@ -65,18 +99,37 @@ RenderRubyAsInline::~RenderRubyAsInline()
{
}
-bool RenderRubyAsInline::isChildAllowed(RenderObject* child, RenderStyle*) const
-{
- return child->isRubyText()
- || child->isRubyRun()
- || child->isInline();
-}
-
void RenderRubyAsInline::addChild(RenderObject* child, RenderObject* beforeChild)
{
- // Insert :before and :after content outside of ruby runs.
- if (child->isBeforeContent() || child->isAfterContent()) {
- RenderInline::addChild(child, beforeChild);
+ // Insert :before and :after content before/after the RenderRubyRun(s)
+ if (child->isBeforeContent()) {
+ if (child->isInline()) {
+ // Add generated inline content normally
+ RenderInline::addChild(child, firstChild());
+ } else {
+ // Wrap non-inline content with an anonymous inline-block.
+ RenderBlock* beforeBlock = rubyBeforeBlock(this);
+ if (!beforeBlock) {
+ beforeBlock = createAnonymousRubyInlineBlock(this, BEFORE);
+ RenderInline::addChild(beforeBlock, firstChild());
+ }
+ beforeBlock->addChild(child);
+ }
+ return;
+ }
+ if (child->isAfterContent()) {
+ if (child->isInline()) {
+ // Add generated inline content normally
+ RenderInline::addChild(child);
+ } else {
+ // Wrap non-inline content with an anonymous inline-block.
+ RenderBlock* afterBlock = rubyAfterBlock(this);
+ if (!afterBlock) {
+ afterBlock = createAnonymousRubyInlineBlock(this, AFTER);
+ RenderInline::addChild(afterBlock);
+ }
+ afterBlock->addChild(child);
+ }
return;
}
@@ -113,15 +166,23 @@ void RenderRubyAsInline::addChild(RenderObject* child, RenderObject* beforeChild
void RenderRubyAsInline::removeChild(RenderObject* child)
{
- // If the child's parent is *this (a ruby run or :before or :after content),
+ // If the child's parent is *this (must be a ruby run or generated content or anonymous block),
// just use the normal remove method.
- if (child->isRubyRun() || child->isBeforeContent() || child->isAfterContent()) {
+ if (child->parent() == this) {
+ ASSERT(child->isRubyRun() || child->isBeforeContent() || child->isAfterContent() || isAnonymousRubyInlineBlock(child));
RenderInline::removeChild(child);
return;
}
+ // If the child's parent is an anoymous block (must be generated :before/:after content)
+ // just use the block's remove method.
+ if (isAnonymousRubyInlineBlock(child->parent())) {
+ ASSERT(child->isBeforeContent() || child->isAfterContent());
+ child->parent()->removeChild(child);
+ removeChild(child->parent());
+ return;
+ }
// Otherwise find the containing run and remove it from there.
- ASSERT(child->parent() != this);
RenderRubyRun* run = findRubyRunParent(child);
ASSERT(run);
run->removeChild(child);
@@ -139,18 +200,37 @@ RenderRubyAsBlock::~RenderRubyAsBlock()
{
}
-bool RenderRubyAsBlock::isChildAllowed(RenderObject* child, RenderStyle*) const
-{
- return child->isRubyText()
- || child->isRubyRun()
- || child->isInline();
-}
-
void RenderRubyAsBlock::addChild(RenderObject* child, RenderObject* beforeChild)
{
- // Insert :before and :after content outside of ruby runs.
- if (child->isBeforeContent() || child->isAfterContent()) {
- RenderBlock::addChild(child, beforeChild);
+ // Insert :before and :after content before/after the RenderRubyRun(s)
+ if (child->isBeforeContent()) {
+ if (child->isInline()) {
+ // Add generated inline content normally
+ RenderBlock::addChild(child, firstChild());
+ } else {
+ // Wrap non-inline content with an anonymous inline-block.
+ RenderBlock* beforeBlock = rubyBeforeBlock(this);
+ if (!beforeBlock) {
+ beforeBlock = createAnonymousRubyInlineBlock(this, BEFORE);
+ RenderBlock::addChild(beforeBlock, firstChild());
+ }
+ beforeBlock->addChild(child);
+ }
+ return;
+ }
+ if (child->isAfterContent()) {
+ if (child->isInline()) {
+ // Add generated inline content normally
+ RenderBlock::addChild(child);
+ } else {
+ // Wrap non-inline content with an anonymous inline-block.
+ RenderBlock* afterBlock = rubyAfterBlock(this);
+ if (!afterBlock) {
+ afterBlock = createAnonymousRubyInlineBlock(this, AFTER);
+ RenderBlock::addChild(afterBlock);
+ }
+ afterBlock->addChild(child);
+ }
return;
}
@@ -187,15 +267,23 @@ void RenderRubyAsBlock::addChild(RenderObject* child, RenderObject* beforeChild)
void RenderRubyAsBlock::removeChild(RenderObject* child)
{
- // If the child's parent is *this (a ruby run or :before or :after content),
+ // If the child's parent is *this (must be a ruby run or generated content or anonymous block),
// just use the normal remove method.
- if (child->isRubyRun() || child->isBeforeContent() || child->isAfterContent()) {
+ if (child->parent() == this) {
+ ASSERT(child->isRubyRun() || child->isBeforeContent() || child->isAfterContent() || isAnonymousRubyInlineBlock(child));
RenderBlock::removeChild(child);
return;
}
+ // If the child's parent is an anoymous block (must be generated :before/:after content)
+ // just use the block's remove method.
+ if (isAnonymousRubyInlineBlock(child->parent())) {
+ ASSERT(child->isBeforeContent() || child->isAfterContent());
+ child->parent()->removeChild(child);
+ removeChild(child->parent());
+ return;
+ }
// Otherwise find the containing run and remove it from there.
- ASSERT(child->parent() != this);
RenderRubyRun* run = findRubyRunParent(child);
ASSERT(run);
run->removeChild(child);
diff --git a/Source/WebCore/rendering/RenderRuby.h b/Source/WebCore/rendering/RenderRuby.h
index 49a84d8..24ac0db 100644
--- a/Source/WebCore/rendering/RenderRuby.h
+++ b/Source/WebCore/rendering/RenderRuby.h
@@ -47,6 +47,8 @@ namespace WebCore {
// 1-n inline object(s)
//
// Note: <rp> elements are defined as having 'display:none' and thus normally are not assigned a renderer.
+//
+// Generated :before/:after content is shunted into anonymous inline blocks
// <ruby> when used as 'display:inline'
class RenderRubyAsInline : public RenderInline {
@@ -54,7 +56,6 @@ public:
RenderRubyAsInline(Node*);
virtual ~RenderRubyAsInline();
- virtual bool isChildAllowed(RenderObject*, RenderStyle*) const;
virtual void addChild(RenderObject* child, RenderObject* beforeChild = 0);
virtual void removeChild(RenderObject* child);
@@ -71,7 +72,6 @@ public:
RenderRubyAsBlock(Node*);
virtual ~RenderRubyAsBlock();
- virtual bool isChildAllowed(RenderObject*, RenderStyle*) const;
virtual void addChild(RenderObject* child, RenderObject* beforeChild = 0);
virtual void removeChild(RenderObject* child);
diff --git a/Source/WebCore/rendering/RenderRubyRun.cpp b/Source/WebCore/rendering/RenderRubyRun.cpp
index 3504ccf..1329d65 100644
--- a/Source/WebCore/rendering/RenderRubyRun.cpp
+++ b/Source/WebCore/rendering/RenderRubyRun.cpp
@@ -268,4 +268,41 @@ void RenderRubyRun::layout()
computeOverflow(clientLogicalBottom());
}
+void RenderRubyRun::getOverhang(bool firstLine, RenderObject* startRenderer, RenderObject* endRenderer, int& startOverhang, int& endOverhang) const
+{
+ ASSERT(!needsLayout());
+
+ startOverhang = 0;
+ endOverhang = 0;
+
+ RenderRubyBase* rubyBase = this->rubyBase();
+ RenderRubyText* rubyText = this->rubyText();
+
+ if (!rubyBase || !rubyText)
+ return;
+
+ if (!rubyBase->firstRootBox())
+ return;
+
+ int logicalWidth = this->logicalWidth();
+
+ // No more than half a ruby is allowed to overhang.
+ int logicalLeftOverhang = rubyText->style(firstLine)->fontSize() / 2;
+ int logicalRightOverhang = logicalLeftOverhang;
+
+ for (RootInlineBox* rootInlineBox = rubyBase->firstRootBox(); rootInlineBox; rootInlineBox = rootInlineBox->nextRootBox()) {
+ logicalLeftOverhang = min<int>(logicalLeftOverhang, rootInlineBox->logicalLeft());
+ logicalRightOverhang = min<int>(logicalRightOverhang, logicalWidth - rootInlineBox->logicalRight());
+ }
+
+ startOverhang = style()->isLeftToRightDirection() ? logicalLeftOverhang : logicalRightOverhang;
+ endOverhang = style()->isLeftToRightDirection() ? logicalRightOverhang : logicalLeftOverhang;
+
+ if (!startRenderer || !startRenderer->isText() || startRenderer->style(firstLine)->fontSize() > rubyBase->style(firstLine)->fontSize())
+ startOverhang = 0;
+
+ if (!endRenderer || !endRenderer->isText() || endRenderer->style(firstLine)->fontSize() > rubyBase->style(firstLine)->fontSize())
+ endOverhang = 0;
+}
+
} // namespace WebCore
diff --git a/Source/WebCore/rendering/RenderRubyRun.h b/Source/WebCore/rendering/RenderRubyRun.h
index 53209bc..f65ad86 100644
--- a/Source/WebCore/rendering/RenderRubyRun.h
+++ b/Source/WebCore/rendering/RenderRubyRun.h
@@ -63,6 +63,8 @@ public:
virtual RenderBlock* firstLineBlock() const;
virtual void updateFirstLetter();
+ void getOverhang(bool firstLine, RenderObject* startRenderer, RenderObject* endRenderer, int& startOverhang, int& endOverhang) const;
+
static RenderRubyRun* staticCreateRubyRun(const RenderObject* parentRuby);
protected:
@@ -75,6 +77,20 @@ private:
virtual void removeLeftoverAnonymousBlock(RenderBlock*) { }
};
+inline RenderRubyRun* toRenderRubyRun(RenderObject* object)
+{
+ ASSERT(!object || object->isRubyRun());
+ return static_cast<RenderRubyRun*>(object);
+}
+
+inline const RenderRubyRun* toRenderRubyRun(const RenderObject* object)
+{
+ ASSERT(!object || object->isBox());
+ return static_cast<const RenderRubyRun*>(object);
+}
+
+void toRenderRubyRun(const RenderRubyRun*);
+
} // namespace WebCore
#endif // RenderRubyRun_h
diff --git a/Source/WebCore/rendering/RenderSlider.cpp b/Source/WebCore/rendering/RenderSlider.cpp
index 1661b7a..ad5ab1a 100644
--- a/Source/WebCore/rendering/RenderSlider.cpp
+++ b/Source/WebCore/rendering/RenderSlider.cpp
@@ -33,6 +33,7 @@
#include "HTMLParserIdioms.h"
#include "MediaControlElements.h"
#include "MouseEvent.h"
+#include "Node.h"
#include "RenderLayer.h"
#include "RenderTheme.h"
#include "RenderView.h"
@@ -101,7 +102,7 @@ void RenderSlider::computePreferredLogicalWidths()
IntRect RenderSlider::thumbRect()
{
- SliderThumbElement* thumbElement = sliderThumbElement();
+ SliderThumbElement* thumbElement = shadowSliderThumb();
if (!thumbElement)
return IntRect();
@@ -128,7 +129,7 @@ void RenderSlider::layout()
{
ASSERT(needsLayout());
- SliderThumbElement* thumbElement = sliderThumbElement();
+ SliderThumbElement* thumbElement = shadowSliderThumb();
RenderBox* thumb = thumbElement ? toRenderBox(thumbElement->renderer()) : 0;
IntSize baseSize(borderAndPaddingWidth(), borderAndPaddingHeight());
@@ -176,14 +177,15 @@ void RenderSlider::layout()
setNeedsLayout(false);
}
-SliderThumbElement* RenderSlider::sliderThumbElement() const
+SliderThumbElement* RenderSlider::shadowSliderThumb() const
{
- return toSliderThumbElement(static_cast<Element*>(node())->shadowRoot());
+ Node* shadow = static_cast<Element*>(node())->shadowRoot();
+ return shadow ? toSliderThumbElement(shadow->firstChild()) : 0;
}
bool RenderSlider::inDragMode() const
{
- SliderThumbElement* thumbElement = sliderThumbElement();
+ SliderThumbElement* thumbElement = shadowSliderThumb();
return thumbElement && thumbElement->inDragMode();
}
diff --git a/Source/WebCore/rendering/RenderSlider.h b/Source/WebCore/rendering/RenderSlider.h
index 0162b71..4e17f30 100644
--- a/Source/WebCore/rendering/RenderSlider.h
+++ b/Source/WebCore/rendering/RenderSlider.h
@@ -46,8 +46,8 @@ namespace WebCore {
virtual void layout();
// FIXME: Eventually, the logic of manipulating slider thumb should move to
- // SliderThumbElement and accessing sliderThumbElement should not be necessary in this class.
- SliderThumbElement* sliderThumbElement() const;
+ // SliderThumbElement and accessing shadowSliderThumb should not be necessary in this class.
+ SliderThumbElement* shadowSliderThumb() const;
virtual bool requiresForcedStyleRecalcPropagation() const { return true; }
};
diff --git a/Source/WebCore/rendering/RenderTableRow.cpp b/Source/WebCore/rendering/RenderTableRow.cpp
index a29f218..2edcfc4 100644
--- a/Source/WebCore/rendering/RenderTableRow.cpp
+++ b/Source/WebCore/rendering/RenderTableRow.cpp
@@ -63,17 +63,23 @@ void RenderTableRow::styleWillChange(StyleDifference diff, const RenderStyle* ne
RenderBox::styleWillChange(diff, newStyle);
}
-void RenderTableRow::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
+void RenderTableRow::updateBeforeAndAfterContent()
{
- RenderBox::styleDidChange(diff, oldStyle);
-
- // Update pseudos for :before and :after now.
if (!isAnonymous() && document()->usesBeforeAfterRules()) {
children()->updateBeforeAfterContent(this, BEFORE);
children()->updateBeforeAfterContent(this, AFTER);
}
}
+void RenderTableRow::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
+{
+ RenderBox::styleDidChange(diff, oldStyle);
+
+ if (parent())
+ updateBeforeAndAfterContent();
+
+}
+
void RenderTableRow::addChild(RenderObject* child, RenderObject* beforeChild)
{
// Make sure we don't append things after :after-generated content if we have it.
diff --git a/Source/WebCore/rendering/RenderTableRow.h b/Source/WebCore/rendering/RenderTableRow.h
index 2af8dcb..570a7f2 100644
--- a/Source/WebCore/rendering/RenderTableRow.h
+++ b/Source/WebCore/rendering/RenderTableRow.h
@@ -39,6 +39,8 @@ public:
RenderTableSection* section() const { return toRenderTableSection(parent()); }
RenderTable* table() const { return toRenderTable(parent()->parent()); }
+ void updateBeforeAndAfterContent();
+
private:
virtual RenderObjectChildList* virtualChildren() { return children(); }
virtual const RenderObjectChildList* virtualChildren() const { return children(); }
diff --git a/Source/WebCore/rendering/RenderTableSection.cpp b/Source/WebCore/rendering/RenderTableSection.cpp
index 7c0a768..06d326f 100644
--- a/Source/WebCore/rendering/RenderTableSection.cpp
+++ b/Source/WebCore/rendering/RenderTableSection.cpp
@@ -148,6 +148,7 @@ void RenderTableSection::addChild(RenderObject* child, RenderObject* beforeChild
ASSERT(!beforeChild || beforeChild->isTableRow());
RenderBox::addChild(child, beforeChild);
+ toRenderTableRow(child)->updateBeforeAndAfterContent();
}
void RenderTableSection::removeChild(RenderObject* oldChild)
diff --git a/Source/WebCore/rendering/RenderText.cpp b/Source/WebCore/rendering/RenderText.cpp
index e660875..b35820a 100644
--- a/Source/WebCore/rendering/RenderText.cpp
+++ b/Source/WebCore/rendering/RenderText.cpp
@@ -177,7 +177,7 @@ void RenderText::styleDidChange(StyleDifference diff, const RenderStyle* oldStyl
}
}
-void RenderText::destroy()
+void RenderText::removeAndDestroyTextBoxes()
{
if (!documentBeingDestroyed()) {
if (firstTextBox()) {
@@ -192,6 +192,11 @@ void RenderText::destroy()
parent()->dirtyLinesFromChangedChild(this);
}
deleteTextBoxes();
+}
+
+void RenderText::destroy()
+{
+ removeAndDestroyTextBoxes();
RenderObject::destroy();
}
@@ -268,7 +273,7 @@ PassRefPtr<StringImpl> RenderText::originalText() const
void RenderText::absoluteRects(Vector<IntRect>& rects, int tx, int ty)
{
for (InlineTextBox* box = firstTextBox(); box; box = box->nextTextBox())
- rects.append(IntRect(tx + box->x(), ty + box->y(), box->logicalWidth(), box->logicalHeight()));
+ rects.append(enclosingIntRect(FloatRect(tx + box->x(), ty + box->y(), box->width(), box->height())));
}
void RenderText::absoluteRectsForRange(Vector<IntRect>& rects, unsigned start, unsigned end, bool useSelectionHeight)
@@ -1300,15 +1305,38 @@ IntRect RenderText::linesBoundingBox() const
return result;
}
-IntRect RenderText::clippedOverflowRectForRepaint(RenderBoxModelObject* repaintContainer)
+IntRect RenderText::linesVisualOverflowBoundingBox() const
{
- RenderObject* cb = containingBlock();
- // The containing block may be an ancestor of repaintContainer, but we need to do a repaintContainer-relative repaint.
- if (repaintContainer && repaintContainer != cb) {
- if (!cb->isDescendantOf(repaintContainer))
- return repaintContainer->clippedOverflowRectForRepaint(repaintContainer);
+ if (!firstTextBox())
+ return IntRect();
+
+ // Return the width of the minimal left side and the maximal right side.
+ int logicalLeftSide = numeric_limits<int>::max();
+ int logicalRightSide = numeric_limits<int>::min();
+ for (InlineTextBox* curr = firstTextBox(); curr; curr = curr->nextTextBox()) {
+ logicalLeftSide = min(logicalLeftSide, curr->logicalLeftVisualOverflow());
+ logicalRightSide = max(logicalRightSide, curr->logicalRightVisualOverflow());
}
- return cb->clippedOverflowRectForRepaint(repaintContainer);
+
+ int logicalTop = firstTextBox()->logicalTopVisualOverflow();
+ int logicalWidth = logicalRightSide - logicalLeftSide;
+ int logicalHeight = lastTextBox()->logicalBottomVisualOverflow() - logicalTop;
+
+ IntRect rect(logicalLeftSide, logicalTop, logicalWidth, logicalHeight);
+ if (!style()->isHorizontalWritingMode())
+ rect = rect.transposedRect();
+ return rect;
+}
+
+IntRect RenderText::clippedOverflowRectForRepaint(RenderBoxModelObject* repaintContainer)
+{
+ bool repaintContainerSkipped;
+ RenderObject* container = this->container(repaintContainer, &repaintContainerSkipped);
+ // The container may be an ancestor of repaintContainer, but we need to do a repaintContainer-relative repaint.
+ if (repaintContainerSkipped)
+ return repaintContainer->clippedOverflowRectForRepaint(repaintContainer);
+
+ return container->clippedOverflowRectForRepaint(repaintContainer);
}
IntRect RenderText::selectionRectForRepaint(RenderBoxModelObject* repaintContainer, bool clipToVisibleContent)
diff --git a/Source/WebCore/rendering/RenderText.h b/Source/WebCore/rendering/RenderText.h
index 7fa3518..2008dad 100644
--- a/Source/WebCore/rendering/RenderText.h
+++ b/Source/WebCore/rendering/RenderText.h
@@ -85,6 +85,7 @@ public:
float& minW, float& maxW, bool& stripFrontSpaces);
virtual IntRect linesBoundingBox() const;
+ IntRect linesVisualOverflowBoundingBox() const;
FloatPoint firstRunOrigin() const;
float firstRunX() const;
@@ -127,6 +128,8 @@ public:
bool knownToHaveNoOverflowAndNoFallbackFonts() const { return m_knownToHaveNoOverflowAndNoFallbackFonts; }
+ void removeAndDestroyTextBoxes();
+
protected:
virtual void styleWillChange(StyleDifference, const RenderStyle*) { }
virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
diff --git a/Source/WebCore/rendering/RenderTextControlSingleLine.cpp b/Source/WebCore/rendering/RenderTextControlSingleLine.cpp
index b9697ff..c5a47fb 100644
--- a/Source/WebCore/rendering/RenderTextControlSingleLine.cpp
+++ b/Source/WebCore/rendering/RenderTextControlSingleLine.cpp
@@ -424,10 +424,6 @@ void RenderTextControlSingleLine::forwardEvent(Event* event)
m_resultsButton->defaultEventHandler(event);
else if (m_cancelButton && localPoint.x() > textRight)
m_cancelButton->defaultEventHandler(event);
- else if (m_innerSpinButton && localPoint.x() > textRight && m_innerSpinButton->renderBox() && localPoint.x() < textRight + m_innerSpinButton->renderBox()->width())
- m_innerSpinButton->defaultEventHandler(event);
- else if (m_outerSpinButton && localPoint.x() > textRight)
- m_outerSpinButton->defaultEventHandler(event);
else
RenderTextControl::forwardEvent(event);
}
diff --git a/Source/WebCore/rendering/RenderTheme.cpp b/Source/WebCore/rendering/RenderTheme.cpp
index f254c99..6617d18 100644
--- a/Source/WebCore/rendering/RenderTheme.cpp
+++ b/Source/WebCore/rendering/RenderTheme.cpp
@@ -485,33 +485,6 @@ bool RenderTheme::paintDecorations(RenderObject* o, const PaintInfo& paintInfo,
}
#if ENABLE(VIDEO)
-bool RenderTheme::hitTestMediaControlPart(RenderObject* o, const IntPoint& absPoint)
-{
- if (!o->isBox())
- return false;
-
- FloatPoint localPoint = o->absoluteToLocal(absPoint, false, true); // respect transforms
- return toRenderBox(o)->borderBoxRect().contains(roundedIntPoint(localPoint));
-}
-
-bool RenderTheme::shouldRenderMediaControlPart(ControlPart part, Element* e)
-{
- HTMLMediaElement* mediaElement = static_cast<HTMLMediaElement*>(e);
- switch (part) {
- case MediaMuteButtonPart:
- return mediaElement->hasAudio();
- case MediaRewindButtonPart:
- return mediaElement->movieLoadType() != MediaPlayer::LiveStream;
- case MediaReturnToRealtimeButtonPart:
- return mediaElement->movieLoadType() == MediaPlayer::LiveStream;
- case MediaFullscreenButtonPart:
- return mediaElement->supportsFullscreen();
- case MediaToggleClosedCaptionsButtonPart:
- return mediaElement->hasClosedCaptions();
- default:
- return true;
- }
-}
String RenderTheme::formatMediaControlsTime(float time) const
{
@@ -968,7 +941,7 @@ IntSize RenderTheme::meterSizeForBounds(const RenderMeter*, const IntRect& bound
return bounds.size();
}
-bool RenderTheme::supportsMeter(ControlPart, bool) const
+bool RenderTheme::supportsMeter(ControlPart) const
{
return false;
}
diff --git a/Source/WebCore/rendering/RenderTheme.h b/Source/WebCore/rendering/RenderTheme.h
index 53c23e3..f18e247 100644
--- a/Source/WebCore/rendering/RenderTheme.h
+++ b/Source/WebCore/rendering/RenderTheme.h
@@ -181,9 +181,10 @@ public:
#if ENABLE(VIDEO)
// Media controls
- virtual bool hitTestMediaControlPart(RenderObject*, const IntPoint& absPoint);
- virtual bool shouldRenderMediaControlPart(ControlPart, Element*);
+ virtual bool supportsClosedCaptioning() const { return false; }
+ virtual bool hasOwnDisabledStateHandlingFor(ControlPart) const { return false; }
virtual bool usesMediaControlStatusDisplay() { return false; }
+ virtual bool usesMediaControlVolumeSlider() const { return true; }
virtual double mediaControlsFadeInDuration() { return 0.1; }
virtual double mediaControlsFadeOutDuration() { return 0.3; }
virtual String formatMediaControlsTime(float time) const;
@@ -196,7 +197,7 @@ public:
#if ENABLE(METER_TAG)
virtual IntSize meterSizeForBounds(const RenderMeter*, const IntRect&) const;
- virtual bool supportsMeter(ControlPart, bool isHorizontal) const;
+ virtual bool supportsMeter(ControlPart) const;
#endif
virtual bool shouldShowPlaceholderWhenFocused() const { return false; }
diff --git a/Source/WebCore/rendering/RenderThemeChromiumLinux.cpp b/Source/WebCore/rendering/RenderThemeChromiumLinux.cpp
index 72ea7cb..c3f15c8 100644
--- a/Source/WebCore/rendering/RenderThemeChromiumLinux.cpp
+++ b/Source/WebCore/rendering/RenderThemeChromiumLinux.cpp
@@ -274,7 +274,8 @@ bool RenderThemeChromiumLinux::paintMenuList(RenderObject* o, const PaintInfo& i
// Match Chromium Win behaviour of showing all borders if any are shown.
extraParams.menuList.hasBorder = box->borderRight() || box->borderLeft() || box->borderTop() || box->borderBottom();
extraParams.menuList.hasBorderRadius = o->style()->hasBorderRadius();
- extraParams.menuList.backgroundColor = SkColorSetRGB(0xdd, 0xdd, 0xdd);
+ // Fallback to transparent if the specified color object is invalid.
+ extraParams.menuList.backgroundColor = Color::transparent;
if (o->hasBackground())
extraParams.menuList.backgroundColor = o->style()->visitedDependentColor(CSSPropertyBackgroundColor).rgb();
diff --git a/Source/WebCore/rendering/RenderThemeChromiumMac.h b/Source/WebCore/rendering/RenderThemeChromiumMac.h
index 4fd371f..dcb23dd 100644
--- a/Source/WebCore/rendering/RenderThemeChromiumMac.h
+++ b/Source/WebCore/rendering/RenderThemeChromiumMac.h
@@ -38,16 +38,18 @@ protected:
virtual bool paintMediaMuteButton(RenderObject*, const PaintInfo&, const IntRect&);
virtual bool paintMediaSliderTrack(RenderObject*, const PaintInfo&, const IntRect&);
virtual bool paintMediaControlsBackground(RenderObject*, const PaintInfo&, const IntRect&);
- virtual bool shouldRenderMediaControlPart(ControlPart, Element*);
virtual String extraMediaControlsStyleSheet();
-
+#if ENABLE(FULLSCREEN_API)
+ virtual String extraFullScreenStyleSheet();
+#endif
+
virtual bool paintMediaSliderThumb(RenderObject*, const PaintInfo&, const IntRect&);
virtual bool paintMediaVolumeSliderContainer(RenderObject*, const PaintInfo&, const IntRect&);
virtual bool paintMediaVolumeSliderTrack(RenderObject*, const PaintInfo&, const IntRect&);
virtual bool paintMediaVolumeSliderThumb(RenderObject*, const PaintInfo&, const IntRect&);
virtual IntPoint volumeSliderOffsetFromMuteButton(RenderBox*, const IntSize&) const;
virtual bool usesMediaControlStatusDisplay() { return false; }
-
+ virtual bool hasOwnDisabledStateHandlingFor(ControlPart) const { return true; }
#endif
virtual bool usesTestModeFocusRingColor() const;
diff --git a/Source/WebCore/rendering/RenderThemeChromiumMac.mm b/Source/WebCore/rendering/RenderThemeChromiumMac.mm
index a7d59a9..e4a10ae 100644
--- a/Source/WebCore/rendering/RenderThemeChromiumMac.mm
+++ b/Source/WebCore/rendering/RenderThemeChromiumMac.mm
@@ -105,11 +105,6 @@ void RenderThemeChromiumMac::adjustMediaSliderThumbSize(RenderObject* o) const
RenderMediaControlsChromium::adjustMediaSliderThumbSize(o);
}
-bool RenderThemeChromiumMac::shouldRenderMediaControlPart(ControlPart part, Element* e)
-{
- return RenderMediaControlsChromium::shouldRenderMediaControlPart(part, e);
-}
-
bool RenderThemeChromiumMac::paintMediaPlayButton(RenderObject* object, const PaintInfo& paintInfo, const IntRect& rect)
{
return RenderMediaControlsChromium::paintMediaControlsPart(MediaPlayButton, object, paintInfo, rect);
@@ -135,6 +130,14 @@ String RenderThemeChromiumMac::extraMediaControlsStyleSheet()
return String(mediaControlsChromiumUserAgentStyleSheet, sizeof(mediaControlsChromiumUserAgentStyleSheet));
}
+#if ENABLE(FULLSCREEN_API)
+String RenderThemeChromiumMac::extraFullScreenStyleSheet()
+{
+ // FIXME: Chromium may wish to style its default media controls differently in fullscreen.
+ return String();
+}
+#endif
+
bool RenderThemeChromiumMac::paintMediaVolumeSliderContainer(RenderObject* object, const PaintInfo& paintInfo, const IntRect& rect)
{
return true;
diff --git a/Source/WebCore/rendering/RenderThemeChromiumSkia.cpp b/Source/WebCore/rendering/RenderThemeChromiumSkia.cpp
index 9691876..cafc34d 100644
--- a/Source/WebCore/rendering/RenderThemeChromiumSkia.cpp
+++ b/Source/WebCore/rendering/RenderThemeChromiumSkia.cpp
@@ -501,13 +501,6 @@ int RenderThemeChromiumSkia::popupInternalPaddingBottom(RenderStyle* style) cons
return menuListInternalPadding(style, BottomPadding);
}
-#if ENABLE(VIDEO)
-bool RenderThemeChromiumSkia::shouldRenderMediaControlPart(ControlPart part, Element* e)
-{
- return RenderMediaControlsChromium::shouldRenderMediaControlPart(part, e);
-}
-#endif
-
// static
void RenderThemeChromiumSkia::setDefaultFontSize(int fontSize)
{
diff --git a/Source/WebCore/rendering/RenderThemeChromiumSkia.h b/Source/WebCore/rendering/RenderThemeChromiumSkia.h
index bf0af34..2faf064 100644
--- a/Source/WebCore/rendering/RenderThemeChromiumSkia.h
+++ b/Source/WebCore/rendering/RenderThemeChromiumSkia.h
@@ -123,7 +123,7 @@ class RenderThemeChromiumSkia : public RenderTheme {
#if ENABLE(VIDEO)
// Media controls
- virtual bool shouldRenderMediaControlPart(ControlPart, Element*);
+ virtual bool hasOwnDisabledStateHandlingFor(ControlPart) const { return true; }
#endif
// Provide a way to pass the default font size from the Settings object
diff --git a/Source/WebCore/rendering/RenderThemeMac.h b/Source/WebCore/rendering/RenderThemeMac.h
index d64944b..8a17acf 100644
--- a/Source/WebCore/rendering/RenderThemeMac.h
+++ b/Source/WebCore/rendering/RenderThemeMac.h
@@ -83,7 +83,7 @@ public:
#if ENABLE(METER_TAG)
virtual IntSize meterSizeForBounds(const RenderMeter*, const IntRect&) const;
virtual bool paintMeter(RenderObject*, const PaintInfo&, const IntRect&);
- virtual bool supportsMeter(ControlPart, bool isHorizontal) const;
+ virtual bool supportsMeter(ControlPart) const;
#endif
#if ENABLE(PROGRESS_TAG)
@@ -166,8 +166,10 @@ protected:
virtual String extraFullScreenStyleSheet();
#endif
- virtual bool shouldRenderMediaControlPart(ControlPart, Element*);
+ virtual bool supportsClosedCaptioning() const { return true; }
+ virtual bool hasOwnDisabledStateHandlingFor(ControlPart) const;
virtual bool usesMediaControlStatusDisplay();
+ virtual bool usesMediaControlVolumeSlider() const;
virtual void adjustMediaSliderThumbSize(RenderObject*) const;
virtual IntPoint volumeSliderOffsetFromMuteButton(RenderBox*, const IntSize&) const;
#endif
diff --git a/Source/WebCore/rendering/RenderThemeMac.mm b/Source/WebCore/rendering/RenderThemeMac.mm
index 0e23c89..a6f999a 100644
--- a/Source/WebCore/rendering/RenderThemeMac.mm
+++ b/Source/WebCore/rendering/RenderThemeMac.mm
@@ -830,10 +830,6 @@ bool RenderThemeMac::paintMeter(RenderObject* renderObject, const PaintInfo& pai
LocalCurrentGraphicsContext localContext(paintInfo.context);
- // Becaue NSLevelIndicatorCell doesn't support vertical gauge, we use a portable version
- if (rect.width() < rect.height())
- return RenderTheme::paintMeter(renderObject, paintInfo, rect);
-
NSLevelIndicatorCell* cell = levelIndicatorFor(toRenderMeter(renderObject));
paintInfo.context->save();
[cell drawWithFrame:rect inView:documentViewFor(renderObject)];
@@ -843,7 +839,7 @@ bool RenderThemeMac::paintMeter(RenderObject* renderObject, const PaintInfo& pai
return false;
}
-bool RenderThemeMac::supportsMeter(ControlPart part, bool isHorizontal) const
+bool RenderThemeMac::supportsMeter(ControlPart part) const
{
switch (part) {
case RelevancyLevelIndicatorPart:
@@ -851,7 +847,7 @@ bool RenderThemeMac::supportsMeter(ControlPart part, bool isHorizontal) const
case RatingLevelIndicatorPart:
case MeterPart:
case ContinuousCapacityLevelIndicatorPart:
- return isHorizontal;
+ return true;
default:
return false;
}
@@ -1976,35 +1972,12 @@ String RenderThemeMac::extraFullScreenStyleSheet()
}
#endif
-bool RenderThemeMac::shouldRenderMediaControlPart(ControlPart part, Element* element)
+bool RenderThemeMac::hasOwnDisabledStateHandlingFor(ControlPart part) const
{
- HTMLMediaElement* mediaElement = static_cast<HTMLMediaElement*>(element);
- switch (part) {
- case MediaVolumeSliderContainerPart:
- case MediaVolumeSliderPart:
- case MediaVolumeSliderMuteButtonPart:
- case MediaVolumeSliderThumbPart: {
- return mediaControllerTheme() == MediaControllerThemeQuickTime && mediaElement->hasAudio();
- }
- case MediaToggleClosedCaptionsButtonPart:
- // We rely on QTKit to render captions so don't enable the button unless it will be able to do so.
- if (!element->hasTagName(videoTag))
- return false;
- break;
- case MediaRewindButtonPart:
- if (mediaElement->isFullscreen())
- return mediaElement->movieLoadType() == MediaPlayer::LiveStream
- || mediaElement->movieLoadType() == MediaPlayer::StoredStream;
- case MediaSeekForwardButtonPart:
- case MediaSeekBackButtonPart:
- if (mediaElement->isFullscreen())
- return mediaElement->movieLoadType() != MediaPlayer::StoredStream
- && mediaElement->movieLoadType() != MediaPlayer::LiveStream;
- default:
- break;
- }
+ if (part == MediaMuteButtonPart)
+ return false;
- return RenderTheme::shouldRenderMediaControlPart(part, element);
+ return mediaControllerTheme() == MediaControllerThemeClassic;
}
bool RenderThemeMac::usesMediaControlStatusDisplay()
@@ -2012,6 +1985,11 @@ bool RenderThemeMac::usesMediaControlStatusDisplay()
return mediaControllerTheme() == MediaControllerThemeQuickTime;
}
+bool RenderThemeMac::usesMediaControlVolumeSlider() const
+{
+ return mediaControllerTheme() == MediaControllerThemeQuickTime;
+}
+
IntPoint RenderThemeMac::volumeSliderOffsetFromMuteButton(RenderBox* muteButtonBox, const IntSize& size) const
{
return RenderMediaControls::volumeSliderOffsetFromMuteButton(muteButtonBox, size);
diff --git a/Source/WebCore/rendering/RenderThemeWin.cpp b/Source/WebCore/rendering/RenderThemeWin.cpp
index af100b7..15f64c5 100644
--- a/Source/WebCore/rendering/RenderThemeWin.cpp
+++ b/Source/WebCore/rendering/RenderThemeWin.cpp
@@ -1029,22 +1029,16 @@ String RenderThemeWin::extraMediaControlsStyleSheet()
return String(mediaControlsQuickTimeUserAgentStyleSheet, sizeof(mediaControlsQuickTimeUserAgentStyleSheet));
}
-bool RenderThemeWin::shouldRenderMediaControlPart(ControlPart part, Element* element)
+bool RenderThemeWin::supportsClosedCaptioning() const
{
- if (part == MediaToggleClosedCaptionsButtonPart) {
// We rely on QuickTime to render captions so only enable the button for a video element.
#if SAFARI_THEME_VERSION >= 4
- if (!element->hasTagName(videoTag))
- return false;
+ return true;
#else
- return false;
+ return false;
#endif
- }
-
- return RenderTheme::shouldRenderMediaControlPart(part, element);
}
-
bool RenderThemeWin::paintMediaFullscreenButton(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
{
return RenderMediaControls::paintMediaControlsPart(MediaFullscreenButton, o, paintInfo, r);
diff --git a/Source/WebCore/rendering/RenderThemeWin.h b/Source/WebCore/rendering/RenderThemeWin.h
index 7e0223a..7e8a491 100644
--- a/Source/WebCore/rendering/RenderThemeWin.h
+++ b/Source/WebCore/rendering/RenderThemeWin.h
@@ -124,7 +124,7 @@ public:
#if ENABLE(VIDEO)
virtual String extraMediaControlsStyleSheet();
- virtual bool shouldRenderMediaControlPart(ControlPart, Element*);
+ virtual bool supportsClosedCaptioning() const;
virtual bool paintMediaControlsBackground(RenderObject*, const PaintInfo&, const IntRect&);
virtual bool paintMediaFullscreenButton(RenderObject*, const PaintInfo&, const IntRect&);
virtual bool paintMediaMuteButton(RenderObject*, const PaintInfo&, const IntRect&);
diff --git a/Source/WebCore/rendering/RenderTreeAsText.cpp b/Source/WebCore/rendering/RenderTreeAsText.cpp
index 8857391..2f5bd74 100644
--- a/Source/WebCore/rendering/RenderTreeAsText.cpp
+++ b/Source/WebCore/rendering/RenderTreeAsText.cpp
@@ -722,7 +722,10 @@ static String nodePosition(Node* node)
result += "body";
break;
}
- result += "child " + String::number(n->nodeIndex()) + " {" + getTagName(n) + "}";
+ if (n->isShadowBoundary())
+ result += "{" + getTagName(n) + "}";
+ else
+ result += "child " + String::number(n->nodeIndex()) + " {" + getTagName(n) + "}";
} else
result += "document";
}
diff --git a/Source/WebCore/rendering/RenderView.cpp b/Source/WebCore/rendering/RenderView.cpp
index d25240b..20afefa 100644
--- a/Source/WebCore/rendering/RenderView.cpp
+++ b/Source/WebCore/rendering/RenderView.cpp
@@ -226,13 +226,17 @@ void RenderView::paintBoxDecorations(PaintInfo& paintInfo, int, int)
RenderBox* rootBox = rootRenderer->isBox() ? toRenderBox(rootRenderer) : 0;
rootFillsViewport = rootBox && !rootBox->x() && !rootBox->y() && rootBox->width() >= width() && rootBox->height() >= height();
}
-
+
+ float pageScaleFactor = 1;
+ if (Frame* frame = m_frameView->frame())
+ pageScaleFactor = frame->pageScaleFactor();
+
// If painting will entirely fill the view, no need to fill the background.
- if (rootFillsViewport && rendererObscuresBackground(firstChild()))
+ if (rootFillsViewport && rendererObscuresBackground(firstChild()) && pageScaleFactor >= 1)
return;
// This code typically only executes if the root element's visibility has been set to hidden,
- // or there is a transform on the <html>.
+ // if there is a transform on the <html>, or if there is a page scale factor less than 1.
// Only fill with the base background color (typically white) if we're the root document,
// since iframes/frames with no background in the child document should show the parent's background.
if (frameView()->isTransparent()) // FIXME: This needs to be dynamic. We should be able to go back to blitting if we ever stop being transparent.
diff --git a/Source/WebCore/rendering/RenderWidget.cpp b/Source/WebCore/rendering/RenderWidget.cpp
index 33f6436..894d689 100644
--- a/Source/WebCore/rendering/RenderWidget.cpp
+++ b/Source/WebCore/rendering/RenderWidget.cpp
@@ -207,8 +207,10 @@ void RenderWidget::setWidget(PassRefPtr<Widget> widget)
setWidgetGeometry(IntRect(localToAbsoluteQuad(FloatQuad(contentBoxRect())).boundingBox()), contentBoxRect().size());
if (style()->visibility() != VISIBLE)
m_widget->hide();
- else
+ else {
m_widget->show();
+ repaint();
+ }
}
moveWidgetToParentSoon(m_widget.get(), m_frameView);
}
diff --git a/Source/WebCore/rendering/RenderingAllInOne.cpp b/Source/WebCore/rendering/RenderingAllInOne.cpp
index c9f6707..d0bb843 100644
--- a/Source/WebCore/rendering/RenderingAllInOne.cpp
+++ b/Source/WebCore/rendering/RenderingAllInOne.cpp
@@ -35,7 +35,6 @@
#include "InlineFlowBox.cpp"
#include "InlineTextBox.cpp"
#include "LayoutState.cpp"
-#include "MediaControlElements.cpp"
#include "PointerEventsHitRules.cpp"
#include "RenderApplet.cpp"
#include "RenderArena.cpp"
@@ -62,7 +61,6 @@
#include "RenderImage.cpp"
#include "RenderImageResource.cpp"
#include "RenderImageResourceStyleImage.cpp"
-#include "RenderIndicator.cpp"
#include "RenderInline.cpp"
#include "RenderLayer.cpp"
#include "RenderLayerCompositor.cpp"
diff --git a/Source/WebCore/rendering/RootInlineBox.cpp b/Source/WebCore/rendering/RootInlineBox.cpp
index c6f1bd8..b504684 100644
--- a/Source/WebCore/rendering/RootInlineBox.cpp
+++ b/Source/WebCore/rendering/RootInlineBox.cpp
@@ -133,11 +133,11 @@ float RootInlineBox::placeEllipsisBox(bool ltr, float blockLeftEdge, float block
return result;
}
-void RootInlineBox::paintEllipsisBox(PaintInfo& paintInfo, int tx, int ty) const
+void RootInlineBox::paintEllipsisBox(PaintInfo& paintInfo, int tx, int ty, int lineTop, int lineBottom) const
{
if (hasEllipsisBox() && paintInfo.shouldPaintWithinRoot(renderer()) && renderer()->style()->visibility() == VISIBLE
&& paintInfo.phase == PaintPhaseForeground)
- ellipsisBox()->paint(paintInfo, tx, ty);
+ ellipsisBox()->paint(paintInfo, tx, ty, lineTop, lineBottom);
}
#if PLATFORM(MAC)
@@ -154,7 +154,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));
- setOverflowFromLogicalRects(inflatedRect, inflatedRect);
+ setOverflowFromLogicalRects(inflatedRect, inflatedRect, lineTop(), lineBottom());
}
void RootInlineBox::paintCustomHighlight(PaintInfo& paintInfo, int tx, int ty, const AtomicString& highlightType)
@@ -178,10 +178,10 @@ void RootInlineBox::paintCustomHighlight(PaintInfo& paintInfo, int tx, int ty, c
#endif
-void RootInlineBox::paint(PaintInfo& paintInfo, int tx, int ty)
+void RootInlineBox::paint(PaintInfo& paintInfo, int tx, int ty, int lineTop, int lineBottom)
{
- InlineFlowBox::paint(paintInfo, tx, ty);
- paintEllipsisBox(paintInfo, tx, ty);
+ InlineFlowBox::paint(paintInfo, tx, ty, lineTop, lineBottom);
+ paintEllipsisBox(paintInfo, tx, ty, lineTop, lineBottom);
#if PLATFORM(MAC)
RenderStyle* styleToUse = renderer()->style(m_firstLine);
if (styleToUse->highlight() != nullAtom && !paintInfo.context->paintingDisabled())
@@ -189,15 +189,15 @@ void RootInlineBox::paint(PaintInfo& paintInfo, int tx, int ty)
#endif
}
-bool RootInlineBox::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, int x, int y, int tx, int ty)
+bool RootInlineBox::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, int x, int y, int tx, int ty, int lineTop, int lineBottom)
{
if (hasEllipsisBox() && visibleToHitTesting()) {
- if (ellipsisBox()->nodeAtPoint(request, result, x, y, tx, ty)) {
+ if (ellipsisBox()->nodeAtPoint(request, result, x, y, tx, ty, lineTop, lineBottom)) {
renderer()->updateHitTestResult(result, IntPoint(x - tx, y - ty));
return true;
}
}
- return InlineFlowBox::nodeAtPoint(request, result, x, y, tx, ty);
+ return InlineFlowBox::nodeAtPoint(request, result, x, y, tx, ty, lineTop, lineBottom);
}
void RootInlineBox::adjustPosition(float dx, float dy)
@@ -529,7 +529,7 @@ void RootInlineBox::attachLineBoxToRenderObject()
IntRect RootInlineBox::paddedLayoutOverflowRect(int endPadding) const
{
- IntRect lineLayoutOverflow = layoutOverflowRect();
+ IntRect lineLayoutOverflow = layoutOverflowRect(lineTop(), lineBottom());
if (!endPadding)
return lineLayoutOverflow;
@@ -785,7 +785,7 @@ bool RootInlineBox::includesRootLineBoxFontOrLeading() const
return (lineBoxContain & LineBoxContainBlock) || (lineBoxContain & LineBoxContainInline) || (lineBoxContain & LineBoxContainFont);
}
-Node* RootInlineBox::getLogicalStartBoxWithNode(InlineBox*& startBox)
+Node* RootInlineBox::getLogicalStartBoxWithNode(InlineBox*& startBox) const
{
Vector<InlineBox*> leafBoxesInLogicalOrder;
collectLeafBoxesInLogicalOrder(leafBoxesInLogicalOrder);
@@ -799,7 +799,7 @@ Node* RootInlineBox::getLogicalStartBoxWithNode(InlineBox*& startBox)
return 0;
}
-Node* RootInlineBox::getLogicalEndBoxWithNode(InlineBox*& endBox)
+Node* RootInlineBox::getLogicalEndBoxWithNode(InlineBox*& endBox) const
{
Vector<InlineBox*> leafBoxesInLogicalOrder;
collectLeafBoxesInLogicalOrder(leafBoxesInLogicalOrder);
diff --git a/Source/WebCore/rendering/RootInlineBox.h b/Source/WebCore/rendering/RootInlineBox.h
index 0ff5704..2564d85 100644
--- a/Source/WebCore/rendering/RootInlineBox.h
+++ b/Source/WebCore/rendering/RootInlineBox.h
@@ -83,8 +83,7 @@ public:
EllipsisBox* ellipsisBox() const;
- void paintEllipsisBox(PaintInfo&, int tx, int ty) const;
- bool hitTestEllipsisBox(HitTestResult&, int x, int y, int tx, int ty, HitTestAction, bool);
+ void paintEllipsisBox(PaintInfo&, int tx, int ty, int lineTop, int lineBottom) const;
virtual void clearTruncation();
@@ -96,8 +95,8 @@ public:
void paintCustomHighlight(PaintInfo&, int tx, int ty, const AtomicString& highlightType);
#endif
- virtual void paint(PaintInfo&, int tx, int ty);
- virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, int, int, int, int);
+ virtual void paint(PaintInfo&, int tx, int ty, int lineTop, int lineBottom);
+ virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, int x, int y, int tx, int ty, int lineTop, int lineBottom);
bool hasSelectedChildren() const { return m_hasSelectedChildrenOrCanHaveLeadingExpansion; }
void setHasSelectedChildren(bool hasSelectedChildren) { m_hasSelectedChildrenOrCanHaveLeadingExpansion = hasSelectedChildren; }
@@ -112,12 +111,13 @@ public:
InlineBox* closestLeafChildForLogicalLeftPosition(int, bool onlyEditableLeaves = false);
- Vector<RenderBox*>& floats()
+ void appendFloat(RenderBox* floatingBox)
{
ASSERT(!isDirty());
- if (!m_floats)
- m_floats= adoptPtr(new Vector<RenderBox*>);
- return *m_floats;
+ if (m_floats)
+ m_floats->append(floatingBox);
+ else
+ m_floats= adoptPtr(new Vector<RenderBox*>(1, floatingBox));
}
Vector<RenderBox*>* floatsPtr() { ASSERT(!isDirty()); return m_floats.get(); }
@@ -141,9 +141,26 @@ public:
bool includeMarginForBox(InlineBox*) const;
bool fitsToGlyphs() const;
bool includesRootLineBoxFontOrLeading() const;
+
+ int logicalTopVisualOverflow() const
+ {
+ return InlineFlowBox::logicalTopVisualOverflow(lineTop());
+ }
+ int logicalBottomVisualOverflow() const
+ {
+ return InlineFlowBox::logicalBottomVisualOverflow(lineBottom());
+ }
+ int logicalTopLayoutOverflow() const
+ {
+ return InlineFlowBox::logicalTopLayoutOverflow(lineTop());
+ }
+ int logicalBottomLayoutOverflow() const
+ {
+ return InlineFlowBox::logicalBottomLayoutOverflow(lineBottom());
+ }
- Node* getLogicalStartBoxWithNode(InlineBox*&);
- Node* getLogicalEndBoxWithNode(InlineBox*&);
+ Node* getLogicalStartBoxWithNode(InlineBox*&) const;
+ Node* getLogicalEndBoxWithNode(InlineBox*&) const;
private:
bool hasEllipsisBox() const { return m_hasEllipsisBoxOrHyphen; }
void setHasEllipsisBox(bool hasEllipsisBox) { m_hasEllipsisBoxOrHyphen = hasEllipsisBox; }
diff --git a/Source/WebCore/rendering/ShadowElement.cpp b/Source/WebCore/rendering/ShadowElement.cpp
index 5b1a962..955384a 100644
--- a/Source/WebCore/rendering/ShadowElement.cpp
+++ b/Source/WebCore/rendering/ShadowElement.cpp
@@ -29,85 +29,6 @@ namespace WebCore {
using namespace HTMLNames;
-PassRefPtr<ShadowBlockElement> ShadowBlockElement::create(HTMLElement* shadowParent)
-{
- return adoptRef(new ShadowBlockElement(shadowParent));
-}
-
-ShadowBlockElement::ShadowBlockElement(HTMLElement* shadowParent)
- : ShadowElement<HTMLDivElement>(divTag, shadowParent)
-{
-}
-
-void ShadowBlockElement::layoutAsPart(const IntRect& partRect)
-{
- RenderBox* parentRenderer = toRenderBox(renderer()->parent());
- RenderBox* selfRenderer = toRenderBox(renderer());
- IntRect oldRect = selfRenderer->frameRect();
-
- LayoutStateMaintainer statePusher(parentRenderer->view(), parentRenderer, parentRenderer->size(), parentRenderer->style()->isFlippedBlocksWritingMode());
-
- if (oldRect.size() != partRect.size())
- selfRenderer->setChildNeedsLayout(true, false);
-
- selfRenderer->layoutIfNeeded();
- selfRenderer->setFrameRect(partRect);
-
- if (selfRenderer->checkForRepaintDuringLayout())
- selfRenderer->repaintDuringLayoutIfMoved(oldRect);
-
- statePusher.pop();
- parentRenderer->addOverflowFromChild(selfRenderer);
-}
-
-void ShadowBlockElement::updateStyleForPart(PseudoId pseudoId)
-{
- if (renderer()->style()->styleType() != pseudoId)
- renderer()->setStyle(createStyleForPart(renderer()->parent(), pseudoId));
-}
-
-PassRefPtr<ShadowBlockElement> ShadowBlockElement::createForPart(HTMLElement* shadowParent, PseudoId pseudoId)
-{
- RefPtr<ShadowBlockElement> part = create(shadowParent);
- part->initAsPart(pseudoId);
- return part.release();
-}
-
-void ShadowBlockElement::initAsPart(PseudoId pseudoId)
-{
- RenderObject* parentRenderer = shadowHost()->renderer();
- RefPtr<RenderStyle> styleForPart = createStyleForPart(parentRenderer, pseudoId);
- setRenderer(createRenderer(parentRenderer->renderArena(), styleForPart.get()));
- renderer()->setStyle(styleForPart.release());
- setAttached();
- setInDocument();
-}
-
-PassRefPtr<RenderStyle> ShadowBlockElement::createStyleForPart(RenderObject* parentRenderer, PseudoId pseudoId)
-{
- RefPtr<RenderStyle> styleForPart;
- RenderStyle* pseudoStyle = parentRenderer->getCachedPseudoStyle(pseudoId);
- if (pseudoStyle)
- styleForPart = RenderStyle::clone(pseudoStyle);
- else
- styleForPart = RenderStyle::create();
-
- styleForPart->inheritFrom(parentRenderer->style());
- styleForPart->setDisplay(BLOCK);
- styleForPart->setAppearance(NoControlPart);
- return styleForPart.release();
-}
-
-bool ShadowBlockElement::partShouldHaveStyle(const RenderObject* parentRenderer, PseudoId pseudoId)
-{
- // We have some -webkit-appearance values for default styles of parts and
- // that appearance get turned off during RenderStyle creation
- // if they have background styles specified.
- // So !hasAppearance() implies that there are something to be styled.
- RenderStyle* pseudoStyle = parentRenderer->getCachedPseudoStyle(pseudoId);
- return !(pseudoStyle && pseudoStyle->hasAppearance());
-}
-
PassRefPtr<ShadowInputElement> ShadowInputElement::create(HTMLElement* shadowParent)
{
return adoptRef(new ShadowInputElement(shadowParent));
diff --git a/Source/WebCore/rendering/ShadowElement.h b/Source/WebCore/rendering/ShadowElement.h
index 9a5d118..0db6a83 100644
--- a/Source/WebCore/rendering/ShadowElement.h
+++ b/Source/WebCore/rendering/ShadowElement.h
@@ -61,21 +61,6 @@ void ShadowElement<BaseElement>::detach()
BaseElement::setShadowHost(0);
}
-class ShadowBlockElement : public ShadowElement<HTMLDivElement> {
-public:
- static PassRefPtr<ShadowBlockElement> create(HTMLElement*);
- static PassRefPtr<ShadowBlockElement> createForPart(HTMLElement*, PseudoId);
- static bool partShouldHaveStyle(const RenderObject* parentRenderer, PseudoId pseudoId);
- void layoutAsPart(const IntRect& partRect);
- virtual void updateStyleForPart(PseudoId);
-
-protected:
- ShadowBlockElement(HTMLElement*);
- void initAsPart(PseudoId pasuedId);
-private:
- static PassRefPtr<RenderStyle> createStyleForPart(RenderObject*, PseudoId);
-};
-
class ShadowInputElement : public ShadowElement<HTMLInputElement> {
public:
static PassRefPtr<ShadowInputElement> create(HTMLElement*);
diff --git a/Source/WebCore/rendering/style/RenderStyle.cpp b/Source/WebCore/rendering/style/RenderStyle.cpp
index 34e972d..60518f7 100644
--- a/Source/WebCore/rendering/style/RenderStyle.cpp
+++ b/Source/WebCore/rendering/style/RenderStyle.cpp
@@ -176,17 +176,17 @@ RenderStyle::~RenderStyle()
bool RenderStyle::operator==(const RenderStyle& o) const
{
// compare everything except the pseudoStyle pointer
- return inherited_flags == o.inherited_flags &&
- noninherited_flags == o.noninherited_flags &&
- m_box == o.m_box &&
- visual == o.visual &&
- m_background == o.m_background &&
- surround == o.surround &&
- rareNonInheritedData == o.rareNonInheritedData &&
- rareInheritedData == o.rareInheritedData &&
- inherited == o.inherited
+ return inherited_flags == o.inherited_flags
+ && noninherited_flags == o.noninherited_flags
+ && m_box == o.m_box
+ && visual == o.visual
+ && m_background == o.m_background
+ && surround == o.surround
+ && rareNonInheritedData == o.rareNonInheritedData
+ && rareInheritedData == o.rareInheritedData
+ && inherited == o.inherited
#if ENABLE(SVG)
- && m_svgStyle == o.m_svgStyle
+ && m_svgStyle == o.m_svgStyle
#endif
;
}
@@ -272,22 +272,22 @@ void RenderStyle::removeCachedPseudoStyle(PseudoId pid)
bool RenderStyle::inheritedNotEqual(const RenderStyle* other) const
{
- return inherited_flags != other->inherited_flags ||
- inherited != other->inherited ||
+ return inherited_flags != other->inherited_flags
+ || inherited != other->inherited
#if ENABLE(SVG)
- m_svgStyle->inheritedNotEqual(other->m_svgStyle.get()) ||
+ || m_svgStyle->inheritedNotEqual(other->m_svgStyle.get())
#endif
- rareInheritedData != other->rareInheritedData;
+ || rareInheritedData != other->rareInheritedData;
}
static bool positionedObjectMoved(const LengthBox& a, const LengthBox& b)
{
// If any unit types are different, then we can't guarantee
// that this was just a movement.
- if (a.left().type() != b.left().type() ||
- a.right().type() != b.right().type() ||
- a.top().type() != b.top().type() ||
- a.bottom().type() != b.bottom().type())
+ if (a.left().type() != b.left().type()
+ || a.right().type() != b.right().type()
+ || a.top().type() != b.top().type()
+ || a.bottom().type() != b.bottom().type())
return false;
// Only one unit can be non-auto in the horizontal direction and
@@ -316,12 +316,12 @@ StyleDifference RenderStyle::diff(const RenderStyle* other, unsigned& changedCon
}
#endif
- if (m_box->width() != other->m_box->width() ||
- m_box->minWidth() != other->m_box->minWidth() ||
- m_box->maxWidth() != other->m_box->maxWidth() ||
- m_box->height() != other->m_box->height() ||
- m_box->minHeight() != other->m_box->minHeight() ||
- m_box->maxHeight() != other->m_box->maxHeight())
+ if (m_box->width() != other->m_box->width()
+ || m_box->minWidth() != other->m_box->minWidth()
+ || m_box->maxWidth() != other->m_box->maxWidth()
+ || m_box->height() != other->m_box->height()
+ || m_box->minHeight() != other->m_box->minHeight()
+ || m_box->maxHeight() != other->m_box->maxHeight())
return StyleDifferenceLayout;
if (m_box->verticalAlign() != other->m_box->verticalAlign() || noninherited_flags._vertical_align != other->noninherited_flags._vertical_align)
@@ -337,15 +337,15 @@ StyleDifference RenderStyle::diff(const RenderStyle* other, unsigned& changedCon
return StyleDifferenceLayout;
if (rareNonInheritedData.get() != other->rareNonInheritedData.get()) {
- if (rareNonInheritedData->m_appearance != other->rareNonInheritedData->m_appearance ||
- rareNonInheritedData->marginBeforeCollapse != other->rareNonInheritedData->marginBeforeCollapse ||
- rareNonInheritedData->marginAfterCollapse != other->rareNonInheritedData->marginAfterCollapse ||
- rareNonInheritedData->lineClamp != other->rareNonInheritedData->lineClamp ||
- rareNonInheritedData->textOverflow != other->rareNonInheritedData->textOverflow)
+ if (rareNonInheritedData->m_appearance != other->rareNonInheritedData->m_appearance
+ || rareNonInheritedData->marginBeforeCollapse != other->rareNonInheritedData->marginBeforeCollapse
+ || rareNonInheritedData->marginAfterCollapse != other->rareNonInheritedData->marginAfterCollapse
+ || rareNonInheritedData->lineClamp != other->rareNonInheritedData->lineClamp
+ || rareNonInheritedData->textOverflow != other->rareNonInheritedData->textOverflow)
return StyleDifferenceLayout;
- if (rareNonInheritedData->flexibleBox.get() != other->rareNonInheritedData->flexibleBox.get() &&
- *rareNonInheritedData->flexibleBox.get() != *other->rareNonInheritedData->flexibleBox.get())
+ if (rareNonInheritedData->flexibleBox.get() != other->rareNonInheritedData->flexibleBox.get()
+ && *rareNonInheritedData->flexibleBox.get() != *other->rareNonInheritedData->flexibleBox.get())
return StyleDifferenceLayout;
// FIXME: We should add an optimized form of layout that just recomputes visual overflow.
@@ -355,12 +355,12 @@ StyleDifference RenderStyle::diff(const RenderStyle* other, unsigned& changedCon
if (!rareNonInheritedData->reflectionDataEquivalent(*other->rareNonInheritedData.get()))
return StyleDifferenceLayout;
- if (rareNonInheritedData->m_multiCol.get() != other->rareNonInheritedData->m_multiCol.get() &&
- *rareNonInheritedData->m_multiCol.get() != *other->rareNonInheritedData->m_multiCol.get())
+ if (rareNonInheritedData->m_multiCol.get() != other->rareNonInheritedData->m_multiCol.get()
+ && *rareNonInheritedData->m_multiCol.get() != *other->rareNonInheritedData->m_multiCol.get())
return StyleDifferenceLayout;
- if (rareNonInheritedData->m_transform.get() != other->rareNonInheritedData->m_transform.get() &&
- *rareNonInheritedData->m_transform.get() != *other->rareNonInheritedData->m_transform.get()) {
+ if (rareNonInheritedData->m_transform.get() != other->rareNonInheritedData->m_transform.get()
+ && *rareNonInheritedData->m_transform.get() != *other->rareNonInheritedData->m_transform.get()) {
#if USE(ACCELERATED_COMPOSITING)
changedContextSensitiveProperties |= ContextSensitivePropertyTransform;
// Don't return; keep looking for another change
@@ -371,11 +371,11 @@ StyleDifference RenderStyle::diff(const RenderStyle* other, unsigned& changedCon
#if !USE(ACCELERATED_COMPOSITING)
if (rareNonInheritedData.get() != other->rareNonInheritedData.get()) {
- if (rareNonInheritedData->m_transformStyle3D != other->rareNonInheritedData->m_transformStyle3D ||
- rareNonInheritedData->m_backfaceVisibility != other->rareNonInheritedData->m_backfaceVisibility ||
- rareNonInheritedData->m_perspective != other->rareNonInheritedData->m_perspective ||
- rareNonInheritedData->m_perspectiveOriginX != other->rareNonInheritedData->m_perspectiveOriginX ||
- rareNonInheritedData->m_perspectiveOriginY != other->rareNonInheritedData->m_perspectiveOriginY)
+ if (rareNonInheritedData->m_transformStyle3D != other->rareNonInheritedData->m_transformStyle3D
+ || rareNonInheritedData->m_backfaceVisibility != other->rareNonInheritedData->m_backfaceVisibility
+ || rareNonInheritedData->m_perspective != other->rareNonInheritedData->m_perspective
+ || rareNonInheritedData->m_perspectiveOriginX != other->rareNonInheritedData->m_perspectiveOriginX
+ || rareNonInheritedData->m_perspectiveOriginY != other->rareNonInheritedData->m_perspectiveOriginY)
return StyleDifferenceLayout;
}
#endif
@@ -388,24 +388,24 @@ StyleDifference RenderStyle::diff(const RenderStyle* other, unsigned& changedCon
}
if (rareInheritedData.get() != other->rareInheritedData.get()) {
- if (rareInheritedData->highlight != other->rareInheritedData->highlight ||
- rareInheritedData->indent != other->rareInheritedData->indent ||
- rareInheritedData->m_effectiveZoom != other->rareInheritedData->m_effectiveZoom ||
- rareInheritedData->textSizeAdjust != other->rareInheritedData->textSizeAdjust ||
- rareInheritedData->wordBreak != other->rareInheritedData->wordBreak ||
- rareInheritedData->wordWrap != other->rareInheritedData->wordWrap ||
- rareInheritedData->nbspMode != other->rareInheritedData->nbspMode ||
- rareInheritedData->khtmlLineBreak != other->rareInheritedData->khtmlLineBreak ||
- rareInheritedData->textSecurity != other->rareInheritedData->textSecurity ||
- rareInheritedData->hyphens != other->rareInheritedData->hyphens ||
- rareInheritedData->hyphenationLimitBefore != other->rareInheritedData->hyphenationLimitBefore ||
- rareInheritedData->hyphenationLimitAfter != other->rareInheritedData->hyphenationLimitAfter ||
- rareInheritedData->hyphenationString != other->rareInheritedData->hyphenationString ||
- rareInheritedData->locale != other->rareInheritedData->locale ||
- rareInheritedData->textEmphasisMark != other->rareInheritedData->textEmphasisMark ||
- rareInheritedData->textEmphasisPosition != other->rareInheritedData->textEmphasisPosition ||
- rareInheritedData->textEmphasisCustomMark != other->rareInheritedData->textEmphasisCustomMark ||
- rareInheritedData->m_lineBoxContain != other->rareInheritedData->m_lineBoxContain)
+ if (rareInheritedData->highlight != other->rareInheritedData->highlight
+ || rareInheritedData->indent != other->rareInheritedData->indent
+ || rareInheritedData->m_effectiveZoom != other->rareInheritedData->m_effectiveZoom
+ || rareInheritedData->textSizeAdjust != other->rareInheritedData->textSizeAdjust
+ || rareInheritedData->wordBreak != other->rareInheritedData->wordBreak
+ || rareInheritedData->wordWrap != other->rareInheritedData->wordWrap
+ || rareInheritedData->nbspMode != other->rareInheritedData->nbspMode
+ || rareInheritedData->khtmlLineBreak != other->rareInheritedData->khtmlLineBreak
+ || rareInheritedData->textSecurity != other->rareInheritedData->textSecurity
+ || rareInheritedData->hyphens != other->rareInheritedData->hyphens
+ || rareInheritedData->hyphenationLimitBefore != other->rareInheritedData->hyphenationLimitBefore
+ || rareInheritedData->hyphenationLimitAfter != other->rareInheritedData->hyphenationLimitAfter
+ || rareInheritedData->hyphenationString != other->rareInheritedData->hyphenationString
+ || rareInheritedData->locale != other->rareInheritedData->locale
+ || rareInheritedData->textEmphasisMark != other->rareInheritedData->textEmphasisMark
+ || rareInheritedData->textEmphasisPosition != other->rareInheritedData->textEmphasisPosition
+ || rareInheritedData->textEmphasisCustomMark != other->rareInheritedData->textEmphasisCustomMark
+ || rareInheritedData->m_lineBoxContain != other->rareInheritedData->m_lineBoxContain)
return StyleDifferenceLayout;
if (!rareInheritedData->shadowDataEquivalent(*other->rareInheritedData.get()))
@@ -415,52 +415,52 @@ StyleDifference RenderStyle::diff(const RenderStyle* other, unsigned& changedCon
return StyleDifferenceLayout;
}
- if (inherited->line_height != other->inherited->line_height ||
- inherited->list_style_image != other->inherited->list_style_image ||
- inherited->font != other->inherited->font ||
- inherited->horizontal_border_spacing != other->inherited->horizontal_border_spacing ||
- inherited->vertical_border_spacing != other->inherited->vertical_border_spacing ||
- inherited_flags._box_direction != other->inherited_flags._box_direction ||
- inherited_flags._visuallyOrdered != other->inherited_flags._visuallyOrdered ||
- noninherited_flags._position != other->noninherited_flags._position ||
- noninherited_flags._floating != other->noninherited_flags._floating ||
- noninherited_flags._originalDisplay != other->noninherited_flags._originalDisplay)
+ if (inherited->line_height != other->inherited->line_height
+ || inherited->list_style_image != other->inherited->list_style_image
+ || inherited->font != other->inherited->font
+ || inherited->horizontal_border_spacing != other->inherited->horizontal_border_spacing
+ || inherited->vertical_border_spacing != other->inherited->vertical_border_spacing
+ || inherited_flags._box_direction != other->inherited_flags._box_direction
+ || inherited_flags._visuallyOrdered != other->inherited_flags._visuallyOrdered
+ || noninherited_flags._position != other->noninherited_flags._position
+ || noninherited_flags._floating != other->noninherited_flags._floating
+ || noninherited_flags._originalDisplay != other->noninherited_flags._originalDisplay)
return StyleDifferenceLayout;
if (((int)noninherited_flags._effectiveDisplay) >= TABLE) {
- if (inherited_flags._border_collapse != other->inherited_flags._border_collapse ||
- inherited_flags._empty_cells != other->inherited_flags._empty_cells ||
- inherited_flags._caption_side != other->inherited_flags._caption_side ||
- noninherited_flags._table_layout != other->noninherited_flags._table_layout)
+ if (inherited_flags._border_collapse != other->inherited_flags._border_collapse
+ || inherited_flags._empty_cells != other->inherited_flags._empty_cells
+ || inherited_flags._caption_side != other->inherited_flags._caption_side
+ || noninherited_flags._table_layout != other->noninherited_flags._table_layout)
return StyleDifferenceLayout;
// In the collapsing border model, 'hidden' suppresses other borders, while 'none'
// does not, so these style differences can be width differences.
- if (inherited_flags._border_collapse &&
- ((borderTopStyle() == BHIDDEN && other->borderTopStyle() == BNONE) ||
- (borderTopStyle() == BNONE && other->borderTopStyle() == BHIDDEN) ||
- (borderBottomStyle() == BHIDDEN && other->borderBottomStyle() == BNONE) ||
- (borderBottomStyle() == BNONE && other->borderBottomStyle() == BHIDDEN) ||
- (borderLeftStyle() == BHIDDEN && other->borderLeftStyle() == BNONE) ||
- (borderLeftStyle() == BNONE && other->borderLeftStyle() == BHIDDEN) ||
- (borderRightStyle() == BHIDDEN && other->borderRightStyle() == BNONE) ||
- (borderRightStyle() == BNONE && other->borderRightStyle() == BHIDDEN)))
+ if (inherited_flags._border_collapse
+ && ((borderTopStyle() == BHIDDEN && other->borderTopStyle() == BNONE)
+ || (borderTopStyle() == BNONE && other->borderTopStyle() == BHIDDEN)
+ || (borderBottomStyle() == BHIDDEN && other->borderBottomStyle() == BNONE)
+ || (borderBottomStyle() == BNONE && other->borderBottomStyle() == BHIDDEN)
+ || (borderLeftStyle() == BHIDDEN && other->borderLeftStyle() == BNONE)
+ || (borderLeftStyle() == BNONE && other->borderLeftStyle() == BHIDDEN)
+ || (borderRightStyle() == BHIDDEN && other->borderRightStyle() == BNONE)
+ || (borderRightStyle() == BNONE && other->borderRightStyle() == BHIDDEN)))
return StyleDifferenceLayout;
}
if (noninherited_flags._effectiveDisplay == LIST_ITEM) {
- if (inherited_flags._list_style_type != other->inherited_flags._list_style_type ||
- inherited_flags._list_style_position != other->inherited_flags._list_style_position)
+ if (inherited_flags._list_style_type != other->inherited_flags._list_style_type
+ || inherited_flags._list_style_position != other->inherited_flags._list_style_position)
return StyleDifferenceLayout;
}
- if (inherited_flags._text_align != other->inherited_flags._text_align ||
- inherited_flags._text_transform != other->inherited_flags._text_transform ||
- inherited_flags._direction != other->inherited_flags._direction ||
- inherited_flags._white_space != other->inherited_flags._white_space ||
- noninherited_flags._clear != other->noninherited_flags._clear ||
- noninherited_flags._unicodeBidi != other->noninherited_flags._unicodeBidi)
+ if (inherited_flags._text_align != other->inherited_flags._text_align
+ || inherited_flags._text_transform != other->inherited_flags._text_transform
+ || inherited_flags._direction != other->inherited_flags._direction
+ || inherited_flags._white_space != other->inherited_flags._white_space
+ || noninherited_flags._clear != other->noninherited_flags._clear
+ || noninherited_flags._unicodeBidi != other->noninherited_flags._unicodeBidi)
return StyleDifferenceLayout;
// Check block flow direction.
@@ -472,16 +472,16 @@ StyleDifference RenderStyle::diff(const RenderStyle* other, unsigned& changedCon
return StyleDifferenceLayout;
// Overflow returns a layout hint.
- if (noninherited_flags._overflowX != other->noninherited_flags._overflowX ||
- noninherited_flags._overflowY != other->noninherited_flags._overflowY)
+ if (noninherited_flags._overflowX != other->noninherited_flags._overflowX
+ || noninherited_flags._overflowY != other->noninherited_flags._overflowY)
return StyleDifferenceLayout;
// If our border widths change, then we need to layout. Other changes to borders
// only necessitate a repaint.
- if (borderLeftWidth() != other->borderLeftWidth() ||
- borderTopWidth() != other->borderTopWidth() ||
- borderBottomWidth() != other->borderBottomWidth() ||
- borderRightWidth() != other->borderRightWidth())
+ if (borderLeftWidth() != other->borderLeftWidth()
+ || borderTopWidth() != other->borderTopWidth()
+ || borderBottomWidth() != other->borderBottomWidth()
+ || borderRightWidth() != other->borderRightWidth())
return StyleDifferenceLayout;
// If the counter directives change, trigger a relayout to re-calculate counter values and rebuild the counter node tree.
@@ -489,15 +489,15 @@ StyleDifference RenderStyle::diff(const RenderStyle* other, unsigned& changedCon
const CounterDirectiveMap* mapB = other->rareNonInheritedData->m_counterDirectives.get();
if (!(mapA == mapB || (mapA && mapB && *mapA == *mapB)))
return StyleDifferenceLayout;
- if (rareNonInheritedData->m_counterIncrement != other->rareNonInheritedData->m_counterIncrement ||
- rareNonInheritedData->m_counterReset != other->rareNonInheritedData->m_counterReset)
+ if (rareNonInheritedData->m_counterIncrement != other->rareNonInheritedData->m_counterIncrement
+ || rareNonInheritedData->m_counterReset != other->rareNonInheritedData->m_counterReset)
return StyleDifferenceLayout;
if ((visibility() == COLLAPSE) != (other->visibility() == COLLAPSE))
return StyleDifferenceLayout;
- if ((rareNonInheritedData->opacity == 1 && other->rareNonInheritedData->opacity < 1) ||
- (rareNonInheritedData->opacity < 1 && other->rareNonInheritedData->opacity == 1)) {
+ if ((rareNonInheritedData->opacity == 1 && other->rareNonInheritedData->opacity < 1)
+ || (rareNonInheritedData->opacity < 1 && other->rareNonInheritedData->opacity == 1)) {
// FIXME: We would like to use SimplifiedLayout here, but we can't quite do that yet.
// We need to make sure SimplifiedLayout can operate correctly on RenderInlines (we will need
// to add a selfNeedsSimplifiedLayout bit in order to not get confused and taint every line).
@@ -527,8 +527,8 @@ StyleDifference RenderStyle::diff(const RenderStyle* other, unsigned& changedCon
// We need to make sure SimplifiedLayout can operate correctly on RenderInlines (we will need
// to add a selfNeedsSimplifiedLayout bit in order to not get confused and taint every line).
return StyleDifferenceLayout;
- } else if (m_box->zIndex() != other->m_box->zIndex() || m_box->hasAutoZIndex() != other->m_box->hasAutoZIndex() ||
- visual->clip != other->visual->clip || visual->hasClip != other->visual->hasClip)
+ } else if (m_box->zIndex() != other->m_box->zIndex() || m_box->hasAutoZIndex() != other->m_box->hasAutoZIndex()
+ || visual->clip != other->visual->clip || visual->hasClip != other->visual->hasClip)
return StyleDifferenceRepaintLayer;
}
@@ -541,35 +541,35 @@ StyleDifference RenderStyle::diff(const RenderStyle* other, unsigned& changedCon
#endif
}
- if (rareNonInheritedData->m_mask != other->rareNonInheritedData->m_mask ||
- rareNonInheritedData->m_maskBoxImage != other->rareNonInheritedData->m_maskBoxImage)
+ if (rareNonInheritedData->m_mask != other->rareNonInheritedData->m_mask
+ || rareNonInheritedData->m_maskBoxImage != other->rareNonInheritedData->m_maskBoxImage)
return StyleDifferenceRepaintLayer;
- if (inherited->color != other->inherited->color ||
- inherited_flags._visibility != other->inherited_flags._visibility ||
- inherited_flags._text_decorations != other->inherited_flags._text_decorations ||
- inherited_flags._force_backgrounds_to_white != other->inherited_flags._force_backgrounds_to_white ||
- inherited_flags._insideLink != other->inherited_flags._insideLink ||
- surround->border != other->surround->border ||
- *m_background.get() != *other->m_background.get() ||
- visual->textDecoration != other->visual->textDecoration ||
- rareInheritedData->userModify != other->rareInheritedData->userModify ||
- rareInheritedData->userSelect != other->rareInheritedData->userSelect ||
- rareNonInheritedData->userDrag != other->rareNonInheritedData->userDrag ||
- rareNonInheritedData->m_borderFit != other->rareNonInheritedData->m_borderFit ||
- rareInheritedData->textFillColor != other->rareInheritedData->textFillColor ||
- rareInheritedData->textStrokeColor != other->rareInheritedData->textStrokeColor ||
- rareInheritedData->textEmphasisColor != other->rareInheritedData->textEmphasisColor ||
- rareInheritedData->textEmphasisFill != other->rareInheritedData->textEmphasisFill)
+ if (inherited->color != other->inherited->color
+ || inherited_flags._visibility != other->inherited_flags._visibility
+ || inherited_flags._text_decorations != other->inherited_flags._text_decorations
+ || inherited_flags._force_backgrounds_to_white != other->inherited_flags._force_backgrounds_to_white
+ || inherited_flags._insideLink != other->inherited_flags._insideLink
+ || surround->border != other->surround->border
+ || *m_background.get() != *other->m_background.get()
+ || visual->textDecoration != other->visual->textDecoration
+ || rareInheritedData->userModify != other->rareInheritedData->userModify
+ || rareInheritedData->userSelect != other->rareInheritedData->userSelect
+ || rareNonInheritedData->userDrag != other->rareNonInheritedData->userDrag
+ || rareNonInheritedData->m_borderFit != other->rareNonInheritedData->m_borderFit
+ || rareInheritedData->textFillColor != other->rareInheritedData->textFillColor
+ || rareInheritedData->textStrokeColor != other->rareInheritedData->textStrokeColor
+ || rareInheritedData->textEmphasisColor != other->rareInheritedData->textEmphasisColor
+ || rareInheritedData->textEmphasisFill != other->rareInheritedData->textEmphasisFill)
return StyleDifferenceRepaint;
#if USE(ACCELERATED_COMPOSITING)
if (rareNonInheritedData.get() != other->rareNonInheritedData.get()) {
- if (rareNonInheritedData->m_transformStyle3D != other->rareNonInheritedData->m_transformStyle3D ||
- rareNonInheritedData->m_backfaceVisibility != other->rareNonInheritedData->m_backfaceVisibility ||
- rareNonInheritedData->m_perspective != other->rareNonInheritedData->m_perspective ||
- rareNonInheritedData->m_perspectiveOriginX != other->rareNonInheritedData->m_perspectiveOriginX ||
- rareNonInheritedData->m_perspectiveOriginY != other->rareNonInheritedData->m_perspectiveOriginY)
+ if (rareNonInheritedData->m_transformStyle3D != other->rareNonInheritedData->m_transformStyle3D
+ || rareNonInheritedData->m_backfaceVisibility != other->rareNonInheritedData->m_backfaceVisibility
+ || rareNonInheritedData->m_perspective != other->rareNonInheritedData->m_perspective
+ || rareNonInheritedData->m_perspectiveOriginX != other->rareNonInheritedData->m_perspectiveOriginX
+ || rareNonInheritedData->m_perspectiveOriginY != other->rareNonInheritedData->m_perspectiveOriginY)
return StyleDifferenceRecompositeLayer;
}
#endif
@@ -693,11 +693,11 @@ void RenderStyle::applyTransform(TransformationMatrix& transform, const IntSize&
if (applyOrigin == IncludeTransformOrigin) {
for (i = 0; i < s; i++) {
TransformOperation::OperationType type = rareNonInheritedData->m_transform->m_operations.operations()[i]->getOperationType();
- if (type != TransformOperation::TRANSLATE_X &&
- type != TransformOperation::TRANSLATE_Y &&
- type != TransformOperation::TRANSLATE &&
- type != TransformOperation::TRANSLATE_Z &&
- type != TransformOperation::TRANSLATE_3D
+ if (type != TransformOperation::TRANSLATE_X
+ && type != TransformOperation::TRANSLATE_Y
+ && type != TransformOperation::TRANSLATE
+ && type != TransformOperation::TRANSLATE_Z
+ && type != TransformOperation::TRANSLATE_3D
) {
applyTransformOrigin = true;
break;
@@ -778,41 +778,66 @@ static float calcConstraintScaleFor(const IntRect& rect, const RoundedIntRect::R
// top
radiiSum = static_cast<unsigned>(radii.topLeft().width()) + static_cast<unsigned>(radii.topRight().width()); // Casts to avoid integer overflow.
if (radiiSum > static_cast<unsigned>(rect.width()))
- factor = std::min(static_cast<float>(rect.width()) / radiiSum, factor);
+ factor = min(static_cast<float>(rect.width()) / radiiSum, factor);
// bottom
radiiSum = static_cast<unsigned>(radii.bottomLeft().width()) + static_cast<unsigned>(radii.bottomRight().width());
if (radiiSum > static_cast<unsigned>(rect.width()))
- factor = std::min(static_cast<float>(rect.width()) / radiiSum, factor);
+ factor = min(static_cast<float>(rect.width()) / radiiSum, factor);
// left
radiiSum = static_cast<unsigned>(radii.topLeft().height()) + static_cast<unsigned>(radii.bottomLeft().height());
if (radiiSum > static_cast<unsigned>(rect.height()))
- factor = std::min(static_cast<float>(rect.height()) / radiiSum, factor);
+ factor = min(static_cast<float>(rect.height()) / radiiSum, factor);
// right
radiiSum = static_cast<unsigned>(radii.topRight().height()) + static_cast<unsigned>(radii.bottomRight().height());
if (radiiSum > static_cast<unsigned>(rect.height()))
- factor = std::min(static_cast<float>(rect.height()) / radiiSum, factor);
+ factor = min(static_cast<float>(rect.height()) / radiiSum, factor);
ASSERT(factor <= 1);
return factor;
}
-RoundedIntRect RenderStyle::getRoundedBorderFor(const IntRect& rect) const
+RoundedIntRect RenderStyle::getRoundedBorderFor(const IntRect& borderRect, bool includeLogicalLeftEdge, bool includeLogicalRightEdge) const
{
- RoundedIntRect::Radii radii = calcRadiiFor(surround->border, rect.width(), rect.height());
- radii.scale(calcConstraintScaleFor(rect, radii));
- return RoundedIntRect(rect, radii);
+ RoundedIntRect roundedRect(borderRect);
+ if (hasBorderRadius()) {
+ RoundedIntRect::Radii radii = calcRadiiFor(surround->border, borderRect.width(), borderRect.height());
+ radii.scale(calcConstraintScaleFor(borderRect, radii));
+ roundedRect.includeLogicalEdges(radii, isHorizontalWritingMode(), includeLogicalLeftEdge, includeLogicalRightEdge);
+ }
+ return roundedRect;
}
-RoundedIntRect RenderStyle::getRoundedInnerBorderWithBorderWidths(const IntRect& innerRect, unsigned short topWidth,
- unsigned short bottomWidth, unsigned short leftWidth, unsigned short rightWidth) const
+RoundedIntRect RenderStyle::getRoundedInnerBorderFor(const IntRect& borderRect, bool includeLogicalLeftEdge, bool includeLogicalRightEdge) const
{
- RoundedIntRect::Radii radii = calcRadiiFor(surround->border, innerRect.width(), innerRect.height());
- radii.shrink(topWidth, bottomWidth, leftWidth, rightWidth);
- radii.scale(calcConstraintScaleFor(innerRect, radii));
- return RoundedIntRect(innerRect, radii);
+ bool horizontal = isHorizontalWritingMode();
+
+ int leftWidth = (!horizontal || includeLogicalLeftEdge) ? borderLeftWidth() : 0;
+ int rightWidth = (!horizontal || includeLogicalRightEdge) ? borderRightWidth() : 0;
+ int topWidth = (horizontal || includeLogicalLeftEdge) ? borderTopWidth() : 0;
+ int bottomWidth = (horizontal || includeLogicalRightEdge) ? borderBottomWidth() : 0;
+
+ return getRoundedInnerBorderFor(borderRect, topWidth, bottomWidth, leftWidth, rightWidth, includeLogicalLeftEdge, includeLogicalRightEdge);
+}
+
+RoundedIntRect RenderStyle::getRoundedInnerBorderFor(const IntRect& borderRect,
+ int topWidth, int bottomWidth, int leftWidth, int rightWidth, bool includeLogicalLeftEdge, bool includeLogicalRightEdge) const
+{
+ IntRect innerRect(borderRect.x() + leftWidth,
+ borderRect.y() + topWidth,
+ borderRect.width() - leftWidth - rightWidth,
+ borderRect.height() - topWidth - bottomWidth);
+
+ RoundedIntRect roundedRect(innerRect);
+
+ if (hasBorderRadius()) {
+ RoundedIntRect::Radii radii = getRoundedBorderFor(borderRect).radii();
+ radii.shrink(topWidth, bottomWidth, leftWidth, rightWidth);
+ roundedRect.includeLogicalEdges(radii, isHorizontalWritingMode(), includeLogicalLeftEdge, includeLogicalRightEdge);
+ }
+ return roundedRect;
}
const CounterDirectiveMap* RenderStyle::counterDirectives() const
@@ -1146,6 +1171,14 @@ const Color RenderStyle::visitedDependentColor(int colorProperty) const
return unvisitedColor;
Color visitedColor = visitedStyle->colorIncludingFallback(colorProperty, borderStyle);
+ // FIXME: Technically someone could explicitly specify the color transparent, but for now we'll just
+ // assume that if the background color is transparent that it wasn't set. Note that it's weird that
+ // we're returning unvisited info for a visited link, but given our restriction that the alpha values
+ // have to match, it makes more sense to return the unvisited background color if specified than it
+ // does to return black. This behavior matches what Firefox 4 does as well.
+ if (colorProperty == CSSPropertyBackgroundColor && visitedColor == Color::transparent)
+ return unvisitedColor;
+
// Take the alpha from the unvisited color, but get the RGB values from the visited color.
return Color(visitedColor.red(), visitedColor.green(), visitedColor.blue(), unvisitedColor.alpha());
}
diff --git a/Source/WebCore/rendering/style/RenderStyle.h b/Source/WebCore/rendering/style/RenderStyle.h
index 859348f..fad5a7b 100644
--- a/Source/WebCore/rendering/style/RenderStyle.h
+++ b/Source/WebCore/rendering/style/RenderStyle.h
@@ -62,6 +62,7 @@
#include "TextOrientation.h"
#include "ThemeTypes.h"
#include "TransformOperations.h"
+#include "UnicodeBidi.h"
#include <wtf/Forward.h>
#include <wtf/OwnPtr.h>
#include <wtf/RefCounted.h>
@@ -160,24 +161,24 @@ protected:
struct InheritedFlags {
bool operator==(const InheritedFlags& other) const
{
- return (_empty_cells == other._empty_cells) &&
- (_caption_side == other._caption_side) &&
- (_list_style_type == other._list_style_type) &&
- (_list_style_position == other._list_style_position) &&
- (_visibility == other._visibility) &&
- (_text_align == other._text_align) &&
- (_text_transform == other._text_transform) &&
- (_text_decorations == other._text_decorations) &&
- (_cursor_style == other._cursor_style) &&
- (_direction == other._direction) &&
- (_border_collapse == other._border_collapse) &&
- (_white_space == other._white_space) &&
- (_box_direction == other._box_direction) &&
- (_visuallyOrdered == other._visuallyOrdered) &&
- (_force_backgrounds_to_white == other._force_backgrounds_to_white) &&
- (_pointerEvents == other._pointerEvents) &&
- (_insideLink == other._insideLink) &&
- (m_writingMode == other.m_writingMode);
+ return (_empty_cells == other._empty_cells)
+ && (_caption_side == other._caption_side)
+ && (_list_style_type == other._list_style_type)
+ && (_list_style_position == other._list_style_position)
+ && (_visibility == other._visibility)
+ && (_text_align == other._text_align)
+ && (_text_transform == other._text_transform)
+ && (_text_decorations == other._text_decorations)
+ && (_cursor_style == other._cursor_style)
+ && (_direction == other._direction)
+ && (_border_collapse == other._border_collapse)
+ && (_white_space == other._white_space)
+ && (_box_direction == other._box_direction)
+ && (_visuallyOrdered == other._visuallyOrdered)
+ && (_force_backgrounds_to_white == other._force_backgrounds_to_white)
+ && (_pointerEvents == other._pointerEvents)
+ && (_insideLink == other._insideLink)
+ && (m_writingMode == other.m_writingMode);
}
bool operator!=(const InheritedFlags& other) const { return !(*this == other); }
@@ -563,7 +564,6 @@ public:
return wordBreak() == BreakWordBreak || wordWrap() == BreakWordWrap;
}
- StyleImage* backgroundImage() const { return m_background->background().image(); }
EFillRepeat backgroundRepeatX() const { return static_cast<EFillRepeat>(m_background->background().repeatX()); }
EFillRepeat backgroundRepeatY() const { return static_cast<EFillRepeat>(m_background->background().repeatY()); }
CompositeOperator backgroundComposite() const { return static_cast<CompositeOperator>(m_background->background().composite()); }
@@ -881,9 +881,11 @@ public:
setBorderRadius(LengthSize(Length(s.width(), Fixed), Length(s.height(), Fixed)));
}
- RoundedIntRect getRoundedBorderFor(const IntRect&) const;
- RoundedIntRect getRoundedInnerBorderWithBorderWidths(const IntRect&, unsigned short topWidth,
- unsigned short bottomWidth, unsigned short leftWidth, unsigned short rightWidth) const;
+ RoundedIntRect getRoundedBorderFor(const IntRect& borderRect, bool includeLogicalLeftEdge = true, bool includeLogicalRightEdge = true) const;
+ RoundedIntRect getRoundedInnerBorderFor(const IntRect& borderRect, bool includeLogicalLeftEdge = true, bool includeLogicalRightEdge = true) const;
+
+ RoundedIntRect getRoundedInnerBorderFor(const IntRect& borderRect,
+ int topWidth, int bottomWidth, int leftWidth, int rightWidth, bool includeLogicalLeftEdge, bool includeLogicalRightEdge) const;
void setBorderLeftWidth(unsigned short v) { SET_VAR(surround, border.m_left.m_width, v) }
void setBorderLeftStyle(EBorderStyle v) { SET_VAR(surround, border.m_left.m_style, v) }
@@ -1205,8 +1207,8 @@ public:
bool isOriginalDisplayInlineType() const
{
- return originalDisplay() == INLINE || originalDisplay() == INLINE_BLOCK ||
- originalDisplay() == INLINE_BOX || originalDisplay() == INLINE_TABLE;
+ return originalDisplay() == INLINE || originalDisplay() == INLINE_BLOCK
+ || originalDisplay() == INLINE_BOX || originalDisplay() == INLINE_TABLE;
}
void setWritingMode(WritingMode v) { inherited_flags.m_writingMode = v; }
diff --git a/Source/WebCore/rendering/style/RenderStyleConstants.h b/Source/WebCore/rendering/style/RenderStyleConstants.h
index 08f2c15..5ad42ce 100644
--- a/Source/WebCore/rendering/style/RenderStyleConstants.h
+++ b/Source/WebCore/rendering/style/RenderStyleConstants.h
@@ -72,8 +72,7 @@ enum PseudoId {
SEARCH_CANCEL_BUTTON, SEARCH_DECORATION, SEARCH_RESULTS_DECORATION, SEARCH_RESULTS_BUTTON,
SCROLLBAR_THUMB, SCROLLBAR_BUTTON, SCROLLBAR_TRACK, SCROLLBAR_TRACK_PIECE, SCROLLBAR_CORNER, RESIZER,
INPUT_LIST_BUTTON, INPUT_SPEECH_BUTTON, INNER_SPIN_BUTTON, OUTER_SPIN_BUTTON, VISITED_LINK,
- METER_HORIZONTAL_BAR, METER_HORIZONTAL_OPTIMUM, METER_HORIZONTAL_SUBOPTIMAL, METER_HORIZONTAL_EVEN_LESS_GOOD,
- METER_VERTICAL_BAR, METER_VERTICAL_OPTIMUM, METER_VERTICAL_SUBOPTIMAL, METER_VERTICAL_EVEN_LESS_GOOD,
+ METER_BAR, METER_OPTIMUM, METER_SUBOPTIMAL, METER_EVEN_LESS_GOOD,
AFTER_LAST_INTERNAL_PSEUDOID,
FULL_SCREEN, FULL_SCREEN_DOCUMENT,
FIRST_PUBLIC_PSEUDOID = FIRST_LINE,
@@ -120,10 +119,6 @@ enum ETableLayout {
TAUTO, TFIXED
};
-enum EUnicodeBidi {
- UBNormal, Embed, Override, Isolate
-};
-
// CSS Text Layout Module Level 3: Vertical writing support
enum WritingMode {
TopToBottomWritingMode, RightToLeftWritingMode, LeftToRightWritingMode, BottomToTopWritingMode
diff --git a/Source/WebCore/rendering/svg/RenderSVGInline.cpp b/Source/WebCore/rendering/svg/RenderSVGInline.cpp
index 543d14b..02a85ce 100644
--- a/Source/WebCore/rendering/svg/RenderSVGInline.cpp
+++ b/Source/WebCore/rendering/svg/RenderSVGInline.cpp
@@ -33,6 +33,7 @@ namespace WebCore {
RenderSVGInline::RenderSVGInline(Node* n)
: RenderInline(n)
{
+ setAlwaysCreateLineBoxes();
}
InlineFlowBox* RenderSVGInline::createInlineFlowBox()
diff --git a/Source/WebCore/rendering/svg/RenderSVGInlineText.cpp b/Source/WebCore/rendering/svg/RenderSVGInlineText.cpp
index a8aa0c8..c8539c6 100644
--- a/Source/WebCore/rendering/svg/RenderSVGInlineText.cpp
+++ b/Source/WebCore/rendering/svg/RenderSVGInlineText.cpp
@@ -179,8 +179,11 @@ VisiblePosition RenderSVGInlineText::positionForPoint(const IntPoint& point)
const SVGTextFragment* closestDistanceFragment = 0;
SVGInlineTextBox* closestDistanceBox = 0;
+ AffineTransform fragmentTransform;
for (InlineTextBox* box = firstTextBox(); box; box = box->nextTextBox()) {
- ASSERT(box->isSVGInlineTextBox());
+ if (!box->isSVGInlineTextBox())
+ continue;
+
SVGInlineTextBox* textBox = static_cast<SVGInlineTextBox*>(box);
Vector<SVGTextFragment>& fragments = textBox->textFragments();
@@ -188,8 +191,9 @@ VisiblePosition RenderSVGInlineText::positionForPoint(const IntPoint& point)
for (unsigned i = 0; i < textFragmentsSize; ++i) {
const SVGTextFragment& fragment = fragments.at(i);
FloatRect fragmentRect(fragment.x, fragment.y - baseline, fragment.width, fragment.height);
- if (!fragment.transform.isIdentity())
- fragmentRect = fragment.transform.mapRect(fragmentRect);
+ fragment.buildFragmentTransform(fragmentTransform);
+ if (!fragmentTransform.isIdentity())
+ fragmentRect = fragmentTransform.mapRect(fragmentRect);
float distance = powf(fragmentRect.x() - absolutePoint.x(), 2) +
powf(fragmentRect.y() + fragmentRect.height() / 2 - absolutePoint.y(), 2);
diff --git a/Source/WebCore/rendering/svg/RenderSVGPath.cpp b/Source/WebCore/rendering/svg/RenderSVGPath.cpp
index 1d9eca1..cc7c86e 100644
--- a/Source/WebCore/rendering/svg/RenderSVGPath.cpp
+++ b/Source/WebCore/rendering/svg/RenderSVGPath.cpp
@@ -128,8 +128,10 @@ void RenderSVGPath::layout()
updateCachedBoundariesInParents = true;
// Invalidate all resources of this client if our layout changed.
- if (m_everHadLayout && selfNeedsLayout())
+ if (m_everHadLayout && selfNeedsLayout()) {
SVGResourcesCache::clientLayoutChanged(this);
+ m_markerLayoutInfo.clear();
+ }
// At this point LayoutRepainter already grabbed the old bounds,
// recalculate them now so repaintAfterLayout() uses the new bounds.
diff --git a/Source/WebCore/rendering/svg/RenderSVGResourceFilter.cpp b/Source/WebCore/rendering/svg/RenderSVGResourceFilter.cpp
index 96514af..09195f5 100644
--- a/Source/WebCore/rendering/svg/RenderSVGResourceFilter.cpp
+++ b/Source/WebCore/rendering/svg/RenderSVGResourceFilter.cpp
@@ -278,7 +278,7 @@ void RenderSVGResourceFilter::postApplyResource(RenderObject* object, GraphicsCo
context = filterData->savedContext;
filterData->savedContext = 0;
-#if !PLATFORM(CG)
+#if !USE(CG)
if (filterData->sourceGraphicBuffer)
filterData->sourceGraphicBuffer->transformColorSpace(ColorSpaceDeviceRGB, ColorSpaceLinearRGB);
#endif
@@ -296,7 +296,7 @@ void RenderSVGResourceFilter::postApplyResource(RenderObject* object, GraphicsCo
// Always true if filterData is just built (filterData->builded is false).
if (!lastEffect->hasResult()) {
lastEffect->apply();
-#if !PLATFORM(CG)
+#if !USE(CG)
ImageBuffer* resultImage = lastEffect->asImageBuffer();
if (resultImage)
resultImage->transformColorSpace(ColorSpaceLinearRGB, ColorSpaceDeviceRGB);
diff --git a/Source/WebCore/rendering/svg/RenderSVGResourceFilterPrimitive.cpp b/Source/WebCore/rendering/svg/RenderSVGResourceFilterPrimitive.cpp
index 64df700..f077bfd 100644
--- a/Source/WebCore/rendering/svg/RenderSVGResourceFilterPrimitive.cpp
+++ b/Source/WebCore/rendering/svg/RenderSVGResourceFilterPrimitive.cpp
@@ -1,6 +1,7 @@
/*
* Copyright (C) 2010 University of Szeged
* Copyright (C) 2010 Zoltan Herczeg
+ * Copyright (C) 2011 Renata Hodovan (reni@webkit.org)
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -32,9 +33,35 @@
#include "RenderSVGResource.h"
#include "SVGFEImage.h"
#include "SVGFilter.h"
+#include "SVGNames.h"
namespace WebCore {
+
+void RenderSVGResourceFilterPrimitive::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
+{
+ RenderSVGHiddenContainer::styleDidChange(diff, oldStyle);
+
+ RenderObject* filter = parent();
+ if (!filter)
+ return;
+ ASSERT(filter->isSVGResourceFilter());
+
+ if (diff == StyleDifferenceEqual || !oldStyle)
+ return;
+
+ const SVGRenderStyle* newStyle = this->style()->svgStyle();
+ if (node()->hasTagName(SVGNames::feFloodTag)) {
+ if (newStyle->floodColor() != oldStyle->svgStyle()->floodColor())
+ static_cast<RenderSVGResourceFilter*>(filter)->primitiveAttributeChanged(this, SVGNames::flood_colorAttr);
+ if (newStyle->floodOpacity() != oldStyle->svgStyle()->floodOpacity())
+ static_cast<RenderSVGResourceFilter*>(filter)->primitiveAttributeChanged(this, SVGNames::flood_opacityAttr);
+ } else if (node()->hasTagName(SVGNames::feDiffuseLightingTag) || node()->hasTagName(SVGNames::feSpecularLightingTag)) {
+ if (newStyle->lightingColor() != oldStyle->svgStyle()->lightingColor())
+ static_cast<RenderSVGResourceFilter*>(filter)->primitiveAttributeChanged(this, SVGNames::lighting_colorAttr);
+ }
+}
+
FloatRect RenderSVGResourceFilterPrimitive::determineFilterPrimitiveSubregion(FilterEffect* effect)
{
FloatRect uniteRect;
diff --git a/Source/WebCore/rendering/svg/RenderSVGResourceFilterPrimitive.h b/Source/WebCore/rendering/svg/RenderSVGResourceFilterPrimitive.h
index 8176d29..e8e4efc 100644
--- a/Source/WebCore/rendering/svg/RenderSVGResourceFilterPrimitive.h
+++ b/Source/WebCore/rendering/svg/RenderSVGResourceFilterPrimitive.h
@@ -43,6 +43,8 @@ public:
{
}
+ virtual void styleDidChange(StyleDifference, const RenderStyle*);
+
virtual const char* renderName() const { return "RenderSVGResourceFilterPrimitive"; }
virtual bool isSVGResourceFilterPrimitive() const { return true; }
diff --git a/Source/WebCore/rendering/svg/RenderSVGResourceGradient.cpp b/Source/WebCore/rendering/svg/RenderSVGResourceGradient.cpp
index 9f2bb8d..a42a227 100644
--- a/Source/WebCore/rendering/svg/RenderSVGResourceGradient.cpp
+++ b/Source/WebCore/rendering/svg/RenderSVGResourceGradient.cpp
@@ -37,7 +37,7 @@ namespace WebCore {
RenderSVGResourceGradient::RenderSVGResourceGradient(SVGGradientElement* node)
: RenderSVGResourceContainer(node)
, m_shouldCollectGradientAttributes(true)
-#if PLATFORM(CG)
+#if USE(CG)
, m_savedContext(0)
#endif
{
@@ -73,7 +73,7 @@ void RenderSVGResourceGradient::removeClientFromCache(RenderObject* client, bool
markClientForInvalidation(client, markForInvalidation ? RepaintInvalidation : ParentOnlyInvalidation);
}
-#if PLATFORM(CG)
+#if USE(CG)
static inline bool createMaskAndSwapContextForTextGradient(GraphicsContext*& context,
GraphicsContext*& savedContext,
OwnPtr<ImageBuffer>& imageBuffer,
@@ -178,7 +178,7 @@ bool RenderSVGResourceGradient::applyResource(RenderObject* object, RenderStyle*
// CG platforms will handle the gradient space transform for text after applying the
// resource, so don't apply it here. For non-CG platforms, we want the text bounding
// box applied to the gradient space transform now, so the gradient shader can use it.
-#if PLATFORM(CG)
+#if USE(CG)
if (boundingBoxMode() && !objectBoundingBox.isEmpty() && !isPaintingText) {
#else
if (boundingBoxMode() && !objectBoundingBox.isEmpty()) {
@@ -201,7 +201,7 @@ bool RenderSVGResourceGradient::applyResource(RenderObject* object, RenderStyle*
context->save();
if (isPaintingText) {
-#if PLATFORM(CG)
+#if USE(CG)
if (!createMaskAndSwapContextForTextGradient(context, m_savedContext, m_imageBuffer, object)) {
context->restore();
return false;
@@ -235,7 +235,7 @@ void RenderSVGResourceGradient::postApplyResource(RenderObject* object, Graphics
ASSERT(resourceMode != ApplyToDefaultMode);
if (resourceMode & ApplyToTextMode) {
-#if PLATFORM(CG)
+#if USE(CG)
// CG requires special handling for gradient on text
if (m_savedContext && m_gradient.contains(object)) {
GradientData* gradientData = m_gradient.get(object);
diff --git a/Source/WebCore/rendering/svg/RenderSVGResourceGradient.h b/Source/WebCore/rendering/svg/RenderSVGResourceGradient.h
index ad40b53..a71b6c5 100644
--- a/Source/WebCore/rendering/svg/RenderSVGResourceGradient.h
+++ b/Source/WebCore/rendering/svg/RenderSVGResourceGradient.h
@@ -65,7 +65,7 @@ private:
bool m_shouldCollectGradientAttributes : 1;
HashMap<RenderObject*, GradientData*> m_gradient;
-#if PLATFORM(CG)
+#if USE(CG)
GraphicsContext* m_savedContext;
OwnPtr<ImageBuffer> m_imageBuffer;
#endif
diff --git a/Source/WebCore/rendering/svg/RenderSVGResourceMasker.cpp b/Source/WebCore/rendering/svg/RenderSVGResourceMasker.cpp
index 7b24248..dc0df08 100644
--- a/Source/WebCore/rendering/svg/RenderSVGResourceMasker.cpp
+++ b/Source/WebCore/rendering/svg/RenderSVGResourceMasker.cpp
@@ -154,7 +154,7 @@ void RenderSVGResourceMasker::drawContentIntoMaskImage(MaskerData* maskerData, c
maskImageContext->restore();
-#if !PLATFORM(CG)
+#if !USE(CG)
maskerData->maskImage->transformColorSpace(ColorSpaceDeviceRGB, ColorSpaceLinearRGB);
#endif
diff --git a/Source/WebCore/rendering/svg/RenderSVGResourcePattern.cpp b/Source/WebCore/rendering/svg/RenderSVGResourcePattern.cpp
index b82be1b..fc26978 100644
--- a/Source/WebCore/rendering/svg/RenderSVGResourcePattern.cpp
+++ b/Source/WebCore/rendering/svg/RenderSVGResourcePattern.cpp
@@ -166,13 +166,13 @@ bool RenderSVGResourcePattern::applyResource(RenderObject* object, RenderStyle*
if (resourceMode & ApplyToFillMode) {
context->setTextDrawingMode(TextModeFill);
-#if PLATFORM(CG)
+#if USE(CG)
context->applyFillPattern();
#endif
} else if (resourceMode & ApplyToStrokeMode) {
context->setTextDrawingMode(TextModeStroke);
-#if PLATFORM(CG)
+#if USE(CG)
context->applyStrokePattern();
#endif
}
diff --git a/Source/WebCore/rendering/svg/RenderSVGShadowTreeRootContainer.cpp b/Source/WebCore/rendering/svg/RenderSVGShadowTreeRootContainer.cpp
index 5736333..d2a1103 100644
--- a/Source/WebCore/rendering/svg/RenderSVGShadowTreeRootContainer.cpp
+++ b/Source/WebCore/rendering/svg/RenderSVGShadowTreeRootContainer.cpp
@@ -38,7 +38,7 @@ RenderSVGShadowTreeRootContainer::~RenderSVGShadowTreeRootContainer()
{
if (m_shadowRoot && m_shadowRoot->attached()) {
m_shadowRoot->detach();
- m_shadowRoot->clearShadowHost();
+ m_shadowRoot->clearSVGShadowHost();
}
}
@@ -59,7 +59,7 @@ void RenderSVGShadowTreeRootContainer::updateFromElement()
useElement->buildPendingResource();
}
- ASSERT(m_shadowRoot->shadowHost() == useElement);
+ ASSERT(m_shadowRoot->svgShadowHost() == useElement);
bool shouldRecreateTree = m_recreateTree;
if (m_recreateTree) {
diff --git a/Source/WebCore/rendering/svg/RenderSVGText.cpp b/Source/WebCore/rendering/svg/RenderSVGText.cpp
index 8ca3d58..7af6cc6 100644
--- a/Source/WebCore/rendering/svg/RenderSVGText.cpp
+++ b/Source/WebCore/rendering/svg/RenderSVGText.cpp
@@ -57,6 +57,11 @@ RenderSVGText::RenderSVGText(SVGTextElement* node)
{
}
+bool RenderSVGText::isChildAllowed(RenderObject* child, RenderStyle*) const
+{
+ return child->isInline();
+}
+
RenderSVGText* RenderSVGText::locateRenderSVGTextAncestor(RenderObject* start)
{
ASSERT(start);
diff --git a/Source/WebCore/rendering/svg/RenderSVGText.h b/Source/WebCore/rendering/svg/RenderSVGText.h
index 93fc5f8..15ace2b 100644
--- a/Source/WebCore/rendering/svg/RenderSVGText.h
+++ b/Source/WebCore/rendering/svg/RenderSVGText.h
@@ -36,6 +36,8 @@ class RenderSVGText : public RenderSVGBlock {
public:
RenderSVGText(SVGTextElement*);
+ virtual bool isChildAllowed(RenderObject*, RenderStyle*) const;
+
void setNeedsPositioningValuesUpdate() { m_needsPositioningValuesUpdate = true; }
virtual void setNeedsTransformUpdate() { m_needsTransformUpdate = true; }
virtual FloatRect repaintRectInLocalCoordinates() const;
diff --git a/Source/WebCore/rendering/svg/SVGInlineFlowBox.cpp b/Source/WebCore/rendering/svg/SVGInlineFlowBox.cpp
index 10735f6..85707da 100644
--- a/Source/WebCore/rendering/svg/SVGInlineFlowBox.cpp
+++ b/Source/WebCore/rendering/svg/SVGInlineFlowBox.cpp
@@ -48,7 +48,7 @@ void SVGInlineFlowBox::paintSelectionBackground(PaintInfo& paintInfo)
}
}
-void SVGInlineFlowBox::paint(PaintInfo& paintInfo, int, int)
+void SVGInlineFlowBox::paint(PaintInfo& paintInfo, int, int, int, int)
{
ASSERT(paintInfo.phase == PaintPhaseForeground || paintInfo.phase == PaintPhaseSelection);
ASSERT(!paintInfo.context->paintingDisabled());
@@ -64,7 +64,7 @@ void SVGInlineFlowBox::paint(PaintInfo& paintInfo, int, int)
if (child->isSVGInlineTextBox())
computeTextMatchMarkerRectForRenderer(toRenderSVGInlineText(static_cast<SVGInlineTextBox*>(child)->textRenderer()));
- child->paint(childPaintInfo, 0, 0);
+ child->paint(childPaintInfo, 0, 0, 0, 0);
}
}
@@ -91,6 +91,7 @@ void SVGInlineFlowBox::computeTextMatchMarkerRectForRenderer(RenderSVGInlineText
RenderStyle* style = textRenderer->style();
ASSERT(style);
+ AffineTransform fragmentTransform;
Document* document = textRenderer->document();
Vector<DocumentMarker> markers = document->markers()->markersForNode(textRenderer->node());
@@ -104,7 +105,9 @@ void SVGInlineFlowBox::computeTextMatchMarkerRectForRenderer(RenderSVGInlineText
FloatRect markerRect;
for (InlineTextBox* box = textRenderer->firstTextBox(); box; box = box->nextTextBox()) {
- ASSERT(box->isSVGInlineTextBox());
+ if (!box->isSVGInlineTextBox())
+ continue;
+
SVGInlineTextBox* textBox = static_cast<SVGInlineTextBox*>(box);
int markerStartPosition = max<int>(marker.startOffset - textBox->start(), 0);
@@ -127,8 +130,9 @@ void SVGInlineFlowBox::computeTextMatchMarkerRectForRenderer(RenderSVGInlineText
continue;
FloatRect fragmentRect = textBox->selectionRectForTextFragment(fragment, fragmentStartPosition, fragmentEndPosition, style);
- if (!fragment.transform.isIdentity())
- fragmentRect = fragment.transform.mapRect(fragmentRect);
+ fragment.buildFragmentTransform(fragmentTransform);
+ if (!fragmentTransform.isIdentity())
+ fragmentRect = fragmentTransform.mapRect(fragmentRect);
markerRect.unite(fragmentRect);
}
diff --git a/Source/WebCore/rendering/svg/SVGInlineFlowBox.h b/Source/WebCore/rendering/svg/SVGInlineFlowBox.h
index 0e56c9f..304c616 100644
--- a/Source/WebCore/rendering/svg/SVGInlineFlowBox.h
+++ b/Source/WebCore/rendering/svg/SVGInlineFlowBox.h
@@ -41,7 +41,7 @@ public:
void setLogicalHeight(int h) { m_logicalHeight = h; }
void paintSelectionBackground(PaintInfo&);
- virtual void paint(PaintInfo&, int tx, int ty);
+ virtual void paint(PaintInfo&, int tx, int ty, int lineTop, int lineBottom);
virtual IntRect calculateBoundaries() const;
diff --git a/Source/WebCore/rendering/svg/SVGInlineTextBox.cpp b/Source/WebCore/rendering/svg/SVGInlineTextBox.cpp
index 17bbfaa..bc550a6 100644
--- a/Source/WebCore/rendering/svg/SVGInlineTextBox.cpp
+++ b/Source/WebCore/rendering/svg/SVGInlineTextBox.cpp
@@ -70,8 +70,10 @@ int SVGInlineTextBox::offsetForPositionInFragment(const SVGTextFragment& fragmen
// Eventually handle lengthAdjust="spacingAndGlyphs".
// FIXME: Handle vertical text.
- if (!fragment.transform.isIdentity())
- textRun.setHorizontalGlyphStretch(narrowPrecisionToFloat(fragment.transform.xScale()));
+ AffineTransform fragmentTransform;
+ fragment.buildFragmentTransform(fragmentTransform);
+ if (!fragmentTransform.isIdentity())
+ textRun.setHorizontalGlyphStretch(narrowPrecisionToFloat(fragmentTransform.xScale()));
return fragment.characterOffset - start() + textRenderer->scaledFont().offsetForPosition(textRun, position * scalingFactor, includePartialGlyphs);
}
@@ -124,6 +126,7 @@ IntRect SVGInlineTextBox::selectionRect(int, int, int startPosition, int endPosi
RenderStyle* style = text->style();
ASSERT(style);
+ AffineTransform fragmentTransform;
FloatRect selectionRect;
int fragmentStartPosition = 0;
int fragmentEndPosition = 0;
@@ -138,8 +141,9 @@ IntRect SVGInlineTextBox::selectionRect(int, int, int startPosition, int endPosi
continue;
FloatRect fragmentRect = selectionRectForTextFragment(fragment, fragmentStartPosition, fragmentEndPosition, style);
- if (!fragment.transform.isIdentity())
- fragmentRect = fragment.transform.mapRect(fragmentRect);
+ fragment.buildFragmentTransform(fragmentTransform);
+ if (!fragmentTransform.isIdentity())
+ fragmentRect = fragmentTransform.mapRect(fragmentRect);
selectionRect.unite(fragmentRect);
}
@@ -211,6 +215,7 @@ void SVGInlineTextBox::paintSelectionBackground(PaintInfo& paintInfo)
int fragmentStartPosition = 0;
int fragmentEndPosition = 0;
+ AffineTransform fragmentTransform;
unsigned textFragmentsSize = m_textFragments.size();
for (unsigned i = 0; i < textFragmentsSize; ++i) {
SVGTextFragment& fragment = m_textFragments.at(i);
@@ -222,9 +227,9 @@ void SVGInlineTextBox::paintSelectionBackground(PaintInfo& paintInfo)
continue;
paintInfo.context->save();
-
- if (!fragment.transform.isIdentity())
- paintInfo.context->concatCTM(fragment.transform);
+ fragment.buildFragmentTransform(fragmentTransform);
+ if (!fragmentTransform.isIdentity())
+ paintInfo.context->concatCTM(fragmentTransform);
paintInfo.context->setFillColor(backgroundColor, style->colorSpace());
paintInfo.context->fillRect(selectionRectForTextFragment(fragment, fragmentStartPosition, fragmentEndPosition, style), backgroundColor, style->colorSpace());
@@ -236,7 +241,7 @@ void SVGInlineTextBox::paintSelectionBackground(PaintInfo& paintInfo)
ASSERT(!m_paintingResource);
}
-void SVGInlineTextBox::paint(PaintInfo& paintInfo, int, int)
+void SVGInlineTextBox::paint(PaintInfo& paintInfo, int, int, int, int)
{
ASSERT(paintInfo.shouldPaintWithinRoot(renderer()));
ASSERT(paintInfo.phase == PaintPhaseForeground || paintInfo.phase == PaintPhaseSelection);
@@ -285,15 +290,16 @@ void SVGInlineTextBox::paint(PaintInfo& paintInfo, int, int)
selectionStyle = style;
}
+ AffineTransform fragmentTransform;
unsigned textFragmentsSize = m_textFragments.size();
for (unsigned i = 0; i < textFragmentsSize; ++i) {
SVGTextFragment& fragment = m_textFragments.at(i);
ASSERT(!m_paintingResource);
paintInfo.context->save();
-
- if (!fragment.transform.isIdentity())
- paintInfo.context->concatCTM(fragment.transform);
+ fragment.buildFragmentTransform(fragmentTransform);
+ if (!fragmentTransform.isIdentity())
+ paintInfo.context->concatCTM(fragmentTransform);
// Spec: All text decorations except line-through should be drawn before the text is filled and stroked; thus, the text is rendered on top of these decorations.
int decorations = style->textDecorationsInEffect();
@@ -694,13 +700,14 @@ IntRect SVGInlineTextBox::calculateBoundaries() const
float baseline = textRenderer->scaledFont().fontMetrics().floatAscent() / scalingFactor;
+ AffineTransform fragmentTransform;
unsigned textFragmentsSize = m_textFragments.size();
for (unsigned i = 0; i < textFragmentsSize; ++i) {
const SVGTextFragment& fragment = m_textFragments.at(i);
FloatRect fragmentRect(fragment.x, fragment.y - baseline, fragment.width, fragment.height);
-
- if (!fragment.transform.isIdentity())
- fragmentRect = fragment.transform.mapRect(fragmentRect);
+ fragment.buildFragmentTransform(fragmentTransform);
+ if (!fragmentTransform.isIdentity())
+ fragmentRect = fragmentTransform.mapRect(fragmentRect);
textRect.unite(fragmentRect);
}
diff --git a/Source/WebCore/rendering/svg/SVGInlineTextBox.h b/Source/WebCore/rendering/svg/SVGInlineTextBox.h
index 79c836f..ce48019 100644
--- a/Source/WebCore/rendering/svg/SVGInlineTextBox.h
+++ b/Source/WebCore/rendering/svg/SVGInlineTextBox.h
@@ -46,7 +46,7 @@ public:
virtual float positionForOffset(int offset) const;
void paintSelectionBackground(PaintInfo&);
- virtual void paint(PaintInfo&, int tx, int ty);
+ virtual void paint(PaintInfo&, int tx, int ty, int lineTop, int lineBottom);
virtual IntRect selectionRect(int absx, int absy, int startPosition, int endPosition);
bool mapStartEndPositionsIntoFragmentCoordinates(const SVGTextFragment&, int& startPosition, int& endPosition) const;
diff --git a/Source/WebCore/rendering/svg/SVGMarkerLayoutInfo.cpp b/Source/WebCore/rendering/svg/SVGMarkerLayoutInfo.cpp
index dea5a0c..27b37f1 100644
--- a/Source/WebCore/rendering/svg/SVGMarkerLayoutInfo.cpp
+++ b/Source/WebCore/rendering/svg/SVGMarkerLayoutInfo.cpp
@@ -98,6 +98,15 @@ FloatRect SVGMarkerLayoutInfo::calculateBoundaries(RenderSVGResourceMarker* star
return bounds;
}
+void SVGMarkerLayoutInfo::clear()
+{
+ m_midMarker = 0;
+ m_elementIndex = 0;
+ m_strokeWidth = 0;
+ m_markerData.updateTypeAndMarker(SVGMarkerData::Unknown, 0);
+ m_layout.clear();
+}
+
void SVGMarkerLayoutInfo::drawMarkers(PaintInfo& paintInfo)
{
if (m_layout.isEmpty())
diff --git a/Source/WebCore/rendering/svg/SVGMarkerLayoutInfo.h b/Source/WebCore/rendering/svg/SVGMarkerLayoutInfo.h
index 32317b9..c2301cc 100644
--- a/Source/WebCore/rendering/svg/SVGMarkerLayoutInfo.h
+++ b/Source/WebCore/rendering/svg/SVGMarkerLayoutInfo.h
@@ -57,6 +57,7 @@ public:
RenderSVGResourceMarker* midMarker() const { return m_midMarker; }
int& elementIndex() { return m_elementIndex; }
void addLayoutedMarker(RenderSVGResourceMarker*, const FloatPoint& origin, float angle);
+ void clear();
private:
RenderSVGResourceMarker* m_midMarker;
diff --git a/Source/WebCore/rendering/svg/SVGRenderTreeAsText.cpp b/Source/WebCore/rendering/svg/SVGRenderTreeAsText.cpp
index a099f87..7d3f909 100644
--- a/Source/WebCore/rendering/svg/SVGRenderTreeAsText.cpp
+++ b/Source/WebCore/rendering/svg/SVGRenderTreeAsText.cpp
@@ -506,8 +506,12 @@ static inline void writeSVGInlineTextBox(TextStream& ts, SVGInlineTextBox* textB
static inline void writeSVGInlineTextBoxes(TextStream& ts, const RenderText& text, int indent)
{
- for (InlineTextBox* box = text.firstTextBox(); box; box = box->nextTextBox())
+ for (InlineTextBox* box = text.firstTextBox(); box; box = box->nextTextBox()) {
+ if (!box->isSVGInlineTextBox())
+ continue;
+
writeSVGInlineTextBox(ts, static_cast<SVGInlineTextBox*>(box), indent);
+ }
}
static void writeStandardPrefix(TextStream& ts, const RenderObject& object, int indent)
diff --git a/Source/WebCore/rendering/svg/SVGResourcesCache.cpp b/Source/WebCore/rendering/svg/SVGResourcesCache.cpp
index 886f76a..74d2950 100644
--- a/Source/WebCore/rendering/svg/SVGResourcesCache.cpp
+++ b/Source/WebCore/rendering/svg/SVGResourcesCache.cpp
@@ -126,6 +126,10 @@ void SVGResourcesCache::clientStyleChanged(RenderObject* renderer, StyleDifferen
if (diff == StyleDifferenceEqual)
return;
+ // In this case the proper SVGFE*Element will imply whether the modifided CSS properties implies a relayout or repaint.
+ if (renderer->isSVGResourceFilterPrimitive() && diff == StyleDifferenceRepaint)
+ return;
+
clientUpdatedFromElement(renderer, newStyle);
RenderSVGResource::markForLayoutAndParentResourceInvalidation(renderer, false);
}
diff --git a/Source/WebCore/rendering/svg/SVGRootInlineBox.cpp b/Source/WebCore/rendering/svg/SVGRootInlineBox.cpp
index ddbd3ea..cc6cb75 100644
--- a/Source/WebCore/rendering/svg/SVGRootInlineBox.cpp
+++ b/Source/WebCore/rendering/svg/SVGRootInlineBox.cpp
@@ -35,7 +35,7 @@
namespace WebCore {
-void SVGRootInlineBox::paint(PaintInfo& paintInfo, int, int)
+void SVGRootInlineBox::paint(PaintInfo& paintInfo, int, int, int, int)
{
ASSERT(paintInfo.phase == PaintPhaseForeground || paintInfo.phase == PaintPhaseSelection);
ASSERT(!paintInfo.context->paintingDisabled());
@@ -63,7 +63,7 @@ void SVGRootInlineBox::paint(PaintInfo& paintInfo, int, int)
if (child->isSVGInlineTextBox())
SVGInlineFlowBox::computeTextMatchMarkerRectForRenderer(toRenderSVGInlineText(static_cast<SVGInlineTextBox*>(child)->textRenderer()));
- child->paint(childPaintInfo, 0, 0);
+ child->paint(childPaintInfo, 0, 0, 0, 0);
}
}
@@ -103,13 +103,13 @@ void SVGRootInlineBox::layoutCharactersInTextBoxes(InlineFlowBox* start, SVGText
SVGInlineTextBox* textBox = static_cast<SVGInlineTextBox*>(child);
characterLayout.layoutInlineTextBox(textBox);
} else {
- ASSERT(child->isInlineFlowBox());
-
// Skip generated content.
Node* node = child->renderer()->node();
if (!node)
continue;
+ ASSERT(child->isInlineFlowBox());
+
SVGInlineFlowBox* flowBox = static_cast<SVGInlineFlowBox*>(child);
bool isTextPath = node->hasTagName(SVGNames::textPathTag);
if (isTextPath) {
@@ -146,12 +146,12 @@ void SVGRootInlineBox::layoutChildBoxes(InlineFlowBox* start)
textBox->setLogicalWidth(boxRect.width());
textBox->setLogicalHeight(boxRect.height());
} else {
- ASSERT(child->isInlineFlowBox());
-
// Skip generated content.
if (!child->renderer()->node())
continue;
+ ASSERT(child->isInlineFlowBox());
+
SVGInlineFlowBox* flowBox = static_cast<SVGInlineFlowBox*>(child);
layoutChildBoxes(flowBox);
@@ -214,6 +214,8 @@ InlineBox* SVGRootInlineBox::closestLeafChildForPosition(const IntPoint& point)
// FIXME: Check for vertical text!
InlineBox* closestLeaf = 0;
for (InlineBox* leaf = firstLeaf; leaf; leaf = leaf->nextLeafChild()) {
+ if (!leaf->isSVGInlineTextBox())
+ continue;
if (point.y() < leaf->m_y)
continue;
if (point.y() > leaf->m_y + leaf->virtualLogicalHeight())
@@ -274,8 +276,13 @@ static inline void reverseInlineBoxRangeAndValueListsIfNeeded(void* userData, Ve
if (first == last || first == --last)
return;
- ASSERT((*first)->isSVGInlineTextBox());
- ASSERT((*last)->isSVGInlineTextBox());
+ if (!(*last)->isSVGInlineTextBox() || !(*first)->isSVGInlineTextBox()) {
+ InlineBox* temp = *first;
+ *first = *last;
+ *last = temp;
+ ++first;
+ continue;
+ }
SVGInlineTextBox* firstTextBox = static_cast<SVGInlineTextBox*>(*first);
SVGInlineTextBox* lastTextBox = static_cast<SVGInlineTextBox*>(*last);
diff --git a/Source/WebCore/rendering/svg/SVGRootInlineBox.h b/Source/WebCore/rendering/svg/SVGRootInlineBox.h
index 39612e7..a83af64 100644
--- a/Source/WebCore/rendering/svg/SVGRootInlineBox.h
+++ b/Source/WebCore/rendering/svg/SVGRootInlineBox.h
@@ -45,7 +45,7 @@ public:
virtual int virtualLogicalHeight() const { return m_logicalHeight; }
void setLogicalHeight(int height) { m_logicalHeight = height; }
- virtual void paint(PaintInfo&, int tx, int ty);
+ virtual void paint(PaintInfo&, int tx, int ty, int lineTop, int lineBottom);
void computePerCharacterLayoutInformation();
diff --git a/Source/WebCore/rendering/svg/SVGShadowTreeElements.cpp b/Source/WebCore/rendering/svg/SVGShadowTreeElements.cpp
index 9ccdef0..ac4a63e 100644
--- a/Source/WebCore/rendering/svg/SVGShadowTreeElements.cpp
+++ b/Source/WebCore/rendering/svg/SVGShadowTreeElements.cpp
@@ -53,21 +53,21 @@ PassRefPtr<Element> SVGShadowTreeContainerElement::cloneElementWithoutAttributes
}
// SVGShadowTreeRootElement
-inline SVGShadowTreeRootElement::SVGShadowTreeRootElement(Document* document, SVGUseElement* shadowParent)
+inline SVGShadowTreeRootElement::SVGShadowTreeRootElement(Document* document, SVGUseElement* host)
: SVGShadowTreeContainerElement(document)
{
- setShadowHost(shadowParent);
+ setParent(host);
setInDocument();
}
-PassRefPtr<SVGShadowTreeRootElement> SVGShadowTreeRootElement::create(Document* document, SVGUseElement* shadowParent)
+PassRefPtr<SVGShadowTreeRootElement> SVGShadowTreeRootElement::create(Document* document, SVGUseElement* host)
{
- return adoptRef(new SVGShadowTreeRootElement(document, shadowParent));
+ return adoptRef(new SVGShadowTreeRootElement(document, host));
}
void SVGShadowTreeRootElement::attachElement(PassRefPtr<RenderStyle> style, RenderArena* arena)
{
- ASSERT(shadowHost());
+ ASSERT(svgShadowHost());
// Create the renderer with the specified style
RenderObject* renderer = createRenderer(arena, style.get());
@@ -81,12 +81,12 @@ void SVGShadowTreeRootElement::attachElement(PassRefPtr<RenderStyle> style, Rend
// Add the renderer to the render tree
if (renderer)
- shadowHost()->renderer()->addChild(renderer);
+ svgShadowHost()->renderer()->addChild(renderer);
}
-void SVGShadowTreeRootElement::clearShadowHost()
+void SVGShadowTreeRootElement::clearSVGShadowHost()
{
- setShadowHost(0);
+ setParent(0);
}
}
diff --git a/Source/WebCore/rendering/svg/SVGShadowTreeElements.h b/Source/WebCore/rendering/svg/SVGShadowTreeElements.h
index 2952e35..8cbd4b7 100644
--- a/Source/WebCore/rendering/svg/SVGShadowTreeElements.h
+++ b/Source/WebCore/rendering/svg/SVGShadowTreeElements.h
@@ -53,13 +53,15 @@ private:
class SVGShadowTreeRootElement : public SVGShadowTreeContainerElement {
public:
- static PassRefPtr<SVGShadowTreeRootElement> create(Document*, SVGUseElement* shadowParent);
+ static PassRefPtr<SVGShadowTreeRootElement> create(Document*, SVGUseElement* host);
void attachElement(PassRefPtr<RenderStyle>, RenderArena*);
- void clearShadowHost();
+ void clearSVGShadowHost();
+
+ virtual bool isSVGShadowRoot() const { return true; }
private:
- SVGShadowTreeRootElement(Document*, SVGUseElement* shadowParent);
+ SVGShadowTreeRootElement(Document*, SVGUseElement* host);
};
}
diff --git a/Source/WebCore/rendering/svg/SVGTextChunkBuilder.cpp b/Source/WebCore/rendering/svg/SVGTextChunkBuilder.cpp
index 47311bd..4391013 100644
--- a/Source/WebCore/rendering/svg/SVGTextChunkBuilder.cpp
+++ b/Source/WebCore/rendering/svg/SVGTextChunkBuilder.cpp
@@ -53,7 +53,7 @@ void SVGTextChunkBuilder::buildTextChunks(Vector<SVGInlineTextBox*>& lineLayoutB
unsigned boxPosition = 0;
unsigned boxCount = lineLayoutBoxes.size();
for (; boxPosition < boxCount; ++boxPosition) {
- SVGInlineTextBox* textBox = lineLayoutBoxes.at(boxPosition);
+ SVGInlineTextBox* textBox = lineLayoutBoxes[boxPosition];
if (!textBox->startsNewTextChunk())
continue;
@@ -82,14 +82,14 @@ void SVGTextChunkBuilder::layoutTextChunks(Vector<SVGInlineTextBox*>& lineLayout
unsigned chunkCount = m_textChunks.size();
for (unsigned i = 0; i < chunkCount; ++i)
- processTextChunk(m_textChunks.at(i));
+ processTextChunk(m_textChunks[i]);
m_textChunks.clear();
}
void SVGTextChunkBuilder::addTextChunk(Vector<SVGInlineTextBox*>& lineLayoutBoxes, unsigned boxStart, unsigned boxCount)
{
- SVGInlineTextBox* textBox = lineLayoutBoxes.at(boxStart);
+ SVGInlineTextBox* textBox = lineLayoutBoxes[boxStart];
ASSERT(textBox);
RenderSVGInlineText* textRenderer = toRenderSVGInlineText(textBox->textRenderer());
@@ -127,7 +127,7 @@ void SVGTextChunkBuilder::addTextChunk(Vector<SVGInlineTextBox*>& lineLayoutBoxe
// Handle 'lengthAdjust' property.
float desiredTextLength = 0;
if (SVGTextContentElement* textContentElement = SVGTextContentElement::elementFromRenderer(textRenderer->parent())) {
- desiredTextLength = textContentElement->textLength().value(textContentElement);
+ desiredTextLength = textContentElement->specifiedTextLength().value(textContentElement);
switch (static_cast<SVGTextContentElement::SVGLengthAdjustType>(textContentElement->lengthAdjust())) {
case SVGTextContentElement::LENGTHADJUST_UNKNOWN:
@@ -145,7 +145,7 @@ void SVGTextChunkBuilder::addTextChunk(Vector<SVGInlineTextBox*>& lineLayoutBoxe
Vector<SVGInlineTextBox*>& boxes = chunk.boxes();
for (unsigned i = boxStart; i < boxStart + boxCount; ++i)
- boxes.append(lineLayoutBoxes.at(i));
+ boxes.append(lineLayoutBoxes[i]);
m_textChunks.append(chunk);
}
@@ -173,26 +173,26 @@ void SVGTextChunkBuilder::processTextChunk(const SVGTextChunk& chunk)
float textLengthShift = (chunk.desiredTextLength() - chunkLength) / chunkCharacters;
unsigned atCharacter = 0;
for (unsigned boxPosition = 0; boxPosition < boxCount; ++boxPosition) {
- Vector<SVGTextFragment>& fragments = boxes.at(boxPosition)->textFragments();
+ Vector<SVGTextFragment>& fragments = boxes[boxPosition]->textFragments();
if (fragments.isEmpty())
- continue;
+ continue;
processTextLengthSpacingCorrection(isVerticalText, textLengthShift, fragments, atCharacter);
}
} else {
ASSERT(chunk.hasLengthAdjustSpacingAndGlyphs());
- float scale = chunk.desiredTextLength() / chunkLength;
+ float textLengthScale = chunk.desiredTextLength() / chunkLength;
AffineTransform spacingAndGlyphsTransform;
bool foundFirstFragment = false;
for (unsigned boxPosition = 0; boxPosition < boxCount; ++boxPosition) {
- SVGInlineTextBox* textBox = boxes.at(boxPosition);
+ SVGInlineTextBox* textBox = boxes[boxPosition];
Vector<SVGTextFragment>& fragments = textBox->textFragments();
if (fragments.isEmpty())
continue;
-
+
if (!foundFirstFragment) {
foundFirstFragment = true;
- buildSpacingAndGlyphsTransform(isVerticalText, scale, fragments.first(), spacingAndGlyphsTransform);
+ buildSpacingAndGlyphsTransform(isVerticalText, textLengthScale, fragments.first(), spacingAndGlyphsTransform);
}
m_textBoxTransformations.set(textBox, spacingAndGlyphsTransform);
@@ -212,7 +212,7 @@ void SVGTextChunkBuilder::processTextChunk(const SVGTextChunk& chunk)
float textAnchorShift = chunk.calculateTextAnchorShift(chunkLength);
for (unsigned boxPosition = 0; boxPosition < boxCount; ++boxPosition) {
- Vector<SVGTextFragment>& fragments = boxes.at(boxPosition)->textFragments();
+ Vector<SVGTextFragment>& fragments = boxes[boxPosition]->textFragments();
if (fragments.isEmpty())
continue;
processTextAnchorCorrection(isVerticalText, textAnchorShift, fragments);
@@ -223,7 +223,7 @@ void SVGTextChunkBuilder::processTextLengthSpacingCorrection(bool isVerticalText
{
unsigned fragmentCount = fragments.size();
for (unsigned i = 0; i < fragmentCount; ++i) {
- SVGTextFragment& fragment = fragments.at(i);
+ SVGTextFragment& fragment = fragments[i];
if (isVerticalText)
fragment.y += textLengthShift * atCharacter;
@@ -238,7 +238,7 @@ void SVGTextChunkBuilder::processTextAnchorCorrection(bool isVerticalText, float
{
unsigned fragmentCount = fragments.size();
for (unsigned i = 0; i < fragmentCount; ++i) {
- SVGTextFragment& fragment = fragments.at(i);
+ SVGTextFragment& fragment = fragments[i];
if (isVerticalText)
fragment.y += textAnchorShift;
diff --git a/Source/WebCore/rendering/svg/SVGTextFragment.h b/Source/WebCore/rendering/svg/SVGTextFragment.h
index b5b3c57..a44d0fa 100644
--- a/Source/WebCore/rendering/svg/SVGTextFragment.h
+++ b/Source/WebCore/rendering/svg/SVGTextFragment.h
@@ -31,6 +31,7 @@ struct SVGTextFragment {
: characterOffset(0)
, metricsListOffset(0)
, length(0)
+ , isTextOnPath(false)
, x(0)
, y(0)
, width(0)
@@ -38,19 +39,74 @@ struct SVGTextFragment {
{
}
+ enum TransformType {
+ TransformRespectingTextLength,
+ TransformIgnoringTextLength
+ };
+
+ void buildFragmentTransform(AffineTransform& result, TransformType type = TransformRespectingTextLength) const
+ {
+ if (type == TransformIgnoringTextLength) {
+ result = transform;
+ transformAroundOrigin(result);
+ return;
+ }
+
+ if (isTextOnPath)
+ buildTransformForTextOnPath(result);
+ else
+ buildTransformForTextOnLine(result);
+ }
+
// The first rendered character starts at RenderSVGInlineText::characters() + characterOffset.
unsigned characterOffset;
unsigned metricsListOffset;
- unsigned length;
+ unsigned length : 31;
+ bool isTextOnPath : 1;
float x;
float y;
float width;
float height;
- // Includes rotation/glyph-orientation-(horizontal|vertical) transforms, lengthAdjust="spacingAndGlyphs" (for textPath only),
- // as well as orientation related shifts (see SVGTextLayoutEngine, which builds this transformation).
+ // Includes rotation/glyph-orientation-(horizontal|vertical) transforms, as well as orientation related shifts
+ // (see SVGTextLayoutEngine, which builds this transformation).
AffineTransform transform;
+
+ // Contains lengthAdjust related transformations, which are not allowd to influence the SVGTextQuery code.
+ AffineTransform lengthAdjustTransform;
+
+private:
+ void transformAroundOrigin(AffineTransform& result) const
+ {
+ // Returns (translate(x, y) * result) * translate(-x, -y).
+ result.setE(result.e() + x);
+ result.setF(result.f() + y);
+ result.translate(-x, -y);
+ }
+
+ void buildTransformForTextOnPath(AffineTransform& result) const
+ {
+ // For text-on-path layout, multiply the transform with the lengthAdjustTransform before orienting the resulting transform.
+ result = lengthAdjustTransform.isIdentity() ? transform : transform * lengthAdjustTransform;
+ if (!result.isIdentity())
+ transformAroundOrigin(result);
+ }
+
+ void buildTransformForTextOnLine(AffineTransform& result) const
+ {
+ // For text-on-line layout, orient the transform first, then multiply the lengthAdjustTransform with the oriented transform.
+ if (transform.isIdentity()) {
+ result = lengthAdjustTransform;
+ return;
+ }
+
+ result = transform;
+ transformAroundOrigin(result);
+
+ if (!lengthAdjustTransform.isIdentity())
+ result = lengthAdjustTransform * result;
+ }
};
} // namespace WebCore
diff --git a/Source/WebCore/rendering/svg/SVGTextLayoutAttributes.cpp b/Source/WebCore/rendering/svg/SVGTextLayoutAttributes.cpp
index 4c227b4..df2cffe 100644
--- a/Source/WebCore/rendering/svg/SVGTextLayoutAttributes.cpp
+++ b/Source/WebCore/rendering/svg/SVGTextLayoutAttributes.cpp
@@ -34,11 +34,44 @@ SVGTextLayoutAttributes::SVGTextLayoutAttributes(RenderSVGInlineText* context)
void SVGTextLayoutAttributes::reserveCapacity(unsigned length)
{
- m_xValues.reserveCapacity(length);
- m_yValues.reserveCapacity(length);
- m_dxValues.reserveCapacity(length);
- m_dyValues.reserveCapacity(length);
- m_rotateValues.reserveCapacity(length);
+ m_positioningLists.xValues.reserveCapacity(length);
+ m_positioningLists.yValues.reserveCapacity(length);
+ m_positioningLists.dxValues.reserveCapacity(length);
+ m_positioningLists.dyValues.reserveCapacity(length);
+ m_positioningLists.rotateValues.reserveCapacity(length);
+ m_textMetricsValues.reserveCapacity(length);
+}
+
+void SVGTextLayoutAttributes::PositioningLists::fillWithEmptyValues(unsigned length)
+{
+ xValues.fill(SVGTextLayoutAttributes::emptyValue(), length);
+ yValues.fill(SVGTextLayoutAttributes::emptyValue(), length);
+ dxValues.fill(SVGTextLayoutAttributes::emptyValue(), length);
+ dyValues.fill(SVGTextLayoutAttributes::emptyValue(), length);
+ rotateValues.fill(SVGTextLayoutAttributes::emptyValue(), length);
+}
+
+void SVGTextLayoutAttributes::PositioningLists::appendEmptyValues()
+{
+ xValues.append(SVGTextLayoutAttributes::emptyValue());
+ yValues.append(SVGTextLayoutAttributes::emptyValue());
+ dxValues.append(SVGTextLayoutAttributes::emptyValue());
+ dyValues.append(SVGTextLayoutAttributes::emptyValue());
+ rotateValues.append(SVGTextLayoutAttributes::emptyValue());
+}
+
+static inline float safeValueAtPosition(const Vector<float>& values, unsigned position)
+{
+ return position < values.size() ? values[position] : SVGTextLayoutAttributes::emptyValue();
+}
+
+void SVGTextLayoutAttributes::PositioningLists::appendValuesFromPosition(const PositioningLists& source, unsigned position)
+{
+ xValues.append(safeValueAtPosition(source.xValues, position));
+ yValues.append(safeValueAtPosition(source.yValues, position));
+ dxValues.append(safeValueAtPosition(source.dxValues, position));
+ dyValues.append(safeValueAtPosition(source.dyValues, position));
+ rotateValues.append(safeValueAtPosition(source.rotateValues, position));
}
float SVGTextLayoutAttributes::emptyValue()
@@ -69,23 +102,23 @@ void SVGTextLayoutAttributes::dump() const
fprintf(stderr, "context: %p\n", m_context);
fprintf(stderr, "x values: ");
- dumpLayoutVector(m_xValues);
+ dumpLayoutVector(m_positioningLists.xValues);
fprintf(stderr, "\n");
fprintf(stderr, "y values: ");
- dumpLayoutVector(m_yValues);
+ dumpLayoutVector(m_positioningLists.yValues);
fprintf(stderr, "\n");
fprintf(stderr, "dx values: ");
- dumpLayoutVector(m_dxValues);
+ dumpLayoutVector(m_positioningLists.dxValues);
fprintf(stderr, "\n");
fprintf(stderr, "dy values: ");
- dumpLayoutVector(m_dyValues);
+ dumpLayoutVector(m_positioningLists.dyValues);
fprintf(stderr, "\n");
fprintf(stderr, "rotate values: ");
- dumpLayoutVector(m_rotateValues);
+ dumpLayoutVector(m_positioningLists.rotateValues);
fprintf(stderr, "\n");
fprintf(stderr, "character data values:\n");
diff --git a/Source/WebCore/rendering/svg/SVGTextLayoutAttributes.h b/Source/WebCore/rendering/svg/SVGTextLayoutAttributes.h
index fc6bd10..8b45d3d 100644
--- a/Source/WebCore/rendering/svg/SVGTextLayoutAttributes.h
+++ b/Source/WebCore/rendering/svg/SVGTextLayoutAttributes.h
@@ -31,6 +31,18 @@ class RenderSVGInlineText;
class SVGTextLayoutAttributes {
public:
+ struct PositioningLists {
+ void fillWithEmptyValues(unsigned length);
+ void appendEmptyValues();
+ void appendValuesFromPosition(const PositioningLists&, unsigned position);
+
+ Vector<float> xValues;
+ Vector<float> yValues;
+ Vector<float> dxValues;
+ Vector<float> dyValues;
+ Vector<float> rotateValues;
+ };
+
SVGTextLayoutAttributes(RenderSVGInlineText* context = 0);
void reserveCapacity(unsigned length);
@@ -40,31 +52,30 @@ public:
RenderSVGInlineText* context() const { return m_context; }
- Vector<float>& xValues() { return m_xValues; }
- const Vector<float>& xValues() const { return m_xValues; }
+ PositioningLists& positioningLists() { return m_positioningLists; }
+ const PositioningLists& positioningLists() const { return m_positioningLists; }
+
+ Vector<float>& xValues() { return m_positioningLists.xValues; }
+ const Vector<float>& xValues() const { return m_positioningLists.xValues; }
- Vector<float>& yValues() { return m_yValues; }
- const Vector<float>& yValues() const { return m_yValues; }
+ Vector<float>& yValues() { return m_positioningLists.yValues; }
+ const Vector<float>& yValues() const { return m_positioningLists.yValues; }
- Vector<float>& dxValues() { return m_dxValues; }
- const Vector<float>& dxValues() const { return m_dxValues; }
+ Vector<float>& dxValues() { return m_positioningLists.dxValues; }
+ const Vector<float>& dxValues() const { return m_positioningLists.dxValues; }
- Vector<float>& dyValues() { return m_dyValues; }
- const Vector<float>& dyValues() const { return m_dyValues; }
+ Vector<float>& dyValues() { return m_positioningLists.dyValues; }
+ const Vector<float>& dyValues() const { return m_positioningLists.dyValues; }
- Vector<float>& rotateValues() { return m_rotateValues; }
- const Vector<float>& rotateValues() const { return m_rotateValues; }
+ Vector<float>& rotateValues() { return m_positioningLists.rotateValues; }
+ const Vector<float>& rotateValues() const { return m_positioningLists.rotateValues; }
Vector<SVGTextMetrics>& textMetricsValues() { return m_textMetricsValues; }
const Vector<SVGTextMetrics>& textMetricsValues() const { return m_textMetricsValues; }
private:
RenderSVGInlineText* m_context;
- Vector<float> m_xValues;
- Vector<float> m_yValues;
- Vector<float> m_dxValues;
- Vector<float> m_dyValues;
- Vector<float> m_rotateValues;
+ PositioningLists m_positioningLists;
Vector<SVGTextMetrics> m_textMetricsValues;
};
diff --git a/Source/WebCore/rendering/svg/SVGTextLayoutAttributesBuilder.cpp b/Source/WebCore/rendering/svg/SVGTextLayoutAttributesBuilder.cpp
index 86be424..42eb8e8 100644
--- a/Source/WebCore/rendering/svg/SVGTextLayoutAttributesBuilder.cpp
+++ b/Source/WebCore/rendering/svg/SVGTextLayoutAttributesBuilder.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) Research In Motion Limited 2010. All rights reserved.
+ * Copyright (C) Research In Motion Limited 2010-2011. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -38,20 +38,19 @@ SVGTextLayoutAttributesBuilder::SVGTextLayoutAttributesBuilder()
void SVGTextLayoutAttributesBuilder::buildLayoutAttributesForTextSubtree(RenderSVGText* textRoot)
{
ASSERT(textRoot);
- m_scopes.clear();
// Build list of x/y/dx/dy/rotate values for each subtree element that may define these values (tspan/textPath etc).
unsigned atCharacter = 0;
UChar lastCharacter = '\0';
- buildLayoutScopes(textRoot, atCharacter, lastCharacter);
+ collectTextPositioningElements(textRoot, atCharacter, lastCharacter);
if (!atCharacter)
return;
- // Build list of x/y/dx/dy/rotate values for the outermost <text> element.
- buildOutermostLayoutScope(textRoot, atCharacter);
+ // Collect x/y/dx/dy/rotate values for each character, stored in the m_positioningLists.xValues()/etc. lists.
+ buildLayoutAttributesForAllCharacters(textRoot, atCharacter);
- // Propagate layout attributes to each RenderSVGInlineText object.
+ // Propagate layout attributes to each RenderSVGInlineText object, and the whole list to the RenderSVGText root.
Vector<SVGTextLayoutAttributes>& allAttributes = textRoot->layoutAttributes();
allAttributes.clear();
atCharacter = 0;
@@ -85,40 +84,6 @@ static inline void extractFloatValuesFromSVGNumberList(const SVGNumberList& list
floatValues.append(list.at(i));
}
-void SVGTextLayoutAttributesBuilder::buildLayoutScope(LayoutScope& scope, RenderObject* renderer, unsigned textContentStart, unsigned textContentLength) const
-{
- ASSERT(renderer);
- ASSERT(renderer->style());
-
- scope.textContentStart = textContentStart;
- scope.textContentLength = textContentLength;
-
- SVGTextPositioningElement* element = SVGTextPositioningElement::elementFromRenderer(renderer);
- if (!element)
- return;
-
- SVGTextLayoutAttributes& attributes = scope.attributes;
- extractFloatValuesFromSVGLengthList(element, element->x(), attributes.xValues(), textContentLength);
- extractFloatValuesFromSVGLengthList(element, element->y(), attributes.yValues(), textContentLength);
- extractFloatValuesFromSVGLengthList(element, element->dx(), attributes.dxValues(), textContentLength);
- extractFloatValuesFromSVGLengthList(element, element->dy(), attributes.dyValues(), textContentLength);
- extractFloatValuesFromSVGNumberList(element->rotate(), attributes.rotateValues(), textContentLength);
-
- // The last rotation value spans the whole scope.
- Vector<float>& rotateValues = attributes.rotateValues();
- if (rotateValues.isEmpty())
- return;
-
- unsigned rotateValuesSize = rotateValues.size();
- if (rotateValuesSize == textContentLength)
- return;
-
- float lastRotation = rotateValues.last();
-
- rotateValues.resize(textContentLength);
- for (unsigned i = rotateValuesSize; i < textContentLength; ++i)
- rotateValues.at(i) = lastRotation;
-}
static inline bool characterIsSpace(const UChar& character)
{
@@ -136,56 +101,84 @@ static inline bool shouldPreserveAllWhiteSpace(RenderStyle* style)
return style->whiteSpace() == PRE;
}
-void SVGTextLayoutAttributesBuilder::buildLayoutScopes(RenderObject* start, unsigned& atCharacter, UChar& lastCharacter)
+static inline void processRenderSVGInlineText(RenderSVGInlineText* text, unsigned& atCharacter, UChar& lastCharacter)
{
- for (RenderObject* child = start->firstChild(); child; child = child->nextSibling()) {
- if (child->isSVGInlineText()) {
- RenderSVGInlineText* text = toRenderSVGInlineText(child);
+ if (shouldPreserveAllWhiteSpace(text->style())) {
+ atCharacter += text->textLength();
+ return;
+ }
- if (!shouldPreserveAllWhiteSpace(text->style())) {
- const UChar* characters = text->characters();
- unsigned textLength = text->textLength();
- for (unsigned textPosition = 0; textPosition < textLength; ++textPosition) {
- const UChar& currentCharacter = characters[textPosition];
- if (characterIsSpace(currentCharacter) && characterIsSpaceOrNull(lastCharacter))
- continue;
+ const UChar* characters = text->characters();
+ unsigned textLength = text->textLength();
+ for (unsigned textPosition = 0; textPosition < textLength; ++textPosition) {
+ const UChar& currentCharacter = characters[textPosition];
+ if (characterIsSpace(currentCharacter) && characterIsSpaceOrNull(lastCharacter))
+ continue;
- lastCharacter = currentCharacter;
- ++atCharacter;
- }
- } else
- atCharacter += text->textLength();
+ lastCharacter = currentCharacter;
+ ++atCharacter;
+ }
+}
+
+void SVGTextLayoutAttributesBuilder::collectTextPositioningElements(RenderObject* start, unsigned& atCharacter, UChar& lastCharacter)
+{
+ ASSERT(!start->isSVGText() || m_textPositions.isEmpty());
+ for (RenderObject* child = start->firstChild(); child; child = child->nextSibling()) {
+ if (child->isSVGInlineText()) {
+ processRenderSVGInlineText(toRenderSVGInlineText(child), atCharacter, lastCharacter);
continue;
}
if (!child->isSVGInline())
continue;
- unsigned textContentStart = atCharacter;
- buildLayoutScopes(child, atCharacter, lastCharacter);
+ SVGTextPositioningElement* element = SVGTextPositioningElement::elementFromRenderer(child);
+ unsigned atPosition = m_textPositions.size();
+ if (element)
+ m_textPositions.append(TextPosition(element, atCharacter));
+
+ collectTextPositioningElements(child, atCharacter, lastCharacter);
+
+ if (!element)
+ continue;
- LayoutScope scope;
- buildLayoutScope(scope, child, textContentStart, atCharacter - textContentStart);
- m_scopes.append(scope);
+ // Update text position, after we're back from recursion.
+ TextPosition& position = m_textPositions[atPosition];
+ ASSERT(!position.length);
+ position.length = atCharacter - position.start;
}
}
-void SVGTextLayoutAttributesBuilder::buildOutermostLayoutScope(RenderSVGText* textRoot, unsigned textLength)
+void SVGTextLayoutAttributesBuilder::buildLayoutAttributesForAllCharacters(RenderSVGText* textRoot, unsigned textLength)
{
- LayoutScope scope;
- buildLayoutScope(scope, textRoot, 0, textLength);
+ ASSERT(textLength);
- // Handle <text> x/y default attributes.
- Vector<float>& xValues = scope.attributes.xValues();
- if (xValues.isEmpty())
- xValues.append(0);
+ SVGTextPositioningElement* outermostTextElement = SVGTextPositioningElement::elementFromRenderer(textRoot);
+ ASSERT(outermostTextElement);
- Vector<float>& yValues = scope.attributes.yValues();
- if (yValues.isEmpty())
- yValues.append(0);
+ // Fill the lists with the special emptyValue marker.
+ m_positioningLists.fillWithEmptyValues(textLength);
- m_scopes.prepend(scope);
+ // Grab outermost <text> element value lists and insert them in the m_positioningLists.
+ TextPosition wholeTextPosition(outermostTextElement, 0, textLength);
+ fillAttributesAtPosition(wholeTextPosition);
+
+ // Handle x/y default attributes.
+ float& xFirst = m_positioningLists.xValues.first();
+ if (xFirst == SVGTextLayoutAttributes::emptyValue())
+ xFirst = 0;
+
+ float& yFirst = m_positioningLists.yValues.first();
+ if (yFirst == SVGTextLayoutAttributes::emptyValue())
+ yFirst = 0;
+
+ // Fill m_positioningLists using child text positioning elements in top-down order.
+ unsigned size = m_textPositions.size();
+ for (unsigned i = 0; i < size; ++i)
+ fillAttributesAtPosition(m_textPositions[i]);
+
+ // Now m_positioningLists.contains a x/y/dx/dy/rotate value for each character in the <text> subtree.
}
void SVGTextLayoutAttributesBuilder::propagateLayoutAttributes(RenderObject* start, Vector<SVGTextLayoutAttributes>& allAttributes, unsigned& atCharacter, UChar& lastCharacter) const
@@ -222,16 +215,19 @@ void SVGTextLayoutAttributesBuilder::propagateLayoutAttributes(RenderObject* sta
metricsLength = currentMetrics.length();
if (!preserveWhiteSpace && characterIsSpace(currentCharacter) && characterIsSpaceOrNull(lastCharacter)) {
- assignEmptyLayoutAttributesForCharacter(attributes);
+ attributes.positioningLists().appendEmptyValues();
attributes.textMetricsValues().append(SVGTextMetrics::emptyMetrics());
continue;
}
- assignLayoutAttributesForCharacter(attributes, currentMetrics, valueListPosition);
+ SVGTextLayoutAttributes::PositioningLists& positioningLists = attributes.positioningLists();
+ positioningLists.appendValuesFromPosition(m_positioningLists, valueListPosition);
+ attributes.textMetricsValues().append(currentMetrics);
+ // Pad x/y/dx/dy/rotate value lists with empty values, if the metrics span more than one character.
if (metricsLength > 1) {
for (unsigned i = 0; i < metricsLength - 1; ++i)
- assignEmptyLayoutAttributesForCharacter(attributes);
+ positioningLists.appendEmptyValues();
}
lastCharacter = currentCharacter;
@@ -257,67 +253,42 @@ void SVGTextLayoutAttributesBuilder::propagateLayoutAttributes(RenderObject* sta
}
}
-float SVGTextLayoutAttributesBuilder::nextLayoutValue(LayoutValueType type, unsigned atCharacter) const
+static inline void fillListAtPosition(Vector<float>& allValues, Vector<float>& values, unsigned start)
{
- for (int i = m_scopes.size() - 1; i >= 0; --i) {
- const LayoutScope& scope = m_scopes.at(i);
- if (scope.textContentStart > atCharacter || scope.textContentStart + scope.textContentLength < atCharacter)
- continue;
+ unsigned valuesSize = values.size();
+ for (unsigned i = 0; i < valuesSize; ++i)
+ allValues[start + i] = values[i];
+}
- const Vector<float>* valuesPointer = 0;
- switch (type) {
- case XValueAttribute:
- valuesPointer = &scope.attributes.xValues();
- break;
- case YValueAttribute:
- valuesPointer = &scope.attributes.yValues();
- break;
- case DxValueAttribute:
- valuesPointer = &scope.attributes.dxValues();
- break;
- case DyValueAttribute:
- valuesPointer = &scope.attributes.dyValues();
- break;
- case RotateValueAttribute:
- valuesPointer = &scope.attributes.rotateValues();
- break;
- default:
- ASSERT_NOT_REACHED();
- }
+void SVGTextLayoutAttributesBuilder::fillAttributesAtPosition(const TextPosition& position)
+{
+ Vector<float> values;
+ extractFloatValuesFromSVGLengthList(position.element, position.element->x(), values, position.length);
+ fillListAtPosition(m_positioningLists.xValues, values, position.start);
- ASSERT(valuesPointer);
- const Vector<float>& values = *valuesPointer;
- if (values.isEmpty())
- continue;
+ values.clear();
+ extractFloatValuesFromSVGLengthList(position.element, position.element->y(), values, position.length);
+ fillListAtPosition(m_positioningLists.yValues, values, position.start);
- unsigned position = atCharacter - scope.textContentStart;
- if (position >= values.size())
- continue;
+ values.clear();
+ extractFloatValuesFromSVGLengthList(position.element, position.element->dx(), values, position.length);
+ fillListAtPosition(m_positioningLists.dxValues, values, position.start);
- return values.at(position);
- }
+ values.clear();
+ extractFloatValuesFromSVGLengthList(position.element, position.element->dy(), values, position.length);
+ fillListAtPosition(m_positioningLists.dyValues, values, position.start);
- return SVGTextLayoutAttributes::emptyValue();
-}
+ values.clear();
+ extractFloatValuesFromSVGNumberList(position.element->rotate(), values, position.length);
+ fillListAtPosition(m_positioningLists.rotateValues, values, position.start);
-void SVGTextLayoutAttributesBuilder::assignLayoutAttributesForCharacter(SVGTextLayoutAttributes& attributes, SVGTextMetrics& metrics, unsigned valueListPosition) const
-{
- attributes.xValues().append(nextLayoutValue(XValueAttribute, valueListPosition));
- attributes.yValues().append(nextLayoutValue(YValueAttribute, valueListPosition));
- attributes.dxValues().append(nextLayoutValue(DxValueAttribute, valueListPosition));
- attributes.dyValues().append(nextLayoutValue(DyValueAttribute, valueListPosition));
- attributes.rotateValues().append(nextLayoutValue(RotateValueAttribute, valueListPosition));
- attributes.textMetricsValues().append(metrics);
-}
+ // The last rotation value always spans the whole scope.
+ if (values.isEmpty())
+ return;
-void SVGTextLayoutAttributesBuilder::assignEmptyLayoutAttributesForCharacter(SVGTextLayoutAttributes& attributes) const
-{
- attributes.xValues().append(SVGTextLayoutAttributes::emptyValue());
- attributes.yValues().append(SVGTextLayoutAttributes::emptyValue());
- attributes.dxValues().append(SVGTextLayoutAttributes::emptyValue());
- attributes.dyValues().append(SVGTextLayoutAttributes::emptyValue());
- attributes.rotateValues().append(SVGTextLayoutAttributes::emptyValue());
- // This doesn't add an empty value to textMetricsValues() on purpose!
+ float lastValue = values.last();
+ for (unsigned i = values.size(); i < position.length; ++i)
+ m_positioningLists.rotateValues[position.start + i] = lastValue;
}
}
diff --git a/Source/WebCore/rendering/svg/SVGTextLayoutAttributesBuilder.h b/Source/WebCore/rendering/svg/SVGTextLayoutAttributesBuilder.h
index b368c51..a5995c0 100644
--- a/Source/WebCore/rendering/svg/SVGTextLayoutAttributesBuilder.h
+++ b/Source/WebCore/rendering/svg/SVGTextLayoutAttributesBuilder.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) Research In Motion Limited 2010. All rights reserved.
+ * Copyright (C) Research In Motion Limited 2010-2011. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -28,6 +28,7 @@ namespace WebCore {
class RenderObject;
class RenderSVGText;
+class SVGTextPositioningElement;
// SVGTextLayoutAttributesBuilder performs the first layout phase for SVG text.
//
@@ -45,37 +46,27 @@ public:
void buildLayoutAttributesForTextSubtree(RenderSVGText*);
private:
- struct LayoutScope {
- LayoutScope()
- : textContentStart(0)
- , textContentLength(0)
+ struct TextPosition {
+ TextPosition(SVGTextPositioningElement* newElement = 0, unsigned newStart = 0, unsigned newLength = 0)
+ : element(newElement)
+ , start(newStart)
+ , length(newLength)
{
}
- unsigned textContentStart;
- unsigned textContentLength;
- SVGTextLayoutAttributes attributes;
+ SVGTextPositioningElement* element;
+ unsigned start;
+ unsigned length;
};
- void buildLayoutScope(LayoutScope&, RenderObject*, unsigned textContentStart, unsigned textContentLength) const;
- void buildLayoutScopes(RenderObject*, unsigned& atCharacter, UChar& lastCharacter);
- void buildOutermostLayoutScope(RenderSVGText*, unsigned textLength);
+ void collectTextPositioningElements(RenderObject*, unsigned& atCharacter, UChar& lastCharacter);
+ void buildLayoutAttributesForAllCharacters(RenderSVGText*, unsigned textLength);
void propagateLayoutAttributes(RenderObject*, Vector<SVGTextLayoutAttributes>& allAttributes, unsigned& atCharacter, UChar& lastCharacter) const;
-
- enum LayoutValueType {
- XValueAttribute,
- YValueAttribute,
- DxValueAttribute,
- DyValueAttribute,
- RotateValueAttribute
- };
-
- float nextLayoutValue(LayoutValueType, unsigned atCharacter) const;
- void assignLayoutAttributesForCharacter(SVGTextLayoutAttributes&, SVGTextMetrics&, unsigned valueListPosition) const;
- void assignEmptyLayoutAttributesForCharacter(SVGTextLayoutAttributes&) const;
+ void fillAttributesAtPosition(const TextPosition&);
private:
- Vector<LayoutScope> m_scopes;
+ Vector<TextPosition> m_textPositions;
+ SVGTextLayoutAttributes::PositioningLists m_positioningLists;
};
} // namespace WebCore
diff --git a/Source/WebCore/rendering/svg/SVGTextLayoutEngine.cpp b/Source/WebCore/rendering/svg/SVGTextLayoutEngine.cpp
index 71db2ea..2bc7e32 100644
--- a/Source/WebCore/rendering/svg/SVGTextLayoutEngine.cpp
+++ b/Source/WebCore/rendering/svg/SVGTextLayoutEngine.cpp
@@ -157,7 +157,7 @@ bool SVGTextLayoutEngine::parentDefinesTextLength(RenderObject* parent) const
SVGTextContentElement* textContentElement = SVGTextContentElement::elementFromRenderer(currentParent);
if (textContentElement) {
SVGTextContentElement::SVGLengthAdjustType lengthAdjust = static_cast<SVGTextContentElement::SVGLengthAdjustType>(textContentElement->lengthAdjust());
- if (lengthAdjust == SVGTextContentElement::LENGTHADJUST_SPACING && textContentElement->textLength().value(textContentElement) > 0)
+ if (lengthAdjust == SVGTextContentElement::LENGTHADJUST_SPACING && textContentElement->specifiedTextLength().value(textContentElement) > 0)
return true;
}
@@ -213,7 +213,7 @@ void SVGTextLayoutEngine::beginTextPathLayout(RenderObject* object, SVGTextLayou
if (SVGTextContentElement* textContentElement = SVGTextContentElement::elementFromRenderer(textPath)) {
lengthAdjust = static_cast<SVGTextContentElement::SVGLengthAdjustType>(textContentElement->lengthAdjust());
- desiredTextLength = textContentElement->textLength().value(textContentElement);
+ desiredTextLength = textContentElement->specifiedTextLength().value(textContentElement);
}
if (!desiredTextLength)
@@ -261,34 +261,10 @@ void SVGTextLayoutEngine::layoutInlineTextBox(SVGInlineTextBox* textBox)
m_lineLayoutBoxes.append(textBox);
}
-void SVGTextLayoutEngine::finishLayout()
-{
- // After all text fragments are stored in their correpsonding SVGInlineTextBoxes, we can layout individual text chunks.
- // Chunk layouting is only performed for line layout boxes, not for path layout, where it has already been done.
- m_chunkLayoutBuilder.layoutTextChunks(m_lineLayoutBoxes);
-
- // Finalize transform matrices, after the chunk layout corrections have been applied, and all fragment x/y positions are finalized.
- if (!m_lineLayoutBoxes.isEmpty()) {
-#if DUMP_TEXT_FRAGMENTS > 0
- fprintf(stderr, "Line layout: ");
-#endif
-
- finalizeTransformMatrices(m_lineLayoutBoxes);
- }
-
- if (!m_pathLayoutBoxes.isEmpty()) {
#if DUMP_TEXT_FRAGMENTS > 0
- fprintf(stderr, "Path layout: ");
-#endif
- finalizeTransformMatrices(m_pathLayoutBoxes);
- }
-}
-
-void SVGTextLayoutEngine::finalizeTransformMatrices(Vector<SVGInlineTextBox*>& boxes)
+static inline void dumpTextBoxes(Vector<SVGInlineTextBox*>& boxes)
{
unsigned boxCount = boxes.size();
-
-#if DUMP_TEXT_FRAGMENTS > 0
fprintf(stderr, "Dumping all text fragments in text sub tree, %i boxes\n", boxCount);
for (unsigned boxPosition = 0; boxPosition < boxCount; ++boxPosition) {
@@ -308,9 +284,12 @@ void SVGTextLayoutEngine::finalizeTransformMatrices(Vector<SVGInlineTextBox*>& b
, i, fragment.x, fragment.y, fragment.width, fragment.height, fragment.characterOffset, fragment.length, fragmentString.utf8().data());
}
}
+}
#endif
-
+void SVGTextLayoutEngine::finalizeTransformMatrices(Vector<SVGInlineTextBox*>& boxes)
+{
+ unsigned boxCount = boxes.size();
if (!boxCount)
return;
@@ -321,29 +300,48 @@ void SVGTextLayoutEngine::finalizeTransformMatrices(Vector<SVGInlineTextBox*>& b
unsigned fragmentCount = fragments.size();
for (unsigned i = 0; i < fragmentCount; ++i) {
- SVGTextFragment& fragment = fragments.at(i);
- AffineTransform& transform = fragment.transform;
- if (!transform.isIdentity()) {
- transform = AffineTransform::translation(fragment.x, fragment.y) * transform;
- transform.translate(-fragment.x, -fragment.y);
- }
-
m_chunkLayoutBuilder.transformationForTextBox(textBox, textBoxTransformation);
if (textBoxTransformation.isIdentity())
continue;
-
- if (transform.isIdentity())
- transform = textBoxTransformation;
- else
- transform = textBoxTransformation * transform;
+ ASSERT(fragments[i].lengthAdjustTransform.isIdentity());
+ fragments[i].lengthAdjustTransform = textBoxTransformation;
}
}
boxes.clear();
}
+void SVGTextLayoutEngine::finishLayout()
+{
+ // After all text fragments are stored in their correpsonding SVGInlineTextBoxes, we can layout individual text chunks.
+ // Chunk layouting is only performed for line layout boxes, not for path layout, where it has already been done.
+ m_chunkLayoutBuilder.layoutTextChunks(m_lineLayoutBoxes);
+
+ // Finalize transform matrices, after the chunk layout corrections have been applied, and all fragment x/y positions are finalized.
+ if (!m_lineLayoutBoxes.isEmpty()) {
+#if DUMP_TEXT_FRAGMENTS > 0
+ fprintf(stderr, "Line layout: ");
+ dumpTextBoxes(m_lineLayoutBoxes);
+#endif
+
+ finalizeTransformMatrices(m_lineLayoutBoxes);
+ }
+
+ if (!m_pathLayoutBoxes.isEmpty()) {
+#if DUMP_TEXT_FRAGMENTS > 0
+ fprintf(stderr, "Path layout: ");
+ dumpTextBoxes(m_pathLayoutBoxes);
+#endif
+
+ finalizeTransformMatrices(m_pathLayoutBoxes);
+ }
+}
+
bool SVGTextLayoutEngine::currentLogicalCharacterAttributes(SVGTextLayoutAttributes& logicalAttributes)
{
+ if (m_layoutAttributes.isEmpty())
+ return false;
+
logicalAttributes = m_layoutAttributes.first();
if (m_logicalCharacterOffset != logicalAttributes.xValues().size())
return true;
@@ -374,6 +372,8 @@ bool SVGTextLayoutEngine::currentLogicalCharacterMetrics(SVGTextLayoutAttributes
continue;
}
+ ASSERT(textMetricsSize);
+ ASSERT(m_logicalMetricsListOffset < textMetricsSize);
logicalMetrics = textMetricsValues.at(m_logicalMetricsListOffset);
if (logicalMetrics == SVGTextMetrics::emptyMetrics() || (!logicalMetrics.width() && !logicalMetrics.height())) {
advanceToNextLogicalCharacter(logicalMetrics);
@@ -634,11 +634,12 @@ void SVGTextLayoutEngine::layoutTextOnLineOrPath(SVGInlineTextBox* textBox, Rend
if (orientationAngle)
m_currentTextFragment.transform.rotate(orientationAngle);
- if (m_inPathLayout && m_textPathScaling != 1) {
+ m_currentTextFragment.isTextOnPath = m_inPathLayout && m_textPathScaling != 1;
+ if (m_currentTextFragment.isTextOnPath) {
if (m_isVerticalText)
- m_currentTextFragment.transform.scaleNonUniform(1, m_textPathScaling);
+ m_currentTextFragment.lengthAdjustTransform.scaleNonUniform(1, m_textPathScaling);
else
- m_currentTextFragment.transform.scaleNonUniform(m_textPathScaling, 1);
+ m_currentTextFragment.lengthAdjustTransform.scaleNonUniform(m_textPathScaling, 1);
}
}
diff --git a/Source/WebCore/rendering/svg/SVGTextQuery.cpp b/Source/WebCore/rendering/svg/SVGTextQuery.cpp
index 5f3523e..c141c11 100644
--- a/Source/WebCore/rendering/svg/SVGTextQuery.cpp
+++ b/Source/WebCore/rendering/svg/SVGTextQuery.cpp
@@ -80,17 +80,6 @@ static inline InlineFlowBox* flowBoxForRenderer(RenderObject* renderer)
return 0;
}
-static inline float mapLengthThroughFragmentTransformation(const SVGTextFragment& fragment, bool isVerticalText, float length)
-{
- if (fragment.transform.isIdentity())
- return length;
-
- if (isVerticalText)
- return narrowPrecisionToFloat(static_cast<double>(length) * fragment.transform.yScale());
-
- return narrowPrecisionToFloat(static_cast<double>(length) * fragment.transform.xScale());
-}
-
SVGTextQuery::SVGTextQuery(RenderObject* renderer)
{
collectTextBoxesInFlowBox(flowBoxForRenderer(renderer));
@@ -111,8 +100,8 @@ void SVGTextQuery::collectTextBoxesInFlowBox(InlineFlowBox* flowBox)
continue;
}
- ASSERT(child->isSVGInlineTextBox());
- m_textBoxes.append(static_cast<SVGInlineTextBox*>(child));
+ if (child->isSVGInlineTextBox())
+ m_textBoxes.append(static_cast<SVGInlineTextBox*>(child));
}
}
@@ -273,9 +262,7 @@ struct TextLengthData : SVGTextQuery::Data {
bool SVGTextQuery::textLengthCallback(Data* queryData, const SVGTextFragment& fragment) const
{
TextLengthData* data = static_cast<TextLengthData*>(queryData);
-
- float fragmentLength = queryData->isVerticalText ? fragment.height : fragment.width;
- data->textLength += mapLengthThroughFragmentTransformation(fragment, queryData->isVerticalText, fragmentLength);
+ data->textLength += queryData->isVerticalText ? fragment.height : fragment.width;
return false;
}
@@ -314,9 +301,7 @@ bool SVGTextQuery::subStringLengthCallback(Data* queryData, const SVGTextFragmen
return false;
SVGTextMetrics metrics = SVGTextMetrics::measureCharacterRange(queryData->textRenderer, fragment.characterOffset + startPosition, endPosition - startPosition);
- float fragmentLength = queryData->isVerticalText ? metrics.height() : metrics.width();
-
- data->subStringLength += mapLengthThroughFragmentTransformation(fragment, queryData->isVerticalText, fragmentLength);
+ data->subStringLength += queryData->isVerticalText ? metrics.height() : metrics.width();
return false;
}
@@ -360,10 +345,12 @@ bool SVGTextQuery::startPositionOfCharacterCallback(Data* queryData, const SVGTe
data->startPosition.move(metrics.width(), 0);
}
- if (fragment.transform.isIdentity())
+ AffineTransform fragmentTransform;
+ fragment.buildFragmentTransform(fragmentTransform, SVGTextFragment::TransformIgnoringTextLength);
+ if (fragmentTransform.isIdentity())
return true;
- data->startPosition = fragment.transform.mapPoint(data->startPosition);
+ data->startPosition = fragmentTransform.mapPoint(data->startPosition);
return true;
}
@@ -405,10 +392,12 @@ bool SVGTextQuery::endPositionOfCharacterCallback(Data* queryData, const SVGText
else
data->endPosition.move(metrics.width(), 0);
- if (fragment.transform.isIdentity())
+ AffineTransform fragmentTransform;
+ fragment.buildFragmentTransform(fragmentTransform, SVGTextFragment::TransformIgnoringTextLength);
+ if (fragmentTransform.isIdentity())
return true;
- data->endPosition = fragment.transform.mapPoint(data->endPosition);
+ data->endPosition = fragmentTransform.mapPoint(data->endPosition);
return true;
}
@@ -443,9 +432,15 @@ bool SVGTextQuery::rotationOfCharacterCallback(Data* queryData, const SVGTextFra
if (!mapStartEndPositionsIntoFragmentCoordinates(queryData, fragment, startPosition, endPosition))
return false;
- AffineTransform newTransform(fragment.transform);
- newTransform.scale(1 / fragment.transform.xScale(), 1 / fragment.transform.yScale());
- data->rotation = narrowPrecisionToFloat(rad2deg(atan2(newTransform.b(), newTransform.a())));
+ AffineTransform fragmentTransform;
+ fragment.buildFragmentTransform(fragmentTransform, SVGTextFragment::TransformIgnoringTextLength);
+ if (fragmentTransform.isIdentity())
+ data->rotation = 0;
+ else {
+ fragmentTransform.scale(1 / fragmentTransform.xScale(), 1 / fragmentTransform.yScale());
+ data->rotation = narrowPrecisionToFloat(rad2deg(atan2(fragmentTransform.b(), fragmentTransform.a())));
+ }
+
return true;
}
@@ -488,10 +483,12 @@ static inline void calculateGlyphBoundaries(SVGTextQuery::Data* queryData, const
SVGTextMetrics metrics = SVGTextMetrics::measureCharacterRange(queryData->textRenderer, fragment.characterOffset + startPosition, 1);
extent.setSize(FloatSize(metrics.width(), metrics.height()));
- if (fragment.transform.isIdentity())
+ AffineTransform fragmentTransform;
+ fragment.buildFragmentTransform(fragmentTransform, SVGTextFragment::TransformIgnoringTextLength);
+ if (fragmentTransform.isIdentity())
return;
- extent = fragment.transform.mapRect(extent);
+ extent = fragmentTransform.mapRect(extent);
}
bool SVGTextQuery::extentOfCharacterCallback(Data* queryData, const SVGTextFragment& fragment) const