summaryrefslogtreecommitdiffstats
path: root/src/3rdparty/webkit/WebCore/rendering
diff options
context:
space:
mode:
Diffstat (limited to 'src/3rdparty/webkit/WebCore/rendering')
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/AutoTableLayout.cpp4
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/EllipsisBox.cpp20
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/EllipsisBox.h11
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/FixedTableLayout.cpp43
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/HitTestRequest.h34
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/HitTestResult.cpp20
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/HitTestResult.h1
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/InlineBox.cpp81
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/InlineBox.h124
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/InlineFlowBox.cpp597
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/InlineFlowBox.h68
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/InlineTextBox.cpp344
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/InlineTextBox.h59
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/LayoutState.cpp25
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/LayoutState.h11
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/ListMarkerBox.cpp45
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/ListMarkerBox.h41
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/MediaControlElements.cpp177
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/MediaControlElements.h38
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/OverlapTestRequestClient.h39
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/PointerEventsHitRules.h2
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderApplet.cpp27
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderApplet.h9
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderArena.cpp4
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderBR.cpp15
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderBR.h8
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderBlock.cpp2014
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderBlock.h243
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderBox.cpp1649
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderBox.h304
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderBoxModelObject.cpp1177
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderBoxModelObject.h134
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderButton.cpp36
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderButton.h22
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderContainer.cpp701
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderContainer.h75
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderCounter.cpp15
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderCounter.h1
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderDataGrid.cpp122
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderDataGrid.h70
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderFieldset.cpp72
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderFieldset.h5
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderFileUploadControl.cpp22
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderFileUploadControl.h2
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderFlexibleBox.cpp248
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderFlexibleBox.h4
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderFlow.cpp883
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderFlow.h146
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderForeignObject.cpp95
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderForeignObject.h19
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderFrame.cpp39
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderFrame.h14
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderFrameSet.cpp45
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderFrameSet.h12
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderHTMLCanvas.cpp16
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderImage.cpp95
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderImage.h16
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderImageGeneratedContent.h14
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderInline.cpp876
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderInline.h129
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderLayer.cpp1529
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderLayer.h236
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderLayerBacking.cpp1082
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderLayerBacking.h176
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderLayerCompositor.cpp914
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderLayerCompositor.h169
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderLegend.cpp36
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderLegend.h42
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderLineBoxList.cpp333
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderLineBoxList.h86
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderListBox.cpp121
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderListBox.h9
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderListItem.cpp32
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderListItem.h2
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderListMarker.cpp67
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderListMarker.h10
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderMarquee.cpp29
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderMarquee.h3
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderMedia.cpp200
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderMedia.h27
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderMediaControls.cpp150
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderMediaControls.h43
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderMenuList.cpp140
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderMenuList.h15
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderObject.cpp2410
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderObject.h781
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderObjectChildList.cpp426
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderObjectChildList.h67
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderPart.cpp86
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderPart.h24
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderPartObject.cpp178
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderPartObject.h10
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderPath.cpp186
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderPath.h46
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderReplaced.cpp140
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderReplaced.h16
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderReplica.cpp25
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderReplica.h2
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderSVGBlock.h3
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderSVGContainer.cpp356
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderSVGContainer.h78
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderSVGGradientStop.cpp4
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderSVGGradientStop.h16
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderSVGHiddenContainer.cpp36
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderSVGHiddenContainer.h29
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderSVGImage.cpp103
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderSVGImage.h38
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderSVGInline.cpp57
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderSVGInline.h18
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderSVGInlineText.cpp92
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderSVGInlineText.h17
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderSVGModelObject.cpp97
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderSVGModelObject.h71
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderSVGRoot.cpp305
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderSVGRoot.h53
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderSVGTSpan.cpp44
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderSVGTSpan.h11
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderSVGText.cpp145
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderSVGText.h37
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderSVGTextPath.cpp51
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderSVGTextPath.h2
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderSVGTransformableContainer.cpp21
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderSVGTransformableContainer.h15
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderSVGViewportContainer.cpp126
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderSVGViewportContainer.h23
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderScrollbar.cpp20
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderScrollbar.h16
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderScrollbarPart.cpp38
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderScrollbarPart.h5
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderSelectionInfo.h104
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderSlider.cpp395
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderSlider.h39
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderTable.cpp254
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderTable.h39
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderTableCell.cpp186
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderTableCell.h43
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderTableCol.cpp34
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderTableCol.h21
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderTableRow.cpp44
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderTableRow.h17
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderTableSection.cpp263
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderTableSection.h34
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderText.cpp428
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderText.h74
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderTextControl.cpp183
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderTextControl.h42
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderTextControlMultiLine.cpp52
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderTextControlMultiLine.h1
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderTextControlSingleLine.cpp285
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderTextControlSingleLine.h23
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderTextFragment.cpp4
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderTheme.cpp179
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderTheme.h92
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderThemeChromiumLinux.cpp99
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderThemeChromiumLinux.h62
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderThemeChromiumMac.h220
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderThemeChromiumMac.mm2016
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderThemeChromiumSkia.cpp619
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderThemeChromiumSkia.h144
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderThemeChromiumWin.cpp581
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderThemeChromiumWin.h106
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderThemeMac.h25
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderThemeSafari.cpp156
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderThemeSafari.h9
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderThemeWin.cpp310
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderThemeWin.h28
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderTreeAsText.cpp124
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderVideo.cpp59
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderVideo.h15
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderView.cpp281
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderView.h151
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderWidget.cpp146
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderWidget.h48
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RootInlineBox.cpp120
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RootInlineBox.h44
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/SVGCharacterLayoutInfo.cpp4
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/SVGInlineFlowBox.cpp3
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/SVGInlineFlowBox.h9
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/SVGInlineTextBox.cpp93
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/SVGInlineTextBox.h12
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/SVGRenderSupport.cpp112
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/SVGRenderSupport.h53
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/SVGRenderTreeAsText.cpp202
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/SVGRenderTreeAsText.h6
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/SVGRootInlineBox.cpp128
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/SVGRootInlineBox.h7
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/ScrollBehavior.cpp55
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/ScrollBehavior.h78
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/TextControlInnerElements.cpp37
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/TransformState.cpp169
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/TransformState.h133
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/bidi.cpp707
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/bidi.h2
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/break_lines.cpp6
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/style/ContentData.cpp58
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/style/ContentData.h50
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/style/CounterContent.h8
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/style/RenderStyle.cpp328
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/style/RenderStyle.h183
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/style/RenderStyleConstants.h53
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/style/SVGRenderStyle.cpp2
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/style/StyleGeneratedImage.cpp23
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/style/StyleInheritedData.cpp2
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/style/StyleRareInheritedData.cpp3
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/style/StyleRareNonInheritedData.cpp50
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/style/StyleRareNonInheritedData.h13
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/style/StyleTransformData.cpp4
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/style/StyleTransformData.h1
208 files changed, 21901 insertions, 11829 deletions
diff --git a/src/3rdparty/webkit/WebCore/rendering/AutoTableLayout.cpp b/src/3rdparty/webkit/WebCore/rendering/AutoTableLayout.cpp
index 8f9feec..648e843 100644
--- a/src/3rdparty/webkit/WebCore/rendering/AutoTableLayout.cpp
+++ b/src/3rdparty/webkit/WebCore/rendering/AutoTableLayout.cpp
@@ -59,7 +59,9 @@ void AutoTableLayout::recalcColumn(int effCol)
RenderTableCell* maxContributor = 0;
while (child) {
- if (child->isTableSection()) {
+ if (child->isTableCol())
+ static_cast<RenderTableCol*>(child)->calcPrefWidths();
+ else if (child->isTableSection()) {
RenderTableSection* section = static_cast<RenderTableSection*>(child);
int numRows = section->numRows();
RenderTableCell* last = 0;
diff --git a/src/3rdparty/webkit/WebCore/rendering/EllipsisBox.cpp b/src/3rdparty/webkit/WebCore/rendering/EllipsisBox.cpp
index 0bd1d1a..db9a101 100644
--- a/src/3rdparty/webkit/WebCore/rendering/EllipsisBox.cpp
+++ b/src/3rdparty/webkit/WebCore/rendering/EllipsisBox.cpp
@@ -31,10 +31,7 @@ namespace WebCore {
void EllipsisBox::paint(RenderObject::PaintInfo& paintInfo, int tx, int ty)
{
GraphicsContext* context = paintInfo.context;
- RenderStyle* style = m_object->style(m_firstLine);
- if (style->font() != context->font())
- context->setFont(style->font());
-
+ RenderStyle* style = m_renderer->style(m_firstLine);
Color textColor = style->color();
if (textColor != context->fillColor())
context->setFillColor(textColor);
@@ -46,15 +43,15 @@ void EllipsisBox::paint(RenderObject::PaintInfo& paintInfo, int tx, int ty)
}
const String& str = m_str;
- context->drawText(TextRun(str.characters(), str.length(), false, 0, 0, false, style->visuallyOrdered()), IntPoint(m_x + tx, m_y + ty + m_baseline));
+ context->drawText(style->font(), TextRun(str.characters(), str.length(), false, 0, 0, false, style->visuallyOrdered()), IntPoint(m_x + tx, m_y + ty + style->font().ascent()));
if (setShadow)
context->clearShadow();
if (m_markupBox) {
// Paint the markup box
- tx += m_x + m_width - m_markupBox->xPos();
- ty += m_y + m_baseline - (m_markupBox->yPos() + m_markupBox->baseline());
+ tx += m_x + m_width - m_markupBox->x();
+ ty += m_y + style->font().ascent() - (m_markupBox->y() + m_markupBox->renderer()->style(m_firstLine)->font().ascent());
m_markupBox->paint(paintInfo, tx, ty);
}
}
@@ -66,16 +63,17 @@ bool EllipsisBox::nodeAtPoint(const HitTestRequest& request, HitTestResult& resu
// Hit test the markup box.
if (m_markupBox) {
- int mtx = tx + m_width - m_markupBox->xPos();
- int mty = ty + m_baseline - (m_markupBox->yPos() + m_markupBox->baseline());
+ RenderStyle* style = m_renderer->style(m_firstLine);
+ int mtx = tx + m_width - m_markupBox->x();
+ int mty = ty + style->font().ascent() - (m_markupBox->y() + m_markupBox->renderer()->style(m_firstLine)->font().ascent());
if (m_markupBox->nodeAtPoint(request, result, x, y, mtx, mty)) {
- object()->updateHitTestResult(result, IntPoint(x - mtx, y - mty));
+ renderer()->updateHitTestResult(result, IntPoint(x - mtx, y - mty));
return true;
}
}
if (visibleToHitTesting() && IntRect(tx, ty, m_width, m_height).contains(x, y)) {
- object()->updateHitTestResult(result, IntPoint(x - tx, y - ty));
+ renderer()->updateHitTestResult(result, IntPoint(x - tx, y - ty));
return true;
}
diff --git a/src/3rdparty/webkit/WebCore/rendering/EllipsisBox.h b/src/3rdparty/webkit/WebCore/rendering/EllipsisBox.h
index dbb30cd..9dbd27f 100644
--- a/src/3rdparty/webkit/WebCore/rendering/EllipsisBox.h
+++ b/src/3rdparty/webkit/WebCore/rendering/EllipsisBox.h
@@ -26,15 +26,15 @@
namespace WebCore {
+class HitTestRequest;
class HitTestResult;
-struct HitTestRequest;
-
class EllipsisBox : public InlineBox {
public:
EllipsisBox(RenderObject* obj, const AtomicString& ellipsisStr, InlineFlowBox* parent,
- int width, int y, int height, int baseline, bool firstLine, InlineBox* markupBox)
- : InlineBox(obj, 0, y, width, height, baseline, firstLine, true, false, false, 0, 0, parent)
+ int width, int height, int y, bool firstLine, InlineBox* markupBox)
+ : InlineBox(obj, 0, y, width, firstLine, true, false, false, 0, 0, parent)
+ , m_height(height)
, m_str(ellipsisStr)
, m_markupBox(markupBox)
{
@@ -44,6 +44,9 @@ public:
virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, int x, int y, int tx, int ty);
private:
+ virtual int height() const { return m_height; }
+
+ int m_height;
AtomicString m_str;
InlineBox* m_markupBox;
};
diff --git a/src/3rdparty/webkit/WebCore/rendering/FixedTableLayout.cpp b/src/3rdparty/webkit/WebCore/rendering/FixedTableLayout.cpp
index d7c1293..63a4f54 100644
--- a/src/3rdparty/webkit/WebCore/rendering/FixedTableLayout.cpp
+++ b/src/3rdparty/webkit/WebCore/rendering/FixedTableLayout.cpp
@@ -85,16 +85,15 @@ int FixedTableLayout::calcWidthArray(int)
// iterate over all <col> elements
RenderObject* child = m_table->firstChild();
- int cCol = 0;
int nEffCols = m_table->numEffCols();
m_width.resize(nEffCols);
m_width.fill(Length(Auto));
+ int currentEffectiveColumn = 0;
Length grpWidth;
while (child) {
if (child->isTableCol()) {
- RenderTableCol *col = static_cast<RenderTableCol *>(child);
- int span = col->span();
+ RenderTableCol* col = static_cast<RenderTableCol*>(child);
if (col->firstChild())
grpWidth = col->style()->width();
else {
@@ -104,30 +103,36 @@ int FixedTableLayout::calcWidthArray(int)
int effWidth = 0;
if (w.isFixed() && w.value() > 0)
effWidth = w.value();
-
- int usedSpan = 0;
- int i = 0;
- while (usedSpan < span) {
- if(cCol + i >= nEffCols) {
- m_table->appendColumn(span - usedSpan);
+
+ int span = col->span();
+ while (span) {
+ int spanInCurrentEffectiveColumn;
+ if (currentEffectiveColumn >= nEffCols) {
+ m_table->appendColumn(span);
nEffCols++;
- m_width.resize(nEffCols);
- m_width[nEffCols-1] = Length();
+ m_width.append(Length());
+ spanInCurrentEffectiveColumn = span;
+ } else {
+ if (span < m_table->spanOfEffCol(currentEffectiveColumn)) {
+ m_table->splitColumn(currentEffectiveColumn, span);
+ nEffCols++;
+ m_width.append(Length());
+ }
+ spanInCurrentEffectiveColumn = m_table->spanOfEffCol(currentEffectiveColumn);
}
- int eSpan = m_table->spanOfEffCol(cCol+i);
if ((w.isFixed() || w.isPercent()) && w.isPositive()) {
- m_width[cCol + i].setRawValue(w.type(), w.rawValue() * eSpan);
- usedWidth += effWidth * eSpan;
+ m_width[currentEffectiveColumn].setRawValue(w.type(), w.rawValue() * spanInCurrentEffectiveColumn);
+ usedWidth += effWidth * spanInCurrentEffectiveColumn;
}
- usedSpan += eSpan;
- i++;
+ span -= spanInCurrentEffectiveColumn;
+ currentEffectiveColumn++;
}
- cCol += i;
}
+ static_cast<RenderTableCol*>(child)->calcPrefWidths();
} else
break;
- RenderObject *next = child->firstChild();
+ RenderObject* next = child->firstChild();
if (!next)
next = child->nextSibling();
if (!next && child->parent()->isTableCol()) {
@@ -146,7 +151,7 @@ int FixedTableLayout::calcWidthArray(int)
if (section && !section->numRows())
section = m_table->sectionBelow(section, true);
if (section) {
- cCol = 0;
+ int cCol = 0;
RenderObject* firstRow = section->firstChild();
child = firstRow->firstChild();
while (child) {
diff --git a/src/3rdparty/webkit/WebCore/rendering/HitTestRequest.h b/src/3rdparty/webkit/WebCore/rendering/HitTestRequest.h
index 11dca4b..46dd7b8 100644
--- a/src/3rdparty/webkit/WebCore/rendering/HitTestRequest.h
+++ b/src/3rdparty/webkit/WebCore/rendering/HitTestRequest.h
@@ -2,6 +2,7 @@
* This file is part of the HTML rendering engine for KDE.
*
* Copyright (C) 2006 Apple Computer, Inc.
+ * Copyright (C) 2009 Torch Mobile Inc. http://www.torchmobile.com/
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -19,24 +20,35 @@
* Boston, MA 02110-1301, USA.
*
*/
+
#ifndef HitTestRequest_h
#define HitTestRequest_h
namespace WebCore {
-struct HitTestRequest {
- HitTestRequest(bool r, bool a, bool m = false, bool u = false)
- : readonly(r)
- , active(a)
- , mouseMove(m)
- , mouseUp(u)
- {
+class HitTestRequest {
+public:
+ enum RequestType {
+ ReadOnly = 0x1,
+ Active = 0x2,
+ MouseMove = 0x4,
+ MouseUp = 0x8,
+ IgnoreClipping = 0x10
+ };
+
+ HitTestRequest(int requestType)
+ : m_requestType(requestType)
+ {
}
- bool readonly;
- bool active;
- bool mouseMove;
- bool mouseUp;
+ bool readOnly() const { return m_requestType & ReadOnly; }
+ bool active() const { return m_requestType & Active; }
+ bool mouseMove() const { return m_requestType & MouseMove; }
+ bool mouseUp() const { return m_requestType & MouseUp; }
+ bool ignoreClipping() const { return m_requestType & IgnoreClipping; }
+
+private:
+ int m_requestType;
};
} // namespace WebCore
diff --git a/src/3rdparty/webkit/WebCore/rendering/HitTestResult.cpp b/src/3rdparty/webkit/WebCore/rendering/HitTestResult.cpp
index 5a041ed..f2ed7db 100644
--- a/src/3rdparty/webkit/WebCore/rendering/HitTestResult.cpp
+++ b/src/3rdparty/webkit/WebCore/rendering/HitTestResult.cpp
@@ -159,6 +159,20 @@ String HitTestResult::spellingToolTip() const
return marker->description;
}
+String HitTestResult::replacedString() const
+{
+ // Return the replaced string associated with this point, if any. This marker is created when a string is autocorrected,
+ // and is used for generating a contextual menu item that allows it to easily be changed back if desired.
+ if (!m_innerNonSharedNode)
+ return String();
+
+ DocumentMarker* marker = m_innerNonSharedNode->document()->markerContainingPoint(m_point, DocumentMarker::Replacement);
+ if (!marker)
+ return String();
+
+ return marker->description;
+}
+
String HitTestResult::title() const
{
// Find the title in the nearest enclosing DOM node.
@@ -177,9 +191,7 @@ String displayString(const String& string, const Node* node)
{
if (!node)
return string;
- String copy(string);
- copy.replace('\\', node->document()->backslashAsCurrencySymbol());
- return copy;
+ return node->document()->displayStringModifiedByEncoding(string);
}
String HitTestResult::altDisplayString() const
@@ -226,7 +238,7 @@ IntRect HitTestResult::imageRect() const
{
if (!image())
return IntRect();
- return m_innerNonSharedNode->renderer()->absoluteContentBox();
+ return m_innerNonSharedNode->renderBox()->absoluteContentBox();
}
KURL HitTestResult::absoluteImageURL() const
diff --git a/src/3rdparty/webkit/WebCore/rendering/HitTestResult.h b/src/3rdparty/webkit/WebCore/rendering/HitTestResult.h
index 5ed9b34..4f0383f 100644
--- a/src/3rdparty/webkit/WebCore/rendering/HitTestResult.h
+++ b/src/3rdparty/webkit/WebCore/rendering/HitTestResult.h
@@ -65,6 +65,7 @@ public:
IntRect boundingBox() const;
bool isSelected() const;
String spellingToolTip() const;
+ String replacedString() const;
String title() const;
String altDisplayString() const;
String titleDisplayString() const;
diff --git a/src/3rdparty/webkit/WebCore/rendering/InlineBox.cpp b/src/3rdparty/webkit/WebCore/rendering/InlineBox.cpp
index f5d0de5..2d956a8 100644
--- a/src/3rdparty/webkit/WebCore/rendering/InlineBox.cpp
+++ b/src/3rdparty/webkit/WebCore/rendering/InlineBox.cpp
@@ -23,6 +23,7 @@
#include "HitTestResult.h"
#include "InlineFlowBox.h"
#include "RenderArena.h"
+#include "RenderBox.h"
#include "RootInlineBox.h"
using namespace std;
@@ -79,19 +80,47 @@ void InlineBox::operator delete(void* ptr, size_t sz)
#ifndef NDEBUG
void InlineBox::showTreeForThis() const
{
- if (m_object)
- m_object->showTreeForThis();
+ if (m_renderer)
+ m_renderer->showTreeForThis();
}
#endif
+int InlineBox::height() const
+{
+#if ENABLE(SVG)
+ if (isSVG())
+ return svgBoxHeight();
+#endif
+
+ if (renderer()->isText())
+ return m_isText ? renderer()->style(m_firstLine)->font().height() : 0;
+ if (renderer()->isBox() && parent())
+ return toRenderBox(m_renderer)->height();
+
+ ASSERT(isInlineFlowBox());
+ const InlineFlowBox* flowBox = static_cast<const InlineFlowBox*>(this);
+ RenderBoxModelObject* flowObject = boxModelObject();
+ const Font& font = renderer()->style(m_firstLine)->font();
+ int result = font.height();
+ bool strictMode = renderer()->document()->inStrictMode();
+ if (parent())
+ result += flowObject->borderTop() + flowObject->paddingTop() + flowObject->borderBottom() + flowObject->paddingBottom();
+ if (strictMode || flowBox->hasTextChildren() || flowObject->hasHorizontalBordersOrPadding())
+ return result;
+ int bottom = root()->bottomOverflow();
+ if (y() + result > bottom)
+ result = bottom - y();
+ return result;
+}
+
int InlineBox::caretMinOffset() const
{
- return m_object->caretMinOffset();
+ return m_renderer->caretMinOffset();
}
int InlineBox::caretMaxOffset() const
{
- return m_object->caretMaxOffset();
+ return m_renderer->caretMaxOffset();
}
unsigned InlineBox::caretMaxRenderedOffset() const
@@ -108,34 +137,38 @@ void InlineBox::dirtyLineBoxes()
void InlineBox::deleteLine(RenderArena* arena)
{
- if (!m_extracted)
- m_object->setInlineBoxWrapper(0);
+ if (!m_extracted && m_renderer->isBox())
+ toRenderBox(m_renderer)->setInlineBoxWrapper(0);
destroy(arena);
}
void InlineBox::extractLine()
{
m_extracted = true;
- m_object->setInlineBoxWrapper(0);
+ if (m_renderer->isBox())
+ toRenderBox(m_renderer)->setInlineBoxWrapper(0);
}
void InlineBox::attachLine()
{
m_extracted = false;
- m_object->setInlineBoxWrapper(this);
+ if (m_renderer->isBox())
+ toRenderBox(m_renderer)->setInlineBoxWrapper(this);
}
void InlineBox::adjustPosition(int dx, int dy)
{
m_x += dx;
m_y += dy;
- if (m_object->isReplaced() || m_object->isBR())
- m_object->setPos(m_object->xPos() + dx, m_object->yPos() + dy);
+ if (m_renderer->isReplaced()) {
+ RenderBox* box = toRenderBox(m_renderer);
+ box->move(dx, dy);
+ }
}
void InlineBox::paint(RenderObject::PaintInfo& paintInfo, int tx, int ty)
{
- if (!object()->shouldPaintWithinRoot(paintInfo) || (paintInfo.phase != PaintPhaseForeground && paintInfo.phase != PaintPhaseSelection))
+ if (!renderer()->shouldPaintWithinRoot(paintInfo) || (paintInfo.phase != PaintPhaseForeground && paintInfo.phase != PaintPhaseSelection))
return;
// Paint all phases of replaced elements atomically, as though the replaced element established its
@@ -144,16 +177,16 @@ void InlineBox::paint(RenderObject::PaintInfo& paintInfo, int tx, int ty)
bool preservePhase = paintInfo.phase == PaintPhaseSelection || paintInfo.phase == PaintPhaseTextClip;
RenderObject::PaintInfo info(paintInfo);
info.phase = preservePhase ? paintInfo.phase : PaintPhaseBlockBackground;
- object()->paint(info, tx, ty);
+ renderer()->paint(info, tx, ty);
if (!preservePhase) {
info.phase = PaintPhaseChildBlockBackgrounds;
- object()->paint(info, tx, ty);
+ renderer()->paint(info, tx, ty);
info.phase = PaintPhaseFloat;
- object()->paint(info, tx, ty);
+ renderer()->paint(info, tx, ty);
info.phase = PaintPhaseForeground;
- object()->paint(info, tx, ty);
+ renderer()->paint(info, tx, ty);
info.phase = PaintPhaseOutline;
- object()->paint(info, tx, ty);
+ renderer()->paint(info, tx, ty);
}
}
@@ -162,7 +195,15 @@ bool InlineBox::nodeAtPoint(const HitTestRequest& request, HitTestResult& result
// 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
// specification.)
- return object()->hitTest(request, result, IntPoint(x, y), tx, ty);
+ return renderer()->hitTest(request, result, IntPoint(x, y), tx, ty);
+}
+
+const RootInlineBox* InlineBox::root() const
+{
+ if (m_parent)
+ return m_parent->root();
+ ASSERT(isRootInlineBox());
+ return static_cast<const RootInlineBox*>(this);
}
RootInlineBox* InlineBox::root()
@@ -225,13 +266,13 @@ InlineBox* InlineBox::prevLeafChild()
RenderObject::SelectionState InlineBox::selectionState()
{
- return object()->selectionState();
+ return renderer()->selectionState();
}
bool InlineBox::canAccommodateEllipsis(bool ltr, int blockEdge, int ellipsisWidth)
{
// Non-replaced elements can always accommodate an ellipsis.
- if (!m_object || !m_object->isReplaced())
+ if (!m_renderer || !m_renderer->isReplaced())
return true;
IntRect boxRect(m_x, 0, m_width, 10);
@@ -239,7 +280,7 @@ bool InlineBox::canAccommodateEllipsis(bool ltr, int blockEdge, int ellipsisWidt
return !(boxRect.intersects(ellipsisRect));
}
-int InlineBox::placeEllipsisBox(bool, int, int, bool&)
+int InlineBox::placeEllipsisBox(bool, int, int, int, bool&)
{
// Use -1 to mean "we didn't set the position."
return -1;
diff --git a/src/3rdparty/webkit/WebCore/rendering/InlineBox.h b/src/3rdparty/webkit/WebCore/rendering/InlineBox.h
index 41ad72a..9585278 100644
--- a/src/3rdparty/webkit/WebCore/rendering/InlineBox.h
+++ b/src/3rdparty/webkit/WebCore/rendering/InlineBox.h
@@ -21,43 +21,41 @@
#ifndef InlineBox_h
#define InlineBox_h
-#include "RenderObject.h" // needed for RenderObject::PaintInfo
+#include "RenderBoxModelObject.h"
#include "TextDirection.h"
namespace WebCore {
+class HitTestRequest;
class HitTestResult;
class RootInlineBox;
-struct HitTestRequest;
// InlineBox represents a rectangle that occurs on a line. It corresponds to
// some RenderObject (i.e., it represents a portion of that RenderObject).
class InlineBox {
public:
InlineBox(RenderObject* obj)
- : m_object(obj)
+ : m_next(0)
+ , m_prev(0)
+ , m_parent(0)
+ , m_renderer(obj)
, m_x(0)
, m_y(0)
, m_width(0)
- , m_height(0)
- , m_baseline(0)
- , m_next(0)
- , m_prev(0)
- , m_parent(0)
, m_firstLine(false)
, m_constructed(false)
, m_bidiEmbeddingLevel(0)
, m_dirty(false)
, m_extracted(false)
- , m_includeLeftEdge(false)
- , m_includeRightEdge(false)
- , m_hasTextChildren(true)
+#if ENABLE(SVG)
+ , m_isSVG(false)
+#endif
, m_endsWithBreak(false)
, m_hasSelectedChildren(false)
, m_hasEllipsisBox(false)
, m_dirOverride(false)
- , m_treatAsText(true)
+ , m_isText(false)
, m_determinedIfNextOnLineExists(false)
, m_determinedIfPrevOnLineExists(false)
, m_nextOnLineExists(false)
@@ -69,30 +67,28 @@ public:
{
}
- InlineBox(RenderObject* obj, int x, int y, int width, int height, int baseline, bool firstLine, bool constructed,
+ InlineBox(RenderObject* obj, int x, int y, int width, bool firstLine, bool constructed,
bool dirty, bool extracted, InlineBox* next, InlineBox* prev, InlineFlowBox* parent)
- : m_object(obj)
+ : m_next(next)
+ , m_prev(prev)
+ , m_parent(parent)
+ , m_renderer(obj)
, m_x(x)
, m_y(y)
, m_width(width)
- , m_height(height)
- , m_baseline(baseline)
- , m_next(next)
- , m_prev(prev)
- , m_parent(parent)
, m_firstLine(firstLine)
, m_constructed(constructed)
, m_bidiEmbeddingLevel(0)
, m_dirty(dirty)
, m_extracted(extracted)
- , m_includeLeftEdge(false)
- , m_includeRightEdge(false)
- , m_hasTextChildren(true)
+#if ENABLE(SVG)
+ , m_isSVG(false)
+#endif
, m_endsWithBreak(false)
, m_hasSelectedChildren(false)
, m_hasEllipsisBox(false)
, m_dirOverride(false)
- , m_treatAsText(true)
+ , m_isText(false)
, m_determinedIfNextOnLineExists(false)
, m_determinedIfPrevOnLineExists(false)
, m_nextOnLineExists(false)
@@ -134,14 +130,16 @@ public:
void showTreeForThis() const;
#endif
virtual bool isInlineBox() { return false; }
- virtual bool isInlineFlowBox() { return false; }
- virtual bool isContainer() { return false; }
+ virtual bool isInlineFlowBox() const { return false; }
virtual bool isInlineTextBox() { return false; }
- virtual bool isRootInlineBox() { return false; }
+ virtual bool isRootInlineBox() const { return false; }
#if ENABLE(SVG)
virtual bool isSVGRootInlineBox() { return false; }
+ bool isSVG() const { return m_isSVG; }
+ void setIsSVG(bool b) { m_isSVG = b; }
#endif
- virtual bool isText() const { return false; }
+ bool isText() const { return m_isText; }
+ void setIsText(bool b) { m_isText = b; }
bool isConstructed() { return m_constructed; }
virtual void setConstructed()
@@ -178,7 +176,7 @@ public:
InlineBox* nextLeafChild();
InlineBox* prevLeafChild();
- RenderObject* object() const { return m_object; }
+ RenderObject* renderer() const { return m_renderer; }
InlineFlowBox* parent() const
{
@@ -187,29 +185,26 @@ public:
}
void setParent(InlineFlowBox* par) { m_parent = par; }
+ const RootInlineBox* root() const;
RootInlineBox* root();
-
+
void setWidth(int w) { m_width = w; }
int width() const { return m_width; }
- void setXPos(int x) { m_x = x; }
- int xPos() const { return m_x; }
-
- void setYPos(int y) { m_y = y; }
- int yPos() const { return m_y; }
+ // x() is the left side of the box in the parent's coordinate system.
+ void setX(int x) { m_x = x; }
+ int x() const { return m_x; }
- void setHeight(int h) { m_height = h; }
- int height() const { return m_height; }
-
- void setBaseline(int b) { m_baseline = b; }
- int baseline() const { return m_baseline; }
+ // y() is the top of the box in the parent's coordinate system.
+ void setY(int y) { m_y = y; }
+ int y() const { return m_y; }
- bool hasTextChildren() const { return m_hasTextChildren; }
+ int height() const;
- virtual int topOverflow() { return yPos(); }
- virtual int bottomOverflow() { return yPos() + height(); }
- virtual int leftOverflow() { return xPos(); }
- virtual int rightOverflow() { return xPos() + width(); }
+ virtual int topOverflow() const { return y(); }
+ virtual int bottomOverflow() const { return y() + height(); }
+ virtual int leftOverflow() const { return x(); }
+ virtual int rightOverflow() const { return x() + width(); }
virtual int caretMinOffset() const;
virtual int caretMaxOffset() const;
@@ -231,28 +226,40 @@ public:
virtual RenderObject::SelectionState selectionState();
virtual bool canAccommodateEllipsis(bool ltr, int blockEdge, int ellipsisWidth);
- virtual int placeEllipsisBox(bool ltr, int blockEdge, int ellipsisWidth, bool&);
+ // visibleLeftEdge, visibleRightEdge are in the parent's coordinate system.
+ virtual int placeEllipsisBox(bool ltr, int visibleLeftEdge, int visibleRightEdge, int ellipsisWidth, bool&);
void setHasBadParent();
int toAdd() const { return m_toAdd; }
- bool visibleToHitTesting() const { return object()->style()->visibility() == VISIBLE && object()->style()->pointerEvents() != PE_NONE; }
+ bool visibleToHitTesting() const { return renderer()->style()->visibility() == VISIBLE && renderer()->style()->pointerEvents() != PE_NONE; }
-public:
- RenderObject* m_object;
+ // Use with caution! The type is not checked!
+ RenderBoxModelObject* boxModelObject() const
+ {
+ if (!m_renderer->isText())
+ return static_cast<RenderBoxModelObject*>(m_renderer);
+ return 0;
+ }
- int m_x;
- int m_y;
- int m_width;
- int m_height;
- int m_baseline;
+protected:
+#if ENABLE(SVG)
+ virtual int svgBoxHeight() const { return 0; }
+#endif
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.
InlineFlowBox* m_parent; // The box that contains us.
+
+public:
+ RenderObject* m_renderer;
+
+ int m_x;
+ int m_y;
+ int m_width;
// Some of these bits are actually for subclasses and moved here to compact the structures.
@@ -266,10 +273,9 @@ protected:
bool m_dirty : 1;
bool m_extracted : 1;
- // for InlineFlowBox
- bool m_includeLeftEdge : 1;
- bool m_includeRightEdge : 1;
- bool m_hasTextChildren : 1;
+#if ENABLE(SVG)
+ bool m_isSVG : 1;
+#endif
// for RootInlineBox
bool m_endsWithBreak : 1; // Whether the line ends with a <br>.
@@ -279,13 +285,13 @@ protected:
// for InlineTextBox
public:
bool m_dirOverride : 1;
- bool m_treatAsText : 1; // Whether or not to treat a <br> as text for the purposes of line height.
+ bool m_isText : 1; // Whether or not this object represents text with a non-zero height. Includes non-image list markers, text boxes.
protected:
mutable bool m_determinedIfNextOnLineExists : 1;
mutable bool m_determinedIfPrevOnLineExists : 1;
mutable bool m_nextOnLineExists : 1;
mutable bool m_prevOnLineExists : 1;
- int m_toAdd : 13; // for justified text
+ int m_toAdd : 12; // for justified text
#ifndef NDEBUG
private:
diff --git a/src/3rdparty/webkit/WebCore/rendering/InlineFlowBox.cpp b/src/3rdparty/webkit/WebCore/rendering/InlineFlowBox.cpp
index b4d240e..be6b966 100644
--- a/src/3rdparty/webkit/WebCore/rendering/InlineFlowBox.cpp
+++ b/src/3rdparty/webkit/WebCore/rendering/InlineFlowBox.cpp
@@ -28,7 +28,7 @@
#include "HitTestResult.h"
#include "RootInlineBox.h"
#include "RenderBlock.h"
-#include "RenderFlow.h"
+#include "RenderInline.h"
#include "RenderListMarker.h"
#include "RenderTableCell.h"
#include "RootInlineBox.h"
@@ -51,47 +51,6 @@ InlineFlowBox::~InlineFlowBox()
#endif
-RenderFlow* InlineFlowBox::flowObject()
-{
- return static_cast<RenderFlow*>(m_object);
-}
-
-int InlineFlowBox::marginLeft()
-{
- if (!includeLeftEdge())
- return 0;
-
- Length margin = object()->style()->marginLeft();
- if (margin.isAuto())
- return 0;
- if (margin.isFixed())
- return margin.value();
- return object()->marginLeft();
-}
-
-int InlineFlowBox::marginRight()
-{
- if (!includeRightEdge())
- return 0;
-
- Length margin = object()->style()->marginRight();
- if (margin.isAuto())
- return 0;
- if (margin.isFixed())
- return margin.value();
- return object()->marginRight();
-}
-
-int InlineFlowBox::marginBorderPaddingLeft()
-{
- return marginLeft() + borderLeft() + paddingLeft();
-}
-
-int InlineFlowBox::marginBorderPaddingRight()
-{
- return marginRight() + borderRight() + paddingRight();
-}
-
int InlineFlowBox::getFlowSpacingWidth()
{
int totWidth = marginBorderPaddingLeft() + marginBorderPaddingRight();
@@ -121,7 +80,7 @@ void InlineFlowBox::addToLine(InlineBox* child)
child->setFirstLineStyleBit(m_firstLine);
if (child->isText())
m_hasTextChildren = true;
- if (child->object()->selectionState() != RenderObject::SelectionNone)
+ if (child->renderer()->selectionState() != RenderObject::SelectionNone)
root()->setHasSelectedChildren(true);
checkConsistency();
@@ -168,26 +127,41 @@ void InlineFlowBox::deleteLine(RenderArena* arena)
m_lastChild = 0;
#endif
- static_cast<RenderFlow*>(m_object)->removeLineBox(this);
+ removeLineBoxFromRenderObject();
destroy(arena);
}
+void InlineFlowBox::removeLineBoxFromRenderObject()
+{
+ toRenderInline(renderer())->lineBoxes()->removeLineBox(this);
+}
+
void InlineFlowBox::extractLine()
{
if (!m_extracted)
- static_cast<RenderFlow*>(m_object)->extractLineBox(this);
+ extractLineBoxFromRenderObject();
for (InlineBox* child = firstChild(); child; child = child->nextOnLine())
child->extractLine();
}
+void InlineFlowBox::extractLineBoxFromRenderObject()
+{
+ toRenderInline(renderer())->lineBoxes()->extractLineBox(this);
+}
+
void InlineFlowBox::attachLine()
{
if (m_extracted)
- static_cast<RenderFlow*>(m_object)->attachLineBox(this);
+ attachLineBoxToRenderObject();
for (InlineBox* child = firstChild(); child; child = child->nextOnLine())
child->attachLine();
}
+void InlineFlowBox::attachLineBoxToRenderObject()
+{
+ toRenderInline(renderer())->lineBoxes()->attachLineBox(this);
+}
+
void InlineFlowBox::adjustPosition(int dx, int dy)
{
InlineRunBox::adjustPosition(dx, dy);
@@ -195,18 +169,23 @@ void InlineFlowBox::adjustPosition(int dx, int dy)
child->adjustPosition(dx, dy);
}
+RenderLineBoxList* InlineFlowBox::rendererLineBoxes() const
+{
+ return toRenderInline(renderer())->lineBoxes();
+}
+
bool InlineFlowBox::onEndChain(RenderObject* endObject)
{
if (!endObject)
return false;
- if (endObject == object())
+ if (endObject == renderer())
return true;
RenderObject* curr = endObject;
RenderObject* parent = curr->parent();
while (parent && !parent->isRenderBlock()) {
- if (parent->lastChild() != curr || parent == object())
+ if (parent->lastChild() != curr || parent == renderer())
return false;
curr = parent;
@@ -223,19 +202,17 @@ void InlineFlowBox::determineSpacingForFlowBoxes(bool lastLine, RenderObject* en
bool includeLeftEdge = false;
bool includeRightEdge = false;
- RenderFlow* flow = static_cast<RenderFlow*>(object());
-
- if (!flow->firstChild())
- includeLeftEdge = includeRightEdge = true; // Empty inlines never split across lines.
- else if (parent()) { // The root inline box never has borders/margins/padding.
- bool ltr = flow->style()->direction() == LTR;
-
+ // The root inline box never has borders/margins/padding.
+ if (parent()) {
+ bool ltr = renderer()->style()->direction() == LTR;
+
// Check to see if all initial lines are unconstructed. If so, then
- // we know the inline began on this line.
- if (!flow->firstLineBox()->isConstructed()) {
- if (ltr && flow->firstLineBox() == this)
+ // we know the inline began on this line (unless we are a continuation).
+ RenderLineBoxList* lineBoxList = rendererLineBoxes();
+ if (!lineBoxList->firstLineBox()->isConstructed() && !renderer()->isInlineContinuation()) {
+ if (ltr && lineBoxList->firstLineBox() == this)
includeLeftEdge = true;
- else if (!ltr && flow->lastLineBox() == this)
+ else if (!ltr && lineBoxList->lastLineBox() == this)
includeRightEdge = true;
}
@@ -246,14 +223,15 @@ void InlineFlowBox::determineSpacingForFlowBoxes(bool lastLine, RenderObject* en
// reverse for rtl), then the inline has closed.
// (3) The line may end on the inline. If we are the last child (climbing up
// the end object's chain), then we just closed as well.
- if (!flow->lastLineBox()->isConstructed()) {
+ if (!lineBoxList->lastLineBox()->isConstructed()) {
+ RenderInline* inlineFlow = toRenderInline(renderer());
if (ltr) {
if (!nextLineBox() &&
- ((lastLine && !object()->continuation()) || nextOnLineExists() || onEndChain(endObject)))
+ ((lastLine && !inlineFlow->continuation()) || nextOnLineExists() || onEndChain(endObject)))
includeRightEdge = true;
} else {
if ((!prevLineBox() || prevLineBox()->isConstructed()) &&
- ((lastLine && !object()->continuation()) || prevOnLineExists() || onEndChain(endObject)))
+ ((lastLine && !inlineFlow->continuation()) || prevOnLineExists() || onEndChain(endObject)))
includeLeftEdge = true;
}
}
@@ -270,32 +248,32 @@ void InlineFlowBox::determineSpacingForFlowBoxes(bool lastLine, RenderObject* en
}
}
-int InlineFlowBox::placeBoxesHorizontally(int x, int& leftPosition, int& rightPosition, bool& needsWordSpacing)
+int InlineFlowBox::placeBoxesHorizontally(int xPos, int& leftPosition, int& rightPosition, bool& needsWordSpacing)
{
// Set our x position.
- setXPos(x);
+ setX(xPos);
int boxShadowLeft = 0;
int boxShadowRight = 0;
- for (ShadowData* boxShadow = object()->style(m_firstLine)->boxShadow(); boxShadow; boxShadow = boxShadow->next) {
+ for (ShadowData* boxShadow = renderer()->style(m_firstLine)->boxShadow(); boxShadow; boxShadow = boxShadow->next) {
boxShadowLeft = min(boxShadow->x - boxShadow->blur, boxShadowLeft);
boxShadowRight = max(boxShadow->x + boxShadow->blur, boxShadowRight);
}
- leftPosition = min(x + boxShadowLeft, leftPosition);
+ leftPosition = min(xPos + boxShadowLeft, leftPosition);
- int startX = x;
- x += borderLeft() + paddingLeft();
+ int startX = xPos;
+ xPos += borderLeft() + paddingLeft();
for (InlineBox* curr = firstChild(); curr; curr = curr->nextOnLine()) {
- if (curr->object()->isText()) {
+ if (curr->renderer()->isText()) {
InlineTextBox* text = static_cast<InlineTextBox*>(curr);
- RenderText* rt = static_cast<RenderText*>(text->object());
+ RenderText* rt = toRenderText(text->renderer());
if (rt->textLength()) {
if (needsWordSpacing && isSpaceOrNewline(rt->characters()[text->start()]))
- x += rt->style(m_firstLine)->font().wordSpacing();
+ xPos += rt->style(m_firstLine)->font().wordSpacing();
needsWordSpacing = !isSpaceOrNewline(rt->characters()[text->end()]);
}
- text->setXPos(x);
+ text->setX(xPos);
int strokeOverflow = static_cast<int>(ceilf(rt->style()->textStrokeWidth() / 2.0f));
@@ -313,49 +291,44 @@ int InlineFlowBox::placeBoxesHorizontally(int x, int& leftPosition, int& rightPo
visualOverflowRight = max(visualOverflowRight, shadow->x + shadow->blur + rightGlyphOverflow);
}
- leftPosition = min(x + visualOverflowLeft, leftPosition);
- rightPosition = max(x + text->width() + visualOverflowRight, rightPosition);
- m_maxHorizontalVisualOverflow = max(max(visualOverflowRight, -visualOverflowLeft), m_maxHorizontalVisualOverflow);
- x += text->width();
+ leftPosition = min(xPos + visualOverflowLeft, leftPosition);
+ rightPosition = max(xPos + text->width() + visualOverflowRight, rightPosition);
+ m_maxHorizontalVisualOverflow = max(max(visualOverflowRight, -visualOverflowLeft), (int)m_maxHorizontalVisualOverflow);
+ xPos += text->width();
} else {
- if (curr->object()->isPositioned()) {
- if (curr->object()->parent()->style()->direction() == LTR)
- curr->setXPos(x);
+ if (curr->renderer()->isPositioned()) {
+ if (curr->renderer()->parent()->style()->direction() == LTR)
+ curr->setX(xPos);
else
// Our offset that we cache needs to be from the edge of the right border box and
// not the left border box. We have to subtract |x| from the width of the block
// (which can be obtained from the root line box).
- curr->setXPos(root()->object()->width()-x);
+ curr->setX(root()->block()->width() - xPos);
continue; // The positioned object has no effect on the width.
}
- if (curr->object()->isInlineFlow()) {
+ if (curr->renderer()->isRenderInline()) {
InlineFlowBox* flow = static_cast<InlineFlowBox*>(curr);
- if (curr->object()->isCompact()) {
- int ignoredX = x;
- flow->placeBoxesHorizontally(ignoredX, leftPosition, rightPosition, needsWordSpacing);
- } else {
- x += flow->marginLeft();
- x = flow->placeBoxesHorizontally(x, leftPosition, rightPosition, needsWordSpacing);
- x += flow->marginRight();
- }
- } else if (!curr->object()->isCompact() && (!curr->object()->isListMarker() || static_cast<RenderListMarker*>(curr->object())->isInside())) {
- x += curr->object()->marginLeft();
- curr->setXPos(x);
- leftPosition = min(x + curr->object()->overflowLeft(false), leftPosition);
- rightPosition = max(x + curr->object()->overflowWidth(false), rightPosition);
- x += curr->width() + curr->object()->marginRight();
+ xPos += flow->marginLeft();
+ xPos = flow->placeBoxesHorizontally(xPos, leftPosition, rightPosition, needsWordSpacing);
+ xPos += flow->marginRight();
+ } else if (!curr->renderer()->isListMarker() || static_cast<RenderListMarker*>(curr->renderer())->isInside()) {
+ xPos += curr->boxModelObject()->marginLeft();
+ curr->setX(xPos);
+ leftPosition = min(xPos + toRenderBox(curr->renderer())->overflowLeft(false), leftPosition);
+ rightPosition = max(xPos + toRenderBox(curr->renderer())->overflowWidth(false), rightPosition);
+ xPos += curr->width() + curr->boxModelObject()->marginRight();
}
}
}
- x += borderRight() + paddingRight();
- setWidth(x - startX);
- rightPosition = max(xPos() + width() + boxShadowRight, rightPosition);
+ xPos += borderRight() + paddingRight();
+ setWidth(xPos - startX);
+ rightPosition = max(x() + width() + boxShadowRight, rightPosition);
- return x;
+ return xPos;
}
-void InlineFlowBox::verticallyAlignBoxes(int& heightOfBlock)
+int InlineFlowBox::verticallyAlignBoxes(int heightOfBlock)
{
int maxPositionTop = 0;
int maxPositionBottom = 0;
@@ -364,8 +337,8 @@ void InlineFlowBox::verticallyAlignBoxes(int& heightOfBlock)
// Figure out if we're in strict mode. Note that we can't simply use !style()->htmlHacks(),
// because that would match almost strict mode as well.
- RenderObject* curr = object();
- while (curr && !curr->element())
+ RenderObject* curr = renderer();
+ while (curr && !curr->node())
curr = curr->container();
bool strictMode = (curr && curr->document()->inStrictMode());
@@ -383,12 +356,10 @@ void InlineFlowBox::verticallyAlignBoxes(int& heightOfBlock)
setVerticalOverflowPositions(topPosition, bottomPosition);
setVerticalSelectionPositions(selectionTop, selectionBottom);
-
- // Shrink boxes with no text children in quirks and almost strict mode.
- if (!strictMode)
- shrinkBoxesWithNoTextChildren(topPosition, bottomPosition);
heightOfBlock += maxHeight;
+
+ return heightOfBlock;
}
void InlineFlowBox::adjustMaxAscentAndDescent(int& maxAscent, int& maxDescent,
@@ -397,16 +368,17 @@ void InlineFlowBox::adjustMaxAscentAndDescent(int& maxAscent, int& maxDescent,
for (InlineBox* curr = firstChild(); curr; curr = curr->nextOnLine()) {
// The computed lineheight needs to be extended for the
// positioned elements
- if (curr->object()->isPositioned())
+ if (curr->renderer()->isPositioned())
continue; // Positioned placeholders don't affect calculations.
- if (curr->yPos() == PositionTop || curr->yPos() == PositionBottom) {
- if (curr->yPos() == PositionTop) {
- if (maxAscent + maxDescent < curr->height())
- maxDescent = curr->height() - maxAscent;
+ if (curr->y() == PositionTop || curr->y() == PositionBottom) {
+ int lineHeight = curr->renderer()->lineHeight(m_firstLine);
+ if (curr->y() == PositionTop) {
+ if (maxAscent + maxDescent < lineHeight)
+ maxDescent = lineHeight - maxAscent;
}
else {
- if (maxAscent + maxDescent < curr->height())
- maxAscent = curr->height() - maxDescent;
+ if (maxAscent + maxDescent < lineHeight)
+ maxAscent = lineHeight - maxDescent;
}
if (maxAscent + maxDescent >= max(maxPositionTop, maxPositionBottom))
@@ -418,47 +390,86 @@ void InlineFlowBox::adjustMaxAscentAndDescent(int& maxAscent, int& maxDescent,
}
}
+static int verticalPositionForBox(InlineBox* curr, bool firstLine)
+{
+ if (curr->renderer()->isText())
+ return curr->parent()->y();
+ if (curr->renderer()->isBox())
+ return toRenderBox(curr->renderer())->verticalPosition(firstLine);
+ return toRenderInline(curr->renderer())->verticalPositionFromCache(firstLine);
+}
+
void InlineFlowBox::computeLogicalBoxHeights(int& maxPositionTop, int& maxPositionBottom,
int& maxAscent, int& maxDescent, bool strictMode)
{
if (isRootInlineBox()) {
// Examine our root box.
- setHeight(object()->lineHeight(m_firstLine, true));
- bool isTableCell = object()->isTableCell();
- if (isTableCell) {
- RenderTableCell* tableCell = static_cast<RenderTableCell*>(object());
- setBaseline(tableCell->RenderBlock::baselinePosition(m_firstLine, true));
- }
- else
- setBaseline(object()->baselinePosition(m_firstLine, true));
+ int lineHeight = renderer()->lineHeight(m_firstLine, true);
+ int baseline = renderer()->baselinePosition(m_firstLine, true);
if (hasTextChildren() || strictMode) {
- int ascent = baseline();
- int descent = height() - ascent;
+ int ascent = baseline;
+ int descent = lineHeight - ascent;
if (maxAscent < ascent)
maxAscent = ascent;
if (maxDescent < descent)
maxDescent = descent;
}
}
-
+
for (InlineBox* curr = firstChild(); curr; curr = curr->nextOnLine()) {
- if (curr->object()->isPositioned())
+ if (curr->renderer()->isPositioned())
continue; // Positioned placeholders don't affect calculations.
- curr->setHeight(curr->object()->lineHeight(m_firstLine));
- curr->setBaseline(curr->object()->baselinePosition(m_firstLine));
- curr->setYPos(curr->object()->verticalPositionHint(m_firstLine));
- if (curr->yPos() == PositionTop) {
- if (maxPositionTop < curr->height())
- maxPositionTop = curr->height();
- }
- else if (curr->yPos() == PositionBottom) {
- if (maxPositionBottom < curr->height())
- maxPositionBottom = curr->height();
+ bool isInlineFlow = curr->isInlineFlowBox();
+
+ int lineHeight;
+ int baseline;
+ Vector<const SimpleFontData*> usedFonts;
+ if (curr->isInlineTextBox())
+ static_cast<InlineTextBox*>(curr)->takeFallbackFonts(usedFonts);
+
+ if (!usedFonts.isEmpty()) {
+ usedFonts.append(curr->renderer()->style(m_firstLine)->font().primaryFont());
+ Length parentLineHeight = curr->renderer()->parent()->style()->lineHeight();
+ if (parentLineHeight.isNegative()) {
+ int baselineToBottom = 0;
+ baseline = 0;
+ for (size_t i = 0; i < usedFonts.size(); ++i) {
+ int halfLeading = (usedFonts[i]->lineSpacing() - usedFonts[i]->ascent() - usedFonts[i]->descent()) / 2;
+ baseline = max(baseline, halfLeading + usedFonts[i]->ascent());
+ baselineToBottom = max(baselineToBottom, usedFonts[i]->lineSpacing() - usedFonts[i]->ascent() - usedFonts[i]->descent() - halfLeading);
+ }
+ lineHeight = baseline + baselineToBottom;
+ } else if (parentLineHeight.isPercent()) {
+ lineHeight = parentLineHeight.calcMinValue(curr->renderer()->style()->fontSize());
+ baseline = 0;
+ for (size_t i = 0; i < usedFonts.size(); ++i) {
+ int halfLeading = (lineHeight - usedFonts[i]->ascent() - usedFonts[i]->descent()) / 2;
+ baseline = max(baseline, halfLeading + usedFonts[i]->ascent());
+ }
+ } else {
+ lineHeight = parentLineHeight.value();
+ baseline = 0;
+ for (size_t i = 0; i < usedFonts.size(); ++i) {
+ int halfLeading = (lineHeight - usedFonts[i]->ascent() - usedFonts[i]->descent()) / 2;
+ baseline = max(baseline, halfLeading + usedFonts[i]->ascent());
+ }
+ }
+ } else {
+ lineHeight = curr->renderer()->lineHeight(m_firstLine);
+ baseline = curr->renderer()->baselinePosition(m_firstLine);
}
- else if (curr->hasTextChildren() || curr->object()->hasHorizontalBordersOrPadding() || strictMode) {
- int ascent = curr->baseline() - curr->yPos();
- int descent = curr->height() - ascent;
+
+ curr->setY(verticalPositionForBox(curr, m_firstLine));
+ if (curr->y() == PositionTop) {
+ if (maxPositionTop < lineHeight)
+ maxPositionTop = lineHeight;
+ } else if (curr->y() == PositionBottom) {
+ if (maxPositionBottom < lineHeight)
+ maxPositionBottom = lineHeight;
+ } else if ((!isInlineFlow || static_cast<InlineFlowBox*>(curr)->hasTextChildren()) || curr->boxModelObject()->hasHorizontalBordersOrPadding() || strictMode) {
+ int ascent = baseline - curr->y();
+ int descent = lineHeight - ascent;
if (maxAscent < ascent)
maxAscent = ascent;
if (maxDescent < descent)
@@ -470,135 +481,112 @@ void InlineFlowBox::computeLogicalBoxHeights(int& maxPositionTop, int& maxPositi
}
}
-void InlineFlowBox::placeBoxesVertically(int y, int maxHeight, int maxAscent, bool strictMode,
+void InlineFlowBox::placeBoxesVertically(int yPos, int maxHeight, int maxAscent, bool strictMode,
int& topPosition, int& bottomPosition, int& selectionTop, int& selectionBottom)
{
if (isRootInlineBox())
- setYPos(y + maxAscent - baseline());// Place our root box.
+ setY(yPos + max(0, maxAscent - renderer()->baselinePosition(m_firstLine, true))); // Place our root box.
for (InlineBox* curr = firstChild(); curr; curr = curr->nextOnLine()) {
- if (curr->object()->isPositioned())
+ if (curr->renderer()->isPositioned())
continue; // Positioned placeholders don't affect calculations.
// Adjust boxes to use their real box y/height and not the logical height (as dictated by
// line-height).
- if (curr->isInlineFlowBox())
- static_cast<InlineFlowBox*>(curr)->placeBoxesVertically(y, maxHeight, maxAscent, strictMode, topPosition, bottomPosition, selectionTop, selectionBottom);
+ bool isInlineFlow = curr->isInlineFlowBox();
+ if (isInlineFlow)
+ static_cast<InlineFlowBox*>(curr)->placeBoxesVertically(yPos, maxHeight, maxAscent, strictMode, topPosition, bottomPosition, selectionTop, selectionBottom);
bool childAffectsTopBottomPos = true;
- if (curr->yPos() == PositionTop)
- curr->setYPos(y);
- else if (curr->yPos() == PositionBottom)
- curr->setYPos(y + maxHeight - curr->height());
+ if (curr->y() == PositionTop)
+ curr->setY(yPos);
+ else if (curr->y() == PositionBottom)
+ curr->setY(yPos + maxHeight - curr->renderer()->lineHeight(m_firstLine));
else {
- if (!curr->hasTextChildren() && !curr->object()->hasHorizontalBordersOrPadding() && !strictMode)
+ if ((isInlineFlow && !static_cast<InlineFlowBox*>(curr)->hasTextChildren()) && !curr->boxModelObject()->hasHorizontalBordersOrPadding() && !strictMode)
childAffectsTopBottomPos = false;
- curr->setYPos(curr->yPos() + y + maxAscent - curr->baseline());
+ int posAdjust = maxAscent - curr->renderer()->baselinePosition(m_firstLine);
+ if (!childAffectsTopBottomPos)
+ posAdjust = max(0, posAdjust);
+ curr->setY(curr->y() + yPos + posAdjust);
}
- int newY = curr->yPos();
- int newHeight = curr->height();
- int newBaseline = curr->baseline();
+ // FIXME: By only considering overflow as part of the root line box, we can't get an accurate picture regarding what the line
+ // actually needs to paint. A line box that is part of a self-painting layer technically shouldn't contribute to the overflow
+ // of the line, but in order to not do this and paint accurately, we have to track the overflow somewhere else (either by storing overflow
+ // in each InlineFlowBox up the chain or in the layer itself). Relative positioned objects on a line will cause scrollbars
+ // to appear when they shouldn't until we fix this issue.
+ int newY = curr->y();
int overflowTop = 0;
int overflowBottom = 0;
if (curr->isText() || curr->isInlineFlowBox()) {
- const Font& font = curr->object()->style(m_firstLine)->font();
- newBaseline = font.ascent();
- newY += curr->baseline() - newBaseline;
- newHeight = newBaseline + font.descent();
- for (ShadowData* shadow = curr->object()->style()->textShadow(); shadow; shadow = shadow->next) {
+ const Font& font = curr->renderer()->style(m_firstLine)->font();
+ newY += curr->renderer()->baselinePosition(m_firstLine) - font.ascent();
+ for (ShadowData* shadow = curr->renderer()->style()->textShadow(); shadow; shadow = shadow->next) {
overflowTop = min(overflowTop, shadow->y - shadow->blur);
overflowBottom = max(overflowBottom, shadow->y + shadow->blur);
}
- for (ShadowData* boxShadow = curr->object()->style(m_firstLine)->boxShadow(); boxShadow; boxShadow = boxShadow->next) {
+ for (ShadowData* boxShadow = curr->renderer()->style(m_firstLine)->boxShadow(); boxShadow; boxShadow = boxShadow->next) {
overflowTop = min(overflowTop, boxShadow->y - boxShadow->blur);
overflowBottom = max(overflowBottom, boxShadow->y + boxShadow->blur);
}
- for (ShadowData* textShadow = curr->object()->style(m_firstLine)->textShadow(); textShadow; textShadow = textShadow->next) {
+ for (ShadowData* textShadow = curr->renderer()->style(m_firstLine)->textShadow(); textShadow; textShadow = textShadow->next) {
overflowTop = min(overflowTop, textShadow->y - textShadow->blur);
overflowBottom = max(overflowBottom, textShadow->y + textShadow->blur);
}
- if (curr->object()->hasReflection()) {
- overflowTop = min(overflowTop, curr->object()->reflectionBox().y());
- overflowBottom = max(overflowBottom, curr->object()->reflectionBox().bottom());
+ if (curr->renderer()->hasReflection()) {
+ RenderBox* box = toRenderBox(curr->renderer());
+ overflowTop = min(overflowTop, box->reflectionBox().y());
+ overflowBottom = max(overflowBottom, box->reflectionBox().bottom());
}
- if (curr->isInlineFlowBox()) {
- newHeight += curr->object()->borderTop() + curr->object()->paddingTop() +
- curr->object()->borderBottom() + curr->object()->paddingBottom();
- newY -= curr->object()->borderTop() + curr->object()->paddingTop();
- newBaseline += curr->object()->borderTop() + curr->object()->paddingTop();
- }
- } else if (!curr->object()->isBR()) {
- newY += curr->object()->marginTop();
- newHeight = curr->height() - (curr->object()->marginTop() + curr->object()->marginBottom());
- overflowTop = curr->object()->overflowTop(false);
- overflowBottom = curr->object()->overflowHeight(false) - newHeight;
+ if (curr->isInlineFlowBox())
+ newY -= curr->boxModelObject()->borderTop() + curr->boxModelObject()->paddingTop();
+ } else if (!curr->renderer()->isBR()) {
+ RenderBox* box = toRenderBox(curr->renderer());
+ newY += box->marginTop();
+ overflowTop = box->overflowTop(false);
+ overflowBottom = box->overflowHeight(false) - box->height();
}
- curr->setYPos(newY);
- curr->setHeight(newHeight);
- curr->setBaseline(newBaseline);
+ curr->setY(newY);
if (childAffectsTopBottomPos) {
+ int boxHeight = curr->height();
selectionTop = min(selectionTop, newY);
- selectionBottom = max(selectionBottom, newY + newHeight);
+ selectionBottom = max(selectionBottom, newY + boxHeight);
topPosition = min(topPosition, newY + overflowTop);
- bottomPosition = max(bottomPosition, newY + newHeight + overflowBottom);
+ bottomPosition = max(bottomPosition, newY + boxHeight + overflowBottom);
}
}
if (isRootInlineBox()) {
- const Font& font = object()->style(m_firstLine)->font();
- setHeight(font.ascent() + font.descent());
- setYPos(yPos() + baseline() - font.ascent());
- setBaseline(font.ascent());
+ const Font& font = renderer()->style(m_firstLine)->font();
+ setY(y() + renderer()->baselinePosition(m_firstLine, true) - font.ascent());
if (hasTextChildren() || strictMode) {
- selectionTop = min(selectionTop, yPos());
- selectionBottom = max(selectionBottom, yPos() + height());
+ selectionTop = min(selectionTop, y());
+ selectionBottom = max(selectionBottom, y() + height());
}
}
}
-void InlineFlowBox::shrinkBoxesWithNoTextChildren(int topPos, int bottomPos)
-{
- // First shrink our kids.
- for (InlineBox* curr = firstChild(); curr; curr = curr->nextOnLine()) {
- if (curr->object()->isPositioned())
- continue; // Positioned placeholders don't affect calculations.
-
- if (curr->isInlineFlowBox())
- static_cast<InlineFlowBox*>(curr)->shrinkBoxesWithNoTextChildren(topPos, bottomPos);
- }
-
- // See if we have text children. If not, then we need to shrink ourselves to fit on the line.
- if (!hasTextChildren() && !object()->hasHorizontalBordersOrPadding()) {
- if (yPos() < topPos)
- setYPos(topPos);
- if (yPos() + height() > bottomPos)
- setHeight(bottomPos - yPos());
- if (baseline() > height())
- setBaseline(height());
- }
-}
-
bool InlineFlowBox::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, int x, int y, int tx, int ty)
{
// Check children first.
for (InlineBox* curr = lastChild(); curr; curr = curr->prevOnLine()) {
- if (!curr->object()->hasLayer() && curr->nodeAtPoint(request, result, x, y, tx, ty)) {
- object()->updateHitTestResult(result, IntPoint(x - tx, y - ty));
+ if ((curr->renderer()->isText() || !curr->boxModelObject()->hasSelfPaintingLayer()) && curr->nodeAtPoint(request, result, x, y, tx, ty)) {
+ renderer()->updateHitTestResult(result, IntPoint(x - tx, y - ty));
return true;
}
}
// Now check ourselves.
- IntRect rect(tx + m_x, ty + m_y, m_width, m_height);
+ IntRect rect(tx + m_x, ty + m_y, m_width, height());
if (visibleToHitTesting() && rect.contains(x, y)) {
- object()->updateHitTestResult(result, IntPoint(x - tx, y - ty)); // Don't add in m_x or m_y here, we want coords in the containing block's space.
+ renderer()->updateHitTestResult(result, IntPoint(x - tx, y - ty)); // Don't add in m_x or m_y here, we want coords in the containing block's space.
return true;
}
@@ -607,15 +595,15 @@ bool InlineFlowBox::nodeAtPoint(const HitTestRequest& request, HitTestResult& re
void InlineFlowBox::paint(RenderObject::PaintInfo& paintInfo, int tx, int ty)
{
- int xPos = tx + m_x - object()->maximalOutlineSize(paintInfo.phase);
- int w = width() + 2 * object()->maximalOutlineSize(paintInfo.phase);
+ int xPos = tx + m_x - renderer()->maximalOutlineSize(paintInfo.phase);
+ int w = width() + 2 * renderer()->maximalOutlineSize(paintInfo.phase);
int shadowLeft = 0;
int shadowRight = 0;
- for (ShadowData* boxShadow = object()->style(m_firstLine)->boxShadow(); boxShadow; boxShadow = boxShadow->next) {
+ for (ShadowData* boxShadow = renderer()->style(m_firstLine)->boxShadow(); boxShadow; boxShadow = boxShadow->next) {
shadowLeft = min(boxShadow->x - boxShadow->blur, shadowLeft);
shadowRight = max(boxShadow->x + boxShadow->blur, shadowRight);
}
- for (ShadowData* textShadow = object()->style(m_firstLine)->textShadow(); textShadow; textShadow = textShadow->next) {
+ for (ShadowData* textShadow = renderer()->style(m_firstLine)->textShadow(); textShadow; textShadow = textShadow->next) {
shadowLeft = min(textShadow->x - textShadow->blur, shadowLeft);
shadowRight = max(textShadow->x + textShadow->blur, shadowRight);
}
@@ -627,14 +615,15 @@ void InlineFlowBox::paint(RenderObject::PaintInfo& paintInfo, int tx, int ty)
if (paintInfo.phase == PaintPhaseOutline || paintInfo.phase == PaintPhaseSelfOutline) {
// Add ourselves to the paint info struct's list of inlines that need to paint their
// outlines.
- if (object()->style()->visibility() == VISIBLE && object()->hasOutline() && !isRootInlineBox()) {
- if ((object()->continuation() || object()->isInlineContinuation()) && !object()->hasLayer()) {
+ if (renderer()->style()->visibility() == VISIBLE && renderer()->hasOutline() && !isRootInlineBox()) {
+ RenderInline* inlineFlow = toRenderInline(renderer());
+ if ((inlineFlow->continuation() || inlineFlow->isInlineContinuation()) && !boxModelObject()->hasSelfPaintingLayer()) {
// Add ourselves to the containing block of the entire continuation so that it can
// paint us atomically.
- RenderBlock* block = object()->containingBlock()->containingBlock();
- block->addContinuationWithOutline(static_cast<RenderFlow*>(object()->element()->renderer()));
- } else if (!object()->isInlineContinuation())
- paintInfo.outlineObjects->add(flowObject());
+ RenderBlock* block = renderer()->containingBlock()->containingBlock();
+ block->addContinuationWithOutline(toRenderInline(renderer()->node()->renderer()));
+ } else if (!inlineFlow->isInlineContinuation())
+ paintInfo.outlineObjects->add(inlineFlow);
}
} else if (paintInfo.phase == PaintPhaseMask) {
paintMask(paintInfo, tx, ty);
@@ -654,12 +643,12 @@ void InlineFlowBox::paint(RenderObject::PaintInfo& paintInfo, int tx, int ty)
PaintPhase paintPhase = paintInfo.phase == PaintPhaseChildOutlines ? PaintPhaseOutline : paintInfo.phase;
RenderObject::PaintInfo childInfo(paintInfo);
childInfo.phase = paintPhase;
- childInfo.paintingRoot = object()->paintingRootForChildren(paintInfo);
+ childInfo.paintingRoot = renderer()->paintingRootForChildren(paintInfo);
// 3. Paint our children.
if (paintPhase != PaintPhaseSelfOutline) {
for (InlineBox* curr = firstChild(); curr; curr = curr->nextOnLine()) {
- if (!curr->object()->hasLayer())
+ if (curr->renderer()->isText() || !curr->boxModelObject()->hasSelfPaintingLayer())
curr->paint(childInfo, tx, ty);
}
}
@@ -669,22 +658,20 @@ void InlineFlowBox::paint(RenderObject::PaintInfo& paintInfo, int tx, int ty)
paintTextDecorations(paintInfo, tx, ty, true);
}
-void InlineFlowBox::paintFillLayers(const RenderObject::PaintInfo& paintInfo, const Color& c, const FillLayer* fillLayer,
- int my, int mh, int _tx, int _ty, int w, int h, CompositeOperator op)
+void InlineFlowBox::paintFillLayers(const RenderObject::PaintInfo& paintInfo, const Color& c, const FillLayer* fillLayer, int _tx, int _ty, int w, int h, CompositeOperator op)
{
if (!fillLayer)
return;
- paintFillLayers(paintInfo, c, fillLayer->next(), my, mh, _tx, _ty, w, h, op);
- paintFillLayer(paintInfo, c, fillLayer, my, mh, _tx, _ty, w, h, op);
+ paintFillLayers(paintInfo, c, fillLayer->next(), _tx, _ty, w, h, op);
+ paintFillLayer(paintInfo, c, fillLayer, _tx, _ty, w, h, op);
}
-void InlineFlowBox::paintFillLayer(const RenderObject::PaintInfo& paintInfo, const Color& c, const FillLayer* fillLayer,
- int my, int mh, int tx, int ty, int w, int h, CompositeOperator op)
+void InlineFlowBox::paintFillLayer(const RenderObject::PaintInfo& paintInfo, const Color& c, const FillLayer* fillLayer, int tx, int ty, int w, int h, CompositeOperator op)
{
StyleImage* img = fillLayer->image();
- bool hasFillImage = img && img->canRender(object()->style()->effectiveZoom());
- if ((!hasFillImage && !object()->style()->hasBorderRadius()) || (!prevLineBox() && !nextLineBox()) || !parent())
- object()->paintFillLayerExtended(paintInfo, c, fillLayer, my, mh, tx, ty, w, h, this, op);
+ 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);
else {
// We have a fill image that spans multiple lines.
// We need to adjust _tx and _ty by the width of all previous lines.
@@ -703,7 +690,7 @@ void InlineFlowBox::paintFillLayer(const RenderObject::PaintInfo& paintInfo, con
totalWidth += curr->width();
paintInfo.context->save();
paintInfo.context->clip(IntRect(tx, ty, width(), height()));
- object()->paintFillLayerExtended(paintInfo, c, fillLayer, my, mh, startX, ty, totalWidth, h, this, op);
+ boxModelObject()->paintFillLayerExtended(paintInfo, c, fillLayer, startX, ty, totalWidth, h, this, op);
paintInfo.context->restore();
}
}
@@ -711,17 +698,17 @@ void InlineFlowBox::paintFillLayer(const RenderObject::PaintInfo& paintInfo, con
void InlineFlowBox::paintBoxShadow(GraphicsContext* context, RenderStyle* s, int tx, int ty, int w, int h)
{
if ((!prevLineBox() && !nextLineBox()) || !parent())
- object()->paintBoxShadow(context, tx, ty, w, h, s);
+ boxModelObject()->paintBoxShadow(context, tx, ty, w, h, s);
else {
// FIXME: We can do better here in the multi-line case. We want to push a clip so that the shadow doesn't
// protrude incorrectly at the edges, and we want to possibly include shadows cast from the previous/following lines
- object()->paintBoxShadow(context, tx, ty, w, h, s, includeLeftEdge(), includeRightEdge());
+ boxModelObject()->paintBoxShadow(context, tx, ty, w, h, s, includeLeftEdge(), includeRightEdge());
}
}
void InlineFlowBox::paintBoxDecorations(RenderObject::PaintInfo& paintInfo, int tx, int ty)
{
- if (!object()->shouldPaintWithinRoot(paintInfo) || object()->style()->visibility() != VISIBLE || paintInfo.phase != PaintPhaseForeground)
+ if (!renderer()->shouldPaintWithinRoot(paintInfo) || renderer()->style()->visibility() != VISIBLE || paintInfo.phase != PaintPhaseForeground)
return;
// Move x/y to our coordinates.
@@ -731,30 +718,23 @@ void InlineFlowBox::paintBoxDecorations(RenderObject::PaintInfo& paintInfo, int
int w = width();
int h = height();
- int my = max(ty, paintInfo.rect.y());
- int mh;
- if (ty < paintInfo.rect.y())
- mh = max(0, h - (paintInfo.rect.y() - ty));
- else
- mh = min(paintInfo.rect.height(), h);
-
GraphicsContext* context = paintInfo.context;
// You can use p::first-line to specify a background. If so, the root line boxes for
// a line may actually have to paint a background.
- RenderStyle* styleToUse = object()->style(m_firstLine);
- if ((!parent() && m_firstLine && styleToUse != object()->style()) || (parent() && object()->hasBoxDecorations())) {
+ RenderStyle* styleToUse = renderer()->style(m_firstLine);
+ if ((!parent() && m_firstLine && styleToUse != renderer()->style()) || (parent() && renderer()->hasBoxDecorations())) {
// Shadow comes first and is behind the background and border.
if (styleToUse->boxShadow())
paintBoxShadow(context, styleToUse, tx, ty, w, h);
Color c = styleToUse->backgroundColor();
- paintFillLayers(paintInfo, c, styleToUse->backgroundLayers(), my, mh, tx, ty, w, h);
+ paintFillLayers(paintInfo, c, styleToUse->backgroundLayers(), tx, ty, w, h);
// :first-line cannot be used to put borders on a line. Always paint borders with our
// non-first-line style.
- if (parent() && object()->style()->hasBorder()) {
- StyleImage* borderImage = object()->style()->borderImage().image();
+ if (parent() && renderer()->style()->hasBorder()) {
+ StyleImage* borderImage = renderer()->style()->borderImage().image();
bool hasBorderImage = borderImage && borderImage->canRender(styleToUse->effectiveZoom());
if (hasBorderImage && !borderImage->isLoaded())
return; // Don't paint anything while we wait for the image to load.
@@ -762,7 +742,7 @@ void InlineFlowBox::paintBoxDecorations(RenderObject::PaintInfo& paintInfo, int
// The simple case is where we either have no border image or we are the only box for this object. In those
// cases only a single call to draw is required.
if (!hasBorderImage || (!prevLineBox() && !nextLineBox()))
- object()->paintBorder(context, tx, ty, w, h, object()->style(), includeLeftEdge(), includeRightEdge());
+ boxModelObject()->paintBorder(context, tx, ty, w, h, renderer()->style(), includeLeftEdge(), includeRightEdge());
else {
// We have a border image that spans multiple lines.
// We need to adjust _tx and _ty by the width of all previous lines.
@@ -780,8 +760,8 @@ void InlineFlowBox::paintBoxDecorations(RenderObject::PaintInfo& paintInfo, int
for (InlineRunBox* curr = this; curr; curr = curr->nextLineBox())
totalWidth += curr->width();
context->save();
- context->clip(IntRect(tx, ty, width(), height()));
- object()->paintBorder(context, startX, ty, totalWidth, h, object()->style());
+ context->clip(IntRect(tx, ty, w, h));
+ boxModelObject()->paintBorder(context, startX, ty, totalWidth, h, renderer()->style());
context->restore();
}
}
@@ -790,7 +770,7 @@ void InlineFlowBox::paintBoxDecorations(RenderObject::PaintInfo& paintInfo, int
void InlineFlowBox::paintMask(RenderObject::PaintInfo& paintInfo, int tx, int ty)
{
- if (!object()->shouldPaintWithinRoot(paintInfo) || object()->style()->visibility() != VISIBLE || paintInfo.phase != PaintPhaseMask)
+ if (!renderer()->shouldPaintWithinRoot(paintInfo) || renderer()->style()->visibility() != VISIBLE || paintInfo.phase != PaintPhaseMask)
return;
// Move x/y to our coordinates.
@@ -800,19 +780,11 @@ void InlineFlowBox::paintMask(RenderObject::PaintInfo& paintInfo, int tx, int ty
int w = width();
int h = height();
- int my = max(ty, paintInfo.rect.y());
- int mh;
- if (ty < paintInfo.rect.y())
- mh = max(0, h - (paintInfo.rect.y() - ty));
- else
- mh = min(paintInfo.rect.height(), h);
-
-
// Figure out if we need to push a transparency layer to render our mask.
bool pushTransparencyLayer = false;
- const NinePieceImage& maskNinePieceImage = object()->style()->maskBoxImage();
- StyleImage* maskBoxImage = object()->style()->maskBoxImage().image();
- if ((maskBoxImage && object()->style()->maskLayers()->hasImage()) || object()->style()->maskLayers()->next())
+ const NinePieceImage& maskNinePieceImage = renderer()->style()->maskBoxImage();
+ StyleImage* maskBoxImage = renderer()->style()->maskBoxImage().image();
+ if ((maskBoxImage && renderer()->style()->maskLayers()->hasImage()) || renderer()->style()->maskLayers()->next())
pushTransparencyLayer = true;
CompositeOperator compositeOp = CompositeDestinationIn;
@@ -822,16 +794,16 @@ void InlineFlowBox::paintMask(RenderObject::PaintInfo& paintInfo, int tx, int ty
compositeOp = CompositeSourceOver;
}
- paintFillLayers(paintInfo, Color(), object()->style()->maskLayers(), my, mh, tx, ty, w, h, compositeOp);
+ paintFillLayers(paintInfo, Color(), renderer()->style()->maskLayers(), tx, ty, w, h, compositeOp);
- bool hasBoxImage = maskBoxImage && maskBoxImage->canRender(object()->style()->effectiveZoom());
+ bool hasBoxImage = maskBoxImage && maskBoxImage->canRender(renderer()->style()->effectiveZoom());
if (!hasBoxImage || !maskBoxImage->isLoaded())
return; // Don't paint anything while we wait for the image to load.
// The simple case is where we are the only box for this object. In those
// cases only a single call to draw is required.
if (!prevLineBox() && !nextLineBox()) {
- object()->paintNinePieceImage(paintInfo.context, tx, ty, w, h, object()->style(), maskNinePieceImage, compositeOp);
+ boxModelObject()->paintNinePieceImage(paintInfo.context, tx, ty, w, h, renderer()->style(), maskNinePieceImage, compositeOp);
} else {
// We have a mask image that spans multiple lines.
// We need to adjust _tx and _ty by the width of all previous lines.
@@ -843,8 +815,8 @@ void InlineFlowBox::paintMask(RenderObject::PaintInfo& paintInfo, int tx, int ty
for (InlineRunBox* curr = this; curr; curr = curr->nextLineBox())
totalWidth += curr->width();
paintInfo.context->save();
- paintInfo.context->clip(IntRect(tx, ty, width(), height()));
- object()->paintNinePieceImage(paintInfo.context, startX, ty, totalWidth, h, object()->style(), maskNinePieceImage, compositeOp);
+ paintInfo.context->clip(IntRect(tx, ty, w, h));
+ boxModelObject()->paintNinePieceImage(paintInfo.context, startX, ty, totalWidth, h, renderer()->style(), maskNinePieceImage, compositeOp);
paintInfo.context->restore();
}
@@ -855,12 +827,12 @@ void InlineFlowBox::paintMask(RenderObject::PaintInfo& paintInfo, int tx, int ty
static bool shouldDrawTextDecoration(RenderObject* obj)
{
for (RenderObject* curr = obj->firstChild(); curr; curr = curr->nextSibling()) {
- if (curr->isInlineFlow())
+ if (curr->isRenderInline())
return true;
if (curr->isText() && !curr->isBR()) {
if (!curr->style()->collapseWhiteSpace())
return true;
- Node* currElement = curr->element();
+ Node* currElement = curr->node();
if (!currElement)
return true;
if (!currElement->isTextNode())
@@ -876,8 +848,8 @@ void InlineFlowBox::paintTextDecorations(RenderObject::PaintInfo& paintInfo, int
{
// Paint text decorations like underlines/overlines. We only do this if we aren't in quirks mode (i.e., in
// almost-strict mode or strict mode).
- if (object()->style()->htmlHacks() || !object()->shouldPaintWithinRoot(paintInfo) ||
- object()->style()->visibility() != VISIBLE)
+ if (renderer()->style()->htmlHacks() || !renderer()->shouldPaintWithinRoot(paintInfo) ||
+ renderer()->style()->visibility() != VISIBLE)
return;
// We don't want underlines or other decorations when we're trying to draw nothing but the selection as white text.
@@ -887,27 +859,46 @@ void InlineFlowBox::paintTextDecorations(RenderObject::PaintInfo& paintInfo, int
GraphicsContext* context = paintInfo.context;
tx += m_x;
ty += m_y;
- RenderStyle* styleToUse = object()->style(m_firstLine);
+ RenderStyle* styleToUse = renderer()->style(m_firstLine);
int deco = parent() ? styleToUse->textDecoration() : styleToUse->textDecorationsInEffect();
if (deco != TDNONE &&
((!paintedChildren && ((deco & UNDERLINE) || (deco & OVERLINE))) || (paintedChildren && (deco & LINE_THROUGH))) &&
- shouldDrawTextDecoration(object())) {
+ shouldDrawTextDecoration(renderer())) {
int x = m_x + borderLeft() + paddingLeft();
int w = m_width - (borderLeft() + paddingLeft() + borderRight() + paddingRight());
RootInlineBox* rootLine = root();
if (rootLine->ellipsisBox()) {
- int ellipsisX = rootLine->ellipsisBox()->xPos();
+ int ellipsisX = m_x + rootLine->ellipsisBox()->x();
int ellipsisWidth = rootLine->ellipsisBox()->width();
-
- // FIXME: Will need to work with RTL
+ bool ltr = renderer()->style()->direction() == LTR;
if (rootLine == this) {
- if (x + w >= ellipsisX + ellipsisWidth)
- w -= (x + w - ellipsisX - ellipsisWidth);
+ // Trim w and x so that the underline isn't drawn underneath the ellipsis.
+ // ltr: is our right edge farther right than the right edge of the ellipsis.
+ // rtl: is the left edge of our box farther left than the left edge of the ellipsis.
+ bool ltrTruncation = ltr && (x + w >= ellipsisX + ellipsisWidth);
+ bool rtlTruncation = !ltr && (x <= ellipsisX + ellipsisWidth);
+ if (ltrTruncation)
+ w -= (x + w) - (ellipsisX + ellipsisWidth);
+ else if (rtlTruncation) {
+ int dx = m_x - ((ellipsisX - m_x) + ellipsisWidth);
+ tx -= dx;
+ w += dx;
+ }
} else {
- if (x >= ellipsisX)
+ bool ltrPastEllipsis = ltr && x >= ellipsisX;
+ bool rtlPastEllipsis = !ltr && (x + w) <= (ellipsisX + ellipsisWidth);
+ if (ltrPastEllipsis || rtlPastEllipsis)
return;
- if (x + w >= ellipsisX)
+
+ bool ltrTruncation = ltr && x + w >= ellipsisX;
+ bool rtlTruncation = !ltr && x <= ellipsisX;
+ if (ltrTruncation)
w -= (x + w - ellipsisX);
+ else if (rtlTruncation) {
+ int dx = m_x - ((ellipsisX - m_x) + ellipsisWidth);
+ tx -= dx;
+ w += dx;
+ }
}
}
@@ -917,9 +908,9 @@ void InlineFlowBox::paintTextDecorations(RenderObject::PaintInfo& paintInfo, int
Color underline, overline, linethrough;
underline = overline = linethrough = styleToUse->color();
if (!parent())
- object()->getTextDecorationColors(deco, underline, overline, linethrough);
+ renderer()->getTextDecorationColors(deco, underline, overline, linethrough);
- bool isPrinting = object()->document()->printing();
+ bool isPrinting = renderer()->document()->printing();
context->setStrokeThickness(1.0f); // FIXME: We should improve this rule and not always just assume 1.
bool paintUnderline = deco & UNDERLINE && !paintedChildren;
@@ -928,13 +919,17 @@ void InlineFlowBox::paintTextDecorations(RenderObject::PaintInfo& paintInfo, int
bool linesAreOpaque = !isPrinting && (!paintUnderline || underline.alpha() == 255) && (!paintOverline || overline.alpha() == 255) && (!paintLineThrough || linethrough.alpha() == 255);
+ int baselinePos = renderer()->style(m_firstLine)->font().ascent();
+ if (!isRootInlineBox())
+ baselinePos += borderTop() + paddingTop();
+
bool setClip = false;
int extraOffset = 0;
ShadowData* shadow = styleToUse->textShadow();
if (!linesAreOpaque && shadow && shadow->next) {
- IntRect clipRect(tx, ty, w, m_baseline + 2);
+ IntRect clipRect(tx, ty, w, baselinePos + 2);
for (ShadowData* s = shadow; s; s = s->next) {
- IntRect shadowRect(tx, ty, w, m_baseline + 2);
+ IntRect shadowRect(tx, ty, w, baselinePos + 2);
shadowRect.inflate(s->blur);
shadowRect.move(s->x, s->y);
clipRect.unite(shadowRect);
@@ -942,7 +937,7 @@ void InlineFlowBox::paintTextDecorations(RenderObject::PaintInfo& paintInfo, int
}
context->save();
context->clip(clipRect);
- extraOffset += m_baseline + 2;
+ extraOffset += baselinePos + 2;
ty += extraOffset;
setClip = true;
}
@@ -962,16 +957,19 @@ void InlineFlowBox::paintTextDecorations(RenderObject::PaintInfo& paintInfo, int
if (paintUnderline) {
context->setStrokeColor(underline);
+ context->setStrokeStyle(SolidStroke);
// Leave one pixel of white between the baseline and the underline.
- context->drawLineForText(IntPoint(tx, ty + m_baseline + 1), w, isPrinting);
+ context->drawLineForText(IntPoint(tx, ty + baselinePos + 1), w, isPrinting);
}
if (paintOverline) {
context->setStrokeColor(overline);
+ context->setStrokeStyle(SolidStroke);
context->drawLineForText(IntPoint(tx, ty), w, isPrinting);
}
if (paintLineThrough) {
context->setStrokeColor(linethrough);
- context->drawLineForText(IntPoint(tx, ty + 2 * m_baseline / 3), w, isPrinting);
+ context->setStrokeStyle(SolidStroke);
+ context->drawLineForText(IntPoint(tx, ty + 2 * baselinePos / 3), w, isPrinting);
}
} while (shadow);
@@ -1026,13 +1024,32 @@ bool InlineFlowBox::canAccommodateEllipsis(bool ltr, int blockEdge, int ellipsis
return true;
}
-int InlineFlowBox::placeEllipsisBox(bool ltr, int blockEdge, int ellipsisWidth, bool& foundBox)
+int InlineFlowBox::placeEllipsisBox(bool ltr, int blockLeftEdge, int blockRightEdge, int ellipsisWidth, bool& foundBox)
{
int result = -1;
- for (InlineBox *box = firstChild(); box; box = box->nextOnLine()) {
- int currResult = box->placeEllipsisBox(ltr, blockEdge, ellipsisWidth, foundBox);
+ // We iterate over all children, the foundBox variable tells us when we've found the
+ // box containing the ellipsis. All boxes after that one in the flow are hidden.
+ // If our flow is ltr then iterate over the boxes from left to right, otherwise iterate
+ // from right to left. Varying the order allows us to correctly hide the boxes following the ellipsis.
+ InlineBox *box = ltr ? firstChild() : lastChild();
+
+ // NOTE: these will cross after foundBox = true.
+ int visibleLeftEdge = blockLeftEdge;
+ int visibleRightEdge = blockRightEdge;
+
+ while(box) {
+ int currResult = box->placeEllipsisBox(ltr, visibleLeftEdge, visibleRightEdge, ellipsisWidth, foundBox);
if (currResult != -1 && result == -1)
result = currResult;
+
+ if (ltr) {
+ visibleLeftEdge += box->width();
+ box = box->nextOnLine();
+ }
+ else {
+ visibleRightEdge -= box->width();
+ box = box->prevOnLine();
+ }
}
return result;
}
diff --git a/src/3rdparty/webkit/WebCore/rendering/InlineFlowBox.h b/src/3rdparty/webkit/WebCore/rendering/InlineFlowBox.h
index 30dad38..ab1b6f2 100644
--- a/src/3rdparty/webkit/WebCore/rendering/InlineFlowBox.h
+++ b/src/3rdparty/webkit/WebCore/rendering/InlineFlowBox.h
@@ -25,9 +25,9 @@
namespace WebCore {
+class HitTestRequest;
class HitTestResult;
-
-struct HitTestRequest;
+class RenderLineBoxList;
class InlineFlowBox : public InlineRunBox {
public:
@@ -36,6 +36,9 @@ public:
, m_firstChild(0)
, m_lastChild(0)
, m_maxHorizontalVisualOverflow(0)
+ , m_includeLeftEdge(false)
+ , m_includeRightEdge(false)
+ , m_hasTextChildren(true)
#ifndef NDEBUG
, m_hasBadChildList(false)
#endif
@@ -52,10 +55,6 @@ public:
virtual ~InlineFlowBox();
#endif
- RenderFlow* flowObject();
-
- virtual bool isInlineFlowBox() { return true; }
-
InlineFlowBox* prevFlowBox() const { return static_cast<InlineFlowBox*>(m_prevLine); }
InlineFlowBox* nextFlowBox() const { return static_cast<InlineFlowBox*>(m_nextLine); }
@@ -80,30 +79,38 @@ public:
virtual void attachLine();
virtual void adjustPosition(int dx, int dy);
+ virtual void extractLineBoxFromRenderObject();
+ virtual void attachLineBoxToRenderObject();
+ virtual void removeLineBoxFromRenderObject();
+
virtual void clearTruncation();
virtual void paintBoxDecorations(RenderObject::PaintInfo&, int tx, int ty);
virtual void paintMask(RenderObject::PaintInfo&, int tx, int ty);
- void paintFillLayers(const RenderObject::PaintInfo&, const Color&, const FillLayer*,
- int my, int mh, int tx, int ty, int w, int h, CompositeOperator = CompositeSourceOver);
- void paintFillLayer(const RenderObject::PaintInfo&, const Color&, const FillLayer*,
- int my, int mh, int tx, int ty, int w, int h, CompositeOperator = CompositeSourceOver);
+ void paintFillLayers(const RenderObject::PaintInfo&, const Color&, const FillLayer*, int tx, int ty, int w, int h, CompositeOperator = CompositeSourceOver);
+ void paintFillLayer(const RenderObject::PaintInfo&, const Color&, const FillLayer*, int tx, int ty, int w, int h, CompositeOperator = CompositeSourceOver);
void paintBoxShadow(GraphicsContext*, RenderStyle*, int tx, int ty, int w, int h);
virtual void paintTextDecorations(RenderObject::PaintInfo&, int tx, int ty, bool paintedChildren = false);
virtual void paint(RenderObject::PaintInfo&, int tx, int ty);
virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, int x, int y, int tx, int ty);
- int marginBorderPaddingLeft();
- int marginBorderPaddingRight();
- int marginLeft();
- int marginRight();
- int borderLeft() { if (includeLeftEdge()) return object()->borderLeft(); return 0; }
- int borderRight() { if (includeRightEdge()) return object()->borderRight(); return 0; }
- int paddingLeft() { if (includeLeftEdge()) return object()->paddingLeft(); return 0; }
- int paddingRight() { if (includeRightEdge()) return object()->paddingRight(); return 0; }
-
- bool includeLeftEdge() { return m_includeLeftEdge; }
- bool includeRightEdge() { return m_includeRightEdge; }
+ virtual RenderLineBoxList* rendererLineBoxes() const;
+
+ int marginBorderPaddingLeft() const { return marginLeft() + borderLeft() + paddingLeft(); }
+ int marginBorderPaddingRight() const { return marginRight() + borderRight() + paddingRight(); }
+ int marginLeft() const { if (includeLeftEdge()) return boxModelObject()->marginLeft(); return 0; }
+ int marginRight() const { if (includeRightEdge()) return boxModelObject()->marginRight(); return 0; }
+ int borderLeft() const { if (includeLeftEdge()) return renderer()->style()->borderLeftWidth(); return 0; }
+ int borderRight() const { if (includeRightEdge()) return renderer()->style()->borderRightWidth(); return 0; }
+ int borderTop() const { return renderer()->style()->borderTopWidth(); }
+ int borderBottom() const { return renderer()->style()->borderBottomWidth(); }
+ int paddingLeft() const { if (includeLeftEdge()) return boxModelObject()->paddingLeft(); return 0; }
+ int paddingRight() const { if (includeRightEdge()) return boxModelObject()->paddingRight(); return 0; }
+ int paddingTop() const { return boxModelObject()->paddingTop(); }
+ int paddingBottom() const { return boxModelObject()->paddingBottom(); }
+
+ bool includeLeftEdge() const { return m_includeLeftEdge; }
+ bool includeRightEdge() const { return m_includeRightEdge; }
void setEdges(bool includeLeft, bool includeRight)
{
m_includeLeftEdge = includeLeft;
@@ -115,33 +122,40 @@ public:
int getFlowSpacingWidth();
bool onEndChain(RenderObject* endObject);
virtual int placeBoxesHorizontally(int x, int& leftPosition, int& rightPosition, bool& needsWordSpacing);
- virtual void verticallyAlignBoxes(int& heightOfBlock);
+ virtual int verticallyAlignBoxes(int heightOfBlock);
void computeLogicalBoxHeights(int& maxPositionTop, int& maxPositionBottom,
int& maxAscent, int& maxDescent, bool strictMode);
void adjustMaxAscentAndDescent(int& maxAscent, int& maxDescent,
int maxPositionTop, int maxPositionBottom);
void placeBoxesVertically(int y, int maxHeight, int maxAscent, bool strictMode,
int& topPosition, int& bottomPosition, int& selectionTop, int& selectionBottom);
- void shrinkBoxesWithNoTextChildren(int topPosition, int bottomPosition);
virtual void setVerticalOverflowPositions(int /*top*/, int /*bottom*/) { }
virtual void setVerticalSelectionPositions(int /*top*/, int /*bottom*/) { }
- int maxHorizontalVisualOverflow() const { return m_maxHorizontalVisualOverflow; }
+ short maxHorizontalVisualOverflow() const { return m_maxHorizontalVisualOverflow; }
void removeChild(InlineBox* child);
virtual RenderObject::SelectionState selectionState();
virtual bool canAccommodateEllipsis(bool ltr, int blockEdge, int ellipsisWidth);
- virtual int placeEllipsisBox(bool ltr, int blockEdge, int ellipsisWidth, bool&);
+ virtual int placeEllipsisBox(bool ltr, int blockLeftEdge, int blockRightEdge, int ellipsisWidth, bool&);
+
+ bool hasTextChildren() const { return m_hasTextChildren; }
void checkConsistency() const;
void setHasBadChildList();
private:
+ virtual bool isInlineFlowBox() const { return true; }
+
InlineBox* m_firstChild;
InlineBox* m_lastChild;
- int m_maxHorizontalVisualOverflow;
+ short m_maxHorizontalVisualOverflow;
+
+ bool m_includeLeftEdge : 1;
+ bool m_includeRightEdge : 1;
+ bool m_hasTextChildren : 1;
#ifndef NDEBUG
bool m_hasBadChildList;
@@ -165,7 +179,7 @@ inline void InlineFlowBox::setHasBadChildList()
#ifndef NDEBUG
// Outside the WebCore namespace for ease of invocation from gdb.
-void showTree(const WebCore::InlineBox*);
+void showTree(const WebCore::InlineFlowBox*);
#endif
#endif // InlineFlowBox_h
diff --git a/src/3rdparty/webkit/WebCore/rendering/InlineTextBox.cpp b/src/3rdparty/webkit/WebCore/rendering/InlineTextBox.cpp
index a5857e0..53646f9 100644
--- a/src/3rdparty/webkit/WebCore/rendering/InlineTextBox.cpp
+++ b/src/3rdparty/webkit/WebCore/rendering/InlineTextBox.cpp
@@ -60,10 +60,10 @@ bool InlineTextBox::isSelected(int startPos, int endPos) const
RenderObject::SelectionState InlineTextBox::selectionState()
{
- RenderObject::SelectionState state = object()->selectionState();
+ RenderObject::SelectionState state = renderer()->selectionState();
if (state == RenderObject::SelectionStart || state == RenderObject::SelectionEnd || state == RenderObject::SelectionBoth) {
int startPos, endPos;
- object()->selectionStartEnd(startPos, endPos);
+ renderer()->selectionStartEnd(startPos, endPos);
// The position after a hard line break is considered to be past its end.
int lastSelectable = start() + len() - (isLineBreak() ? 1 : 0);
@@ -92,7 +92,7 @@ IntRect InlineTextBox::selectionRect(int tx, int ty, int startPos, int endPos)
if (sPos >= ePos)
return IntRect();
- RenderText* textObj = textObject();
+ RenderText* textObj = textRenderer();
int selTop = selectionTop();
int selHeight = selectionHeight();
const Font& f = textObj->style(m_firstLine)->font();
@@ -108,7 +108,7 @@ IntRect InlineTextBox::selectionRect(int tx, int ty, int startPos, int endPos)
void InlineTextBox::deleteLine(RenderArena* arena)
{
- static_cast<RenderText*>(m_object)->removeTextBox(this);
+ toRenderText(renderer())->removeTextBox(this);
destroy(arena);
}
@@ -117,7 +117,7 @@ void InlineTextBox::extractLine()
if (m_extracted)
return;
- static_cast<RenderText*>(m_object)->extractTextBox(this);
+ toRenderText(renderer())->extractTextBox(this);
}
void InlineTextBox::attachLine()
@@ -125,48 +125,70 @@ void InlineTextBox::attachLine()
if (!m_extracted)
return;
- static_cast<RenderText*>(m_object)->attachTextBox(this);
+ toRenderText(renderer())->attachTextBox(this);
}
-int InlineTextBox::placeEllipsisBox(bool ltr, int blockEdge, int ellipsisWidth, bool& foundBox)
+int InlineTextBox::placeEllipsisBox(bool flowIsLTR, int visibleLeftEdge, int visibleRightEdge, int ellipsisWidth, bool& foundBox)
{
if (foundBox) {
m_truncation = cFullTruncation;
return -1;
}
- int ellipsisX = ltr ? blockEdge - ellipsisWidth : blockEdge + ellipsisWidth;
+ // For LTR this is the left edge of the box, for RTL, the right edge in parent coordinates.
+ int ellipsisX = flowIsLTR ? visibleRightEdge - ellipsisWidth : visibleLeftEdge + ellipsisWidth;
- // For LTR, if the left edge of the ellipsis is to the left of our text run, then we are the run that will get truncated.
- if (ltr) {
- if (ellipsisX <= m_x) {
- // Too far. Just set full truncation, but return -1 and let the ellipsis just be placed at the edge of the box.
+ // Criteria for full truncation:
+ // LTR: the left edge of the ellipsis is to the left of our text run.
+ // RTL: the right edge of the ellipsis is to the right of our text run.
+ bool ltrFullTruncation = flowIsLTR && ellipsisX <= m_x;
+ bool rtlFullTruncation = !flowIsLTR && ellipsisX >= (m_x + m_width);
+ if (ltrFullTruncation || rtlFullTruncation) {
+ // Too far. Just set full truncation, but return -1 and let the ellipsis just be placed at the edge of the box.
+ m_truncation = cFullTruncation;
+ foundBox = true;
+ return -1;
+ }
+
+ bool ltrEllipsisWithinBox = flowIsLTR && (ellipsisX < m_x + m_width);
+ bool rtlEllipsisWithinBox = !flowIsLTR && (ellipsisX > m_x);
+ if (ltrEllipsisWithinBox || rtlEllipsisWithinBox) {
+ foundBox = true;
+
+ // The inline box may have different directionality than it's parent. Since truncation
+ // behavior depends both on both the parent and the inline block's directionality, we
+ // must keep track of these separately.
+ bool ltr = direction() == LTR;
+ if (ltr != flowIsLTR) {
+ // Width in pixels of the visible portion of the box, excluding the ellipsis.
+ int visibleBoxWidth = visibleRightEdge - visibleLeftEdge - ellipsisWidth;
+ ellipsisX = ltr ? m_x + visibleBoxWidth : m_x + m_width - visibleBoxWidth;
+ }
+
+ int offset = offsetForPosition(ellipsisX, false);
+ if (offset == 0) {
+ // No characters should be rendered. Set ourselves to full truncation and place the ellipsis at the min of our start
+ // and the ellipsis edge.
m_truncation = cFullTruncation;
- foundBox = true;
- return -1;
+ return min(ellipsisX, m_x);
}
- if (ellipsisX < m_x + m_width) {
- if (direction() == RTL)
- return -1; // FIXME: Support LTR truncation when the last run is RTL someday.
+ // Set the truncation index on the text run.
+ m_truncation = offset;
- foundBox = true;
+ // If we got here that means that we were only partially truncated and we need to return the pixel offset at which
+ // to place the ellipsis.
+ int widthOfVisibleText = toRenderText(renderer())->width(m_start, offset, textPos(), m_firstLine);
- int offset = offsetForPosition(ellipsisX, false);
- if (offset == 0) {
- // No characters should be rendered. Set ourselves to full truncation and place the ellipsis at the min of our start
- // and the ellipsis edge.
- m_truncation = cFullTruncation;
- return min(ellipsisX, m_x);
- }
-
- // Set the truncation index on the text run. The ellipsis needs to be placed just after the last visible character.
- m_truncation = offset;
- return m_x + static_cast<RenderText*>(m_object)->width(m_start, offset, textPos(), m_firstLine);
- }
- }
- else {
- // FIXME: Support RTL truncation someday, including both modes (when the leftmost run on the line is either RTL or LTR)
+ // The ellipsis needs to be placed just after the last visible character.
+ // Where "after" is defined by the flow directionality, not the inline
+ // box directionality.
+ // e.g. In the case of an LTR inline box truncated in an RTL flow then we can
+ // have a situation such as |Hello| -> |...He|
+ if (flowIsLTR)
+ return m_x + widthOfVisibleText;
+ else
+ return (m_x + m_width) - widthOfVisibleText - ellipsisWidth;
}
return -1;
}
@@ -216,7 +238,7 @@ void updateGraphicsContext(GraphicsContext* context, const Color& fillColor, con
bool InlineTextBox::isLineBreak() const
{
- return object()->isBR() || (object()->style()->preserveNewline() && len() == 1 && (*textObject()->text())[start()] == '\n');
+ 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)
@@ -224,15 +246,15 @@ bool InlineTextBox::nodeAtPoint(const HitTestRequest&, HitTestResult& result, in
if (isLineBreak())
return false;
- IntRect rect(tx + m_x, ty + m_y, m_width, m_height);
+ IntRect rect(tx + m_x, ty + m_y, m_width, height());
if (m_truncation != cFullTruncation && visibleToHitTesting() && rect.contains(x, y)) {
- object()->updateHitTestResult(result, IntPoint(x - tx, y - ty));
+ renderer()->updateHitTestResult(result, IntPoint(x - tx, y - ty));
return true;
}
return false;
}
-static void paintTextWithShadows(GraphicsContext* context, const TextRun& textRun, int startOffset, int endOffset, const IntPoint& textOrigin, int x, int y, int w, int h, ShadowData* shadow, bool stroked)
+static void paintTextWithShadows(GraphicsContext* context, const Font& font, const TextRun& textRun, int startOffset, int endOffset, const IntPoint& textOrigin, int x, int y, int w, int h, ShadowData* shadow, bool stroked)
{
do {
IntSize extraOffset;
@@ -256,12 +278,12 @@ static void paintTextWithShadows(GraphicsContext* context, const TextRun& textRu
}
if (startOffset <= endOffset)
- context->drawText(textRun, textOrigin + extraOffset, startOffset, endOffset);
+ context->drawText(font, textRun, textOrigin + extraOffset, startOffset, endOffset);
else {
if (endOffset > 0)
- context->drawText(textRun, textOrigin + extraOffset, 0, endOffset);
+ context->drawText(font, textRun, textOrigin + extraOffset, 0, endOffset);
if (startOffset < textRun.length())
- context->drawText(textRun, textOrigin + extraOffset, startOffset);
+ context->drawText(font, textRun, textOrigin + extraOffset, startOffset);
}
if (!shadow)
@@ -278,10 +300,10 @@ static void paintTextWithShadows(GraphicsContext* context, const TextRun& textRu
void InlineTextBox::paint(RenderObject::PaintInfo& paintInfo, int tx, int ty)
{
- if (isLineBreak() || !object()->shouldPaintWithinRoot(paintInfo) || object()->style()->visibility() != VISIBLE ||
+ if (isLineBreak() || !renderer()->shouldPaintWithinRoot(paintInfo) || renderer()->style()->visibility() != VISIBLE ||
m_truncation == cFullTruncation || paintInfo.phase == PaintPhaseOutline)
return;
-
+
ASSERT(paintInfo.phase != PaintPhaseSelfOutline && paintInfo.phase != PaintPhaseChildOutlines);
int xPos = tx + m_x - parent()->maxHorizontalVisualOverflow();
@@ -289,7 +311,7 @@ void InlineTextBox::paint(RenderObject::PaintInfo& paintInfo, int tx, int ty)
if (xPos >= paintInfo.rect.right() || xPos + w <= paintInfo.rect.x())
return;
- bool isPrinting = textObject()->document()->printing();
+ bool isPrinting = textRenderer()->document()->printing();
// Determine whether or not we're selected.
bool haveSelection = !isPrinting && paintInfo.phase != PaintPhaseTextClip && selectionState() != RenderObject::SelectionNone;
@@ -297,18 +319,34 @@ void InlineTextBox::paint(RenderObject::PaintInfo& paintInfo, int tx, int ty)
// When only painting the selection, don't bother to paint if there is none.
return;
+ if (m_truncation != cNoTruncation) {
+ TextDirection flowDirection = renderer()->containingBlock()->style()->direction();
+ if (flowDirection != direction()) {
+ // Make the visible fragment of text hug the edge closest to the rest of the run by moving the origin
+ // at which we start drawing text.
+ // e.g. In the case of LTR text truncated in an RTL Context, the correct behavior is:
+ // |Hello|CBA| -> |...He|CBA|
+ // In order to draw the fragment "He" aligned to the right edge of it's box, we need to start drawing
+ // farther to the right.
+ // NOTE: WebKit's behavior differs from that of IE which appears to just overlay the ellipsis on top of the
+ // truncated string i.e. |Hello|CBA| -> |...lo|CBA|
+ int widthOfVisibleText = toRenderText(renderer())->width(m_start, m_truncation, textPos(), m_firstLine);
+ int widthOfHiddenText = m_width - widthOfVisibleText;
+ // FIXME: The hit testing logic also needs to take this translation int account.
+ tx += direction() == LTR ? widthOfHiddenText : -widthOfHiddenText;
+ }
+ }
+
GraphicsContext* context = paintInfo.context;
// Determine whether or not we have composition underlines to draw.
- bool containsComposition = object()->document()->frame()->editor()->compositionNode() == object()->node();
- bool useCustomUnderlines = containsComposition && object()->document()->frame()->editor()->compositionUsesCustomUnderlines();
+ bool containsComposition = renderer()->node() && renderer()->document()->frame()->editor()->compositionNode() == renderer()->node();
+ bool useCustomUnderlines = containsComposition && renderer()->document()->frame()->editor()->compositionUsesCustomUnderlines();
// Set our font.
- RenderStyle* styleToUse = object()->style(m_firstLine);
+ RenderStyle* styleToUse = renderer()->style(m_firstLine);
int d = styleToUse->textDecorationsInEffect();
- const Font* font = &styleToUse->font();
- if (*font != context->font())
- context->setFont(*font);
+ const Font& font = styleToUse->font();
// 1. Paint backgrounds behind text if needed. Examples of such backgrounds include selection
// and composition underlines.
@@ -321,8 +359,8 @@ void InlineTextBox::paint(RenderObject::PaintInfo& paintInfo, int tx, int ty)
if (containsComposition && !useCustomUnderlines)
paintCompositionBackground(context, tx, ty, styleToUse, font,
- object()->document()->frame()->editor()->compositionStart(),
- object()->document()->frame()->editor()->compositionEnd());
+ renderer()->document()->frame()->editor()->compositionStart(),
+ renderer()->document()->frame()->editor()->compositionEnd());
paintDocumentMarkers(context, tx, ty, styleToUse, font, true);
@@ -369,14 +407,14 @@ void InlineTextBox::paint(RenderObject::PaintInfo& paintInfo, int tx, int ty)
ShadowData* selectionShadow = textShadow;
if (haveSelection) {
// Check foreground color first.
- Color foreground = paintInfo.forceBlackText ? Color::black : object()->selectionForegroundColor();
+ Color foreground = paintInfo.forceBlackText ? Color::black : renderer()->selectionForegroundColor();
if (foreground.isValid() && foreground != selectionFillColor) {
if (!paintSelectedTextOnly)
paintSelectedTextSeparately = true;
selectionFillColor = foreground;
}
- if (RenderStyle* pseudoStyle = object()->getCachedPseudoStyle(RenderStyle::SELECTION)) {
+ if (RenderStyle* pseudoStyle = renderer()->getCachedPseudoStyle(SELECTION)) {
ShadowData* shadow = paintInfo.forceBlackText ? 0 : pseudoStyle->textShadow();
if (shadow != selectionShadow) {
if (!paintSelectedTextOnly)
@@ -402,8 +440,9 @@ void InlineTextBox::paint(RenderObject::PaintInfo& paintInfo, int tx, int ty)
}
}
- IntPoint textOrigin(m_x + tx, m_y + ty + m_baseline);
- TextRun textRun(textObject()->text()->characters() + m_start, m_len, textObject()->allowTabs(), textPos(), m_toAdd, direction() == RTL, m_dirOverride || styleToUse->visuallyOrdered());
+ int baseline = renderer()->style(m_firstLine)->font().ascent();
+ IntPoint textOrigin(m_x + tx, m_y + ty + baseline);
+ TextRun textRun(textRenderer()->text()->characters() + m_start, m_len, textRenderer()->allowTabs(), textPos(), m_toAdd, direction() == RTL, m_dirOverride || styleToUse->visuallyOrdered());
int sPos = 0;
int ePos = 0;
@@ -419,9 +458,9 @@ void InlineTextBox::paint(RenderObject::PaintInfo& paintInfo, int tx, int ty)
updateGraphicsContext(context, textFillColor, textStrokeColor, textStrokeWidth);
if (!paintSelectedTextSeparately || ePos <= sPos) {
// FIXME: Truncate right-to-left text correctly.
- paintTextWithShadows(context, textRun, 0, m_truncation == cNoTruncation ? m_len : m_truncation, textOrigin, m_x + tx, m_y + ty, width(), height(), textShadow, textStrokeWidth > 0);
+ paintTextWithShadows(context, font, textRun, 0, m_truncation == cNoTruncation ? m_len : m_truncation, textOrigin, m_x + tx, m_y + ty, width(), height(), textShadow, textStrokeWidth > 0);
} else
- paintTextWithShadows(context, textRun, ePos, sPos, textOrigin, m_x + tx, m_y + ty, width(), height(), textShadow, textStrokeWidth > 0);
+ paintTextWithShadows(context, font, textRun, ePos, sPos, textOrigin, m_x + tx, m_y + ty, width(), height(), textShadow, textStrokeWidth > 0);
if (textStrokeWidth > 0)
context->restore();
@@ -433,7 +472,7 @@ void InlineTextBox::paint(RenderObject::PaintInfo& paintInfo, int tx, int ty)
context->save();
updateGraphicsContext(context, selectionFillColor, selectionStrokeColor, selectionStrokeWidth);
- paintTextWithShadows(context, textRun, sPos, ePos, textOrigin, m_x + tx, m_y + ty, width(), height(), selectionShadow, selectionStrokeWidth > 0);
+ paintTextWithShadows(context, font, textRun, sPos, ePos, textOrigin, m_x + tx, m_y + ty, width(), height(), selectionShadow, selectionStrokeWidth > 0);
if (selectionStrokeWidth > 0)
context->restore();
@@ -449,7 +488,7 @@ void InlineTextBox::paint(RenderObject::PaintInfo& paintInfo, int tx, int ty)
paintDocumentMarkers(context, tx, ty, styleToUse, font, false);
if (useCustomUnderlines) {
- const Vector<CompositionUnderline>& underlines = object()->document()->frame()->editor()->customCompositionUnderlines();
+ const Vector<CompositionUnderline>& underlines = renderer()->document()->frame()->editor()->customCompositionUnderlines();
size_t numUnderlines = underlines.size();
for (size_t index = 0; index < numUnderlines; ++index) {
@@ -478,14 +517,14 @@ void InlineTextBox::paint(RenderObject::PaintInfo& paintInfo, int tx, int ty)
void InlineTextBox::selectionStartEnd(int& sPos, int& ePos)
{
int startPos, endPos;
- if (object()->selectionState() == RenderObject::SelectionInside) {
+ if (renderer()->selectionState() == RenderObject::SelectionInside) {
startPos = 0;
- endPos = textObject()->textLength();
+ endPos = textRenderer()->textLength();
} else {
- textObject()->selectionStartEnd(startPos, endPos);
- if (object()->selectionState() == RenderObject::SelectionStart)
- endPos = textObject()->textLength();
- else if (object()->selectionState() == RenderObject::SelectionEnd)
+ textRenderer()->selectionStartEnd(startPos, endPos);
+ if (renderer()->selectionState() == RenderObject::SelectionStart)
+ endPos = textRenderer()->textLength();
+ else if (renderer()->selectionState() == RenderObject::SelectionEnd)
startPos = 0;
}
@@ -493,7 +532,7 @@ void InlineTextBox::selectionStartEnd(int& sPos, int& ePos)
ePos = min(endPos - m_start, (int)m_len);
}
-void InlineTextBox::paintSelection(GraphicsContext* context, int tx, int ty, RenderStyle* style, const Font*)
+void InlineTextBox::paintSelection(GraphicsContext* context, int tx, int ty, RenderStyle* style, const Font& font)
{
// See if we have a selection to paint at all.
int sPos, ePos;
@@ -502,7 +541,7 @@ void InlineTextBox::paintSelection(GraphicsContext* context, int tx, int ty, Ren
return;
Color textColor = style->color();
- Color c = object()->selectionBackgroundColor();
+ Color c = renderer()->selectionBackgroundColor();
if (!c.isValid() || c.alpha() == 0)
return;
@@ -516,12 +555,13 @@ void InlineTextBox::paintSelection(GraphicsContext* context, int tx, int ty, Ren
int y = selectionTop();
int h = selectionHeight();
context->clip(IntRect(m_x + tx, y + ty, m_width, h));
- context->drawHighlightForText(TextRun(textObject()->text()->characters() + m_start, m_len, textObject()->allowTabs(), textPos(), m_toAdd, direction() == RTL, m_dirOverride || style->visuallyOrdered()),
- IntPoint(m_x + tx, y + ty), h, c, sPos, ePos);
+ context->drawHighlightForText(font, TextRun(textRenderer()->text()->characters() + m_start, m_len, textRenderer()->allowTabs(), textPos(), m_toAdd,
+ direction() == RTL, m_dirOverride || style->visuallyOrdered()),
+ IntPoint(m_x + tx, y + ty), h, c, sPos, ePos);
context->restore();
}
-void InlineTextBox::paintCompositionBackground(GraphicsContext* context, int tx, int ty, RenderStyle* style, const Font*, int startPos, int endPos)
+void InlineTextBox::paintCompositionBackground(GraphicsContext* context, int tx, int ty, RenderStyle* style, const Font& font, int startPos, int endPos)
{
int offset = m_start;
int sPos = max(startPos - offset, 0);
@@ -538,8 +578,9 @@ void InlineTextBox::paintCompositionBackground(GraphicsContext* context, int tx,
int y = selectionTop();
int h = selectionHeight();
- context->drawHighlightForText(TextRun(textObject()->text()->characters() + m_start, m_len, textObject()->allowTabs(), textPos(), m_toAdd, direction() == RTL, m_dirOverride || style->visuallyOrdered()),
- IntPoint(m_x + tx, y + ty), h, c, sPos, ePos);
+ context->drawHighlightForText(font, TextRun(textRenderer()->text()->characters() + m_start, m_len, textRenderer()->allowTabs(), textPos(), m_toAdd,
+ direction() == RTL, m_dirOverride || style->visuallyOrdered()),
+ IntPoint(m_x + tx, y + ty), h, c, sPos, ePos);
context->restore();
}
@@ -547,7 +588,7 @@ void InlineTextBox::paintCompositionBackground(GraphicsContext* context, int tx,
void InlineTextBox::paintCustomHighlight(int tx, int ty, const AtomicString& type)
{
- Frame* frame = object()->document()->frame();
+ Frame* frame = renderer()->document()->frame();
if (!frame)
return;
Page* page = frame->page();
@@ -555,10 +596,10 @@ void InlineTextBox::paintCustomHighlight(int tx, int ty, const AtomicString& typ
return;
RootInlineBox* r = root();
- FloatRect rootRect(tx + r->xPos(), ty + selectionTop(), r->width(), selectionHeight());
- FloatRect textRect(tx + xPos(), rootRect.y(), width(), rootRect.height());
+ FloatRect rootRect(tx + r->x(), ty + selectionTop(), r->width(), selectionHeight());
+ FloatRect textRect(tx + x(), rootRect.y(), width(), rootRect.height());
- page->chrome()->client()->paintCustomHighlight(object()->node(), type, textRect, rootRect, true, false);
+ page->chrome()->client()->paintCustomHighlight(renderer()->node(), type, textRect, rootRect, true, false);
}
#endif
@@ -570,27 +611,33 @@ void InlineTextBox::paintDecoration(GraphicsContext* context, int tx, int ty, in
if (m_truncation == cFullTruncation)
return;
-
- int width = (m_truncation == cNoTruncation) ? m_width
- : static_cast<RenderText*>(m_object)->width(m_start, m_truncation, textPos(), m_firstLine);
+
+ int width = m_width;
+ if (m_truncation != cNoTruncation) {
+ width = toRenderText(renderer())->width(m_start, m_truncation, textPos(), m_firstLine);
+ if (direction() == RTL)
+ tx += (m_width - width);
+ }
// Get the text decoration colors.
Color underline, overline, linethrough;
- object()->getTextDecorationColors(deco, underline, overline, linethrough, true);
+ renderer()->getTextDecorationColors(deco, underline, overline, linethrough, true);
// Use a special function for underlines to get the positioning exactly right.
- bool isPrinting = textObject()->document()->printing();
+ bool isPrinting = textRenderer()->document()->printing();
context->setStrokeThickness(1.0f); // FIXME: We should improve this rule and not always just assume 1.
bool linesAreOpaque = !isPrinting && (!(deco & UNDERLINE) || underline.alpha() == 255) && (!(deco & OVERLINE) || overline.alpha() == 255) && (!(deco & LINE_THROUGH) || linethrough.alpha() == 255);
+ int baseline = renderer()->style(m_firstLine)->font().ascent();
+
bool setClip = false;
int extraOffset = 0;
if (!linesAreOpaque && shadow && shadow->next) {
context->save();
- IntRect clipRect(tx, ty, width, m_baseline + 2);
+ IntRect clipRect(tx, ty, width, baseline + 2);
for (ShadowData* s = shadow; s; s = s->next) {
- IntRect shadowRect(tx, ty, width, m_baseline + 2);
+ IntRect shadowRect(tx, ty, width, baseline + 2);
shadowRect.inflate(s->blur);
shadowRect.move(s->x, s->y);
clipRect.unite(shadowRect);
@@ -598,12 +645,13 @@ void InlineTextBox::paintDecoration(GraphicsContext* context, int tx, int ty, in
}
context->save();
context->clip(clipRect);
- extraOffset += m_baseline + 2;
+ extraOffset += baseline + 2;
ty += extraOffset;
setClip = true;
}
bool setShadow = false;
+
do {
if (shadow) {
if (!shadow->next) {
@@ -618,16 +666,19 @@ void InlineTextBox::paintDecoration(GraphicsContext* context, int tx, int ty, in
if (deco & UNDERLINE) {
context->setStrokeColor(underline);
+ context->setStrokeStyle(SolidStroke);
// Leave one pixel of white between the baseline and the underline.
- context->drawLineForText(IntPoint(tx, ty + m_baseline + 1), width, isPrinting);
+ context->drawLineForText(IntPoint(tx, ty + baseline + 1), width, isPrinting);
}
if (deco & OVERLINE) {
context->setStrokeColor(overline);
+ context->setStrokeStyle(SolidStroke);
context->drawLineForText(IntPoint(tx, ty), width, isPrinting);
}
if (deco & LINE_THROUGH) {
context->setStrokeColor(linethrough);
- context->drawLineForText(IntPoint(tx, ty + 2 * m_baseline / 3), width, isPrinting);
+ context->setStrokeStyle(SolidStroke);
+ context->drawLineForText(IntPoint(tx, ty + 2 * baseline / 3), width, isPrinting);
}
} while (shadow);
@@ -637,10 +688,10 @@ void InlineTextBox::paintDecoration(GraphicsContext* context, int tx, int ty, in
context->clearShadow();
}
-void InlineTextBox::paintSpellingOrGrammarMarker(GraphicsContext* pt, int tx, int ty, DocumentMarker marker, RenderStyle* style, const Font* f, bool grammar)
+void InlineTextBox::paintSpellingOrGrammarMarker(GraphicsContext* pt, int tx, int ty, DocumentMarker marker, RenderStyle* style, const Font& font, bool grammar)
{
// Never print spelling/grammar markers (5327887)
- if (textObject()->document()->printing())
+ if (textRenderer()->document()->printing())
return;
if (m_truncation == cFullTruncation)
@@ -667,17 +718,17 @@ void InlineTextBox::paintSpellingOrGrammarMarker(GraphicsContext* pt, int tx, in
// Calculate start & width
IntPoint startPoint(tx + m_x, ty + selectionTop());
- TextRun run(textObject()->text()->characters() + m_start, m_len, textObject()->allowTabs(), textPos(), m_toAdd, direction() == RTL, m_dirOverride || style->visuallyOrdered());
+ TextRun run(textRenderer()->text()->characters() + m_start, m_len, textRenderer()->allowTabs(), textPos(), m_toAdd, direction() == RTL, m_dirOverride || style->visuallyOrdered());
int h = selectionHeight();
- IntRect markerRect = enclosingIntRect(f->selectionRectForText(run, startPoint, h, startPosition, endPosition));
+ IntRect markerRect = enclosingIntRect(font.selectionRectForText(run, startPoint, h, startPosition, endPosition));
start = markerRect.x() - startPoint.x();
width = markerRect.width();
// Store rendered rects for bad grammar markers, so we can hit-test against it elsewhere in order to
// display a toolTip. We don't do this for misspelling markers.
if (grammar)
- object()->document()->setRenderedRectForMarker(object()->node(), marker, markerRect);
+ renderer()->document()->setRenderedRectForMarker(renderer()->node(), marker, markerRect);
}
// IMPORTANT: The misspelling underline is not considered when calculating the text bounds, so we have to
@@ -687,19 +738,20 @@ void InlineTextBox::paintSpellingOrGrammarMarker(GraphicsContext* pt, int tx, in
// So, we generally place the underline at the bottom of the text, but in larger fonts that's not so good so
// we pin to two pixels under the baseline.
int lineThickness = cMisspellingLineThickness;
- int descent = m_height - m_baseline;
+ int baseline = renderer()->style(m_firstLine)->font().ascent();
+ int descent = height() - baseline;
int underlineOffset;
if (descent <= (2 + lineThickness)) {
- // place the underline at the very bottom of the text in small/medium fonts
- underlineOffset = m_height - lineThickness;
+ // Place the underline at the very bottom of the text in small/medium fonts.
+ underlineOffset = height() - lineThickness;
} else {
- // in larger fonts, tho, place the underline up near the baseline to prevent big gap
- underlineOffset = m_baseline + 2;
+ // In larger fonts, though, place the underline up near the baseline to prevent a big gap.
+ underlineOffset = baseline + 2;
}
pt->drawLineForMisspellingOrBadGrammar(IntPoint(tx + m_x + start, ty + m_y + underlineOffset), width, grammar);
}
-void InlineTextBox::paintTextMatchMarker(GraphicsContext* pt, int tx, int ty, DocumentMarker marker, RenderStyle* style, const Font* f)
+void InlineTextBox::paintTextMatchMarker(GraphicsContext* pt, int tx, int ty, DocumentMarker marker, RenderStyle* style, const Font& font)
{
// Use same y positioning and height as for selection, so that when the selection and this highlight are on
// the same word there are no pieces sticking out.
@@ -708,27 +760,48 @@ void InlineTextBox::paintTextMatchMarker(GraphicsContext* pt, int tx, int ty, Do
int sPos = max(marker.startOffset - m_start, (unsigned)0);
int ePos = min(marker.endOffset - m_start, (unsigned)m_len);
- TextRun run(textObject()->text()->characters() + m_start, m_len, textObject()->allowTabs(), textPos(), m_toAdd, direction() == RTL, m_dirOverride || style->visuallyOrdered());
+ TextRun run(textRenderer()->text()->characters() + m_start, m_len, textRenderer()->allowTabs(), textPos(), m_toAdd, direction() == RTL, m_dirOverride || style->visuallyOrdered());
IntPoint startPoint = IntPoint(m_x + tx, y + ty);
// Always compute and store the rect associated with this marker
- IntRect markerRect = enclosingIntRect(f->selectionRectForText(run, startPoint, h, sPos, ePos));
- object()->document()->setRenderedRectForMarker(object()->node(), marker, markerRect);
+ IntRect markerRect = enclosingIntRect(font.selectionRectForText(run, startPoint, h, sPos, ePos));
+ renderer()->document()->setRenderedRectForMarker(renderer()->node(), marker, markerRect);
// Optionally highlight the text
- if (object()->document()->frame()->markedTextMatchesAreHighlighted()) {
- Color color = theme()->platformTextSearchHighlightColor();
+ if (renderer()->document()->frame()->markedTextMatchesAreHighlighted()) {
+ Color color = marker.activeMatch ?
+ renderer()->theme()->platformActiveTextSearchHighlightColor() :
+ renderer()->theme()->platformInactiveTextSearchHighlightColor();
pt->save();
updateGraphicsContext(pt, color, color, 0); // Don't draw text at all!
pt->clip(IntRect(tx + m_x, ty + y, m_width, h));
- pt->drawHighlightForText(run, startPoint, h, color, sPos, ePos);
+ pt->drawHighlightForText(font, run, startPoint, h, color, sPos, ePos);
pt->restore();
}
}
-void InlineTextBox::paintDocumentMarkers(GraphicsContext* pt, int tx, int ty, RenderStyle* style, const Font* f, bool background)
+void InlineTextBox::computeRectForReplacementMarker(int tx, int ty, DocumentMarker marker, RenderStyle* style, const Font& font)
+{
+ // Replacement markers are not actually drawn, but their rects need to be computed for hit testing.
+ int y = selectionTop();
+ int h = selectionHeight();
+
+ int sPos = max(marker.startOffset - m_start, (unsigned)0);
+ int ePos = min(marker.endOffset - m_start, (unsigned)m_len);
+ TextRun run(textRenderer()->text()->characters() + m_start, m_len, textRenderer()->allowTabs(), textPos(), m_toAdd, direction() == RTL, m_dirOverride || style->visuallyOrdered());
+ IntPoint startPoint = IntPoint(m_x + tx, y + ty);
+
+ // Compute and store the rect associated with this marker.
+ IntRect markerRect = enclosingIntRect(font.selectionRectForText(run, startPoint, h, sPos, ePos));
+ renderer()->document()->setRenderedRectForMarker(renderer()->node(), marker, markerRect);
+}
+
+void InlineTextBox::paintDocumentMarkers(GraphicsContext* pt, int tx, int ty, RenderStyle* style, const Font& font, bool background)
{
- Vector<DocumentMarker> markers = object()->document()->markersForNode(object()->node());
+ if (!renderer()->node())
+ return;
+
+ Vector<DocumentMarker> markers = renderer()->document()->markersForNode(renderer()->node());
Vector<DocumentMarker>::iterator markerIt = markers.begin();
// Give any document markers that touch this run a chance to draw before the text has been drawn.
@@ -740,6 +813,7 @@ void InlineTextBox::paintDocumentMarkers(GraphicsContext* pt, int tx, int ty, Re
switch (marker.type) {
case DocumentMarker::Grammar:
case DocumentMarker::Spelling:
+ case DocumentMarker::Replacement:
if (background)
continue;
break;
@@ -765,13 +839,16 @@ void InlineTextBox::paintDocumentMarkers(GraphicsContext* pt, int tx, int ty, Re
// marker intersects this run. Paint it.
switch (marker.type) {
case DocumentMarker::Spelling:
- paintSpellingOrGrammarMarker(pt, tx, ty, marker, style, f, false);
+ paintSpellingOrGrammarMarker(pt, tx, ty, marker, style, font, false);
break;
case DocumentMarker::Grammar:
- paintSpellingOrGrammarMarker(pt, tx, ty, marker, style, f, true);
+ paintSpellingOrGrammarMarker(pt, tx, ty, marker, style, font, true);
break;
case DocumentMarker::TextMatch:
- paintTextMatchMarker(pt, tx, ty, marker, style, f);
+ paintTextMatchMarker(pt, tx, ty, marker, style, font);
+ break;
+ case DocumentMarker::Replacement:
+ computeRectForReplacementMarker(tx, ty, marker, style, font);
break;
default:
ASSERT_NOT_REACHED();
@@ -797,7 +874,7 @@ void InlineTextBox::paintCompositionUnderline(GraphicsContext* ctx, int tx, int
if (paintStart <= underline.startOffset) {
paintStart = underline.startOffset;
useWholeWidth = false;
- start = static_cast<RenderText*>(m_object)->width(m_start, paintStart - m_start, textPos(), m_firstLine);
+ start = toRenderText(renderer())->width(m_start, paintStart - m_start, textPos(), m_firstLine);
}
if (paintEnd != underline.endOffset) { // end points at the last char, not past it
paintEnd = min(paintEnd, (unsigned)underline.endOffset);
@@ -808,14 +885,15 @@ void InlineTextBox::paintCompositionUnderline(GraphicsContext* ctx, int tx, int
useWholeWidth = false;
}
if (!useWholeWidth) {
- width = static_cast<RenderText*>(m_object)->width(paintStart, paintEnd - paintStart, textPos() + start, m_firstLine);
+ width = toRenderText(renderer())->width(paintStart, paintEnd - paintStart, textPos() + start, m_firstLine);
}
// Thick marked text underlines are 2px thick as long as there is room for the 2px line under the baseline.
// All other marked text underlines are 1px thick.
// If there's not enough space the underline will touch or overlap characters.
int lineThickness = 1;
- if (underline.thick && m_height - m_baseline >= 2)
+ int baseline = renderer()->style(m_firstLine)->font().ascent();
+ if (underline.thick && height() - baseline >= 2)
lineThickness = 2;
// We need to have some space between underlines of subsequent clauses, because some input methods do not use different underline styles for those.
@@ -825,7 +903,7 @@ void InlineTextBox::paintCompositionUnderline(GraphicsContext* ctx, int tx, int
ctx->setStrokeColor(underline.color);
ctx->setStrokeThickness(lineThickness);
- ctx->drawLineForText(IntPoint(tx + start, ty + m_height - lineThickness), width, textObject()->document()->printing());
+ ctx->drawLineForText(IntPoint(tx + start, ty + height() - lineThickness), width, textRenderer()->document()->printing());
}
int InlineTextBox::caretMinOffset() const
@@ -845,12 +923,12 @@ unsigned InlineTextBox::caretMaxRenderedOffset() const
int InlineTextBox::textPos() const
{
- if (xPos() == 0)
+ if (x() == 0)
return 0;
- RenderBlock *blockElement = object()->containingBlock();
- return direction() == RTL ? xPos() - blockElement->borderRight() - blockElement->paddingRight()
- : xPos() - blockElement->borderLeft() - blockElement->paddingLeft();
+ RenderBlock *blockElement = renderer()->containingBlock();
+ return direction() == RTL ? x() - blockElement->borderRight() - blockElement->paddingRight()
+ : x() - blockElement->borderLeft() - blockElement->paddingLeft();
}
int InlineTextBox::offsetForPosition(int _x, bool includePartialGlyphs) const
@@ -858,10 +936,10 @@ int InlineTextBox::offsetForPosition(int _x, bool includePartialGlyphs) const
if (isLineBreak())
return 0;
- RenderText* text = static_cast<RenderText*>(m_object);
+ RenderText* text = toRenderText(renderer());
RenderStyle *style = text->style(m_firstLine);
const Font* f = &style->font();
- return f->offsetForPosition(TextRun(textObject()->text()->characters() + m_start, m_len, textObject()->allowTabs(), textPos(), m_toAdd, direction() == RTL, m_dirOverride || style->visuallyOrdered()),
+ return f->offsetForPosition(TextRun(textRenderer()->text()->characters() + m_start, m_len, textRenderer()->allowTabs(), textPos(), m_toAdd, direction() == RTL, m_dirOverride || style->visuallyOrdered()),
_x - m_x, includePartialGlyphs);
}
@@ -873,12 +951,12 @@ int InlineTextBox::positionForOffset(int offset) const
if (isLineBreak())
return m_x;
- RenderText* text = static_cast<RenderText*>(m_object);
+ RenderText* text = toRenderText(renderer());
const Font& f = text->style(m_firstLine)->font();
int from = direction() == RTL ? offset - m_start : 0;
int to = direction() == RTL ? m_len : offset - m_start;
// FIXME: Do we need to add rightBearing here?
- return enclosingIntRect(f.selectionRectForText(TextRun(text->text()->characters() + m_start, m_len, textObject()->allowTabs(), textPos(), m_toAdd, direction() == RTL, m_dirOverride),
+ return enclosingIntRect(f.selectionRectForText(TextRun(text->text()->characters() + m_start, m_len, textRenderer()->allowTabs(), textPos(), m_toAdd, direction() == RTL, m_dirOverride),
IntPoint(m_x, 0), 0, from, to)).right();
}
@@ -906,4 +984,30 @@ bool InlineTextBox::containsCaretOffset(int offset) const
return true;
}
+typedef HashMap<InlineTextBox*, Vector<const SimpleFontData*> > FallbackFontsMap;
+static FallbackFontsMap* gFallbackFontsMap;
+
+void InlineTextBox::setFallbackFonts(const HashSet<const SimpleFontData*>& fallbackFonts)
+{
+ if (!gFallbackFontsMap)
+ gFallbackFontsMap = new FallbackFontsMap;
+
+ FallbackFontsMap::iterator it = gFallbackFontsMap->set(this, Vector<const SimpleFontData*>()).first;
+ ASSERT(it->second.isEmpty());
+ copyToVector(fallbackFonts, it->second);
+}
+
+void InlineTextBox::takeFallbackFonts(Vector<const SimpleFontData*>& fallbackFonts)
+{
+ if (!gFallbackFontsMap)
+ return;
+
+ FallbackFontsMap::iterator it = gFallbackFontsMap->find(this);
+ if (it == gFallbackFontsMap->end())
+ return;
+
+ fallbackFonts.swap(it->second);
+ gFallbackFontsMap->remove(it);
+}
+
} // namespace WebCore
diff --git a/src/3rdparty/webkit/WebCore/rendering/InlineTextBox.h b/src/3rdparty/webkit/WebCore/rendering/InlineTextBox.h
index d8a250b..3bbb453 100644
--- a/src/3rdparty/webkit/WebCore/rendering/InlineTextBox.h
+++ b/src/3rdparty/webkit/WebCore/rendering/InlineTextBox.h
@@ -1,9 +1,7 @@
/*
- * This file is part of the DOM implementation for KDE.
- *
* (C) 1999 Lars Knoll (knoll@kde.org)
* (C) 2000 Dirk Mueller (mueller@kde.org)
- * Copyright (C) 2004, 2005, 2006 Apple Computer, Inc.
+ * Copyright (C) 2004, 2005, 2006, 2009 Apple Inc. 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
@@ -25,22 +23,16 @@
#ifndef InlineTextBox_h
#define InlineTextBox_h
-#include "DocumentMarker.h"
#include "InlineRunBox.h"
-#include "RenderText.h"
+#include "RenderText.h" // so textRenderer() can be inline
namespace WebCore {
+struct CompositionUnderline;
+
const unsigned short cNoTruncation = USHRT_MAX;
const unsigned short cFullTruncation = USHRT_MAX - 1;
-class String;
-class StringImpl;
-class HitTestResult;
-class Position;
-
-struct CompositionUnderline;
-
// Helper functions shared by InlineTextBox / SVGRootInlineBox
void updateGraphicsContext(GraphicsContext* context, const Color& fillColor, const Color& strokeColor, float strokeThickness);
Color correctedTextColor(Color textColor, Color backgroundColor);
@@ -67,46 +59,61 @@ public:
void offsetRun(int d) { m_start += d; }
+ void setFallbackFonts(const HashSet<const SimpleFontData*>&);
+ void takeFallbackFonts(Vector<const SimpleFontData*>&);
+
+private:
virtual int selectionTop();
virtual int selectionHeight();
+public:
virtual IntRect selectionRect(int absx, int absy, int startPos, int endPos);
bool isSelected(int startPos, int endPos) const;
void selectionStartEnd(int& sPos, int& ePos);
+private:
virtual void paint(RenderObject::PaintInfo&, int tx, int ty);
virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, int x, int y, int tx, int ty);
- RenderText* textObject() const;
+public:
+ RenderText* textRenderer() const;
+private:
virtual void deleteLine(RenderArena*);
virtual void extractLine();
virtual void attachLine();
+public:
virtual RenderObject::SelectionState selectionState();
+private:
virtual void clearTruncation() { m_truncation = cNoTruncation; }
- virtual int placeEllipsisBox(bool ltr, int blockEdge, int ellipsisWidth, bool& foundBox);
+ virtual int placeEllipsisBox(bool flowIsLTR, int visibleLeftEdge, int visibleRightEdge, int ellipsisWidth, bool& foundBox);
+public:
virtual bool isLineBreak() const;
void setSpaceAdd(int add) { m_width -= m_toAdd; m_toAdd = add; m_width += m_toAdd; }
- int spaceAdd() { return m_toAdd; }
+private:
virtual bool isInlineTextBox() { return true; }
- virtual bool isText() const { return m_treatAsText; }
- void setIsText(bool b) { m_treatAsText = b; }
+public:
virtual int caretMinOffset() const;
virtual int caretMaxOffset() const;
+
+private:
virtual unsigned caretMaxRenderedOffset() const;
int textPos() const;
+
+public:
virtual int offsetForPosition(int x, bool includePartialGlyphs = true) const;
virtual int positionForOffset(int offset) const;
bool containsCaretOffset(int offset) const; // false for offset after line break
+private:
int m_start;
unsigned short m_len;
@@ -114,24 +121,24 @@ public:
// denote no truncation (the whole run paints) and full truncation (nothing paints at all).
protected:
- void paintCompositionBackground(GraphicsContext*, int tx, int ty, RenderStyle*, const Font*, int startPos, int endPos);
- void paintDocumentMarkers(GraphicsContext*, int tx, int ty, RenderStyle*, const Font*, bool background);
+ void paintCompositionBackground(GraphicsContext*, int tx, int ty, RenderStyle*, const Font&, int startPos, int endPos);
+ void paintDocumentMarkers(GraphicsContext*, int tx, int ty, RenderStyle*, const Font&, bool background);
void paintCompositionUnderline(GraphicsContext*, int tx, int ty, const CompositionUnderline&);
#if PLATFORM(MAC)
void paintCustomHighlight(int tx, int ty, const AtomicString& type);
#endif
private:
- void paintDecoration(GraphicsContext*, int tx, int ty, int decoration, ShadowData* shadow);
- void paintSelection(GraphicsContext*, int tx, int ty, RenderStyle*, const Font*);
- void paintSpellingOrGrammarMarker(GraphicsContext*, int tx, int ty, DocumentMarker, RenderStyle*, const Font*, bool grammar);
- void paintTextMatchMarker(GraphicsContext*, int tx, int ty, DocumentMarker, RenderStyle*, const Font*);
- friend class RenderText;
+ void paintDecoration(GraphicsContext*, int tx, int ty, int decoration, ShadowData*);
+ void paintSelection(GraphicsContext*, int tx, int ty, RenderStyle*, const Font&);
+ void paintSpellingOrGrammarMarker(GraphicsContext*, int tx, int ty, DocumentMarker, RenderStyle*, const Font&, bool grammar);
+ void paintTextMatchMarker(GraphicsContext*, int tx, int ty, DocumentMarker, RenderStyle*, const Font&);
+ void computeRectForReplacementMarker(int tx, int ty, DocumentMarker, RenderStyle*, const Font&);
};
-inline RenderText* InlineTextBox::textObject() const
+inline RenderText* InlineTextBox::textRenderer() const
{
- return static_cast<RenderText*>(m_object);
+ return toRenderText(renderer());
}
} // namespace WebCore
diff --git a/src/3rdparty/webkit/WebCore/rendering/LayoutState.cpp b/src/3rdparty/webkit/WebCore/rendering/LayoutState.cpp
index 20d0b99..883f74d 100644
--- a/src/3rdparty/webkit/WebCore/rendering/LayoutState.cpp
+++ b/src/3rdparty/webkit/WebCore/rendering/LayoutState.cpp
@@ -27,16 +27,19 @@
#include "LayoutState.h"
#include "RenderArena.h"
+#include "RenderInline.h"
#include "RenderLayer.h"
#include "RenderView.h"
namespace WebCore {
LayoutState::LayoutState(LayoutState* prev, RenderBox* renderer, const IntSize& offset)
+ : m_next(prev)
+#ifndef NDEBUG
+ , m_renderer(renderer)
+#endif
{
- ASSERT(prev);
-
- m_next = prev;
+ ASSERT(m_next);
bool fixed = renderer->isPositioned() && renderer->style()->position() == FixedPosition;
if (fixed) {
@@ -50,8 +53,10 @@ LayoutState::LayoutState(LayoutState* prev, RenderBox* renderer, const IntSize&
if (renderer->hasLayer())
m_offset += renderer->layer()->relativePositionOffset();
} else if (renderer->isPositioned() && !fixed) {
- if (RenderObject* container = renderer->container())
- m_offset += renderer->offsetForPositionedInContainer(container);
+ if (RenderObject* container = renderer->container()) {
+ if (container->isRelPositioned() && container->isRenderInline())
+ m_offset += toRenderInline(container)->relativePositionedInlineOffset(renderer);
+ }
}
m_clipped = !fixed && prev->m_clipped;
@@ -72,16 +77,22 @@ LayoutState::LayoutState(LayoutState* prev, RenderBox* renderer, const IntSize&
layer->subtractScrolledContentOffset(x, y);
m_offset = IntSize(x, y);
}
+
+ m_layoutDelta = m_next->m_layoutDelta;
+
// FIXME: <http://bugs.webkit.org/show_bug.cgi?id=13443> Apply control clip if present.
}
LayoutState::LayoutState(RenderObject* root)
: m_clipped(false)
+ , m_next(0)
+#ifndef NDEBUG
+ , m_renderer(root)
+#endif
{
RenderObject* container = root->container();
- FloatPoint absContentPoint = container->localToAbsoluteForContent(FloatPoint(), false, true);
+ FloatPoint absContentPoint = container->localToAbsolute(FloatPoint(), false, true);
m_offset = IntSize(absContentPoint.x(), absContentPoint.y());
- m_next = 0;
}
#ifndef NDEBUG
diff --git a/src/3rdparty/webkit/WebCore/rendering/LayoutState.h b/src/3rdparty/webkit/WebCore/rendering/LayoutState.h
index 551c74a..afa2952 100644
--- a/src/3rdparty/webkit/WebCore/rendering/LayoutState.h
+++ b/src/3rdparty/webkit/WebCore/rendering/LayoutState.h
@@ -41,6 +41,9 @@ public:
LayoutState()
: m_clipped(false)
, m_next(0)
+#ifndef NDEBUG
+ , m_renderer(0)
+#endif
{
}
@@ -62,8 +65,14 @@ private:
public:
bool m_clipped;
IntRect m_clipRect;
- IntSize m_offset;
+ IntSize m_offset; // x/y offset from container.
+ IntSize m_layoutDelta; // Transient offset from the final position of the object
+ // used to ensure that repaints happen in the correct place.
+ // This is a total delta accumulated from the root.
LayoutState* m_next;
+#ifndef NDEBUG
+ RenderObject* m_renderer;
+#endif
};
} // namespace WebCore
diff --git a/src/3rdparty/webkit/WebCore/rendering/ListMarkerBox.cpp b/src/3rdparty/webkit/WebCore/rendering/ListMarkerBox.cpp
deleted file mode 100644
index 0455eae..0000000
--- a/src/3rdparty/webkit/WebCore/rendering/ListMarkerBox.cpp
+++ /dev/null
@@ -1,45 +0,0 @@
-/**
- * This file is part of the DOM implementation for KDE.
- *
- * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
- * (C) 1999 Antti Koivisto (koivisto@kde.org)
- * Copyright (C) 2003, 2004, 2005, 2006 Apple Computer, Inc.
- * Copyright (C) 2006 Andrew Wellington (proton@wiretapped.net)
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-
-#include "config.h"
-#include "ListMarkerBox.h"
-
-#include "InlineFlowBox.h"
-#include "RenderArena.h"
-#include "RenderListMarker.h"
-
-namespace WebCore {
-
-ListMarkerBox::ListMarkerBox(RenderObject* obj)
- : InlineBox(obj)
-{
-}
-
-bool ListMarkerBox::isText() const
-{
- return static_cast<RenderListMarker*>(object())->isText();
-}
-
-} // namespace WebCore
diff --git a/src/3rdparty/webkit/WebCore/rendering/ListMarkerBox.h b/src/3rdparty/webkit/WebCore/rendering/ListMarkerBox.h
deleted file mode 100644
index 47ae256..0000000
--- a/src/3rdparty/webkit/WebCore/rendering/ListMarkerBox.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * This file is part of the DOM implementation for KDE.
- *
- * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
- * (C) 1999 Antti Koivisto (koivisto@kde.org)
- * Copyright (C) 2003, 2004, 2005, 2006 Apple Computer, Inc.
- *
- * 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 ListMarkerBox_h
-#define ListMarkerBox_h
-
-#include "InlineBox.h"
-
-namespace WebCore {
-
-class ListMarkerBox : public InlineBox {
-public:
- ListMarkerBox(RenderObject*);
-
- virtual bool isText() const;
-};
-
-} // namespace WebCore
-
-#endif // ListMarkerBox_h
diff --git a/src/3rdparty/webkit/WebCore/rendering/MediaControlElements.cpp b/src/3rdparty/webkit/WebCore/rendering/MediaControlElements.cpp
index 48ea3ab..fc2790c 100644
--- a/src/3rdparty/webkit/WebCore/rendering/MediaControlElements.cpp
+++ b/src/3rdparty/webkit/WebCore/rendering/MediaControlElements.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2008, 2009 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -32,12 +32,12 @@
#include "MediaControlElements.h"
-#include "Event.h"
#include "EventNames.h"
-#include "EventHandler.h"
#include "FloatConversion.h"
#include "Frame.h"
#include "HTMLNames.h"
+#include "MouseEvent.h"
+#include "RenderMedia.h"
#include "RenderSlider.h"
#include "RenderTheme.h"
@@ -59,21 +59,28 @@ MediaControlShadowRootElement::MediaControlShadowRootElement(Document* doc, HTML
rootStyle->setDisplay(BLOCK);
rootStyle->setPosition(RelativePosition);
RenderMediaControlShadowRoot* renderer = new (mediaElement->renderer()->renderArena()) RenderMediaControlShadowRoot(this);
- renderer->setParent(mediaElement->renderer());
renderer->setStyle(rootStyle.release());
setRenderer(renderer);
setAttached();
setInDocument(true);
}
+void MediaControlShadowRootElement::updateStyle()
+{
+ if (renderer()) {
+ RenderStyle* timelineContainerStyle = m_mediaElement->renderer()->getCachedPseudoStyle(MEDIA_CONTROLS_TIMELINE_CONTAINER);
+ renderer()->setStyle(timelineContainerStyle);
+ }
+}
+
// ----------------------------
-MediaControlInputElement::MediaControlInputElement(Document* doc, RenderStyle::PseudoId pseudo, const String& type, HTMLMediaElement* mediaElement)
- : HTMLInputElement(inputTag, doc)
+MediaTextDisplayElement::MediaTextDisplayElement(Document* doc, PseudoId pseudo, HTMLMediaElement* mediaElement)
+ : HTMLDivElement(divTag, doc)
, m_mediaElement(mediaElement)
+ , m_pseudoStyleId(pseudo)
{
- setInputType(type);
- RenderStyle* style = m_mediaElement->renderer()->getCachedPseudoStyle(pseudo);
+ RenderStyle* style = m_mediaElement->renderer()->getCachedPseudoStyle(m_pseudoStyleId);
RenderObject* renderer = createRenderer(m_mediaElement->renderer()->renderArena(), style);
if (renderer) {
setRenderer(renderer);
@@ -83,30 +90,111 @@ MediaControlInputElement::MediaControlInputElement(Document* doc, RenderStyle::P
setInDocument(true);
}
+void MediaTextDisplayElement::attachToParent(Element* parent)
+{
+ parent->addChild(this);
+ if (renderer() && parent->renderer())
+ parent->renderer()->addChild(renderer());
+}
+
+void MediaTextDisplayElement::update()
+{
+ if (renderer())
+ renderer()->updateFromElement();
+ updateStyle();
+}
+
+void MediaTextDisplayElement::updateStyle()
+{
+ if (renderer() && m_mediaElement->renderer()) {
+ RenderStyle* style = m_mediaElement->renderer()->getCachedPseudoStyle(m_pseudoStyleId);
+ renderer()->setStyle(style);
+ }
+}
+
+MediaTimeDisplayElement::MediaTimeDisplayElement(Document* doc, HTMLMediaElement* element, bool currentTime)
+ : MediaTextDisplayElement(doc, currentTime ? MEDIA_CONTROLS_CURRENT_TIME_DISPLAY : MEDIA_CONTROLS_TIME_REMAINING_DISPLAY, element)
+{
+}
+
+// ----------------------------
+
+MediaControlInputElement::MediaControlInputElement(Document* doc, PseudoId pseudo, const String& type, HTMLMediaElement* mediaElement, MediaControlElementType displayType)
+ : HTMLInputElement(inputTag, doc)
+ , m_mediaElement(mediaElement)
+ , m_pseudoStyleId(pseudo)
+ , m_displayType(displayType)
+{
+ setInputType(type);
+ updateStyle();
+ setInDocument(true);
+}
+
void MediaControlInputElement::attachToParent(Element* parent)
{
parent->addChild(this);
- parent->renderer()->addChild(renderer());
+ if (renderer() && parent->renderer())
+ parent->renderer()->addChild(renderer());
}
void MediaControlInputElement::update()
{
+ updateDisplayType();
if (renderer())
renderer()->updateFromElement();
+ updateStyle();
+}
+
+void MediaControlInputElement::updateStyle()
+{
+ if (!m_mediaElement || !m_mediaElement->renderer())
+ return;
+
+ RenderStyle* style = m_mediaElement->renderer()->getCachedPseudoStyle(m_pseudoStyleId);
+
+ bool needsRenderer = rendererIsNeeded(style);
+ if (renderer() && !needsRenderer)
+ detach();
+ else if (!renderer() && needsRenderer) {
+ RenderObject* renderer = createRenderer(m_mediaElement->renderer()->renderArena(), style);
+ if (!renderer)
+ return;
+ renderer->setStyle(style);
+ setRenderer(renderer);
+ setAttached();
+ if (parent() && parent()->renderer()) {
+ // Find next sibling with a renderer to determine where to insert.
+ Node* sibling = nextSibling();
+ while (sibling && !sibling->renderer())
+ sibling = sibling->nextSibling();
+ parent()->renderer()->addChild(renderer, sibling ? sibling->renderer() : 0);
+ }
+ } else if (renderer())
+ renderer()->setStyle(style);
}
bool MediaControlInputElement::hitTest(const IntPoint& absPoint)
{
if (renderer() && renderer()->style()->hasAppearance())
- return theme()->hitTestMediaControlPart(renderer(), absPoint);
+ return renderer()->theme()->hitTestMediaControlPart(renderer(), absPoint);
return false;
}
+void MediaControlInputElement::setDisplayType(MediaControlElementType displayType)
+{
+ if (displayType == m_displayType)
+ return;
+
+ m_displayType = displayType;
+ if (RenderObject* o = renderer())
+ o->repaint();
+}
+
// ----------------------------
MediaControlMuteButtonElement::MediaControlMuteButtonElement(Document* doc, HTMLMediaElement* element)
- : MediaControlInputElement(doc, RenderStyle::MEDIA_CONTROLS_MUTE_BUTTON, "button", element)
+ : MediaControlInputElement(doc, MEDIA_CONTROLS_MUTE_BUTTON, "button", element, element->muted() ? MediaUnMuteButton : MediaMuteButton)
{
}
@@ -119,30 +207,37 @@ void MediaControlMuteButtonElement::defaultEventHandler(Event* event)
HTMLInputElement::defaultEventHandler(event);
}
+void MediaControlMuteButtonElement::updateDisplayType()
+{
+ setDisplayType(m_mediaElement->muted() ? MediaUnMuteButton : MediaMuteButton);
+}
+
// ----------------------------
MediaControlPlayButtonElement::MediaControlPlayButtonElement(Document* doc, HTMLMediaElement* element)
- : MediaControlInputElement(doc, RenderStyle::MEDIA_CONTROLS_PLAY_BUTTON, "button", element)
+ : MediaControlInputElement(doc, MEDIA_CONTROLS_PLAY_BUTTON, "button", element, element->canPlay() ? MediaPlayButton : MediaPauseButton)
{
}
void MediaControlPlayButtonElement::defaultEventHandler(Event* event)
{
if (event->type() == eventNames().clickEvent) {
- ExceptionCode ec;
- if (m_mediaElement->canPlay())
- m_mediaElement->play(ec);
- else
- m_mediaElement->pause(ec);
+ m_mediaElement->togglePlayState();
event->setDefaultHandled();
}
HTMLInputElement::defaultEventHandler(event);
}
+void MediaControlPlayButtonElement::updateDisplayType()
+{
+ setDisplayType(m_mediaElement->canPlay() ? MediaPlayButton : MediaPauseButton);
+}
+
// ----------------------------
MediaControlSeekButtonElement::MediaControlSeekButtonElement(Document* doc, HTMLMediaElement* element, bool forward)
- : MediaControlInputElement(doc, forward ? RenderStyle::MEDIA_CONTROLS_SEEK_FORWARD_BUTTON : RenderStyle::MEDIA_CONTROLS_SEEK_BACK_BUTTON, "button", element)
+ : MediaControlInputElement(doc, forward ? MEDIA_CONTROLS_SEEK_FORWARD_BUTTON : MEDIA_CONTROLS_SEEK_BACK_BUTTON,
+ "button", element, forward ? MediaSeekForwardButton : MediaSeekBackButton)
, m_forward(forward)
, m_seeking(false)
, m_capturing(false)
@@ -157,8 +252,7 @@ void MediaControlSeekButtonElement::defaultEventHandler(Event* event)
m_capturing = true;
frame->eventHandler()->setCapturingMouseEventsNode(this);
}
- ExceptionCode ec;
- m_mediaElement->pause(ec);
+ m_mediaElement->pause();
m_seekTimer.startRepeating(cSeekRepeatDelay);
event->setDefaultHandled();
} else if (event->type() == eventNames().mouseupEvent) {
@@ -191,37 +285,34 @@ void MediaControlSeekButtonElement::seekTimerFired(Timer<MediaControlSeekButtonE
// ----------------------------
-MediaControlTimelineElement::MediaControlTimelineElement(Document* doc, HTMLMediaElement* element)
- : MediaControlInputElement(doc, RenderStyle::MEDIA_CONTROLS_TIMELINE, "range", element)
+MediaControlTimelineElement::MediaControlTimelineElement(Document* document, HTMLMediaElement* element)
+ : MediaControlInputElement(document, MEDIA_CONTROLS_TIMELINE, "range", element, MediaTimelineContainer)
{
- setAttribute(precisionAttr, "float");
}
void MediaControlTimelineElement::defaultEventHandler(Event* event)
{
- RenderSlider* slider = static_cast<RenderSlider*>(renderer());
- bool oldInDragMode = slider && slider->inDragMode();
- float oldTime = narrowPrecisionToFloat(value().toDouble());
- bool oldEnded = m_mediaElement->ended();
+ if (event->type() == eventNames().mousedownEvent)
+ m_mediaElement->beginScrubbing();
HTMLInputElement::defaultEventHandler(event);
+ if (event->type() == eventNames().mouseoverEvent || event->type() == eventNames().mouseoutEvent || event->type() == eventNames().mousemoveEvent ) {
+ return;
+ }
+
float time = narrowPrecisionToFloat(value().toDouble());
- if (oldTime != time || event->type() == eventNames().inputEvent) {
+ if (time != m_mediaElement->currentTime()) {
ExceptionCode ec;
m_mediaElement->setCurrentTime(time, ec);
}
- // Media element stays in non-paused state when it reaches end. If the slider is now dragged
- // to some other position the playback resumes which does not match usual media player UIs.
- // Get the expected behavior by pausing explicitly in this case.
- if (oldEnded && !m_mediaElement->ended() && !m_mediaElement->paused()) {
- ExceptionCode ec;
- m_mediaElement->pause(ec);
- }
- // Pause playback during drag, but do it without using DOM API which would generate events
- bool inDragMode = slider && slider->inDragMode();
- if (inDragMode != oldInDragMode)
- m_mediaElement->setPausedInternal(inDragMode);
+
+ RenderSlider* slider = static_cast<RenderSlider*>(renderer());
+ if (slider && slider->inDragMode())
+ static_cast<RenderMedia*>(m_mediaElement->renderer())->updateTimeDisplay();
+
+ if (event->type() == eventNames().mouseupEvent)
+ m_mediaElement->endScrubbing();
}
void MediaControlTimelineElement::update(bool updateDuration)
@@ -236,7 +327,7 @@ void MediaControlTimelineElement::update(bool updateDuration)
// ----------------------------
MediaControlFullscreenButtonElement::MediaControlFullscreenButtonElement(Document* doc, HTMLMediaElement* element)
- : MediaControlInputElement(doc, RenderStyle::MEDIA_CONTROLS_FULLSCREEN_BUTTON, "button", element)
+ : MediaControlInputElement(doc, MEDIA_CONTROLS_FULLSCREEN_BUTTON, "button", element, MediaFullscreenButton)
{
}
@@ -248,6 +339,12 @@ void MediaControlFullscreenButtonElement::defaultEventHandler(Event* event)
HTMLInputElement::defaultEventHandler(event);
}
+bool MediaControlFullscreenButtonElement::rendererIsNeeded(RenderStyle* style)
+{
+ return m_mediaElement->supportsFullscreen() && MediaControlInputElement::rendererIsNeeded(style);
+}
+
+
// ----------------------------
} //namespace WebCore
diff --git a/src/3rdparty/webkit/WebCore/rendering/MediaControlElements.h b/src/3rdparty/webkit/WebCore/rendering/MediaControlElements.h
index 4741534..eefb2ce 100644
--- a/src/3rdparty/webkit/WebCore/rendering/MediaControlElements.h
+++ b/src/3rdparty/webkit/WebCore/rendering/MediaControlElements.h
@@ -43,7 +43,7 @@ namespace WebCore {
class Event;
class Frame;
-enum MediaControlElements {
+enum MediaControlElementType {
MediaFullscreenButton, MediaMuteButton, MediaPlayButton,
MediaSeekBackButton, MediaSeekForwardButton, MediaSlider, MediaSliderThumb,
MediaUnMuteButton, MediaPauseButton, MediaTimelineContainer, MediaCurrentTimeDisplay,
@@ -56,21 +56,52 @@ public:
virtual bool isShadowNode() const { return true; }
virtual Node* shadowParentNode() { return m_mediaElement; }
+
+ void updateStyle();
private:
HTMLMediaElement* m_mediaElement;
};
+ // ----------------------------
+
+class MediaTextDisplayElement : public HTMLDivElement
+{
+public:
+ MediaTextDisplayElement(Document*, PseudoId, HTMLMediaElement*);
+ void attachToParent(Element*);
+ void update();
+ void updateStyle();
+protected:
+ HTMLMediaElement* m_mediaElement;
+ PseudoId m_pseudoStyleId;
+};
+
+// ----------------------------
+
+class MediaTimeDisplayElement : public MediaTextDisplayElement {
+public:
+ MediaTimeDisplayElement(Document*, HTMLMediaElement*, bool currentTime);
+};
+
// ----------------------------
class MediaControlInputElement : public HTMLInputElement {
public:
- MediaControlInputElement(Document*, RenderStyle::PseudoId, const String& type, HTMLMediaElement*);
+ MediaControlInputElement(Document*, PseudoId, const String& type, HTMLMediaElement*, MediaControlElementType);
void attachToParent(Element*);
void update();
+ virtual void updateStyle();
bool hitTest(const IntPoint& absPoint);
+ MediaControlElementType displayType() const { return m_displayType; }
+
protected:
+ virtual void updateDisplayType() { }
+ void setDisplayType(MediaControlElementType);
+
HTMLMediaElement* m_mediaElement;
+ PseudoId m_pseudoStyleId;
+ MediaControlElementType m_displayType; // some elements can show multiple types (e.g. play/pause)
};
// ----------------------------
@@ -79,6 +110,7 @@ class MediaControlMuteButtonElement : public MediaControlInputElement {
public:
MediaControlMuteButtonElement(Document*, HTMLMediaElement*);
virtual void defaultEventHandler(Event*);
+ virtual void updateDisplayType();
};
// ----------------------------
@@ -87,6 +119,7 @@ class MediaControlPlayButtonElement : public MediaControlInputElement {
public:
MediaControlPlayButtonElement(Document*, HTMLMediaElement*);
virtual void defaultEventHandler(Event*);
+ virtual void updateDisplayType();
};
// ----------------------------
@@ -119,6 +152,7 @@ class MediaControlFullscreenButtonElement : public MediaControlInputElement {
public:
MediaControlFullscreenButtonElement(Document*, HTMLMediaElement*);
virtual void defaultEventHandler(Event*);
+ virtual bool rendererIsNeeded(RenderStyle*);
};
// ----------------------------
diff --git a/src/3rdparty/webkit/WebCore/rendering/OverlapTestRequestClient.h b/src/3rdparty/webkit/WebCore/rendering/OverlapTestRequestClient.h
new file mode 100644
index 0000000..71400ab
--- /dev/null
+++ b/src/3rdparty/webkit/WebCore/rendering/OverlapTestRequestClient.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2009 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``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 INC. OR
+ * 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 OverlapTestRequestClient_h
+#define OverlapTestRequestClient_h
+
+namespace WebCore {
+
+class OverlapTestRequestClient {
+public:
+ virtual ~OverlapTestRequestClient() { }
+ virtual void setOverlapTestResult(bool) = 0;
+};
+
+} // namespace WebCore
+
+#endif // OverlapTestRequestClient_h
diff --git a/src/3rdparty/webkit/WebCore/rendering/PointerEventsHitRules.h b/src/3rdparty/webkit/WebCore/rendering/PointerEventsHitRules.h
index e2dae3b..3d8939a 100644
--- a/src/3rdparty/webkit/WebCore/rendering/PointerEventsHitRules.h
+++ b/src/3rdparty/webkit/WebCore/rendering/PointerEventsHitRules.h
@@ -22,7 +22,7 @@
#ifndef PointerEventsHitRules_h
#define PointerEventsHitRules_h
-#include "RenderStyle.h"
+#include "RenderStyleConstants.h"
namespace WebCore {
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderApplet.cpp b/src/3rdparty/webkit/WebCore/rendering/RenderApplet.cpp
index 7483943..a989d6f 100644
--- a/src/3rdparty/webkit/WebCore/rendering/RenderApplet.cpp
+++ b/src/3rdparty/webkit/WebCore/rendering/RenderApplet.cpp
@@ -1,8 +1,6 @@
-/**
- * This file is part of the HTML widget for KDE.
- *
+/*
* Copyright (C) 1999 Lars Knoll (knoll@kde.org)
- * Copyright (C) 2003, 2006 Apple Computer, Inc.
+ * Copyright (C) 2003, 2006, 2009 Apple Inc. 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
@@ -24,13 +22,10 @@
#include "config.h"
#include "RenderApplet.h"
-#include "Document.h"
#include "Frame.h"
-#include "FrameLoader.h"
#include "HTMLAppletElement.h"
#include "HTMLNames.h"
#include "HTMLParamElement.h"
-#include "Widget.h"
namespace WebCore {
@@ -43,33 +38,29 @@ RenderApplet::RenderApplet(HTMLAppletElement* applet, const HashMap<String, Stri
setInline(true);
}
-RenderApplet::~RenderApplet()
-{
-}
-
IntSize RenderApplet::intrinsicSize() const
{
// FIXME: This doesn't make sense. We can't just start returning
// a different size once we've created the widget and expect
// layout and sizing to be correct. We should remove this and
// pass the appropriate intrinsic size in the constructor.
- return m_widget ? IntSize(50, 50) : IntSize(150, 150);
+ return widget() ? IntSize(50, 50) : IntSize(150, 150);
}
void RenderApplet::createWidgetIfNecessary()
{
HTMLAppletElement* element = static_cast<HTMLAppletElement*>(node());
- if (m_widget || !element->isFinishedParsingChildren())
+ if (widget() || !element->isFinishedParsingChildren())
return;
// FIXME: Java applets can't be resized (this is a bug in Apple's Java implementation).
// In order to work around this problem and have a correct size from the start, we will
// use fixed widths/heights from the style system when we can, since the widget might
// not have an accurate m_width/m_height.
- int width = style()->width().isFixed() ? style()->width().value() :
- m_width - borderLeft() - borderRight() - paddingLeft() - paddingRight();
- int height = style()->height().isFixed() ? style()->height().value() :
- m_height - borderTop() - borderBottom() - paddingTop() - paddingBottom();
+ int contentWidth = style()->width().isFixed() ? style()->width().value() :
+ width() - borderLeft() - borderRight() - paddingLeft() - paddingRight();
+ int contentHeight = style()->height().isFixed() ? style()->height().value() :
+ height() - borderTop() - borderBottom() - paddingTop() - paddingBottom();
for (Node* child = element->firstChild(); child; child = child->nextSibling()) {
if (child->hasTagName(paramTag)) {
HTMLParamElement* p = static_cast<HTMLParamElement*>(child);
@@ -80,7 +71,7 @@ void RenderApplet::createWidgetIfNecessary()
Frame* frame = document()->frame();
ASSERT(frame);
- setWidget(frame->loader()->createJavaAppletWidget(IntSize(width, height), element, m_args));
+ setWidget(frame->loader()->createJavaAppletWidget(IntSize(contentWidth, contentHeight), element, m_args));
}
void RenderApplet::layout()
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderApplet.h b/src/3rdparty/webkit/WebCore/rendering/RenderApplet.h
index 6746c22..b481d87 100644
--- a/src/3rdparty/webkit/WebCore/rendering/RenderApplet.h
+++ b/src/3rdparty/webkit/WebCore/rendering/RenderApplet.h
@@ -1,6 +1,6 @@
/*
* Copyright (C) 1999 Lars Knoll (knoll@kde.org)
- * Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
+ * Copyright (C) 2006, 2007, 2009 Apple Inc. 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
@@ -32,8 +32,10 @@ namespace WebCore {
class RenderApplet : public RenderWidget {
public:
RenderApplet(HTMLAppletElement*, const HashMap<String, String>& args);
- virtual ~RenderApplet();
+ void createWidgetIfNecessary();
+
+ private:
virtual const char* renderName() const { return "RenderApplet"; }
virtual bool isApplet() const { return true; }
@@ -41,9 +43,6 @@ namespace WebCore {
virtual void layout();
virtual IntSize intrinsicSize() const;
- void createWidgetIfNecessary();
-
- private:
HashMap<String, String> m_args;
};
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderArena.cpp b/src/3rdparty/webkit/WebCore/rendering/RenderArena.cpp
index 69d08a5..b7bfe4d 100644
--- a/src/3rdparty/webkit/WebCore/rendering/RenderArena.cpp
+++ b/src/3rdparty/webkit/WebCore/rendering/RenderArena.cpp
@@ -76,7 +76,7 @@ void* RenderArena::allocate(size_t size)
// Use standard malloc so that memory debugging tools work.
ASSERT(this);
void* block = ::malloc(sizeof(RenderArenaDebugHeader) + size);
- RenderArenaDebugHeader* header = (RenderArenaDebugHeader*)block;
+ RenderArenaDebugHeader* header = static_cast<RenderArenaDebugHeader*>(block);
header->arena = this;
header->size = size;
header->signature = signature;
@@ -112,7 +112,7 @@ void RenderArena::free(size_t size, void* ptr)
{
#ifndef NDEBUG
// Use standard free so that memory debugging tools work.
- RenderArenaDebugHeader* header = (RenderArenaDebugHeader*)ptr - 1;
+ RenderArenaDebugHeader* header = static_cast<RenderArenaDebugHeader*>(ptr) - 1;
ASSERT(header->signature == signature);
ASSERT(header->size == size);
ASSERT(header->arena == this);
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderBR.cpp b/src/3rdparty/webkit/WebCore/rendering/RenderBR.cpp
index 2532c5b..f407099 100644
--- a/src/3rdparty/webkit/WebCore/rendering/RenderBR.cpp
+++ b/src/3rdparty/webkit/WebCore/rendering/RenderBR.cpp
@@ -40,15 +40,6 @@ RenderBR::~RenderBR()
{
}
-InlineBox* RenderBR::createInlineBox(bool makePlaceholder, bool isRootLineBox, bool isOnlyRun)
-{
- // We only treat a box as text for a <br> if we are on a line by ourself or in strict mode
- // (Note the use of strict mode. In "almost strict" mode, we don't treat the box for <br> as text.)
- InlineTextBox* box = static_cast<InlineTextBox*>(RenderText::createInlineBox(makePlaceholder, isRootLineBox, isOnlyRun));
- box->setIsText(isOnlyRun || document()->inStrictMode());
- return box;
-}
-
int RenderBR::baselinePosition(bool firstLine, bool isRootLineBox) const
{
if (firstTextBox() && !firstTextBox()->isText())
@@ -82,7 +73,7 @@ int RenderBR::lineHeight(bool firstLine, bool /*isRootLineBox*/) const
return m_lineHeight;
}
-void RenderBR::styleDidChange(RenderStyle::Diff diff, const RenderStyle* oldStyle)
+void RenderBR::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
{
RenderText::styleDidChange(diff, oldStyle);
m_lineHeight = -1;
@@ -103,9 +94,9 @@ unsigned RenderBR::caretMaxRenderedOffset() const
return 1;
}
-VisiblePosition RenderBR::positionForCoordinates(int /*x*/, int /*y*/)
+VisiblePosition RenderBR::positionForPoint(const IntPoint&)
{
- return VisiblePosition(element(), 0, DOWNSTREAM);
+ return createVisiblePosition(0, DOWNSTREAM);
}
} // namespace WebCore
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderBR.h b/src/3rdparty/webkit/WebCore/rendering/RenderBR.h
index b65bb58..7eae8ea 100644
--- a/src/3rdparty/webkit/WebCore/rendering/RenderBR.h
+++ b/src/3rdparty/webkit/WebCore/rendering/RenderBR.h
@@ -40,7 +40,7 @@ public:
virtual const char* renderName() const { return "RenderBR"; }
- virtual IntRect selectionRect(bool) { return IntRect(); }
+ virtual IntRect selectionRectForRepaint(RenderBoxModelObject* /*repaintContainer*/, bool /*clipToVisibleContent*/) { return IntRect(); }
virtual unsigned width(unsigned /*from*/, unsigned /*len*/, const Font&, int /*xpos*/) const { return 0; }
virtual unsigned width(unsigned /*from*/, unsigned /*len*/, int /*xpos*/, bool /*firstLine = false*/) const { return 0; }
@@ -49,18 +49,16 @@ public:
virtual int baselinePosition(bool firstLine, bool isRootLineBox = false) const;
// overrides
- virtual InlineBox* createInlineBox(bool, bool, bool isOnlyRun = false);
-
virtual bool isBR() const { return true; }
virtual int caretMinOffset() const;
virtual int caretMaxOffset() const;
virtual unsigned caretMaxRenderedOffset() const;
- virtual VisiblePosition positionForCoordinates(int x, int y);
+ virtual VisiblePosition positionForPoint(const IntPoint&);
protected:
- virtual void styleDidChange(RenderStyle::Diff, const RenderStyle* oldStyle);
+ virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
private:
mutable int m_lineHeight;
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderBlock.cpp b/src/3rdparty/webkit/WebCore/rendering/RenderBlock.cpp
index 0aa58da..98426ed 100644
--- a/src/3rdparty/webkit/WebCore/rendering/RenderBlock.cpp
+++ b/src/3rdparty/webkit/WebCore/rendering/RenderBlock.cpp
@@ -25,13 +25,16 @@
#include "Document.h"
#include "Element.h"
+#include "FloatQuad.h"
#include "Frame.h"
#include "FrameView.h"
#include "GraphicsContext.h"
+#include "HTMLFormElement.h"
#include "HTMLNames.h"
#include "HitTestResult.h"
#include "InlineTextBox.h"
#include "RenderImage.h"
+#include "RenderInline.h"
#include "RenderMarquee.h"
#include "RenderReplica.h"
#include "RenderTableCell.h"
@@ -39,6 +42,7 @@
#include "RenderTheme.h"
#include "RenderView.h"
#include "SelectionController.h"
+#include "Settings.h"
#include <wtf/StdLibExtras.h>
using namespace std;
@@ -49,10 +53,16 @@ namespace WebCore {
// Number of pixels to allow as a fudge factor when clicking above or below a line.
// clicking up to verticalLineClickFudgeFactor pixels above a line will correspond to the closest point on the line.
-const int verticalLineClickFudgeFactor= 3;
+static const int verticalLineClickFudgeFactor = 3;
using namespace HTMLNames;
+static void moveChild(RenderObject* to, RenderObjectChildList* toChildList, RenderObject* from, RenderObjectChildList* fromChildList, RenderObject* child)
+{
+ ASSERT(from == child->parent());
+ toChildList->appendChildNode(to, fromChildList->removeChildNode(from, child, false), false);
+}
+
struct ColumnInfo {
ColumnInfo()
: m_desiredColumnWidth(0)
@@ -72,7 +82,7 @@ static PercentHeightDescendantsMap* gPercentHeightDescendantsMap = 0;
typedef WTF::HashMap<const RenderBox*, HashSet<RenderBlock*>*> PercentHeightContainerMap;
static PercentHeightContainerMap* gPercentHeightContainerMap = 0;
-typedef WTF::HashMap<RenderBlock*, RenderFlowSequencedSet*> ContinuationOutlineTableMap;
+typedef WTF::HashMap<RenderBlock*, ListHashSet<RenderInline*>*> ContinuationOutlineTableMap;
// Our MarginInfo state used when laying out block children.
RenderBlock::MarginInfo::MarginInfo(RenderBlock* block, int top, int bottom)
@@ -109,15 +119,18 @@ RenderBlock::MarginInfo::MarginInfo(RenderBlock* block, int top, int bottom)
// -------------------------------------------------------------------------------------------------------
RenderBlock::RenderBlock(Node* node)
- : RenderFlow(node)
+ : RenderBox(node)
, m_floatingObjects(0)
, m_positionedObjects(0)
+ , m_inlineContinuation(0)
, m_maxMargin(0)
, m_overflowHeight(0)
, m_overflowWidth(0)
, m_overflowLeft(0)
, m_overflowTop(0)
+ , m_lineHeight(-1)
{
+ setChildrenInline(true);
}
RenderBlock::~RenderBlock()
@@ -126,7 +139,7 @@ RenderBlock::~RenderBlock()
delete m_positionedObjects;
delete m_maxMargin;
- if (m_hasColumns)
+ if (hasColumns())
delete gColumnInfoMap->take(this);
if (gPercentHeightDescendantsMap) {
@@ -149,15 +162,76 @@ RenderBlock::~RenderBlock()
}
}
-void RenderBlock::styleWillChange(RenderStyle::Diff diff, const RenderStyle* newStyle)
+void RenderBlock::destroy()
+{
+ // Detach our continuation first.
+ if (m_inlineContinuation)
+ m_inlineContinuation->destroy();
+ m_inlineContinuation = 0;
+
+ // Make sure to destroy anonymous children first while they are still connected to the rest of the tree, so that they will
+ // properly dirty line boxes that they are removed from. Effects that do :before/:after only on hover could crash otherwise.
+ children()->destroyLeftoverChildren();
+
+ if (!documentBeingDestroyed()) {
+ if (firstLineBox()) {
+ // We can't wait for RenderBox::destroy to clear the selection,
+ // because by then we will have nuked the line boxes.
+ // FIXME: The SelectionController should be responsible for this when it
+ // is notified of DOM mutations.
+ if (isSelectionBorder())
+ view()->clearSelection();
+
+ // If we are an anonymous block, then our line boxes might have children
+ // that will outlast this block. In the non-anonymous block case those
+ // children will be destroyed by the time we return from this function.
+ if (isAnonymousBlock()) {
+ for (InlineFlowBox* box = firstLineBox(); box; box = box->nextFlowBox()) {
+ while (InlineBox* childBox = box->firstChild())
+ childBox->remove();
+ }
+ }
+ } else if (isInline() && parent())
+ parent()->dirtyLinesFromChangedChild(this);
+ }
+
+ m_lineBoxes.deleteLineBoxes(renderArena());
+
+ RenderBox::destroy();
+}
+
+void RenderBlock::styleWillChange(StyleDifference diff, const RenderStyle* newStyle)
{
setReplaced(newStyle->isDisplayReplacedType());
- RenderFlow::styleWillChange(diff, newStyle);
+
+ if (style() && parent() && diff == StyleDifferenceLayout && style()->position() != newStyle->position()) {
+ if (newStyle->position() == StaticPosition)
+ // Clear our positioned objects list. Our absolutely positioned descendants will be
+ // inserted into our containing block's positioned objects list during layout.
+ removePositionedObjects(0);
+ else if (style()->position() == StaticPosition) {
+ // Remove our absolutely positioned descendants from their current containing block.
+ // They will be inserted into our positioned objects list during layout.
+ RenderObject* cb = parent();
+ while (cb && (cb->style()->position() == StaticPosition || (cb->isInline() && !cb->isReplaced())) && !cb->isRenderView()) {
+ if (cb->style()->position() == RelativePosition && cb->isInline() && !cb->isReplaced()) {
+ cb = cb->containingBlock();
+ break;
+ }
+ cb = cb->parent();
+ }
+
+ if (cb->isRenderBlock())
+ toRenderBlock(cb)->removePositionedObjects(this);
+ }
+ }
+
+ RenderBox::styleWillChange(diff, newStyle);
}
-void RenderBlock::styleDidChange(RenderStyle::Diff diff, const RenderStyle* oldStyle)
+void RenderBlock::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
{
- RenderFlow::styleDidChange(diff, oldStyle);
+ RenderBox::styleDidChange(diff, oldStyle);
// FIXME: We could save this call when the change only affected non-inherited properties
for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
@@ -172,14 +246,22 @@ void RenderBlock::styleDidChange(RenderStyle::Diff diff, const RenderStyle* oldS
m_lineHeight = -1;
// Update pseudos for :before and :after now.
- if (!isAnonymous() && canHaveChildren()) {
- updateBeforeAfterContent(RenderStyle::BEFORE);
- updateBeforeAfterContent(RenderStyle::AFTER);
+ if (!isAnonymous() && document()->usesBeforeAfterRules() && canHaveChildren()) {
+ updateBeforeAfterContent(BEFORE);
+ updateBeforeAfterContent(AFTER);
}
updateFirstLetter();
}
-void RenderBlock::addChildToFlow(RenderObject* newChild, RenderObject* beforeChild)
+void RenderBlock::updateBeforeAfterContent(PseudoId pseudoId)
+{
+ // If this is an anonymous wrapper, then the parent applies its own pseudo-element style to it.
+ if (parent() && parent()->createsAnonymousWrapper())
+ return;
+ return children()->updateBeforeAfterContent(this, pseudoId);
+}
+
+void RenderBlock::addChild(RenderObject* newChild, RenderObject* beforeChild)
{
// Make sure we don't append things after :after-generated content if we have it.
if (!beforeChild && isAfterContent(lastChild()))
@@ -203,13 +285,13 @@ void RenderBlock::addChildToFlow(RenderObject* newChild, RenderObject* beforeChi
if (newChild->isInline() || beforeChild->parent()->firstChild() != beforeChild)
beforeChild->parent()->addChild(newChild, beforeChild);
else
- addChildToFlow(newChild, beforeChild->parent());
+ addChild(newChild, beforeChild->parent());
return;
}
ASSERT(anonymousChild->isTable());
- if (newChild->isTableCol() && newChild->style()->display() == TABLE_COLUMN_GROUP
- || newChild->isRenderBlock() && newChild->style()->display() == TABLE_CAPTION
+ if ((newChild->isTableCol() && newChild->style()->display() == TABLE_COLUMN_GROUP)
+ || (newChild->isRenderBlock() && newChild->style()->display() == TABLE_CAPTION)
|| newChild->isTableSection()
|| newChild->isTableRow()
|| newChild->isTableCell()) {
@@ -225,7 +307,7 @@ void RenderBlock::addChildToFlow(RenderObject* newChild, RenderObject* beforeChi
// A block has to either have all of its children inline, or all of its children as blocks.
// So, if our children are currently inline and a block child has to be inserted, we move all our
// inline children into anonymous block boxes.
- if (m_childrenInline && !newChild->isInline() && !newChild->isFloatingOrPositioned()) {
+ if (childrenInline() && !newChild->isInline() && !newChild->isFloatingOrPositioned()) {
// This is a block with inline content. Wrap the inline content in anonymous blocks.
makeChildrenNonInline(beforeChild);
madeBoxesNonInline = true;
@@ -235,7 +317,7 @@ void RenderBlock::addChildToFlow(RenderObject* newChild, RenderObject* beforeChi
ASSERT(beforeChild->isAnonymousBlock());
ASSERT(beforeChild->parent() == this);
}
- } else if (!m_childrenInline && (newChild->isFloatingOrPositioned() || newChild->isInline())) {
+ } else if (!childrenInline() && (newChild->isFloatingOrPositioned() || newChild->isInline())) {
// If we're inserting an inline child but all of our children are blocks, then we have to make sure
// it is put into an anomyous block box. We try to use an existing anonymous box if possible, otherwise
// a new one is created and inserted into our list of children in the appropriate position.
@@ -249,17 +331,16 @@ void RenderBlock::addChildToFlow(RenderObject* newChild, RenderObject* beforeChi
if (newChild->isInline()) {
// No suitable existing anonymous box - create a new one.
RenderBlock* newBox = createAnonymousBlock();
- RenderContainer::addChild(newBox, beforeChild);
+ RenderBox::addChild(newBox, beforeChild);
newBox->addChild(newChild);
return;
}
}
- RenderContainer::addChild(newChild, beforeChild);
- // ### care about aligned stuff
+ RenderBox::addChild(newChild, beforeChild);
- if (madeBoxesNonInline && parent() && isAnonymousBlock())
- parent()->removeLeftoverAnonymousBlock(this);
+ if (madeBoxesNonInline && parent() && isAnonymousBlock() && parent()->isRenderBlock())
+ toRenderBlock(parent())->removeLeftoverAnonymousBlock(this);
// this object may be dead here
}
@@ -305,14 +386,19 @@ static void getInlineRun(RenderObject* start, RenderObject* boundary,
void RenderBlock::deleteLineBoxTree()
{
- InlineFlowBox* line = m_firstLineBox;
- InlineFlowBox* nextLine;
- while (line) {
- nextLine = line->nextFlowBox();
- line->deleteLine(renderArena());
- line = nextLine;
- }
- m_firstLineBox = m_lastLineBox = 0;
+ m_lineBoxes.deleteLineBoxTree(renderArena());
+}
+
+RootInlineBox* RenderBlock::createRootBox()
+{
+ return new (renderArena()) RootInlineBox(this);
+}
+
+RootInlineBox* RenderBlock::createRootInlineBox()
+{
+ RootInlineBox* rootBox = createRootBox();
+ m_lineBoxes.appendLineBox(rootBox);
+ return rootBox;
}
void RenderBlock::makeChildrenNonInline(RenderObject *insertionPoint)
@@ -327,7 +413,7 @@ void RenderBlock::makeChildrenNonInline(RenderObject *insertionPoint)
ASSERT(isInlineBlockOrInlineTable() || !isInline());
ASSERT(!insertionPoint || insertionPoint->parent() == this);
- m_childrenInline = false;
+ setChildrenInline(false);
RenderObject *child = firstChild();
if (!child)
@@ -344,16 +430,16 @@ void RenderBlock::makeChildrenNonInline(RenderObject *insertionPoint)
child = inlineRunEnd->nextSibling();
- RenderBlock* box = createAnonymousBlock();
- insertChildNode(box, inlineRunStart);
+ RenderBlock* block = createAnonymousBlock();
+ children()->insertChildNode(this, block, inlineRunStart);
RenderObject* o = inlineRunStart;
- while(o != inlineRunEnd)
- {
+ while (o != inlineRunEnd) {
RenderObject* no = o;
o = no->nextSibling();
- box->moveChildNode(no);
+
+ moveChild(block, block->children(), this, children(), no);
}
- box->moveChildNode(inlineRunEnd);
+ moveChild(block, block->children(), this, children(), inlineRunEnd);
}
#ifndef NDEBUG
@@ -364,7 +450,49 @@ void RenderBlock::makeChildrenNonInline(RenderObject *insertionPoint)
repaint();
}
-void RenderBlock::removeChild(RenderObject *oldChild)
+void RenderBlock::removeLeftoverAnonymousBlock(RenderBlock* child)
+{
+ ASSERT(child->isAnonymousBlock());
+ ASSERT(!child->childrenInline());
+
+ if (child->inlineContinuation())
+ return;
+
+ RenderObject* firstAnChild = child->m_children.firstChild();
+ RenderObject* lastAnChild = child->m_children.lastChild();
+ if (firstAnChild) {
+ RenderObject* o = firstAnChild;
+ while (o) {
+ o->setParent(this);
+ o = o->nextSibling();
+ }
+ firstAnChild->setPreviousSibling(child->previousSibling());
+ lastAnChild->setNextSibling(child->nextSibling());
+ if (child->previousSibling())
+ child->previousSibling()->setNextSibling(firstAnChild);
+ if (child->nextSibling())
+ child->nextSibling()->setPreviousSibling(lastAnChild);
+ } else {
+ if (child->previousSibling())
+ child->previousSibling()->setNextSibling(child->nextSibling());
+ if (child->nextSibling())
+ child->nextSibling()->setPreviousSibling(child->previousSibling());
+ }
+ if (child == m_children.firstChild())
+ m_children.setFirstChild(firstAnChild);
+ if (child == m_children.lastChild())
+ m_children.setLastChild(lastAnChild);
+ child->setParent(0);
+ child->setPreviousSibling(0);
+ child->setNextSibling(0);
+
+ child->children()->setFirstChild(0);
+ child->m_next = 0;
+
+ child->destroy();
+}
+
+void RenderBlock::removeChild(RenderObject* oldChild)
{
// If this child is a block, and if our previous and next siblings are
// both anonymous blocks with inline content, then we can go ahead and
@@ -372,7 +500,7 @@ void RenderBlock::removeChild(RenderObject *oldChild)
RenderObject* prev = oldChild->previousSibling();
RenderObject* next = oldChild->nextSibling();
bool canDeleteAnonymousBlocks = !documentBeingDestroyed() && !isInline() && !oldChild->isInline() &&
- !oldChild->continuation() &&
+ (!oldChild->isRenderBlock() || !toRenderBlock(oldChild)->inlineContinuation()) &&
(!prev || (prev->isAnonymousBlock() && prev->childrenInline())) &&
(!next || (next->isAnonymousBlock() && next->childrenInline()));
if (canDeleteAnonymousBlocks && prev && next) {
@@ -380,20 +508,22 @@ void RenderBlock::removeChild(RenderObject *oldChild)
// the |prev| block.
prev->setNeedsLayoutAndPrefWidthsRecalc();
RenderObject* o = next->firstChild();
+
+ RenderBlock* nextBlock = toRenderBlock(next);
+ RenderBlock* prevBlock = toRenderBlock(prev);
while (o) {
RenderObject* no = o;
o = no->nextSibling();
- prev->moveChildNode(no);
+ moveChild(prevBlock, prevBlock->children(), nextBlock, nextBlock->children(), no);
}
- RenderBlock* nextBlock = static_cast<RenderBlock*>(next);
nextBlock->deleteLineBoxTree();
// Nuke the now-empty block.
next->destroy();
}
- RenderFlow::removeChild(oldChild);
+ RenderBox::removeChild(oldChild);
RenderObject* child = prev ? prev : next;
if (canDeleteAnonymousBlocks && child && !child->previousSibling() && !child->nextSibling() && !isFlexibleBox()) {
@@ -401,13 +531,13 @@ void RenderBlock::removeChild(RenderObject *oldChild)
// box. We can go ahead and pull the content right back up into our
// box.
setNeedsLayoutAndPrefWidthsRecalc();
- RenderBlock* anonBlock = static_cast<RenderBlock*>(removeChildNode(child, false));
- m_childrenInline = true;
+ RenderBlock* anonBlock = toRenderBlock(children()->removeChildNode(this, child, false));
+ setChildrenInline(true);
RenderObject* o = anonBlock->firstChild();
while (o) {
RenderObject* no = o;
o = no->nextSibling();
- moveChildNode(no);
+ moveChild(this, children(), anonBlock, anonBlock->children(), no);
}
// Delete the now-empty block's lines and nuke it.
@@ -422,10 +552,10 @@ int RenderBlock::overflowHeight(bool includeInterior) const
int shadowHeight = 0;
for (ShadowData* boxShadow = style()->boxShadow(); boxShadow; boxShadow = boxShadow->next)
shadowHeight = max(boxShadow->y + boxShadow->blur, shadowHeight);
- int height = m_height + shadowHeight;
+ int inflatedHeight = height() + shadowHeight;
if (hasReflection())
- height = max(height, reflectionBox().bottom());
- return height;
+ inflatedHeight = max(inflatedHeight, reflectionBox().bottom());
+ return inflatedHeight;
}
return m_overflowHeight;
}
@@ -436,10 +566,10 @@ int RenderBlock::overflowWidth(bool includeInterior) const
int shadowWidth = 0;
for (ShadowData* boxShadow = style()->boxShadow(); boxShadow; boxShadow = boxShadow->next)
shadowWidth = max(boxShadow->x + boxShadow->blur, shadowWidth);
- int width = m_width + shadowWidth;
+ int inflatedWidth = width() + shadowWidth;
if (hasReflection())
- width = max(width, reflectionBox().right());
- return width;
+ inflatedWidth = max(inflatedWidth, reflectionBox().right());
+ return inflatedWidth;
}
return m_overflowWidth;
}
@@ -475,7 +605,7 @@ int RenderBlock::overflowTop(bool includeInterior) const
IntRect RenderBlock::overflowRect(bool includeInterior) const
{
if (!includeInterior && hasOverflowClip()) {
- IntRect box = borderBox();
+ IntRect box = borderBoxRect();
int shadowLeft = 0;
int shadowRight = 0;
int shadowTop = 0;
@@ -508,10 +638,10 @@ IntRect RenderBlock::overflowRect(bool includeInterior) const
}
if (!includeInterior && hasOverflowClip())
- return borderBox();
+ return borderBoxRect();
int l = overflowLeft(includeInterior);
- int t = min(overflowTop(includeInterior), -borderTopExtra());
- return IntRect(l, t, overflowWidth(includeInterior) - l, max(overflowHeight(includeInterior), height() + borderBottomExtra()) - t);
+ int t = overflowTop(includeInterior);
+ return IntRect(l, t, overflowWidth(includeInterior) - l, max(overflowHeight(includeInterior), height()) - t);
}
bool RenderBlock::isSelfCollapsingBlock() const
@@ -522,7 +652,7 @@ bool RenderBlock::isSelfCollapsingBlock() const
// (c) have border/padding,
// (d) have a min-height
// (e) have specified that one of our margins can't collapse using a CSS extension
- if (m_height > 0 ||
+ if (height() > 0 ||
isTable() || (borderBottom() + paddingBottom() + borderTop() + paddingTop()) != 0 ||
style()->minHeight().isPositive() ||
style()->marginTopCollapse() == MSEPARATE || style()->marginBottomCollapse() == MSEPARATE)
@@ -547,7 +677,7 @@ bool RenderBlock::isSelfCollapsingBlock() const
// Whether or not we collapse is dependent on whether all our normal flow children
// are also self-collapsing.
- for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
+ for (RenderBox* child = firstChildBox(); child; child = child->nextSiblingBox()) {
if (child->isFloatingOrPositioned())
continue;
if (!child->isSelfCollapsingBlock())
@@ -570,8 +700,8 @@ void RenderBlock::layout()
// It's safe to check for control clip here, since controls can never be table cells.
if (hasControlClip()) {
// Because of the lightweight clip, there can never be any overflow from children.
- m_overflowWidth = m_width;
- m_overflowHeight = m_height;
+ m_overflowWidth = width();
+ m_overflowHeight = height();
m_overflowLeft = 0;
m_overflowTop = 0;
}
@@ -587,35 +717,29 @@ void RenderBlock::layoutBlock(bool relayoutChildren)
if (!relayoutChildren && layoutOnlyPositionedObjects())
return;
- IntRect oldBounds;
- IntRect oldOutlineBox;
- bool checkForRepaint = m_everHadLayout && checkForRepaintDuringLayout();
- if (checkForRepaint) {
- oldBounds = absoluteClippedOverflowRect();
- oldOutlineBox = absoluteOutlineBounds();
- }
-
- LayoutStateMaintainer statePusher(view(), this, IntSize(xPos(), yPos()), !m_hasColumns && !hasReflection());
+ LayoutRepainter repainter(*this, m_everHadLayout && checkForRepaintDuringLayout());
+ LayoutStateMaintainer statePusher(view(), this, IntSize(x(), y()), hasColumns() || hasTransform() || hasReflection());
- int oldWidth = m_width;
+ int oldWidth = width();
int oldColumnWidth = desiredColumnWidth();
calcWidth();
calcColumnWidth();
- m_overflowWidth = m_width;
+ m_overflowWidth = width();
m_overflowLeft = 0;
- if (oldWidth != m_width || oldColumnWidth != desiredColumnWidth())
+ if (oldWidth != width() || oldColumnWidth != desiredColumnWidth())
relayoutChildren = true;
clearFloats();
- int previousHeight = m_height;
- m_height = 0;
+ int previousHeight = height();
+ setHeight(0);
+
m_overflowHeight = 0;
- // We use four values, maxTopPos, maxPosNeg, maxBottomPos, and maxBottomNeg, to track
+ // We use four values, maxTopPos, maxTopNeg, maxBottomPos, and maxBottomNeg, to track
// our current maximal positive and negative margins. These values are used when we
// are collapsed with adjacent blocks, so for example, if you have block A and B
// collapsing together, then you'd take the maximal positive margin from both A and B
@@ -629,11 +753,11 @@ void RenderBlock::layoutBlock(bool relayoutChildren)
if (!isCell) {
initMaxMarginValues();
- m_topMarginQuirk = style()->marginTop().quirk();
- m_bottomMarginQuirk = style()->marginBottom().quirk();
+ setTopMarginQuirk(style()->marginTop().quirk());
+ setBottomMarginQuirk(style()->marginBottom().quirk());
- Node* node = element();
- if (node && node->hasTagName(formTag) && static_cast<HTMLFormElement*>(node)->isMalformed()) {
+ Node* n = node();
+ if (n && n->hasTagName(formTag) && static_cast<HTMLFormElement*>(n)->isMalformed()) {
// See if this form is malformed (i.e., unclosed). If so, don't give the form
// a bottom margin.
setMaxBottomMargins(0, 0);
@@ -643,9 +767,9 @@ void RenderBlock::layoutBlock(bool relayoutChildren)
// For overflow:scroll blocks, ensure we have both scrollbars in place always.
if (scrollsOverflow()) {
if (style()->overflowX() == OSCROLL)
- m_layer->setHasHorizontalScrollbar(true);
+ layer()->setHasHorizontalScrollbar(true);
if (style()->overflowY() == OSCROLL)
- m_layer->setHasVerticalScrollbar(true);
+ layer()->setHasVerticalScrollbar(true);
}
int repaintTop = 0;
@@ -658,25 +782,24 @@ void RenderBlock::layoutBlock(bool relayoutChildren)
// Expand our intrinsic height to encompass floats.
int toAdd = borderBottom() + paddingBottom() + horizontalScrollbarHeight();
- if (floatBottom() > (m_height - toAdd) && (isInlineBlockOrInlineTable() || isFloatingOrPositioned() || hasOverflowClip() ||
- (parent() && parent()->isFlexibleBox() || m_hasColumns)))
- m_height = floatBottom() + toAdd;
+ if (floatBottom() > (height() - toAdd) && expandsToEncloseOverhangingFloats())
+ setHeight(floatBottom() + toAdd);
// Now lay out our columns within this intrinsic height, since they can slightly affect the intrinsic height as
// we adjust for clean column breaks.
int singleColumnBottom = layoutColumns();
// Calculate our new height.
- int oldHeight = m_height;
+ int oldHeight = height();
calcHeight();
- if (oldHeight != m_height) {
- if (oldHeight > m_height && maxFloatBottom > m_height && !childrenInline()) {
+ if (oldHeight != height()) {
+ if (oldHeight > height() && maxFloatBottom > height() && !childrenInline()) {
// One of our children's floats may have become an overhanging float for us. We need to look for it.
for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
if (child->isBlockFlow() && !child->isFloatingOrPositioned()) {
- RenderBlock* block = static_cast<RenderBlock*>(child);
- if (block->floatBottom() + block->yPos() > m_height)
- addOverhangingFloats(block, -block->xPos(), -block->yPos(), false);
+ RenderBlock* block = toRenderBlock(child);
+ if (block->floatBottom() + block->y() > height())
+ addOverhangingFloats(block, -block->x(), -block->y(), false);
}
}
}
@@ -684,21 +807,14 @@ void RenderBlock::layoutBlock(bool relayoutChildren)
layoutColumns(singleColumnBottom);
// If the block got expanded in size, then increase our overflowheight to match.
- if (m_overflowHeight > m_height)
+ if (m_overflowHeight > height())
m_overflowHeight -= toAdd;
- if (m_overflowHeight < m_height)
- m_overflowHeight = m_height;
+ if (m_overflowHeight < height())
+ m_overflowHeight = height();
}
- if (previousHeight != m_height)
+ if (previousHeight != height())
relayoutChildren = true;
- // Some classes of objects (floats and fieldsets with no specified heights and table cells) expand to encompass
- // overhanging floats.
- if (hasOverhangingFloats() && expandsToEncloseOverhangingFloats()) {
- m_height = floatBottom();
- m_height += borderBottom() + paddingBottom();
- }
-
if ((isCell || isInline() || isFloatingOrPositioned() || isRoot()) && !hasOverflowClip() && !hasControlClip())
addVisualOverflow(floatRect());
@@ -707,15 +823,15 @@ void RenderBlock::layoutBlock(bool relayoutChildren)
positionListMarker();
// Always ensure our overflow width/height are at least as large as our width/height.
- m_overflowWidth = max(m_overflowWidth, m_width);
- m_overflowHeight = max(m_overflowHeight, m_height);
+ m_overflowWidth = max(m_overflowWidth, width());
+ m_overflowHeight = max(m_overflowHeight, height());
if (!hasOverflowClip()) {
for (ShadowData* boxShadow = style()->boxShadow(); boxShadow; boxShadow = boxShadow->next) {
m_overflowLeft = min(m_overflowLeft, boxShadow->x - boxShadow->blur);
- m_overflowWidth = max(m_overflowWidth, m_width + boxShadow->x + boxShadow->blur);
+ m_overflowWidth = max(m_overflowWidth, width() + boxShadow->x + boxShadow->blur);
m_overflowTop = min(m_overflowTop, boxShadow->y - boxShadow->blur);
- m_overflowHeight = max(m_overflowHeight, m_height + boxShadow->y + boxShadow->blur);
+ m_overflowHeight = max(m_overflowHeight, height() + boxShadow->y + boxShadow->blur);
}
if (hasReflection()) {
@@ -729,12 +845,10 @@ void RenderBlock::layoutBlock(bool relayoutChildren)
// Update our scroll information if we're overflow:auto/scroll/hidden now that we know if
// we overflow or not.
if (hasOverflowClip())
- m_layer->updateScrollInfoAfterLayout();
+ layer()->updateScrollInfoAfterLayout();
// Repaint with our new bounds if they are different from our old bounds.
- bool didFullRepaint = false;
- if (checkForRepaint)
- didFullRepaint = repaintAfterLayoutIfNeeded(oldBounds, oldOutlineBox);
+ bool didFullRepaint = repainter.repaintAfterLayout();
if (!didFullRepaint && repaintTop != repaintBottom && (style()->visibility() == VISIBLE || enclosingLayer()->hasVisibleContent())) {
IntRect repaintRect(m_overflowLeft, repaintTop, m_overflowWidth - m_overflowLeft, repaintBottom - repaintTop);
@@ -752,30 +866,35 @@ void RenderBlock::layoutBlock(bool relayoutChildren)
repaintRect.setY(y);
// Don't allow this rect to spill out of our overflow box.
- repaintRect.intersect(IntRect(0, 0, m_width, m_height));
+ repaintRect.intersect(IntRect(0, 0, width(), height()));
}
// Make sure the rect is still non-empty after intersecting for overflow above
if (!repaintRect.isEmpty()) {
repaintRectangle(repaintRect); // We need to do a partial repaint of our content.
if (hasReflection())
- layer()->reflection()->repaintRectangle(repaintRect);
+ repaintRectangle(reflectedRect(repaintRect));
}
}
setNeedsLayout(false);
}
-void RenderBlock::adjustPositionedBlock(RenderObject* child, const MarginInfo& marginInfo)
+bool RenderBlock::expandsToEncloseOverhangingFloats() const
+{
+ return isInlineBlockOrInlineTable() || isFloatingOrPositioned() || hasOverflowClip() || (parent() && parent()->isFlexibleBox()) || hasColumns() || isTableCell() || isFieldset();
+}
+
+void RenderBlock::adjustPositionedBlock(RenderBox* child, const MarginInfo& marginInfo)
{
- if (child->hasStaticX()) {
+ if (child->style()->hasStaticX()) {
if (style()->direction() == LTR)
- child->setStaticX(borderLeft() + paddingLeft());
+ child->layer()->setStaticX(borderLeft() + paddingLeft());
else
- child->setStaticX(borderRight() + paddingRight());
+ child->layer()->setStaticX(borderRight() + paddingRight());
}
- if (child->hasStaticY()) {
- int y = m_height;
+ if (child->style()->hasStaticY()) {
+ int y = height();
if (!marginInfo.canCollapseWithTop()) {
child->calcVerticalMargins();
int marginTop = child->marginTop();
@@ -790,7 +909,7 @@ void RenderBlock::adjustPositionedBlock(RenderObject* child, const MarginInfo& m
}
y += (collapsedTopPos - collapsedTopNeg) - marginTop;
}
- child->setStaticY(y);
+ child->layer()->setStaticY(y);
}
}
@@ -810,143 +929,95 @@ void RenderBlock::adjustFloatingBlock(const MarginInfo& marginInfo)
// http://www.hixie.ch/tests/adhoc/css/box/block/margin-collapse/046.html for
// an example of this scenario.
int marginOffset = marginInfo.canCollapseWithTop() ? 0 : marginInfo.margin();
- m_height += marginOffset;
+ setHeight(height() + marginOffset);
positionNewFloats();
- m_height -= marginOffset;
+ setHeight(height() - marginOffset);
}
-RenderObject* RenderBlock::handleSpecialChild(RenderObject* child, const MarginInfo& marginInfo, CompactInfo& compactInfo, bool& handled)
+bool RenderBlock::handleSpecialChild(RenderBox* child, const MarginInfo& marginInfo)
{
- // Handle positioned children first.
- RenderObject* next = handlePositionedChild(child, marginInfo, handled);
- if (handled) return next;
-
- // Handle floating children next.
- next = handleFloatingChild(child, marginInfo, handled);
- if (handled) return next;
-
- // See if we have a compact element. If we do, then try to tuck the compact element into the margin space of the next block.
- next = handleCompactChild(child, compactInfo, handled);
- if (handled) return next;
-
- // Finally, see if we have a run-in element.
- return handleRunInChild(child, handled);
+ // Handle in the given order
+ return handlePositionedChild(child, marginInfo)
+ || handleFloatingChild(child, marginInfo)
+ || handleRunInChild(child);
}
-RenderObject* RenderBlock::handlePositionedChild(RenderObject* child, const MarginInfo& marginInfo, bool& handled)
+bool RenderBlock::handlePositionedChild(RenderBox* child, const MarginInfo& marginInfo)
{
if (child->isPositioned()) {
- handled = true;
child->containingBlock()->insertPositionedObject(child);
adjustPositionedBlock(child, marginInfo);
- return child->nextSibling();
+ return true;
}
-
- return 0;
+ return false;
}
-RenderObject* RenderBlock::handleFloatingChild(RenderObject* child, const MarginInfo& marginInfo, bool& handled)
+bool RenderBlock::handleFloatingChild(RenderBox* child, const MarginInfo& marginInfo)
{
if (child->isFloating()) {
- handled = true;
insertFloatingObject(child);
adjustFloatingBlock(marginInfo);
- return child->nextSibling();
- }
-
- return 0;
-}
-
-RenderObject* RenderBlock::handleCompactChild(RenderObject* child, CompactInfo& compactInfo, bool& handled)
-{
- // FIXME: We only deal with one compact at a time. It is unclear what should be
- // done if multiple contiguous compacts are encountered. For now we assume that
- // compact A followed by another compact B should simply be treated as block A.
- if (child->isCompact() && !compactInfo.compact() && (child->childrenInline() || child->isReplaced())) {
- // Get the next non-positioned/non-floating RenderBlock.
- RenderObject* next = child->nextSibling();
- RenderObject* curr = next;
- while (curr && curr->isFloatingOrPositioned())
- curr = curr->nextSibling();
- if (curr && curr->isRenderBlock() && !curr->isCompact() && !curr->isRunIn()) {
- curr->calcWidth(); // So that horizontal margins are correct.
-
- child->setInline(true); // Need to compute the margins/width for the child as though it is an inline, so that it won't try to puff up the margins to
- // fill the containing block width.
- child->calcWidth();
- int childMargins = child->marginLeft() + child->marginRight();
- int margin = style()->direction() == LTR ? curr->marginLeft() : curr->marginRight();
- if (margin >= (childMargins + child->maxPrefWidth())) {
- // The compact will fit in the margin.
- handled = true;
- compactInfo.set(child, curr);
- child->setPos(0,0); // This position will be updated to reflect the compact's
- // desired position and the line box for the compact will
- // pick that position up.
-
- // Remove the child.
- RenderObject* next = child->nextSibling();
- removeChildNode(child);
-
- // Now insert the child under |curr|.
- curr->insertChildNode(child, curr->firstChild());
- return next;
- }
- else
- child->setInline(false); // We didn't fit, so we remain a block-level element.
- }
- }
- return 0;
-}
-
-void RenderBlock::insertCompactIfNeeded(RenderObject* child, CompactInfo& compactInfo)
-{
- if (compactInfo.matches(child)) {
- // We have a compact child to squeeze in.
- RenderObject* compactChild = compactInfo.compact();
- int compactXPos = borderLeft() + paddingLeft() + compactChild->marginLeft();
- if (style()->direction() == RTL) {
- compactChild->calcWidth(); // have to do this because of the capped maxwidth
- compactXPos = width() - borderRight() - paddingRight() - marginRight() -
- compactChild->width() - compactChild->marginRight();
- }
- compactXPos -= child->xPos(); // Put compactXPos into the child's coordinate space.
- compactChild->setPos(compactXPos, compactChild->yPos()); // Set the x position.
- compactInfo.clear();
+ return true;
}
+ return false;
}
-RenderObject* RenderBlock::handleRunInChild(RenderObject* child, bool& handled)
+bool RenderBlock::handleRunInChild(RenderBox* child)
{
// See if we have a run-in element with inline children. If the
// children aren't inline, then just treat the run-in as a normal
// block.
- if (child->isRunIn() && (child->childrenInline() || child->isReplaced())) {
- // Get the next non-positioned/non-floating RenderBlock.
- RenderObject* curr = child->nextSibling();
- while (curr && curr->isFloatingOrPositioned())
- curr = curr->nextSibling();
- if (curr && (curr->isRenderBlock() && curr->childrenInline() && !curr->isCompact() && !curr->isRunIn())) {
- // The block acts like an inline, so just null out its
- // position.
- handled = true;
- child->setInline(true);
- child->setPos(0,0);
-
- // Remove the child.
- RenderObject* next = child->nextSibling();
- removeChildNode(child);
-
- // Now insert the child under |curr|.
- curr->insertChildNode(child, curr->firstChild());
- return next;
+ if (!child->isRunIn() || !child->childrenInline() && !child->isReplaced())
+ return false;
+
+ RenderBlock* blockRunIn = toRenderBlock(child);
+ // Get the next non-positioned/non-floating RenderBlock.
+ RenderObject* curr = blockRunIn->nextSibling();
+ while (curr && curr->isFloatingOrPositioned())
+ curr = curr->nextSibling();
+
+ if (!curr || !curr->isRenderBlock() || !curr->childrenInline() || curr->isRunIn())
+ return false;
+
+ RenderBlock* currBlock = toRenderBlock(curr);
+
+ // Remove the old child.
+ children()->removeChildNode(this, blockRunIn);
+
+ // Create an inline.
+ Node* runInNode = blockRunIn->node();
+ RenderInline* inlineRunIn = new (renderArena()) RenderInline(runInNode ? runInNode : document());
+ inlineRunIn->setStyle(blockRunIn->style());
+
+ bool runInIsGenerated = child->style()->styleType() == BEFORE || child->style()->styleType() == AFTER;
+
+ // Move the nodes from the old child to the new child, but skip any :before/:after content. It has already
+ // been regenerated by the new inline.
+ for (RenderObject* runInChild = blockRunIn->firstChild(); runInChild; runInChild = runInChild->nextSibling()) {
+ if (runInIsGenerated || runInChild->style()->styleType() != BEFORE && runInChild->style()->styleType() != AFTER) {
+ blockRunIn->children()->removeChildNode(blockRunIn, runInChild, false);
+ inlineRunIn->addChild(runInChild); // Use addChild instead of appendChildNode since it handles correct placement of the children relative to :after-generated content.
}
}
- return 0;
+
+ // Now insert the new child under |currBlock|.
+ currBlock->children()->insertChildNode(currBlock, inlineRunIn, currBlock->firstChild());
+
+ // If the run-in had an element, we need to set the new renderer.
+ if (runInNode)
+ runInNode->setRenderer(inlineRunIn);
+
+ // Destroy the block run-in.
+ blockRunIn->destroy();
+
+ // The block acts like an inline, so just null out its
+ // position.
+
+ return true;
}
-void RenderBlock::collapseMargins(RenderObject* child, MarginInfo& marginInfo, int yPosEstimate)
+int RenderBlock::collapseMargins(RenderBox* child, MarginInfo& marginInfo)
{
// Get our max pos and neg top margins.
int posTop = child->maxTopMargin(true);
@@ -975,7 +1046,7 @@ void RenderBlock::collapseMargins(RenderObject* child, MarginInfo& marginInfo, i
// has an example of this, a <dt> with 0.8em author-specified inside
// a <dl> inside a <td>.
if (!marginInfo.determinedTopQuirk() && !topQuirk && (posTop-negTop)) {
- m_topMarginQuirk = false;
+ setTopMarginQuirk(false);
marginInfo.setDeterminedTopQuirk(true);
}
@@ -985,13 +1056,13 @@ void RenderBlock::collapseMargins(RenderObject* child, MarginInfo& marginInfo, i
// This deals with the <td><div><p> case.
// Don't do this for a block that split two inlines though. You do
// still apply margins in this case.
- m_topMarginQuirk = true;
+ setTopMarginQuirk(true);
}
if (marginInfo.quirkContainer() && marginInfo.atTopOfBlock() && (posTop - negTop))
marginInfo.setTopQuirk(topQuirk);
- int ypos = m_height;
+ int ypos = height();
if (child->isSelfCollapsingBlock()) {
// This child has no height. We need to compute our
// position before we collapse the child's margins together,
@@ -1010,20 +1081,20 @@ void RenderBlock::collapseMargins(RenderObject* child, MarginInfo& marginInfo, i
// is correct, since it could have overflowing content
// that needs to be positioned correctly (e.g., a block that
// had a specified height of 0 but that actually had subcontent).
- ypos = m_height + collapsedTopPos - collapsedTopNeg;
+ ypos = height() + collapsedTopPos - collapsedTopNeg;
}
else {
if (child->style()->marginTopCollapse() == MSEPARATE) {
- m_height += marginInfo.margin() + child->marginTop();
- ypos = m_height;
+ setHeight(height() + marginInfo.margin() + child->marginTop());
+ ypos = height();
}
else if (!marginInfo.atTopOfBlock() ||
(!marginInfo.canCollapseTopWithChildren()
&& (!style()->htmlHacks() || !marginInfo.quirkContainer() || !marginInfo.topQuirk()))) {
// We're collapsing with a previous sibling's margins and not
// with the top of the block.
- m_height += max(marginInfo.posMargin(), posTop) - max(marginInfo.negMargin(), negTop);
- ypos = m_height;
+ setHeight(height() + max(marginInfo.posMargin(), posTop) - max(marginInfo.negMargin(), negTop));
+ ypos = height();
}
marginInfo.setPosMargin(child->maxBottomMargin(true));
@@ -1034,34 +1105,15 @@ void RenderBlock::collapseMargins(RenderObject* child, MarginInfo& marginInfo, i
marginInfo.setSelfCollapsingBlockClearedFloat(false);
}
-
- view()->addLayoutDelta(IntSize(0, yPosEstimate - ypos));
- child->setPos(child->xPos(), ypos);
- if (ypos != yPosEstimate) {
- if (child->shrinkToAvoidFloats())
- // The child's width depends on the line width.
- // When the child shifts to clear an item, its width can
- // change (because it has more available line width).
- // So go ahead and mark the item as dirty.
- child->setChildNeedsLayout(true, false);
-
- if (!child->avoidsFloats() && child->containsFloats())
- child->markAllDescendantsWithFloatsForLayout();
-
- // Our guess was wrong. Make the child lay itself out again.
- child->layoutIfNeeded();
- }
+
+ return ypos;
}
-void RenderBlock::clearFloatsIfNeeded(RenderObject* child, MarginInfo& marginInfo, int oldTopPosMargin, int oldTopNegMargin)
+int RenderBlock::clearFloatsIfNeeded(RenderBox* child, MarginInfo& marginInfo, int oldTopPosMargin, int oldTopNegMargin, int yPos)
{
- int heightIncrease = getClearDelta(child);
+ int heightIncrease = getClearDelta(child, yPos);
if (!heightIncrease)
- return;
-
- // The child needs to be lowered. Move the child so that it just clears the float.
- view()->addLayoutDelta(IntSize(0, -heightIncrease));
- child->setPos(child->xPos(), child->yPos() + heightIncrease);
+ return yPos;
if (child->isSelfCollapsingBlock()) {
// For self-collapsing blocks that clear, they can still collapse their
@@ -1071,7 +1123,7 @@ void RenderBlock::clearFloatsIfNeeded(RenderObject* child, MarginInfo& marginInf
marginInfo.setNegMargin(max(child->maxTopMargin(false), child->maxBottomMargin(false)));
// Adjust our height such that we are ready to be collapsed with subsequent siblings.
- m_height = child->yPos() - max(0, marginInfo.margin());
+ setHeight(child->y() - max(0, marginInfo.margin()));
// Set a flag that we cleared a float so that we know both to increase the height of the block
// to compensate for the clear and to avoid collapsing our margins with the parent block's
@@ -1079,7 +1131,7 @@ void RenderBlock::clearFloatsIfNeeded(RenderObject* child, MarginInfo& marginInf
marginInfo.setSelfCollapsingBlockClearedFloat(true);
} else
// Increase our height by the amount we had to clear.
- m_height += heightIncrease;
+ setHeight(height() + heightIncrease);
if (marginInfo.canCollapseWithTop()) {
// We can no longer collapse with the top of the block since a clear
@@ -1090,34 +1142,24 @@ void RenderBlock::clearFloatsIfNeeded(RenderObject* child, MarginInfo& marginInf
setMaxTopMargins(oldTopPosMargin, oldTopNegMargin);
marginInfo.setAtTopOfBlock(false);
}
-
- // If our value of clear caused us to be repositioned vertically to be
- // underneath a float, we might have to do another layout to take into account
- // the extra space we now have available.
- if (child->shrinkToAvoidFloats())
- // The child's width depends on the line width.
- // When the child shifts to clear an item, its width can
- // change (because it has more available line width).
- // So go ahead and mark the item as dirty.
- child->setChildNeedsLayout(true, false);
- if (!child->avoidsFloats() && child->containsFloats())
- child->markAllDescendantsWithFloatsForLayout();
- child->layoutIfNeeded();
+
+ return yPos + heightIncrease;
}
-int RenderBlock::estimateVerticalPosition(RenderObject* child, const MarginInfo& marginInfo)
+int RenderBlock::estimateVerticalPosition(RenderBox* child, const MarginInfo& marginInfo)
{
// FIXME: We need to eliminate the estimation of vertical position, because when it's wrong we sometimes trigger a pathological
// relayout if there are intruding floats.
- int yPosEstimate = m_height;
+ int yPosEstimate = height();
if (!marginInfo.canCollapseWithTop()) {
int childMarginTop = child->selfNeedsLayout() ? child->marginTop() : child->collapsedMarginTop();
yPosEstimate += max(marginInfo.margin(), childMarginTop);
}
+ yPosEstimate += getClearDelta(child, yPosEstimate);
return yPosEstimate;
}
-void RenderBlock::determineHorizontalPosition(RenderObject* child)
+void RenderBlock::determineHorizontalPosition(RenderBox* child)
{
if (style()->direction() == LTR) {
int xPos = borderLeft() + paddingLeft();
@@ -1128,7 +1170,7 @@ void RenderBlock::determineHorizontalPosition(RenderObject* child)
// Some objects (e.g., tables, horizontal rules, overflow:auto blocks) avoid floats. They need
// to shift over as necessary to dodge any floats that might get in the way.
if (child->avoidsFloats()) {
- int leftOff = leftOffset(m_height);
+ int leftOff = leftOffset(height(), false);
if (style()->textAlign() != WEBKIT_CENTER && child->style()->marginLeft().type() != Auto) {
if (child->marginLeft() < 0)
leftOff += child->marginLeft();
@@ -1140,17 +1182,17 @@ void RenderBlock::determineHorizontalPosition(RenderObject* child)
// width computation will take into account the delta between |leftOff| and |xPos|
// so that we can just pass the content width in directly to the |calcHorizontalMargins|
// function.
- static_cast<RenderBox*>(child)->calcHorizontalMargins(child->style()->marginLeft(), child->style()->marginRight(), lineWidth(child->yPos()));
+ child->calcHorizontalMargins(child->style()->marginLeft(), child->style()->marginRight(), lineWidth(child->y(), false));
chPos = leftOff + child->marginLeft();
}
}
- view()->addLayoutDelta(IntSize(child->xPos() - chPos, 0));
- child->setPos(chPos, child->yPos());
+ view()->addLayoutDelta(IntSize(child->x() - chPos, 0));
+ child->setLocation(chPos, child->y());
} else {
- int xPos = m_width - borderRight() - paddingRight() - verticalScrollbarWidth();
+ int xPos = width() - borderRight() - paddingRight() - verticalScrollbarWidth();
int chPos = xPos - (child->width() + child->marginRight());
if (child->avoidsFloats()) {
- int rightOff = rightOffset(m_height);
+ int rightOff = rightOffset(height(), false);
if (style()->textAlign() != WEBKIT_CENTER && child->style()->marginRight().type() != Auto) {
if (child->marginRight() < 0)
rightOff -= child->marginRight();
@@ -1161,12 +1203,12 @@ void RenderBlock::determineHorizontalPosition(RenderObject* child)
// width computation will take into account the delta between |rightOff| and |xPos|
// so that we can just pass the content width in directly to the |calcHorizontalMargins|
// function.
- static_cast<RenderBox*>(child)->calcHorizontalMargins(child->style()->marginLeft(), child->style()->marginRight(), lineWidth(child->yPos()));
+ child->calcHorizontalMargins(child->style()->marginLeft(), child->style()->marginRight(), lineWidth(child->y(), false));
chPos = rightOff - child->marginRight() - child->width();
}
}
- view()->addLayoutDelta(IntSize(child->xPos() - chPos, 0));
- child->setPos(chPos, child->yPos());
+ view()->addLayoutDelta(IntSize(child->x() - chPos, 0));
+ child->setLocation(chPos, child->y());
}
}
@@ -1178,13 +1220,13 @@ void RenderBlock::setCollapsedBottomMargin(const MarginInfo& marginInfo)
setMaxBottomMargins(max(maxBottomPosMargin(), marginInfo.posMargin()), max(maxBottomNegMargin(), marginInfo.negMargin()));
if (!marginInfo.bottomQuirk())
- m_bottomMarginQuirk = false;
+ setBottomMarginQuirk(false);
if (marginInfo.bottomQuirk() && marginBottom() == 0)
// We have no bottom margin and our last child has a quirky margin.
// We will pick up this quirky margin and pass it through.
// This deals with the <td><div><p> case.
- m_bottomMarginQuirk = true;
+ setBottomMarginQuirk(true);
}
}
@@ -1205,17 +1247,17 @@ void RenderBlock::handleBottomOfBlock(int top, int bottom, MarginInfo& marginInf
// If we can't collapse with children then go ahead and add in the bottom margin.
if (!marginInfo.canCollapseWithBottom() && !marginInfo.canCollapseWithTop()
&& (!style()->htmlHacks() || !marginInfo.quirkContainer() || !marginInfo.bottomQuirk()))
- m_height += marginInfo.margin();
+ setHeight(height() + marginInfo.margin());
// Now add in our bottom border/padding.
- m_height += bottom;
+ setHeight(height() + bottom);
// Negative margins can cause our height to shrink below our minimal height (border/padding).
// If this happens, ensure that the computed height is increased to the minimal height.
- m_height = max(m_height, top + bottom);
+ setHeight(max(height(), top + bottom));
// Always make sure our overflow height is at least our height.
- m_overflowHeight = max(m_height, m_overflowHeight);
+ m_overflowHeight = max(height(), m_overflowHeight);
// Update our bottom collapsed margin info.
setCollapsedBottomMargin(marginInfo);
@@ -1244,11 +1286,11 @@ void RenderBlock::layoutBlockChildren(bool relayoutChildren, int& maxFloatBottom
int top = borderTop() + paddingTop();
int bottom = borderBottom() + paddingBottom() + horizontalScrollbarHeight();
- m_height = m_overflowHeight = top;
+ m_overflowHeight = top;
+ setHeight(m_overflowHeight);
// The margin struct caches all our current margin collapsing state. The compact struct caches state when we encounter compacts,
MarginInfo marginInfo(this, top, bottom);
- CompactInfo compactInfo;
// Fieldsets need to find their legend and position it inside the border of the object.
// The legend then gets skipped during normal layout.
@@ -1257,12 +1299,14 @@ void RenderBlock::layoutBlockChildren(bool relayoutChildren, int& maxFloatBottom
int previousFloatBottom = 0;
maxFloatBottom = 0;
- RenderObject* child = firstChild();
- while (child) {
- if (legend == child) {
- child = child->nextSibling();
+ RenderBox* next = firstChildBox();
+
+ while (next) {
+ RenderBox* child = next;
+ next = child->nextSiblingBox();
+
+ if (legend == child)
continue; // Skip the legend, since it has already been positioned up in the fieldset's border.
- }
int oldTopPosMargin = maxTopPosMargin();
int oldTopNegMargin = maxTopNegMargin();
@@ -1279,12 +1323,8 @@ void RenderBlock::layoutBlockChildren(bool relayoutChildren, int& maxFloatBottom
// Handle the four types of special elements first. These include positioned content, floating content, compacts and
// run-ins. When we encounter these four types of objects, we don't actually lay them out as normal flow blocks.
- bool handled = false;
- RenderObject* next = handleSpecialChild(child, marginInfo, compactInfo, handled);
- if (handled) {
- child = next;
+ if (handleSpecialChild(child, marginInfo))
continue;
- }
// The child is a normal flow object. Compute its vertical margins now.
child->calcVerticalMargins();
@@ -1301,28 +1341,31 @@ void RenderBlock::layoutBlockChildren(bool relayoutChildren, int& maxFloatBottom
int yPosEstimate = estimateVerticalPosition(child, marginInfo);
// Cache our old rect so that we can dirty the proper repaint rects if the child moves.
- IntRect oldRect(child->xPos(), child->yPos() , child->width(), child->height());
-
+ IntRect oldRect(child->x(), child->y() , child->width(), child->height());
+#ifndef NDEBUG
+ IntSize oldLayoutDelta = view()->layoutDelta();
+#endif
// Go ahead and position the child as though it didn't collapse with the top.
- view()->addLayoutDelta(IntSize(0, child->yPos() - yPosEstimate));
- child->setPos(child->xPos(), yPosEstimate);
+ view()->addLayoutDelta(IntSize(0, child->y() - yPosEstimate));
+ child->setLocation(child->x(), yPosEstimate);
bool markDescendantsWithFloats = false;
- if (yPosEstimate != oldRect.y() && !child->avoidsFloats() && child->containsFloats())
+ if (yPosEstimate != oldRect.y() && !child->avoidsFloats() && child->isBlockFlow() && toRenderBlock(child)->containsFloats())
markDescendantsWithFloats = true;
else if (!child->avoidsFloats() || child->shrinkToAvoidFloats()) {
// If an element might be affected by the presence of floats, then always mark it for
// layout.
int fb = max(previousFloatBottom, floatBottom());
- if (fb > m_height || fb > yPosEstimate)
+ if (fb > yPosEstimate)
markDescendantsWithFloats = true;
}
- if (markDescendantsWithFloats)
- child->markAllDescendantsWithFloatsForLayout();
+ if (child->isRenderBlock()) {
+ if (markDescendantsWithFloats)
+ toRenderBlock(child)->markAllDescendantsWithFloatsForLayout();
- if (child->isRenderBlock())
- previousFloatBottom = max(previousFloatBottom, oldRect.y() + static_cast<RenderBlock*>(child)->floatBottom());
+ previousFloatBottom = max(previousFloatBottom, oldRect.y() + toRenderBlock(child)->floatBottom());
+ }
bool childHadLayout = child->m_everHadLayout;
bool childNeededLayout = child->needsLayout();
@@ -1331,10 +1374,28 @@ void RenderBlock::layoutBlockChildren(bool relayoutChildren, int& maxFloatBottom
// Now determine the correct ypos based off examination of collapsing margin
// values.
- collapseMargins(child, marginInfo, yPosEstimate);
+ int yBeforeClear = collapseMargins(child, marginInfo);
// Now check for clear.
- clearFloatsIfNeeded(child, marginInfo, oldTopPosMargin, oldTopNegMargin);
+ int yAfterClear = clearFloatsIfNeeded(child, marginInfo, oldTopPosMargin, oldTopNegMargin, yBeforeClear);
+
+ view()->addLayoutDelta(IntSize(0, yPosEstimate - yAfterClear));
+ child->setLocation(child->x(), yAfterClear);
+
+ // Now we have a final y position. See if it really does end up being different from our estimate.
+ if (yAfterClear != yPosEstimate) {
+ if (child->shrinkToAvoidFloats()) {
+ // The child's width depends on the line width.
+ // When the child shifts to clear an item, its width can
+ // change (because it has more available line width).
+ // So go ahead and mark the item as dirty.
+ child->setChildNeedsLayout(true, false);
+ }
+ if (!child->avoidsFloats() && child->isBlockFlow() && toRenderBlock(child)->containsFloats())
+ toRenderBlock(child)->markAllDescendantsWithFloatsForLayout();
+ // Our guess was wrong. Make the child lay itself out again.
+ child->layoutIfNeeded();
+ }
// We are no longer at the top of the block if we encounter a non-empty child.
// This has to be done after checking for clear, so that margins can be reset if a clear occurred.
@@ -1345,25 +1406,26 @@ void RenderBlock::layoutBlockChildren(bool relayoutChildren, int& maxFloatBottom
determineHorizontalPosition(child);
// Update our height now that the child has been placed in the correct position.
- m_height += child->height();
+ setHeight(height() + child->height());
if (child->style()->marginBottomCollapse() == MSEPARATE) {
- m_height += child->marginBottom();
+ setHeight(height() + child->marginBottom());
marginInfo.clearMargin();
}
// If the child has overhanging floats that intrude into following siblings (or possibly out
// of this block), then the parent gets notified of the floats now.
- maxFloatBottom = max(maxFloatBottom, addOverhangingFloats(static_cast<RenderBlock *>(child), -child->xPos(), -child->yPos(), !childNeededLayout));
-
- // Update our overflow in case the child spills out the block.
- m_overflowTop = min(m_overflowTop, child->yPos() + child->overflowTop(false));
- m_overflowHeight = max(m_overflowHeight, m_height + child->overflowHeight(false) - child->height());
- m_overflowWidth = max(child->xPos() + child->overflowWidth(false), m_overflowWidth);
- m_overflowLeft = min(child->xPos() + child->overflowLeft(false), m_overflowLeft);
-
- // Insert our compact into the block margin if we have one.
- insertCompactIfNeeded(child, compactInfo);
+ if (child->isBlockFlow() && toRenderBlock(child)->containsFloats())
+ maxFloatBottom = max(maxFloatBottom, addOverhangingFloats(toRenderBlock(child), -child->x(), -child->y(), !childNeededLayout));
+
+ // Update our visual overflow in case the child spills out the block, but only if we were going to paint
+ // the child block ourselves.
+ if (!child->hasSelfPaintingLayer()) {
+ m_overflowTop = min(m_overflowTop, child->y() + child->overflowTop(false));
+ m_overflowHeight = max(m_overflowHeight, height() + child->overflowHeight(false) - child->height());
+ m_overflowWidth = max(child->x() + child->overflowWidth(false), m_overflowWidth);
+ m_overflowLeft = min(child->x() + child->overflowLeft(false), m_overflowLeft);
+ }
- IntSize childOffset(child->xPos() - oldRect.x(), child->yPos() - oldRect.y());
+ IntSize childOffset(child->x() - oldRect.x(), child->y() - oldRect.y());
if (childOffset.width() || childOffset.height()) {
view()->addLayoutDelta(childOffset);
@@ -1377,7 +1439,7 @@ void RenderBlock::layoutBlockChildren(bool relayoutChildren, int& maxFloatBottom
if (!childHadLayout && child->checkForRepaintDuringLayout())
child->repaint();
- child = child->nextSibling();
+ ASSERT(oldLayoutDelta == view()->layoutDelta());
}
// Now do the handling of the bottom of the block, adding in our bottom border/padding and
@@ -1390,7 +1452,7 @@ bool RenderBlock::layoutOnlyPositionedObjects()
if (!posChildNeedsLayout() || normalChildNeedsLayout() || selfNeedsLayout())
return false;
- LayoutStateMaintainer statePusher(view(), this, IntSize(xPos(), yPos()), !m_hasColumns);
+ LayoutStateMaintainer statePusher(view(), this, IntSize(x(), y()), hasColumns() || hasTransform() || hasReflection());
if (needsPositionedMovementLayout()) {
tryLayoutDoingPositionedMovementOnly();
@@ -1404,7 +1466,7 @@ bool RenderBlock::layoutOnlyPositionedObjects()
statePusher.pop();
if (hasOverflowClip())
- m_layer->updateScrollInfoAfterLayout();
+ layer()->updateScrollInfoAfterLayout();
setNeedsLayout(false);
return true;
@@ -1413,7 +1475,7 @@ bool RenderBlock::layoutOnlyPositionedObjects()
void RenderBlock::layoutPositionedObjects(bool relayoutChildren)
{
if (m_positionedObjects) {
- RenderObject* r;
+ RenderBox* r;
Iterator end = m_positionedObjects->end();
for (Iterator it = m_positionedObjects->begin(); it != end; ++it) {
r = *it;
@@ -1421,11 +1483,11 @@ void RenderBlock::layoutPositionedObjects(bool relayoutChildren)
// non-positioned block. Rather than trying to detect all of these movement cases, we just always lay out positioned
// objects that are positioned implicitly like this. Such objects are rare, and so in typical DHTML menu usage (where everything is
// positioned explicitly) this should not incur a performance penalty.
- if (relayoutChildren || (r->hasStaticY() && r->parent() != this && r->parent()->isBlockFlow()))
+ if (relayoutChildren || (r->style()->hasStaticY() && r->parent() != this && r->parent()->isBlockFlow()))
r->setChildNeedsLayout(true, false);
// If relayoutChildren is set and we have percentage padding, we also need to invalidate the child's pref widths.
- if (relayoutChildren && (r->style()->paddingLeft().isPercent() || r->style()->paddingRight().isPercent()))
+ //if (relayoutChildren && (r->style()->paddingLeft().isPercent() || r->style()->paddingRight().isPercent()))
r->setPrefWidthsDirty(true, false);
// 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
@@ -1440,7 +1502,7 @@ void RenderBlock::layoutPositionedObjects(bool relayoutChildren)
void RenderBlock::markPositionedObjectsForLayout()
{
if (m_positionedObjects) {
- RenderObject* r;
+ RenderBox* r;
Iterator end = m_positionedObjects->end();
for (Iterator it = m_positionedObjects->begin(); it != end; ++it) {
r = *it;
@@ -1469,7 +1531,7 @@ void RenderBlock::repaintOverhangingFloats(bool paintAllDescendants)
// Only repaint the object if it is overhanging, is not in its own layer, and
// is our responsibility to paint (m_shouldPaint is set). When paintAllDescendants is true, the latter
// condition is replaced with being a descendant of us.
- if (r->m_bottom > m_height && (paintAllDescendants && r->m_renderer->isDescendantOf(this) || r->m_shouldPaint) && !r->m_renderer->hasLayer()) {
+ if (r->m_bottom > height() && ((paintAllDescendants && r->m_renderer->isDescendantOf(this)) || r->m_shouldPaint) && !r->m_renderer->hasSelfPaintingLayer()) {
r->m_renderer->repaint();
r->m_renderer->repaintOverhangingFloats();
}
@@ -1477,18 +1539,18 @@ void RenderBlock::repaintOverhangingFloats(bool paintAllDescendants)
view()->enableLayoutState();
}
}
-
+
void RenderBlock::paint(PaintInfo& paintInfo, int tx, int ty)
{
- tx += m_x;
- ty += m_y;
+ tx += x();
+ ty += y();
PaintPhase phase = paintInfo.phase;
// Check if we need to do anything at all.
// FIXME: Could eliminate the isRoot() check if we fix background painting so that the RenderView
// paints the root's background.
- if (!isInlineFlow() && !isRoot()) {
+ if (!isRoot()) {
IntRect overflowBox = overflowRect(false);
overflowBox.inflate(maximalOutlineSize(paintInfo.phase));
overflowBox.move(tx, ty);
@@ -1496,52 +1558,69 @@ void RenderBlock::paint(PaintInfo& paintInfo, int tx, int ty)
return;
}
- bool useControlClip = phase != PaintPhaseBlockBackground && phase != PaintPhaseSelfOutline && phase != PaintPhaseMask && hasControlClip();
+ bool pushedClip = pushContentsClip(paintInfo, tx, ty);
+ paintObject(paintInfo, tx, ty);
+ if (pushedClip)
+ popContentsClip(paintInfo, phase, tx, ty);
- // Push a clip.
- if (useControlClip) {
- if (phase == PaintPhaseOutline)
- paintInfo.phase = PaintPhaseChildOutlines;
- else if (phase == PaintPhaseChildBlockBackground) {
- paintInfo.phase = PaintPhaseBlockBackground;
- paintObject(paintInfo, tx, ty);
- paintInfo.phase = PaintPhaseChildBlockBackgrounds;
- }
- IntRect clipRect(controlClipRect(tx, ty));
- if (clipRect.isEmpty())
- return;
- paintInfo.context->save();
- paintInfo.context->clip(clipRect);
- }
+ // Our scrollbar widgets paint exactly when we tell them to, so that they work properly with
+ // z-index. We paint after we painted the background/border, so that the scrollbars will
+ // sit above the background/border.
+ if (hasOverflowClip() && style()->visibility() == VISIBLE && (phase == PaintPhaseBlockBackground || phase == PaintPhaseChildBlockBackground))
+ layer()->paintOverflowControls(paintInfo.context, tx, ty, paintInfo.rect);
+}
- paintObject(paintInfo, tx, ty);
-
- // Pop the clip.
- if (useControlClip) {
- paintInfo.context->restore();
- if (phase == PaintPhaseOutline) {
- paintInfo.phase = PaintPhaseSelfOutline;
- paintObject(paintInfo, tx, ty);
- paintInfo.phase = phase;
- } else if (phase == PaintPhaseChildBlockBackground)
- paintInfo.phase = phase;
+void RenderBlock::paintColumnRules(PaintInfo& paintInfo, int tx, int ty)
+{
+ const Color& ruleColor = style()->columnRuleColor();
+ bool ruleTransparent = style()->columnRuleIsTransparent();
+ EBorderStyle ruleStyle = style()->columnRuleStyle();
+ int ruleWidth = style()->columnRuleWidth();
+ int colGap = columnGap();
+ bool renderRule = ruleStyle > BHIDDEN && !ruleTransparent && ruleWidth <= colGap;
+ if (!renderRule)
+ return;
+
+ // We need to do multiple passes, breaking up our child painting into strips.
+ int currXOffset = 0;
+ int ruleAdd = borderLeft() + paddingLeft();
+ int ruleX = 0;
+ Vector<IntRect>* colRects = columnRects();
+ unsigned colCount = colRects->size();
+ for (unsigned i = 0; i < colCount; i++) {
+ // For each rect, we clip to the rect, and then we adjust our coords.
+ IntRect colRect = colRects->at(i);
+
+ // Move to the next position.
+ if (style()->direction() == LTR) {
+ ruleX += colRect.width() + colGap / 2;
+ currXOffset += colRect.width() + colGap;
+ } else {
+ ruleX -= (colRect.width() + colGap / 2);
+ currXOffset -= (colRect.width() + colGap);
+ }
+
+ // Now paint the column rule.
+ if (i < colCount - 1) {
+ int ruleStart = tx + ruleX - ruleWidth / 2 + ruleAdd;
+ int ruleEnd = ruleStart + ruleWidth;
+ int ruleTop = ty + borderTop() + paddingTop();
+ int ruleBottom = ruleTop + contentHeight();
+ drawLineForBoxSide(paintInfo.context, ruleStart, ruleTop, ruleEnd, ruleBottom,
+ style()->direction() == LTR ? BSLeft : BSRight, ruleColor, style()->color(), ruleStyle, 0, 0);
+ }
+
+ ruleX = currXOffset;
}
}
-void RenderBlock::paintColumns(PaintInfo& paintInfo, int tx, int ty, bool paintingFloats)
+void RenderBlock::paintColumnContents(PaintInfo& paintInfo, int tx, int ty, bool paintingFloats)
{
// We need to do multiple passes, breaking up our child painting into strips.
GraphicsContext* context = paintInfo.context;
int currXOffset = 0;
int currYOffset = 0;
- int ruleAdd = borderLeft() + paddingLeft();
- int ruleX = 0;
int colGap = columnGap();
- const Color& ruleColor = style()->columnRuleColor();
- bool ruleTransparent = style()->columnRuleIsTransparent();
- EBorderStyle ruleStyle = style()->columnRuleStyle();
- int ruleWidth = style()->columnRuleWidth();
- bool renderRule = !paintingFloats && ruleStyle > BHIDDEN && !ruleTransparent && ruleWidth <= colGap;
Vector<IntRect>* colRects = columnRects();
unsigned colCount = colRects->size();
for (unsigned i = 0; i < colCount; i++) {
@@ -1567,27 +1646,14 @@ void RenderBlock::paintColumns(PaintInfo& paintInfo, int tx, int ty, bool painti
paintContents(info, finalX, finalY);
// Move to the next position.
- if (style()->direction() == LTR) {
- ruleX += colRect.width() + colGap / 2;
+ if (style()->direction() == LTR)
currXOffset += colRect.width() + colGap;
- } else {
- ruleX -= (colRect.width() + colGap / 2);
+ else
currXOffset -= (colRect.width() + colGap);
- }
-
+
currYOffset -= colRect.height();
context->restore();
-
- // Now paint the column rule.
- if (renderRule && paintInfo.phase == PaintPhaseForeground && i < colCount - 1) {
- int ruleStart = ruleX - ruleWidth / 2 + ruleAdd;
- int ruleEnd = ruleStart + ruleWidth;
- drawBorder(paintInfo.context, tx + ruleStart, ty + borderTop() + paddingTop(), tx + ruleEnd, ty + borderTop() + paddingTop() + contentHeight(),
- style()->direction() == LTR ? BSLeft : BSRight, ruleColor, style()->color(), ruleStyle, 0, 0);
- }
-
- ruleX = currXOffset;
}
}
@@ -1600,7 +1666,7 @@ void RenderBlock::paintContents(PaintInfo& paintInfo, int tx, int ty)
return;
if (childrenInline())
- paintLines(paintInfo, tx, ty);
+ m_lineBoxes.paint(this, paintInfo, tx, ty);
else
paintChildren(paintInfo, tx, ty);
}
@@ -1616,23 +1682,23 @@ void RenderBlock::paintChildren(PaintInfo& paintInfo, int tx, int ty)
info.paintingRoot = paintingRootForChildren(paintInfo);
bool isPrinting = document()->printing();
- for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
+ for (RenderBox* child = firstChildBox(); child; child = child->nextSiblingBox()) {
// Check for page-break-before: always, and if it's set, break and bail.
if (isPrinting && !childrenInline() && child->style()->pageBreakBefore() == PBALWAYS &&
- inRootBlockContext() && (ty + child->yPos()) > paintInfo.rect.y() &&
- (ty + child->yPos()) < paintInfo.rect.bottom()) {
- view()->setBestTruncatedAt(ty + child->yPos(), this, true);
+ inRootBlockContext() && (ty + child->y()) > paintInfo.rect.y() &&
+ (ty + child->y()) < paintInfo.rect.bottom()) {
+ view()->setBestTruncatedAt(ty + child->y(), this, true);
return;
}
- if (!child->hasLayer() && !child->isFloating())
+ if (!child->hasSelfPaintingLayer() && !child->isFloating())
child->paint(info, tx, ty);
// Check for page-break-after: always, and if it's set, break and bail.
if (isPrinting && !childrenInline() && child->style()->pageBreakAfter() == PBALWAYS &&
- inRootBlockContext() && (ty + child->yPos() + child->height()) > paintInfo.rect.y() &&
- (ty + child->yPos() + child->height()) < paintInfo.rect.bottom()) {
- view()->setBestTruncatedAt(ty + child->yPos() + child->height() + max(0, child->collapsedMarginBottom()), this, true);
+ inRootBlockContext() && (ty + child->y() + child->height()) > paintInfo.rect.y() &&
+ (ty + child->y() + child->height()) < paintInfo.rect.bottom()) {
+ view()->setBestTruncatedAt(ty + child->y() + child->height() + max(0, child->collapsedMarginBottom()), this, true);
return;
}
}
@@ -1642,9 +1708,10 @@ void RenderBlock::paintCaret(PaintInfo& paintInfo, int tx, int ty, CaretType typ
{
SelectionController* selection = type == CursorCaret ? document()->frame()->selection() : document()->frame()->dragCaretController();
- // Ask the SelectionController if the caret should be painted by this block
+ // Paint the caret if the SelectionController says so or if caret browsing is enabled
+ bool caretBrowsing = document()->frame()->settings() && document()->frame()->settings()->caretBrowsingEnabled();
RenderObject* caretPainter = selection->caretRenderer();
- if (caretPainter == this && selection->isContentEditable()) {
+ if (caretPainter == this && (selection->isContentEditable() || caretBrowsing)) {
// Convert the painting offset into the local coordinate system of this renderer,
// to match the localCaretRect computed by the SelectionController
offsetForContents(tx, ty);
@@ -1660,14 +1727,12 @@ void RenderBlock::paintObject(PaintInfo& paintInfo, int tx, int ty)
{
PaintPhase paintPhase = paintInfo.phase;
- // If we're a repositioned run-in or a compact, don't paint background/borders.
- bool inlineFlow = isInlineFlow();
-
// 1. paint background, borders etc
- if (!inlineFlow &&
- (paintPhase == PaintPhaseBlockBackground || paintPhase == PaintPhaseChildBlockBackground) &&
- hasBoxDecorations() && style()->visibility() == VISIBLE) {
- paintBoxDecorations(paintInfo, tx, ty);
+ if ((paintPhase == PaintPhaseBlockBackground || paintPhase == PaintPhaseChildBlockBackground) && style()->visibility() == VISIBLE) {
+ if (hasBoxDecorations())
+ paintBoxDecorations(paintInfo, tx, ty);
+ if (hasColumns())
+ paintColumnRules(paintInfo, tx, ty);
}
if (paintPhase == PaintPhaseMask && style()->visibility() == VISIBLE) {
@@ -1683,12 +1748,12 @@ void RenderBlock::paintObject(PaintInfo& paintInfo, int tx, int ty)
int scrolledX = tx;
int scrolledY = ty;
if (hasOverflowClip())
- m_layer->subtractScrolledContentOffset(scrolledX, scrolledY);
+ layer()->subtractScrolledContentOffset(scrolledX, scrolledY);
// 2. paint contents
if (paintPhase != PaintPhaseSelfOutline) {
- if (m_hasColumns)
- paintColumns(paintInfo, scrolledX, scrolledY);
+ if (hasColumns())
+ paintColumnContents(paintInfo, scrolledX, scrolledY);
else
paintContents(paintInfo, scrolledX, scrolledY);
}
@@ -1696,30 +1761,30 @@ void RenderBlock::paintObject(PaintInfo& paintInfo, int tx, int ty)
// 3. paint selection
// FIXME: Make this work with multi column layouts. For now don't fill gaps.
bool isPrinting = document()->printing();
- if (!inlineFlow && !isPrinting && !m_hasColumns)
+ if (!isPrinting && !hasColumns())
paintSelection(paintInfo, scrolledX, scrolledY); // Fill in gaps in selection on lines and between blocks.
// 4. paint floats.
- if (!inlineFlow && (paintPhase == PaintPhaseFloat || paintPhase == PaintPhaseSelection || paintPhase == PaintPhaseTextClip)) {
- if (m_hasColumns)
- paintColumns(paintInfo, scrolledX, scrolledY, true);
+ if (paintPhase == PaintPhaseFloat || paintPhase == PaintPhaseSelection || paintPhase == PaintPhaseTextClip) {
+ if (hasColumns())
+ paintColumnContents(paintInfo, scrolledX, scrolledY, true);
else
paintFloats(paintInfo, scrolledX, scrolledY, paintPhase == PaintPhaseSelection || paintPhase == PaintPhaseTextClip);
}
// 5. paint outline.
- if (!inlineFlow && (paintPhase == PaintPhaseOutline || paintPhase == PaintPhaseSelfOutline) && hasOutline() && style()->visibility() == VISIBLE)
- RenderObject::paintOutline(paintInfo.context, tx, ty, width(), height(), style());
+ if ((paintPhase == PaintPhaseOutline || paintPhase == PaintPhaseSelfOutline) && hasOutline() && style()->visibility() == VISIBLE)
+ paintOutline(paintInfo.context, tx, ty, width(), height(), style());
// 6. paint continuation outlines.
- if (!inlineFlow && (paintPhase == PaintPhaseOutline || paintPhase == PaintPhaseChildOutlines)) {
- if (continuation() && continuation()->hasOutline() && continuation()->style()->visibility() == VISIBLE) {
- RenderFlow* inlineFlow = static_cast<RenderFlow*>(continuation()->element()->renderer());
- if (!inlineFlow->hasLayer())
- containingBlock()->addContinuationWithOutline(inlineFlow);
- else if (!inlineFlow->firstLineBox())
- inlineFlow->paintOutline(paintInfo.context, tx - xPos() + inlineFlow->containingBlock()->xPos(),
- ty - yPos() + inlineFlow->containingBlock()->yPos());
+ if ((paintPhase == PaintPhaseOutline || paintPhase == PaintPhaseChildOutlines)) {
+ if (inlineContinuation() && inlineContinuation()->hasOutline() && inlineContinuation()->style()->visibility() == VISIBLE) {
+ RenderInline* inlineRenderer = toRenderInline(inlineContinuation()->node()->renderer());
+ if (!inlineRenderer->hasSelfPaintingLayer())
+ containingBlock()->addContinuationWithOutline(inlineRenderer);
+ else if (!inlineRenderer->firstLineBox())
+ inlineRenderer->paintOutline(paintInfo.context, tx - x() + inlineRenderer->containingBlock()->x(),
+ ty - y() + inlineRenderer->containingBlock()->y());
}
paintContinuationOutlines(paintInfo, tx, ty);
}
@@ -1727,7 +1792,7 @@ void RenderBlock::paintObject(PaintInfo& paintInfo, int tx, int ty)
// 7. paint caret.
// If the caret's node's render object's containing block is this block, and the paint action is PaintPhaseForeground,
// then paint the caret.
- if (!inlineFlow && paintPhase == PaintPhaseForeground) {
+ if (paintPhase == PaintPhaseForeground) {
paintCaret(paintInfo, scrolledX, scrolledY, CursorCaret);
paintCaret(paintInfo, scrolledX, scrolledY, DragCaret);
}
@@ -1742,11 +1807,11 @@ void RenderBlock::paintFloats(PaintInfo& paintInfo, int tx, int ty, bool preserv
DeprecatedPtrListIterator<FloatingObject> it(*m_floatingObjects);
for (; (r = it.current()); ++it) {
// Only paint the object if our m_shouldPaint flag is set.
- if (r->m_shouldPaint && !r->m_renderer->hasLayer()) {
+ if (r->m_shouldPaint && !r->m_renderer->hasSelfPaintingLayer()) {
PaintInfo currentPaintInfo(paintInfo);
currentPaintInfo.phase = preservePhase ? paintInfo.phase : PaintPhaseBlockBackground;
- int currentTX = tx + r->m_left - r->m_renderer->xPos() + r->m_renderer->marginLeft();
- int currentTY = ty + r->m_top - r->m_renderer->yPos() + r->m_renderer->marginTop();
+ int currentTX = tx + r->m_left - r->m_renderer->x() + r->m_renderer->marginLeft();
+ int currentTY = ty + r->m_top - r->m_renderer->y() + r->m_renderer->marginTop();
r->m_renderer->paint(currentPaintInfo, currentTX, currentTY);
if (!preservePhase) {
currentPaintInfo.phase = PaintPhaseChildBlockBackgrounds;
@@ -1770,8 +1835,8 @@ void RenderBlock::paintEllipsisBoxes(PaintInfo& paintInfo, int tx, int ty)
if (style()->visibility() == VISIBLE && paintInfo.phase == PaintPhaseForeground) {
// We can check the first box and last box and avoid painting if we don't
// intersect.
- int yPos = ty + firstLineBox()->yPos();
- int h = lastLineBox()->yPos() + lastLineBox()->height() - firstLineBox()->yPos();
+ int yPos = ty + firstLineBox()->y();
+ int h = lastLineBox()->y() + lastLineBox()->height() - firstLineBox()->y();
if (yPos >= paintInfo.rect.bottom() || yPos + h <= paintInfo.rect.y())
return;
@@ -1779,7 +1844,7 @@ void RenderBlock::paintEllipsisBoxes(PaintInfo& paintInfo, int tx, int ty)
// them. Note that boxes can easily overlap, so we can't make any assumptions
// based off positions of our first line box or our last line box.
for (RootInlineBox* curr = firstRootBox(); curr; curr = curr->nextRootBox()) {
- yPos = ty + curr->yPos();
+ yPos = ty + curr->y();
h = curr->height();
if (curr->ellipsisBox() && yPos < paintInfo.rect.bottom() && yPos + h > paintInfo.rect.y())
curr->paintEllipsisBox(paintInfo, tx, ty);
@@ -1787,22 +1852,22 @@ void RenderBlock::paintEllipsisBoxes(PaintInfo& paintInfo, int tx, int ty)
}
}
-ContinuationOutlineTableMap* continuationOutlineTable()
+static ContinuationOutlineTableMap* continuationOutlineTable()
{
DEFINE_STATIC_LOCAL(ContinuationOutlineTableMap, table, ());
return &table;
}
-void RenderBlock::addContinuationWithOutline(RenderFlow* flow)
+void RenderBlock::addContinuationWithOutline(RenderInline* flow)
{
// We can't make this work if the inline is in a layer. We'll just rely on the broken
// way of painting.
- ASSERT(!flow->layer());
+ ASSERT(!flow->layer() && !flow->isInlineContinuation());
ContinuationOutlineTableMap* table = continuationOutlineTable();
- RenderFlowSequencedSet* continuations = table->get(this);
+ ListHashSet<RenderInline*>* continuations = table->get(this);
if (!continuations) {
- continuations = new RenderFlowSequencedSet;
+ continuations = new ListHashSet<RenderInline*>;
table->set(this, continuations);
}
@@ -1815,19 +1880,19 @@ void RenderBlock::paintContinuationOutlines(PaintInfo& info, int tx, int ty)
if (table->isEmpty())
return;
- RenderFlowSequencedSet* continuations = table->get(this);
+ ListHashSet<RenderInline*>* continuations = table->get(this);
if (!continuations)
return;
// Paint each continuation outline.
- RenderFlowSequencedSet::iterator end = continuations->end();
- for (RenderFlowSequencedSet::iterator it = continuations->begin(); it != end; ++it) {
+ ListHashSet<RenderInline*>::iterator end = continuations->end();
+ for (ListHashSet<RenderInline*>::iterator it = continuations->begin(); it != end; ++it) {
// Need to add in the coordinates of the intervening blocks.
- RenderFlow* flow = *it;
+ RenderInline* flow = *it;
RenderBlock* block = flow->containingBlock();
for ( ; block && block != this; block = block->containingBlock()) {
- tx += block->xPos();
- ty += block->yPos();
+ tx += block->x();
+ ty += block->y();
}
ASSERT(block);
flow->paintOutline(info.context, tx, ty);
@@ -1848,9 +1913,9 @@ void RenderBlock::setSelectionState(SelectionState s)
if ((s == SelectionStart && selectionState() == SelectionEnd) ||
(s == SelectionEnd && selectionState() == SelectionStart))
- m_selectionState = SelectionBoth;
+ RenderBox::setSelectionState(SelectionBoth);
else
- m_selectionState = s;
+ RenderBox::setSelectionState(s);
RenderBlock* cb = containingBlock();
if (cb && !cb->isRenderView())
@@ -1859,12 +1924,12 @@ void RenderBlock::setSelectionState(SelectionState s)
bool RenderBlock::shouldPaintSelectionGaps() const
{
- return m_selectionState != SelectionNone && style()->visibility() == VISIBLE && isSelectionRoot();
+ return selectionState() != SelectionNone && style()->visibility() == VISIBLE && isSelectionRoot();
}
bool RenderBlock::isSelectionRoot() const
{
- if (!element())
+ if (!node())
return false;
// FIXME: Eventually tables should have to learn how to fill gaps between cells, at least in simple non-spanning cases.
@@ -1877,27 +1942,27 @@ bool RenderBlock::isSelectionRoot() const
return true;
if (view() && view()->selectionStart()) {
- Node* startElement = view()->selectionStart()->element();
- if (startElement && startElement->rootEditableElement() == element())
+ Node* startElement = view()->selectionStart()->node();
+ if (startElement && startElement->rootEditableElement() == node())
return true;
}
return false;
}
-GapRects RenderBlock::selectionGapRects()
+GapRects RenderBlock::selectionGapRectsForRepaint(RenderBoxModelObject* /*repaintContainer*/)
{
ASSERT(!needsLayout());
if (!shouldPaintSelectionGaps())
return GapRects();
- // FIXME: this is broken with transforms
- FloatPoint absContentPoint = localToAbsoluteForContent(FloatPoint());
+ // FIXME: this is broken with transforms and a non-null repaintContainer
+ FloatPoint absContentPoint = localToAbsolute(FloatPoint());
if (hasOverflowClip())
absContentPoint -= layer()->scrolledContentOffset();
- int lastTop = -borderTopExtra();
+ int lastTop = 0;
int lastLeft = leftSelectionOffset(this, lastTop);
int lastRight = rightSelectionOffset(this, lastTop);
@@ -1907,7 +1972,7 @@ GapRects RenderBlock::selectionGapRects()
void RenderBlock::paintSelection(PaintInfo& paintInfo, int tx, int ty)
{
if (shouldPaintSelectionGaps() && paintInfo.phase == PaintPhaseForeground) {
- int lastTop = -borderTopExtra();
+ int lastTop = 0;
int lastLeft = leftSelectionOffset(this, lastTop);
int lastRight = rightSelectionOffset(this, lastTop);
paintInfo.context->save();
@@ -1916,21 +1981,24 @@ void RenderBlock::paintSelection(PaintInfo& paintInfo, int tx, int ty)
}
}
-static void clipOutPositionedObjects(const RenderObject::PaintInfo* paintInfo, int tx, int ty, ListHashSet<RenderObject*>* positionedObjects)
+#ifndef BUILDING_ON_TIGER
+static void clipOutPositionedObjects(const RenderObject::PaintInfo* paintInfo, int tx, int ty, ListHashSet<RenderBox*>* positionedObjects)
{
if (!positionedObjects)
return;
- ListHashSet<RenderObject*>::const_iterator end = positionedObjects->end();
- for (ListHashSet<RenderObject*>::const_iterator it = positionedObjects->begin(); it != end; ++it) {
- RenderObject* r = *it;
- paintInfo->context->clipOut(IntRect(tx + r->xPos(), ty + r->yPos(), r->width(), r->height()));
+ ListHashSet<RenderBox*>::const_iterator end = positionedObjects->end();
+ for (ListHashSet<RenderBox*>::const_iterator it = positionedObjects->begin(); it != end; ++it) {
+ RenderBox* r = *it;
+ paintInfo->context->clipOut(IntRect(tx + r->x(), ty + r->y(), r->width(), r->height()));
}
}
+#endif
GapRects RenderBlock::fillSelectionGaps(RenderBlock* rootBlock, int blockX, int blockY, int tx, int ty,
int& lastTop, int& lastLeft, int& lastRight, const PaintInfo* paintInfo)
{
+#ifndef BUILDING_ON_TIGER
// IMPORTANT: Callers of this method that intend for painting to happen need to do a save/restore.
// Clip out floating and positioned objects when painting selection gaps.
if (paintInfo) {
@@ -1938,7 +2006,7 @@ GapRects RenderBlock::fillSelectionGaps(RenderBlock* rootBlock, int blockX, int
clipOutPositionedObjects(paintInfo, tx, ty, m_positionedObjects);
if (isBody() || isRoot()) // The <body> must make sure to examine its containingBlock's positioned objects.
for (RenderBlock* cb = containingBlock(); cb && !cb->isRenderView(); cb = cb->containingBlock())
- clipOutPositionedObjects(paintInfo, cb->xPos(), cb->yPos(), cb->m_positionedObjects);
+ clipOutPositionedObjects(paintInfo, cb->x(), cb->y(), cb->m_positionedObjects);
if (m_floatingObjects) {
for (DeprecatedPtrListIterator<FloatingObject> it(*m_floatingObjects); it.current(); ++it) {
FloatingObject* r = it.current();
@@ -1948,6 +2016,7 @@ GapRects RenderBlock::fillSelectionGaps(RenderBlock* rootBlock, int blockX, int
}
}
}
+#endif
// FIXME: overflow: auto/scroll regions need more math here, since painting in the border box is different from painting in the padding box (one is scrolled, the other is
// fixed).
@@ -1955,7 +2024,7 @@ GapRects RenderBlock::fillSelectionGaps(RenderBlock* rootBlock, int blockX, int
if (!isBlockFlow()) // FIXME: Make multi-column selection gap filling work someday.
return result;
- if (m_hasColumns || hasTransform()) {
+ if (hasColumns() || hasTransform()) {
// FIXME: We should learn how to gap fill multiple columns and transforms eventually.
lastTop = (ty - blockY) + height();
lastLeft = leftSelectionOffset(rootBlock, height());
@@ -1969,8 +2038,8 @@ GapRects RenderBlock::fillSelectionGaps(RenderBlock* rootBlock, int blockX, int
result = fillBlockSelectionGaps(rootBlock, blockX, blockY, tx, ty, lastTop, lastLeft, lastRight, paintInfo);
// Go ahead and fill the vertical gap all the way to the bottom of our block if the selection extends past our block.
- if (rootBlock == this && (m_selectionState != SelectionBoth && m_selectionState != SelectionEnd))
- result.uniteCenter(fillVerticalSelectionGap(lastTop, lastLeft, lastRight, ty + height() + borderBottomExtra(),
+ if (rootBlock == this && (selectionState() != SelectionBoth && selectionState() != SelectionEnd))
+ result.uniteCenter(fillVerticalSelectionGap(lastTop, lastLeft, lastRight, ty + height(),
rootBlock, blockX, blockY, paintInfo));
return result;
}
@@ -2007,14 +2076,14 @@ GapRects RenderBlock::fillInlineSelectionGaps(RenderBlock* rootBlock, int blockX
result.uniteCenter(fillVerticalSelectionGap(lastTop, lastLeft, lastRight, ty + selTop,
rootBlock, blockX, blockY, paintInfo));
- if (!paintInfo || ty + selTop < paintInfo->rect.bottom() && ty + selTop + selHeight > paintInfo->rect.y())
+ if (!paintInfo || (ty + selTop < paintInfo->rect.bottom() && ty + selTop + selHeight > paintInfo->rect.y()))
result.unite(curr->fillLineSelectionGap(selTop, selHeight, rootBlock, blockX, blockY, tx, ty, paintInfo));
lastSelectedLine = curr;
}
if (containsStart && !lastSelectedLine)
- // Selection must start just after our last line.
+ // VisibleSelection must start just after our last line.
lastSelectedLine = lastRootBox();
if (lastSelectedLine && selectionState() != SelectionEnd && selectionState() != SelectionBoth) {
@@ -2032,10 +2101,10 @@ GapRects RenderBlock::fillBlockSelectionGaps(RenderBlock* rootBlock, int blockX,
GapRects result;
// Go ahead and jump right to the first block child that contains some selected objects.
- RenderObject* curr;
- for (curr = firstChild(); curr && curr->selectionState() == SelectionNone; curr = curr->nextSibling()) { }
+ RenderBox* curr;
+ for (curr = firstChildBox(); curr && curr->selectionState() == SelectionNone; curr = curr->nextSiblingBox()) { }
- for (bool sawSelectionEnd = false; curr && !sawSelectionEnd; curr = curr->nextSibling()) {
+ for (bool sawSelectionEnd = false; curr && !sawSelectionEnd; curr = curr->nextSiblingBox()) {
SelectionState childState = curr->selectionState();
if (childState == SelectionBoth || childState == SelectionEnd)
sawSelectionEnd = true;
@@ -2058,7 +2127,7 @@ GapRects RenderBlock::fillBlockSelectionGaps(RenderBlock* rootBlock, int blockX,
if (childState == SelectionEnd || childState == SelectionInside)
// Fill the gap above the object.
result.uniteCenter(fillVerticalSelectionGap(lastTop, lastLeft, lastRight,
- ty + curr->yPos(), rootBlock, blockX, blockY, paintInfo));
+ ty + curr->y(), rootBlock, blockX, blockY, paintInfo));
// Only fill side gaps for objects that paint their own selection if we know for sure the selection is going to extend all the way *past*
// our object. We know this if the selection did not end inside our object.
@@ -2070,19 +2139,19 @@ GapRects RenderBlock::fillBlockSelectionGaps(RenderBlock* rootBlock, int blockX,
getHorizontalSelectionGapInfo(childState, leftGap, rightGap);
if (leftGap)
- result.uniteLeft(fillLeftSelectionGap(this, curr->xPos(), curr->yPos(), curr->height(), rootBlock, blockX, blockY, tx, ty, paintInfo));
+ result.uniteLeft(fillLeftSelectionGap(this, curr->x(), curr->y(), curr->height(), rootBlock, blockX, blockY, tx, ty, paintInfo));
if (rightGap)
- result.uniteRight(fillRightSelectionGap(this, curr->xPos() + curr->width(), curr->yPos(), curr->height(), rootBlock, blockX, blockY, tx, ty, paintInfo));
+ result.uniteRight(fillRightSelectionGap(this, curr->x() + curr->width(), curr->y(), curr->height(), rootBlock, blockX, blockY, tx, ty, paintInfo));
// Update lastTop to be just underneath the object. lastLeft and lastRight extend as far as
// they can without bumping into floating or positioned objects. Ideally they will go right up
// to the border of the root selection block.
- lastTop = (ty - blockY) + (curr->yPos() + curr->height());
- lastLeft = leftSelectionOffset(rootBlock, curr->yPos() + curr->height());
- lastRight = rightSelectionOffset(rootBlock, curr->yPos() + curr->height());
+ lastTop = (ty - blockY) + (curr->y() + curr->height());
+ lastLeft = leftSelectionOffset(rootBlock, curr->y() + curr->height());
+ lastRight = rightSelectionOffset(rootBlock, curr->y() + curr->height());
} else if (childState != SelectionNone)
// We must be a block that has some selected object inside it. Go ahead and recur.
- result.unite(static_cast<RenderBlock*>(curr)->fillSelectionGaps(rootBlock, blockX, blockY, tx + curr->xPos(), ty + curr->yPos(),
+ result.unite(toRenderBlock(curr)->fillSelectionGaps(rootBlock, blockX, blockY, tx + curr->x(), ty + curr->y(),
lastTop, lastLeft, lastRight, paintInfo));
}
return result;
@@ -2162,19 +2231,19 @@ void RenderBlock::getHorizontalSelectionGapInfo(SelectionState state, bool& left
(state == RenderObject::SelectionEnd && !ltr);
}
-int RenderBlock::leftSelectionOffset(RenderBlock* rootBlock, int y)
+int RenderBlock::leftSelectionOffset(RenderBlock* rootBlock, int yPos)
{
- int left = leftOffset(y);
+ int left = leftOffset(yPos, false);
if (left == borderLeft() + paddingLeft()) {
if (rootBlock != this)
// The border can potentially be further extended by our containingBlock().
- return containingBlock()->leftSelectionOffset(rootBlock, y + yPos());
+ return containingBlock()->leftSelectionOffset(rootBlock, yPos + y());
return left;
}
else {
RenderBlock* cb = this;
while (cb != rootBlock) {
- left += cb->xPos();
+ left += cb->x();
cb = cb->containingBlock();
}
}
@@ -2182,35 +2251,35 @@ int RenderBlock::leftSelectionOffset(RenderBlock* rootBlock, int y)
return left;
}
-int RenderBlock::rightSelectionOffset(RenderBlock* rootBlock, int y)
+int RenderBlock::rightSelectionOffset(RenderBlock* rootBlock, int yPos)
{
- int right = rightOffset(y);
+ int right = rightOffset(yPos, false);
if (right == (contentWidth() + (borderLeft() + paddingLeft()))) {
if (rootBlock != this)
// The border can potentially be further extended by our containingBlock().
- return containingBlock()->rightSelectionOffset(rootBlock, y + yPos());
+ return containingBlock()->rightSelectionOffset(rootBlock, yPos + y());
return right;
}
else {
RenderBlock* cb = this;
while (cb != rootBlock) {
- right += cb->xPos();
+ right += cb->x();
cb = cb->containingBlock();
}
}
return right;
}
-void RenderBlock::insertPositionedObject(RenderObject *o)
+void RenderBlock::insertPositionedObject(RenderBox* o)
{
// Create the list of special objects if we don't aleady have one
if (!m_positionedObjects)
- m_positionedObjects = new ListHashSet<RenderObject*>;
+ m_positionedObjects = new ListHashSet<RenderBox*>;
m_positionedObjects->add(o);
}
-void RenderBlock::removePositionedObject(RenderObject *o)
+void RenderBlock::removePositionedObject(RenderBox* o)
{
if (m_positionedObjects)
m_positionedObjects->remove(o);
@@ -2221,11 +2290,11 @@ void RenderBlock::removePositionedObjects(RenderBlock* o)
if (!m_positionedObjects)
return;
- RenderObject* r;
+ RenderBox* r;
Iterator end = m_positionedObjects->end();
- Vector<RenderObject*, 16> deadObjects;
+ Vector<RenderBox*, 16> deadObjects;
for (Iterator it = m_positionedObjects->begin(); it != end; ++it) {
r = *it;
@@ -2249,7 +2318,7 @@ void RenderBlock::removePositionedObjects(RenderBlock* o)
m_positionedObjects->remove(deadObjects.at(i));
}
-void RenderBlock::insertFloatingObject(RenderObject *o)
+void RenderBlock::insertFloatingObject(RenderBox* o)
{
ASSERT(o->isFloating());
@@ -2276,14 +2345,14 @@ void RenderBlock::insertFloatingObject(RenderObject *o)
newObj->m_top = -1;
newObj->m_bottom = -1;
newObj->m_width = o->width() + o->marginLeft() + o->marginRight();
- newObj->m_shouldPaint = !o->hasLayer(); // If a layer exists, the float will paint itself. Otherwise someone else will.
+ newObj->m_shouldPaint = !o->hasSelfPaintingLayer(); // If a layer exists, the float will paint itself. Otherwise someone else will.
newObj->m_isDescendant = true;
newObj->m_renderer = o;
m_floatingObjects->append(newObj);
}
-void RenderBlock::removeFloatingObject(RenderObject *o)
+void RenderBlock::removeFloatingObject(RenderBox* o)
{
if (m_floatingObjects) {
DeprecatedPtrListIterator<FloatingObject> it(*m_floatingObjects);
@@ -2318,7 +2387,7 @@ bool RenderBlock::positionNewFloats()
lastFloat = m_floatingObjects->getPrev();
}
- int y = m_height;
+ int y = height();
// The float cannot start above the y position of the last positioned float.
if (lastFloat)
@@ -2333,7 +2402,7 @@ bool RenderBlock::positionNewFloats()
continue;
}
- RenderObject* o = f->m_renderer;
+ RenderBox* o = f->m_renderer;
int _height = o->height() + o->marginTop() + o->marginBottom();
int ro = rightOffset(); // Constant part of right offset.
@@ -2342,7 +2411,7 @@ bool RenderBlock::positionNewFloats()
if (ro - lo < fwidth)
fwidth = ro - lo; // Never look for more than what will be available.
- IntRect oldRect(o->xPos(), o->yPos() , o->width(), o->height());
+ IntRect oldRect(o->x(), o->y() , o->width(), o->height());
if (o->style()->clear() & CLEFT)
y = max(leftBottom(), y);
@@ -2359,7 +2428,7 @@ bool RenderBlock::positionNewFloats()
}
fx = max(0, fx);
f->m_left = fx;
- o->setPos(fx + o->marginLeft(), y + o->marginTop());
+ o->setLocation(fx + o->marginLeft(), y + o->marginTop());
} else {
int heightRemainingLeft = 1;
int heightRemainingRight = 1;
@@ -2369,7 +2438,7 @@ bool RenderBlock::positionNewFloats()
fx = rightRelOffset(y, ro, false, &heightRemainingRight);
}
f->m_left = fx - f->m_width;
- o->setPos(fx - o->marginRight() - o->width(), y + o->marginTop());
+ o->setLocation(fx - o->marginRight() - o->width(), y + o->marginTop());
}
f->m_top = y;
@@ -2402,8 +2471,8 @@ void RenderBlock::newLine(EClear clear)
default:
break;
}
- if (m_height < newY)
- m_height = newY;
+ if (height() < newY)
+ setHeight(newY);
}
void RenderBlock::addPercentHeightDescendant(RenderBox* descendant)
@@ -2461,15 +2530,17 @@ void RenderBlock::removePercentHeightDescendant(RenderBox* descendant)
delete containerSet;
}
-int
-RenderBlock::leftOffset() const
+HashSet<RenderBox*>* RenderBlock::percentHeightDescendants() const
{
- return borderLeft()+paddingLeft();
+ return gPercentHeightDescendantsMap ? gPercentHeightDescendantsMap->get(this) : 0;
}
-int
-RenderBlock::leftRelOffset(int y, int fixedOffset, bool applyTextIndent,
- int *heightRemaining ) const
+int RenderBlock::leftOffset() const
+{
+ return borderLeft() + paddingLeft();
+}
+
+int RenderBlock::leftRelOffset(int y, int fixedOffset, bool applyTextIndent, int* heightRemaining) const
{
int left = fixedOffset;
if (m_floatingObjects) {
@@ -2487,7 +2558,7 @@ RenderBlock::leftRelOffset(int y, int fixedOffset, bool applyTextIndent,
}
}
- if (applyTextIndent && m_firstLine && style()->direction() == LTR) {
+ if (applyTextIndent && style()->direction() == LTR) {
int cw = 0;
if (style()->textIndent().isPercent())
cw = containingBlock()->availableWidth();
@@ -2497,15 +2568,12 @@ RenderBlock::leftRelOffset(int y, int fixedOffset, bool applyTextIndent,
return left;
}
-int
-RenderBlock::rightOffset() const
+int RenderBlock::rightOffset() const
{
return borderLeft() + paddingLeft() + availableWidth();
}
-int
-RenderBlock::rightRelOffset(int y, int fixedOffset, bool applyTextIndent,
- int *heightRemaining ) const
+int RenderBlock::rightRelOffset(int y, int fixedOffset, bool applyTextIndent, int* heightRemaining) const
{
int right = fixedOffset;
@@ -2524,7 +2592,7 @@ RenderBlock::rightRelOffset(int y, int fixedOffset, bool applyTextIndent,
}
}
- if (applyTextIndent && m_firstLine && style()->direction() == RTL) {
+ if (applyTextIndent && style()->direction() == RTL) {
int cw = 0;
if (style()->textIndent().isPercent())
cw = containingBlock()->availableWidth();
@@ -2535,9 +2603,9 @@ RenderBlock::rightRelOffset(int y, int fixedOffset, bool applyTextIndent,
}
int
-RenderBlock::lineWidth(int y) const
+RenderBlock::lineWidth(int y, bool firstLine) const
{
- int result = rightOffset(y) - leftOffset(y);
+ int result = rightOffset(y, firstLine) - leftOffset(y, firstLine);
return (result < 0) ? 0 : result;
}
@@ -2578,7 +2646,7 @@ IntRect RenderBlock::floatRect() const
FloatingObject* r;
DeprecatedPtrListIterator<FloatingObject> it(*m_floatingObjects);
for (; (r = it.current()); ++it) {
- if (r->m_shouldPaint && !r->m_renderer->hasLayer()) {
+ if (r->m_shouldPaint && !r->m_renderer->hasSelfPaintingLayer()) {
IntRect childRect = r->m_renderer->overflowRect(false);
childRect.move(r->m_left + r->m_renderer->marginLeft(), r->m_top + r->m_renderer->marginTop());
result.unite(childRect);
@@ -2590,7 +2658,27 @@ IntRect RenderBlock::floatRect() const
int RenderBlock::lowestPosition(bool includeOverflowInterior, bool includeSelf) const
{
- int bottom = RenderFlow::lowestPosition(includeOverflowInterior, includeSelf);
+ if (!includeOverflowInterior && (hasOverflowClip() || hasControlClip()))
+ return includeSelf && width() > 0 ? overflowHeight(false) : 0;
+
+ int bottom = includeSelf && width() > 0 ? height() : 0;
+ if (!hasColumns()) {
+ // FIXME: Come up with a way to use the layer tree to avoid visiting all the kids.
+ // For now, we have to descend into all the children, since we may have a huge abs div inside
+ // a tiny rel div buried somewhere deep in our child tree. In this case we have to get to
+ // the abs div.
+ // See the last test case in https://bugs.webkit.org/show_bug.cgi?id=9314 for why this is a problem.
+ // For inline children, we miss relative positioned boxes that might be buried inside <span>s.
+ for (RenderObject* c = firstChild(); c; c = c->nextSibling()) {
+ if (!c->isFloatingOrPositioned() && c->isBox()) {
+ RenderBox* childBox = toRenderBox(c);
+ bottom = max(bottom, childBox->y() + childBox->lowestPosition(false));
+ }
+ }
+ }
+
+ if (includeSelf && isRelPositioned())
+ bottom += relativePositionOffsetY();
if (!includeOverflowInterior && hasOverflowClip())
return bottom;
@@ -2600,7 +2688,7 @@ int RenderBlock::lowestPosition(bool includeOverflowInterior, bool includeSelf)
bottom = max(bottom, m_overflowHeight + relativeOffset);
if (m_positionedObjects) {
- RenderObject* r;
+ RenderBox* r;
Iterator end = m_positionedObjects->end();
for (Iterator it = m_positionedObjects->begin(); it != end; ++it) {
r = *it;
@@ -2610,15 +2698,15 @@ int RenderBlock::lowestPosition(bool includeOverflowInterior, bool includeSelf)
// FIXME: Should work for overflow sections too.
// If a positioned object lies completely to the left of the root it will be unreachable via scrolling.
// Therefore we should not allow it to contribute to the lowest position.
- if (!isRenderView() || r->xPos() + r->width() > 0 || r->xPos() + r->rightmostPosition(false) > 0) {
- int lp = r->yPos() + r->lowestPosition(false);
+ if (!isRenderView() || r->x() + r->width() > 0 || r->x() + r->rightmostPosition(false) > 0) {
+ int lp = r->y() + r->lowestPosition(false);
bottom = max(bottom, lp + relativeOffset);
}
}
}
}
- if (m_hasColumns) {
+ if (hasColumns()) {
Vector<IntRect>* colRects = columnRects();
for (unsigned i = 0; i < colRects->size(); i++)
bottom = max(bottom, colRects->at(i).bottom() + relativeOffset);
@@ -2629,17 +2717,30 @@ int RenderBlock::lowestPosition(bool includeOverflowInterior, bool includeSelf)
FloatingObject* r;
DeprecatedPtrListIterator<FloatingObject> it(*m_floatingObjects);
for ( ; (r = it.current()); ++it ) {
- if (r->m_shouldPaint || r->m_renderer->hasLayer()) {
+ if (r->m_shouldPaint || r->m_renderer->hasSelfPaintingLayer()) {
int lp = r->m_top + r->m_renderer->marginTop() + r->m_renderer->lowestPosition(false);
bottom = max(bottom, lp + relativeOffset);
}
}
}
-
- if (!includeSelf && lastLineBox()) {
- int lp = lastLineBox()->yPos() + lastLineBox()->height();
- bottom = max(bottom, lp);
+ if (!includeSelf) {
+ bottom = max(bottom, borderTop() + paddingTop() + paddingBottom() + relativeOffset);
+ if (childrenInline()) {
+ if (lastLineBox()) {
+ int childBottomEdge = lastLineBox()->y() + lastLineBox()->height();
+ bottom = max(bottom, childBottomEdge + paddingBottom() + relativeOffset);
+ }
+ } else {
+ // Find the last normal flow child.
+ RenderBox* currBox = lastChildBox();
+ while (currBox && currBox->isFloatingOrPositioned())
+ currBox = currBox->previousSiblingBox();
+ if (currBox) {
+ int childBottomEdge = currBox->y() + currBox->height() + currBox->collapsedMarginBottom();
+ bottom = max(bottom, childBottomEdge + paddingBottom() + relativeOffset);
+ }
+ }
}
return bottom;
@@ -2647,7 +2748,27 @@ int RenderBlock::lowestPosition(bool includeOverflowInterior, bool includeSelf)
int RenderBlock::rightmostPosition(bool includeOverflowInterior, bool includeSelf) const
{
- int right = RenderFlow::rightmostPosition(includeOverflowInterior, includeSelf);
+ if (!includeOverflowInterior && (hasOverflowClip() || hasControlClip()))
+ return includeSelf && height() > 0 ? overflowWidth(false) : 0;
+
+ int right = includeSelf && height() > 0 ? width() : 0;
+
+ if (!hasColumns()) {
+ // FIXME: Come up with a way to use the layer tree to avoid visiting all the kids.
+ // For now, we have to descend into all the children, since we may have a huge abs div inside
+ // a tiny rel div buried somewhere deep in our child tree. In this case we have to get to
+ // the abs div.
+ for (RenderObject* c = firstChild(); c; c = c->nextSibling()) {
+ if (!c->isFloatingOrPositioned() && c->isBox()) {
+ RenderBox* childBox = toRenderBox(c);
+ right = max(right, childBox->x() + childBox->rightmostPosition(false));
+ }
+ }
+ }
+
+ if (includeSelf && isRelPositioned())
+ right += relativePositionOffsetX();
+
if (!includeOverflowInterior && hasOverflowClip())
return right;
@@ -2657,7 +2778,7 @@ int RenderBlock::rightmostPosition(bool includeOverflowInterior, bool includeSel
right = max(right, m_overflowWidth + relativeOffset);
if (m_positionedObjects) {
- RenderObject* r;
+ RenderBox* r;
Iterator end = m_positionedObjects->end();
for (Iterator it = m_positionedObjects->begin() ; it != end; ++it) {
r = *it;
@@ -2667,15 +2788,15 @@ int RenderBlock::rightmostPosition(bool includeOverflowInterior, bool includeSel
// FIXME: Should work for overflow sections too.
// If a positioned object lies completely above the root it will be unreachable via scrolling.
// Therefore we should not allow it to contribute to the rightmost position.
- if (!isRenderView() || r->yPos() + r->height() > 0 || r->yPos() + r->lowestPosition(false) > 0) {
- int rp = r->xPos() + r->rightmostPosition(false);
+ if (!isRenderView() || r->y() + r->height() > 0 || r->y() + r->lowestPosition(false) > 0) {
+ int rp = r->x() + r->rightmostPosition(false);
right = max(right, rp + relativeOffset);
}
}
}
}
- if (m_hasColumns) {
+ if (hasColumns()) {
// This only matters for LTR
if (style()->direction() == LTR)
right = max(columnRects()->last().right() + relativeOffset, right);
@@ -2686,21 +2807,33 @@ int RenderBlock::rightmostPosition(bool includeOverflowInterior, bool includeSel
FloatingObject* r;
DeprecatedPtrListIterator<FloatingObject> it(*m_floatingObjects);
for ( ; (r = it.current()); ++it ) {
- if (r->m_shouldPaint || r->m_renderer->hasLayer()) {
+ if (r->m_shouldPaint || r->m_renderer->hasSelfPaintingLayer()) {
int rp = r->m_left + r->m_renderer->marginLeft() + r->m_renderer->rightmostPosition(false);
right = max(right, rp + relativeOffset);
}
}
}
- if (!includeSelf && firstLineBox()) {
- for (InlineRunBox* currBox = firstLineBox(); currBox; currBox = currBox->nextLineBox()) {
- int rp = currBox->xPos() + currBox->width();
- // If this node is a root editable element, then the rightmostPosition should account for a caret at the end.
- // FIXME: Need to find another way to do this, since scrollbars could show when we don't want them to.
- if (node()->isContentEditable() && node() == node()->rootEditableElement() && style()->direction() == LTR)
- rp += 1;
- right = max(right, rp);
+ if (!includeSelf) {
+ right = max(right, borderLeft() + paddingLeft() + paddingRight() + relativeOffset);
+ if (childrenInline()) {
+ for (InlineRunBox* currBox = firstLineBox(); currBox; currBox = currBox->nextLineBox()) {
+ int childRightEdge = currBox->x() + currBox->width();
+
+ // If this node is a root editable element, then the rightmostPosition should account for a caret at the end.
+ // FIXME: Need to find another way to do this, since scrollbars could show when we don't want them to.
+ if (node() && node()->isContentEditable() && node() == node()->rootEditableElement() && style()->direction() == LTR && !paddingRight())
+ childRightEdge += 1;
+ right = max(right, childRightEdge + paddingRight() + relativeOffset);
+ }
+ } else {
+ // Walk all normal flow children.
+ for (RenderBox* currBox = firstChildBox(); currBox; currBox = currBox->nextSiblingBox()) {
+ if (currBox->isFloatingOrPositioned())
+ continue;
+ int childRightEdge = currBox->x() + currBox->width() + currBox->marginRight();
+ right = max(right, childRightEdge + paddingRight() + relativeOffset);
+ }
}
}
@@ -2709,7 +2842,26 @@ int RenderBlock::rightmostPosition(bool includeOverflowInterior, bool includeSel
int RenderBlock::leftmostPosition(bool includeOverflowInterior, bool includeSelf) const
{
- int left = RenderFlow::leftmostPosition(includeOverflowInterior, includeSelf);
+ if (!includeOverflowInterior && (hasOverflowClip() || hasControlClip()))
+ return includeSelf && height() > 0 ? overflowLeft(false) : width();
+
+ int left = includeSelf && height() > 0 ? 0 : width();
+ if (!hasColumns()) {
+ // FIXME: Come up with a way to use the layer tree to avoid visiting all the kids.
+ // For now, we have to descend into all the children, since we may have a huge abs div inside
+ // a tiny rel div buried somewhere deep in our child tree. In this case we have to get to
+ // the abs div.
+ for (RenderObject* c = firstChild(); c; c = c->nextSibling()) {
+ if (!c->isFloatingOrPositioned() && c->isBox()) {
+ RenderBox* childBox = toRenderBox(c);
+ left = min(left, childBox->x() + childBox->leftmostPosition(false));
+ }
+ }
+ }
+
+ if (includeSelf && isRelPositioned())
+ left += relativePositionOffsetX();
+
if (!includeOverflowInterior && hasOverflowClip())
return left;
@@ -2719,7 +2871,7 @@ int RenderBlock::leftmostPosition(bool includeOverflowInterior, bool includeSelf
left = min(left, m_overflowLeft + relativeOffset);
if (m_positionedObjects) {
- RenderObject* r;
+ RenderBox* r;
Iterator end = m_positionedObjects->end();
for (Iterator it = m_positionedObjects->begin(); it != end; ++it) {
r = *it;
@@ -2729,15 +2881,15 @@ int RenderBlock::leftmostPosition(bool includeOverflowInterior, bool includeSelf
// FIXME: Should work for overflow sections too.
// If a positioned object lies completely above the root it will be unreachable via scrolling.
// Therefore we should not allow it to contribute to the leftmost position.
- if (!isRenderView() || r->yPos() + r->height() > 0 || r->yPos() + r->lowestPosition(false) > 0) {
- int lp = r->xPos() + r->leftmostPosition(false);
+ if (!isRenderView() || r->y() + r->height() > 0 || r->y() + r->lowestPosition(false) > 0) {
+ int lp = r->x() + r->leftmostPosition(false);
left = min(left, lp + relativeOffset);
}
}
}
}
- if (m_hasColumns) {
+ if (hasColumns()) {
// This only matters for RTL
if (style()->direction() == RTL)
left = min(columnRects()->last().x() + relativeOffset, left);
@@ -2748,7 +2900,7 @@ int RenderBlock::leftmostPosition(bool includeOverflowInterior, bool includeSelf
FloatingObject* r;
DeprecatedPtrListIterator<FloatingObject> it(*m_floatingObjects);
for ( ; (r = it.current()); ++it ) {
- if (r->m_shouldPaint || r->m_renderer->hasLayer()) {
+ if (r->m_shouldPaint || r->m_renderer->hasSelfPaintingLayer()) {
int lp = r->m_left + r->m_renderer->marginLeft() + r->m_renderer->leftmostPosition(false);
left = min(left, lp + relativeOffset);
}
@@ -2757,7 +2909,7 @@ int RenderBlock::leftmostPosition(bool includeOverflowInterior, bool includeSelf
if (!includeSelf && firstLineBox()) {
for (InlineRunBox* currBox = firstLineBox(); currBox; currBox = currBox->nextLineBox())
- left = min(left, (int)currBox->xPos());
+ left = min(left, (int)currBox->x() + relativeOffset);
}
return left;
@@ -2834,31 +2986,33 @@ void RenderBlock::clearFloats()
// out of flow (like floating/positioned elements), and we also skip over any objects that may have shifted
// to avoid floats.
bool parentHasFloats = false;
- RenderObject *prev = previousSibling();
- while (prev && (!prev->isRenderBlock() || prev->avoidsFloats() || prev->isFloatingOrPositioned())) {
+ RenderObject* prev = previousSibling();
+ while (prev && (prev->isFloatingOrPositioned() || !prev->isBox() || !prev->isRenderBlock() || toRenderBlock(prev)->avoidsFloats())) {
if (prev->isFloating())
parentHasFloats = true;
prev = prev->previousSibling();
}
// First add in floats from the parent.
- int offset = m_y;
- if (parentHasFloats)
- addIntrudingFloats(static_cast<RenderBlock *>(parent()),
- parent()->borderLeft() + parent()->paddingLeft(), offset);
-
+ int offset = y();
+ if (parentHasFloats) {
+ RenderBlock* parentBlock = toRenderBlock(parent());
+ addIntrudingFloats(parentBlock, parentBlock->borderLeft() + parentBlock->paddingLeft(), offset);
+ }
+
int xoffset = 0;
if (prev)
- offset -= prev->yPos();
- else {
+ offset -= toRenderBox(prev)->y();
+ else if (parent()->isBox()) {
prev = parent();
- xoffset += prev->borderLeft() + prev->paddingLeft();
+ xoffset += toRenderBox(prev)->borderLeft() + toRenderBox(prev)->paddingLeft();
}
// Add overhanging floats from the previous RenderBlock, but only if it has a float that intrudes into our space.
- if (!prev->isRenderBlock()) return;
- RenderBlock* block = static_cast<RenderBlock *>(prev);
-
+ if (!prev || !prev->isRenderBlock())
+ return;
+
+ RenderBlock* block = toRenderBlock(prev);
if (block->m_floatingObjects && block->floatBottom() > offset)
addIntrudingFloats(block, xoffset, offset);
@@ -2913,7 +3067,7 @@ int RenderBlock::addOverhangingFloats(RenderBlock* child, int xoff, int yoff, bo
IntRect floatsOverflowRect;
DeprecatedPtrListIterator<FloatingObject> it(*child->m_floatingObjects);
for (FloatingObject* r; (r = it.current()); ++it) {
- int bottom = child->yPos() + r->m_bottom;
+ int bottom = child->y() + r->m_bottom;
lowestFloatBottom = max(lowestFloatBottom, bottom);
if (bottom > height()) {
@@ -2929,8 +3083,8 @@ int RenderBlock::addOverhangingFloats(RenderBlock* child, int xoff, int yoff, bo
// The nearest enclosing layer always paints the float (so that zindex and stacking
// behaves properly). We always want to propagate the desire to paint the float as
// far out as we can, to the outermost block that overlaps the float, stopping only
- // if we hit a layer boundary.
- if (r->m_renderer->enclosingLayer() == enclosingLayer())
+ // if we hit a self-painting layer boundary.
+ if (r->m_renderer->enclosingSelfPaintingLayer() == enclosingSelfPaintingLayer())
r->m_shouldPaint = false;
else
floatingObj->m_shouldPaint = false;
@@ -2942,7 +3096,8 @@ int RenderBlock::addOverhangingFloats(RenderBlock* child, int xoff, int yoff, bo
}
m_floatingObjects->append(floatingObj);
}
- } else if (makeChildPaintOtherFloats && !r->m_shouldPaint && !r->m_renderer->hasLayer() && r->m_renderer->isDescendantOf(child) && r->m_renderer->enclosingLayer() == child->enclosingLayer())
+ } else if (makeChildPaintOtherFloats && !r->m_shouldPaint && !r->m_renderer->hasSelfPaintingLayer() &&
+ r->m_renderer->isDescendantOf(child) && r->m_renderer->enclosingLayer() == child->enclosingLayer())
// The float is not overhanging from this block, so if it is a descendant of the child, the child should
// paint it (the other case is that it is intruding into the child), unless it has its own layer or enclosing
// layer.
@@ -2950,7 +3105,7 @@ int RenderBlock::addOverhangingFloats(RenderBlock* child, int xoff, int yoff, bo
// it should paint.
r->m_shouldPaint = true;
- if (r->m_shouldPaint && !r->m_renderer->hasLayer()) {
+ if (r->m_shouldPaint && !r->m_renderer->hasSelfPaintingLayer()) {
IntRect floatOverflowRect = r->m_renderer->overflowRect(false);
floatOverflowRect.move(r->m_left + r->m_renderer->marginLeft(), r->m_top + r->m_renderer->marginTop());
floatsOverflowRect.unite(floatOverflowRect);
@@ -3010,7 +3165,7 @@ void RenderBlock::addIntrudingFloats(RenderBlock* prev, int xoff, int yoff)
bool RenderBlock::avoidsFloats() const
{
// Floats can't intrude into our box if we have a non-auto column count or width.
- return RenderFlow::avoidsFloats() || !style()->hasAutoColumnCount() || !style()->hasAutoColumnWidth();
+ return RenderBox::avoidsFloats() || !style()->hasAutoColumnCount() || !style()->hasAutoColumnWidth();
}
bool RenderBlock::containsFloat(RenderObject* o)
@@ -3026,9 +3181,9 @@ bool RenderBlock::containsFloat(RenderObject* o)
return false;
}
-void RenderBlock::markAllDescendantsWithFloatsForLayout(RenderObject* floatToRemove)
+void RenderBlock::markAllDescendantsWithFloatsForLayout(RenderBox* floatToRemove, bool inLayout)
{
- setChildNeedsLayout(true);
+ setChildNeedsLayout(true, !inLayout);
if (floatToRemove)
removeFloatingObject(floatToRemove);
@@ -3036,14 +3191,16 @@ void RenderBlock::markAllDescendantsWithFloatsForLayout(RenderObject* floatToRem
// Iterate over our children and mark them as needed.
if (!childrenInline()) {
for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
- if (isBlockFlow() && !child->isFloatingOrPositioned() &&
- ((floatToRemove ? child->containsFloat(floatToRemove) : child->containsFloats()) || child->shrinkToAvoidFloats()))
- child->markAllDescendantsWithFloatsForLayout(floatToRemove);
+ if ((!floatToRemove && child->isFloatingOrPositioned()) || !child->isRenderBlock())
+ continue;
+ RenderBlock* childBlock = toRenderBlock(child);
+ if ((floatToRemove ? childBlock->containsFloat(floatToRemove) : childBlock->containsFloats()) || childBlock->shrinkToAvoidFloats())
+ childBlock->markAllDescendantsWithFloatsForLayout(floatToRemove, inLayout);
}
}
}
-int RenderBlock::getClearDelta(RenderObject *child)
+int RenderBlock::getClearDelta(RenderBox* child, int yPos)
{
// There is no need to compute clearance if we have no floats.
if (!containsFloats())
@@ -3071,11 +3228,11 @@ int RenderBlock::getClearDelta(RenderObject *child)
// to fit) and not all (we should be using nextFloatBottomBelow and looping).
// Do not allow tables to wrap in quirks or even in almost strict mode
// (ebay on the PLT, finance.yahoo.com in the real world, versiontracker.com forces even almost strict mode not to work)
- int result = clearSet ? max(0, bottom - child->yPos()) : 0;
+ int result = clearSet ? max(0, bottom - yPos) : 0;
if (!result && child->avoidsFloats() && child->style()->width().isFixed() &&
- child->minPrefWidth() > lineWidth(child->yPos()) && child->minPrefWidth() <= availableWidth() &&
+ child->minPrefWidth() > lineWidth(yPos, false) && child->minPrefWidth() <= availableWidth() &&
document()->inStrictMode())
- result = max(0, floatBottom() - child->yPos());
+ result = max(0, floatBottom() - yPos);
return result;
}
@@ -3099,12 +3256,10 @@ bool RenderBlock::isPointInOverflowControl(HitTestResult& result, int, int, int,
bool RenderBlock::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, int _x, int _y, int _tx, int _ty, HitTestAction hitTestAction)
{
- bool inlineFlow = isInlineFlow();
-
- int tx = _tx + m_x;
- int ty = _ty + m_y + borderTopExtra();
+ int tx = _tx + x();
+ int ty = _ty + y();
- if (!inlineFlow && !isRenderView()) {
+ if (!isRenderView()) {
// Check if we need to do anything at all.
IntRect overflowBox = overflowRect(false);
overflowBox.move(tx, ty);
@@ -3112,43 +3267,43 @@ bool RenderBlock::nodeAtPoint(const HitTestRequest& request, HitTestResult& resu
return false;
}
- if (isPointInOverflowControl(result, _x, _y, tx, ty)) {
- if (hitTestAction == HitTestBlockBackground) {
- updateHitTestResult(result, IntPoint(_x - tx, _y - ty));
- return true;
- }
- return false;
+ if ((hitTestAction == HitTestBlockBackground || hitTestAction == HitTestChildBlockBackground) && isPointInOverflowControl(result, _x, _y, tx, ty)) {
+ updateHitTestResult(result, IntPoint(_x - tx, _y - ty));
+ return true;
}
- // If we have lightweight control clipping, then we can't have any spillout.
- if (!hasControlClip() || controlClipRect(tx, ty).contains(_x, _y)) {
+ // If we have clipping, then we can't have any spillout.
+ bool useOverflowClip = hasOverflowClip() && !hasSelfPaintingLayer();
+ bool useClip = (hasControlClip() || useOverflowClip);
+ bool checkChildren = !useClip || (hasControlClip() ? controlClipRect(tx, ty).contains(_x, _y) : overflowClipRect(tx, ty).contains(_x, _y));
+ if (checkChildren) {
// Hit test descendants first.
int scrolledX = tx;
int scrolledY = ty;
if (hasOverflowClip())
- m_layer->subtractScrolledContentOffset(scrolledX, scrolledY);
+ layer()->subtractScrolledContentOffset(scrolledX, scrolledY);
// Hit test contents if we don't have columns.
- if (!m_hasColumns && hitTestContents(request, result, _x, _y, scrolledX, scrolledY, hitTestAction))
+ if (!hasColumns() && hitTestContents(request, result, _x, _y, scrolledX, scrolledY, hitTestAction))
return true;
// Hit test our columns if we do have them.
- if (m_hasColumns && hitTestColumns(request, result, _x, _y, scrolledX, scrolledY, hitTestAction))
+ if (hasColumns() && hitTestColumns(request, result, _x, _y, scrolledX, scrolledY, hitTestAction))
return true;
// Hit test floats.
if (hitTestAction == HitTestFloat && m_floatingObjects) {
if (isRenderView()) {
- scrolledX += static_cast<RenderView*>(this)->frameView()->scrollX();
- scrolledY += static_cast<RenderView*>(this)->frameView()->scrollY();
+ scrolledX += toRenderView(this)->frameView()->scrollX();
+ scrolledY += toRenderView(this)->frameView()->scrollY();
}
FloatingObject* o;
DeprecatedPtrListIterator<FloatingObject> it(*m_floatingObjects);
for (it.toLast(); (o = it.current()); --it) {
- if (o->m_shouldPaint && !o->m_renderer->hasLayer()) {
- int xoffset = scrolledX + o->m_left + o->m_renderer->marginLeft() - o->m_renderer->xPos();
- int yoffset = scrolledY + o->m_top + o->m_renderer->marginTop() - o->m_renderer->yPos();
+ if (o->m_shouldPaint && !o->m_renderer->hasSelfPaintingLayer()) {
+ int xoffset = scrolledX + o->m_left + o->m_renderer->marginLeft() - o->m_renderer->x();
+ int yoffset = scrolledY + o->m_top + o->m_renderer->marginTop() - o->m_renderer->y();
if (o->m_renderer->hitTest(request, result, IntPoint(_x, _y), xoffset, yoffset)) {
updateHitTestResult(result, IntPoint(_x - xoffset, _y - yoffset));
return true;
@@ -3159,11 +3314,10 @@ bool RenderBlock::nodeAtPoint(const HitTestRequest& request, HitTestResult& resu
}
// Now hit test our background
- if (!inlineFlow && (hitTestAction == HitTestBlockBackground || hitTestAction == HitTestChildBlockBackground)) {
- int topExtra = borderTopExtra();
- IntRect boundsRect(tx, ty - topExtra, m_width, m_height + topExtra + borderBottomExtra());
+ if (hitTestAction == HitTestBlockBackground || hitTestAction == HitTestChildBlockBackground) {
+ IntRect boundsRect(tx, ty, width(), height());
if (visibleToHitTesting() && boundsRect.contains(_x, _y)) {
- updateHitTestResult(result, IntPoint(_x - tx, _y - ty + topExtra));
+ updateHitTestResult(result, IntPoint(_x - tx, _y - ty));
return true;
}
}
@@ -3209,7 +3363,7 @@ bool RenderBlock::hitTestContents(const HitTestRequest& request, HitTestResult&
{
if (childrenInline() && !isTable()) {
// We have to hit-test our line boxes.
- if (hitTestLines(request, result, x, y, tx, ty, hitTestAction)) {
+ if (m_lineBoxes.hitTest(this, request, result, x, y, tx, ty, hitTestAction)) {
updateHitTestResult(result, IntPoint(x - tx, y - ty));
return true;
}
@@ -3218,10 +3372,8 @@ bool RenderBlock::hitTestContents(const HitTestRequest& request, HitTestResult&
HitTestAction childHitTest = hitTestAction;
if (hitTestAction == HitTestChildBlockBackgrounds)
childHitTest = HitTestChildBlockBackground;
- for (RenderObject* child = lastChild(); child; child = child->previousSibling()) {
- // FIXME: We have to skip over inline flows, since they can show up inside RenderTables at the moment (a demoted inline <form> for example). If we ever implement a
- // table-specific hit-test method (which we should do for performance reasons anyway), then we can remove this check.
- if (!child->hasLayer() && !child->isFloating() && !child->isInlineFlow() && child->nodeAtPoint(request, result, x, y, tx, ty, childHitTest)) {
+ for (RenderBox* child = lastChildBox(); child; child = child->previousSiblingBox()) {
+ if (!child->hasSelfPaintingLayer() && !child->isFloating() && child->nodeAtPoint(request, result, x, y, tx, ty, childHitTest)) {
updateHitTestResult(result, IntPoint(x - tx, y - ty));
return true;
}
@@ -3236,158 +3388,178 @@ Position RenderBlock::positionForBox(InlineBox *box, bool start) const
if (!box)
return Position();
- if (!box->object()->element())
- return Position(element(), start ? caretMinOffset() : caretMaxOffset());
+ if (!box->renderer()->node())
+ return Position(node(), start ? caretMinOffset() : caretMaxOffset());
if (!box->isInlineTextBox())
- return Position(box->object()->element(), start ? box->object()->caretMinOffset() : box->object()->caretMaxOffset());
+ return Position(box->renderer()->node(), start ? box->renderer()->caretMinOffset() : box->renderer()->caretMaxOffset());
InlineTextBox *textBox = static_cast<InlineTextBox *>(box);
- return Position(box->object()->element(), start ? textBox->start() : textBox->start() + textBox->len());
+ return Position(box->renderer()->node(), start ? textBox->start() : textBox->start() + textBox->len());
}
Position RenderBlock::positionForRenderer(RenderObject* renderer, bool start) const
{
if (!renderer)
- return Position(element(), 0);
+ return Position(node(), 0);
- Node* node = renderer->element() ? renderer->element() : element();
- if (!node)
+ Node* n = renderer->node() ? renderer->node() : node();
+ if (!n)
return Position();
- ASSERT(renderer == node->renderer());
+ ASSERT(renderer == n->renderer());
int offset = start ? renderer->caretMinOffset() : renderer->caretMaxOffset();
// FIXME: This was a runtime check that seemingly couldn't fail; changed it to an assertion for now.
- ASSERT(!node->isCharacterDataNode() || renderer->isText());
+ ASSERT(!n->isCharacterDataNode() || renderer->isText());
- return Position(node, offset);
+ return Position(n, offset);
}
-VisiblePosition RenderBlock::positionForCoordinates(int x, int y)
+// FIXME: This function should go on RenderObject as an instance method. Then
+// all cases in which positionForPoint recurs could call this instead to
+// prevent crossing editable boundaries. This would require many tests.
+static VisiblePosition positionForPointRespectingEditingBoundaries(RenderBox* parent, RenderBox* child, const IntPoint& pointInParentCoordinates)
{
- if (isTable())
- return RenderFlow::positionForCoordinates(x, y);
+ IntPoint pointInChildCoordinates(pointInParentCoordinates - child->location());
- int top = borderTop();
- int bottom = top + borderTopExtra() + paddingTop() + contentHeight() + paddingBottom() + borderBottomExtra();
+ // If this is an anonymous renderer, we just recur normally
+ Node* childNode = child->node();
+ if (!childNode)
+ return child->positionForPoint(pointInChildCoordinates);
- int left = borderLeft();
- int right = left + paddingLeft() + contentWidth() + paddingRight();
+ // Otherwise, first make sure that the editability of the parent and child agree.
+ // If they don't agree, then we return a visible position just before or after the child
+ RenderObject* ancestor = parent;
+ while (ancestor && !ancestor->node())
+ ancestor = ancestor->parent();
- Node* n = element();
-
- int contentsX = x;
- int contentsY = y;
- offsetForContents(contentsX, contentsY);
+ // If we can't find an ancestor to check editability on, or editability is unchanged, we recur like normal
+ if (!ancestor || ancestor->node()->isContentEditable() == childNode->isContentEditable())
+ return child->positionForPoint(pointInChildCoordinates);
- if (isReplaced()) {
- if (y < 0 || y < height() && x < 0)
- return VisiblePosition(n, caretMinOffset(), DOWNSTREAM);
- if (y >= height() || y >= 0 && x >= width())
- return VisiblePosition(n, caretMaxOffset(), DOWNSTREAM);
- }
+ // Otherwise return before or after the child, depending on if the click was left or right of the child
+ int childMidX = child->width() / 2;
+ if (pointInChildCoordinates.x() < childMidX)
+ return ancestor->createVisiblePosition(childNode->nodeIndex(), DOWNSTREAM);
+ return ancestor->createVisiblePosition(childNode->nodeIndex() + 1, UPSTREAM);
+}
- // If we start inside the shadow tree, we will stay inside (even if the point is above or below).
- if (!(n && n->isShadowNode()) && !childrenInline()) {
- // Don't return positions inside editable roots for coordinates outside those roots, except for coordinates outside
- // a document that is entirely editable.
- bool isEditableRoot = n && n->rootEditableElement() == n && !n->hasTagName(bodyTag) && !n->hasTagName(htmlTag);
-
- if (y < top || (isEditableRoot && (y < bottom && x < left))) {
- if (!isEditableRoot)
- if (RenderObject* c = firstChild()) { // FIXME: This code doesn't make any sense. This child could be an inline or a positioned element or a float or a compact, etc.
- VisiblePosition p = c->positionForCoordinates(contentsX - c->xPos(), contentsY - c->yPos());
- if (p.isNotNull())
- return p;
- }
- if (n) {
- if (Node* sp = n->shadowParentNode())
- n = sp;
- if (Node* p = n->parent())
- return VisiblePosition(p, n->nodeIndex(), DOWNSTREAM);
- }
- return VisiblePosition(n, 0, DOWNSTREAM);
- }
+VisiblePosition RenderBlock::positionForPointWithInlineChildren(const IntPoint& pointInContents)
+{
+ ASSERT(childrenInline());
- if (y >= bottom || (isEditableRoot && (y >= top && x >= right))) {
- if (!isEditableRoot)
- if (RenderObject* c = lastChild()) { // FIXME: This code doesn't make any sense. This child could be an inline or a positioned element or a float or a compact, ect.
- VisiblePosition p = c->positionForCoordinates(contentsX - c->xPos(), contentsY - c->yPos());
- if (p.isNotNull())
- return p;
- }
- if (n) {
- if (Node* sp = n->shadowParentNode())
- n = sp;
- if (Node* p = n->parent())
- return VisiblePosition(p, n->nodeIndex() + 1, DOWNSTREAM);
- }
- return VisiblePosition(n, 0, DOWNSTREAM);
+ if (!firstRootBox())
+ return createVisiblePosition(0, DOWNSTREAM);
+
+ // look for the closest line box in the root box which is at the passed-in y coordinate
+ InlineBox* closestBox = 0;
+ RootInlineBox* firstRootBoxWithChildren = 0;
+ RootInlineBox* lastRootBoxWithChildren = 0;
+ for (RootInlineBox* root = firstRootBox(); root; root = root->nextRootBox()) {
+ if (!root->firstChild())
+ continue;
+ if (!firstRootBoxWithChildren)
+ firstRootBoxWithChildren = root;
+ lastRootBoxWithChildren = root;
+
+ // set the bottom based on whether there is a next root box
+ // FIXME: This will consider nextRootBox even if it has no children, and maybe it shouldn't.
+ int bottom;
+ if (root->nextRootBox()) {
+ // FIXME: We would prefer to make the break point halfway between the bottom
+ // of the previous root box and the top of the next root box.
+ bottom = root->nextRootBox()->topOverflow();
+ } else
+ bottom = root->bottomOverflow() + verticalLineClickFudgeFactor;
+
+ // check if this root line box is located at this y coordinate
+ if (pointInContents.y() < bottom) {
+ closestBox = root->closestLeafChildForXPos(pointInContents.x());
+ if (closestBox)
+ break;
}
}
- if (childrenInline()) {
- if (!firstRootBox())
- return VisiblePosition(n, 0, DOWNSTREAM);
+ Settings* settings = document()->settings();
+ bool useWindowsBehavior = settings && settings->editingBehavior() == EditingWindowsBehavior;
- if (contentsY < firstRootBox()->topOverflow() - verticalLineClickFudgeFactor)
- // y coordinate is above first root line box
- return VisiblePosition(positionForBox(firstRootBox()->firstLeafChild(), true), DOWNSTREAM);
-
- // look for the closest line box in the root box which is at the passed-in y coordinate
- for (RootInlineBox* root = firstRootBox(); root; root = root->nextRootBox()) {
- // set the bottom based on whether there is a next root box
- if (root->nextRootBox())
- // FIXME: make the break point halfway between the bottom of the previous root box and the top of the next root box
- bottom = root->nextRootBox()->topOverflow();
- else
- bottom = root->bottomOverflow() + verticalLineClickFudgeFactor;
- // check if this root line box is located at this y coordinate
- if (contentsY < bottom && root->firstChild()) {
- InlineBox* closestBox = root->closestLeafChildForXPos(x);
- if (closestBox)
- // pass the box a y position that is inside it
- return closestBox->object()->positionForCoordinates(contentsX, closestBox->m_y);
- }
+ if (useWindowsBehavior && !closestBox && lastRootBoxWithChildren) {
+ // y coordinate is below last root line box, pretend we hit it
+ closestBox = lastRootBoxWithChildren->closestLeafChildForXPos(pointInContents.x());
+ }
+
+ if (closestBox) {
+ if (!useWindowsBehavior && pointInContents.y() < firstRootBoxWithChildren->topOverflow() - verticalLineClickFudgeFactor) {
+ // y coordinate is above first root line box, so return the start of the first
+ return VisiblePosition(positionForBox(firstRootBoxWithChildren->firstLeafChild(), true), DOWNSTREAM);
}
- if (lastRootBox())
- // y coordinate is below last root line box
- return VisiblePosition(positionForBox(lastRootBox()->lastLeafChild(), false), DOWNSTREAM);
+ // pass the box a y position that is inside it
+ return closestBox->renderer()->positionForPoint(IntPoint(pointInContents.x(), closestBox->m_y));
+ }
- return VisiblePosition(n, 0, DOWNSTREAM);
+ if (lastRootBoxWithChildren) {
+ // We hit this case for Mac behavior when the Y coordinate is below the last box.
+ ASSERT(!useWindowsBehavior);
+ return VisiblePosition(positionForBox(lastRootBoxWithChildren->lastLeafChild(), false), DOWNSTREAM);
}
-
- // See if any child blocks exist at this y coordinate.
- if (firstChild() && contentsY < firstChild()->yPos())
- return VisiblePosition(n, 0, DOWNSTREAM);
- for (RenderObject* renderer = firstChild(); renderer; renderer = renderer->nextSibling()) {
- if (renderer->height() == 0 || renderer->style()->visibility() != VISIBLE || renderer->isFloatingOrPositioned())
- continue;
- RenderObject* next = renderer->nextSibling();
- while (next && next->isFloatingOrPositioned())
- next = next->nextSibling();
- if (next)
- bottom = next->yPos();
- else
- bottom = top + scrollHeight();
- if (contentsY >= renderer->yPos() && contentsY < bottom)
- return renderer->positionForCoordinates(contentsX - renderer->xPos(), contentsY - renderer->yPos());
+
+ // Can't reach this. We have a root line box, but it has no kids.
+ // FIXME: This should ASSERT_NOT_REACHED(), but clicking on placeholder text
+ // seems to hit this code path.
+ return createVisiblePosition(0, DOWNSTREAM);
+}
+
+static inline bool isChildHitTestCandidate(RenderBox* box)
+{
+ return box->height() && box->style()->visibility() == VISIBLE && !box->isFloatingOrPositioned();
+}
+
+VisiblePosition RenderBlock::positionForPoint(const IntPoint& point)
+{
+ if (isTable())
+ return RenderBox::positionForPoint(point);
+
+ if (isReplaced()) {
+ if (point.y() < 0 || (point.y() < height() && point.x() < 0))
+ return createVisiblePosition(caretMinOffset(), DOWNSTREAM);
+ if (point.y() >= height() || (point.y() >= 0 && point.x() >= width()))
+ return createVisiblePosition(caretMaxOffset(), DOWNSTREAM);
+ }
+
+ int contentsX = point.x();
+ int contentsY = point.y();
+ offsetForContents(contentsX, contentsY);
+ IntPoint pointInContents(contentsX, contentsY);
+
+ if (childrenInline())
+ return positionForPointWithInlineChildren(pointInContents);
+
+ if (lastChildBox() && contentsY > lastChildBox()->y()) {
+ for (RenderBox* childBox = lastChildBox(); childBox; childBox = childBox->previousSiblingBox()) {
+ if (isChildHitTestCandidate(childBox))
+ return positionForPointRespectingEditingBoundaries(this, childBox, pointInContents);
+ }
+ } else {
+ for (RenderBox* childBox = firstChildBox(); childBox; childBox = childBox->nextSiblingBox()) {
+ // We hit child if our click is above the bottom of its padding box (like IE6/7 and FF3).
+ if (isChildHitTestCandidate(childBox) && contentsY < childBox->frameRect().bottom())
+ return positionForPointRespectingEditingBoundaries(this, childBox, pointInContents);
+ }
}
-
- return RenderFlow::positionForCoordinates(x, y);
+
+ // We only get here if there are no hit test candidate children below the click.
+ return RenderBox::positionForPoint(point);
}
void RenderBlock::offsetForContents(int& tx, int& ty) const
{
- ty -= borderTopExtra();
-
if (hasOverflowClip())
- m_layer->addScrolledContentOffset(tx, ty);
+ layer()->addScrolledContentOffset(tx, ty);
- if (m_hasColumns) {
+ if (hasColumns()) {
IntPoint contentsPoint(tx, ty);
adjustPointToColumnContents(contentsPoint);
tx = contentsPoint.x();
@@ -3398,7 +3570,7 @@ void RenderBlock::offsetForContents(int& tx, int& ty) const
int RenderBlock::availableWidth() const
{
// If we have multiple columns, then the available width is reduced to our column width.
- if (m_hasColumns)
+ if (hasColumns())
return desiredColumnWidth();
return contentWidth();
}
@@ -3456,20 +3628,20 @@ void RenderBlock::calcColumnWidth()
void RenderBlock::setDesiredColumnCountAndWidth(int count, int width)
{
if (count == 1) {
- if (m_hasColumns) {
+ if (hasColumns()) {
delete gColumnInfoMap->take(this);
- m_hasColumns = false;
+ setHasColumns(false);
}
} else {
ColumnInfo* info;
- if (m_hasColumns)
+ if (hasColumns())
info = gColumnInfoMap->get(this);
else {
if (!gColumnInfoMap)
gColumnInfoMap = new ColumnInfoMap;
info = new ColumnInfo;
gColumnInfoMap->add(this, info);
- m_hasColumns = true;
+ setHasColumns(true);
}
info->m_desiredColumnCount = count;
info->m_desiredColumnWidth = width;
@@ -3478,21 +3650,21 @@ void RenderBlock::setDesiredColumnCountAndWidth(int count, int width)
int RenderBlock::desiredColumnWidth() const
{
- if (!m_hasColumns)
+ if (!hasColumns())
return contentWidth();
return gColumnInfoMap->get(this)->m_desiredColumnWidth;
}
unsigned RenderBlock::desiredColumnCount() const
{
- if (!m_hasColumns)
+ if (!hasColumns())
return 1;
return gColumnInfoMap->get(this)->m_desiredColumnCount;
}
Vector<IntRect>* RenderBlock::columnRects() const
{
- if (!m_hasColumns)
+ if (!hasColumns())
return 0;
return &gColumnInfoMap->get(this)->m_columnRects;
}
@@ -3500,7 +3672,7 @@ Vector<IntRect>* RenderBlock::columnRects() const
int RenderBlock::layoutColumns(int endOfContent)
{
// Don't do anything if we have no columns
- if (!m_hasColumns)
+ if (!hasColumns())
return -1;
ColumnInfo* info = gColumnInfoMap->get(this);
@@ -3552,9 +3724,9 @@ int RenderBlock::layoutColumns(int endOfContent)
GraphicsContext context((PlatformGraphicsContext*)0);
RenderObject::PaintInfo paintInfo(&context, pageRect, PaintPhaseForeground, false, 0, 0);
- m_hasColumns = false;
+ setHasColumns(false);
paintObject(paintInfo, 0, 0);
- m_hasColumns = true;
+ setHasColumns(true);
int adjustedBottom = v->bestTruncatedAt();
if (adjustedBottom <= currY)
@@ -3592,14 +3764,14 @@ int RenderBlock::layoutColumns(int endOfContent)
colCount++;
}
- m_overflowWidth = max(m_width, currX - colGap);
+ m_overflowWidth = max(width(), currX - colGap);
m_overflowLeft = min(0, currX + desiredColumnWidth + colGap);
m_overflowHeight = maxColBottom;
int toAdd = borderBottom() + paddingBottom() + horizontalScrollbarHeight();
if (computeIntrinsicHeight)
- m_height = m_overflowHeight + toAdd;
+ setHeight(m_overflowHeight + toAdd);
v->setPrintRect(IntRect());
v->setTruncatedAt(0);
@@ -3612,7 +3784,7 @@ int RenderBlock::layoutColumns(int endOfContent)
void RenderBlock::adjustPointToColumnContents(IntPoint& point) const
{
// Just bail if we have no columns.
- if (!m_hasColumns)
+ if (!hasColumns())
return;
Vector<IntRect>* colRects = columnRects();
@@ -3641,7 +3813,7 @@ void RenderBlock::adjustPointToColumnContents(IntPoint& point) const
void RenderBlock::adjustRectForColumns(IntRect& r) const
{
// Just bail if we have no columns.
- if (!m_hasColumns)
+ if (!hasColumns())
return;
Vector<IntRect>* colRects = columnRects();
@@ -3698,7 +3870,7 @@ void RenderBlock::calcPrefWidths()
m_minPrefWidth = m_maxPrefWidth;
// A horizontal marquee with inline children has no minimum width.
- if (m_layer && m_layer->marquee() && m_layer->marquee()->isHorizontal())
+ if (layer() && layer()->marquee() && layer()->marquee()->isHorizontal())
m_minPrefWidth = 0;
}
@@ -3760,7 +3932,7 @@ RenderObject* InlineMinMaxIterator::next()
result = current->firstChild();
if (!result) {
// We hit the end of our inline. (It was empty, e.g., <span></span>.)
- if (!oldEndOfInline && current->isInlineFlow()) {
+ if (!oldEndOfInline && current->isRenderInline()) {
result = current;
endOfInline = true;
break;
@@ -3770,7 +3942,7 @@ RenderObject* InlineMinMaxIterator::next()
result = current->nextSibling();
if (result) break;
current = current->parent();
- if (current && current != parent && current->isInlineFlow()) {
+ if (current && current != parent && current->isRenderInline()) {
result = current;
endOfInline = true;
break;
@@ -3781,7 +3953,7 @@ RenderObject* InlineMinMaxIterator::next()
if (!result)
break;
- if (!result->isPositioned() && (result->isText() || result->isFloating() || result->isReplaced() || result->isInlineFlow()))
+ if (!result->isPositioned() && (result->isText() || result->isFloating() || result->isReplaced() || result->isRenderInline()))
break;
current = result;
@@ -3800,7 +3972,7 @@ static int getBPMWidth(int childValue, Length cssUnit)
return 0;
}
-static int getBorderPaddingMargin(const RenderObject* child, bool endOfInline)
+static int getBorderPaddingMargin(const RenderBoxModelObject* child, bool endOfInline)
{
RenderStyle* cstyle = child->style();
int result = 0;
@@ -3820,7 +3992,7 @@ static inline void stripTrailingSpace(int& inlineMax, int& inlineMin,
{
if (trailingSpaceChild && trailingSpaceChild->isText()) {
// Collapse away the trailing space at the end of a block.
- RenderText* t = static_cast<RenderText*>(trailingSpaceChild);
+ RenderText* t = toRenderText(trailingSpaceChild);
const UChar space = ' ';
const Font& font = t->style()->font(); // FIXME: This ignores first-line.
int spaceWidth = font.width(TextRun(&space, 1));
@@ -3900,10 +4072,10 @@ void RenderBlock::calcInlinePrefWidths()
if (!child->isText()) {
// Case (1) and (2). Inline replaced and inline flow elements.
- if (child->isInlineFlow()) {
+ if (child->isRenderInline()) {
// Add in padding/border/margin from the appropriate side of
// the element.
- int bpm = getBorderPaddingMargin(child, childIterator.endOfInline);
+ int bpm = getBorderPaddingMargin(toRenderInline(child), childIterator.endOfInline);
childMin += bpm;
childMax += bpm;
@@ -3935,14 +4107,14 @@ void RenderBlock::calcInlinePrefWidths()
bool clearPreviousFloat;
if (child->isFloating()) {
clearPreviousFloat = (prevFloat
- && (prevFloat->style()->floating() == FLEFT && (child->style()->clear() & CLEFT)
- || prevFloat->style()->floating() == FRIGHT && (child->style()->clear() & CRIGHT)));
+ && ((prevFloat->style()->floating() == FLEFT && (child->style()->clear() & CLEFT))
+ || (prevFloat->style()->floating() == FRIGHT && (child->style()->clear() & CRIGHT))));
prevFloat = child;
} else
clearPreviousFloat = false;
bool canBreakReplacedElement = !child->isImage() || allowImagesToBreak;
- if (canBreakReplacedElement && (autoWrap || oldAutoWrap) || clearPreviousFloat) {
+ if ((canBreakReplacedElement && (autoWrap || oldAutoWrap)) || clearPreviousFloat) {
m_minPrefWidth = max(inlineMin, m_minPrefWidth);
inlineMin = 0;
}
@@ -3986,7 +4158,7 @@ void RenderBlock::calcInlinePrefWidths()
}
} else if (child->isText()) {
// Case (3). Text.
- RenderText* t = static_cast<RenderText *>(child);
+ RenderText* t = toRenderText(child);
if (t->isWordBreak()) {
m_minPrefWidth = max(inlineMin, m_minPrefWidth);
@@ -4077,7 +4249,7 @@ void RenderBlock::calcInlinePrefWidths()
}
oldAutoWrap = autoWrap;
- if (!child->isInlineFlow())
+ if (!child->isRenderInline())
previousLeaf = child;
}
@@ -4104,7 +4276,7 @@ void RenderBlock::calcBlockPrefWidths()
continue;
}
- if (child->isFloating() || child->avoidsFloats()) {
+ if (child->isFloating() || (child->isBox() && toRenderBox(child)->avoidsFloats())) {
int floatTotalWidth = floatLeftWidth + floatRightWidth;
if (child->style()->clear() & CLEFT) {
m_maxPrefWidth = max(floatTotalWidth, m_maxPrefWidth);
@@ -4138,7 +4310,7 @@ void RenderBlock::calcBlockPrefWidths()
w = child->maxPrefWidth() + margin;
if (!child->isFloating()) {
- if (child->avoidsFloats()) {
+ if (child->isBox() && toRenderBox(child)->avoidsFloats()) {
// Determine a left and right max value based off whether or not the floats can fit in the
// margins of the object. For negative margins, we will attempt to overlap the float if the negative margin
// is smaller than the float width.
@@ -4194,11 +4366,19 @@ void RenderBlock::calcBlockPrefWidths()
bool RenderBlock::hasLineIfEmpty() const
{
- return element() && (element()->isContentEditable() && element()->rootEditableElement() == element() ||
- element()->isShadowNode() && element()->shadowParentNode()->hasTagName(inputTag));
+ if (!node())
+ return false;
+
+ if (node()->isContentEditable() && node()->rootEditableElement() == node())
+ return true;
+
+ if (node()->isShadowNode() && (node()->shadowParentNode()->hasTagName(inputTag) || node()->shadowParentNode()->hasTagName(textareaTag)))
+ return true;
+
+ return false;
}
-int RenderBlock::lineHeight(bool b, bool isRootLineBox) const
+int RenderBlock::lineHeight(bool firstLine, bool isRootLineBox) const
{
// Inline blocks are replaced elements. Otherwise, just pass off to
// the base class. If we're being queried as though we're the root line
@@ -4206,7 +4386,17 @@ int RenderBlock::lineHeight(bool b, bool isRootLineBox) const
// just like a block.
if (isReplaced() && !isRootLineBox)
return height() + marginTop() + marginBottom();
- return RenderFlow::lineHeight(b, isRootLineBox);
+
+ if (firstLine && document()->usesFirstLineRules()) {
+ RenderStyle* s = style(firstLine);
+ if (s != style())
+ return s->computedLineHeight();
+ }
+
+ if (m_lineHeight == -1)
+ m_lineHeight = style()->computedLineHeight();
+
+ return m_lineHeight;
}
int RenderBlock::baselinePosition(bool b, bool isRootLineBox) const
@@ -4228,31 +4418,31 @@ int RenderBlock::baselinePosition(bool b, bool isRootLineBox) const
// We also give up on finding a baseline if we have a vertical scrollbar, or if we are scrolled
// vertically (e.g., an overflow:hidden block that has had scrollTop moved) or if the baseline is outside
// of our content box.
- int baselinePos = (m_layer && (m_layer->marquee() || m_layer->verticalScrollbar() || m_layer->scrollYOffset() != 0)) ? -1 : getBaselineOfLastLineBox();
+ int baselinePos = (layer() && (layer()->marquee() || layer()->verticalScrollbar() || layer()->scrollYOffset() != 0)) ? -1 : lastLineBoxBaseline();
if (baselinePos != -1 && baselinePos <= borderTop() + paddingTop() + contentHeight())
return marginTop() + baselinePos;
return height() + marginTop() + marginBottom();
}
- return RenderFlow::baselinePosition(b, isRootLineBox);
+ return RenderBox::baselinePosition(b, isRootLineBox);
}
-int RenderBlock::getBaselineOfFirstLineBox() const
+int RenderBlock::firstLineBoxBaseline() const
{
if (!isBlockFlow())
- return RenderFlow::getBaselineOfFirstLineBox();
+ return -1;
if (childrenInline()) {
if (firstLineBox())
- return firstLineBox()->yPos() + firstLineBox()->baseline();
+ return firstLineBox()->y() + style(true)->font().ascent();
else
return -1;
}
else {
- for (RenderObject* curr = firstChild(); curr; curr = curr->nextSibling()) {
+ for (RenderBox* curr = firstChildBox(); curr; curr = curr->nextSiblingBox()) {
if (!curr->isFloatingOrPositioned()) {
- int result = curr->getBaselineOfFirstLineBox();
+ int result = curr->firstLineBoxBaseline();
if (result != -1)
- return curr->yPos() + result; // Translate to our coordinate space.
+ return curr->y() + result; // Translate to our coordinate space.
}
}
}
@@ -4260,30 +4450,30 @@ int RenderBlock::getBaselineOfFirstLineBox() const
return -1;
}
-int RenderBlock::getBaselineOfLastLineBox() const
+int RenderBlock::lastLineBoxBaseline() const
{
if (!isBlockFlow())
- return RenderFlow::getBaselineOfLastLineBox();
+ return -1;
if (childrenInline()) {
if (!firstLineBox() && hasLineIfEmpty())
- return RenderFlow::baselinePosition(true, true) + borderTop() + paddingTop();
+ return RenderBox::baselinePosition(true, true) + borderTop() + paddingTop();
if (lastLineBox())
- return lastLineBox()->yPos() + lastLineBox()->baseline();
+ return lastLineBox()->y() + style(lastLineBox() == firstLineBox())->font().ascent();
return -1;
}
else {
bool haveNormalFlowChild = false;
- for (RenderObject* curr = lastChild(); curr; curr = curr->previousSibling()) {
+ for (RenderBox* curr = lastChildBox(); curr; curr = curr->previousSiblingBox()) {
if (!curr->isFloatingOrPositioned()) {
haveNormalFlowChild = true;
- int result = curr->getBaselineOfLastLineBox();
+ int result = curr->lastLineBoxBaseline();
if (result != -1)
- return curr->yPos() + result; // Translate to our coordinate space.
+ return curr->y() + result; // Translate to our coordinate space.
}
}
if (!haveNormalFlowChild && hasLineIfEmpty())
- return RenderFlow::baselinePosition(true, true) + borderTop() + paddingTop();
+ return RenderBox::baselinePosition(true, true) + borderTop() + paddingTop();
}
return -1;
@@ -4302,31 +4492,32 @@ bool RenderBlock::containsNonZeroBidiLevel() const
RenderBlock* RenderBlock::firstLineBlock() const
{
- const RenderObject* firstLineBlock = this;
+ RenderBlock* firstLineBlock = const_cast<RenderBlock*>(this);
bool hasPseudo = false;
while (true) {
- hasPseudo = firstLineBlock->style()->hasPseudoStyle(RenderStyle::FIRST_LINE);
+ hasPseudo = firstLineBlock->style()->hasPseudoStyle(FIRST_LINE);
if (hasPseudo)
break;
RenderObject* parentBlock = firstLineBlock->parent();
if (firstLineBlock->isReplaced() || firstLineBlock->isFloating() ||
!parentBlock || parentBlock->firstChild() != firstLineBlock || !parentBlock->isBlockFlow())
break;
- firstLineBlock = parentBlock;
+ ASSERT(parentBlock->isRenderBlock());
+ firstLineBlock = toRenderBlock(parentBlock);
}
if (!hasPseudo)
return 0;
- return (RenderBlock*)(firstLineBlock);
+ return firstLineBlock;
}
void RenderBlock::updateFirstLetter()
{
if (!document()->usesFirstLetterRules())
return;
- // Don't recurse
- if (style()->styleType() == RenderStyle::FIRST_LETTER)
+ // Don't recur
+ if (style()->styleType() == FIRST_LETTER)
return;
// FIXME: We need to destroy the first-letter object if it is no longer the first child. Need to find
@@ -4336,7 +4527,7 @@ void RenderBlock::updateFirstLetter()
while (true) {
// We only honor first-letter if the firstLetterBlock can have children in the DOM. This correctly
// prevents form controls from honoring first-letter.
- hasPseudoStyle = firstLetterBlock->style()->hasPseudoStyle(RenderStyle::FIRST_LETTER)
+ hasPseudoStyle = firstLetterBlock->style()->hasPseudoStyle(FIRST_LETTER)
&& firstLetterBlock->canHaveChildren();
if (hasPseudoStyle)
break;
@@ -4354,7 +4545,7 @@ void RenderBlock::updateFirstLetter()
RenderObject* currChild = firstLetterBlock->firstChild();
while (currChild && currChild->needsLayout() && (!currChild->isReplaced() || currChild->isFloatingOrPositioned()) && !currChild->isText()) {
if (currChild->isFloatingOrPositioned()) {
- if (currChild->style()->styleType() == RenderStyle::FIRST_LETTER)
+ if (currChild->style()->styleType() == FIRST_LETTER)
break;
currChild = currChild->nextSibling();
} else
@@ -4372,8 +4563,8 @@ void RenderBlock::updateFirstLetter()
// If the child already has style, then it has already been created, so we just want
// to update it.
- if (currChild->style()->styleType() == RenderStyle::FIRST_LETTER) {
- RenderStyle* pseudo = firstLetterBlock->getCachedPseudoStyle(RenderStyle::FIRST_LETTER,
+ if (currChild->style()->styleType() == FIRST_LETTER) {
+ RenderStyle* pseudo = firstLetterBlock->getCachedPseudoStyle(FIRST_LETTER,
firstLetterContainer->firstLineStyle());
currChild->setStyle(pseudo);
for (RenderObject* genChild = currChild->firstChild(); genChild; genChild = genChild->nextSibling()) {
@@ -4384,22 +4575,27 @@ void RenderBlock::updateFirstLetter()
}
// If the child does not already have style, we create it here.
- if (currChild->isText() && !currChild->isBR() && currChild->parent()->style()->styleType() != RenderStyle::FIRST_LETTER) {
+ if (currChild->isText() && !currChild->isBR() && currChild->parent()->style()->styleType() != FIRST_LETTER) {
// Our layout state is not valid for the repaints we are going to trigger by
// adding and removing children of firstLetterContainer.
view()->disableLayoutState();
- RenderText* textObj = static_cast<RenderText*>(currChild);
+ RenderText* textObj = toRenderText(currChild);
// Create our pseudo style now that we have our firstLetterContainer determined.
- RenderStyle* pseudoStyle = firstLetterBlock->getCachedPseudoStyle(RenderStyle::FIRST_LETTER,
+ RenderStyle* pseudoStyle = firstLetterBlock->getCachedPseudoStyle(FIRST_LETTER,
firstLetterContainer->firstLineStyle());
// Force inline display (except for floating first-letters)
- pseudoStyle->setDisplay( pseudoStyle->isFloating() ? BLOCK : INLINE);
- pseudoStyle->setPosition( StaticPosition ); // CSS2 says first-letter can't be positioned.
+ pseudoStyle->setDisplay(pseudoStyle->isFloating() ? BLOCK : INLINE);
+ pseudoStyle->setPosition(StaticPosition); // CSS2 says first-letter can't be positioned.
- RenderObject* firstLetter = RenderFlow::createAnonymousFlow(document(), pseudoStyle); // anonymous box
+ RenderObject* firstLetter = 0;
+ if (pseudoStyle->display() == INLINE)
+ firstLetter = new (renderArena()) RenderInline(document());
+ else
+ firstLetter = new (renderArena()) RenderBlock(document());
+ firstLetter->setStyle(pseudoStyle);
firstLetterContainer->addChild(firstLetter, currChild);
// The original string is going to be either a generated content string or a DOM node's
@@ -4421,10 +4617,10 @@ void RenderBlock::updateFirstLetter()
// construct text fragment for the text after the first letter
// NOTE: this might empty
RenderTextFragment* remainingText =
- new (renderArena()) RenderTextFragment(textObj->node(), oldText.get(), length, oldText->length() - length);
+ new (renderArena()) RenderTextFragment(textObj->node() ? textObj->node() : textObj->document(), oldText.get(), length, oldText->length() - length);
remainingText->setStyle(textObj->style());
- if (remainingText->element())
- remainingText->element()->setRenderer(remainingText);
+ if (remainingText->node())
+ remainingText->node()->setRenderer(remainingText);
RenderObject* nextObj = textObj->nextSibling();
firstLetterContainer->removeChild(textObj);
@@ -4433,7 +4629,7 @@ void RenderBlock::updateFirstLetter()
// construct text fragment for the first letter
RenderTextFragment* letter =
- new (renderArena()) RenderTextFragment(remainingText->node(), oldText.get(), 0, length);
+ new (renderArena()) RenderTextFragment(remainingText->node() ? remainingText->node() : remainingText->document(), oldText.get(), 0, length);
RefPtr<RenderStyle> newStyle = RenderStyle::create();
newStyle->inheritFrom(pseudoStyle);
letter->setStyle(newStyle.release());
@@ -4460,7 +4656,7 @@ bool RenderBlock::inRootBlockContext() const
// (crawling into blocks).
static bool shouldCheckLines(RenderObject* obj)
{
- return !obj->isFloatingOrPositioned() && !obj->isCompact() && !obj->isRunIn() &&
+ return !obj->isFloatingOrPositioned() && !obj->isRunIn() &&
obj->isBlockFlow() && obj->style()->height().isAuto() &&
(!obj->isFlexibleBox() || obj->style()->boxOrient() == VERTICAL);
}
@@ -4477,7 +4673,7 @@ static RootInlineBox* getLineAtIndex(RenderBlock* block, int i, int& count)
else {
for (RenderObject* obj = block->firstChild(); obj; obj = obj->nextSibling()) {
if (shouldCheckLines(obj)) {
- RootInlineBox *box = getLineAtIndex(static_cast<RenderBlock*>(obj), i, count);
+ RootInlineBox *box = getLineAtIndex(toRenderBlock(obj), i, count);
if (box)
return box;
}
@@ -4487,7 +4683,7 @@ static RootInlineBox* getLineAtIndex(RenderBlock* block, int i, int& count)
return 0;
}
-int getHeightForLineCount(RenderBlock* block, int l, bool includeBottom, int& count)
+static int getHeightForLineCount(RenderBlock* block, int l, bool includeBottom, int& count)
{
if (block->style()->visibility() == VISIBLE) {
if (block->childrenInline()) {
@@ -4497,18 +4693,18 @@ int getHeightForLineCount(RenderBlock* block, int l, bool includeBottom, int& co
}
}
else {
- RenderObject* normalFlowChildWithoutLines = 0;
- for (RenderObject* obj = block->firstChild(); obj; obj = obj->nextSibling()) {
+ RenderBox* normalFlowChildWithoutLines = 0;
+ for (RenderBox* obj = block->firstChildBox(); obj; obj = obj->nextSiblingBox()) {
if (shouldCheckLines(obj)) {
- int result = getHeightForLineCount(static_cast<RenderBlock*>(obj), l, false, count);
+ int result = getHeightForLineCount(toRenderBlock(obj), l, false, count);
if (result != -1)
- return result + obj->yPos() + (includeBottom ? (block->borderBottom() + block->paddingBottom()) : 0);
+ return result + obj->y() + (includeBottom ? (block->borderBottom() + block->paddingBottom()) : 0);
}
- else if (!obj->isFloatingOrPositioned() && !obj->isCompact() && !obj->isRunIn())
+ else if (!obj->isFloatingOrPositioned() && !obj->isRunIn())
normalFlowChildWithoutLines = obj;
}
if (normalFlowChildWithoutLines && l == 0)
- return normalFlowChildWithoutLines->yPos() + normalFlowChildWithoutLines->height();
+ return normalFlowChildWithoutLines->y() + normalFlowChildWithoutLines->height();
}
}
@@ -4531,7 +4727,7 @@ int RenderBlock::lineCount()
else
for (RenderObject* obj = firstChild(); obj; obj = obj->nextSibling())
if (shouldCheckLines(obj))
- count += static_cast<RenderBlock*>(obj)->lineCount();
+ count += toRenderBlock(obj)->lineCount();
}
return count;
}
@@ -4550,20 +4746,20 @@ void RenderBlock::adjustForBorderFit(int x, int& left, int& right) const
if (childrenInline()) {
for (RootInlineBox* box = firstRootBox(); box; box = box->nextRootBox()) {
if (box->firstChild())
- left = min(left, x + box->firstChild()->xPos());
+ left = min(left, x + box->firstChild()->x());
if (box->lastChild())
- right = max(right, x + box->lastChild()->xPos() + box->lastChild()->width());
+ right = max(right, x + box->lastChild()->x() + box->lastChild()->width());
}
}
else {
- for (RenderObject* obj = firstChild(); obj; obj = obj->nextSibling()) {
+ for (RenderBox* obj = firstChildBox(); obj; obj = obj->nextSiblingBox()) {
if (!obj->isFloatingOrPositioned()) {
if (obj->isBlockFlow() && !obj->hasOverflowClip())
- static_cast<RenderBlock*>(obj)->adjustForBorderFit(x + obj->xPos(), left, right);
+ toRenderBlock(obj)->adjustForBorderFit(x + obj->x(), left, right);
else if (obj->style()->visibility() == VISIBLE) {
// We are a replaced element or some kind of non-block-flow object.
- left = min(left, x + obj->xPos());
- right = max(right, x + obj->xPos() + obj->width());
+ left = min(left, x + obj->x());
+ right = max(right, x + obj->x() + obj->width());
}
}
}
@@ -4575,7 +4771,7 @@ void RenderBlock::adjustForBorderFit(int x, int& left, int& right) const
for (; (r = it.current()); ++it) {
// Only examine the object if our m_shouldPaint flag is set.
if (r->m_shouldPaint) {
- int floatLeft = r->m_left - r->m_renderer->xPos() + r->m_renderer->marginLeft();
+ int floatLeft = r->m_left - r->m_renderer->x() + r->m_renderer->marginLeft();
int floatRight = floatLeft + r->m_renderer->width();
left = min(left, floatLeft);
right = max(right, floatRight);
@@ -4620,7 +4816,7 @@ void RenderBlock::clearTruncation()
else
for (RenderObject* obj = firstChild(); obj; obj = obj->nextSibling())
if (shouldCheckLines(obj))
- static_cast<RenderBlock*>(obj)->clearTruncation();
+ toRenderBlock(obj)->clearTruncation();
}
}
@@ -4646,6 +4842,218 @@ void RenderBlock::setMaxBottomMargins(int pos, int neg)
m_maxMargin->m_bottomNeg = neg;
}
+void RenderBlock::absoluteRects(Vector<IntRect>& rects, int tx, int ty)
+{
+ // For blocks inside inlines, we go ahead and include margins so that we run right up to the
+ // inline boxes above and below us (thus getting merged with them to form a single irregular
+ // shape).
+ if (inlineContinuation()) {
+ rects.append(IntRect(tx, ty - collapsedMarginTop(),
+ width(), height() + collapsedMarginTop() + collapsedMarginBottom()));
+ inlineContinuation()->absoluteRects(rects,
+ tx - x() + inlineContinuation()->containingBlock()->x(),
+ ty - y() + inlineContinuation()->containingBlock()->y());
+ } else
+ rects.append(IntRect(tx, ty, width(), height()));
+}
+
+void RenderBlock::absoluteQuads(Vector<FloatQuad>& quads)
+{
+ // For blocks inside inlines, we go ahead and include margins so that we run right up to the
+ // inline boxes above and below us (thus getting merged with them to form a single irregular
+ // shape).
+ if (inlineContinuation()) {
+ FloatRect localRect(0, -collapsedMarginTop(),
+ width(), height() + collapsedMarginTop() + collapsedMarginBottom());
+ quads.append(localToAbsoluteQuad(localRect));
+ inlineContinuation()->absoluteQuads(quads);
+ } else
+ quads.append(RenderBox::localToAbsoluteQuad(FloatRect(0, 0, width(), height())));
+}
+
+IntRect RenderBlock::rectWithOutlineForRepaint(RenderBoxModelObject* repaintContainer, int outlineWidth)
+{
+ IntRect r(RenderBox::rectWithOutlineForRepaint(repaintContainer, outlineWidth));
+ if (inlineContinuation())
+ r.inflateY(collapsedMarginTop());
+ return r;
+}
+
+RenderObject* RenderBlock::hoverAncestor() const
+{
+ return inlineContinuation() ? inlineContinuation() : RenderBox::hoverAncestor();
+}
+
+void RenderBlock::updateDragState(bool dragOn)
+{
+ RenderBox::updateDragState(dragOn);
+ if (inlineContinuation())
+ inlineContinuation()->updateDragState(dragOn);
+}
+
+RenderStyle* RenderBlock::outlineStyleForRepaint() const
+{
+ return inlineContinuation() ? inlineContinuation()->style() : style();
+}
+
+void RenderBlock::childBecameNonInline(RenderObject*)
+{
+ makeChildrenNonInline();
+ if (isAnonymousBlock() && parent() && parent()->isRenderBlock())
+ toRenderBlock(parent())->removeLeftoverAnonymousBlock(this);
+ // |this| may be dead here
+}
+
+void RenderBlock::updateHitTestResult(HitTestResult& result, const IntPoint& point)
+{
+ if (result.innerNode())
+ return;
+
+ Node* n = node();
+ if (inlineContinuation())
+ // We are in the margins of block elements that are part of a continuation. In
+ // this case we're actually still inside the enclosing inline element that was
+ // split. Go ahead and set our inner node accordingly.
+ n = inlineContinuation()->node();
+
+ if (n) {
+ result.setInnerNode(n);
+ if (!result.innerNonSharedNode())
+ result.setInnerNonSharedNode(n);
+ result.setLocalPoint(point);
+ }
+}
+
+IntRect RenderBlock::localCaretRect(InlineBox* inlineBox, int caretOffset, int* extraWidthToEndOfLine)
+{
+ // Do the normal calculation in most cases.
+ if (firstChild())
+ return RenderBox::localCaretRect(inlineBox, caretOffset, extraWidthToEndOfLine);
+
+ // This is a special case:
+ // The element is not an inline element, and it's empty. So we have to
+ // calculate a fake position to indicate where objects are to be inserted.
+
+ // FIXME: This does not take into account either :first-line or :first-letter
+ // However, as soon as some content is entered, the line boxes will be
+ // constructed and this kludge is not called any more. So only the caret size
+ // of an empty :first-line'd block is wrong. I think we can live with that.
+ RenderStyle* currentStyle = firstLineStyle();
+ int height = lineHeight(true);
+
+ enum CaretAlignment { alignLeft, alignRight, alignCenter };
+
+ CaretAlignment alignment = alignLeft;
+
+ switch (currentStyle->textAlign()) {
+ case TAAUTO:
+ case JUSTIFY:
+ if (currentStyle->direction() == RTL)
+ alignment = alignRight;
+ break;
+ case LEFT:
+ case WEBKIT_LEFT:
+ break;
+ case CENTER:
+ case WEBKIT_CENTER:
+ alignment = alignCenter;
+ break;
+ case RIGHT:
+ case WEBKIT_RIGHT:
+ alignment = alignRight;
+ break;
+ }
+
+ int x = borderLeft() + paddingLeft();
+ int w = width();
+
+ switch (alignment) {
+ case alignLeft:
+ break;
+ case alignCenter:
+ x = (x + w - (borderRight() + paddingRight())) / 2;
+ break;
+ case alignRight:
+ x = w - (borderRight() + paddingRight()) - caretWidth;
+ break;
+ }
+
+ if (extraWidthToEndOfLine) {
+ if (isRenderBlock()) {
+ *extraWidthToEndOfLine = w - (x + caretWidth);
+ } else {
+ // FIXME: This code looks wrong.
+ // myRight and containerRight are set up, but then clobbered.
+ // So *extraWidthToEndOfLine will always be 0 here.
+
+ int myRight = x + caretWidth;
+ // FIXME: why call localToAbsoluteForContent() twice here, too?
+ FloatPoint absRightPoint = localToAbsolute(FloatPoint(myRight, 0));
+
+ int containerRight = containingBlock()->x() + containingBlockWidthForContent();
+ FloatPoint absContainerPoint = localToAbsolute(FloatPoint(containerRight, 0));
+
+ *extraWidthToEndOfLine = absContainerPoint.x() - absRightPoint.x();
+ }
+ }
+
+ int y = paddingTop() + borderTop();
+
+ return IntRect(x, y, caretWidth, height);
+}
+
+void RenderBlock::addFocusRingRects(GraphicsContext* graphicsContext, int tx, int ty)
+{
+ // For blocks inside inlines, we go ahead and include margins so that we run right up to the
+ // inline boxes above and below us (thus getting merged with them to form a single irregular
+ // shape).
+ if (inlineContinuation()) {
+ // FIXME: This check really isn't accurate.
+ bool nextInlineHasLineBox = inlineContinuation()->firstLineBox();
+ // FIXME: This is wrong. The principal renderer may not be the continuation preceding this block.
+ bool prevInlineHasLineBox = toRenderInline(inlineContinuation()->node()->renderer())->firstLineBox();
+ int topMargin = prevInlineHasLineBox ? collapsedMarginTop() : 0;
+ int bottomMargin = nextInlineHasLineBox ? collapsedMarginBottom() : 0;
+ graphicsContext->addFocusRingRect(IntRect(tx, ty - topMargin,
+ width(), height() + topMargin + bottomMargin));
+ } else
+ graphicsContext->addFocusRingRect(IntRect(tx, ty, width(), height()));
+
+ if (!hasOverflowClip() && !hasControlClip()) {
+ for (InlineRunBox* curr = firstLineBox(); curr; curr = curr->nextLineBox())
+ graphicsContext->addFocusRingRect(IntRect(tx + curr->x(), ty + curr->y(), curr->width(), curr->height()));
+
+ for (RenderObject* curr = firstChild(); curr; curr = curr->nextSibling()) {
+ if (!curr->isText() && !curr->isListMarker() && curr->isBox()) {
+ RenderBox* box = toRenderBox(curr);
+ FloatPoint pos;
+ // FIXME: This doesn't work correctly with transforms.
+ if (box->layer())
+ pos = curr->localToAbsolute();
+ else
+ pos = FloatPoint(tx + box->x(), ty + box->y());
+ box->addFocusRingRects(graphicsContext, pos.x(), pos.y());
+ }
+ }
+ }
+
+ if (inlineContinuation())
+ inlineContinuation()->addFocusRingRects(graphicsContext,
+ tx - x() + inlineContinuation()->containingBlock()->x(),
+ ty - y() + inlineContinuation()->containingBlock()->y());
+}
+
+RenderBlock* RenderBlock::createAnonymousBlock() const
+{
+ RefPtr<RenderStyle> newStyle = RenderStyle::create();
+ newStyle->inheritFrom(style());
+ newStyle->setDisplay(BLOCK);
+
+ RenderBlock* newBox = new (renderArena()) RenderBlock(document() /* anonymous box */);
+ newBox->setStyle(newStyle.release());
+ return newBox;
+}
+
const char* RenderBlock::renderName() const
{
if (isBody())
@@ -4661,8 +5069,6 @@ const char* RenderBlock::renderName() const
return "RenderBlock (generated)";
if (isRelPositioned())
return "RenderBlock (relative positioned)";
- if (isCompact())
- return "RenderBlock (compact)";
if (isRunIn())
return "RenderBlock (run-in)";
return "RenderBlock";
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderBlock.h b/src/3rdparty/webkit/WebCore/rendering/RenderBlock.h
index 902460d..31eae7c8 100644
--- a/src/3rdparty/webkit/WebCore/rendering/RenderBlock.h
+++ b/src/3rdparty/webkit/WebCore/rendering/RenderBlock.h
@@ -27,27 +27,39 @@
#include "DeprecatedPtrList.h"
#include "GapRects.h"
-#include "RenderFlow.h"
+#include "RenderBox.h"
+#include "RenderLineBoxList.h"
#include "RootInlineBox.h"
#include <wtf/ListHashSet.h>
namespace WebCore {
class InlineIterator;
-class BidiRun;
class Position;
+class RenderInline;
class RootInlineBox;
+struct BidiRun;
+
template <class Iterator, class Run> class BidiResolver;
+template <class Iterator> class MidpointState;
typedef BidiResolver<InlineIterator, BidiRun> InlineBidiResolver;
+typedef MidpointState<InlineIterator> LineMidpointState;
enum CaretType { CursorCaret, DragCaret };
-class RenderBlock : public RenderFlow {
+class RenderBlock : public RenderBox {
public:
RenderBlock(Node*);
virtual ~RenderBlock();
+ virtual RenderObjectChildList* virtualChildren() { return children(); }
+ virtual const RenderObjectChildList* virtualChildren() const { return children(); }
+ const RenderObjectChildList* children() const { return &m_children; }
+ RenderObjectChildList* children() { return &m_children; }
+
+ virtual void destroy();
+
virtual const char* renderName() const;
// These two functions are overridden for inline-block.
@@ -56,13 +68,19 @@ public:
virtual bool isRenderBlock() const { return true; }
virtual bool isBlockFlow() const { return (!isInline() || isReplaced()) && !isTable(); }
- virtual bool isInlineFlow() const { return isInline() && !isReplaced(); }
virtual bool isInlineBlockOrInlineTable() const { return isInline() && isReplaced(); }
- virtual bool childrenInline() const { return m_childrenInline; }
- virtual void setChildrenInline(bool b) { m_childrenInline = b; }
void makeChildrenNonInline(RenderObject* insertionPoint = 0);
+ virtual void removeLeftoverAnonymousBlock(RenderBlock* child);
+
+ RenderLineBoxList* lineBoxes() { return &m_lineBoxes; }
+ const RenderLineBoxList* lineBoxes() const { return &m_lineBoxes; }
+
+ InlineFlowBox* firstLineBox() const { return m_lineBoxes.firstLineBox(); }
+ InlineFlowBox* lastLineBox() const { return m_lineBoxes.lastLineBox(); }
+
void deleteLineBoxTree();
+ virtual void dirtyLinesFromChangedChild(RenderObject* child) { m_lineBoxes.dirtyLinesFromChangedChild(this, child); }
// The height (and width) of a block when you include overflow spillage out of the bottom
// of the block (e.g., a <div style="height:25px"> that has a 100px tall image inside
@@ -78,8 +96,6 @@ public:
void addVisualOverflow(const IntRect&);
virtual bool isSelfCollapsingBlock() const;
- virtual bool isTopMarginQuirk() const { return m_topMarginQuirk; }
- virtual bool isBottomMarginQuirk() const { return m_bottomMarginQuirk; }
virtual int maxTopMargin(bool positive) const { return positive ? maxTopPosMargin() : maxTopNegMargin(); }
virtual int maxBottomMargin(bool positive) const { return positive ? maxBottomPosMargin() : maxBottomNegMargin(); }
@@ -101,7 +117,7 @@ public:
}
}
- virtual void addChildToFlow(RenderObject* newChild, RenderObject* beforeChild);
+ virtual void addChild(RenderObject* newChild, RenderObject* beforeChild = 0);
virtual void removeChild(RenderObject*);
virtual void repaintOverhangingFloats(bool paintAllDescendants);
@@ -112,47 +128,53 @@ public:
void layoutInlineChildren(bool relayoutChildren, int& repaintTop, int& repaintBottom);
void layoutPositionedObjects(bool relayoutChildren);
- void insertPositionedObject(RenderObject*);
- void removePositionedObject(RenderObject*);
- virtual void removePositionedObjects(RenderBlock*);
+ void insertPositionedObject(RenderBox*);
+ void removePositionedObject(RenderBox*);
+ void removePositionedObjects(RenderBlock*);
void addPercentHeightDescendant(RenderBox*);
static void removePercentHeightDescendant(RenderBox*);
+ HashSet<RenderBox*>* percentHeightDescendants() const;
virtual void positionListMarker() { }
virtual void borderFitAdjust(int& x, int& w) const; // Shrink the box in which the border paints if border-fit is set.
+ virtual void updateBeforeAfterContent(PseudoId);
+
+ RootInlineBox* createRootInlineBox();
+
// Called to lay out the legend for a fieldset.
virtual RenderObject* layoutLegend(bool /*relayoutChildren*/) { return 0; }
// the implementation of the following functions is in bidi.cpp
struct FloatWithRect {
- FloatWithRect(RenderObject* f)
+ FloatWithRect(RenderBox* f)
: object(f)
- , rect(IntRect(f->xPos() - f->marginLeft(), f->yPos() - f->marginTop(), f->width() + f->marginLeft() + f->marginRight(), f->height() + f->marginTop() + f->marginBottom()))
+ , rect(IntRect(f->x() - f->marginLeft(), f->y() - f->marginTop(), f->width() + f->marginLeft() + f->marginRight(), f->height() + f->marginTop() + f->marginBottom()))
{
}
- RenderObject* object;
+ RenderBox* object;
IntRect rect;
};
- void bidiReorderLine(InlineBidiResolver&, const InlineIterator& end);
- RootInlineBox* determineStartPosition(bool& fullLayout, InlineBidiResolver&, Vector<FloatWithRect>& floats, unsigned& numCleanFloats);
+ void bidiReorderLine(InlineBidiResolver&, const InlineIterator& end, bool previousLineBrokeCleanly);
+ RootInlineBox* determineStartPosition(bool& firstLine, bool& fullLayout, bool& previousLineBrokeCleanly,
+ InlineBidiResolver&, Vector<FloatWithRect>& floats, unsigned& numCleanFloats);
RootInlineBox* determineEndPosition(RootInlineBox* startBox, InlineIterator& cleanLineStart,
BidiStatus& cleanLineBidiStatus,
int& yPos);
bool matchedEndLine(const InlineBidiResolver&, const InlineIterator& endLineStart, const BidiStatus& endLineStatus,
RootInlineBox*& endLine, int& endYPos, int& repaintBottom, int& repaintTop);
- bool generatesLineBoxesForInlineChild(RenderObject*);
- void skipTrailingWhitespace(InlineIterator&);
- int skipLeadingWhitespace(InlineBidiResolver&);
- void fitBelowFloats(int widthToFit, int& availableWidth);
- InlineIterator findNextLineBreak(InlineBidiResolver&, EClear* clear = 0);
- RootInlineBox* constructLine(unsigned runCount, BidiRun* firstRun, BidiRun* lastRun, bool lastLine, RenderObject* endObject);
- InlineFlowBox* createLineBoxes(RenderObject*);
- void computeHorizontalPositionsForLine(RootInlineBox*, BidiRun* firstRun, BidiRun* trailingSpaceRun, bool reachedEnd);
+ bool generatesLineBoxesForInlineChild(RenderObject*, bool isLineEmpty = true, bool previousLineBrokeCleanly = true);
+ void skipTrailingWhitespace(InlineIterator&, bool isLineEmpty, bool previousLineBrokeCleanly);
+ int skipLeadingWhitespace(InlineBidiResolver&, bool firstLine, bool isLineEmpty, bool previousLineBrokeCleanly);
+ void fitBelowFloats(int widthToFit, bool firstLine, int& availableWidth);
+ InlineIterator findNextLineBreak(InlineBidiResolver&, bool firstLine, bool& isLineEmpty, bool& previousLineBrokeCleanly, EClear* clear = 0);
+ RootInlineBox* constructLine(unsigned runCount, BidiRun* firstRun, BidiRun* lastRun, bool firstLine, bool lastLine, RenderObject* endObject);
+ InlineFlowBox* createLineBoxes(RenderObject*, bool firstLine);
+ void computeHorizontalPositionsForLine(RootInlineBox*, bool firstLine, BidiRun* firstRun, BidiRun* trailingSpaceRun, bool reachedEnd);
void computeVerticalPositionsForLine(RootInlineBox*, BidiRun*);
void checkLinesForOverflow();
void deleteEllipsisLineBoxes();
@@ -163,29 +185,30 @@ public:
virtual void paintObject(PaintInfo&, int tx, int ty);
void paintFloats(PaintInfo&, int tx, int ty, bool preservePhase = false);
void paintContents(PaintInfo&, int tx, int ty);
- void paintColumns(PaintInfo&, int tx, int ty, bool paintFloats = false);
+ void paintColumnContents(PaintInfo&, int tx, int ty, bool paintFloats = false);
+ void paintColumnRules(PaintInfo&, int tx, int ty);
void paintChildren(PaintInfo&, int tx, int ty);
void paintEllipsisBoxes(PaintInfo&, int tx, int ty);
void paintSelection(PaintInfo&, int tx, int ty);
void paintCaret(PaintInfo&, int tx, int ty, CaretType);
- void insertFloatingObject(RenderObject*);
- void removeFloatingObject(RenderObject*);
+ void insertFloatingObject(RenderBox*);
+ void removeFloatingObject(RenderBox*);
// Called from lineWidth, to position the floats added in the last line.
// Returns ture if and only if it has positioned any floats.
bool positionNewFloats();
void clearFloats();
- int getClearDelta(RenderObject* child);
- virtual void markAllDescendantsWithFloatsForLayout(RenderObject* floatToRemove = 0);
+ int getClearDelta(RenderBox* child, int yPos);
+ void markAllDescendantsWithFloatsForLayout(RenderBox* floatToRemove = 0, bool inLayout = true);
void markPositionedObjectsForLayout();
- virtual bool containsFloats() { return m_floatingObjects && !m_floatingObjects->isEmpty(); }
- virtual bool containsFloat(RenderObject*);
+ bool containsFloats() { return m_floatingObjects && !m_floatingObjects->isEmpty(); }
+ bool containsFloat(RenderObject*);
virtual bool avoidsFloats() const;
- virtual bool hasOverhangingFloats() { return !hasColumns() && floatBottom() > m_height; }
+ bool hasOverhangingFloats() { return parent() && !hasColumns() && floatBottom() > height(); }
void addIntrudingFloats(RenderBlock* prev, int xoffset, int yoffset);
int addOverhangingFloats(RenderBlock* child, int xoffset, int yoffset, bool makeChildPaintOtherFloats);
@@ -195,18 +218,18 @@ public:
inline int rightBottom();
IntRect floatRect() const;
- virtual int lineWidth(int) const;
+ int lineWidth(int y, bool firstLine) const;
virtual int lowestPosition(bool includeOverflowInterior = true, bool includeSelf = true) const;
virtual int rightmostPosition(bool includeOverflowInterior = true, bool includeSelf = true) const;
virtual int leftmostPosition(bool includeOverflowInterior = true, bool includeSelf = true) const;
int rightOffset() const;
int rightRelOffset(int y, int fixedOffset, bool applyTextIndent = true, int* heightRemaining = 0) const;
- int rightOffset(int y) const { return rightRelOffset(y, rightOffset(), true); }
+ int rightOffset(int y, bool firstLine) const { return rightRelOffset(y, rightOffset(), firstLine); }
int leftOffset() const;
int leftRelOffset(int y, int fixedOffset, bool applyTextIndent = true, int* heightRemaining = 0) const;
- int leftOffset(int y) const { return leftRelOffset(y, leftOffset(), true); }
+ int leftOffset(int y, bool firstLine) const { return leftRelOffset(y, leftOffset(), firstLine); }
virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, int x, int y, int tx, int ty, HitTestAction);
virtual bool hitTestColumns(const HitTestRequest&, HitTestResult&, int x, int y, int tx, int ty, HitTestAction);
@@ -214,7 +237,7 @@ public:
virtual bool isPointInOverflowControl(HitTestResult&, int x, int y, int tx, int ty);
- virtual VisiblePosition positionForCoordinates(int x, int y);
+ virtual VisiblePosition positionForPoint(const IntPoint&);
// Block flows subclass availableWidth to handle multi column layout (shrinking the width available to children when laying out.)
virtual int availableWidth() const;
@@ -223,8 +246,8 @@ public:
void calcInlinePrefWidths();
void calcBlockPrefWidths();
- virtual int getBaselineOfFirstLineBox() const;
- virtual int getBaselineOfLastLineBox() const;
+ virtual int firstLineBoxBaseline() const;
+ virtual int lastLineBoxBaseline() const;
RootInlineBox* firstRootBox() const { return static_cast<RootInlineBox*>(firstLineBox()); }
RootInlineBox* lastRootBox() const { return static_cast<RootInlineBox*>(lastLineBox()); }
@@ -238,38 +261,22 @@ public:
bool inRootBlockContext() const;
- void setHasMarkupTruncation(bool b = true) { m_hasMarkupTruncation = b; }
- bool hasMarkupTruncation() const { return m_hasMarkupTruncation; }
+ virtual IntRect rectWithOutlineForRepaint(RenderBoxModelObject* repaintContainer, int outlineWidth);
+ virtual RenderStyle* outlineStyleForRepaint() const;
+
+ virtual RenderObject* hoverAncestor() const;
+ virtual void updateDragState(bool dragOn);
+ virtual void updateHitTestResult(HitTestResult&, const IntPoint&);
+
+ virtual void childBecameNonInline(RenderObject* child);
- virtual bool hasSelectedChildren() const { return m_selectionState != SelectionNone; }
- virtual SelectionState selectionState() const { return static_cast<SelectionState>(m_selectionState); }
virtual void setSelectionState(SelectionState s);
- struct BlockSelectionInfo {
- RenderBlock* m_block;
- GapRects m_rects;
- SelectionState m_state;
-
- BlockSelectionInfo()
- : m_block(0)
- , m_state(SelectionNone)
- {
- }
-
- BlockSelectionInfo(RenderBlock* b)
- : m_block(b)
- , m_rects(b->needsLayout() ? GapRects() : b->selectionGapRects())
- , m_state(b->selectionState())
- {
- }
-
- RenderBlock* block() const { return m_block; }
- GapRects rects() const { return m_rects; }
- SelectionState state() const { return m_state; }
- };
-
- virtual IntRect selectionRect(bool) { return selectionGapRects(); }
- GapRects selectionGapRects();
+ virtual IntRect selectionRectForRepaint(RenderBoxModelObject* repaintContainer, bool /*clipToVisibleContent*/)
+ {
+ return selectionGapRectsForRepaint(repaintContainer);
+ }
+ GapRects selectionGapRectsForRepaint(RenderBoxModelObject* repaintContainer);
virtual bool shouldPaintSelectionGaps() const;
bool isSelectionRoot() const;
GapRects fillSelectionGaps(RenderBlock* rootBlock, int blockX, int blockY, int tx, int ty,
@@ -290,6 +297,9 @@ public:
int leftSelectionOffset(RenderBlock* rootBlock, int y);
int rightSelectionOffset(RenderBlock* rootBlock, int y);
+ virtual void absoluteRects(Vector<IntRect>&, int tx, int ty);
+ virtual void absoluteQuads(Vector<FloatQuad>&);
+
// Helper methods for computing line counts and heights for line counts.
RootInlineBox* lineAtIndex(int);
int lineCount();
@@ -300,12 +310,24 @@ public:
unsigned desiredColumnCount() const;
Vector<IntRect>* columnRects() const;
void setDesiredColumnCountAndWidth(int count, int width);
+ int columnGap() const;
void adjustRectForColumns(IntRect&) const;
- void addContinuationWithOutline(RenderFlow*);
+ void addContinuationWithOutline(RenderInline*);
void paintContinuationOutlines(PaintInfo&, int tx, int ty);
+ RenderInline* inlineContinuation() const { return m_inlineContinuation; }
+ void setInlineContinuation(RenderInline* c) { m_inlineContinuation = c; }
+
+ virtual IntRect localCaretRect(InlineBox*, int caretOffset, int* extraWidthToEndOfLine = 0);
+
+ virtual void addFocusRingRects(GraphicsContext*, int tx, int ty);
+
+ // This function is a convenience helper for creating an anonymous block that inherits its
+ // style from this RenderBlock.
+ RenderBlock* createAnonymousBlock() const;
+
private:
void adjustPointToColumnContents(IntPoint&) const;
void adjustForBorderFit(int x, int& left, int& right) const; // Helper function for borderFitAdjust
@@ -313,24 +335,28 @@ private:
void markLinesDirtyInVerticalRange(int top, int bottom);
protected:
- virtual void styleWillChange(RenderStyle::Diff, const RenderStyle* newStyle);
- virtual void styleDidChange(RenderStyle::Diff, const RenderStyle* oldStyle);
+ virtual void styleWillChange(StyleDifference, const RenderStyle* newStyle);
+ virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
void newLine(EClear);
virtual bool hasLineIfEmpty() const;
bool layoutOnlyPositionedObjects();
+ virtual RootInlineBox* createRootBox(); // Subclassed by SVG.
+
private:
Position positionForBox(InlineBox*, bool start = true) const;
Position positionForRenderer(RenderObject*, bool start = true) const;
+ VisiblePosition positionForPointWithInlineChildren(const IntPoint&);
// Adjust tx and ty from painting offsets to the local coords of this renderer
void offsetForContents(int& tx, int& ty) const;
- int columnGap() const;
void calcColumnWidth();
int layoutColumns(int endOfContent = -1);
+ bool expandsToEncloseOverhangingFloats() const;
+
protected:
struct FloatingObject {
enum Type {
@@ -352,7 +378,7 @@ protected:
Type type() { return static_cast<Type>(m_type); }
- RenderObject* m_renderer;
+ RenderBox* m_renderer;
int m_top;
int m_bottom;
int m_left;
@@ -362,25 +388,6 @@ protected:
bool m_isDescendant : 1;
};
- // The following helper functions and structs are used by layoutBlockChildren.
- class CompactInfo {
- // A compact child that needs to be collapsed into the margin of the following block.
- RenderObject* m_compact;
-
- // The block with the open margin that the compact child is going to place itself within.
- RenderObject* m_block;
-
- public:
- RenderObject* compact() const { return m_compact; }
- RenderObject* block() const { return m_block; }
- bool matches(RenderObject* child) const { return m_compact && m_block == child; }
-
- void clear() { set(0, 0); }
- void set(RenderObject* c, RenderObject* b) { m_compact = c; m_block = b; }
-
- CompactInfo() { clear(); }
- };
-
class MarginInfo {
// Collapsing flags for whether we can collapse our margins with our children's margins.
bool m_canCollapseWithChildren : 1;
@@ -447,27 +454,31 @@ protected:
int margin() const { return m_posMargin - m_negMargin; }
};
- void adjustPositionedBlock(RenderObject* child, const MarginInfo&);
+ void adjustPositionedBlock(RenderBox* child, const MarginInfo&);
void adjustFloatingBlock(const MarginInfo&);
- RenderObject* handleSpecialChild(RenderObject* child, const MarginInfo&, CompactInfo&, bool& handled);
- RenderObject* handleFloatingChild(RenderObject* child, const MarginInfo&, bool& handled);
- RenderObject* handlePositionedChild(RenderObject* child, const MarginInfo&, bool& handled);
- RenderObject* handleCompactChild(RenderObject* child, CompactInfo&, bool& handled);
- RenderObject* handleRunInChild(RenderObject* child, bool& handled);
- void collapseMargins(RenderObject* child, MarginInfo&, int yPosEstimate);
- void clearFloatsIfNeeded(RenderObject* child, MarginInfo&, int oldTopPosMargin, int oldTopNegMargin);
- void insertCompactIfNeeded(RenderObject* child, CompactInfo&);
- int estimateVerticalPosition(RenderObject* child, const MarginInfo&);
- void determineHorizontalPosition(RenderObject* child);
+ bool handleSpecialChild(RenderBox* child, const MarginInfo&);
+ bool handleFloatingChild(RenderBox* child, const MarginInfo&);
+ bool handlePositionedChild(RenderBox* child, const MarginInfo&);
+ bool handleRunInChild(RenderBox* child);
+ int collapseMargins(RenderBox* child, MarginInfo&);
+ int clearFloatsIfNeeded(RenderBox* child, MarginInfo&, int oldTopPosMargin, int oldTopNegMargin, int yPos);
+ int estimateVerticalPosition(RenderBox* child, const MarginInfo&);
+ void determineHorizontalPosition(RenderBox* child);
void handleBottomOfBlock(int top, int bottom, MarginInfo&);
void setCollapsedBottomMargin(const MarginInfo&);
// End helper functions and structs used by layoutBlockChildren.
private:
- typedef ListHashSet<RenderObject*>::const_iterator Iterator;
+ typedef ListHashSet<RenderBox*>::const_iterator Iterator;
DeprecatedPtrList<FloatingObject>* m_floatingObjects;
- ListHashSet<RenderObject*>* m_positionedObjects;
-
+ ListHashSet<RenderBox*>* m_positionedObjects;
+
+ // An inline can be split with blocks occurring in between the inline content.
+ // When this occurs we need a pointer to our next object. We can basically be
+ // split into a sequence of inlines and blocks. The continuation will either be
+ // an anonymous block (that houses other blocks) or it will be an inline flow.
+ RenderInline* m_inlineContinuation;
+
// Allocated only when some of these fields have non-default values
struct MaxMargin {
MaxMargin(const RenderBlock* o)
@@ -492,13 +503,33 @@ private:
MaxMargin* m_maxMargin;
protected:
+ RenderObjectChildList m_children;
+ RenderLineBoxList m_lineBoxes; // All of the root line boxes created for this block flow. For example, <div>Hello<br>world.</div> will have two total lines for the <div>.
+
// How much content overflows out of our block vertically or horizontally.
int m_overflowHeight;
int m_overflowWidth;
int m_overflowLeft;
int m_overflowTop;
+
+ mutable int m_lineHeight;
};
+inline RenderBlock* toRenderBlock(RenderObject* o)
+{
+ ASSERT(!o || o->isRenderBlock());
+ return static_cast<RenderBlock*>(o);
+}
+
+inline const RenderBlock* toRenderBlock(const RenderObject* o)
+{
+ ASSERT(!o || o->isRenderBlock());
+ return static_cast<const RenderBlock*>(o);
+}
+
+// This will catch anyone doing an unnecessary cast.
+void toRenderBlock(const RenderBlock* o);
+
} // namespace WebCore
#endif // RenderBlock_h
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderBox.cpp b/src/3rdparty/webkit/WebCore/rendering/RenderBox.cpp
index 78691de..ab0d153 100644
--- a/src/3rdparty/webkit/WebCore/rendering/RenderBox.cpp
+++ b/src/3rdparty/webkit/WebCore/rendering/RenderBox.cpp
@@ -30,21 +30,28 @@
#include "Document.h"
#include "FrameView.h"
#include "GraphicsContext.h"
+#include "htmlediting.h"
#include "HTMLElement.h"
#include "HTMLNames.h"
#include "ImageBuffer.h"
+#include "FloatQuad.h"
#include "Frame.h"
#include "Page.h"
#include "RenderArena.h"
#include "RenderFlexibleBox.h"
+#include "RenderInline.h"
#include "RenderLayer.h"
-#include "RenderReplica.h"
#include "RenderTableCell.h"
#include "RenderTheme.h"
#include "RenderView.h"
+#include "TransformState.h"
#include <algorithm>
#include <math.h>
+#if ENABLE(WML)
+#include "WMLNames.h"
+#endif
+
using namespace std;
namespace WebCore {
@@ -55,24 +62,19 @@ using namespace HTMLNames;
typedef WTF::HashMap<const RenderBox*, int> OverrideSizeMap;
static OverrideSizeMap* gOverrideSizeMap = 0;
-bool RenderBox::s_wasFloating = false;
bool RenderBox::s_hadOverflowClip = false;
RenderBox::RenderBox(Node* node)
- : RenderObject(node)
- , m_width(0)
- , m_height(0)
- , m_x(0)
- , m_y(0)
+ : RenderBoxModelObject(node)
, m_marginLeft(0)
, m_marginRight(0)
, m_marginTop(0)
, m_marginBottom(0)
, m_minPrefWidth(-1)
, m_maxPrefWidth(-1)
- , m_layer(0)
, m_inlineBoxWrapper(0)
{
+ setIsBox();
}
RenderBox::~RenderBox()
@@ -87,60 +89,107 @@ void RenderBox::destroy()
if (hasOverrideSize())
gOverrideSizeMap->remove(this);
- // This must be done before we destroy the RenderObject.
- if (m_layer)
- m_layer->clearClipRects();
-
if (style() && (style()->height().isPercent() || style()->minHeight().isPercent() || style()->maxHeight().isPercent()))
RenderBlock::removePercentHeightDescendant(this);
- RenderObject::destroy();
+ RenderBoxModelObject::destroy();
}
-void RenderBox::styleWillChange(RenderStyle::Diff diff, const RenderStyle* newStyle)
+void RenderBox::removeFloatingOrPositionedChildFromBlockLists()
{
- s_wasFloating = isFloating();
- s_hadOverflowClip = hasOverflowClip();
+ ASSERT(isFloatingOrPositioned());
+
+ if (documentBeingDestroyed())
+ return;
- RenderObject::styleWillChange(diff, newStyle);
+ if (isFloating()) {
+ RenderBlock* outermostBlock = containingBlock();
+ for (RenderBlock* p = outermostBlock; p && !p->isRenderView(); p = p->containingBlock()) {
+ if (p->containsFloat(this))
+ outermostBlock = p;
+ }
+
+ if (outermostBlock)
+ outermostBlock->markAllDescendantsWithFloatsForLayout(this, false);
+ }
+
+ if (isPositioned()) {
+ RenderObject* p;
+ for (p = parent(); p; p = p->parent()) {
+ if (p->isRenderBlock())
+ toRenderBlock(p)->removePositionedObject(this);
+ }
+ }
}
-void RenderBox::styleDidChange(RenderStyle::Diff diff, const RenderStyle* oldStyle)
+void RenderBox::styleWillChange(StyleDifference diff, const RenderStyle* newStyle)
{
- // We need to ensure that view->maximalOutlineSize() is valid for any repaints that happen
- // during the style change (it's used by absoluteClippedOverflowRect()).
- if (style()->outlineWidth() > 0 && style()->outlineSize() > maximalOutlineSize(PaintPhaseOutline))
- static_cast<RenderView*>(document()->renderer())->setMaximalOutlineSize(style()->outlineSize());
+ s_hadOverflowClip = hasOverflowClip();
+
+ if (style()) {
+ // The background of the root element or the body element could propagate up to
+ // the canvas. Just dirty the entire canvas when our style changes substantially.
+ if (diff >= StyleDifferenceRepaint && node() &&
+ (node()->hasTagName(htmlTag) || node()->hasTagName(bodyTag)))
+ view()->repaint();
+
+ // When a layout hint happens and an object's position style changes, we have to do a layout
+ // to dirty the render tree using the old position value now.
+ if (diff == StyleDifferenceLayout && parent() && style()->position() != newStyle->position()) {
+ markContainingBlocksForLayout();
+ if (style()->position() == StaticPosition)
+ repaint();
+ if (isFloating() && !isPositioned() && (newStyle->position() == AbsolutePosition || newStyle->position() == FixedPosition))
+ removeFloatingOrPositionedChildFromBlockLists();
+ }
+ }
+
+ RenderBoxModelObject::styleWillChange(diff, newStyle);
+}
- RenderObject::styleDidChange(diff, oldStyle);
+void RenderBox::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
+{
+ RenderBoxModelObject::styleDidChange(diff, oldStyle);
if (needsLayout() && oldStyle && (oldStyle->height().isPercent() || oldStyle->minHeight().isPercent() || oldStyle->maxHeight().isPercent()))
RenderBlock::removePercentHeightDescendant(this);
- // The root and the RenderView always paint their backgrounds/borders.
- if (isRoot() || isRenderView())
- setHasBoxDecorations(true);
+ // If our zoom factor changes and we have a defined scrollLeft/Top, we need to adjust that value into the
+ // new zoomed coordinate space.
+ if (hasOverflowClip() && oldStyle && style() && oldStyle->effectiveZoom() != style()->effectiveZoom()) {
+ int left = scrollLeft();
+ if (left) {
+ left = (left / oldStyle->effectiveZoom()) * style()->effectiveZoom();
+ setScrollLeft(left);
+ }
+ int top = scrollTop();
+ if (top) {
+ top = (top / oldStyle->effectiveZoom()) * style()->effectiveZoom();
+ setScrollTop(top);
+ }
+ }
- setInline(style()->isDisplayInlineType());
+ // Set the text color if we're the body.
+ if (isBody())
+ document()->setTextColor(style()->color());
+}
- switch (style()->position()) {
- case AbsolutePosition:
- case FixedPosition:
- setPositioned(true);
- break;
- default:
- setPositioned(false);
+void RenderBox::updateBoxModelInfoFromStyle()
+{
+ RenderBoxModelObject::updateBoxModelInfoFromStyle();
- if (style()->isFloating())
- setFloating(true);
+ bool isRootObject = isRoot();
+ bool isViewObject = isRenderView();
- if (style()->position() == RelativePosition)
- setRelPositioned(true);
- break;
- }
+ // The root and the RenderView always paint their backgrounds/borders.
+ if (isRootObject || isViewObject)
+ setHasBoxDecorations(true);
+
+ setPositioned(style()->position() == AbsolutePosition || style()->position() == FixedPosition);
+ setFloating(!isPositioned() && style()->isFloating());
// We also handle <body> and <html>, whose overflow applies to the viewport.
- if (!isRoot() && (isRenderBlock() || isTableRow() || isTableSection()) && style()->overflowX() != OVISIBLE) {
+ if (style()->overflowX() != OVISIBLE && !isRootObject && (isRenderBlock() || isTableRow() || isTableSection())) {
bool boxHasOverflowClip = true;
if (isBody()) {
// Overflow on the body can propagate to the viewport under the following conditions.
@@ -148,7 +197,7 @@ void RenderBox::styleDidChange(RenderStyle::Diff diff, const RenderStyle* oldSty
// (2) We are the primary <body> (can be checked by looking at document.body).
// (3) The root element has visible overflow.
if (document()->documentElement()->hasTagName(htmlTag) &&
- document()->body() == element() &&
+ document()->body() == node() &&
document()->documentElement()->renderer()->style()->overflowX() == OVISIBLE)
boxHasOverflowClip = false;
}
@@ -163,52 +212,220 @@ void RenderBox::styleDidChange(RenderStyle::Diff diff, const RenderStyle* oldSty
}
}
- setHasTransform(style()->hasTransform());
+ setHasTransform(style()->hasTransformRelatedProperty());
setHasReflection(style()->boxReflect());
+}
- if (requiresLayer()) {
- if (!m_layer) {
- if (s_wasFloating && isFloating())
- setChildNeedsLayout(true);
- m_layer = new (renderArena()) RenderLayer(this);
- setHasLayer(true);
- m_layer->insertOnlyThisLayer();
- if (parent() && !needsLayout() && containingBlock())
- m_layer->updateLayerPositions();
- }
- } else if (m_layer && !isRoot() && !isRenderView()) {
- ASSERT(m_layer->parent());
- RenderLayer* layer = m_layer;
- m_layer = 0;
- setHasLayer(false);
- setHasTransform(false); // Either a transform wasn't specified or the object doesn't support transforms, so just null out the bit.
- setHasReflection(false);
- layer->removeOnlyThisLayer();
- if (s_wasFloating && isFloating())
- setChildNeedsLayout(true);
+void RenderBox::layout()
+{
+ ASSERT(needsLayout());
+
+ RenderObject* child = firstChild();
+ if (!child) {
+ setNeedsLayout(false);
+ return;
}
- // If our zoom factor changes and we have a defined scrollLeft/Top, we need to adjust that value into the
- // new zoomed coordinate space.
- if (hasOverflowClip() && oldStyle && style() && oldStyle->effectiveZoom() != style()->effectiveZoom()) {
- int left = scrollLeft();
- if (left) {
- left = (left / oldStyle->effectiveZoom()) * style()->effectiveZoom();
- setScrollLeft(left);
- }
- int top = scrollTop();
- if (top) {
- top = (top / oldStyle->effectiveZoom()) * style()->effectiveZoom();
- setScrollTop(top);
- }
+ LayoutStateMaintainer statePusher(view(), this, IntSize(x(), y()));
+ while (child) {
+ child->layoutIfNeeded();
+ ASSERT(!child->needsLayout());
+ child = child->nextSibling();
}
+ statePusher.pop();
+ setNeedsLayout(false);
+}
+
+// More IE extensions. clientWidth and clientHeight represent the interior of an object
+// excluding border and scrollbar.
+int RenderBox::clientWidth() const
+{
+ return width() - borderLeft() - borderRight() - verticalScrollbarWidth();
+}
- if (m_layer)
- m_layer->styleChanged(diff, oldStyle);
+int RenderBox::clientHeight() const
+{
+ return height() - borderTop() - borderBottom() - horizontalScrollbarHeight();
+}
- // Set the text color if we're the body.
- if (isBody())
- document()->setTextColor(style()->color());
+int RenderBox::scrollWidth() const
+{
+ if (hasOverflowClip())
+ return layer()->scrollWidth();
+ // For objects with visible overflow, this matches IE.
+ if (style()->direction() == LTR)
+ return max(clientWidth(), rightmostPosition(true, false) - borderLeft());
+ return clientWidth() - min(0, leftmostPosition(true, false) - borderLeft());
+}
+
+int RenderBox::scrollHeight() const
+{
+ if (hasOverflowClip())
+ return layer()->scrollHeight();
+ // For objects with visible overflow, this matches IE.
+ return max(clientHeight(), lowestPosition(true, false) - borderTop());
+}
+
+int RenderBox::scrollLeft() const
+{
+ return hasOverflowClip() ? layer()->scrollXOffset() : 0;
+}
+
+int RenderBox::scrollTop() const
+{
+ return hasOverflowClip() ? layer()->scrollYOffset() : 0;
+}
+
+void RenderBox::setScrollLeft(int newLeft)
+{
+ if (hasOverflowClip())
+ layer()->scrollToXOffset(newLeft);
+}
+
+void RenderBox::setScrollTop(int newTop)
+{
+ if (hasOverflowClip())
+ layer()->scrollToYOffset(newTop);
+}
+
+void RenderBox::absoluteRects(Vector<IntRect>& rects, int tx, int ty)
+{
+ rects.append(IntRect(tx, ty, width(), height()));
+}
+
+void RenderBox::absoluteQuads(Vector<FloatQuad>& quads)
+{
+ quads.append(localToAbsoluteQuad(FloatRect(0, 0, width(), height())));
+}
+
+IntRect RenderBox::absoluteContentBox() const
+{
+ IntRect rect = contentBoxRect();
+ FloatPoint absPos = localToAbsolute(FloatPoint());
+ rect.move(absPos.x(), absPos.y());
+ return rect;
+}
+
+FloatQuad RenderBox::absoluteContentQuad() const
+{
+ IntRect rect = contentBoxRect();
+ return localToAbsoluteQuad(FloatRect(rect));
+}
+
+IntRect RenderBox::outlineBoundsForRepaint(RenderBoxModelObject* repaintContainer) const
+{
+ IntRect box = borderBoundingBox();
+ adjustRectForOutlineAndShadow(box);
+
+ FloatQuad containerRelativeQuad = localToContainerQuad(FloatRect(box), repaintContainer);
+ box = containerRelativeQuad.enclosingBoundingBox();
+
+ // FIXME: layoutDelta needs to be applied in parts before/after transforms and
+ // repaint containers. https://bugs.webkit.org/show_bug.cgi?id=23308
+ box.move(view()->layoutDelta());
+
+ return box;
+}
+
+void RenderBox::addFocusRingRects(GraphicsContext* graphicsContext, int tx, int ty)
+{
+ graphicsContext->addFocusRingRect(IntRect(tx, ty, width(), height()));
+}
+
+
+IntRect RenderBox::reflectionBox() const
+{
+ IntRect result;
+ if (!style()->boxReflect())
+ return result;
+ IntRect box = borderBoxRect();
+ result = box;
+ switch (style()->boxReflect()->direction()) {
+ case ReflectionBelow:
+ result.move(0, box.height() + reflectionOffset());
+ break;
+ case ReflectionAbove:
+ result.move(0, -box.height() - reflectionOffset());
+ break;
+ case ReflectionLeft:
+ result.move(-box.width() - reflectionOffset(), 0);
+ break;
+ case ReflectionRight:
+ result.move(box.width() + reflectionOffset(), 0);
+ break;
+ }
+ return result;
+}
+
+int RenderBox::reflectionOffset() const
+{
+ if (!style()->boxReflect())
+ return 0;
+ if (style()->boxReflect()->direction() == ReflectionLeft || style()->boxReflect()->direction() == ReflectionRight)
+ return style()->boxReflect()->offset().calcValue(borderBoxRect().width());
+ return style()->boxReflect()->offset().calcValue(borderBoxRect().height());
+}
+
+IntRect RenderBox::reflectedRect(const IntRect& r) const
+{
+ if (!style()->boxReflect())
+ return IntRect();
+
+ IntRect box = borderBoxRect();
+ IntRect result = r;
+ switch (style()->boxReflect()->direction()) {
+ case ReflectionBelow:
+ result.setY(box.bottom() + reflectionOffset() + (box.bottom() - r.bottom()));
+ break;
+ case ReflectionAbove:
+ result.setY(box.y() - reflectionOffset() - box.height() + (box.bottom() - r.bottom()));
+ break;
+ case ReflectionLeft:
+ result.setX(box.x() - reflectionOffset() - box.width() + (box.right() - r.right()));
+ break;
+ case ReflectionRight:
+ result.setX(box.right() + reflectionOffset() + (box.right() - r.right()));
+ break;
+ }
+ return result;
+}
+
+int RenderBox::verticalScrollbarWidth() const
+{
+ return includeVerticalScrollbarSize() ? layer()->verticalScrollbarWidth() : 0;
+}
+
+int RenderBox::horizontalScrollbarHeight() const
+{
+ return includeHorizontalScrollbarSize() ? layer()->horizontalScrollbarHeight() : 0;
+}
+
+bool RenderBox::scroll(ScrollDirection direction, ScrollGranularity granularity, float multiplier)
+{
+ RenderLayer* l = layer();
+ if (l && l->scroll(direction, granularity, multiplier))
+ return true;
+ RenderBlock* b = containingBlock();
+ if (b && !b->isRenderView())
+ return b->scroll(direction, granularity, multiplier);
+ return false;
+}
+
+bool RenderBox::canBeProgramaticallyScrolled(bool) const
+{
+ return (hasOverflowClip() && (scrollsOverflow() || (node() && node()->isContentEditable()))) || (node() && node()->isDocumentNode());
+}
+
+void RenderBox::autoscroll()
+{
+ if (layer())
+ layer()->autoscroll();
+}
+
+void RenderBox::panScroll(const IntPoint& source)
+{
+ if (layer())
+ layer()->panScrollFromPoint(source);
}
int RenderBox::minPrefWidth() const
@@ -251,22 +468,12 @@ void RenderBox::setOverrideSize(int s)
int RenderBox::overrideWidth() const
{
- return hasOverrideSize() ? overrideSize() : m_width;
+ return hasOverrideSize() ? overrideSize() : width();
}
int RenderBox::overrideHeight() const
{
- return hasOverrideSize() ? overrideSize() : m_height;
-}
-
-void RenderBox::setPos(int xPos, int yPos)
-{
- // Optimize for the case where we don't move at all.
- if (xPos == m_x && yPos == m_y)
- return;
-
- m_x = xPos;
- m_y = yPos;
+ return hasOverrideSize() ? overrideSize() : height();
}
int RenderBox::calcBorderBoxWidth(int width) const
@@ -300,27 +507,23 @@ int RenderBox::calcContentBoxHeight(int height) const
}
// Hit Testing
-bool RenderBox::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, int x, int y, int tx, int ty, HitTestAction action)
+bool RenderBox::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, int xPos, int yPos, int tx, int ty, HitTestAction action)
{
- tx += m_x;
- ty += m_y;
+ tx += x();
+ ty += y();
// Check kids first.
for (RenderObject* child = lastChild(); child; child = child->previousSibling()) {
- // FIXME: We have to skip over inline flows, since they can show up inside table rows
- // at the moment (a demoted inline <form> for example). If we ever implement a
- // table-specific hit-test method (which we should do for performance reasons anyway),
- // then we can remove this check.
- if (!child->hasLayer() && !child->isInlineFlow() && child->nodeAtPoint(request, result, x, y, tx, ty, action)) {
- updateHitTestResult(result, IntPoint(x - tx, y - ty));
+ if (!child->hasLayer() && child->nodeAtPoint(request, result, xPos, yPos, tx, ty, action)) {
+ updateHitTestResult(result, IntPoint(xPos - tx, yPos - ty));
return true;
}
}
// Check our bounds next. For this purpose always assume that we can only be hit in the
// foreground phase (which is true for replaced elements like images).
- if (visibleToHitTesting() && action == HitTestForeground && IntRect(tx, ty, m_width, m_height).contains(x, y)) {
- updateHitTestResult(result, IntPoint(x - tx, y - ty));
+ if (visibleToHitTesting() && action == HitTestForeground && IntRect(tx, ty, width(), height()).contains(xPos, yPos)) {
+ updateHitTestResult(result, IntPoint(xPos - tx, yPos - ty));
return true;
}
@@ -331,8 +534,8 @@ bool RenderBox::nodeAtPoint(const HitTestRequest& request, HitTestResult& result
void RenderBox::paint(PaintInfo& paintInfo, int tx, int ty)
{
- tx += m_x;
- ty += m_y;
+ tx += x();
+ ty += y();
// default implementation. Just pass paint through to the children
PaintInfo childInfo(paintInfo);
@@ -345,7 +548,7 @@ void RenderBox::paintRootBoxDecorations(PaintInfo& paintInfo, int tx, int ty)
{
const FillLayer* bgLayer = style()->backgroundLayers();
Color bgColor = style()->backgroundColor();
- if (!style()->hasBackground() && element() && element()->hasTagName(HTMLNames::htmlTag)) {
+ if (!style()->hasBackground() && node() && node()->hasTagName(HTMLNames::htmlTag)) {
// Locate the <body> element using the DOM. This is easier than trying
// to crawl around a render tree with potential :before/:after content and
// anonymous blocks created by inline <body> tags etc. We can locate the <body>
@@ -379,9 +582,7 @@ void RenderBox::paintRootBoxDecorations(PaintInfo& paintInfo, int tx, int ty)
int bw = max(w + marginLeft() + marginRight() + borderLeft() + borderRight(), rw);
int bh = max(h + marginTop() + marginBottom() + borderTop() + borderBottom(), rh);
- int my = max(by, paintInfo.rect.y());
-
- paintFillLayers(paintInfo, bgColor, bgLayer, my, paintInfo.rect.height(), bx, by, bw, bh);
+ paintFillLayers(paintInfo, bgColor, bgLayer, bx, by, bw, bh);
if (style()->hasBorder() && style()->display() != INLINE)
paintBorder(paintInfo.context, tx, ty, w, h, style());
@@ -398,20 +599,12 @@ void RenderBox::paintBoxDecorations(PaintInfo& paintInfo, int tx, int ty)
}
int w = width();
- int h = height() + borderTopExtra() + borderBottomExtra();
- ty -= borderTopExtra();
+ int h = height();
// border-fit can adjust where we paint our border and background. If set, we snugly fit our line box descendants. (The iChat
// balloon layout is an example of this).
borderFitAdjust(tx, w);
- int my = max(ty, paintInfo.rect.y());
- int mh;
- if (ty < paintInfo.rect.y())
- mh = max(0, h - (paintInfo.rect.y() - ty));
- else
- mh = min(paintInfo.rect.height(), h);
-
// FIXME: Should eventually give the theme control over whether the box shadow should paint, since controls could have
// custom shadows of their own.
paintBoxShadow(paintInfo.context, tx, ty, w, h, style());
@@ -424,7 +617,7 @@ void RenderBox::paintBoxDecorations(PaintInfo& paintInfo, int tx, int ty)
// independent of the body. Go through the DOM to get to the root element's render object,
// since the root could be inline and wrapped in an anonymous block.
if (!isBody() || document()->documentElement()->renderer()->style()->hasBackground())
- paintFillLayers(paintInfo, style()->backgroundColor(), style()->backgroundLayers(), my, mh, tx, ty, w, h);
+ paintFillLayers(paintInfo, style()->backgroundColor(), style()->backgroundLayers(), tx, ty, w, h);
if (style()->hasAppearance())
theme()->paintDecorations(this, paintInfo, IntRect(tx, ty, w, h));
}
@@ -440,35 +633,38 @@ void RenderBox::paintMask(PaintInfo& paintInfo, int tx, int ty)
return;
int w = width();
- int h = height() + borderTopExtra() + borderBottomExtra();
- ty -= borderTopExtra();
+ int h = height();
// border-fit can adjust where we paint our border and background. If set, we snugly fit our line box descendants. (The iChat
// balloon layout is an example of this).
borderFitAdjust(tx, w);
- int my = max(ty, paintInfo.rect.y());
- int mh;
- if (ty < paintInfo.rect.y())
- mh = max(0, h - (paintInfo.rect.y() - ty));
- else
- mh = min(paintInfo.rect.height(), h);
-
- paintMaskImages(paintInfo, my, mh, tx, ty, w, h);
+ paintMaskImages(paintInfo, tx, ty, w, h);
}
-void RenderBox::paintMaskImages(const PaintInfo& paintInfo, int my, int mh, int tx, int ty, int w, int h)
+void RenderBox::paintMaskImages(const PaintInfo& paintInfo, int tx, int ty, int w, int h)
{
// Figure out if we need to push a transparency layer to render our mask.
bool pushTransparencyLayer = false;
StyleImage* maskBoxImage = style()->maskBoxImage().image();
- if ((maskBoxImage && style()->maskLayers()->hasImage()) || style()->maskLayers()->next())
+ if (maskBoxImage && style()->maskLayers()->hasImage()) {
+ pushTransparencyLayer = true;
+ } else {
// We have to use an extra image buffer to hold the mask. Multiple mask images need
// to composite together using source-over so that they can then combine into a single unified mask that
// can be composited with the content using destination-in. SVG images need to be able to set compositing modes
// as they draw images contained inside their sub-document, so we paint all our images into a separate buffer
// and composite that buffer as the mask.
- pushTransparencyLayer = true;
+ // We have to check that the mask images to be rendered contain at least one image that can be actually used in rendering
+ // before pushing the transparency layer.
+ for (const FillLayer* fillLayer = style()->maskLayers()->next(); fillLayer; fillLayer = fillLayer->next()) {
+ if (fillLayer->hasImage() && fillLayer->image()->canRender(style()->effectiveZoom())) {
+ pushTransparencyLayer = true;
+ // We found one image that can be used in rendering, exit the loop
+ break;
+ }
+ }
+ }
CompositeOperator compositeOp = CompositeDestinationIn;
if (pushTransparencyLayer) {
@@ -477,7 +673,7 @@ void RenderBox::paintMaskImages(const PaintInfo& paintInfo, int my, int mh, int
compositeOp = CompositeSourceOver;
}
- paintFillLayers(paintInfo, Color(), style()->maskLayers(), my, mh, tx, ty, w, h, compositeOp);
+ paintFillLayers(paintInfo, Color(), style()->maskLayers(), tx, ty, w, h, compositeOp);
paintNinePieceImage(paintInfo.context, tx, ty, w, h, style(), style()->maskBoxImage(), compositeOp);
if (pushTransparencyLayer)
@@ -486,7 +682,7 @@ void RenderBox::paintMaskImages(const PaintInfo& paintInfo, int my, int mh, int
IntRect RenderBox::maskClipRect()
{
- IntRect bbox = borderBox();
+ IntRect bbox = borderBoxRect();
if (style()->maskBoxImage().image())
return bbox;
@@ -503,79 +699,39 @@ IntRect RenderBox::maskClipRect()
return result;
}
-void RenderBox::paintFillLayers(const PaintInfo& paintInfo, const Color& c, const FillLayer* fillLayer,
- int clipY, int clipH, int tx, int ty, int width, int height, CompositeOperator op)
+void RenderBox::paintFillLayers(const PaintInfo& paintInfo, const Color& c, const FillLayer* fillLayer, int tx, int ty, int width, int height, CompositeOperator op)
{
if (!fillLayer)
return;
- paintFillLayers(paintInfo, c, fillLayer->next(), clipY, clipH, tx, ty, width, height, op);
- paintFillLayer(paintInfo, c, fillLayer, clipY, clipH, tx, ty, width, height, op);
+ paintFillLayers(paintInfo, c, fillLayer->next(), tx, ty, width, height, op);
+ paintFillLayer(paintInfo, c, fillLayer, tx, ty, width, height, op);
}
-void RenderBox::paintFillLayer(const PaintInfo& paintInfo, const Color& c, const FillLayer* fillLayer,
- int clipY, int clipH, int tx, int ty, int width, int height, CompositeOperator op)
+void RenderBox::paintFillLayer(const PaintInfo& paintInfo, const Color& c, const FillLayer* fillLayer, int tx, int ty, int width, int height, CompositeOperator op)
{
- paintFillLayerExtended(paintInfo, c, fillLayer, clipY, clipH, tx, ty, width, height, 0, op);
-}
-
-IntSize RenderBox::calculateBackgroundSize(const FillLayer* bgLayer, int scaledWidth, int scaledHeight) const
-{
- StyleImage* bg = bgLayer->image();
- bg->setImageContainerSize(IntSize(scaledWidth, scaledHeight)); // Use the box established by background-origin.
-
- if (bgLayer->isSizeSet()) {
- int w = scaledWidth;
- int h = scaledHeight;
- Length bgWidth = bgLayer->size().width();
- Length bgHeight = bgLayer->size().height();
-
- if (bgWidth.isFixed())
- w = bgWidth.value();
- else if (bgWidth.isPercent())
- w = bgWidth.calcValue(scaledWidth);
-
- if (bgHeight.isFixed())
- h = bgHeight.value();
- else if (bgHeight.isPercent())
- h = bgHeight.calcValue(scaledHeight);
-
- // If one of the values is auto we have to use the appropriate
- // scale to maintain our aspect ratio.
- if (bgWidth.isAuto() && !bgHeight.isAuto())
- w = bg->imageSize(this, style()->effectiveZoom()).width() * h / bg->imageSize(this, style()->effectiveZoom()).height();
- else if (!bgWidth.isAuto() && bgHeight.isAuto())
- h = bg->imageSize(this, style()->effectiveZoom()).height() * w / bg->imageSize(this, style()->effectiveZoom()).width();
- else if (bgWidth.isAuto() && bgHeight.isAuto()) {
- // If both width and height are auto, we just want to use the image's
- // intrinsic size.
- w = bg->imageSize(this, style()->effectiveZoom()).width();
- h = bg->imageSize(this, style()->effectiveZoom()).height();
- }
-
- return IntSize(max(1, w), max(1, h));
- } else
- return bg->imageSize(this, style()->effectiveZoom());
+ paintFillLayerExtended(paintInfo, c, fillLayer, tx, ty, width, height, 0, op);
}
void RenderBox::imageChanged(WrappedImagePtr image, const IntRect*)
{
- if (isInlineFlow() ||
- style()->borderImage().image() && style()->borderImage().image()->data() == image ||
- style()->maskBoxImage().image() && style()->maskBoxImage().image()->data() == image) {
+ if (!parent())
+ return;
+
+ if ((style()->borderImage().image() && style()->borderImage().image()->data() == image) ||
+ (style()->maskBoxImage().image() && style()->maskBoxImage().image()->data() == image)) {
repaint();
return;
}
bool didFullRepaint = repaintLayerRectsForImage(image, style()->backgroundLayers(), true);
- if (!didFullRepaint) {
+ if (!didFullRepaint)
repaintLayerRectsForImage(image, style()->maskLayers(), false);
- }
}
bool RenderBox::repaintLayerRectsForImage(WrappedImagePtr image, const FillLayer* layers, bool drawingBackground)
{
- IntRect absoluteRect;
+ IntRect rendererRect;
RenderBox* layerRenderer = 0;
for (const FillLayer* curLayer = layers; curLayer; curLayer = curLayer->next()) {
@@ -590,287 +746,35 @@ bool RenderBox::repaintLayerRectsForImage(WrappedImagePtr image, const FillLayer
int rw;
int rh;
- if (FrameView* frameView = static_cast<RenderView*>(layerRenderer)->frameView()) {
+ if (FrameView* frameView = toRenderView(layerRenderer)->frameView()) {
rw = frameView->contentsWidth();
rh = frameView->contentsHeight();
} else {
rw = layerRenderer->width();
rh = layerRenderer->height();
}
- absoluteRect = IntRect(-layerRenderer->marginLeft(),
+ rendererRect = IntRect(-layerRenderer->marginLeft(),
-layerRenderer->marginTop(),
max(layerRenderer->width() + layerRenderer->marginLeft() + layerRenderer->marginRight() + layerRenderer->borderLeft() + layerRenderer->borderRight(), rw),
max(layerRenderer->height() + layerRenderer->marginTop() + layerRenderer->marginBottom() + layerRenderer->borderTop() + layerRenderer->borderBottom(), rh));
} else {
layerRenderer = this;
- absoluteRect = borderBox();
+ rendererRect = borderBoxRect();
}
-
- layerRenderer->computeAbsoluteRepaintRect(absoluteRect);
}
IntRect repaintRect;
IntPoint phase;
IntSize tileSize;
- layerRenderer->calculateBackgroundImageGeometry(curLayer, absoluteRect.x(), absoluteRect.y(), absoluteRect.width(), absoluteRect.height(), repaintRect, phase, tileSize);
- view()->repaintViewRectangle(repaintRect);
- if (repaintRect == absoluteRect)
+ layerRenderer->calculateBackgroundImageGeometry(curLayer, rendererRect.x(), rendererRect.y(), rendererRect.width(), rendererRect.height(), repaintRect, phase, tileSize);
+ layerRenderer->repaintRectangle(repaintRect);
+ if (repaintRect == rendererRect)
return true;
}
}
return false;
}
-void RenderBox::calculateBackgroundImageGeometry(const FillLayer* bgLayer, int tx, int ty, int w, int h, IntRect& destRect, IntPoint& phase, IntSize& tileSize)
-{
- int pw;
- int ph;
- int left = 0;
- int right = 0;
- int top = 0;
- int bottom = 0;
- int cx;
- int cy;
- int rw = 0;
- int rh = 0;
-
- // CSS2 chapter 14.2.1
-
- if (bgLayer->attachment()) {
- // Scroll
- if (bgLayer->origin() != BorderFillBox) {
- left = borderLeft();
- right = borderRight();
- top = borderTop();
- bottom = borderBottom();
- if (bgLayer->origin() == ContentFillBox) {
- left += paddingLeft();
- right += paddingRight();
- top += paddingTop();
- bottom += paddingBottom();
- }
- }
-
- // The background of the box generated by the root element covers the entire canvas including
- // its margins. Since those were added in already, we have to factor them out when computing the
- // box used by background-origin/size/position.
- if (isRoot()) {
- rw = width() - left - right;
- rh = height() - top - bottom;
- left += marginLeft();
- right += marginRight();
- top += marginTop();
- bottom += marginBottom();
- }
- cx = tx;
- cy = ty;
- pw = w - left - right;
- ph = h - top - bottom;
- } else {
- // Fixed
- IntRect vr = viewRect();
- cx = vr.x();
- cy = vr.y();
- pw = vr.width();
- ph = vr.height();
- }
-
- int sx = 0;
- int sy = 0;
- int cw;
- int ch;
-
- IntSize scaledImageSize;
- if (isRoot() && bgLayer->attachment())
- scaledImageSize = calculateBackgroundSize(bgLayer, rw, rh);
- else
- scaledImageSize = calculateBackgroundSize(bgLayer, pw, ph);
-
- int scaledImageWidth = scaledImageSize.width();
- int scaledImageHeight = scaledImageSize.height();
-
- EFillRepeat backgroundRepeat = bgLayer->repeat();
-
- int xPosition;
- if (isRoot() && bgLayer->attachment())
- xPosition = bgLayer->xPosition().calcMinValue(rw - scaledImageWidth, true);
- else
- xPosition = bgLayer->xPosition().calcMinValue(pw - scaledImageWidth, true);
- if (backgroundRepeat == RepeatFill || backgroundRepeat == RepeatXFill) {
- cw = pw + left + right;
- sx = scaledImageWidth ? scaledImageWidth - (xPosition + left) % scaledImageWidth : 0;
- } else {
- cx += max(xPosition + left, 0);
- sx = -min(xPosition + left, 0);
- cw = scaledImageWidth + min(xPosition + left, 0);
- }
-
- int yPosition;
- if (isRoot() && bgLayer->attachment())
- yPosition = bgLayer->yPosition().calcMinValue(rh - scaledImageHeight, true);
- else
- yPosition = bgLayer->yPosition().calcMinValue(ph - scaledImageHeight, true);
- if (backgroundRepeat == RepeatFill || backgroundRepeat == RepeatYFill) {
- ch = ph + top + bottom;
- sy = scaledImageHeight ? scaledImageHeight - (yPosition + top) % scaledImageHeight : 0;
- } else {
- cy += max(yPosition + top, 0);
- sy = -min(yPosition + top, 0);
- ch = scaledImageHeight + min(yPosition + top, 0);
- }
-
- if (!bgLayer->attachment()) {
- sx += max(tx - cx, 0);
- sy += max(ty - cy, 0);
- }
-
- destRect = IntRect(cx, cy, cw, ch);
- destRect.intersect(IntRect(tx, ty, w, h));
- phase = IntPoint(sx, sy);
- tileSize = IntSize(scaledImageWidth, scaledImageHeight);
-}
-
-void RenderBox::paintFillLayerExtended(const PaintInfo& paintInfo, const Color& c, const FillLayer* bgLayer, int clipY, int clipH,
- int tx, int ty, int w, int h, InlineFlowBox* box, CompositeOperator op)
-{
- GraphicsContext* context = paintInfo.context;
- bool includeLeftEdge = box ? box->includeLeftEdge() : true;
- bool includeRightEdge = box ? box->includeRightEdge() : true;
- int bLeft = includeLeftEdge ? borderLeft() : 0;
- int bRight = includeRightEdge ? borderRight() : 0;
- int pLeft = includeLeftEdge ? paddingLeft() : 0;
- int pRight = includeRightEdge ? paddingRight() : 0;
-
- bool clippedToBorderRadius = false;
- if (style()->hasBorderRadius() && (includeLeftEdge || includeRightEdge)) {
- context->save();
- context->addRoundedRectClip(IntRect(tx, ty, w, h),
- includeLeftEdge ? style()->borderTopLeftRadius() : IntSize(),
- includeRightEdge ? style()->borderTopRightRadius() : IntSize(),
- includeLeftEdge ? style()->borderBottomLeftRadius() : IntSize(),
- includeRightEdge ? style()->borderBottomRightRadius() : IntSize());
- clippedToBorderRadius = true;
- }
-
- if (bgLayer->clip() == PaddingFillBox || bgLayer->clip() == ContentFillBox) {
- // Clip to the padding or content boxes as necessary.
- bool includePadding = bgLayer->clip() == ContentFillBox;
- int x = tx + bLeft + (includePadding ? pLeft : 0);
- int y = ty + borderTop() + (includePadding ? paddingTop() : 0);
- int width = w - bLeft - bRight - (includePadding ? pLeft + pRight : 0);
- int height = h - borderTop() - borderBottom() - (includePadding ? paddingTop() + paddingBottom() : 0);
- context->save();
- context->clip(IntRect(x, y, width, height));
- } else if (bgLayer->clip() == TextFillBox) {
- // We have to draw our text into a mask that can then be used to clip background drawing.
- // First figure out how big the mask has to be. It should be no bigger than what we need
- // to actually render, so we should intersect the dirty rect with the border box of the background.
- IntRect maskRect(tx, ty, w, h);
- maskRect.intersect(paintInfo.rect);
-
- // Now create the mask.
- auto_ptr<ImageBuffer> maskImage = ImageBuffer::create(maskRect.size(), false);
- if (!maskImage.get())
- return;
-
- GraphicsContext* maskImageContext = maskImage->context();
- maskImageContext->translate(-maskRect.x(), -maskRect.y());
-
- // 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->xPos(), ty - box->yPos());
- else
- paint(info, tx, ty);
-
- // The mask has been created. Now we just need to clip to it.
- context->save();
- context->clipToImageBuffer(maskRect, maskImage.get());
- }
-
- 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;
- }
- }
-
- // 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 isTransparent = false;
- if (!bgLayer->next() && isRoot() && !(bgColor.isValid() && bgColor.alpha() > 0) && view()->frameView()) {
- Node* elt = document()->ownerElement();
- if (elt) {
- if (!elt->hasTagName(frameTag)) {
- // Locate the <body> element using the DOM. This is easier than trying
- // to crawl around a render tree with potential :before/:after content and
- // anonymous blocks created by inline <body> tags etc. We can locate the <body>
- // render object very easily via the DOM.
- HTMLElement* body = document()->body();
- isTransparent = !body || !body->hasLocalName(framesetTag); // Can't scroll a frameset document anyway.
- }
- } else
- isTransparent = view()->frameView()->isTransparent();
-
- // FIXME: This needs to be dynamic. We should be able to go back to blitting if we ever stop being transparent.
- if (isTransparent)
- view()->frameView()->setUseSlowRepaints(); // The parent must show behind the child.
- }
-
- // Paint the color first underneath all images.
- if (!bgLayer->next()) {
- IntRect rect(tx, clipY, w, clipH);
- // If we have an alpha and we are painting the root element, go ahead and blend with the base background color.
- if (isRoot() && (!bgColor.isValid() || bgColor.alpha() < 0xFF) && !isTransparent) {
- Color baseColor = view()->frameView()->baseBackgroundColor();
- if (baseColor.alpha() > 0) {
- context->save();
- context->setCompositeOperation(CompositeCopy);
- context->fillRect(rect, baseColor);
- context->restore();
- } else
- context->clearRect(rect);
- }
-
- if (bgColor.isValid() && bgColor.alpha() > 0)
- context->fillRect(rect, bgColor);
- }
-
- // no progressive loading of the background image
- if (shouldPaintBackgroundImage) {
- IntRect destRect;
- IntPoint phase;
- IntSize tileSize;
-
- calculateBackgroundImageGeometry(bgLayer, tx, ty, w, h, destRect, phase, tileSize);
- if (!destRect.isEmpty()) {
- CompositeOperator compositeOp = op == CompositeSourceOver ? bgLayer->composite() : op;
- context->drawTiledImage(bg->image(this, tileSize), destRect, phase, tileSize, compositeOp);
- }
- }
-
- if (bgLayer->clip() != BorderFillBox)
- // Undo the background clip
- context->restore();
-
- if (clippedToBorderRadius)
- // Undo the border radius clip
- context->restore();
-}
-
#if PLATFORM(MAC)
void RenderBox::paintCustomHighlight(int tx, int ty, const AtomicString& type, bool behindText)
@@ -885,18 +789,63 @@ void RenderBox::paintCustomHighlight(int tx, int ty, const AtomicString& type, b
InlineBox* boxWrap = inlineBoxWrapper();
RootInlineBox* r = boxWrap ? boxWrap->root() : 0;
if (r) {
- FloatRect rootRect(tx + r->xPos(), ty + r->selectionTop(), r->width(), r->selectionHeight());
- FloatRect imageRect(tx + m_x, rootRect.y(), width(), rootRect.height());
+ FloatRect rootRect(tx + r->x(), ty + r->selectionTop(), r->width(), r->selectionHeight());
+ FloatRect imageRect(tx + x(), rootRect.y(), width(), rootRect.height());
page->chrome()->client()->paintCustomHighlight(node(), type, imageRect, rootRect, behindText, false);
} else {
- FloatRect imageRect(tx + m_x, ty + m_y, width(), height());
+ FloatRect imageRect(tx + x(), ty + y(), width(), height());
page->chrome()->client()->paintCustomHighlight(node(), type, imageRect, imageRect, behindText, false);
}
}
#endif
-IntRect RenderBox::getOverflowClipRect(int tx, int ty)
+bool RenderBox::pushContentsClip(PaintInfo& paintInfo, int tx, int ty)
+{
+ if (paintInfo.phase == PaintPhaseBlockBackground || paintInfo.phase == PaintPhaseSelfOutline || paintInfo.phase == PaintPhaseMask)
+ return false;
+
+ bool isControlClip = hasControlClip();
+ bool isOverflowClip = hasOverflowClip() && !layer()->isSelfPaintingLayer();
+
+ if (!isControlClip && !isOverflowClip)
+ return false;
+
+ if (paintInfo.phase == PaintPhaseOutline)
+ paintInfo.phase = PaintPhaseChildOutlines;
+ else if (paintInfo.phase == PaintPhaseChildBlockBackground) {
+ paintInfo.phase = PaintPhaseBlockBackground;
+ paintObject(paintInfo, tx, ty);
+ paintInfo.phase = PaintPhaseChildBlockBackgrounds;
+ }
+ IntRect clipRect(isControlClip ? controlClipRect(tx, ty) : overflowClipRect(tx, ty));
+ paintInfo.context->save();
+ if (style()->hasBorderRadius()) {
+ IntSize topLeft, topRight, bottomLeft, bottomRight;
+ IntRect borderRect = IntRect(tx, ty, width(), height());
+ style()->getBorderRadiiForRect(borderRect, topLeft, topRight, bottomLeft, bottomRight);
+
+ paintInfo.context->addRoundedRectClip(borderRect, topLeft, topRight, bottomLeft, bottomRight);
+ }
+
+ paintInfo.context->clip(clipRect);
+ return true;
+}
+
+void RenderBox::popContentsClip(PaintInfo& paintInfo, PaintPhase originalPhase, int tx, int ty)
+{
+ ASSERT(hasControlClip() || (hasOverflowClip() && !layer()->isSelfPaintingLayer()));
+
+ paintInfo.context->restore();
+ if (originalPhase == PaintPhaseOutline) {
+ paintInfo.phase = PaintPhaseSelfOutline;
+ paintObject(paintInfo, tx, ty);
+ paintInfo.phase = originalPhase;
+ } else if (originalPhase == PaintPhaseChildBlockBackground)
+ paintInfo.phase = originalPhase;
+}
+
+IntRect RenderBox::overflowClipRect(int tx, int ty)
{
// FIXME: When overflow-clip (CSS3) is implemented, we'll obtain the property
// here.
@@ -906,103 +855,68 @@ IntRect RenderBox::getOverflowClipRect(int tx, int ty)
int clipX = tx + bLeft;
int clipY = ty + bTop;
- int clipWidth = m_width - bLeft - borderRight();
- int clipHeight = m_height - bTop - borderBottom() + borderTopExtra() + borderBottomExtra();
+ int clipWidth = width() - bLeft - borderRight();
+ int clipHeight = height() - bTop - borderBottom();
// Subtract out scrollbars if we have them.
- if (m_layer) {
- clipWidth -= m_layer->verticalScrollbarWidth();
- clipHeight -= m_layer->horizontalScrollbarHeight();
+ if (layer()) {
+ clipWidth -= layer()->verticalScrollbarWidth();
+ clipHeight -= layer()->horizontalScrollbarHeight();
}
return IntRect(clipX, clipY, clipWidth, clipHeight);
}
-IntRect RenderBox::getClipRect(int tx, int ty)
+IntRect RenderBox::clipRect(int tx, int ty)
{
int clipX = tx;
int clipY = ty;
- int clipWidth = m_width;
- int clipHeight = m_height;
+ int clipWidth = width();
+ int clipHeight = height();
if (!style()->clipLeft().isAuto()) {
- int c = style()->clipLeft().calcValue(m_width);
+ int c = style()->clipLeft().calcValue(width());
clipX += c;
clipWidth -= c;
}
if (!style()->clipRight().isAuto())
- clipWidth -= m_width - style()->clipRight().calcValue(m_width);
+ clipWidth -= width() - style()->clipRight().calcValue(width());
if (!style()->clipTop().isAuto()) {
- int c = style()->clipTop().calcValue(m_height);
+ int c = style()->clipTop().calcValue(height());
clipY += c;
clipHeight -= c;
}
if (!style()->clipBottom().isAuto())
- clipHeight -= m_height - style()->clipBottom().calcValue(m_height);
+ clipHeight -= height() - style()->clipBottom().calcValue(height());
return IntRect(clipX, clipY, clipWidth, clipHeight);
}
-int RenderBox::containingBlockWidth() const
+int RenderBox::containingBlockWidthForContent() const
{
RenderBlock* cb = containingBlock();
- if (!cb)
- return 0;
if (shrinkToAvoidFloats())
- return cb->lineWidth(m_y);
+ return cb->lineWidth(y(), false);
return cb->availableWidth();
}
-IntSize RenderBox::offsetForPositionedInContainer(RenderObject* container) const
+void RenderBox::mapLocalToContainer(RenderBoxModelObject* repaintContainer, bool fixed, bool useTransforms, TransformState& transformState) const
{
- if (!container->isRelPositioned() || !container->isInlineFlow())
- return IntSize();
-
- // When we have an enclosing relpositioned inline, we need to add in the offset of the first line
- // box from the rest of the content, but only in the cases where we know we're positioned
- // relative to the inline itself.
-
- IntSize offset;
- RenderFlow* flow = static_cast<RenderFlow*>(container);
- int sx;
- int sy;
- if (flow->firstLineBox()) {
- sx = flow->firstLineBox()->xPos();
- sy = flow->firstLineBox()->yPos();
- } else {
- sx = flow->staticX();
- sy = flow->staticY();
- }
-
- if (!hasStaticX())
- offset.setWidth(sx);
- // This is not terribly intuitive, but we have to match other browsers. Despite being a block display type inside
- // an inline, we still keep our x locked to the left of the relative positioned inline. Arguably the correct
- // behavior would be to go flush left to the block that contains the inline, but that isn't what other browsers
- // do.
- else if (!style()->isOriginalDisplayInlineType())
- // Avoid adding in the left border/padding of the containing block twice. Subtract it out.
- offset.setWidth(sx - (containingBlock()->borderLeft() + containingBlock()->paddingLeft()));
-
- if (!hasStaticY())
- offset.setHeight(sy);
-
- return offset;
-}
+ if (repaintContainer == this)
+ return;
-FloatPoint RenderBox::localToAbsolute(FloatPoint localPoint, bool fixed, bool useTransforms) const
-{
if (RenderView* v = view()) {
- if (LayoutState* layoutState = v->layoutState()) {
+ if (v->layoutStateEnabled() && !repaintContainer) {
+ LayoutState* layoutState = v->layoutState();
IntSize offset = layoutState->m_offset;
- offset.expand(m_x, m_y);
- localPoint += offset;
- if (style()->position() == RelativePosition && m_layer)
- localPoint += m_layer->relativePositionOffset();
- return localPoint;
+ offset.expand(x(), y());
+ if (style()->position() == RelativePosition && layer())
+ offset += layer()->relativePositionOffset();
+ transformState.move(offset);
+ return;
}
}
@@ -1010,73 +924,53 @@ FloatPoint RenderBox::localToAbsolute(FloatPoint localPoint, bool fixed, bool us
fixed = true;
RenderObject* o = container();
- if (o) {
- if (useTransforms && m_layer && m_layer->transform()) {
- fixed = false; // Elements with transforms act as a containing block for fixed position descendants
- localPoint = m_layer->transform()->mapPoint(localPoint);
- }
+ if (!o)
+ return;
- localPoint += offsetFromContainer(o);
+ bool hasTransform = hasLayer() && layer()->transform();
+ if (hasTransform)
+ fixed = false; // Elements with transforms act as a containing block for fixed position descendants
- return o->localToAbsoluteForContent(localPoint, fixed, useTransforms);
- }
-
- return FloatPoint();
+ IntSize containerOffset = offsetFromContainer(o);
+
+ bool preserve3D = useTransforms && (o->style()->preserves3D() || style()->preserves3D());
+ if (useTransforms && shouldUseTransformFromContainer(o)) {
+ TransformationMatrix t;
+ getTransformFromContainer(o, containerOffset, t);
+ transformState.applyTransform(t, preserve3D ? TransformState::AccumulateTransform : TransformState::FlattenTransform);
+ } else
+ transformState.move(containerOffset.width(), containerOffset.height(), preserve3D ? TransformState::AccumulateTransform : TransformState::FlattenTransform);
+
+ o->mapLocalToContainer(repaintContainer, fixed, useTransforms, transformState);
}
-FloatPoint RenderBox::absoluteToLocal(FloatPoint containerPoint, bool fixed, bool useTransforms) const
+void RenderBox::mapAbsoluteToLocalPoint(bool fixed, bool useTransforms, TransformState& transformState) const
{
// We don't expect absoluteToLocal() to be called during layout (yet)
- ASSERT(!view() || !view()->layoutState());
+ ASSERT(!view() || !view()->layoutStateEnabled());
if (style()->position() == FixedPosition)
fixed = true;
- if (useTransforms && m_layer && m_layer->transform())
- fixed = false;
-
- RenderObject* o = container();
- if (o) {
- FloatPoint localPoint = o->absoluteToLocal(containerPoint, fixed, useTransforms);
-
- // Take into account space above a vertically aligned table cell
- // (see localToAbsoluteForContent())
- localPoint.move(0.0f, -static_cast<float>(borderTopExtra()));
-
- localPoint -= offsetFromContainer(o);
-
- if (useTransforms && m_layer && m_layer->transform())
- localPoint = m_layer->transform()->inverse().mapPoint(localPoint);
-
- return localPoint;
- }
+ bool hasTransform = hasLayer() && layer()->transform();
+ if (hasTransform)
+ fixed = false; // Elements with transforms act as a containing block for fixed position descendants
- return FloatPoint();
-}
-
-FloatQuad RenderBox::localToAbsoluteQuad(const FloatQuad& localQuad, bool fixed) const
-{
- if (style()->position() == FixedPosition)
- fixed = true;
-
RenderObject* o = container();
- if (o) {
- FloatQuad quad = localQuad;
- if (m_layer && m_layer->transform()) {
- fixed = false; // Elements with transforms act as a containing block for fixed position descendants
- quad = m_layer->transform()->mapQuad(quad);
- }
+ if (!o)
+ return;
- quad += offsetFromContainer(o);
+ o->mapAbsoluteToLocalPoint(fixed, useTransforms, transformState);
- // Take into account space above a vertically aligned table cell
- // (see localToAbsoluteForContent())
- quad.move(0.0f, static_cast<float>(o->borderTopExtra()));
+ IntSize containerOffset = offsetFromContainer(o);
- return o->localToAbsoluteQuad(quad, fixed);
- }
-
- return FloatQuad();
+ bool preserve3D = useTransforms && (o->style()->preserves3D() || style()->preserves3D());
+ if (useTransforms && shouldUseTransformFromContainer(o)) {
+ TransformationMatrix t;
+ getTransformFromContainer(o, containerOffset, t);
+ transformState.applyTransform(t, preserve3D ? TransformState::AccumulateTransform : TransformState::FlattenTransform);
+ } else
+ transformState.move(-containerOffset.width(), -containerOffset.height(), preserve3D ? TransformState::AccumulateTransform : TransformState::FlattenTransform);
}
IntSize RenderBox::offsetFromContainer(RenderObject* o) const
@@ -1090,24 +984,29 @@ IntSize RenderBox::offsetFromContainer(RenderObject* o) const
if (!isInline() || isReplaced()) {
RenderBlock* cb;
if (o->isBlockFlow() && style()->position() != AbsolutePosition && style()->position() != FixedPosition
- && (cb = static_cast<RenderBlock*>(o))->hasColumns()) {
- IntRect rect(m_x, m_y, 1, 1);
+ && (cb = toRenderBlock(o))->hasColumns()) {
+ IntRect rect(x(), y(), 1, 1);
cb->adjustRectForColumns(rect);
offset.expand(rect.x(), rect.y());
} else
- offset.expand(m_x, m_y);
+ offset.expand(x(), y());
}
if (o->hasOverflowClip())
- offset -= o->layer()->scrolledContentOffset();
+ offset -= toRenderBox(o)->layer()->scrolledContentOffset();
- if (style()->position() == AbsolutePosition)
- offset += offsetForPositionedInContainer(o);
+ if (style()->position() == AbsolutePosition && o->isRelPositioned() && o->isRenderInline())
+ offset += toRenderInline(o)->relativePositionedInlineOffset(this);
return offset;
}
-void RenderBox::dirtyLineBoxes(bool fullLayout, bool /*isRootLineBox*/)
+InlineBox* RenderBox::createInlineBox()
+{
+ return new (renderArena()) InlineBox(this);
+}
+
+void RenderBox::dirtyLineBoxes(bool fullLayout)
{
if (m_inlineBoxWrapper) {
if (fullLayout) {
@@ -1118,23 +1017,23 @@ void RenderBox::dirtyLineBoxes(bool fullLayout, bool /*isRootLineBox*/)
}
}
-void RenderBox::position(InlineBox* box)
+void RenderBox::positionLineBox(InlineBox* box)
{
if (isPositioned()) {
// Cache the x position only if we were an INLINE type originally.
bool wasInline = style()->isOriginalDisplayInlineType();
- if (wasInline && hasStaticX()) {
+ if (wasInline && style()->hasStaticX()) {
// The value is cached in the xPos of the box. We only need this value if
// our object was inline originally, since otherwise it would have ended up underneath
// the inlines.
- setStaticX(box->xPos());
+ layer()->setStaticX(box->x());
setChildNeedsLayout(true, false); // Just go ahead and mark the positioned object as needing layout, so it will update its position properly.
- } else if (!wasInline && hasStaticY()) {
+ } else if (!wasInline && style()->hasStaticY()) {
// Our object was a block originally, so we make our normal flow position be
// just below the line box (as though all the inlines that came before us got
// wrapped in an anonymous block, which is what would have happened had we been
- // in flow). This value was cached in the yPos() of the box.
- setStaticY(box->yPos());
+ // in flow). This value was cached in the y() of the box.
+ layer()->setStaticY(box->y());
setChildNeedsLayout(true, false); // Just go ahead and mark the positioned object as needing layout, so it will update its position properly.
}
@@ -1142,8 +1041,7 @@ void RenderBox::position(InlineBox* box)
box->remove();
box->destroy(renderArena());
} else if (isReplaced()) {
- m_x = box->xPos();
- m_y = box->yPos();
+ setLocation(box->x(), box->y());
m_inlineBoxWrapper = box;
}
}
@@ -1158,7 +1056,7 @@ void RenderBox::deleteLineBoxWrapper()
}
}
-IntRect RenderBox::absoluteClippedOverflowRect()
+IntRect RenderBox::clippedOverflowRectForRepaint(RenderBoxModelObject* repaintContainer)
{
if (style()->visibility() != VISIBLE && !enclosingLayer()->hasVisibleContent())
return IntRect();
@@ -1166,9 +1064,12 @@ IntRect RenderBox::absoluteClippedOverflowRect()
IntRect r = overflowRect(false);
RenderView* v = view();
- if (v)
+ if (v) {
+ // FIXME: layoutDelta needs to be applied in parts before/after transforms and
+ // repaint containers. https://bugs.webkit.org/show_bug.cgi?id=23308
r.move(v->layoutDelta());
-
+ }
+
if (style()) {
if (style()->hasAppearance())
// The theme may wish to inflate the rect used when repainting.
@@ -1181,18 +1082,24 @@ IntRect RenderBox::absoluteClippedOverflowRect()
r.inflate(v->maximalOutlineSize());
}
}
- computeAbsoluteRepaintRect(r);
+ computeRectForRepaint(repaintContainer, r);
return r;
}
-void RenderBox::computeAbsoluteRepaintRect(IntRect& rect, bool fixed)
+void RenderBox::computeRectForRepaint(RenderBoxModelObject* repaintContainer, IntRect& rect, bool fixed)
{
if (RenderView* v = view()) {
- if (LayoutState* layoutState = v->layoutState()) {
- if (style()->position() == RelativePosition && m_layer)
- rect.move(m_layer->relativePositionOffset());
+ // LayoutState is only valid for root-relative repainting
+ if (v->layoutStateEnabled() && !repaintContainer) {
+ LayoutState* layoutState = v->layoutState();
+
+ if (layer() && layer()->transform())
+ rect = layer()->transform()->mapRect(rect);
- rect.move(m_x, m_y);
+ if (style()->position() == RelativePosition && layer())
+ rect.move(layer()->relativePositionOffset());
+
+ rect.move(x(), y());
rect.move(layoutState->m_offset);
if (layoutState->m_clipped)
rect.intersect(layoutState->m_clipRect);
@@ -1203,18 +1110,21 @@ void RenderBox::computeAbsoluteRepaintRect(IntRect& rect, bool fixed)
if (hasReflection())
rect.unite(reflectedRect(rect));
+ if (repaintContainer == this)
+ return;
+
RenderObject* o = container();
if (!o)
return;
IntPoint topLeft = rect.location();
- topLeft.move(m_x, m_y);
+ topLeft.move(x(), y());
if (style()->position() == FixedPosition)
fixed = true;
if (o->isBlockFlow() && style()->position() != AbsolutePosition && style()->position() != FixedPosition) {
- RenderBlock* cb = static_cast<RenderBlock*>(o);
+ RenderBlock* cb = toRenderBlock(o);
if (cb->hasColumns()) {
IntRect repaintRect(topLeft, rect.size());
cb->adjustRectForColumns(repaintRect);
@@ -1225,92 +1135,63 @@ void RenderBox::computeAbsoluteRepaintRect(IntRect& rect, bool fixed)
// We are now in our parent container's coordinate space. Apply our transform to obtain a bounding box
// in the parent's coordinate space that encloses us.
- if (m_layer && m_layer->transform()) {
+ if (layer() && layer()->transform()) {
fixed = false;
- rect = m_layer->transform()->mapRect(rect);
+ rect = layer()->transform()->mapRect(rect);
// FIXME: this clobbers topLeft adjustment done for multicol above
topLeft = rect.location();
- topLeft.move(m_x, m_y);
+ topLeft.move(x(), y());
}
- if (style()->position() == AbsolutePosition)
- topLeft += offsetForPositionedInContainer(o);
- else if (style()->position() == RelativePosition && m_layer) {
+ if (style()->position() == AbsolutePosition && o->isRelPositioned() && o->isRenderInline())
+ topLeft += toRenderInline(o)->relativePositionedInlineOffset(this);
+ else if (style()->position() == RelativePosition && layer()) {
// Apply the relative position offset when invalidating a rectangle. The layer
// is translated, but the render box isn't, so we need to do this to get the
// right dirty rect. Since this is called from RenderObject::setStyle, the relative position
// flag on the RenderObject has been cleared, so use the one on the style().
- topLeft += m_layer->relativePositionOffset();
+ topLeft += layer()->relativePositionOffset();
}
// FIXME: We ignore the lightweight clipping rect that controls use, since if |o| is in mid-layout,
// its controlClipRect will be wrong. For overflow clip we use the values cached by the layer.
if (o->hasOverflowClip()) {
+ RenderBox* containerBox = toRenderBox(o);
+
// o->height() is inaccurate if we're in the middle of a layout of |o|, so use the
// layer's size instead. Even if the layer's size is wrong, the layer itself will repaint
// anyway if its size does change.
- topLeft -= o->layer()->scrolledContentOffset(); // For overflow:auto/scroll/hidden.
+ topLeft -= containerBox->layer()->scrolledContentOffset(); // For overflow:auto/scroll/hidden.
IntRect repaintRect(topLeft, rect.size());
- IntRect boxRect(0, 0, o->layer()->width(), o->layer()->height());
+ IntRect boxRect(0, 0, containerBox->layer()->width(), containerBox->layer()->height());
rect = intersection(repaintRect, boxRect);
if (rect.isEmpty())
return;
} else
rect.setLocation(topLeft);
- o->computeAbsoluteRepaintRect(rect, fixed);
+ o->computeRectForRepaint(repaintContainer, rect, fixed);
}
void RenderBox::repaintDuringLayoutIfMoved(const IntRect& rect)
{
- int newX = m_x;
- int newY = m_y;
- int newWidth = m_width;
- int newHeight = m_height;
+ int newX = x();
+ int newY = y();
+ int newWidth = width();
+ int newHeight = height();
if (rect.x() != newX || rect.y() != newY) {
// The child moved. Invalidate the object's old and new positions. We have to do this
// since the object may not have gotten a layout.
- m_x = rect.x();
- m_y = rect.y();
- m_width = rect.width();
- m_height = rect.height();
+ m_frameRect = rect;
repaint();
repaintOverhangingFloats(true);
-
- m_x = newX;
- m_y = newY;
- m_width = newWidth;
- m_height = newHeight;
+ m_frameRect = IntRect(newX, newY, newWidth, newHeight);
repaint();
repaintOverhangingFloats(true);
}
}
-int RenderBox::relativePositionOffsetX() const
-{
- if (!style()->left().isAuto()) {
- if (!style()->right().isAuto() && containingBlock()->style()->direction() == RTL)
- return -style()->right().calcValue(containingBlockWidth());
- return style()->left().calcValue(containingBlockWidth());
- }
- if (!style()->right().isAuto())
- return -style()->right().calcValue(containingBlockWidth());
- return 0;
-}
-
-int RenderBox::relativePositionOffsetY() const
-{
- if (!style()->top().isAuto()) {
- if (!style()->top().isPercent() || containingBlock()->style()->height().isFixed())
- return style()->top().calcValue(containingBlockHeight());
- } else if (!style()->bottom().isAuto()) {
- if (!style()->bottom().isPercent() || containingBlock()->style()->height().isFixed())
- return -style()->bottom().calcValue(containingBlockHeight());
- }
- return 0;
-}
-
void RenderBox::calcWidth()
{
if (isPositioned()) {
@@ -1326,7 +1207,7 @@ void RenderBox::calcWidth()
// width. Use the width from the style context.
if (hasOverrideSize() && parent()->style()->boxOrient() == HORIZONTAL
&& parent()->isFlexibleBox() && parent()->isFlexingChildren()) {
- m_width = overrideSize();
+ setWidth(overrideSize());
return;
}
@@ -1334,10 +1215,10 @@ void RenderBox::calcWidth()
bool stretching = (parent()->style()->boxAlign() == BSTRETCH);
bool treatAsReplaced = shouldCalculateSizeAsReplaced() && (!inVerticalBox || !stretching);
- Length width = (treatAsReplaced) ? Length(calcReplacedWidth(), Fixed) : style()->width();
+ Length w = (treatAsReplaced) ? Length(calcReplacedWidth(), Fixed) : style()->width();
RenderBlock* cb = containingBlock();
- int containerWidth = max(0, containingBlockWidth());
+ int containerWidth = max(0, containingBlockWidthForContent());
Length marginLeft = style()->marginLeft();
Length marginRight = style()->marginRight();
@@ -1347,42 +1228,42 @@ void RenderBox::calcWidth()
m_marginLeft = marginLeft.calcMinValue(containerWidth);
m_marginRight = marginRight.calcMinValue(containerWidth);
if (treatAsReplaced)
- m_width = max(width.value() + borderLeft() + borderRight() + paddingLeft() + paddingRight(), minPrefWidth());
+ setWidth(max(w.value() + borderLeft() + borderRight() + paddingLeft() + paddingRight(), minPrefWidth()));
return;
}
// Width calculations
if (treatAsReplaced)
- m_width = width.value() + borderLeft() + borderRight() + paddingLeft() + paddingRight();
+ setWidth(w.value() + borderLeft() + borderRight() + paddingLeft() + paddingRight());
else {
// Calculate Width
- m_width = calcWidthUsing(Width, containerWidth);
+ setWidth(calcWidthUsing(Width, containerWidth));
// Calculate MaxWidth
if (!style()->maxWidth().isUndefined()) {
int maxW = calcWidthUsing(MaxWidth, containerWidth);
- if (m_width > maxW) {
- m_width = maxW;
- width = style()->maxWidth();
+ if (width() > maxW) {
+ setWidth(maxW);
+ w = style()->maxWidth();
}
}
// Calculate MinWidth
int minW = calcWidthUsing(MinWidth, containerWidth);
- if (m_width < minW) {
- m_width = minW;
- width = style()->minWidth();
+ if (width() < minW) {
+ setWidth(minW);
+ w = style()->minWidth();
}
}
if (stretchesToMinIntrinsicWidth()) {
- m_width = max(m_width, minPrefWidth());
- width = Length(m_width, Fixed);
+ setWidth(max(width(), minPrefWidth()));
+ w = Length(width(), Fixed);
}
// Margin calculations
- if (width.isAuto()) {
+ if (w.isAuto()) {
m_marginLeft = marginLeft.calcMinValue(containerWidth);
m_marginRight = marginRight.calcMinValue(containerWidth);
} else {
@@ -1391,18 +1272,18 @@ void RenderBox::calcWidth()
calcHorizontalMargins(marginLeft, marginRight, containerWidth);
}
- if (containerWidth && containerWidth != (m_width + m_marginLeft + m_marginRight)
+ if (containerWidth && containerWidth != (width() + m_marginLeft + m_marginRight)
&& !isFloating() && !isInline() && !cb->isFlexibleBox()) {
if (cb->style()->direction() == LTR)
- m_marginRight = containerWidth - m_width - m_marginLeft;
+ m_marginRight = containerWidth - width() - m_marginLeft;
else
- m_marginLeft = containerWidth - m_width - m_marginRight;
+ m_marginLeft = containerWidth - width() - m_marginRight;
}
}
int RenderBox::calcWidthUsing(WidthType widthType, int cw)
{
- int width = m_width;
+ int widthResult = width();
Length w;
if (widthType == Width)
w = style()->width();
@@ -1415,24 +1296,23 @@ int RenderBox::calcWidthUsing(WidthType widthType, int cw)
int marginLeft = style()->marginLeft().calcMinValue(cw);
int marginRight = style()->marginRight().calcMinValue(cw);
if (cw)
- width = cw - marginLeft - marginRight;
+ widthResult = cw - marginLeft - marginRight;
if (sizesToIntrinsicWidth(widthType)) {
- width = max(width, minPrefWidth());
- width = min(width, maxPrefWidth());
+ widthResult = max(widthResult, minPrefWidth());
+ widthResult = min(widthResult, maxPrefWidth());
}
} else
- width = calcBorderBoxWidth(w.calcValue(cw));
+ widthResult = calcBorderBoxWidth(w.calcValue(cw));
- return width;
+ return widthResult;
}
bool RenderBox::sizesToIntrinsicWidth(WidthType widthType) const
{
// Marquees in WinIE are like a mixture of blocks and inline-blocks. They size as though they're blocks,
// but they allow text to sit on the same line as the marquee.
- if (isFloating() || (isCompact() && isInline())
- || (isInlineBlockOrInlineTable() && !isHTMLMarquee()))
+ if (isFloating() || (isInlineBlockOrInlineTable() && !isHTMLMarquee()))
return true;
// This code may look a bit strange. Basically width:intrinsic should clamp the size when testing both
@@ -1467,20 +1347,20 @@ void RenderBox::calcHorizontalMargins(const Length& marginLeft, const Length& ma
return;
}
- if ((marginLeft.isAuto() && marginRight.isAuto() && m_width < containerWidth)
+ if ((marginLeft.isAuto() && marginRight.isAuto() && width() < containerWidth)
|| (!marginLeft.isAuto() && !marginRight.isAuto() && containingBlock()->style()->textAlign() == WEBKIT_CENTER)) {
- m_marginLeft = max(0, (containerWidth - m_width) / 2);
- m_marginRight = containerWidth - m_width - m_marginLeft;
- } else if ((marginRight.isAuto() && m_width < containerWidth)
+ m_marginLeft = max(0, (containerWidth - width()) / 2);
+ m_marginRight = containerWidth - width() - m_marginLeft;
+ } else if ((marginRight.isAuto() && width() < containerWidth)
|| (!marginLeft.isAuto() && containingBlock()->style()->direction() == RTL && containingBlock()->style()->textAlign() == WEBKIT_LEFT)) {
m_marginLeft = marginLeft.calcValue(containerWidth);
- m_marginRight = containerWidth - m_width - m_marginLeft;
- } else if ((marginLeft.isAuto() && m_width < containerWidth)
+ m_marginRight = containerWidth - width() - m_marginLeft;
+ } else if ((marginLeft.isAuto() && width() < containerWidth)
|| (!marginRight.isAuto() && containingBlock()->style()->direction() == LTR && containingBlock()->style()->textAlign() == WEBKIT_RIGHT)) {
m_marginRight = marginRight.calcValue(containerWidth);
- m_marginLeft = containerWidth - m_width - m_marginRight;
+ m_marginLeft = containerWidth - width() - m_marginRight;
} else {
- // This makes auto margins 0 if we failed a m_width < containerWidth test above (css2.1, 10.3.3).
+ // This makes auto margins 0 if we failed a width() < containerWidth test above (css2.1, 10.3.3).
m_marginLeft = marginLeft.calcMinValue(containerWidth);
m_marginRight = marginRight.calcMinValue(containerWidth);
}
@@ -1492,6 +1372,7 @@ void RenderBox::calcHeight()
if (isTableCell() || (isInline() && !isReplaced()))
return;
+ Length h;
if (isPositioned())
calcAbsoluteVertical();
else {
@@ -1501,7 +1382,6 @@ void RenderBox::calcHeight()
if (isTable())
return;
- Length h;
bool inHorizontalBox = parent()->isFlexibleBox() && parent()->style()->boxOrient() == HORIZONTAL;
bool stretching = parent()->style()->boxAlign() == BSTRETCH;
bool treatAsReplaced = shouldCalculateSizeAsReplaced() && (!inHorizontalBox || !stretching);
@@ -1522,44 +1402,49 @@ void RenderBox::calcHeight()
// Block children of horizontal flexible boxes fill the height of the box.
if (h.isAuto() && parent()->isFlexibleBox() && parent()->style()->boxOrient() == HORIZONTAL
&& parent()->isStretchingChildren()) {
- h = Length(parent()->contentHeight() - marginTop() - marginBottom() -
+ h = Length(parentBox()->contentHeight() - marginTop() - marginBottom() -
borderTop() - paddingTop() - borderBottom() - paddingBottom(), Fixed);
checkMinMaxHeight = false;
}
- int height;
+ int heightResult;
if (checkMinMaxHeight) {
- height = calcHeightUsing(style()->height());
- if (height == -1)
- height = m_height;
+ heightResult = calcHeightUsing(style()->height());
+ if (heightResult == -1)
+ heightResult = height();
int minH = calcHeightUsing(style()->minHeight()); // Leave as -1 if unset.
- int maxH = style()->maxHeight().isUndefined() ? height : calcHeightUsing(style()->maxHeight());
+ int maxH = style()->maxHeight().isUndefined() ? heightResult : calcHeightUsing(style()->maxHeight());
if (maxH == -1)
- maxH = height;
- height = min(maxH, height);
- height = max(minH, height);
- } else
+ maxH = heightResult;
+ heightResult = min(maxH, heightResult);
+ heightResult = max(minH, heightResult);
+ } else {
// The only times we don't check min/max height are when a fixed length has
// been given as an override. Just use that. The value has already been adjusted
// for box-sizing.
- height = h.value() + borderTop() + borderBottom() + paddingTop() + paddingBottom();
+ heightResult = h.value() + borderTop() + borderBottom() + paddingTop() + paddingBottom();
+ }
- m_height = height;
+ setHeight(heightResult);
}
// WinIE quirk: The <html> block always fills the entire canvas in quirks mode. The <body> always fills the
// <html> block in quirks mode. Only apply this quirk if the block is normal flow and no height
- // is specified.
- if (stretchesToViewHeight() && !document()->printing()) {
+ // is specified. When we're printing, we also need this quirk if the body or root has a percentage
+ // height since we don't set a height in RenderView when we're printing. So without this quirk, the
+ // height has nothing to be a percentage of, and it ends up being 0. That is bad.
+ bool printingNeedsBaseHeight = document()->printing() && h.isPercent()
+ && (isRoot() || isBody() && document()->documentElement()->renderer()->style()->height().isPercent());
+ if (stretchesToViewHeight() || printingNeedsBaseHeight) {
int margins = collapsedMarginTop() + collapsedMarginBottom();
- int visHeight = view()->viewHeight();
+ int visHeight = document()->printing() ? view()->frameView()->visibleHeight() : view()->viewHeight();
if (isRoot())
- m_height = max(m_height, visHeight - margins);
+ setHeight(max(height(), visHeight - margins));
else {
- int marginsBordersPadding = margins + parent()->marginTop() + parent()->marginBottom()
- + parent()->borderTop() + parent()->borderBottom()
- + parent()->paddingTop() + parent()->paddingBottom();
- m_height = max(m_height, visHeight - marginsBordersPadding);
+ int marginsBordersPadding = margins + parentBox()->marginTop() + parentBox()->marginBottom()
+ + parentBox()->borderTop() + parentBox()->borderBottom()
+ + parentBox()->paddingTop() + parentBox()->paddingBottom();
+ setHeight(max(height(), visHeight - marginsBordersPadding));
}
}
}
@@ -1630,7 +1515,7 @@ int RenderBox::calcPercentageHeight(const Length& height)
if (result != -1)
result = cb->calcContentBoxHeight(result);
} else if (cb->isRenderView() || (cb->isBody() && style()->htmlHacks()) || isPositionedWithSpecifiedHeight) {
- // Don't allow this to affect the block' m_height member variable, since this
+ // Don't allow this to affect the block' height() member variable, since this
// can get called while the block is still laying out its kids.
int oldHeight = cb->height();
cb->calcHeight();
@@ -1669,7 +1554,7 @@ int RenderBox::calcReplacedWidthUsing(Length width) const
case Fixed:
return calcContentBoxWidth(width.value());
case Percent: {
- const int cw = isPositioned() ? containingBlockWidthForPositioned(container()) : containingBlockWidth();
+ const int cw = isPositioned() ? containingBlockWidthForPositioned(toRenderBoxModelObject(container())) : containingBlockWidthForContent();
if (cw > 0)
return calcContentBoxWidth(width.calcMinValue(cw));
}
@@ -1698,12 +1583,12 @@ int RenderBox::calcReplacedHeightUsing(Length height) const
RenderObject* cb = isPositioned() ? container() : containingBlock();
while (cb->isAnonymous()) {
cb = cb->containingBlock();
- static_cast<RenderBlock*>(cb)->addPercentHeightDescendant(const_cast<RenderBox*>(this));
+ toRenderBlock(cb)->addPercentHeightDescendant(const_cast<RenderBox*>(this));
}
if (cb->isPositioned() && cb->style()->height().isAuto() && !(cb->style()->top().isAuto() || cb->style()->bottom().isAuto())) {
ASSERT(cb->isRenderBlock());
- RenderBlock* block = static_cast<RenderBlock*>(cb);
+ RenderBlock* block = toRenderBlock(cb);
int oldHeight = block->height();
block->calcHeight();
int newHeight = block->calcContentBoxHeight(block->contentHeight());
@@ -1711,7 +1596,7 @@ int RenderBox::calcReplacedHeightUsing(Length height) const
return calcContentBoxHeight(height.calcValue(newHeight));
}
- int availableHeight = isPositioned() ? containingBlockHeightForPositioned(cb) : cb->availableHeight();
+ int availableHeight = isPositioned() ? containingBlockHeightForPositioned(toRenderBoxModelObject(cb)) : toRenderBox(cb)->availableHeight();
// It is necessary to use the border-box to match WinIE's broken
// box model. This is essential for sizing inside
@@ -1742,7 +1627,7 @@ int RenderBox::availableHeightUsing(const Length& h) const
return calcContentBoxHeight(h.value());
if (isRenderView())
- return static_cast<const RenderView*>(this)->frameView()->visibleHeight();
+ return toRenderView(this)->frameView()->visibleHeight();
// We need to stop here, since we don't want to increase the height of the table
// artificially. We're going to rely on this cell getting expanded to some new
@@ -1754,7 +1639,7 @@ int RenderBox::availableHeightUsing(const Length& h) const
return calcContentBoxHeight(h.calcValue(containingBlock()->availableHeight()));
if (isRenderBlock() && isPositioned() && style()->height().isAuto() && !(style()->top().isAuto() || style()->bottom().isAuto())) {
- RenderBlock* block = const_cast<RenderBlock*>(static_cast<const RenderBlock*>(this));
+ RenderBlock* block = const_cast<RenderBlock*>(toRenderBlock(this));
int oldHeight = block->height();
block->calcHeight();
int newHeight = block->calcContentBoxHeight(block->contentHeight());
@@ -1781,65 +1666,46 @@ void RenderBox::calcVerticalMargins()
m_marginBottom = style()->marginBottom().calcMinValue(cw);
}
-int RenderBox::staticX() const
-{
- return m_layer ? m_layer->staticX() : 0;
-}
-
-int RenderBox::staticY() const
-{
- return m_layer ? m_layer->staticY() : 0;
-}
-
-void RenderBox::setStaticX(int staticX)
-{
- ASSERT(isPositioned() || isRelPositioned());
- m_layer->setStaticX(staticX);
-}
-
-void RenderBox::setStaticY(int staticY)
+int RenderBox::containingBlockWidthForPositioned(const RenderBoxModelObject* containingBlock) const
{
- ASSERT(isPositioned() || isRelPositioned());
-
- if (staticY == m_layer->staticY())
- return;
+ if (containingBlock->isBox()) {
+ const RenderBox* containingBlockBox = toRenderBox(containingBlock);
+ return containingBlockBox->width() - containingBlockBox->borderLeft() - containingBlockBox->borderRight() - containingBlockBox->verticalScrollbarWidth();
+ }
- m_layer->setStaticY(staticY);
- setChildNeedsLayout(true, false);
-}
-
-int RenderBox::containingBlockWidthForPositioned(const RenderObject* containingBlock) const
-{
- if (containingBlock->isInlineFlow()) {
- ASSERT(containingBlock->isRelPositioned());
-
- const RenderFlow* flow = static_cast<const RenderFlow*>(containingBlock);
- InlineFlowBox* first = flow->firstLineBox();
- InlineFlowBox* last = flow->lastLineBox();
+ ASSERT(containingBlock->isRenderInline() && containingBlock->isRelPositioned());
- // If the containing block is empty, return a width of 0.
- if (!first || !last)
- return 0;
+ const RenderInline* flow = toRenderInline(containingBlock);
+ InlineFlowBox* first = flow->firstLineBox();
+ InlineFlowBox* last = flow->lastLineBox();
- int fromLeft;
- int fromRight;
- if (containingBlock->style()->direction() == LTR) {
- fromLeft = first->xPos() + first->borderLeft();
- fromRight = last->xPos() + last->width() - last->borderRight();
- } else {
- fromRight = first->xPos() + first->width() - first->borderRight();
- fromLeft = last->xPos() + last->borderLeft();
- }
+ // If the containing block is empty, return a width of 0.
+ if (!first || !last)
+ return 0;
- return max(0, (fromRight - fromLeft));
+ int fromLeft;
+ int fromRight;
+ if (containingBlock->style()->direction() == LTR) {
+ fromLeft = first->x() + first->borderLeft();
+ fromRight = last->x() + last->width() - last->borderRight();
+ } else {
+ fromRight = first->x() + first->width() - first->borderRight();
+ fromLeft = last->x() + last->borderLeft();
}
- return containingBlock->width() - containingBlock->borderLeft() - containingBlock->borderRight() - containingBlock->verticalScrollbarWidth();
+ return max(0, (fromRight - fromLeft));
}
-int RenderBox::containingBlockHeightForPositioned(const RenderObject* containingBlock) const
-{
- return containingBlock->height() - containingBlock->borderTop() - containingBlock->borderBottom();
+int RenderBox::containingBlockHeightForPositioned(const RenderBoxModelObject* containingBlock) const
+{
+ int heightResult = 0;
+ if (containingBlock->isBox())
+ heightResult = toRenderBox(containingBlock)->height();
+ else if (containingBlock->isRenderInline()) {
+ ASSERT(containingBlock->isRelPositioned());
+ heightResult = toRenderInline(containingBlock)->linesBoundingBox().height();
+ }
+ return heightResult - containingBlock->borderTop() - containingBlock->borderBottom();
}
void RenderBox::calcAbsoluteHorizontal()
@@ -1864,7 +1730,7 @@ void RenderBox::calcAbsoluteHorizontal()
// NOTE: 'static' is not a legal value for 'left' or 'right' as of CSS 2.1.
// FIXME 3: Can perhaps optimize out cases when max-width/min-width are greater
- // than or less than the computed m_width. Be careful of box-sizing and
+ // than or less than the computed width(). Be careful of box-sizing and
// percentage issues.
// The following is based off of the W3C Working Draft from April 11, 2006 of
@@ -1876,8 +1742,8 @@ void RenderBox::calcAbsoluteHorizontal()
// We don't use containingBlock(), since we may be positioned by an enclosing
// relative positioned inline.
- const RenderObject* containerBlock = container();
-
+ const RenderBoxModelObject* containerBlock = toRenderBoxModelObject(container());
+
const int containerWidth = containingBlockWidthForPositioned(containerBlock);
// To match WinIE, in quirks mode use the parent's 'direction' property
@@ -1919,25 +1785,35 @@ void RenderBox::calcAbsoluteHorizontal()
if (left.isAuto() && right.isAuto()) {
if (containerDirection == LTR) {
// 'staticX' should already have been set through layout of the parent.
- int staticPosition = staticX() - containerBlock->borderLeft();
- for (RenderObject* po = parent(); po && po != containerBlock; po = po->parent())
- staticPosition += po->xPos();
+ int staticPosition = layer()->staticX() - containerBlock->borderLeft();
+ for (RenderObject* po = parent(); po && po != containerBlock; po = po->parent()) {
+ if (po->isBox())
+ staticPosition += toRenderBox(po)->x();
+ }
left.setValue(Fixed, staticPosition);
} else {
RenderObject* po = parent();
// 'staticX' should already have been set through layout of the parent.
- int staticPosition = staticX() + containerWidth + containerBlock->borderRight() - po->width();
- for (; po && po != containerBlock; po = po->parent())
- staticPosition -= po->xPos();
+ int staticPosition = layer()->staticX() + containerWidth + containerBlock->borderRight();
+ if (po->isBox())
+ staticPosition -= toRenderBox(po)->width();
+ for (; po && po != containerBlock; po = po->parent()) {
+ if (po->isBox())
+ staticPosition -= toRenderBox(po)->x();
+ }
right.setValue(Fixed, staticPosition);
}
}
// Calculate constraint equation values for 'width' case.
+ int widthResult;
+ int xResult;
calcAbsoluteHorizontalValues(style()->width(), containerBlock, containerDirection,
containerWidth, bordersPlusPadding,
left, right, marginLeft, marginRight,
- m_width, m_marginLeft, m_marginRight, m_x);
+ widthResult, m_marginLeft, m_marginRight, xResult);
+ setWidth(widthResult);
+ setX(xResult);
// Calculate constraint equation values for 'max-width' case.
if (!style()->maxWidth().isUndefined()) {
@@ -1951,11 +1827,11 @@ void RenderBox::calcAbsoluteHorizontal()
left, right, marginLeft, marginRight,
maxWidth, maxMarginLeft, maxMarginRight, maxXPos);
- if (m_width > maxWidth) {
- m_width = maxWidth;
+ if (width() > maxWidth) {
+ setWidth(maxWidth);
m_marginLeft = maxMarginLeft;
m_marginRight = maxMarginRight;
- m_x = maxXPos;
+ m_frameRect.setX(maxXPos);
}
}
@@ -1971,25 +1847,28 @@ void RenderBox::calcAbsoluteHorizontal()
left, right, marginLeft, marginRight,
minWidth, minMarginLeft, minMarginRight, minXPos);
- if (m_width < minWidth) {
- m_width = minWidth;
+ if (width() < minWidth) {
+ setWidth(minWidth);
m_marginLeft = minMarginLeft;
m_marginRight = minMarginRight;
- m_x = minXPos;
+ m_frameRect.setX(minXPos);
}
}
- if (stretchesToMinIntrinsicWidth() && m_width < minPrefWidth() - bordersPlusPadding)
+ if (stretchesToMinIntrinsicWidth() && width() < minPrefWidth() - bordersPlusPadding) {
calcAbsoluteHorizontalValues(Length(minPrefWidth() - bordersPlusPadding, Fixed), containerBlock, containerDirection,
containerWidth, bordersPlusPadding,
left, right, marginLeft, marginRight,
- m_width, m_marginLeft, m_marginRight, m_x);
+ widthResult, m_marginLeft, m_marginRight, xResult);
+ setWidth(widthResult);
+ setX(xResult);
+ }
- // Put m_width into correct form.
- m_width += bordersPlusPadding;
+ // Put width() into correct form.
+ setWidth(width() + bordersPlusPadding);
}
-void RenderBox::calcAbsoluteHorizontalValues(Length width, const RenderObject* containerBlock, TextDirection containerDirection,
+void RenderBox::calcAbsoluteHorizontalValues(Length width, const RenderBoxModelObject* containerBlock, TextDirection containerDirection,
const int containerWidth, const int bordersPlusPadding,
const Length left, const Length right, const Length marginLeft, const Length marginRight,
int& widthValue, int& marginLeftValue, int& marginRightValue, int& xPos)
@@ -2145,15 +2024,15 @@ void RenderBox::calcAbsoluteHorizontalValues(Length width, const RenderObject* c
// Use computed values to calculate the horizontal position.
// FIXME: This hack is needed to calculate the xPos for a 'rtl' relatively
- // positioned, inline containing block because right now, it is using the xPos
+ // positioned, inline because right now, it is using the xPos
// of the first line box when really it should use the last line box. When
// this is fixed elsewhere, this block should be removed.
- if (containerBlock->isInline() && containerBlock->style()->direction() == RTL) {
- const RenderFlow* flow = static_cast<const RenderFlow*>(containerBlock);
+ if (containerBlock->isRenderInline() && containerBlock->style()->direction() == RTL) {
+ const RenderInline* flow = toRenderInline(containerBlock);
InlineFlowBox* firstLine = flow->firstLineBox();
InlineFlowBox* lastLine = flow->lastLineBox();
if (firstLine && lastLine && firstLine != lastLine) {
- xPos = leftValue + marginLeftValue + lastLine->borderLeft() + (lastLine->xPos() - firstLine->xPos());
+ xPos = leftValue + marginLeftValue + lastLine->borderLeft() + (lastLine->x() - firstLine->x());
return;
}
}
@@ -2176,7 +2055,7 @@ void RenderBox::calcAbsoluteVertical()
// We don't use containingBlock(), since we may be positioned by an enclosing relpositioned inline.
- const RenderObject* containerBlock = container();
+ const RenderBoxModelObject* containerBlock = toRenderBoxModelObject(container());
const int containerHeight = containingBlockHeightForPositioned(containerBlock);
@@ -2207,21 +2086,23 @@ void RenderBox::calcAbsoluteVertical()
// Calculate the static distance if needed.
if (top.isAuto() && bottom.isAuto()) {
// staticY should already have been set through layout of the parent()
- int staticTop = staticY() - containerBlock->borderTop();
+ int staticTop = layer()->staticY() - containerBlock->borderTop();
for (RenderObject* po = parent(); po && po != containerBlock; po = po->parent()) {
- if (!po->isTableRow())
- staticTop += po->yPos();
+ if (po->isBox() && !po->isTableRow())
+ staticTop += toRenderBox(po)->y();
}
top.setValue(Fixed, staticTop);
}
- int height; // Needed to compute overflow.
+ int h; // Needed to compute overflow.
+ int y;
// Calculate constraint equation values for 'height' case.
calcAbsoluteVerticalValues(style()->height(), containerBlock, containerHeight, bordersPlusPadding,
top, bottom, marginTop, marginBottom,
- height, m_marginTop, m_marginBottom, m_y);
+ h, m_marginTop, m_marginBottom, y);
+ setY(y);
// Avoid doing any work in the common case (where the values of min-height and max-height are their defaults).
// see FIXME 3
@@ -2237,11 +2118,11 @@ void RenderBox::calcAbsoluteVertical()
top, bottom, marginTop, marginBottom,
maxHeight, maxMarginTop, maxMarginBottom, maxYPos);
- if (height > maxHeight) {
- height = maxHeight;
+ if (h > maxHeight) {
+ h = maxHeight;
m_marginTop = maxMarginTop;
m_marginBottom = maxMarginBottom;
- m_y = maxYPos;
+ m_frameRect.setY(maxYPos);
}
}
@@ -2256,19 +2137,19 @@ void RenderBox::calcAbsoluteVertical()
top, bottom, marginTop, marginBottom,
minHeight, minMarginTop, minMarginBottom, minYPos);
- if (height < minHeight) {
- height = minHeight;
+ if (h < minHeight) {
+ h = minHeight;
m_marginTop = minMarginTop;
m_marginBottom = minMarginBottom;
- m_y = minYPos;
+ m_frameRect.setY(minYPos);
}
}
// Set final height value.
- m_height = height + bordersPlusPadding;
+ setHeight(h + bordersPlusPadding);
}
-void RenderBox::calcAbsoluteVerticalValues(Length height, const RenderObject* containerBlock,
+void RenderBox::calcAbsoluteVerticalValues(Length h, const RenderBoxModelObject* containerBlock,
const int containerHeight, const int bordersPlusPadding,
const Length top, const Length bottom, const Length marginTop, const Length marginBottom,
int& heightValue, int& marginTopValue, int& marginBottomValue, int& yPos)
@@ -2277,17 +2158,17 @@ void RenderBox::calcAbsoluteVerticalValues(Length height, const RenderObject* co
// converted to the static position in calcAbsoluteVertical()
ASSERT(!(top.isAuto() && bottom.isAuto()));
- int contentHeight = m_height - bordersPlusPadding;
+ int contentHeight = height() - bordersPlusPadding;
int topValue = 0;
- bool heightIsAuto = height.isAuto();
+ bool heightIsAuto = h.isAuto();
bool topIsAuto = top.isAuto();
bool bottomIsAuto = bottom.isAuto();
// Height is never unsolved for tables.
if (isTable()) {
- height.setValue(Fixed, contentHeight);
+ h.setValue(Fixed, contentHeight);
heightIsAuto = false;
}
@@ -2303,7 +2184,7 @@ void RenderBox::calcAbsoluteVerticalValues(Length height, const RenderObject* co
// NOTE: It is not necessary to solve for 'bottom' in the over constrained
// case because the value is not used for any further calculations.
- heightValue = calcContentBoxHeight(height.calcValue(containerHeight));
+ heightValue = calcContentBoxHeight(h.calcValue(containerHeight));
topValue = top.calcValue(containerHeight);
const int availableSpace = containerHeight - (topValue + heightValue + bottom.calcValue(containerHeight) + bordersPlusPadding);
@@ -2370,7 +2251,7 @@ void RenderBox::calcAbsoluteVerticalValues(Length height, const RenderObject* co
heightValue = contentHeight;
} else if (topIsAuto && !heightIsAuto && !bottomIsAuto) {
// RULE 4: (solve of top)
- heightValue = calcContentBoxHeight(height.calcValue(containerHeight));
+ heightValue = calcContentBoxHeight(h.calcValue(containerHeight));
topValue = availableSpace - (heightValue + bottom.calcValue(containerHeight));
} else if (!topIsAuto && heightIsAuto && !bottomIsAuto) {
// RULE 5: (solve of height)
@@ -2378,7 +2259,7 @@ void RenderBox::calcAbsoluteVerticalValues(Length height, const RenderObject* co
heightValue = max(0, availableSpace - (topValue + bottom.calcValue(containerHeight)));
} else if (!topIsAuto && !heightIsAuto && bottomIsAuto) {
// RULE 6: (no need solve of bottom)
- heightValue = calcContentBoxHeight(height.calcValue(containerHeight));
+ heightValue = calcContentBoxHeight(h.calcValue(containerHeight));
topValue = top.calcValue(containerHeight);
}
}
@@ -2397,7 +2278,7 @@ void RenderBox::calcAbsoluteHorizontalReplaced()
// We don't use containingBlock(), since we may be positioned by an enclosing
// relative positioned inline.
- const RenderObject* containerBlock = container();
+ const RenderBoxModelObject* containerBlock = toRenderBoxModelObject(container());
const int containerWidth = containingBlockWidthForPositioned(containerBlock);
@@ -2419,8 +2300,8 @@ void RenderBox::calcAbsoluteHorizontalReplaced()
// NOTE: This value of width is FINAL in that the min/max width calculations
// are dealt with in calcReplacedWidth(). This means that the steps to produce
// correct max/min in the non-replaced version, are not necessary.
- m_width = calcReplacedWidth() + borderLeft() + borderRight() + paddingLeft() + paddingRight();
- const int availableSpace = containerWidth - m_width;
+ setWidth(calcReplacedWidth() + borderLeft() + borderRight() + paddingLeft() + paddingRight());
+ const int availableSpace = containerWidth - width();
/*-----------------------------------------------------------------------*\
* 2. If both 'left' and 'right' have the value 'auto', then if 'direction'
@@ -2432,16 +2313,20 @@ void RenderBox::calcAbsoluteHorizontalReplaced()
// see FIXME 1
if (containerDirection == LTR) {
// 'staticX' should already have been set through layout of the parent.
- int staticPosition = staticX() - containerBlock->borderLeft();
- for (RenderObject* po = parent(); po && po != containerBlock; po = po->parent())
- staticPosition += po->xPos();
+ int staticPosition = layer()->staticX() - containerBlock->borderLeft();
+ for (RenderObject* po = parent(); po && po != containerBlock; po = po->parent()) {
+ if (po->isBox())
+ staticPosition += toRenderBox(po)->x();
+ }
left.setValue(Fixed, staticPosition);
} else {
RenderObject* po = parent();
// 'staticX' should already have been set through layout of the parent.
- int staticPosition = staticX() + containerWidth + containerBlock->borderRight() - po->width();
- for (; po && po != containerBlock; po = po->parent())
- staticPosition -= po->xPos();
+ int staticPosition = layer()->staticX() + containerWidth + containerBlock->borderRight();
+ for ( ; po && po != containerBlock; po = po->parent()) {
+ if (po->isBox())
+ staticPosition += toRenderBox(po)->x();
+ }
right.setValue(Fixed, staticPosition);
}
}
@@ -2538,7 +2423,7 @@ void RenderBox::calcAbsoluteHorizontalReplaced()
\*-----------------------------------------------------------------------*/
// NOTE: It is not necessary to solve for 'right' when the direction is
// LTR because the value is not used.
- int totalWidth = m_width + leftValue + rightValue + m_marginLeft + m_marginRight;
+ int totalWidth = width() + leftValue + rightValue + m_marginLeft + m_marginRight;
if (totalWidth > containerWidth && (containerDirection == RTL))
leftValue = containerWidth - (totalWidth - leftValue);
@@ -2549,16 +2434,16 @@ void RenderBox::calcAbsoluteHorizontalReplaced()
// of the first line box when really it should use the last line box. When
// this is fixed elsewhere, this block should be removed.
if (containerBlock->isInline() && containerBlock->style()->direction() == RTL) {
- const RenderFlow* flow = static_cast<const RenderFlow*>(containerBlock);
+ const RenderInline* flow = toRenderInline(containerBlock);
InlineFlowBox* firstLine = flow->firstLineBox();
InlineFlowBox* lastLine = flow->lastLineBox();
if (firstLine && lastLine && firstLine != lastLine) {
- m_x = leftValue + m_marginLeft + lastLine->borderLeft() + (lastLine->xPos() - firstLine->xPos());
+ m_frameRect.setX(leftValue + m_marginLeft + lastLine->borderLeft() + (lastLine->x() - firstLine->x()));
return;
}
}
- m_x = leftValue + m_marginLeft + containerBlock->borderLeft();
+ m_frameRect.setX(leftValue + m_marginLeft + containerBlock->borderLeft());
}
void RenderBox::calcAbsoluteVerticalReplaced()
@@ -2570,7 +2455,7 @@ void RenderBox::calcAbsoluteVerticalReplaced()
// the numbers correspond to numbers in spec)
// We don't use containingBlock(), since we may be positioned by an enclosing relpositioned inline.
- const RenderObject* containerBlock = container();
+ const RenderBoxModelObject* containerBlock = toRenderBoxModelObject(container());
const int containerHeight = containingBlockHeightForPositioned(containerBlock);
@@ -2588,8 +2473,8 @@ void RenderBox::calcAbsoluteVerticalReplaced()
// NOTE: This value of height is FINAL in that the min/max height calculations
// are dealt with in calcReplacedHeight(). This means that the steps to produce
// correct max/min in the non-replaced version, are not necessary.
- m_height = calcReplacedHeight() + borderTop() + borderBottom() + paddingTop() + paddingBottom();
- const int availableSpace = containerHeight - m_height;
+ setHeight(calcReplacedHeight() + borderTop() + borderBottom() + paddingTop() + paddingBottom());
+ const int availableSpace = containerHeight - height();
/*-----------------------------------------------------------------------*\
* 2. If both 'top' and 'bottom' have the value 'auto', replace 'top'
@@ -2598,10 +2483,10 @@ void RenderBox::calcAbsoluteVerticalReplaced()
// see FIXME 2
if (top.isAuto() && bottom.isAuto()) {
// staticY should already have been set through layout of the parent().
- int staticTop = staticY() - containerBlock->borderTop();
+ int staticTop = layer()->staticY() - containerBlock->borderTop();
for (RenderObject* po = parent(); po && po != containerBlock; po = po->parent()) {
- if (!po->isTableRow())
- staticTop += po->yPos();
+ if (po->isBox() && !po->isTableRow())
+ staticTop += toRenderBox(po)->y();
}
top.setValue(Fixed, staticTop);
}
@@ -2690,7 +2575,7 @@ void RenderBox::calcAbsoluteVerticalReplaced()
// or not.
// Use computed values to calculate the vertical position.
- m_y = topValue + m_marginTop + containerBlock->borderTop();
+ m_frameRect.setY(topValue + m_marginTop + containerBlock->borderTop());
}
IntRect RenderBox::localCaretRect(InlineBox* box, int caretOffset, int* extraWidthToEndOfLine)
@@ -2701,12 +2586,11 @@ IntRect RenderBox::localCaretRect(InlineBox* box, int caretOffset, int* extraWid
// FIXME: Paint the carets inside empty blocks differently than the carets before/after elements.
// FIXME: What about border and padding?
- const int caretWidth = 1;
- IntRect rect(xPos(), yPos(), caretWidth, m_height);
+ IntRect rect(x(), y(), caretWidth, height());
TextDirection direction = box ? box->direction() : style()->direction();
if ((!caretOffset) ^ (direction == LTR))
- rect.move(IntSize(m_width - caretWidth, 0));
+ rect.move(IntSize(width() - caretWidth, 0));
if (box) {
RootInlineBox* rootBox = box->root();
@@ -2724,22 +2608,22 @@ IntRect RenderBox::localCaretRect(InlineBox* box, int caretOffset, int* extraWid
//
// FIXME: ignoring :first-line, missing good reason to take care of
int fontHeight = style()->font().height();
- if (fontHeight > rect.height() || !isReplaced() && !isTable())
+ if (fontHeight > rect.height() || (!isReplaced() && !isTable()))
rect.setHeight(fontHeight);
if (extraWidthToEndOfLine)
- *extraWidthToEndOfLine = xPos() + m_width - rect.right();
+ *extraWidthToEndOfLine = x() + width() - rect.right();
// Move to local coords
- rect.move(-xPos(), -yPos());
+ rect.move(-x(), -y());
return rect;
}
int RenderBox::lowestPosition(bool /*includeOverflowInterior*/, bool includeSelf) const
{
- if (!includeSelf || !m_width)
+ if (!includeSelf || !width())
return 0;
- int bottom = m_height;
+ int bottom = height();
if (isRelPositioned())
bottom += relativePositionOffsetY();
return bottom;
@@ -2747,9 +2631,9 @@ int RenderBox::lowestPosition(bool /*includeOverflowInterior*/, bool includeSelf
int RenderBox::rightmostPosition(bool /*includeOverflowInterior*/, bool includeSelf) const
{
- if (!includeSelf || !m_height)
+ if (!includeSelf || !height())
return 0;
- int right = m_width;
+ int right = width();
if (isRelPositioned())
right += relativePositionOffsetX();
return right;
@@ -2757,12 +2641,133 @@ int RenderBox::rightmostPosition(bool /*includeOverflowInterior*/, bool includeS
int RenderBox::leftmostPosition(bool /*includeOverflowInterior*/, bool includeSelf) const
{
- if (!includeSelf || !m_height)
- return m_width;
+ if (!includeSelf || !height())
+ return width();
int left = 0;
if (isRelPositioned())
left += relativePositionOffsetX();
return left;
}
+bool RenderBox::isAfterContent(RenderObject* child) const
+{
+ return (child && child->style()->styleType() == AFTER && (!child->isText() || child->isBR()));
+}
+
+VisiblePosition RenderBox::positionForPoint(const IntPoint& point)
+{
+ // no children...return this render object's element, if there is one, and offset 0
+ if (!firstChild())
+ return createVisiblePosition(firstDeepEditingPositionForNode(node()));
+
+ int xPos = point.x();
+ int yPos = point.y();
+
+ if (isTable() && node()) {
+ int right = contentWidth() + borderRight() + paddingRight() + borderLeft() + paddingLeft();
+ int bottom = contentHeight() + borderTop() + paddingTop() + borderBottom() + paddingBottom();
+
+ if (xPos < 0 || xPos > right || yPos < 0 || yPos > bottom) {
+ if (xPos <= right / 2)
+ return createVisiblePosition(firstDeepEditingPositionForNode(node()));
+ return createVisiblePosition(lastDeepEditingPositionForNode(node()));
+ }
+ }
+
+ // Pass off to the closest child.
+ int minDist = INT_MAX;
+ RenderBox* closestRenderer = 0;
+ int newX = xPos;
+ int newY = yPos;
+ if (isTableRow()) {
+ newX += x();
+ newY += y();
+ }
+ for (RenderObject* renderObject = firstChild(); renderObject; renderObject = renderObject->nextSibling()) {
+ if ((!renderObject->firstChild() && !renderObject->isInline() && !renderObject->isBlockFlow() )
+ || renderObject->style()->visibility() != VISIBLE)
+ continue;
+
+ if (!renderObject->isBox())
+ continue;
+
+ RenderBox* renderer = toRenderBox(renderObject);
+
+ int top = renderer->borderTop() + renderer->paddingTop() + (isTableRow() ? 0 : renderer->y());
+ int bottom = top + renderer->contentHeight();
+ int left = renderer->borderLeft() + renderer->paddingLeft() + (isTableRow() ? 0 : renderer->x());
+ int right = left + renderer->contentWidth();
+
+ if (xPos <= right && xPos >= left && yPos <= top && yPos >= bottom) {
+ if (renderer->isTableRow())
+ return renderer->positionForCoordinates(xPos + newX - renderer->x(), yPos + newY - renderer->y());
+ return renderer->positionForCoordinates(xPos - renderer->x(), yPos - renderer->y());
+ }
+
+ // Find the distance from (x, y) to the box. Split the space around the box into 8 pieces
+ // and use a different compare depending on which piece (x, y) is in.
+ IntPoint cmp;
+ if (xPos > right) {
+ if (yPos < top)
+ cmp = IntPoint(right, top);
+ else if (yPos > bottom)
+ cmp = IntPoint(right, bottom);
+ else
+ cmp = IntPoint(right, yPos);
+ } else if (xPos < left) {
+ if (yPos < top)
+ cmp = IntPoint(left, top);
+ else if (yPos > bottom)
+ cmp = IntPoint(left, bottom);
+ else
+ cmp = IntPoint(left, yPos);
+ } else {
+ if (yPos < top)
+ cmp = IntPoint(xPos, top);
+ else
+ cmp = IntPoint(xPos, bottom);
+ }
+
+ int x1minusx2 = cmp.x() - xPos;
+ int y1minusy2 = cmp.y() - yPos;
+
+ int dist = x1minusx2 * x1minusx2 + y1minusy2 * y1minusy2;
+ if (dist < minDist) {
+ closestRenderer = renderer;
+ minDist = dist;
+ }
+ }
+
+ if (closestRenderer)
+ return closestRenderer->positionForCoordinates(newX - closestRenderer->x(), newY - closestRenderer->y());
+
+ return createVisiblePosition(firstDeepEditingPositionForNode(node()));
+}
+
+bool RenderBox::shrinkToAvoidFloats() const
+{
+ // FIXME: Technically we should be able to shrink replaced elements on a line, but this is difficult to accomplish, since this
+ // involves doing a relayout during findNextLineBreak and somehow overriding the containingBlockWidth method to return the
+ // current remaining width on a line.
+ if ((isInline() && !isHTMLMarquee()) || !avoidsFloats())
+ return false;
+
+ // All auto-width objects that avoid floats should always use lineWidth.
+ return style()->width().isAuto();
+}
+
+bool RenderBox::avoidsFloats() const
+{
+ return isReplaced() || hasOverflowClip() || isHR();
+}
+
+#if ENABLE(SVG)
+
+TransformationMatrix RenderBox::localTransform() const
+{
+ return TransformationMatrix(1, 0, 0, 1, x(), y());
+}
+
+#endif
+
} // namespace WebCore
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderBox.h b/src/3rdparty/webkit/WebCore/rendering/RenderBox.h
index 54349fa..95c0637 100644
--- a/src/3rdparty/webkit/WebCore/rendering/RenderBox.h
+++ b/src/3rdparty/webkit/WebCore/rendering/RenderBox.h
@@ -23,19 +23,127 @@
#ifndef RenderBox_h
#define RenderBox_h
-#include "RenderObject.h"
+#include "RenderBoxModelObject.h"
+#include "ScrollTypes.h"
namespace WebCore {
- enum WidthType { Width, MinWidth, MaxWidth };
+enum WidthType { Width, MinWidth, MaxWidth };
-class RenderBox : public RenderObject {
+class RenderBox : public RenderBoxModelObject {
public:
RenderBox(Node*);
virtual ~RenderBox();
- virtual const char* renderName() const { return "RenderBox"; }
+ // Use this with caution! No type checking is done!
+ RenderBox* firstChildBox() const;
+ RenderBox* lastChildBox() const;
+ int x() const { return m_frameRect.x(); }
+ int y() const { return m_frameRect.y(); }
+ int width() const { return m_frameRect.width(); }
+ int height() const { return m_frameRect.height(); }
+
+ void setX(int x) { m_frameRect.setX(x); }
+ void setY(int y) { m_frameRect.setY(y); }
+ void setWidth(int width) { m_frameRect.setWidth(width); }
+ void setHeight(int height) { m_frameRect.setHeight(height); }
+
+ IntPoint location() const { return m_frameRect.location(); }
+ IntSize size() const { return m_frameRect.size(); }
+
+ void setLocation(const IntPoint& location) { m_frameRect.setLocation(location); }
+ void setLocation(int x, int y) { setLocation(IntPoint(x, y)); }
+
+ void setSize(const IntSize& size) { m_frameRect.setSize(size); }
+ void move(int dx, int dy) { m_frameRect.move(dx, dy); }
+
+ IntRect frameRect() const { return m_frameRect; }
+ void setFrameRect(const IntRect& rect) { m_frameRect = rect; }
+
+ IntRect borderBoxRect() const { return IntRect(0, 0, width(), height()); }
+ virtual IntRect borderBoundingBox() const { return borderBoxRect(); }
+
+ // The content area of the box (excludes padding and border).
+ IntRect contentBoxRect() const { return IntRect(borderLeft() + paddingLeft(), borderTop() + paddingTop(), contentWidth(), contentHeight()); }
+ // The content box in absolute coords. Ignores transforms.
+ IntRect absoluteContentBox() const;
+ // The content box converted to absolute coords (taking transforms into account).
+ FloatQuad absoluteContentQuad() const;
+
+ // Bounds of the outline box in absolute coords. Respects transforms
+ virtual IntRect outlineBoundsForRepaint(RenderBoxModelObject* /*repaintContainer*/) const;
+ virtual void addFocusRingRects(GraphicsContext*, int tx, int ty);
+
+ // Use this with caution! No type checking is done!
+ RenderBox* previousSiblingBox() const;
+ RenderBox* nextSiblingBox() const;
+ RenderBox* parentBox() const;
+
+ // The height of a block when you include normal flow overflow spillage out of the bottom
+ // of the block (e.g., a <div style="height:25px"> that has a 100px tall image inside
+ // it would have an overflow height of borderTop() + paddingTop() + 100px.
+ virtual int overflowHeight(bool /*includeInterior*/ = true) const { return height(); }
+ virtual int overflowWidth(bool /*includeInterior*/ = true) const { return width(); }
+ virtual void setOverflowHeight(int) { }
+ virtual void setOverflowWidth(int) { }
+ virtual int overflowLeft(bool /*includeInterior*/ = true) const { return 0; }
+ virtual int overflowTop(bool /*includeInterior*/ = true) const { return 0; }
+ virtual IntRect overflowRect(bool /*includeInterior*/ = true) const { return borderBoxRect(); }
+
+ int contentWidth() const { return clientWidth() - paddingLeft() - paddingRight(); }
+ int contentHeight() const { return clientHeight() - paddingTop() - paddingBottom(); }
+
+ // IE extensions. Used to calculate offsetWidth/Height. Overridden by inlines (RenderFlow)
+ // to return the remaining width on a given line (and the height of a single line).
+ virtual int offsetWidth() const { return width(); }
+ virtual int offsetHeight() const { return height(); }
+
+ // More IE extensions. clientWidth and clientHeight represent the interior of an object
+ // excluding border and scrollbar. clientLeft/Top are just the borderLeftWidth and borderTopWidth.
+ int clientLeft() const { return borderLeft(); }
+ int clientTop() const { return borderTop(); }
+ int clientWidth() const;
+ int clientHeight() const;
+
+ // scrollWidth/scrollHeight will be the same as clientWidth/clientHeight unless the
+ // object has overflow:hidden/scroll/auto specified and also has overflow.
+ // scrollLeft/Top return the current scroll position. These methods are virtual so that objects like
+ // textareas can scroll shadow content (but pretend that they are the objects that are
+ // scrolling).
+ virtual int scrollLeft() const;
+ virtual int scrollTop() const;
+ virtual int scrollWidth() const;
+ virtual int scrollHeight() const;
+ virtual void setScrollLeft(int);
+ virtual void setScrollTop(int);
+
+ virtual int marginTop() const { return m_marginTop; }
+ virtual int marginBottom() const { return m_marginBottom; }
+ virtual int marginLeft() const { return m_marginLeft; }
+ virtual int marginRight() const { return m_marginRight; }
+
+ // The following five functions are used to implement collapsing margins.
+ // All objects know their maximal positive and negative margins. The
+ // formula for computing a collapsed margin is |maxPosMargin| - |maxNegmargin|.
+ // For a non-collapsing box, such as a leaf element, this formula will simply return
+ // the margin of the element. Blocks override the maxTopMargin and maxBottomMargin
+ // methods.
+ virtual bool isSelfCollapsingBlock() const { return false; }
+ int collapsedMarginTop() const { return maxTopMargin(true) - maxTopMargin(false); }
+ int collapsedMarginBottom() const { return maxBottomMargin(true) - maxBottomMargin(false); }
+ virtual int maxTopMargin(bool positive) const { return positive ? std::max(0, marginTop()) : -std::min(0, marginTop()); }
+ virtual int maxBottomMargin(bool positive) const { return positive ? std::max(0, marginBottom()) : -std::min(0, marginBottom()); }
+
+ virtual void absoluteRects(Vector<IntRect>&, int tx, int ty);
+ virtual void absoluteQuads(Vector<FloatQuad>&);
+
+ IntRect reflectionBox() const;
+ int reflectionOffset() const;
+ // Given a rect in the object's coordinate space, returns the corresponding rect in the reflection.
+ IntRect reflectedRect(const IntRect&) const;
+
+ virtual void layout();
virtual void paint(PaintInfo&, int tx, int ty);
virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, int x, int y, int tx, int ty, HitTestAction);
@@ -44,33 +152,13 @@ public:
virtual int minPrefWidth() const;
virtual int maxPrefWidth() const;
- virtual int overrideSize() const;
- virtual int overrideWidth() const;
- virtual int overrideHeight() const;
+ int overrideSize() const;
+ int overrideWidth() const;
+ int overrideHeight() const;
virtual void setOverrideSize(int);
- virtual FloatPoint localToAbsolute(FloatPoint localPoint = FloatPoint(), bool fixed = false, bool useTransforms = false) const;
- virtual FloatPoint absoluteToLocal(FloatPoint containerPoint, bool fixed = false, bool useTransforms = false) const;
- virtual FloatQuad localToAbsoluteQuad(const FloatQuad&, bool fixed = false) const;
-
virtual IntSize offsetFromContainer(RenderObject*) const;
-
- virtual int xPos() const { return m_x; }
- virtual int yPos() const { return m_y; }
- virtual void setPos(int x, int y);
-
- virtual int width() const { return m_width; }
- virtual int height() const { return m_height; }
- virtual void setWidth(int width) { m_width = width; }
- virtual void setHeight(int height) { m_height = height; }
-
- virtual int marginTop() const { return m_marginTop; }
- virtual int marginBottom() const { return m_marginBottom; }
- virtual int marginLeft() const { return m_marginLeft; }
- virtual int marginRight() const { return m_marginRight; }
-
- virtual IntRect borderBox() const { return IntRect(0, -borderTopExtra(), width(), height() + borderTopExtra() + borderBottomExtra()); }
-
+
int calcBorderBoxWidth(int width) const;
int calcBorderBoxHeight(int height) const;
int calcContentBoxWidth(int width) const;
@@ -84,28 +172,28 @@ public:
// shifted. -dwh
void calcHorizontalMargins(const Length& marginLeft, const Length& marginRight, int containerWidth);
- virtual void position(InlineBox*);
+ void positionLineBox(InlineBox*);
- virtual void dirtyLineBoxes(bool fullLayout, bool isRootLineBox = false);
+ virtual InlineBox* createInlineBox();
+ void dirtyLineBoxes(bool fullLayout);
// For inline replaced elements, this function returns the inline box that owns us. Enables
// the replaced RenderObject to quickly determine what line it is contained on and to easily
// iterate over structures on the line.
- virtual InlineBox* inlineBoxWrapper() const { return m_inlineBoxWrapper; }
- virtual void setInlineBoxWrapper(InlineBox* boxWrapper) { m_inlineBoxWrapper = boxWrapper; }
- virtual void deleteLineBoxWrapper();
+ InlineBox* inlineBoxWrapper() const { return m_inlineBoxWrapper; }
+ void setInlineBoxWrapper(InlineBox* boxWrapper) { m_inlineBoxWrapper = boxWrapper; }
+ void deleteLineBoxWrapper();
virtual int lowestPosition(bool includeOverflowInterior = true, bool includeSelf = true) const;
virtual int rightmostPosition(bool includeOverflowInterior = true, bool includeSelf = true) const;
virtual int leftmostPosition(bool includeOverflowInterior = true, bool includeSelf = true) const;
- virtual IntRect absoluteClippedOverflowRect();
- virtual void computeAbsoluteRepaintRect(IntRect&, bool fixed = false);
- IntSize offsetForPositionedInContainer(RenderObject*) const;
+ virtual IntRect clippedOverflowRectForRepaint(RenderBoxModelObject* repaintContainer);
+ virtual void computeRectForRepaint(RenderBoxModelObject* repaintContainer, IntRect&, bool fixed = false);
virtual void repaintDuringLayoutIfMoved(const IntRect&);
- virtual int containingBlockWidth() const;
+ virtual int containingBlockWidthForContent() const;
virtual void calcWidth();
virtual void calcHeight();
@@ -132,31 +220,36 @@ public:
int calcPercentageHeight(const Length& height);
+ // Block flows subclass availableWidth to handle multi column layout (shrinking the width available to children when laying out.)
+ virtual int availableWidth() const { return contentWidth(); }
virtual int availableHeight() const;
int availableHeightUsing(const Length&) const;
void calcVerticalMargins();
- int relativePositionOffsetX() const;
- int relativePositionOffsetY() const;
- IntSize relativePositionOffset() const { return IntSize(relativePositionOffsetX(), relativePositionOffsetY()); }
+ virtual int verticalScrollbarWidth() const;
+ int horizontalScrollbarHeight() const;
+ virtual bool scroll(ScrollDirection, ScrollGranularity, float multiplier = 1.0f);
+ virtual bool canBeProgramaticallyScrolled(bool) const;
+ virtual void autoscroll();
+ virtual void stopAutoscroll() { }
+ virtual void panScroll(const IntPoint&);
+ bool hasAutoVerticalScrollbar() const { return hasOverflowClip() && (style()->overflowY() == OAUTO || style()->overflowY() == OOVERLAY); }
+ bool hasAutoHorizontalScrollbar() const { return hasOverflowClip() && (style()->overflowX() == OAUTO || style()->overflowX() == OOVERLAY); }
+ bool scrollsOverflow() const { return scrollsOverflowX() || scrollsOverflowY(); }
+ bool scrollsOverflowX() const { return hasOverflowClip() && (style()->overflowX() == OSCROLL || hasAutoHorizontalScrollbar()); }
+ bool scrollsOverflowY() const { return hasOverflowClip() && (style()->overflowY() == OSCROLL || hasAutoVerticalScrollbar()); }
- virtual RenderLayer* layer() const { return m_layer; }
-
virtual IntRect localCaretRect(InlineBox*, int caretOffset, int* extraWidthToEndOfLine = 0);
- virtual void paintFillLayerExtended(const PaintInfo&, const Color&, const FillLayer*, int clipY, int clipHeight,
- int tx, int ty, int width, int height, InlineFlowBox* = 0, CompositeOperator = CompositeSourceOver);
- IntSize calculateBackgroundSize(const FillLayer*, int scaledWidth, int scaledHeight) const;
-
- virtual int staticX() const;
- virtual int staticY() const;
- virtual void setStaticX(int staticX);
- virtual void setStaticY(int staticY);
-
- virtual IntRect getOverflowClipRect(int tx, int ty);
- virtual IntRect getClipRect(int tx, int ty);
+ virtual IntRect overflowClipRect(int tx, int ty);
+ IntRect clipRect(int tx, int ty);
+ virtual bool hasControlClip() const { return false; }
+ virtual IntRect controlClipRect(int /*tx*/, int /*ty*/) const { return IntRect(); }
+ bool pushContentsClip(PaintInfo&, int tx, int ty);
+ void popContentsClip(PaintInfo&, PaintPhase originalPhase, int tx, int ty);
+ virtual void paintObject(PaintInfo&, int /*tx*/, int /*ty*/) { ASSERT_NOT_REACHED(); }
virtual void paintBoxDecorations(PaintInfo&, int tx, int ty);
virtual void paintMask(PaintInfo& paintInfo, int tx, int ty);
virtual void imageChanged(WrappedImagePtr, const IntRect* = 0);
@@ -165,25 +258,40 @@ public:
// that just updates the object's position.
virtual void tryLayoutDoingPositionedMovementOnly()
{
- int oldWidth = m_width;
+ int oldWidth = width();
calcWidth();
// If we shrink to fit our width may have changed, so we still need full layout.
- if (oldWidth != m_width)
+ if (oldWidth != width())
return;
calcHeight();
setNeedsLayout(false);
}
- virtual IntRect maskClipRect();
+ IntRect maskClipRect();
+
+ virtual VisiblePosition positionForPoint(const IntPoint&);
+
+ void removeFloatingOrPositionedChildFromBlockLists();
+ virtual int firstLineBoxBaseline() const { return -1; }
+ virtual int lastLineBoxBaseline() const { return -1; }
+
+ bool shrinkToAvoidFloats() const;
+ virtual bool avoidsFloats() const;
+
+#if ENABLE(SVG)
+ virtual TransformationMatrix localTransform() const;
+#endif
+
protected:
- virtual void styleWillChange(RenderStyle::Diff, const RenderStyle* newStyle);
- virtual void styleDidChange(RenderStyle::Diff, const RenderStyle* oldStyle);
+ virtual void styleWillChange(StyleDifference, const RenderStyle* newStyle);
+ virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
+ virtual void updateBoxModelInfoFromStyle();
- void paintFillLayer(const PaintInfo&, const Color&, const FillLayer*, int clipY, int clipHeight, int tx, int ty, int width, int height, CompositeOperator = CompositeSourceOver);
- void paintFillLayers(const PaintInfo&, const Color&, const FillLayer*, int clipY, int clipHeight, int tx, int ty, int width, int height, CompositeOperator = CompositeSourceOver);
+ void paintFillLayer(const PaintInfo&, const Color&, const FillLayer*, int tx, int ty, int width, int height, CompositeOperator = CompositeSourceOver);
+ void paintFillLayers(const PaintInfo&, const Color&, const FillLayer*, int tx, int ty, int width, int height, CompositeOperator = CompositeSourceOver);
- void paintMaskImages(const PaintInfo&, int clipY, int clipHeight, int tx, int ty, int width, int height);
+ void paintMaskImages(const PaintInfo&, int tx, int ty, int width, int height);
#if PLATFORM(MAC)
void paintCustomHighlight(int tx, int ty, const AtomicString& type, bool behindText);
@@ -193,22 +301,26 @@ protected:
virtual bool shouldCalculateSizeAsReplaced() const { return isReplaced() && !isInlineBlockOrInlineTable(); }
+ virtual void mapLocalToContainer(RenderBoxModelObject* repaintContainer, bool useTransforms, bool fixed, TransformState&) const;
+ virtual void mapAbsoluteToLocalPoint(bool fixed, bool useTransforms, TransformState&) const;
+
private:
+ bool includeVerticalScrollbarSize() const { return hasOverflowClip() && (style()->overflowY() == OSCROLL || style()->overflowY() == OAUTO); }
+ bool includeHorizontalScrollbarSize() const { return hasOverflowClip() && (style()->overflowX() == OSCROLL || style()->overflowX() == OAUTO); }
+
void paintRootBoxDecorations(PaintInfo&, int tx, int ty);
// Returns true if we did a full repaint
bool repaintLayerRectsForImage(WrappedImagePtr image, const FillLayer* layers, bool drawingBackground);
-
- void calculateBackgroundImageGeometry(const FillLayer*, int tx, int ty, int w, int h, IntRect& destRect, IntPoint& phase, IntSize& tileSize);
-
- int containingBlockWidthForPositioned(const RenderObject* containingBlock) const;
- int containingBlockHeightForPositioned(const RenderObject* containingBlock) const;
+
+ int containingBlockWidthForPositioned(const RenderBoxModelObject* containingBlock) const;
+ int containingBlockHeightForPositioned(const RenderBoxModelObject* containingBlock) const;
void calcAbsoluteVertical();
- void calcAbsoluteHorizontalValues(Length width, const RenderObject* cb, TextDirection containerDirection,
+ void calcAbsoluteHorizontalValues(Length width, const RenderBoxModelObject* cb, TextDirection containerDirection,
int containerWidth, int bordersPlusPadding,
Length left, Length right, Length marginLeft, Length marginRight,
int& widthValue, int& marginLeftValue, int& marginRightValue, int& xPos);
- void calcAbsoluteVerticalValues(Length height, const RenderObject* cb,
+ void calcAbsoluteVerticalValues(Length height, const RenderBoxModelObject* cb,
int containerHeight, int bordersPlusPadding,
Length top, Length bottom, Length marginTop, Length marginBottom,
int& heightValue, int& marginTopValue, int& marginBottomValue, int& yPos);
@@ -219,16 +331,16 @@ private:
// This function calculates the minimum and maximum preferred widths for an object.
// These values are used in shrink-to-fit layout systems.
// These include tables, positioned objects, floats and flexible boxes.
- virtual void calcPrefWidths() = 0;
+ virtual void calcPrefWidths() { setPrefWidthsDirty(false); }
protected:
- // The width/height of the contents + borders + padding.
- int m_width;
- int m_height;
+ bool isAfterContent(RenderObject* child) const;
- int m_x;
- int m_y;
+private:
+ // The width/height of the contents + borders + padding. The x/y location is relative to our container (which is not always our parent).
+ IntRect m_frameRect;
+protected:
int m_marginLeft;
int m_marginRight;
int m_marginTop;
@@ -240,18 +352,54 @@ protected:
// The preferred width of the element if it never breaks any lines at all.
int m_maxPrefWidth;
- // A pointer to our layer if we have one.
- RenderLayer* m_layer;
-
// For inline replaced elements, the inline box that owns us.
InlineBox* m_inlineBoxWrapper;
private:
// Used to store state between styleWillChange and styleDidChange
- static bool s_wasFloating;
static bool s_hadOverflowClip;
};
+inline RenderBox* toRenderBox(RenderObject* o)
+{
+ ASSERT(!o || o->isBox());
+ return static_cast<RenderBox*>(o);
+}
+
+inline const RenderBox* toRenderBox(const RenderObject* o)
+{
+ ASSERT(!o || o->isBox());
+ return static_cast<const RenderBox*>(o);
+}
+
+// This will catch anyone doing an unnecessary cast.
+void toRenderBox(const RenderBox*);
+
+inline RenderBox* RenderBox::previousSiblingBox() const
+{
+ return toRenderBox(previousSibling());
+}
+
+inline RenderBox* RenderBox::nextSiblingBox() const
+{
+ return toRenderBox(nextSibling());
+}
+
+inline RenderBox* RenderBox::parentBox() const
+{
+ return toRenderBox(parent());
+}
+
+inline RenderBox* RenderBox::firstChildBox() const
+{
+ return toRenderBox(firstChild());
+}
+
+inline RenderBox* RenderBox::lastChildBox() const
+{
+ return toRenderBox(lastChild());
+}
+
} // namespace WebCore
#endif // RenderBox_h
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderBoxModelObject.cpp b/src/3rdparty/webkit/WebCore/rendering/RenderBoxModelObject.cpp
new file mode 100644
index 0000000..8973e64
--- /dev/null
+++ b/src/3rdparty/webkit/WebCore/rendering/RenderBoxModelObject.cpp
@@ -0,0 +1,1177 @@
+/*
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ * (C) 1999 Antti Koivisto (koivisto@kde.org)
+ * (C) 2005 Allan Sandfeld Jensen (kde@carewolf.com)
+ * (C) 2005, 2006 Samuel Weinig (sam.weinig@gmail.com)
+ * Copyright (C) 2005, 2006, 2007, 2008, 2009 Apple Inc. 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
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "RenderBoxModelObject.h"
+
+#include "GraphicsContext.h"
+#include "HTMLElement.h"
+#include "HTMLNames.h"
+#include "ImageBuffer.h"
+#include "RenderBlock.h"
+#include "RenderInline.h"
+#include "RenderLayer.h"
+#include "RenderView.h"
+
+using namespace std;
+
+namespace WebCore {
+
+using namespace HTMLNames;
+
+bool RenderBoxModelObject::s_wasFloating = false;
+bool RenderBoxModelObject::s_hadLayer = false;
+bool RenderBoxModelObject::s_layerWasSelfPainting = false;
+
+RenderBoxModelObject::RenderBoxModelObject(Node* node)
+ : RenderObject(node)
+ , m_layer(0)
+{
+}
+
+RenderBoxModelObject::~RenderBoxModelObject()
+{
+ // Our layer should have been destroyed and cleared by now
+ ASSERT(!hasLayer());
+ ASSERT(!m_layer);
+}
+
+void RenderBoxModelObject::destroyLayer()
+{
+ ASSERT(!hasLayer()); // Callers should have already called setHasLayer(false)
+ ASSERT(m_layer);
+ m_layer->destroy(renderArena());
+ m_layer = 0;
+}
+
+void RenderBoxModelObject::destroy()
+{
+ // This must be done before we destroy the RenderObject.
+ if (m_layer)
+ m_layer->clearClipRects();
+
+ // RenderObject::destroy calls back to destroyLayer() for layer destruction
+ RenderObject::destroy();
+}
+
+bool RenderBoxModelObject::hasSelfPaintingLayer() const
+{
+ return m_layer && m_layer->isSelfPaintingLayer();
+}
+
+void RenderBoxModelObject::styleWillChange(StyleDifference diff, const RenderStyle* newStyle)
+{
+ s_wasFloating = isFloating();
+ s_hadLayer = hasLayer();
+ if (s_hadLayer)
+ s_layerWasSelfPainting = layer()->isSelfPaintingLayer();
+
+ // If our z-index changes value or our visibility changes,
+ // we need to dirty our stacking context's z-order list.
+ if (style() && newStyle) {
+ if (parent()) {
+ // Do a repaint with the old style first, e.g., for example if we go from
+ // having an outline to not having an outline.
+ if (diff == StyleDifferenceRepaintLayer) {
+ layer()->repaintIncludingDescendants();
+ if (!(style()->clip() == newStyle->clip()))
+ layer()->clearClipRectsIncludingDescendants();
+ } else if (diff == StyleDifferenceRepaint || newStyle->outlineSize() < style()->outlineSize())
+ repaint();
+ }
+
+ if (diff == StyleDifferenceLayout) {
+ // When a layout hint happens, we go ahead and do a repaint of the layer, since the layer could
+ // end up being destroyed.
+ if (hasLayer()) {
+ if (style()->position() != newStyle->position() ||
+ style()->zIndex() != newStyle->zIndex() ||
+ style()->hasAutoZIndex() != newStyle->hasAutoZIndex() ||
+ !(style()->clip() == newStyle->clip()) ||
+ style()->hasClip() != newStyle->hasClip() ||
+ style()->opacity() != newStyle->opacity() ||
+ style()->transform() != newStyle->transform())
+ layer()->repaintIncludingDescendants();
+ } else if (newStyle->hasTransform() || newStyle->opacity() < 1) {
+ // If we don't have a layer yet, but we are going to get one because of transform or opacity,
+ // then we need to repaint the old position of the object.
+ repaint();
+ }
+ }
+
+ if (hasLayer() && (style()->hasAutoZIndex() != newStyle->hasAutoZIndex() ||
+ style()->zIndex() != newStyle->zIndex() ||
+ style()->visibility() != newStyle->visibility())) {
+ layer()->dirtyStackingContextZOrderLists();
+ if (style()->hasAutoZIndex() != newStyle->hasAutoZIndex() || style()->visibility() != newStyle->visibility())
+ layer()->dirtyZOrderLists();
+ }
+ }
+
+ RenderObject::styleWillChange(diff, newStyle);
+}
+
+void RenderBoxModelObject::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
+{
+ RenderObject::styleDidChange(diff, oldStyle);
+ updateBoxModelInfoFromStyle();
+
+ if (requiresLayer()) {
+ if (!layer()) {
+ if (s_wasFloating && isFloating())
+ setChildNeedsLayout(true);
+ m_layer = new (renderArena()) RenderLayer(this);
+ setHasLayer(true);
+ m_layer->insertOnlyThisLayer();
+ if (parent() && !needsLayout() && containingBlock())
+ m_layer->updateLayerPositions();
+ }
+ } else if (layer() && layer()->parent()) {
+ setHasTransform(false); // Either a transform wasn't specified or the object doesn't support transforms, so just null out the bit.
+ setHasReflection(false);
+ m_layer->removeOnlyThisLayer(); // calls destroyLayer() which clears m_layer
+ if (s_wasFloating && isFloating())
+ setChildNeedsLayout(true);
+ }
+
+ if (layer()) {
+ layer()->styleChanged(diff, oldStyle);
+ if (s_hadLayer && layer()->isSelfPaintingLayer() != s_layerWasSelfPainting)
+ setChildNeedsLayout(true);
+ }
+}
+
+void RenderBoxModelObject::updateBoxModelInfoFromStyle()
+{
+ // Set the appropriate bits for a box model object. Since all bits are cleared in styleWillChange,
+ // we only check for bits that could possibly be set to true.
+ setHasBoxDecorations(style()->hasBorder() || style()->hasBackground() || style()->hasAppearance() || style()->boxShadow());
+ setInline(style()->isDisplayInlineType());
+ setRelPositioned(style()->position() == RelativePosition);
+}
+
+int RenderBoxModelObject::relativePositionOffsetX() const
+{
+ if (!style()->left().isAuto()) {
+ if (!style()->right().isAuto() && containingBlock()->style()->direction() == RTL)
+ return -style()->right().calcValue(containingBlockWidthForContent());
+ return style()->left().calcValue(containingBlockWidthForContent());
+ }
+ if (!style()->right().isAuto())
+ return -style()->right().calcValue(containingBlockWidthForContent());
+ return 0;
+}
+
+int RenderBoxModelObject::relativePositionOffsetY() const
+{
+ if (!style()->top().isAuto())
+ return style()->top().calcValue(containingBlock()->availableHeight());
+ else if (!style()->bottom().isAuto())
+ return -style()->bottom().calcValue(containingBlock()->availableHeight());
+
+ return 0;
+}
+
+int RenderBoxModelObject::offsetLeft() const
+{
+ // If the element is the HTML body element or does not have an associated box
+ // return 0 and stop this algorithm.
+ if (isBody())
+ return 0;
+
+ RenderBoxModelObject* offsetPar = offsetParent();
+ int xPos = (isBox() ? toRenderBox(this)->x() : 0);
+
+ // If the offsetParent of the element is null, or is the HTML body element,
+ // return the distance between the canvas origin and the left border edge
+ // of the element and stop this algorithm.
+ if (offsetPar) {
+ if (offsetPar->isBox() && !offsetPar->isBody())
+ xPos -= toRenderBox(offsetPar)->borderLeft();
+ if (!isPositioned()) {
+ if (isRelPositioned())
+ xPos += relativePositionOffsetX();
+ RenderObject* curr = parent();
+ while (curr && curr != offsetPar) {
+ // FIXME: What are we supposed to do inside SVG content?
+ if (curr->isBox() && !curr->isTableRow())
+ xPos += toRenderBox(curr)->x();
+ curr = curr->parent();
+ }
+ if (offsetPar->isBox() && offsetPar->isBody() && !offsetPar->isRelPositioned() && !offsetPar->isPositioned())
+ xPos += toRenderBox(offsetPar)->x();
+ }
+ }
+
+ return xPos;
+}
+
+int RenderBoxModelObject::offsetTop() const
+{
+ // If the element is the HTML body element or does not have an associated box
+ // return 0 and stop this algorithm.
+ if (isBody())
+ return 0;
+
+ RenderBoxModelObject* offsetPar = offsetParent();
+ int yPos = (isBox() ? toRenderBox(this)->y() : 0);
+
+ // If the offsetParent of the element is null, or is the HTML body element,
+ // return the distance between the canvas origin and the top border edge
+ // of the element and stop this algorithm.
+ if (offsetPar) {
+ if (offsetPar->isBox() && !offsetPar->isBody())
+ yPos -= toRenderBox(offsetPar)->borderTop();
+ if (!isPositioned()) {
+ if (isRelPositioned())
+ yPos += relativePositionOffsetY();
+ RenderObject* curr = parent();
+ while (curr && curr != offsetPar) {
+ // FIXME: What are we supposed to do inside SVG content?
+ if (curr->isBox() && !curr->isTableRow())
+ yPos += toRenderBox(curr)->y();
+ curr = curr->parent();
+ }
+ if (offsetPar->isBox() && offsetPar->isBody() && !offsetPar->isRelPositioned() && !offsetPar->isPositioned())
+ yPos += toRenderBox(offsetPar)->y();
+ }
+ }
+ return yPos;
+}
+
+int RenderBoxModelObject::paddingTop(bool) const
+{
+ int w = 0;
+ Length padding = style()->paddingTop();
+ if (padding.isPercent())
+ w = containingBlock()->availableWidth();
+ return padding.calcMinValue(w);
+}
+
+int RenderBoxModelObject::paddingBottom(bool) const
+{
+ int w = 0;
+ Length padding = style()->paddingBottom();
+ if (padding.isPercent())
+ w = containingBlock()->availableWidth();
+ return padding.calcMinValue(w);
+}
+
+int RenderBoxModelObject::paddingLeft(bool) const
+{
+ int w = 0;
+ Length padding = style()->paddingLeft();
+ if (padding.isPercent())
+ w = containingBlock()->availableWidth();
+ return padding.calcMinValue(w);
+}
+
+int RenderBoxModelObject::paddingRight(bool) const
+{
+ int w = 0;
+ Length padding = style()->paddingRight();
+ if (padding.isPercent())
+ w = containingBlock()->availableWidth();
+ 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)
+{
+ GraphicsContext* context = paintInfo.context;
+ bool includeLeftEdge = box ? box->includeLeftEdge() : true;
+ bool includeRightEdge = box ? box->includeRightEdge() : true;
+ int bLeft = includeLeftEdge ? borderLeft() : 0;
+ int bRight = includeRightEdge ? borderRight() : 0;
+ int pLeft = includeLeftEdge ? paddingLeft() : 0;
+ int pRight = includeRightEdge ? paddingRight() : 0;
+
+ bool clippedToBorderRadius = false;
+ if (style()->hasBorderRadius() && (includeLeftEdge || includeRightEdge)) {
+ context->save();
+
+ IntSize topLeft, topRight, bottomLeft, bottomRight;
+ IntRect borderRect(tx, ty, w, h);
+ style()->getBorderRadiiForRect(borderRect, topLeft, topRight, bottomLeft, bottomRight);
+
+ context->addRoundedRectClip(borderRect, includeLeftEdge ? topLeft : IntSize(),
+ includeRightEdge ? topRight : IntSize(),
+ includeLeftEdge ? bottomLeft : IntSize(),
+ includeRightEdge ? bottomRight : IntSize());
+ clippedToBorderRadius = true;
+ }
+
+ if (bgLayer->clip() == PaddingFillBox || bgLayer->clip() == ContentFillBox) {
+ // Clip to the padding or content boxes as necessary.
+ bool includePadding = bgLayer->clip() == ContentFillBox;
+ int x = tx + bLeft + (includePadding ? pLeft : 0);
+ int y = ty + borderTop() + (includePadding ? paddingTop() : 0);
+ int width = w - bLeft - bRight - (includePadding ? pLeft + pRight : 0);
+ int height = h - borderTop() - borderBottom() - (includePadding ? paddingTop() + paddingBottom() : 0);
+ context->save();
+ context->clip(IntRect(x, y, width, height));
+ } else if (bgLayer->clip() == TextFillBox) {
+ // We have to draw our text into a mask that can then be used to clip background drawing.
+ // First figure out how big the mask has to be. It should be no bigger than what we need
+ // to actually render, so we should intersect the dirty rect with the border box of the background.
+ IntRect maskRect(tx, ty, w, h);
+ maskRect.intersect(paintInfo.rect);
+
+ // Now create the mask.
+ OwnPtr<ImageBuffer> maskImage = ImageBuffer::create(maskRect.size(), false);
+ if (!maskImage)
+ return;
+
+ GraphicsContext* maskImageContext = maskImage->context();
+ maskImageContext->translate(-maskRect.x(), -maskRect.y());
+
+ // 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 {
+ int x = isBox() ? toRenderBox(this)->x() : 0;
+ int y = isBox() ? toRenderBox(this)->y() : 0;
+ paint(info, tx - x, ty - y);
+ }
+
+ // The mask has been created. Now we just need to clip to it.
+ context->save();
+ context->clipToImageBuffer(maskRect, maskImage.get());
+ }
+
+ 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;
+ if (isRoot) {
+ isOpaqueRoot = true;
+ if (!bgLayer->next() && !(bgColor.isValid() && bgColor.alpha() == 255) && view()->frameView()) {
+ Element* ownerElement = document()->ownerElement();
+ if (ownerElement) {
+ if (!ownerElement->hasTagName(frameTag)) {
+ // Locate the <body> element using the DOM. This is easier than trying
+ // to crawl around a render tree with potential :before/:after content and
+ // anonymous blocks created by inline <body> tags etc. We can locate the <body>
+ // render object very easily via the DOM.
+ HTMLElement* body = document()->body();
+ if (body) {
+ // Can't scroll a frameset document anyway.
+ isOpaqueRoot = body->hasLocalName(framesetTag);
+ }
+ }
+ } else
+ isOpaqueRoot = !view()->frameView()->isTransparent();
+ }
+ view()->frameView()->setContentIsOpaque(isOpaqueRoot);
+ }
+
+ // Paint the color first underneath all images.
+ if (!bgLayer->next()) {
+ IntRect rect(tx, ty, w, h);
+ rect.intersect(paintInfo.rect);
+ // If we have an alpha and we are painting the root element, go ahead and blend with the base background color.
+ if (isOpaqueRoot) {
+ Color baseColor = view()->frameView()->baseBackgroundColor();
+ if (baseColor.alpha() > 0) {
+ context->save();
+ context->setCompositeOperation(CompositeCopy);
+ context->fillRect(rect, baseColor);
+ context->restore();
+ } else
+ context->clearRect(rect);
+ }
+
+ if (bgColor.isValid() && bgColor.alpha() > 0)
+ context->fillRect(rect, bgColor);
+ }
+
+ // no progressive loading of the background image
+ if (shouldPaintBackgroundImage) {
+ IntRect destRect;
+ IntPoint phase;
+ IntSize tileSize;
+
+ calculateBackgroundImageGeometry(bgLayer, tx, ty, w, h, destRect, phase, tileSize);
+ IntPoint destOrigin = destRect.location();
+ destRect.intersect(paintInfo.rect);
+ if (!destRect.isEmpty()) {
+ phase += destRect.location() - destOrigin;
+ CompositeOperator compositeOp = op == CompositeSourceOver ? bgLayer->composite() : op;
+ RenderObject* clientForBackgroundImage = this;
+ // Check if this is the root element painting a background layer propagated from <body>,
+ // and pass the body's renderer as the client in that case.
+ if (isRoot && !style()->hasBackground()) {
+ ASSERT(node()->hasTagName(htmlTag));
+ HTMLElement* body = document()->body();
+ ASSERT(body);
+ ASSERT(body->hasLocalName(bodyTag));
+ ASSERT(body->renderer());
+ if (body) {
+ if (RenderObject* bodyRenderer = body->renderer())
+ clientForBackgroundImage = bodyRenderer;
+ }
+ }
+ context->drawTiledImage(bg->image(clientForBackgroundImage, tileSize), destRect, phase, tileSize, compositeOp);
+ }
+ }
+
+ if (bgLayer->clip() != BorderFillBox)
+ // Undo the background clip
+ context->restore();
+
+ if (clippedToBorderRadius)
+ // Undo the border radius clip
+ context->restore();
+}
+
+IntSize RenderBoxModelObject::calculateBackgroundSize(const FillLayer* bgLayer, int scaledWidth, int scaledHeight) const
+{
+ StyleImage* bg = bgLayer->image();
+ bg->setImageContainerSize(IntSize(scaledWidth, scaledHeight)); // Use the box established by background-origin.
+
+ if (bgLayer->isSizeSet()) {
+ int w = scaledWidth;
+ int h = scaledHeight;
+ Length bgWidth = bgLayer->size().width();
+ Length bgHeight = bgLayer->size().height();
+
+ if (bgWidth.isFixed())
+ w = bgWidth.value();
+ else if (bgWidth.isPercent())
+ w = bgWidth.calcValue(scaledWidth);
+
+ if (bgHeight.isFixed())
+ h = bgHeight.value();
+ else if (bgHeight.isPercent())
+ h = bgHeight.calcValue(scaledHeight);
+
+ // If one of the values is auto we have to use the appropriate
+ // scale to maintain our aspect ratio.
+ if (bgWidth.isAuto() && !bgHeight.isAuto())
+ w = bg->imageSize(this, style()->effectiveZoom()).width() * h / bg->imageSize(this, style()->effectiveZoom()).height();
+ else if (!bgWidth.isAuto() && bgHeight.isAuto())
+ h = bg->imageSize(this, style()->effectiveZoom()).height() * w / bg->imageSize(this, style()->effectiveZoom()).width();
+ else if (bgWidth.isAuto() && bgHeight.isAuto()) {
+ // If both width and height are auto, we just want to use the image's
+ // intrinsic size.
+ w = bg->imageSize(this, style()->effectiveZoom()).width();
+ h = bg->imageSize(this, style()->effectiveZoom()).height();
+ }
+
+ return IntSize(max(1, w), max(1, h));
+ } else
+ return bg->imageSize(this, style()->effectiveZoom());
+}
+
+void RenderBoxModelObject::calculateBackgroundImageGeometry(const FillLayer* bgLayer, int tx, int ty, int w, int h,
+ IntRect& destRect, IntPoint& phase, IntSize& tileSize)
+{
+ int pw;
+ int ph;
+ int left = 0;
+ int right = 0;
+ int top = 0;
+ int bottom = 0;
+ int cx;
+ int cy;
+ int rw = 0;
+ int rh = 0;
+
+ // CSS2 chapter 14.2.1
+
+ if (bgLayer->attachment()) {
+ // Scroll
+ if (bgLayer->origin() != BorderFillBox) {
+ left = borderLeft();
+ right = borderRight();
+ top = borderTop();
+ bottom = borderBottom();
+ if (bgLayer->origin() == ContentFillBox) {
+ left += paddingLeft();
+ right += paddingRight();
+ top += paddingTop();
+ bottom += paddingBottom();
+ }
+ }
+
+ // The background of the box generated by the root element covers the entire canvas including
+ // its margins. Since those were added in already, we have to factor them out when computing the
+ // box used by background-origin/size/position.
+ if (isRoot()) {
+ rw = toRenderBox(this)->width() - left - right;
+ rh = toRenderBox(this)->height() - top - bottom;
+ left += marginLeft();
+ right += marginRight();
+ top += marginTop();
+ bottom += marginBottom();
+ }
+ cx = tx;
+ cy = ty;
+ pw = w - left - right;
+ ph = h - top - bottom;
+ } else {
+ // Fixed
+ IntRect vr = viewRect();
+ cx = vr.x();
+ cy = vr.y();
+ pw = vr.width();
+ ph = vr.height();
+ }
+
+ int sx = 0;
+ int sy = 0;
+ int cw;
+ int ch;
+
+ IntSize scaledImageSize;
+ if (isRoot() && bgLayer->attachment())
+ scaledImageSize = calculateBackgroundSize(bgLayer, rw, rh);
+ else
+ scaledImageSize = calculateBackgroundSize(bgLayer, pw, ph);
+
+ int scaledImageWidth = scaledImageSize.width();
+ int scaledImageHeight = scaledImageSize.height();
+
+ EFillRepeat backgroundRepeat = bgLayer->repeat();
+
+ int xPosition;
+ if (isRoot() && bgLayer->attachment())
+ xPosition = bgLayer->xPosition().calcMinValue(rw - scaledImageWidth, true);
+ else
+ xPosition = bgLayer->xPosition().calcMinValue(pw - scaledImageWidth, true);
+ if (backgroundRepeat == RepeatFill || backgroundRepeat == RepeatXFill) {
+ cw = pw + left + right;
+ sx = scaledImageWidth ? scaledImageWidth - (xPosition + left) % scaledImageWidth : 0;
+ } else {
+ cx += max(xPosition + left, 0);
+ sx = -min(xPosition + left, 0);
+ cw = scaledImageWidth + min(xPosition + left, 0);
+ }
+
+ int yPosition;
+ if (isRoot() && bgLayer->attachment())
+ yPosition = bgLayer->yPosition().calcMinValue(rh - scaledImageHeight, true);
+ else
+ yPosition = bgLayer->yPosition().calcMinValue(ph - scaledImageHeight, true);
+ if (backgroundRepeat == RepeatFill || backgroundRepeat == RepeatYFill) {
+ ch = ph + top + bottom;
+ sy = scaledImageHeight ? scaledImageHeight - (yPosition + top) % scaledImageHeight : 0;
+ } else {
+ cy += max(yPosition + top, 0);
+ sy = -min(yPosition + top, 0);
+ ch = scaledImageHeight + min(yPosition + top, 0);
+ }
+
+ if (!bgLayer->attachment()) {
+ sx += max(tx - cx, 0);
+ sy += max(ty - cy, 0);
+ }
+
+ destRect = IntRect(cx, cy, cw, ch);
+ destRect.intersect(IntRect(tx, ty, w, h));
+ phase = IntPoint(sx, sy);
+ tileSize = IntSize(scaledImageWidth, scaledImageHeight);
+}
+
+int RenderBoxModelObject::verticalPosition(bool firstLine) const
+{
+ // This method determines the vertical position for inline elements.
+ ASSERT(isInline());
+ if (!isInline())
+ return 0;
+
+ int vpos = 0;
+ EVerticalAlign va = style()->verticalAlign();
+ if (va == TOP)
+ vpos = PositionTop;
+ else if (va == BOTTOM)
+ vpos = PositionBottom;
+ else {
+ bool checkParent = parent()->isRenderInline() && parent()->style()->verticalAlign() != TOP && parent()->style()->verticalAlign() != BOTTOM;
+ vpos = checkParent ? toRenderInline(parent())->verticalPositionFromCache(firstLine) : 0;
+ // don't allow elements nested inside text-top to have a different valignment.
+ if (va == BASELINE)
+ return vpos;
+
+ const Font& f = parent()->style(firstLine)->font();
+ int fontsize = f.pixelSize();
+
+ if (va == SUB)
+ vpos += fontsize / 5 + 1;
+ else if (va == SUPER)
+ vpos -= fontsize / 3 + 1;
+ else if (va == TEXT_TOP)
+ vpos += baselinePosition(firstLine) - f.ascent();
+ else if (va == MIDDLE)
+ vpos += -static_cast<int>(f.xHeight() / 2) - lineHeight(firstLine) / 2 + baselinePosition(firstLine);
+ else if (va == TEXT_BOTTOM) {
+ vpos += f.descent();
+ if (!isReplaced()) // lineHeight - baselinePosition is always 0 for replaced elements, so don't bother wasting time in that case.
+ vpos -= (lineHeight(firstLine) - baselinePosition(firstLine));
+ } else if (va == BASELINE_MIDDLE)
+ vpos += -lineHeight(firstLine) / 2 + baselinePosition(firstLine);
+ else if (va == LENGTH)
+ vpos -= style()->verticalAlignLength().calcValue(lineHeight(firstLine));
+ }
+
+ return vpos;
+}
+
+bool RenderBoxModelObject::paintNinePieceImage(GraphicsContext* graphicsContext, int tx, int ty, int w, int h, const RenderStyle* style,
+ const NinePieceImage& ninePieceImage, CompositeOperator op)
+{
+ StyleImage* styleImage = ninePieceImage.image();
+ if (!styleImage)
+ return false;
+
+ if (!styleImage->isLoaded())
+ return true; // Never paint a nine-piece image incrementally, but don't paint the fallback borders either.
+
+ if (!styleImage->canRender(style->effectiveZoom()))
+ return false;
+
+ // FIXME: border-image is broken with full page zooming when tiling has to happen, since the tiling function
+ // doesn't have any understanding of the zoom that is in effect on the tile.
+ styleImage->setImageContainerSize(IntSize(w, h));
+ IntSize imageSize = styleImage->imageSize(this, 1.0f);
+ int imageWidth = imageSize.width();
+ int imageHeight = imageSize.height();
+
+ int topSlice = min(imageHeight, ninePieceImage.m_slices.top().calcValue(imageHeight));
+ int bottomSlice = min(imageHeight, ninePieceImage.m_slices.bottom().calcValue(imageHeight));
+ int leftSlice = min(imageWidth, ninePieceImage.m_slices.left().calcValue(imageWidth));
+ int rightSlice = min(imageWidth, ninePieceImage.m_slices.right().calcValue(imageWidth));
+
+ ENinePieceImageRule hRule = ninePieceImage.horizontalRule();
+ ENinePieceImageRule vRule = ninePieceImage.verticalRule();
+
+ bool fitToBorder = style->borderImage() == ninePieceImage;
+
+ int leftWidth = fitToBorder ? style->borderLeftWidth() : leftSlice;
+ int topWidth = fitToBorder ? style->borderTopWidth() : topSlice;
+ int rightWidth = fitToBorder ? style->borderRightWidth() : rightSlice;
+ int bottomWidth = fitToBorder ? style->borderBottomWidth() : bottomSlice;
+
+ bool drawLeft = leftSlice > 0 && leftWidth > 0;
+ bool drawTop = topSlice > 0 && topWidth > 0;
+ bool drawRight = rightSlice > 0 && rightWidth > 0;
+ bool drawBottom = bottomSlice > 0 && bottomWidth > 0;
+ bool drawMiddle = (imageWidth - leftSlice - rightSlice) > 0 && (w - leftWidth - rightWidth) > 0 &&
+ (imageHeight - topSlice - bottomSlice) > 0 && (h - topWidth - bottomWidth) > 0;
+
+ Image* image = styleImage->image(this, imageSize);
+
+ if (drawLeft) {
+ // Paint the top and bottom left corners.
+
+ // The top left corner rect is (tx, ty, leftWidth, topWidth)
+ // The rect to use from within the image is obtained from our slice, and is (0, 0, leftSlice, topSlice)
+ if (drawTop)
+ graphicsContext->drawImage(image, IntRect(tx, ty, leftWidth, topWidth),
+ IntRect(0, 0, leftSlice, topSlice), op);
+
+ // The bottom left corner rect is (tx, ty + h - bottomWidth, leftWidth, bottomWidth)
+ // The rect to use from within the image is (0, imageHeight - bottomSlice, leftSlice, botomSlice)
+ if (drawBottom)
+ graphicsContext->drawImage(image, IntRect(tx, ty + h - bottomWidth, leftWidth, bottomWidth),
+ IntRect(0, imageHeight - bottomSlice, leftSlice, bottomSlice), op);
+
+ // Paint the left edge.
+ // Have to scale and tile into the border rect.
+ graphicsContext->drawTiledImage(image, IntRect(tx, ty + topWidth, leftWidth,
+ h - topWidth - bottomWidth),
+ IntRect(0, topSlice, leftSlice, imageHeight - topSlice - bottomSlice),
+ Image::StretchTile, (Image::TileRule)vRule, op);
+ }
+
+ if (drawRight) {
+ // Paint the top and bottom right corners
+ // The top right corner rect is (tx + w - rightWidth, ty, rightWidth, topWidth)
+ // The rect to use from within the image is obtained from our slice, and is (imageWidth - rightSlice, 0, rightSlice, topSlice)
+ if (drawTop)
+ graphicsContext->drawImage(image, IntRect(tx + w - rightWidth, ty, rightWidth, topWidth),
+ IntRect(imageWidth - rightSlice, 0, rightSlice, topSlice), op);
+
+ // The bottom right corner rect is (tx + w - rightWidth, ty + h - bottomWidth, rightWidth, bottomWidth)
+ // The rect to use from within the image is (imageWidth - rightSlice, imageHeight - bottomSlice, rightSlice, bottomSlice)
+ if (drawBottom)
+ graphicsContext->drawImage(image, IntRect(tx + w - rightWidth, ty + h - bottomWidth, rightWidth, bottomWidth),
+ IntRect(imageWidth - rightSlice, imageHeight - bottomSlice, rightSlice, bottomSlice), op);
+
+ // Paint the right edge.
+ graphicsContext->drawTiledImage(image, IntRect(tx + w - rightWidth, ty + topWidth, rightWidth,
+ h - topWidth - bottomWidth),
+ IntRect(imageWidth - rightSlice, topSlice, rightSlice, imageHeight - topSlice - bottomSlice),
+ Image::StretchTile, (Image::TileRule)vRule, op);
+ }
+
+ // Paint the top edge.
+ if (drawTop)
+ graphicsContext->drawTiledImage(image, IntRect(tx + leftWidth, ty, w - leftWidth - rightWidth, topWidth),
+ IntRect(leftSlice, 0, imageWidth - rightSlice - leftSlice, topSlice),
+ (Image::TileRule)hRule, Image::StretchTile, op);
+
+ // Paint the bottom edge.
+ if (drawBottom)
+ graphicsContext->drawTiledImage(image, IntRect(tx + leftWidth, ty + h - bottomWidth,
+ w - leftWidth - rightWidth, bottomWidth),
+ IntRect(leftSlice, imageHeight - bottomSlice, imageWidth - rightSlice - leftSlice, bottomSlice),
+ (Image::TileRule)hRule, Image::StretchTile, op);
+
+ // Paint the middle.
+ if (drawMiddle)
+ graphicsContext->drawTiledImage(image, IntRect(tx + leftWidth, ty + topWidth, w - leftWidth - rightWidth,
+ h - topWidth - bottomWidth),
+ IntRect(leftSlice, topSlice, imageWidth - rightSlice - leftSlice, imageHeight - topSlice - bottomSlice),
+ (Image::TileRule)hRule, (Image::TileRule)vRule, op);
+
+ return true;
+}
+
+void RenderBoxModelObject::paintBorder(GraphicsContext* graphicsContext, int tx, int ty, int w, int h,
+ const RenderStyle* style, bool begin, bool end)
+{
+ if (paintNinePieceImage(graphicsContext, tx, ty, w, h, style, style->borderImage()))
+ return;
+
+ const Color& topColor = style->borderTopColor();
+ const Color& bottomColor = style->borderBottomColor();
+ const Color& leftColor = style->borderLeftColor();
+ const Color& rightColor = style->borderRightColor();
+
+ bool topTransparent = style->borderTopIsTransparent();
+ bool bottomTransparent = style->borderBottomIsTransparent();
+ bool rightTransparent = style->borderRightIsTransparent();
+ bool leftTransparent = style->borderLeftIsTransparent();
+
+ EBorderStyle topStyle = style->borderTopStyle();
+ EBorderStyle bottomStyle = style->borderBottomStyle();
+ EBorderStyle leftStyle = style->borderLeftStyle();
+ EBorderStyle rightStyle = style->borderRightStyle();
+
+ bool renderTop = topStyle > BHIDDEN && !topTransparent;
+ bool renderLeft = leftStyle > BHIDDEN && begin && !leftTransparent;
+ bool renderRight = rightStyle > BHIDDEN && end && !rightTransparent;
+ bool renderBottom = bottomStyle > BHIDDEN && !bottomTransparent;
+
+ bool renderRadii = false;
+ IntSize topLeft, topRight, bottomLeft, bottomRight;
+
+ if (style->hasBorderRadius()) {
+ IntRect borderRect = IntRect(tx, ty, w, h);
+
+ IntSize topLeftRadius, topRightRadius, bottomLeftRadius, bottomRightRadius;
+ style->getBorderRadiiForRect(borderRect, topLeftRadius, topRightRadius, bottomLeftRadius, bottomRightRadius);
+
+ if (begin) {
+ topLeft = topLeftRadius;
+ bottomLeft = bottomLeftRadius;
+ }
+ if (end) {
+ topRight = topRightRadius;
+ bottomRight = bottomRightRadius;
+ }
+
+ renderRadii = true;
+
+ // Clip to the rounded rectangle.
+ graphicsContext->save();
+ graphicsContext->addRoundedRectClip(borderRect, topLeft, topRight, bottomLeft, bottomRight);
+ }
+
+ int firstAngleStart, secondAngleStart, firstAngleSpan, secondAngleSpan;
+ float thickness;
+ 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);
+
+ if (renderTop) {
+ bool ignore_left = (renderRadii && topLeft.width() > 0) ||
+ (topColor == leftColor && topTransparent == leftTransparent && topStyle >= OUTSET &&
+ (leftStyle == DOTTED || leftStyle == DASHED || leftStyle == SOLID || leftStyle == OUTSET));
+
+ bool ignore_right = (renderRadii && topRight.width() > 0) ||
+ (topColor == rightColor && topTransparent == rightTransparent && topStyle >= OUTSET &&
+ (rightStyle == DOTTED || rightStyle == DASHED || rightStyle == SOLID || rightStyle == INSET));
+
+ int x = tx;
+ int x2 = tx + w;
+ if (renderRadii) {
+ x += topLeft.width();
+ x2 -= topRight.width();
+ }
+
+ drawLineForBoxSide(graphicsContext, x, ty, x2, ty + style->borderTopWidth(), BSTop, topColor, style->color(), topStyle,
+ ignore_left ? 0 : style->borderLeftWidth(), ignore_right ? 0 : style->borderRightWidth());
+
+ if (renderRadii) {
+ int leftY = ty;
+
+ // We make the arc double thick and let the clip rect take care of clipping the extra off.
+ // We're doing this because it doesn't seem possible to match the curve of the clip exactly
+ // with the arc-drawing function.
+ thickness = style->borderTopWidth() * 2;
+
+ if (topLeft.width()) {
+ int leftX = tx;
+ // The inner clip clips inside the arc. This is especially important for 1px borders.
+ bool applyLeftInnerClip = (style->borderLeftWidth() < topLeft.width())
+ && (style->borderTopWidth() < topLeft.height())
+ && (topStyle != DOUBLE || style->borderTopWidth() > 6);
+ if (applyLeftInnerClip) {
+ graphicsContext->save();
+ graphicsContext->addInnerRoundedRectClip(IntRect(leftX, leftY, topLeft.width() * 2, topLeft.height() * 2),
+ style->borderTopWidth());
+ }
+
+ firstAngleStart = 90;
+ firstAngleSpan = upperLeftBorderStylesMatch ? 90 : 45;
+
+ // Draw upper left arc
+ drawArcForBoxSide(graphicsContext, leftX, leftY, thickness, topLeft, firstAngleStart, firstAngleSpan,
+ BSTop, topColor, style->color(), topStyle, true);
+ if (applyLeftInnerClip)
+ graphicsContext->restore();
+ }
+
+ if (topRight.width()) {
+ int rightX = tx + w - topRight.width() * 2;
+ bool applyRightInnerClip = (style->borderRightWidth() < topRight.width())
+ && (style->borderTopWidth() < topRight.height())
+ && (topStyle != DOUBLE || style->borderTopWidth() > 6);
+ if (applyRightInnerClip) {
+ graphicsContext->save();
+ graphicsContext->addInnerRoundedRectClip(IntRect(rightX, leftY, topRight.width() * 2, topRight.height() * 2),
+ style->borderTopWidth());
+ }
+
+ if (upperRightBorderStylesMatch) {
+ secondAngleStart = 0;
+ secondAngleSpan = 90;
+ } else {
+ secondAngleStart = 45;
+ secondAngleSpan = 45;
+ }
+
+ // Draw upper right arc
+ drawArcForBoxSide(graphicsContext, rightX, leftY, thickness, topRight, secondAngleStart, secondAngleSpan,
+ BSTop, topColor, style->color(), topStyle, false);
+ if (applyRightInnerClip)
+ graphicsContext->restore();
+ }
+ }
+ }
+
+ if (renderBottom) {
+ bool ignore_left = (renderRadii && bottomLeft.width() > 0) ||
+ (bottomColor == leftColor && bottomTransparent == leftTransparent && bottomStyle >= OUTSET &&
+ (leftStyle == DOTTED || leftStyle == DASHED || leftStyle == SOLID || leftStyle == OUTSET));
+
+ bool ignore_right = (renderRadii && bottomRight.width() > 0) ||
+ (bottomColor == rightColor && bottomTransparent == rightTransparent && bottomStyle >= OUTSET &&
+ (rightStyle == DOTTED || rightStyle == DASHED || rightStyle == SOLID || rightStyle == INSET));
+
+ int x = tx;
+ int x2 = tx + w;
+ if (renderRadii) {
+ x += bottomLeft.width();
+ x2 -= bottomRight.width();
+ }
+
+ drawLineForBoxSide(graphicsContext, x, ty + h - style->borderBottomWidth(), x2, ty + h, BSBottom, bottomColor, style->color(), bottomStyle,
+ ignore_left ? 0 : style->borderLeftWidth(), ignore_right ? 0 : style->borderRightWidth());
+
+ if (renderRadii) {
+ thickness = style->borderBottomWidth() * 2;
+
+ if (bottomLeft.width()) {
+ int leftX = tx;
+ int leftY = ty + h - bottomLeft.height() * 2;
+ bool applyLeftInnerClip = (style->borderLeftWidth() < bottomLeft.width())
+ && (style->borderBottomWidth() < bottomLeft.height())
+ && (bottomStyle != DOUBLE || style->borderBottomWidth() > 6);
+ if (applyLeftInnerClip) {
+ graphicsContext->save();
+ graphicsContext->addInnerRoundedRectClip(IntRect(leftX, leftY, bottomLeft.width() * 2, bottomLeft.height() * 2),
+ style->borderBottomWidth());
+ }
+
+ if (lowerLeftBorderStylesMatch) {
+ firstAngleStart = 180;
+ firstAngleSpan = 90;
+ } else {
+ firstAngleStart = 225;
+ firstAngleSpan = 45;
+ }
+
+ // Draw lower left arc
+ drawArcForBoxSide(graphicsContext, leftX, leftY, thickness, bottomLeft, firstAngleStart, firstAngleSpan,
+ BSBottom, bottomColor, style->color(), bottomStyle, true);
+ if (applyLeftInnerClip)
+ graphicsContext->restore();
+ }
+
+ if (bottomRight.width()) {
+ int rightY = ty + h - bottomRight.height() * 2;
+ int rightX = tx + w - bottomRight.width() * 2;
+ bool applyRightInnerClip = (style->borderRightWidth() < bottomRight.width())
+ && (style->borderBottomWidth() < bottomRight.height())
+ && (bottomStyle != DOUBLE || style->borderBottomWidth() > 6);
+ if (applyRightInnerClip) {
+ graphicsContext->save();
+ graphicsContext->addInnerRoundedRectClip(IntRect(rightX, rightY, bottomRight.width() * 2, bottomRight.height() * 2),
+ style->borderBottomWidth());
+ }
+
+ secondAngleStart = 270;
+ secondAngleSpan = lowerRightBorderStylesMatch ? 90 : 45;
+
+ // Draw lower right arc
+ drawArcForBoxSide(graphicsContext, rightX, rightY, thickness, bottomRight, secondAngleStart, secondAngleSpan,
+ BSBottom, bottomColor, style->color(), bottomStyle, false);
+ if (applyRightInnerClip)
+ graphicsContext->restore();
+ }
+ }
+ }
+
+ if (renderLeft) {
+ bool ignore_top = (renderRadii && topLeft.height() > 0) ||
+ (topColor == leftColor && topTransparent == leftTransparent && leftStyle >= OUTSET &&
+ (topStyle == DOTTED || topStyle == DASHED || topStyle == SOLID || topStyle == OUTSET));
+
+ bool ignore_bottom = (renderRadii && bottomLeft.height() > 0) ||
+ (bottomColor == leftColor && bottomTransparent == leftTransparent && leftStyle >= OUTSET &&
+ (bottomStyle == DOTTED || bottomStyle == DASHED || bottomStyle == SOLID || bottomStyle == INSET));
+
+ int y = ty;
+ int y2 = ty + h;
+ if (renderRadii) {
+ y += topLeft.height();
+ y2 -= bottomLeft.height();
+ }
+
+ drawLineForBoxSide(graphicsContext, tx, y, tx + style->borderLeftWidth(), y2, BSLeft, leftColor, style->color(), leftStyle,
+ ignore_top ? 0 : style->borderTopWidth(), ignore_bottom ? 0 : style->borderBottomWidth());
+
+ if (renderRadii && (!upperLeftBorderStylesMatch || !lowerLeftBorderStylesMatch)) {
+ int topX = tx;
+ thickness = style->borderLeftWidth() * 2;
+
+ if (!upperLeftBorderStylesMatch && topLeft.width()) {
+ int topY = ty;
+ bool applyTopInnerClip = (style->borderLeftWidth() < topLeft.width())
+ && (style->borderTopWidth() < topLeft.height())
+ && (leftStyle != DOUBLE || style->borderLeftWidth() > 6);
+ if (applyTopInnerClip) {
+ graphicsContext->save();
+ graphicsContext->addInnerRoundedRectClip(IntRect(topX, topY, topLeft.width() * 2, topLeft.height() * 2),
+ style->borderLeftWidth());
+ }
+
+ firstAngleStart = 135;
+ firstAngleSpan = 45;
+
+ // Draw top left arc
+ drawArcForBoxSide(graphicsContext, topX, topY, thickness, topLeft, firstAngleStart, firstAngleSpan,
+ BSLeft, leftColor, style->color(), leftStyle, true);
+ if (applyTopInnerClip)
+ graphicsContext->restore();
+ }
+
+ if (!lowerLeftBorderStylesMatch && bottomLeft.width()) {
+ int bottomY = ty + h - bottomLeft.height() * 2;
+ bool applyBottomInnerClip = (style->borderLeftWidth() < bottomLeft.width())
+ && (style->borderBottomWidth() < bottomLeft.height())
+ && (leftStyle != DOUBLE || style->borderLeftWidth() > 6);
+ if (applyBottomInnerClip) {
+ graphicsContext->save();
+ graphicsContext->addInnerRoundedRectClip(IntRect(topX, bottomY, bottomLeft.width() * 2, bottomLeft.height() * 2),
+ style->borderLeftWidth());
+ }
+
+ secondAngleStart = 180;
+ secondAngleSpan = 45;
+
+ // Draw bottom left arc
+ drawArcForBoxSide(graphicsContext, topX, bottomY, thickness, bottomLeft, secondAngleStart, secondAngleSpan,
+ BSLeft, leftColor, style->color(), leftStyle, false);
+ if (applyBottomInnerClip)
+ graphicsContext->restore();
+ }
+ }
+ }
+
+ if (renderRight) {
+ bool ignore_top = (renderRadii && topRight.height() > 0) ||
+ ((topColor == rightColor) && (topTransparent == rightTransparent) &&
+ (rightStyle >= DOTTED || rightStyle == INSET) &&
+ (topStyle == DOTTED || topStyle == DASHED || topStyle == SOLID || topStyle == OUTSET));
+
+ bool ignore_bottom = (renderRadii && bottomRight.height() > 0) ||
+ ((bottomColor == rightColor) && (bottomTransparent == rightTransparent) &&
+ (rightStyle >= DOTTED || rightStyle == INSET) &&
+ (bottomStyle == DOTTED || bottomStyle == DASHED || bottomStyle == SOLID || bottomStyle == INSET));
+
+ int y = ty;
+ int y2 = ty + h;
+ if (renderRadii) {
+ y += topRight.height();
+ y2 -= bottomRight.height();
+ }
+
+ drawLineForBoxSide(graphicsContext, tx + w - style->borderRightWidth(), y, tx + w, y2, BSRight, rightColor, style->color(), rightStyle,
+ ignore_top ? 0 : style->borderTopWidth(), ignore_bottom ? 0 : style->borderBottomWidth());
+
+ if (renderRadii && (!upperRightBorderStylesMatch || !lowerRightBorderStylesMatch)) {
+ thickness = style->borderRightWidth() * 2;
+
+ if (!upperRightBorderStylesMatch && topRight.width()) {
+ int topX = tx + w - topRight.width() * 2;
+ int topY = ty;
+ bool applyTopInnerClip = (style->borderRightWidth() < topRight.width())
+ && (style->borderTopWidth() < topRight.height())
+ && (rightStyle != DOUBLE || style->borderRightWidth() > 6);
+ if (applyTopInnerClip) {
+ graphicsContext->save();
+ graphicsContext->addInnerRoundedRectClip(IntRect(topX, topY, topRight.width() * 2, topRight.height() * 2),
+ style->borderRightWidth());
+ }
+
+ firstAngleStart = 0;
+ firstAngleSpan = 45;
+
+ // Draw top right arc
+ drawArcForBoxSide(graphicsContext, topX, topY, thickness, topRight, firstAngleStart, firstAngleSpan,
+ BSRight, rightColor, style->color(), rightStyle, true);
+ if (applyTopInnerClip)
+ graphicsContext->restore();
+ }
+
+ if (!lowerRightBorderStylesMatch && bottomRight.width()) {
+ int bottomX = tx + w - bottomRight.width() * 2;
+ int bottomY = ty + h - bottomRight.height() * 2;
+ bool applyBottomInnerClip = (style->borderRightWidth() < bottomRight.width())
+ && (style->borderBottomWidth() < bottomRight.height())
+ && (rightStyle != DOUBLE || style->borderRightWidth() > 6);
+ if (applyBottomInnerClip) {
+ graphicsContext->save();
+ graphicsContext->addInnerRoundedRectClip(IntRect(bottomX, bottomY, bottomRight.width() * 2, bottomRight.height() * 2),
+ style->borderRightWidth());
+ }
+
+ secondAngleStart = 315;
+ secondAngleSpan = 45;
+
+ // Draw bottom right arc
+ drawArcForBoxSide(graphicsContext, bottomX, bottomY, thickness, bottomRight, secondAngleStart, secondAngleSpan,
+ BSRight, rightColor, style->color(), rightStyle, false);
+ if (applyBottomInnerClip)
+ graphicsContext->restore();
+ }
+ }
+ }
+
+ if (renderRadii)
+ graphicsContext->restore();
+}
+
+void RenderBoxModelObject::paintBoxShadow(GraphicsContext* context, int tx, int ty, int w, int h, const RenderStyle* s, bool begin, bool end)
+{
+ // FIXME: Deal with border-image. Would be great to use border-image as a mask.
+
+ IntRect rect(tx, ty, w, h);
+ bool hasBorderRadius = s->hasBorderRadius();
+ bool hasOpaqueBackground = s->backgroundColor().isValid() && s->backgroundColor().alpha() == 255;
+ for (ShadowData* shadow = s->boxShadow(); shadow; shadow = shadow->next) {
+ context->save();
+
+ IntSize shadowOffset(shadow->x, shadow->y);
+ int shadowBlur = shadow->blur;
+ IntRect fillRect(rect);
+
+ if (hasBorderRadius) {
+ IntRect shadowRect(rect);
+ shadowRect.inflate(shadowBlur);
+ shadowRect.move(shadowOffset);
+ context->clip(shadowRect);
+
+ // Move the fill just outside the clip, adding 1 pixel separation so that the fill does not
+ // bleed in (due to antialiasing) if the context is transformed.
+ IntSize extraOffset(w + max(0, shadowOffset.width()) + shadowBlur + 1, 0);
+ shadowOffset -= extraOffset;
+ fillRect.move(extraOffset);
+ }
+
+ context->setShadow(shadowOffset, shadowBlur, shadow->color);
+ if (hasBorderRadius) {
+ IntSize topLeftRadius, topRightRadius, bottomLeftRadius, bottomRightRadius;
+ s->getBorderRadiiForRect(rect, topLeftRadius, topRightRadius, bottomLeftRadius, bottomRightRadius);
+
+ IntSize topLeft = begin ? topLeftRadius : IntSize();
+ IntSize topRight = end ? topRightRadius : IntSize();
+ IntSize bottomLeft = begin ? bottomLeftRadius : IntSize();
+ IntSize bottomRight = end ? bottomRightRadius : IntSize();
+
+ if (!hasOpaqueBackground)
+ context->clipOutRoundedRect(rect, topLeft, topRight, bottomLeft, bottomRight);
+ context->fillRoundedRect(fillRect, topLeft, topRight, bottomLeft, bottomRight, Color::black);
+ } else {
+ if (!hasOpaqueBackground)
+ context->clipOut(rect);
+ context->fillRect(fillRect, Color::black);
+ }
+ context->restore();
+ }
+}
+
+int RenderBoxModelObject::containingBlockWidthForContent() const
+{
+ return containingBlock()->availableWidth();
+}
+
+} // namespace WebCore
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderBoxModelObject.h b/src/3rdparty/webkit/WebCore/rendering/RenderBoxModelObject.h
new file mode 100644
index 0000000..9feaf2f
--- /dev/null
+++ b/src/3rdparty/webkit/WebCore/rendering/RenderBoxModelObject.h
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ * (C) 1999 Antti Koivisto (koivisto@kde.org)
+ * Copyright (C) 2003, 2006, 2007, 2009 Apple Inc. 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
+ * 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 RenderBoxModelObject_h
+#define RenderBoxModelObject_h
+
+#include "RenderObject.h"
+
+namespace WebCore {
+
+// Values for vertical alignment.
+const int PositionTop = -0x7fffffff;
+const int PositionBottom = 0x7fffffff;
+const int PositionUndefined = 0x80000000;
+
+// 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
+
+class RenderBoxModelObject : public RenderObject {
+public:
+ RenderBoxModelObject(Node*);
+ virtual ~RenderBoxModelObject();
+
+ virtual void destroy();
+
+ int relativePositionOffsetX() const;
+ int relativePositionOffsetY() const;
+ IntSize relativePositionOffset() const { return IntSize(relativePositionOffsetX(), relativePositionOffsetY()); }
+
+ // IE extensions. Used to calculate offsetWidth/Height. Overridden by inlines (RenderFlow)
+ // to return the remaining width on a given line (and the height of a single line).
+ virtual int offsetLeft() const;
+ virtual int offsetTop() const;
+ virtual int offsetWidth() const = 0;
+ virtual int offsetHeight() const = 0;
+
+ virtual void styleWillChange(StyleDifference, const RenderStyle* newStyle);
+ virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
+ virtual void updateBoxModelInfoFromStyle();
+
+ bool hasSelfPaintingLayer() const;
+ RenderLayer* layer() const { return m_layer; }
+ virtual bool requiresLayer() const { return isRoot() || isPositioned() || isRelPositioned() || isTransparent() || hasOverflowClip() || hasTransform() || hasMask() || hasReflection(); }
+
+ // This will work on inlines to return the bounding box of all of the lines' border boxes.
+ virtual IntRect borderBoundingBox() const = 0;
+
+ // Virtual since table cells override
+ virtual int paddingTop(bool includeIntrinsicPadding = true) const;
+ virtual int paddingBottom(bool includeIntrinsicPadding = true) const;
+ virtual int paddingLeft(bool includeIntrinsicPadding = true) const;
+ virtual int paddingRight(bool includeIntrinsicPadding = true) const;
+
+ virtual int borderTop() const { return style()->borderTopWidth(); }
+ virtual int borderBottom() const { return style()->borderBottomWidth(); }
+ virtual int borderLeft() const { return style()->borderLeftWidth(); }
+ virtual int borderRight() const { return style()->borderRightWidth(); }
+
+ virtual int marginTop() const = 0;
+ virtual int marginBottom() const = 0;
+ virtual int marginLeft() const = 0;
+ virtual int marginRight() const = 0;
+
+ bool hasHorizontalBordersPaddingOrMargin() const { return hasHorizontalBordersOrPadding() || marginLeft() != 0 || marginRight() != 0; }
+ bool hasHorizontalBordersOrPadding() const { return borderLeft() != 0 || borderRight() != 0 || paddingLeft() != 0 || paddingRight() != 0; }
+
+ virtual int containingBlockWidthForContent() const;
+
+ virtual void childBecameNonInline(RenderObject* /*child*/) { }
+
+ void paintBorder(GraphicsContext*, int tx, int ty, int w, int h, const RenderStyle*, bool begin = true, bool end = 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*, bool begin = true, bool end = true);
+ void paintFillLayerExtended(const PaintInfo&, const Color&, const FillLayer*, int tx, int ty, int width, int height, InlineFlowBox* = 0, CompositeOperator = CompositeSourceOver);
+
+ // The difference between this inline's baseline position and the line's baseline position.
+ int verticalPosition(bool firstLine) const;
+
+ // Called by RenderObject::destroy() (and RenderWidget::destroy()) and is the only way layers should ever be destroyed
+ void destroyLayer();
+
+protected:
+ void calculateBackgroundImageGeometry(const FillLayer*, int tx, int ty, int w, int h, IntRect& destRect, IntPoint& phase, IntSize& tileSize);
+ IntSize calculateBackgroundSize(const FillLayer*, int scaledWidth, int scaledHeight) const;
+
+private:
+ virtual bool isBoxModelObject() const { return true; }
+ friend class RenderView;
+
+ RenderLayer* m_layer;
+
+ // Used to store state between styleWillChange and styleDidChange
+ static bool s_wasFloating;
+ static bool s_hadLayer;
+ static bool s_layerWasSelfPainting;
+};
+
+inline RenderBoxModelObject* toRenderBoxModelObject(RenderObject* o)
+{
+ ASSERT(!o || o->isBoxModelObject());
+ return static_cast<RenderBoxModelObject*>(o);
+}
+
+inline const RenderBoxModelObject* toRenderBoxModelObject(const RenderObject* o)
+{
+ ASSERT(!o || o->isBoxModelObject());
+ return static_cast<const RenderBoxModelObject*>(o);
+}
+
+// This will catch anyone doing an unnecessary cast.
+void toRenderBoxModelObject(const RenderBoxModelObject*);
+
+} // namespace WebCore
+
+#endif // RenderBoxModelObject_h
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderButton.cpp b/src/3rdparty/webkit/WebCore/rendering/RenderButton.cpp
index 10e21c3..b266f42 100644
--- a/src/3rdparty/webkit/WebCore/rendering/RenderButton.cpp
+++ b/src/3rdparty/webkit/WebCore/rendering/RenderButton.cpp
@@ -69,7 +69,7 @@ void RenderButton::removeChild(RenderObject* oldChild)
m_inner->removeChild(oldChild);
}
-void RenderButton::styleWillChange(RenderStyle::Diff diff, const RenderStyle* newStyle)
+void RenderButton::styleWillChange(StyleDifference diff, const RenderStyle* newStyle)
{
if (m_inner) {
// RenderBlock::setStyle is going to apply a new style to the inner block, which
@@ -81,7 +81,7 @@ void RenderButton::styleWillChange(RenderStyle::Diff diff, const RenderStyle* ne
RenderBlock::styleWillChange(diff, newStyle);
}
-void RenderButton::styleDidChange(RenderStyle::Diff diff, const RenderStyle* oldStyle)
+void RenderButton::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
{
RenderBlock::styleDidChange(diff, oldStyle);
@@ -108,23 +108,26 @@ void RenderButton::setupInnerStyle(RenderStyle* innerStyle)
// RenderBlock::createAnonymousBlock creates a new RenderStyle, so this is
// safe to modify.
innerStyle->setBoxFlex(1.0f);
- if (style()->hasAppearance())
- theme()->adjustButtonInnerStyle(innerStyle);
+
+ innerStyle->setPaddingTop(Length(theme()->buttonInternalPaddingTop(), Fixed));
+ innerStyle->setPaddingRight(Length(theme()->buttonInternalPaddingRight(), Fixed));
+ innerStyle->setPaddingBottom(Length(theme()->buttonInternalPaddingBottom(), Fixed));
+ innerStyle->setPaddingLeft(Length(theme()->buttonInternalPaddingLeft(), Fixed));
}
void RenderButton::updateFromElement()
{
// If we're an input element, we may need to change our button text.
- if (element()->hasTagName(inputTag)) {
- HTMLInputElement* input = static_cast<HTMLInputElement*>(element());
+ if (node()->hasTagName(inputTag)) {
+ HTMLInputElement* input = static_cast<HTMLInputElement*>(node());
String value = input->valueWithDefault();
setText(value);
}
#if ENABLE(WML)
- else if (element()->hasTagName(WMLNames::doTag)) {
- WMLDoElement* doElement = static_cast<WMLDoElement*>(element());
+ else if (node()->hasTagName(WMLNames::doTag)) {
+ WMLDoElement* doElement = static_cast<WMLDoElement*>(node());
String value = doElement->label();
if (value.isEmpty())
@@ -140,7 +143,7 @@ bool RenderButton::canHaveChildren() const
// Input elements can't have children, but button elements can. We'll
// write the code assuming any other button types that might emerge in the future
// can also have children.
- return !element()->hasTagName(inputTag);
+ return !node()->hasTagName(inputTag);
}
void RenderButton::setText(const String& str)
@@ -161,22 +164,29 @@ void RenderButton::setText(const String& str)
}
}
-void RenderButton::updateBeforeAfterContent(RenderStyle::PseudoId type)
+void RenderButton::updateBeforeAfterContent(PseudoId type)
{
if (m_inner)
- m_inner->updateBeforeAfterContentForContainer(type, this);
+ m_inner->children()->updateBeforeAfterContent(m_inner, type, this);
else
- updateBeforeAfterContentForContainer(type, this);
+ children()->updateBeforeAfterContent(this, type);
}
IntRect RenderButton::controlClipRect(int tx, int ty) const
{
// Clip to the padding box to at least give content the extra padding space.
- return IntRect(tx + borderLeft(), ty + borderTop(), m_width - borderLeft() - borderRight(), m_height - borderTop() - borderBottom());
+ return IntRect(tx + borderLeft(), ty + borderTop(), width() - borderLeft() - borderRight(), height() - borderTop() - borderBottom());
}
void RenderButton::timerFired(Timer<RenderButton>*)
{
+ // FIXME Bug 25110: Ideally we would stop our timer when our Document
+ // enters the page cache. But we currently have no way of being notified
+ // when that happens, so we'll just ignore the timer firing as long as
+ // we're in the cache.
+ if (document()->inPageCache())
+ return;
+
repaint();
}
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderButton.h b/src/3rdparty/webkit/WebCore/rendering/RenderButton.h
index 24e4767..89f7cf8 100644
--- a/src/3rdparty/webkit/WebCore/rendering/RenderButton.h
+++ b/src/3rdparty/webkit/WebCore/rendering/RenderButton.h
@@ -39,6 +39,7 @@ public:
RenderButton(Node*);
virtual const char* renderName() const { return "RenderButton"; }
+ virtual bool isRenderButton() const { return true; }
virtual void addChild(RenderObject* newChild, RenderObject *beforeChild = 0);
virtual void removeChild(RenderObject*);
@@ -48,7 +49,7 @@ public:
void setupInnerStyle(RenderStyle*);
virtual void updateFromElement();
- virtual void updateBeforeAfterContent(RenderStyle::PseudoId);
+ virtual void updateBeforeAfterContent(PseudoId);
virtual bool hasControlClip() const { return true; }
virtual IntRect controlClipRect(int /*tx*/, int /*ty*/) const;
@@ -58,8 +59,8 @@ public:
virtual bool canHaveChildren() const;
protected:
- virtual void styleWillChange(RenderStyle::Diff, const RenderStyle* newStyle);
- virtual void styleDidChange(RenderStyle::Diff, const RenderStyle* oldStyle);
+ virtual void styleWillChange(StyleDifference, const RenderStyle* newStyle);
+ virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
virtual bool hasLineIfEmpty() const { return true; }
@@ -72,6 +73,21 @@ protected:
bool m_default;
};
+inline RenderButton* toRenderButton(RenderObject* o)
+{
+ ASSERT(!o || o->isRenderButton());
+ return static_cast<RenderButton*>(o);
+}
+
+inline const RenderButton* toRenderButton(const RenderObject* o)
+{
+ ASSERT(!o || o->isRenderButton());
+ return static_cast<const RenderButton*>(o);
+}
+
+// This will catch anyone doing an unnecessary cast.
+void toRenderButton(const RenderButton*);
+
} // namespace WebCore
#endif // RenderButton_h
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderContainer.cpp b/src/3rdparty/webkit/WebCore/rendering/RenderContainer.cpp
deleted file mode 100644
index 9f6d737..0000000
--- a/src/3rdparty/webkit/WebCore/rendering/RenderContainer.cpp
+++ /dev/null
@@ -1,701 +0,0 @@
-/**
- * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
- * (C) 1999 Antti Koivisto (koivisto@kde.org)
- * (C) 2000 Dirk Mueller (mueller@kde.org)
- * (C) 2004 Allan Sandfeld Jensen (kde@carewolf.com)
- * Copyright (C) 2003, 2004, 2005, 2006, 2007 Apple Inc. All rights reserved.
- * Copyright (C) 2006 Andrew Wellington (proton@wiretapped.net)
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-
-#include "config.h"
-#include "RenderContainer.h"
-
-#include "AXObjectCache.h"
-#include "Document.h"
-#include "RenderCounter.h"
-#include "RenderImageGeneratedContent.h"
-#include "RenderLayer.h"
-#include "RenderListItem.h"
-#include "RenderTable.h"
-#include "RenderTextFragment.h"
-#include "RenderView.h"
-#include "htmlediting.h"
-
-namespace WebCore {
-
-RenderContainer::RenderContainer(Node* node)
- : RenderBox(node)
- , m_firstChild(0)
- , m_lastChild(0)
-{
-}
-
-RenderContainer::~RenderContainer()
-{
-}
-
-void RenderContainer::destroy()
-{
- destroyLeftoverChildren();
- RenderBox::destroy();
-}
-
-void RenderContainer::destroyLeftoverChildren()
-{
- while (m_firstChild) {
- if (m_firstChild->isListMarker() || (m_firstChild->style()->styleType() == RenderStyle::FIRST_LETTER && !m_firstChild->isText()))
- m_firstChild->remove(); // List markers are owned by their enclosing list and so don't get destroyed by this container. Similarly, first letters are destroyed by their remaining text fragment.
- else {
- // Destroy any anonymous children remaining in the render tree, as well as implicit (shadow) DOM elements like those used in the engine-based text fields.
- if (m_firstChild->element())
- m_firstChild->element()->setRenderer(0);
- m_firstChild->destroy();
- }
- }
-}
-
-bool RenderContainer::canHaveChildren() const
-{
- return true;
-}
-
-static void updateListMarkerNumbers(RenderObject* child)
-{
- for (RenderObject* r = child; r; r = r->nextSibling())
- if (r->isListItem())
- static_cast<RenderListItem*>(r)->updateValue();
-}
-
-void RenderContainer::addChild(RenderObject* newChild, RenderObject* beforeChild)
-{
- bool needsTable = false;
-
- if (newChild->isListItem())
- updateListMarkerNumbers(beforeChild ? beforeChild : m_lastChild);
- else if (newChild->isTableCol() && newChild->style()->display() == TABLE_COLUMN_GROUP)
- needsTable = !isTable();
- else if (newChild->isRenderBlock() && newChild->style()->display() == TABLE_CAPTION)
- needsTable = !isTable();
- else if (newChild->isTableSection())
- needsTable = !isTable();
- else if (newChild->isTableRow())
- needsTable = !isTableSection();
- else if (newChild->isTableCell()) {
- needsTable = !isTableRow();
- // I'm not 100% sure this is the best way to fix this, but without this
- // change we recurse infinitely when trying to render the CSS2 test page:
- // http://www.bath.ac.uk/%7Epy8ieh/internet/eviltests/htmlbodyheadrendering2.html.
- // See Radar 2925291.
- if (needsTable && isTableCell() && !m_firstChild && !newChild->isTableCell())
- needsTable = false;
- }
-
- if (needsTable) {
- RenderTable* table;
- RenderObject* afterChild = beforeChild ? beforeChild->previousSibling() : m_lastChild;
- if (afterChild && afterChild->isAnonymous() && afterChild->isTable())
- table = static_cast<RenderTable*>(afterChild);
- else {
- table = new (renderArena()) RenderTable(document() /* is anonymous */);
- RefPtr<RenderStyle> newStyle = RenderStyle::create();
- newStyle->inheritFrom(style());
- newStyle->setDisplay(TABLE);
- table->setStyle(newStyle.release());
- addChild(table, beforeChild);
- }
- table->addChild(newChild);
- } else {
- // just add it...
- insertChildNode(newChild, beforeChild);
- }
-
- if (newChild->isText() && newChild->style()->textTransform() == CAPITALIZE) {
- RefPtr<StringImpl> textToTransform = static_cast<RenderText*>(newChild)->originalText();
- if (textToTransform)
- static_cast<RenderText*>(newChild)->setText(textToTransform.release(), true);
- }
-}
-
-RenderObject* RenderContainer::removeChildNode(RenderObject* oldChild, bool fullRemove)
-{
- ASSERT(oldChild->parent() == this);
-
- // So that we'll get the appropriate dirty bit set (either that a normal flow child got yanked or
- // that a positioned child got yanked). We also repaint, so that the area exposed when the child
- // disappears gets repainted properly.
- if (!documentBeingDestroyed() && fullRemove && oldChild->m_everHadLayout) {
- oldChild->setNeedsLayoutAndPrefWidthsRecalc();
- oldChild->repaint();
- }
-
- // If we have a line box wrapper, delete it.
- oldChild->deleteLineBoxWrapper();
-
- if (!documentBeingDestroyed() && fullRemove) {
- // if we remove visible child from an invisible parent, we don't know the layer visibility any more
- RenderLayer* layer = 0;
- if (m_style->visibility() != VISIBLE && oldChild->style()->visibility() == VISIBLE && !oldChild->hasLayer()) {
- layer = enclosingLayer();
- layer->dirtyVisibleContentStatus();
- }
-
- // Keep our layer hierarchy updated.
- if (oldChild->firstChild() || oldChild->hasLayer()) {
- if (!layer) layer = enclosingLayer();
- oldChild->removeLayers(layer);
- }
-
- // renumber ordered lists
- if (oldChild->isListItem())
- updateListMarkerNumbers(oldChild->nextSibling());
-
- if (oldChild->isPositioned() && childrenInline())
- dirtyLinesFromChangedChild(oldChild);
- }
-
- // If oldChild is the start or end of the selection, then clear the selection to
- // avoid problems of invalid pointers.
- // FIXME: The SelectionController should be responsible for this when it
- // is notified of DOM mutations.
- if (!documentBeingDestroyed() && oldChild->isSelectionBorder())
- view()->clearSelection();
-
- // remove the child
- if (oldChild->previousSibling())
- oldChild->previousSibling()->setNextSibling(oldChild->nextSibling());
- if (oldChild->nextSibling())
- oldChild->nextSibling()->setPreviousSibling(oldChild->previousSibling());
-
- if (m_firstChild == oldChild)
- m_firstChild = oldChild->nextSibling();
- if (m_lastChild == oldChild)
- m_lastChild = oldChild->previousSibling();
-
- oldChild->setPreviousSibling(0);
- oldChild->setNextSibling(0);
- oldChild->setParent(0);
-
- if (AXObjectCache::accessibilityEnabled())
- document()->axObjectCache()->childrenChanged(this);
-
- return oldChild;
-}
-
-void RenderContainer::removeChild(RenderObject* oldChild)
-{
- // We do this here instead of in removeChildNode, since the only extremely low-level uses of remove/appendChildNode
- // cannot affect the positioned object list, and the floating object list is irrelevant (since the list gets cleared on
- // layout anyway).
- oldChild->removeFromObjectLists();
-
- removeChildNode(oldChild);
-}
-
-RenderObject* RenderContainer::beforeAfterContainer(RenderStyle::PseudoId type)
-{
- if (type == RenderStyle::BEFORE) {
- RenderObject* first = this;
- do {
- // Skip list markers.
- first = first->firstChild();
- while (first && first->isListMarker())
- first = first->nextSibling();
- } while (first && first->isAnonymous() && first->style()->styleType() == RenderStyle::NOPSEUDO);
- if (first && first->style()->styleType() != type)
- return 0;
- return first;
- }
- if (type == RenderStyle::AFTER) {
- RenderObject* last = this;
- do {
- last = last->lastChild();
- } while (last && last->isAnonymous() && last->style()->styleType() == RenderStyle::NOPSEUDO && !last->isListMarker());
- if (last && last->style()->styleType() != type)
- return 0;
- return last;
- }
-
- ASSERT_NOT_REACHED();
- return 0;
-}
-
-void RenderContainer::updateBeforeAfterContent(RenderStyle::PseudoId type)
-{
- // If this is an anonymous wrapper, then the parent applies its own pseudo-element style to it.
- if (parent() && parent()->createsAnonymousWrapper())
- return;
- updateBeforeAfterContentForContainer(type, this);
-}
-
-static RenderObject* findBeforeAfterParent(RenderObject* object)
-{
- // Only table parts need to search for the :before or :after parent
- if (!(object->isTable() || object->isTableSection() || object->isTableRow()))
- return object;
-
- RenderObject* beforeAfterParent = object;
- while (beforeAfterParent && !(beforeAfterParent->isText() || beforeAfterParent->isImage()))
- beforeAfterParent = beforeAfterParent->firstChild();
- return beforeAfterParent;
-}
-
-void RenderContainer::updateBeforeAfterContentForContainer(RenderStyle::PseudoId type, RenderContainer* styledObject)
-{
- // In CSS2, before/after pseudo-content cannot nest. Check this first.
- if (style()->styleType() == RenderStyle::BEFORE || style()->styleType() == RenderStyle::AFTER)
- return;
-
- RenderStyle* pseudoElementStyle = styledObject->getCachedPseudoStyle(type);
- RenderObject* child = beforeAfterContainer(type);
-
- // Whether or not we currently have generated content attached.
- bool oldContentPresent = child;
-
- // Whether or not we now want generated content.
- bool newContentWanted = pseudoElementStyle && pseudoElementStyle->display() != NONE;
-
- // For <q><p/></q>, if this object is the inline continuation of the <q>, we only want to generate
- // :after content and not :before content.
- if (newContentWanted && type == RenderStyle::BEFORE && isInlineContinuation())
- newContentWanted = false;
-
- // Similarly, if we're the beginning of a <q>, and there's an inline continuation for our object,
- // then we don't generate the :after content.
- if (newContentWanted && type == RenderStyle::AFTER && isRenderInline() && continuation())
- newContentWanted = false;
-
- // If we don't want generated content any longer, or if we have generated content, but it's no longer
- // identical to the new content data we want to build render objects for, then we nuke all
- // of the old generated content.
- if (!newContentWanted || (oldContentPresent && Node::diff(child->style(), pseudoElementStyle) == Node::Detach)) {
- // Nuke the child.
- if (child && child->style()->styleType() == type) {
- oldContentPresent = false;
- child->destroy();
- child = (type == RenderStyle::BEFORE) ? m_firstChild : m_lastChild;
- }
- }
-
- // If we have no pseudo-element style or if the pseudo-element style's display type is NONE, then we
- // have no generated content and can now return.
- if (!newContentWanted)
- return;
-
- if (isInlineFlow() && !pseudoElementStyle->isDisplayInlineType() && pseudoElementStyle->floating() == FNONE &&
- !(pseudoElementStyle->position() == AbsolutePosition || pseudoElementStyle->position() == FixedPosition))
- // According to the CSS2 spec (the end of section 12.1), the only allowed
- // display values for the pseudo style are NONE and INLINE for inline flows.
- // FIXME: CSS2.1 lifted this restriction, but block display types will crash.
- // For now we at least relax the restriction to allow all inline types like inline-block
- // and inline-table.
- pseudoElementStyle->setDisplay(INLINE);
-
- if (oldContentPresent) {
- if (child && child->style()->styleType() == type) {
- // We have generated content present still. We want to walk this content and update our
- // style information with the new pseudo-element style.
- child->setStyle(pseudoElementStyle);
-
- RenderObject* beforeAfterParent = findBeforeAfterParent(child);
- if (!beforeAfterParent)
- return;
-
- // Note that if we ever support additional types of generated content (which should be way off
- // in the future), this code will need to be patched.
- for (RenderObject* genChild = beforeAfterParent->firstChild(); genChild; genChild = genChild->nextSibling()) {
- if (genChild->isText())
- // Generated text content is a child whose style also needs to be set to the pseudo-element style.
- genChild->setStyle(pseudoElementStyle);
- else if (genChild->isImage()) {
- // Images get an empty style that inherits from the pseudo.
- RefPtr<RenderStyle> style = RenderStyle::create();
- style->inheritFrom(pseudoElementStyle);
- genChild->setStyle(style.release());
- } else
- // Must be a first-letter container. updateFirstLetter() will take care of it.
- ASSERT(genChild->style()->styleType() == RenderStyle::FIRST_LETTER);
- }
- }
- return; // We've updated the generated content. That's all we needed to do.
- }
-
- RenderObject* insertBefore = (type == RenderStyle::BEFORE) ? firstChild() : 0;
-
- // Generated content consists of a single container that houses multiple children (specified
- // by the content property). This generated content container gets the pseudo-element style set on it.
- RenderObject* generatedContentContainer = 0;
-
- // Walk our list of generated content and create render objects for each.
- for (const ContentData* content = pseudoElementStyle->contentData(); content; content = content->m_next) {
- RenderObject* renderer = 0;
- switch (content->m_type) {
- case CONTENT_NONE:
- break;
- case CONTENT_TEXT:
- renderer = new (renderArena()) RenderTextFragment(document() /* anonymous object */, content->m_content.m_text);
- renderer->setStyle(pseudoElementStyle);
- break;
- case CONTENT_OBJECT: {
- RenderImageGeneratedContent* image = new (renderArena()) RenderImageGeneratedContent(document()); // anonymous object
- RefPtr<RenderStyle> style = RenderStyle::create();
- style->inheritFrom(pseudoElementStyle);
- image->setStyle(style.release());
- if (StyleImage* styleImage = content->m_content.m_image)
- image->setStyleImage(styleImage);
- renderer = image;
- break;
- }
- case CONTENT_COUNTER:
- renderer = new (renderArena()) RenderCounter(document(), *content->m_content.m_counter);
- renderer->setStyle(pseudoElementStyle);
- break;
- }
-
- if (renderer) {
- if (!generatedContentContainer) {
- // Make a generated box that might be any display type now that we are able to drill down into children
- // to find the original content properly.
- generatedContentContainer = RenderObject::createObject(document(), pseudoElementStyle);
- generatedContentContainer->setStyle(pseudoElementStyle);
- addChild(generatedContentContainer, insertBefore);
- }
- generatedContentContainer->addChild(renderer);
- }
- }
-}
-
-bool RenderContainer::isAfterContent(RenderObject* child) const
-{
- if (!child)
- return false;
- if (child->style()->styleType() != RenderStyle::AFTER)
- return false;
- // Text nodes don't have their own styles, so ignore the style on a text node.
- if (child->isText() && !child->isBR())
- return false;
- return true;
-}
-
-static void invalidateCountersInContainer(RenderObject* container)
-{
- if (!container)
- return;
- container = findBeforeAfterParent(container);
- if (!container)
- return;
- for (RenderObject* content = container->firstChild(); content; content = content->nextSibling()) {
- if (content->isCounter())
- static_cast<RenderCounter*>(content)->invalidate();
- }
-}
-
-void RenderContainer::invalidateCounters()
-{
- if (documentBeingDestroyed())
- return;
-
- invalidateCountersInContainer(beforeAfterContainer(RenderStyle::BEFORE));
- invalidateCountersInContainer(beforeAfterContainer(RenderStyle::AFTER));
-}
-
-void RenderContainer::appendChildNode(RenderObject* newChild, bool fullAppend)
-{
- ASSERT(newChild->parent() == 0);
- ASSERT(!isBlockFlow() || (!newChild->isTableSection() && !newChild->isTableRow() && !newChild->isTableCell()));
-
- newChild->setParent(this);
- RenderObject* lChild = m_lastChild;
-
- if (lChild) {
- newChild->setPreviousSibling(lChild);
- lChild->setNextSibling(newChild);
- } else
- m_firstChild = newChild;
-
- m_lastChild = newChild;
-
- if (fullAppend) {
- // Keep our layer hierarchy updated. Optimize for the common case where we don't have any children
- // and don't have a layer attached to ourselves.
- RenderLayer* layer = 0;
- if (newChild->firstChild() || newChild->hasLayer()) {
- layer = enclosingLayer();
- newChild->addLayers(layer, newChild);
- }
-
- // if the new child is visible but this object was not, tell the layer it has some visible content
- // that needs to be drawn and layer visibility optimization can't be used
- if (style()->visibility() != VISIBLE && newChild->style()->visibility() == VISIBLE && !newChild->hasLayer()) {
- if (!layer)
- layer = enclosingLayer();
- if (layer)
- layer->setHasVisibleContent(true);
- }
-
- if (!newChild->isFloatingOrPositioned() && childrenInline())
- dirtyLinesFromChangedChild(newChild);
- }
-
- newChild->setNeedsLayoutAndPrefWidthsRecalc(); // Goes up the containing block hierarchy.
- if (!normalChildNeedsLayout())
- setChildNeedsLayout(true); // We may supply the static position for an absolute positioned child.
-
- if (AXObjectCache::accessibilityEnabled())
- document()->axObjectCache()->childrenChanged(this);
-}
-
-void RenderContainer::insertChildNode(RenderObject* child, RenderObject* beforeChild, bool fullInsert)
-{
- if (!beforeChild) {
- appendChildNode(child);
- return;
- }
-
- ASSERT(!child->parent());
- while (beforeChild->parent() != this && beforeChild->parent()->isAnonymousBlock())
- beforeChild = beforeChild->parent();
- ASSERT(beforeChild->parent() == this);
-
- ASSERT(!isBlockFlow() || (!child->isTableSection() && !child->isTableRow() && !child->isTableCell()));
-
- if (beforeChild == m_firstChild)
- m_firstChild = child;
-
- RenderObject* prev = beforeChild->previousSibling();
- child->setNextSibling(beforeChild);
- beforeChild->setPreviousSibling(child);
- if(prev) prev->setNextSibling(child);
- child->setPreviousSibling(prev);
-
- child->setParent(this);
-
- if (fullInsert) {
- // Keep our layer hierarchy updated. Optimize for the common case where we don't have any children
- // and don't have a layer attached to ourselves.
- RenderLayer* layer = 0;
- if (child->firstChild() || child->hasLayer()) {
- layer = enclosingLayer();
- child->addLayers(layer, child);
- }
-
- // if the new child is visible but this object was not, tell the layer it has some visible content
- // that needs to be drawn and layer visibility optimization can't be used
- if (style()->visibility() != VISIBLE && child->style()->visibility() == VISIBLE && !child->hasLayer()) {
- if (!layer)
- layer = enclosingLayer();
- if (layer)
- layer->setHasVisibleContent(true);
- }
-
-
- if (!child->isFloating() && childrenInline())
- dirtyLinesFromChangedChild(child);
- }
-
- child->setNeedsLayoutAndPrefWidthsRecalc();
- if (!normalChildNeedsLayout())
- setChildNeedsLayout(true); // We may supply the static position for an absolute positioned child.
-
- if (AXObjectCache::accessibilityEnabled())
- document()->axObjectCache()->childrenChanged(this);
-}
-
-void RenderContainer::layout()
-{
- ASSERT(needsLayout());
-
- LayoutStateMaintainer statePusher(view(), this, IntSize(m_x, m_y));
-
- RenderObject* child = m_firstChild;
- while (child) {
- child->layoutIfNeeded();
- ASSERT(child->isRenderInline() || !child->needsLayout());
- child = child->nextSibling();
- }
-
- statePusher.pop();
- setNeedsLayout(false);
-}
-
-void RenderContainer::removeLeftoverAnonymousBlock(RenderBlock* child)
-{
- ASSERT(child->isAnonymousBlock());
- ASSERT(!child->childrenInline());
-
- if (child->continuation())
- return;
-
- RenderObject* firstAnChild = child->firstChild();
- RenderObject* lastAnChild = child->lastChild();
- if (firstAnChild) {
- RenderObject* o = firstAnChild;
- while(o) {
- o->setParent(this);
- o = o->nextSibling();
- }
- firstAnChild->setPreviousSibling(child->previousSibling());
- lastAnChild->setNextSibling(child->nextSibling());
- if (child->previousSibling())
- child->previousSibling()->setNextSibling(firstAnChild);
- if (child->nextSibling())
- child->nextSibling()->setPreviousSibling(lastAnChild);
- } else {
- if (child->previousSibling())
- child->previousSibling()->setNextSibling(child->nextSibling());
- if (child->nextSibling())
- child->nextSibling()->setPreviousSibling(child->previousSibling());
- }
- if (child == m_firstChild)
- m_firstChild = firstAnChild;
- if (child == m_lastChild)
- m_lastChild = lastAnChild;
- child->setParent(0);
- child->setPreviousSibling(0);
- child->setNextSibling(0);
- if (!child->isText()) {
- RenderContainer *c = static_cast<RenderContainer*>(child);
- c->m_firstChild = 0;
- c->m_next = 0;
- }
- child->destroy();
-}
-
-VisiblePosition RenderContainer::positionForCoordinates(int x, int y)
-{
- // no children...return this render object's element, if there is one, and offset 0
- if (!m_firstChild)
- return VisiblePosition(element(), 0, DOWNSTREAM);
-
- if (isTable() && element()) {
- int right = contentWidth() + borderRight() + paddingRight() + borderLeft() + paddingLeft();
- int bottom = contentHeight() + borderTop() + paddingTop() + borderBottom() + paddingBottom();
-
- if (x < 0 || x > right || y < 0 || y > bottom) {
- if (x <= right / 2)
- return VisiblePosition(Position(element(), 0));
- else
- return VisiblePosition(Position(element(), maxDeepOffset(element())));
- }
- }
-
- // Pass off to the closest child.
- int minDist = INT_MAX;
- RenderObject* closestRenderer = 0;
- int newX = x;
- int newY = y;
- if (isTableRow()) {
- newX += xPos();
- newY += yPos();
- }
- for (RenderObject* renderer = m_firstChild; renderer; renderer = renderer->nextSibling()) {
- if (!renderer->firstChild() && !renderer->isInline() && !renderer->isBlockFlow()
- || renderer->style()->visibility() != VISIBLE)
- continue;
-
- int top = borderTop() + paddingTop() + (isTableRow() ? 0 : renderer->yPos());
- int bottom = top + renderer->contentHeight();
- int left = borderLeft() + paddingLeft() + (isTableRow() ? 0 : renderer->xPos());
- int right = left + renderer->contentWidth();
-
- if (x <= right && x >= left && y <= top && y >= bottom) {
- if (renderer->isTableRow())
- return renderer->positionForCoordinates(x + newX - renderer->xPos(), y + newY - renderer->yPos());
- return renderer->positionForCoordinates(x - renderer->xPos(), y - renderer->yPos());
- }
-
- // Find the distance from (x, y) to the box. Split the space around the box into 8 pieces
- // and use a different compare depending on which piece (x, y) is in.
- IntPoint cmp;
- if (x > right) {
- if (y < top)
- cmp = IntPoint(right, top);
- else if (y > bottom)
- cmp = IntPoint(right, bottom);
- else
- cmp = IntPoint(right, y);
- } else if (x < left) {
- if (y < top)
- cmp = IntPoint(left, top);
- else if (y > bottom)
- cmp = IntPoint(left, bottom);
- else
- cmp = IntPoint(left, y);
- } else {
- if (y < top)
- cmp = IntPoint(x, top);
- else
- cmp = IntPoint(x, bottom);
- }
-
- int x1minusx2 = cmp.x() - x;
- int y1minusy2 = cmp.y() - y;
-
- int dist = x1minusx2 * x1minusx2 + y1minusy2 * y1minusy2;
- if (dist < minDist) {
- closestRenderer = renderer;
- minDist = dist;
- }
- }
-
- if (closestRenderer)
- return closestRenderer->positionForCoordinates(newX - closestRenderer->xPos(), newY - closestRenderer->yPos());
-
- return VisiblePosition(element(), 0, DOWNSTREAM);
-}
-
-void RenderContainer::addLineBoxRects(Vector<IntRect>& rects, unsigned start, unsigned end, bool)
-{
- if (!m_firstChild && (isInline() || isAnonymousBlock())) {
- FloatPoint absPos = localToAbsoluteForContent(FloatPoint());
- absoluteRects(rects, absPos.x(), absPos.y());
- return;
- }
-
- if (!m_firstChild)
- return;
-
- unsigned offset = start;
- for (RenderObject* child = childAt(start); child && offset < end; child = child->nextSibling(), ++offset) {
- if (child->isText() || child->isInline() || child->isAnonymousBlock()) {
- FloatPoint absPos = child->localToAbsoluteForContent(FloatPoint());
- child->absoluteRects(rects, absPos.x(), absPos.y());
- }
- }
-}
-
-void RenderContainer::collectAbsoluteLineBoxQuads(Vector<FloatQuad>& quads, unsigned start, unsigned end, bool /*useSelectionHeight*/)
-{
- if (!m_firstChild && (isInline() || isAnonymousBlock())) {
- absoluteQuads(quads);
- return;
- }
-
- if (!m_firstChild)
- return;
-
- unsigned offset = start;
- for (RenderObject* child = childAt(start); child && offset < end; child = child->nextSibling(), ++offset) {
- if (child->isText() || child->isInline() || child->isAnonymousBlock())
- child->absoluteQuads(quads);
- }
-}
-
-#undef DEBUG_LAYOUT
-
-} // namespace WebCore
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderContainer.h b/src/3rdparty/webkit/WebCore/rendering/RenderContainer.h
deleted file mode 100644
index 68aba84..0000000
--- a/src/3rdparty/webkit/WebCore/rendering/RenderContainer.h
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright (C) 2001 Antti Koivisto (koivisto@kde.org)
- * Copyright (C) 2003, 2004, 2005, 2006, 2007 Apple Inc. 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
- * 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 RenderContainer_h
-#define RenderContainer_h
-
-#include "RenderBox.h"
-
-namespace WebCore {
-
-// Base class for rendering objects that can have children.
-class RenderContainer : public RenderBox {
-public:
- RenderContainer(Node*);
- virtual ~RenderContainer();
-
- virtual RenderObject* firstChild() const { return m_firstChild; }
- virtual RenderObject* lastChild() const { return m_lastChild; }
-
- virtual bool canHaveChildren() const;
- virtual void addChild(RenderObject* newChild, RenderObject* beforeChild = 0);
- virtual void removeChild(RenderObject*);
-
- virtual void destroy();
- void destroyLeftoverChildren();
-
- virtual RenderObject* removeChildNode(RenderObject*, bool fullRemove = true);
- virtual void appendChildNode(RenderObject*, bool fullAppend = true);
- virtual void insertChildNode(RenderObject* child, RenderObject* before, bool fullInsert = true);
-
- // Designed for speed. Don't waste time doing a bunch of work like layer updating and repainting when we know that our
- // change in parentage is not going to affect anything.
- virtual void moveChildNode(RenderObject* child) { appendChildNode(child->parent()->removeChildNode(child, false), false); }
-
- virtual void layout();
- virtual void calcPrefWidths() { setPrefWidthsDirty(false); }
-
- virtual void removeLeftoverAnonymousBlock(RenderBlock* child);
-
- RenderObject* beforeAfterContainer(RenderStyle::PseudoId);
- virtual void updateBeforeAfterContent(RenderStyle::PseudoId);
- void updateBeforeAfterContentForContainer(RenderStyle::PseudoId, RenderContainer*);
- bool isAfterContent(RenderObject* child) const;
- virtual void invalidateCounters();
-
- virtual VisiblePosition positionForCoordinates(int x, int y);
-
- virtual void addLineBoxRects(Vector<IntRect>&, unsigned startOffset = 0, unsigned endOffset = UINT_MAX, bool useSelectionHeight = false);
- virtual void collectAbsoluteLineBoxQuads(Vector<FloatQuad>&, unsigned startOffset = 0, unsigned endOffset = UINT_MAX, bool useSelectionHeight = false);
-
-private:
- RenderObject* m_firstChild;
- RenderObject* m_lastChild;
-};
-
-} // namespace WebCore
-
-#endif // RenderContainer_h
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderCounter.cpp b/src/3rdparty/webkit/WebCore/rendering/RenderCounter.cpp
index 598f40d..fd6d80d 100644
--- a/src/3rdparty/webkit/WebCore/rendering/RenderCounter.cpp
+++ b/src/3rdparty/webkit/WebCore/rendering/RenderCounter.cpp
@@ -116,7 +116,7 @@ static bool planCounter(RenderObject* object, const AtomicString& counterName, b
isReset = false;
return true;
}
- if (Node* e = object->element()) {
+ if (Node* e = object->node()) {
if (e->hasTagName(olTag)) {
value = static_cast<HTMLOListElement*>(e)->start();
isReset = true;
@@ -251,13 +251,6 @@ PassRefPtr<StringImpl> RenderCounter::originalText() const
return text.impl();
}
-void RenderCounter::dirtyLineBoxes(bool fullLayout, bool dummy)
-{
- if (prefWidthsDirty())
- calcPrefWidths(0);
- RenderText::dirtyLineBoxes(fullLayout, dummy);
-}
-
void RenderCounter::calcPrefWidths(int lead)
{
setTextInternal(originalText());
@@ -278,7 +271,11 @@ static void destroyCounterNodeChildren(AtomicStringImpl* identifier, CounterNode
child->parent()->removeChild(child);
ASSERT(counterMaps().get(child->renderer())->get(identifier) == child);
counterMaps().get(child->renderer())->remove(identifier);
- child->renderer()->invalidateCounters();
+ if (!child->renderer()->documentBeingDestroyed()) {
+ RenderObjectChildList* children = child->renderer()->virtualChildren();
+ if (children)
+ children->invalidateCounters(child->renderer());
+ }
delete child;
}
}
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderCounter.h b/src/3rdparty/webkit/WebCore/rendering/RenderCounter.h
index 10be066..55aab73 100644
--- a/src/3rdparty/webkit/WebCore/rendering/RenderCounter.h
+++ b/src/3rdparty/webkit/WebCore/rendering/RenderCounter.h
@@ -37,7 +37,6 @@ public:
virtual bool isCounter() const;
virtual PassRefPtr<StringImpl> originalText() const;
- virtual void dirtyLineBoxes(bool, bool);
virtual void calcPrefWidths(int leadWidth);
void invalidate();
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderDataGrid.cpp b/src/3rdparty/webkit/WebCore/rendering/RenderDataGrid.cpp
new file mode 100644
index 0000000..b207a31
--- /dev/null
+++ b/src/3rdparty/webkit/WebCore/rendering/RenderDataGrid.cpp
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2009 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``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 COMPUTER, INC. OR
+ * 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"
+#include "RenderDataGrid.h"
+
+#include "FocusController.h"
+#include "Frame.h"
+#include "GraphicsContext.h"
+#include "Page.h"
+#include "Scrollbar.h"
+
+using std::min;
+
+namespace WebCore {
+
+static const int cDefaultWidth = 300;
+
+RenderDataGrid::RenderDataGrid(Element* elt)
+ : RenderBlock(elt)
+{
+}
+
+RenderDataGrid::~RenderDataGrid()
+{
+}
+
+void RenderDataGrid::calcPrefWidths()
+{
+ m_minPrefWidth = 0;
+ m_maxPrefWidth = 0;
+
+ if (style()->width().isFixed() && style()->width().value() > 0)
+ m_minPrefWidth = m_maxPrefWidth = calcContentBoxWidth(style()->width().value());
+ else
+ m_maxPrefWidth = calcContentBoxWidth(cDefaultWidth);
+
+ if (style()->minWidth().isFixed() && style()->minWidth().value() > 0) {
+ m_maxPrefWidth = max(m_maxPrefWidth, calcContentBoxWidth(style()->minWidth().value()));
+ m_minPrefWidth = max(m_minPrefWidth, calcContentBoxWidth(style()->minWidth().value()));
+ } else if (style()->width().isPercent() || (style()->width().isAuto() && style()->height().isPercent()))
+ m_minPrefWidth = 0;
+ else
+ m_minPrefWidth = m_maxPrefWidth;
+
+ if (style()->maxWidth().isFixed() && style()->maxWidth().value() != undefinedLength) {
+ m_maxPrefWidth = min(m_maxPrefWidth, calcContentBoxWidth(style()->maxWidth().value()));
+ m_minPrefWidth = min(m_minPrefWidth, calcContentBoxWidth(style()->maxWidth().value()));
+ }
+
+ int toAdd = paddingLeft() + paddingRight() + borderLeft() + borderRight();
+ m_minPrefWidth += toAdd;
+ m_maxPrefWidth += toAdd;
+
+ setPrefWidthsDirty(false);
+}
+
+void RenderDataGrid::paintObject(PaintInfo& paintInfo, int tx, int ty)
+{
+ if (style()->visibility() != VISIBLE)
+ return;
+
+ // Paint our background and border.
+ RenderBlock::paintObject(paintInfo, tx, ty);
+
+ if (paintInfo.phase != PaintPhaseForeground)
+ return;
+
+ // Paint our column headers first.
+ paintColumnHeaders(paintInfo, tx, ty);
+}
+
+void RenderDataGrid::paintColumnHeaders(PaintInfo&, int, int)
+{
+ gridElement()->columns();
+
+}
+
+void RenderDataGrid::rebuildColumns()
+{
+}
+
+// Scrolling implementation functions
+void RenderDataGrid::valueChanged(Scrollbar*)
+{
+ // FIXME: Implement.
+}
+
+void RenderDataGrid::invalidateScrollbarRect(Scrollbar*, const IntRect&)
+{
+ // FIXME: Implement.
+}
+
+bool RenderDataGrid::isActive() const
+{
+ Page* page = document()->frame()->page();
+ return page && page->focusController()->isActive();
+}
+
+}
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderDataGrid.h b/src/3rdparty/webkit/WebCore/rendering/RenderDataGrid.h
new file mode 100644
index 0000000..6a4b32e
--- /dev/null
+++ b/src/3rdparty/webkit/WebCore/rendering/RenderDataGrid.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2009 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``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 COMPUTER, INC. OR
+ * 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 RenderDataGrid_h
+#define RenderDataGrid_h
+
+#include "HTMLDataGridElement.h"
+#include "RenderBlock.h"
+#include "ScrollbarClient.h"
+#include "StyleImage.h"
+#include <wtf/RefPtr.h>
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+class RenderDataGrid : public RenderBlock, private ScrollbarClient {
+public:
+ RenderDataGrid(Element*);
+ ~RenderDataGrid();
+
+ virtual const char* renderName() const { return "RenderDataGrid"; }
+
+ virtual bool canHaveChildren() const { return false; }
+
+ virtual void calcPrefWidths();
+
+ virtual void paintObject(PaintInfo&, int tx, int ty);
+
+ void columnsChanged();
+
+private:
+ void paintColumnHeaders(PaintInfo&, int tx, int ty);
+ void rebuildColumns();
+
+ HTMLDataGridElement* gridElement() const { return static_cast<HTMLDataGridElement*>(node()); }
+
+ // ScrollbarClient interface.
+ virtual void valueChanged(Scrollbar*);
+ virtual void invalidateScrollbarRect(Scrollbar*, const IntRect&);
+ virtual bool isActive() const;
+ virtual bool scrollbarCornerPresent() const { return false; } // We don't support resize on data grids yet. If we did this would have to change.
+
+ RefPtr<Scrollbar> m_vBar;
+};
+
+}
+
+#endif // RenderDataGrid_h
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderFieldset.cpp b/src/3rdparty/webkit/WebCore/rendering/RenderFieldset.cpp
index 0e944f4..1275882 100644
--- a/src/3rdparty/webkit/WebCore/rendering/RenderFieldset.cpp
+++ b/src/3rdparty/webkit/WebCore/rendering/RenderFieldset.cpp
@@ -48,7 +48,7 @@ RenderFieldset::RenderFieldset(Node* element)
void RenderFieldset::calcPrefWidths()
{
RenderBlock::calcPrefWidths();
- if (RenderObject* legend = findLegend()) {
+ if (RenderBox* legend = findLegend()) {
int legendMinWidth = legend->minPrefWidth();
Length legendMarginLeft = legend->style()->marginLeft();
@@ -66,7 +66,7 @@ void RenderFieldset::calcPrefWidths()
RenderObject* RenderFieldset::layoutLegend(bool relayoutChildren)
{
- RenderObject* legend = findLegend();
+ RenderBox* legend = findLegend();
if (legend) {
if (relayoutChildren)
legend->setNeedsLayout(true);
@@ -79,18 +79,18 @@ RenderObject* RenderFieldset::layoutLegend(bool relayoutChildren)
xPos = borderLeft() + paddingLeft();
break;
case CENTER:
- xPos = (m_width - legend->width()) / 2;
+ xPos = (width() - legend->width()) / 2;
break;
default:
- xPos = m_width - paddingRight() - borderRight() - legend->width() - legend->marginRight();
+ xPos = width() - paddingRight() - borderRight() - legend->width() - legend->marginRight();
}
} else {
switch (legend->style()->textAlign()) {
case RIGHT:
- xPos = m_width - paddingRight() - borderRight() - legend->width();
+ xPos = width() - paddingRight() - borderRight() - legend->width();
break;
case CENTER:
- xPos = (m_width - legend->width()) / 2;
+ xPos = (width() - legend->width()) / 2;
break;
default:
xPos = borderLeft() + paddingLeft() + legend->marginLeft();
@@ -98,22 +98,22 @@ RenderObject* RenderFieldset::layoutLegend(bool relayoutChildren)
}
int b = borderTop();
int h = legend->height();
- legend->setPos(xPos, max((b-h)/2, 0));
- m_height = max(b,h) + paddingTop();
+ legend->setLocation(xPos, max((b-h)/2, 0));
+ setHeight(max(b,h) + paddingTop());
}
return legend;
}
-RenderObject* RenderFieldset::findLegend() const
+RenderBox* RenderFieldset::findLegend() const
{
for (RenderObject* legend = firstChild(); legend; legend = legend->nextSibling()) {
- if (!legend->isFloatingOrPositioned() && legend->element() &&
- legend->element()->hasTagName(legendTag)
+ if (!legend->isFloatingOrPositioned() && legend->node() &&
+ legend->node()->hasTagName(legendTag)
#if ENABLE(WML)
- || legend->element()->hasTagName(WMLNames::insertedLegendTag)
+ || legend->node()->hasTagName(WMLNames::insertedLegendTag)
#endif
)
- return legend;
+ return toRenderBox(legend);
}
return 0;
}
@@ -121,30 +121,26 @@ RenderObject* RenderFieldset::findLegend() const
void RenderFieldset::paintBoxDecorations(PaintInfo& paintInfo, int tx, int ty)
{
int w = width();
- int h = height() + borderTopExtra() + borderBottomExtra();
- RenderObject* legend = findLegend();
+ int h = height();
+ RenderBox* legend = findLegend();
if (!legend)
return RenderBlock::paintBoxDecorations(paintInfo, tx, ty);
- int yOff = (legend->yPos() > 0) ? 0 : (legend->height() - borderTop()) / 2;
- int legendBottom = ty + legend->yPos() + legend->height();
+ int yOff = (legend->y() > 0) ? 0 : (legend->height() - borderTop()) / 2;
+ int legendBottom = ty + legend->y() + legend->height();
h -= yOff;
- ty += yOff - borderTopExtra();
-
- int my = max(ty, paintInfo.rect.y());
- int end = min(paintInfo.rect.bottom(), ty + h);
- int mh = end - my;
+ ty += yOff;
paintBoxShadow(paintInfo.context, tx, ty, w, h, style());
- paintFillLayers(paintInfo, style()->backgroundColor(), style()->backgroundLayers(), my, mh, tx, ty, w, h);
+ paintFillLayers(paintInfo, style()->backgroundColor(), style()->backgroundLayers(), tx, ty, w, h);
if (!style()->hasBorder())
return;
// Save time by not saving and restoring the GraphicsContext in the straight border case
if (!style()->hasBorderRadius())
- return paintBorderMinusLegend(paintInfo.context, tx, ty, w, h, style(), legend->xPos(), legend->width(), legendBottom);
+ return paintBorderMinusLegend(paintInfo.context, tx, ty, w, h, style(), legend->x(), legend->width(), legendBottom);
// We have rounded borders, create a clipping region
// around the legend and paint the border as normal
@@ -154,7 +150,7 @@ void RenderFieldset::paintBoxDecorations(PaintInfo& paintInfo, int tx, int ty)
int clipTop = ty;
int clipHeight = max(static_cast<int>(style()->borderTopWidth()), legend->height());
- graphicsContext->clipOut(IntRect(tx + legend->xPos(), clipTop,
+ graphicsContext->clipOut(IntRect(tx + legend->x(), clipTop,
legend->width(), clipHeight));
paintBorder(paintInfo.context, tx, ty, w, h, style(), true, true);
@@ -167,20 +163,16 @@ void RenderFieldset::paintMask(PaintInfo& paintInfo, int tx, int ty)
return;
int w = width();
- int h = height() + borderTopExtra() + borderBottomExtra();
- RenderObject* legend = findLegend();
+ int h = height();
+ RenderBox* legend = findLegend();
if (!legend)
return RenderBlock::paintMask(paintInfo, tx, ty);
- int yOff = (legend->yPos() > 0) ? 0 : (legend->height() - borderTop()) / 2;
+ int yOff = (legend->y() > 0) ? 0 : (legend->height() - borderTop()) / 2;
h -= yOff;
- ty += yOff - borderTopExtra();
-
- int my = max(ty, paintInfo.rect.y());
- int end = min(paintInfo.rect.bottom(), ty + h);
- int mh = end - my;
+ ty += yOff;
- paintMaskImages(paintInfo, my, mh, tx, ty, w, h);
+ paintMaskImages(paintInfo, tx, ty, w, h);
}
void RenderFieldset::paintBorderMinusLegend(GraphicsContext* graphicsContext, int tx, int ty, int w, int h,
@@ -204,17 +196,17 @@ void RenderFieldset::paintBorderMinusLegend(GraphicsContext* graphicsContext, in
if (render_t) {
if (lx >= borderLeftWidth)
- drawBorder(graphicsContext, tx, ty, tx + min(lx, w), ty + style->borderTopWidth(), BSTop, tc, style->color(), ts,
+ drawLineForBoxSide(graphicsContext, tx, ty, tx + min(lx, w), ty + style->borderTopWidth(), BSTop, tc, style->color(), ts,
(render_l && (ls == DOTTED || ls == DASHED || ls == DOUBLE) ? borderLeftWidth : 0),
(lx >= w && render_r && (rs == DOTTED || rs == DASHED || rs == DOUBLE) ? borderRightWidth : 0));
if (lx + lw <= w - borderRightWidth)
- drawBorder(graphicsContext, tx + max(0, lx + lw), ty, tx + w, ty + style->borderTopWidth(), BSTop, tc, style->color(), ts,
+ drawLineForBoxSide(graphicsContext, tx + max(0, lx + lw), ty, tx + w, ty + style->borderTopWidth(), BSTop, tc, style->color(), ts,
(lx + lw <= 0 && render_l && (ls == DOTTED || ls == DASHED || ls == DOUBLE) ? borderLeftWidth : 0),
(render_r && (rs == DOTTED || rs == DASHED || rs == DOUBLE) ? borderRightWidth : 0));
}
if (render_b)
- drawBorder(graphicsContext, tx, ty + h - style->borderBottomWidth(), tx + w, ty + h, BSBottom, bc, style->color(), bs,
+ drawLineForBoxSide(graphicsContext, tx, ty + h - style->borderBottomWidth(), tx + w, ty + h, BSBottom, bc, style->color(), bs,
(render_l && (ls == DOTTED || ls == DASHED || ls == DOUBLE) ? style->borderLeftWidth() : 0),
(render_r && (rs == DOTTED || rs == DASHED || rs == DOUBLE) ? style->borderRightWidth() : 0));
@@ -238,7 +230,7 @@ void RenderFieldset::paintBorderMinusLegend(GraphicsContext* graphicsContext, in
startY = lb;
}
- drawBorder(graphicsContext, tx, startY, tx + borderLeftWidth, ty + h, BSLeft, lc, style->color(), ls,
+ drawLineForBoxSide(graphicsContext, tx, startY, tx + borderLeftWidth, ty + h, BSLeft, lc, style->color(), ls,
ignore_top ? 0 : style->borderTopWidth(), ignore_bottom ? 0 : style->borderBottomWidth());
}
@@ -262,12 +254,12 @@ void RenderFieldset::paintBorderMinusLegend(GraphicsContext* graphicsContext, in
startY = lb;
}
- drawBorder(graphicsContext, tx + w - borderRightWidth, startY, tx + w, ty + h, BSRight, rc, style->color(), rs,
+ drawLineForBoxSide(graphicsContext, tx + w - borderRightWidth, startY, tx + w, ty + h, BSRight, rc, style->color(), rs,
ignore_top ? 0 : style->borderTopWidth(), ignore_bottom ? 0 : style->borderBottomWidth());
}
}
-void RenderFieldset::styleDidChange(RenderStyle::Diff diff, const RenderStyle* oldStyle)
+void RenderFieldset::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
{
RenderBlock::styleDidChange(diff, oldStyle);
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderFieldset.h b/src/3rdparty/webkit/WebCore/rendering/RenderFieldset.h
index 47d1a91..ed57d3a 100644
--- a/src/3rdparty/webkit/WebCore/rendering/RenderFieldset.h
+++ b/src/3rdparty/webkit/WebCore/rendering/RenderFieldset.h
@@ -41,13 +41,12 @@ public:
virtual void calcPrefWidths();
virtual bool avoidsFloats() const { return true; }
- virtual bool expandsToEncloseOverhangingFloats() const { return style()->height().isAuto(); }
virtual bool stretchesToMinIntrinsicWidth() const { return true; }
- RenderObject* findLegend() const;
+ RenderBox* findLegend() const;
protected:
- virtual void styleDidChange(RenderStyle::Diff, const RenderStyle* oldStyle);
+ virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
private:
virtual void paintBoxDecorations(PaintInfo&, int tx, int ty);
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderFileUploadControl.cpp b/src/3rdparty/webkit/WebCore/rendering/RenderFileUploadControl.cpp
index 6a4bb54..72623f7 100644
--- a/src/3rdparty/webkit/WebCore/rendering/RenderFileUploadControl.cpp
+++ b/src/3rdparty/webkit/WebCore/rendering/RenderFileUploadControl.cpp
@@ -22,6 +22,7 @@
#include "RenderFileUploadControl.h"
#include "FileList.h"
+#include "Frame.h"
#include "FrameView.h"
#include "GraphicsContext.h"
#include "HTMLInputElement.h"
@@ -73,7 +74,7 @@ RenderFileUploadControl::~RenderFileUploadControl()
m_fileChooser->disconnectClient();
}
-void RenderFileUploadControl::styleDidChange(RenderStyle::Diff diff, const RenderStyle* oldStyle)
+void RenderFileUploadControl::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
{
RenderBlock::styleDidChange(diff, oldStyle);
if (m_button)
@@ -84,12 +85,12 @@ void RenderFileUploadControl::styleDidChange(RenderStyle::Diff diff, const Rende
void RenderFileUploadControl::valueChanged()
{
- // onChange may destroy this renderer
+ // dispatchFormControlChangeEvent may destroy this renderer
RefPtr<FileChooser> fileChooser = m_fileChooser;
HTMLInputElement* inputElement = static_cast<HTMLInputElement*>(node());
inputElement->setFileListFromRenderer(fileChooser->filenames());
- inputElement->onChange();
+ inputElement->dispatchFormControlChangeEvent();
// only repaint if it doesn't seem we have been destroyed
if (!fileChooser->disconnected())
@@ -147,13 +148,13 @@ void RenderFileUploadControl::updateFromElement()
int RenderFileUploadControl::maxFilenameWidth() const
{
- return max(0, contentWidth() - m_button->renderer()->width() - afterButtonSpacing
+ return max(0, contentWidth() - m_button->renderBox()->width() - afterButtonSpacing
- (m_fileChooser->icon() ? iconWidth + iconFilenameSpacing : 0));
}
PassRefPtr<RenderStyle> RenderFileUploadControl::createButtonStyle(const RenderStyle* parentStyle) const
{
- RefPtr<RenderStyle> style = getCachedPseudoStyle(RenderStyle::FILE_UPLOAD_BUTTON);
+ RefPtr<RenderStyle> style = getCachedPseudoStyle(FILE_UPLOAD_BUTTON);
if (!style) {
style = RenderStyle::create();
if (parentStyle)
@@ -190,7 +191,7 @@ void RenderFileUploadControl::paintObject(PaintInfo& paintInfo, int tx, int ty)
// Determine where the filename should be placed
int contentLeft = tx + borderLeft() + paddingLeft();
- int buttonAndIconWidth = m_button->renderer()->width() + afterButtonSpacing
+ int buttonAndIconWidth = m_button->renderBox()->width() + afterButtonSpacing
+ (m_fileChooser->icon() ? iconWidth + iconFilenameSpacing : 0);
int textX;
if (style()->direction() == LTR)
@@ -198,25 +199,24 @@ void RenderFileUploadControl::paintObject(PaintInfo& paintInfo, int tx, int ty)
else
textX = contentLeft + contentWidth() - buttonAndIconWidth - style()->font().width(textRun);
// We want to match the button's baseline
- RenderButton* buttonRenderer = static_cast<RenderButton*>(m_button->renderer());
+ RenderButton* buttonRenderer = toRenderButton(m_button->renderer());
int textY = buttonRenderer->absoluteBoundingBoxRect().y()
+ buttonRenderer->marginTop() + buttonRenderer->borderTop() + buttonRenderer->paddingTop()
+ buttonRenderer->baselinePosition(true, false);
- paintInfo.context->setFont(style()->font());
paintInfo.context->setFillColor(style()->color());
// Draw the filename
- paintInfo.context->drawBidiText(textRun, IntPoint(textX, textY));
+ paintInfo.context->drawBidiText(style()->font(), textRun, IntPoint(textX, textY));
if (m_fileChooser->icon()) {
// Determine where the icon should be placed
int iconY = ty + borderTop() + paddingTop() + (contentHeight() - iconHeight) / 2;
int iconX;
if (style()->direction() == LTR)
- iconX = contentLeft + m_button->renderer()->width() + afterButtonSpacing;
+ iconX = contentLeft + m_button->renderBox()->width() + afterButtonSpacing;
else
- iconX = contentLeft + contentWidth() - m_button->renderer()->width() - afterButtonSpacing - iconWidth;
+ iconX = contentLeft + contentWidth() - m_button->renderBox()->width() - afterButtonSpacing - iconWidth;
// Draw the file icon
m_fileChooser->icon()->paint(paintInfo.context, IntRect(iconX, iconY, iconWidth, iconHeight));
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderFileUploadControl.h b/src/3rdparty/webkit/WebCore/rendering/RenderFileUploadControl.h
index 60e7a7b..85bc09f 100644
--- a/src/3rdparty/webkit/WebCore/rendering/RenderFileUploadControl.h
+++ b/src/3rdparty/webkit/WebCore/rendering/RenderFileUploadControl.h
@@ -55,7 +55,7 @@ public:
bool allowsMultipleFiles();
protected:
- virtual void styleDidChange(RenderStyle::Diff, const RenderStyle* oldStyle);
+ virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
private:
int maxFilenameWidth() const;
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderFlexibleBox.cpp b/src/3rdparty/webkit/WebCore/rendering/RenderFlexibleBox.cpp
index 08bc567..1dcef36 100644
--- a/src/3rdparty/webkit/WebCore/rendering/RenderFlexibleBox.cpp
+++ b/src/3rdparty/webkit/WebCore/rendering/RenderFlexibleBox.cpp
@@ -45,11 +45,11 @@ public:
lastOrdinal = 1;
if (!forward) {
// No choice, since we're going backwards, we have to find out the highest ordinal up front.
- RenderObject* child = box->firstChild();
+ RenderBox* child = box->firstChildBox();
while (child) {
if (child->style()->boxOrdinalGroup() > lastOrdinal)
lastOrdinal = child->style()->boxOrdinalGroup();
- child = child->nextSibling();
+ child = child->nextSiblingBox();
}
}
@@ -61,29 +61,28 @@ public:
currentOrdinal = forward ? 0 : lastOrdinal+1;
}
- RenderObject* first() {
+ RenderBox* first() {
reset();
return next();
}
- RenderObject* next() {
-
+ RenderBox* next() {
do {
if (!current) {
if (forward) {
currentOrdinal++;
if (currentOrdinal > lastOrdinal)
return 0;
- current = box->firstChild();
+ current = box->firstChildBox();
} else {
currentOrdinal--;
if (currentOrdinal == 0)
return 0;
- current = box->lastChild();
+ current = box->lastChildBox();
}
}
else
- current = forward ? current->nextSibling() : current->previousSibling();
+ current = forward ? current->nextSiblingBox() : current->previousSiblingBox();
if (current && current->style()->boxOrdinalGroup() > lastOrdinal)
lastOrdinal = current->style()->boxOrdinalGroup();
} while (!current || current->style()->boxOrdinalGroup() != currentOrdinal ||
@@ -93,7 +92,7 @@ public:
private:
RenderFlexibleBox* box;
- RenderObject* current;
+ RenderBox* current;
bool forward;
unsigned int currentOrdinal;
unsigned int lastOrdinal;
@@ -112,13 +111,10 @@ RenderFlexibleBox::~RenderFlexibleBox()
void RenderFlexibleBox::calcHorizontalPrefWidths()
{
- RenderObject *child = firstChild();
- while (child) {
+ for (RenderBox* child = firstChildBox(); child; child = child->nextSiblingBox()) {
// positioned children don't affect the minmaxwidth
- if (child->isPositioned() || child->style()->visibility() == COLLAPSE) {
- child = child->nextSibling();
+ if (child->isPositioned() || child->style()->visibility() == COLLAPSE)
continue;
- }
// A margin basically has three types: fixed, percentage, and auto (variable).
// Auto and percentage margins simply become 0 when computing min/max width.
@@ -134,21 +130,15 @@ void RenderFlexibleBox::calcHorizontalPrefWidths()
m_minPrefWidth += child->minPrefWidth() + margin;
m_maxPrefWidth += child->maxPrefWidth() + margin;
-
- child = child->nextSibling();
}
}
void RenderFlexibleBox::calcVerticalPrefWidths()
{
- RenderObject *child = firstChild();
- while(child != 0)
- {
+ for (RenderBox* child = firstChildBox(); child; child = child->nextSiblingBox()) {
// Positioned children and collapsed children don't affect the min/max width
- if (child->isPositioned() || child->style()->visibility() == COLLAPSE) {
- child = child->nextSibling();
+ if (child->isPositioned() || child->style()->visibility() == COLLAPSE)
continue;
- }
// A margin basically has three types: fixed, percentage, and auto (variable).
// Auto/percentage margins simply become 0 when computing min/max width.
@@ -166,8 +156,6 @@ void RenderFlexibleBox::calcVerticalPrefWidths()
w = child->maxPrefWidth() + margin;
m_maxPrefWidth = max(w, m_maxPrefWidth);
-
- child = child->nextSibling();
}
}
@@ -212,29 +200,22 @@ void RenderFlexibleBox::layoutBlock(bool relayoutChildren)
if (!relayoutChildren && layoutOnlyPositionedObjects())
return;
- IntRect oldBounds;
- IntRect oldOutlineBox;
- bool checkForRepaint = checkForRepaintDuringLayout();
- if (checkForRepaint) {
- oldBounds = absoluteClippedOverflowRect();
- oldOutlineBox = absoluteOutlineBounds();
- }
-
- LayoutStateMaintainer statePusher(view(), this, IntSize(m_x, m_y), !hasReflection());
+ LayoutRepainter repainter(*this, checkForRepaintDuringLayout());
+ LayoutStateMaintainer statePusher(view(), this, IntSize(x(), y()), hasTransform() || hasReflection());
- int previousWidth = m_width;
- int previousHeight = m_height;
+ int previousWidth = width();
+ int previousHeight = height();
calcWidth();
calcHeight();
- m_overflowWidth = m_width;
+ m_overflowWidth = width();
- if (previousWidth != m_width || previousHeight != m_height ||
+ if (previousWidth != width() || previousHeight != height() ||
(parent()->isFlexibleBox() && parent()->style()->boxOrient() == HORIZONTAL &&
parent()->style()->boxAlign() == BSTRETCH))
relayoutChildren = true;
- m_height = 0;
+ setHeight(0);
m_overflowHeight = 0;
m_flexingChildren = m_stretchingChildren = false;
@@ -243,9 +224,9 @@ void RenderFlexibleBox::layoutBlock(bool relayoutChildren)
// For overflow:scroll blocks, ensure we have both scrollbars in place always.
if (scrollsOverflow()) {
if (style()->overflowX() == OSCROLL)
- m_layer->setHasHorizontalScrollbar(true);
+ layer()->setHasHorizontalScrollbar(true);
if (style()->overflowY() == OSCROLL)
- m_layer->setHasVerticalScrollbar(true);
+ layer()->setHasVerticalScrollbar(true);
}
if (isHorizontal())
@@ -253,21 +234,21 @@ void RenderFlexibleBox::layoutBlock(bool relayoutChildren)
else
layoutVerticalBox(relayoutChildren);
- int oldHeight = m_height;
+ int oldHeight = height();
calcHeight();
- if (oldHeight != m_height) {
+ if (oldHeight != height()) {
// If the block got expanded in size, then increase our overflowheight to match.
- if (m_overflowHeight > m_height)
+ if (m_overflowHeight > height())
m_overflowHeight -= (borderBottom() + paddingBottom() + horizontalScrollbarHeight());
- if (m_overflowHeight < m_height)
- m_overflowHeight = m_height;
+ if (m_overflowHeight < height())
+ m_overflowHeight = height();
}
- if (previousHeight != m_height)
+ if (previousHeight != height())
relayoutChildren = true;
layoutPositionedObjects(relayoutChildren || isRoot());
- if (!isFloatingOrPositioned() && m_height == 0) {
+ if (!isFloatingOrPositioned() && height() == 0) {
// We are a block with no border and padding and a computed height
// of 0. The CSS spec states that zero-height blocks collapse their margins
// together.
@@ -286,15 +267,15 @@ void RenderFlexibleBox::layoutBlock(bool relayoutChildren)
}
// Always ensure our overflow width is at least as large as our width.
- if (m_overflowWidth < m_width)
- m_overflowWidth = m_width;
+ if (m_overflowWidth < width())
+ m_overflowWidth = width();
if (!hasOverflowClip()) {
for (ShadowData* boxShadow = style()->boxShadow(); boxShadow; boxShadow = boxShadow->next) {
m_overflowLeft = min(m_overflowLeft, boxShadow->x - boxShadow->blur);
- m_overflowWidth = max(m_overflowWidth, m_width + boxShadow->x + boxShadow->blur);
+ m_overflowWidth = max(m_overflowWidth, width() + boxShadow->x + boxShadow->blur);
m_overflowTop = min(m_overflowTop, boxShadow->y - boxShadow->blur);
- m_overflowHeight = max(m_overflowHeight, m_height + boxShadow->y + boxShadow->blur);
+ m_overflowHeight = max(m_overflowHeight, height() + boxShadow->y + boxShadow->blur);
}
if (hasReflection()) {
@@ -311,11 +292,10 @@ void RenderFlexibleBox::layoutBlock(bool relayoutChildren)
// Update our scrollbars if we're overflow:auto/scroll/hidden now that we know if
// we overflow or not.
if (hasOverflowClip())
- m_layer->updateScrollInfoAfterLayout();
+ layer()->updateScrollInfoAfterLayout();
// Repaint with our new bounds if they are different from our old bounds.
- if (checkForRepaint)
- repaintAfterLayoutIfNeeded(oldBounds, oldOutlineBox);
+ repainter.repaintAfterLayout();
setNeedsLayout(false);
}
@@ -332,11 +312,11 @@ void RenderFlexibleBox::layoutHorizontalBox(bool relayoutChildren)
unsigned int lowestFlexGroup = 0;
bool haveFlex = false;
int remainingSpace = 0;
- m_overflowHeight = m_height;
+ m_overflowHeight = height();
// The first walk over our kids is to find out if we have any flexible children.
FlexBoxIterator iterator(this);
- RenderObject* child = iterator.next();
+ RenderBox* child = iterator.next();
while (child) {
// Check to see if this child flexes.
if (!child->isPositioned() && child->style()->boxFlex() > 0.0f) {
@@ -361,8 +341,8 @@ void RenderFlexibleBox::layoutHorizontalBox(bool relayoutChildren)
// their preferred widths. The second pass handles flexing the children.
do {
// Reset our height.
- m_height = yPos;
- m_overflowHeight = m_height;
+ setHeight(yPos);
+ m_overflowHeight = height();
xPos = borderLeft() + paddingLeft();
// Our first pass is done without flexing. We simply lay the children
@@ -388,9 +368,10 @@ void RenderFlexibleBox::layoutHorizontalBox(bool relayoutChildren)
// Update our height and overflow height.
if (style()->boxAlign() == BBASELINE) {
- int ascent = child->marginTop() + child->getBaselineOfFirstLineBox();
+ int ascent = child->firstLineBoxBaseline();
if (ascent == -1)
- ascent = child->marginTop() + child->height() + child->marginBottom();
+ ascent = child->height() + child->marginBottom();
+ ascent += child->marginTop();
int descent = (child->marginTop() + child->height() + child->marginBottom()) - ascent;
// Update our maximum ascent.
@@ -400,28 +381,28 @@ void RenderFlexibleBox::layoutHorizontalBox(bool relayoutChildren)
maxDescent = max(maxDescent, descent);
// Now update our height.
- m_height = max(yPos + maxAscent + maxDescent, m_height);
+ setHeight(max(yPos + maxAscent + maxDescent, height()));
}
else
- m_height = max(m_height, yPos + child->marginTop() + child->height() + child->marginBottom());
+ setHeight(max(height(), yPos + child->marginTop() + child->height() + child->marginBottom()));
child = iterator.next();
}
if (!iterator.first() && hasLineIfEmpty())
- m_height += lineHeight(true, true);
+ setHeight(height() + lineHeight(true, true));
- m_height += toAdd;
+ setHeight(height() + toAdd);
// Always make sure our overflowheight is at least our height.
- if (m_overflowHeight < m_height)
- m_overflowHeight = m_height;
+ if (m_overflowHeight < height())
+ m_overflowHeight = height();
- oldHeight = m_height;
+ oldHeight = height();
calcHeight();
relayoutChildren = false;
- if (oldHeight != m_height)
+ if (oldHeight != height())
heightSpecified = true;
// Now that our height is actually known, we can place our boxes.
@@ -430,13 +411,13 @@ void RenderFlexibleBox::layoutHorizontalBox(bool relayoutChildren)
while (child) {
if (child->isPositioned()) {
child->containingBlock()->insertPositionedObject(child);
- if (child->hasStaticX()) {
+ if (child->style()->hasStaticX()) {
if (style()->direction() == LTR)
- child->setStaticX(xPos);
- else child->setStaticX(width() - xPos);
+ child->layer()->setStaticX(xPos);
+ else child->layer()->setStaticX(width() - xPos);
}
- if (child->hasStaticY())
- child->setStaticY(yPos);
+ if (child->style()->hasStaticY())
+ child->layer()->setStaticY(yPos);
child = iterator.next();
continue;
}
@@ -445,7 +426,7 @@ void RenderFlexibleBox::layoutHorizontalBox(bool relayoutChildren)
// fill the height of a containing box by default.
// Now do a layout.
int oldChildHeight = child->height();
- static_cast<RenderBox*>(child)->calcHeight();
+ child->calcHeight();
if (oldChildHeight != child->height())
child->setChildNeedsLayout(true, false);
child->layoutIfNeeded();
@@ -458,9 +439,10 @@ void RenderFlexibleBox::layoutHorizontalBox(bool relayoutChildren)
childY += child->marginTop() + max(0, (contentHeight() - (child->height() + child->marginTop() + child->marginBottom()))/2);
break;
case BBASELINE: {
- int ascent = child->marginTop() + child->getBaselineOfFirstLineBox();
+ int ascent = child->firstLineBoxBaseline();
if (ascent == -1)
- ascent = child->marginTop() + child->height() + child->marginBottom();
+ ascent = child->height() + child->marginBottom();
+ ascent += child->marginTop();
childY += child->marginTop() + (maxAscent - ascent);
break;
}
@@ -475,10 +457,10 @@ void RenderFlexibleBox::layoutHorizontalBox(bool relayoutChildren)
placeChild(child, xPos, childY);
if (child->isRenderBlock())
- static_cast<RenderBlock*>(child)->addVisualOverflow(static_cast<RenderBlock*>(child)->floatRect());
+ toRenderBlock(child)->addVisualOverflow(toRenderBlock(child)->floatRect());
m_overflowHeight = max(m_overflowHeight, childY + child->overflowHeight(false));
- m_overflowTop = min(m_overflowTop, child->yPos() + child->overflowTop(false));
+ m_overflowTop = min(m_overflowTop, child->y() + child->overflowTop(false));
xPos += child->width() + child->marginRight();
@@ -619,7 +601,7 @@ void RenderFlexibleBox::layoutHorizontalBox(bool relayoutChildren)
remainingSpace -= (remainingSpace/totalChildren);
totalChildren--;
- placeChild(child, child->xPos()+offset, child->yPos());
+ placeChild(child, child->x()+offset, child->y());
child = iterator.next();
}
}
@@ -634,7 +616,7 @@ void RenderFlexibleBox::layoutHorizontalBox(bool relayoutChildren)
child = iterator.next();
continue;
}
- placeChild(child, child->xPos()+offset, child->yPos());
+ placeChild(child, child->x()+offset, child->y());
child = iterator.next();
}
}
@@ -646,20 +628,20 @@ void RenderFlexibleBox::layoutHorizontalBox(bool relayoutChildren)
}
if (child) {
- m_overflowLeft = min(child->xPos() + child->overflowLeft(false), m_overflowLeft);
+ m_overflowLeft = min(child->x() + child->overflowLeft(false), m_overflowLeft);
- RenderObject* lastChild = child;
+ RenderBox* lastChild = child;
while ((child = iterator.next())) {
if (!child->isPositioned())
lastChild = child;
}
- m_overflowWidth = max(lastChild->xPos() + lastChild->overflowWidth(false), m_overflowWidth);
+ m_overflowWidth = max(lastChild->x() + lastChild->overflowWidth(false), m_overflowWidth);
}
// So that the calcHeight in layoutBlock() knows to relayout positioned objects because of
// a height change, we revert our height back to the intrinsic height before returning.
if (heightSpecified)
- m_height = oldHeight;
+ setHeight(oldHeight);
}
void RenderFlexibleBox::layoutVerticalBox(bool relayoutChildren)
@@ -667,7 +649,7 @@ void RenderFlexibleBox::layoutVerticalBox(bool relayoutChildren)
int xPos = borderLeft() + paddingLeft();
int yPos = borderTop() + paddingTop();
if( style()->direction() == RTL )
- xPos = m_width - paddingRight() - borderRight();
+ xPos = width() - paddingRight() - borderRight();
int toAdd = borderBottom() + paddingBottom() + horizontalScrollbarHeight();
bool heightSpecified = false;
int oldHeight = 0;
@@ -679,7 +661,7 @@ void RenderFlexibleBox::layoutVerticalBox(bool relayoutChildren)
// The first walk over our kids is to find out if we have any flexible children.
FlexBoxIterator iterator(this);
- RenderObject *child = iterator.next();
+ RenderBox* child = iterator.next();
while (child) {
// Check to see if this child flexes.
if (!child->isPositioned() && child->style()->boxFlex() > 0.0f) {
@@ -714,13 +696,13 @@ void RenderFlexibleBox::layoutVerticalBox(bool relayoutChildren)
// Dirty all the positioned objects.
if (child->isRenderBlock()) {
- static_cast<RenderBlock*>(child)->markPositionedObjectsForLayout();
- static_cast<RenderBlock*>(child)->clearTruncation();
+ toRenderBlock(child)->markPositionedObjectsForLayout();
+ toRenderBlock(child)->clearTruncation();
}
}
child->layoutIfNeeded();
if (child->style()->height().isAuto() && child->isBlockFlow())
- maxLineCount = max(maxLineCount, static_cast<RenderBlock*>(child)->lineCount());
+ maxLineCount = max(maxLineCount, toRenderBlock(child)->lineCount());
}
child = iterator.next();
}
@@ -733,7 +715,7 @@ void RenderFlexibleBox::layoutVerticalBox(bool relayoutChildren)
if (child->isPositioned() || !child->style()->height().isAuto() || !child->isBlockFlow())
continue;
- RenderBlock* blockChild = static_cast<RenderBlock*>(child);
+ RenderBlock* blockChild = toRenderBlock(child);
int lineCount = blockChild->lineCount();
if (lineCount <= numVisibleLines)
continue;
@@ -762,9 +744,9 @@ void RenderFlexibleBox::layoutVerticalBox(bool relayoutChildren)
InlineBox* anchorBox = lastLine->lastChild();
if (!anchorBox)
continue;
- if (!anchorBox->object()->element())
+ if (!anchorBox->renderer()->node())
continue;
- if (!anchorBox->object()->element()->isLink())
+ if (!anchorBox->renderer()->node()->isLink())
continue;
RootInlineBox* lastVisibleLine = blockChild->lineAtIndex(numVisibleLines-1);
@@ -781,23 +763,27 @@ void RenderFlexibleBox::layoutVerticalBox(bool relayoutChildren)
int totalWidth = ellipsisAndSpaceWidth + anchorBox->width();
// See if this width can be accommodated on the last visible line
- RenderBlock* destBlock = static_cast<RenderBlock*>(lastVisibleLine->object());
- RenderBlock* srcBlock = static_cast<RenderBlock*>(lastLine->object());
+ RenderBlock* destBlock = toRenderBlock(lastVisibleLine->renderer());
+ RenderBlock* srcBlock = toRenderBlock(lastLine->renderer());
// FIXME: Directions of src/destBlock could be different from our direction and from one another.
if (srcBlock->style()->direction() != LTR)
continue;
if (destBlock->style()->direction() != LTR)
continue;
+ int ltr = true;
+
+ int blockRightEdge = destBlock->rightOffset(lastVisibleLine->y(), false);
+ int blockLeftEdge = destBlock->leftOffset(lastVisibleLine->y(), false);
- int blockEdge = destBlock->rightOffset(lastVisibleLine->yPos());
- if (!lastVisibleLine->canAccommodateEllipsis(true, blockEdge,
- lastVisibleLine->xPos() + lastVisibleLine->width(),
+ int blockEdge = ltr ? blockRightEdge : blockLeftEdge;
+ if (!lastVisibleLine->canAccommodateEllipsis(ltr, blockEdge,
+ lastVisibleLine->x() + lastVisibleLine->width(),
totalWidth))
continue;
// Let the truncation code kick in.
- lastVisibleLine->placeEllipsis(ellipsisAndSpaceStr, true, blockEdge, totalWidth, anchorBox);
+ lastVisibleLine->placeEllipsis(ellipsisAndSpaceStr, ltr, blockLeftEdge, blockRightEdge, totalWidth, anchorBox);
destBlock->setHasMarkupTruncation(true);
}
}
@@ -808,9 +794,9 @@ void RenderFlexibleBox::layoutVerticalBox(bool relayoutChildren)
// Our first pass is done without flexing. We simply lay the children
// out within the box.
do {
- m_height = borderTop() + paddingTop();
- int minHeight = m_height + toAdd;
- m_overflowHeight = m_height;
+ setHeight(borderTop() + paddingTop());
+ int minHeight = height() + toAdd;
+ m_overflowHeight = height();
child = iterator.first();
while (child) {
@@ -821,14 +807,14 @@ void RenderFlexibleBox::layoutVerticalBox(bool relayoutChildren)
if (child->isPositioned())
{
child->containingBlock()->insertPositionedObject(child);
- if (child->hasStaticX()) {
+ if (child->style()->hasStaticX()) {
if (style()->direction() == LTR)
- child->setStaticX(borderLeft()+paddingLeft());
+ child->layer()->setStaticX(borderLeft()+paddingLeft());
else
- child->setStaticX(borderRight()+paddingRight());
+ child->layer()->setStaticX(borderRight()+paddingRight());
}
- if (child->hasStaticY())
- child->setStaticY(m_height);
+ if (child->style()->hasStaticY())
+ child->layer()->setStaticY(height());
child = iterator.next();
continue;
}
@@ -837,7 +823,7 @@ void RenderFlexibleBox::layoutVerticalBox(bool relayoutChildren)
child->calcVerticalMargins();
// Add in the child's marginTop to our height.
- m_height += child->marginTop();
+ setHeight(height() + child->marginTop());
// Now do a layout.
child->layoutIfNeeded();
@@ -864,39 +850,39 @@ void RenderFlexibleBox::layoutVerticalBox(bool relayoutChildren)
}
// Place the child.
- placeChild(child, childX, m_height);
- m_height += child->height() + child->marginBottom();
+ placeChild(child, childX, height());
+ setHeight(height() + child->height() + child->marginBottom());
if (child->isRenderBlock())
- static_cast<RenderBlock*>(child)->addVisualOverflow(static_cast<RenderBlock*>(child)->floatRect());
+ toRenderBlock(child)->addVisualOverflow(toRenderBlock(child)->floatRect());
// See if this child has made our overflow need to grow.
- m_overflowWidth = max(child->xPos() + child->overflowWidth(false), m_overflowWidth);
- m_overflowLeft = min(child->xPos() + child->overflowLeft(false), m_overflowLeft);
+ m_overflowWidth = max(child->x() + child->overflowWidth(false), m_overflowWidth);
+ m_overflowLeft = min(child->x() + child->overflowLeft(false), m_overflowLeft);
child = iterator.next();
}
- yPos = m_height;
+ yPos = height();
if (!iterator.first() && hasLineIfEmpty())
- m_height += lineHeight(true, true);
+ setHeight(height() + lineHeight(true, true));
- m_height += toAdd;
+ setHeight(height() + toAdd);
// Negative margins can cause our height to shrink below our minimal height (border/padding).
// If this happens, ensure that the computed height is increased to the minimal height.
- if (m_height < minHeight)
- m_height = minHeight;
+ if (height() < minHeight)
+ setHeight(minHeight);
// Always make sure our overflowheight is at least our height.
- if (m_overflowHeight < m_height)
- m_overflowHeight = m_height;
+ if (m_overflowHeight < height())
+ m_overflowHeight = height();
// Now we have to calc our height, so we know how much space we have remaining.
- oldHeight = m_height;
+ oldHeight = height();
calcHeight();
- if (oldHeight != m_height)
+ if (oldHeight != height())
heightSpecified = true;
remainingSpace = borderTop() + paddingTop() + contentHeight() - yPos;
@@ -1028,7 +1014,7 @@ void RenderFlexibleBox::layoutVerticalBox(bool relayoutChildren)
offset += remainingSpace/totalChildren;
remainingSpace -= (remainingSpace/totalChildren);
totalChildren--;
- placeChild(child, child->xPos(), child->yPos()+offset);
+ placeChild(child, child->x(), child->y()+offset);
child = iterator.next();
}
}
@@ -1043,7 +1029,7 @@ void RenderFlexibleBox::layoutVerticalBox(bool relayoutChildren)
child = iterator.next();
continue;
}
- placeChild(child, child->xPos(), child->yPos()+offset);
+ placeChild(child, child->x(), child->y()+offset);
child = iterator.next();
}
}
@@ -1055,28 +1041,28 @@ void RenderFlexibleBox::layoutVerticalBox(bool relayoutChildren)
}
if (child) {
- m_overflowTop = min(child->yPos() + child->overflowTop(false), m_overflowTop);
+ m_overflowTop = min(child->y() + child->overflowTop(false), m_overflowTop);
- RenderObject* lastChild = child;
+ RenderBox* lastChild = child;
while ((child = iterator.next())) {
if (!child->isPositioned())
lastChild = child;
}
- m_overflowHeight = max(lastChild->yPos() + lastChild->overflowHeight(false), m_overflowHeight);
+ m_overflowHeight = max(lastChild->y() + lastChild->overflowHeight(false), m_overflowHeight);
}
// So that the calcHeight in layoutBlock() knows to relayout positioned objects because of
// a height change, we revert our height back to the intrinsic height before returning.
if (heightSpecified)
- m_height = oldHeight;
+ setHeight(oldHeight);
}
-void RenderFlexibleBox::placeChild(RenderObject* child, int x, int y)
+void RenderFlexibleBox::placeChild(RenderBox* child, int x, int y)
{
- IntRect oldRect(child->xPos(), child->yPos() , child->width(), child->height());
+ IntRect oldRect(child->x(), child->y() , child->width(), child->height());
// Place the child.
- child->setPos(x, y);
+ child->setLocation(x, y);
// If the child moved, we have to repaint it as well as any floating/positioned
// descendants. An exception is if we need a layout. In this case, we know we're going to
@@ -1085,7 +1071,7 @@ void RenderFlexibleBox::placeChild(RenderObject* child, int x, int y)
child->repaintDuringLayoutIfMoved(oldRect);
}
-int RenderFlexibleBox::allowedChildFlex(RenderObject* child, bool expanding, unsigned int group)
+int RenderFlexibleBox::allowedChildFlex(RenderBox* child, bool expanding, unsigned int group)
{
if (child->isPositioned() || child->style()->boxFlex() == 0.0f || child->style()->boxFlexGroup() != group)
return 0;
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderFlexibleBox.h b/src/3rdparty/webkit/WebCore/rendering/RenderFlexibleBox.h
index f48caf5..a0f84ce 100644
--- a/src/3rdparty/webkit/WebCore/rendering/RenderFlexibleBox.h
+++ b/src/3rdparty/webkit/WebCore/rendering/RenderFlexibleBox.h
@@ -48,10 +48,10 @@ public:
virtual bool isFlexingChildren() const { return m_flexingChildren; }
virtual bool isStretchingChildren() const { return m_stretchingChildren; }
- void placeChild(RenderObject* child, int x, int y);
+ void placeChild(RenderBox* child, int x, int y);
protected:
- int allowedChildFlex(RenderObject* child, bool expanding, unsigned group);
+ int allowedChildFlex(RenderBox* child, bool expanding, unsigned group);
bool hasMultipleLines() const { return style()->boxLines() == MULTIPLE; }
bool isVertical() const { return style()->boxOrient() == VERTICAL; }
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderFlow.cpp b/src/3rdparty/webkit/WebCore/rendering/RenderFlow.cpp
deleted file mode 100644
index 86a92f3..0000000
--- a/src/3rdparty/webkit/WebCore/rendering/RenderFlow.cpp
+++ /dev/null
@@ -1,883 +0,0 @@
-/*
- * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
- * (C) 1999 Antti Koivisto (koivisto@kde.org)
- * Copyright (C) 2003, 2004, 2005, 2006, 2007 Apple Inc. 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
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#include "config.h"
-#include "RenderFlow.h"
-
-#include "Document.h"
-#include "GraphicsContext.h"
-#include "HTMLNames.h"
-#include "InlineTextBox.h"
-#include "RenderArena.h"
-#include "RenderInline.h"
-#include "RenderLayer.h"
-#include "RenderView.h"
-
-using namespace std;
-
-namespace WebCore {
-
-using namespace HTMLNames;
-
-#ifndef NDEBUG
-
-RenderFlow::~RenderFlow()
-{
- ASSERT(!m_firstLineBox);
- ASSERT(!m_lastLineBox);
-}
-
-#endif
-
-RenderFlow* RenderFlow::createAnonymousFlow(Document* doc, PassRefPtr<RenderStyle> style)
-{
- RenderFlow* result;
- if (style->display() == INLINE)
- result = new (doc->renderArena()) RenderInline(doc);
- else
- result = new (doc->renderArena()) RenderBlock(doc);
- result->setStyle(style);
- return result;
-}
-
-RenderFlow* RenderFlow::continuationBefore(RenderObject* beforeChild)
-{
- if (beforeChild && beforeChild->parent() == this)
- return this;
-
- RenderFlow* curr = continuation();
- RenderFlow* nextToLast = this;
- RenderFlow* last = this;
- while (curr) {
- if (beforeChild && beforeChild->parent() == curr) {
- if (curr->firstChild() == beforeChild)
- return last;
- return curr;
- }
-
- nextToLast = last;
- last = curr;
- curr = curr->continuation();
- }
-
- if (!beforeChild && !last->firstChild())
- return nextToLast;
- return last;
-}
-
-void RenderFlow::addChildWithContinuation(RenderObject* newChild, RenderObject* beforeChild)
-{
- if (beforeChild && (beforeChild->parent()->isTableRow() || beforeChild->parent()->isTableSection() || beforeChild->parent()->isTable())) {
- RenderObject* anonymousTablePart = beforeChild->parent();
- ASSERT(anonymousTablePart->isAnonymous());
- while (!anonymousTablePart->isTable()) {
- anonymousTablePart = anonymousTablePart->parent();
- ASSERT(anonymousTablePart->isAnonymous());
- }
- return anonymousTablePart->addChild(newChild, beforeChild);
- }
-
- RenderFlow* flow = continuationBefore(beforeChild);
- ASSERT(!beforeChild || beforeChild->parent()->isRenderBlock() ||
- beforeChild->parent()->isRenderInline());
- RenderFlow* beforeChildParent = beforeChild ? static_cast<RenderFlow*>(beforeChild->parent()) :
- (flow->continuation() ? flow->continuation() : flow);
-
- if (newChild->isFloatingOrPositioned())
- return beforeChildParent->addChildToFlow(newChild, beforeChild);
-
- // A continuation always consists of two potential candidates: an inline or an anonymous
- // block box holding block children.
- bool childInline = newChild->isInline();
- bool bcpInline = beforeChildParent->isInline();
- bool flowInline = flow->isInline();
-
- if (flow == beforeChildParent)
- return flow->addChildToFlow(newChild, beforeChild);
- else {
- // The goal here is to match up if we can, so that we can coalesce and create the
- // minimal # of continuations needed for the inline.
- if (childInline == bcpInline)
- return beforeChildParent->addChildToFlow(newChild, beforeChild);
- else if (flowInline == childInline)
- return flow->addChildToFlow(newChild, 0); // Just treat like an append.
- else
- return beforeChildParent->addChildToFlow(newChild, beforeChild);
- }
-}
-
-void RenderFlow::addChild(RenderObject* newChild, RenderObject* beforeChild)
-{
- if (continuation())
- return addChildWithContinuation(newChild, beforeChild);
- return addChildToFlow(newChild, beforeChild);
-}
-
-void RenderFlow::extractLineBox(InlineFlowBox* box)
-{
- checkConsistency();
-
- m_lastLineBox = box->prevFlowBox();
- if (box == m_firstLineBox)
- m_firstLineBox = 0;
- if (box->prevLineBox())
- box->prevLineBox()->setNextLineBox(0);
- box->setPreviousLineBox(0);
- for (InlineRunBox* curr = box; curr; curr = curr->nextLineBox())
- curr->setExtracted();
-
- checkConsistency();
-}
-
-void RenderFlow::attachLineBox(InlineFlowBox* box)
-{
- checkConsistency();
-
- if (m_lastLineBox) {
- m_lastLineBox->setNextLineBox(box);
- box->setPreviousLineBox(m_lastLineBox);
- } else
- m_firstLineBox = box;
- InlineFlowBox* last = box;
- for (InlineFlowBox* curr = box; curr; curr = curr->nextFlowBox()) {
- curr->setExtracted(false);
- last = curr;
- }
- m_lastLineBox = last;
-
- checkConsistency();
-}
-
-void RenderFlow::removeLineBox(InlineFlowBox* box)
-{
- checkConsistency();
-
- if (box == m_firstLineBox)
- m_firstLineBox = box->nextFlowBox();
- if (box == m_lastLineBox)
- m_lastLineBox = box->prevFlowBox();
- if (box->nextLineBox())
- box->nextLineBox()->setPreviousLineBox(box->prevLineBox());
- if (box->prevLineBox())
- box->prevLineBox()->setNextLineBox(box->nextLineBox());
-
- checkConsistency();
-}
-
-void RenderFlow::deleteLineBoxes()
-{
- if (m_firstLineBox) {
- RenderArena* arena = renderArena();
- InlineRunBox* next;
- for (InlineRunBox* curr = m_firstLineBox; curr; curr = next) {
- next = curr->nextLineBox();
- curr->destroy(arena);
- }
- m_firstLineBox = 0;
- m_lastLineBox = 0;
- }
-}
-
-void RenderFlow::destroy()
-{
- // Detach our continuation first.
- if (m_continuation)
- m_continuation->destroy();
- m_continuation = 0;
-
- // Make sure to destroy anonymous children first while they are still connected to the rest of the tree, so that they will
- // properly dirty line boxes that they are removed from. Effects that do :before/:after only on hover could crash otherwise.
- RenderContainer::destroyLeftoverChildren();
-
- if (!documentBeingDestroyed()) {
- if (m_firstLineBox) {
- // We can't wait for RenderContainer::destroy to clear the selection,
- // because by then we will have nuked the line boxes.
- // FIXME: The SelectionController should be responsible for this when it
- // is notified of DOM mutations.
- if (isSelectionBorder())
- view()->clearSelection();
-
- // If line boxes are contained inside a root, that means we're an inline.
- // In that case, we need to remove all the line boxes so that the parent
- // lines aren't pointing to deleted children. If the first line box does
- // not have a parent that means they are either already disconnected or
- // root lines that can just be destroyed without disconnecting.
- if (m_firstLineBox->parent()) {
- for (InlineRunBox* box = m_firstLineBox; box; box = box->nextLineBox())
- box->remove();
- }
-
- // If we are an anonymous block, then our line boxes might have children
- // that will outlast this block. In the non-anonymous block case those
- // children will be destroyed by the time we return from this function.
- if (isAnonymousBlock()) {
- for (InlineFlowBox* box = m_firstLineBox; box; box = box->nextFlowBox()) {
- while (InlineBox* childBox = box->firstChild())
- childBox->remove();
- }
- }
- } else if (isInline() && parent())
- parent()->dirtyLinesFromChangedChild(this);
- }
-
- deleteLineBoxes();
-
- RenderContainer::destroy();
-}
-
-void RenderFlow::dirtyLinesFromChangedChild(RenderObject* child)
-{
- if (!parent() || (selfNeedsLayout() && !isInlineFlow()) || isTable())
- return;
-
- // If we have no first line box, then just bail early.
- if (!firstLineBox()) {
- // For an empty inline, go ahead and propagate the check up to our parent, unless the parent
- // is already dirty.
- if (isInline() && !parent()->selfNeedsLayout())
- parent()->dirtyLinesFromChangedChild(this);
- return;
- }
-
- // Try to figure out which line box we belong in. First try to find a previous
- // line box by examining our siblings. If we didn't find a line box, then use our
- // parent's first line box.
- RootInlineBox* box = 0;
- RenderObject* curr = 0;
- for (curr = child->previousSibling(); curr; curr = curr->previousSibling()) {
- if (curr->isFloatingOrPositioned())
- continue;
-
- if (curr->isReplaced()) {
- InlineBox* wrapper = curr->inlineBoxWrapper();
- if (wrapper)
- box = wrapper->root();
- } else if (curr->isText()) {
- InlineTextBox* textBox = static_cast<RenderText*>(curr)->lastTextBox();
- if (textBox)
- box = textBox->root();
- } else if (curr->isInlineFlow()) {
- InlineRunBox* runBox = static_cast<RenderFlow*>(curr)->lastLineBox();
- if (runBox)
- box = runBox->root();
- }
-
- if (box)
- break;
- }
- if (!box)
- box = firstLineBox()->root();
-
- // If we found a line box, then dirty it.
- if (box) {
- RootInlineBox* adjacentBox;
- box->markDirty();
-
- // dirty the adjacent lines that might be affected
- // NOTE: we dirty the previous line because RootInlineBox objects cache
- // the address of the first object on the next line after a BR, which we may be
- // invalidating here. For more info, see how RenderBlock::layoutInlineChildren
- // calls setLineBreakInfo with the result of findNextLineBreak. findNextLineBreak,
- // despite the name, actually returns the first RenderObject after the BR.
- // <rdar://problem/3849947> "Typing after pasting line does not appear until after window resize."
- adjacentBox = box->prevRootBox();
- if (adjacentBox)
- adjacentBox->markDirty();
- if (child->isBR() || (curr && curr->isBR())) {
- adjacentBox = box->nextRootBox();
- if (adjacentBox)
- adjacentBox->markDirty();
- }
- }
-}
-
-int RenderFlow::lineHeight(bool firstLine, bool /*isRootLineBox*/) const
-{
- if (firstLine) {
- RenderStyle* s = style(firstLine);
- Length lh = s->lineHeight();
- if (lh.isNegative()) {
- if (s == style()) {
- if (m_lineHeight == -1)
- m_lineHeight = RenderObject::lineHeight(false);
- return m_lineHeight;
- }
- return s->font().lineSpacing();
- }
- if (lh.isPercent())
- return lh.calcMinValue(s->fontSize());
- return lh.value();
- }
-
- if (m_lineHeight == -1)
- m_lineHeight = RenderObject::lineHeight(false);
- return m_lineHeight;
-}
-
-void RenderFlow::dirtyLineBoxes(bool fullLayout, bool isRootLineBox)
-{
- if (!isRootLineBox && isReplaced())
- return RenderContainer::dirtyLineBoxes(fullLayout, isRootLineBox);
-
- if (fullLayout)
- deleteLineBoxes();
- else {
- for (InlineRunBox* curr = firstLineBox(); curr; curr = curr->nextLineBox())
- curr->dirtyLineBoxes();
- }
-}
-
-InlineBox* RenderFlow::createInlineBox(bool makePlaceHolderBox, bool isRootLineBox, bool /*isOnlyRun*/)
-{
- checkConsistency();
-
- if (!isRootLineBox &&
- (isReplaced() || makePlaceHolderBox)) // Inline tables and inline blocks
- return RenderContainer::createInlineBox(false, isRootLineBox); // (or positioned element placeholders).
-
- InlineFlowBox* flowBox = 0;
- if (isInlineFlow())
- flowBox = new (renderArena()) InlineFlowBox(this);
- else
- flowBox = new (renderArena()) RootInlineBox(this);
-
- if (!m_firstLineBox)
- m_firstLineBox = m_lastLineBox = flowBox;
- else {
- m_lastLineBox->setNextLineBox(flowBox);
- flowBox->setPreviousLineBox(m_lastLineBox);
- m_lastLineBox = flowBox;
- }
-
- checkConsistency();
-
- return flowBox;
-}
-
-void RenderFlow::paintLines(PaintInfo& paintInfo, int tx, int ty)
-{
- // Only paint during the foreground/selection phases.
- if (paintInfo.phase != PaintPhaseForeground && paintInfo.phase != PaintPhaseSelection && paintInfo.phase != PaintPhaseOutline
- && paintInfo.phase != PaintPhaseSelfOutline && paintInfo.phase != PaintPhaseChildOutlines && paintInfo.phase != PaintPhaseTextClip
- && paintInfo.phase != PaintPhaseMask)
- return;
-
- bool inlineFlow = isInlineFlow();
- if (inlineFlow)
- ASSERT(m_layer); // The only way a compact/run-in/inline could paint like this is if it has a layer.
-
- // If we have no lines then we have no work to do.
- if (!firstLineBox())
- return;
-
- // We can check the first box and last box and avoid painting if we don't
- // intersect. This is a quick short-circuit that we can take to avoid walking any lines.
- // FIXME: This check is flawed in the following extremely obscure way:
- // if some line in the middle has a huge overflow, it might actually extend below the last line.
- int yPos = firstLineBox()->root()->topOverflow() - maximalOutlineSize(paintInfo.phase);
- int h = maximalOutlineSize(paintInfo.phase) + lastLineBox()->root()->bottomOverflow() - yPos;
- yPos += ty;
- if (yPos >= paintInfo.rect.bottom() || yPos + h <= paintInfo.rect.y())
- return;
-
- PaintInfo info(paintInfo);
- RenderFlowSequencedSet outlineObjects;
- info.outlineObjects = &outlineObjects;
-
- // See if our root lines intersect with the dirty rect. If so, then we paint
- // them. Note that boxes can easily overlap, so we can't make any assumptions
- // based off positions of our first line box or our last line box.
- RenderView* v = view();
- bool usePrintRect = !v->printRect().isEmpty();
- for (InlineFlowBox* curr = firstLineBox(); curr; curr = curr->nextFlowBox()) {
- if (usePrintRect) {
- // FIXME: This is a feeble effort to avoid splitting a line across two pages.
- // It is utterly inadequate, and this should not be done at paint time at all.
- // The whole way objects break across pages needs to be redone.
- // Try to avoid splitting a line vertically, but only if it's less than the height
- // of the entire page.
- if (curr->root()->bottomOverflow() - curr->root()->topOverflow() <= v->printRect().height()) {
- if (ty + curr->root()->bottomOverflow() > v->printRect().bottom()) {
- if (ty + curr->root()->topOverflow() < v->truncatedAt())
- v->setBestTruncatedAt(ty + curr->root()->topOverflow(), this);
- // If we were able to truncate, don't paint.
- if (ty + curr->root()->topOverflow() >= v->truncatedAt())
- break;
- }
- }
- }
-
- int top = min(curr->root()->topOverflow(), curr->root()->selectionTop()) - maximalOutlineSize(info.phase);
- int bottom = curr->root()->bottomOverflow() + maximalOutlineSize(info.phase);
- h = bottom - top;
- yPos = ty + top;
- if (yPos < info.rect.bottom() && yPos + h > info.rect.y())
- curr->paint(info, tx, ty);
- }
-
- if (info.phase == PaintPhaseOutline || info.phase == PaintPhaseSelfOutline || info.phase == PaintPhaseChildOutlines) {
- RenderFlowSequencedSet::iterator end = info.outlineObjects->end();
- for (RenderFlowSequencedSet::iterator it = info.outlineObjects->begin(); it != end; ++it) {
- RenderFlow* flow = *it;
- flow->paintOutline(info.context, tx, ty);
- }
- info.outlineObjects->clear();
- }
-}
-
-bool RenderFlow::hitTestLines(const HitTestRequest& request, HitTestResult& result, int x, int y, int tx, int ty, HitTestAction hitTestAction)
-{
- if (hitTestAction != HitTestForeground)
- return false;
-
- bool inlineFlow = isInlineFlow();
- if (inlineFlow)
- ASSERT(m_layer); // The only way a compact/run-in/inline could paint like this is if it has a layer.
-
- // If we have no lines then we have no work to do.
- if (!firstLineBox())
- return false;
-
- // We can check the first box and last box and avoid hit testing if we don't
- // contain the point. This is a quick short-circuit that we can take to avoid walking any lines.
- // FIXME: This check is flawed in the following extremely obscure way:
- // if some line in the middle has a huge overflow, it might actually extend below the last line.
- if ((y >= ty + lastLineBox()->root()->bottomOverflow()) || (y < ty + firstLineBox()->root()->topOverflow()))
- return false;
-
- // See if our root lines contain the point. If so, then we hit test
- // them further. Note that boxes can easily overlap, so we can't make any assumptions
- // based off positions of our first line box or our last line box.
- for (InlineFlowBox* curr = lastLineBox(); curr; curr = curr->prevFlowBox()) {
- if (y >= ty + curr->root()->topOverflow() && y < ty + curr->root()->bottomOverflow()) {
- bool inside = curr->nodeAtPoint(request, result, x, y, tx, ty);
- if (inside) {
- updateHitTestResult(result, IntPoint(x - tx, y - ty));
- return true;
- }
- }
- }
-
- return false;
-}
-
-IntRect RenderFlow::absoluteClippedOverflowRect()
-{
- if (isInlineFlow()) {
- // Only compacts and run-ins are allowed in here during layout.
- ASSERT(!view() || !view()->layoutState() || isCompact() || isRunIn());
-
- if (!firstLineBox() && !continuation())
- return IntRect();
-
- // Find our leftmost position.
- int left = 0;
- int top = firstLineBox() ? firstLineBox()->yPos() : 0;
- for (InlineRunBox* curr = firstLineBox(); curr; curr = curr->nextLineBox()) {
- if (curr == firstLineBox() || curr->xPos() < left)
- left = curr->xPos();
- }
-
- // Now invalidate a rectangle.
- int ow = style() ? style()->outlineSize() : 0;
- if (isCompact())
- left -= m_x;
-
- // We need to add in the relative position offsets of any inlines (including us) up to our
- // containing block.
- RenderBlock* cb = containingBlock();
- for (RenderObject* inlineFlow = this; inlineFlow && inlineFlow->isInlineFlow() && inlineFlow != cb;
- inlineFlow = inlineFlow->parent()) {
- if (inlineFlow->style()->position() == RelativePosition && inlineFlow->hasLayer())
- inlineFlow->layer()->relativePositionOffset(left, top);
- }
-
- IntRect r(-ow + left, -ow + top, width() + ow * 2, height() + ow * 2);
- if (cb->hasColumns())
- cb->adjustRectForColumns(r);
-
- if (cb->hasOverflowClip()) {
- // cb->height() is inaccurate if we're in the middle of a layout of |cb|, so use the
- // layer's size instead. Even if the layer's size is wrong, the layer itself will repaint
- // anyway if its size does change.
- int x = r.x();
- int y = r.y();
- IntRect boxRect(0, 0, cb->layer()->width(), cb->layer()->height());
- cb->layer()->subtractScrolledContentOffset(x, y); // For overflow:auto/scroll/hidden.
- IntRect repaintRect(x, y, r.width(), r.height());
- r = intersection(repaintRect, boxRect);
- }
- cb->computeAbsoluteRepaintRect(r);
-
- if (ow) {
- for (RenderObject* curr = firstChild(); curr; curr = curr->nextSibling()) {
- if (!curr->isText()) {
- IntRect childRect = curr->getAbsoluteRepaintRectWithOutline(ow);
- r.unite(childRect);
- }
- }
-
- if (continuation() && !continuation()->isInline()) {
- IntRect contRect = continuation()->getAbsoluteRepaintRectWithOutline(ow);
- r.unite(contRect);
- }
- }
-
- return r;
- }
-
- return RenderContainer::absoluteClippedOverflowRect();
-}
-
-int RenderFlow::lowestPosition(bool includeOverflowInterior, bool includeSelf) const
-{
- ASSERT(!isInlineFlow());
- if (!includeOverflowInterior && (hasOverflowClip() || hasControlClip()))
- return includeSelf && m_width > 0 ? overflowHeight(false) : 0;
-
- int bottom = includeSelf && m_width > 0 ? m_height : 0;
- if (!hasColumns()) {
- // FIXME: Come up with a way to use the layer tree to avoid visiting all the kids.
- // For now, we have to descend into all the children, since we may have a huge abs div inside
- // a tiny rel div buried somewhere deep in our child tree. In this case we have to get to
- // the abs div.
- for (RenderObject* c = firstChild(); c; c = c->nextSibling()) {
- if (!c->isFloatingOrPositioned() && !c->isText() && !c->isInlineFlow())
- bottom = max(bottom, c->yPos() + c->lowestPosition(false));
- }
- }
-
- if (includeSelf && isRelPositioned())
- bottom += relativePositionOffsetY();
-
- return bottom;
-}
-
-int RenderFlow::rightmostPosition(bool includeOverflowInterior, bool includeSelf) const
-{
- ASSERT(!isInlineFlow());
- if (!includeOverflowInterior && (hasOverflowClip() || hasControlClip()))
- return includeSelf && m_height > 0 ? overflowWidth(false) : 0;
-
- int right = includeSelf && m_height > 0 ? m_width : 0;
- if (!hasColumns()) {
- // FIXME: Come up with a way to use the layer tree to avoid visiting all the kids.
- // For now, we have to descend into all the children, since we may have a huge abs div inside
- // a tiny rel div buried somewhere deep in our child tree. In this case we have to get to
- // the abs div.
- for (RenderObject* c = firstChild(); c; c = c->nextSibling()) {
- if (!c->isFloatingOrPositioned() && !c->isText() && !c->isInlineFlow())
- right = max(right, c->xPos() + c->rightmostPosition(false));
- }
- }
-
- if (includeSelf && isRelPositioned())
- right += relativePositionOffsetX();
-
- return right;
-}
-
-int RenderFlow::leftmostPosition(bool includeOverflowInterior, bool includeSelf) const
-{
- ASSERT(!isInlineFlow());
- if (!includeOverflowInterior && (hasOverflowClip() || hasControlClip()))
- return includeSelf && m_height > 0 ? overflowLeft(false) : m_width;
-
- int left = includeSelf && m_height > 0 ? 0 : m_width;
- if (!hasColumns()) {
- // FIXME: Come up with a way to use the layer tree to avoid visiting all the kids.
- // For now, we have to descend into all the children, since we may have a huge abs div inside
- // a tiny rel div buried somewhere deep in our child tree. In this case we have to get to
- // the abs div.
- for (RenderObject* c = firstChild(); c; c = c->nextSibling()) {
- if (!c->isFloatingOrPositioned() && !c->isText() && !c->isInlineFlow())
- left = min(left, c->xPos() + c->leftmostPosition(false));
- }
- }
-
- if (includeSelf && isRelPositioned())
- left += relativePositionOffsetX();
-
- return left;
-}
-
-IntRect RenderFlow::localCaretRect(InlineBox* inlineBox, int caretOffset, int* extraWidthToEndOfLine)
-{
- // Do the normal calculation in most cases.
- if (firstChild() || style()->display() == INLINE)
- return RenderContainer::localCaretRect(inlineBox, caretOffset, extraWidthToEndOfLine);
-
- // This is a special case:
- // The element is not an inline element, and it's empty. So we have to
- // calculate a fake position to indicate where objects are to be inserted.
-
- // FIXME: This does not take into account either :first-line or :first-letter
- // However, as soon as some content is entered, the line boxes will be
- // constructed and this kludge is not called any more. So only the caret size
- // of an empty :first-line'd block is wrong. I think we can live with that.
- RenderStyle* currentStyle = firstLineStyle();
- int height = lineHeight(true);
- const int caretWidth = 1;
-
- enum CaretAlignment { alignLeft, alignRight, alignCenter };
-
- CaretAlignment alignment = alignLeft;
-
- switch (currentStyle->textAlign()) {
- case TAAUTO:
- case JUSTIFY:
- if (currentStyle->direction() == RTL)
- alignment = alignRight;
- break;
- case LEFT:
- case WEBKIT_LEFT:
- break;
- case CENTER:
- case WEBKIT_CENTER:
- alignment = alignCenter;
- break;
- case RIGHT:
- case WEBKIT_RIGHT:
- alignment = alignRight;
- break;
- }
-
- int x = borderLeft() + paddingLeft();
- int w = width();
-
- switch (alignment) {
- case alignLeft:
- break;
- case alignCenter:
- x = (x + w - (borderRight() + paddingRight())) / 2;
- break;
- case alignRight:
- x = w - (borderRight() + paddingRight());
- break;
- }
-
- if (extraWidthToEndOfLine) {
- if (isRenderBlock()) {
- *extraWidthToEndOfLine = w - (x + caretWidth);
- } else {
- // FIXME: This code looks wrong.
- // myRight and containerRight are set up, but then clobbered.
- // So *extraWidthToEndOfLine will always be 0 here.
-
- int myRight = x + caretWidth;
- // FIXME: why call localToAbsoluteForContent() twice here, too?
- FloatPoint absRightPoint = localToAbsoluteForContent(FloatPoint(myRight, 0));
-
- int containerRight = containingBlock()->xPos() + containingBlockWidth();
- FloatPoint absContainerPoint = localToAbsoluteForContent(FloatPoint(containerRight, 0));
-
- *extraWidthToEndOfLine = absContainerPoint.x() - absRightPoint.x();
- }
- }
-
- int y = paddingTop() + borderTop();
-
- return IntRect(x, y, caretWidth, height);
-}
-
-void RenderFlow::addFocusRingRects(GraphicsContext* graphicsContext, int tx, int ty)
-{
- if (isRenderBlock()) {
- // Continuations should include their margins in the outline rect.
- if (continuation()) {
- bool nextInlineHasLineBox = continuation()->firstLineBox();
- bool prevInlineHasLineBox = static_cast<RenderFlow*>(continuation()->element()->renderer())->firstLineBox();
- int topMargin = prevInlineHasLineBox ? collapsedMarginTop() : 0;
- int bottomMargin = nextInlineHasLineBox ? collapsedMarginBottom() : 0;
- graphicsContext->addFocusRingRect(IntRect(tx, ty - topMargin,
- width(), height() + topMargin + bottomMargin));
- } else
- graphicsContext->addFocusRingRect(IntRect(tx, ty, width(), height()));
- }
-
- if (!hasOverflowClip() && !hasControlClip()) {
- for (InlineRunBox* curr = firstLineBox(); curr; curr = curr->nextLineBox())
- graphicsContext->addFocusRingRect(IntRect(tx + curr->xPos(), ty + curr->yPos(), curr->width(), curr->height()));
-
- for (RenderObject* curr = firstChild(); curr; curr = curr->nextSibling())
- if (!curr->isText() && !curr->isListMarker()) {
- FloatPoint pos;
- // FIXME: This doesn't work correctly with transforms.
- if (curr->layer())
- pos = curr->localToAbsolute();
- else
- pos = FloatPoint(tx + curr->xPos(), ty + curr->yPos());
- curr->addFocusRingRects(graphicsContext, pos.x(), pos.y());
- }
- }
-
- if (continuation()) {
- if (isInline())
- continuation()->addFocusRingRects(graphicsContext,
- tx - containingBlock()->xPos() + continuation()->xPos(),
- ty - containingBlock()->yPos() + continuation()->yPos());
- else
- continuation()->addFocusRingRects(graphicsContext,
- tx - xPos() + continuation()->containingBlock()->xPos(),
- ty - yPos() + continuation()->containingBlock()->yPos());
- }
-}
-
-void RenderFlow::paintOutline(GraphicsContext* graphicsContext, int tx, int ty)
-{
- if (!hasOutline())
- return;
-
- if (style()->outlineStyleIsAuto() || hasOutlineAnnotation()) {
- int ow = style()->outlineWidth();
- Color oc = style()->outlineColor();
- if (!oc.isValid())
- oc = style()->color();
-
- graphicsContext->initFocusRing(ow, style()->outlineOffset());
- addFocusRingRects(graphicsContext, tx, ty);
- if (style()->outlineStyleIsAuto())
- graphicsContext->drawFocusRing(oc);
- else
- addPDFURLRect(graphicsContext, graphicsContext->focusRingBoundingRect());
- graphicsContext->clearFocusRing();
- }
-
- if (style()->outlineStyleIsAuto() || style()->outlineStyle() == BNONE)
- return;
-
- Vector<IntRect> rects;
-
- rects.append(IntRect());
- for (InlineRunBox* curr = firstLineBox(); curr; curr = curr->nextLineBox())
- rects.append(IntRect(curr->xPos(), curr->yPos(), curr->width(), curr->height()));
-
- rects.append(IntRect());
-
- for (unsigned i = 1; i < rects.size() - 1; i++)
- paintOutlineForLine(graphicsContext, tx, ty, rects.at(i - 1), rects.at(i), rects.at(i + 1));
-}
-
-void RenderFlow::paintOutlineForLine(GraphicsContext* graphicsContext, int tx, int ty,
- const IntRect& lastline, const IntRect& thisline, const IntRect& nextline)
-{
- int ow = style()->outlineWidth();
- EBorderStyle os = style()->outlineStyle();
- Color oc = style()->outlineColor();
- if (!oc.isValid())
- oc = style()->color();
-
- int offset = style()->outlineOffset();
-
- int t = ty + thisline.y() - offset;
- int l = tx + thisline.x() - offset;
- int b = ty + thisline.bottom() + offset;
- int r = tx + thisline.right() + offset;
-
- // left edge
- drawBorder(graphicsContext,
- l - ow,
- t - (lastline.isEmpty() || thisline.x() < lastline.x() || (lastline.right() - 1) <= thisline.x() ? ow : 0),
- l,
- b + (nextline.isEmpty() || thisline.x() <= nextline.x() || (nextline.right() - 1) <= thisline.x() ? ow : 0),
- BSLeft,
- oc, style()->color(), os,
- (lastline.isEmpty() || thisline.x() < lastline.x() || (lastline.right() - 1) <= thisline.x() ? ow : -ow),
- (nextline.isEmpty() || thisline.x() <= nextline.x() || (nextline.right() - 1) <= thisline.x() ? ow : -ow));
-
- // right edge
- drawBorder(graphicsContext,
- r,
- t - (lastline.isEmpty() || lastline.right() < thisline.right() || (thisline.right() - 1) <= lastline.x() ? ow : 0),
- r + ow,
- b + (nextline.isEmpty() || nextline.right() <= thisline.right() || (thisline.right() - 1) <= nextline.x() ? ow : 0),
- BSRight,
- oc, style()->color(), os,
- (lastline.isEmpty() || lastline.right() < thisline.right() || (thisline.right() - 1) <= lastline.x() ? ow : -ow),
- (nextline.isEmpty() || nextline.right() <= thisline.right() || (thisline.right() - 1) <= nextline.x() ? ow : -ow));
- // upper edge
- if (thisline.x() < lastline.x())
- drawBorder(graphicsContext,
- l - ow,
- t - ow,
- min(r+ow, (lastline.isEmpty() ? 1000000 : tx + lastline.x())),
- t ,
- BSTop, oc, style()->color(), os,
- ow,
- (!lastline.isEmpty() && tx + lastline.x() + 1 < r + ow) ? -ow : ow);
-
- if (lastline.right() < thisline.right())
- drawBorder(graphicsContext,
- max(lastline.isEmpty() ? -1000000 : tx + lastline.right(), l - ow),
- t - ow,
- r + ow,
- t ,
- BSTop, oc, style()->color(), os,
- (!lastline.isEmpty() && l - ow < tx + lastline.right()) ? -ow : ow,
- ow);
-
- // lower edge
- if (thisline.x() < nextline.x())
- drawBorder(graphicsContext,
- l - ow,
- b,
- min(r + ow, !nextline.isEmpty() ? tx + nextline.x() + 1 : 1000000),
- b + ow,
- BSBottom, oc, style()->color(), os,
- ow,
- (!nextline.isEmpty() && tx + nextline.x() + 1 < r + ow) ? -ow : ow);
-
- if (nextline.right() < thisline.right())
- drawBorder(graphicsContext,
- max(!nextline.isEmpty() ? tx + nextline.right() : -1000000, l - ow),
- b,
- r + ow,
- b + ow,
- BSBottom, oc, style()->color(), os,
- (!nextline.isEmpty() && l - ow < tx + nextline.right()) ? -ow : ow,
- ow);
-}
-
-void RenderFlow::calcMargins(int containerWidth)
-{
- m_marginLeft = style()->marginLeft().calcMinValue(containerWidth);
- m_marginRight = style()->marginRight().calcMinValue(containerWidth);
-}
-
-#ifndef NDEBUG
-
-void RenderFlow::checkConsistency() const
-{
-#ifdef CHECK_CONSISTENCY
- const InlineFlowBox* prev = 0;
- for (const InlineFlowBox* child = m_firstLineBox; child != 0; child = child->nextFlowBox()) {
- ASSERT(child->object() == this);
- ASSERT(child->prevFlowBox() == prev);
- prev = child;
- }
- ASSERT(prev == m_lastLineBox);
-#endif
-}
-
-#endif
-
-} // namespace WebCore
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderFlow.h b/src/3rdparty/webkit/WebCore/rendering/RenderFlow.h
deleted file mode 100644
index 7e3a345..0000000
--- a/src/3rdparty/webkit/WebCore/rendering/RenderFlow.h
+++ /dev/null
@@ -1,146 +0,0 @@
-/*
- * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
- * (C) 1999 Antti Koivisto (koivisto@kde.org)
- * Copyright (C) 2003, 2004, 2005, 2006, 2007 Apple Inc. 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
- * 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 RenderFlow_h
-#define RenderFlow_h
-
-#include "RenderContainer.h"
-
-namespace WebCore {
-
-/**
- * all geometry managing stuff is only in the block elements.
- *
- * Inline elements don't layout themselves, but the whole paragraph
- * gets flowed by the surrounding block element. This is, because
- * one needs to know the whole paragraph to calculate bidirectional
- * behaviour of text, so putting the layouting routines in the inline
- * elements is impossible.
- */
-class RenderFlow : public RenderContainer {
-public:
- RenderFlow(Node* node)
- : RenderContainer(node)
- , m_continuation(0)
- , m_firstLineBox(0)
- , m_lastLineBox(0)
- , m_lineHeight(-1)
- , m_childrenInline(true)
- , m_firstLine(false)
- , m_topMarginQuirk(false)
- , m_bottomMarginQuirk(false)
- , m_hasMarkupTruncation(false)
- , m_selectionState(SelectionNone)
- , m_hasColumns(false)
- , m_isContinuation(false)
- {
- }
-#ifndef NDEBUG
- virtual ~RenderFlow();
-#endif
-
- virtual RenderFlow* continuation() const { return m_continuation; }
- void setContinuation(RenderFlow* c) { m_continuation = c; }
- RenderFlow* continuationBefore(RenderObject* beforeChild);
-
- void addChildWithContinuation(RenderObject* newChild, RenderObject* beforeChild);
- virtual void addChildToFlow(RenderObject* newChild, RenderObject* beforeChild) = 0;
- virtual void addChild(RenderObject* newChild, RenderObject* beforeChild = 0);
-
- static RenderFlow* createAnonymousFlow(Document*, PassRefPtr<RenderStyle>);
-
- void extractLineBox(InlineFlowBox*);
- void attachLineBox(InlineFlowBox*);
- void removeLineBox(InlineFlowBox*);
- void deleteLineBoxes();
- virtual void destroy();
-
- virtual void dirtyLinesFromChangedChild(RenderObject* child);
-
- virtual int lineHeight(bool firstLine, bool isRootLineBox = false) const;
-
- InlineFlowBox* firstLineBox() const { return m_firstLineBox; }
- InlineFlowBox* lastLineBox() const { return m_lastLineBox; }
-
- virtual InlineBox* createInlineBox(bool makePlaceHolderBox, bool isRootLineBox, bool isOnlyRun=false);
- virtual void dirtyLineBoxes(bool fullLayout, bool isRootLineBox = false);
-
- void paintLines(PaintInfo&, int tx, int ty);
- bool hitTestLines(const HitTestRequest&, HitTestResult&, int x, int y, int tx, int ty, HitTestAction);
-
- virtual IntRect absoluteClippedOverflowRect();
-
- virtual int lowestPosition(bool includeOverflowInterior = true, bool includeSelf = true) const;
- virtual int rightmostPosition(bool includeOverflowInterior = true, bool includeSelf = true) const;
- virtual int leftmostPosition(bool includeOverflowInterior = true, bool includeSelf = true) const;
-
- virtual IntRect localCaretRect(InlineBox*, int caretOffset, int* extraWidthToEndOfLine = 0);
-
- virtual void addFocusRingRects(GraphicsContext*, int tx, int ty);
- void paintOutlineForLine(GraphicsContext*, int tx, int ty, const IntRect& prevLine, const IntRect& thisLine, const IntRect& nextLine);
- void paintOutline(GraphicsContext*, int tx, int ty);
-
- virtual bool hasColumns() const { return m_hasColumns; }
-
- void calcMargins(int containerWidth);
-
- void checkConsistency() const;
-
-private:
- // An inline can be split with blocks occurring in between the inline content.
- // When this occurs we need a pointer to our next object. We can basically be
- // split into a sequence of inlines and blocks. The continuation will either be
- // an anonymous block (that houses other blocks) or it will be an inline flow.
- RenderFlow* m_continuation;
-
-protected:
- // For block flows, each box represents the root inline box for a line in the
- // paragraph.
- // For inline flows, each box represents a portion of that inline.
- InlineFlowBox* m_firstLineBox;
- InlineFlowBox* m_lastLineBox;
-
- mutable int m_lineHeight;
-
- // These bitfields are moved here from subclasses to pack them together
- // from RenderBlock
- bool m_childrenInline : 1;
- bool m_firstLine : 1;
- bool m_topMarginQuirk : 1;
- bool m_bottomMarginQuirk : 1;
- bool m_hasMarkupTruncation : 1;
- unsigned m_selectionState : 3; // SelectionState
- bool m_hasColumns : 1;
-
- // from RenderInline
- bool m_isContinuation : 1; // Whether or not we're a continuation of an inline.
-};
-
-#ifdef NDEBUG
-inline void RenderFlow::checkConsistency() const
-{
-}
-#endif
-
-} // namespace WebCore
-
-#endif // RenderFlow_h
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderForeignObject.cpp b/src/3rdparty/webkit/WebCore/rendering/RenderForeignObject.cpp
index 83401fc..b15d55c 100644
--- a/src/3rdparty/webkit/WebCore/rendering/RenderForeignObject.cpp
+++ b/src/3rdparty/webkit/WebCore/rendering/RenderForeignObject.cpp
@@ -1,7 +1,6 @@
/*
- * This file is part of the WebKit project.
- *
* Copyright (C) 2006 Apple Computer, Inc.
+ * Copyright (C) 2009 Google, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -29,6 +28,7 @@
#include "RenderView.h"
#include "SVGForeignObjectElement.h"
#include "SVGLength.h"
+#include "SVGRenderSupport.h"
#include "SVGTransformList.h"
namespace WebCore {
@@ -38,93 +38,84 @@ RenderForeignObject::RenderForeignObject(SVGForeignObjectElement* node)
{
}
-TransformationMatrix RenderForeignObject::translationForAttributes()
+TransformationMatrix RenderForeignObject::translationForAttributes() const
{
- SVGForeignObjectElement* foreign = static_cast<SVGForeignObjectElement*>(element());
+ SVGForeignObjectElement* foreign = static_cast<SVGForeignObjectElement*>(node());
return TransformationMatrix().translate(foreign->x().value(foreign), foreign->y().value(foreign));
}
-void RenderForeignObject::paint(PaintInfo& paintInfo, int parentX, int parentY)
+void RenderForeignObject::paint(PaintInfo& paintInfo, int, int)
{
if (paintInfo.context->paintingDisabled())
return;
- paintInfo.context->save();
- paintInfo.context->concatCTM(TransformationMatrix().translate(parentX, parentY));
- paintInfo.context->concatCTM(localTransform());
- paintInfo.context->concatCTM(translationForAttributes());
- paintInfo.context->clip(getClipRect(parentX, parentY));
+ // Copy the paint info so that modifications to the damage rect do not affect callers
+ PaintInfo childPaintInfo = paintInfo;
+ childPaintInfo.context->save();
+ applyTransformToPaintInfo(childPaintInfo, localToParentTransform());
+ childPaintInfo.context->clip(clipRect(0, 0));
float opacity = style()->opacity();
if (opacity < 1.0f)
- // FIXME: Possible optimization by clipping to bbox here, once relativeBBox is implemented & clip, mask and filter support added.
- paintInfo.context->beginTransparencyLayer(opacity);
+ childPaintInfo.context->beginTransparencyLayer(opacity);
- PaintInfo pi(paintInfo);
- pi.rect = absoluteTransform().inverse().mapRect(paintInfo.rect);
- RenderBlock::paint(pi, 0, 0);
+ RenderBlock::paint(childPaintInfo, 0, 0);
if (opacity < 1.0f)
- paintInfo.context->endTransparencyLayer();
+ childPaintInfo.context->endTransparencyLayer();
- paintInfo.context->restore();
+ childPaintInfo.context->restore();
}
-void RenderForeignObject::computeAbsoluteRepaintRect(IntRect& r, bool f)
+FloatRect RenderForeignObject::objectBoundingBox() const
{
- TransformationMatrix transform = translationForAttributes() * localTransform();
- r = transform.mapRect(r);
+ return borderBoxRect();
+}
- RenderBlock::computeAbsoluteRepaintRect(r, f);
+FloatRect RenderForeignObject::repaintRectInLocalCoordinates() const
+{
+ // HACK: to maintain historical LayoutTest results for now.
+ // RenderForeignObject is a RenderBlock (not a RenderSVGModelObject) so this
+ // should not affect repaint correctness. But it should really be:
+ // return borderBoxRect();
+ return FloatRect();
}
-bool RenderForeignObject::requiresLayer()
+void RenderForeignObject::computeRectForRepaint(RenderBoxModelObject* repaintContainer, IntRect& rect, bool fixed)
{
- return false;
+ rect = localToParentTransform().mapRect(rect);
+ RenderBlock::computeRectForRepaint(repaintContainer, rect, fixed);
}
-bool RenderForeignObject::calculateLocalTransform()
+TransformationMatrix RenderForeignObject::localToParentTransform() const
{
- TransformationMatrix oldTransform = m_localTransform;
- m_localTransform = static_cast<SVGForeignObjectElement*>(element())->animatedLocalTransform();
- return (oldTransform != m_localTransform);
+ return localTransform() * translationForAttributes();
}
void RenderForeignObject::layout()
{
ASSERT(needsLayout());
+ ASSERT(!view()->layoutStateEnabled()); // RenderSVGRoot disables layoutState for the SVG rendering tree.
- // Arbitrary affine transforms are incompatible with LayoutState.
- view()->disableLayoutState();
-
- IntRect oldBounds;
- IntRect oldOutlineBox;
- bool checkForRepaint = checkForRepaintDuringLayout();
- if (checkForRepaint) {
- oldBounds = m_absoluteBounds;
- oldOutlineBox = absoluteOutlineBounds();
- }
-
- calculateLocalTransform();
-
- RenderBlock::layout();
-
- m_absoluteBounds = absoluteClippedOverflowRect();
+ LayoutRepainter repainter(*this, checkForRepaintDuringLayout());
+ m_localTransform = static_cast<SVGForeignObjectElement*>(node())->animatedLocalTransform();
- if (checkForRepaint)
- repaintAfterLayoutIfNeeded(oldBounds, oldOutlineBox);
+ RenderBlock::layout();
+ repainter.repaintAfterLayout();
- view()->enableLayoutState();
setNeedsLayout(false);
}
-bool RenderForeignObject::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, int x, int y, int tx, int ty, HitTestAction hitTestAction)
+bool RenderForeignObject::nodeAtFloatPoint(const HitTestRequest& request, HitTestResult& result, const FloatPoint& pointInParent, HitTestAction hitTestAction)
{
- TransformationMatrix totalTransform = absoluteTransform();
- totalTransform *= translationForAttributes();
- double localX, localY;
- totalTransform.inverse().map(x, y, &localX, &localY);
- return RenderBlock::nodeAtPoint(request, result, static_cast<int>(localX), static_cast<int>(localY), tx, ty, hitTestAction);
+ FloatPoint localPoint = localToParentTransform().inverse().mapPoint(pointInParent);
+ return RenderBlock::nodeAtPoint(request, result, static_cast<int>(localPoint.x()), static_cast<int>(localPoint.y()), 0, 0, hitTestAction);
+}
+
+bool RenderForeignObject::nodeAtPoint(const HitTestRequest&, HitTestResult&, int, int, int, int, HitTestAction)
+{
+ ASSERT_NOT_REACHED();
+ return false;
}
} // namespace WebCore
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderForeignObject.h b/src/3rdparty/webkit/WebCore/rendering/RenderForeignObject.h
index c7f30e9..8fdb816 100644
--- a/src/3rdparty/webkit/WebCore/rendering/RenderForeignObject.h
+++ b/src/3rdparty/webkit/WebCore/rendering/RenderForeignObject.h
@@ -1,7 +1,6 @@
/*
- * This file is part of the WebKit project.
- *
* Copyright (C) 2006 Apple Computer, Inc.
+ * Copyright (C) 2009 Google, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -39,20 +38,24 @@ public:
virtual void paint(PaintInfo&, int parentX, int parentY);
- virtual TransformationMatrix localTransform() const { return m_localTransform; }
- virtual bool calculateLocalTransform();
+ virtual TransformationMatrix localToParentTransform() const;
- virtual void computeAbsoluteRepaintRect(IntRect&, bool fixed);
- virtual bool requiresLayer();
+ virtual void computeRectForRepaint(RenderBoxModelObject* repaintContainer, IntRect&, bool fixed = false);
+ virtual bool requiresLayer() const { return false; }
virtual void layout();
+ virtual FloatRect objectBoundingBox() const;
+ virtual FloatRect repaintRectInLocalCoordinates() const;
+
+ virtual bool nodeAtFloatPoint(const HitTestRequest&, HitTestResult&, const FloatPoint& pointInParent, HitTestAction);
virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, int x, int y, int tx, int ty, HitTestAction);
private:
- TransformationMatrix translationForAttributes();
+ TransformationMatrix translationForAttributes() const;
+
+ virtual TransformationMatrix localTransform() const { return m_localTransform; }
TransformationMatrix m_localTransform;
- IntRect m_absoluteBounds;
};
} // namespace WebCore
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderFrame.cpp b/src/3rdparty/webkit/WebCore/rendering/RenderFrame.cpp
index 15bd24e..a7b131b 100644
--- a/src/3rdparty/webkit/WebCore/rendering/RenderFrame.cpp
+++ b/src/3rdparty/webkit/WebCore/rendering/RenderFrame.cpp
@@ -1,10 +1,8 @@
-/**
- * This file is part of the KDE project.
- *
+/*
* Copyright (C) 1999 Lars Knoll (knoll@kde.org)
* (C) 2000 Simon Hausmann <hausmann@kde.org>
* (C) 2000 Stefan Schimanski (1Stein@gmx.de)
- * Copyright (C) 2004, 2005, 2006 Apple Computer, Inc.
+ * Copyright (C) 2004, 2005, 2006, 2009 Apple Inc. 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
@@ -25,15 +23,12 @@
#include "config.h"
#include "RenderFrame.h"
-#include "RenderFrameSet.h"
+
#include "FrameView.h"
-#include "HTMLFrameSetElement.h"
-#include "HTMLNames.h"
+#include "HTMLFrameElement.h"
namespace WebCore {
-using namespace HTMLNames;
-
RenderFrame::RenderFrame(HTMLFrameElement* frame)
: RenderPart(frame)
{
@@ -42,21 +37,25 @@ RenderFrame::RenderFrame(HTMLFrameElement* frame)
FrameEdgeInfo RenderFrame::edgeInfo() const
{
- return FrameEdgeInfo(element()->noResize(), element()->hasFrameBorder());
+ HTMLFrameElement* element = static_cast<HTMLFrameElement*>(node());
+ return FrameEdgeInfo(element->noResize(), element->hasFrameBorder());
}
void RenderFrame::viewCleared()
{
- if (element() && m_widget && m_widget->isFrameView()) {
- FrameView* view = static_cast<FrameView*>(m_widget);
- int marginw = element()->getMarginWidth();
- int marginh = element()->getMarginHeight();
-
- if (marginw != -1)
- view->setMarginWidth(marginw);
- if (marginh != -1)
- view->setMarginHeight(marginh);
- }
+ HTMLFrameElement* element = static_cast<HTMLFrameElement*>(node());
+ if (!element || !widget() || !widget()->isFrameView())
+ return;
+
+ FrameView* view = static_cast<FrameView*>(widget());
+
+ int marginw = element->getMarginWidth();
+ int marginh = element->getMarginHeight();
+
+ if (marginw != -1)
+ view->setMarginWidth(marginw);
+ if (marginh != -1)
+ view->setMarginHeight(marginh);
}
} // namespace WebCore
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderFrame.h b/src/3rdparty/webkit/WebCore/rendering/RenderFrame.h
index 49aedd3..2716e14 100644
--- a/src/3rdparty/webkit/WebCore/rendering/RenderFrame.h
+++ b/src/3rdparty/webkit/WebCore/rendering/RenderFrame.h
@@ -1,9 +1,7 @@
/*
- * This file is part of the KDE project.
- *
* Copyright (C) 1999 Lars Knoll (knoll@kde.org)
* (C) 2000 Simon Hausmann <hausmann@kde.org>
- * Copyright (C) 2006 Apple Computer, Inc.
+ * Copyright (C) 2006, 2009 Apple Inc. 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
@@ -25,23 +23,23 @@
#ifndef RenderFrame_h
#define RenderFrame_h
-#include "HTMLFrameElement.h"
#include "RenderPart.h"
#include "RenderFrameSet.h"
namespace WebCore {
+class HTMLFrameElement;
+
class RenderFrame : public RenderPart {
public:
RenderFrame(HTMLFrameElement*);
+ FrameEdgeInfo edgeInfo() const;
+
+private:
virtual const char* renderName() const { return "RenderFrame"; }
virtual bool isFrame() const { return true; }
- HTMLFrameElement* element() const { return static_cast<HTMLFrameElement*>(RenderPart::element()); }
-
- FrameEdgeInfo edgeInfo() const;
-
virtual void viewCleared();
};
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderFrameSet.cpp b/src/3rdparty/webkit/WebCore/rendering/RenderFrameSet.cpp
index d93fa86..5995117 100644
--- a/src/3rdparty/webkit/WebCore/rendering/RenderFrameSet.cpp
+++ b/src/3rdparty/webkit/WebCore/rendering/RenderFrameSet.cpp
@@ -42,7 +42,7 @@
namespace WebCore {
RenderFrameSet::RenderFrameSet(HTMLFrameSetElement* frameSet)
- : RenderContainer(frameSet)
+ : RenderBox(frameSet)
, m_isResizing(false)
, m_isChildResizing(false)
{
@@ -126,8 +126,8 @@ void RenderFrameSet::paint(PaintInfo& paintInfo, int tx, int ty)
return;
// Add in our offsets.
- tx += m_x;
- ty += m_y;
+ tx += x();
+ ty += y();
int rows = frameSet()->totalRows();
int cols = frameSet()->totalCols();
@@ -161,11 +161,11 @@ bool RenderFrameSet::nodeAtPoint(const HitTestRequest& request, HitTestResult& r
if (action != HitTestForeground)
return false;
- bool inside = RenderContainer::nodeAtPoint(request, result, x, y, tx, ty, action)
- || m_isResizing || canResize(IntPoint(x, y));
+ bool inside = RenderBox::nodeAtPoint(request, result, x, y, tx, ty, action)
+ || m_isResizing;
if (inside && frameSet()->noResize()
- && !request.readonly && !result.innerNode()) {
+ && !request.readOnly() && !result.innerNode()) {
result.setInnerNode(node());
result.setInnerNonSharedNode(node());
}
@@ -457,8 +457,8 @@ void RenderFrameSet::layout()
oldBounds = absoluteClippedOverflowRect();
if (!parent()->isFrameSet() && !document()->printing()) {
- m_width = view()->viewWidth();
- m_height = view()->viewHeight();
+ setWidth(view()->viewWidth());
+ setHeight(view()->viewHeight());
}
size_t cols = frameSet()->totalCols();
@@ -470,12 +470,12 @@ void RenderFrameSet::layout()
}
int borderThickness = frameSet()->border();
- layOutAxis(m_rows, frameSet()->rowLengths(), m_height - (rows - 1) * borderThickness);
- layOutAxis(m_cols, frameSet()->colLengths(), m_width - (cols - 1) * borderThickness);
+ layOutAxis(m_rows, frameSet()->rowLengths(), height() - (rows - 1) * borderThickness);
+ layOutAxis(m_cols, frameSet()->colLengths(), width() - (cols - 1) * borderThickness);
positionFrames();
- RenderContainer::layout();
+ RenderBox::layout();
computeEdgeInfo();
@@ -491,7 +491,7 @@ void RenderFrameSet::layout()
void RenderFrameSet::positionFrames()
{
- RenderObject* child = firstChild();
+ RenderBox* child = firstChildBox();
if (!child)
return;
@@ -504,7 +504,7 @@ void RenderFrameSet::positionFrames()
int xPos = 0;
int height = m_rows.m_sizes[r];
for (int c = 0; c < cols; c++) {
- child->setPos(xPos, yPos);
+ child->setLocation(xPos, yPos);
int width = m_cols.m_sizes[c];
// has to be resized and itself resize its contents
@@ -517,7 +517,7 @@ void RenderFrameSet::positionFrames()
xPos += width + borderThickness;
- child = child->nextSibling();
+ child = child->nextSiblingBox();
if (!child)
return;
}
@@ -525,7 +525,7 @@ void RenderFrameSet::positionFrames()
}
// all the remaining frames are hidden to avoid ugly spurious unflowed frames
- for (; child; child = child->nextSibling()) {
+ for (; child; child = child->nextSiblingBox()) {
child->setWidth(0);
child->setHeight(0);
child->setNeedsLayout(false);
@@ -564,8 +564,9 @@ bool RenderFrameSet::userResize(MouseEvent* evt)
if (needsLayout())
return false;
if (evt->type() == eventNames().mousedownEvent && evt->button() == LeftButton) {
- startResizing(m_cols, evt->pageX() - xPos());
- startResizing(m_rows, evt->pageY() - yPos());
+ FloatPoint pos = localToAbsolute();
+ startResizing(m_cols, evt->absoluteLocation().x() - pos.x());
+ startResizing(m_rows, evt->absoluteLocation().y() - pos.y());
if (m_cols.m_splitBeingResized != noSplit || m_rows.m_splitBeingResized != noSplit) {
setIsResizing(true);
return true;
@@ -573,8 +574,9 @@ bool RenderFrameSet::userResize(MouseEvent* evt)
}
} else {
if (evt->type() == eventNames().mousemoveEvent || (evt->type() == eventNames().mouseupEvent && evt->button() == LeftButton)) {
- continueResizing(m_cols, evt->pageX() - xPos());
- continueResizing(m_rows, evt->pageY() - yPos());
+ FloatPoint pos = localToAbsolute();
+ continueResizing(m_cols, evt->absoluteLocation().x() - pos.x());
+ continueResizing(m_rows, evt->absoluteLocation().y() - pos.y());
if (evt->type() == eventNames().mouseupEvent && evt->button() == LeftButton) {
setIsResizing(false);
return true;
@@ -605,11 +607,6 @@ bool RenderFrameSet::isResizingColumn() const
return m_isResizing && m_cols.m_splitBeingResized != noSplit;
}
-bool RenderFrameSet::canResize(const IntPoint& p) const
-{
- return hitTestSplit(m_cols, p.x()) != noSplit || hitTestSplit(m_rows, p.y()) != noSplit;
-}
-
bool RenderFrameSet::canResizeRow(const IntPoint& p) const
{
int r = hitTestSplit(m_rows, p.y());
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderFrameSet.h b/src/3rdparty/webkit/WebCore/rendering/RenderFrameSet.h
index 5401c1b..294e5df 100644
--- a/src/3rdparty/webkit/WebCore/rendering/RenderFrameSet.h
+++ b/src/3rdparty/webkit/WebCore/rendering/RenderFrameSet.h
@@ -23,7 +23,7 @@
#ifndef RenderFrameSet_h
#define RenderFrameSet_h
-#include "RenderContainer.h"
+#include "RenderBox.h"
namespace WebCore {
@@ -53,11 +53,16 @@ private:
Vector<bool> m_allowBorder;
};
-class RenderFrameSet : public RenderContainer {
+class RenderFrameSet : public RenderBox {
public:
RenderFrameSet(HTMLFrameSetElement*);
virtual ~RenderFrameSet();
+ virtual RenderObjectChildList* virtualChildren() { return children(); }
+ virtual const RenderObjectChildList* virtualChildren() const { return children(); }
+ const RenderObjectChildList* children() const { return &m_children; }
+ RenderObjectChildList* children() { return &m_children; }
+
virtual const char* renderName() const { return "RenderFrameSet"; }
virtual bool isFrameSet() const { return true; }
@@ -93,7 +98,6 @@ private:
inline HTMLFrameSetElement* frameSet() const;
- bool canResize(const IntPoint&) const;
void setIsResizing(bool);
void layOutAxis(GridAxis&, const Length*, int availableSpace);
@@ -110,6 +114,8 @@ private:
void paintRowBorder(const PaintInfo& paintInfo, const IntRect& rect);
void paintColumnBorder(const PaintInfo& paintInfo, const IntRect& rect);
+ RenderObjectChildList m_children;
+
GridAxis m_rows;
GridAxis m_cols;
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderHTMLCanvas.cpp b/src/3rdparty/webkit/WebCore/rendering/RenderHTMLCanvas.cpp
index cc8c2c1..1fc07f0 100644
--- a/src/3rdparty/webkit/WebCore/rendering/RenderHTMLCanvas.cpp
+++ b/src/3rdparty/webkit/WebCore/rendering/RenderHTMLCanvas.cpp
@@ -31,6 +31,7 @@
#include "HTMLCanvasElement.h"
#include "HTMLNames.h"
#include "RenderView.h"
+#include "FrameView.h"
namespace WebCore {
@@ -39,32 +40,33 @@ using namespace HTMLNames;
RenderHTMLCanvas::RenderHTMLCanvas(HTMLCanvasElement* element)
: RenderReplaced(element, element->size())
{
+ view()->frameView()->setIsVisuallyNonEmpty();
}
void RenderHTMLCanvas::paintReplaced(PaintInfo& paintInfo, int tx, int ty)
{
- IntRect rect = contentBox();
+ IntRect rect = contentBoxRect();
rect.move(tx, ty);
static_cast<HTMLCanvasElement*>(node())->paint(paintInfo.context, rect);
}
void RenderHTMLCanvas::canvasSizeChanged()
{
- IntSize size = static_cast<HTMLCanvasElement*>(node())->size();
- IntSize zoomedSize(size.width() * style()->effectiveZoom(), size.height() * style()->effectiveZoom());
+ IntSize canvasSize = static_cast<HTMLCanvasElement*>(node())->size();
+ IntSize zoomedSize(canvasSize.width() * style()->effectiveZoom(), canvasSize.height() * style()->effectiveZoom());
- if (size == intrinsicSize())
+ if (canvasSize == intrinsicSize())
return;
- setIntrinsicSize(size);
+ setIntrinsicSize(canvasSize);
if (!prefWidthsDirty())
setPrefWidthsDirty(true);
- IntSize oldSize = IntSize(m_width, m_height);
+ IntSize oldSize = size();
calcWidth();
calcHeight();
- if (oldSize == IntSize(m_width, m_height))
+ if (oldSize == size())
return;
if (!selfNeedsLayout())
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderImage.cpp b/src/3rdparty/webkit/WebCore/rendering/RenderImage.cpp
index fc6f19b..cd84a09 100644
--- a/src/3rdparty/webkit/WebCore/rendering/RenderImage.cpp
+++ b/src/3rdparty/webkit/WebCore/rendering/RenderImage.cpp
@@ -37,7 +37,8 @@
#include "HitTestResult.h"
#include "Page.h"
#include "RenderView.h"
-#include "SystemTime.h"
+#include <wtf/CurrentTime.h>
+#include <wtf/UnusedParam.h>
#if ENABLE(WML)
#include "WMLImageElement.h"
@@ -281,21 +282,21 @@ void RenderImage::imageChanged(WrappedImagePtr newImage, const IntRect* rect)
// layout when we get added in to the render tree hierarchy later.
if (containingBlock()) {
// lets see if we need to relayout at all..
- int oldwidth = m_width;
- int oldheight = m_height;
+ int oldwidth = width();
+ int oldheight = height();
if (!prefWidthsDirty())
setPrefWidthsDirty(true);
calcWidth();
calcHeight();
- if (imageSizeChanged || m_width != oldwidth || m_height != oldheight) {
+ if (imageSizeChanged || width() != oldwidth || height() != oldheight) {
shouldRepaint = false;
if (!selfNeedsLayout())
setNeedsLayout(true);
}
- m_width = oldwidth;
- m_height = oldheight;
+ setWidth(oldwidth);
+ setHeight(oldheight);
}
}
@@ -304,16 +305,39 @@ void RenderImage::imageChanged(WrappedImagePtr newImage, const IntRect* rect)
if (rect) {
// The image changed rect is in source image coordinates (pre-zooming),
// so map from the bounds of the image to the contentsBox.
- repaintRect = enclosingIntRect(mapRect(*rect, FloatRect(FloatPoint(), imageSize(1.0f)), contentBox()));
+ repaintRect = enclosingIntRect(mapRect(*rect, FloatRect(FloatPoint(), imageSize(1.0f)), contentBoxRect()));
// Guard against too-large changed rects.
- repaintRect.intersect(contentBox());
+ repaintRect.intersect(contentBoxRect());
} else
- repaintRect = contentBox();
+ repaintRect = contentBoxRect();
repaintRectangle(repaintRect);
+
+#if USE(ACCELERATED_COMPOSITING)
+ if (hasLayer()) {
+ // Tell any potential compositing layers that the image needs updating.
+ layer()->rendererContentChanged();
+ }
+#endif
}
}
+void RenderImage::notifyFinished(CachedResource* newImage)
+{
+ if (documentBeingDestroyed())
+ return;
+
+#if USE(ACCELERATED_COMPOSITING)
+ if ((newImage == m_cachedImage) && hasLayer()) {
+ // tell any potential compositing layers
+ // that the image is done and they can reference it directly.
+ layer()->rendererContentChanged();
+ }
+#else
+ UNUSED_PARAM(newImage);
+#endif
+}
+
void RenderImage::resetAnimation()
{
if (m_cachedImage) {
@@ -371,9 +395,7 @@ void RenderImage::paintReplaced(PaintInfo& paintInfo, int tx, int ty)
}
if (!m_altText.isEmpty()) {
- String text = m_altText;
- text.replace('\\', backslashAsCurrencySymbol());
- context->setFont(style()->font());
+ String text = document()->displayStringModifiedByEncoding(m_altText);
context->setFillColor(style()->color());
int ax = tx + leftBorder + leftPad;
int ay = ty + topBorder + topPad;
@@ -386,9 +408,9 @@ void RenderImage::paintReplaced(PaintInfo& paintInfo, int tx, int ty)
int textWidth = font.width(textRun);
if (errorPictureDrawn) {
if (usableWidth >= textWidth && font.height() <= imageY)
- context->drawText(textRun, IntPoint(ax, ay + ascent));
+ context->drawText(style()->font(), textRun, IntPoint(ax, ay + ascent));
} else if (usableWidth >= textWidth && cHeight >= font.height())
- context->drawText(textRun, IntPoint(ax, ay + ascent));
+ context->drawText(style()->font(), textRun, IntPoint(ax, ay + ascent));
}
}
} else if (hasImage() && cWidth > 0 && cHeight > 0) {
@@ -398,13 +420,13 @@ void RenderImage::paintReplaced(PaintInfo& paintInfo, int tx, int ty)
#if PLATFORM(MAC)
if (style()->highlight() != nullAtom && !paintInfo.context->paintingDisabled())
- paintCustomHighlight(tx - m_x, ty - m_y, style()->highlight(), true);
+ paintCustomHighlight(tx - x(), ty - y(), style()->highlight(), true);
#endif
IntSize contentSize(cWidth, cHeight);
bool useLowQualityScaling = RenderImageScaleObserver::shouldImagePaintAtLowQuality(this, contentSize);
IntRect rect(IntPoint(tx + leftBorder + leftPad, ty + topBorder + topPad), contentSize);
- HTMLImageElement* imageElt = (element() && element()->hasTagName(imgTag)) ? static_cast<HTMLImageElement*>(element()) : 0;
+ HTMLImageElement* imageElt = (node() && node()->hasTagName(imgTag)) ? static_cast<HTMLImageElement*>(node()) : 0;
CompositeOperator compositeOperator = imageElt ? imageElt->compositeOperator() : CompositeSourceOver;
context->drawImage(image(cWidth, cHeight), rect, compositeOperator, useLowQualityScaling);
}
@@ -417,41 +439,42 @@ int RenderImage::minimumReplacedHeight() const
HTMLMapElement* RenderImage::imageMap()
{
- HTMLImageElement* i = element() && element()->hasTagName(imgTag) ? static_cast<HTMLImageElement*>(element()) : 0;
+ HTMLImageElement* i = node() && node()->hasTagName(imgTag) ? static_cast<HTMLImageElement*>(node()) : 0;
return i ? i->document()->getImageMap(i->useMap()) : 0;
}
bool RenderImage::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, int _x, int _y, int _tx, int _ty, HitTestAction hitTestAction)
{
- bool inside = RenderReplaced::nodeAtPoint(request, result, _x, _y, _tx, _ty, hitTestAction);
+ HitTestResult tempResult(result.point());
+ bool inside = RenderReplaced::nodeAtPoint(request, tempResult, _x, _y, _tx, _ty, hitTestAction);
- if (inside && element()) {
- int tx = _tx + m_x;
- int ty = _ty + m_y;
+ if (inside && node()) {
+ int tx = _tx + x();
+ int ty = _ty + y();
- HTMLMapElement* map = imageMap();
- if (map) {
- // we're a client side image map
- inside = map->mapMouseEvent(_x - tx, _y - ty, IntSize(contentWidth(), contentHeight()), result);
- result.setInnerNonSharedNode(element());
+ if (HTMLMapElement* map = imageMap()) {
+ if (map->mapMouseEvent(_x - tx, _y - ty, IntSize(contentWidth(), contentHeight()), tempResult))
+ tempResult.setInnerNonSharedNode(node());
}
}
+ if (inside)
+ result = tempResult;
return inside;
}
void RenderImage::updateAltText()
{
- if (!element())
+ if (!node())
return;
- if (element()->hasTagName(inputTag))
- m_altText = static_cast<HTMLInputElement*>(element())->altText();
- else if (element()->hasTagName(imgTag))
- m_altText = static_cast<HTMLImageElement*>(element())->altText();
+ if (node()->hasTagName(inputTag))
+ m_altText = static_cast<HTMLInputElement*>(node())->altText();
+ else if (node()->hasTagName(imgTag))
+ m_altText = static_cast<HTMLImageElement*>(node())->altText();
#if ENABLE(WML)
- else if (element()->hasTagName(WMLNames::imgTag))
- m_altText = static_cast<WMLImageElement*>(element())->altText();
+ else if (node()->hasTagName(WMLNames::imgTag))
+ m_altText = static_cast<WMLImageElement*>(node())->altText();
#endif
}
@@ -492,8 +515,10 @@ bool RenderImage::isHeightSpecified() const
int RenderImage::calcReplacedWidth(bool includeMaxWidth) const
{
if (imageHasRelativeWidth())
- if (RenderObject* cb = isPositioned() ? container() : containingBlock())
- setImageContainerSize(IntSize(cb->availableWidth(), cb->availableHeight()));
+ if (RenderObject* cb = isPositioned() ? container() : containingBlock()) {
+ if (cb->isBox())
+ setImageContainerSize(IntSize(toRenderBox(cb)->availableWidth(), toRenderBox(cb)->availableHeight()));
+ }
int width;
if (isWidthSpecified())
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderImage.h b/src/3rdparty/webkit/WebCore/rendering/RenderImage.h
index 71896d6..042452f 100644
--- a/src/3rdparty/webkit/WebCore/rendering/RenderImage.h
+++ b/src/3rdparty/webkit/WebCore/rendering/RenderImage.h
@@ -48,6 +48,7 @@ public:
virtual int minimumReplacedHeight() const;
virtual void imageChanged(WrappedImagePtr, const IntRect* = 0);
+ virtual void notifyFinished(CachedResource*);
bool setImageSizeForAltText(CachedImage* newImage = 0);
@@ -102,6 +103,21 @@ protected:
friend class RenderImageScaleObserver;
};
+inline RenderImage* toRenderImage(RenderObject* o)
+{
+ ASSERT(!o || o->isRenderImage());
+ return static_cast<RenderImage*>(o);
+}
+
+inline const RenderImage* toRenderImage(const RenderObject* o)
+{
+ ASSERT(!o || o->isRenderImage());
+ return static_cast<const RenderImage*>(o);
+}
+
+// This will catch anyone doing an unnecessary cast.
+void toRenderImage(const RenderImage*);
+
} // namespace WebCore
#endif // RenderImage_h
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderImageGeneratedContent.h b/src/3rdparty/webkit/WebCore/rendering/RenderImageGeneratedContent.h
index cab0192..9f8330d8 100644
--- a/src/3rdparty/webkit/WebCore/rendering/RenderImageGeneratedContent.h
+++ b/src/3rdparty/webkit/WebCore/rendering/RenderImageGeneratedContent.h
@@ -27,16 +27,14 @@
#define RenderImageGeneratedContent_h
#include "RenderImage.h"
+#include "StyleImage.h"
#include <wtf/RefPtr.h>
-#include "RenderStyle.h"
-
namespace WebCore {
class StyleImage;
-class RenderImageGeneratedContent : public RenderImage
-{
+class RenderImageGeneratedContent : public RenderImage {
public:
RenderImageGeneratedContent(Node*);
virtual ~RenderImageGeneratedContent();
@@ -53,12 +51,14 @@ protected:
virtual bool imageHasRelativeWidth() const { return m_styleImage->imageHasRelativeWidth(); }
virtual bool imageHasRelativeHeight() const { return m_styleImage->imageHasRelativeHeight(); }
virtual IntSize imageSize(float multiplier) const { return m_styleImage->imageSize(this, multiplier); }
- virtual WrappedImagePtr imagePtr() const { return m_styleImage->data(); }
+
+ // |m_styleImage| can be 0 if we get a callback for a background image from RenderObject::setStyle.
+ virtual WrappedImagePtr imagePtr() const { return m_styleImage ? m_styleImage->data() : 0; }
private:
RefPtr<StyleImage> m_styleImage;
};
-}
+} // namespace WebCore
-#endif
+#endif // RenderImageGeneratedContent_h
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderInline.cpp b/src/3rdparty/webkit/WebCore/rendering/RenderInline.cpp
index 40e5029..3965d94 100644
--- a/src/3rdparty/webkit/WebCore/rendering/RenderInline.cpp
+++ b/src/3rdparty/webkit/WebCore/rendering/RenderInline.cpp
@@ -25,28 +25,95 @@
#include "config.h"
#include "RenderInline.h"
-#include "Document.h"
+#include "FloatQuad.h"
+#include "GraphicsContext.h"
+#include "HitTestResult.h"
+#include "Page.h"
#include "RenderArena.h"
#include "RenderBlock.h"
+#include "RenderView.h"
#include "VisiblePosition.h"
+#if ENABLE(DASHBOARD_SUPPORT)
+#include "Frame.h"
+#endif
+
+using namespace std;
+
namespace WebCore {
RenderInline::RenderInline(Node* node)
- : RenderFlow(node)
+ : RenderBoxModelObject(node)
+ , m_continuation(0)
+ , m_lineHeight(-1)
+ , m_verticalPosition(PositionUndefined)
{
+ setChildrenInline(true);
}
RenderInline::~RenderInline()
{
}
-void RenderInline::styleDidChange(RenderStyle::Diff diff, const RenderStyle* oldStyle)
+void RenderInline::destroy()
+{
+ // Detach our continuation first.
+ if (m_continuation)
+ m_continuation->destroy();
+ m_continuation = 0;
+
+ // Make sure to destroy anonymous children first while they are still connected to the rest of the tree, so that they will
+ // properly dirty line boxes that they are removed from. Effects that do :before/:after only on hover could crash otherwise.
+ children()->destroyLeftoverChildren();
+
+ if (!documentBeingDestroyed()) {
+ if (firstLineBox()) {
+ // We can't wait for RenderBoxModelObject::destroy to clear the selection,
+ // because by then we will have nuked the line boxes.
+ // FIXME: The SelectionController should be responsible for this when it
+ // is notified of DOM mutations.
+ if (isSelectionBorder())
+ view()->clearSelection();
+
+ // If line boxes are contained inside a root, that means we're an inline.
+ // In that case, we need to remove all the line boxes so that the parent
+ // lines aren't pointing to deleted children. If the first line box does
+ // not have a parent that means they are either already disconnected or
+ // root lines that can just be destroyed without disconnecting.
+ if (firstLineBox()->parent()) {
+ for (InlineRunBox* box = firstLineBox(); box; box = box->nextLineBox())
+ box->remove();
+ }
+ } else if (isInline() && parent())
+ parent()->dirtyLinesFromChangedChild(this);
+ }
+
+ m_lineBoxes.deleteLineBoxes(renderArena());
+
+ RenderBoxModelObject::destroy();
+}
+
+RenderInline* RenderInline::inlineContinuation() const
+{
+ if (!m_continuation || m_continuation->isInline())
+ return toRenderInline(m_continuation);
+ return toRenderBlock(m_continuation)->inlineContinuation();
+}
+
+void RenderInline::updateBoxModelInfoFromStyle()
{
- RenderFlow::styleDidChange(diff, oldStyle);
+ RenderBoxModelObject::updateBoxModelInfoFromStyle();
- setInline(true);
- setHasReflection(false);
+ setInline(true); // Needed for run-ins, since run-in is considered a block display type.
+
+ // FIXME: Support transforms and reflections on inline flows someday.
+ setHasTransform(false);
+ setHasReflection(false);
+}
+
+void RenderInline::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
+{
+ RenderBoxModelObject::styleDidChange(diff, oldStyle);
// Ensure that all of the split inlines pick up the new style. We
// only do this if we're an inline, since we don't want to propagate
@@ -54,36 +121,27 @@ void RenderInline::styleDidChange(RenderStyle::Diff diff, const RenderStyle* old
// e.g., <font>foo <h4>goo</h4> moo</font>. The <font> inlines before
// and after the block share the same style, but the block doesn't
// need to pass its style on to anyone else.
- RenderFlow* currCont = continuation();
- while (currCont) {
- if (currCont->isInline()) {
- RenderFlow* nextCont = currCont->continuation();
- currCont->setContinuation(0);
- currCont->setStyle(style());
- currCont->setContinuation(nextCont);
- }
- currCont = currCont->continuation();
+ for (RenderInline* currCont = inlineContinuation(); currCont; currCont = currCont->inlineContinuation()) {
+ RenderBoxModelObject* nextCont = currCont->continuation();
+ currCont->setContinuation(0);
+ currCont->setStyle(style());
+ currCont->setContinuation(nextCont);
}
m_lineHeight = -1;
// Update pseudos for :before and :after now.
- if (!isAnonymous()) {
- updateBeforeAfterContent(RenderStyle::BEFORE);
- updateBeforeAfterContent(RenderStyle::AFTER);
+ if (!isAnonymous() && document()->usesBeforeAfterRules()) {
+ children()->updateBeforeAfterContent(this, BEFORE);
+ children()->updateBeforeAfterContent(this, AFTER);
}
}
-bool RenderInline::isInlineContinuation() const
-{
- return m_isContinuation;
-}
-
static inline bool isAfterContent(RenderObject* child)
{
if (!child)
return false;
- if (child->style()->styleType() != RenderStyle::AFTER)
+ if (child->style()->styleType() != AFTER)
return false;
// Text nodes don't have their own styles, so ignore the style on a text node.
if (child->isText() && !child->isBR())
@@ -91,7 +149,46 @@ static inline bool isAfterContent(RenderObject* child)
return true;
}
-void RenderInline::addChildToFlow(RenderObject* newChild, RenderObject* beforeChild)
+void RenderInline::addChild(RenderObject* newChild, RenderObject* beforeChild)
+{
+ if (continuation())
+ return addChildToContinuation(newChild, beforeChild);
+ return addChildIgnoringContinuation(newChild, beforeChild);
+}
+
+static RenderBoxModelObject* nextContinuation(RenderObject* renderer)
+{
+ if (renderer->isInline() && !renderer->isReplaced())
+ return toRenderInline(renderer)->continuation();
+ return toRenderBlock(renderer)->inlineContinuation();
+}
+
+RenderBoxModelObject* RenderInline::continuationBefore(RenderObject* beforeChild)
+{
+ if (beforeChild && beforeChild->parent() == this)
+ return this;
+
+ RenderBoxModelObject* curr = nextContinuation(this);
+ RenderBoxModelObject* nextToLast = this;
+ RenderBoxModelObject* last = this;
+ while (curr) {
+ if (beforeChild && beforeChild->parent() == curr) {
+ if (curr->firstChild() == beforeChild)
+ return last;
+ return curr;
+ }
+
+ nextToLast = last;
+ last = curr;
+ curr = nextContinuation(curr);
+ }
+
+ if (!beforeChild && !last->firstChild())
+ return nextToLast;
+ return last;
+}
+
+void RenderInline::addChildIgnoringContinuation(RenderObject* newChild, RenderObject* beforeChild)
{
// Make sure we don't append things after :after-generated content if we have it.
if (!beforeChild && isAfterContent(lastChild()))
@@ -108,14 +205,15 @@ void RenderInline::addChildToFlow(RenderObject* newChild, RenderObject* beforeCh
RenderBlock* newBox = new (renderArena()) RenderBlock(document() /* anonymous box */);
newBox->setStyle(newStyle.release());
- RenderFlow* oldContinuation = continuation();
+ RenderBoxModelObject* oldContinuation = continuation();
setContinuation(newBox);
// Someone may have put a <p> inside a <q>, causing a split. When this happens, the :after content
// has to move into the inline continuation. Call updateBeforeAfterContent to ensure that our :after
// content gets properly destroyed.
bool isLastChild = (beforeChild == lastChild());
- updateBeforeAfterContent(RenderStyle::AFTER);
+ if (document()->usesBeforeAfterRules())
+ children()->updateBeforeAfterContent(this, AFTER);
if (isLastChild && beforeChild != lastChild())
beforeChild = 0; // We destroyed the last child, so now we need to update our insertion
// point to be 0. It's just a straight append now.
@@ -124,22 +222,21 @@ void RenderInline::addChildToFlow(RenderObject* newChild, RenderObject* beforeCh
return;
}
- RenderContainer::addChild(newChild, beforeChild);
+ RenderBoxModelObject::addChild(newChild, beforeChild);
newChild->setNeedsLayoutAndPrefWidthsRecalc();
}
-RenderInline* RenderInline::cloneInline(RenderFlow* src)
+RenderInline* RenderInline::cloneInline(RenderInline* src)
{
- RenderInline* o = new (src->renderArena()) RenderInline(src->element());
- o->m_isContinuation = true;
+ RenderInline* o = new (src->renderArena()) RenderInline(src->node());
o->setStyle(src->style());
return o;
}
void RenderInline::splitInlines(RenderBlock* fromBlock, RenderBlock* toBlock,
RenderBlock* middleBlock,
- RenderObject* beforeChild, RenderFlow* oldCont)
+ RenderObject* beforeChild, RenderBoxModelObject* oldCont)
{
// Create a clone of this inline.
RenderInline* clone = cloneInline(this);
@@ -151,18 +248,18 @@ void RenderInline::splitInlines(RenderBlock* fromBlock, RenderBlock* toBlock,
while (o) {
RenderObject* tmp = o;
o = tmp->nextSibling();
- clone->addChildToFlow(removeChildNode(tmp), 0);
+ clone->addChildIgnoringContinuation(children()->removeChildNode(this, tmp), 0);
tmp->setNeedsLayoutAndPrefWidthsRecalc();
}
// Hook |clone| up as the continuation of the middle block.
- middleBlock->setContinuation(clone);
+ middleBlock->setInlineContinuation(clone);
// We have been reparented and are now under the fromBlock. We need
// to walk up our inline parent chain until we hit the containing block.
// Once we hit the containing block we're done.
- RenderFlow* curr = static_cast<RenderFlow*>(parent());
- RenderFlow* currChild = this;
+ RenderBoxModelObject* curr = static_cast<RenderBoxModelObject*>(parent());
+ RenderBoxModelObject* currChild = this;
// FIXME: Because splitting is O(n^2) as tags nest pathologically, we cap the depth at which we're willing to clone.
// There will eventually be a better approach to this problem that will let us nest to a much
@@ -171,23 +268,26 @@ void RenderInline::splitInlines(RenderBlock* fromBlock, RenderBlock* toBlock,
unsigned splitDepth = 1;
const unsigned cMaxSplitDepth = 200;
while (curr && curr != fromBlock) {
+ ASSERT(curr->isRenderInline());
if (splitDepth < cMaxSplitDepth) {
// Create a new clone.
RenderInline* cloneChild = clone;
- clone = cloneInline(curr);
+ clone = cloneInline(toRenderInline(curr));
// Insert our child clone as the first child.
- clone->addChildToFlow(cloneChild, 0);
+ clone->addChildIgnoringContinuation(cloneChild, 0);
// Hook the clone up as a continuation of |curr|.
- RenderFlow* oldCont = curr->continuation();
- curr->setContinuation(clone);
+ RenderInline* inlineCurr = toRenderInline(curr);
+ oldCont = inlineCurr->continuation();
+ inlineCurr->setContinuation(clone);
clone->setContinuation(oldCont);
// Someone may have indirectly caused a <q> to split. When this happens, the :after content
// has to move into the inline continuation. Call updateBeforeAfterContent to ensure that the inline's :after
// content gets properly destroyed.
- curr->updateBeforeAfterContent(RenderStyle::AFTER);
+ if (document()->usesBeforeAfterRules())
+ inlineCurr->children()->updateBeforeAfterContent(this, AFTER);
// Now we need to take all of the children starting from the first child
// *after* currChild and append them all to the clone.
@@ -195,19 +295,19 @@ void RenderInline::splitInlines(RenderBlock* fromBlock, RenderBlock* toBlock,
while (o) {
RenderObject* tmp = o;
o = tmp->nextSibling();
- clone->addChildToFlow(curr->removeChildNode(tmp), 0);
+ clone->addChildIgnoringContinuation(inlineCurr->children()->removeChildNode(curr, tmp), 0);
tmp->setNeedsLayoutAndPrefWidthsRecalc();
}
}
// Keep walking up the chain.
currChild = curr;
- curr = static_cast<RenderFlow*>(curr->parent());
+ curr = static_cast<RenderBoxModelObject*>(curr->parent());
splitDepth++;
}
// Now we are at the block level. We need to put the clone into the toBlock.
- toBlock->appendChildNode(clone);
+ toBlock->children()->appendChildNode(toBlock, clone);
// Now take all the children after currChild and remove them from the fromBlock
// and put them in the toBlock.
@@ -215,12 +315,12 @@ void RenderInline::splitInlines(RenderBlock* fromBlock, RenderBlock* toBlock,
while (o) {
RenderObject* tmp = o;
o = tmp->nextSibling();
- toBlock->appendChildNode(fromBlock->removeChildNode(tmp));
+ toBlock->children()->appendChildNode(toBlock, fromBlock->children()->removeChildNode(fromBlock, tmp));
}
}
void RenderInline::splitFlow(RenderObject* beforeChild, RenderBlock* newBlockBox,
- RenderObject* newChild, RenderFlow* oldCont)
+ RenderObject* newChild, RenderBoxModelObject* oldCont)
{
RenderBlock* pre = 0;
RenderBlock* block = containingBlock();
@@ -232,6 +332,7 @@ void RenderInline::splitFlow(RenderObject* beforeChild, RenderBlock* newBlockBox
if (block->isAnonymousBlock() && (!block->parent() || !block->parent()->createsAnonymousWrapper())) {
// We can reuse this block and make it the preBlock of the next continuation.
pre = block;
+ pre->removePositionedObjects(0);
block = block->containingBlock();
} else {
// No anonymous block available for use. Make one.
@@ -243,9 +344,9 @@ void RenderInline::splitFlow(RenderObject* beforeChild, RenderBlock* newBlockBox
RenderObject* boxFirst = madeNewBeforeBlock ? block->firstChild() : pre->nextSibling();
if (madeNewBeforeBlock)
- block->insertChildNode(pre, boxFirst);
- block->insertChildNode(newBlockBox, boxFirst);
- block->insertChildNode(post, boxFirst);
+ block->children()->insertChildNode(block, pre, boxFirst);
+ block->children()->insertChildNode(block, newBlockBox, boxFirst);
+ block->children()->insertChildNode(block, post, boxFirst);
block->setChildrenInline(false);
if (madeNewBeforeBlock) {
@@ -253,7 +354,7 @@ void RenderInline::splitFlow(RenderObject* beforeChild, RenderBlock* newBlockBox
while (o) {
RenderObject* no = o;
o = no->nextSibling();
- pre->appendChildNode(block->removeChildNode(no));
+ pre->children()->appendChildNode(pre, block->children()->removeChildNode(block, no));
no->setNeedsLayoutAndPrefWidthsRecalc();
}
}
@@ -264,12 +365,10 @@ void RenderInline::splitFlow(RenderObject* beforeChild, RenderBlock* newBlockBox
// time in makeChildrenNonInline by just setting this explicitly up front.
newBlockBox->setChildrenInline(false);
- // We don't just call addChild, since it would pass things off to the
- // continuation, so we call addChildToFlow explicitly instead. We delayed
- // adding the newChild until now so that the |newBlockBox| would be fully
+ // We delayed adding the newChild until now so that the |newBlockBox| would be fully
// connected, thus allowing newChild access to a renderArena should it need
// to wrap itself in additional boxes (e.g., table construction).
- newBlockBox->addChildToFlow(newChild, 0);
+ newBlockBox->addChild(newChild);
// Always just do a full layout in order to ensure that line boxes (especially wrappers for images)
// get deleted properly. Because objects moves from the pre block into the post block, we want to
@@ -279,121 +378,656 @@ void RenderInline::splitFlow(RenderObject* beforeChild, RenderBlock* newBlockBox
post->setNeedsLayoutAndPrefWidthsRecalc();
}
-void RenderInline::paint(PaintInfo& paintInfo, int tx, int ty)
-{
- paintLines(paintInfo, tx, ty);
-}
-
-void RenderInline::absoluteRects(Vector<IntRect>& rects, int tx, int ty, bool topLevel)
+void RenderInline::addChildToContinuation(RenderObject* newChild, RenderObject* beforeChild)
{
- for (InlineRunBox* curr = firstLineBox(); curr; curr = curr->nextLineBox())
- rects.append(IntRect(tx + curr->xPos(), ty + curr->yPos(), curr->width(), curr->height()));
-
- for (RenderObject* curr = firstChild(); curr; curr = curr->nextSibling()) {
- if (!curr->isText())
- curr->absoluteRects(rects, tx + curr->xPos(), ty + curr->yPos(), false);
+ RenderBoxModelObject* flow = continuationBefore(beforeChild);
+ ASSERT(!beforeChild || beforeChild->parent()->isRenderBlock() || beforeChild->parent()->isRenderInline());
+ RenderBoxModelObject* beforeChildParent = 0;
+ if (beforeChild)
+ beforeChildParent = static_cast<RenderBoxModelObject*>(beforeChild->parent());
+ else {
+ RenderBoxModelObject* cont = nextContinuation(flow);
+ if (cont)
+ beforeChildParent = cont;
+ else
+ beforeChildParent = flow;
}
- if (continuation() && topLevel)
- continuation()->absoluteRects(rects,
- tx - containingBlock()->xPos() + continuation()->xPos(),
- ty - containingBlock()->yPos() + continuation()->yPos(),
- topLevel);
-}
+ if (newChild->isFloatingOrPositioned())
+ return beforeChildParent->addChildIgnoringContinuation(newChild, beforeChild);
-void RenderInline::absoluteQuads(Vector<FloatQuad>& quads, bool topLevel)
-{
- for (InlineRunBox* curr = firstLineBox(); curr; curr = curr->nextLineBox()) {
- FloatRect localRect(curr->xPos(), curr->yPos(), curr->width(), curr->height());
- quads.append(localToAbsoluteQuad(localRect));
- }
-
- for (RenderObject* curr = firstChild(); curr; curr = curr->nextSibling()) {
- if (!curr->isText())
- curr->absoluteQuads(quads, false);
- }
+ // A continuation always consists of two potential candidates: an inline or an anonymous
+ // block box holding block children.
+ bool childInline = newChild->isInline();
+ bool bcpInline = beforeChildParent->isInline();
+ bool flowInline = flow->isInline();
- if (continuation() && topLevel)
- continuation()->absoluteQuads(quads, topLevel);
+ if (flow == beforeChildParent)
+ return flow->addChildIgnoringContinuation(newChild, beforeChild);
+ else {
+ // The goal here is to match up if we can, so that we can coalesce and create the
+ // minimal # of continuations needed for the inline.
+ if (childInline == bcpInline)
+ return beforeChildParent->addChildIgnoringContinuation(newChild, beforeChild);
+ else if (flowInline == childInline)
+ return flow->addChildIgnoringContinuation(newChild, 0); // Just treat like an append.
+ else
+ return beforeChildParent->addChildIgnoringContinuation(newChild, beforeChild);
+ }
}
-bool RenderInline::requiresLayer()
+void RenderInline::paint(PaintInfo& paintInfo, int tx, int ty)
{
- return isRelPositioned() || isTransparent() || hasMask();
+ m_lineBoxes.paint(this, paintInfo, tx, ty);
}
-int RenderInline::width() const
+void RenderInline::absoluteRects(Vector<IntRect>& rects, int tx, int ty)
{
- // Return the width of the minimal left side and the maximal right side.
- int leftSide = 0;
- int rightSide = 0;
- for (InlineRunBox* curr = firstLineBox(); curr; curr = curr->nextLineBox()) {
- if (curr == firstLineBox() || curr->xPos() < leftSide)
- leftSide = curr->xPos();
- if (curr == firstLineBox() || curr->xPos() + curr->width() > rightSide)
- rightSide = curr->xPos() + curr->width();
- }
+ if (InlineRunBox* curr = firstLineBox()) {
+ for (; curr; curr = curr->nextLineBox())
+ rects.append(IntRect(tx + curr->x(), ty + curr->y(), curr->width(), curr->height()));
+ } else
+ rects.append(IntRect(tx, ty, 0, 0));
- return rightSide - leftSide;
+ if (continuation()) {
+ if (continuation()->isBox()) {
+ RenderBox* box = toRenderBox(continuation());
+ continuation()->absoluteRects(rects,
+ tx - containingBlock()->x() + box->x(),
+ ty - containingBlock()->y() + box->y());
+ } else
+ continuation()->absoluteRects(rects, tx - containingBlock()->x(), ty - containingBlock()->y());
+ }
}
-int RenderInline::height() const
+void RenderInline::absoluteQuads(Vector<FloatQuad>& quads)
{
- // See <rdar://problem/5289721>, for an unknown reason the linked list here is sometimes inconsistent, first is non-zero and last is zero. We have been
- // unable to reproduce this at all (and consequently unable to figure ot why this is happening). The assert will hopefully catch the problem in debug
- // builds and help us someday figure out why. We also put in a redundant check of lastLineBox() to avoid the crash for now.
- ASSERT(!firstLineBox() == !lastLineBox()); // Either both are null or both exist.
- if (firstLineBox() && lastLineBox())
- return lastLineBox()->yPos() + lastLineBox()->height() - firstLineBox()->yPos();
- return 0;
+ if (InlineRunBox* curr = firstLineBox()) {
+ for (; curr; curr = curr->nextLineBox()) {
+ FloatRect localRect(curr->x(), curr->y(), curr->width(), curr->height());
+ quads.append(localToAbsoluteQuad(localRect));
+ }
+ } else
+ quads.append(localToAbsoluteQuad(FloatRect()));
+
+ if (continuation())
+ continuation()->absoluteQuads(quads);
}
int RenderInline::offsetLeft() const
{
- int x = RenderFlow::offsetLeft();
+ int x = RenderBoxModelObject::offsetLeft();
if (firstLineBox())
- x += firstLineBox()->xPos();
+ x += firstLineBox()->x();
return x;
}
int RenderInline::offsetTop() const
{
- int y = RenderFlow::offsetTop();
+ int y = RenderBoxModelObject::offsetTop();
if (firstLineBox())
- y += firstLineBox()->yPos();
+ y += firstLineBox()->y();
return y;
}
+int RenderInline::marginLeft() const
+{
+ Length margin = style()->marginLeft();
+ if (margin.isAuto())
+ return 0;
+ if (margin.isFixed())
+ return margin.value();
+ if (margin.isPercent())
+ return margin.calcMinValue(max(0, containingBlock()->availableWidth()));
+ return 0;
+}
+
+int RenderInline::marginRight() const
+{
+ Length margin = style()->marginRight();
+ if (margin.isAuto())
+ return 0;
+ if (margin.isFixed())
+ return margin.value();
+ if (margin.isPercent())
+ return margin.calcMinValue(max(0, containingBlock()->availableWidth()));
+ return 0;
+}
+
const char* RenderInline::renderName() const
{
if (isRelPositioned())
return "RenderInline (relative positioned)";
if (isAnonymous())
return "RenderInline (generated)";
+ if (isRunIn())
+ return "RenderInline (run-in)";
return "RenderInline";
}
bool RenderInline::nodeAtPoint(const HitTestRequest& request, HitTestResult& result,
int x, int y, int tx, int ty, HitTestAction hitTestAction)
{
- return hitTestLines(request, result, x, y, tx, ty, hitTestAction);
+ return m_lineBoxes.hitTest(this, request, result, x, y, tx, ty, hitTestAction);
}
-VisiblePosition RenderInline::positionForCoordinates(int x, int y)
+VisiblePosition RenderInline::positionForPoint(const IntPoint& point)
{
- // Translate the coords from the pre-anonymous block to the post-anonymous block.
+ // FIXME: Does not deal with relative positioned inlines (should it?)
RenderBlock* cb = containingBlock();
- int parentBlockX = cb->xPos() + x;
- int parentBlockY = cb->yPos() + y;
- for (RenderObject* c = continuation(); c; c = c->continuation()) {
- RenderObject* contBlock = c;
- if (c->isInline())
- contBlock = c->containingBlock();
+ if (firstLineBox()) {
+ // This inline actually has a line box. We must have clicked in the border/padding of one of these boxes. We
+ // should try to find a result by asking our containing block.
+ return cb->positionForPoint(point);
+ }
+
+ // Translate the coords from the pre-anonymous block to the post-anonymous block.
+ int parentBlockX = cb->x() + point.x();
+ int parentBlockY = cb->y() + point.y();
+ RenderBoxModelObject* c = continuation();
+ while (c) {
+ RenderBox* contBlock = c->isInline() ? c->containingBlock() : toRenderBlock(c);
if (c->isInline() || c->firstChild())
- return c->positionForCoordinates(parentBlockX - contBlock->xPos(), parentBlockY - contBlock->yPos());
+ return c->positionForCoordinates(parentBlockX - contBlock->x(), parentBlockY - contBlock->y());
+ c = toRenderBlock(c)->inlineContinuation();
+ }
+
+ return RenderBoxModelObject::positionForPoint(point);
+}
+
+IntRect RenderInline::linesBoundingBox() const
+{
+ IntRect result;
+
+ // See <rdar://problem/5289721>, for an unknown reason the linked list here is sometimes inconsistent, first is non-zero and last is zero. We have been
+ // unable to reproduce this at all (and consequently unable to figure ot why this is happening). The assert will hopefully catch the problem in debug
+ // builds and help us someday figure out why. We also put in a redundant check of lastLineBox() to avoid the crash for now.
+ ASSERT(!firstLineBox() == !lastLineBox()); // Either both are null or both exist.
+ if (firstLineBox() && lastLineBox()) {
+ // Return the width of the minimal left side and the maximal right side.
+ int leftSide = 0;
+ int rightSide = 0;
+ for (InlineRunBox* curr = firstLineBox(); curr; curr = curr->nextLineBox()) {
+ if (curr == firstLineBox() || curr->x() < leftSide)
+ leftSide = curr->x();
+ if (curr == firstLineBox() || curr->x() + curr->width() > rightSide)
+ rightSide = curr->x() + curr->width();
+ }
+ result.setWidth(rightSide - leftSide);
+ result.setX(leftSide);
+ result.setHeight(lastLineBox()->y() + lastLineBox()->height() - firstLineBox()->y());
+ result.setY(firstLineBox()->y());
}
- return RenderFlow::positionForCoordinates(x, y);
+ return result;
+}
+
+IntRect RenderInline::clippedOverflowRectForRepaint(RenderBoxModelObject* repaintContainer)
+{
+ // Only run-ins are allowed in here during layout.
+ ASSERT(!view() || !view()->layoutStateEnabled() || isRunIn());
+
+ if (!firstLineBox() && !continuation())
+ return IntRect();
+
+ // Find our leftmost position.
+ IntRect boundingBox(linesBoundingBox());
+ int left = boundingBox.x();
+ int top = boundingBox.y();
+
+ // Now invalidate a rectangle.
+ int ow = style() ? style()->outlineSize() : 0;
+
+ // We need to add in the relative position offsets of any inlines (including us) up to our
+ // containing block.
+ RenderBlock* cb = containingBlock();
+ for (RenderObject* inlineFlow = this; inlineFlow && inlineFlow->isRenderInline() && inlineFlow != cb;
+ inlineFlow = inlineFlow->parent()) {
+ if (inlineFlow->style()->position() == RelativePosition && inlineFlow->hasLayer())
+ toRenderInline(inlineFlow)->layer()->relativePositionOffset(left, top);
+ }
+
+ IntRect r(-ow + left, -ow + top, boundingBox.width() + ow * 2, boundingBox.height() + ow * 2);
+ if (cb->hasColumns())
+ cb->adjustRectForColumns(r);
+
+ if (cb->hasOverflowClip()) {
+ // cb->height() is inaccurate if we're in the middle of a layout of |cb|, so use the
+ // layer's size instead. Even if the layer's size is wrong, the layer itself will repaint
+ // anyway if its size does change.
+ int x = r.x();
+ int y = r.y();
+ IntRect boxRect(0, 0, cb->layer()->width(), cb->layer()->height());
+ cb->layer()->subtractScrolledContentOffset(x, y); // For overflow:auto/scroll/hidden.
+ IntRect repaintRect(x, y, r.width(), r.height());
+ r = intersection(repaintRect, boxRect);
+ }
+
+ // FIXME: need to ensure that we compute the correct repaint rect when the repaint container
+ // is an inline.
+ if (repaintContainer != this)
+ cb->computeRectForRepaint(repaintContainer, r);
+
+ if (ow) {
+ for (RenderObject* curr = firstChild(); curr; curr = curr->nextSibling()) {
+ if (!curr->isText()) {
+ IntRect childRect = curr->rectWithOutlineForRepaint(repaintContainer, ow);
+ r.unite(childRect);
+ }
+ }
+
+ if (continuation() && !continuation()->isInline()) {
+ IntRect contRect = continuation()->rectWithOutlineForRepaint(repaintContainer, ow);
+ r.unite(contRect);
+ }
+ }
+
+ return r;
+}
+
+IntRect RenderInline::rectWithOutlineForRepaint(RenderBoxModelObject* repaintContainer, int outlineWidth)
+{
+ IntRect r(RenderBoxModelObject::rectWithOutlineForRepaint(repaintContainer, outlineWidth));
+ for (RenderObject* curr = firstChild(); curr; curr = curr->nextSibling()) {
+ if (!curr->isText())
+ r.unite(curr->rectWithOutlineForRepaint(repaintContainer, outlineWidth));
+ }
+ return r;
+}
+
+void RenderInline::computeRectForRepaint(RenderBoxModelObject* repaintContainer, IntRect& rect, bool fixed)
+{
+ if (RenderView* v = view()) {
+ // LayoutState is only valid for root-relative repainting
+ if (v->layoutStateEnabled() && !repaintContainer) {
+ LayoutState* layoutState = v->layoutState();
+ if (style()->position() == RelativePosition && layer())
+ rect.move(layer()->relativePositionOffset());
+ rect.move(layoutState->m_offset);
+ if (layoutState->m_clipped)
+ rect.intersect(layoutState->m_clipRect);
+ return;
+ }
+ }
+
+ if (repaintContainer == this)
+ return;
+
+ RenderObject* o = container();
+ if (!o)
+ return;
+
+ IntPoint topLeft = rect.location();
+
+ if (o->isBlockFlow() && style()->position() != AbsolutePosition && style()->position() != FixedPosition) {
+ RenderBlock* cb = toRenderBlock(o);
+ if (cb->hasColumns()) {
+ IntRect repaintRect(topLeft, rect.size());
+ cb->adjustRectForColumns(repaintRect);
+ topLeft = repaintRect.location();
+ rect = repaintRect;
+ }
+ }
+
+ if (style()->position() == RelativePosition && layer()) {
+ // Apply the relative position offset when invalidating a rectangle. The layer
+ // is translated, but the render box isn't, so we need to do this to get the
+ // right dirty rect. Since this is called from RenderObject::setStyle, the relative position
+ // flag on the RenderObject has been cleared, so use the one on the style().
+ topLeft += layer()->relativePositionOffset();
+ }
+
+ // FIXME: We ignore the lightweight clipping rect that controls use, since if |o| is in mid-layout,
+ // its controlClipRect will be wrong. For overflow clip we use the values cached by the layer.
+ if (o->hasOverflowClip()) {
+ RenderBox* containerBox = toRenderBox(o);
+
+ // o->height() is inaccurate if we're in the middle of a layout of |o|, so use the
+ // layer's size instead. Even if the layer's size is wrong, the layer itself will repaint
+ // anyway if its size does change.
+ topLeft -= containerBox->layer()->scrolledContentOffset(); // For overflow:auto/scroll/hidden.
+
+ IntRect repaintRect(topLeft, rect.size());
+ IntRect boxRect(0, 0, containerBox->layer()->width(), containerBox->layer()->height());
+ rect = intersection(repaintRect, boxRect);
+ if (rect.isEmpty())
+ return;
+ } else
+ rect.setLocation(topLeft);
+
+ o->computeRectForRepaint(repaintContainer, rect, fixed);
+}
+
+void RenderInline::updateDragState(bool dragOn)
+{
+ RenderBoxModelObject::updateDragState(dragOn);
+ if (continuation())
+ continuation()->updateDragState(dragOn);
+}
+
+void RenderInline::childBecameNonInline(RenderObject* child)
+{
+ // We have to split the parent flow.
+ RenderBlock* newBox = containingBlock()->createAnonymousBlock();
+ RenderBoxModelObject* oldContinuation = continuation();
+ setContinuation(newBox);
+ RenderObject* beforeChild = child->nextSibling();
+ children()->removeChildNode(this, child);
+ splitFlow(beforeChild, newBox, child, oldContinuation);
+}
+
+void RenderInline::updateHitTestResult(HitTestResult& result, const IntPoint& point)
+{
+ if (result.innerNode())
+ return;
+
+ Node* n = node();
+ IntPoint localPoint(point);
+ if (n) {
+ if (isInlineContinuation()) {
+ // We're in the continuation of a split inline. Adjust our local point to be in the coordinate space
+ // of the principal renderer's containing block. This will end up being the innerNonSharedNode.
+ RenderBlock* firstBlock = n->renderer()->containingBlock();
+
+ // Get our containing block.
+ RenderBox* block = containingBlock();
+ localPoint.move(block->x() - firstBlock->x(), block->y() - firstBlock->y());
+ }
+
+ result.setInnerNode(n);
+ if (!result.innerNonSharedNode())
+ result.setInnerNonSharedNode(n);
+ result.setLocalPoint(localPoint);
+ }
+}
+
+void RenderInline::dirtyLineBoxes(bool fullLayout)
+{
+ if (fullLayout)
+ m_lineBoxes.deleteLineBoxes(renderArena());
+ else
+ m_lineBoxes.dirtyLineBoxes();
+}
+
+InlineFlowBox* RenderInline::createFlowBox()
+{
+ return new (renderArena()) InlineFlowBox(this);
+}
+
+InlineFlowBox* RenderInline::createInlineFlowBox()
+{
+ InlineFlowBox* flowBox = createFlowBox();
+ m_lineBoxes.appendLineBox(flowBox);
+ return flowBox;
+}
+
+int RenderInline::lineHeight(bool firstLine, bool /*isRootLineBox*/) const
+{
+ if (firstLine && document()->usesFirstLineRules()) {
+ RenderStyle* s = style(firstLine);
+ if (s != style())
+ return s->computedLineHeight();
+ }
+
+ if (m_lineHeight == -1)
+ m_lineHeight = style()->computedLineHeight();
+
+ return m_lineHeight;
+}
+
+int RenderInline::verticalPositionFromCache(bool firstLine) const
+{
+ if (firstLine) // We're only really a first-line style if the document actually uses first-line rules.
+ firstLine = document()->usesFirstLineRules();
+ int vpos = m_verticalPosition;
+ if (m_verticalPosition == PositionUndefined || firstLine) {
+ vpos = verticalPosition(firstLine);
+ if (!firstLine)
+ m_verticalPosition = vpos;
+ }
+ return vpos;
+}
+
+IntSize RenderInline::relativePositionedInlineOffset(const RenderBox* child) const
+{
+ ASSERT(isRelPositioned());
+ if (!isRelPositioned())
+ return IntSize();
+
+ // When we have an enclosing relpositioned inline, we need to add in the offset of the first line
+ // box from the rest of the content, but only in the cases where we know we're positioned
+ // relative to the inline itself.
+
+ IntSize offset;
+ int sx;
+ int sy;
+ if (firstLineBox()) {
+ sx = firstLineBox()->x();
+ sy = firstLineBox()->y();
+ } else {
+ sx = layer()->staticX();
+ sy = layer()->staticY();
+ }
+
+ if (!child->style()->hasStaticX())
+ offset.setWidth(sx);
+ // This is not terribly intuitive, but we have to match other browsers. Despite being a block display type inside
+ // an inline, we still keep our x locked to the left of the relative positioned inline. Arguably the correct
+ // behavior would be to go flush left to the block that contains the inline, but that isn't what other browsers
+ // do.
+ else if (!child->style()->isOriginalDisplayInlineType())
+ // Avoid adding in the left border/padding of the containing block twice. Subtract it out.
+ offset.setWidth(sx - (child->containingBlock()->borderLeft() + child->containingBlock()->paddingLeft()));
+
+ if (!child->style()->hasStaticY())
+ offset.setHeight(sy);
+
+ return offset;
+}
+
+void RenderInline::imageChanged(WrappedImagePtr, const IntRect*)
+{
+ if (!parent())
+ return;
+
+ // FIXME: We can do better.
+ repaint();
+}
+
+void RenderInline::addFocusRingRects(GraphicsContext* graphicsContext, int tx, int ty)
+{
+ for (InlineRunBox* curr = firstLineBox(); curr; curr = curr->nextLineBox())
+ graphicsContext->addFocusRingRect(IntRect(tx + curr->x(), ty + curr->y(), curr->width(), curr->height()));
+
+ for (RenderObject* curr = firstChild(); curr; curr = curr->nextSibling()) {
+ if (!curr->isText() && !curr->isListMarker()) {
+ FloatPoint pos(tx, ty);
+ // FIXME: This doesn't work correctly with transforms.
+ if (curr->hasLayer())
+ pos = curr->localToAbsolute();
+ else if (curr->isBox())
+ pos.move(toRenderBox(curr)->x(), toRenderBox(curr)->y());
+ curr->addFocusRingRects(graphicsContext, pos.x(), pos.y());
+ }
+ }
+
+ if (continuation()) {
+ if (continuation()->isInline())
+ continuation()->addFocusRingRects(graphicsContext,
+ tx - containingBlock()->x() + continuation()->containingBlock()->x(),
+ ty - containingBlock()->y() + continuation()->containingBlock()->y());
+ else
+ continuation()->addFocusRingRects(graphicsContext,
+ tx - containingBlock()->x() + toRenderBox(continuation())->x(),
+ ty - containingBlock()->y() + toRenderBox(continuation())->y());
+ }
+}
+
+void RenderInline::paintOutline(GraphicsContext* graphicsContext, int tx, int ty)
+{
+ if (!hasOutline())
+ return;
+
+ if (style()->outlineStyleIsAuto() || hasOutlineAnnotation()) {
+ int ow = style()->outlineWidth();
+ Color oc = style()->outlineColor();
+ if (!oc.isValid())
+ oc = style()->color();
+
+ graphicsContext->initFocusRing(ow, style()->outlineOffset());
+ addFocusRingRects(graphicsContext, tx, ty);
+ if (style()->outlineStyleIsAuto())
+ graphicsContext->drawFocusRing(oc);
+ else
+ addPDFURLRect(graphicsContext, graphicsContext->focusRingBoundingRect());
+ graphicsContext->clearFocusRing();
+ }
+
+ if (style()->outlineStyleIsAuto() || style()->outlineStyle() == BNONE)
+ return;
+
+ Vector<IntRect> rects;
+
+ rects.append(IntRect());
+ for (InlineRunBox* curr = firstLineBox(); curr; curr = curr->nextLineBox())
+ rects.append(IntRect(curr->x(), curr->y(), curr->width(), curr->height()));
+
+ rects.append(IntRect());
+
+ for (unsigned i = 1; i < rects.size() - 1; i++)
+ paintOutlineForLine(graphicsContext, tx, ty, rects.at(i - 1), rects.at(i), rects.at(i + 1));
+}
+
+void RenderInline::paintOutlineForLine(GraphicsContext* graphicsContext, int tx, int ty,
+ const IntRect& lastline, const IntRect& thisline, const IntRect& nextline)
+{
+ int ow = style()->outlineWidth();
+ EBorderStyle os = style()->outlineStyle();
+ Color oc = style()->outlineColor();
+ if (!oc.isValid())
+ oc = style()->color();
+
+ int offset = style()->outlineOffset();
+
+ int t = ty + thisline.y() - offset;
+ int l = tx + thisline.x() - offset;
+ int b = ty + thisline.bottom() + offset;
+ int r = tx + thisline.right() + offset;
+
+ // left edge
+ drawLineForBoxSide(graphicsContext,
+ l - ow,
+ t - (lastline.isEmpty() || thisline.x() < lastline.x() || (lastline.right() - 1) <= thisline.x() ? ow : 0),
+ l,
+ b + (nextline.isEmpty() || thisline.x() <= nextline.x() || (nextline.right() - 1) <= thisline.x() ? ow : 0),
+ BSLeft,
+ oc, style()->color(), os,
+ (lastline.isEmpty() || thisline.x() < lastline.x() || (lastline.right() - 1) <= thisline.x() ? ow : -ow),
+ (nextline.isEmpty() || thisline.x() <= nextline.x() || (nextline.right() - 1) <= thisline.x() ? ow : -ow));
+
+ // right edge
+ drawLineForBoxSide(graphicsContext,
+ r,
+ t - (lastline.isEmpty() || lastline.right() < thisline.right() || (thisline.right() - 1) <= lastline.x() ? ow : 0),
+ r + ow,
+ b + (nextline.isEmpty() || nextline.right() <= thisline.right() || (thisline.right() - 1) <= nextline.x() ? ow : 0),
+ BSRight,
+ oc, style()->color(), os,
+ (lastline.isEmpty() || lastline.right() < thisline.right() || (thisline.right() - 1) <= lastline.x() ? ow : -ow),
+ (nextline.isEmpty() || nextline.right() <= thisline.right() || (thisline.right() - 1) <= nextline.x() ? ow : -ow));
+ // upper edge
+ if (thisline.x() < lastline.x())
+ drawLineForBoxSide(graphicsContext,
+ l - ow,
+ t - ow,
+ min(r+ow, (lastline.isEmpty() ? 1000000 : tx + lastline.x())),
+ t ,
+ BSTop, oc, style()->color(), os,
+ ow,
+ (!lastline.isEmpty() && tx + lastline.x() + 1 < r + ow) ? -ow : ow);
+
+ if (lastline.right() < thisline.right())
+ drawLineForBoxSide(graphicsContext,
+ max(lastline.isEmpty() ? -1000000 : tx + lastline.right(), l - ow),
+ t - ow,
+ r + ow,
+ t ,
+ BSTop, oc, style()->color(), os,
+ (!lastline.isEmpty() && l - ow < tx + lastline.right()) ? -ow : ow,
+ ow);
+
+ // lower edge
+ if (thisline.x() < nextline.x())
+ drawLineForBoxSide(graphicsContext,
+ l - ow,
+ b,
+ min(r + ow, !nextline.isEmpty() ? tx + nextline.x() + 1 : 1000000),
+ b + ow,
+ BSBottom, oc, style()->color(), os,
+ ow,
+ (!nextline.isEmpty() && tx + nextline.x() + 1 < r + ow) ? -ow : ow);
+
+ if (nextline.right() < thisline.right())
+ drawLineForBoxSide(graphicsContext,
+ max(!nextline.isEmpty() ? tx + nextline.right() : -1000000, l - ow),
+ b,
+ r + ow,
+ b + ow,
+ BSBottom, oc, style()->color(), os,
+ (!nextline.isEmpty() && l - ow < tx + nextline.right()) ? -ow : ow,
+ ow);
+}
+
+#if ENABLE(DASHBOARD_SUPPORT)
+void RenderInline::addDashboardRegions(Vector<DashboardRegionValue>& regions)
+{
+ // Convert the style regions to absolute coordinates.
+ if (style()->visibility() != VISIBLE)
+ return;
+
+ const Vector<StyleDashboardRegion>& styleRegions = style()->dashboardRegions();
+ unsigned i, count = styleRegions.size();
+ for (i = 0; i < count; i++) {
+ StyleDashboardRegion styleRegion = styleRegions[i];
+
+ IntRect linesBoundingBox = this->linesBoundingBox();
+ int w = linesBoundingBox.width();
+ int h = linesBoundingBox.height();
+
+ DashboardRegionValue region;
+ region.label = styleRegion.label;
+ region.bounds = IntRect(linesBoundingBox.x() + styleRegion.offset.left().value(),
+ linesBoundingBox.y() + styleRegion.offset.top().value(),
+ w - styleRegion.offset.left().value() - styleRegion.offset.right().value(),
+ h - styleRegion.offset.top().value() - styleRegion.offset.bottom().value());
+ region.type = styleRegion.type;
+
+ RenderObject* container = containingBlock();
+ if (!container)
+ container = this;
+
+ region.clip = region.bounds;
+ container->computeAbsoluteRepaintRect(region.clip);
+ if (region.clip.height() < 0) {
+ region.clip.setHeight(0);
+ region.clip.setWidth(0);
+ }
+
+ FloatPoint absPos = container->localToAbsolute();
+ region.bounds.setX(absPos.x() + region.bounds.x());
+ region.bounds.setY(absPos.y() + region.bounds.y());
+
+ if (document()->frame()) {
+ float pageScaleFactor = document()->frame()->page()->chrome()->scaleFactor();
+ if (pageScaleFactor != 1.0f) {
+ region.bounds.scale(pageScaleFactor);
+ region.clip.scale(pageScaleFactor);
+ }
+ }
+
+ regions.append(region);
+ }
}
+#endif
} // namespace WebCore
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderInline.h b/src/3rdparty/webkit/WebCore/rendering/RenderInline.h
index 1c42a6f..cf6b84b 100644
--- a/src/3rdparty/webkit/WebCore/rendering/RenderInline.h
+++ b/src/3rdparty/webkit/WebCore/rendering/RenderInline.h
@@ -25,60 +25,147 @@
#ifndef RenderInline_h
#define RenderInline_h
-#include "RenderFlow.h"
+#include "RenderBoxModelObject.h"
+#include "RenderLineBoxList.h"
namespace WebCore {
class Position;
-class RenderInline : public RenderFlow {
+class RenderInline : public RenderBoxModelObject {
public:
RenderInline(Node*);
virtual ~RenderInline();
+ virtual RenderObjectChildList* virtualChildren() { return children(); }
+ virtual const RenderObjectChildList* virtualChildren() const { return children(); }
+ const RenderObjectChildList* children() const { return &m_children; }
+ RenderObjectChildList* children() { return &m_children; }
+
+ virtual void destroy();
+
virtual const char* renderName() const;
virtual bool isRenderInline() const { return true; }
- virtual bool isInlineFlow() const { return true; }
- virtual bool childrenInline() const { return true; }
- virtual bool isInlineContinuation() const;
+ virtual void addChild(RenderObject* newChild, RenderObject* beforeChild = 0);
+ void addChildToContinuation(RenderObject* newChild, RenderObject* beforeChild);
+ virtual void addChildIgnoringContinuation(RenderObject* newChild, RenderObject* beforeChild = 0);
- virtual void addChildToFlow(RenderObject* newChild, RenderObject* beforeChild);
void splitInlines(RenderBlock* fromBlock, RenderBlock* toBlock, RenderBlock* middleBlock,
- RenderObject* beforeChild, RenderFlow* oldCont);
+ RenderObject* beforeChild, RenderBoxModelObject* oldCont);
void splitFlow(RenderObject* beforeChild, RenderBlock* newBlockBox,
- RenderObject* newChild, RenderFlow* oldCont);
+ RenderObject* newChild, RenderBoxModelObject* oldCont);
- virtual void layout() { } // Do nothing for layout()
+ virtual void layout() { ASSERT_NOT_REACHED(); } // Do nothing for layout()
virtual void paint(PaintInfo&, int tx, int ty);
virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, int x, int y, int tx, int ty, HitTestAction);
- // overrides RenderObject
- virtual bool requiresLayer();
-
- virtual int width() const;
- virtual int height() const;
+ virtual bool requiresLayer() const { return isRelPositioned() || isTransparent() || hasMask(); }
- // used to calculate offsetWidth/Height. Overridden by inlines (RenderFlow) to return
- // the remaining width on a given line (and the height of a single line).
virtual int offsetLeft() const;
virtual int offsetTop() const;
+ virtual int offsetWidth() const { return linesBoundingBox().width(); }
+ virtual int offsetHeight() const { return linesBoundingBox().height(); }
+
+ // Just ignore top/bottom margins on RenderInlines.
+ virtual int marginTop() const { return 0; }
+ virtual int marginBottom() const { return 0; }
+ virtual int marginLeft() const;
+ virtual int marginRight() const;
+
+ virtual void absoluteRects(Vector<IntRect>&, int tx, int ty);
+ virtual void absoluteQuads(Vector<FloatQuad>&);
+
+ virtual IntRect clippedOverflowRectForRepaint(RenderBoxModelObject* repaintContainer);
+ virtual IntRect rectWithOutlineForRepaint(RenderBoxModelObject* repaintContainer, int outlineWidth);
+ virtual void computeRectForRepaint(RenderBoxModelObject* repaintContainer, IntRect& rect, bool fixed);
+
+ virtual VisiblePosition positionForPoint(const IntPoint&);
+
+ IntRect linesBoundingBox() const;
+
+ virtual IntRect borderBoundingBox() const
+ {
+ IntRect boundingBox = linesBoundingBox();
+ return IntRect(0, 0, boundingBox.width(), boundingBox.height());
+ }
+
+ InlineFlowBox* createInlineFlowBox();
+ void dirtyLineBoxes(bool fullLayout);
+ virtual void dirtyLinesFromChangedChild(RenderObject* child) { m_lineBoxes.dirtyLinesFromChangedChild(this, child); }
+
+ RenderLineBoxList* lineBoxes() { return &m_lineBoxes; }
+ const RenderLineBoxList* lineBoxes() const { return &m_lineBoxes; }
+
+ InlineFlowBox* firstLineBox() const { return m_lineBoxes.firstLineBox(); }
+ InlineFlowBox* lastLineBox() const { return m_lineBoxes.lastLineBox(); }
- void absoluteRects(Vector<IntRect>&, int tx, int ty, bool topLevel = true);
- virtual void absoluteQuads(Vector<FloatQuad>&, bool topLevel = true);
+ virtual int lineHeight(bool firstLine, bool isRootLineBox = false) const;
- virtual VisiblePosition positionForCoordinates(int x, int y);
+ RenderBoxModelObject* continuation() const { return m_continuation; }
+ RenderInline* inlineContinuation() const;
+ void setContinuation(RenderBoxModelObject* c) { m_continuation = c; }
+
+ virtual void updateDragState(bool dragOn);
+
+ virtual void childBecameNonInline(RenderObject* child);
+ virtual void updateHitTestResult(HitTestResult&, const IntPoint&);
+
+ IntSize relativePositionedInlineOffset(const RenderBox* child) const;
+
+ virtual void addFocusRingRects(GraphicsContext*, int tx, int ty);
+ void paintOutline(GraphicsContext*, int tx, int ty);
+
+ virtual void imageChanged(WrappedImagePtr, const IntRect* = 0);
+
+ int verticalPositionFromCache(bool firstLine) const;
+ void invalidateVerticalPosition() { m_verticalPosition = PositionUndefined; }
+
+#if ENABLE(DASHBOARD_SUPPORT)
+ virtual void addDashboardRegions(Vector<DashboardRegionValue>&);
+#endif
+
protected:
- virtual void styleDidChange(RenderStyle::Diff, const RenderStyle* oldStyle);
+ virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
+ virtual void updateBoxModelInfoFromStyle();
+ virtual InlineFlowBox* createFlowBox(); // Subclassed by SVG
+
+ static RenderInline* cloneInline(RenderInline* src);
- static RenderInline* cloneInline(RenderFlow* src);
+private:
+ void paintOutlineForLine(GraphicsContext*, int tx, int ty, const IntRect& prevLine, const IntRect& thisLine, const IntRect& nextLine);
+ RenderBoxModelObject* continuationBefore(RenderObject* beforeChild);
+protected:
+ 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.
+
+private:
+ RenderBoxModelObject* m_continuation; // Can be either a block or an inline. <b><i><p>Hello</p></i></b>. In this example the <i> will have a block as its continuation but the
+ // <b> will just have an inline as its continuation.
+ mutable int m_lineHeight;
+ mutable int m_verticalPosition;
};
+inline RenderInline* toRenderInline(RenderObject* o)
+{
+ ASSERT(!o || o->isRenderInline());
+ return static_cast<RenderInline*>(o);
+}
+
+inline const RenderInline* toRenderInline(const RenderObject* o)
+{
+ ASSERT(!o || o->isRenderInline());
+ return static_cast<const RenderInline*>(o);
+}
+
+// This will catch anyone doing an unnecessary cast.
+void toRenderInline(const RenderInline*);
+
} // namespace WebCore
#endif // RenderInline_h
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderLayer.cpp b/src/3rdparty/webkit/WebCore/rendering/RenderLayer.cpp
index 9c9eff0..ba85f1a 100644
--- a/src/3rdparty/webkit/WebCore/rendering/RenderLayer.cpp
+++ b/src/3rdparty/webkit/WebCore/rendering/RenderLayer.cpp
@@ -44,10 +44,14 @@
#include "config.h"
#include "RenderLayer.h"
+#include "CString.h"
#include "CSSPropertyNames.h"
+#include "CSSStyleDeclaration.h"
+#include "CSSStyleSelector.h"
#include "Document.h"
#include "EventHandler.h"
#include "EventNames.h"
+#include "FloatPoint3D.h"
#include "FloatRect.h"
#include "FocusController.h"
#include "Frame.h"
@@ -59,6 +63,7 @@
#include "HitTestRequest.h"
#include "HitTestResult.h"
#include "OverflowEvent.h"
+#include "OverlapTestRequestClient.h"
#include "Page.h"
#include "PlatformMouseEvent.h"
#include "RenderArena.h"
@@ -73,8 +78,16 @@
#include "Scrollbar.h"
#include "ScrollbarTheme.h"
#include "SelectionController.h"
+#include "TransformationMatrix.h"
+#include "TransformState.h"
#include "TranslateTransformOperation.h"
#include <wtf/StdLibExtras.h>
+#include <wtf/UnusedParam.h>
+
+#if USE(ACCELERATED_COMPOSITING)
+#include "RenderLayerBacking.h"
+#include "RenderLayerCompositor.h"
+#endif
#if ENABLE(SVG)
#include "SVGNames.h"
@@ -88,12 +101,6 @@ namespace WebCore {
using namespace HTMLNames;
-const RenderLayer::ScrollAlignment RenderLayer::gAlignCenterIfNeeded = { RenderLayer::noScroll, RenderLayer::alignCenter, RenderLayer::alignToClosestEdge };
-const RenderLayer::ScrollAlignment RenderLayer::gAlignToEdgeIfNeeded = { RenderLayer::noScroll, RenderLayer::alignToClosestEdge, RenderLayer::alignToClosestEdge };
-const RenderLayer::ScrollAlignment RenderLayer::gAlignCenterAlways = { RenderLayer::alignCenter, RenderLayer::alignCenter, RenderLayer::alignCenter };
-const RenderLayer::ScrollAlignment RenderLayer::gAlignTopAlways = { RenderLayer::alignTop, RenderLayer::alignTop, RenderLayer::alignTop };
-const RenderLayer::ScrollAlignment RenderLayer::gAlignBottomAlways = { RenderLayer::alignBottom, RenderLayer::alignBottom, RenderLayer::alignBottom };
-
const int MinimumWidthWhileResizing = 100;
const int MinimumHeightWhileResizing = 40;
@@ -116,8 +123,8 @@ void ClipRects::destroy(RenderArena* renderArena)
renderArena->free(*(size_t *)this, this);
}
-RenderLayer::RenderLayer(RenderObject* object)
- : m_object(object)
+RenderLayer::RenderLayer(RenderBoxModelObject* renderer)
+ : m_renderer(renderer)
, m_parent(0)
, m_previous(0)
, m_next(0)
@@ -138,15 +145,15 @@ RenderLayer::RenderLayer(RenderObject* object)
, m_inResizeMode(false)
, m_posZOrderList(0)
, m_negZOrderList(0)
- , m_overflowList(0)
+ , m_normalFlowList(0)
, m_clipRects(0)
#ifndef NDEBUG
, m_clipRectsRoot(0)
#endif
, m_scrollDimensionsDirty(true)
, m_zOrderListsDirty(true)
- , m_overflowListDirty(true)
- , m_isOverflowOnly(shouldBeOverflowOnly())
+ , m_normalFlowListDirty(true)
+ , m_isNormalFlowOnly(shouldBeNormalFlowOnly())
, m_usedTransparency(false)
, m_paintingInsideReflection(false)
, m_inOverflowRelayout(false)
@@ -156,17 +163,22 @@ RenderLayer::RenderLayer(RenderObject* object)
, m_hasVisibleContent(false)
, m_visibleDescendantStatusDirty(false)
, m_hasVisibleDescendant(false)
+ , m_3DTransformedDescendantStatusDirty(true)
+ , m_has3DTransformedDescendant(false)
+#if USE(ACCELERATED_COMPOSITING)
+ , m_hasCompositingDescendant(false)
+ , m_mustOverlayCompositedLayers(false)
+#endif
, m_marquee(0)
, m_staticX(0)
, m_staticY(0)
- , m_transform(0)
, m_reflection(0)
, m_scrollCorner(0)
, m_resizer(0)
{
- if (!object->firstChild() && object->style()) {
+ if (!renderer->firstChild() && renderer->style()) {
m_visibleContentStatusDirty = false;
- m_hasVisibleContent = object->style()->visibility() == VISIBLE;
+ m_hasVisibleContent = renderer->style()->visibility() == VISIBLE;
}
}
@@ -185,9 +197,13 @@ RenderLayer::~RenderLayer()
delete m_posZOrderList;
delete m_negZOrderList;
- delete m_overflowList;
+ delete m_normalFlowList;
delete m_marquee;
+#if USE(ACCELERATED_COMPOSITING)
+ clearBacking();
+#endif
+
// Make sure we have no lingering clip rects.
ASSERT(!m_clipRects);
@@ -204,11 +220,53 @@ RenderLayer::~RenderLayer()
m_resizer->destroy();
}
+#if USE(ACCELERATED_COMPOSITING)
+RenderLayerCompositor* RenderLayer::compositor() const
+{
+ ASSERT(renderer()->view());
+ return renderer()->view()->compositor();
+}
+
+void RenderLayer::rendererContentChanged()
+{
+ // This can get called when video becomes accelerated, so the layers may change.
+ if (compositor()->updateLayerCompositingState(this))
+ compositor()->setCompositingLayersNeedUpdate();
+
+ if (m_backing)
+ m_backing->rendererContentChanged();
+}
+#endif // USE(ACCELERATED_COMPOSITING)
+
+bool RenderLayer::hasAcceleratedCompositing() const
+{
+#if USE(ACCELERATED_COMPOSITING)
+ return compositor()->hasAcceleratedCompositing();
+#else
+ return false;
+#endif
+}
+
+void RenderLayer::setStaticY(int staticY)
+{
+ if (m_staticY == staticY)
+ return;
+ m_staticY = staticY;
+ renderer()->setChildNeedsLayout(true, false);
+}
+
void RenderLayer::updateLayerPositions(bool doFullRepaint, bool checkForRepaint)
{
if (doFullRepaint) {
- m_object->repaint();
+ renderer()->repaint();
+#if USE(ACCELERATED_COMPOSITING)
+ checkForRepaint = false;
+ // We need the full repaint to propagate to child layers if we are hardware compositing.
+ if (!compositor()->inCompositingMode())
+ doFullRepaint = false;
+#else
checkForRepaint = doFullRepaint = false;
+#endif
}
updateLayerPosition(); // For relpositioned layers or non-positioned layers,
@@ -225,22 +283,23 @@ void RenderLayer::updateLayerPositions(bool doFullRepaint, bool checkForRepaint)
updateTransform();
if (m_hasVisibleContent) {
- RenderView* view = m_object->view();
+ RenderView* view = renderer()->view();
ASSERT(view);
// FIXME: Optimize using LayoutState and remove the disableLayoutState() call
// from updateScrollInfoAfterLayout().
- ASSERT(!view->layoutState());
+ ASSERT(!view->layoutStateEnabled());
- IntRect newRect = m_object->absoluteClippedOverflowRect();
- IntRect newOutlineBox = m_object->absoluteOutlineBounds();
+ RenderBoxModelObject* repaintContainer = renderer()->containerForRepaint();
+ IntRect newRect = renderer()->clippedOverflowRectForRepaint(repaintContainer);
+ IntRect newOutlineBox = renderer()->outlineBoundsForRepaint(repaintContainer);
if (checkForRepaint) {
if (view && !view->printing()) {
if (m_needsFullRepaint) {
- view->repaintViewRectangle(m_repaintRect);
+ renderer()->repaintUsingContainer(repaintContainer, m_repaintRect);
if (newRect != m_repaintRect)
- view->repaintViewRectangle(newRect);
+ renderer()->repaintUsingContainer(repaintContainer, newRect);
} else
- m_object->repaintAfterLayoutIfNeeded(m_repaintRect, m_outlineBox);
+ renderer()->repaintAfterLayoutIfNeeded(repaintContainer, m_repaintRect, m_outlineBox);
}
}
m_repaintRect = newRect;
@@ -258,6 +317,11 @@ void RenderLayer::updateLayerPositions(bool doFullRepaint, bool checkForRepaint)
for (RenderLayer* child = firstChild(); child; child = child->nextSibling())
child->updateLayerPositions(doFullRepaint, checkForRepaint);
+
+#if USE(ACCELERATED_COMPOSITING)
+ if (isComposited())
+ backing()->updateAfterLayout();
+#endif
// With all our children positioned, now update our marquee if we need to.
if (m_marquee)
@@ -266,7 +330,11 @@ void RenderLayer::updateLayerPositions(bool doFullRepaint, bool checkForRepaint)
void RenderLayer::updateTransform()
{
- bool hasTransform = renderer()->hasTransform();
+ // hasTransform() on the renderer is also true when there is transform-style: preserve-3d or perspective set,
+ // so check style too.
+ bool hasTransform = renderer()->hasTransform() && renderer()->style()->hasTransform();
+ bool had3DTransform = has3DTransform();
+
bool hadTransform = m_transform;
if (hasTransform != hadTransform) {
if (hasTransform)
@@ -276,9 +344,33 @@ void RenderLayer::updateTransform()
}
if (hasTransform) {
- m_transform->reset();
- renderer()->style()->applyTransform(*m_transform, renderer()->borderBox().size());
+ RenderBox* box = renderBox();
+ ASSERT(box);
+ m_transform->makeIdentity();
+ box->style()->applyTransform(*m_transform, box->borderBoxRect().size(), RenderStyle::IncludeTransformOrigin);
+ makeMatrixRenderable(*m_transform, hasAcceleratedCompositing());
}
+
+ if (had3DTransform != has3DTransform())
+ dirty3DTransformedDescendantStatus();
+}
+
+TransformationMatrix RenderLayer::currentTransform() const
+{
+ if (!m_transform)
+ return TransformationMatrix();
+
+#if USE(ACCELERATED_COMPOSITING)
+ if (renderer()->style()->isRunningAcceleratedAnimation()) {
+ TransformationMatrix currTransform;
+ RefPtr<RenderStyle> style = renderer()->animation()->getAnimatedStyleForRenderer(renderer());
+ style->applyTransform(currTransform, renderBox()->borderBoxRect().size(), RenderStyle::IncludeTransformOrigin);
+ makeMatrixRenderable(currTransform, hasAcceleratedCompositing());
+ return currTransform;
+ }
+#endif
+
+ return *m_transform;
}
void RenderLayer::setHasVisibleContent(bool b)
@@ -288,9 +380,10 @@ void RenderLayer::setHasVisibleContent(bool b)
m_visibleContentStatusDirty = false;
m_hasVisibleContent = b;
if (m_hasVisibleContent) {
- m_repaintRect = renderer()->absoluteClippedOverflowRect();
- m_outlineBox = renderer()->absoluteOutlineBounds();
- if (!isOverflowOnly())
+ RenderBoxModelObject* repaintContainer = renderer()->containerForRepaint();
+ m_repaintRect = renderer()->clippedOverflowRectForRepaint(repaintContainer);
+ m_outlineBox = renderer()->outlineBoundsForRepaint(repaintContainer);
+ if (!isNormalFlowOnly())
dirtyStackingContextZOrderLists();
}
if (parent())
@@ -342,12 +435,12 @@ void RenderLayer::updateVisibilityStatus()
}
if (m_visibleContentStatusDirty) {
- if (m_object->style()->visibility() == VISIBLE)
+ if (renderer()->style()->visibility() == VISIBLE)
m_hasVisibleContent = true;
else {
// layer may be hidden but still have some visible content, check for this
m_hasVisibleContent = false;
- RenderObject* r = m_object->firstChild();
+ RenderObject* r = renderer()->firstChild();
while (r) {
if (r->style()->visibility() == VISIBLE && !r->hasLayer()) {
m_hasVisibleContent = true;
@@ -360,7 +453,7 @@ void RenderLayer::updateVisibilityStatus()
else {
do {
r = r->parent();
- if (r==m_object)
+ if (r==renderer())
r = 0;
} while (r && !r->nextSibling());
if (r)
@@ -372,83 +465,180 @@ void RenderLayer::updateVisibilityStatus()
}
}
+void RenderLayer::dirty3DTransformedDescendantStatus()
+{
+ RenderLayer* curr = stackingContext();
+ if (curr)
+ curr->m_3DTransformedDescendantStatusDirty = true;
+
+ // This propagates up through preserve-3d hierarchies to the enclosing flattening layer.
+ // Note that preserves3D() creates stacking context, so we can just run up the stacking contexts.
+ while (curr && curr->preserves3D()) {
+ curr->m_3DTransformedDescendantStatusDirty = true;
+ curr = curr->stackingContext();
+ }
+}
+
+// Return true if this layer or any preserve-3d descendants have 3d.
+bool RenderLayer::update3DTransformedDescendantStatus()
+{
+ if (m_3DTransformedDescendantStatusDirty) {
+ m_has3DTransformedDescendant = false;
+
+ // Transformed or preserve-3d descendants can only be in the z-order lists, not
+ // in the normal flow list, so we only need to check those.
+ if (m_posZOrderList) {
+ for (unsigned i = 0; i < m_posZOrderList->size(); ++i)
+ m_has3DTransformedDescendant |= m_posZOrderList->at(i)->update3DTransformedDescendantStatus();
+ }
+
+ // Now check our negative z-index children.
+ if (m_negZOrderList) {
+ for (unsigned i = 0; i < m_negZOrderList->size(); ++i)
+ m_has3DTransformedDescendant |= m_negZOrderList->at(i)->update3DTransformedDescendantStatus();
+ }
+
+ m_3DTransformedDescendantStatusDirty = false;
+ }
+
+ // If we live in a 3d hierarchy, then the layer at the root of that hierarchy needs
+ // the m_has3DTransformedDescendant set.
+ if (preserves3D())
+ return has3DTransform() || m_has3DTransformedDescendant;
+
+ return has3DTransform();
+}
+
void RenderLayer::updateLayerPosition()
{
// Clear our cached clip rect information.
clearClipRects();
- int x = m_object->xPos();
- int y = m_object->yPos() - m_object->borderTopExtra();
+ RenderBox* rendererBox = renderBox();
+
+ int x = rendererBox ? rendererBox->x() : 0;
+ int y = rendererBox ? rendererBox->y() : 0;
- if (!m_object->isPositioned() && m_object->parent()) {
+ if (!renderer()->isPositioned() && renderer()->parent()) {
// We must adjust our position by walking up the render tree looking for the
// nearest enclosing object with a layer.
- RenderObject* curr = m_object->parent();
+ RenderObject* curr = renderer()->parent();
while (curr && !curr->hasLayer()) {
- if (!curr->isTableRow()) {
+ if (curr->isBox() && !curr->isTableRow()) {
// Rows and cells share the same coordinate space (that of the section).
// Omit them when computing our xpos/ypos.
- x += curr->xPos();
- y += curr->yPos();
+ RenderBox* currBox = toRenderBox(curr);
+ x += currBox->x();
+ y += currBox->y();
}
curr = curr->parent();
}
- y += curr->borderTopExtra();
- if (curr->isTableRow()) {
+ if (curr->isBox() && curr->isTableRow()) {
// Put ourselves into the row coordinate space.
- x -= curr->xPos();
- y -= curr->yPos();
+ RenderBox* currBox = toRenderBox(curr);
+ x -= currBox->x();
+ y -= currBox->y();
}
}
m_relX = m_relY = 0;
- if (m_object->isRelPositioned()) {
- m_relX = static_cast<RenderBox*>(m_object)->relativePositionOffsetX();
- m_relY = static_cast<RenderBox*>(m_object)->relativePositionOffsetY();
+ if (renderer()->isRelPositioned()) {
+ m_relX = renderer()->relativePositionOffsetX();
+ m_relY = renderer()->relativePositionOffsetY();
x += m_relX; y += m_relY;
}
// Subtract our parent's scroll offset.
- if (m_object->isPositioned() && enclosingPositionedAncestor()) {
+ if (renderer()->isPositioned() && enclosingPositionedAncestor()) {
RenderLayer* positionedParent = enclosingPositionedAncestor();
// For positioned layers, we subtract out the enclosing positioned layer's scroll offset.
positionedParent->subtractScrolledContentOffset(x, y);
- if (m_object->isPositioned()) {
- IntSize offset = static_cast<RenderBox*>(m_object)->offsetForPositionedInContainer(positionedParent->renderer());
+ if (renderer()->isPositioned() && positionedParent->renderer()->isRelPositioned() && positionedParent->renderer()->isRenderInline()) {
+ IntSize offset = toRenderInline(positionedParent->renderer())->relativePositionedInlineOffset(toRenderBox(renderer()));
x += offset.width();
y += offset.height();
}
} else if (parent())
parent()->subtractScrolledContentOffset(x, y);
- setPos(x,y);
+ // FIXME: We'd really like to just get rid of the concept of a layer rectangle and rely on the renderers.
- setWidth(m_object->width());
- setHeight(m_object->height() + m_object->borderTopExtra() + m_object->borderBottomExtra());
+ setLocation(x, y);
- if (!m_object->hasOverflowClip()) {
- if (m_object->overflowWidth() > m_object->width())
- setWidth(m_object->overflowWidth());
- if (m_object->overflowHeight() > m_object->height())
- setHeight(m_object->overflowHeight());
+ if (renderer()->isRenderInline()) {
+ RenderInline* inlineFlow = toRenderInline(renderer());
+ IntRect lineBox = inlineFlow->linesBoundingBox();
+ setWidth(lineBox.width());
+ setHeight(lineBox.height());
+ } else if (RenderBox* box = renderBox()) {
+ setWidth(box->width());
+ setHeight(box->height());
+
+ if (!box->hasOverflowClip()) {
+ if (box->overflowWidth() > box->width())
+ setWidth(box->overflowWidth());
+ if (box->overflowHeight() > box->height())
+ setHeight(box->overflowHeight());
+ }
}
}
-RenderLayer *RenderLayer::stackingContext() const
+TransformationMatrix RenderLayer::perspectiveTransform() const
{
- RenderLayer* curr = parent();
- for ( ; curr && !curr->m_object->isRenderView() && !curr->m_object->isRoot() &&
- curr->m_object->style()->hasAutoZIndex();
- curr = curr->parent()) { }
- return curr;
+ if (!renderer()->hasTransform())
+ return TransformationMatrix();
+
+ RenderStyle* style = renderer()->style();
+ if (!style->hasPerspective())
+ return TransformationMatrix();
+
+ // Maybe fetch the perspective from the backing?
+ const IntRect borderBox = toRenderBox(renderer())->borderBoxRect();
+ const float boxWidth = borderBox.width();
+ const float boxHeight = borderBox.height();
+
+ float perspectiveOriginX = style->perspectiveOriginX().calcFloatValue(boxWidth);
+ float perspectiveOriginY = style->perspectiveOriginY().calcFloatValue(boxHeight);
+
+ // A perspective origin of 0,0 makes the vanishing point in the center of the element.
+ // We want it to be in the top-left, so subtract half the height and width.
+ perspectiveOriginX -= boxWidth / 2.0f;
+ perspectiveOriginY -= boxHeight / 2.0f;
+
+ TransformationMatrix t;
+ t.translate(perspectiveOriginX, perspectiveOriginY);
+ t.applyPerspective(style->perspective());
+ t.translate(-perspectiveOriginX, -perspectiveOriginY);
+
+ return t;
+}
+
+FloatPoint RenderLayer::perspectiveOrigin() const
+{
+ if (!renderer()->hasTransform())
+ return FloatPoint();
+
+ const IntRect borderBox = toRenderBox(renderer())->borderBoxRect();
+ RenderStyle* style = renderer()->style();
+
+ return FloatPoint(style->perspectiveOriginX().calcFloatValue(borderBox.width()),
+ style->perspectiveOriginY().calcFloatValue(borderBox.height()));
+}
+
+RenderLayer* RenderLayer::stackingContext() const
+{
+ RenderLayer* layer = parent();
+ while (layer && !layer->renderer()->isRenderView() && !layer->renderer()->isRoot() && layer->renderer()->style()->hasAutoZIndex())
+ layer = layer->parent();
+ return layer;
}
RenderLayer* RenderLayer::enclosingPositionedAncestor() const
{
RenderLayer* curr = parent();
- for ( ; curr && !curr->m_object->isRenderView() && !curr->m_object->isPositioned() && !curr->m_object->isRelPositioned() && !curr->hasTransform();
+ for ( ; curr && !curr->renderer()->isRenderView() && !curr->renderer()->isPositioned() && !curr->renderer()->isRelPositioned() && !curr->hasTransform();
curr = curr->parent()) { }
return curr;
}
@@ -456,11 +646,32 @@ RenderLayer* RenderLayer::enclosingPositionedAncestor() const
RenderLayer* RenderLayer::enclosingTransformedAncestor() const
{
RenderLayer* curr = parent();
- for ( ; curr && !curr->m_object->isRenderView() && !curr->transform(); curr = curr->parent())
+ for ( ; curr && !curr->renderer()->isRenderView() && !curr->transform(); curr = curr->parent())
{ }
return curr;
}
+#if USE(ACCELERATED_COMPOSITING)
+RenderLayer* RenderLayer::enclosingCompositingLayer(bool includeSelf) const
+{
+ if (includeSelf && isComposited())
+ return const_cast<RenderLayer*>(this);
+
+ // Compositing layers are parented according to stacking order and overflow list,
+ // so we have to check whether the parent is a stacking context, or whether
+ // the child is overflow-only.
+ bool inNormalFlowList = isNormalFlowOnly();
+ for (RenderLayer* curr = parent(); curr; curr = curr->parent()) {
+ if (curr->isComposited() && (inNormalFlowList || curr->isStackingContext()))
+ return curr;
+
+ inNormalFlowList = curr->isNormalFlowOnly();
+ }
+
+ return 0;
+}
+#endif
+
IntPoint RenderLayer::absoluteToContents(const IntPoint& absolutePoint) const
{
// We don't use convertToLayerCoords because it doesn't know about transforms
@@ -479,18 +690,24 @@ bool RenderLayer::requiresSlowRepaints() const
bool RenderLayer::isTransparent() const
{
#if ENABLE(SVG)
- if (m_object->node()->namespaceURI() == SVGNames::svgNamespaceURI)
+ if (renderer()->node() && renderer()->node()->namespaceURI() == SVGNames::svgNamespaceURI)
return false;
#endif
- return m_object->isTransparent() || m_object->hasMask();
+ return renderer()->isTransparent() || renderer()->hasMask();
}
-RenderLayer*
-RenderLayer::transparentAncestor()
+RenderLayer* RenderLayer::transparentPaintingAncestor()
{
- RenderLayer* curr = parent();
- for ( ; curr && !curr->isTransparent(); curr = curr->parent()) { }
- return curr;
+ if (isComposited())
+ return 0;
+
+ for (RenderLayer* curr = parent(); curr; curr = curr->parent()) {
+ if (curr->isComposited())
+ return 0;
+ if (curr->isTransparent())
+ return curr;
+ }
+ return 0;
}
static IntRect transparencyClipBox(const TransformationMatrix& enclosingTransform, const RenderLayer* l, const RenderLayer* rootLayer)
@@ -499,16 +716,16 @@ static IntRect transparencyClipBox(const TransformationMatrix& enclosingTransfor
// paintDirtyRect, and that should cut down on the amount we have to paint. Still it
// would be better to respect clips.
- TransformationMatrix* t = l->transform();
- if (t && rootLayer != l) {
+ if (rootLayer != l && l->paintsWithTransform()) {
// The best we can do here is to use enclosed bounding boxes to establish a "fuzzy" enough clip to encompass
// the transformed layer and all of its children.
int x = 0;
int y = 0;
l->convertToLayerCoords(rootLayer, x, y);
+
TransformationMatrix transform;
transform.translate(x, y);
- transform = *t * transform;
+ transform = *l->transform() * transform;
transform = transform * enclosingTransform;
// We now have a transform that will produce a rectangle in our view's space.
@@ -542,14 +759,14 @@ static IntRect transparencyClipBox(const TransformationMatrix& enclosingTransfor
void RenderLayer::beginTransparencyLayers(GraphicsContext* p, const RenderLayer* rootLayer)
{
- if (p->paintingDisabled() || (isTransparent() && m_usedTransparency))
+ if (p->paintingDisabled() || (paintsWithTransparency() && m_usedTransparency))
return;
- RenderLayer* ancestor = transparentAncestor();
+ RenderLayer* ancestor = transparentPaintingAncestor();
if (ancestor)
ancestor->beginTransparencyLayers(p, rootLayer);
- if (isTransparent()) {
+ if (paintsWithTransparency()) {
m_usedTransparency = true;
p->save();
p->clip(transparencyClipBox(TransformationMatrix(), this, rootLayer));
@@ -569,7 +786,7 @@ void RenderLayer::operator delete(void* ptr, size_t sz)
}
void RenderLayer::destroy(RenderArena* renderArena)
-{
+{
delete this;
// Recover the size left there for us by operator delete and free the memory.
@@ -593,10 +810,10 @@ void RenderLayer::addChild(RenderLayer* child, RenderLayer* beforeChild)
child->setParent(this);
- if (child->isOverflowOnly())
- dirtyOverflowList();
+ if (child->isNormalFlowOnly())
+ dirtyNormalFlowList();
- if (!child->isOverflowOnly() || child->firstChild()) {
+ if (!child->isNormalFlowOnly() || child->firstChild()) {
// Dirty the z-order list in which we are contained. The stackingContext() can be null in the
// case where we're building up generated content layers. This is ok, since the lists will start
// off dirty in that case anyway.
@@ -606,10 +823,19 @@ void RenderLayer::addChild(RenderLayer* child, RenderLayer* beforeChild)
child->updateVisibilityStatus();
if (child->m_hasVisibleContent || child->m_hasVisibleDescendant)
childVisibilityChanged(true);
+
+#if USE(ACCELERATED_COMPOSITING)
+ compositor()->layerWasAdded(this, child);
+#endif
}
RenderLayer* RenderLayer::removeChild(RenderLayer* oldChild)
{
+#if USE(ACCELERATED_COMPOSITING)
+ if (!renderer()->documentBeingDestroyed())
+ compositor()->layerWillBeRemoved(this, oldChild);
+#endif
+
// remove the child
if (oldChild->previousSibling())
oldChild->previousSibling()->setNextSibling(oldChild->nextSibling());
@@ -621,9 +847,9 @@ RenderLayer* RenderLayer::removeChild(RenderLayer* oldChild)
if (m_last == oldChild)
m_last = oldChild->previousSibling();
- if (oldChild->isOverflowOnly())
- dirtyOverflowList();
- if (!oldChild->isOverflowOnly() || oldChild->firstChild()) {
+ if (oldChild->isNormalFlowOnly())
+ dirtyNormalFlowList();
+ if (!oldChild->isNormalFlowOnly() || oldChild->firstChild()) {
// Dirty the z-order list in which we are contained. When called via the
// reattachment process in removeOnlyThisLayer, the layer may already be disconnected
// from the main layer tree, so we need to null-check the |stackingContext| value.
@@ -645,7 +871,15 @@ void RenderLayer::removeOnlyThisLayer()
{
if (!m_parent)
return;
-
+
+ // Mark that we are about to lose our layer. This makes render tree
+ // walks ignore this layer while we're removing it.
+ m_renderer->setHasLayer(false);
+
+#if USE(ACCELERATED_COMPOSITING)
+ compositor()->layerWillBeRemoved(m_parent, this);
+#endif
+
// Dirty the clip rects.
clearClipRectsIncludingDescendants();
@@ -663,11 +897,11 @@ void RenderLayer::removeOnlyThisLayer()
RenderLayer* next = current->nextSibling();
removeChild(current);
parent->addChild(current, nextSib);
- current->updateLayerPositions();
+ current->updateLayerPositions(); // Depends on hasLayer() already being false for proper layout.
current = next;
}
-
- destroy(renderer()->renderArena());
+
+ m_renderer->destroyLayer();
}
void RenderLayer::insertOnlyThisLayer()
@@ -676,46 +910,46 @@ void RenderLayer::insertOnlyThisLayer()
// We need to connect ourselves when our renderer() has a parent.
// Find our enclosingLayer and add ourselves.
RenderLayer* parentLayer = renderer()->parent()->enclosingLayer();
+ ASSERT(parentLayer);
RenderLayer* beforeChild = parentLayer->reflectionLayer() != this ? renderer()->parent()->findNextLayer(parentLayer, renderer()) : 0;
- if (parentLayer)
- parentLayer->addChild(this, beforeChild);
+ parentLayer->addChild(this, beforeChild);
}
-
+
// Remove all descendant layers from the hierarchy and add them to the new position.
for (RenderObject* curr = renderer()->firstChild(); curr; curr = curr->nextSibling())
curr->moveLayers(m_parent, this);
-
+
// Clear out all the clip rects.
clearClipRectsIncludingDescendants();
}
void
-RenderLayer::convertToLayerCoords(const RenderLayer* ancestorLayer, int& x, int& y) const
+RenderLayer::convertToLayerCoords(const RenderLayer* ancestorLayer, int& xPos, int& yPos) const
{
if (ancestorLayer == this)
return;
- if (m_object->style()->position() == FixedPosition) {
+ if (renderer()->style()->position() == FixedPosition) {
// Add in the offset of the view. We can obtain this by calling
// localToAbsolute() on the RenderView.
- FloatPoint absPos = m_object->localToAbsolute(FloatPoint(), true);
- x += absPos.x();
- y += absPos.y();
+ FloatPoint absPos = renderer()->localToAbsolute(FloatPoint(), true);
+ xPos += absPos.x();
+ yPos += absPos.y();
return;
}
RenderLayer* parentLayer;
- if (m_object->style()->position() == AbsolutePosition)
+ if (renderer()->style()->position() == AbsolutePosition)
parentLayer = enclosingPositionedAncestor();
else
parentLayer = parent();
if (!parentLayer) return;
- parentLayer->convertToLayerCoords(ancestorLayer, x, y);
+ parentLayer->convertToLayerCoords(ancestorLayer, xPos, yPos);
- x += xPos();
- y += yPos();
+ xPos += x();
+ yPos += y();
}
void RenderLayer::panScrollFromPoint(const IntPoint& sourcePoint)
@@ -724,7 +958,6 @@ void RenderLayer::panScrollFromPoint(const IntPoint& sourcePoint)
const int shortDistanceLimit = 100; // We delimit a 200 pixels long square enclosing the original point
const int speedReducer = 2; // Within this square we divide the scrolling speed by 2
- const int iconRadius = 10;
Frame* frame = renderer()->document()->frame();
if (!frame)
return;
@@ -741,9 +974,9 @@ void RenderLayer::panScrollFromPoint(const IntPoint& sourcePoint)
int xDelta = currentMousePosition.x() - sourcePoint.x();
int yDelta = currentMousePosition.y() - sourcePoint.y();
- if (abs(xDelta) < iconRadius) // at the center we let the space for the icon
+ if (abs(xDelta) < ScrollView::noPanScrollRadius) // at the center we let the space for the icon
xDelta = 0;
- if (abs(yDelta) < iconRadius)
+ if (abs(yDelta) < ScrollView::noPanScrollRadius)
yDelta = 0;
// Let's attenuate the speed for the short distances
@@ -758,10 +991,10 @@ void RenderLayer::panScrollFromPoint(const IntPoint& sourcePoint)
void RenderLayer::scrollByRecursively(int xDelta, int yDelta)
{
bool restrictedByLineClamp = false;
- if (m_object->parent())
- restrictedByLineClamp = m_object->parent()->style()->lineClamp() >= 0;
+ if (renderer()->parent())
+ restrictedByLineClamp = renderer()->parent()->style()->lineClamp() >= 0;
- if (m_object->hasOverflowClip() && !restrictedByLineClamp) {
+ if (renderer()->hasOverflowClip() && !restrictedByLineClamp) {
int newOffsetX = scrollXOffset() + xDelta;
int newOffsetY = scrollYOffset() + yDelta;
scrollToOffset(newOffsetX, newOffsetY);
@@ -769,14 +1002,14 @@ void RenderLayer::scrollByRecursively(int xDelta, int yDelta)
// If this layer can't do the scroll we ask its parent
int leftToScrollX = newOffsetX - scrollXOffset();
int leftToScrollY = newOffsetY - scrollYOffset();
- if ((leftToScrollX || leftToScrollY) && m_object->parent()) {
- m_object->parent()->enclosingLayer()->scrollByRecursively(leftToScrollX, leftToScrollY);
+ if ((leftToScrollX || leftToScrollY) && renderer()->parent()) {
+ renderer()->parent()->enclosingLayer()->scrollByRecursively(leftToScrollX, leftToScrollY);
Frame* frame = renderer()->document()->frame();
if (frame)
frame->eventHandler()->updateAutoscrollRenderer();
}
- } else if (m_object->view()->frameView())
- m_object->view()->frameView()->scrollBy(IntSize(xDelta, yDelta));
+ } else if (renderer()->view()->frameView())
+ renderer()->view()->frameView()->scrollBy(IntSize(xDelta, yDelta));
}
@@ -796,14 +1029,18 @@ RenderLayer::subtractScrolledContentOffset(int& x, int& y) const
void RenderLayer::scrollToOffset(int x, int y, bool updateScrollbars, bool repaint)
{
- if (renderer()->style()->overflowX() != OMARQUEE) {
+ RenderBox* box = renderBox();
+ if (!box)
+ return;
+
+ if (box->style()->overflowX() != OMARQUEE) {
if (x < 0) x = 0;
if (y < 0) y = 0;
// Call the scrollWidth/Height functions so that the dimensions will be computed if they need
// to be (for overflow:hidden blocks).
- int maxX = scrollWidth() - m_object->clientWidth();
- int maxY = scrollHeight() - m_object->clientHeight();
+ int maxX = scrollWidth() - box->clientWidth();
+ int maxY = scrollHeight() - box->clientHeight();
if (x > maxX) x = maxX;
if (y > maxY) y = maxY;
@@ -823,6 +1060,13 @@ void RenderLayer::scrollToOffset(int x, int y, bool updateScrollbars, bool repai
// Update the positions of our child layers.
for (RenderLayer* child = firstChild(); child; child = child->nextSibling())
child->updateLayerPositions(false, false);
+
+#if USE(ACCELERATED_COMPOSITING)
+ if (compositor()->inCompositingMode()) {
+ if (RenderLayer* compositingAncestor = ancestorCompositingLayer())
+ compositingAncestor->backing()->updateAfterLayout();
+ }
+#endif
RenderView* view = renderer()->view();
@@ -845,7 +1089,7 @@ void RenderLayer::scrollToOffset(int x, int y, bool updateScrollbars, bool repai
// Just schedule a full repaint of our object.
if (repaint)
- m_object->repaint();
+ renderer()->repaint();
if (updateScrollbars) {
if (m_hBar)
@@ -857,7 +1101,7 @@ void RenderLayer::scrollToOffset(int x, int y, bool updateScrollbars, bool repai
// Schedule the scroll DOM event.
if (view) {
if (FrameView* frameView = view->frameView())
- frameView->scheduleEvent(Event::create(eventNames().scrollEvent, false, false), EventTargetNodeCast(renderer()->element()));
+ frameView->scheduleEvent(Event::create(eventNames().scrollEvent, false, false), renderer()->node());
}
}
@@ -868,24 +1112,26 @@ void RenderLayer::scrollRectToVisible(const IntRect &rect, bool scrollToAnchor,
int xOffset = 0, yOffset = 0;
// We may end up propagating a scroll event. It is important that we suspend events until
- // the end of the function since they could delete the layer or the layer's m_object.
- FrameView* frameView = m_object->document()->view();
+ // the end of the function since they could delete the layer or the layer's renderer().
+ FrameView* frameView = renderer()->document()->view();
if (frameView)
frameView->pauseScheduledEvents();
bool restrictedByLineClamp = false;
- if (m_object->parent()) {
- parentLayer = m_object->parent()->enclosingLayer();
- restrictedByLineClamp = m_object->parent()->style()->lineClamp() >= 0;
+ if (renderer()->parent()) {
+ parentLayer = renderer()->parent()->enclosingLayer();
+ restrictedByLineClamp = renderer()->parent()->style()->lineClamp() >= 0;
}
- if (m_object->hasOverflowClip() && !restrictedByLineClamp) {
+ if (renderer()->hasOverflowClip() && !restrictedByLineClamp) {
// Don't scroll to reveal an overflow layer that is restricted by the -webkit-line-clamp property.
// This will prevent us from revealing text hidden by the slider in Safari RSS.
- FloatPoint absPos = m_object->localToAbsolute();
- absPos.move(m_object->borderLeft(), m_object->borderTop());
+ RenderBox* box = renderBox();
+ ASSERT(box);
+ FloatPoint absPos = box->localToAbsolute();
+ absPos.move(box->borderLeft(), box->borderTop());
- IntRect layerBounds = IntRect(absPos.x() + scrollXOffset(), absPos.y() + scrollYOffset(), m_object->clientWidth(), m_object->clientHeight());
+ IntRect layerBounds = IntRect(absPos.x() + scrollXOffset(), absPos.y() + scrollYOffset(), box->clientWidth(), box->clientHeight());
IntRect exposeRect = IntRect(rect.x() + scrollXOffset(), rect.y() + scrollYOffset(), rect.width(), rect.height());
IntRect r = getRectToExpose(layerBounds, exposeRect, alignX, alignY);
@@ -904,9 +1150,9 @@ void RenderLayer::scrollRectToVisible(const IntRect &rect, bool scrollToAnchor,
newRect.setX(rect.x() - diffX);
newRect.setY(rect.y() - diffY);
}
- } else if (!parentLayer && renderer()->canBeProgramaticallyScrolled(scrollToAnchor)) {
+ } else if (!parentLayer && renderer()->isBox() && renderBox()->canBeProgramaticallyScrolled(scrollToAnchor)) {
if (frameView) {
- if (m_object->document() && m_object->document()->ownerElement() && m_object->document()->ownerElement()->renderer()) {
+ if (renderer()->document() && renderer()->document()->ownerElement() && renderer()->document()->ownerElement()->renderer()) {
IntRect viewRect = frameView->visibleContentRect();
IntRect r = getRectToExpose(viewRect, rect, alignX, alignY);
@@ -917,7 +1163,7 @@ void RenderLayer::scrollRectToVisible(const IntRect &rect, bool scrollToAnchor,
yOffset = max(0, min(frameView->contentsHeight(), yOffset));
frameView->setScrollPosition(IntPoint(xOffset, yOffset));
- parentLayer = m_object->document()->ownerElement()->renderer()->enclosingLayer();
+ parentLayer = renderer()->document()->ownerElement()->renderer()->enclosingLayer();
newRect.setX(rect.x() - frameView->scrollX() + frameView->x());
newRect.setY(rect.y() - frameView->scrollY() + frameView->y());
} else {
@@ -948,17 +1194,17 @@ IntRect RenderLayer::getRectToExpose(const IntRect &visibleRect, const IntRect &
// If the rectangle is fully visible, use the specified visible behavior.
// If the rectangle is partially visible, but over a certain threshold,
// then treat it as fully visible to avoid unnecessary horizontal scrolling
- scrollX = getVisibleBehavior(alignX);
+ scrollX = ScrollAlignment::getVisibleBehavior(alignX);
else if (intersectWidth == visibleRect.width()) {
// If the rect is bigger than the visible area, don't bother trying to center. Other alignments will work.
- scrollX = getVisibleBehavior(alignX);
+ scrollX = ScrollAlignment::getVisibleBehavior(alignX);
if (scrollX == alignCenter)
scrollX = noScroll;
} else if (intersectWidth > 0)
// If the rectangle is partially visible, but not above the minimum threshold, use the specified partial behavior
- scrollX = getPartialBehavior(alignX);
+ scrollX = ScrollAlignment::getPartialBehavior(alignX);
else
- scrollX = getHiddenBehavior(alignX);
+ scrollX = ScrollAlignment::getHiddenBehavior(alignX);
// If we're trying to align to the closest edge, and the exposeRect is further right
// than the visibleRect, and not bigger than the visible area, then align with the right.
if (scrollX == alignToClosestEdge && exposeRect.right() > visibleRect.right() && exposeRect.width() < visibleRect.width())
@@ -981,17 +1227,17 @@ IntRect RenderLayer::getRectToExpose(const IntRect &visibleRect, const IntRect &
int intersectHeight = intersection(visibleRect, exposeRectY).height();
if (intersectHeight == exposeRect.height())
// If the rectangle is fully visible, use the specified visible behavior.
- scrollY = getVisibleBehavior(alignY);
+ scrollY = ScrollAlignment::getVisibleBehavior(alignY);
else if (intersectHeight == visibleRect.height()) {
// If the rect is bigger than the visible area, don't bother trying to center. Other alignments will work.
- scrollY = getVisibleBehavior(alignY);
+ scrollY = ScrollAlignment::getVisibleBehavior(alignY);
if (scrollY == alignCenter)
scrollY = noScroll;
} else if (intersectHeight > 0)
// If the rectangle is partially visible, use the specified partial behavior
- scrollY = getPartialBehavior(alignY);
+ scrollY = ScrollAlignment::getPartialBehavior(alignY);
else
- scrollY = getHiddenBehavior(alignY);
+ scrollY = ScrollAlignment::getHiddenBehavior(alignY);
// If we're trying to align to the closest edge, and the exposeRect is further down
// than the visibleRect, and not bigger than the visible area, then align with the bottom.
if (scrollY == alignToClosestEdge && exposeRect.bottom() > visibleRect.bottom() && exposeRect.height() < visibleRect.height())
@@ -1024,18 +1270,19 @@ void RenderLayer::autoscroll()
frame->eventHandler()->updateSelectionForMouseDrag();
IntPoint currentDocumentPosition = frameView->windowToContents(frame->eventHandler()->currentMousePosition());
- scrollRectToVisible(IntRect(currentDocumentPosition, IntSize(1, 1)), false, gAlignToEdgeIfNeeded, gAlignToEdgeIfNeeded);
+ scrollRectToVisible(IntRect(currentDocumentPosition, IntSize(1, 1)), false, ScrollAlignment::alignToEdgeIfNeeded, ScrollAlignment::alignToEdgeIfNeeded);
}
void RenderLayer::resize(const PlatformMouseEvent& evt, const IntSize& oldOffset)
{
- if (!inResizeMode() || !m_object->hasOverflowClip())
+ // FIXME: This should be possible on generated content but is not right now.
+ if (!inResizeMode() || !renderer()->hasOverflowClip() || !renderer()->node())
return;
// Set the width and height of the shadow ancestor node if there is one.
// This is necessary for textarea elements since the resizable layer is in the shadow content.
- Element* element = static_cast<Element*>(m_object->node()->shadowAncestorNode());
- RenderBox* renderer = static_cast<RenderBox*>(element->renderer());
+ Element* element = static_cast<Element*>(renderer()->node()->shadowAncestorNode());
+ RenderBox* renderer = toRenderBox(element->renderer());
EResize resize = renderer->style()->resize();
if (resize == RESIZE_NONE)
@@ -1064,8 +1311,8 @@ void RenderLayer::resize(const PlatformMouseEvent& evt, const IntSize& oldOffset
ExceptionCode ec;
- if (difference.width()) {
- if (element && element->isControl()) {
+ if (resize != RESIZE_VERTICAL && difference.width()) {
+ if (element->isFormControlElement()) {
// Make implicit margins from the theme explicit (see <http://bugs.webkit.org/show_bug.cgi?id=9547>).
style->setProperty(CSSPropertyMarginLeft, String::number(renderer->marginLeft() / zoomFactor) + "px", false, ec);
style->setProperty(CSSPropertyMarginRight, String::number(renderer->marginRight() / zoomFactor) + "px", false, ec);
@@ -1076,8 +1323,8 @@ void RenderLayer::resize(const PlatformMouseEvent& evt, const IntSize& oldOffset
style->setProperty(CSSPropertyWidth, String::number(baseWidth + difference.width()) + "px", false, ec);
}
- if (difference.height()) {
- if (element && element->isControl()) {
+ if (resize != RESIZE_HORIZONTAL && difference.height()) {
+ if (element->isFormControlElement()) {
// Make implicit margins from the theme explicit (see <http://bugs.webkit.org/show_bug.cgi?id=9547>).
style->setProperty(CSSPropertyMarginTop, String::number(renderer->marginTop() / zoomFactor) + "px", false, ec);
style->setProperty(CSSPropertyMarginBottom, String::number(renderer->marginBottom() / zoomFactor) + "px", false, ec);
@@ -1164,6 +1411,7 @@ static IntRect scrollCornerRect(const RenderLayer* layer, const IntRect& bounds)
static IntRect resizerCornerRect(const RenderLayer* layer, const IntRect& bounds)
{
+ ASSERT(layer->renderer()->isBox());
if (layer->renderer()->style()->resize() == RESIZE_NONE)
return IntRect();
return cornerRect(layer, bounds);
@@ -1171,28 +1419,32 @@ static IntRect resizerCornerRect(const RenderLayer* layer, const IntRect& bounds
bool RenderLayer::scrollbarCornerPresent() const
{
- return !scrollCornerRect(this, m_object->borderBox()).isEmpty();
+ ASSERT(renderer()->isBox());
+ return !scrollCornerRect(this, renderBox()->borderBoxRect()).isEmpty();
}
void RenderLayer::invalidateScrollbarRect(Scrollbar* scrollbar, const IntRect& rect)
{
IntRect scrollRect = rect;
+ RenderBox* box = renderBox();
+ ASSERT(box);
if (scrollbar == m_vBar.get())
- scrollRect.move(renderer()->width() - renderer()->borderRight() - scrollbar->width(), renderer()->borderTop());
+ scrollRect.move(box->width() - box->borderRight() - scrollbar->width(), box->borderTop());
else
- scrollRect.move(renderer()->borderLeft(), renderer()->height() - renderer()->borderBottom() - scrollbar->height());
+ scrollRect.move(box->borderLeft(), box->height() - box->borderBottom() - scrollbar->height());
renderer()->repaintRectangle(scrollRect);
}
PassRefPtr<Scrollbar> RenderLayer::createScrollbar(ScrollbarOrientation orientation)
{
RefPtr<Scrollbar> widget;
- bool hasCustomScrollbarStyle = m_object->node()->shadowAncestorNode()->renderer()->style()->hasPseudoStyle(RenderStyle::SCROLLBAR);
+ RenderObject* actualRenderer = renderer()->node() ? renderer()->node()->shadowAncestorNode()->renderer() : renderer();
+ bool hasCustomScrollbarStyle = actualRenderer->isBox() && actualRenderer->style()->hasPseudoStyle(SCROLLBAR);
if (hasCustomScrollbarStyle)
- widget = RenderScrollbar::createCustomScrollbar(this, orientation, m_object->node()->shadowAncestorNode()->renderer());
+ widget = RenderScrollbar::createCustomScrollbar(this, orientation, toRenderBox(actualRenderer));
else
widget = Scrollbar::createNativeScrollbar(this, orientation, RegularScrollbar);
- m_object->document()->view()->addChild(widget.get());
+ renderer()->document()->view()->addChild(widget.get());
return widget.release();
}
@@ -1224,8 +1476,8 @@ void RenderLayer::setHasHorizontalScrollbar(bool hasScrollbar)
#if ENABLE(DASHBOARD_SUPPORT)
// Force an update since we know the scrollbars have changed things.
- if (m_object->document()->hasDashboardRegions())
- m_object->document()->setDashboardRegionsDirty(true);
+ if (renderer()->document()->hasDashboardRegions())
+ renderer()->document()->setDashboardRegionsDirty(true);
#endif
}
@@ -1247,8 +1499,8 @@ void RenderLayer::setHasVerticalScrollbar(bool hasScrollbar)
#if ENABLE(DASHBOARD_SUPPORT)
// Force an update since we know the scrollbars have changed things.
- if (m_object->document()->hasDashboardRegions())
- m_object->document()->setDashboardRegionsDirty(true);
+ if (renderer()->document()->hasDashboardRegions())
+ renderer()->document()->setDashboardRegionsDirty(true);
#endif
}
@@ -1276,28 +1528,32 @@ IntSize RenderLayer::offsetFromResizeCorner(const IntPoint& absolutePoint) const
void RenderLayer::positionOverflowControls(int tx, int ty)
{
- if (!m_hBar && !m_vBar && (!m_object->hasOverflowClip() || m_object->style()->resize() == RESIZE_NONE))
+ if (!m_hBar && !m_vBar && (!renderer()->hasOverflowClip() || renderer()->style()->resize() == RESIZE_NONE))
return;
- IntRect borderBox = m_object->borderBox();
+ RenderBox* box = renderBox();
+ if (!box)
+ return;
+
+ IntRect borderBox = box->borderBoxRect();
IntRect scrollCorner(scrollCornerRect(this, borderBox));
IntRect absBounds(borderBox.x() + tx, borderBox.y() + ty, borderBox.width(), borderBox.height());
if (m_vBar)
- m_vBar->setFrameRect(IntRect(absBounds.right() - m_object->borderRight() - m_vBar->width(),
- absBounds.y() + m_object->borderTop(),
+ m_vBar->setFrameRect(IntRect(absBounds.right() - box->borderRight() - m_vBar->width(),
+ absBounds.y() + box->borderTop(),
m_vBar->width(),
- absBounds.height() - (m_object->borderTop() + m_object->borderBottom()) - scrollCorner.height()));
+ absBounds.height() - (box->borderTop() + box->borderBottom()) - scrollCorner.height()));
if (m_hBar)
- m_hBar->setFrameRect(IntRect(absBounds.x() + m_object->borderLeft(),
- absBounds.bottom() - m_object->borderBottom() - m_hBar->height(),
- absBounds.width() - (m_object->borderLeft() + m_object->borderRight()) - scrollCorner.width(),
+ m_hBar->setFrameRect(IntRect(absBounds.x() + box->borderLeft(),
+ absBounds.bottom() - box->borderBottom() - m_hBar->height(),
+ absBounds.width() - (box->borderLeft() + box->borderRight()) - scrollCorner.width(),
m_hBar->height()));
if (m_scrollCorner)
- m_scrollCorner->setRect(scrollCorner);
+ m_scrollCorner->setFrameRect(scrollCorner);
if (m_resizer)
- m_resizer->setRect(resizerCornerRect(this, borderBox));
+ m_resizer->setFrameRect(resizerCornerRect(this, borderBox));
}
int RenderLayer::scrollWidth()
@@ -1316,19 +1572,22 @@ int RenderLayer::scrollHeight()
void RenderLayer::computeScrollDimensions(bool* needHBar, bool* needVBar)
{
+ RenderBox* box = renderBox();
+ ASSERT(box);
+
m_scrollDimensionsDirty = false;
- bool ltr = m_object->style()->direction() == LTR;
+ bool ltr = renderer()->style()->direction() == LTR;
- int clientWidth = m_object->clientWidth();
- int clientHeight = m_object->clientHeight();
+ int clientWidth = box->clientWidth();
+ int clientHeight = box->clientHeight();
- m_scrollLeftOverflow = ltr ? 0 : min(0, m_object->leftmostPosition(true, false) - m_object->borderLeft());
+ m_scrollLeftOverflow = ltr ? 0 : min(0, box->leftmostPosition(true, false) - box->borderLeft());
int rightPos = ltr ?
- m_object->rightmostPosition(true, false) - m_object->borderLeft() :
+ box->rightmostPosition(true, false) - box->borderLeft() :
clientWidth - m_scrollLeftOverflow;
- int bottomPos = m_object->lowestPosition(true, false) - m_object->borderTop();
+ int bottomPos = box->lowestPosition(true, false) - box->borderTop();
m_scrollWidth = max(rightPos, clientWidth);
m_scrollHeight = max(bottomPos, clientHeight);
@@ -1358,9 +1617,9 @@ void RenderLayer::updateOverflowStatus(bool horizontalOverflow, bool verticalOve
m_horizontalOverflow = horizontalOverflow;
m_verticalOverflow = verticalOverflow;
- if (FrameView* frameView = m_object->document()->view()) {
+ if (FrameView* frameView = renderer()->document()->view()) {
frameView->scheduleEvent(OverflowEvent::create(horizontalOverflowChanged, horizontalOverflow, verticalOverflowChanged, verticalOverflow),
- EventTargetNodeCast(m_object->element()));
+ renderer()->node());
}
}
}
@@ -1368,18 +1627,22 @@ void RenderLayer::updateOverflowStatus(bool horizontalOverflow, bool verticalOve
void
RenderLayer::updateScrollInfoAfterLayout()
{
+ RenderBox* box = renderBox();
+ if (!box)
+ return;
+
m_scrollDimensionsDirty = true;
bool horizontalOverflow, verticalOverflow;
computeScrollDimensions(&horizontalOverflow, &verticalOverflow);
- if (m_object->style()->overflowX() != OMARQUEE) {
+ if (box->style()->overflowX() != OMARQUEE) {
// Layout may cause us to be in an invalid scroll position. In this case we need
// to pull our scroll offsets back to the max (or push them up to the min).
- int newX = max(0, min(scrollXOffset(), scrollWidth() - m_object->clientWidth()));
- int newY = max(0, min(m_scrollY, scrollHeight() - m_object->clientHeight()));
+ int newX = max(0, min(scrollXOffset(), scrollWidth() - box->clientWidth()));
+ int newY = max(0, min(m_scrollY, scrollHeight() - box->clientHeight()));
if (newX != scrollXOffset() || newY != m_scrollY) {
- RenderView* view = m_object->view();
+ RenderView* view = renderer()->view();
ASSERT(view);
// scrollToOffset() may call updateLayerPositions(), which doesn't work
// with LayoutState.
@@ -1396,58 +1659,58 @@ RenderLayer::updateScrollInfoAfterLayout()
bool haveVerticalBar = m_vBar;
// overflow:scroll should just enable/disable.
- if (m_object->style()->overflowX() == OSCROLL)
+ if (renderer()->style()->overflowX() == OSCROLL)
m_hBar->setEnabled(horizontalOverflow);
- if (m_object->style()->overflowY() == OSCROLL)
+ if (renderer()->style()->overflowY() == OSCROLL)
m_vBar->setEnabled(verticalOverflow);
// A dynamic change from a scrolling overflow to overflow:hidden means we need to get rid of any
// scrollbars that may be present.
- if (m_object->style()->overflowX() == OHIDDEN && haveHorizontalBar)
+ if (renderer()->style()->overflowX() == OHIDDEN && haveHorizontalBar)
setHasHorizontalScrollbar(false);
- if (m_object->style()->overflowY() == OHIDDEN && haveVerticalBar)
+ if (renderer()->style()->overflowY() == OHIDDEN && haveVerticalBar)
setHasVerticalScrollbar(false);
// overflow:auto may need to lay out again if scrollbars got added/removed.
- bool scrollbarsChanged = (m_object->hasAutoHorizontalScrollbar() && haveHorizontalBar != horizontalOverflow) ||
- (m_object->hasAutoVerticalScrollbar() && haveVerticalBar != verticalOverflow);
+ bool scrollbarsChanged = (box->hasAutoHorizontalScrollbar() && haveHorizontalBar != horizontalOverflow) ||
+ (box->hasAutoVerticalScrollbar() && haveVerticalBar != verticalOverflow);
if (scrollbarsChanged) {
- if (m_object->hasAutoHorizontalScrollbar())
+ if (box->hasAutoHorizontalScrollbar())
setHasHorizontalScrollbar(horizontalOverflow);
- if (m_object->hasAutoVerticalScrollbar())
+ if (box->hasAutoVerticalScrollbar())
setHasVerticalScrollbar(verticalOverflow);
#if ENABLE(DASHBOARD_SUPPORT)
// Force an update since we know the scrollbars have changed things.
- if (m_object->document()->hasDashboardRegions())
- m_object->document()->setDashboardRegionsDirty(true);
+ if (renderer()->document()->hasDashboardRegions())
+ renderer()->document()->setDashboardRegionsDirty(true);
#endif
- m_object->repaint();
+ renderer()->repaint();
- if (m_object->style()->overflowX() == OAUTO || m_object->style()->overflowY() == OAUTO) {
+ if (renderer()->style()->overflowX() == OAUTO || renderer()->style()->overflowY() == OAUTO) {
if (!m_inOverflowRelayout) {
// Our proprietary overflow: overlay value doesn't trigger a layout.
m_inOverflowRelayout = true;
- m_object->setNeedsLayout(true);
- if (m_object->isRenderBlock())
- static_cast<RenderBlock*>(m_object)->layoutBlock(true);
+ renderer()->setNeedsLayout(true, false);
+ if (renderer()->isRenderBlock())
+ toRenderBlock(renderer())->layoutBlock(true);
else
- m_object->layout();
+ renderer()->layout();
m_inOverflowRelayout = false;
}
}
}
// If overflow:scroll is turned into overflow:auto a bar might still be disabled (Bug 11985).
- if (m_hBar && m_object->hasAutoHorizontalScrollbar())
+ if (m_hBar && box->hasAutoHorizontalScrollbar())
m_hBar->setEnabled(true);
- if (m_vBar && m_object->hasAutoVerticalScrollbar())
+ if (m_vBar && box->hasAutoVerticalScrollbar())
m_vBar->setEnabled(true);
// Set up the range (and page step/line step).
if (m_hBar) {
- int clientWidth = m_object->clientWidth();
+ int clientWidth = box->clientWidth();
int pageStep = (clientWidth - cAmountToKeepWhenPaging);
if (pageStep < 0) pageStep = clientWidth;
m_hBar->setSteps(cScrollbarPixelsPerLineStep, pageStep);
@@ -1455,21 +1718,21 @@ RenderLayer::updateScrollInfoAfterLayout()
m_hBar->setValue(scrollXOffset());
}
if (m_vBar) {
- int clientHeight = m_object->clientHeight();
+ int clientHeight = box->clientHeight();
int pageStep = (clientHeight - cAmountToKeepWhenPaging);
if (pageStep < 0) pageStep = clientHeight;
m_vBar->setSteps(cScrollbarPixelsPerLineStep, pageStep);
m_vBar->setProportion(clientHeight, m_scrollHeight);
}
- if (m_object->element() && m_object->document()->hasListenerType(Document::OVERFLOWCHANGED_LISTENER))
+ if (renderer()->node() && renderer()->document()->hasListenerType(Document::OVERFLOWCHANGED_LISTENER))
updateOverflowStatus(horizontalOverflow, verticalOverflow);
}
void RenderLayer::paintOverflowControls(GraphicsContext* context, int tx, int ty, const IntRect& damageRect)
{
// Don't do anything if we have no overflow.
- if (!m_object->hasOverflowClip())
+ if (!renderer()->hasOverflowClip())
return;
// Move the scrollbar widgets if necessary. We normally move and resize widgets during layout, but sometimes
@@ -1493,7 +1756,10 @@ void RenderLayer::paintOverflowControls(GraphicsContext* context, int tx, int ty
void RenderLayer::paintScrollCorner(GraphicsContext* context, int tx, int ty, const IntRect& damageRect)
{
- IntRect cornerRect = scrollCornerRect(this, m_object->borderBox());
+ RenderBox* box = renderBox();
+ ASSERT(box);
+
+ IntRect cornerRect = scrollCornerRect(this, box->borderBoxRect());
IntRect absRect = IntRect(cornerRect.x() + tx, cornerRect.y() + ty, cornerRect.width(), cornerRect.height());
if (!absRect.intersects(damageRect))
return;
@@ -1513,10 +1779,13 @@ void RenderLayer::paintScrollCorner(GraphicsContext* context, int tx, int ty, co
void RenderLayer::paintResizer(GraphicsContext* context, int tx, int ty, const IntRect& damageRect)
{
- if (m_object->style()->resize() == RESIZE_NONE)
+ if (renderer()->style()->resize() == RESIZE_NONE)
return;
- IntRect cornerRect = resizerCornerRect(this, m_object->borderBox());
+ RenderBox* box = renderBox();
+ ASSERT(box);
+
+ IntRect cornerRect = resizerCornerRect(this, box->borderBoxRect());
IntRect absRect = IntRect(cornerRect.x() + tx, cornerRect.y() + ty, cornerRect.width(), cornerRect.height());
if (!absRect.intersects(damageRect))
return;
@@ -1540,6 +1809,7 @@ void RenderLayer::paintResizer(GraphicsContext* context, int tx, int ty, const I
// Clipping will exclude the right and bottom edges of this frame.
if (m_hBar || m_vBar) {
context->save();
+ context->clip(absRect);
IntRect largerCorner = absRect;
largerCorner.setSize(IntSize(largerCorner.width() + 1, largerCorner.height() + 1));
context->setStrokeColor(Color(makeRGB(217, 217, 217)));
@@ -1552,12 +1822,15 @@ void RenderLayer::paintResizer(GraphicsContext* context, int tx, int ty, const I
bool RenderLayer::isPointInResizeControl(const IntPoint& absolutePoint) const
{
- if (!m_object->hasOverflowClip() || m_object->style()->resize() == RESIZE_NONE)
+ if (!renderer()->hasOverflowClip() || renderer()->style()->resize() == RESIZE_NONE)
return false;
+ RenderBox* box = renderBox();
+ ASSERT(box);
+
IntPoint localPoint = absoluteToContents(absolutePoint);
- IntRect localBounds(0, 0, m_object->width(), m_object->height());
+ IntRect localBounds(0, 0, box->width(), box->height());
return resizerCornerRect(this, localBounds).contains(localPoint);
}
@@ -1566,10 +1839,13 @@ bool RenderLayer::hitTestOverflowControls(HitTestResult& result)
if (!m_hBar && !m_vBar && (!renderer()->hasOverflowClip() || renderer()->style()->resize() == RESIZE_NONE))
return false;
+ RenderBox* box = renderBox();
+ ASSERT(box);
+
int x = 0;
int y = 0;
convertToLayerCoords(root(), x, y);
- IntRect absBounds(x, y, renderer()->width(), renderer()->height());
+ IntRect absBounds(x, y, box->width(), box->height());
IntRect resizeControlRect;
if (renderer()->style()->resize() != RESIZE_NONE) {
@@ -1581,7 +1857,10 @@ bool RenderLayer::hitTestOverflowControls(HitTestResult& result)
int resizeControlSize = max(resizeControlRect.height(), 0);
if (m_vBar) {
- IntRect vBarRect(absBounds.right() - renderer()->borderRight() - m_vBar->width(), absBounds.y() + renderer()->borderTop(), m_vBar->width(), absBounds.height() - (renderer()->borderTop() + renderer()->borderBottom()) - (m_hBar ? m_hBar->height() : resizeControlSize));
+ IntRect vBarRect(absBounds.right() - box->borderRight() - m_vBar->width(),
+ absBounds.y() + box->borderTop(),
+ m_vBar->width(),
+ absBounds.height() - (box->borderTop() + box->borderBottom()) - (m_hBar ? m_hBar->height() : resizeControlSize));
if (vBarRect.contains(result.point())) {
result.setScrollbar(m_vBar.get());
return true;
@@ -1590,7 +1869,10 @@ bool RenderLayer::hitTestOverflowControls(HitTestResult& result)
resizeControlSize = max(resizeControlRect.width(), 0);
if (m_hBar) {
- IntRect hBarRect(absBounds.x() + renderer()->borderLeft(), absBounds.bottom() - renderer()->borderBottom() - m_hBar->height(), absBounds.width() - (renderer()->borderLeft() + renderer()->borderRight()) - (m_vBar ? m_vBar->width() : resizeControlSize), m_hBar->height());
+ IntRect hBarRect(absBounds.x() + box->borderLeft(),
+ absBounds.bottom() - box->borderBottom() - m_hBar->height(),
+ absBounds.width() - (box->borderLeft() + box->borderRight()) - (m_vBar ? m_vBar->width() : resizeControlSize),
+ m_hBar->height());
if (hBarRect.contains(result.point())) {
result.setScrollbar(m_hBar.get());
return true;
@@ -1620,10 +1902,13 @@ bool RenderLayer::scroll(ScrollDirection direction, ScrollGranularity granularit
return (didHorizontalScroll || didVerticalScroll);
}
-void
-RenderLayer::paint(GraphicsContext* p, const IntRect& damageRect, PaintRestriction paintRestriction, RenderObject *paintingRoot)
+void RenderLayer::paint(GraphicsContext* p, const IntRect& damageRect, PaintRestriction paintRestriction, RenderObject *paintingRoot)
{
- paintLayer(this, p, damageRect, false, paintRestriction, paintingRoot);
+ RenderObject::OverlapTestRequestMap overlapTestRequests;
+ paintLayer(this, p, damageRect, paintRestriction, paintingRoot, &overlapTestRequests);
+ RenderObject::OverlapTestRequestMap::iterator end = overlapTestRequests.end();
+ for (RenderObject::OverlapTestRequestMap::iterator it = overlapTestRequests.begin(); it != end; ++it)
+ it->first->setOverlapTestResult(false);
}
static void setClip(GraphicsContext* p, const IntRect& paintDirtyRect, const IntRect& clipRect)
@@ -1641,11 +1926,46 @@ static void restoreClip(GraphicsContext* p, const IntRect& paintDirtyRect, const
p->restore();
}
-void
-RenderLayer::paintLayer(RenderLayer* rootLayer, GraphicsContext* p,
- const IntRect& paintDirtyRect, bool haveTransparency, PaintRestriction paintRestriction,
- RenderObject* paintingRoot, bool appliedTransform, bool temporaryClipRects)
+static void performOverlapTests(RenderObject::OverlapTestRequestMap& overlapTestRequests, const IntRect& layerBounds)
+{
+ Vector<OverlapTestRequestClient*> overlappedRequestClients;
+ RenderObject::OverlapTestRequestMap::iterator end = overlapTestRequests.end();
+ for (RenderObject::OverlapTestRequestMap::iterator it = overlapTestRequests.begin(); it != end; ++it) {
+ if (!layerBounds.intersects(it->second))
+ continue;
+
+ it->first->setOverlapTestResult(true);
+ overlappedRequestClients.append(it->first);
+ }
+ for (size_t i = 0; i < overlappedRequestClients.size(); ++i)
+ overlapTestRequests.remove(overlappedRequestClients[i]);
+}
+
+#if USE(ACCELERATED_COMPOSITING)
+static bool shouldDoSoftwarePaint(const RenderLayer* layer, bool paintingReflection)
{
+ return paintingReflection && !layer->has3DTransform();
+}
+#endif
+
+void RenderLayer::paintLayer(RenderLayer* rootLayer, GraphicsContext* p,
+ const IntRect& paintDirtyRect, PaintRestriction paintRestriction,
+ RenderObject* paintingRoot, RenderObject::OverlapTestRequestMap* overlapTestRequests,
+ PaintLayerFlags paintFlags)
+{
+#if USE(ACCELERATED_COMPOSITING)
+ if (isComposited()) {
+ // The updatingControlTints() painting pass goes through compositing layers,
+ // but we need to ensure that we don't cache clip rects computed with the wrong root in this case.
+ if (p->updatingControlTints())
+ paintFlags |= PaintLayerTemporaryClipRects;
+ else if (!backing()->paintingGoesToWindow() && !shouldDoSoftwarePaint(this, paintFlags & PaintLayerPaintingReflection)) {
+ // If this RenderLayer should paint into its backing, that will be done via RenderLayerBacking::paintIntoLayer().
+ return;
+ }
+ }
+#endif
+
// 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().
@@ -1653,34 +1973,29 @@ RenderLayer::paintLayer(RenderLayer* rootLayer, GraphicsContext* p,
return;
// If this layer is totally invisible then there is nothing to paint.
- if (!m_object->opacity())
+ if (!renderer()->opacity())
return;
- if (isTransparent())
- haveTransparency = true;
+ if (paintsWithTransparency())
+ paintFlags |= PaintLayerHaveTransparency;
// Apply a transform if we have one. A reflection is considered to be a transform, since it is a flip and a translate.
- if (m_transform && !appliedTransform) {
+ if (paintsWithTransform() && !(paintFlags & PaintLayerAppliedTransform)) {
// If the transform can't be inverted, then don't paint anything.
if (!m_transform->isInvertible())
return;
// If we have a transparency layer enclosing us and we are the root of a transform, then we need to establish the transparency
// layer from the parent now.
- if (haveTransparency)
+ if (paintFlags & PaintLayerHaveTransparency)
parent()->beginTransparencyLayers(p, rootLayer);
// Make sure the parent's clip rects have been calculated.
IntRect clipRect = paintDirtyRect;
if (parent()) {
- if (temporaryClipRects) {
- ClipRects parentClipRects;
- parent()->calculateClipRects(rootLayer, parentClipRects);
- clipRect = parentClipRects.overflowClipRect();
- } else {
- parent()->updateClipRects(rootLayer);
- clipRect = parent()->clipRects()->overflowClipRect();
- }
+ ClipRects parentRects;
+ parentClipRects(rootLayer, parentRects, paintFlags & PaintLayerTemporaryClipRects);
+ clipRect = parentRects.overflowClipRect();
clipRect.intersect(paintDirtyRect);
}
@@ -1701,8 +2016,8 @@ RenderLayer::paintLayer(RenderLayer* rootLayer, GraphicsContext* p,
p->concatCTM(transform);
// Now do a paint with the root layer shifted to be us.
- paintLayer(this, p, transform.inverse().mapRect(paintDirtyRect), haveTransparency, paintRestriction, paintingRoot, true, temporaryClipRects);
-
+ paintLayer(this, p, transform.inverse().mapRect(paintDirtyRect), paintRestriction, paintingRoot, overlapTestRequests, paintFlags | PaintLayerAppliedTransform);
+
p->restore();
// Restore the clip.
@@ -1711,25 +2026,27 @@ RenderLayer::paintLayer(RenderLayer* rootLayer, GraphicsContext* p,
return;
}
+ PaintLayerFlags localPaintFlags = paintFlags & ~PaintLayerAppliedTransform;
+ bool haveTransparency = localPaintFlags & PaintLayerHaveTransparency;
+
// Paint the reflection first if we have one.
- if (m_reflection && !m_paintingInsideReflection && (!m_transform || appliedTransform)) {
+ if (m_reflection && !m_paintingInsideReflection) {
// Mark that we are now inside replica painting.
m_paintingInsideReflection = true;
- reflectionLayer()->paintLayer(rootLayer, p, paintDirtyRect, haveTransparency, paintRestriction, paintingRoot, false, temporaryClipRects);
+ reflectionLayer()->paintLayer(rootLayer, p, paintDirtyRect, paintRestriction, paintingRoot, overlapTestRequests, localPaintFlags | PaintLayerPaintingReflection);
m_paintingInsideReflection = false;
}
// Calculate the clip rects we should use.
IntRect layerBounds, damageRect, clipRectToApply, outlineRect;
- calculateRects(rootLayer, paintDirtyRect, layerBounds, damageRect, clipRectToApply, outlineRect, temporaryClipRects);
+ calculateRects(rootLayer, paintDirtyRect, layerBounds, damageRect, clipRectToApply, outlineRect, localPaintFlags & PaintLayerTemporaryClipRects);
int x = layerBounds.x();
int y = layerBounds.y();
- int tx = x - renderer()->xPos();
- int ty = y - renderer()->yPos() + renderer()->borderTopExtra();
+ int tx = x - renderBoxX();
+ int ty = y - renderBoxY();
// Ensure our lists are up-to-date.
- updateZOrderLists();
- updateOverflowList();
+ updateLayerListsIfNeeded();
bool selectionOnly = paintRestriction == PaintRestrictionSelectionOnly || paintRestriction == PaintRestrictionSelectionOnlyBlackText;
bool forceBlackText = paintRestriction == PaintRestrictionSelectionOnlyBlackText;
@@ -1739,11 +2056,14 @@ RenderLayer::paintLayer(RenderLayer* rootLayer, GraphicsContext* p,
// Else, our renderer tree may or may not contain the painting root, so we pass that root along
// so it will be tested against as we decend through the renderers.
RenderObject* paintingRootForRenderer = 0;
- if (paintingRoot && !m_object->isDescendantOf(paintingRoot))
+ if (paintingRoot && !renderer()->isDescendantOf(paintingRoot))
paintingRootForRenderer = paintingRoot;
+ if (overlapTestRequests)
+ performOverlapTests(*overlapTestRequests, layerBounds);
+
// We want to paint our layer, but only if we intersect the damage rect.
- bool shouldPaint = intersectsDamageRect(layerBounds, damageRect, rootLayer) && m_hasVisibleContent;
+ bool shouldPaint = intersectsDamageRect(layerBounds, damageRect, rootLayer) && m_hasVisibleContent && isSelfPaintingLayer();
if (shouldPaint && !selectionOnly && !damageRect.isEmpty()) {
// Begin transparency layers lazily now that we know we have to paint something.
if (haveTransparency)
@@ -1757,11 +2077,6 @@ RenderLayer::paintLayer(RenderLayer* rootLayer, GraphicsContext* p,
RenderObject::PaintInfo paintInfo(p, damageRect, PaintPhaseBlockBackground, false, paintingRootForRenderer, 0);
renderer()->paint(paintInfo, tx, ty);
- // Our scrollbar widgets paint exactly when we tell them to, so that they work properly with
- // z-index. We paint after we painted the background/border, so that the scrollbars will
- // sit above the background/border.
- paintOverflowControls(p, x, y, damageRect);
-
// Restore the clip.
restoreClip(p, paintDirtyRect, damageRect);
}
@@ -1769,7 +2084,7 @@ RenderLayer::paintLayer(RenderLayer* rootLayer, GraphicsContext* p,
// Now walk the sorted list of children with negative z-indices.
if (m_negZOrderList)
for (Vector<RenderLayer*>::iterator it = m_negZOrderList->begin(); it != m_negZOrderList->end(); ++it)
- it[0]->paintLayer(rootLayer, p, paintDirtyRect, haveTransparency, paintRestriction, paintingRoot, false, temporaryClipRects);
+ it[0]->paintLayer(rootLayer, p, paintDirtyRect, paintRestriction, paintingRoot, overlapTestRequests, localPaintFlags);
// Now establish the appropriate clip and paint our child RenderObjects.
if (shouldPaint && !clipRectToApply.isEmpty()) {
@@ -1787,6 +2102,7 @@ RenderLayer::paintLayer(RenderLayer* rootLayer, GraphicsContext* p,
paintInfo.phase = PaintPhaseFloat;
renderer()->paint(paintInfo, tx, ty);
paintInfo.phase = PaintPhaseForeground;
+ paintInfo.overlapTestRequests = overlapTestRequests;
renderer()->paint(paintInfo, tx, ty);
paintInfo.phase = PaintPhaseChildOutlines;
renderer()->paint(paintInfo, tx, ty);
@@ -1796,7 +2112,7 @@ RenderLayer::paintLayer(RenderLayer* rootLayer, GraphicsContext* p,
restoreClip(p, paintDirtyRect, clipRectToApply);
}
- if (!outlineRect.isEmpty()) {
+ if (!outlineRect.isEmpty() && isSelfPaintingLayer()) {
// Paint our own outline
RenderObject::PaintInfo paintInfo(p, outlineRect, PaintPhaseSelfOutline, false, paintingRootForRenderer, 0);
setClip(p, paintDirtyRect, outlineRect);
@@ -1805,14 +2121,14 @@ RenderLayer::paintLayer(RenderLayer* rootLayer, GraphicsContext* p,
}
// Paint any child layers that have overflow.
- if (m_overflowList)
- for (Vector<RenderLayer*>::iterator it = m_overflowList->begin(); it != m_overflowList->end(); ++it)
- it[0]->paintLayer(rootLayer, p, paintDirtyRect, haveTransparency, paintRestriction, paintingRoot, false, temporaryClipRects);
-
+ if (m_normalFlowList)
+ for (Vector<RenderLayer*>::iterator it = m_normalFlowList->begin(); it != m_normalFlowList->end(); ++it)
+ it[0]->paintLayer(rootLayer, p, paintDirtyRect, paintRestriction, paintingRoot, overlapTestRequests, localPaintFlags);
+
// Now walk the sorted list of children with positive z-indices.
if (m_posZOrderList)
for (Vector<RenderLayer*>::iterator it = m_posZOrderList->begin(); it != m_posZOrderList->end(); ++it)
- it[0]->paintLayer(rootLayer, p, paintDirtyRect, haveTransparency, paintRestriction, paintingRoot, false, temporaryClipRects);
+ it[0]->paintLayer(rootLayer, p, paintDirtyRect, paintRestriction, paintingRoot, overlapTestRequests, localPaintFlags);
if (renderer()->hasMask() && shouldPaint && !selectionOnly && !damageRect.isEmpty()) {
setClip(p, paintDirtyRect, damageRect);
@@ -1826,7 +2142,7 @@ RenderLayer::paintLayer(RenderLayer* rootLayer, GraphicsContext* p,
}
// End our transparency layer
- if (isTransparent() && m_usedTransparency) {
+ if (haveTransparency && m_usedTransparency && !m_paintingInsideReflection) {
p->endTransparencyLayer();
p->restore();
m_usedTransparency = false;
@@ -1847,9 +2163,19 @@ bool RenderLayer::hitTest(const HitTestRequest& request, HitTestResult& result)
renderer()->document()->updateLayout();
IntRect boundsRect(m_x, m_y, width(), height());
- boundsRect.intersect(frameVisibleRect(renderer()));
-
- RenderLayer* insideLayer = hitTestLayer(this, request, result, boundsRect, result.point());
+ if (!request.ignoreClipping())
+ boundsRect.intersect(frameVisibleRect(renderer()));
+
+ RenderLayer* insideLayer = hitTestLayer(this, 0, request, result, boundsRect, result.point(), false);
+ if (!insideLayer) {
+ // We didn't hit any layer. If we are the root layer and the mouse is -- or just was -- down,
+ // return ourselves. We do this so mouse events continue getting delivered after a drag has
+ // exited the WebView, and so hit testing over a scrollbar hits the content document.
+ if ((request.active() || request.mouseUp()) && renderer()->isRenderView()) {
+ renderer()->updateHitTestResult(result, result.point());
+ insideLayer = this;
+ }
+ }
// Now determine if the result is inside an anchor; make sure an image map wins if
// it already set URLElement and only use the innermost.
@@ -1872,135 +2198,306 @@ bool RenderLayer::hitTest(const HitTestRequest& request, HitTestResult& result)
Node* RenderLayer::enclosingElement() const
{
for (RenderObject* r = renderer(); r; r = r->parent()) {
- if (Node* e = r->element())
+ if (Node* e = r->node())
return e;
}
ASSERT_NOT_REACHED();
return 0;
}
-RenderLayer* RenderLayer::hitTestLayer(RenderLayer* rootLayer, const HitTestRequest& request, HitTestResult& result,
- const IntRect& hitTestRect, const IntPoint& hitTestPoint, bool appliedTransform)
+// Compute the z-offset of the point in the transformState.
+// This is effectively projecting a ray normal to the plane of ancestor, finding where that
+// ray intersects target, and computing the z delta between those two points.
+static double computeZOffset(const HitTestingTransformState& transformState)
{
+ // We got an affine transform, so no z-offset
+ if (transformState.m_accumulatedTransform.isAffine())
+ return 0;
+
+ // Flatten the point into the target plane
+ FloatPoint targetPoint = transformState.mappedPoint();
+
+ // Now map the point back through the transform, which computes Z.
+ FloatPoint3D backmappedPoint = transformState.m_accumulatedTransform.mapPoint(FloatPoint3D(targetPoint));
+ return backmappedPoint.z();
+}
+
+PassRefPtr<HitTestingTransformState> RenderLayer::createLocalTransformState(RenderLayer* rootLayer, RenderLayer* containerLayer,
+ const IntRect& hitTestRect, const IntPoint& hitTestPoint,
+ const HitTestingTransformState* containerTransformState) const
+{
+ RefPtr<HitTestingTransformState> transformState;
+ int offsetX = 0;
+ int offsetY = 0;
+ if (containerTransformState) {
+ // If we're already computing transform state, then it's relative to the container (which we know is non-null).
+ transformState = HitTestingTransformState::create(*containerTransformState);
+ convertToLayerCoords(containerLayer, offsetX, offsetY);
+ } else {
+ // If this is the first time we need to make transform state, then base it off of hitTestPoint,
+ // which is relative to rootLayer.
+ transformState = HitTestingTransformState::create(hitTestPoint, FloatQuad(hitTestRect));
+ convertToLayerCoords(rootLayer, offsetX, offsetY);
+ }
+
+ RenderObject* containerRenderer = containerLayer ? containerLayer->renderer() : 0;
+ if (renderer()->shouldUseTransformFromContainer(containerRenderer)) {
+ TransformationMatrix containerTransform;
+ renderer()->getTransformFromContainer(containerRenderer, IntSize(offsetX, offsetY), containerTransform);
+ transformState->applyTransform(containerTransform, HitTestingTransformState::AccumulateTransform);
+ } else {
+ transformState->translate(offsetX, offsetY, HitTestingTransformState::AccumulateTransform);
+ }
+
+ return transformState;
+}
+
+
+static bool isHitCandidate(const RenderLayer* hitLayer, bool canDepthSort, double* zOffset, const HitTestingTransformState* transformState)
+{
+ if (!hitLayer)
+ return false;
+
+ // The hit layer is depth-sorting with other layers, so just say that it was hit.
+ if (canDepthSort)
+ return true;
+
+ // We need to look at z-depth to decide if this layer was hit.
+ if (zOffset) {
+ ASSERT(transformState);
+ // This is actually computing our z, but that's OK because the hitLayer is coplanar with us.
+ double childZOffset = computeZOffset(*transformState);
+ if (childZOffset > *zOffset) {
+ *zOffset = childZOffset;
+ return true;
+ }
+ return false;
+ }
+
+ return true;
+}
+
+// hitTestPoint and hitTestRect are relative to rootLayer.
+// A 'flattening' layer is one preserves3D() == false.
+// transformState.m_accumulatedTransform holds the transform from the containing flattening layer.
+// transformState.m_lastPlanarPoint is the hitTestPoint in the plane of the containing flattening layer.
+// transformState.m_lastPlanarQuad is the hitTestRect as a quad in the plane of the containing flattening layer.
+//
+// If zOffset is non-null (which indicates that the caller wants z offset information),
+// *zOffset on return is the z offset of the hit point relative to the containing flattening layer.
+RenderLayer* RenderLayer::hitTestLayer(RenderLayer* rootLayer, RenderLayer* containerLayer, const HitTestRequest& request, HitTestResult& result,
+ const IntRect& hitTestRect, const IntPoint& hitTestPoint, bool appliedTransform,
+ const HitTestingTransformState* transformState, double* zOffset)
+{
+ // The natural thing would be to keep HitTestingTransformState on the stack, but it's big, so we heap-allocate.
+
+ bool useTemporaryClipRects = false;
+#if USE(ACCELERATED_COMPOSITING)
+ useTemporaryClipRects = compositor()->inCompositingMode();
+#endif
+
// Apply a transform if we have one.
- if (m_transform && !appliedTransform) {
- // If the transform can't be inverted, then don't hit test this layer at all.
- if (!m_transform->isInvertible())
- return 0;
-
+ if (transform() && !appliedTransform) {
// Make sure the parent's clip rects have been calculated.
if (parent()) {
- parent()->updateClipRects(rootLayer);
-
+ ClipRects parentRects;
+ parentClipRects(rootLayer, parentRects, useTemporaryClipRects);
+ IntRect clipRect = parentRects.overflowClipRect();
// Go ahead and test the enclosing clip now.
- IntRect clipRect = parent()->clipRects()->overflowClipRect();
if (!clipRect.contains(hitTestPoint))
return 0;
}
- // Adjust the transform such that the renderer's upper left corner is at (0,0) in user space.
- // This involves subtracting out the position of the layer in our current coordinate space.
- int x = 0;
- int y = 0;
- convertToLayerCoords(rootLayer, x, y);
- TransformationMatrix transform;
- transform.translate(x, y);
- transform = *m_transform * transform;
-
- // Map the hit test point into the transformed space and then do a hit test with the root layer shifted to be us.
- return hitTestLayer(this, request, result, transform.inverse().mapRect(hitTestRect), transform.inverse().mapPoint(hitTestPoint), true);
+ // Create a transform state to accumulate this transform.
+ RefPtr<HitTestingTransformState> newTransformState = createLocalTransformState(rootLayer, containerLayer, hitTestRect, hitTestPoint, transformState);
+
+ // If the transform can't be inverted, then don't hit test this layer at all.
+ if (!newTransformState->m_accumulatedTransform.isInvertible())
+ return 0;
+
+ // Compute the point and the hit test rect in the coords of this layer by using the values
+ // from the transformState, which store the point and quad in the coords of the last flattened
+ // layer, and the accumulated transform which lets up map through preserve-3d layers.
+ //
+ // We can't just map hitTestPoint and hitTestRect because they may have been flattened (losing z)
+ // by our container.
+ IntPoint localPoint = roundedIntPoint(newTransformState->mappedPoint());
+ IntRect localHitTestRect;
+#if USE(ACCELERATED_COMPOSITING)
+ if (isComposited()) {
+ // It doesn't make sense to project hitTestRect into the plane of this layer, so use the same bounds we use for painting.
+ localHitTestRect = backing()->compositedBounds();
+ } else
+#endif
+ localHitTestRect = newTransformState->mappedQuad().enclosingBoundingBox();
+
+ // Now do a hit test with the root layer shifted to be us.
+ return hitTestLayer(this, containerLayer, request, result, localHitTestRect, localPoint, true, newTransformState.get(), zOffset);
+ }
+
+ // Ensure our lists and 3d status are up-to-date.
+ updateLayerListsIfNeeded();
+ update3DTransformedDescendantStatus();
+
+ RefPtr<HitTestingTransformState> localTransformState;
+ if (appliedTransform) {
+ // We computed the correct state in the caller (above code), so just reference it.
+ ASSERT(transformState);
+ localTransformState = const_cast<HitTestingTransformState*>(transformState);
+ } else if (transformState || m_has3DTransformedDescendant || preserves3D()) {
+ // We need transform state for the first time, or to offset the container state, so create it here.
+ localTransformState = createLocalTransformState(rootLayer, containerLayer, hitTestRect, hitTestPoint, transformState);
}
+ // Check for hit test on backface if backface-visibility is 'hidden'
+ if (localTransformState && renderer()->style()->backfaceVisibility() == BackfaceVisibilityHidden) {
+ TransformationMatrix invertedMatrix = localTransformState->m_accumulatedTransform.inverse();
+ // If the z-vector of the matrix is negative, the back is facing towards the viewer.
+ if (invertedMatrix.m33() < 0)
+ return 0;
+ }
+
+ RefPtr<HitTestingTransformState> unflattenedTransformState = localTransformState;
+ if (localTransformState && !preserves3D()) {
+ // Keep a copy of the pre-flattening state, for computing z-offsets for the container
+ unflattenedTransformState = HitTestingTransformState::create(*localTransformState);
+ // This layer is flattening, so flatten the state passed to descendants.
+ localTransformState->flatten();
+ }
+
// Calculate the clip rects we should use.
IntRect layerBounds;
IntRect bgRect;
IntRect fgRect;
IntRect outlineRect;
- calculateRects(rootLayer, hitTestRect, layerBounds, bgRect, fgRect, outlineRect);
-
- // Ensure our lists are up-to-date.
- updateZOrderLists();
- updateOverflowList();
-
- // This variable tracks which layer the mouse ends up being inside. The minute we find an insideLayer,
- // we are done and can return it.
- RenderLayer* insideLayer = 0;
-
- // Begin by walking our list of positive layers from highest z-index down to the lowest
- // z-index.
+ calculateRects(rootLayer, hitTestRect, layerBounds, bgRect, fgRect, outlineRect, useTemporaryClipRects);
+
+ // The following are used for keeping track of the z-depth of the hit point of 3d-transformed
+ // descendants.
+ double localZOffset = -numeric_limits<double>::infinity();
+ double* zOffsetForDescendantsPtr = 0;
+ double* zOffsetForContentsPtr = 0;
+
+ bool depthSortDescendants = false;
+ if (preserves3D()) {
+ depthSortDescendants = true;
+ // Our layers can depth-test with our container, so share the z depth pointer with the container, if it passed one down.
+ zOffsetForDescendantsPtr = zOffset ? zOffset : &localZOffset;
+ zOffsetForContentsPtr = zOffset ? zOffset : &localZOffset;
+ } else if (m_has3DTransformedDescendant) {
+ // Flattening layer with 3d children; use a local zOffset pointer to depth-test children and foreground.
+ depthSortDescendants = true;
+ zOffsetForDescendantsPtr = zOffset ? zOffset : &localZOffset;
+ zOffsetForContentsPtr = zOffset ? zOffset : &localZOffset;
+ } else if (zOffset) {
+ zOffsetForDescendantsPtr = 0;
+ // Container needs us to give back a z offset for the hit layer.
+ zOffsetForContentsPtr = zOffset;
+ }
+
+ // This variable tracks which layer the mouse ends up being inside.
+ RenderLayer* candidateLayer = 0;
+
+ // Begin by walking our list of positive layers from highest z-index down to the lowest z-index.
if (m_posZOrderList) {
for (int i = m_posZOrderList->size() - 1; i >= 0; --i) {
- insideLayer = m_posZOrderList->at(i)->hitTestLayer(rootLayer, request, result, hitTestRect, hitTestPoint);
- if (insideLayer)
- return insideLayer;
+ HitTestResult tempResult(result.point());
+ RenderLayer* hitLayer = m_posZOrderList->at(i)->hitTestLayer(rootLayer, this, request, tempResult, hitTestRect, hitTestPoint, false, localTransformState.get(), zOffsetForDescendantsPtr);
+ if (isHitCandidate(hitLayer, depthSortDescendants, zOffset, unflattenedTransformState.get())) {
+ result = tempResult;
+ if (!depthSortDescendants)
+ return hitLayer;
+
+ candidateLayer = hitLayer;
+ }
}
}
// Now check our overflow objects.
- if (m_overflowList) {
- for (int i = m_overflowList->size() - 1; i >= 0; --i) {
- insideLayer = m_overflowList->at(i)->hitTestLayer(rootLayer, request, result, hitTestRect, hitTestPoint);
- if (insideLayer)
- return insideLayer;
+ if (m_normalFlowList) {
+ for (int i = m_normalFlowList->size() - 1; i >= 0; --i) {
+ RenderLayer* currLayer = m_normalFlowList->at(i);
+ HitTestResult tempResult(result.point());
+ RenderLayer* hitLayer = currLayer->hitTestLayer(rootLayer, this, request, tempResult, hitTestRect, hitTestPoint, false, localTransformState.get(), zOffsetForDescendantsPtr);
+ if (isHitCandidate(hitLayer, depthSortDescendants, zOffset, unflattenedTransformState.get())) {
+ result = tempResult;
+ if (!depthSortDescendants)
+ return hitLayer;
+
+ candidateLayer = hitLayer;
+ }
}
}
// Next we want to see if the mouse pos is inside the child RenderObjects of the layer.
- if (fgRect.contains(hitTestPoint) &&
- renderer()->hitTest(request, result, hitTestPoint,
- layerBounds.x() - renderer()->xPos(),
- layerBounds.y() - renderer()->yPos() + m_object->borderTopExtra(),
- HitTestDescendants)) {
- // For positioned generated content, we might still not have a
- // node by the time we get to the layer level, since none of
- // the content in the layer has an element. So just walk up
- // the tree.
- if (!result.innerNode() || !result.innerNonSharedNode()) {
- Node* e = enclosingElement();
- if (!result.innerNode())
- result.setInnerNode(e);
- if (!result.innerNonSharedNode())
- result.setInnerNonSharedNode(e);
+ if (fgRect.contains(hitTestPoint) && isSelfPaintingLayer()) {
+ // Hit test with a temporary HitTestResult, because we onlyl want to commit to 'result' if we know we're frontmost.
+ HitTestResult tempResult(result.point());
+ if (hitTestContents(request, tempResult, layerBounds, hitTestPoint, HitTestDescendants) &&
+ isHitCandidate(this, false, zOffsetForContentsPtr, unflattenedTransformState.get())) {
+ result = tempResult;
+ if (!depthSortDescendants)
+ return this;
+ // Foreground can depth-sort with descendant layers, so keep this as a candidate.
+ candidateLayer = this;
}
-
- return this;
}
-
+
// Now check our negative z-index children.
if (m_negZOrderList) {
for (int i = m_negZOrderList->size() - 1; i >= 0; --i) {
- insideLayer = m_negZOrderList->at(i)->hitTestLayer(rootLayer, request, result, hitTestRect, hitTestPoint);
- if (insideLayer)
- return insideLayer;
+ HitTestResult tempResult(result.point());
+ RenderLayer* hitLayer = m_negZOrderList->at(i)->hitTestLayer(rootLayer, this, request, tempResult, hitTestRect, hitTestPoint, false, localTransformState.get(), zOffsetForDescendantsPtr);
+ if (isHitCandidate(hitLayer, depthSortDescendants, zOffset, unflattenedTransformState.get())) {
+ result = tempResult;
+ if (!depthSortDescendants)
+ return hitLayer;
+
+ candidateLayer = hitLayer;
+ }
}
}
+
+ // If we found a layer, return. Child layers, and foreground always render in front of background.
+ if (candidateLayer)
+ return candidateLayer;
- // Next we want to see if the mouse is inside this layer but not any of its children.
- if (bgRect.contains(hitTestPoint) &&
- renderer()->hitTest(request, result, hitTestPoint,
- layerBounds.x() - renderer()->xPos(),
- layerBounds.y() - renderer()->yPos() + m_object->borderTopExtra(),
- HitTestSelf)) {
- if (!result.innerNode() || !result.innerNonSharedNode()) {
- Node* e = enclosingElement();
- if (!result.innerNode())
- result.setInnerNode(e);
- if (!result.innerNonSharedNode())
- result.setInnerNonSharedNode(e);
+ if (bgRect.contains(hitTestPoint) && isSelfPaintingLayer()) {
+ HitTestResult tempResult(result.point());
+ if (hitTestContents(request, tempResult, layerBounds, hitTestPoint, HitTestSelf) &&
+ isHitCandidate(this, false, zOffsetForContentsPtr, unflattenedTransformState.get())) {
+ result = tempResult;
+ return this;
}
-
- return this;
}
+
+ return 0;
+}
- // We didn't hit any layer. If we are the root layer and the mouse is -- or just was -- down,
- // return ourselves. We do this so mouse events continue getting delivered after a drag has
- // exited the WebView, and so hit testing over a scrollbar hits the content document.
- if ((request.active || request.mouseUp) && renderer()->isRenderView()) {
- renderer()->updateHitTestResult(result, hitTestPoint);
- return this;
+bool RenderLayer::hitTestContents(const HitTestRequest& request, HitTestResult& result, const IntRect& layerBounds, const IntPoint& hitTestPoint, HitTestFilter hitTestFilter) const
+{
+ if (!renderer()->hitTest(request, result, hitTestPoint,
+ layerBounds.x() - renderBoxX(),
+ layerBounds.y() - renderBoxY(),
+ hitTestFilter)) {
+ // It's wrong to set innerNode, but then claim that you didn't hit anything.
+ ASSERT(!result.innerNode());
+ return false;
}
- return 0;
+ // For positioned generated content, we might still not have a
+ // node by the time we get to the layer level, since none of
+ // the content in the layer has an element. So just walk up
+ // the tree.
+ if (!result.innerNode() || !result.innerNonSharedNode()) {
+ Node* e = enclosingElement();
+ if (!result.innerNode())
+ result.setInnerNode(e);
+ if (!result.innerNonSharedNode())
+ result.setInnerNonSharedNode(e);
+ }
+
+ return true;
}
void RenderLayer::updateClipRects(const RenderLayer* rootLayer)
@@ -2022,7 +2519,7 @@ void RenderLayer::updateClipRects(const RenderLayer* rootLayer)
if (parentLayer && parentLayer->clipRects() && clipRects == *parentLayer->clipRects())
m_clipRects = parentLayer->clipRects();
else
- m_clipRects = new (m_object->renderArena()) ClipRects(clipRects);
+ m_clipRects = new (renderer()->renderArena()) ClipRects(clipRects);
m_clipRects->ref();
#ifndef NDEBUG
m_clipRectsRoot = rootLayer;
@@ -2031,10 +2528,9 @@ void RenderLayer::updateClipRects(const RenderLayer* rootLayer)
void RenderLayer::calculateClipRects(const RenderLayer* rootLayer, ClipRects& clipRects, bool useCached) const
{
- IntRect infiniteRect(INT_MIN/2, INT_MIN/2, INT_MAX, INT_MAX);
if (!parent()) {
// The root layer's clip rect is always infinite.
- clipRects.reset(infiniteRect);
+ clipRects.reset(ClipRects::infiniteRect());
return;
}
@@ -2050,22 +2546,22 @@ void RenderLayer::calculateClipRects(const RenderLayer* rootLayer, ClipRects& cl
parentLayer->calculateClipRects(rootLayer, clipRects);
}
else
- clipRects.reset(infiniteRect);
+ clipRects.reset(ClipRects::infiniteRect());
// A fixed object is essentially the root of its containing block hierarchy, so when
// we encounter such an object, we reset our clip rects to the fixedClipRect.
- if (m_object->style()->position() == FixedPosition) {
+ if (renderer()->style()->position() == FixedPosition) {
clipRects.setPosClipRect(clipRects.fixedClipRect());
clipRects.setOverflowClipRect(clipRects.fixedClipRect());
clipRects.setFixed(true);
}
- else if (m_object->style()->position() == RelativePosition)
+ else if (renderer()->style()->position() == RelativePosition)
clipRects.setPosClipRect(clipRects.overflowClipRect());
- else if (m_object->style()->position() == AbsolutePosition)
+ else if (renderer()->style()->position() == AbsolutePosition)
clipRects.setOverflowClipRect(clipRects.posClipRect());
// Update the clip rects that will be passed to child layers.
- if (m_object->hasOverflowClip() || m_object->hasClip()) {
+ if (renderer()->hasOverflowClip() || renderer()->hasClip()) {
// This layer establishes a clip of some kind.
int x = 0;
int y = 0;
@@ -2077,14 +2573,14 @@ void RenderLayer::calculateClipRects(const RenderLayer* rootLayer, ClipRects& cl
y -= view->frameView()->scrollY();
}
- if (m_object->hasOverflowClip()) {
- IntRect newOverflowClip = m_object->getOverflowClipRect(x,y);
+ if (renderer()->hasOverflowClip()) {
+ IntRect newOverflowClip = toRenderBox(renderer())->overflowClipRect(x,y);
clipRects.setOverflowClipRect(intersection(newOverflowClip, clipRects.overflowClipRect()));
- if (m_object->isPositioned() || m_object->isRelPositioned())
+ if (renderer()->isPositioned() || renderer()->isRelPositioned())
clipRects.setPosClipRect(intersection(newOverflowClip, clipRects.posClipRect()));
}
- if (m_object->hasClip()) {
- IntRect newPosClip = m_object->getClipRect(x,y);
+ if (renderer()->hasClip()) {
+ IntRect newPosClip = toRenderBox(renderer())->clipRect(x,y);
clipRects.setPosClipRect(intersection(newPosClip, clipRects.posClipRect()));
clipRects.setOverflowClipRect(intersection(newPosClip, clipRects.overflowClipRect()));
clipRects.setFixedClipRect(intersection(newPosClip, clipRects.fixedClipRect()));
@@ -2092,24 +2588,30 @@ void RenderLayer::calculateClipRects(const RenderLayer* rootLayer, ClipRects& cl
}
}
+void RenderLayer::parentClipRects(const RenderLayer* rootLayer, ClipRects& clipRects, bool temporaryClipRects) const
+{
+ ASSERT(parent());
+ if (temporaryClipRects) {
+ parent()->calculateClipRects(rootLayer, clipRects);
+ return;
+ }
+
+ parent()->updateClipRects(rootLayer);
+ clipRects = *parent()->clipRects();
+}
+
void RenderLayer::calculateRects(const RenderLayer* rootLayer, const IntRect& paintDirtyRect, IntRect& layerBounds,
IntRect& backgroundRect, IntRect& foregroundRect, IntRect& outlineRect, bool temporaryClipRects) const
{
if (rootLayer != this && parent()) {
- ClipRects parentClipRects;
- if (temporaryClipRects)
- parent()->calculateClipRects(rootLayer, parentClipRects);
- else {
- parent()->updateClipRects(rootLayer);
- parentClipRects = *parent()->clipRects();
- }
-
- backgroundRect = m_object->style()->position() == FixedPosition ? parentClipRects.fixedClipRect() :
- (m_object->isPositioned() ? parentClipRects.posClipRect() :
- parentClipRects.overflowClipRect());
+ ClipRects parentRects;
+ parentClipRects(rootLayer, parentRects, temporaryClipRects);
+ backgroundRect = renderer()->style()->position() == FixedPosition ? parentRects.fixedClipRect() :
+ (renderer()->isPositioned() ? parentRects.posClipRect() :
+ parentRects.overflowClipRect());
RenderView* view = renderer()->view();
ASSERT(view);
- if (view && parentClipRects.fixed() && rootLayer->renderer() == view)
+ if (view && parentRects.fixed() && rootLayer->renderer() == view)
backgroundRect.move(view->frameView()->scrollX(), view->frameView()->scrollY());
backgroundRect.intersect(paintDirtyRect);
@@ -2122,16 +2624,16 @@ void RenderLayer::calculateRects(const RenderLayer* rootLayer, const IntRect& pa
int x = 0;
int y = 0;
convertToLayerCoords(rootLayer, x, y);
- layerBounds = IntRect(x,y,width(),height());
+ layerBounds = IntRect(x, y, width(), height());
// Update the clip rects that will be passed to child layers.
- if (m_object->hasOverflowClip() || m_object->hasClip()) {
+ if (renderer()->hasOverflowClip() || renderer()->hasClip()) {
// This layer establishes a clip of some kind.
- if (m_object->hasOverflowClip())
- foregroundRect.intersect(m_object->getOverflowClipRect(x,y));
- if (m_object->hasClip()) {
+ if (renderer()->hasOverflowClip())
+ foregroundRect.intersect(toRenderBox(renderer())->overflowClipRect(x,y));
+ if (renderer()->hasClip()) {
// Clip applies to *us* as well, so go ahead and update the damageRect.
- IntRect newPosClip = m_object->getClipRect(x,y);
+ IntRect newPosClip = toRenderBox(renderer())->clipRect(x,y);
backgroundRect.intersect(newPosClip);
foregroundRect.intersect(newPosClip);
outlineRect.intersect(newPosClip);
@@ -2156,7 +2658,7 @@ void RenderLayer::calculateRects(const RenderLayer* rootLayer, const IntRect& pa
IntRect RenderLayer::childrenClipRect() const
{
- RenderLayer* rootLayer = renderer()->document()->renderer()->layer();
+ RenderLayer* rootLayer = renderer()->view()->layer();
IntRect layerBounds, backgroundRect, foregroundRect, outlineRect;
calculateRects(rootLayer, rootLayer->boundingBox(rootLayer), layerBounds, backgroundRect, foregroundRect, outlineRect);
return foregroundRect;
@@ -2164,7 +2666,7 @@ IntRect RenderLayer::childrenClipRect() const
IntRect RenderLayer::selfClipRect() const
{
- RenderLayer* rootLayer = renderer()->document()->renderer()->layer();
+ RenderLayer* rootLayer = renderer()->view()->layer();
IntRect layerBounds, backgroundRect, foregroundRect, outlineRect;
calculateRects(rootLayer, rootLayer->boundingBox(rootLayer), layerBounds, backgroundRect, foregroundRect, outlineRect);
return backgroundRect;
@@ -2182,7 +2684,7 @@ bool RenderLayer::intersectsDamageRect(const IntRect& layerBounds, const IntRect
// can go ahead and return true.
RenderView* view = renderer()->view();
ASSERT(view);
- if (view && !renderer()->isInlineFlow()) {
+ if (view && !renderer()->isRenderInline()) {
IntRect b = layerBounds;
b.inflate(view->maximalOutlineSize());
if (b.intersects(damageRect))
@@ -2194,7 +2696,7 @@ bool RenderLayer::intersectsDamageRect(const IntRect& layerBounds, const IntRect
return boundingBox(rootLayer).intersects(damageRect);
}
-IntRect RenderLayer::boundingBox(const RenderLayer* rootLayer) const
+IntRect RenderLayer::localBoundingBox() const
{
// There are three special cases we need to consider.
// (1) Inline Flows. For inline flows we will create a bounding box that fully encompasses all of the lines occupied by the
@@ -2206,64 +2708,66 @@ IntRect RenderLayer::boundingBox(const RenderLayer* rootLayer) const
// as part of our bounding box. We do this because we are the responsible layer for both hit testing and painting those
// floats.
IntRect result;
- if (renderer()->isInlineFlow()) {
+ if (renderer()->isRenderInline()) {
// Go from our first line box to our last line box.
- RenderInline* inlineFlow = static_cast<RenderInline*>(renderer());
+ RenderInline* inlineFlow = toRenderInline(renderer());
InlineFlowBox* firstBox = inlineFlow->firstLineBox();
if (!firstBox)
return result;
int top = firstBox->root()->topOverflow();
int bottom = inlineFlow->lastLineBox()->root()->bottomOverflow();
- int left = firstBox->xPos();
+ int left = firstBox->x();
for (InlineRunBox* curr = firstBox->nextLineBox(); curr; curr = curr->nextLineBox())
- left = min(left, curr->xPos());
- result = IntRect(m_x + left, m_y + (top - renderer()->yPos()), width(), bottom - top);
+ left = min(left, curr->x());
+ result = IntRect(left, top, width(), bottom - top);
} else if (renderer()->isTableRow()) {
// Our bounding box is just the union of all of our cells' border/overflow rects.
for (RenderObject* child = renderer()->firstChild(); child; child = child->nextSibling()) {
if (child->isTableCell()) {
- IntRect bbox = child->borderBox();
- bbox.move(0, child->borderTopExtra());
+ IntRect bbox = toRenderBox(child)->borderBoxRect();
result.unite(bbox);
- IntRect overflowRect = renderer()->overflowRect(false);
- overflowRect.move(0, child->borderTopExtra());
+ IntRect overflowRect = renderBox()->overflowRect(false);
if (bbox != overflowRect)
result.unite(overflowRect);
}
}
- result.move(m_x, m_y);
} else {
- if (renderer()->hasMask())
- result = renderer()->maskClipRect();
+ RenderBox* box = renderBox();
+ ASSERT(box);
+ if (box->hasMask())
+ result = box->maskClipRect();
else {
- IntRect bbox = renderer()->borderBox();
+ IntRect bbox = box->borderBoxRect();
result = bbox;
- IntRect overflowRect = renderer()->overflowRect(false);
+ IntRect overflowRect = box->overflowRect(false);
if (bbox != overflowRect)
result.unite(overflowRect);
}
-
- // We have to adjust the x/y of this result so that it is in the coordinate space of the layer.
- // We also have to add in borderTopExtra here, since borderBox(), in order to play well with methods like
- // floatRect that deal with child content, uses an origin of (0,0) that is at the child content box (so
- // border box returns a y coord of -borderTopExtra(). The layer, however, uses the outer box. This is all
- // really confusing.
- result.move(m_x, m_y + renderer()->borderTopExtra());
}
-
- // Convert the bounding box to an absolute position. We can do this easily by looking at the delta
- // between the bounding box's xpos and our layer's xpos and then applying that to the absolute layerBounds
- // passed in.
- int absX = 0, absY = 0;
- convertToLayerCoords(rootLayer, absX, absY);
- result.move(absX - m_x, absY - m_y);
+
RenderView* view = renderer()->view();
ASSERT(view);
if (view)
- result.inflate(view->maximalOutlineSize());
+ result.inflate(view->maximalOutlineSize()); // Used to apply a fudge factor to dirty-rect checks on blocks/tables.
+
+ return result;
+}
+
+IntRect RenderLayer::boundingBox(const RenderLayer* ancestorLayer) const
+{
+ IntRect result = localBoundingBox();
+
+ int deltaX = 0, deltaY = 0;
+ convertToLayerCoords(ancestorLayer, deltaX, deltaY);
+ result.move(deltaX, deltaY);
return result;
}
+IntRect RenderLayer::absoluteBoundingBox() const
+{
+ return boundingBox(root());
+}
+
void RenderLayer::clearClipRectsIncludingDescendants()
{
if (!m_clipRects)
@@ -2278,7 +2782,7 @@ void RenderLayer::clearClipRectsIncludingDescendants()
void RenderLayer::clearClipRects()
{
if (m_clipRects) {
- m_clipRects->deref(m_object->renderArena());
+ m_clipRects->deref(renderer()->renderArena());
m_clipRects = 0;
#ifndef NDEBUG
m_clipRectsRoot = 0;
@@ -2286,6 +2790,38 @@ void RenderLayer::clearClipRects()
}
}
+#if USE(ACCELERATED_COMPOSITING)
+RenderLayerBacking* RenderLayer::ensureBacking()
+{
+ if (!m_backing)
+ m_backing.set(new RenderLayerBacking(this));
+ return m_backing.get();
+}
+
+void RenderLayer::clearBacking()
+{
+ m_backing.clear();
+}
+#endif
+
+void RenderLayer::setParent(RenderLayer* parent)
+{
+ if (parent == m_parent)
+ return;
+
+#if USE(ACCELERATED_COMPOSITING)
+ if (m_parent && !renderer()->documentBeingDestroyed())
+ compositor()->layerWillBeRemoved(m_parent, this);
+#endif
+
+ m_parent = parent;
+
+#if USE(ACCELERATED_COMPOSITING)
+ if (m_parent && !renderer()->documentBeingDestroyed())
+ compositor()->layerWasAdded(m_parent, this);
+#endif
+}
+
static RenderObject* commonAncestor(RenderObject* obj1, RenderObject* obj2)
{
if (!obj1 || !obj2)
@@ -2301,28 +2837,28 @@ static RenderObject* commonAncestor(RenderObject* obj1, RenderObject* obj2)
void RenderLayer::updateHoverActiveState(const HitTestRequest& request, HitTestResult& result)
{
- // We don't update :hover/:active state when the result is marked as readonly.
- if (request.readonly)
+ // We don't update :hover/:active state when the result is marked as readOnly.
+ if (request.readOnly())
return;
Document* doc = renderer()->document();
Node* activeNode = doc->activeNode();
- if (activeNode && !request.active) {
+ if (activeNode && !request.active()) {
// We are clearing the :active chain because the mouse has been released.
for (RenderObject* curr = activeNode->renderer(); curr; curr = curr->parent()) {
- if (curr->element() && !curr->isText())
- curr->element()->setInActiveChain(false);
+ if (curr->node() && !curr->isText())
+ curr->node()->setInActiveChain(false);
}
doc->setActiveNode(0);
} else {
Node* newActiveNode = result.innerNode();
- if (!activeNode && newActiveNode && request.active) {
+ if (!activeNode && newActiveNode && request.active()) {
// We are setting the :active chain and freezing it. If future moves happen, they
// will need to reference this chain.
for (RenderObject* curr = newActiveNode->renderer(); curr; curr = curr->parent()) {
- if (curr->element() && !curr->isText()) {
- curr->element()->setInActiveChain(true);
+ if (curr->node() && !curr->isText()) {
+ curr->node()->setInActiveChain(true);
}
}
doc->setActiveNode(newActiveNode);
@@ -2332,7 +2868,7 @@ void RenderLayer::updateHoverActiveState(const HitTestRequest& request, HitTestR
// If the mouse is down and if this is a mouse move event, we want to restrict changes in
// :hover/:active to only apply to elements that are in the :active chain that we froze
// at the time the mouse went down.
- bool mustBeInActiveChain = request.active && request.mouseMove;
+ bool mustBeInActiveChain = request.active() && request.mouseMove();
// Check to see if the hovered node has changed. If not, then we don't need to
// do anything.
@@ -2352,18 +2888,18 @@ void RenderLayer::updateHoverActiveState(const HitTestRequest& request, HitTestR
if (oldHoverObj != newHoverObj) {
// The old hover path only needs to be cleared up to (and not including) the common ancestor;
for (RenderObject* curr = oldHoverObj; curr && curr != ancestor; curr = curr->hoverAncestor()) {
- if (curr->element() && !curr->isText() && (!mustBeInActiveChain || curr->element()->inActiveChain())) {
- curr->element()->setActive(false);
- curr->element()->setHovered(false);
+ if (curr->node() && !curr->isText() && (!mustBeInActiveChain || curr->node()->inActiveChain())) {
+ curr->node()->setActive(false);
+ curr->node()->setHovered(false);
}
}
}
// Now set the hover state for our new object up to the root.
for (RenderObject* curr = newHoverObj; curr; curr = curr->hoverAncestor()) {
- if (curr->element() && !curr->isText() && (!mustBeInActiveChain || curr->element()->inActiveChain())) {
- curr->element()->setActive(request.active);
- curr->element()->setHovered(true);
+ if (curr->node() && !curr->isText() && (!mustBeInActiveChain || curr->node()->inActiveChain())) {
+ curr->node()->setActive(request.active());
+ curr->node()->setHovered(true);
}
}
}
@@ -2381,6 +2917,11 @@ void RenderLayer::dirtyZOrderLists()
if (m_negZOrderList)
m_negZOrderList->clear();
m_zOrderListsDirty = true;
+
+#if USE(ACCELERATED_COMPOSITING)
+ if (!renderer()->documentBeingDestroyed())
+ compositor()->setCompositingLayersNeedUpdate();
+#endif
}
void RenderLayer::dirtyStackingContextZOrderLists()
@@ -2390,18 +2931,23 @@ void RenderLayer::dirtyStackingContextZOrderLists()
sc->dirtyZOrderLists();
}
-void RenderLayer::dirtyOverflowList()
+void RenderLayer::dirtyNormalFlowList()
{
- if (m_overflowList)
- m_overflowList->clear();
- m_overflowListDirty = true;
+ if (m_normalFlowList)
+ m_normalFlowList->clear();
+ m_normalFlowListDirty = true;
+
+#if USE(ACCELERATED_COMPOSITING)
+ if (!renderer()->documentBeingDestroyed())
+ compositor()->setCompositingLayersNeedUpdate();
+#endif
}
void RenderLayer::updateZOrderLists()
{
if (!isStackingContext() || !m_zOrderListsDirty)
return;
-
+
for (RenderLayer* child = firstChild(); child; child = child->nextSibling())
if (!m_reflection || reflectionLayer() != child)
child->collectLayers(m_posZOrderList, m_negZOrderList);
@@ -2409,27 +2955,28 @@ void RenderLayer::updateZOrderLists()
// Sort the two lists.
if (m_posZOrderList)
std::stable_sort(m_posZOrderList->begin(), m_posZOrderList->end(), compareZIndex);
+
if (m_negZOrderList)
std::stable_sort(m_negZOrderList->begin(), m_negZOrderList->end(), compareZIndex);
m_zOrderListsDirty = false;
}
-void RenderLayer::updateOverflowList()
+void RenderLayer::updateNormalFlowList()
{
- if (!m_overflowListDirty)
+ if (!m_normalFlowListDirty)
return;
for (RenderLayer* child = firstChild(); child; child = child->nextSibling()) {
// Ignore non-overflow layers and reflections.
- if (child->isOverflowOnly() && (!m_reflection || reflectionLayer() != child)) {
- if (!m_overflowList)
- m_overflowList = new Vector<RenderLayer*>;
- m_overflowList->append(child);
+ if (child->isNormalFlowOnly() && (!m_reflection || reflectionLayer() != child)) {
+ if (!m_normalFlowList)
+ m_normalFlowList = new Vector<RenderLayer*>;
+ m_normalFlowList->append(child);
}
}
- m_overflowListDirty = false;
+ m_normalFlowListDirty = false;
}
void RenderLayer::collectLayers(Vector<RenderLayer*>*& posBuffer, Vector<RenderLayer*>*& negBuffer)
@@ -2437,7 +2984,7 @@ void RenderLayer::collectLayers(Vector<RenderLayer*>*& posBuffer, Vector<RenderL
updateVisibilityStatus();
// Overflow layers are just painted by their enclosing layers, so they don't get put in zorder lists.
- if ((m_hasVisibleContent || (m_hasVisibleDescendant && isStackingContext())) && !isOverflowOnly()) {
+ if ((m_hasVisibleContent || (m_hasVisibleDescendant && isStackingContext())) && !isNormalFlowOnly()) {
// Determine which buffer the child should be in.
Vector<RenderLayer*>*& buffer = (zIndex() >= 0) ? posBuffer : negBuffer;
@@ -2460,34 +3007,97 @@ void RenderLayer::collectLayers(Vector<RenderLayer*>*& posBuffer, Vector<RenderL
}
}
+void RenderLayer::updateLayerListsIfNeeded()
+{
+#if USE(ACCELERATED_COMPOSITING)
+ if (compositor()->inCompositingMode()) {
+ if ((isStackingContext() && m_zOrderListsDirty) || m_normalFlowListDirty)
+ compositor()->updateCompositingLayers(this);
+ return;
+ }
+#endif
+ updateZOrderLists();
+ updateNormalFlowList();
+}
+
void RenderLayer::repaintIncludingDescendants()
{
- m_object->repaint();
+ renderer()->repaint();
for (RenderLayer* curr = firstChild(); curr; curr = curr->nextSibling())
curr->repaintIncludingDescendants();
}
-bool RenderLayer::shouldBeOverflowOnly() const
+#if USE(ACCELERATED_COMPOSITING)
+void RenderLayer::setBackingNeedsRepaint()
+{
+ ASSERT(isComposited());
+ if (backing()->paintingGoesToWindow()) {
+ // If we're trying to repaint the placeholder document layer, propagate the
+ // repaint to the native view system.
+ RenderView* view = renderer()->view();
+ if (view)
+ view->repaintViewRectangle(absoluteBoundingBox());
+ } else
+ backing()->setContentsNeedDisplay();
+}
+
+void RenderLayer::setBackingNeedsRepaintInRect(const IntRect& r)
+{
+ ASSERT(isComposited());
+ if (backing()->paintingGoesToWindow()) {
+ // If we're trying to repaint the placeholder document layer, propagate the
+ // repaint to the native view system.
+ IntRect absRect(r);
+ int x = 0;
+ int y = 0;
+ convertToLayerCoords(root(), x, y);
+ absRect.move(x, y);
+
+ RenderView* view = renderer()->view();
+ if (view)
+ view->repaintViewRectangle(absRect);
+ } else
+ backing()->setContentsNeedDisplayInRect(r);
+}
+
+// Since we're only painting non-composited layers, we know that they all share the same repaintContainer.
+void RenderLayer::repaintIncludingNonCompositingDescendants(RenderBoxModelObject* repaintContainer)
+{
+ renderer()->repaintUsingContainer(repaintContainer, renderer()->clippedOverflowRectForRepaint(repaintContainer));
+
+ for (RenderLayer* curr = firstChild(); curr; curr = curr->nextSibling()) {
+ if (!curr->isComposited())
+ curr->repaintIncludingNonCompositingDescendants(repaintContainer);
+ }
+}
+#endif
+
+bool RenderLayer::shouldBeNormalFlowOnly() const
{
- return (renderer()->hasOverflowClip() || renderer()->hasReflection()) &&
+ return (renderer()->hasOverflowClip() || renderer()->hasReflection() || renderer()->hasMask() || renderer()->isVideo()) &&
!renderer()->isPositioned() &&
!renderer()->isRelPositioned() &&
!renderer()->hasTransform() &&
!isTransparent();
}
-void RenderLayer::styleChanged(RenderStyle::Diff, const RenderStyle*)
+bool RenderLayer::isSelfPaintingLayer() const
{
- bool isOverflowOnly = shouldBeOverflowOnly();
- if (isOverflowOnly != m_isOverflowOnly) {
- m_isOverflowOnly = isOverflowOnly;
+ return !isNormalFlowOnly() || renderer()->hasReflection() || renderer()->hasMask() || renderer()->isTableRow() || renderer()->isVideo();
+}
+
+void RenderLayer::styleChanged(StyleDifference diff, const RenderStyle*)
+{
+ bool isNormalFlowOnly = shouldBeNormalFlowOnly();
+ if (isNormalFlowOnly != m_isNormalFlowOnly) {
+ m_isNormalFlowOnly = isNormalFlowOnly;
RenderLayer* p = parent();
if (p)
- p->dirtyOverflowList();
+ p->dirtyNormalFlowList();
dirtyStackingContextZOrderLists();
}
- if (m_object->style()->overflowX() == OMARQUEE && m_object->style()->marqueeBehavior() != MNONE) {
+ if (renderer()->style()->overflowX() == OMARQUEE && renderer()->style()->marqueeBehavior() != MNONE) {
if (!m_marquee)
m_marquee = new RenderMarquee(this);
m_marquee->updateMarqueeStyle();
@@ -2514,16 +3124,30 @@ void RenderLayer::styleChanged(RenderStyle::Diff, const RenderStyle*)
updateScrollCornerStyle();
updateResizerStyle();
+
+#if USE(ACCELERATED_COMPOSITING)
+ updateTransform();
+
+ if (compositor()->updateLayerCompositingState(this))
+ compositor()->setCompositingLayersNeedUpdate();
+ else if (m_backing)
+ m_backing->updateGraphicsLayerGeometry();
+
+ if (m_backing && diff >= StyleDifferenceRepaint)
+ m_backing->setContentsNeedDisplay();
+#else
+ UNUSED_PARAM(diff);
+#endif
}
void RenderLayer::updateScrollCornerStyle()
{
- RenderObject* actualRenderer = m_object->node()->isElementNode() ? m_object->node()->shadowAncestorNode()->renderer() : m_object;
- RefPtr<RenderStyle> corner = m_object->hasOverflowClip() ? actualRenderer->getUncachedPseudoStyle(RenderStyle::SCROLLBAR_CORNER, actualRenderer->style()) : 0;
+ RenderObject* actualRenderer = renderer()->node() ? renderer()->node()->shadowAncestorNode()->renderer() : renderer();
+ RefPtr<RenderStyle> corner = renderer()->hasOverflowClip() ? actualRenderer->getUncachedPseudoStyle(SCROLLBAR_CORNER, actualRenderer->style()) : 0;
if (corner) {
if (!m_scrollCorner) {
- m_scrollCorner = new (m_object->renderArena()) RenderScrollbarPart(m_object->document());
- m_scrollCorner->setParent(m_object);
+ m_scrollCorner = new (renderer()->renderArena()) RenderScrollbarPart(renderer()->document());
+ m_scrollCorner->setParent(renderer());
}
m_scrollCorner->setStyle(corner.release());
} else if (m_scrollCorner) {
@@ -2534,12 +3158,12 @@ void RenderLayer::updateScrollCornerStyle()
void RenderLayer::updateResizerStyle()
{
- RenderObject* actualRenderer = m_object->node()->isElementNode() ? m_object->node()->shadowAncestorNode()->renderer() : m_object;
- RefPtr<RenderStyle> resizer = m_object->hasOverflowClip() ? actualRenderer->getUncachedPseudoStyle(RenderStyle::RESIZER, actualRenderer->style()) : 0;
+ RenderObject* actualRenderer = renderer()->node() ? renderer()->node()->shadowAncestorNode()->renderer() : renderer();
+ RefPtr<RenderStyle> resizer = renderer()->hasOverflowClip() ? actualRenderer->getUncachedPseudoStyle(RESIZER, actualRenderer->style()) : 0;
if (resizer) {
if (!m_resizer) {
- m_resizer = new (m_object->renderArena()) RenderScrollbarPart(m_object->document());
- m_resizer->setParent(m_object);
+ m_resizer = new (renderer()->renderArena()) RenderScrollbarPart(renderer()->document());
+ m_resizer->setParent(renderer());
}
m_resizer->setStyle(resizer.release());
} else if (m_resizer) {
@@ -2597,13 +3221,4 @@ void RenderLayer::updateReflectionStyle()
m_reflection->setStyle(newStyle.release());
}
-void RenderLayer::suspendMarquees()
-{
- if (m_marquee)
- m_marquee->suspend();
-
- for (RenderLayer* curr = firstChild(); curr; curr = curr->nextSibling())
- curr->suspendMarquees();
-}
-
} // namespace WebCore
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderLayer.h b/src/3rdparty/webkit/WebCore/rendering/RenderLayer.h
index b2ba48c..4feede8 100644
--- a/src/3rdparty/webkit/WebCore/rendering/RenderLayer.h
+++ b/src/3rdparty/webkit/WebCore/rendering/RenderLayer.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003 Apple Computer, Inc.
+ * Copyright (C) 2003, 2009 Apple Inc. All rights reserved.
*
* Portions are Copyright (C) 1998 Netscape Communications Corporation.
*
@@ -44,19 +44,20 @@
#ifndef RenderLayer_h
#define RenderLayer_h
+#include "RenderBox.h"
+#include "ScrollBehavior.h"
#include "ScrollbarClient.h"
-#include "RenderObject.h"
#include "Timer.h"
#include <wtf/OwnPtr.h>
namespace WebCore {
-class TransformationMatrix;
class CachedResource;
+class HitTestRequest;
class HitTestResult;
+class HitTestingTransformState;
class RenderFrameSet;
class RenderMarquee;
-class RenderObject;
class RenderReplica;
class RenderScrollbarPart;
class RenderStyle;
@@ -64,8 +65,12 @@ class RenderTable;
class RenderText;
class RenderView;
class Scrollbar;
+class TransformationMatrix;
-struct HitTestRequest;
+#if USE(ACCELERATED_COMPOSITING)
+class RenderLayerBacking;
+class RenderLayerCompositor;
+#endif
class ClipRects {
public:
@@ -140,7 +145,9 @@ public:
m_fixed = other.fixed();
return *this;
}
-
+
+ static IntRect infiniteRect() { return IntRect(INT_MIN/2, INT_MIN/2, INT_MAX, INT_MAX); }
+
private:
// The normal operator new is disallowed on all render objects.
void* operator new(size_t) throw();
@@ -155,38 +162,13 @@ private:
class RenderLayer : public ScrollbarClient {
public:
- enum ScrollBehavior {
- noScroll,
- alignCenter,
- alignTop,
- alignBottom,
- alignLeft,
- alignRight,
- alignToClosestEdge
- };
-
- struct ScrollAlignment {
- ScrollBehavior m_rectVisible;
- ScrollBehavior m_rectHidden;
- ScrollBehavior m_rectPartial;
- };
-
friend class RenderReplica;
- static const ScrollAlignment gAlignCenterIfNeeded;
- static const ScrollAlignment gAlignToEdgeIfNeeded;
- static const ScrollAlignment gAlignCenterAlways;
- static const ScrollAlignment gAlignTopAlways;
- static const ScrollAlignment gAlignBottomAlways;
-
- static ScrollBehavior getVisibleBehavior(const ScrollAlignment& s) { return s.m_rectVisible; }
- static ScrollBehavior getPartialBehavior(const ScrollAlignment& s) { return s.m_rectPartial; }
- static ScrollBehavior getHiddenBehavior(const ScrollAlignment& s) { return s.m_rectHidden; }
-
- RenderLayer(RenderObject*);
+ RenderLayer(RenderBoxModelObject*);
~RenderLayer();
- RenderObject* renderer() const { return m_object; }
+ RenderBoxModelObject* renderer() const { return m_renderer; }
+ RenderBox* renderBox() const { return m_renderer && m_renderer->isBox() ? toRenderBox(m_renderer) : 0; }
RenderLayer* parent() const { return m_parent; }
RenderLayer* previousSibling() const { return m_previous; }
RenderLayer* nextSibling() const { return m_next; }
@@ -201,20 +183,28 @@ public:
void repaintIncludingDescendants();
- void styleChanged(RenderStyle::Diff, const RenderStyle*);
+#if USE(ACCELERATED_COMPOSITING)
+ // Indicate that the layer contents need to be repainted. Only has an effect
+ // if layer compositing is being used,
+ void setBackingNeedsRepaint();
+ void setBackingNeedsRepaintInRect(const IntRect& r); // r is in the coordinate space of the layer's render object
+ void repaintIncludingNonCompositingDescendants(RenderBoxModelObject* repaintContainer);
+#endif
+
+ void styleChanged(StyleDifference, const RenderStyle*);
RenderMarquee* marquee() const { return m_marquee; }
- void suspendMarquees();
- bool isOverflowOnly() const { return m_isOverflowOnly; }
+ bool isNormalFlowOnly() const { return m_isNormalFlowOnly; }
+ bool isSelfPaintingLayer() const;
bool requiresSlowRepaints() const;
bool isTransparent() const;
- RenderLayer* transparentAncestor();
+ RenderLayer* transparentPaintingAncestor();
void beginTransparencyLayers(GraphicsContext*, const RenderLayer* rootLayer);
- bool hasReflection() const { return m_object->hasReflection(); }
+ bool hasReflection() const { return renderer()->hasReflection(); }
RenderReplica* reflection() const { return m_reflection; }
RenderLayer* reflectionLayer() const;
@@ -226,12 +216,12 @@ public:
return curr;
}
- int xPos() const { return m_x; }
- int yPos() const { return m_y; }
- void setPos(int xPos, int yPos)
+ int x() const { return m_x; }
+ int y() const { return m_y; }
+ void setLocation(int x, int y)
{
- m_x = xPos;
- m_y = yPos;
+ m_x = x;
+ m_y = y;
}
int width() const { return m_width; }
@@ -256,9 +246,9 @@ public:
void scrollToOffset(int x, int y, bool updateScrollbars = true, bool repaint = true);
void scrollToXOffset(int x) { scrollToOffset(x, m_scrollY); }
void scrollToYOffset(int y) { scrollToOffset(m_scrollX + m_scrollOriginX, y); }
- void scrollRectToVisible(const IntRect&, bool scrollToAnchor = false, const ScrollAlignment& alignX = gAlignCenterIfNeeded, const ScrollAlignment& alignY = gAlignCenterIfNeeded);
+ void scrollRectToVisible(const IntRect&, bool scrollToAnchor = false, const ScrollAlignment& alignX = ScrollAlignment::alignCenterIfNeeded, const ScrollAlignment& alignY = ScrollAlignment::alignCenterIfNeeded);
- IntRect getRectToExpose(const IntRect& visibleRect, const IntRect& exposeRect, const ScrollAlignment& alignX, const ScrollAlignment& alignY);
+ IntRect getRectToExpose(const IntRect& visibleRect, const IntRect& exposeRect, const ScrollAlignment& alignX, const ScrollAlignment& alignY);
void setHasHorizontalScrollbar(bool);
void setHasVerticalScrollbar(bool);
@@ -289,6 +279,19 @@ public:
void resize(const PlatformMouseEvent&, const IntSize&);
bool inResizeMode() const { return m_inResizeMode; }
void setInResizeMode(bool b) { m_inResizeMode = b; }
+
+ bool isRootLayer() const { return renderer()->isRenderView(); }
+
+#if USE(ACCELERATED_COMPOSITING)
+ RenderLayerCompositor* compositor() const;
+
+ // Notification from the renderer that its content changed (e.g. current frame of image changed).
+ // Allows updates of layer content without repainting.
+ void rendererContentChanged();
+#endif
+
+ // Returns true if the accelerated compositing is enabled
+ bool hasAcceleratedCompositing() const;
void updateLayerPosition();
void updateLayerPositions(bool doFullRepaint = false, bool checkForRepaint = true);
@@ -312,9 +315,9 @@ public:
Vector<RenderLayer*>* posZOrderList() const { return m_posZOrderList; }
Vector<RenderLayer*>* negZOrderList() const { return m_negZOrderList; }
- void dirtyOverflowList();
- void updateOverflowList();
- Vector<RenderLayer*>* overflowList() const { return m_overflowList; }
+ void dirtyNormalFlowList();
+ void updateNormalFlowList();
+ Vector<RenderLayer*>* normalFlowList() const { return m_normalFlowList; }
bool hasVisibleContent() const { return m_hasVisibleContent; }
void setHasVisibleContent(bool);
@@ -324,6 +327,13 @@ public:
// the <html> layer and the root layer).
RenderLayer* enclosingPositionedAncestor() const;
+#if USE(ACCELERATED_COMPOSITING)
+ // Enclosing compositing layer; if includeSelf is true, may return this.
+ RenderLayer* enclosingCompositingLayer(bool includeSelf = true) const;
+ // Ancestor compositing layer, excluding this.
+ RenderLayer* ancestorCompositingLayer() const { return enclosingCompositingLayer(false); }
+#endif
+
void convertToLayerCoords(const RenderLayer* ancestorLayer, int& x, int& y) const;
bool hasAutoZIndex() const { return renderer()->style()->hasAutoZIndex(); }
@@ -354,23 +364,39 @@ public:
bool intersectsDamageRect(const IntRect& layerBounds, const IntRect& damageRect, const RenderLayer* rootLayer) const;
- // Returns a bounding box for this layer only.
+ // Bounding box relative to some ancestor layer.
IntRect boundingBox(const RenderLayer* rootLayer) const;
+ // Bounding box in the coordinates of this layer.
+ IntRect localBoundingBox() const;
+ // Bounding box relative to the root.
+ IntRect absoluteBoundingBox() const;
void updateHoverActiveState(const HitTestRequest&, HitTestResult&);
+ // Return a cached repaint rect, computed relative to the layer renderer's containerForRepaint.
IntRect repaintRect() const { return m_repaintRect; }
void setNeedsFullRepaint(bool f = true) { m_needsFullRepaint = f; }
int staticX() const { return m_staticX; }
int staticY() const { return m_staticY; }
void setStaticX(int staticX) { m_staticX = staticX; }
- void setStaticY(int staticY) { m_staticY = staticY; }
+ void setStaticY(int staticY);
- bool hasTransform() const { return m_object->hasTransform(); }
+ bool hasTransform() const { return renderer()->hasTransform(); }
+ // Note that this transform has the transform-origin baked in.
TransformationMatrix* transform() const { return m_transform.get(); }
-
- void destroy(RenderArena*);
+ // currentTransform computes a transform which takes accelerated animations into account. The
+ // resulting transform has transform-origin baked in. If the layer does not have a transform,
+ // returns the identity matrix.
+ TransformationMatrix currentTransform() const;
+
+ // Get the perspective transform, which is applied to transformed sublayers.
+ // Returns true if the layer has a -webkit-perspective.
+ // Note that this transform has the perspective-origin baked in.
+ TransformationMatrix perspectiveTransform() const;
+ FloatPoint perspectiveOrigin() const;
+ bool preserves3D() const { return renderer()->style()->transformStyle3D() == TransformStyle3DPreserve3D; }
+ bool has3DTransform() const { return m_transform && !m_transform->isAffine(); }
// Overloaded new operator. Derived classes must override operator new
// in order to allocate out of the RenderArena.
@@ -379,6 +405,25 @@ public:
// Overridden to prevent the normal delete from being called.
void operator delete(void*, size_t);
+#if USE(ACCELERATED_COMPOSITING)
+ bool isComposited() const { return m_backing != 0; }
+ RenderLayerBacking* backing() const { return m_backing.get(); }
+ RenderLayerBacking* ensureBacking();
+ void clearBacking();
+#else
+ bool isComposited() const { return false; }
+#endif
+
+ bool paintsWithTransparency() const
+ {
+ return isTransparent() && !isComposited();
+ }
+
+ bool paintsWithTransform() const
+ {
+ return transform() && !isComposited();
+ }
+
private:
// The normal operator new is disallowed on all render objects.
void* operator new(size_t) throw();
@@ -386,19 +431,43 @@ private:
private:
void setNextSibling(RenderLayer* next) { m_next = next; }
void setPreviousSibling(RenderLayer* prev) { m_previous = prev; }
- void setParent(RenderLayer* parent) { m_parent = parent; }
+ void setParent(RenderLayer* parent);
void setFirstChild(RenderLayer* first) { m_first = first; }
void setLastChild(RenderLayer* last) { m_last = last; }
+ int renderBoxX() const { return renderer()->isBox() ? toRenderBox(renderer())->x() : 0; }
+ int renderBoxY() const { return renderer()->isBox() ? toRenderBox(renderer())->y() : 0; }
+
void collectLayers(Vector<RenderLayer*>*&, Vector<RenderLayer*>*&);
+ void updateLayerListsIfNeeded();
+
+ enum PaintLayerFlag {
+ PaintLayerHaveTransparency = 1,
+ PaintLayerAppliedTransform = 1 << 1,
+ PaintLayerTemporaryClipRects = 1 << 2,
+ PaintLayerPaintingReflection = 1 << 3
+ };
+
+ typedef unsigned PaintLayerFlags;
+
void paintLayer(RenderLayer* rootLayer, GraphicsContext*, const IntRect& paintDirtyRect,
- bool haveTransparency, PaintRestriction, RenderObject* paintingRoot,
- bool appliedTransform = false, bool temporaryClipRects = false);
- RenderLayer* hitTestLayer(RenderLayer* rootLayer, const HitTestRequest&, HitTestResult&, const IntRect& hitTestRect, const IntPoint& hitTestPoint, bool appliedTransform = false);
+ PaintRestriction, RenderObject* paintingRoot, RenderObject::OverlapTestRequestMap* = 0,
+ PaintLayerFlags paintFlags = 0);
+
+ RenderLayer* hitTestLayer(RenderLayer* rootLayer, RenderLayer* containerLayer, const HitTestRequest& request, HitTestResult& result,
+ const IntRect& hitTestRect, const IntPoint& hitTestPoint, bool appliedTransform,
+ const HitTestingTransformState* transformState = 0, double* zOffset = 0);
+
+ PassRefPtr<HitTestingTransformState> createLocalTransformState(RenderLayer* rootLayer, RenderLayer* containerLayer,
+ const IntRect& hitTestRect, const IntPoint& hitTestPoint,
+ const HitTestingTransformState* containerTransformState) const;
+
+ bool hitTestContents(const HitTestRequest&, HitTestResult&, const IntRect& layerBounds, const IntPoint& hitTestPoint, HitTestFilter) const;
+
void computeScrollDimensions(bool* needHBar = 0, bool* needVBar = 0);
- bool shouldBeOverflowOnly() const;
+ bool shouldBeNormalFlowOnly() const;
virtual void valueChanged(Scrollbar*);
virtual void invalidateScrollbarRect(Scrollbar*, const IntRect&);
@@ -411,11 +480,22 @@ private:
void dirtyVisibleDescendantStatus();
void updateVisibilityStatus();
+ // This flag is computed by RenderLayerCompositor, which knows more about 3d hierarchies than we do.
+ void setHas3DTransformedDescendant(bool b) { m_has3DTransformedDescendant = b; }
+ bool has3DTransformedDescendant() const { return m_has3DTransformedDescendant; }
+
+ void dirty3DTransformedDescendantStatus();
+ // Both updates the status, and returns true if descendants of this have 3d.
+ bool update3DTransformedDescendantStatus();
+
Node* enclosingElement() const;
void createReflection();
void updateReflectionStyle();
bool paintingInsideReflection() const { return m_paintingInsideReflection; }
+ void setPaintingInsideReflection(bool b) { m_paintingInsideReflection = b; }
+
+ void parentClipRects(const RenderLayer* rootLayer, ClipRects&, bool temporaryClipRects = false) const;
RenderLayer* enclosingTransformedAncestor() const;
@@ -425,8 +505,24 @@ private:
void updateScrollCornerStyle();
void updateResizerStyle();
-protected:
- RenderObject* m_object;
+#if USE(ACCELERATED_COMPOSITING)
+ bool hasCompositingDescendant() const { return m_hasCompositingDescendant; }
+ void setHasCompositingDescendant(bool b) { m_hasCompositingDescendant = b; }
+
+ bool mustOverlayCompositedLayers() const { return m_mustOverlayCompositedLayers; }
+ void setMustOverlayCompositedLayers(bool b) { m_mustOverlayCompositedLayers = b; }
+#endif
+
+private:
+ friend class RenderLayerBacking;
+ friend class RenderLayerCompositor;
+ friend class RenderBoxModelObject;
+
+ // Only safe to call from RenderBoxModelObject::destroyLayer(RenderArena*)
+ void destroy(RenderArena*);
+
+protected:
+ RenderBoxModelObject* m_renderer;
RenderLayer* m_parent;
RenderLayer* m_previous;
@@ -475,7 +571,7 @@ protected:
// This list contains child layers that cannot create stacking contexts. For now it is just
// overflow layers, but that may change in the future.
- Vector<RenderLayer*>* m_overflowList;
+ Vector<RenderLayer*>* m_normalFlowList;
ClipRects* m_clipRects; // Cached clip rects used when painting and hit testing.
#ifndef NDEBUG
@@ -484,8 +580,8 @@ protected:
bool m_scrollDimensionsDirty : 1;
bool m_zOrderListsDirty : 1;
- bool m_overflowListDirty: 1;
- bool m_isOverflowOnly : 1;
+ bool m_normalFlowListDirty: 1;
+ bool m_isNormalFlowOnly : 1;
bool m_usedTransparency : 1; // Tracks whether we need to close a transparent layer, i.e., whether
// we ended up painting this layer or any descendants (and therefore need to
@@ -502,6 +598,14 @@ protected:
bool m_visibleDescendantStatusDirty : 1;
bool m_hasVisibleDescendant : 1;
+ bool m_3DTransformedDescendantStatusDirty : 1;
+ 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_mustOverlayCompositedLayers : 1;
+#endif
+
RenderMarquee* m_marquee; // Used by layers with overflow:marquee
// Cached normal flow values for absolute positioned elements with static left/top values.
@@ -516,6 +620,10 @@ protected:
// Renderers to hold our custom scroll corner and resizer.
RenderScrollbarPart* m_scrollCorner;
RenderScrollbarPart* m_resizer;
+
+#if USE(ACCELERATED_COMPOSITING)
+ OwnPtr<RenderLayerBacking> m_backing;
+#endif
};
} // namespace WebCore
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderLayerBacking.cpp b/src/3rdparty/webkit/WebCore/rendering/RenderLayerBacking.cpp
new file mode 100644
index 0000000..1c6d43c
--- /dev/null
+++ b/src/3rdparty/webkit/WebCore/rendering/RenderLayerBacking.cpp
@@ -0,0 +1,1082 @@
+/*
+ * Copyright (C) 2009 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``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 COMPUTER, INC. OR
+ * 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 USE(ACCELERATED_COMPOSITING)
+
+#include "AnimationController.h"
+#include "CSSPropertyNames.h"
+#include "CSSStyleSelector.h"
+#include "FrameView.h"
+#include "GraphicsContext.h"
+#include "GraphicsLayer.h"
+#include "HTMLElement.h"
+#include "HTMLNames.h"
+#include "RenderBox.h"
+#include "RenderImage.h"
+#include "RenderLayerCompositor.h"
+#include "RenderVideo.h"
+#include "RenderView.h"
+
+#include "RenderLayerBacking.h"
+
+using namespace std;
+
+namespace WebCore {
+
+static bool hasBorderOutlineOrShadow(const RenderStyle*);
+static bool hasBoxDecorations(const RenderStyle*);
+static bool hasBoxDecorationsWithBackgroundImage(const RenderStyle*);
+
+RenderLayerBacking::RenderLayerBacking(RenderLayer* layer)
+ : m_owningLayer(layer)
+ , m_ancestorClippingLayer(0)
+ , m_graphicsLayer(0)
+ , m_contentsLayer(0)
+ , m_clippingLayer(0)
+ , m_hasDirectlyCompositedContent(false)
+{
+ createGraphicsLayer();
+}
+
+RenderLayerBacking::~RenderLayerBacking()
+{
+ updateClippingLayers(false, false);
+ updateContentsLayer(false);
+ destroyGraphicsLayer();
+}
+
+void RenderLayerBacking::createGraphicsLayer()
+{
+ m_graphicsLayer = GraphicsLayer::createGraphicsLayer(this);
+
+#ifndef NDEBUG
+ if (renderer()->node()) {
+ if (renderer()->node()->isDocumentNode())
+ m_graphicsLayer->setName("Document Node");
+ else {
+ if (renderer()->node()->isHTMLElement() && renderer()->node()->hasID())
+ m_graphicsLayer->setName(renderer()->renderName() + String(" ") + static_cast<HTMLElement*>(renderer()->node())->id());
+ else
+ m_graphicsLayer->setName(renderer()->renderName());
+ }
+ } else
+ m_graphicsLayer->setName("Anonymous Node");
+#endif // NDEBUG
+
+ updateLayerOpacity();
+ updateLayerTransform();
+}
+
+void RenderLayerBacking::destroyGraphicsLayer()
+{
+ if (m_graphicsLayer)
+ m_graphicsLayer->removeFromParent();
+
+ delete m_graphicsLayer;
+ m_graphicsLayer = 0;
+
+ delete m_contentsLayer;
+ m_contentsLayer = 0;
+
+ delete m_clippingLayer;
+ m_clippingLayer = 0;
+}
+
+void RenderLayerBacking::updateLayerOpacity()
+{
+ m_graphicsLayer->setOpacity(compositingOpacity(renderer()->opacity()), 0, 0);
+}
+
+void RenderLayerBacking::updateLayerTransform()
+{
+ RenderStyle* style = renderer()->style();
+
+ // FIXME: This could use m_owningLayer->transform(), but that currently has transform-origin
+ // baked into it, and we don't want that.
+ TransformationMatrix t;
+ if (m_owningLayer->hasTransform()) {
+ style->applyTransform(t, toRenderBox(renderer())->borderBoxRect().size(), RenderStyle::ExcludeTransformOrigin);
+ makeMatrixRenderable(t, compositor()->hasAcceleratedCompositing());
+ }
+
+ m_graphicsLayer->setTransform(t);
+}
+
+void RenderLayerBacking::updateAfterLayout()
+{
+ RenderLayerCompositor* layerCompositor = compositor();
+ if (!layerCompositor->compositingLayersNeedUpdate()) {
+ // Calling updateGraphicsLayerGeometry() here gives incorrect results, because the
+ // position of this layer's GraphicsLayer depends on the position of our compositing
+ // ancestor's GraphicsLayer. That cannot be determined until all the descendant
+ // RenderLayers of that ancestor have been processed via updateLayerPositions().
+ //
+ // The solution is to update compositing children of this layer here,
+ // via updateCompositingChildrenGeometry().
+ setCompositedBounds(layerCompositor->calculateCompositedBounds(m_owningLayer, m_owningLayer));
+ layerCompositor->updateCompositingChildrenGeometry(m_owningLayer, m_owningLayer);
+
+ if (!m_owningLayer->parent())
+ layerCompositor->updateRootLayerPosition();
+ }
+}
+
+bool RenderLayerBacking::updateGraphicsLayerConfiguration()
+{
+ RenderLayerCompositor* compositor = this->compositor();
+
+ bool layerConfigChanged = false;
+ if (updateContentsLayer(compositor->needsContentsCompositingLayer(m_owningLayer)))
+ layerConfigChanged = true;
+
+ if (updateClippingLayers(compositor->clippedByAncestor(m_owningLayer), compositor->clipsCompositingDescendants(m_owningLayer)))
+ layerConfigChanged = true;
+
+ m_hasDirectlyCompositedContent = false;
+ if (canUseDirectCompositing()) {
+ if (renderer()->isImage()) {
+ updateImageContents();
+ m_hasDirectlyCompositedContent = true;
+ m_graphicsLayer->setDrawsContent(false);
+ }
+
+ if (rendererHasBackground())
+ m_graphicsLayer->setBackgroundColor(rendererBackgroundColor());
+ else
+ m_graphicsLayer->clearBackgroundColor();
+ }
+
+ return layerConfigChanged;
+}
+
+void RenderLayerBacking::updateGraphicsLayerGeometry()
+{
+ // If we haven't built z-order lists yet, wait until later.
+ if (m_owningLayer->isStackingContext() && m_owningLayer->m_zOrderListsDirty)
+ return;
+
+ // Set transform property, if it is not animating. We have to do this here because the transform
+ // is affected by the layer dimensions.
+ if (!renderer()->animation()->isAnimatingPropertyOnRenderer(renderer(), CSSPropertyWebkitTransform))
+ updateLayerTransform();
+
+ // Set opacity, if it is not animating.
+ if (!renderer()->animation()->isAnimatingPropertyOnRenderer(renderer(), CSSPropertyOpacity))
+ updateLayerOpacity();
+
+ RenderStyle* style = renderer()->style();
+ m_graphicsLayer->setPreserves3D(style->transformStyle3D() == TransformStyle3DPreserve3D);
+ m_graphicsLayer->setBackfaceVisibility(style->backfaceVisibility() == BackfaceVisibilityVisible);
+
+ RenderLayer* compAncestor = m_owningLayer->ancestorCompositingLayer();
+
+ // We compute everything relative to the enclosing compositing layer.
+ IntRect ancestorCompositingBounds;
+ if (compAncestor) {
+ ASSERT(compAncestor->backing());
+ ancestorCompositingBounds = compAncestor->backing()->compositedBounds();
+ }
+
+ IntRect localCompositingBounds = compositedBounds();
+
+ IntRect relativeCompositingBounds(localCompositingBounds);
+ int deltaX = 0, deltaY = 0;
+ m_owningLayer->convertToLayerCoords(compAncestor, deltaX, deltaY);
+ relativeCompositingBounds.move(deltaX, deltaY);
+
+ IntPoint graphicsLayerParentLocation;
+ if (compAncestor && compAncestor->backing()->hasClippingLayer()) {
+ // If the compositing ancestor has a layer to clip children, we parent in that, and therefore
+ // position relative to it.
+ graphicsLayerParentLocation = toRenderBox(compAncestor->renderer())->overflowClipRect(0, 0).location();
+ } else
+ graphicsLayerParentLocation = ancestorCompositingBounds.location();
+
+ if (compAncestor && m_ancestorClippingLayer) {
+ // Call calculateRects to get the backgroundRect which is what is used to clip the contents of this
+ // layer. Note that we call it with temporaryClipRects = true because normally when computing clip rects
+ // for a compositing layer, rootLayer is the layer itself.
+ ClipRects parentRects;
+ m_owningLayer->parentClipRects(compAncestor, parentRects, true);
+ IntRect parentClipRect = parentRects.overflowClipRect();
+
+ m_ancestorClippingLayer->setPosition(FloatPoint() + (parentClipRect.location() - graphicsLayerParentLocation));
+ m_ancestorClippingLayer->setSize(parentClipRect.size());
+
+ // backgroundRect is relative to compAncestor, so subtract deltaX/deltaY to get back to local coords.
+ IntSize rendererOffset(parentClipRect.location().x() - deltaX, parentClipRect.location().y() - deltaY);
+ m_ancestorClippingLayer->setOffsetFromRenderer(rendererOffset);
+
+ // The primary layer is then parented in, and positioned relative to this clipping layer.
+ graphicsLayerParentLocation = parentClipRect.location();
+ }
+
+ m_graphicsLayer->setPosition(FloatPoint() + (relativeCompositingBounds.location() - graphicsLayerParentLocation));
+ m_graphicsLayer->setOffsetFromRenderer(localCompositingBounds.location() - IntPoint());
+
+ FloatSize oldSize = m_graphicsLayer->size();
+ FloatSize newSize = relativeCompositingBounds.size();
+ if (oldSize != newSize) {
+ m_graphicsLayer->setSize(newSize);
+ // A bounds change will almost always require redisplay. Usually that redisplay
+ // will happen because of a repaint elsewhere, but not always:
+ // e.g. see RenderView::setMaximalOutlineSize()
+ m_graphicsLayer->setNeedsDisplay();
+ }
+
+ // If we have a layer that clips children, position it.
+ if (m_clippingLayer) {
+ IntRect clippingBox = toRenderBox(renderer())->overflowClipRect(0, 0);
+ m_clippingLayer->setPosition(FloatPoint() + (clippingBox.location() - localCompositingBounds.location()));
+ m_clippingLayer->setSize(clippingBox.size());
+ m_clippingLayer->setOffsetFromRenderer(clippingBox.location() - IntPoint());
+ }
+
+ if (m_owningLayer->hasTransform()) {
+ const IntRect borderBox = toRenderBox(renderer())->borderBoxRect();
+
+ // Get layout bounds in the coords of compAncestor to match relativeCompositingBounds.
+ IntRect layerBounds = IntRect(deltaX, deltaY, borderBox.width(), borderBox.height());
+
+ // Update properties that depend on layer dimensions
+ FloatPoint3D transformOrigin = computeTransformOrigin(borderBox);
+ // Compute the anchor point, which is in the center of the renderer box unless transform-origin is set.
+ FloatPoint3D anchor(relativeCompositingBounds.width() != 0.0f ? ((layerBounds.x() - relativeCompositingBounds.x()) + transformOrigin.x()) / relativeCompositingBounds.width() : 0.5f,
+ relativeCompositingBounds.height() != 0.0f ? ((layerBounds.y() - relativeCompositingBounds.y()) + transformOrigin.y()) / relativeCompositingBounds.height() : 0.5f,
+ transformOrigin.z());
+ m_graphicsLayer->setAnchorPoint(anchor);
+
+ RenderStyle* style = renderer()->style();
+ if (style->hasPerspective()) {
+ TransformationMatrix t = owningLayer()->perspectiveTransform();
+
+ if (m_clippingLayer) {
+ m_clippingLayer->setChildrenTransform(t);
+ m_graphicsLayer->setChildrenTransform(TransformationMatrix());
+ }
+ else
+ m_graphicsLayer->setChildrenTransform(t);
+ } else {
+ if (m_clippingLayer)
+ m_clippingLayer->setChildrenTransform(TransformationMatrix());
+ else
+ m_graphicsLayer->setChildrenTransform(TransformationMatrix());
+ }
+ } else {
+ m_graphicsLayer->setAnchorPoint(FloatPoint3D(0.5f, 0.5f, 0));
+ }
+
+ if (m_contentsLayer) {
+ // The contents layer is always coincidental with the graphicsLayer for now.
+ m_contentsLayer->setPosition(IntPoint(0, 0));
+ m_contentsLayer->setSize(newSize);
+ m_contentsLayer->setOffsetFromRenderer(m_graphicsLayer->offsetFromRenderer());
+ }
+
+ m_graphicsLayer->updateContentsRect();
+ if (!m_hasDirectlyCompositedContent)
+ m_graphicsLayer->setDrawsContent(!isSimpleContainerCompositingLayer() && !paintingGoesToWindow());
+}
+
+void RenderLayerBacking::updateInternalHierarchy()
+{
+ // m_contentsLayer has to be inserted in the correct order with child layers,
+ // so it's not inserted here.
+ if (m_ancestorClippingLayer) {
+ m_ancestorClippingLayer->removeAllChildren();
+ m_graphicsLayer->removeFromParent();
+ m_ancestorClippingLayer->addChild(m_graphicsLayer);
+ }
+
+ if (m_clippingLayer) {
+ m_clippingLayer->removeFromParent();
+ m_graphicsLayer->addChild(m_clippingLayer);
+ }
+}
+
+// Return true if the layers changed.
+bool RenderLayerBacking::updateClippingLayers(bool needsAncestorClip, bool needsDescendantClip)
+{
+ bool layersChanged = false;
+
+ if (needsAncestorClip) {
+ if (!m_ancestorClippingLayer) {
+ m_ancestorClippingLayer = GraphicsLayer::createGraphicsLayer(this);
+#ifndef NDEBUG
+ m_ancestorClippingLayer->setName("Ancestor clipping Layer");
+#endif
+ m_ancestorClippingLayer->setMasksToBounds(true);
+ layersChanged = true;
+ }
+ } else if (m_ancestorClippingLayer) {
+ m_ancestorClippingLayer->removeFromParent();
+ delete m_ancestorClippingLayer;
+ m_ancestorClippingLayer = 0;
+ layersChanged = true;
+ }
+
+ if (needsDescendantClip) {
+ if (!m_clippingLayer) {
+ m_clippingLayer = GraphicsLayer::createGraphicsLayer(0);
+#ifndef NDEBUG
+ m_clippingLayer->setName("Child clipping Layer");
+#endif
+ m_clippingLayer->setMasksToBounds(true);
+ layersChanged = true;
+ }
+ } else if (m_clippingLayer) {
+ m_clippingLayer->removeFromParent();
+ delete m_clippingLayer;
+ m_clippingLayer = 0;
+ layersChanged = true;
+ }
+
+ if (layersChanged)
+ updateInternalHierarchy();
+
+ return layersChanged;
+}
+
+bool RenderLayerBacking::updateContentsLayer(bool needsContentsLayer)
+{
+ bool layerChanged = false;
+ if (needsContentsLayer) {
+ if (!m_contentsLayer) {
+ m_contentsLayer = GraphicsLayer::createGraphicsLayer(this);
+#ifndef NDEBUG
+ m_contentsLayer->setName("Contents");
+#endif
+ m_contentsLayer->setDrawsContent(true);
+ m_contentsLayer->setDrawingPhase(GraphicsLayerPaintForegroundMask);
+ m_graphicsLayer->setDrawingPhase(GraphicsLayerPaintBackgroundMask);
+ layerChanged = true;
+ }
+ } else if (m_contentsLayer) {
+ m_contentsLayer->removeFromParent();
+ delete m_contentsLayer;
+ m_contentsLayer = 0;
+ m_graphicsLayer->setDrawingPhase(GraphicsLayerPaintAllMask);
+ layerChanged = true;
+ }
+ return layerChanged;
+}
+
+float RenderLayerBacking::compositingOpacity(float rendererOpacity) const
+{
+ float finalOpacity = rendererOpacity;
+
+ for (RenderLayer* curr = m_owningLayer->parent(); curr; curr = curr->parent()) {
+ // We only care about parents that are stacking contexts.
+ // Recall that opacity creates stacking context.
+ if (!curr->isStackingContext())
+ continue;
+
+ // If we found a compositing layer, we want to compute opacity
+ // relative to it. So we can break here.
+ if (curr->isComposited())
+ break;
+
+ finalOpacity *= curr->renderer()->opacity();
+ }
+
+ return finalOpacity;
+}
+
+static bool hasBorderOutlineOrShadow(const RenderStyle* style)
+{
+ return style->hasBorder() || style->hasBorderRadius() || style->hasOutline() || style->hasAppearance() || style->boxShadow();
+}
+
+static bool hasBoxDecorations(const RenderStyle* style)
+{
+ return hasBorderOutlineOrShadow(style) || style->hasBackground();
+}
+
+static bool hasBoxDecorationsWithBackgroundImage(const RenderStyle* style)
+{
+ return hasBorderOutlineOrShadow(style) || style->hasBackgroundImage();
+}
+
+bool RenderLayerBacking::rendererHasBackground() const
+{
+ // FIXME: share more code here
+ if (renderer()->node() && renderer()->node()->isDocumentNode()) {
+ RenderObject* htmlObject = renderer()->firstChild();
+ if (!htmlObject)
+ return false;
+
+ RenderStyle* style = htmlObject->style();
+ if (style->hasBackground())
+ return true;
+
+ RenderObject* bodyObject = htmlObject->firstChild();
+ if (!bodyObject)
+ return false;
+
+ style = bodyObject->style();
+ return style->hasBackground();
+ }
+
+ return renderer()->style()->hasBackground();
+}
+
+const Color& RenderLayerBacking::rendererBackgroundColor() const
+{
+ // FIXME: share more code here
+ if (renderer()->node() && renderer()->node()->isDocumentNode()) {
+ RenderObject* htmlObject = renderer()->firstChild();
+ RenderStyle* style = htmlObject->style();
+ if (style->hasBackground())
+ return style->backgroundColor();
+
+ RenderObject* bodyObject = htmlObject->firstChild();
+ style = bodyObject->style();
+ return style->backgroundColor();
+ }
+
+ return renderer()->style()->backgroundColor();
+}
+
+// A "simple container layer" is a RenderLayer which has no visible content to render.
+// It may have no children, or all its children may be themselves composited.
+// This is a useful optimization, because it allows us to avoid allocating backing store.
+bool RenderLayerBacking::isSimpleContainerCompositingLayer() const
+{
+ RenderObject* renderObject = renderer();
+ if (renderObject->isReplaced() || // replaced objects are not containers
+ renderObject->hasMask()) // masks require special treatment
+ return false;
+
+ RenderStyle* style = renderObject->style();
+
+ // Reject anything that has a border, a border-radius or outline,
+ // or any background (color or image).
+ // FIXME: we could optimize layers for simple backgrounds.
+ if (hasBoxDecorations(style))
+ return false;
+
+ // If we have got this far and the renderer has no children, then we're ok.
+ if (!renderObject->firstChild())
+ return true;
+
+ if (renderObject->node() && renderObject->node()->isDocumentNode()) {
+ // Look to see if the root object has a non-simple backgound
+ RenderObject* rootObject = renderObject->document()->documentElement()->renderer();
+ if (!rootObject)
+ return false;
+
+ style = rootObject->style();
+
+ // Reject anything that has a border, a border-radius or outline,
+ // or is not a simple background (no background, or solid color).
+ if (hasBoxDecorationsWithBackgroundImage(style))
+ return false;
+
+ // Now look at the body's renderer.
+ HTMLElement* body = renderObject->document()->body();
+ RenderObject* bodyObject = (body && body->hasLocalName(HTMLNames::bodyTag)) ? body->renderer() : 0;
+ if (!bodyObject)
+ return false;
+
+ style = bodyObject->style();
+
+ if (hasBoxDecorationsWithBackgroundImage(style))
+ return false;
+
+ // Ceck to see if all the body's children are compositing layers.
+ if (hasNonCompositingContent())
+ return false;
+
+ return true;
+ }
+
+ // Check to see if all the renderer's children are compositing layers.
+ if (hasNonCompositingContent())
+ return false;
+
+ return true;
+}
+
+bool RenderLayerBacking::hasNonCompositingContent() const
+{
+ // Conservative test for having no rendered children.
+
+ // Some HTML can cause whitespace text nodes to have renderers, like:
+ // <div>
+ // <img src=...>
+ // </div>
+ // so test for 0x0 RenderTexts here
+ for (RenderObject* child = renderer()->firstChild(); child; child = child->nextSibling()) {
+ if (!child->hasLayer()) {
+ if (child->isRenderInline() || !child->isBox())
+ return true;
+
+ if (toRenderBox(child)->width() > 0 || toRenderBox(child)->height() > 0)
+ return true;
+ }
+ }
+
+ // FIXME: test for overflow controls.
+ if (m_owningLayer->isStackingContext()) {
+ // Use the m_hasCompositingDescendant bit to optimize?
+ if (Vector<RenderLayer*>* negZOrderList = m_owningLayer->negZOrderList()) {
+ size_t listSize = negZOrderList->size();
+ for (size_t i = 0; i < listSize; ++i) {
+ RenderLayer* curLayer = negZOrderList->at(i);
+ if (!curLayer->isComposited())
+ return true;
+ }
+ }
+
+ if (Vector<RenderLayer*>* posZOrderList = m_owningLayer->posZOrderList()) {
+ size_t listSize = posZOrderList->size();
+ for (size_t i = 0; i < listSize; ++i) {
+ RenderLayer* curLayer = posZOrderList->at(i);
+ if (!curLayer->isComposited())
+ return true;
+ }
+ }
+ }
+
+ if (Vector<RenderLayer*>* normalFlowList = m_owningLayer->normalFlowList()) {
+ size_t listSize = normalFlowList->size();
+ for (size_t i = 0; i < listSize; ++i) {
+ RenderLayer* curLayer = normalFlowList->at(i);
+ if (!curLayer->isComposited())
+ return true;
+ }
+ }
+
+ return false;
+}
+
+// A layer can use direct compositing if the render layer's object is a replaced object and has no children.
+// This allows the GraphicsLayer to display the RenderLayer contents directly; it's used for images.
+bool RenderLayerBacking::canUseDirectCompositing() const
+{
+ RenderObject* renderObject = renderer();
+
+ // Reject anything that isn't an image
+ if (!renderObject->isImage() && !renderObject->isVideo())
+ return false;
+
+ if (renderObject->hasMask() || renderObject->hasReflection())
+ return false;
+
+ // Video can use an inner layer even if it has box decorations; we draw those into another layer.
+ if (renderObject->isVideo())
+ return true;
+
+ // Reject anything that would require the image to be drawn via the GraphicsContext,
+ // like border, shadows etc. Solid background color is OK.
+ return !hasBoxDecorationsWithBackgroundImage(renderObject->style());
+}
+
+void RenderLayerBacking::rendererContentChanged()
+{
+ if (canUseDirectCompositing() && renderer()->isImage())
+ updateImageContents();
+}
+
+void RenderLayerBacking::updateImageContents()
+{
+ ASSERT(renderer()->isImage());
+ RenderImage* imageRenderer = static_cast<RenderImage*>(renderer());
+
+ CachedImage* cachedImage = imageRenderer->cachedImage();
+ if (!cachedImage)
+ return;
+
+ Image* image = cachedImage->image();
+ if (!image)
+ return;
+
+ // We have to wait until the image is fully loaded before setting it on the layer.
+ if (!cachedImage->isLoaded())
+ return;
+
+ // This is a no-op if the layer doesn't have an inner layer for the image.
+ m_graphicsLayer->setContentsToImage(image);
+
+ // Image animation is "lazy", in that it automatically stops unless someone is drawing
+ // the image. So we have to kick the animation each time; this has the downside that the
+ // image will keep animating, even if its layer is not visible.
+ image->startAnimation();
+}
+
+FloatPoint3D RenderLayerBacking::computeTransformOrigin(const IntRect& borderBox) const
+{
+ RenderStyle* style = renderer()->style();
+
+ FloatPoint3D origin;
+ origin.setX(style->transformOriginX().calcFloatValue(borderBox.width()));
+ origin.setY(style->transformOriginY().calcFloatValue(borderBox.height()));
+ origin.setZ(style->transformOriginZ());
+
+ return origin;
+}
+
+FloatPoint RenderLayerBacking::computePerspectiveOrigin(const IntRect& borderBox) const
+{
+ RenderStyle* style = renderer()->style();
+
+ float boxWidth = borderBox.width();
+ float boxHeight = borderBox.height();
+
+ FloatPoint origin;
+ origin.setX(style->perspectiveOriginX().calcFloatValue(boxWidth));
+ origin.setY(style->perspectiveOriginY().calcFloatValue(boxHeight));
+
+ return origin;
+}
+
+// Return the offset from the top-left of this compositing layer at which the renderer's contents are painted.
+IntSize RenderLayerBacking::contentOffsetInCompostingLayer()
+{
+ return IntSize(-m_compositedBounds.x(), -m_compositedBounds.y());
+}
+
+IntRect RenderLayerBacking::contentsBox(const GraphicsLayer*)
+{
+ if (!renderer()->isBox())
+ return IntRect();
+
+ IntRect contentsRect;
+#if ENABLE(VIDEO)
+ if (renderer()->isVideo()) {
+ RenderVideo* videoRenderer = static_cast<RenderVideo*>(renderer());
+ contentsRect = videoRenderer->videoBox();
+ } else
+#endif
+ contentsRect = toRenderBox(renderer())->contentBoxRect();
+
+ IntSize contentOffset = contentOffsetInCompostingLayer();
+ contentsRect.move(contentOffset);
+ return contentsRect;
+}
+
+// Map the given point from coordinates in the GraphicsLayer to RenderLayer coordinates.
+FloatPoint RenderLayerBacking::graphicsLayerToContentsCoordinates(const GraphicsLayer* graphicsLayer, const FloatPoint& point)
+{
+ return point + FloatSize(graphicsLayer->offsetFromRenderer());
+}
+
+// Map the given point from coordinates in the RenderLayer to GraphicsLayer coordinates.
+FloatPoint RenderLayerBacking::contentsToGraphicsLayerCoordinates(const GraphicsLayer* graphicsLayer, const FloatPoint& point)
+{
+ return point - FloatSize(graphicsLayer->offsetFromRenderer());
+}
+
+bool RenderLayerBacking::paintingGoesToWindow() const
+{
+ return m_owningLayer->isRootLayer();
+}
+
+void RenderLayerBacking::setContentsNeedDisplay()
+{
+ bool needViewUpdate = false;
+
+ if (m_graphicsLayer && m_graphicsLayer->drawsContent()) {
+ m_graphicsLayer->setNeedsDisplay();
+ needViewUpdate = true;
+ }
+
+ if (m_contentsLayer && m_contentsLayer->drawsContent()) {
+ m_contentsLayer->setNeedsDisplay();
+ needViewUpdate = true;
+ }
+
+ // Make sure layout happens before we get rendered again.
+ if (needViewUpdate)
+ compositor()->scheduleViewUpdate();
+}
+
+// r is in the coordinate space of the layer's render object
+void RenderLayerBacking::setContentsNeedDisplayInRect(const IntRect& r)
+{
+ bool needViewUpdate = false;
+
+ if (m_graphicsLayer && m_graphicsLayer->drawsContent()) {
+ FloatPoint dirtyOrigin = contentsToGraphicsLayerCoordinates(m_graphicsLayer, FloatPoint(r.x(), r.y()));
+ FloatRect dirtyRect(dirtyOrigin, r.size());
+ FloatRect bounds(FloatPoint(), m_graphicsLayer->size());
+ if (bounds.intersects(dirtyRect)) {
+ m_graphicsLayer->setNeedsDisplayInRect(dirtyRect);
+ needViewUpdate = true;
+ }
+ }
+
+ if (m_contentsLayer && m_contentsLayer->drawsContent()) {
+ // FIXME: do incremental repaint
+ m_contentsLayer->setNeedsDisplay();
+ needViewUpdate = true;
+ }
+
+ // Make sure layout happens before we get rendered again.
+ if (needViewUpdate)
+ compositor()->scheduleViewUpdate();
+}
+
+static void setClip(GraphicsContext* p, const IntRect& paintDirtyRect, const IntRect& clipRect)
+{
+ if (paintDirtyRect == clipRect)
+ return;
+ p->save();
+ p->clip(clipRect);
+}
+
+static void restoreClip(GraphicsContext* p, const IntRect& paintDirtyRect, const IntRect& clipRect)
+{
+ if (paintDirtyRect == clipRect)
+ return;
+ p->restore();
+}
+
+// Share this with RenderLayer::paintLayer, which would have to be educated about GraphicsLayerPaintingPhase?
+void RenderLayerBacking::paintIntoLayer(RenderLayer* rootLayer, GraphicsContext* context,
+ const IntRect& paintDirtyRect, // in the coords of rootLayer
+ PaintRestriction paintRestriction, GraphicsLayerPaintingPhase paintingPhase,
+ RenderObject* paintingRoot)
+{
+ if (paintingGoesToWindow()) {
+ ASSERT_NOT_REACHED();
+ return;
+ }
+
+ m_owningLayer->updateLayerListsIfNeeded();
+
+ // Paint the reflection first if we have one.
+ if (m_owningLayer->hasReflection()) {
+ // Mark that we are now inside replica painting.
+ m_owningLayer->setPaintingInsideReflection(true);
+ m_owningLayer->reflectionLayer()->paintLayer(rootLayer, context, paintDirtyRect, paintRestriction, paintingRoot, 0, RenderLayer::PaintLayerPaintingReflection);
+ m_owningLayer->setPaintingInsideReflection(false);
+ }
+
+ // Calculate the clip rects we should use.
+ IntRect layerBounds, damageRect, clipRectToApply, outlineRect;
+ m_owningLayer->calculateRects(rootLayer, paintDirtyRect, layerBounds, damageRect, clipRectToApply, outlineRect);
+
+ int x = layerBounds.x(); // layerBounds is computed relative to rootLayer
+ int y = layerBounds.y();
+ int tx = x - m_owningLayer->renderBoxX();
+ int ty = y - m_owningLayer->renderBoxY();
+
+ // If this layer's renderer is a child of the paintingRoot, we render unconditionally, which
+ // is done by passing a nil paintingRoot down to our renderer (as if no paintingRoot was ever set).
+ // Else, our renderer tree may or may not contain the painting root, so we pass that root along
+ // so it will be tested against as we decend through the renderers.
+ RenderObject *paintingRootForRenderer = 0;
+ if (paintingRoot && !renderer()->isDescendantOf(paintingRoot))
+ paintingRootForRenderer = paintingRoot;
+
+ bool shouldPaint = m_owningLayer->hasVisibleContent() && m_owningLayer->isSelfPaintingLayer();
+
+ if (shouldPaint && (paintingPhase & GraphicsLayerPaintBackgroundMask)) {
+ // If this is the root then we need to send in a bigger bounding box
+ // because we'll be painting the background as well (see RenderBox::paintRootBoxDecorations()).
+ IntRect paintBox = clipRectToApply;
+
+ // FIXME: do we need this code?
+ if (renderer()->node() && renderer()->node()->isDocumentNode() && renderer()->document()->isHTMLDocument()) {
+ RenderBox* box = toRenderBox(renderer());
+ int w = box->width();
+ int h = box->height();
+
+ int rw;
+ int rh;
+ if (box->view()->frameView()) {
+ rw = box->view()->frameView()->contentsWidth();
+ rh = box->view()->frameView()->contentsHeight();
+ } else {
+ rw = box->view()->width();
+ rh = box->view()->height();
+ }
+
+ int bx = tx - box->marginLeft();
+ int by = ty - box->marginTop();
+ int bw = max(w + box->marginLeft() + box->marginRight() + box->borderLeft() + box->borderRight(), rw);
+ int bh = max(h + box->marginTop() + box->marginBottom() + box->borderTop() + box->borderBottom(), rh);
+ paintBox = IntRect(bx, by, bw, bh);
+ }
+
+ // Paint our background first, before painting any child layers.
+ // Establish the clip used to paint our background.
+ setClip(context, paintDirtyRect, damageRect);
+
+ RenderObject::PaintInfo info(context, paintBox, PaintPhaseBlockBackground, false, paintingRootForRenderer, 0);
+ renderer()->paint(info, tx, ty);
+
+ // Our scrollbar widgets paint exactly when we tell them to, so that they work properly with
+ // z-index. We paint after we painted the background/border, so that the scrollbars will
+ // sit above the background/border.
+ m_owningLayer->paintOverflowControls(context, x, y, damageRect);
+
+ // Restore the clip.
+ restoreClip(context, paintDirtyRect, damageRect);
+ }
+
+ if (shouldPaint && (paintingPhase & GraphicsLayerPaintForegroundMask)) {
+ // Now walk the sorted list of children with negative z-indices. Only RenderLayers without compositing layers will paint.
+ // FIXME: should these be painted as background?
+ Vector<RenderLayer*>* negZOrderList = m_owningLayer->negZOrderList();
+ if (negZOrderList) {
+ for (Vector<RenderLayer*>::iterator it = negZOrderList->begin(); it != negZOrderList->end(); ++it)
+ it[0]->paintLayer(rootLayer, context, paintDirtyRect, paintRestriction, paintingRoot);
+ }
+
+ bool forceBlackText = paintRestriction == PaintRestrictionSelectionOnlyBlackText;
+ bool selectionOnly = paintRestriction == PaintRestrictionSelectionOnly || paintRestriction == PaintRestrictionSelectionOnlyBlackText;
+
+ // Set up the clip used when painting our children.
+ setClip(context, paintDirtyRect, clipRectToApply);
+ RenderObject::PaintInfo paintInfo(context, clipRectToApply,
+ selectionOnly ? PaintPhaseSelection : PaintPhaseChildBlockBackgrounds,
+ forceBlackText, paintingRootForRenderer, 0);
+ renderer()->paint(paintInfo, tx, ty);
+
+ if (!selectionOnly) {
+ paintInfo.phase = PaintPhaseFloat;
+ renderer()->paint(paintInfo, tx, ty);
+
+ paintInfo.phase = PaintPhaseForeground;
+ renderer()->paint(paintInfo, tx, ty);
+
+ paintInfo.phase = PaintPhaseChildOutlines;
+ renderer()->paint(paintInfo, tx, ty);
+ }
+
+ // Now restore our clip.
+ restoreClip(context, paintDirtyRect, clipRectToApply);
+
+ if (!outlineRect.isEmpty()) {
+ // Paint our own outline
+ RenderObject::PaintInfo paintInfo(context, outlineRect, PaintPhaseSelfOutline, false, paintingRootForRenderer, 0);
+ setClip(context, paintDirtyRect, outlineRect);
+ renderer()->paint(paintInfo, tx, ty);
+ restoreClip(context, paintDirtyRect, outlineRect);
+ }
+
+ // Paint any child layers that have overflow.
+ Vector<RenderLayer*>* normalFlowList = m_owningLayer->normalFlowList();
+ if (normalFlowList) {
+ for (Vector<RenderLayer*>::iterator it = normalFlowList->begin(); it != normalFlowList->end(); ++it)
+ it[0]->paintLayer(rootLayer, context, paintDirtyRect, paintRestriction, paintingRoot);
+ }
+
+ // Now walk the sorted list of children with positive z-indices.
+ Vector<RenderLayer*>* posZOrderList = m_owningLayer->posZOrderList();
+ if (posZOrderList) {
+ for (Vector<RenderLayer*>::iterator it = posZOrderList->begin(); it != posZOrderList->end(); ++it)
+ it[0]->paintLayer(rootLayer, context, paintDirtyRect, paintRestriction, paintingRoot);
+ }
+
+ if (renderer()->hasMask() && !selectionOnly && !damageRect.isEmpty()) {
+ setClip(context, paintDirtyRect, damageRect);
+
+ // Paint the mask.
+ RenderObject::PaintInfo paintInfo(context, damageRect, PaintPhaseMask, false, paintingRootForRenderer, 0);
+ renderer()->paint(paintInfo, tx, ty);
+
+ // Restore the clip.
+ restoreClip(context, paintDirtyRect, damageRect);
+ }
+ }
+
+ ASSERT(!m_owningLayer->m_usedTransparency);
+}
+
+// Up-call from compositing layer drawing callback.
+void RenderLayerBacking::paintContents(const GraphicsLayer*, GraphicsContext& context, GraphicsLayerPaintingPhase drawingPhase, const IntRect& clip)
+{
+ // We have to use the same root as for hit testing, because both methods
+ // can compute and cache clipRects.
+ IntRect enclosingBBox = compositedBounds();
+
+ IntRect clipRect(clip);
+
+ // Set up the coordinate space to be in the layer's rendering coordinates.
+ context.translate(-enclosingBBox.x(), -enclosingBBox.y());
+
+ // Offset the clip.
+ clipRect.move(enclosingBBox.x(), enclosingBBox.y());
+
+ // The dirtyRect is in the coords of the painting root.
+ IntRect dirtyRect = enclosingBBox;
+ dirtyRect.intersect(clipRect);
+
+ paintIntoLayer(m_owningLayer, &context, dirtyRect, PaintRestrictionNone, drawingPhase, renderer());
+}
+
+bool RenderLayerBacking::startAnimation(double beginTime, const Animation* anim, const KeyframeList& keyframes)
+{
+ bool hasOpacity = keyframes.containsProperty(CSSPropertyOpacity);
+ bool hasTransform = keyframes.containsProperty(CSSPropertyWebkitTransform);
+
+ if (!hasOpacity && !hasTransform)
+ return false;
+
+ GraphicsLayer::TransformValueList transformVector;
+ GraphicsLayer::FloatValueList opacityVector;
+
+ for (Vector<KeyframeValue>::const_iterator it = keyframes.beginKeyframes(); it != keyframes.endKeyframes(); ++it) {
+ const RenderStyle* keyframeStyle = it->style();
+ float key = it->key();
+
+ if (!keyframeStyle)
+ continue;
+
+ // get timing function
+ const TimingFunction* tf = keyframeStyle->hasAnimations() ? &((*keyframeStyle->animations()).animation(0)->timingFunction()) : 0;
+
+ if (hasTransform)
+ transformVector.insert(key, &(keyframeStyle->transform()), tf);
+
+ if (hasOpacity)
+ opacityVector.insert(key, keyframeStyle->opacity(), tf);
+ }
+
+ bool didAnimateTransform = !hasTransform;
+ bool didAnimateOpacity = !hasOpacity;
+
+ if (hasTransform && m_graphicsLayer->animateTransform(transformVector, toRenderBox(renderer())->borderBoxRect().size(), anim, beginTime, false))
+ didAnimateTransform = true;
+
+ if (hasOpacity && m_graphicsLayer->animateFloat(AnimatedPropertyOpacity, opacityVector, anim, beginTime))
+ didAnimateOpacity = true;
+
+ return didAnimateTransform && didAnimateOpacity;
+}
+
+bool RenderLayerBacking::startTransition(double beginTime, int property, const RenderStyle* fromStyle, const RenderStyle* toStyle)
+{
+ bool didAnimate = false;
+ ASSERT(property != cAnimateAll);
+
+ if (property == (int)CSSPropertyOpacity) {
+ const Animation* opacityAnim = toStyle->transitionForProperty(CSSPropertyOpacity);
+ if (opacityAnim && !opacityAnim->isEmptyOrZeroDuration()) {
+ // If beginTime is not 0, we are restarting this transition, so first set the from value
+ // in case it was smashed by a previous animation.
+ if (beginTime > 0)
+ m_graphicsLayer->setOpacity(compositingOpacity(fromStyle->opacity()), 0, 0);
+
+ if (m_graphicsLayer->setOpacity(compositingOpacity(toStyle->opacity()), opacityAnim, beginTime))
+ didAnimate = true;
+ }
+ }
+
+ if (property == (int)CSSPropertyWebkitTransform && m_owningLayer->hasTransform()) {
+ // We get a TransformOperation, which is a linked list of primitive operations and their arguments.
+ // Arguments can be floats or Length values, which need to be converted to numbers using
+ // val.calcFloatValue(renderer()->width()) (or height()).
+ const Animation* transformAnim = toStyle->transitionForProperty(CSSPropertyWebkitTransform);
+ if (transformAnim && !transformAnim->isEmptyOrZeroDuration()) {
+ GraphicsLayer::TransformValueList transformVector;
+ transformVector.insert(0, &fromStyle->transform(), 0);
+ transformVector.insert(1, &toStyle->transform(), 0);
+ if (m_graphicsLayer->animateTransform(transformVector, toRenderBox(renderer())->borderBoxRect().size(), transformAnim, beginTime, true))
+ didAnimate = true;
+ }
+ }
+
+ return didAnimate;
+}
+
+void RenderLayerBacking::notifyAnimationStarted(const GraphicsLayer*, double time)
+{
+ renderer()->animation()->notifyAnimationStarted(renderer(), time);
+}
+
+void RenderLayerBacking::animationFinished(const String& name, int index, bool reset)
+{
+ m_graphicsLayer->removeFinishedAnimations(name, index, reset);
+}
+
+void RenderLayerBacking::transitionFinished(int property)
+{
+ AnimatedPropertyID animatedProperty = cssToGraphicsLayerProperty(property);
+ if (animatedProperty != AnimatedPropertyInvalid)
+ m_graphicsLayer->removeFinishedTransitions(animatedProperty);
+}
+
+void RenderLayerBacking::suspendAnimations()
+{
+ m_graphicsLayer->suspendAnimations();
+}
+
+void RenderLayerBacking::resumeAnimations()
+{
+ m_graphicsLayer->resumeAnimations();
+}
+
+IntRect RenderLayerBacking::compositedBounds() const
+{
+ return m_compositedBounds;
+}
+
+void RenderLayerBacking::setCompositedBounds(const IntRect& bounds)
+{
+ m_compositedBounds = bounds;
+
+}
+int RenderLayerBacking::graphicsLayerToCSSProperty(AnimatedPropertyID property)
+{
+ int cssProperty = CSSPropertyInvalid;
+ switch (property) {
+ case AnimatedPropertyWebkitTransform:
+ cssProperty = CSSPropertyWebkitTransform;
+ break;
+ case AnimatedPropertyOpacity:
+ cssProperty = CSSPropertyOpacity;
+ break;
+ case AnimatedPropertyBackgroundColor:
+ cssProperty = CSSPropertyBackgroundColor;
+ break;
+ case AnimatedPropertyInvalid:
+ ASSERT_NOT_REACHED();
+ }
+ return cssProperty;
+}
+
+AnimatedPropertyID RenderLayerBacking::cssToGraphicsLayerProperty(int cssProperty)
+{
+ switch (cssProperty) {
+ case CSSPropertyWebkitTransform:
+ return AnimatedPropertyWebkitTransform;
+ case CSSPropertyOpacity:
+ return AnimatedPropertyOpacity;
+ case CSSPropertyBackgroundColor:
+ return AnimatedPropertyBackgroundColor;
+ // It's fine if we see other css properties here; they are just not accelerated.
+ }
+ return AnimatedPropertyInvalid;
+}
+
+} // namespace WebCore
+
+#endif // USE(ACCELERATED_COMPOSITING)
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderLayerBacking.h b/src/3rdparty/webkit/WebCore/rendering/RenderLayerBacking.h
new file mode 100644
index 0000000..50a77db
--- /dev/null
+++ b/src/3rdparty/webkit/WebCore/rendering/RenderLayerBacking.h
@@ -0,0 +1,176 @@
+/*
+ * Copyright (C) 2009 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``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 COMPUTER, INC. OR
+ * 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 RenderLayerBacking_h
+#define RenderLayerBacking_h
+
+#if USE(ACCELERATED_COMPOSITING)
+
+#include "FloatPoint.h"
+#include "FloatPoint3D.h"
+#include "GraphicsLayer.h"
+#include "GraphicsLayerClient.h"
+#include "RenderLayer.h"
+#include "TransformationMatrix.h"
+
+namespace WebCore {
+
+class KeyframeList;
+class RenderLayerCompositor;
+
+// RenderLayerBacking controls the compositing behavior for a single RenderLayer.
+// It holds the various GraphicsLayers, and makes decisions about intra-layer rendering
+// optimizations.
+//
+// There is one RenderLayerBacking for each RenderLayer that is composited.
+
+class RenderLayerBacking : public GraphicsLayerClient {
+public:
+ RenderLayerBacking(RenderLayer*);
+ ~RenderLayerBacking();
+
+ RenderLayer* owningLayer() const { return m_owningLayer; }
+
+ void updateAfterLayout();
+
+ // Returns true if layer configuration changed.
+ bool updateGraphicsLayerConfiguration();
+ // Update graphics layer position and bounds.
+ void updateGraphicsLayerGeometry(); // make private
+ // Update contents and clipping structure.
+ void updateInternalHierarchy(); // make private
+
+ GraphicsLayer* graphicsLayer() const { return m_graphicsLayer; }
+
+ // Layer to clip children
+ bool hasClippingLayer() const { return m_clippingLayer != 0; }
+ GraphicsLayer* clippingLayer() const { return m_clippingLayer; }
+
+ // Layer to get clipped by ancestor
+ bool hasAncestorClippingLayer() const { return m_ancestorClippingLayer != 0; }
+ GraphicsLayer* ancestorClippingLayer() const { return m_ancestorClippingLayer; }
+
+ bool hasContentsLayer() const { return m_contentsLayer != 0; }
+ GraphicsLayer* contentsLayer() const { return m_contentsLayer; }
+
+ GraphicsLayer* parentForSublayers() const { return m_clippingLayer ? m_clippingLayer : m_graphicsLayer; }
+ GraphicsLayer* childForSuperlayers() const { return m_ancestorClippingLayer ? m_ancestorClippingLayer : m_graphicsLayer; }
+
+ // RenderLayers with backing normally short-circuit paintLayer() because
+ // their content is rendered via callbacks from GraphicsLayer. However, the document
+ // layer is special, because it has a GraphicsLayer to act as a container for the GraphicsLayers
+ // for descendants, but its contents usually render into the window (in which case this returns true).
+ // This returns false for other layers, and when the document layer actually needs to paint into its backing store
+ // for some reason.
+ bool paintingGoesToWindow() const;
+
+ void setContentsNeedDisplay();
+ // r is in the coordinate space of the layer's render object
+ void setContentsNeedDisplayInRect(const IntRect& r);
+
+ // Notification from the renderer that its content changed; used by RenderImage.
+ void rendererContentChanged();
+
+ // Interface to start, finish, suspend and resume animations and transitions
+ bool startAnimation(double beginTime, const Animation* anim, const KeyframeList& keyframes);
+ bool startTransition(double beginTime, int property, const RenderStyle* fromStyle, const RenderStyle* toStyle);
+ void animationFinished(const String& name, int index, bool reset);
+ void transitionFinished(int property);
+
+ void suspendAnimations();
+ void resumeAnimations();
+
+ IntRect compositedBounds() const;
+ void setCompositedBounds(const IntRect&);
+
+ FloatPoint graphicsLayerToContentsCoordinates(const GraphicsLayer*, const FloatPoint&);
+ FloatPoint contentsToGraphicsLayerCoordinates(const GraphicsLayer*, const FloatPoint&);
+
+ // GraphicsLayerClient interface
+ virtual void notifyAnimationStarted(const GraphicsLayer*, double startTime);
+
+ virtual void paintContents(const GraphicsLayer*, GraphicsContext&, GraphicsLayerPaintingPhase, const IntRect& clip);
+
+ virtual IntRect contentsBox(const GraphicsLayer*);
+
+private:
+ void createGraphicsLayer();
+ void destroyGraphicsLayer();
+
+ RenderBoxModelObject* renderer() const { return m_owningLayer->renderer(); }
+ RenderLayerCompositor* compositor() const { return m_owningLayer->compositor(); }
+
+ bool updateClippingLayers(bool needsAncestorClip, bool needsDescendantClip);
+ bool updateContentsLayer(bool needsContentsLayer);
+
+ IntSize contentOffsetInCompostingLayer();
+ // Result is transform origin in pixels.
+ FloatPoint3D computeTransformOrigin(const IntRect& borderBox) const;
+ // Result is perspective origin in pixels.
+ FloatPoint computePerspectiveOrigin(const IntRect& borderBox) const;
+
+ void updateLayerOpacity();
+ void updateLayerTransform();
+
+ // Return the opacity value that this layer should use for compositing.
+ float compositingOpacity(float rendererOpacity) const;
+
+ // Returns true if this RenderLayer only has content that can be rendered directly
+ // by the compositing layer, without drawing (e.g. solid background color).
+ bool isSimpleContainerCompositingLayer() const;
+ // Returns true if we can optimize the RenderLayer to draw the replaced content
+ // directly into a compositing buffer
+ bool canUseDirectCompositing() const;
+ void updateImageContents();
+
+ bool rendererHasBackground() const;
+ const Color& rendererBackgroundColor() const;
+
+ bool hasNonCompositingContent() const;
+
+ void paintIntoLayer(RenderLayer* rootLayer, GraphicsContext*, const IntRect& paintDirtyRect,
+ PaintRestriction paintRestriction, GraphicsLayerPaintingPhase, RenderObject* paintingRoot);
+
+ static int graphicsLayerToCSSProperty(AnimatedPropertyID);
+ static AnimatedPropertyID cssToGraphicsLayerProperty(int);
+
+private:
+ RenderLayer* m_owningLayer;
+
+ GraphicsLayer* m_ancestorClippingLayer; // only used if we are clipped by an ancestor which is not a stacking context
+ GraphicsLayer* m_graphicsLayer;
+ GraphicsLayer* m_contentsLayer; // only used in cases where we need to draw the foreground separately
+ GraphicsLayer* m_clippingLayer; // only used if we have clipping on a stacking context, with compositing children
+
+ IntRect m_compositedBounds;
+
+ bool m_hasDirectlyCompositedContent;
+};
+
+} // namespace WebCore
+
+#endif // USE(ACCELERATED_COMPOSITING)
+
+#endif // RenderLayerBacking_h
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderLayerCompositor.cpp b/src/3rdparty/webkit/WebCore/rendering/RenderLayerCompositor.cpp
new file mode 100644
index 0000000..8b07ca9
--- /dev/null
+++ b/src/3rdparty/webkit/WebCore/rendering/RenderLayerCompositor.cpp
@@ -0,0 +1,914 @@
+/*
+ * Copyright (C) 2009 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``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 COMPUTER, INC. OR
+ * 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 USE(ACCELERATED_COMPOSITING)
+#include "RenderLayerCompositor.h"
+
+#include "AnimationController.h"
+#include "ChromeClient.h"
+#include "CSSPropertyNames.h"
+#include "Frame.h"
+#include "FrameView.h"
+#include "GraphicsLayer.h"
+#include "HitTestRequest.h"
+#include "HitTestResult.h"
+#include "Page.h"
+#include "RenderLayerBacking.h"
+#include "RenderVideo.h"
+#include "RenderView.h"
+#include "Settings.h"
+
+#if PROFILE_LAYER_REBUILD
+#include <wtf/CurrentTime.h>
+#endif
+
+#ifndef NDEBUG
+#include "CString.h"
+#include "RenderTreeAsText.h"
+#endif
+
+#if ENABLE(3D_RENDERING)
+// This symbol is used to determine from a script whether 3D rendering is enabled (via 'nm').
+bool WebCoreHas3DRendering = true;
+#endif
+
+namespace WebCore {
+
+struct CompositingState {
+ CompositingState(RenderLayer* compAncestor)
+ : m_compositingAncestor(compAncestor)
+ , m_subtreeIsCompositing(false)
+#ifndef NDEBUG
+ , m_depth(0)
+#endif
+ {
+ }
+
+ RenderLayer* m_compositingAncestor;
+ bool m_subtreeIsCompositing;
+#ifndef NDEBUG
+ int m_depth;
+#endif
+};
+
+static TransformationMatrix flipTransform()
+{
+ TransformationMatrix flipper;
+ flipper.flipY();
+ return flipper;
+}
+
+RenderLayerCompositor::RenderLayerCompositor(RenderView* renderView)
+ : m_renderView(renderView)
+ , m_rootPlatformLayer(0)
+ , m_compositing(false)
+ , m_rootLayerAttached(false)
+ , m_compositingLayersNeedUpdate(false)
+ , m_hasAcceleratedCompositing(true)
+#if PROFILE_LAYER_REBUILD
+ , m_rootLayerUpdateCount(0)
+#endif // PROFILE_LAYER_REBUILD
+{
+}
+
+RenderLayerCompositor::~RenderLayerCompositor()
+{
+ ASSERT(!m_rootLayerAttached);
+ delete m_rootPlatformLayer;
+}
+
+void RenderLayerCompositor::enableCompositingMode(bool enable /* = true */)
+{
+ if (enable != m_compositing) {
+ m_compositing = enable;
+
+ // We never go out of compositing mode for a given page,
+ // but if all the layers disappear, we'll just be left with
+ // the empty root layer, which has minimal overhead.
+ if (m_compositing)
+ ensureRootPlatformLayer();
+ else
+ destroyRootPlatformLayer();
+ }
+}
+
+void RenderLayerCompositor::cacheAcceleratedCompositingEnabledFlag()
+{
+ bool hasAcceleratedCompositing = false;
+ if (Settings* settings = m_renderView->document()->settings())
+ hasAcceleratedCompositing = settings-> acceleratedCompositingEnabled();
+
+ if (hasAcceleratedCompositing != m_hasAcceleratedCompositing)
+ setCompositingLayersNeedUpdate();
+
+ m_hasAcceleratedCompositing = hasAcceleratedCompositing;
+}
+
+void RenderLayerCompositor::setCompositingLayersNeedUpdate(bool needUpdate)
+{
+ if (inCompositingMode()) {
+ if (!m_compositingLayersNeedUpdate && needUpdate)
+ scheduleViewUpdate();
+
+ m_compositingLayersNeedUpdate = needUpdate;
+ }
+}
+
+void RenderLayerCompositor::scheduleViewUpdate()
+{
+ Frame* frame = m_renderView->frameView()->frame();
+ Page* page = frame ? frame->page() : 0;
+ if (!page)
+ return;
+
+ page->chrome()->client()->scheduleViewUpdate();
+}
+
+void RenderLayerCompositor::updateCompositingLayers(RenderLayer* updateRoot)
+{
+ if (!m_compositingLayersNeedUpdate)
+ return;
+
+ ASSERT(inCompositingMode());
+
+ if (!updateRoot) {
+ // Only clear the flag if we're updating the entire hierarchy
+ m_compositingLayersNeedUpdate = false;
+ updateRoot = rootRenderLayer();
+ }
+
+#if PROFILE_LAYER_REBUILD
+ ++m_rootLayerUpdateCount;
+
+ double startTime = WTF::currentTime();
+#endif
+
+ // Go through the layers in presentation order, so that we can compute which
+ // RLs need compositing layers.
+ // FIXME: we could maybe do this in one pass, but the parenting logic would be more
+ // complex.
+ {
+ CompositingState compState(updateRoot);
+ computeCompositingRequirements(updateRoot, compState);
+ }
+
+ // Now create and parent the compositing layers.
+ {
+ CompositingState compState(updateRoot);
+ rebuildCompositingLayerTree(updateRoot, compState);
+ }
+
+#if PROFILE_LAYER_REBUILD
+ double endTime = WTF::currentTime();
+ if (updateRoot == rootRenderLayer())
+ fprintf(stderr, "Update %d: computeCompositingRequirements for the world took %fms\n",
+ m_rootLayerUpdateCount, 1000.0 * (endTime - startTime));
+#endif
+ ASSERT(updateRoot || !m_compositingLayersNeedUpdate);
+
+ if (!hasAcceleratedCompositing())
+ enableCompositingMode(false);
+}
+
+bool RenderLayerCompositor::updateBacking(RenderLayer* layer, CompositingChangeRepaint shouldRepaint)
+{
+ bool layerChanged = false;
+
+ if (needsToBeComposited(layer)) {
+ enableCompositingMode();
+ if (!layer->backing()) {
+
+ // If we need to repaint, do so before making backing
+ if (shouldRepaint == CompositingChangeRepaintNow)
+ repaintOnCompositingChange(layer);
+
+ layer->ensureBacking();
+ layerChanged = true;
+ }
+ } else {
+ if (layer->backing()) {
+ layer->clearBacking();
+ layerChanged = true;
+
+ // If we need to repaint, do so now that we've removed the backing
+ if (shouldRepaint == CompositingChangeRepaintNow)
+ repaintOnCompositingChange(layer);
+ }
+ }
+
+#if ENABLE(VIDEO)
+ if (layerChanged && layer->renderer()->isVideo()) {
+ // If it's a video, give the media player a chance to hook up to the layer.
+ RenderVideo* video = static_cast<RenderVideo*>(layer->renderer());
+ video->acceleratedRenderingStateChanged();
+ }
+#endif
+ return layerChanged;
+}
+
+bool RenderLayerCompositor::updateLayerCompositingState(RenderLayer* layer, CompositingChangeRepaint shouldRepaint)
+{
+ bool layerChanged = updateBacking(layer, shouldRepaint);
+
+ // See if we need content or clipping layers. Methods called here should assume
+ // that the compositing state of descendant layers has not been updated yet.
+ if (layer->backing() && layer->backing()->updateGraphicsLayerConfiguration())
+ layerChanged = true;
+
+ return layerChanged;
+}
+
+void RenderLayerCompositor::repaintOnCompositingChange(RenderLayer* layer)
+{
+ RenderBoxModelObject* repaintContainer = layer->renderer()->containerForRepaint();
+ if (!repaintContainer)
+ repaintContainer = m_renderView;
+
+ layer->repaintIncludingNonCompositingDescendants(repaintContainer);
+ if (repaintContainer == m_renderView) {
+ // The contents of this layer may be moving between the window
+ // and a GraphicsLayer, so we need to make sure the window system
+ // synchronizes those changes on the screen.
+ m_renderView->frameView()->setNeedsOneShotDrawingSynchronization();
+ }
+}
+
+// The bounds of the GraphicsLayer created for a compositing layer is the union of the bounds of all the descendant
+// RenderLayers that are rendered by the composited RenderLayer.
+IntRect RenderLayerCompositor::calculateCompositedBounds(const RenderLayer* layer, const RenderLayer* ancestorLayer)
+{
+ IntRect boundingBoxRect, unionBounds;
+ boundingBoxRect = unionBounds = layer->localBoundingBox();
+
+ ASSERT(layer->isStackingContext() || (!layer->m_posZOrderList || layer->m_posZOrderList->size() == 0));
+
+ if (!layer->isSelfPaintingLayer())
+ return IntRect();
+
+ if (Vector<RenderLayer*>* negZOrderList = layer->negZOrderList()) {
+ size_t listSize = negZOrderList->size();
+ for (size_t i = 0; i < listSize; ++i) {
+ RenderLayer* curLayer = negZOrderList->at(i);
+ if (!curLayer->isComposited()) {
+ IntRect childUnionBounds = calculateCompositedBounds(curLayer, layer);
+ unionBounds.unite(childUnionBounds);
+ }
+ }
+ }
+
+ if (Vector<RenderLayer*>* posZOrderList = layer->posZOrderList()) {
+ size_t listSize = posZOrderList->size();
+ for (size_t i = 0; i < listSize; ++i) {
+ RenderLayer* curLayer = posZOrderList->at(i);
+ if (!curLayer->isComposited()) {
+ IntRect childUnionBounds = calculateCompositedBounds(curLayer, layer);
+ unionBounds.unite(childUnionBounds);
+ }
+ }
+ }
+
+ if (Vector<RenderLayer*>* normalFlowList = layer->normalFlowList()) {
+ size_t listSize = normalFlowList->size();
+ for (size_t i = 0; i < listSize; ++i) {
+ RenderLayer* curLayer = normalFlowList->at(i);
+ if (!curLayer->isComposited()) {
+ IntRect curAbsBounds = calculateCompositedBounds(curLayer, layer);
+ unionBounds.unite(curAbsBounds);
+ }
+ }
+ }
+
+ if (layer->paintsWithTransform()) {
+ TransformationMatrix* affineTrans = layer->transform();
+ boundingBoxRect = affineTrans->mapRect(boundingBoxRect);
+ unionBounds = affineTrans->mapRect(unionBounds);
+ }
+
+ int ancestorRelX = 0, ancestorRelY = 0;
+ layer->convertToLayerCoords(ancestorLayer, ancestorRelX, ancestorRelY);
+ unionBounds.move(ancestorRelX, ancestorRelY);
+
+ return unionBounds;
+}
+
+void RenderLayerCompositor::layerWasAdded(RenderLayer* /*parent*/, RenderLayer* /*child*/)
+{
+ setCompositingLayersNeedUpdate();
+}
+
+void RenderLayerCompositor::layerWillBeRemoved(RenderLayer* parent, RenderLayer* child)
+{
+ if (!child->isComposited() || parent->renderer()->documentBeingDestroyed())
+ return;
+
+ setCompositingParent(child, 0);
+
+ RenderLayer* compLayer = parent->enclosingCompositingLayer();
+ if (compLayer) {
+ ASSERT(compLayer->backing());
+ IntRect compBounds = child->backing()->compositedBounds();
+
+ int offsetX = 0, offsetY = 0;
+ child->convertToLayerCoords(compLayer, offsetX, offsetY);
+ compBounds.move(offsetX, offsetY);
+
+ compLayer->setBackingNeedsRepaintInRect(compBounds);
+
+ // The contents of this layer may be moving from a GraphicsLayer to the window,
+ // so we need to make sure the window system synchronizes those changes on the screen.
+ m_renderView->frameView()->setNeedsOneShotDrawingSynchronization();
+ }
+
+ setCompositingLayersNeedUpdate();
+}
+
+RenderLayer* RenderLayerCompositor::enclosingNonStackingClippingLayer(const RenderLayer* layer) const
+{
+ for (RenderLayer* curr = layer->parent(); curr != 0; curr = curr->parent()) {
+ if (curr->isStackingContext())
+ return 0;
+
+ if (curr->renderer()->hasOverflowClip())
+ return curr;
+ }
+ return 0;
+}
+
+// Recurse through the layers in z-index and overflow order (which is equivalent to painting order)
+// For the z-order children of a compositing layer:
+// If a child layers has a compositing layer, then all subsequent layers must
+// be compositing in order to render above that layer.
+//
+// If a child in the negative z-order list is compositing, then the layer itself
+// must be compositing so that its contents render over that child.
+// This implies that its positive z-index children must also be compositing.
+//
+void RenderLayerCompositor::computeCompositingRequirements(RenderLayer* layer, struct CompositingState& compositingState)
+{
+ layer->updateLayerPosition();
+ layer->updateZOrderLists();
+ layer->updateNormalFlowList();
+
+ // Clear the flag
+ layer->setHasCompositingDescendant(false);
+ layer->setMustOverlayCompositedLayers(compositingState.m_subtreeIsCompositing);
+
+ // The children of this layer don't need to composite, unless there is
+ // a compositing layer among them, so start by inheriting the compositing
+ // ancestor with m_subtreeIsCompositing set to false.
+ CompositingState childState(compositingState.m_compositingAncestor);
+#ifndef NDEBUG
+ ++childState.m_depth;
+#endif
+
+ const bool willBeComposited = needsToBeComposited(layer);
+ if (willBeComposited) {
+ // Tell the parent it has compositing descendants.
+ compositingState.m_subtreeIsCompositing = true;
+ // This layer now acts as the ancestor for kids.
+ childState.m_compositingAncestor = layer;
+ }
+
+#if ENABLE(VIDEO)
+ // Video is special. It's a replaced element with a content layer, but has shadow content
+ // for the controller that must render in front. Without this, the controls fail to show
+ // when the video element is a stacking context (e.g. due to opacity or transform).
+ if (willBeComposited && layer->renderer()->isVideo())
+ childState.m_subtreeIsCompositing = true;
+#endif
+
+ if (layer->isStackingContext()) {
+ ASSERT(!layer->m_zOrderListsDirty);
+ if (Vector<RenderLayer*>* negZOrderList = layer->negZOrderList()) {
+ size_t listSize = negZOrderList->size();
+ for (size_t i = 0; i < listSize; ++i) {
+ RenderLayer* curLayer = negZOrderList->at(i);
+ computeCompositingRequirements(curLayer, childState);
+
+ // If we have to make a layer for this child, make one now so we can have a contents layer
+ // (since we need to ensure that the -ve z-order child renders underneath our contents).
+ if (childState.m_subtreeIsCompositing) {
+ // make layer compositing
+ layer->setMustOverlayCompositedLayers(true);
+ childState.m_compositingAncestor = layer;
+ }
+ }
+ }
+ }
+
+ ASSERT(!layer->m_normalFlowListDirty);
+ if (Vector<RenderLayer*>* normalFlowList = layer->normalFlowList()) {
+ size_t listSize = normalFlowList->size();
+ for (size_t i = 0; i < listSize; ++i) {
+ RenderLayer* curLayer = normalFlowList->at(i);
+ computeCompositingRequirements(curLayer, childState);
+ }
+ }
+
+ if (layer->isStackingContext()) {
+ if (Vector<RenderLayer*>* posZOrderList = layer->posZOrderList()) {
+ size_t listSize = posZOrderList->size();
+ for (size_t i = 0; i < listSize; ++i) {
+ RenderLayer* curLayer = posZOrderList->at(i);
+ computeCompositingRequirements(curLayer, childState);
+ }
+ }
+ }
+
+ // If we have a software transform, and we have layers under us, we need to also
+ // be composited. Also, if we have opacity < 1, then we need to be a layer so that
+ // the child layers are opaque, then rendered with opacity on this layer.
+ if (childState.m_subtreeIsCompositing &&
+ (layer->renderer()->hasTransform() || layer->renderer()->style()->opacity() < 1))
+ layer->setMustOverlayCompositedLayers(true);
+
+ // Subsequent layers in the parent stacking context also need to composite.
+ if (childState.m_subtreeIsCompositing)
+ compositingState.m_subtreeIsCompositing = true;
+
+ // If the layer is going into compositing mode, repaint its old location.
+ if (!layer->isComposited() && needsToBeComposited(layer))
+ repaintOnCompositingChange(layer);
+
+ // Set the flag to say that this SC has compositing children.
+ // this can affect the answer to needsToBeComposited() when clipping,
+ // but that's ok here.
+ layer->setHasCompositingDescendant(childState.m_subtreeIsCompositing);
+
+ // Update backing now, so that we can use isComposited() reliably during tree traversal in rebuildCompositingLayerTree().
+ updateBacking(layer, CompositingChangeRepaintNow);
+}
+
+void RenderLayerCompositor::setCompositingParent(RenderLayer* childLayer, RenderLayer* parentLayer)
+{
+ ASSERT(childLayer->isComposited());
+
+ // It's possible to be called with a parent that isn't yet composited when we're doing
+ // partial updates as required by painting or hit testing. Just bail in that case;
+ // we'll do a full layer update soon.
+ if (!parentLayer || !parentLayer->isComposited())
+ return;
+
+ if (parentLayer) {
+ GraphicsLayer* hostingLayer = parentLayer->backing()->parentForSublayers();
+ GraphicsLayer* hostedLayer = childLayer->backing()->childForSuperlayers();
+
+ hostingLayer->addChild(hostedLayer);
+ } else
+ childLayer->backing()->childForSuperlayers()->removeFromParent();
+}
+
+void RenderLayerCompositor::removeCompositedChildren(RenderLayer* layer)
+{
+ ASSERT(layer->isComposited());
+
+ GraphicsLayer* hostingLayer = layer->backing()->parentForSublayers();
+ hostingLayer->removeAllChildren();
+}
+
+void RenderLayerCompositor::parentInRootLayer(RenderLayer* layer)
+{
+ ASSERT(layer->isComposited());
+
+ GraphicsLayer* layerAnchor = layer->backing()->childForSuperlayers();
+
+ if (layerAnchor->parent() != m_rootPlatformLayer) {
+ layerAnchor->removeFromParent();
+ if (m_rootPlatformLayer)
+ m_rootPlatformLayer->addChild(layerAnchor);
+ }
+}
+
+#if ENABLE(VIDEO)
+bool RenderLayerCompositor::canAccelerateVideoRendering(RenderVideo* o) const
+{
+ // FIXME: ideally we need to look at all ancestors for mask or video. But for now,
+ // just bail on the obvious cases.
+ if (o->hasMask() || o->hasReflection() || !m_hasAcceleratedCompositing)
+ return false;
+
+ return o->supportsAcceleratedRendering();
+}
+#endif
+
+void RenderLayerCompositor::rebuildCompositingLayerTree(RenderLayer* layer, struct CompositingState& compositingState)
+{
+ // Make the layer compositing if necessary, and set up clipping and content layers.
+ // Note that we can only do work here that is independent of whether the descendant layers
+ // have been processed. computeCompositingRequirements() will already have done the repaint if necessary.
+ RenderLayerBacking* layerBacking = layer->backing();
+ if (layerBacking) {
+ // The compositing state of all our children has been updated already, so now
+ // we can compute and cache the composited bounds for this layer.
+ layerBacking->setCompositedBounds(calculateCompositedBounds(layer, layer));
+
+ layerBacking->updateGraphicsLayerConfiguration();
+ layerBacking->updateGraphicsLayerGeometry();
+
+ if (!layer->parent())
+ updateRootLayerPosition();
+
+ // FIXME: make this more incremental
+ layerBacking->parentForSublayers()->removeAllChildren();
+ }
+
+ // host the document layer in the RenderView's root layer
+ if (layer->isRootLayer() && layer->isComposited())
+ parentInRootLayer(layer);
+
+ CompositingState childState = compositingState;
+ if (layer->isComposited())
+ childState.m_compositingAncestor = layer;
+
+#ifndef NDEBUG
+ ++childState.m_depth;
+#endif
+
+ // The children of this stacking context don't need to composite, unless there is
+ // a compositing layer among them, so start by assuming false.
+ childState.m_subtreeIsCompositing = false;
+
+ if (layer->isStackingContext()) {
+ ASSERT(!layer->m_zOrderListsDirty);
+
+ if (Vector<RenderLayer*>* negZOrderList = layer->negZOrderList()) {
+ size_t listSize = negZOrderList->size();
+ for (size_t i = 0; i < listSize; ++i) {
+ RenderLayer* curLayer = negZOrderList->at(i);
+ rebuildCompositingLayerTree(curLayer, childState);
+ if (curLayer->isComposited())
+ setCompositingParent(curLayer, childState.m_compositingAncestor);
+ }
+ }
+
+ if (layerBacking && layerBacking->contentsLayer()) {
+ // we only have a contents layer if we have an m_layer
+ layerBacking->contentsLayer()->removeFromParent();
+
+ GraphicsLayer* hostingLayer = layerBacking->clippingLayer() ? layerBacking->clippingLayer() : layerBacking->graphicsLayer();
+ hostingLayer->addChild(layerBacking->contentsLayer());
+ }
+ }
+
+ ASSERT(!layer->m_normalFlowListDirty);
+ if (Vector<RenderLayer*>* normalFlowList = layer->normalFlowList()) {
+ size_t listSize = normalFlowList->size();
+ for (size_t i = 0; i < listSize; ++i) {
+ RenderLayer* curLayer = normalFlowList->at(i);
+ rebuildCompositingLayerTree(curLayer, childState);
+ if (curLayer->isComposited())
+ setCompositingParent(curLayer, childState.m_compositingAncestor);
+ }
+ }
+
+ if (layer->isStackingContext()) {
+ if (Vector<RenderLayer*>* posZOrderList = layer->posZOrderList()) {
+ size_t listSize = posZOrderList->size();
+ for (size_t i = 0; i < listSize; ++i) {
+ RenderLayer* curLayer = posZOrderList->at(i);
+ rebuildCompositingLayerTree(curLayer, childState);
+ if (curLayer->isComposited())
+ setCompositingParent(curLayer, childState.m_compositingAncestor);
+ }
+ }
+ }
+}
+
+
+// Recurs down the RenderLayer tree until its finds the compositing descendants of compositingAncestor and updates their geometry.
+void RenderLayerCompositor::updateCompositingChildrenGeometry(RenderLayer* compositingAncestor, RenderLayer* layer)
+{
+ if (layer != compositingAncestor) {
+ if (RenderLayerBacking* layerBacking = layer->backing()) {
+ layerBacking->setCompositedBounds(calculateCompositedBounds(layer, layer));
+ layerBacking->updateGraphicsLayerGeometry();
+ return;
+ }
+ }
+
+ if (!layer->hasCompositingDescendant())
+ return;
+
+ if (layer->isStackingContext()) {
+ if (Vector<RenderLayer*>* negZOrderList = layer->negZOrderList()) {
+ size_t listSize = negZOrderList->size();
+ for (size_t i = 0; i < listSize; ++i)
+ updateCompositingChildrenGeometry(compositingAncestor, negZOrderList->at(i));
+ }
+ }
+
+ if (Vector<RenderLayer*>* normalFlowList = layer->normalFlowList()) {
+ size_t listSize = normalFlowList->size();
+ for (size_t i = 0; i < listSize; ++i)
+ updateCompositingChildrenGeometry(compositingAncestor, normalFlowList->at(i));
+ }
+
+ if (layer->isStackingContext()) {
+ if (Vector<RenderLayer*>* posZOrderList = layer->posZOrderList()) {
+ size_t listSize = posZOrderList->size();
+ for (size_t i = 0; i < listSize; ++i)
+ updateCompositingChildrenGeometry(compositingAncestor, posZOrderList->at(i));
+ }
+ }
+}
+
+
+void RenderLayerCompositor::repaintCompositedLayersAbsoluteRect(const IntRect& absRect)
+{
+ recursiveRepaintLayerRect(rootRenderLayer(), absRect);
+}
+
+void RenderLayerCompositor::recursiveRepaintLayerRect(RenderLayer* layer, const IntRect& rect)
+{
+ if (layer->isComposited())
+ layer->setBackingNeedsRepaintInRect(rect);
+
+ if (layer->hasCompositingDescendant()) {
+ if (Vector<RenderLayer*>* negZOrderList = layer->negZOrderList()) {
+ size_t listSize = negZOrderList->size();
+ for (size_t i = 0; i < listSize; ++i) {
+ RenderLayer* curLayer = negZOrderList->at(i);
+ int x = 0, y = 0;
+ curLayer->convertToLayerCoords(layer, x, y);
+ IntRect childRect(rect);
+ childRect.move(-x, -y);
+ recursiveRepaintLayerRect(curLayer, childRect);
+ }
+ }
+
+ if (Vector<RenderLayer*>* posZOrderList = layer->posZOrderList()) {
+ size_t listSize = posZOrderList->size();
+ for (size_t i = 0; i < listSize; ++i) {
+ RenderLayer* curLayer = posZOrderList->at(i);
+ int x = 0, y = 0;
+ curLayer->convertToLayerCoords(layer, x, y);
+ IntRect childRect(rect);
+ childRect.move(-x, -y);
+ recursiveRepaintLayerRect(curLayer, childRect);
+ }
+ }
+ }
+ if (Vector<RenderLayer*>* normalFlowList = layer->normalFlowList()) {
+ size_t listSize = normalFlowList->size();
+ for (size_t i = 0; i < listSize; ++i) {
+ RenderLayer* curLayer = normalFlowList->at(i);
+ int x = 0, y = 0;
+ curLayer->convertToLayerCoords(layer, x, y);
+ IntRect childRect(rect);
+ childRect.move(-x, -y);
+ recursiveRepaintLayerRect(curLayer, childRect);
+ }
+ }
+}
+
+RenderLayer* RenderLayerCompositor::rootRenderLayer() const
+{
+ return m_renderView->layer();
+}
+
+GraphicsLayer* RenderLayerCompositor::rootPlatformLayer() const
+{
+ return m_rootPlatformLayer;
+}
+
+void RenderLayerCompositor::didMoveOnscreen()
+{
+ if (!m_rootPlatformLayer)
+ return;
+
+ Frame* frame = m_renderView->frameView()->frame();
+ Page* page = frame ? frame->page() : 0;
+ if (!page)
+ return;
+
+ page->chrome()->client()->attachRootGraphicsLayer(frame, m_rootPlatformLayer);
+ m_rootLayerAttached = true;
+}
+
+void RenderLayerCompositor::willMoveOffscreen()
+{
+ if (!m_rootPlatformLayer || !m_rootLayerAttached)
+ return;
+
+ Frame* frame = m_renderView->frameView()->frame();
+ Page* page = frame ? frame->page() : 0;
+ if (!page)
+ return;
+
+ page->chrome()->client()->attachRootGraphicsLayer(frame, 0);
+ m_rootLayerAttached = false;
+}
+
+void RenderLayerCompositor::updateRootLayerPosition()
+{
+ if (m_rootPlatformLayer)
+ m_rootPlatformLayer->setSize(FloatSize(m_renderView->overflowWidth(), m_renderView->overflowHeight()));
+}
+
+bool RenderLayerCompositor::has3DContent() const
+{
+ return layerHas3DContent(rootRenderLayer());
+}
+
+bool RenderLayerCompositor::needsToBeComposited(const RenderLayer* layer) const
+{
+ if (!m_hasAcceleratedCompositing || !layer->isSelfPaintingLayer())
+ return false;
+
+ return requiresCompositingLayer(layer) || layer->mustOverlayCompositedLayers();
+}
+
+// Note: this specifies whether the RL needs a compositing layer for intrinsic reasons.
+// Use needsToBeComposited() to determine if a RL actually needs a compositing layer.
+// static
+bool RenderLayerCompositor::requiresCompositingLayer(const RenderLayer* layer) const
+{
+ // The root layer always has a compositing layer, but it may not have backing.
+ return (inCompositingMode() && layer->isRootLayer()) ||
+ requiresCompositingForTransform(layer->renderer()) ||
+ requiresCompositingForVideo(layer->renderer()) ||
+ layer->renderer()->style()->backfaceVisibility() == BackfaceVisibilityHidden ||
+ clipsCompositingDescendants(layer) ||
+ requiresCompositingForAnimation(layer->renderer());
+}
+
+// Return true if the given layer has some ancestor in the RenderLayer hierarchy that clips,
+// up to the enclosing compositing ancestor. This is required because compositing layers are parented
+// according to the z-order hierarchy, yet clipping goes down the renderer hierarchy.
+// Thus, a RenderLayer can be clipped by a RenderLayer that is an ancestor in the renderer hierarchy,
+// but a sibling in the z-order hierarchy.
+bool RenderLayerCompositor::clippedByAncestor(RenderLayer* layer) const
+{
+ if (!layer->isComposited() || !layer->parent())
+ return false;
+
+ RenderLayer* compositingAncestor = layer->ancestorCompositingLayer();
+ if (!compositingAncestor)
+ return false;
+
+ // If the compositingAncestor clips, that will be taken care of by clipsCompositingDescendants(),
+ // so we only care about clipping between its first child that is our ancestor (the computeClipRoot),
+ // and layer.
+ RenderLayer* computeClipRoot = 0;
+ RenderLayer* curr = layer;
+ while (curr) {
+ RenderLayer* next = curr->parent();
+ if (next == compositingAncestor) {
+ computeClipRoot = curr;
+ break;
+ }
+ curr = next;
+ }
+
+ if (!computeClipRoot || computeClipRoot == layer)
+ return false;
+
+ ClipRects parentRects;
+ layer->parentClipRects(computeClipRoot, parentRects, true);
+
+ return parentRects.overflowClipRect() != ClipRects::infiniteRect();
+}
+
+// Return true if the given layer is a stacking context and has compositing child
+// layers that it needs to clip. In this case we insert a clipping GraphicsLayer
+// into the hierarchy between this layer and its children in the z-order hierarchy.
+bool RenderLayerCompositor::clipsCompositingDescendants(const RenderLayer* layer) const
+{
+ // FIXME: need to look at hasClip() too eventually
+ return layer->hasCompositingDescendant() &&
+ layer->renderer()->hasOverflowClip();
+}
+
+bool RenderLayerCompositor::requiresCompositingForTransform(RenderObject* renderer) const
+{
+ RenderStyle* style = renderer->style();
+ // Note that we ask the renderer if it has a transform, because the style may have transforms,
+ // but the renderer may be an inline that doesn't suppport them.
+ return renderer->hasTransform() && (style->transform().has3DOperation() || style->transformStyle3D() == TransformStyle3DPreserve3D || style->hasPerspective());
+}
+
+bool RenderLayerCompositor::requiresCompositingForVideo(RenderObject* renderer) const
+{
+#if ENABLE(VIDEO)
+ if (renderer->isVideo()) {
+ RenderVideo* video = static_cast<RenderVideo*>(renderer);
+ return canAccelerateVideoRendering(video);
+ }
+#endif
+ return false;
+}
+
+bool RenderLayerCompositor::requiresCompositingForAnimation(RenderObject* renderer) const
+{
+ if (AnimationController* animController = renderer->animation()) {
+ return (animController->isAnimatingPropertyOnRenderer(renderer, CSSPropertyOpacity) && inCompositingMode())
+ || animController->isAnimatingPropertyOnRenderer(renderer, CSSPropertyWebkitTransform);
+ }
+ return false;
+}
+
+// If an element has negative z-index children, those children render in front of the
+// layer background, so we need an extra 'contents' layer for the foreground of the layer
+// object.
+bool RenderLayerCompositor::needsContentsCompositingLayer(const RenderLayer* layer) const
+{
+ return (layer->m_negZOrderList && layer->m_negZOrderList->size() > 0);
+}
+
+void RenderLayerCompositor::ensureRootPlatformLayer()
+{
+ if (m_rootPlatformLayer)
+ return;
+
+ m_rootPlatformLayer = GraphicsLayer::createGraphicsLayer(0);
+ m_rootPlatformLayer->setSize(FloatSize(m_renderView->overflowWidth(), m_renderView->overflowHeight()));
+ m_rootPlatformLayer->setPosition(FloatPoint(0, 0));
+
+ if (GraphicsLayer::compositingCoordinatesOrientation() == GraphicsLayer::CompositingCoordinatesBottomUp)
+ m_rootPlatformLayer->setChildrenTransform(flipTransform());
+
+ // Need to clip to prevent transformed content showing outside this frame
+ m_rootPlatformLayer->setMasksToBounds(true);
+
+ didMoveOnscreen();
+}
+
+void RenderLayerCompositor::destroyRootPlatformLayer()
+{
+ if (!m_rootPlatformLayer)
+ return;
+
+ willMoveOffscreen();
+ delete m_rootPlatformLayer;
+ m_rootPlatformLayer = 0;
+}
+
+bool RenderLayerCompositor::layerHas3DContent(const RenderLayer* layer) const
+{
+ const RenderStyle* style = layer->renderer()->style();
+
+ if (style &&
+ (style->transformStyle3D() == TransformStyle3DPreserve3D ||
+ style->hasPerspective() ||
+ style->transform().has3DOperation()))
+ return true;
+
+ if (layer->isStackingContext()) {
+ if (Vector<RenderLayer*>* negZOrderList = layer->negZOrderList()) {
+ size_t listSize = negZOrderList->size();
+ for (size_t i = 0; i < listSize; ++i) {
+ RenderLayer* curLayer = negZOrderList->at(i);
+ if (layerHas3DContent(curLayer))
+ return true;
+ }
+ }
+
+ if (Vector<RenderLayer*>* posZOrderList = layer->posZOrderList()) {
+ size_t listSize = posZOrderList->size();
+ for (size_t i = 0; i < listSize; ++i) {
+ RenderLayer* curLayer = posZOrderList->at(i);
+ if (layerHas3DContent(curLayer))
+ return true;
+ }
+ }
+ }
+
+ if (Vector<RenderLayer*>* normalFlowList = layer->normalFlowList()) {
+ size_t listSize = normalFlowList->size();
+ for (size_t i = 0; i < listSize; ++i) {
+ RenderLayer* curLayer = normalFlowList->at(i);
+ if (layerHas3DContent(curLayer))
+ return true;
+ }
+ }
+ return false;
+}
+
+} // namespace WebCore
+
+#endif // USE(ACCELERATED_COMPOSITING)
+
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderLayerCompositor.h b/src/3rdparty/webkit/WebCore/rendering/RenderLayerCompositor.h
new file mode 100644
index 0000000..bcd6a3f
--- /dev/null
+++ b/src/3rdparty/webkit/WebCore/rendering/RenderLayerCompositor.h
@@ -0,0 +1,169 @@
+/*
+ * Copyright (C) 2009 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``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 COMPUTER, INC. OR
+ * 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 RenderLayerCompositor_h
+#define RenderLayerCompositor_h
+
+#include "RenderLayer.h"
+
+namespace WebCore {
+
+#define PROFILE_LAYER_REBUILD 0
+
+class GraphicsLayer;
+#if ENABLE(VIDEO)
+class RenderVideo;
+#endif
+
+// RenderLayerCompositor manages the hierarchy of
+// composited RenderLayers. It determines which RenderLayers
+// become compositing, and creates and maintains a hierarchy of
+// GraphicsLayers based on the RenderLayer painting order.
+//
+// There is one RenderLayerCompositor per RenderView.
+
+class RenderLayerCompositor {
+public:
+
+ RenderLayerCompositor(RenderView*);
+ ~RenderLayerCompositor();
+
+ // Return true if this RenderView is in "compositing mode" (i.e. has one or more
+ // composited RenderLayers)
+ bool inCompositingMode() const { return m_compositing; }
+ // This will make a compositing layer at the root automatically, and hook up to
+ // the native view/window system.
+ void enableCompositingMode(bool enable = true);
+
+ // Returns true if the accelerated compositing is enabled
+ bool hasAcceleratedCompositing() const { return m_hasAcceleratedCompositing; }
+
+ // Copy the acceleratedCompositingEnabledFlag from Settings
+ void cacheAcceleratedCompositingEnabledFlag();
+
+ void setCompositingLayersNeedUpdate(bool needUpdate = true);
+ bool compositingLayersNeedUpdate() const { return m_compositingLayersNeedUpdate; }
+
+ void scheduleViewUpdate();
+
+ // Rebuild the tree of compositing layers
+ void updateCompositingLayers(RenderLayer* updateRoot = 0);
+
+ // Update the compositing state of the given layer. Returns true if that state changed.
+ enum CompositingChangeRepaint { CompositingChangeRepaintNow, CompositingChangeWillRepaintLater };
+ bool updateLayerCompositingState(RenderLayer*, CompositingChangeRepaint = CompositingChangeRepaintNow);
+
+ // Update the geometry for compositing children of compositingAncestor.
+ void updateCompositingChildrenGeometry(RenderLayer* compositingAncestor, RenderLayer* layer);
+
+ // Whether layer's backing needs a graphics layer to do clipping by an ancestor (non-stacking-context parent with overflow).
+ bool clippedByAncestor(RenderLayer*) const;
+ // Whether layer's backing needs a graphics layer to clip z-order children of the given layer.
+ bool clipsCompositingDescendants(const RenderLayer*) const;
+
+ // Whether the given layer needs an extra 'contents' layer.
+ bool needsContentsCompositingLayer(const RenderLayer*) const;
+ // Return the bounding box required for compositing layer and its childern, relative to ancestorLayer.
+ // If layerBoundingBox is not 0, on return it contains the bounding box of this layer only.
+ IntRect calculateCompositedBounds(const RenderLayer* layer, const RenderLayer* ancestorLayer);
+
+ // Repaint the appropriate layers when the given RenderLayer starts or stops being composited.
+ void repaintOnCompositingChange(RenderLayer*);
+
+ // Notify us that a layer has been added or removed
+ void layerWasAdded(RenderLayer* parent, RenderLayer* child);
+ void layerWillBeRemoved(RenderLayer* parent, RenderLayer* child);
+
+ // Get the nearest ancestor layer that has overflow or clip, but is not a stacking context
+ RenderLayer* enclosingNonStackingClippingLayer(const RenderLayer* layer) const;
+
+ // Repaint parts of all composited layers that intersect the given absolute rectangle.
+ void repaintCompositedLayersAbsoluteRect(const IntRect&);
+
+ RenderLayer* rootRenderLayer() const;
+ GraphicsLayer* rootPlatformLayer() const;
+
+ void didMoveOnscreen();
+ void willMoveOffscreen();
+
+ void updateRootLayerPosition();
+
+#if ENABLE(VIDEO)
+ // Use by RenderVideo to ask if it should try to use accelerated compositing.
+ bool canAccelerateVideoRendering(RenderVideo*) const;
+#endif
+
+ // Walk the tree looking for layers with 3d transforms. Useful in case you need
+ // to know if there is non-affine content, e.g. for drawing into an image.
+ bool has3DContent() const;
+
+private:
+ // Whether the given RL needs a compositing layer.
+ bool needsToBeComposited(const RenderLayer*) const;
+ // Whether the layer has an intrinsic need for compositing layer.
+ bool requiresCompositingLayer(const RenderLayer*) const;
+
+ // Make or destroy the backing for this layer; returns true if backing changed.
+ bool updateBacking(RenderLayer*, CompositingChangeRepaint shouldRepaint);
+
+ // Repaint the given rect (which is layer's coords), and regions of child layers that intersect that rect.
+ void recursiveRepaintLayerRect(RenderLayer* layer, const IntRect& rect);
+
+ void computeCompositingRequirements(RenderLayer*, struct CompositingState&);
+ void rebuildCompositingLayerTree(RenderLayer* layer, struct CompositingState&);
+
+ // Hook compositing layers together
+ void setCompositingParent(RenderLayer* childLayer, RenderLayer* parentLayer);
+ void removeCompositedChildren(RenderLayer*);
+
+ void parentInRootLayer(RenderLayer*);
+
+ bool layerHas3DContent(const RenderLayer*) const;
+
+ void ensureRootPlatformLayer();
+ void destroyRootPlatformLayer();
+
+ // Whether a running transition or animation enforces the need for a compositing layer.
+ bool requiresCompositingForAnimation(RenderObject*) const;
+ bool requiresCompositingForTransform(RenderObject*) const;
+ bool requiresCompositingForVideo(RenderObject*) const;
+
+private:
+ RenderView* m_renderView;
+ GraphicsLayer* m_rootPlatformLayer;
+ bool m_compositing;
+ bool m_rootLayerAttached;
+ bool m_compositingLayersNeedUpdate;
+ bool m_hasAcceleratedCompositing;
+
+#if PROFILE_LAYER_REBUILD
+ int m_rootLayerUpdateCount;
+#endif
+};
+
+
+} // namespace WebCore
+
+#endif // RenderLayerCompositor_h
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderLegend.cpp b/src/3rdparty/webkit/WebCore/rendering/RenderLegend.cpp
deleted file mode 100644
index 1fac53f..0000000
--- a/src/3rdparty/webkit/WebCore/rendering/RenderLegend.cpp
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * This file is part of the DOM implementation for KDE.
- *
- * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
- * (C) 1999 Antti Koivisto (koivisto@kde.org)
- * (C) 2000 Dirk Mueller (mueller@kde.org)
- * Copyright (C) 2004, 2005, 2006 Apple Computer, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-
-#include "config.h"
-#include "RenderLegend.h"
-
-namespace WebCore {
-
-RenderLegend::RenderLegend(Node* element)
- : RenderBlock(element)
-{
-}
-
-} // namespace WebCore
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderLegend.h b/src/3rdparty/webkit/WebCore/rendering/RenderLegend.h
deleted file mode 100644
index 649f132..0000000
--- a/src/3rdparty/webkit/WebCore/rendering/RenderLegend.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * This file is part of the DOM implementation for KDE.
- *
- * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
- * (C) 1999 Antti Koivisto (koivisto@kde.org)
- * (C) 2000 Dirk Mueller (mueller@kde.org)
- * Copyright (C) 2004, 2006 Apple Computer, Inc.
- *
- * 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 RenderLegend_h
-#define RenderLegend_h
-
-#include "RenderBlock.h"
-
-namespace WebCore {
-
- class RenderLegend : public RenderBlock {
- public:
- RenderLegend(Node*);
-
- virtual const char* renderName() const { return "RenderLegend"; }
- };
-
-} // namespace WebCore
-
-#endif // RenderLegend_h
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderLineBoxList.cpp b/src/3rdparty/webkit/WebCore/rendering/RenderLineBoxList.cpp
new file mode 100644
index 0000000..00566b8
--- /dev/null
+++ b/src/3rdparty/webkit/WebCore/rendering/RenderLineBoxList.cpp
@@ -0,0 +1,333 @@
+/*
+ * Copyright (C) 2008 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"
+#include "RenderLineBoxList.h"
+
+#include "InlineTextBox.h"
+#include "RenderArena.h"
+#include "RenderInline.h"
+#include "RenderView.h"
+#include "RootInlineBox.h"
+
+using namespace std;
+
+namespace WebCore {
+
+#ifndef NDEBUG
+RenderLineBoxList::~RenderLineBoxList()
+{
+ ASSERT(!m_firstLineBox);
+ ASSERT(!m_lastLineBox);
+}
+#endif
+
+void RenderLineBoxList::appendLineBox(InlineFlowBox* box)
+{
+ checkConsistency();
+
+ if (!m_firstLineBox)
+ m_firstLineBox = m_lastLineBox = box;
+ else {
+ m_lastLineBox->setNextLineBox(box);
+ box->setPreviousLineBox(m_lastLineBox);
+ m_lastLineBox = box;
+ }
+
+ checkConsistency();
+}
+
+void RenderLineBoxList::deleteLineBoxTree(RenderArena* arena)
+{
+ InlineFlowBox* line = m_firstLineBox;
+ InlineFlowBox* nextLine;
+ while (line) {
+ nextLine = line->nextFlowBox();
+ line->deleteLine(arena);
+ line = nextLine;
+ }
+ m_firstLineBox = m_lastLineBox = 0;
+}
+
+void RenderLineBoxList::extractLineBox(InlineFlowBox* box)
+{
+ checkConsistency();
+
+ m_lastLineBox = box->prevFlowBox();
+ if (box == m_firstLineBox)
+ m_firstLineBox = 0;
+ if (box->prevLineBox())
+ box->prevLineBox()->setNextLineBox(0);
+ box->setPreviousLineBox(0);
+ for (InlineRunBox* curr = box; curr; curr = curr->nextLineBox())
+ curr->setExtracted();
+
+ checkConsistency();
+}
+
+void RenderLineBoxList::attachLineBox(InlineFlowBox* box)
+{
+ checkConsistency();
+
+ if (m_lastLineBox) {
+ m_lastLineBox->setNextLineBox(box);
+ box->setPreviousLineBox(m_lastLineBox);
+ } else
+ m_firstLineBox = box;
+ InlineFlowBox* last = box;
+ for (InlineFlowBox* curr = box; curr; curr = curr->nextFlowBox()) {
+ curr->setExtracted(false);
+ last = curr;
+ }
+ m_lastLineBox = last;
+
+ checkConsistency();
+}
+
+void RenderLineBoxList::removeLineBox(InlineFlowBox* box)
+{
+ checkConsistency();
+
+ if (box == m_firstLineBox)
+ m_firstLineBox = box->nextFlowBox();
+ if (box == m_lastLineBox)
+ m_lastLineBox = box->prevFlowBox();
+ if (box->nextLineBox())
+ box->nextLineBox()->setPreviousLineBox(box->prevLineBox());
+ if (box->prevLineBox())
+ box->prevLineBox()->setNextLineBox(box->nextLineBox());
+
+ checkConsistency();
+}
+
+void RenderLineBoxList::deleteLineBoxes(RenderArena* arena)
+{
+ if (m_firstLineBox) {
+ InlineRunBox* next;
+ for (InlineRunBox* curr = m_firstLineBox; curr; curr = next) {
+ next = curr->nextLineBox();
+ curr->destroy(arena);
+ }
+ m_firstLineBox = 0;
+ m_lastLineBox = 0;
+ }
+}
+
+void RenderLineBoxList::dirtyLineBoxes()
+{
+ for (InlineRunBox* curr = firstLineBox(); curr; curr = curr->nextLineBox())
+ curr->dirtyLineBoxes();
+}
+
+void RenderLineBoxList::paint(RenderBoxModelObject* renderer, RenderObject::PaintInfo& paintInfo, int tx, int ty) const
+{
+ // Only paint during the foreground/selection phases.
+ if (paintInfo.phase != PaintPhaseForeground && paintInfo.phase != PaintPhaseSelection && paintInfo.phase != PaintPhaseOutline
+ && paintInfo.phase != PaintPhaseSelfOutline && paintInfo.phase != PaintPhaseChildOutlines && paintInfo.phase != PaintPhaseTextClip
+ && paintInfo.phase != PaintPhaseMask)
+ return;
+
+ ASSERT(renderer->isRenderBlock() || (renderer->isRenderInline() && renderer->hasLayer())); // The only way an inline could paint like this is if it has a layer.
+
+ // If we have no lines then we have no work to do.
+ if (!firstLineBox())
+ return;
+
+ // We can check the first box and last box and avoid painting if we don't
+ // intersect. This is a quick short-circuit that we can take to avoid walking any lines.
+ // FIXME: This check is flawed in the following extremely obscure way:
+ // if some line in the middle has a huge overflow, it might actually extend below the last line.
+ int yPos = firstLineBox()->root()->topOverflow() - renderer->maximalOutlineSize(paintInfo.phase);
+ int h = renderer->maximalOutlineSize(paintInfo.phase) + lastLineBox()->root()->bottomOverflow() - yPos;
+ yPos += ty;
+ if (yPos >= paintInfo.rect.bottom() || yPos + h <= paintInfo.rect.y())
+ return;
+
+ RenderObject::PaintInfo info(paintInfo);
+ ListHashSet<RenderInline*> outlineObjects;
+ info.outlineObjects = &outlineObjects;
+
+ // See if our root lines intersect with the dirty rect. If so, then we paint
+ // them. Note that boxes can easily overlap, so we can't make any assumptions
+ // based off positions of our first line box or our last line box.
+ RenderView* v = renderer->view();
+ bool usePrintRect = !v->printRect().isEmpty();
+ for (InlineFlowBox* curr = firstLineBox(); curr; curr = curr->nextFlowBox()) {
+ if (usePrintRect) {
+ // FIXME: This is a feeble effort to avoid splitting a line across two pages.
+ // It is utterly inadequate, and this should not be done at paint time at all.
+ // The whole way objects break across pages needs to be redone.
+ // Try to avoid splitting a line vertically, but only if it's less than the height
+ // of the entire page.
+ if (curr->root()->bottomOverflow() - curr->root()->topOverflow() <= v->printRect().height()) {
+ if (ty + curr->root()->bottomOverflow() > v->printRect().bottom()) {
+ if (ty + curr->root()->topOverflow() < v->truncatedAt())
+ v->setBestTruncatedAt(ty + curr->root()->topOverflow(), renderer);
+ // If we were able to truncate, don't paint.
+ if (ty + curr->root()->topOverflow() >= v->truncatedAt())
+ break;
+ }
+ }
+ }
+
+ int top = min(curr->root()->topOverflow(), curr->root()->selectionTop()) - renderer->maximalOutlineSize(info.phase);
+ int bottom = curr->root()->bottomOverflow() + renderer->maximalOutlineSize(info.phase);
+ h = bottom - top;
+ yPos = ty + top;
+ if (yPos < info.rect.bottom() && yPos + h > info.rect.y())
+ curr->paint(info, tx, ty);
+ }
+
+ if (info.phase == PaintPhaseOutline || info.phase == PaintPhaseSelfOutline || info.phase == PaintPhaseChildOutlines) {
+ ListHashSet<RenderInline*>::iterator end = info.outlineObjects->end();
+ for (ListHashSet<RenderInline*>::iterator it = info.outlineObjects->begin(); it != end; ++it) {
+ RenderInline* flow = *it;
+ flow->paintOutline(info.context, tx, ty);
+ }
+ info.outlineObjects->clear();
+ }
+}
+
+
+bool RenderLineBoxList::hitTest(RenderBoxModelObject* renderer, const HitTestRequest& request, HitTestResult& result, int x, int y, int tx, int ty, HitTestAction hitTestAction) const
+{
+ if (hitTestAction != HitTestForeground)
+ return false;
+
+ ASSERT(renderer->isRenderBlock() || (renderer->isRenderInline() && renderer->hasLayer())); // The only way an inline could hit test like this is if it has a layer.
+
+ // If we have no lines then we have no work to do.
+ if (!firstLineBox())
+ return false;
+
+ // We can check the first box and last box and avoid hit testing if we don't
+ // contain the point. This is a quick short-circuit that we can take to avoid walking any lines.
+ // FIXME: This check is flawed in the following extremely obscure way:
+ // if some line in the middle has a huge overflow, it might actually extend below the last line.
+ if ((y >= ty + lastLineBox()->root()->bottomOverflow()) || (y < ty + firstLineBox()->root()->topOverflow()))
+ return false;
+
+ // See if our root lines contain the point. If so, then we hit test
+ // them further. Note that boxes can easily overlap, so we can't make any assumptions
+ // based off positions of our first line box or our last line box.
+ for (InlineFlowBox* curr = lastLineBox(); curr; curr = curr->prevFlowBox()) {
+ if (y >= ty + curr->root()->topOverflow() && y < ty + curr->root()->bottomOverflow()) {
+ bool inside = curr->nodeAtPoint(request, result, x, y, tx, ty);
+ if (inside) {
+ renderer->updateHitTestResult(result, IntPoint(x - tx, y - ty));
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+void RenderLineBoxList::dirtyLinesFromChangedChild(RenderObject* container, RenderObject* child)
+{
+ if (!container->parent() || (container->isRenderBlock() && (container->selfNeedsLayout() || !container->isBlockFlow())))
+ return;
+
+ // If we have no first line box, then just bail early.
+ if (!firstLineBox()) {
+ // 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())
+ container->parent()->dirtyLinesFromChangedChild(container);
+ return;
+ }
+
+ // Try to figure out which line box we belong in. First try to find a previous
+ // line box by examining our siblings. If we didn't find a line box, then use our
+ // parent's first line box.
+ RootInlineBox* box = 0;
+ RenderObject* curr = 0;
+ for (curr = child->previousSibling(); curr; curr = curr->previousSibling()) {
+ if (curr->isFloatingOrPositioned())
+ continue;
+
+ if (curr->isReplaced()) {
+ InlineBox* wrapper = toRenderBox(curr)->inlineBoxWrapper();
+ if (wrapper)
+ box = wrapper->root();
+ } else if (curr->isText()) {
+ InlineTextBox* textBox = toRenderText(curr)->lastTextBox();
+ if (textBox)
+ box = textBox->root();
+ } else if (curr->isRenderInline()) {
+ InlineRunBox* runBox = toRenderInline(curr)->lastLineBox();
+ if (runBox)
+ box = runBox->root();
+ }
+
+ if (box)
+ break;
+ }
+ if (!box)
+ box = firstLineBox()->root();
+
+ // If we found a line box, then dirty it.
+ if (box) {
+ RootInlineBox* adjacentBox;
+ box->markDirty();
+
+ // dirty the adjacent lines that might be affected
+ // NOTE: we dirty the previous line because RootInlineBox objects cache
+ // the address of the first object on the next line after a BR, which we may be
+ // invalidating here. For more info, see how RenderBlock::layoutInlineChildren
+ // calls setLineBreakInfo with the result of findNextLineBreak. findNextLineBreak,
+ // despite the name, actually returns the first RenderObject after the BR.
+ // <rdar://problem/3849947> "Typing after pasting line does not appear until after window resize."
+ adjacentBox = box->prevRootBox();
+ if (adjacentBox)
+ adjacentBox->markDirty();
+ if (child->isBR() || (curr && curr->isBR())) {
+ adjacentBox = box->nextRootBox();
+ if (adjacentBox)
+ adjacentBox->markDirty();
+ }
+ }
+}
+
+#ifndef NDEBUG
+
+void RenderLineBoxList::checkConsistency() const
+{
+#ifdef CHECK_CONSISTENCY
+ const InlineFlowBox* prev = 0;
+ for (const InlineFlowBox* child = m_firstLineBox; child != 0; child = child->nextFlowBox()) {
+ ASSERT(child->prevFlowBox() == prev);
+ prev = child;
+ }
+ ASSERT(prev == m_lastLineBox);
+#endif
+}
+
+#endif
+
+}
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderLineBoxList.h b/src/3rdparty/webkit/WebCore/rendering/RenderLineBoxList.h
new file mode 100644
index 0000000..52d7542
--- /dev/null
+++ b/src/3rdparty/webkit/WebCore/rendering/RenderLineBoxList.h
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2009 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 RenderLineBoxList_h
+#define RenderLineBoxList_h
+
+#include "RenderBox.h"
+
+namespace WebCore {
+
+class RenderLineBoxList {
+public:
+ RenderLineBoxList()
+ : m_firstLineBox(0)
+ , m_lastLineBox(0)
+ {
+ }
+
+#ifndef NDEBUG
+ ~RenderLineBoxList();
+#endif
+
+ InlineFlowBox* firstLineBox() const { return m_firstLineBox; }
+ InlineFlowBox* lastLineBox() const { return m_lastLineBox; }
+
+ void checkConsistency() const;
+
+ void appendLineBox(InlineFlowBox*);
+
+ void deleteLineBoxTree(RenderArena*);
+ void deleteLineBoxes(RenderArena*);
+
+ void extractLineBox(InlineFlowBox*);
+ void attachLineBox(InlineFlowBox*);
+ void removeLineBox(InlineFlowBox*);
+
+ void dirtyLineBoxes();
+ void dirtyLinesFromChangedChild(RenderObject* parent, RenderObject* child);
+
+ void paint(RenderBoxModelObject*, RenderObject::PaintInfo&, int x, int y) const;
+ bool hitTest(RenderBoxModelObject*, const HitTestRequest&, HitTestResult&, int x, int y, int tx, int ty, HitTestAction) const;
+
+private:
+ // For block flows, each box represents the root inline box for a line in the
+ // paragraph.
+ // For inline flows, each box represents a portion of that inline.
+ InlineFlowBox* m_firstLineBox;
+ InlineFlowBox* m_lastLineBox;
+};
+
+
+#ifdef NDEBUG
+inline void RenderLineBoxList::checkConsistency() const
+{
+}
+#endif
+
+} // namespace WebCore
+
+#endif // RenderFlow_h
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderListBox.cpp b/src/3rdparty/webkit/WebCore/rendering/RenderListBox.cpp
index 35b9451..83c569e 100644
--- a/src/3rdparty/webkit/WebCore/rendering/RenderListBox.cpp
+++ b/src/3rdparty/webkit/WebCore/rendering/RenderListBox.cpp
@@ -2,6 +2,7 @@
* This file is part of the select element renderer in WebCore.
*
* Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -41,15 +42,15 @@
#include "FrameView.h"
#include "GraphicsContext.h"
#include "HTMLNames.h"
-#include "HTMLOptGroupElement.h"
-#include "HTMLOptionElement.h"
-#include "HTMLSelectElement.h"
#include "HitTestResult.h"
+#include "OptionGroupElement.h"
+#include "OptionElement.h"
#include "Page.h"
#include "RenderScrollbar.h"
#include "RenderTheme.h"
#include "RenderView.h"
#include "Scrollbar.h"
+#include "SelectElement.h"
#include "SelectionController.h"
#include "NodeRenderStyle.h"
#include <math.h>
@@ -71,7 +72,7 @@ const int maxDefaultSize = 10;
// widget, but I'm not sure this is right for the new control.
const int baselineAdjustment = 7;
-RenderListBox::RenderListBox(HTMLSelectElement* element)
+RenderListBox::RenderListBox(Element* element)
: RenderBlock(element)
, m_optionsChanged(true)
, m_scrollToRevealSelectionAfterLayout(false)
@@ -86,7 +87,7 @@ RenderListBox::~RenderListBox()
setHasVerticalScrollbar(false);
}
-void RenderListBox::styleDidChange(RenderStyle::Diff diff, const RenderStyle* oldStyle)
+void RenderListBox::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
{
RenderBlock::styleDidChange(diff, oldStyle);
setReplaced(isInline());
@@ -95,18 +96,18 @@ void RenderListBox::styleDidChange(RenderStyle::Diff diff, const RenderStyle* ol
void RenderListBox::updateFromElement()
{
if (m_optionsChanged) {
- const Vector<HTMLElement*>& listItems = static_cast<HTMLSelectElement*>(node())->listItems();
+ const Vector<Element*>& listItems = toSelectElement(static_cast<Element*>(node()))->listItems();
int size = numItems();
float width = 0;
for (int i = 0; i < size; ++i) {
- HTMLElement* element = listItems[i];
+ Element* element = listItems[i];
String text;
Font itemFont = style()->font();
- if (element->hasTagName(optionTag))
- text = static_cast<HTMLOptionElement*>(element)->optionText();
- else if (element->hasTagName(optgroupTag)) {
- text = static_cast<HTMLOptGroupElement*>(element)->groupLabelText();
+ if (OptionElement* optionElement = toOptionElement(element))
+ text = optionElement->textIndentedToRespectGroupLabel();
+ else if (OptionGroupElement* optionGroupElement = toOptionGroupElement(element)) {
+ text = optionGroupElement->groupLabelText();
FontDescription d = itemFont.fontDescription();
d.setWeight(d.bolderWeight());
itemFont = Font(d, itemFont.letterSpacing(), itemFont.wordSpacing());
@@ -150,7 +151,7 @@ void RenderListBox::layout()
void RenderListBox::scrollToRevealSelection()
{
- HTMLSelectElement* select = static_cast<HTMLSelectElement*>(node());
+ SelectElement* select = toSelectElement(static_cast<Element*>(node()));
m_scrollToRevealSelectionAfterLayout = false;
@@ -196,7 +197,7 @@ void RenderListBox::calcPrefWidths()
int RenderListBox::size() const
{
- int specifiedSize = static_cast<HTMLSelectElement*>(node())->size();
+ int specifiedSize = toSelectElement(static_cast<Element*>(node()))->size();
if (specifiedSize > 1)
return max(minSize, specifiedSize);
return min(max(minSize, numItems()), maxDefaultSize);
@@ -210,7 +211,7 @@ int RenderListBox::numVisibleItems() const
int RenderListBox::numItems() const
{
- return static_cast<HTMLSelectElement*>(node())->listItems().size();
+ return toSelectElement(static_cast<Element*>(node()))->listItems().size();
}
int RenderListBox::listHeight() const
@@ -223,7 +224,7 @@ void RenderListBox::calcHeight()
int toAdd = paddingTop() + paddingBottom() + borderTop() + borderBottom();
int itemHeight = RenderListBox::itemHeight();
- m_height = itemHeight * size() - rowSpacing + toAdd;
+ setHeight(itemHeight * size() - rowSpacing + toAdd);
RenderBlock::calcHeight();
@@ -292,16 +293,17 @@ void RenderListBox::paintScrollbar(PaintInfo& paintInfo, int tx, int ty)
void RenderListBox::paintItemForeground(PaintInfo& paintInfo, int tx, int ty, int listIndex)
{
- HTMLSelectElement* select = static_cast<HTMLSelectElement*>(node());
- const Vector<HTMLElement*>& listItems = select->listItems();
- HTMLElement* element = listItems[listIndex];
+ SelectElement* select = toSelectElement(static_cast<Element*>(node()));
+ const Vector<Element*>& listItems = select->listItems();
+ Element* element = listItems[listIndex];
+ OptionElement* optionElement = toOptionElement(element);
String itemText;
- if (element->hasTagName(optionTag))
- itemText = static_cast<HTMLOptionElement*>(element)->optionText();
- else if (element->hasTagName(optgroupTag))
- itemText = static_cast<HTMLOptGroupElement*>(element)->groupLabelText();
-
+ if (optionElement)
+ itemText = optionElement->textIndentedToRespectGroupLabel();
+ else if (OptionGroupElement* optionGroupElement = toOptionGroupElement(element))
+ itemText = optionGroupElement->groupLabelText();
+
// Determine where the item text should be placed
IntRect r = itemBoundingBoxRect(tx, ty, listIndex);
r.move(optionsSpacingHorizontal, style()->font().ascent());
@@ -311,7 +313,7 @@ void RenderListBox::paintItemForeground(PaintInfo& paintInfo, int tx, int ty, in
itemStyle = style();
Color textColor = element->renderStyle() ? element->renderStyle()->color() : style()->color();
- if (element->hasTagName(optionTag) && static_cast<HTMLOptionElement*>(element)->selected()) {
+ if (optionElement && optionElement->selected()) {
if (document()->frame()->selection()->isFocusedAndActive() && document()->focusedNode() == node())
textColor = theme()->activeListBoxSelectionForegroundColor();
// Honor the foreground color for disabled items
@@ -322,31 +324,31 @@ void RenderListBox::paintItemForeground(PaintInfo& paintInfo, int tx, int ty, in
paintInfo.context->setFillColor(textColor);
Font itemFont = style()->font();
- if (element->hasTagName(optgroupTag)) {
+ if (isOptionGroupElement(element)) {
FontDescription d = itemFont.fontDescription();
d.setWeight(d.bolderWeight());
itemFont = Font(d, itemFont.letterSpacing(), itemFont.wordSpacing());
itemFont.update(document()->styleSelector()->fontSelector());
}
- paintInfo.context->setFont(itemFont);
-
+
unsigned length = itemText.length();
const UChar* string = itemText.characters();
TextRun textRun(string, length, 0, 0, 0, itemStyle->direction() == RTL, itemStyle->unicodeBidi() == Override, false, false);
// Draw the item text
if (itemStyle->visibility() != HIDDEN)
- paintInfo.context->drawBidiText(textRun, r.location());
+ paintInfo.context->drawBidiText(itemFont, textRun, r.location());
}
void RenderListBox::paintItemBackground(PaintInfo& paintInfo, int tx, int ty, int listIndex)
{
- HTMLSelectElement* select = static_cast<HTMLSelectElement*>(node());
- const Vector<HTMLElement*>& listItems = select->listItems();
- HTMLElement* element = listItems[listIndex];
+ SelectElement* select = toSelectElement(static_cast<Element*>(node()));
+ const Vector<Element*>& listItems = select->listItems();
+ Element* element = listItems[listIndex];
+ OptionElement* optionElement = toOptionElement(element);
Color backColor;
- if (element->hasTagName(optionTag) && static_cast<HTMLOptionElement*>(element)->selected()) {
+ if (optionElement && optionElement->selected()) {
if (document()->frame()->selection()->isFocusedAndActive() && document()->focusedNode() == node())
backColor = theme()->activeListBoxSelectionBackgroundColor();
else
@@ -368,9 +370,9 @@ bool RenderListBox::isPointInOverflowControl(HitTestResult& result, int _x, int
return false;
IntRect vertRect(_tx + width() - borderRight() - m_vBar->width(),
- _ty + borderTop() - borderTopExtra(),
- m_vBar->width(),
- height() + borderTopExtra() + borderBottomExtra() - borderTop() - borderBottom());
+ _ty,
+ m_vBar->width(),
+ height() - borderTop() - borderBottom());
if (vertRect.contains(_x, _y)) {
result.setScrollbar(m_vBar.get());
@@ -436,7 +438,7 @@ void RenderListBox::panScroll(const IntPoint& panStartMousePosition)
return;
m_inAutoscroll = true;
- HTMLSelectElement* select = static_cast<HTMLSelectElement*>(node());
+ SelectElement* select = toSelectElement(static_cast<Element*>(node()));
select->updateListBoxSelection(!select->multiple());
m_inAutoscroll = false;
}
@@ -466,7 +468,7 @@ void RenderListBox::autoscroll()
int endIndex = scrollToward(pos);
if (endIndex >= 0) {
- HTMLSelectElement* select = static_cast<HTMLSelectElement*>(node());
+ SelectElement* select = toSelectElement(static_cast<Element*>(node()));
m_inAutoscroll = true;
if (!select->multiple())
@@ -480,7 +482,7 @@ void RenderListBox::autoscroll()
void RenderListBox::stopAutoscroll()
{
- static_cast<HTMLSelectElement*>(node())->listBoxOnChange();
+ toSelectElement(static_cast<Element*>(node()))->listBoxOnChange();
}
bool RenderListBox::scrollToRevealElementAtListIndex(int index)
@@ -513,9 +515,10 @@ bool RenderListBox::scroll(ScrollDirection direction, ScrollGranularity granular
void RenderListBox::valueChanged(unsigned listIndex)
{
- HTMLSelectElement* select = static_cast<HTMLSelectElement*>(node());
+ Element* element = static_cast<Element*>(node());
+ SelectElement* select = toSelectElement(element);
select->setSelectedIndex(select->listToOptionIndex(listIndex));
- select->onChange();
+ element->dispatchFormControlChangeEvent();
}
void RenderListBox::valueChanged(Scrollbar*)
@@ -525,7 +528,7 @@ void RenderListBox::valueChanged(Scrollbar*)
m_indexOffset = newOffset;
repaint();
// Fire the scroll DOM event.
- EventTargetNodeCast(node())->dispatchEventForType(eventNames().scrollEvent, false, false);
+ node()->dispatchEvent(eventNames().scrollEvent, false, false);
}
}
@@ -577,9 +580,32 @@ void RenderListBox::setScrollTop(int newTop)
m_vBar->setValue(index);
}
+bool RenderListBox::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, int x, int y, int tx, int ty, HitTestAction hitTestAction)
+{
+ if (!RenderBlock::nodeAtPoint(request, result, x, y, tx, ty, hitTestAction))
+ return false;
+ const Vector<Element*>& listItems = toSelectElement(static_cast<Element*>(node()))->listItems();
+ int size = numItems();
+ tx += this->x();
+ ty += this->y();
+ for (int i = 0; i < size; ++i) {
+ if (itemBoundingBoxRect(tx, ty, i).contains(x, y)) {
+ if (Element* node = listItems[i]) {
+ result.setInnerNode(node);
+ if (!result.innerNonSharedNode())
+ result.setInnerNonSharedNode(node);
+ result.setLocalPoint(IntPoint(x - tx, y - ty));
+ break;
+ }
+ }
+ }
+
+ return true;
+}
+
IntRect RenderListBox::controlClipRect(int tx, int ty) const
{
- IntRect clipRect = contentBox();
+ IntRect clipRect = contentBoxRect();
clipRect.move(tx, ty);
return clipRect;
}
@@ -597,21 +623,14 @@ void RenderListBox::invalidateScrollbarRect(Scrollbar* scrollbar, const IntRect&
repaintRectangle(scrollRect);
}
-bool RenderListBox::isScrollable() const
-{
- if (numVisibleItems() < numItems())
- return true;
- return RenderObject::isScrollable();
-}
-
PassRefPtr<Scrollbar> RenderListBox::createScrollbar()
{
RefPtr<Scrollbar> widget;
- bool hasCustomScrollbarStyle = style()->hasPseudoStyle(RenderStyle::SCROLLBAR);
+ bool hasCustomScrollbarStyle = style()->hasPseudoStyle(SCROLLBAR);
if (hasCustomScrollbarStyle)
widget = RenderScrollbar::createCustomScrollbar(this, VerticalScrollbar, this);
else
- widget = Scrollbar::createNativeScrollbar(this, VerticalScrollbar, SmallScrollbar);
+ widget = Scrollbar::createNativeScrollbar(this, VerticalScrollbar, theme()->scrollbarControlSizeForPart(ListboxPart));
document()->view()->addChild(widget.get());
return widget.release();
}
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderListBox.h b/src/3rdparty/webkit/WebCore/rendering/RenderListBox.h
index ccc6847..b8c0540 100644
--- a/src/3rdparty/webkit/WebCore/rendering/RenderListBox.h
+++ b/src/3rdparty/webkit/WebCore/rendering/RenderListBox.h
@@ -36,11 +36,9 @@
namespace WebCore {
-class HTMLSelectElement;
-
class RenderListBox : public RenderBlock, private ScrollbarClient {
public:
- RenderListBox(HTMLSelectElement*);
+ RenderListBox(Element*);
~RenderListBox();
virtual const char* renderName() const { return "RenderListBox"; }
@@ -58,7 +56,6 @@ public:
virtual bool isPointInOverflowControl(HitTestResult&, int x, int y, int tx, int ty);
virtual bool scroll(ScrollDirection, ScrollGranularity, float multiplier = 1.0f);
- virtual bool isScrollable() const;
virtual void calcPrefWidths();
virtual int baselinePosition(bool firstLine, bool isRootLineBox) const;
@@ -93,8 +90,10 @@ public:
virtual void setScrollLeft(int);
virtual void setScrollTop(int);
+ virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, int x, int y, int tx, int ty, HitTestAction);
+
protected:
- virtual void styleDidChange(RenderStyle::Diff, const RenderStyle* oldStyle);
+ virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
private:
// ScrollbarClient interface.
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderListItem.cpp b/src/3rdparty/webkit/WebCore/rendering/RenderListItem.cpp
index f88f131..fb965d2 100644
--- a/src/3rdparty/webkit/WebCore/rendering/RenderListItem.cpp
+++ b/src/3rdparty/webkit/WebCore/rendering/RenderListItem.cpp
@@ -49,7 +49,7 @@ RenderListItem::RenderListItem(Node* node)
setInline(false);
}
-void RenderListItem::styleDidChange(RenderStyle::Diff diff, const RenderStyle* oldStyle)
+void RenderListItem::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
{
RenderBlock::styleDidChange(diff, oldStyle);
@@ -144,7 +144,7 @@ static RenderObject* getParentOfFirstLineBox(RenderBlock* curr, RenderObject* ma
if (currChild == marker)
continue;
- if (currChild->isInline() && (!currChild->isInlineFlow() || curr->generatesLineBoxesForInlineChild(currChild)))
+ if (currChild->isInline() && (!currChild->isRenderInline() || curr->generatesLineBoxesForInlineChild(currChild)))
return curr;
if (currChild->isFloating() || currChild->isPositioned())
@@ -153,11 +153,11 @@ static RenderObject* getParentOfFirstLineBox(RenderBlock* curr, RenderObject* ma
if (currChild->isTable() || !currChild->isRenderBlock())
break;
- if (curr->isListItem() && currChild->style()->htmlHacks() && currChild->element() &&
- (currChild->element()->hasTagName(ulTag)|| currChild->element()->hasTagName(olTag)))
+ if (curr->isListItem() && currChild->style()->htmlHacks() && currChild->node() &&
+ (currChild->node()->hasTagName(ulTag)|| currChild->node()->hasTagName(olTag)))
break;
- RenderObject* lineBox = getParentOfFirstLineBox(static_cast<RenderBlock*>(currChild), marker);
+ RenderObject* lineBox = getParentOfFirstLineBox(toRenderBlock(currChild), marker);
if (lineBox)
return lineBox;
}
@@ -235,12 +235,12 @@ void RenderListItem::layout()
void RenderListItem::positionListMarker()
{
if (m_marker && !m_marker->isInside() && m_marker->inlineBoxWrapper()) {
- int markerOldX = m_marker->xPos();
+ int markerOldX = m_marker->x();
int yOffset = 0;
int xOffset = 0;
- for (RenderObject* o = m_marker->parent(); o != this; o = o->parent()) {
- yOffset += o->yPos();
- xOffset += o->xPos();
+ for (RenderBox* o = m_marker->parentBox(); o != this; o = o->parentBox()) {
+ yOffset += o->y();
+ xOffset += o->x();
}
bool adjustOverflow = false;
@@ -248,7 +248,7 @@ void RenderListItem::positionListMarker()
RootInlineBox* root = m_marker->inlineBoxWrapper()->root();
if (style()->direction() == LTR) {
- int leftLineOffset = leftRelOffset(yOffset, leftOffset(yOffset));
+ int leftLineOffset = leftRelOffset(yOffset, leftOffset(yOffset, false), false);
markerXPos = leftLineOffset - xOffset - paddingLeft() - borderLeft() + m_marker->marginLeft();
m_marker->inlineBoxWrapper()->adjustPosition(markerXPos - markerOldX, 0);
if (markerXPos < root->leftOverflow()) {
@@ -256,7 +256,7 @@ void RenderListItem::positionListMarker()
adjustOverflow = true;
}
} else {
- int rightLineOffset = rightRelOffset(yOffset, rightOffset(yOffset));
+ int rightLineOffset = rightRelOffset(yOffset, rightOffset(yOffset, false), false);
markerXPos = rightLineOffset - xOffset + paddingRight() + borderRight() + m_marker->marginLeft();
m_marker->inlineBoxWrapper()->adjustPosition(markerXPos - markerOldX, 0);
if (markerXPos + m_marker->width() > root->rightOverflow()) {
@@ -267,12 +267,12 @@ void RenderListItem::positionListMarker()
if (adjustOverflow) {
IntRect markerRect(markerXPos + xOffset, yOffset, m_marker->width(), m_marker->height());
- RenderObject* o = m_marker;
+ RenderBox* o = m_marker;
do {
- o = o->parent();
+ o = o->parentBox();
if (o->isRenderBlock())
- static_cast<RenderBlock*>(o)->addVisualOverflow(markerRect);
- markerRect.move(-o->xPos(), -o->yPos());
+ toRenderBlock(o)->addVisualOverflow(markerRect);
+ markerRect.move(-o->x(), -o->y());
} while (o != this);
}
}
@@ -280,7 +280,7 @@ void RenderListItem::positionListMarker()
void RenderListItem::paint(PaintInfo& paintInfo, int tx, int ty)
{
- if (!m_height)
+ if (!height())
return;
RenderBlock::paint(paintInfo, tx, ty);
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderListItem.h b/src/3rdparty/webkit/WebCore/rendering/RenderListItem.h
index d4dd675..91844f7 100644
--- a/src/3rdparty/webkit/WebCore/rendering/RenderListItem.h
+++ b/src/3rdparty/webkit/WebCore/rendering/RenderListItem.h
@@ -61,7 +61,7 @@ public:
const String& markerText() const;
protected:
- virtual void styleDidChange(RenderStyle::Diff, const RenderStyle* oldStyle);
+ virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
private:
void updateMarkerLocation();
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderListMarker.cpp b/src/3rdparty/webkit/WebCore/rendering/RenderListMarker.cpp
index 4209906..9627711 100644
--- a/src/3rdparty/webkit/WebCore/rendering/RenderListMarker.cpp
+++ b/src/3rdparty/webkit/WebCore/rendering/RenderListMarker.cpp
@@ -28,7 +28,6 @@
#include "CharacterNames.h"
#include "Document.h"
#include "GraphicsContext.h"
-#include "ListMarkerBox.h"
#include "RenderLayer.h"
#include "RenderListItem.h"
#include "RenderView.h"
@@ -159,7 +158,7 @@ static int toArmenianUnder10000(int number, bool upper, bool addCircumflex, UCha
int lowerOffset = upper ? 0 : 0x0030;
- if (int thousands = number / 1000)
+ if (int thousands = number / 1000) {
if (thousands == 7) {
letters[length++] = 0x0548 + lowerOffset;
letters[length++] = 0x0552 + lowerOffset;
@@ -170,6 +169,7 @@ static int toArmenianUnder10000(int number, bool upper, bool addCircumflex, UCha
if (addCircumflex)
letters[length++] = 0x0302;
}
+ }
if (int hundreds = (number / 100) % 10) {
letters[length++] = (0x0543 - 1 + lowerOffset) + hundreds;
@@ -472,7 +472,6 @@ String listMarkerText(EListStyleType type, int value)
RenderListMarker::RenderListMarker(RenderListItem* item)
: RenderBox(item->document())
, m_listItem(item)
- , m_selectionState(SelectionNone)
{
// init RenderObject attributes
setInline(true); // our object is Inline
@@ -485,7 +484,7 @@ RenderListMarker::~RenderListMarker()
m_image->removeClient(this);
}
-void RenderListMarker::styleWillChange(RenderStyle::Diff diff, const RenderStyle* newStyle)
+void RenderListMarker::styleWillChange(StyleDifference diff, const RenderStyle* newStyle)
{
if (style() && (newStyle->listStylePosition() != style()->listStylePosition() || newStyle->listStyleType() != style()->listStyleType()))
setNeedsLayoutAndPrefWidthsRecalc();
@@ -493,7 +492,7 @@ void RenderListMarker::styleWillChange(RenderStyle::Diff diff, const RenderStyle
RenderBox::styleWillChange(diff, newStyle);
}
-void RenderListMarker::styleDidChange(RenderStyle::Diff diff, const RenderStyle* oldStyle)
+void RenderListMarker::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
{
RenderBox::styleDidChange(diff, oldStyle);
@@ -506,12 +505,11 @@ void RenderListMarker::styleDidChange(RenderStyle::Diff diff, const RenderStyle*
}
}
-InlineBox* RenderListMarker::createInlineBox(bool, bool isRootLineBox, bool)
+InlineBox* RenderListMarker::createInlineBox()
{
- ASSERT(!isRootLineBox);
- ListMarkerBox* box = new (renderArena()) ListMarkerBox(this);
- m_inlineBoxWrapper = box;
- return box;
+ InlineBox* result = RenderBox::createInlineBox();
+ result->setIsText(isText());
+ return result;
}
bool RenderListMarker::isImage() const
@@ -530,7 +528,7 @@ void RenderListMarker::paint(PaintInfo& paintInfo, int tx, int ty)
IntRect marker = getRelativeMarkerRect();
marker.move(tx, ty);
- IntRect box(tx + m_x, ty + m_y, m_width, m_height);
+ IntRect box(tx + x(), ty + y(), width(), height());
if (box.y() > paintInfo.rect.bottom() || box.y() + box.height() < paintInfo.rect.y())
return;
@@ -539,7 +537,6 @@ void RenderListMarker::paint(PaintInfo& paintInfo, int tx, int ty)
paintBoxDecorations(paintInfo, box.x(), box.y());
GraphicsContext* context = paintInfo.context;
- context->setFont(style()->font());
if (isImage()) {
#if PLATFORM(MAC)
@@ -547,8 +544,10 @@ void RenderListMarker::paint(PaintInfo& paintInfo, int tx, int ty)
paintCustomHighlight(tx, ty, style()->highlight(), true);
#endif
context->drawImage(m_image->image(this, marker.size()), marker.location());
- if (selectionState() != SelectionNone)
+ if (selectionState() != SelectionNone) {
+ // FIXME: selectionRect() is in absolute, not painting coordinates.
context->fillRect(selectionRect(), selectionBackgroundColor());
+ }
return;
}
@@ -558,8 +557,10 @@ void RenderListMarker::paint(PaintInfo& paintInfo, int tx, int ty)
paintCustomHighlight(tx, ty, style()->highlight(), true);
#endif
- if (selectionState() != SelectionNone)
+ if (selectionState() != SelectionNone) {
+ // FIXME: selectionRect() is in absolute, not painting coordinates.
context->fillRect(selectionRect(), selectionBackgroundColor());
+ }
const Color color(style()->color());
context->setStrokeColor(color);
@@ -619,15 +620,15 @@ void RenderListMarker::paint(PaintInfo& paintInfo, int tx, int ty)
const Font& font = style()->font();
if (style()->direction() == LTR) {
int width = font.width(textRun);
- context->drawText(textRun, marker.location());
+ context->drawText(style()->font(), textRun, marker.location());
const UChar periodSpace[2] = { '.', ' ' };
- context->drawText(TextRun(periodSpace, 2), marker.location() + IntSize(width, 0));
+ context->drawText(style()->font(), TextRun(periodSpace, 2), marker.location() + IntSize(width, 0));
} else {
const UChar spacePeriod[2] = { ' ', '.' };
TextRun spacePeriodRun(spacePeriod, 2);
int width = font.width(spacePeriodRun);
- context->drawText(spacePeriodRun, marker.location());
- context->drawText(textRun, marker.location() + IntSize(width, 0));
+ context->drawText(style()->font(), spacePeriodRun, marker.location());
+ context->drawText(style()->font(), textRun, marker.location() + IntSize(width, 0));
}
}
@@ -637,11 +638,11 @@ void RenderListMarker::layout()
ASSERT(!prefWidthsDirty());
if (isImage()) {
- m_width = m_image->imageSize(this, style()->effectiveZoom()).width();
- m_height = m_image->imageSize(this, style()->effectiveZoom()).height();
+ setWidth(m_image->imageSize(this, style()->effectiveZoom()).width());
+ setHeight(m_image->imageSize(this, style()->effectiveZoom()).height());
} else {
- m_width = minPrefWidth();
- m_height = style()->font().height();
+ setWidth(minPrefWidth());
+ setHeight(style()->font().height());
}
m_marginLeft = m_marginRight = 0;
@@ -662,7 +663,7 @@ void RenderListMarker::imageChanged(WrappedImagePtr o, const IntRect*)
if (o != m_image->data())
return;
- if (m_width != m_image->imageSize(this, style()->effectiveZoom()).width() || m_height != m_image->imageSize(this, style()->effectiveZoom()).height() || m_image->errorOccurred())
+ if (width() != m_image->imageSize(this, style()->effectiveZoom()).width() || height() != m_image->imageSize(this, style()->effectiveZoom()).height() || m_image->errorOccurred())
setNeedsLayoutAndPrefWidthsRecalc();
else
repaint();
@@ -830,7 +831,7 @@ bool RenderListMarker::isInside() const
IntRect RenderListMarker::getRelativeMarkerRect()
{
if (isImage())
- return IntRect(m_x, m_y, m_image->imageSize(this, style()->effectiveZoom()).width(), m_image->imageSize(this, style()->effectiveZoom()).height());
+ return IntRect(x(), y(), m_image->imageSize(this, style()->effectiveZoom()).width(), m_image->imageSize(this, style()->effectiveZoom()).height());
switch (style()->listStyleType()) {
case DISC:
@@ -840,7 +841,7 @@ IntRect RenderListMarker::getRelativeMarkerRect()
const Font& font = style()->font();
int ascent = font.ascent();
int bulletWidth = (ascent * 2 / 3 + 1) / 2;
- return IntRect(m_x + 1, m_y + 3 * (ascent - ascent * 2 / 3) / 2, bulletWidth, bulletWidth);
+ return IntRect(x() + 1, y() + 3 * (ascent - ascent * 2 / 3) / 2, bulletWidth, bulletWidth);
}
case LNONE:
return IntRect();
@@ -867,7 +868,7 @@ IntRect RenderListMarker::getRelativeMarkerRect()
int itemWidth = font.width(m_text);
const UChar periodSpace[2] = { '.', ' ' };
int periodSpaceWidth = font.width(TextRun(periodSpace, 2));
- return IntRect(m_x, m_y + font.ascent(), itemWidth + periodSpaceWidth, font.height());
+ return IntRect(x(), y() + font.ascent(), itemWidth + periodSpaceWidth, font.height());
}
return IntRect();
@@ -875,14 +876,14 @@ IntRect RenderListMarker::getRelativeMarkerRect()
void RenderListMarker::setSelectionState(SelectionState state)
{
- m_selectionState = state;
+ RenderBox::setSelectionState(state);
if (InlineBox* box = inlineBoxWrapper())
if (RootInlineBox* root = box->root())
root->setHasSelectedChildren(state != SelectionNone);
containingBlock()->setSelectionState(state);
}
-IntRect RenderListMarker::selectionRect(bool clipToVisibleContent)
+IntRect RenderListMarker::selectionRectForRepaint(RenderBoxModelObject* repaintContainer, bool clipToVisibleContent)
{
ASSERT(!needsLayout());
@@ -890,14 +891,12 @@ IntRect RenderListMarker::selectionRect(bool clipToVisibleContent)
return IntRect();
RootInlineBox* root = inlineBoxWrapper()->root();
- IntRect rect(0, root->selectionTop() - yPos(), width(), root->selectionHeight());
+ IntRect rect(0, root->selectionTop() - y(), width(), root->selectionHeight());
if (clipToVisibleContent)
- computeAbsoluteRepaintRect(rect);
- else {
- FloatPoint absPos = localToAbsolute();
- rect.move(absPos.x(), absPos.y());
- }
+ computeRectForRepaint(repaintContainer, rect);
+ else
+ rect = localToContainerQuad(FloatRect(rect), repaintContainer).enclosingBoundingBox();
return rect;
}
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderListMarker.h b/src/3rdparty/webkit/WebCore/rendering/RenderListMarker.h
index 738427c..57580a8 100644
--- a/src/3rdparty/webkit/WebCore/rendering/RenderListMarker.h
+++ b/src/3rdparty/webkit/WebCore/rendering/RenderListMarker.h
@@ -49,7 +49,7 @@ public:
virtual void imageChanged(WrappedImagePtr, const IntRect* = 0);
- virtual InlineBox* createInlineBox(bool, bool, bool);
+ virtual InlineBox* createInlineBox();
virtual int lineHeight(bool firstLine, bool isRootLineBox = false) const;
virtual int baselinePosition(bool firstLine, bool isRootLineBox = false) const;
@@ -60,16 +60,15 @@ public:
bool isInside() const;
- virtual SelectionState selectionState() const { return m_selectionState; }
virtual void setSelectionState(SelectionState);
- virtual IntRect selectionRect(bool clipToVisibleContent = true);
+ virtual IntRect selectionRectForRepaint(RenderBoxModelObject* repaintContainer, bool clipToVisibleContent = true);
virtual bool canBeSelectionLeaf() const { return true; }
void updateMargins();
protected:
- virtual void styleWillChange(RenderStyle::Diff, const RenderStyle* newStyle);
- virtual void styleDidChange(RenderStyle::Diff, const RenderStyle* oldStyle);
+ virtual void styleWillChange(StyleDifference, const RenderStyle* newStyle);
+ virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
private:
IntRect getRelativeMarkerRect();
@@ -77,7 +76,6 @@ private:
String m_text;
RefPtr<StyleImage> m_image;
RenderListItem* m_listItem;
- SelectionState m_selectionState;
};
} // namespace WebCore
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderMarquee.cpp b/src/3rdparty/webkit/WebCore/rendering/RenderMarquee.cpp
index 96d26ea..48659f7 100644
--- a/src/3rdparty/webkit/WebCore/rendering/RenderMarquee.cpp
+++ b/src/3rdparty/webkit/WebCore/rendering/RenderMarquee.cpp
@@ -68,9 +68,9 @@ RenderMarquee::RenderMarquee(RenderLayer* l)
int RenderMarquee::marqueeSpeed() const
{
int result = m_layer->renderer()->style()->marqueeSpeed();
- Node* elt = m_layer->renderer()->element();
- if (elt && elt->hasTagName(marqueeTag)) {
- HTMLMarqueeElement* marqueeElt = static_cast<HTMLMarqueeElement*>(elt);
+ Node* n = m_layer->renderer()->node();
+ if (n && n->hasTagName(marqueeTag)) {
+ HTMLMarqueeElement* marqueeElt = static_cast<HTMLMarqueeElement*>(n);
result = max(result, marqueeElt->minimumDelay());
}
return result;
@@ -105,17 +105,18 @@ bool RenderMarquee::isHorizontal() const
int RenderMarquee::computePosition(EMarqueeDirection dir, bool stopAtContentEdge)
{
- RenderObject* o = m_layer->renderer();
- RenderStyle* s = o->style();
+ RenderBox* box = m_layer->renderBox();
+ ASSERT(box);
+ RenderStyle* s = box->style();
if (isHorizontal()) {
bool ltr = s->direction() == LTR;
- int clientWidth = o->clientWidth();
- int contentWidth = ltr ? o->rightmostPosition(true, false) : o->leftmostPosition(true, false);
+ int clientWidth = box->clientWidth();
+ int contentWidth = ltr ? box->rightmostPosition(true, false) : box->leftmostPosition(true, false);
if (ltr)
- contentWidth += (o->paddingRight() - o->borderLeft());
+ contentWidth += (box->paddingRight() - box->borderLeft());
else {
- contentWidth = o->width() - contentWidth;
- contentWidth += (o->paddingLeft() - o->borderRight());
+ contentWidth = box->width() - contentWidth;
+ contentWidth += (box->paddingLeft() - box->borderRight());
}
if (dir == MRIGHT) {
if (stopAtContentEdge)
@@ -131,9 +132,9 @@ int RenderMarquee::computePosition(EMarqueeDirection dir, bool stopAtContentEdge
}
}
else {
- int contentHeight = m_layer->renderer()->lowestPosition(true, false) -
- m_layer->renderer()->borderTop() + m_layer->renderer()->paddingBottom();
- int clientHeight = m_layer->renderer()->clientHeight();
+ int contentHeight = box->lowestPosition(true, false) -
+ box->borderTop() + box->paddingBottom();
+ int clientHeight = box->clientHeight();
if (dir == MUP) {
if (stopAtContentEdge)
return min(contentHeight - clientHeight, 0);
@@ -283,7 +284,7 @@ void RenderMarquee::timerFired(Timer<RenderMarquee>*)
addIncrement = !addIncrement;
}
bool positive = range > 0;
- int clientSize = (isHorizontal() ? m_layer->renderer()->clientWidth() : m_layer->renderer()->clientHeight());
+ int clientSize = (isHorizontal() ? m_layer->renderBox()->clientWidth() : m_layer->renderBox()->clientHeight());
int increment = max(1, abs(m_layer->renderer()->style()->marqueeIncrement().calcValue(clientSize)));
int currentPos = (isHorizontal() ? m_layer->scrollXOffset() : m_layer->scrollYOffset());
newPos = currentPos + (addIncrement ? increment : -increment);
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderMarquee.h b/src/3rdparty/webkit/WebCore/rendering/RenderMarquee.h
index d9d20cd..886c343 100644
--- a/src/3rdparty/webkit/WebCore/rendering/RenderMarquee.h
+++ b/src/3rdparty/webkit/WebCore/rendering/RenderMarquee.h
@@ -44,7 +44,8 @@
#ifndef RenderMarquee_h
#define RenderMarquee_h
-#include "RenderStyle.h"
+#include "Length.h"
+#include "RenderStyleConstants.h"
#include "Timer.h"
namespace WebCore {
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderMedia.cpp b/src/3rdparty/webkit/WebCore/rendering/RenderMedia.cpp
index a224136..b0eb097 100644
--- a/src/3rdparty/webkit/WebCore/rendering/RenderMedia.cpp
+++ b/src/3rdparty/webkit/WebCore/rendering/RenderMedia.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2007, 2008, 2009 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -28,25 +28,20 @@
#if ENABLE(VIDEO)
#include "RenderMedia.h"
-#include "CSSStyleSelector.h"
-#include "Event.h"
#include "EventNames.h"
#include "FloatConversion.h"
-#include "FrameView.h"
-#include "GraphicsContext.h"
-#include "HTMLMediaElement.h"
#include "HTMLNames.h"
#include "MediaControlElements.h"
#include "MouseEvent.h"
-#include "MediaPlayer.h"
-#include "RenderSlider.h"
-#include "SystemTime.h"
+#include <wtf/CurrentTime.h>
#include <wtf/MathExtras.h>
using namespace std;
namespace WebCore {
+using namespace HTMLNames;
+
static const double cTimeUpdateRepeatDelay = 0.2;
static const double cOpacityAnimationRepeatDelay = 0.05;
// FIXME get this from style
@@ -82,8 +77,14 @@ RenderMedia::~RenderMedia()
void RenderMedia::destroy()
{
if (m_controlsShadowRoot && m_controlsShadowRoot->renderer()) {
+
+ // detach the panel before removing the shadow renderer to prevent a crash in m_controlsShadowRoot->detach()
+ // when display: style changes
+ m_panel->detach();
+
removeChild(m_controlsShadowRoot->renderer());
m_controlsShadowRoot->detach();
+ m_controlsShadowRoot = 0;
}
RenderReplaced::destroy();
}
@@ -98,18 +99,40 @@ MediaPlayer* RenderMedia::player() const
return mediaElement()->player();
}
+void RenderMedia::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
+{
+ RenderReplaced::styleDidChange(diff, oldStyle);
+
+ if (m_controlsShadowRoot) {
+ if (m_panel->renderer())
+ m_panel->renderer()->setStyle(getCachedPseudoStyle(MEDIA_CONTROLS_PANEL));
+
+ if (m_timelineContainer->renderer())
+ m_timelineContainer->renderer()->setStyle(getCachedPseudoStyle(MEDIA_CONTROLS_TIMELINE_CONTAINER));
+
+ m_muteButton->updateStyle();
+ m_playButton->updateStyle();
+ m_seekBackButton->updateStyle();
+ m_seekForwardButton->updateStyle();
+ m_timeline->updateStyle();
+ m_fullscreenButton->updateStyle();
+ m_currentTimeDisplay->updateStyle();
+ m_timeRemainingDisplay->updateStyle();
+ }
+}
+
void RenderMedia::layout()
{
- IntSize oldSize = contentBox().size();
+ IntSize oldSize = contentBoxRect().size();
RenderReplaced::layout();
- RenderObject* controlsRenderer = m_controlsShadowRoot ? m_controlsShadowRoot->renderer() : 0;
+ RenderBox* controlsRenderer = m_controlsShadowRoot ? m_controlsShadowRoot->renderBox() : 0;
if (!controlsRenderer)
return;
- IntSize newSize = contentBox().size();
+ IntSize newSize = contentBoxRect().size();
if (newSize != oldSize || controlsRenderer->needsLayout()) {
- controlsRenderer->setPos(borderLeft() + paddingLeft(), borderTop() + paddingTop());
+ controlsRenderer->setLocation(borderLeft() + paddingLeft(), borderTop() + paddingTop());
controlsRenderer->style()->setHeight(Length(newSize.height(), Fixed));
controlsRenderer->style()->setWidth(Length(newSize.width(), Fixed));
controlsRenderer->setNeedsLayout(true, false);
@@ -118,34 +141,17 @@ void RenderMedia::layout()
}
}
-RenderObject* RenderMedia::firstChild() const
-{
- return m_controlsShadowRoot ? m_controlsShadowRoot->renderer() : 0;
-}
-
-RenderObject* RenderMedia::lastChild() const
-{
- return m_controlsShadowRoot ? m_controlsShadowRoot->renderer() : 0;
-}
-
-void RenderMedia::removeChild(RenderObject* child)
-{
- ASSERT(m_controlsShadowRoot);
- ASSERT(child == m_controlsShadowRoot->renderer());
- child->removeLayers(enclosingLayer());
- static_cast<RenderMediaControlShadowRoot*>(child)->setParent(0);
-}
-
void RenderMedia::createControlsShadowRoot()
{
ASSERT(!m_controlsShadowRoot);
m_controlsShadowRoot = new MediaControlShadowRootElement(document(), mediaElement());
+ addChild(m_controlsShadowRoot->renderer());
}
void RenderMedia::createPanel()
{
ASSERT(!m_panel);
- RenderStyle* style = getCachedPseudoStyle(RenderStyle::MEDIA_CONTROLS_PANEL);
+ RenderStyle* style = getCachedPseudoStyle(MEDIA_CONTROLS_PANEL);
m_panel = new HTMLDivElement(HTMLNames::divTag, document());
RenderObject* renderer = m_panel->createRenderer(renderArena(), style);
if (renderer) {
@@ -186,27 +192,42 @@ void RenderMedia::createSeekForwardButton()
m_seekForwardButton->attachToParent(m_panel.get());
}
+void RenderMedia::createTimelineContainer()
+{
+ ASSERT(!m_timelineContainer);
+ RenderStyle* style = getCachedPseudoStyle(MEDIA_CONTROLS_TIMELINE_CONTAINER);
+ m_timelineContainer = new HTMLDivElement(HTMLNames::divTag, document());
+ RenderObject* renderer = m_timelineContainer->createRenderer(renderArena(), style);
+ if (renderer) {
+ m_timelineContainer->setRenderer(renderer);
+ renderer->setStyle(style);
+ m_timelineContainer->setAttached();
+ m_timelineContainer->setInDocument(true);
+ m_panel->addChild(m_timelineContainer);
+ m_panel->renderer()->addChild(renderer);
+ }
+}
+
void RenderMedia::createTimeline()
{
ASSERT(!m_timeline);
m_timeline = new MediaControlTimelineElement(document(), mediaElement());
- m_timeline->attachToParent(m_panel.get());
+ m_timeline->setAttribute(precisionAttr, "float");
+ m_timeline->attachToParent(m_timelineContainer.get());
}
-void RenderMedia::createTimeDisplay()
+void RenderMedia::createCurrentTimeDisplay()
{
- ASSERT(!m_timeDisplay);
- RenderStyle* style = getCachedPseudoStyle(RenderStyle::MEDIA_CONTROLS_TIME_DISPLAY);
- m_timeDisplay = new HTMLDivElement(HTMLNames::divTag, document());
- RenderObject* renderer = m_timeDisplay->createRenderer(renderArena(), style);
- if (renderer) {
- m_timeDisplay->setRenderer(renderer);
- renderer->setStyle(style);
- m_timeDisplay->setAttached();
- m_timeDisplay->setInDocument(true);
- m_panel->addChild(m_timeDisplay);
- m_panel->renderer()->addChild(renderer);
- }
+ ASSERT(!m_currentTimeDisplay);
+ m_currentTimeDisplay = new MediaTimeDisplayElement(document(), mediaElement(), true);
+ m_currentTimeDisplay->attachToParent(m_timelineContainer.get());
+}
+
+void RenderMedia::createTimeRemainingDisplay()
+{
+ ASSERT(!m_timeRemainingDisplay);
+ m_timeRemainingDisplay = new MediaTimeDisplayElement(document(), mediaElement(), false);
+ m_timeRemainingDisplay->attachToParent(m_timelineContainer.get());
}
void RenderMedia::createFullscreenButton()
@@ -230,10 +251,12 @@ void RenderMedia::updateControls()
m_panel = 0;
m_muteButton = 0;
m_playButton = 0;
+ m_timelineContainer = 0;
m_timeline = 0;
m_seekBackButton = 0;
m_seekForwardButton = 0;
- m_timeDisplay = 0;
+ m_currentTimeDisplay = 0;
+ m_timeRemainingDisplay = 0;
m_fullscreenButton = 0;
m_controlsShadowRoot = 0;
}
@@ -246,19 +269,29 @@ void RenderMedia::updateControls()
if (!m_controlsShadowRoot) {
createControlsShadowRoot();
createPanel();
- createMuteButton();
- createPlayButton();
- createTimeline();
- createSeekBackButton();
- createSeekForwardButton();
- createTimeDisplay();
- createFullscreenButton();
+ if (m_panel && m_panel->renderer()) {
+ createMuteButton();
+ createPlayButton();
+ createTimelineContainer();
+ createSeekBackButton();
+ createSeekForwardButton();
+ createFullscreenButton();
+ }
+ if (m_timelineContainer && m_timelineContainer->renderer()) {
+ createCurrentTimeDisplay();
+ createTimeline();
+ createTimeRemainingDisplay();
+ }
}
-
- if (media->paused() || media->ended() || media->networkState() < HTMLMediaElement::LOADED_METADATA)
- m_timeUpdateTimer.stop();
- else
+
+ if (media->canPlay()) {
+ if (m_timeUpdateTimer.isActive())
+ m_timeUpdateTimer.stop();
+ } else if (style()->visibility() == VISIBLE && m_timeline && m_timeline->renderer() && m_timeline->renderer()->style()->display() != NONE ) {
m_timeUpdateTimer.startRepeating(cTimeUpdateRepeatDelay);
+ }
+
+ m_previousVisible = style()->visibility();
if (m_muteButton)
m_muteButton->update();
@@ -266,6 +299,10 @@ void RenderMedia::updateControls()
m_playButton->update();
if (m_timeline)
m_timeline->update();
+ if (m_currentTimeDisplay)
+ m_currentTimeDisplay->update();
+ if (m_timeRemainingDisplay)
+ m_timeRemainingDisplay->update();
if (m_seekBackButton)
m_seekBackButton->update();
if (m_seekForwardButton)
@@ -287,32 +324,47 @@ String RenderMedia::formatTime(float time)
{
if (!isfinite(time))
time = 0;
- int seconds = (int)time;
+ int seconds = (int)fabsf(time);
int hours = seconds / (60 * 60);
int minutes = (seconds / 60) % 60;
seconds %= 60;
- return String::format("%02d:%02d:%02d", hours, minutes, seconds);
+ if (hours) {
+ if (hours > 9)
+ return String::format("%s%02d:%02d:%02d", (time < 0 ? "-" : ""), hours, minutes, seconds);
+ else
+ return String::format("%s%01d:%02d:%02d", (time < 0 ? "-" : ""), hours, minutes, seconds);
+ }
+ else
+ return String::format("%s%02d:%02d", (time < 0 ? "-" : ""), minutes, seconds);
}
void RenderMedia::updateTimeDisplay()
{
- if (!m_timeDisplay)
+ if (!m_currentTimeDisplay || !m_currentTimeDisplay->renderer() || m_currentTimeDisplay->renderer()->style()->display() == NONE || style()->visibility() != VISIBLE)
return;
- String timeString = formatTime(mediaElement()->currentTime());
+ float now = mediaElement()->currentTime();
+ float duration = mediaElement()->duration();
+
+ String timeString = formatTime(now);
ExceptionCode ec;
- m_timeDisplay->setInnerText(timeString, ec);
-}
+ m_currentTimeDisplay->setInnerText(timeString, ec);
+ timeString = formatTime(now - duration);
+ m_timeRemainingDisplay->setInnerText(timeString, ec);
+}
+
void RenderMedia::updateControlVisibility()
{
if (!m_panel || !m_panel->renderer())
return;
+
// Don't fade for audio controls.
HTMLMediaElement* media = mediaElement();
- if (player() && !player()->hasVideo() || !media->isVideo())
+ if (!media->hasVideo())
return;
+
// do fading manually, css animations don't work well with shadow trees
- bool visible = style()->visibility() == VISIBLE && (m_mouseOver || media->paused() || media->ended() || media->networkState() < HTMLMediaElement::LOADED_METADATA);
+ bool visible = style()->visibility() == VISIBLE && (m_mouseOver || media->canPlay());
if (visible == (m_opacityAnimationTo > 0))
return;
@@ -320,7 +372,7 @@ void RenderMedia::updateControlVisibility()
// don't fade gradually if it the element has just changed visibility
m_previousVisible = style()->visibility();
m_opacityAnimationTo = m_previousVisible == VISIBLE ? 1.0f : 0;
- changeOpacity(m_panel.get(), 0);
+ changeOpacity(m_panel.get(), m_opacityAnimationTo);
return;
}
@@ -361,7 +413,7 @@ void RenderMedia::forwardEvent(Event* event)
{
if (event->isMouseEvent() && m_controlsShadowRoot) {
MouseEvent* mouseEvent = static_cast<MouseEvent*>(event);
- IntPoint point(mouseEvent->pageX(), mouseEvent->pageY());
+ IntPoint point(mouseEvent->absoluteLocation());
if (m_muteButton && m_muteButton->hitTest(point))
m_muteButton->defaultEventHandler(event);
@@ -385,8 +437,10 @@ void RenderMedia::forwardEvent(Event* event)
updateControlVisibility();
}
if (event->type() == eventNames().mouseoutEvent) {
- // FIXME: moving over scrollbar thumb generates mouseout for the ancestor media element for some reason
- m_mouseOver = absoluteBoundingBoxRect().contains(point);
+ // When the scrollbar thumb captures mouse events, we should treat the mouse as still being over our renderer if the new target is a descendant
+ Node* mouseOverNode = mouseEvent->relatedTarget() ? mouseEvent->relatedTarget()->toNode() : 0;
+ RenderObject* mouseOverRenderer = mouseOverNode ? mouseOverNode->renderer() : 0;
+ m_mouseOver = mouseOverRenderer && mouseOverRenderer->isDescendantOf(this);
updateControlVisibility();
}
}
@@ -398,7 +452,7 @@ int RenderMedia::lowestPosition(bool includeOverflowInterior, bool includeSelf)
if (!m_controlsShadowRoot || !m_controlsShadowRoot->renderer())
return bottom;
- return max(bottom, m_controlsShadowRoot->renderer()->yPos() + m_controlsShadowRoot->renderer()->lowestPosition(includeOverflowInterior, includeSelf));
+ return max(bottom, m_controlsShadowRoot->renderBox()->y() + m_controlsShadowRoot->renderBox()->lowestPosition(includeOverflowInterior, includeSelf));
}
int RenderMedia::rightmostPosition(bool includeOverflowInterior, bool includeSelf) const
@@ -407,7 +461,7 @@ int RenderMedia::rightmostPosition(bool includeOverflowInterior, bool includeSel
if (!m_controlsShadowRoot || !m_controlsShadowRoot->renderer())
return right;
- return max(right, m_controlsShadowRoot->renderer()->xPos() + m_controlsShadowRoot->renderer()->rightmostPosition(includeOverflowInterior, includeSelf));
+ return max(right, m_controlsShadowRoot->renderBox()->x() + m_controlsShadowRoot->renderBox()->rightmostPosition(includeOverflowInterior, includeSelf));
}
int RenderMedia::leftmostPosition(bool includeOverflowInterior, bool includeSelf) const
@@ -416,7 +470,7 @@ int RenderMedia::leftmostPosition(bool includeOverflowInterior, bool includeSelf
if (!m_controlsShadowRoot || !m_controlsShadowRoot->renderer())
return left;
- return min(left, m_controlsShadowRoot->renderer()->xPos() + m_controlsShadowRoot->renderer()->leftmostPosition(includeOverflowInterior, includeSelf));
+ return min(left, m_controlsShadowRoot->renderBox()->x() + m_controlsShadowRoot->renderBox()->leftmostPosition(includeOverflowInterior, includeSelf));
}
} // namespace WebCore
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderMedia.h b/src/3rdparty/webkit/WebCore/rendering/RenderMedia.h
index 8f48caf..6013d7b 100644
--- a/src/3rdparty/webkit/WebCore/rendering/RenderMedia.h
+++ b/src/3rdparty/webkit/WebCore/rendering/RenderMedia.h
@@ -40,6 +40,7 @@ class MediaControlPlayButtonElement;
class MediaControlSeekButtonElement;
class MediaControlTimelineElement;
class MediaControlFullscreenButtonElement;
+class MediaTimeDisplayElement;
class MediaPlayer;
class RenderMedia : public RenderReplaced {
@@ -48,9 +49,11 @@ public:
RenderMedia(HTMLMediaElement*, const IntSize& intrinsicSize);
virtual ~RenderMedia();
- virtual RenderObject* firstChild() const;
- virtual RenderObject* lastChild() const;
- virtual void removeChild(RenderObject*);
+ virtual RenderObjectChildList* virtualChildren() { return children(); }
+ virtual const RenderObjectChildList* virtualChildren() const { return children(); }
+ const RenderObjectChildList* children() const { return &m_children; }
+ RenderObjectChildList* children() { return &m_children; }
+
virtual void destroy();
virtual void layout();
@@ -66,6 +69,7 @@ public:
void updateFromElement();
void updatePlayer();
void updateControls();
+ void updateTimeDisplay();
void forwardEvent(Event*);
@@ -75,22 +79,26 @@ public:
private:
void createControlsShadowRoot();
+ void destroyControlsShadowRoot();
void createPanel();
void createMuteButton();
void createPlayButton();
void createSeekBackButton();
void createSeekForwardButton();
+ void createTimelineContainer();
void createTimeline();
- void createTimeDisplay();
+ void createCurrentTimeDisplay();
+ void createTimeRemainingDisplay();
void createFullscreenButton();
void timeUpdateTimerFired(Timer<RenderMedia>*);
- void updateTimeDisplay();
void updateControlVisibility();
void changeOpacity(HTMLElement*, float opacity);
void opacityAnimationTimerFired(Timer<RenderMedia>*);
+ virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
+
RefPtr<HTMLElement> m_controlsShadowRoot;
RefPtr<HTMLElement> m_panel;
RefPtr<MediaControlMuteButtonElement> m_muteButton;
@@ -99,9 +107,12 @@ private:
RefPtr<MediaControlSeekButtonElement> m_seekForwardButton;
RefPtr<MediaControlTimelineElement> m_timeline;
RefPtr<MediaControlFullscreenButtonElement> m_fullscreenButton;
- RefPtr<HTMLElement> m_timeDisplay;
- EventTargetNode* m_lastUnderNode;
- EventTargetNode* m_nodeUnderMouse;
+ RefPtr<HTMLElement> m_timelineContainer;
+ RefPtr<MediaTimeDisplayElement> m_currentTimeDisplay;
+ RefPtr<MediaTimeDisplayElement> m_timeRemainingDisplay;
+ RenderObjectChildList m_children;
+ Node* m_lastUnderNode;
+ Node* m_nodeUnderMouse;
Timer<RenderMedia> m_timeUpdateTimer;
Timer<RenderMedia> m_opacityAnimationTimer;
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderMediaControls.cpp b/src/3rdparty/webkit/WebCore/rendering/RenderMediaControls.cpp
new file mode 100644
index 0000000..06d901a
--- /dev/null
+++ b/src/3rdparty/webkit/WebCore/rendering/RenderMediaControls.cpp
@@ -0,0 +1,150 @@
+/*
+ * Copyright (C) 2009 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``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 INC. OR
+ * 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"
+#include "RenderMediaControls.h"
+
+#include "GraphicsContext.h"
+#include "HTMLMediaElement.h"
+#include "HTMLNames.h"
+#include "RenderThemeSafari.h"
+#include "SoftLinking.h"
+#include <CoreGraphics/CoreGraphics.h>
+
+using namespace std;
+
+namespace WebCore {
+
+#if !defined(NDEBUG) && defined(USE_DEBUG_SAFARI_THEME)
+SOFT_LINK_DEBUG_LIBRARY(SafariTheme)
+#else
+SOFT_LINK_LIBRARY(SafariTheme)
+#endif
+
+SOFT_LINK(SafariTheme, paintThemePart, void, __stdcall, (ThemePart part, CGContextRef context, const CGRect& rect, NSControlSize size, ThemeControlState state), (part, context, rect, size, state))
+SOFT_LINK(SafariTheme, STPaintProgressIndicator, void, APIENTRY, (ProgressIndicatorType type, CGContextRef context, const CGRect& rect, NSControlSize size, ThemeControlState state, float value), (type, context, rect, size, state, value))
+
+#if ENABLE(VIDEO)
+
+static ThemeControlState determineState(RenderObject* o)
+{
+ ThemeControlState result = 0;
+ RenderTheme* theme = o->theme();
+ if (theme->isActive(o))
+ result |= SafariTheme::ActiveState;
+ if (theme->isEnabled(o) && !theme->isReadOnlyControl(o))
+ result |= SafariTheme::EnabledState;
+ if (theme->isPressed(o))
+ result |= SafariTheme::PressedState;
+ if (theme->isChecked(o))
+ result |= SafariTheme::CheckedState;
+ if (theme->isIndeterminate(o))
+ result |= SafariTheme::IndeterminateCheckedState;
+ if (theme->isFocused(o))
+ result |= SafariTheme::FocusedState;
+ if (theme->isDefault(o))
+ result |= SafariTheme::DefaultState;
+ return result;
+}
+
+static const int mediaSliderThumbWidth = 13;
+static const int mediaSliderThumbHeight = 14;
+
+void RenderMediaControls::adjustMediaSliderThumbSize(RenderObject* o)
+{
+ if (o->style()->appearance() != MediaSliderThumbPart)
+ return;
+
+ float zoomLevel = o->style()->effectiveZoom();
+ o->style()->setWidth(Length(static_cast<int>(mediaSliderThumbWidth * zoomLevel), Fixed));
+ o->style()->setHeight(Length(static_cast<int>(mediaSliderThumbHeight * zoomLevel), Fixed));
+}
+
+static HTMLMediaElement* parentMediaElement(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);
+}
+
+bool RenderMediaControls::paintMediaControlsPart(MediaControlElementType part, RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
+{
+ ASSERT(SafariThemeLibrary());
+
+ switch (part) {
+ case MediaFullscreenButton:
+ paintThemePart(SafariTheme::MediaFullscreenButtonPart, paintInfo.context->platformContext(), r, NSRegularControlSize, determineState(o));
+ break;
+ case MediaMuteButton:
+ case MediaUnMuteButton:
+ if (MediaControlMuteButtonElement* btn = static_cast<MediaControlMuteButtonElement*>(o->node())) {
+ bool audioEnabled = btn->displayType() == MediaMuteButton;
+ paintThemePart(audioEnabled ? SafariTheme::MediaMuteButtonPart : SafariTheme::MediaUnMuteButtonPart, paintInfo.context->platformContext(), r, NSRegularControlSize, determineState(o));
+ }
+ break;
+ case MediaPauseButton:
+ case MediaPlayButton:
+ if (MediaControlPlayButtonElement* btn = static_cast<MediaControlPlayButtonElement*>(o->node())) {
+ bool currentlyPlaying = btn->displayType() == MediaPlayButton;
+ paintThemePart(currentlyPlaying ? SafariTheme::MediaPauseButtonPart : SafariTheme::MediaPlayButtonPart, paintInfo.context->platformContext(), r, NSRegularControlSize, determineState(o));
+ }
+ break;
+ case MediaSeekBackButton:
+ paintThemePart(SafariTheme::MediaSeekBackButtonPart, paintInfo.context->platformContext(), r, NSRegularControlSize, determineState(o));
+ break;
+ case MediaSeekForwardButton:
+ paintThemePart(SafariTheme::MediaSeekForwardButtonPart, paintInfo.context->platformContext(), r, NSRegularControlSize, determineState(o));
+ break;
+ case MediaSlider: {
+ if (HTMLMediaElement* mediaElement = parentMediaElement(o))
+ STPaintProgressIndicator(SafariTheme::MediaType, paintInfo.context->platformContext(), r, NSRegularControlSize, 0, mediaElement->percentLoaded());
+ break;
+ }
+ case MediaSliderThumb:
+ paintThemePart(SafariTheme::MediaSliderThumbPart, paintInfo.context->platformContext(), r, NSRegularControlSize, determineState(o));
+ break;
+ case MediaTimelineContainer:
+ ASSERT_NOT_REACHED();
+ break;
+ case MediaCurrentTimeDisplay:
+ ASSERT_NOT_REACHED();
+ break;
+ case MediaTimeRemainingDisplay:
+ ASSERT_NOT_REACHED();
+ break;
+ case MediaControlsPanel:
+ ASSERT_NOT_REACHED();
+ break;
+ }
+ return false;
+}
+
+#endif // #if ENABLE(VIDEO)
+
+} // namespace WebCore
+
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderMediaControls.h b/src/3rdparty/webkit/WebCore/rendering/RenderMediaControls.h
new file mode 100644
index 0000000..529dbac
--- /dev/null
+++ b/src/3rdparty/webkit/WebCore/rendering/RenderMediaControls.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2009 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``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 INC. OR
+ * 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 RenderMediaControls_h
+#define RenderMediaControls_h
+
+#include "RenderObject.h"
+#include "MediaControlElements.h"
+
+namespace WebCore {
+
+class HTMLMediaElement;
+class RenderMediaControls {
+public:
+ static bool paintMediaControlsPart(MediaControlElementType, RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+ static void adjustMediaSliderThumbSize(RenderObject*);
+};
+
+} // namespace WebCore
+
+#endif // RenderMediaControls_h
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderMenuList.cpp b/src/3rdparty/webkit/WebCore/rendering/RenderMenuList.cpp
index baec309..4cd7b43 100644
--- a/src/3rdparty/webkit/WebCore/rendering/RenderMenuList.cpp
+++ b/src/3rdparty/webkit/WebCore/rendering/RenderMenuList.cpp
@@ -1,7 +1,8 @@
-/**
+/*
* This file is part of the select element renderer in WebCore.
*
* Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
+ * 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -24,20 +25,16 @@
#include "RenderMenuList.h"
#include "CSSStyleSelector.h"
-#include "Document.h"
-#include "FontSelector.h"
#include "FrameView.h"
-#include "GraphicsContext.h"
#include "HTMLNames.h"
-#include "HTMLOptionElement.h"
-#include "HTMLOptGroupElement.h"
-#include "HTMLSelectElement.h"
+#include "NodeRenderStyle.h"
+#include "OptionElement.h"
+#include "OptionGroupElement.h"
#include "PopupMenu.h"
#include "RenderBR.h"
#include "RenderScrollbar.h"
-#include "RenderText.h"
#include "RenderTheme.h"
-#include "NodeRenderStyle.h"
+#include "SelectElement.h"
#include <math.h>
using namespace std;
@@ -46,7 +43,7 @@ namespace WebCore {
using namespace HTMLNames;
-RenderMenuList::RenderMenuList(HTMLSelectElement* element)
+RenderMenuList::RenderMenuList(Element* element)
: RenderFlexibleBox(element)
, m_buttonText(0)
, m_innerBlock(0)
@@ -64,12 +61,6 @@ RenderMenuList::~RenderMenuList()
m_popup = 0;
}
-// this static cast is safe because RenderMenuLists are only created for HTMLSelectElements
-HTMLSelectElement* RenderMenuList::selectElement()
-{
- return static_cast<HTMLSelectElement*>(node());
-}
-
void RenderMenuList::createInnerBlock()
{
if (m_innerBlock) {
@@ -118,7 +109,7 @@ void RenderMenuList::removeChild(RenderObject* oldChild)
m_innerBlock->removeChild(oldChild);
}
-void RenderMenuList::styleDidChange(RenderStyle::Diff diff, const RenderStyle* oldStyle)
+void RenderMenuList::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
{
RenderBlock::styleDidChange(diff, oldStyle);
@@ -137,15 +128,25 @@ void RenderMenuList::styleDidChange(RenderStyle::Diff diff, const RenderStyle* o
void RenderMenuList::updateOptionsWidth()
{
float maxOptionWidth = 0;
- const Vector<HTMLElement*>& listItems = static_cast<HTMLSelectElement*>(node())->listItems();
+ const Vector<Element*>& listItems = toSelectElement(static_cast<Element*>(node()))->listItems();
int size = listItems.size();
for (int i = 0; i < size; ++i) {
- HTMLElement* element = listItems[i];
- if (element->hasTagName(optionTag)) {
- String text = static_cast<HTMLOptionElement*>(element)->optionText();
+ Element* element = listItems[i];
+ OptionElement* optionElement = toOptionElement(element);
+ if (!optionElement)
+ continue;
+
+ String text = optionElement->textIndentedToRespectGroupLabel();
+ if (theme()->popupOptionSupportsTextIndent()) {
+ // Add in the option's text indent. We can't calculate percentage values for now.
+ float optionWidth = 0;
+ if (RenderStyle* optionStyle = element->renderStyle())
+ optionWidth += optionStyle->textIndent().calcMinValue(0);
if (!text.isEmpty())
- maxOptionWidth = max(maxOptionWidth, style()->font().floatWidth(text));
- }
+ optionWidth += style()->font().floatWidth(text);
+ maxOptionWidth = max(maxOptionWidth, optionWidth);
+ } else if (!text.isEmpty())
+ maxOptionWidth = max(maxOptionWidth, style()->font().floatWidth(text));
}
int width = static_cast<int>(ceilf(maxOptionWidth));
@@ -153,7 +154,8 @@ void RenderMenuList::updateOptionsWidth()
return;
m_optionsWidth = width;
- setNeedsLayoutAndPrefWidthsRecalc();
+ if (parent())
+ setNeedsLayoutAndPrefWidthsRecalc();
}
void RenderMenuList::updateFromElement()
@@ -166,22 +168,22 @@ void RenderMenuList::updateFromElement()
if (m_popupIsVisible)
m_popup->updateFromElement();
else
- setTextFromOption(static_cast<HTMLSelectElement*>(node())->selectedIndex());
+ setTextFromOption(toSelectElement(static_cast<Element*>(node()))->selectedIndex());
}
void RenderMenuList::setTextFromOption(int optionIndex)
{
- HTMLSelectElement* select = static_cast<HTMLSelectElement*>(node());
- const Vector<HTMLElement*>& listItems = select->listItems();
+ SelectElement* select = toSelectElement(static_cast<Element*>(node()));
+ const Vector<Element*>& listItems = select->listItems();
int size = listItems.size();
int i = select->optionToListIndex(optionIndex);
String text = "";
if (i >= 0 && i < size) {
- HTMLElement* element = listItems[i];
- if (element->hasTagName(optionTag))
- text = static_cast<HTMLOptionElement*>(listItems[i])->optionText();
+ if (OptionElement* optionElement = toOptionElement(listItems[i]))
+ text = optionElement->textIndentedToRespectGroupLabel();
}
+
setText(text.stripWhiteSpace());
}
@@ -224,8 +226,8 @@ IntRect RenderMenuList::controlClipRect(int tx, int ty) const
contentWidth(),
contentHeight());
- IntRect innerBox(tx + m_innerBlock->xPos() + m_innerBlock->paddingLeft(),
- ty + m_innerBlock->yPos() + m_innerBlock->paddingTop(),
+ IntRect innerBox(tx + m_innerBlock->x() + m_innerBlock->paddingLeft(),
+ ty + m_innerBlock->y() + m_innerBlock->paddingTop(),
m_innerBlock->contentWidth(),
m_innerBlock->contentHeight());
@@ -273,7 +275,7 @@ void RenderMenuList::showPopup()
createInnerBlock();
if (!m_popup)
m_popup = PopupMenu::create(this);
- HTMLSelectElement* select = static_cast<HTMLSelectElement*>(node());
+ SelectElement* select = toSelectElement(static_cast<Element*>(node()));
m_popupIsVisible = true;
// Compute the top left taking transforms into account, but use
@@ -294,46 +296,52 @@ void RenderMenuList::hidePopup()
void RenderMenuList::valueChanged(unsigned listIndex, bool fireOnChange)
{
- HTMLSelectElement* select = static_cast<HTMLSelectElement*>(node());
- select->setSelectedIndex(select->listToOptionIndex(listIndex), true, fireOnChange);
+ SelectElement* select = toSelectElement(static_cast<Element*>(node()));
+ select->setSelectedIndexByUser(select->listToOptionIndex(listIndex), true, fireOnChange);
}
String RenderMenuList::itemText(unsigned listIndex) const
{
- HTMLSelectElement* select = static_cast<HTMLSelectElement*>(node());
- HTMLElement* element = select->listItems()[listIndex];
- if (element->hasTagName(optgroupTag))
- return static_cast<HTMLOptGroupElement*>(element)->groupLabelText();
- else if (element->hasTagName(optionTag))
- return static_cast<HTMLOptionElement*>(element)->optionText();
+ SelectElement* select = toSelectElement(static_cast<Element*>(node()));
+ Element* element = select->listItems()[listIndex];
+ if (OptionGroupElement* optionGroupElement = toOptionGroupElement(element))
+ return optionGroupElement->groupLabelText();
+ else if (OptionElement* optionElement = toOptionElement(element))
+ return optionElement->textIndentedToRespectGroupLabel();
return String();
}
bool RenderMenuList::itemIsEnabled(unsigned listIndex) const
{
- HTMLSelectElement* select = static_cast<HTMLSelectElement*>(node());
- HTMLElement* element = select->listItems()[listIndex];
- if (!element->hasTagName(optionTag))
+ SelectElement* select = toSelectElement(static_cast<Element*>(node()));
+ Element* element = select->listItems()[listIndex];
+ if (!isOptionElement(element))
return false;
+
bool groupEnabled = true;
- if (element->parentNode() && element->parentNode()->hasTagName(optgroupTag))
- groupEnabled = element->parentNode()->isEnabled();
- return element->isEnabled() && groupEnabled;
+ if (Element* parentElement = element->parentElement()) {
+ if (isOptionGroupElement(parentElement))
+ groupEnabled = parentElement->isEnabledFormControl();
+ }
+ if (!groupEnabled)
+ return false;
+
+ return element->isEnabledFormControl();
}
PopupMenuStyle RenderMenuList::itemStyle(unsigned listIndex) const
{
- HTMLSelectElement* select = static_cast<HTMLSelectElement*>(node());
- HTMLElement* element = select->listItems()[listIndex];
+ SelectElement* select = toSelectElement(static_cast<Element*>(node()));
+ Element* element = select->listItems()[listIndex];
RenderStyle* style = element->renderStyle() ? element->renderStyle() : element->computedStyle();
- return style ? PopupMenuStyle(style->color(), itemBackgroundColor(listIndex), style->font(), style->visibility() == VISIBLE) : menuStyle();
+ return style ? PopupMenuStyle(style->color(), itemBackgroundColor(listIndex), style->font(), style->visibility() == VISIBLE, style->textIndent(), style->direction()) : menuStyle();
}
Color RenderMenuList::itemBackgroundColor(unsigned listIndex) const
{
- HTMLSelectElement* select = static_cast<HTMLSelectElement*>(node());
- HTMLElement* element = select->listItems()[listIndex];
+ SelectElement* select = toSelectElement(static_cast<Element*>(node()));
+ Element* element = select->listItems()[listIndex];
Color backgroundColor;
if (element->renderStyle())
@@ -355,7 +363,7 @@ PopupMenuStyle RenderMenuList::menuStyle() const
{
RenderStyle* s = m_innerBlock ? m_innerBlock->style() : style();
- return PopupMenuStyle(s->color(), s->backgroundColor(), s->font(), s->visibility() == VISIBLE);
+ return PopupMenuStyle(s->color(), s->backgroundColor(), s->font(), s->visibility() == VISIBLE, s->textIndent(), s->direction());
}
HostWindow* RenderMenuList::hostWindow() const
@@ -366,7 +374,7 @@ HostWindow* RenderMenuList::hostWindow() const
PassRefPtr<Scrollbar> RenderMenuList::createScrollbar(ScrollbarClient* client, ScrollbarOrientation orientation, ScrollbarControlSize controlSize)
{
RefPtr<Scrollbar> widget;
- bool hasCustomScrollbarStyle = style()->hasPseudoStyle(RenderStyle::SCROLLBAR);
+ bool hasCustomScrollbarStyle = style()->hasPseudoStyle(SCROLLBAR);
if (hasCustomScrollbarStyle)
widget = RenderScrollbar::createCustomScrollbar(client, orientation, this);
else
@@ -396,40 +404,42 @@ int RenderMenuList::clientPaddingRight() const
int RenderMenuList::listSize() const
{
- HTMLSelectElement* select = static_cast<HTMLSelectElement*>(node());
+ SelectElement* select = toSelectElement(static_cast<Element*>(node()));
return select->listItems().size();
}
int RenderMenuList::selectedIndex() const
{
- HTMLSelectElement* select = static_cast<HTMLSelectElement*>(node());
+ SelectElement* select = toSelectElement(static_cast<Element*>(node()));
return select->optionToListIndex(select->selectedIndex());
}
bool RenderMenuList::itemIsSeparator(unsigned listIndex) const
{
- HTMLSelectElement* select = static_cast<HTMLSelectElement*>(node());
- HTMLElement* element = select->listItems()[listIndex];
+ SelectElement* select = toSelectElement(static_cast<Element*>(node()));
+ Element* element = select->listItems()[listIndex];
return element->hasTagName(hrTag);
}
bool RenderMenuList::itemIsLabel(unsigned listIndex) const
{
- HTMLSelectElement* select = static_cast<HTMLSelectElement*>(node());
- HTMLElement* element = select->listItems()[listIndex];
- return element->hasTagName(optgroupTag);
+ SelectElement* select = toSelectElement(static_cast<Element*>(node()));
+ Element* element = select->listItems()[listIndex];
+ return isOptionGroupElement(element);
}
bool RenderMenuList::itemIsSelected(unsigned listIndex) const
{
- HTMLSelectElement* select = static_cast<HTMLSelectElement*>(node());
- HTMLElement* element = select->listItems()[listIndex];
- return element->hasTagName(optionTag)&& static_cast<HTMLOptionElement*>(element)->selected();
+ SelectElement* select = toSelectElement(static_cast<Element*>(node()));
+ Element* element = select->listItems()[listIndex];
+ if (OptionElement* optionElement = toOptionElement(element))
+ return optionElement->selected();
+ return false;
}
void RenderMenuList::setTextFromItem(unsigned listIndex)
{
- HTMLSelectElement* select = static_cast<HTMLSelectElement*>(node());
+ SelectElement* select = toSelectElement(static_cast<Element*>(node()));
setTextFromOption(select->listToOptionIndex(listIndex));
}
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderMenuList.h b/src/3rdparty/webkit/WebCore/rendering/RenderMenuList.h
index f31ef32..7966eff 100644
--- a/src/3rdparty/webkit/WebCore/rendering/RenderMenuList.h
+++ b/src/3rdparty/webkit/WebCore/rendering/RenderMenuList.h
@@ -23,8 +23,8 @@
#ifndef RenderMenuList_h
#define RenderMenuList_h
-#include "RenderFlexibleBox.h"
#include "PopupMenuClient.h"
+#include "RenderFlexibleBox.h"
#if PLATFORM(MAC)
#define POPUP_MENU_PULLS_DOWN 0
@@ -34,16 +34,15 @@
namespace WebCore {
-class HTMLSelectElement;
class PopupMenu;
+class RenderText;
class RenderMenuList : public RenderFlexibleBox, private PopupMenuClient {
public:
- RenderMenuList(HTMLSelectElement*);
+ RenderMenuList(Element*);
~RenderMenuList();
-
- HTMLSelectElement* selectElement();
+private:
virtual bool isMenuList() const { return true; }
virtual void addChild(RenderObject* newChild, RenderObject* beforeChild = 0);
@@ -60,6 +59,7 @@ public:
virtual void calcPrefWidths();
+public:
bool popupIsVisible() const { return m_popupIsVisible; }
void showPopup();
void hidePopup();
@@ -68,10 +68,9 @@ public:
String text() const;
-protected:
- virtual void styleDidChange(RenderStyle::Diff, const RenderStyle* oldStyle);
-
private:
+ virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
+
// PopupMenuClient methods
virtual String itemText(unsigned listIndex) const;
virtual bool itemIsEnabled(unsigned listIndex) const;
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderObject.cpp b/src/3rdparty/webkit/WebCore/rendering/RenderObject.cpp
index 3ef7af7..098932a 100644
--- a/src/3rdparty/webkit/WebCore/rendering/RenderObject.cpp
+++ b/src/3rdparty/webkit/WebCore/rendering/RenderObject.cpp
@@ -26,26 +26,14 @@
#include "RenderObject.h"
#include "AXObjectCache.h"
-#include "TransformationMatrix.h"
-#include "AnimationController.h"
#include "CSSStyleSelector.h"
-#include "CachedImage.h"
-#include "Chrome.h"
-#include "Document.h"
-#include "Element.h"
-#include "EventHandler.h"
-#include "FloatRect.h"
+#include "FloatQuad.h"
#include "Frame.h"
#include "FrameView.h"
#include "GraphicsContext.h"
#include "HTMLNames.h"
-#include "HTMLOListElement.h"
-#include "HitTestRequest.h"
#include "HitTestResult.h"
-#include "KURL.h"
#include "Page.h"
-#include "PlatformScreen.h"
-#include "Position.h"
#include "RenderArena.h"
#include "RenderCounter.h"
#include "RenderFlexibleBox.h"
@@ -55,14 +43,17 @@
#include "RenderTableCell.h"
#include "RenderTableCol.h"
#include "RenderTableRow.h"
-#include "RenderText.h"
#include "RenderTheme.h"
#include "RenderView.h"
-#include "SelectionController.h"
-#include "TextResourceDecoder.h"
+#include "TransformState.h"
#include <algorithm>
#include <stdio.h>
#include <wtf/RefCountedLeakCounter.h>
+#include <wtf/UnusedParam.h>
+
+#if USE(ACCELERATED_COMPOSITING)
+#include "RenderLayerCompositor.h"
+#endif
#if ENABLE(WML)
#include "WMLNames.h"
@@ -102,10 +93,10 @@ RenderObject* RenderObject::createObject(Node* node, RenderStyle* style)
// Works only if we have exactly one piece of content and it's a URL.
// Otherwise acts as if we didn't support this feature.
const ContentData* contentData = style->contentData();
- if (contentData && !contentData->m_next && contentData->m_type == CONTENT_OBJECT && doc != node) {
+ if (contentData && !contentData->next() && contentData->isImage() && doc != node) {
RenderImageGeneratedContent* image = new (arena) RenderImageGeneratedContent(node);
image->setStyle(style);
- if (StyleImage* styleImage = contentData->m_content.m_image)
+ if (StyleImage* styleImage = contentData->image())
image->setStyleImage(styleImage);
return image;
}
@@ -175,8 +166,8 @@ RenderObject::RenderObject(Node* node)
, m_next(0)
#ifndef NDEBUG
, m_hasAXObject(false)
+ , m_setNeedsLayoutForbidden(false)
#endif
- , m_verticalPosition(PositionUndefined)
, m_needsLayout(false)
, m_needsPositionedMovementLayout(false)
, m_normalChildNeedsLayout(false)
@@ -188,6 +179,7 @@ RenderObject::RenderObject(Node* node)
, m_paintBackground(false)
, m_isAnonymous(node == node->document())
, m_isText(false)
+ , m_isBox(false)
, m_inline(true)
, m_replaced(false)
, m_isDragging(false)
@@ -198,10 +190,19 @@ RenderObject::RenderObject(Node* node)
, m_hasOverrideSize(false)
, m_hasCounterNodeMap(false)
, m_everHadLayout(false)
+ , m_childrenInline(false)
+ , m_topMarginQuirk(false)
+ , m_bottomMarginQuirk(false)
+ , m_hasMarkupTruncation(false)
+ , m_selectionState(SelectionNone)
+ , m_hasColumns(false)
+ , m_cellWidthChanged(false)
+ , m_replacedHasOverflow(false)
{
#ifndef NDEBUG
renderObjectCounter.increment();
#endif
+ ASSERT(node);
}
RenderObject::~RenderObject()
@@ -213,6 +214,13 @@ RenderObject::~RenderObject()
#endif
}
+RenderTheme* RenderObject::theme() const
+{
+ ASSERT(document()->page());
+
+ return document()->page()->theme();
+}
+
bool RenderObject::isDescendantOf(const RenderObject* obj) const
{
for (const RenderObject* r = this; r; r = r->m_parent) {
@@ -224,63 +232,95 @@ bool RenderObject::isDescendantOf(const RenderObject* obj) const
bool RenderObject::isBody() const
{
- return node()->hasTagName(bodyTag);
+ return node() && node()->hasTagName(bodyTag);
}
bool RenderObject::isHR() const
{
- return element() && element()->hasTagName(hrTag);
+ return node() && node()->hasTagName(hrTag);
}
bool RenderObject::isHTMLMarquee() const
{
- return element() && element()->renderer() == this && element()->hasTagName(marqueeTag);
-}
-
-bool RenderObject::canHaveChildren() const
-{
- return false;
-}
-
-RenderFlow* RenderObject::continuation() const
-{
- return 0;
+ return node() && node()->renderer() == this && node()->hasTagName(marqueeTag);
}
-bool RenderObject::isInlineContinuation() const
+static void updateListMarkerNumbers(RenderObject* child)
{
- return false;
+ for (RenderObject* r = child; r; r = r->nextSibling())
+ if (r->isListItem())
+ static_cast<RenderListItem*>(r)->updateValue();
}
-void RenderObject::addChild(RenderObject*, RenderObject*)
+void RenderObject::addChild(RenderObject* newChild, RenderObject* beforeChild)
{
- ASSERT_NOT_REACHED();
-}
-
-RenderObject* RenderObject::removeChildNode(RenderObject*, bool)
-{
- ASSERT_NOT_REACHED();
- return 0;
-}
-
-void RenderObject::removeChild(RenderObject*)
-{
- ASSERT_NOT_REACHED();
-}
+ RenderObjectChildList* children = virtualChildren();
+ ASSERT(children);
+ if (!children)
+ return;
-void RenderObject::moveChildNode(RenderObject*)
-{
- ASSERT_NOT_REACHED();
+ bool needsTable = false;
+
+ if (newChild->isListItem())
+ updateListMarkerNumbers(beforeChild ? beforeChild : children->lastChild());
+ else if (newChild->isTableCol() && newChild->style()->display() == TABLE_COLUMN_GROUP)
+ needsTable = !isTable();
+ else if (newChild->isRenderBlock() && newChild->style()->display() == TABLE_CAPTION)
+ needsTable = !isTable();
+ else if (newChild->isTableSection())
+ needsTable = !isTable();
+ else if (newChild->isTableRow())
+ needsTable = !isTableSection();
+ else if (newChild->isTableCell()) {
+ needsTable = !isTableRow();
+ // I'm not 100% sure this is the best way to fix this, but without this
+ // change we recurse infinitely when trying to render the CSS2 test page:
+ // http://www.bath.ac.uk/%7Epy8ieh/internet/eviltests/htmlbodyheadrendering2.html.
+ // See Radar 2925291.
+ if (needsTable && isTableCell() && !children->firstChild() && !newChild->isTableCell())
+ needsTable = false;
+ }
+
+ if (needsTable) {
+ RenderTable* table;
+ RenderObject* afterChild = beforeChild ? beforeChild->previousSibling() : children->lastChild();
+ if (afterChild && afterChild->isAnonymous() && afterChild->isTable())
+ table = static_cast<RenderTable*>(afterChild);
+ else {
+ table = new (renderArena()) RenderTable(document() /* is anonymous */);
+ RefPtr<RenderStyle> newStyle = RenderStyle::create();
+ newStyle->inheritFrom(style());
+ newStyle->setDisplay(TABLE);
+ table->setStyle(newStyle.release());
+ addChild(table, beforeChild);
+ }
+ table->addChild(newChild);
+ } else {
+ // Just add it...
+ children->insertChildNode(this, newChild, beforeChild);
+ }
+
+ if (newChild->isText() && newChild->style()->textTransform() == CAPITALIZE) {
+ RefPtr<StringImpl> textToTransform = toRenderText(newChild)->originalText();
+ if (textToTransform)
+ toRenderText(newChild)->setText(textToTransform.release(), true);
+ }
}
-void RenderObject::appendChildNode(RenderObject*, bool)
+void RenderObject::removeChild(RenderObject* oldChild)
{
- ASSERT_NOT_REACHED();
-}
+ RenderObjectChildList* children = virtualChildren();
+ ASSERT(children);
+ if (!children)
+ return;
-void RenderObject::insertChildNode(RenderObject*, RenderObject*, bool)
-{
- ASSERT_NOT_REACHED();
+ // We do this here instead of in removeChildNode, since the only extremely low-level uses of remove/appendChildNode
+ // cannot affect the positioned object list, and the floating object list is irrelevant (since the list gets cleared on
+ // layout anyway).
+ if (oldChild->isFloatingOrPositioned())
+ toRenderBox(oldChild)->removeFloatingOrPositionedChildFromBlockLists();
+
+ children->removeChildNode(this, oldChild);
}
RenderObject* RenderObject::nextInPreOrder() const
@@ -352,20 +392,6 @@ RenderObject* RenderObject::childAt(unsigned index) const
return child;
}
-bool RenderObject::isEditable() const
-{
- RenderText* textRenderer = 0;
- if (isText())
- textRenderer = static_cast<RenderText*>(const_cast<RenderObject*>(this));
-
- return style()->visibility() == VISIBLE &&
- element() && element()->isContentEditable() &&
- ((isBlockFlow() && !firstChild()) ||
- isReplaced() ||
- isBR() ||
- (textRenderer && textRenderer->firstTextBox()));
-}
-
RenderObject* RenderObject::firstLeafChild() const
{
RenderObject* r = firstChild();
@@ -403,7 +429,7 @@ static void addLayers(RenderObject* obj, RenderLayer* parentLayer, RenderObject*
beforeChild = newObject->parent()->findNextLayer(parentLayer, newObject);
newObject = 0;
}
- parentLayer->addChild(obj->layer(), beforeChild);
+ parentLayer->addChild(toRenderBoxModelObject(obj)->layer(), beforeChild);
return;
}
@@ -427,7 +453,7 @@ void RenderObject::removeLayers(RenderLayer* parentLayer)
return;
if (hasLayer()) {
- parentLayer->removeChild(layer());
+ parentLayer->removeChild(toRenderBoxModelObject(this)->layer());
return;
}
@@ -441,9 +467,11 @@ void RenderObject::moveLayers(RenderLayer* oldParent, RenderLayer* newParent)
return;
if (hasLayer()) {
+ RenderLayer* layer = toRenderBoxModelObject(this)->layer();
+ ASSERT(oldParent == layer->parent());
if (oldParent)
- oldParent->removeChild(layer());
- newParent->addChild(layer());
+ oldParent->removeChild(layer);
+ newParent->addChild(layer);
return;
}
@@ -459,7 +487,7 @@ RenderLayer* RenderObject::findNextLayer(RenderLayer* parentLayer, RenderObject*
return 0;
// Step 1: If our layer is a child of the desired parent, then return our layer.
- RenderLayer* ourLayer = layer();
+ RenderLayer* ourLayer = hasLayer() ? toRenderBoxModelObject(this)->layer() : 0;
if (ourLayer && ourLayer->parent() == parentLayer)
return ourLayer;
@@ -491,7 +519,7 @@ RenderLayer* RenderObject::enclosingLayer() const
{
const RenderObject* curr = this;
while (curr) {
- RenderLayer* layer = curr->layer();
+ RenderLayer* layer = curr->hasLayer() ? toRenderBoxModelObject(curr)->layer() : 0;
if (layer)
return layer;
curr = curr->parent();
@@ -499,190 +527,34 @@ RenderLayer* RenderObject::enclosingLayer() const
return 0;
}
-bool RenderObject::requiresLayer()
+RenderLayer* RenderObject::enclosingSelfPaintingLayer() const
{
- return isRoot() || isPositioned() || isRelPositioned() || isTransparent() || hasOverflowClip() || hasTransform() || hasMask() || hasReflection();
-}
-
-RenderBlock* RenderObject::firstLineBlock() const
-{
- return 0;
-}
-
-int RenderObject::offsetLeft() const
-{
- RenderObject* offsetPar = offsetParent();
- if (!offsetPar)
- return 0;
- int x = xPos() - offsetPar->borderLeft();
- if (!isPositioned()) {
- if (isRelPositioned())
- x += static_cast<const RenderBox*>(this)->relativePositionOffsetX();
- RenderObject* curr = parent();
- while (curr && curr != offsetPar) {
- x += curr->xPos();
- curr = curr->parent();
- }
- if (offsetPar->isBody() && !offsetPar->isRelPositioned() && !offsetPar->isPositioned())
- x += offsetPar->xPos();
- }
- return x;
-}
-
-int RenderObject::offsetTop() const
-{
- RenderObject* offsetPar = offsetParent();
- if (!offsetPar)
- return 0;
- int y = yPos() - borderTopExtra() - offsetPar->borderTop();
- if (!isPositioned()) {
- if (isRelPositioned())
- y += static_cast<const RenderBox*>(this)->relativePositionOffsetY();
- RenderObject* curr = parent();
- while (curr && curr != offsetPar) {
- if (!curr->isTableRow())
- y += curr->yPos();
- curr = curr->parent();
- }
- if (offsetPar->isBody() && !offsetPar->isRelPositioned() && !offsetPar->isPositioned())
- y += offsetPar->yPos();
+ const RenderObject* curr = this;
+ while (curr) {
+ RenderLayer* layer = curr->hasLayer() ? toRenderBoxModelObject(curr)->layer() : 0;
+ if (layer && layer->isSelfPaintingLayer())
+ return layer;
+ curr = curr->parent();
}
- return y;
+ return 0;
}
-RenderObject* RenderObject::offsetParent() const
+RenderBox* RenderObject::enclosingBox() const
{
- // FIXME: It feels like this function could almost be written using containing blocks.
- if (isBody())
- return 0;
-
- bool skipTables = isPositioned() || isRelPositioned();
- float currZoom = style()->effectiveZoom();
- RenderObject* curr = parent();
- while (curr && (!curr->element() ||
- (!curr->isPositioned() && !curr->isRelPositioned() && !curr->isBody()))) {
- Node* element = curr->element();
- if (!skipTables && element) {
- bool isTableElement = element->hasTagName(tableTag) ||
- element->hasTagName(tdTag) ||
- element->hasTagName(thTag);
-
-#if ENABLE(WML)
- if (!isTableElement && element->isWMLElement())
- isTableElement = element->hasTagName(WMLNames::tableTag) ||
- element->hasTagName(WMLNames::tdTag);
-#endif
-
- if (isTableElement)
- break;
- }
-
- float newZoom = curr->style()->effectiveZoom();
- if (currZoom != newZoom)
- break;
- currZoom = newZoom;
+ RenderObject* curr = const_cast<RenderObject*>(this);
+ while (curr) {
+ if (curr->isBox())
+ return toRenderBox(curr);
curr = curr->parent();
}
- return curr;
-}
-
-int RenderObject::verticalScrollbarWidth() const
-{
- return includeVerticalScrollbarSize() ? layer()->verticalScrollbarWidth() : 0;
-}
-
-int RenderObject::horizontalScrollbarHeight() const
-{
- return includeHorizontalScrollbarSize() ? layer()->horizontalScrollbarHeight() : 0;
-}
-
-// More IE extensions. clientWidth and clientHeight represent the interior of an object
-// excluding border and scrollbar.
-int RenderObject::clientWidth() const
-{
- return width() - borderLeft() - borderRight() - verticalScrollbarWidth();
-}
-
-int RenderObject::clientHeight() const
-{
- return height() - borderTop() - borderBottom() - horizontalScrollbarHeight();
-}
-
-// scrollWidth/scrollHeight will be the same as clientWidth/clientHeight unless the
-// object has overflow:hidden/scroll/auto specified and also has overflow.
-int RenderObject::scrollWidth() const
-{
- return hasOverflowClip() ? layer()->scrollWidth() : overflowWidth();
-}
-
-int RenderObject::scrollHeight() const
-{
- return hasOverflowClip() ? layer()->scrollHeight() : overflowHeight();
-}
-
-int RenderObject::scrollLeft() const
-{
- return hasOverflowClip() ? layer()->scrollXOffset() : 0;
-}
-
-int RenderObject::scrollTop() const
-{
- return hasOverflowClip() ? layer()->scrollYOffset() : 0;
-}
-
-void RenderObject::setScrollLeft(int newLeft)
-{
- if (hasOverflowClip())
- layer()->scrollToXOffset(newLeft);
-}
-
-void RenderObject::setScrollTop(int newTop)
-{
- if (hasOverflowClip())
- layer()->scrollToYOffset(newTop);
-}
-
-bool RenderObject::scroll(ScrollDirection direction, ScrollGranularity granularity, float multiplier)
-{
- RenderLayer* l = layer();
- if (l && l->scroll(direction, granularity, multiplier))
- return true;
- RenderBlock* b = containingBlock();
- if (b && !b->isRenderView())
- return b->scroll(direction, granularity, multiplier);
- return false;
-}
-bool RenderObject::canBeProgramaticallyScrolled(bool) const
-{
- if (!layer())
- return false;
-
- return (hasOverflowClip() && (scrollsOverflow() || (node() && node()->isContentEditable()))) || (node() && node()->isDocumentNode());
-}
-
-void RenderObject::autoscroll()
-{
- layer()->autoscroll();
-}
-
-void RenderObject::panScroll(const IntPoint& source)
-{
- layer()->panScrollFromPoint(source);
-}
-
-bool RenderObject::hasStaticX() const
-{
- return (style()->left().isAuto() && style()->right().isAuto()) || style()->left().isStatic() || style()->right().isStatic();
-}
-
-bool RenderObject::hasStaticY() const
-{
- return (style()->top().isAuto() && style()->bottom().isAuto()) || style()->top().isStatic();
+ ASSERT_NOT_REACHED();
+ return 0;
}
-void RenderObject::markAllDescendantsWithFloatsForLayout(RenderObject*)
+RenderBlock* RenderObject::firstLineBlock() const
{
+ return 0;
}
void RenderObject::setPrefWidthsDirty(bool b, bool markParents)
@@ -699,109 +571,25 @@ void RenderObject::invalidateContainerPrefWidths()
// in the chain that we mark dirty (even though they're kind of irrelevant).
RenderObject* o = isTableCell() ? containingBlock() : container();
while (o && !o->m_prefWidthsDirty) {
+ // Don't invalidate the outermost object of an unrooted subtree. That object will be
+ // invalidated when the subtree is added to the document.
+ RenderObject* container = o->isTableCell() ? o->containingBlock() : o->container();
+ if (!container && !o->isRenderView())
+ break;
+
o->m_prefWidthsDirty = true;
if (o->style()->position() == FixedPosition || o->style()->position() == AbsolutePosition)
// A positioned object has no effect on the min/max width of its containing block ever.
// We can optimize this case and not go up any further.
break;
- o = o->isTableCell() ? o->containingBlock() : o->container();
+ o = container;
}
}
-void RenderObject::setNeedsLayout(bool b, bool markParents)
+void RenderObject::setLayerNeedsFullRepaint()
{
- bool alreadyNeededLayout = m_needsLayout;
- m_needsLayout = b;
- if (b) {
- if (!alreadyNeededLayout) {
- if (markParents)
- markContainingBlocksForLayout();
- if (hasLayer())
- layer()->setNeedsFullRepaint();
- }
- } else {
- m_everHadLayout = true;
- m_posChildNeedsLayout = false;
- m_normalChildNeedsLayout = false;
- m_needsPositionedMovementLayout = false;
- }
-}
-
-void RenderObject::setChildNeedsLayout(bool b, bool markParents)
-{
- bool alreadyNeededLayout = m_normalChildNeedsLayout;
- m_normalChildNeedsLayout = b;
- if (b) {
- if (!alreadyNeededLayout && markParents)
- markContainingBlocksForLayout();
- } else {
- m_posChildNeedsLayout = false;
- m_normalChildNeedsLayout = false;
- m_needsPositionedMovementLayout = false;
- }
-}
-
-void RenderObject::setNeedsPositionedMovementLayout()
-{
- bool alreadyNeededLayout = needsLayout();
- m_needsPositionedMovementLayout = true;
- if (!alreadyNeededLayout) {
- markContainingBlocksForLayout();
- if (hasLayer())
- layer()->setNeedsFullRepaint();
- }
-}
-
-static inline bool objectIsRelayoutBoundary(const RenderObject *obj)
-{
- // FIXME: In future it may be possible to broaden this condition in order to improve performance.
- // Table cells are excluded because even when their CSS height is fixed, their height()
- // may depend on their contents.
- return obj->isTextField() || obj->isTextArea()
- || obj->hasOverflowClip() && !obj->style()->width().isIntrinsicOrAuto() && !obj->style()->height().isIntrinsicOrAuto() && !obj->style()->height().isPercent() && !obj->isTableCell()
-#if ENABLE(SVG)
- || obj->isSVGRoot()
-#endif
- ;
-}
-
-void RenderObject::markContainingBlocksForLayout(bool scheduleRelayout, RenderObject* newRoot)
-{
- ASSERT(!scheduleRelayout || !newRoot);
-
- RenderObject* o = container();
- RenderObject* last = this;
-
- while (o) {
- if (!last->isText() && (last->style()->position() == FixedPosition || last->style()->position() == AbsolutePosition)) {
- if (last->hasStaticY()) {
- RenderObject* parent = last->parent();
- if (!parent->normalChildNeedsLayout()) {
- parent->setChildNeedsLayout(true, false);
- if (parent != newRoot)
- parent->markContainingBlocksForLayout(scheduleRelayout, newRoot);
- }
- }
- if (o->m_posChildNeedsLayout)
- return;
- o->m_posChildNeedsLayout = true;
- } else {
- if (o->m_normalChildNeedsLayout)
- return;
- o->m_normalChildNeedsLayout = true;
- }
-
- if (o == newRoot)
- return;
-
- last = o;
- if (scheduleRelayout && objectIsRelayoutBoundary(last))
- break;
- o = o->container();
- }
-
- if (scheduleRelayout)
- last->scheduleRelayout();
+ ASSERT(hasLayer());
+ toRenderBoxModelObject(this)->layer()->setNeedsFullRepaint(true);
}
RenderBlock* RenderObject::containingBlock() const
@@ -814,7 +602,7 @@ RenderBlock* RenderObject::containingBlock() const
}
if (isRenderView())
- return const_cast<RenderBlock*>(static_cast<const RenderBlock*>(this));
+ return const_cast<RenderView*>(toRenderView(this));
RenderObject* o = parent();
if (!isText() && m_style->position() == FixedPosition) {
@@ -844,19 +632,7 @@ RenderBlock* RenderObject::containingBlock() const
if (!o || !o->isRenderBlock())
return 0; // Probably doesn't happen any more, but leave just in case. -dwh
- return static_cast<RenderBlock*>(o);
-}
-
-int RenderObject::containingBlockWidth() const
-{
- // FIXME ?
- return containingBlock()->availableWidth();
-}
-
-int RenderObject::containingBlockHeight() const
-{
- // FIXME ?
- return containingBlock()->contentHeight();
+ return toRenderBlock(o);
}
static bool mustRepaintFillLayers(const RenderObject* renderer, const FillLayer* layer)
@@ -867,13 +643,16 @@ static bool mustRepaintFillLayers(const RenderObject* renderer, const FillLayer*
// Make sure we have a valid image.
StyleImage* img = layer->image();
- bool shouldPaintBackgroundImage = img && img->canRender(renderer->style()->effectiveZoom());
+ if (!img || !img->canRender(renderer->style()->effectiveZoom()))
+ return false;
+
+ if (!layer->xPosition().isZero() || !layer->yPosition().isZero())
+ return true;
- // These are always percents or auto.
- if (shouldPaintBackgroundImage &&
- (!layer->xPosition().isZero() || !layer->yPosition().isZero() ||
- layer->size().width().isPercent() || layer->size().height().isPercent()))
- // The image will shift unpredictably if the size changes.
+ if (layer->isSizeSet()) {
+ if (layer->size().width().isPercent() || layer->size().height().isPercent())
+ return true;
+ } else if (img->usesImageContainerSize())
return true;
return false;
@@ -905,97 +684,9 @@ bool RenderObject::mustRepaintBackgroundOrBorder() const
return false;
}
-void RenderObject::drawBorderArc(GraphicsContext* graphicsContext, int x, int y, float thickness, IntSize radius,
- int angleStart, int angleSpan, BorderSide s, Color c, const Color& textColor,
- EBorderStyle style, bool firstCorner)
-{
- if ((style == DOUBLE && thickness / 2 < 3) || ((style == RIDGE || style == GROOVE) && thickness / 2 < 2))
- style = SOLID;
-
- if (!c.isValid()) {
- if (style == INSET || style == OUTSET || style == RIDGE || style == GROOVE)
- c.setRGB(238, 238, 238);
- else
- c = textColor;
- }
-
- switch (style) {
- case BNONE:
- case BHIDDEN:
- return;
- case DOTTED:
- case DASHED:
- graphicsContext->setStrokeColor(c);
- graphicsContext->setStrokeStyle(style == DOTTED ? DottedStroke : DashedStroke);
- graphicsContext->setStrokeThickness(thickness);
- graphicsContext->strokeArc(IntRect(x, y, radius.width() * 2, radius.height() * 2), angleStart, angleSpan);
- break;
- case DOUBLE: {
- float third = thickness / 3.0f;
- float innerThird = (thickness + 1.0f) / 6.0f;
- int shiftForInner = static_cast<int>(innerThird * 2.5f);
-
- int outerY = y;
- int outerHeight = radius.height() * 2;
- int innerX = x + shiftForInner;
- int innerY = y + shiftForInner;
- int innerWidth = (radius.width() - shiftForInner) * 2;
- int innerHeight = (radius.height() - shiftForInner) * 2;
- if (innerThird > 1 && (s == BSTop || (firstCorner && (s == BSLeft || s == BSRight)))) {
- outerHeight += 2;
- innerHeight += 2;
- }
-
- graphicsContext->setStrokeStyle(SolidStroke);
- graphicsContext->setStrokeColor(c);
- graphicsContext->setStrokeThickness(third);
- graphicsContext->strokeArc(IntRect(x, outerY, radius.width() * 2, outerHeight), angleStart, angleSpan);
- graphicsContext->setStrokeThickness(innerThird > 2 ? innerThird - 1 : innerThird);
- graphicsContext->strokeArc(IntRect(innerX, innerY, innerWidth, innerHeight), angleStart, angleSpan);
- break;
- }
- case GROOVE:
- case RIDGE: {
- Color c2;
- if ((style == RIDGE && (s == BSTop || s == BSLeft)) ||
- (style == GROOVE && (s == BSBottom || s == BSRight)))
- c2 = c.dark();
- else {
- c2 = c;
- c = c.dark();
- }
-
- graphicsContext->setStrokeStyle(SolidStroke);
- graphicsContext->setStrokeColor(c);
- graphicsContext->setStrokeThickness(thickness);
- graphicsContext->strokeArc(IntRect(x, y, radius.width() * 2, radius.height() * 2), angleStart, angleSpan);
-
- float halfThickness = (thickness + 1.0f) / 4.0f;
- int shiftForInner = static_cast<int>(halfThickness * 1.5f);
- graphicsContext->setStrokeColor(c2);
- graphicsContext->setStrokeThickness(halfThickness > 2 ? halfThickness - 1 : halfThickness);
- graphicsContext->strokeArc(IntRect(x + shiftForInner, y + shiftForInner, (radius.width() - shiftForInner) * 2,
- (radius.height() - shiftForInner) * 2), angleStart, angleSpan);
- break;
- }
- case INSET:
- if (s == BSTop || s == BSLeft)
- c = c.dark();
- case OUTSET:
- if (style == OUTSET && (s == BSBottom || s == BSRight))
- c = c.dark();
- case SOLID:
- graphicsContext->setStrokeStyle(SolidStroke);
- graphicsContext->setStrokeColor(c);
- graphicsContext->setStrokeThickness(thickness);
- graphicsContext->strokeArc(IntRect(x, y, radius.width() * 2, radius.height() * 2), angleStart, angleSpan);
- break;
- }
-}
-
-void RenderObject::drawBorder(GraphicsContext* graphicsContext, int x1, int y1, int x2, int y2,
- BorderSide s, Color c, const Color& textcolor, EBorderStyle style,
- int adjbw1, int adjbw2)
+void RenderObject::drawLineForBoxSide(GraphicsContext* graphicsContext, int x1, int y1, int x2, int y2,
+ BoxSide s, Color c, const Color& textcolor, EBorderStyle style,
+ int adjbw1, int adjbw2)
{
int width = (s == BSTop || s == BSBottom ? y2 - y1 : x2 - x1);
@@ -1058,34 +749,34 @@ void RenderObject::drawBorder(GraphicsContext* graphicsContext, int x1, int y1,
switch (s) {
case BSTop:
- drawBorder(graphicsContext, x1 + max((-adjbw1 * 2 + 1) / 3, 0),
+ drawLineForBoxSide(graphicsContext, x1 + max((-adjbw1 * 2 + 1) / 3, 0),
y1, x2 - max((-adjbw2 * 2 + 1) / 3, 0), y1 + third,
s, c, textcolor, SOLID, adjbw1bigthird, adjbw2bigthird);
- drawBorder(graphicsContext, x1 + max((adjbw1 * 2 + 1) / 3, 0),
+ drawLineForBoxSide(graphicsContext, x1 + max((adjbw1 * 2 + 1) / 3, 0),
y2 - third, x2 - max((adjbw2 * 2 + 1) / 3, 0), y2,
s, c, textcolor, SOLID, adjbw1bigthird, adjbw2bigthird);
break;
case BSLeft:
- drawBorder(graphicsContext, x1, y1 + max((-adjbw1 * 2 + 1) / 3, 0),
+ drawLineForBoxSide(graphicsContext, x1, y1 + max((-adjbw1 * 2 + 1) / 3, 0),
x1 + third, y2 - max((-adjbw2 * 2 + 1) / 3, 0),
s, c, textcolor, SOLID, adjbw1bigthird, adjbw2bigthird);
- drawBorder(graphicsContext, x2 - third, y1 + max((adjbw1 * 2 + 1) / 3, 0),
+ drawLineForBoxSide(graphicsContext, x2 - third, y1 + max((adjbw1 * 2 + 1) / 3, 0),
x2, y2 - max((adjbw2 * 2 + 1) / 3, 0),
s, c, textcolor, SOLID, adjbw1bigthird, adjbw2bigthird);
break;
case BSBottom:
- drawBorder(graphicsContext, x1 + max((adjbw1 * 2 + 1) / 3, 0),
+ drawLineForBoxSide(graphicsContext, x1 + max((adjbw1 * 2 + 1) / 3, 0),
y1, x2 - max((adjbw2 * 2 + 1) / 3, 0), y1 + third,
s, c, textcolor, SOLID, adjbw1bigthird, adjbw2bigthird);
- drawBorder(graphicsContext, x1 + max((-adjbw1 * 2 + 1) / 3, 0),
+ drawLineForBoxSide(graphicsContext, x1 + max((-adjbw1 * 2 + 1) / 3, 0),
y2 - third, x2 - max((-adjbw2 * 2 + 1) / 3, 0), y2,
s, c, textcolor, SOLID, adjbw1bigthird, adjbw2bigthird);
break;
case BSRight:
- drawBorder(graphicsContext, x1, y1 + max((adjbw1 * 2 + 1) / 3, 0),
+ drawLineForBoxSide(graphicsContext, x1, y1 + max((adjbw1 * 2 + 1) / 3, 0),
x1 + third, y2 - max(( adjbw2 * 2 + 1) / 3, 0),
s, c, textcolor, SOLID, adjbw1bigthird, adjbw2bigthird);
- drawBorder(graphicsContext, x2 - third, y1 + max((-adjbw1 * 2 + 1) / 3, 0),
+ drawLineForBoxSide(graphicsContext, x2 - third, y1 + max((-adjbw1 * 2 + 1) / 3, 0),
x2, y2 - max((-adjbw2 * 2 + 1) / 3, 0),
s, c, textcolor, SOLID, adjbw1bigthird, adjbw2bigthird);
break;
@@ -1113,27 +804,27 @@ void RenderObject::drawBorder(GraphicsContext* graphicsContext, int x1, int y1,
switch (s) {
case BSTop:
- drawBorder(graphicsContext, x1 + max(-adjbw1, 0) / 2, y1, x2 - max(-adjbw2, 0) / 2, (y1 + y2 + 1) / 2,
+ drawLineForBoxSide(graphicsContext, x1 + max(-adjbw1, 0) / 2, y1, x2 - max(-adjbw2, 0) / 2, (y1 + y2 + 1) / 2,
s, c, textcolor, s1, adjbw1bighalf, adjbw2bighalf);
- drawBorder(graphicsContext, x1 + max(adjbw1 + 1, 0) / 2, (y1 + y2 + 1) / 2, x2 - max(adjbw2 + 1, 0) / 2, y2,
+ drawLineForBoxSide(graphicsContext, x1 + max(adjbw1 + 1, 0) / 2, (y1 + y2 + 1) / 2, x2 - max(adjbw2 + 1, 0) / 2, y2,
s, c, textcolor, s2, adjbw1 / 2, adjbw2 / 2);
break;
case BSLeft:
- drawBorder(graphicsContext, x1, y1 + max(-adjbw1, 0) / 2, (x1 + x2 + 1) / 2, y2 - max(-adjbw2, 0) / 2,
+ drawLineForBoxSide(graphicsContext, x1, y1 + max(-adjbw1, 0) / 2, (x1 + x2 + 1) / 2, y2 - max(-adjbw2, 0) / 2,
s, c, textcolor, s1, adjbw1bighalf, adjbw2bighalf);
- drawBorder(graphicsContext, (x1 + x2 + 1) / 2, y1 + max(adjbw1 + 1, 0) / 2, x2, y2 - max(adjbw2 + 1, 0) / 2,
+ drawLineForBoxSide(graphicsContext, (x1 + x2 + 1) / 2, y1 + max(adjbw1 + 1, 0) / 2, x2, y2 - max(adjbw2 + 1, 0) / 2,
s, c, textcolor, s2, adjbw1 / 2, adjbw2 / 2);
break;
case BSBottom:
- drawBorder(graphicsContext, x1 + max(adjbw1, 0) / 2, y1, x2 - max(adjbw2, 0) / 2, (y1 + y2 + 1) / 2,
+ drawLineForBoxSide(graphicsContext, x1 + max(adjbw1, 0) / 2, y1, x2 - max(adjbw2, 0) / 2, (y1 + y2 + 1) / 2,
s, c, textcolor, s2, adjbw1bighalf, adjbw2bighalf);
- drawBorder(graphicsContext, x1 + max(-adjbw1 + 1, 0) / 2, (y1 + y2 + 1) / 2, x2 - max(-adjbw2 + 1, 0) / 2, y2,
+ drawLineForBoxSide(graphicsContext, x1 + max(-adjbw1 + 1, 0) / 2, (y1 + y2 + 1) / 2, x2 - max(-adjbw2 + 1, 0) / 2, y2,
s, c, textcolor, s1, adjbw1/2, adjbw2/2);
break;
case BSRight:
- drawBorder(graphicsContext, x1, y1 + max(adjbw1, 0) / 2, (x1 + x2 + 1) / 2, y2 - max(adjbw2, 0) / 2,
+ drawLineForBoxSide(graphicsContext, x1, y1 + max(adjbw1, 0) / 2, (x1 + x2 + 1) / 2, y2 - max(adjbw2, 0) / 2,
s, c, textcolor, s2, adjbw1bighalf, adjbw2bighalf);
- drawBorder(graphicsContext, (x1 + x2 + 1) / 2, y1 + max(-adjbw1 + 1, 0) / 2, x2, y2 - max(-adjbw2 + 1, 0) / 2,
+ drawLineForBoxSide(graphicsContext, (x1 + x2 + 1) / 2, y1 + max(-adjbw1 + 1, 0) / 2, x2, y2 - max(-adjbw2 + 1, 0) / 2,
s, c, textcolor, s1, adjbw1/2, adjbw2/2);
break;
}
@@ -1189,536 +880,156 @@ void RenderObject::drawBorder(GraphicsContext* graphicsContext, int x1, int y1,
}
}
-bool RenderObject::paintNinePieceImage(GraphicsContext* graphicsContext, int tx, int ty, int w, int h, const RenderStyle* style,
- const NinePieceImage& ninePieceImage, CompositeOperator op)
+void RenderObject::drawArcForBoxSide(GraphicsContext* graphicsContext, int x, int y, float thickness, IntSize radius,
+ int angleStart, int angleSpan, BoxSide s, Color c, const Color& textColor,
+ EBorderStyle style, bool firstCorner)
{
- StyleImage* styleImage = ninePieceImage.image();
- if (!styleImage || !styleImage->canRender(style->effectiveZoom()))
- return false;
-
- if (!styleImage->isLoaded())
- return true; // Never paint a nine-piece image incrementally, but don't paint the fallback borders either.
-
- // If we have a border radius, the image gets clipped to the rounded rect.
- bool clipped = false;
- if (style->hasBorderRadius()) {
- IntRect clipRect(tx, ty, w, h);
- graphicsContext->save();
- graphicsContext->addRoundedRectClip(clipRect, style->borderTopLeftRadius(), style->borderTopRightRadius(),
- style->borderBottomLeftRadius(), style->borderBottomRightRadius());
- clipped = true;
- }
-
- // FIXME: border-image is broken with full page zooming when tiling has to happen, since the tiling function
- // doesn't have any understanding of the zoom that is in effect on the tile.
- styleImage->setImageContainerSize(IntSize(w, h));
- IntSize imageSize = styleImage->imageSize(this, 1.0f);
- int imageWidth = imageSize.width();
- int imageHeight = imageSize.height();
-
- int topSlice = min(imageHeight, ninePieceImage.m_slices.top().calcValue(imageHeight));
- int bottomSlice = min(imageHeight, ninePieceImage.m_slices.bottom().calcValue(imageHeight));
- int leftSlice = min(imageWidth, ninePieceImage.m_slices.left().calcValue(imageWidth));
- int rightSlice = min(imageWidth, ninePieceImage.m_slices.right().calcValue(imageWidth));
-
- ENinePieceImageRule hRule = ninePieceImage.horizontalRule();
- ENinePieceImageRule vRule = ninePieceImage.verticalRule();
-
- bool fitToBorder = style->borderImage() == ninePieceImage;
-
- int leftWidth = fitToBorder ? style->borderLeftWidth() : leftSlice;
- int topWidth = fitToBorder ? style->borderTopWidth() : topSlice;
- int rightWidth = fitToBorder ? style->borderRightWidth() : rightSlice;
- int bottomWidth = fitToBorder ? style->borderBottomWidth() : bottomSlice;
-
- bool drawLeft = leftSlice > 0 && leftWidth > 0;
- bool drawTop = topSlice > 0 && topWidth > 0;
- bool drawRight = rightSlice > 0 && rightWidth > 0;
- bool drawBottom = bottomSlice > 0 && bottomWidth > 0;
- bool drawMiddle = (imageWidth - leftSlice - rightSlice) > 0 && (w - leftWidth - rightWidth) > 0 &&
- (imageHeight - topSlice - bottomSlice) > 0 && (h - topWidth - bottomWidth) > 0;
-
- Image* image = styleImage->image(this, imageSize);
-
- if (drawLeft) {
- // Paint the top and bottom left corners.
-
- // The top left corner rect is (tx, ty, leftWidth, topWidth)
- // The rect to use from within the image is obtained from our slice, and is (0, 0, leftSlice, topSlice)
- if (drawTop)
- graphicsContext->drawImage(image, IntRect(tx, ty, leftWidth, topWidth),
- IntRect(0, 0, leftSlice, topSlice), op);
-
- // The bottom left corner rect is (tx, ty + h - bottomWidth, leftWidth, bottomWidth)
- // The rect to use from within the image is (0, imageHeight - bottomSlice, leftSlice, botomSlice)
- if (drawBottom)
- graphicsContext->drawImage(image, IntRect(tx, ty + h - bottomWidth, leftWidth, bottomWidth),
- IntRect(0, imageHeight - bottomSlice, leftSlice, bottomSlice), op);
-
- // Paint the left edge.
- // Have to scale and tile into the border rect.
- graphicsContext->drawTiledImage(image, IntRect(tx, ty + topWidth, leftWidth,
- h - topWidth - bottomWidth),
- IntRect(0, topSlice, leftSlice, imageHeight - topSlice - bottomSlice),
- Image::StretchTile, (Image::TileRule)vRule, op);
- }
-
- if (drawRight) {
- // Paint the top and bottom right corners
- // The top right corner rect is (tx + w - rightWidth, ty, rightWidth, topWidth)
- // The rect to use from within the image is obtained from our slice, and is (imageWidth - rightSlice, 0, rightSlice, topSlice)
- if (drawTop)
- graphicsContext->drawImage(image, IntRect(tx + w - rightWidth, ty, rightWidth, topWidth),
- IntRect(imageWidth - rightSlice, 0, rightSlice, topSlice), op);
-
- // The bottom right corner rect is (tx + w - rightWidth, ty + h - bottomWidth, rightWidth, bottomWidth)
- // The rect to use from within the image is (imageWidth - rightSlice, imageHeight - bottomSlice, rightSlice, bottomSlice)
- if (drawBottom)
- graphicsContext->drawImage(image, IntRect(tx + w - rightWidth, ty + h - bottomWidth, rightWidth, bottomWidth),
- IntRect(imageWidth - rightSlice, imageHeight - bottomSlice, rightSlice, bottomSlice), op);
-
- // Paint the right edge.
- graphicsContext->drawTiledImage(image, IntRect(tx + w - rightWidth, ty + topWidth, rightWidth,
- h - topWidth - bottomWidth),
- IntRect(imageWidth - rightSlice, topSlice, rightSlice, imageHeight - topSlice - bottomSlice),
- Image::StretchTile, (Image::TileRule)vRule, op);
- }
-
- // Paint the top edge.
- if (drawTop)
- graphicsContext->drawTiledImage(image, IntRect(tx + leftWidth, ty, w - leftWidth - rightWidth, topWidth),
- IntRect(leftSlice, 0, imageWidth - rightSlice - leftSlice, topSlice),
- (Image::TileRule)hRule, Image::StretchTile, op);
-
- // Paint the bottom edge.
- if (drawBottom)
- graphicsContext->drawTiledImage(image, IntRect(tx + leftWidth, ty + h - bottomWidth,
- w - leftWidth - rightWidth, bottomWidth),
- IntRect(leftSlice, imageHeight - bottomSlice, imageWidth - rightSlice - leftSlice, bottomSlice),
- (Image::TileRule)hRule, Image::StretchTile, op);
-
- // Paint the middle.
- if (drawMiddle)
- graphicsContext->drawTiledImage(image, IntRect(tx + leftWidth, ty + topWidth, w - leftWidth - rightWidth,
- h - topWidth - bottomWidth),
- IntRect(leftSlice, topSlice, imageWidth - rightSlice - leftSlice, imageHeight - topSlice - bottomSlice),
- (Image::TileRule)hRule, (Image::TileRule)vRule, op);
-
- // Clear the clip for the border radius.
- if (clipped)
- graphicsContext->restore();
-
- return true;
-}
-
-void RenderObject::paintBorder(GraphicsContext* graphicsContext, int tx, int ty, int w, int h,
- const RenderStyle* style, bool begin, bool end)
-{
- if (paintNinePieceImage(graphicsContext, tx, ty, w, h, style, style->borderImage()))
- return;
-
- const Color& tc = style->borderTopColor();
- const Color& bc = style->borderBottomColor();
- const Color& lc = style->borderLeftColor();
- const Color& rc = style->borderRightColor();
-
- bool tt = style->borderTopIsTransparent();
- bool bt = style->borderBottomIsTransparent();
- bool rt = style->borderRightIsTransparent();
- bool lt = style->borderLeftIsTransparent();
-
- EBorderStyle ts = style->borderTopStyle();
- EBorderStyle bs = style->borderBottomStyle();
- EBorderStyle ls = style->borderLeftStyle();
- EBorderStyle rs = style->borderRightStyle();
-
- bool renderTop = ts > BHIDDEN && !tt;
- bool renderLeft = ls > BHIDDEN && begin && !lt;
- bool renderRight = rs > BHIDDEN && end && !rt;
- bool renderBottom = bs > BHIDDEN && !bt;
-
- // Need sufficient width and height to contain border radius curves. Sanity check our border radii
- // and our width/height values to make sure the curves can all fit. If not, then we won't paint
- // any border radii.
- bool renderRadii = false;
- IntSize topLeft = style->borderTopLeftRadius();
- IntSize topRight = style->borderTopRightRadius();
- IntSize bottomLeft = style->borderBottomLeftRadius();
- IntSize bottomRight = style->borderBottomRightRadius();
-
- if (style->hasBorderRadius() &&
- static_cast<unsigned>(w) >= static_cast<unsigned>(topLeft.width()) + static_cast<unsigned>(topRight.width()) &&
- static_cast<unsigned>(w) >= static_cast<unsigned>(bottomLeft.width()) + static_cast<unsigned>(bottomRight.width()) &&
- static_cast<unsigned>(h) >= static_cast<unsigned>(topLeft.height()) + static_cast<unsigned>(bottomLeft.height()) &&
- static_cast<unsigned>(h) >= static_cast<unsigned>(topRight.height()) + static_cast<unsigned>(bottomRight.height()))
- renderRadii = true;
-
- // Clip to the rounded rectangle.
- if (renderRadii) {
- graphicsContext->save();
- graphicsContext->addRoundedRectClip(IntRect(tx, ty, w, h), topLeft, topRight, bottomLeft, bottomRight);
- }
-
- int firstAngleStart, secondAngleStart, firstAngleSpan, secondAngleSpan;
- float thickness;
- bool upperLeftBorderStylesMatch = renderLeft && (ts == ls) && (tc == lc);
- bool upperRightBorderStylesMatch = renderRight && (ts == rs) && (tc == rc) && (ts != OUTSET) && (ts != RIDGE) && (ts != INSET) && (ts != GROOVE);
- bool lowerLeftBorderStylesMatch = renderLeft && (bs == ls) && (bc == lc) && (bs != OUTSET) && (bs != RIDGE) && (bs != INSET) && (bs != GROOVE);
- bool lowerRightBorderStylesMatch = renderRight && (bs == rs) && (bc == rc);
-
- if (renderTop) {
- bool ignore_left = (renderRadii && topLeft.width() > 0) ||
- (tc == lc && tt == lt && ts >= OUTSET &&
- (ls == DOTTED || ls == DASHED || ls == SOLID || ls == OUTSET));
-
- bool ignore_right = (renderRadii && topRight.width() > 0) ||
- (tc == rc && tt == rt && ts >= OUTSET &&
- (rs == DOTTED || rs == DASHED || rs == SOLID || rs == INSET));
-
- int x = tx;
- int x2 = tx + w;
- if (renderRadii) {
- x += topLeft.width();
- x2 -= topRight.width();
- }
-
- drawBorder(graphicsContext, x, ty, x2, ty + style->borderTopWidth(), BSTop, tc, style->color(), ts,
- ignore_left ? 0 : style->borderLeftWidth(), ignore_right ? 0 : style->borderRightWidth());
-
- if (renderRadii) {
- int leftY = ty;
-
- // We make the arc double thick and let the clip rect take care of clipping the extra off.
- // We're doing this because it doesn't seem possible to match the curve of the clip exactly
- // with the arc-drawing function.
- thickness = style->borderTopWidth() * 2;
-
- if (topLeft.width()) {
- int leftX = tx;
- // The inner clip clips inside the arc. This is especially important for 1px borders.
- bool applyLeftInnerClip = (style->borderLeftWidth() < topLeft.width())
- && (style->borderTopWidth() < topLeft.height())
- && (ts != DOUBLE || style->borderTopWidth() > 6);
- if (applyLeftInnerClip) {
- graphicsContext->save();
- graphicsContext->addInnerRoundedRectClip(IntRect(leftX, leftY, topLeft.width() * 2, topLeft.height() * 2),
- style->borderTopWidth());
- }
-
- firstAngleStart = 90;
- firstAngleSpan = upperLeftBorderStylesMatch ? 90 : 45;
-
- // Draw upper left arc
- drawBorderArc(graphicsContext, leftX, leftY, thickness, topLeft, firstAngleStart, firstAngleSpan,
- BSTop, tc, style->color(), ts, true);
- if (applyLeftInnerClip)
- graphicsContext->restore();
- }
-
- if (topRight.width()) {
- int rightX = tx + w - topRight.width() * 2;
- bool applyRightInnerClip = (style->borderRightWidth() < topRight.width())
- && (style->borderTopWidth() < topRight.height())
- && (ts != DOUBLE || style->borderTopWidth() > 6);
- if (applyRightInnerClip) {
- graphicsContext->save();
- graphicsContext->addInnerRoundedRectClip(IntRect(rightX, leftY, topRight.width() * 2, topRight.height() * 2),
- style->borderTopWidth());
- }
-
- if (upperRightBorderStylesMatch) {
- secondAngleStart = 0;
- secondAngleSpan = 90;
- } else {
- secondAngleStart = 45;
- secondAngleSpan = 45;
- }
+ if ((style == DOUBLE && thickness / 2 < 3) || ((style == RIDGE || style == GROOVE) && thickness / 2 < 2))
+ style = SOLID;
- // Draw upper right arc
- drawBorderArc(graphicsContext, rightX, leftY, thickness, topRight, secondAngleStart, secondAngleSpan,
- BSTop, tc, style->color(), ts, false);
- if (applyRightInnerClip)
- graphicsContext->restore();
- }
- }
+ if (!c.isValid()) {
+ if (style == INSET || style == OUTSET || style == RIDGE || style == GROOVE)
+ c.setRGB(238, 238, 238);
+ else
+ c = textColor;
}
- if (renderBottom) {
- bool ignore_left = (renderRadii && bottomLeft.width() > 0) ||
- (bc == lc && bt == lt && bs >= OUTSET &&
- (ls == DOTTED || ls == DASHED || ls == SOLID || ls == OUTSET));
-
- bool ignore_right = (renderRadii && bottomRight.width() > 0) ||
- (bc == rc && bt == rt && bs >= OUTSET &&
- (rs == DOTTED || rs == DASHED || rs == SOLID || rs == INSET));
-
- int x = tx;
- int x2 = tx + w;
- if (renderRadii) {
- x += bottomLeft.width();
- x2 -= bottomRight.width();
- }
-
- drawBorder(graphicsContext, x, ty + h - style->borderBottomWidth(), x2, ty + h, BSBottom, bc, style->color(), bs,
- ignore_left ? 0 : style->borderLeftWidth(), ignore_right ? 0 : style->borderRightWidth());
-
- if (renderRadii) {
- thickness = style->borderBottomWidth() * 2;
-
- if (bottomLeft.width()) {
- int leftX = tx;
- int leftY = ty + h - bottomLeft.height() * 2;
- bool applyLeftInnerClip = (style->borderLeftWidth() < bottomLeft.width())
- && (style->borderBottomWidth() < bottomLeft.height())
- && (bs != DOUBLE || style->borderBottomWidth() > 6);
- if (applyLeftInnerClip) {
- graphicsContext->save();
- graphicsContext->addInnerRoundedRectClip(IntRect(leftX, leftY, bottomLeft.width() * 2, bottomLeft.height() * 2),
- style->borderBottomWidth());
- }
-
- if (lowerLeftBorderStylesMatch) {
- firstAngleStart = 180;
- firstAngleSpan = 90;
- } else {
- firstAngleStart = 225;
- firstAngleSpan = 45;
- }
-
- // Draw lower left arc
- drawBorderArc(graphicsContext, leftX, leftY, thickness, bottomLeft, firstAngleStart, firstAngleSpan,
- BSBottom, bc, style->color(), bs, true);
- if (applyLeftInnerClip)
- graphicsContext->restore();
- }
-
- if (bottomRight.width()) {
- int rightY = ty + h - bottomRight.height() * 2;
- int rightX = tx + w - bottomRight.width() * 2;
- bool applyRightInnerClip = (style->borderRightWidth() < bottomRight.width())
- && (style->borderBottomWidth() < bottomRight.height())
- && (bs != DOUBLE || style->borderBottomWidth() > 6);
- if (applyRightInnerClip) {
- graphicsContext->save();
- graphicsContext->addInnerRoundedRectClip(IntRect(rightX, rightY, bottomRight.width() * 2, bottomRight.height() * 2),
- style->borderBottomWidth());
- }
-
- secondAngleStart = 270;
- secondAngleSpan = lowerRightBorderStylesMatch ? 90 : 45;
+ switch (style) {
+ case BNONE:
+ case BHIDDEN:
+ return;
+ case DOTTED:
+ case DASHED:
+ graphicsContext->setStrokeColor(c);
+ graphicsContext->setStrokeStyle(style == DOTTED ? DottedStroke : DashedStroke);
+ graphicsContext->setStrokeThickness(thickness);
+ graphicsContext->strokeArc(IntRect(x, y, radius.width() * 2, radius.height() * 2), angleStart, angleSpan);
+ break;
+ case DOUBLE: {
+ float third = thickness / 3.0f;
+ float innerThird = (thickness + 1.0f) / 6.0f;
+ int shiftForInner = static_cast<int>(innerThird * 2.5f);
- // Draw lower right arc
- drawBorderArc(graphicsContext, rightX, rightY, thickness, bottomRight, secondAngleStart, secondAngleSpan,
- BSBottom, bc, style->color(), bs, false);
- if (applyRightInnerClip)
- graphicsContext->restore();
+ int outerY = y;
+ int outerHeight = radius.height() * 2;
+ int innerX = x + shiftForInner;
+ int innerY = y + shiftForInner;
+ int innerWidth = (radius.width() - shiftForInner) * 2;
+ int innerHeight = (radius.height() - shiftForInner) * 2;
+ if (innerThird > 1 && (s == BSTop || (firstCorner && (s == BSLeft || s == BSRight)))) {
+ outerHeight += 2;
+ innerHeight += 2;
}
- }
- }
-
- if (renderLeft) {
- bool ignore_top = (renderRadii && topLeft.height() > 0) ||
- (tc == lc && tt == lt && ls >= OUTSET &&
- (ts == DOTTED || ts == DASHED || ts == SOLID || ts == OUTSET));
- bool ignore_bottom = (renderRadii && bottomLeft.height() > 0) ||
- (bc == lc && bt == lt && ls >= OUTSET &&
- (bs == DOTTED || bs == DASHED || bs == SOLID || bs == INSET));
-
- int y = ty;
- int y2 = ty + h;
- if (renderRadii) {
- y += topLeft.height();
- y2 -= bottomLeft.height();
+ graphicsContext->setStrokeStyle(SolidStroke);
+ graphicsContext->setStrokeColor(c);
+ graphicsContext->setStrokeThickness(third);
+ graphicsContext->strokeArc(IntRect(x, outerY, radius.width() * 2, outerHeight), angleStart, angleSpan);
+ graphicsContext->setStrokeThickness(innerThird > 2 ? innerThird - 1 : innerThird);
+ graphicsContext->strokeArc(IntRect(innerX, innerY, innerWidth, innerHeight), angleStart, angleSpan);
+ break;
}
-
- drawBorder(graphicsContext, tx, y, tx + style->borderLeftWidth(), y2, BSLeft, lc, style->color(), ls,
- ignore_top ? 0 : style->borderTopWidth(), ignore_bottom ? 0 : style->borderBottomWidth());
-
- if (renderRadii && (!upperLeftBorderStylesMatch || !lowerLeftBorderStylesMatch)) {
- int topX = tx;
- thickness = style->borderLeftWidth() * 2;
-
- if (!upperLeftBorderStylesMatch && topLeft.width()) {
- int topY = ty;
- bool applyTopInnerClip = (style->borderLeftWidth() < topLeft.width())
- && (style->borderTopWidth() < topLeft.height())
- && (ls != DOUBLE || style->borderLeftWidth() > 6);
- if (applyTopInnerClip) {
- graphicsContext->save();
- graphicsContext->addInnerRoundedRectClip(IntRect(topX, topY, topLeft.width() * 2, topLeft.height() * 2),
- style->borderLeftWidth());
- }
-
- firstAngleStart = 135;
- firstAngleSpan = 45;
-
- // Draw top left arc
- drawBorderArc(graphicsContext, topX, topY, thickness, topLeft, firstAngleStart, firstAngleSpan,
- BSLeft, lc, style->color(), ls, true);
- if (applyTopInnerClip)
- graphicsContext->restore();
+ case GROOVE:
+ case RIDGE: {
+ Color c2;
+ if ((style == RIDGE && (s == BSTop || s == BSLeft)) ||
+ (style == GROOVE && (s == BSBottom || s == BSRight)))
+ c2 = c.dark();
+ else {
+ c2 = c;
+ c = c.dark();
}
- if (!lowerLeftBorderStylesMatch && bottomLeft.width()) {
- int bottomY = ty + h - bottomLeft.height() * 2;
- bool applyBottomInnerClip = (style->borderLeftWidth() < bottomLeft.width())
- && (style->borderBottomWidth() < bottomLeft.height())
- && (ls != DOUBLE || style->borderLeftWidth() > 6);
- if (applyBottomInnerClip) {
- graphicsContext->save();
- graphicsContext->addInnerRoundedRectClip(IntRect(topX, bottomY, bottomLeft.width() * 2, bottomLeft.height() * 2),
- style->borderLeftWidth());
- }
-
- secondAngleStart = 180;
- secondAngleSpan = 45;
+ graphicsContext->setStrokeStyle(SolidStroke);
+ graphicsContext->setStrokeColor(c);
+ graphicsContext->setStrokeThickness(thickness);
+ graphicsContext->strokeArc(IntRect(x, y, radius.width() * 2, radius.height() * 2), angleStart, angleSpan);
- // Draw bottom left arc
- drawBorderArc(graphicsContext, topX, bottomY, thickness, bottomLeft, secondAngleStart, secondAngleSpan,
- BSLeft, lc, style->color(), ls, false);
- if (applyBottomInnerClip)
- graphicsContext->restore();
- }
+ float halfThickness = (thickness + 1.0f) / 4.0f;
+ int shiftForInner = static_cast<int>(halfThickness * 1.5f);
+ graphicsContext->setStrokeColor(c2);
+ graphicsContext->setStrokeThickness(halfThickness > 2 ? halfThickness - 1 : halfThickness);
+ graphicsContext->strokeArc(IntRect(x + shiftForInner, y + shiftForInner, (radius.width() - shiftForInner) * 2,
+ (radius.height() - shiftForInner) * 2), angleStart, angleSpan);
+ break;
}
+ case INSET:
+ if (s == BSTop || s == BSLeft)
+ c = c.dark();
+ case OUTSET:
+ if (style == OUTSET && (s == BSBottom || s == BSRight))
+ c = c.dark();
+ case SOLID:
+ graphicsContext->setStrokeStyle(SolidStroke);
+ graphicsContext->setStrokeColor(c);
+ graphicsContext->setStrokeThickness(thickness);
+ graphicsContext->strokeArc(IntRect(x, y, radius.width() * 2, radius.height() * 2), angleStart, angleSpan);
+ break;
}
+}
- if (renderRight) {
- bool ignore_top = (renderRadii && topRight.height() > 0) ||
- ((tc == rc) && (tt == rt) &&
- (rs >= DOTTED || rs == INSET) &&
- (ts == DOTTED || ts == DASHED || ts == SOLID || ts == OUTSET));
-
- bool ignore_bottom = (renderRadii && bottomRight.height() > 0) ||
- ((bc == rc) && (bt == rt) &&
- (rs >= DOTTED || rs == INSET) &&
- (bs == DOTTED || bs == DASHED || bs == SOLID || bs == INSET));
-
- int y = ty;
- int y2 = ty + h;
- if (renderRadii) {
- y += topRight.height();
- y2 -= bottomRight.height();
- }
-
- drawBorder(graphicsContext, tx + w - style->borderRightWidth(), y, tx + w, y2, BSRight, rc, style->color(), rs,
- ignore_top ? 0 : style->borderTopWidth(), ignore_bottom ? 0 : style->borderBottomWidth());
-
- if (renderRadii && (!upperRightBorderStylesMatch || !lowerRightBorderStylesMatch)) {
- thickness = style->borderRightWidth() * 2;
-
- if (!upperRightBorderStylesMatch && topRight.width()) {
- int topX = tx + w - topRight.width() * 2;
- int topY = ty;
- bool applyTopInnerClip = (style->borderRightWidth() < topRight.width())
- && (style->borderTopWidth() < topRight.height())
- && (rs != DOUBLE || style->borderRightWidth() > 6);
- if (applyTopInnerClip) {
- graphicsContext->save();
- graphicsContext->addInnerRoundedRectClip(IntRect(topX, topY, topRight.width() * 2, topRight.height() * 2),
- style->borderRightWidth());
- }
+void RenderObject::addPDFURLRect(GraphicsContext* context, const IntRect& rect)
+{
+ if (rect.isEmpty())
+ return;
+ Node* n = node();
+ if (!n || !n->isLink() || !n->isElementNode())
+ return;
+ const AtomicString& href = static_cast<Element*>(n)->getAttribute(hrefAttr);
+ if (href.isNull())
+ return;
+ context->setURLForRect(n->document()->completeURL(href), rect);
+}
- firstAngleStart = 0;
- firstAngleSpan = 45;
+void RenderObject::paintOutline(GraphicsContext* graphicsContext, int tx, int ty, int w, int h, const RenderStyle* style)
+{
+ if (!hasOutline())
+ return;
- // Draw top right arc
- drawBorderArc(graphicsContext, topX, topY, thickness, topRight, firstAngleStart, firstAngleSpan,
- BSRight, rc, style->color(), rs, true);
- if (applyTopInnerClip)
- graphicsContext->restore();
- }
+ int ow = style->outlineWidth();
+ EBorderStyle os = style->outlineStyle();
- if (!lowerRightBorderStylesMatch && bottomRight.width()) {
- int bottomX = tx + w - bottomRight.width() * 2;
- int bottomY = ty + h - bottomRight.height() * 2;
- bool applyBottomInnerClip = (style->borderRightWidth() < bottomRight.width())
- && (style->borderBottomWidth() < bottomRight.height())
- && (rs != DOUBLE || style->borderRightWidth() > 6);
- if (applyBottomInnerClip) {
- graphicsContext->save();
- graphicsContext->addInnerRoundedRectClip(IntRect(bottomX, bottomY, bottomRight.width() * 2, bottomRight.height() * 2),
- style->borderRightWidth());
- }
+ Color oc = style->outlineColor();
+ if (!oc.isValid())
+ oc = style->color();
- secondAngleStart = 315;
- secondAngleSpan = 45;
+ int offset = style->outlineOffset();
- // Draw bottom right arc
- drawBorderArc(graphicsContext, bottomX, bottomY, thickness, bottomRight, secondAngleStart, secondAngleSpan,
- BSRight, rc, style->color(), rs, false);
- if (applyBottomInnerClip)
- graphicsContext->restore();
- }
+ if (style->outlineStyleIsAuto() || hasOutlineAnnotation()) {
+ if (!theme()->supportsFocusRing(style)) {
+ // Only paint the focus ring by hand if the theme isn't able to draw the focus ring.
+ graphicsContext->initFocusRing(ow, offset);
+ addFocusRingRects(graphicsContext, tx, ty);
+ if (style->outlineStyleIsAuto())
+ graphicsContext->drawFocusRing(oc);
+ else
+ addPDFURLRect(graphicsContext, graphicsContext->focusRingBoundingRect());
+ graphicsContext->clearFocusRing();
}
}
- if (renderRadii)
- graphicsContext->restore();
-}
-
-void RenderObject::paintBoxShadow(GraphicsContext* context, int tx, int ty, int w, int h, const RenderStyle* s, bool begin, bool end)
-{
- // FIXME: Deal with border-image. Would be great to use border-image as a mask.
-
- IntRect rect(tx, ty, w, h);
- bool hasBorderRadius = s->hasBorderRadius();
- bool hasOpaqueBackground = s->backgroundColor().isValid() && s->backgroundColor().alpha() == 255;
- for (ShadowData* shadow = s->boxShadow(); shadow; shadow = shadow->next) {
- context->save();
+ if (style->outlineStyleIsAuto() || style->outlineStyle() == BNONE)
+ return;
- IntSize shadowOffset(shadow->x, shadow->y);
- int shadowBlur = shadow->blur;
- IntRect fillRect(rect);
+ tx -= offset;
+ ty -= offset;
+ w += 2 * offset;
+ h += 2 * offset;
- if (hasBorderRadius) {
- IntRect shadowRect(rect);
- shadowRect.inflate(shadowBlur);
- shadowRect.move(shadowOffset);
- context->clip(shadowRect);
+ if (h < 0 || w < 0)
+ return;
- // Move the fill just outside the clip, adding 1 pixel separation so that the fill does not
- // bleed in (due to antialiasing) if the context is transformed.
- IntSize extraOffset(w + max(0, shadowOffset.width()) + shadowBlur + 1, 0);
- shadowOffset -= extraOffset;
- fillRect.move(extraOffset);
- }
+ drawLineForBoxSide(graphicsContext, tx - ow, ty - ow, tx, ty + h + ow,
+ BSLeft, Color(oc), style->color(), os, ow, ow);
- context->setShadow(shadowOffset, shadowBlur, shadow->color);
- if (hasBorderRadius) {
- IntSize topLeft = begin ? s->borderTopLeftRadius() : IntSize();
- IntSize topRight = end ? s->borderTopRightRadius() : IntSize();
- IntSize bottomLeft = begin ? s->borderBottomLeftRadius() : IntSize();
- IntSize bottomRight = end ? s->borderBottomRightRadius() : IntSize();
- if (!hasOpaqueBackground)
- context->clipOutRoundedRect(rect, topLeft, topRight, bottomLeft, bottomRight);
- context->fillRoundedRect(fillRect, topLeft, topRight, bottomLeft, bottomRight, Color::black);
- } else {
- if (!hasOpaqueBackground)
- context->clipOut(rect);
- context->fillRect(fillRect, Color::black);
- }
- context->restore();
- }
-}
+ drawLineForBoxSide(graphicsContext, tx - ow, ty - ow, tx + w + ow, ty,
+ BSTop, Color(oc), style->color(), os, ow, ow);
-void RenderObject::addLineBoxRects(Vector<IntRect>&, unsigned, unsigned, bool)
-{
-}
+ drawLineForBoxSide(graphicsContext, tx + w, ty - ow, tx + w + ow, ty + h + ow,
+ BSRight, Color(oc), style->color(), os, ow, ow);
-void RenderObject::absoluteRects(Vector<IntRect>& rects, int tx, int ty, bool topLevel)
-{
- // For blocks inside inlines, we go ahead and include margins so that we run right up to the
- // inline boxes above and below us (thus getting merged with them to form a single irregular
- // shape).
- if (topLevel && continuation()) {
- rects.append(IntRect(tx, ty - collapsedMarginTop(),
- width(), height() + collapsedMarginTop() + collapsedMarginBottom()));
- continuation()->absoluteRects(rects,
- tx - xPos() + continuation()->containingBlock()->xPos(),
- ty - yPos() + continuation()->containingBlock()->yPos(), topLevel);
- } else
- rects.append(IntRect(tx, ty, width(), height() + borderTopExtra() + borderBottomExtra()));
+ drawLineForBoxSide(graphicsContext, tx - ow, ty + h, tx + w + ow, ty + h + ow,
+ BSBottom, Color(oc), style->color(), os, ow, ow);
}
IntRect RenderObject::absoluteBoundingBoxRect(bool useTransforms)
@@ -1751,24 +1062,6 @@ IntRect RenderObject::absoluteBoundingBoxRect(bool useTransforms)
return result;
}
-void RenderObject::collectAbsoluteLineBoxQuads(Vector<FloatQuad>&, unsigned, unsigned, bool)
-{
-}
-
-void RenderObject::absoluteQuads(Vector<FloatQuad>& quads, bool topLevel)
-{
- // For blocks inside inlines, we go ahead and include margins so that we run right up to the
- // inline boxes above and below us (thus getting merged with them to form a single irregular
- // shape).
- if (topLevel && continuation()) {
- FloatRect localRect(0, -collapsedMarginTop(),
- width(), height() + collapsedMarginTop() + collapsedMarginBottom());
- quads.append(localToAbsoluteQuad(localRect));
- continuation()->absoluteQuads(quads, topLevel);
- } else
- quads.append(localToAbsoluteQuad(FloatRect(0, 0, width(), height() + borderTopExtra() + borderBottomExtra())));
-}
-
void RenderObject::addAbsoluteRectForLayer(IntRect& result)
{
if (hasLayer())
@@ -1786,128 +1079,84 @@ IntRect RenderObject::paintingRootRect(IntRect& topLevelRect)
return result;
}
-void RenderObject::addPDFURLRect(GraphicsContext* context, const IntRect& rect)
-{
- if (rect.isEmpty())
- return;
- Node* node = element();
- if (!node || !node->isLink() || !node->isElementNode())
- return;
- const AtomicString& href = static_cast<Element*>(node)->getAttribute(hrefAttr);
- if (href.isNull())
- return;
- context->setURLForRect(node->document()->completeURL(href), rect);
-}
-
-
-void RenderObject::addFocusRingRects(GraphicsContext* graphicsContext, int tx, int ty)
+void RenderObject::paint(PaintInfo& /*paintInfo*/, int /*tx*/, int /*ty*/)
{
- // For blocks inside inlines, we go ahead and include margins so that we run right up to the
- // inline boxes above and below us (thus getting merged with them to form a single irregular
- // shape).
- if (continuation()) {
- graphicsContext->addFocusRingRect(IntRect(tx, ty - collapsedMarginTop(), width(), height() + collapsedMarginTop() + collapsedMarginBottom()));
- continuation()->addFocusRingRects(graphicsContext,
- tx - xPos() + continuation()->containingBlock()->xPos(),
- ty - yPos() + continuation()->containingBlock()->yPos());
- } else
- graphicsContext->addFocusRingRect(IntRect(tx, ty, width(), height()));
}
-void RenderObject::paintOutline(GraphicsContext* graphicsContext, int tx, int ty, int w, int h, const RenderStyle* style)
+RenderBoxModelObject* RenderObject::containerForRepaint() const
{
- if (!hasOutline())
- return;
-
- int ow = style->outlineWidth();
-
- EBorderStyle os = style->outlineStyle();
-
- Color oc = style->outlineColor();
- if (!oc.isValid())
- oc = style->color();
-
- int offset = style->outlineOffset();
-
- if (style->outlineStyleIsAuto() || hasOutlineAnnotation()) {
- if (!theme()->supportsFocusRing(style)) {
- // Only paint the focus ring by hand if the theme isn't able to draw the focus ring.
- graphicsContext->initFocusRing(ow, offset);
- if (style->outlineStyleIsAuto())
- addFocusRingRects(graphicsContext, tx, ty);
- else
- addPDFURLRect(graphicsContext, graphicsContext->focusRingBoundingRect());
- graphicsContext->drawFocusRing(oc);
- graphicsContext->clearFocusRing();
+#if USE(ACCELERATED_COMPOSITING)
+ if (RenderView* v = view()) {
+ if (v->usesCompositing()) {
+ RenderLayer* compLayer = enclosingLayer()->enclosingCompositingLayer();
+ return compLayer ? compLayer->renderer() : 0;
}
}
-
- if (style->outlineStyleIsAuto() || style->outlineStyle() == BNONE)
- return;
-
- tx -= offset;
- ty -= offset;
- w += 2 * offset;
- h += 2 * offset;
-
- if (h < 0 || w < 0)
- return;
-
- drawBorder(graphicsContext, tx - ow, ty - ow, tx, ty + h + ow,
- BSLeft, Color(oc), style->color(), os, ow, ow);
-
- drawBorder(graphicsContext, tx - ow, ty - ow, tx + w + ow, ty,
- BSTop, Color(oc), style->color(), os, ow, ow);
-
- drawBorder(graphicsContext, tx + w, ty - ow, tx + w + ow, ty + h + ow,
- BSRight, Color(oc), style->color(), os, ow, ow);
-
- drawBorder(graphicsContext, tx - ow, ty + h, tx + w + ow, ty + h + ow,
- BSBottom, Color(oc), style->color(), os, ow, ow);
+#endif
+ // Do root-relative repaint.
+ return 0;
}
-void RenderObject::paint(PaintInfo& /*paintInfo*/, int /*tx*/, int /*ty*/)
+void RenderObject::repaintUsingContainer(RenderBoxModelObject* repaintContainer, const IntRect& r, bool immediate)
{
+ if (!repaintContainer || repaintContainer->isRenderView()) {
+ RenderView* v = repaintContainer ? toRenderView(repaintContainer) : view();
+ v->repaintViewRectangle(r, immediate);
+ } else {
+#if USE(ACCELERATED_COMPOSITING)
+ RenderView* v = view();
+ if (v->usesCompositing()) {
+ ASSERT(repaintContainer->hasLayer() && repaintContainer->layer()->isComposited());
+ repaintContainer->layer()->setBackingNeedsRepaintInRect(r);
+ }
+#else
+ ASSERT_NOT_REACHED();
+#endif
+ }
}
void RenderObject::repaint(bool immediate)
{
- // Can't use view(), since we might be unrooted.
- RenderObject* o = this;
- while (o->parent())
- o = o->parent();
- if (!o->isRenderView())
+ // Don't repaint if we're unrooted (note that view() still returns the view when unrooted)
+ RenderView* view;
+ if (!isRooted(&view))
return;
- RenderView* view = static_cast<RenderView*>(o);
+
if (view->printing())
return; // Don't repaint if we're printing.
- view->repaintViewRectangle(absoluteClippedOverflowRect(), immediate);
+
+ RenderBoxModelObject* repaintContainer = containerForRepaint();
+ repaintUsingContainer(repaintContainer ? repaintContainer : view, clippedOverflowRectForRepaint(repaintContainer), immediate);
}
void RenderObject::repaintRectangle(const IntRect& r, bool immediate)
{
- // Can't use view(), since we might be unrooted.
- RenderObject* o = this;
- while (o->parent())
- o = o->parent();
- if (!o->isRenderView())
+ // Don't repaint if we're unrooted (note that view() still returns the view when unrooted)
+ RenderView* view;
+ if (!isRooted(&view))
return;
- RenderView* view = static_cast<RenderView*>(o);
+
if (view->printing())
return; // Don't repaint if we're printing.
- IntRect absRect(r);
- absRect.move(view->layoutDelta());
- computeAbsoluteRepaintRect(absRect);
- view->repaintViewRectangle(absRect, immediate);
+
+ IntRect dirtyRect(r);
+
+ // FIXME: layoutDelta needs to be applied in parts before/after transforms and
+ // repaint containers. https://bugs.webkit.org/show_bug.cgi?id=23308
+ dirtyRect.move(view->layoutDelta());
+
+ RenderBoxModelObject* repaintContainer = containerForRepaint();
+ computeRectForRepaint(repaintContainer, dirtyRect);
+ repaintUsingContainer(repaintContainer ? repaintContainer : view, dirtyRect, immediate);
}
-bool RenderObject::repaintAfterLayoutIfNeeded(const IntRect& oldBounds, const IntRect& oldOutlineBox)
+bool RenderObject::repaintAfterLayoutIfNeeded(RenderBoxModelObject* repaintContainer, const IntRect& oldBounds, const IntRect& oldOutlineBox)
{
RenderView* v = view();
if (v->printing())
return false; // Don't repaint if we're printing.
- IntRect newBounds = absoluteClippedOverflowRect();
+ IntRect newBounds = clippedOverflowRectForRepaint(repaintContainer);
IntRect newOutlineBox;
bool fullRepaint = selfNeedsLayout();
@@ -1915,14 +1164,18 @@ bool RenderObject::repaintAfterLayoutIfNeeded(const IntRect& oldBounds, const In
if (!fullRepaint && style()->borderFit() == BorderFitLines)
fullRepaint = true;
if (!fullRepaint) {
- newOutlineBox = absoluteOutlineBounds();
+ newOutlineBox = outlineBoundsForRepaint(repaintContainer);
if (newOutlineBox.location() != oldOutlineBox.location() || (mustRepaintBackgroundOrBorder() && (newBounds != oldBounds || newOutlineBox != oldOutlineBox)))
fullRepaint = true;
}
+
+ if (!repaintContainer)
+ repaintContainer = v;
+
if (fullRepaint) {
- v->repaintViewRectangle(oldBounds);
+ repaintUsingContainer(repaintContainer, oldBounds);
if (newBounds != oldBounds)
- v->repaintViewRectangle(newBounds);
+ repaintUsingContainer(repaintContainer, newBounds);
return true;
}
@@ -1931,34 +1184,34 @@ bool RenderObject::repaintAfterLayoutIfNeeded(const IntRect& oldBounds, const In
int deltaLeft = newBounds.x() - oldBounds.x();
if (deltaLeft > 0)
- v->repaintViewRectangle(IntRect(oldBounds.x(), oldBounds.y(), deltaLeft, oldBounds.height()));
+ repaintUsingContainer(repaintContainer, IntRect(oldBounds.x(), oldBounds.y(), deltaLeft, oldBounds.height()));
else if (deltaLeft < 0)
- v->repaintViewRectangle(IntRect(newBounds.x(), newBounds.y(), -deltaLeft, newBounds.height()));
+ repaintUsingContainer(repaintContainer, IntRect(newBounds.x(), newBounds.y(), -deltaLeft, newBounds.height()));
int deltaRight = newBounds.right() - oldBounds.right();
if (deltaRight > 0)
- v->repaintViewRectangle(IntRect(oldBounds.right(), newBounds.y(), deltaRight, newBounds.height()));
+ repaintUsingContainer(repaintContainer, IntRect(oldBounds.right(), newBounds.y(), deltaRight, newBounds.height()));
else if (deltaRight < 0)
- v->repaintViewRectangle(IntRect(newBounds.right(), oldBounds.y(), -deltaRight, oldBounds.height()));
+ repaintUsingContainer(repaintContainer, IntRect(newBounds.right(), oldBounds.y(), -deltaRight, oldBounds.height()));
int deltaTop = newBounds.y() - oldBounds.y();
if (deltaTop > 0)
- v->repaintViewRectangle(IntRect(oldBounds.x(), oldBounds.y(), oldBounds.width(), deltaTop));
+ repaintUsingContainer(repaintContainer, IntRect(oldBounds.x(), oldBounds.y(), oldBounds.width(), deltaTop));
else if (deltaTop < 0)
- v->repaintViewRectangle(IntRect(newBounds.x(), newBounds.y(), newBounds.width(), -deltaTop));
+ repaintUsingContainer(repaintContainer, IntRect(newBounds.x(), newBounds.y(), newBounds.width(), -deltaTop));
int deltaBottom = newBounds.bottom() - oldBounds.bottom();
if (deltaBottom > 0)
- v->repaintViewRectangle(IntRect(newBounds.x(), oldBounds.bottom(), newBounds.width(), deltaBottom));
+ repaintUsingContainer(repaintContainer, IntRect(newBounds.x(), oldBounds.bottom(), newBounds.width(), deltaBottom));
else if (deltaBottom < 0)
- v->repaintViewRectangle(IntRect(oldBounds.x(), newBounds.bottom(), oldBounds.width(), -deltaBottom));
+ repaintUsingContainer(repaintContainer, IntRect(oldBounds.x(), newBounds.bottom(), oldBounds.width(), -deltaBottom));
if (newOutlineBox == oldOutlineBox)
return false;
// We didn't move, but we did change size. Invalidate the delta, which will consist of possibly
// two rectangles (but typically only one).
- RenderStyle* outlineStyle = !isInline() && continuation() ? continuation()->style() : style();
+ RenderStyle* outlineStyle = outlineStyleForRepaint();
int ow = outlineStyle->outlineSize();
ShadowData* boxShadow = style()->boxShadow();
int width = abs(newOutlineBox.width() - oldOutlineBox.width());
@@ -1967,7 +1220,8 @@ bool RenderObject::repaintAfterLayoutIfNeeded(const IntRect& oldBounds, const In
for (ShadowData* shadow = boxShadow; shadow; shadow = shadow->next)
shadowRight = max(shadow->x + shadow->blur, shadowRight);
- int borderWidth = max(-outlineStyle->outlineOffset(), max(borderRight(), max(style()->borderTopRightRadius().width(), style()->borderBottomRightRadius().width()))) + max(ow, shadowRight);
+ int borderRight = isBox() ? toRenderBox(this)->borderRight() : 0;
+ int borderWidth = max(-outlineStyle->outlineOffset(), max(borderRight, max(style()->borderTopRightRadius().width(), style()->borderBottomRightRadius().width()))) + max(ow, shadowRight);
IntRect rightRect(newOutlineBox.x() + min(newOutlineBox.width(), oldOutlineBox.width()) - borderWidth,
newOutlineBox.y(),
width + borderWidth,
@@ -1975,7 +1229,7 @@ bool RenderObject::repaintAfterLayoutIfNeeded(const IntRect& oldBounds, const In
int right = min(newBounds.right(), oldBounds.right());
if (rightRect.x() < right) {
rightRect.setWidth(min(rightRect.width(), right - rightRect.x()));
- v->repaintViewRectangle(rightRect);
+ repaintUsingContainer(repaintContainer, rightRect);
}
}
int height = abs(newOutlineBox.height() - oldOutlineBox.height());
@@ -1984,7 +1238,8 @@ bool RenderObject::repaintAfterLayoutIfNeeded(const IntRect& oldBounds, const In
for (ShadowData* shadow = boxShadow; shadow; shadow = shadow->next)
shadowBottom = max(shadow->y + shadow->blur, shadowBottom);
- int borderHeight = max(-outlineStyle->outlineOffset(), max(borderBottom(), max(style()->borderBottomLeftRadius().height(), style()->borderBottomRightRadius().height()))) + max(ow, shadowBottom);
+ int borderBottom = isBox() ? toRenderBox(this)->borderBottom() : 0;
+ int borderHeight = max(-outlineStyle->outlineOffset(), max(borderBottom, max(style()->borderBottomLeftRadius().height(), style()->borderBottomRightRadius().height()))) + max(ow, shadowBottom);
IntRect bottomRect(newOutlineBox.x(),
min(newOutlineBox.bottom(), oldOutlineBox.bottom()) - borderHeight,
max(newOutlineBox.width(), oldOutlineBox.width()),
@@ -1992,7 +1247,7 @@ bool RenderObject::repaintAfterLayoutIfNeeded(const IntRect& oldBounds, const In
int bottom = min(newBounds.bottom(), oldBounds.bottom());
if (bottomRect.y() < bottom) {
bottomRect.setHeight(min(bottomRect.height(), bottom - bottomRect.y()));
- v->repaintViewRectangle(bottomRect);
+ repaintUsingContainer(repaintContainer, bottomRect);
}
}
return false;
@@ -2014,36 +1269,27 @@ bool RenderObject::checkForRepaintDuringLayout() const
return !document()->view()->needsFullRepaint() && !hasLayer();
}
-IntRect RenderObject::getAbsoluteRepaintRectWithOutline(int ow)
+IntRect RenderObject::rectWithOutlineForRepaint(RenderBoxModelObject* repaintContainer, int outlineWidth)
{
- IntRect r(absoluteClippedOverflowRect());
- r.inflate(ow);
-
- if (continuation() && !isInline())
- r.inflateY(collapsedMarginTop());
-
- if (isInlineFlow()) {
- for (RenderObject* curr = firstChild(); curr; curr = curr->nextSibling()) {
- if (!curr->isText())
- r.unite(curr->getAbsoluteRepaintRectWithOutline(ow));
- }
- }
-
+ IntRect r(clippedOverflowRectForRepaint(repaintContainer));
+ r.inflate(outlineWidth);
return r;
}
-IntRect RenderObject::absoluteClippedOverflowRect()
+IntRect RenderObject::clippedOverflowRectForRepaint(RenderBoxModelObject*)
{
- if (parent())
- return parent()->absoluteClippedOverflowRect();
+ ASSERT_NOT_REACHED();
return IntRect();
}
-void RenderObject::computeAbsoluteRepaintRect(IntRect& rect, bool fixed)
+void RenderObject::computeRectForRepaint(RenderBoxModelObject* repaintContainer, IntRect& rect, bool fixed)
{
+ if (repaintContainer == this)
+ return;
+
if (RenderObject* o = parent()) {
if (o->isBlockFlow()) {
- RenderBlock* cb = static_cast<RenderBlock*>(o);
+ RenderBlock* cb = toRenderBlock(o);
if (cb->hasColumns())
cb->adjustRectForColumns(rect);
}
@@ -2052,17 +1298,19 @@ void RenderObject::computeAbsoluteRepaintRect(IntRect& rect, bool fixed)
// o->height() is inaccurate if we're in the middle of a layout of |o|, so use the
// layer's size instead. Even if the layer's size is wrong, the layer itself will repaint
// anyway if its size does change.
- IntRect boxRect(0, 0, o->layer()->width(), o->layer()->height());
+ RenderBox* boxParent = toRenderBox(o);
+
+ IntRect boxRect(0, 0, boxParent->layer()->width(), boxParent->layer()->height());
int x = rect.x();
int y = rect.y();
- o->layer()->subtractScrolledContentOffset(x, y); // For overflow:auto/scroll/hidden.
+ boxParent->layer()->subtractScrolledContentOffset(x, y); // For overflow:auto/scroll/hidden.
IntRect repaintRect(x, y, rect.width(), rect.height());
rect = intersection(repaintRect, boxRect);
if (rect.isEmpty())
return;
}
- o->computeAbsoluteRepaintRect(rect, fixed);
+ o->computeRectForRepaint(repaintContainer, rect, fixed);
}
}
@@ -2074,8 +1322,8 @@ void RenderObject::dirtyLinesFromChangedChild(RenderObject*)
void RenderObject::showTreeForThis() const
{
- if (element())
- element()->showTreeForThis();
+ if (node())
+ node()->showTreeForThis();
}
#endif // NDEBUG
@@ -2084,7 +1332,7 @@ Color RenderObject::selectionBackgroundColor() const
{
Color color;
if (style()->userSelect() != SELECT_NONE) {
- RenderStyle* pseudoStyle = getCachedPseudoStyle(RenderStyle::SELECTION);
+ RefPtr<RenderStyle> pseudoStyle = getUncachedPseudoStyle(SELECTION);
if (pseudoStyle && pseudoStyle->backgroundColor().isValid())
color = pseudoStyle->backgroundColor().blendWithWhite();
else
@@ -2102,14 +1350,14 @@ Color RenderObject::selectionForegroundColor() const
if (style()->userSelect() == SELECT_NONE)
return color;
- if (RenderStyle* pseudoStyle = getCachedPseudoStyle(RenderStyle::SELECTION)) {
+ if (RefPtr<RenderStyle> pseudoStyle = getUncachedPseudoStyle(SELECTION)) {
color = pseudoStyle->textFillColor();
if (!color.isValid())
color = pseudoStyle->color();
} else
color = document()->frame()->selection()->isFocusedAndActive() ?
- theme()->platformActiveSelectionForegroundColor() :
- theme()->platformInactiveSelectionForegroundColor();
+ theme()->activeSelectionForegroundColor() :
+ theme()->inactiveSelectionForegroundColor();
return color;
}
@@ -2120,7 +1368,7 @@ Node* RenderObject::draggableNode(bool dhtmlOK, bool uaOK, int x, int y, bool& d
return 0;
for (const RenderObject* curr = this; curr; curr = curr->parent()) {
- Node* elt = curr->element();
+ Node* elt = curr->node();
if (elt && elt->nodeType() == Node::TEXT_NODE) {
// Since there's no way for the author to address the -webkit-user-drag style for a text node,
// we use our own judgement.
@@ -2154,17 +1402,6 @@ void RenderObject::selectionStartEnd(int& spos, int& epos) const
view()->selectionStartEnd(spos, epos);
}
-RenderBlock* RenderObject::createAnonymousBlock()
-{
- RefPtr<RenderStyle> newStyle = RenderStyle::create();
- newStyle->inheritFrom(m_style.get());
- newStyle->setDisplay(BLOCK);
-
- RenderBlock* newBox = new (renderArena()) RenderBlock(document() /* anonymous box */);
- newBox->setStyle(newStyle.release());
- return newBox;
-}
-
void RenderObject::handleDynamicFloatPositionChange()
{
// We have gone from not affecting the inline status of the parent flow to suddenly
@@ -2172,30 +1409,14 @@ void RenderObject::handleDynamicFloatPositionChange()
// childrenInline() state and our state.
setInline(style()->isDisplayInlineType());
if (isInline() != parent()->childrenInline()) {
- if (!isInline()) {
- if (parent()->isRenderInline()) {
- // We have to split the parent flow.
- RenderInline* parentInline = static_cast<RenderInline*>(parent());
- RenderBlock* newBox = parentInline->createAnonymousBlock();
-
- RenderFlow* oldContinuation = parent()->continuation();
- parentInline->setContinuation(newBox);
-
- RenderObject* beforeChild = nextSibling();
- parent()->removeChildNode(this);
- parentInline->splitFlow(beforeChild, newBox, this, oldContinuation);
- } else if (parent()->isRenderBlock()) {
- RenderBlock* o = static_cast<RenderBlock*>(parent());
- o->makeChildrenNonInline();
- if (o->isAnonymousBlock() && o->parent())
- o->parent()->removeLeftoverAnonymousBlock(o);
- // o may be dead here
- }
- } else {
+ if (!isInline())
+ toRenderBoxModelObject(parent())->childBecameNonInline(this);
+ else {
// An anonymous block must be made to wrap this inline.
- RenderBlock* box = createAnonymousBlock();
- parent()->insertChildNode(box, this);
- box->appendChildNode(parent()->removeChildNode(this));
+ RenderBlock* block = toRenderBlock(parent())->createAnonymousBlock();
+ RenderObjectChildList* childlist = parent()->virtualChildren();
+ childlist->insertChildNode(parent(), block, this);
+ block->children()->appendChildNode(block, childlist->removeChildNode(parent(), this));
}
}
}
@@ -2208,18 +1429,50 @@ void RenderObject::setAnimatableStyle(PassRefPtr<RenderStyle> style)
setStyle(style);
}
+StyleDifference RenderObject::adjustStyleDifference(StyleDifference diff, unsigned contextSensitiveProperties) const
+{
+#if USE(ACCELERATED_COMPOSITING)
+ // If transform changed, and we are not composited, need to do a layout.
+ if (contextSensitiveProperties & ContextSensitivePropertyTransform) {
+ // Text nodes share style with their parents but transforms don't apply to them,
+ // hence the !isText() check.
+ // FIXME: when transforms are taken into account for overflow, we will need to do a layout.
+ if (!isText() && (!hasLayer() || !toRenderBoxModelObject(this)->layer()->isComposited()))
+ diff = StyleDifferenceLayout;
+ else if (diff < StyleDifferenceRecompositeLayer)
+ diff = StyleDifferenceRecompositeLayer;
+ }
+
+ // If opacity changed, and we are not composited, need to repaint (also
+ // ignoring text nodes)
+ if (contextSensitiveProperties & ContextSensitivePropertyOpacity) {
+ if (!isText() && (!hasLayer() || !toRenderBoxModelObject(this)->layer()->isComposited()))
+ diff = StyleDifferenceRepaintLayer;
+ else if (diff < StyleDifferenceRecompositeLayer)
+ diff = StyleDifferenceRecompositeLayer;
+ }
+#else
+ UNUSED_PARAM(contextSensitiveProperties);
+#endif
+
+ // If we have no layer(), just treat a RepaintLayer hint as a normal Repaint.
+ if (diff == StyleDifferenceRepaintLayer && !hasLayer())
+ diff = StyleDifferenceRepaint;
+
+ return diff;
+}
+
void RenderObject::setStyle(PassRefPtr<RenderStyle> style)
{
if (m_style == style)
return;
- RenderStyle::Diff diff = RenderStyle::Equal;
+ StyleDifference diff = StyleDifferenceEqual;
+ unsigned contextSensitiveProperties = ContextSensitivePropertyNone;
if (m_style)
- diff = m_style->diff(style.get());
+ diff = m_style->diff(style.get(), contextSensitiveProperties);
- // If we have no layer(), just treat a RepaintLayer hint as a normal Repaint.
- if (diff == RenderStyle::RepaintLayer && !hasLayer())
- diff = RenderStyle::Repaint;
+ diff = adjustStyleDifference(diff, contextSensitiveProperties);
styleWillChange(diff, style.get());
@@ -2232,7 +1485,32 @@ void RenderObject::setStyle(PassRefPtr<RenderStyle> style)
updateImage(oldStyle ? oldStyle->borderImage().image() : 0, m_style ? m_style->borderImage().image() : 0);
updateImage(oldStyle ? oldStyle->maskBoxImage().image() : 0, m_style ? m_style->maskBoxImage().image() : 0);
+ // We need to ensure that view->maximalOutlineSize() is valid for any repaints that happen
+ // during styleDidChange (it's used by clippedOverflowRectForRepaint()).
+ if (m_style->outlineWidth() > 0 && m_style->outlineSize() > maximalOutlineSize(PaintPhaseOutline))
+ toRenderView(document()->renderer())->setMaximalOutlineSize(m_style->outlineSize());
+
styleDidChange(diff, oldStyle.get());
+
+ if (!m_parent || isText())
+ return;
+
+ // Now that the layer (if any) has been updated, we need to adjust the diff again,
+ // check whether we should layout now, and decide if we need to repaint.
+ StyleDifference updatedDiff = adjustStyleDifference(diff, contextSensitiveProperties);
+
+ if (diff <= StyleDifferenceLayoutPositionedMovementOnly) {
+ if (updatedDiff == StyleDifferenceLayout)
+ setNeedsLayoutAndPrefWidthsRecalc();
+ else if (updatedDiff == StyleDifferenceLayoutPositionedMovementOnly)
+ setNeedsPositionedMovementLayout();
+ }
+
+ if (updatedDiff == StyleDifferenceRepaintLayer || updatedDiff == StyleDifferenceRepaint) {
+ // Do a repaint with the new style now, e.g., for example if we go from
+ // not having an outline to having an outline.
+ repaint();
+ }
}
void RenderObject::setStyleInternal(PassRefPtr<RenderStyle> style)
@@ -2240,120 +1518,53 @@ void RenderObject::setStyleInternal(PassRefPtr<RenderStyle> style)
m_style = style;
}
-void RenderObject::styleWillChange(RenderStyle::Diff diff, const RenderStyle* newStyle)
+void RenderObject::styleWillChange(StyleDifference diff, const RenderStyle* newStyle)
{
if (m_style) {
// If our z-index changes value or our visibility changes,
// we need to dirty our stacking context's z-order list.
if (newStyle) {
+ bool visibilityChanged = m_style->visibility() != newStyle->visibility()
+ || m_style->zIndex() != newStyle->zIndex()
+ || m_style->hasAutoZIndex() != newStyle->hasAutoZIndex();
#if ENABLE(DASHBOARD_SUPPORT)
- if (m_style->visibility() != newStyle->visibility() ||
- m_style->zIndex() != newStyle->zIndex() ||
- m_style->hasAutoZIndex() != newStyle->hasAutoZIndex())
+ if (visibilityChanged)
document()->setDashboardRegionsDirty(true);
#endif
+ if (visibilityChanged && AXObjectCache::accessibilityEnabled())
+ document()->axObjectCache()->childrenChanged(this);
- if ((m_style->hasAutoZIndex() != newStyle->hasAutoZIndex() ||
- m_style->zIndex() != newStyle->zIndex() ||
- m_style->visibility() != newStyle->visibility()) && hasLayer()) {
- layer()->dirtyStackingContextZOrderLists();
- if (m_style->hasAutoZIndex() != newStyle->hasAutoZIndex() ||
- m_style->visibility() != newStyle->visibility())
- layer()->dirtyZOrderLists();
- }
- // keep layer hierarchy visibility bits up to date if visibility changes
+ // Keep layer hierarchy visibility bits up to date if visibility changes.
if (m_style->visibility() != newStyle->visibility()) {
if (RenderLayer* l = enclosingLayer()) {
if (newStyle->visibility() == VISIBLE)
l->setHasVisibleContent(true);
else if (l->hasVisibleContent() && (this == l->renderer() || l->renderer()->style()->visibility() != VISIBLE)) {
l->dirtyVisibleContentStatus();
- if (diff > RenderStyle::RepaintLayer)
+ if (diff > StyleDifferenceRepaintLayer)
repaint();
}
}
}
}
- // The background of the root element or the body element could propagate up to
- // the canvas. Just dirty the entire canvas when our style changes substantially.
- if (diff >= RenderStyle::Repaint && element() &&
- (element()->hasTagName(htmlTag) || element()->hasTagName(bodyTag)))
- view()->repaint();
- else if (m_parent && !isText()) {
- // Do a repaint with the old style first, e.g., for example if we go from
- // having an outline to not having an outline.
- if (diff == RenderStyle::RepaintLayer) {
- layer()->repaintIncludingDescendants();
- if (!(m_style->clip() == newStyle->clip()))
- layer()->clearClipRectsIncludingDescendants();
- } else if (diff == RenderStyle::Repaint || newStyle->outlineSize() < m_style->outlineSize())
- repaint();
- }
-
- if (diff == RenderStyle::Layout) {
- // When a layout hint happens, we go ahead and do a repaint of the layer, since the layer could
- // end up being destroyed.
- if (hasLayer()) {
- if (m_style->position() != newStyle->position() ||
- m_style->zIndex() != newStyle->zIndex() ||
- m_style->hasAutoZIndex() != newStyle->hasAutoZIndex() ||
- !(m_style->clip() == newStyle->clip()) ||
- m_style->hasClip() != newStyle->hasClip() ||
- m_style->opacity() != newStyle->opacity() ||
- m_style->transform() != newStyle->transform())
- layer()->repaintIncludingDescendants();
- } else if (newStyle->hasTransform() || newStyle->opacity() < 1) {
- // If we don't have a layer yet, but we are going to get one because of transform or opacity,
- // then we need to repaint the old position of the object.
- repaint();
- }
- }
-
- // When a layout hint happens and an object's position style changes, we have to do a layout
- // to dirty the render tree using the old position value now.
- if (diff == RenderStyle::Layout && m_parent && m_style->position() != newStyle->position()) {
- markContainingBlocksForLayout();
- if (m_style->position() == StaticPosition)
- repaint();
- if (isFloating() && !isPositioned() && (newStyle->position() == AbsolutePosition || newStyle->position() == FixedPosition))
- removeFromObjectLists();
- if (isRenderBlock()) {
- if (newStyle->position() == StaticPosition)
- // Clear our positioned objects list. Our absolutely positioned descendants will be
- // inserted into our containing block's positioned objects list during layout.
- removePositionedObjects(0);
- else if (m_style->position() == StaticPosition) {
- // Remove our absolutely positioned descendants from their current containing block.
- // They will be inserted into our positioned objects list during layout.
- RenderObject* cb = parent();
- while (cb && (cb->style()->position() == StaticPosition || (cb->isInline() && !cb->isReplaced())) && !cb->isRenderView()) {
- if (cb->style()->position() == RelativePosition && cb->isInline() && !cb->isReplaced()) {
- cb = cb->containingBlock();
- break;
- }
- cb = cb->parent();
- }
- cb->removePositionedObjects(static_cast<RenderBlock*>(this));
- }
- }
- }
-
+ if (m_parent && (diff == StyleDifferenceRepaint || newStyle->outlineSize() < m_style->outlineSize()))
+ repaint();
if (isFloating() && (m_style->floating() != newStyle->floating()))
// For changes in float styles, we need to conceivably remove ourselves
// from the floating objects list.
- removeFromObjectLists();
+ toRenderBox(this)->removeFloatingOrPositionedChildFromBlockLists();
else if (isPositioned() && (newStyle->position() != AbsolutePosition && newStyle->position() != FixedPosition))
// For changes in positioning styles, we need to conceivably remove ourselves
// from the positioned objects list.
- removeFromObjectLists();
+ toRenderBox(this)->removeFloatingOrPositionedChildFromBlockLists();
s_affectsParentBlock = isFloatingOrPositioned() &&
(!newStyle->isFloating() && newStyle->position() != AbsolutePosition && newStyle->position() != FixedPosition)
- && parent() && (parent()->isBlockFlow() || parent()->isInlineFlow());
+ && parent() && (parent()->isBlockFlow() || parent()->isRenderInline());
// reset style flags
- if (diff == RenderStyle::Layout || diff == RenderStyle::LayoutPositionedMovementOnly) {
+ if (diff == StyleDifferenceLayout || diff == StyleDifferenceLayoutPositionedMovementOnly) {
m_floating = false;
m_positioned = false;
m_relPositioned = false;
@@ -2379,25 +1590,21 @@ void RenderObject::styleWillChange(RenderStyle::Diff diff, const RenderStyle* ne
}
}
-void RenderObject::styleDidChange(RenderStyle::Diff diff, const RenderStyle*)
+void RenderObject::styleDidChange(StyleDifference diff, const RenderStyle*)
{
- setHasBoxDecorations(m_style->hasBorder() || m_style->hasBackground() || m_style->hasAppearance() || m_style->boxShadow());
-
if (s_affectsParentBlock)
handleDynamicFloatPositionChange();
- // No need to ever schedule repaints from a style change of a text run, since
- // we already did this for the parent of the text run.
- // We do have to schedule layouts, though, since a style change can force us to
- // need to relayout.
- if (diff == RenderStyle::Layout && m_parent)
+ if (!m_parent)
+ return;
+
+ if (diff == StyleDifferenceLayout)
setNeedsLayoutAndPrefWidthsRecalc();
- else if (diff == RenderStyle::LayoutPositionedMovementOnly && m_parent && !isText())
+ else if (diff == StyleDifferenceLayoutPositionedMovementOnly)
setNeedsPositionedMovementLayout();
- else if (m_parent && !isText() && (diff == RenderStyle::RepaintLayer || diff == RenderStyle::Repaint))
- // Do a repaint with the new style now, e.g., for example if we go from
- // not having an outline to having an outline.
- repaint();
+
+ // Don't check for repaint here; we need to wait until the layer has been
+ // updated by subclasses before we know if we have to repaint (in setStyle()).
}
void RenderObject::updateFillImages(const FillLayer* oldLayers, const FillLayer* newLayers)
@@ -2430,42 +1637,92 @@ IntRect RenderObject::viewRect() const
FloatPoint RenderObject::localToAbsolute(FloatPoint localPoint, bool fixed, bool useTransforms) const
{
+ TransformState transformState(TransformState::ApplyTransformDirection, localPoint);
+ mapLocalToContainer(0, fixed, useTransforms, transformState);
+ transformState.flatten();
+
+ return transformState.lastPlanarPoint();
+}
+
+FloatPoint RenderObject::absoluteToLocal(FloatPoint containerPoint, bool fixed, bool useTransforms) const
+{
+ TransformState transformState(TransformState::UnapplyInverseTransformDirection, containerPoint);
+ mapAbsoluteToLocalPoint(fixed, useTransforms, transformState);
+ transformState.flatten();
+
+ return transformState.lastPlanarPoint();
+}
+
+void RenderObject::mapLocalToContainer(RenderBoxModelObject* repaintContainer, bool fixed, bool useTransforms, TransformState& transformState) const
+{
+ if (repaintContainer == this)
+ return;
+
RenderObject* o = parent();
- if (o) {
- localPoint.move(0.0f, static_cast<float>(o->borderTopExtra()));
- if (o->hasOverflowClip())
- localPoint -= o->layer()->scrolledContentOffset();
- return o->localToAbsolute(localPoint, fixed, useTransforms);
- }
+ if (!o)
+ return;
- return FloatPoint();
+ if (o->hasOverflowClip())
+ transformState.move(-toRenderBox(o)->layer()->scrolledContentOffset());
+
+ o->mapLocalToContainer(repaintContainer, fixed, useTransforms, transformState);
}
-FloatPoint RenderObject::absoluteToLocal(FloatPoint containerPoint, bool fixed, bool useTransforms) const
+void RenderObject::mapAbsoluteToLocalPoint(bool fixed, bool useTransforms, TransformState& transformState) const
{
RenderObject* o = parent();
if (o) {
- FloatPoint localPoint = o->absoluteToLocal(containerPoint, fixed, useTransforms);
- localPoint.move(0.0f, -static_cast<float>(o->borderTopExtra()));
+ o->mapAbsoluteToLocalPoint(fixed, useTransforms, transformState);
if (o->hasOverflowClip())
- localPoint += o->layer()->scrolledContentOffset();
- return localPoint;
+ transformState.move(toRenderBox(o)->layer()->scrolledContentOffset());
}
- return FloatPoint();
}
-FloatQuad RenderObject::localToAbsoluteQuad(const FloatQuad& localQuad, bool fixed) const
+bool RenderObject::shouldUseTransformFromContainer(const RenderObject* containerObject) const
{
- RenderObject* o = parent();
- if (o) {
- FloatQuad quad = localQuad;
- quad.move(0.0f, static_cast<float>(o->borderTopExtra()));
- if (o->hasOverflowClip())
- quad -= o->layer()->scrolledContentOffset();
- return o->localToAbsoluteQuad(quad, fixed);
+#if ENABLE(3D_RENDERING)
+ // hasTransform() indicates whether the object has transform, transform-style or perspective. We just care about transform,
+ // so check the layer's transform directly.
+ return (hasLayer() && toRenderBoxModelObject(this)->layer()->transform()) || (containerObject && containerObject->style()->hasPerspective());
+#else
+ UNUSED_PARAM(containerObject);
+ return hasTransform();
+#endif
+}
+
+void RenderObject::getTransformFromContainer(const RenderObject* containerObject, const IntSize& offsetInContainer, TransformationMatrix& transform) const
+{
+ transform.makeIdentity();
+ transform.translate(offsetInContainer.width(), offsetInContainer.height());
+ RenderLayer* layer;
+ if (hasLayer() && (layer = toRenderBoxModelObject(this)->layer()) && layer->transform())
+ transform.multLeft(layer->currentTransform());
+
+#if ENABLE(3D_RENDERING)
+ if (containerObject && containerObject->hasLayer() && containerObject->style()->hasPerspective()) {
+ // Perpsective on the container affects us, so we have to factor it in here.
+ ASSERT(containerObject->hasLayer());
+ FloatPoint perspectiveOrigin = toRenderBox(containerObject)->layer()->perspectiveOrigin();
+
+ TransformationMatrix perspectiveMatrix;
+ perspectiveMatrix.applyPerspective(containerObject->style()->perspective());
+
+ transform.translateRight3d(-perspectiveOrigin.x(), -perspectiveOrigin.y(), 0);
+ transform.multiply(perspectiveMatrix);
+ transform.translateRight3d(perspectiveOrigin.x(), perspectiveOrigin.y(), 0);
}
+#else
+ UNUSED_PARAM(containerObject);
+#endif
+}
- return FloatQuad();
+FloatQuad RenderObject::localToContainerQuad(const FloatQuad& localQuad, RenderBoxModelObject* repaintContainer, bool fixed) const
+{
+ TransformState transformState(TransformState::ApplyTransformDirection, FloatPoint(), &localQuad);
+ mapLocalToContainer(repaintContainer, fixed, true, transformState);
+ transformState.flatten();
+
+ return transformState.lastPlanarQuad();
}
IntSize RenderObject::offsetFromContainer(RenderObject* o) const
@@ -2473,10 +1730,8 @@ IntSize RenderObject::offsetFromContainer(RenderObject* o) const
ASSERT(o == container());
IntSize offset;
- offset.expand(0, o->borderTopExtra());
-
if (o->hasOverflowClip())
- offset -= o->layer()->scrolledContentOffset();
+ offset -= toRenderBox(o)->layer()->scrolledContentOffset();
return offset;
}
@@ -2489,50 +1744,29 @@ IntRect RenderObject::localCaretRect(InlineBox*, int, int* extraWidthToEndOfLine
return IntRect();
}
-int RenderObject::paddingTop() const
+RenderView* RenderObject::view() const
{
- int w = 0;
- Length padding = m_style->paddingTop();
- if (padding.isPercent())
- w = containingBlock()->availableWidth();
- return padding.calcMinValue(w);
+ return toRenderView(document()->renderer());
}
-int RenderObject::paddingBottom() const
+bool RenderObject::isRooted(RenderView** view)
{
- int w = 0;
- Length padding = style()->paddingBottom();
- if (padding.isPercent())
- w = containingBlock()->availableWidth();
- return padding.calcMinValue(w);
-}
+ RenderObject* o = this;
+ while (o->parent())
+ o = o->parent();
-int RenderObject::paddingLeft() const
-{
- int w = 0;
- Length padding = style()->paddingLeft();
- if (padding.isPercent())
- w = containingBlock()->availableWidth();
- return padding.calcMinValue(w);
-}
+ if (!o->isRenderView())
+ return false;
-int RenderObject::paddingRight() const
-{
- int w = 0;
- Length padding = style()->paddingRight();
- if (padding.isPercent())
- w = containingBlock()->availableWidth();
- return padding.calcMinValue(w);
-}
+ if (view)
+ *view = toRenderView(o);
-RenderView* RenderObject::view() const
-{
- return static_cast<RenderView*>(document()->renderer());
+ return true;
}
bool RenderObject::hasOutlineAnnotation() const
{
- return element() && element()->isLink() && document()->printing();
+ return node() && node()->isLink() && document()->printing();
}
RenderObject* RenderObject::container() const
@@ -2559,6 +1793,8 @@ RenderObject* RenderObject::container() const
// as we can. If we're in the tree, we'll get the root. If we
// aren't we'll get the root of our little subtree (most likely
// we'll just return 0).
+ // FIXME: The definition of view() has changed to not crawl up the render tree. It might
+ // be safe now to use it.
while (o && o->parent() && !(o->hasTransform() && o->isRenderBlock()))
o = o->parent();
} else if (pos == AbsolutePosition) {
@@ -2572,61 +1808,30 @@ RenderObject* RenderObject::container() const
return o;
}
-// This code has been written to anticipate the addition of CSS3-::outside and ::inside generated
-// content (and perhaps XBL). That's why it uses the render tree and not the DOM tree.
-RenderObject* RenderObject::hoverAncestor() const
-{
- return (!isInline() && continuation()) ? continuation() : parent();
-}
-
bool RenderObject::isSelectionBorder() const
{
SelectionState st = selectionState();
return st == SelectionStart || st == SelectionEnd || st == SelectionBoth;
}
-void RenderObject::removeFromObjectLists()
-{
- if (documentBeingDestroyed())
- return;
-
- if (isFloating()) {
- RenderBlock* outermostBlock = containingBlock();
- for (RenderBlock* p = outermostBlock; p && !p->isRenderView(); p = p->containingBlock()) {
- if (p->containsFloat(this))
- outermostBlock = p;
- }
-
- if (outermostBlock)
- outermostBlock->markAllDescendantsWithFloatsForLayout(this);
- }
-
- if (isPositioned()) {
- RenderObject* p;
- for (p = parent(); p; p = p->parent()) {
- if (p->isRenderBlock())
- static_cast<RenderBlock*>(p)->removePositionedObject(this);
- }
- }
-}
-
-bool RenderObject::documentBeingDestroyed() const
-{
- return !document()->renderer();
-}
-
void RenderObject::destroy()
{
+ // Destroy any leftover anonymous children.
+ RenderObjectChildList* children = virtualChildren();
+ if (children)
+ children->destroyLeftoverChildren();
+
// If this renderer is being autoscrolled, stop the autoscroll timer
- if (document()->frame() && document()->frame()->eventHandler()->autoscrollRenderer() == this)
+ if (document()->frame()->eventHandler()->autoscrollRenderer() == this)
document()->frame()->eventHandler()->stopAutoscrollTimer(true);
if (m_hasCounterNodeMap)
RenderCounter::destroyCounterNodes(this);
- if (AXObjectCache::accessibilityEnabled())
+ if (AXObjectCache::accessibilityEnabled()) {
+ document()->axObjectCache()->childrenChanged(this->parent());
document()->axObjectCache()->remove(this);
-
+ }
animation()->cancelAnimations(this);
// By default no ref-counting. RenderWidget::destroy() doesn't call
@@ -2635,12 +1840,13 @@ void RenderObject::destroy()
remove();
- RenderArena* arena = renderArena();
-
- if (hasLayer())
- layer()->destroy(arena);
-
- arenaDelete(arena, this);
+ // FIXME: Would like to do this in RenderBoxModelObject, but the timing is so complicated that this can't easily
+ // be moved into RenderBoxModelObject::destroy.
+ if (hasLayer()) {
+ setHasLayer(false);
+ toRenderBoxModelObject(this)->destroyLayer();
+ }
+ arenaDelete(renderArena(), this);
}
void RenderObject::arenaDelete(RenderArena* arena, void* base)
@@ -2676,9 +1882,14 @@ void RenderObject::arenaDelete(RenderArena* arena, void* base)
arena->free(*(size_t*)base, base);
}
-VisiblePosition RenderObject::positionForCoordinates(int, int)
+VisiblePosition RenderObject::positionForCoordinates(int x, int y)
{
- return VisiblePosition(element(), caretMinOffset(), DOWNSTREAM);
+ return positionForPoint(IntPoint(x, y));
+}
+
+VisiblePosition RenderObject::positionForPoint(const IntPoint&)
+{
+ return createVisiblePosition(caretMinOffset(), DOWNSTREAM);
}
void RenderObject::updateDragState(bool dragOn)
@@ -2686,11 +1897,9 @@ void RenderObject::updateDragState(bool dragOn)
bool valueChanged = (dragOn != m_isDragging);
m_isDragging = dragOn;
if (valueChanged && style()->affectedByDragRules())
- element()->setChanged();
+ node()->setNeedsStyleRecalc();
for (RenderObject* curr = firstChild(); curr; curr = curr->nextSibling())
curr->updateDragState(dragOn);
- if (continuation())
- continuation()->updateDragState(dragOn);
}
bool RenderObject::hitTest(const HitTestRequest& request, HitTestResult& result, const IntPoint& point, int tx, int ty, HitTestFilter hitTestFilter)
@@ -2721,34 +1930,12 @@ void RenderObject::updateHitTestResult(HitTestResult& result, const IntPoint& po
if (result.innerNode())
return;
- Node* node = element();
- IntPoint localPoint(point);
- if (isRenderView())
- node = document()->documentElement();
- else if (!isInline() && continuation())
- // We are in the margins of block elements that are part of a continuation. In
- // this case we're actually still inside the enclosing inline element that was
- // split. Go ahead and set our inner node accordingly.
- node = continuation()->element();
-
- if (node) {
- if (node->renderer() && node->renderer()->continuation() && node->renderer() != this) {
- // We're in the continuation of a split inline. Adjust our local point to be in the coordinate space
- // of the principal renderer's containing block. This will end up being the innerNonSharedNode.
- RenderObject* firstBlock = node->renderer()->containingBlock();
-
- // Get our containing block.
- RenderObject* block = this;
- if (isInline())
- block = containingBlock();
-
- localPoint.move(block->xPos() - firstBlock->xPos(), block->yPos() - firstBlock->yPos());
- }
-
- result.setInnerNode(node);
+ Node* n = node();
+ if (n) {
+ result.setInnerNode(n);
if (!result.innerNonSharedNode())
- result.setInnerNonSharedNode(node);
- result.setLocalPoint(localPoint);
+ result.setInnerNonSharedNode(n);
+ result.setLocalPoint(point);
}
}
@@ -2757,78 +1944,9 @@ bool RenderObject::nodeAtPoint(const HitTestRequest&, HitTestResult&, int /*x*/,
return false;
}
-int RenderObject::verticalPositionHint(bool firstLine) const
-{
- if (firstLine) // We're only really a first-line style if the document actually uses first-line rules.
- firstLine = document()->usesFirstLineRules();
- int vpos = m_verticalPosition;
- if (m_verticalPosition == PositionUndefined || firstLine) {
- vpos = getVerticalPosition(firstLine);
- if (!firstLine)
- m_verticalPosition = vpos;
- }
-
- return vpos;
-}
-
-int RenderObject::getVerticalPosition(bool firstLine) const
-{
- if (!isInline())
- return 0;
-
- // This method determines the vertical position for inline elements.
- int vpos = 0;
- EVerticalAlign va = style()->verticalAlign();
- if (va == TOP)
- vpos = PositionTop;
- else if (va == BOTTOM)
- vpos = PositionBottom;
- else {
- bool checkParent = parent()->isInline() && !parent()->isInlineBlockOrInlineTable() && parent()->style()->verticalAlign() != TOP && parent()->style()->verticalAlign() != BOTTOM;
- vpos = checkParent ? parent()->verticalPositionHint(firstLine) : 0;
- // don't allow elements nested inside text-top to have a different valignment.
- if (va == BASELINE)
- return vpos;
-
- const Font& f = parent()->style(firstLine)->font();
- int fontsize = f.pixelSize();
-
- if (va == SUB)
- vpos += fontsize / 5 + 1;
- else if (va == SUPER)
- vpos -= fontsize / 3 + 1;
- else if (va == TEXT_TOP)
- vpos += baselinePosition(firstLine) - f.ascent();
- else if (va == MIDDLE)
- vpos += -static_cast<int>(f.xHeight() / 2) - lineHeight(firstLine) / 2 + baselinePosition(firstLine);
- else if (va == TEXT_BOTTOM) {
- vpos += f.descent();
- if (!isReplaced())
- vpos -= style(firstLine)->font().descent();
- } else if (va == BASELINE_MIDDLE)
- vpos += -lineHeight(firstLine) / 2 + baselinePosition(firstLine);
- else if (va == LENGTH)
- vpos -= style()->verticalAlignLength().calcValue(lineHeight(firstLine));
- }
-
- return vpos;
-}
-
int RenderObject::lineHeight(bool firstLine, bool /*isRootLineBox*/) const
{
- RenderStyle* s = style(firstLine);
-
- Length lh = s->lineHeight();
-
- // its "unset", choose nice default
- if (lh.isNegative())
- return s->font().lineSpacing();
-
- if (lh.isPercent())
- return lh.calcMinValue(s->fontSize());
-
- // its fixed
- return lh.value();
+ return style(firstLine)->computedLineHeight();
}
int RenderObject::baselinePosition(bool firstLine, bool isRootLineBox) const
@@ -2840,7 +1958,7 @@ int RenderObject::baselinePosition(bool firstLine, bool isRootLineBox) const
void RenderObject::scheduleRelayout()
{
if (isRenderView()) {
- FrameView* view = static_cast<RenderView*>(this)->frameView();
+ FrameView* view = toRenderView(this)->frameView();
if (view)
view->scheduleRelayout();
} else if (parent()) {
@@ -2850,59 +1968,42 @@ void RenderObject::scheduleRelayout()
}
}
-void RenderObject::removeLeftoverAnonymousBlock(RenderBlock*)
-{
-}
-
-InlineBox* RenderObject::createInlineBox(bool, bool isRootLineBox, bool)
-{
- ASSERT(!isRootLineBox);
- return new (renderArena()) InlineBox(this);
-}
-
-void RenderObject::dirtyLineBoxes(bool, bool)
-{
-}
-
-InlineBox* RenderObject::inlineBoxWrapper() const
-{
- return 0;
-}
-
-void RenderObject::setInlineBoxWrapper(InlineBox*)
-{
-}
-
-void RenderObject::deleteLineBoxWrapper()
+void RenderObject::layout()
{
+ ASSERT(needsLayout());
+ RenderObject* child = firstChild();
+ while (child) {
+ child->layoutIfNeeded();
+ ASSERT(!child->needsLayout());
+ child = child->nextSibling();
+ }
+ setNeedsLayout(false);
}
-RenderStyle* RenderObject::firstLineStyle() const
+RenderStyle* RenderObject::firstLineStyleSlowCase() const
{
- if (!document()->usesFirstLineRules())
- return m_style.get();
+ ASSERT(document()->usesFirstLineRules());
- RenderStyle* s = m_style.get();
- const RenderObject* obj = isText() ? parent() : this;
- if (obj->isBlockFlow()) {
- RenderBlock* firstLineBlock = obj->firstLineBlock();
- if (firstLineBlock)
- s = firstLineBlock->getCachedPseudoStyle(RenderStyle::FIRST_LINE, style());
- } else if (!obj->isAnonymous() && obj->isInlineFlow()) {
- RenderStyle* parentStyle = obj->parent()->firstLineStyle();
- if (parentStyle != obj->parent()->style()) {
- // A first-line style is in effect. We need to cache a first-line style
- // for ourselves.
- style()->setHasPseudoStyle(RenderStyle::FIRST_LINE_INHERITED);
- s = obj->getCachedPseudoStyle(RenderStyle::FIRST_LINE_INHERITED, parentStyle);
+ RenderStyle* style = m_style.get();
+ const RenderObject* renderer = isText() ? parent() : this;
+ if (renderer->isBlockFlow()) {
+ if (RenderBlock* firstLineBlock = renderer->firstLineBlock())
+ style = firstLineBlock->getCachedPseudoStyle(FIRST_LINE, style);
+ } else if (!renderer->isAnonymous() && renderer->isRenderInline()) {
+ RenderStyle* parentStyle = renderer->parent()->firstLineStyle();
+ if (parentStyle != renderer->parent()->style()) {
+ // A first-line style is in effect. Cache a first-line style for ourselves.
+ style->setHasPseudoStyle(FIRST_LINE_INHERITED);
+ style = renderer->getCachedPseudoStyle(FIRST_LINE_INHERITED, parentStyle);
}
}
- return s;
+
+ return style;
}
-RenderStyle* RenderObject::getCachedPseudoStyle(RenderStyle::PseudoId pseudo, RenderStyle* parentStyle) const
+RenderStyle* RenderObject::getCachedPseudoStyle(PseudoId pseudo, RenderStyle* parentStyle) const
{
- if (pseudo < RenderStyle::FIRST_INTERNAL_PSEUDOID && !style()->hasPseudoStyle(pseudo))
+ if (pseudo < FIRST_INTERNAL_PSEUDOID && !style()->hasPseudoStyle(pseudo))
return 0;
RenderStyle* cachedStyle = style()->getCachedPseudoStyle(pseudo);
@@ -2915,26 +2016,26 @@ RenderStyle* RenderObject::getCachedPseudoStyle(RenderStyle::PseudoId pseudo, Re
return 0;
}
-PassRefPtr<RenderStyle> RenderObject::getUncachedPseudoStyle(RenderStyle::PseudoId pseudo, RenderStyle* parentStyle) const
+PassRefPtr<RenderStyle> RenderObject::getUncachedPseudoStyle(PseudoId pseudo, RenderStyle* parentStyle) const
{
- if (pseudo < RenderStyle::FIRST_INTERNAL_PSEUDOID && !style()->hasPseudoStyle(pseudo))
+ if (pseudo < FIRST_INTERNAL_PSEUDOID && !style()->hasPseudoStyle(pseudo))
return 0;
if (!parentStyle)
parentStyle = style();
- Node* node = element();
- while (node && !node->isElementNode())
- node = node->parentNode();
- if (!node)
+ Node* n = node();
+ while (n && !n->isElementNode())
+ n = n->parentNode();
+ if (!n)
return 0;
RefPtr<RenderStyle> result;
- if (pseudo == RenderStyle::FIRST_LINE_INHERITED) {
- result = document()->styleSelector()->styleForElement(static_cast<Element*>(node), parentStyle, false);
- result->setStyleType(RenderStyle::FIRST_LINE_INHERITED);
+ if (pseudo == FIRST_LINE_INHERITED) {
+ result = document()->styleSelector()->styleForElement(static_cast<Element*>(n), parentStyle, false);
+ result->setStyleType(FIRST_LINE_INHERITED);
} else
- result = document()->styleSelector()->pseudoStyleForElement(pseudo, static_cast<Element*>(node), parentStyle);
+ result = document()->styleSelector()->pseudoStyleForElement(pseudo, static_cast<Element*>(n), parentStyle);
return result.release();
}
@@ -2977,10 +2078,10 @@ void RenderObject::getTextDecorationColors(int decorations, Color& underline, Co
}
}
curr = curr->parent();
- if (curr && curr->isRenderBlock() && curr->continuation())
- curr = curr->continuation();
- } while (curr && decorations && (!quirksMode || !curr->element() ||
- (!curr->element()->hasTagName(aTag) && !curr->element()->hasTagName(fontTag))));
+ if (curr && curr->isRenderBlock() && toRenderBlock(curr)->inlineContinuation())
+ curr = toRenderBlock(curr)->inlineContinuation();
+ } while (curr && decorations && (!quirksMode || !curr->node() ||
+ (!curr->node()->hasTagName(aTag) && !curr->node()->hasTagName(fontTag))));
// If we bailed out, use the element we bailed out at (typically a <font> or <a> element).
if (decorations && curr) {
@@ -2993,24 +2094,22 @@ void RenderObject::getTextDecorationColors(int decorations, Color& underline, Co
}
}
-void RenderObject::updateWidgetPosition()
-{
-}
-
#if ENABLE(DASHBOARD_SUPPORT)
void RenderObject::addDashboardRegions(Vector<DashboardRegionValue>& regions)
{
// Convert the style regions to absolute coordinates.
- if (style()->visibility() != VISIBLE)
+ if (style()->visibility() != VISIBLE || !isBox())
return;
+
+ RenderBox* box = toRenderBox(this);
const Vector<StyleDashboardRegion>& styleRegions = style()->dashboardRegions();
unsigned i, count = styleRegions.size();
for (i = 0; i < count; i++) {
StyleDashboardRegion styleRegion = styleRegions[i];
- int w = width();
- int h = height();
+ int w = box->width();
+ int h = box->height();
DashboardRegionValue region;
region.label = styleRegion.label;
@@ -3056,32 +2155,6 @@ void RenderObject::collectDashboardRegions(Vector<DashboardRegionValue>& regions
}
#endif
-bool RenderObject::avoidsFloats() const
-{
- return isReplaced() || hasOverflowClip() || isHR();
-}
-
-bool RenderObject::shrinkToAvoidFloats() const
-{
- // FIXME: Technically we should be able to shrink replaced elements on a line, but this is difficult to accomplish, since this
- // involves doing a relayout during findNextLineBreak and somehow overriding the containingBlockWidth method to return the
- // current remaining width on a line.
- if (isInline() && !isHTMLMarquee() || !avoidsFloats())
- return false;
-
- // All auto-width objects that avoid floats should always use lineWidth.
- return style()->width().isAuto();
-}
-
-UChar RenderObject::backslashAsCurrencySymbol() const
-{
- if (Node *node = element()) {
- if (TextResourceDecoder* decoder = node->document()->decoder())
- return decoder->encoding().backslashAsCurrencySymbol();
- }
- return '\\';
-}
-
bool RenderObject::willRenderImage(CachedImage*)
{
// Without visibility we won't render (and therefore don't care about animation).
@@ -3097,7 +2170,7 @@ int RenderObject::maximalOutlineSize(PaintPhase p) const
{
if (p != PaintPhaseOutline && p != PaintPhaseSelfOutline && p != PaintPhaseChildOutlines)
return 0;
- return static_cast<RenderView*>(document()->renderer())->maximalOutlineSize();
+ return toRenderView(document()->renderer())->maximalOutlineSize();
}
int RenderObject::caretMinOffset() const
@@ -3108,7 +2181,7 @@ int RenderObject::caretMinOffset() const
int RenderObject::caretMaxOffset() const
{
if (isReplaced())
- return element() ? max(1U, element()->childNodeCount()) : 1;
+ return node() ? max(1U, node()->childNodeCount()) : 1;
if (isHR())
return 1;
return 0;
@@ -3124,44 +2197,19 @@ int RenderObject::previousOffset(int current) const
return current - 1;
}
-int RenderObject::nextOffset(int current) const
+int RenderObject::previousOffsetForBackwardDeletion(int current) const
{
- return current + 1;
-}
-
-int RenderObject::maxTopMargin(bool positive) const
-{
- return positive ? max(0, marginTop()) : -min(0, marginTop());
-}
-
-int RenderObject::maxBottomMargin(bool positive) const
-{
- return positive ? max(0, marginBottom()) : -min(0, marginBottom());
-}
-
-IntRect RenderObject::contentBox() const
-{
- return IntRect(borderLeft() + paddingLeft(), borderTop() + paddingTop(),
- contentWidth(), contentHeight());
-}
-
-IntRect RenderObject::absoluteContentBox() const
-{
- IntRect rect = contentBox();
- FloatPoint absPos = localToAbsoluteForContent(FloatPoint());
- rect.move(absPos.x(), absPos.y());
- return rect;
+ return current - 1;
}
-FloatQuad RenderObject::absoluteContentQuad() const
+int RenderObject::nextOffset(int current) const
{
- IntRect rect = contentBox();
- return localToAbsoluteQuad(FloatRect(rect));
+ return current + 1;
}
void RenderObject::adjustRectForOutlineAndShadow(IntRect& rect) const
{
- int outlineSize = !isInline() && continuation() ? continuation()->style()->outlineSize() : style()->outlineSize();
+ int outlineSize = outlineStyleForRepaint()->outlineSize();
if (ShadowData* boxShadow = style()->boxShadow()) {
int shadowLeft = 0;
int shadowRight = 0;
@@ -3184,24 +2232,6 @@ void RenderObject::adjustRectForOutlineAndShadow(IntRect& rect) const
rect.inflate(outlineSize);
}
-IntRect RenderObject::absoluteOutlineBounds() const
-{
- IntRect box = borderBox();
- adjustRectForOutlineAndShadow(box);
-
- FloatQuad absOutlineQuad = localToAbsoluteQuad(FloatRect(box));
- box = absOutlineQuad.enclosingBoundingBox();
- box.move(view()->layoutDelta());
-
- return box;
-}
-
-bool RenderObject::isScrollable() const
-{
- RenderLayer* l = enclosingLayer();
- return l && (l->verticalScrollbar() || l->horizontalScrollbar());
-}
-
AnimationController* RenderObject::animation() const
{
return document()->frame()->animation();
@@ -3212,82 +2242,150 @@ void RenderObject::imageChanged(CachedImage* image, const IntRect* rect)
imageChanged(static_cast<WrappedImagePtr>(image), rect);
}
-IntRect RenderObject::reflectionBox() const
+RenderBoxModelObject* RenderObject::offsetParent() const
{
- IntRect result;
- if (!m_style->boxReflect())
- return result;
- IntRect box = borderBox();
- result = box;
- switch (m_style->boxReflect()->direction()) {
- case ReflectionBelow:
- result.move(0, box.height() + reflectionOffset());
- break;
- case ReflectionAbove:
- result.move(0, -box.height() - reflectionOffset());
- break;
- case ReflectionLeft:
- result.move(-box.width() - reflectionOffset(), 0);
- break;
- case ReflectionRight:
- result.move(box.width() + reflectionOffset(), 0);
+ // If any of the following holds true return null and stop this algorithm:
+ // A is the root element.
+ // A is the HTML body element.
+ // The computed value of the position property for element A is fixed.
+ if (isRoot() || isBody() || (isPositioned() && style()->position() == FixedPosition))
+ return 0;
+
+ // If A is an area HTML element which has a map HTML element somewhere in the ancestor
+ // chain return the nearest ancestor map HTML element and stop this algorithm.
+ // FIXME: Implement!
+
+ // Return the nearest ancestor element of A for which at least one of the following is
+ // true and stop this algorithm if such an ancestor is found:
+ // * The computed value of the position property is not static.
+ // * It is the HTML body element.
+ // * The computed value of the position property of A is static and the ancestor
+ // is one of the following HTML elements: td, th, or table.
+ // * Our own extension: if there is a difference in the effective zoom
+ bool skipTables = isPositioned() || isRelPositioned();
+ float currZoom = style()->effectiveZoom();
+ RenderObject* curr = parent();
+ while (curr && (!curr->node() ||
+ (!curr->isPositioned() && !curr->isRelPositioned() && !curr->isBody()))) {
+ Node* element = curr->node();
+ if (!skipTables && element) {
+ bool isTableElement = element->hasTagName(tableTag) ||
+ element->hasTagName(tdTag) ||
+ element->hasTagName(thTag);
+
+#if ENABLE(WML)
+ if (!isTableElement && element->isWMLElement())
+ isTableElement = element->hasTagName(WMLNames::tableTag) ||
+ element->hasTagName(WMLNames::tdTag);
+#endif
+
+ if (isTableElement)
+ break;
+ }
+
+ float newZoom = curr->style()->effectiveZoom();
+ if (currZoom != newZoom)
break;
+ currZoom = newZoom;
+ curr = curr->parent();
}
- return result;
+ return curr && curr->isBoxModelObject() ? toRenderBoxModelObject(curr) : 0;
}
-int RenderObject::reflectionOffset() const
+VisiblePosition RenderObject::createVisiblePosition(int offset, EAffinity affinity)
{
- if (!m_style->boxReflect())
- return 0;
- if (m_style->boxReflect()->direction() == ReflectionLeft || m_style->boxReflect()->direction() == ReflectionRight)
- return m_style->boxReflect()->offset().calcValue(borderBox().width());
- return m_style->boxReflect()->offset().calcValue(borderBox().height());
+ // If this is a non-anonymous renderer, then it's simple.
+ if (Node* node = this->node())
+ return VisiblePosition(node, offset, affinity);
+
+ // We don't want to cross the boundary between editable and non-editable
+ // regions of the document, but that is either impossible or at least
+ // extremely unlikely in any normal case because we stop as soon as we
+ // find a single non-anonymous renderer.
+
+ // Find a nearby non-anonymous renderer.
+ RenderObject* child = this;
+ while (RenderObject* parent = child->parent()) {
+ // Find non-anonymous content after.
+ RenderObject* renderer = child;
+ while ((renderer = renderer->nextInPreOrder(parent))) {
+ if (Node* node = renderer->node())
+ return VisiblePosition(node, 0, DOWNSTREAM);
+ }
+
+ // Find non-anonymous content before.
+ renderer = child;
+ while ((renderer = renderer->previousInPreOrder())) {
+ if (renderer == parent)
+ break;
+ if (Node* node = renderer->node())
+ return VisiblePosition(lastDeepEditingPositionForNode(node), DOWNSTREAM);
+ }
+
+ // Use the parent itself unless it too is anonymous.
+ if (Node* node = parent->node())
+ return VisiblePosition(node, 0, DOWNSTREAM);
+
+ // Repeat at the next level up.
+ child = parent;
+ }
+
+ // Everything was anonymous. Give up.
+ return VisiblePosition();
}
-IntRect RenderObject::reflectedRect(const IntRect& r) const
+VisiblePosition RenderObject::createVisiblePosition(const Position& position)
{
- if (!m_style->boxReflect())
- return IntRect();
+ if (position.isNotNull())
+ return VisiblePosition(position);
- IntRect box = borderBox();
- IntRect result = r;
- switch (m_style->boxReflect()->direction()) {
- case ReflectionBelow:
- result.setY(box.bottom() + reflectionOffset() + (box.bottom() - r.bottom()));
- break;
- case ReflectionAbove:
- result.setY(box.y() - reflectionOffset() - box.height() + (box.bottom() - r.bottom()));
- break;
- case ReflectionLeft:
- result.setX(box.x() - reflectionOffset() - box.width() + (box.right() - r.right()));
- break;
- case ReflectionRight:
- result.setX(box.right() + reflectionOffset() + (box.right() - r.right()));
- break;
- }
- return result;
+ ASSERT(!node());
+ return createVisiblePosition(0, DOWNSTREAM);
}
#if ENABLE(SVG)
-FloatRect RenderObject::relativeBBox(bool) const
+FloatRect RenderObject::objectBoundingBox() const
{
+ ASSERT_NOT_REACHED();
+ return FloatRect();
+}
+
+// Returns the smallest rectangle enclosing all of the painted content
+// respecting clipping, masking, filters, opacity, stroke-width and markers
+FloatRect RenderObject::repaintRectInLocalCoordinates() const
+{
+ ASSERT_NOT_REACHED();
return FloatRect();
}
TransformationMatrix RenderObject::localTransform() const
{
- return TransformationMatrix(1, 0, 0, 1, xPos(), yPos());
+ return TransformationMatrix();
+}
+
+TransformationMatrix RenderObject::localToParentTransform() const
+{
+ // FIXME: This double virtual call indirection is temporary until I can land the
+ // rest of the of the localToParentTransform() support for SVG.
+ return localTransform();
}
TransformationMatrix RenderObject::absoluteTransform() const
{
+ // FIXME: This should use localToParentTransform(), but much of the SVG code
+ // depends on RenderBox::absoluteTransform() being the sum of the localTransform()s of all parent renderers.
if (parent())
return localTransform() * parent()->absoluteTransform();
return localTransform();
}
+bool RenderObject::nodeAtFloatPoint(const HitTestRequest&, HitTestResult&, const FloatPoint&, HitTestAction)
+{
+ ASSERT_NOT_REACHED();
+ return false;
+}
+
#endif // ENABLE(SVG)
} // namespace WebCore
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderObject.h b/src/3rdparty/webkit/WebCore/rendering/RenderObject.h
index 70841b7..311ef9c 100644
--- a/src/3rdparty/webkit/WebCore/rendering/RenderObject.h
+++ b/src/3rdparty/webkit/WebCore/rendering/RenderObject.h
@@ -3,7 +3,7 @@
* (C) 2000 Antti Koivisto (koivisto@kde.org)
* (C) 2000 Dirk Mueller (mueller@kde.org)
* (C) 2004 Allan Sandfeld Jensen (kde@carewolf.com)
- * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. 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
@@ -27,38 +27,30 @@
#include "CachedResourceClient.h"
#include "Document.h"
+#include "Element.h"
#include "FloatQuad.h"
+#include "RenderObjectChildList.h"
#include "RenderStyle.h"
-#include "ScrollTypes.h"
-#include "VisiblePosition.h"
-#include <wtf/HashMap.h>
+#include "TextAffinity.h"
+#include "TransformationMatrix.h"
+#include <wtf/UnusedParam.h>
namespace WebCore {
-class TransformationMatrix;
class AnimationController;
-class Color;
-class Document;
-class Element;
-class Event;
-class FloatRect;
-class FrameView;
-class HTMLAreaElement;
class HitTestResult;
class InlineBox;
class InlineFlowBox;
+class OverlapTestRequestClient;
class Position;
-class RenderArena;
+class RenderBoxModelObject;
+class RenderInline;
class RenderBlock;
class RenderFlow;
-class RenderFrameSet;
class RenderLayer;
-class RenderTable;
-class RenderText;
-class RenderView;
-class String;
-
-struct HitTestRequest;
+class RenderTheme;
+class TransformState;
+class VisiblePosition;
/*
* The painting of a layer occurs in three distinct phases. Each phase involves
@@ -104,12 +96,17 @@ enum HitTestAction {
HitTestForeground
};
-enum VerticalPositionHint {
- PositionTop = -0x7fffffff,
- PositionBottom = 0x7fffffff,
- PositionUndefined = static_cast<int>(0x80000000)
+// Sides used when drawing borders and outlines. This is in RenderObject rather than RenderBoxModelObject since outlines can
+// be drawn by SVG around bounding boxes.
+enum BoxSide {
+ BSTop,
+ BSBottom,
+ BSLeft,
+ BSRight
};
+const int caretWidth = 1;
+
#if ENABLE(DASHBOARD_SUPPORT)
struct DashboardRegionValue {
bool operator==(const DashboardRegionValue& o) const
@@ -128,22 +125,22 @@ struct DashboardRegionValue {
};
#endif
-// FIXME: This should be a HashSequencedSet, but we don't have that data structure yet.
-// This means the paint order of outlines will be wrong, although this is a minor issue.
-typedef HashSet<RenderFlow*> RenderFlowSequencedSet;
-
// Base class for all rendering tree objects.
class RenderObject : public CachedResourceClient {
- friend class RenderContainer;
- friend class RenderSVGContainer;
+ friend class RenderBlock;
+ friend class RenderBox;
friend class RenderLayer;
+ friend class RenderObjectChildList;
+ friend class RenderSVGContainer;
public:
// Anonymous objects should pass the document as their node, and they will then automatically be
// marked as anonymous in the constructor.
RenderObject(Node*);
virtual ~RenderObject();
- virtual const char* renderName() const { return "RenderObject"; }
+ RenderTheme* theme() const;
+
+ virtual const char* renderName() const = 0;
RenderObject* parent() const { return m_parent; }
bool isDescendantOf(const RenderObject*) const;
@@ -151,8 +148,20 @@ public:
RenderObject* previousSibling() const { return m_previous; }
RenderObject* nextSibling() const { return m_next; }
- virtual RenderObject* firstChild() const { return 0; }
- virtual RenderObject* lastChild() const { return 0; }
+ RenderObject* firstChild() const
+ {
+ if (const RenderObjectChildList* children = virtualChildren())
+ return children->firstChild();
+ return 0;
+ }
+ RenderObject* lastChild() const
+ {
+ if (const RenderObjectChildList* children = virtualChildren())
+ return children->lastChild();
+ return 0;
+ }
+ virtual RenderObjectChildList* virtualChildren() { return 0; }
+ virtual const RenderObjectChildList* virtualChildren() const { return 0; }
RenderObject* nextInPreOrder() const;
RenderObject* nextInPreOrder(RenderObject* stayWithin) const;
@@ -164,30 +173,26 @@ public:
RenderObject* firstLeafChild() const;
RenderObject* lastLeafChild() const;
- virtual RenderLayer* layer() const { return 0; }
+ // The following six functions are used when the render tree hierarchy changes to make sure layers get
+ // properly added and removed. Since containership can be implemented by any subclass, and since a hierarchy
+ // can contain a mixture of boxes and other object types, these functions need to be in the base class.
RenderLayer* enclosingLayer() const;
+ RenderLayer* enclosingSelfPaintingLayer() const;
void addLayers(RenderLayer* parentLayer, RenderObject* newObject);
void removeLayers(RenderLayer* parentLayer);
void moveLayers(RenderLayer* oldParent, RenderLayer* newParent);
RenderLayer* findNextLayer(RenderLayer* parentLayer, RenderObject* startPoint, bool checkParent = true);
- virtual void positionChildLayers() { }
- virtual bool requiresLayer();
-
- virtual IntRect getOverflowClipRect(int /*tx*/, int /*ty*/) { return IntRect(0, 0, 0, 0); }
- virtual IntRect getClipRect(int /*tx*/, int /*ty*/) { return IntRect(0, 0, 0, 0); }
- bool hasClip() { return isPositioned() && style()->hasClip(); }
-
- virtual int getBaselineOfFirstLineBox() const { return -1; }
- virtual int getBaselineOfLastLineBox() const { return -1; }
+ // Convenience function for getting to the nearest enclosing box of a RenderObject.
+ RenderBox* enclosingBox() const;
+
virtual bool isEmpty() const { return firstChild() == 0; }
- virtual bool isEdited() const { return false; }
- virtual void setEdited(bool) { }
-
#ifndef NDEBUG
void setHasAXObject(bool flag) { m_hasAXObject = flag; }
bool hasAXObject() const { return m_hasAXObject; }
+ bool isSetNeedsLayoutForbidden() const { return m_setNeedsLayoutForbidden; }
+ void setNeedsLayoutIsForbidden(bool flag) { m_setNeedsLayoutForbidden = flag; }
#endif
// Obtains the nearest enclosing block (including this block) that contributes a first-line style to our inline
@@ -198,35 +203,15 @@ public:
// again. We have to make sure the render tree updates as needed to accommodate the new
// normal flow object.
void handleDynamicFloatPositionChange();
-
- // This function is a convenience helper for creating an anonymous block that inherits its
- // style from this RenderObject.
- RenderBlock* createAnonymousBlock();
-
- // Whether or not a positioned element requires normal flow x/y to be computed
- // to determine its position.
- bool hasStaticX() const;
- bool hasStaticY() const;
- virtual void setStaticX(int /*staticX*/) { }
- virtual void setStaticY(int /*staticY*/) { }
- virtual int staticX() const { return 0; }
- virtual int staticY() const { return 0; }
-
+
// RenderObject tree manipulation
//////////////////////////////////////////
- virtual bool canHaveChildren() const;
+ virtual bool canHaveChildren() const { return virtualChildren(); }
virtual bool isChildAllowed(RenderObject*, RenderStyle*) const { return true; }
virtual void addChild(RenderObject* newChild, RenderObject* beforeChild = 0);
+ virtual void addChildIgnoringContinuation(RenderObject* newChild, RenderObject* beforeChild = 0) { return addChild(newChild, beforeChild); }
virtual void removeChild(RenderObject*);
virtual bool createsAnonymousWrapper() const { return false; }
-
- // raw tree manipulation
- virtual RenderObject* removeChildNode(RenderObject*, bool fullRemove = true);
- virtual void appendChildNode(RenderObject*, bool fullAppend = true);
- virtual void insertChildNode(RenderObject* child, RenderObject* before, bool fullInsert = true);
- // Designed for speed. Don't waste time doing a bunch of work like layer updating and repainting when we know that our
- // change in parentage is not going to affect anything.
- virtual void moveChildNode(RenderObject*);
//////////////////////////////////////////
protected:
@@ -238,6 +223,7 @@ protected:
//////////////////////////////////////////
private:
void addAbsoluteRectForLayer(IntRect& result);
+ void setLayerNeedsFullRepaint();
public:
#ifndef NDEBUG
@@ -263,20 +249,20 @@ public:
virtual bool isApplet() const { return false; }
virtual bool isBR() const { return false; }
virtual bool isBlockFlow() const { return false; }
+ virtual bool isBoxModelObject() const { return false; }
virtual bool isCounter() const { return false; }
virtual bool isFieldset() const { return false; }
virtual bool isFrame() const { return false; }
virtual bool isFrameSet() const { return false; }
virtual bool isImage() const { return false; }
virtual bool isInlineBlockOrInlineTable() const { return false; }
- virtual bool isInlineContinuation() const;
- virtual bool isInlineFlow() const { return false; }
virtual bool isListBox() const { return false; }
virtual bool isListItem() const { return false; }
virtual bool isListMarker() const { return false; }
virtual bool isMedia() const { return false; }
virtual bool isMenuList() const { return false; }
virtual bool isRenderBlock() const { return false; }
+ virtual bool isRenderButton() const { return false; }
virtual bool isRenderImage() const { return false; }
virtual bool isRenderInline() const { return false; }
virtual bool isRenderPart() const { return false; }
@@ -287,50 +273,80 @@ public:
virtual bool isTableCol() const { return false; }
virtual bool isTableRow() const { return false; }
virtual bool isTableSection() const { return false; }
+ virtual bool isTextControl() const { return false; }
virtual bool isTextArea() const { return false; }
virtual bool isTextField() const { return false; }
+ virtual bool isVideo() const { return false; }
virtual bool isWidget() const { return false; }
-
- bool isRoot() const { return document()->documentElement() == node(); }
+ bool isRoot() const { return document()->documentElement() == m_node; }
bool isBody() const;
bool isHR() const;
bool isHTMLMarquee() const;
- virtual bool childrenInline() const { return false; }
- virtual void setChildrenInline(bool) { }
-
- virtual RenderFlow* continuation() const;
+ bool childrenInline() const { return m_childrenInline; }
+ void setChildrenInline(bool b = true) { m_childrenInline = b; }
+ bool hasColumns() const { return m_hasColumns; }
+ void setHasColumns(bool b = true) { m_hasColumns = b; }
+ bool cellWidthChanged() const { return m_cellWidthChanged; }
+ void setCellWidthChanged(bool b = true) { m_cellWidthChanged = b; }
#if ENABLE(SVG)
+ // FIXME: Until all SVG renders can be subclasses of RenderSVGModelObject we have
+ // to add SVG renderer methods to RenderObject with an ASSERT_NOT_REACHED() default implementation.
virtual bool isSVGRoot() const { return false; }
virtual bool isSVGContainer() const { return false; }
virtual bool isSVGHiddenContainer() const { return false; }
virtual bool isRenderPath() const { return false; }
virtual bool isSVGText() const { return false; }
+ virtual bool isSVGImage() const { return false; }
+
+ // Per SVG 1.1 objectBoundingBox ignores clipping, masking, filter effects, opacity and stroke-width.
+ // This is used for all computation of objectBoundingBox relative units and by SVGLocateable::getBBox().
+ // NOTE: Markers are not specifically ignored here by SVG 1.1 spec, but we ignore them
+ // since stroke-width is ignored (and marker size can depend on stroke-width).
+ // objectBoundingBox is returned local coordinates.
+ // The name objectBoundingBox is taken from the SVG 1.1 spec.
+ virtual FloatRect objectBoundingBox() const;
+
+ // Returns the smallest rectangle enclosing all of the painted content
+ // respecting clipping, masking, filters, opacity, stroke-width and markers
+ virtual FloatRect repaintRectInLocalCoordinates() const;
+
+ // FIXME: This accessor is deprecated and mostly around for SVGRenderTreeAsText.
+ // This only returns the transform="" value from the element
+ // most callsites want localToParentTransform() instead.
+ virtual TransformationMatrix localTransform() const;
- virtual FloatRect relativeBBox(bool includeStroke = true) const;
+ // Returns the full transform mapping from local coordinates to local coords for the parent SVG renderer
+ // This includes any viewport transforms and x/y offsets as well as the transform="" value off the element.
+ virtual TransformationMatrix localToParentTransform() const;
- virtual TransformationMatrix localTransform() const;
+ // Walks up the parent chain to create a transform which maps from local to document coords
+ // NOTE: This method is deprecated! It doesn't respect scroll offsets or repaint containers.
+ // FIXME: This is only virtual so that RenderSVGHiddenContainer can override it to match old LayoutTest results.
virtual TransformationMatrix absoluteTransform() const;
-#endif
- virtual bool isEditable() const;
+ // SVG uses FloatPoint precise hit testing, and passes the point in parent
+ // coordinates instead of in repaint container coordinates. Eventually the
+ // rest of the rendering tree will move to a similar model.
+ virtual bool nodeAtFloatPoint(const HitTestRequest&, HitTestResult&, const FloatPoint& pointInParent, HitTestAction);
+#endif
bool isAnonymous() const { return m_isAnonymous; }
void setIsAnonymous(bool b) { m_isAnonymous = b; }
bool isAnonymousBlock() const
{
- return m_isAnonymous && style()->display() == BLOCK && style()->styleType() == RenderStyle::NOPSEUDO && !isListMarker();
+ return m_isAnonymous && style()->display() == BLOCK && style()->styleType() == NOPSEUDO && !isListMarker();
}
-
+ bool isInlineContinuation() const { return (node() ? node()->renderer() != this : false) && isRenderInline(); }
bool isFloating() const { return m_floating; }
bool isPositioned() const { return m_positioned; } // absolute or fixed positioning
bool isRelPositioned() const { return m_relPositioned; } // relative positioning
bool isText() const { return m_isText; }
+ bool isBox() const { return m_isBox; }
bool isInline() const { return m_inline; } // inline object
- bool isCompact() const { return style()->display() == COMPACT; } // compact object
bool isRunIn() const { return style()->display() == RUN_IN; } // run-in object
bool isDragging() const { return m_isDragging; }
bool isReplaced() const { return m_replaced; } // a "replaced" element (see CSS)
@@ -340,9 +356,6 @@ public:
bool hasBoxDecorations() const { return m_paintBackground; }
bool mustRepaintBackgroundOrBorder() const;
- bool hasHorizontalBordersPaddingOrMargin() const { return hasHorizontalBordersOrPadding() || marginLeft() != 0 || marginRight() != 0; }
- bool hasHorizontalBordersOrPadding() const { return borderLeft() != 0 || borderRight() != 0 || paddingLeft() != 0 || paddingRight() != 0; }
-
bool needsLayout() const { return m_needsLayout || m_normalChildNeedsLayout || m_posChildNeedsLayout || m_needsPositionedMovementLayout; }
bool selfNeedsLayout() const { return m_needsLayout; }
bool needsPositionedMovementLayout() const { return m_needsPositionedMovementLayout; }
@@ -354,43 +367,33 @@ public:
bool isSelectionBorder() const;
+ bool hasClip() const { return isPositioned() && style()->hasClip(); }
bool hasOverflowClip() const { return m_hasOverflowClip; }
- virtual bool hasControlClip() const { return false; }
- virtual IntRect controlClipRect(int /*tx*/, int /*ty*/) const { return IntRect(); }
-
- bool hasAutoVerticalScrollbar() const { return hasOverflowClip() && (style()->overflowY() == OAUTO || style()->overflowY() == OOVERLAY); }
- bool hasAutoHorizontalScrollbar() const { return hasOverflowClip() && (style()->overflowX() == OAUTO || style()->overflowX() == OOVERLAY); }
-
- bool scrollsOverflow() const { return scrollsOverflowX() || scrollsOverflowY(); }
- bool scrollsOverflowX() const { return hasOverflowClip() && (style()->overflowX() == OSCROLL || hasAutoHorizontalScrollbar()); }
- bool scrollsOverflowY() const { return hasOverflowClip() && (style()->overflowY() == OSCROLL || hasAutoVerticalScrollbar()); }
- virtual int verticalScrollbarWidth() const;
- virtual int horizontalScrollbarHeight() const;
-
bool hasTransform() const { return m_hasTransform; }
bool hasMask() const { return style() && style()->hasMask(); }
- virtual IntRect maskClipRect() { return borderBox(); }
-private:
- bool includeVerticalScrollbarSize() const { return hasOverflowClip() && (style()->overflowY() == OSCROLL || style()->overflowY() == OAUTO); }
- bool includeHorizontalScrollbarSize() const { return hasOverflowClip() && (style()->overflowX() == OSCROLL || style()->overflowX() == OAUTO); }
+ void drawLineForBoxSide(GraphicsContext*, int x1, int y1, int x2, int y2, BoxSide,
+ Color, const Color& textcolor, EBorderStyle, int adjbw1, int adjbw2);
+ void drawArcForBoxSide(GraphicsContext*, int x, int y, float thickness, IntSize radius, int angleStart,
+ int angleSpan, BoxSide, Color, const Color& textcolor, EBorderStyle, bool firstCorner);
public:
// The pseudo element style can be cached or uncached. Use the cached method if the pseudo element doesn't respect
// any pseudo classes (and therefore has no concept of changing state).
- RenderStyle* getCachedPseudoStyle(RenderStyle::PseudoId, RenderStyle* parentStyle = 0) const;
- PassRefPtr<RenderStyle> getUncachedPseudoStyle(RenderStyle::PseudoId, RenderStyle* parentStyle = 0) const;
+ RenderStyle* getCachedPseudoStyle(PseudoId, RenderStyle* parentStyle = 0) const;
+ PassRefPtr<RenderStyle> getUncachedPseudoStyle(PseudoId, RenderStyle* parentStyle = 0) const;
- void updateDragState(bool dragOn);
+ virtual void updateDragState(bool dragOn);
RenderView* view() const;
- // don't even think about making this method virtual!
- Node* element() const { return m_isAnonymous ? 0 : m_node; }
+ // Returns true if this renderer is rooted, and optionally returns the hosting view (the root of the hierarchy).
+ bool isRooted(RenderView** = 0);
+
+ Node* node() const { return m_isAnonymous ? 0 : m_node; }
Document* document() const { return m_node->document(); }
void setNode(Node* node) { m_node = node; }
- Node* node() const { return m_node; }
bool hasOutlineAnnotation() const;
bool hasOutline() const { return style()->hasOutline() || hasOutlineAnnotation(); }
@@ -400,16 +403,17 @@ public:
* positioned elements
*/
RenderObject* container() const;
- RenderObject* hoverAncestor() const;
+ virtual RenderObject* hoverAncestor() const { return parent(); }
+
+ // IE Extension that can be called on any RenderObject. See the implementation for the details.
+ RenderBoxModelObject* offsetParent() const;
- virtual void markAllDescendantsWithFloatsForLayout(RenderObject* floatToRemove = 0);
void markContainingBlocksForLayout(bool scheduleRelayout = true, RenderObject* newRoot = 0);
void setNeedsLayout(bool b, bool markParents = true);
void setChildNeedsLayout(bool b, bool markParents = true);
void setNeedsPositionedMovementLayout();
void setPrefWidthsDirty(bool, bool markParents = true);
void invalidateContainerPrefWidths();
- virtual void invalidateCounters() { }
void setNeedsLayoutAndPrefWidthsRecalc()
{
@@ -422,7 +426,8 @@ public:
void setFloating(bool b = true) { m_floating = b; }
void setInline(bool b = true) { m_inline = b; }
void setHasBoxDecorations(bool b = true) { m_paintBackground = b; }
- void setRenderText() { m_isText = true; }
+ void setIsText() { m_isText = true; }
+ void setIsBox() { m_isBox = true; }
void setReplaced(bool b = true) { m_replaced = b; }
void setHasOverflowClip(bool b = true) { m_hasOverflowClip = b; }
void setHasLayer(bool b = true) { m_hasLayer = b; }
@@ -434,37 +439,29 @@ public:
void updateFillImages(const FillLayer*, const FillLayer*);
void updateImage(StyleImage*, StyleImage*);
- virtual InlineBox* createInlineBox(bool makePlaceHolderBox, bool isRootLineBox, bool isOnlyRun = false);
- virtual void dirtyLineBoxes(bool fullLayout, bool isRootLineBox = false);
-
- // For inline replaced elements, this function returns the inline box that owns us. Enables
- // the replaced RenderObject to quickly determine what line it is contained on and to easily
- // iterate over structures on the line.
- virtual InlineBox* inlineBoxWrapper() const;
- virtual void setInlineBoxWrapper(InlineBox*);
- virtual void deleteLineBoxWrapper();
-
// for discussion of lineHeight see CSS2 spec
virtual int lineHeight(bool firstLine, bool isRootLineBox = false) const;
// for the vertical-align property of inline elements
- // the difference between this objects baseline position and the lines baseline position.
- virtual int verticalPositionHint(bool firstLine) const;
// the offset of baseline from the top of the object.
virtual int baselinePosition(bool firstLine, bool isRootLineBox = false) const;
+ typedef HashMap<OverlapTestRequestClient*, IntRect> OverlapTestRequestMap;
+
/*
* Paint the object and its children, clipped by (x|y|w|h).
* (tx|ty) is the calculated position of the parent
*/
struct PaintInfo {
PaintInfo(GraphicsContext* newContext, const IntRect& newRect, PaintPhase newPhase, bool newForceBlackText,
- RenderObject* newPaintingRoot, RenderFlowSequencedSet* newOutlineObjects)
+ RenderObject* newPaintingRoot, ListHashSet<RenderInline*>* newOutlineObjects,
+ OverlapTestRequestMap* overlapTestRequests = 0)
: context(newContext)
, rect(newRect)
, phase(newPhase)
, forceBlackText(newForceBlackText)
, paintingRoot(newPaintingRoot)
, outlineObjects(newOutlineObjects)
+ , overlapTestRequests(overlapTestRequests)
{
}
@@ -473,40 +470,14 @@ public:
PaintPhase phase;
bool forceBlackText;
RenderObject* paintingRoot; // used to draw just one element and its visual kids
- RenderFlowSequencedSet* outlineObjects; // used to list outlines that should be painted by a block with inline children
+ ListHashSet<RenderInline*>* outlineObjects; // used to list outlines that should be painted by a block with inline children
+ OverlapTestRequestMap* overlapTestRequests;
};
virtual void paint(PaintInfo&, int tx, int ty);
- void paintBorder(GraphicsContext*, int tx, int ty, int w, int h, const RenderStyle*, bool begin = true, bool end = true);
- bool paintNinePieceImage(GraphicsContext*, int tx, int ty, int w, int h, const RenderStyle*, const NinePieceImage&, CompositeOperator = CompositeSourceOver);
- void paintOutline(GraphicsContext*, int tx, int ty, int w, int h, const RenderStyle*);
- void paintBoxShadow(GraphicsContext*, int tx, int ty, int w, int h, const RenderStyle*, bool begin = true, bool end = true);
-
- // RenderBox implements this.
- virtual void paintBoxDecorations(PaintInfo&, int /*tx*/, int /*ty*/) { }
- virtual void paintMask(PaintInfo&, int /*tx*/, int /*ty*/) { }
- virtual void paintFillLayerExtended(const PaintInfo&, const Color&, const FillLayer*,
- int /*clipY*/, int /*clipH*/, int /*tx*/, int /*ty*/, int /*width*/, int /*height*/,
- InlineFlowBox* = 0, CompositeOperator = CompositeSourceOver) { }
-
-
- /*
- * Calculates the actual width of the object (only for non inline
- * objects)
- */
- virtual void calcWidth() { }
- /*
- * This function should cause the Element to calculate its
- * width and height and the layout of its content
- *
- * when the Element calls setNeedsLayout(false), layout() is no
- * longer called during relayouts, as long as there is no
- * style sheet change. When that occurs, m_needsLayout will be
- * set to true and the Element receives layout() calls
- * again.
- */
- virtual void layout() = 0;
+ // Recursive function that computes the size and position of this object and all its descendants.
+ virtual void layout();
/* This function performs a layout only if one is needed. */
void layoutIfNeeded() { if (needsLayout()) layout(); }
@@ -519,24 +490,19 @@ public:
// repaint and do not need a relayout
virtual void updateFromElement() { }
- // Block flows subclass availableWidth to handle multi column layout (shrinking the width available to children when laying out.)
- virtual int availableWidth() const { return contentWidth(); }
-
- virtual int availableHeight() const { return 0; }
-
- virtual void updateWidgetPosition();
-
#if ENABLE(DASHBOARD_SUPPORT)
- void addDashboardRegions(Vector<DashboardRegionValue>&);
+ virtual void addDashboardRegions(Vector<DashboardRegionValue>&);
void collectDashboardRegions(Vector<DashboardRegionValue>&);
#endif
bool hitTest(const HitTestRequest&, HitTestResult&, const IntPoint&, int tx, int ty, HitTestFilter = HitTestAll);
virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, int x, int y, int tx, int ty, HitTestAction);
- void updateHitTestResult(HitTestResult&, const IntPoint&);
+ virtual void updateHitTestResult(HitTestResult&, const IntPoint&);
- virtual VisiblePosition positionForCoordinates(int x, int y);
- VisiblePosition positionForPoint(const IntPoint& point) { return positionForCoordinates(point.x(), point.y()); }
+ VisiblePosition positionForCoordinates(int x, int y);
+ virtual VisiblePosition positionForPoint(const IntPoint&);
+ VisiblePosition createVisiblePosition(int offset, EAffinity);
+ VisiblePosition createVisiblePosition(const Position&);
virtual void dirtyLinesFromChangedChild(RenderObject*);
@@ -555,186 +521,54 @@ public:
// returns the containing block level element for this element.
RenderBlock* containingBlock() const;
- // return just the width of the containing block
- virtual int containingBlockWidth() const;
- // return just the height of the containing block
- virtual int containingBlockHeight() const;
-
- // content area (box minus padding/border)
- IntRect contentBox() const;
- // absolute coords of content area. Ignores transforms.
- IntRect absoluteContentBox() const;
- // content rect converted to absolute coords, taking transforms into account
- FloatQuad absoluteContentQuad() const;
-
- int contentWidth() const { return clientWidth() - paddingLeft() - paddingRight(); }
- int contentHeight() const { return clientHeight() - paddingTop() - paddingBottom(); }
-
- // used by flexible boxes to impose a flexed width/height override
- virtual int overrideSize() const { return 0; }
- virtual int overrideWidth() const { return 0; }
- virtual int overrideHeight() const { return 0; }
- virtual void setOverrideSize(int /*overrideSize*/) { }
-
- // relative to parent node
- virtual void setPos(int /*xPos*/, int /*yPos*/) { }
- virtual void setWidth(int /*width*/) { }
- virtual void setHeight(int /*height*/) { }
- virtual void setRect(const IntRect& rect) { setPos(rect.x(), rect.y()); setWidth(rect.width()); setHeight(rect.height()); }
-
- virtual int xPos() const { return 0; }
- virtual int yPos() const { return 0; }
-
// Convert the given local point to absolute coordinates
// FIXME: Temporary. If useTransforms is true, take transforms into account. Eventually localToAbsolute() will always be transform-aware.
- virtual FloatPoint localToAbsolute(FloatPoint localPoint = FloatPoint(), bool fixed = false, bool useTransforms = false) const;
- virtual FloatPoint absoluteToLocal(FloatPoint, bool fixed = false, bool useTransforms = false) const;
+ FloatPoint localToAbsolute(FloatPoint localPoint = FloatPoint(), bool fixed = false, bool useTransforms = false) const;
+ FloatPoint absoluteToLocal(FloatPoint, bool fixed = false, bool useTransforms = false) const;
- // This function is used to deal with the extra top space that can occur in table cells (called borderTopExtra).
- // The children of the cell do not factor this space in, so we have to add it in. Any code that wants to
- // accurately deal with the contents of a cell must call this function instad of absolutePosition.
- FloatPoint localToAbsoluteForContent(FloatPoint localPoint = FloatPoint(), bool fixed = false, bool useTransforms = false) const
+ // Convert a local quad to absolute coordinates, taking transforms into account.
+ FloatQuad localToAbsoluteQuad(const FloatQuad& quad, bool fixed = false) const
{
- localPoint.move(0.0f, static_cast<float>(borderTopExtra()));
- return localToAbsolute(localPoint, fixed, useTransforms);
+ return localToContainerQuad(quad, 0, fixed);
}
-
- // Convert a local quad to an absolute quad, taking transforms into account.
- virtual FloatQuad localToAbsoluteQuad(const FloatQuad&, bool fixed = false) const;
+ // Convert a local quad into the coordinate system of container, taking transforms into account.
+ FloatQuad localToContainerQuad(const FloatQuad&, RenderBoxModelObject* repaintContainer, bool fixed = false) const;
// Return the offset from the container() renderer (excluding transforms)
virtual IntSize offsetFromContainer(RenderObject*) const;
-
- // width and height are without margins but include paddings and borders
- virtual int width() const { return 0; }
- virtual int height() const { return 0; }
-
- virtual IntRect borderBox() const { return IntRect(0, 0, width(), height()); }
- // Bounds of the outline box in absolute coords. Respects transforms
- IntRect absoluteOutlineBounds() const;
-
- // The height of a block when you include normal flow overflow spillage out of the bottom
- // of the block (e.g., a <div style="height:25px"> that has a 100px tall image inside
- // it would have an overflow height of borderTop() + paddingTop() + 100px.
- virtual int overflowHeight(bool /*includeInterior*/ = true) const { return height(); }
- virtual int overflowWidth(bool /*includeInterior*/ = true) const { return width(); }
- virtual void setOverflowHeight(int) { }
- virtual void setOverflowWidth(int) { }
- virtual int overflowLeft(bool /*includeInterior*/ = true) const { return 0; }
- virtual int overflowTop(bool /*includeInterior*/ = true) const { return 0; }
- virtual IntRect overflowRect(bool /*includeInterior*/ = true) const { return borderBox(); }
-
- // IE extensions. Used to calculate offsetWidth/Height. Overridden by inlines (RenderFlow)
- // to return the remaining width on a given line (and the height of a single line).
- virtual int offsetWidth() const { return width(); }
- virtual int offsetHeight() const { return height() + borderTopExtra() + borderBottomExtra(); }
-
- // IE extensions. Also supported by Gecko. We override in render flow to get the
- // left and top correct. -dwh
- virtual int offsetLeft() const;
- virtual int offsetTop() const;
- virtual RenderObject* offsetParent() const;
-
- // More IE extensions. clientWidth and clientHeight represent the interior of an object
- // excluding border and scrollbar. clientLeft/Top are just the borderLeftWidth and borderTopWidth.
- int clientLeft() const { return borderLeft(); }
- int clientTop() const { return borderTop(); }
- int clientWidth() const;
- int clientHeight() const;
-
- // scrollWidth/scrollHeight will be the same as clientWidth/clientHeight unless the
- // object has overflow:hidden/scroll/auto specified and also has overflow.
- // scrollLeft/Top return the current scroll position. These methods are virtual so that objects like
- // textareas can scroll shadow content (but pretend that they are the objects that are
- // scrolling).
- virtual int scrollLeft() const;
- virtual int scrollTop() const;
- virtual int scrollWidth() const;
- virtual int scrollHeight() const;
- virtual void setScrollLeft(int);
- virtual void setScrollTop(int);
-
- virtual bool scroll(ScrollDirection, ScrollGranularity, float multiplier = 1.0f);
- virtual bool canBeProgramaticallyScrolled(bool) const;
- virtual void autoscroll();
- virtual void stopAutoscroll() { }
-
- virtual void panScroll(const IntPoint&);
-
- virtual bool isScrollable() const;
-
- // The following seven functions are used to implement collapsing margins.
- // All objects know their maximal positive and negative margins. The
- // formula for computing a collapsed margin is |maxPosMargin|-|maxNegmargin|.
- // For a non-collapsing, e.g., a leaf element, this formula will simply return
- // the margin of the element. Blocks override the maxTopMargin and maxBottomMargin
- // methods.
- virtual bool isSelfCollapsingBlock() const { return false; }
- virtual int collapsedMarginTop() const { return maxTopMargin(true) - maxTopMargin(false); }
- virtual int collapsedMarginBottom() const { return maxBottomMargin(true) - maxBottomMargin(false); }
- virtual bool isTopMarginQuirk() const { return false; }
- virtual bool isBottomMarginQuirk() const { return false; }
-
- virtual int maxTopMargin(bool positive) const;
- virtual int maxBottomMargin(bool positive) const;
-
- virtual int marginTop() const { return 0; }
- virtual int marginBottom() const { return 0; }
- virtual int marginLeft() const { return 0; }
- virtual int marginRight() const { return 0; }
-
- // Virtual since table cells override
- virtual int paddingTop() const;
- virtual int paddingBottom() const;
- virtual int paddingLeft() const;
- virtual int paddingRight() const;
-
- virtual int borderTop() const { return style()->borderTopWidth(); }
- virtual int borderBottom() const { return style()->borderBottomWidth(); }
- virtual int borderTopExtra() const { return 0; }
- virtual int borderBottomExtra() const { return 0; }
- virtual int borderLeft() const { return style()->borderLeftWidth(); }
- virtual int borderRight() const { return style()->borderRightWidth(); }
-
- virtual void addLineBoxRects(Vector<IntRect>&, unsigned startOffset = 0, unsigned endOffset = UINT_MAX, bool useSelectionHeight = false);
-
- virtual void absoluteRects(Vector<IntRect>&, int tx, int ty, bool topLevel = true);
+
+ virtual void absoluteRects(Vector<IntRect>&, int, int) { }
// FIXME: useTransforms should go away eventually
IntRect absoluteBoundingBoxRect(bool useTransforms = false);
// Build an array of quads in absolute coords for line boxes
- virtual void collectAbsoluteLineBoxQuads(Vector<FloatQuad>&, unsigned startOffset = 0, unsigned endOffset = UINT_MAX, bool useSelectionHeight = false);
- virtual void absoluteQuads(Vector<FloatQuad>&, bool topLevel = true);
+ virtual void absoluteQuads(Vector<FloatQuad>&) { }
// the rect that will be painted if this object is passed as the paintingRoot
IntRect paintingRootRect(IntRect& topLevelRect);
- void addPDFURLRect(GraphicsContext*, const IntRect&);
-
- virtual void addFocusRingRects(GraphicsContext*, int tx, int ty);
-
virtual int minPrefWidth() const { return 0; }
virtual int maxPrefWidth() const { return 0; }
RenderStyle* style() const { return m_style.get(); }
- RenderStyle* firstLineStyle() const;
+ RenderStyle* firstLineStyle() const { return document()->usesFirstLineRules() ? firstLineStyleSlowCase() : style(); }
RenderStyle* style(bool firstLine) const { return firstLine ? firstLineStyle() : style(); }
-
+
+ // Anonymous blocks that are part of of a continuation chain will return their inline continuation's outline style instead.
+ // This is typically only relevant when repainting.
+ virtual RenderStyle* outlineStyleForRepaint() const { return style(); }
+
void getTextDecorationColors(int decorations, Color& underline, Color& overline,
Color& linethrough, bool quirksMode = false);
- enum BorderSide {
- BSTop,
- BSBottom,
- BSLeft,
- BSRight
- };
-
- void drawBorderArc(GraphicsContext*, int x, int y, float thickness, IntSize radius, int angleStart,
- int angleSpan, BorderSide, Color, const Color& textcolor, EBorderStyle, bool firstCorner);
- void drawBorder(GraphicsContext*, int x1, int y1, int x2, int y2, BorderSide,
- Color, const Color& textcolor, EBorderStyle, int adjbw1, int adjbw2);
-
+ // Return the RenderBox in the container chain which is responsible for painting this object, or 0
+ // if painting is root-relative. This is the container that should be passed to the 'forRepaint'
+ // methods.
+ RenderBoxModelObject* containerForRepaint() const;
+ // Actually do the repaint of rect r for this object which has been computed in the coordinate space
+ // of repaintContainer. If repaintContainer is 0, repaint via the view.
+ void repaintUsingContainer(RenderBoxModelObject* repaintContainer, const IntRect& r, bool immediate = false);
+
// Repaint the entire object. Called when, e.g., the color of a border changes, or when a border
// style changes.
void repaint(bool immediate = false);
@@ -743,7 +577,7 @@ public:
void repaintRectangle(const IntRect&, bool immediate = false);
// Repaint only if our old bounds and new bounds are different.
- bool repaintAfterLayoutIfNeeded(const IntRect& oldBounds, const IntRect& oldOutlineBox);
+ bool repaintAfterLayoutIfNeeded(RenderBoxModelObject* repaintContainer, const IntRect& oldBounds, const IntRect& oldOutlineBox);
// Repaint only if the object moved.
virtual void repaintDuringLayoutIfMoved(const IntRect& rect);
@@ -755,42 +589,38 @@ public:
// Returns the rect that should be repainted whenever this object changes. The rect is in the view's
// coordinate space. This method deals with outlines and overflow.
- virtual IntRect absoluteClippedOverflowRect();
-
- IntRect getAbsoluteRepaintRectWithOutline(int ow);
+ IntRect absoluteClippedOverflowRect()
+ {
+ return clippedOverflowRectForRepaint(0);
+ }
+ virtual IntRect clippedOverflowRectForRepaint(RenderBoxModelObject* repaintContainer);
+ virtual IntRect rectWithOutlineForRepaint(RenderBoxModelObject* repaintContainer, int outlineWidth);
- // Given a rect in the object's coordinate space, this method converts the rectangle to the view's
- // coordinate space.
- virtual void computeAbsoluteRepaintRect(IntRect&, bool fixed = false);
+ // Given a rect in the object's coordinate space, compute a rect suitable for repainting
+ // that rect in view coordinates.
+ void computeAbsoluteRepaintRect(IntRect& r, bool fixed = false)
+ {
+ return computeRectForRepaint(0, r, fixed);
+ }
+ // Given a rect in the object's coordinate space, compute a rect suitable for repainting
+ // that rect in the coordinate space of repaintContainer.
+ virtual void computeRectForRepaint(RenderBoxModelObject* repaintContainer, IntRect&, bool fixed = false);
virtual unsigned int length() const { return 1; }
bool isFloatingOrPositioned() const { return (isFloating() || isPositioned()); }
- virtual bool containsFloats() { return false; }
- virtual bool containsFloat(RenderObject*) { return false; }
- virtual bool hasOverhangingFloats() { return false; }
- virtual bool expandsToEncloseOverhangingFloats() const { return isFloating() && style()->height().isAuto(); }
-
- virtual void removePositionedObjects(RenderBlock*) { }
-
- virtual bool avoidsFloats() const;
- bool shrinkToAvoidFloats() const;
-
- // positioning of inline children (bidi)
- virtual void position(InlineBox*) { }
bool isTransparent() const { return style()->opacity() < 1.0f; }
float opacity() const { return style()->opacity(); }
bool hasReflection() const { return m_hasReflection; }
- IntRect reflectionBox() const;
- int reflectionOffset() const;
- // Given a rect in the object's coordinate space, returns the corresponding rect in the reflection.
- IntRect reflectedRect(const IntRect&) const;
// Applied as a "slop" to dirty rect checks during the outline painting phase's dirty-rect checks.
int maximalOutlineSize(PaintPhase) const;
+ void setHasMarkupTruncation(bool b = true) { m_hasMarkupTruncation = b; }
+ bool hasMarkupTruncation() const { return m_hasMarkupTruncation; }
+
enum SelectionState {
SelectionNone, // The object is not selected.
SelectionStart, // The object either contains the start of a selection run or is the start of a run
@@ -801,20 +631,21 @@ public:
// The current selection state for an object. For blocks, the state refers to the state of the leaf
// descendants (as described above in the SelectionState enum declaration).
- virtual SelectionState selectionState() const { return SelectionNone; }
+ SelectionState selectionState() const { return static_cast<SelectionState>(m_selectionState);; }
// Sets the selection state for an object.
- virtual void setSelectionState(SelectionState state) { if (parent()) parent()->setSelectionState(state); }
+ virtual void setSelectionState(SelectionState state) { m_selectionState = state; }
// A single rectangle that encompasses all of the selected objects within this object. Used to determine the tightest
// possible bounding box for the selection.
- virtual IntRect selectionRect(bool) { return IntRect(); }
+ IntRect selectionRect(bool clipToVisibleContent = true) { return selectionRectForRepaint(0, clipToVisibleContent); }
+ virtual IntRect selectionRectForRepaint(RenderBoxModelObject* /*repaintContainer*/, bool /*clipToVisibleContent*/ = true) { return IntRect(); }
// Whether or not an object can be part of the leaf elements of the selection.
virtual bool canBeSelectionLeaf() const { return false; }
// Whether or not a block has selected children.
- virtual bool hasSelectedChildren() const { return false; }
+ bool hasSelectedChildren() const { return m_selectionState != SelectionNone; }
// Obtains the selection colors that should be used when painting a selection.
Color selectionBackgroundColor() const;
@@ -823,30 +654,6 @@ public:
// Whether or not a given block needs to paint selection gaps.
virtual bool shouldPaintSelectionGaps() const { return false; }
- // This struct is used when the selection changes to cache the old and new state of the selection for each RenderObject.
- struct SelectionInfo {
- SelectionInfo()
- : m_object(0)
- , m_state(SelectionNone)
- {
- }
-
- SelectionInfo(RenderObject* o, bool clipToVisibleContent)
- : m_object(o)
- , m_rect(o->needsLayout() ? IntRect() : o->selectionRect(clipToVisibleContent))
- , m_state(o->selectionState())
- {
- }
-
- RenderObject* object() const { return m_object; }
- IntRect rect() const { return m_rect; }
- SelectionState state() const { return m_state; }
-
- RenderObject* m_object;
- IntRect m_rect;
- SelectionState m_state;
- };
-
Node* draggableNode(bool dhtmlOK, bool uaOK, int x, int y, bool& dhtmlWillDrag) const;
/**
@@ -857,12 +664,11 @@ public:
*/
virtual IntRect localCaretRect(InlineBox*, int caretOffset, int* extraWidthToEndOfLine = 0);
- virtual int lowestPosition(bool /*includeOverflowInterior*/ = true, bool /*includeSelf*/ = true) const { return 0; }
- virtual int rightmostPosition(bool /*includeOverflowInterior*/ = true, bool /*includeSelf*/ = true) const { return 0; }
- virtual int leftmostPosition(bool /*includeOverflowInterior*/ = true, bool /*includeSelf*/ = true) const { return 0; }
-
virtual void calcVerticalMargins() { }
- void removeFromObjectLists();
+ bool isTopMarginQuirk() const { return m_topMarginQuirk; }
+ bool isBottomMarginQuirk() const { return m_bottomMarginQuirk; }
+ void setTopMarginQuirk(bool b = true) { m_topMarginQuirk = b; }
+ void setBottomMarginQuirk(bool b = true) { m_bottomMarginQuirk = b; }
// When performing a global document tear-down, the renderer of the document is cleared. We use this
// as a hook to detect the case of document destruction and don't waste time doing unnecessary work.
@@ -875,21 +681,19 @@ public:
virtual bool isFlexingChildren() const { return false; }
virtual bool isStretchingChildren() const { return false; }
- // Convenience, to avoid repeating the code to dig down to get this.
- UChar backslashAsCurrencySymbol() const;
-
virtual int caretMinOffset() const;
virtual int caretMaxOffset() const;
virtual unsigned caretMaxRenderedOffset() const;
virtual int previousOffset(int current) const;
+ virtual int previousOffsetForBackwardDeletion(int current) const;
virtual int nextOffset(int current) const;
virtual void imageChanged(CachedImage*, const IntRect* = 0);
virtual void imageChanged(WrappedImagePtr, const IntRect* = 0) { }
virtual bool willRenderImage(CachedImage*);
- virtual void selectionStartEnd(int& spos, int& epos) const;
+ void selectionStartEnd(int& spos, int& epos) const;
RenderObject* paintingRootForChildren(PaintInfo& paintInfo) const
{
@@ -907,33 +711,79 @@ public:
void remove() { if (parent()) parent()->removeChild(this); }
- void invalidateVerticalPosition() { m_verticalPosition = PositionUndefined; }
-
- virtual void removeLeftoverAnonymousBlock(RenderBlock* child);
-
- virtual void capsLockStateMayHaveChanged() { }
-
AnimationController* animation() const;
bool visibleToHitTesting() const { return style()->visibility() == VISIBLE && style()->pointerEvents() != PE_NONE; }
+
+ // Map points and quads through elements, potentially via 3d transforms. You should never need to call these directly; use
+ // localToAbsolute/absoluteToLocal methods instead.
+ virtual void mapLocalToContainer(RenderBoxModelObject* repaintContainer, bool useTransforms, bool fixed, TransformState&) const;
+ virtual void mapAbsoluteToLocalPoint(bool fixed, bool useTransforms, TransformState&) const;
+
+ bool shouldUseTransformFromContainer(const RenderObject* container) const;
+ void getTransformFromContainer(const RenderObject* container, const IntSize& offsetInContainer, TransformationMatrix&) const;
+
+ virtual void addFocusRingRects(GraphicsContext*, int /*tx*/, int /*ty*/) { };
+
+ IntRect absoluteOutlineBounds() const
+ {
+ return outlineBoundsForRepaint(0);
+ }
+
+ bool replacedHasOverflow() const { return m_replacedHasOverflow; }
+ void setReplacedHasOverflow(bool b = true) { m_replacedHasOverflow = b; }
protected:
// Overrides should call the superclass at the end
- virtual void styleWillChange(RenderStyle::Diff, const RenderStyle* newStyle);
+ virtual void styleWillChange(StyleDifference, const RenderStyle* newStyle);
// Overrides should call the superclass at the start
- virtual void styleDidChange(RenderStyle::Diff, const RenderStyle* oldStyle);
-
- virtual void printBoxDecorations(GraphicsContext*, int /*x*/, int /*y*/, int /*w*/, int /*h*/, int /*tx*/, int /*ty*/) { }
+ virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
- virtual IntRect viewRect() const;
+ void paintOutline(GraphicsContext*, int tx, int ty, int w, int h, const RenderStyle*);
+ void addPDFURLRect(GraphicsContext*, const IntRect&);
- int getVerticalPosition(bool firstLine) const;
+ virtual IntRect viewRect() const;
void adjustRectForOutlineAndShadow(IntRect&) const;
void arenaDelete(RenderArena*, void* objectBase);
+ virtual IntRect outlineBoundsForRepaint(RenderBoxModelObject* /*repaintContainer*/) const { return IntRect(); }
+
+ class LayoutRepainter {
+ public:
+ LayoutRepainter(RenderObject& object, bool checkForRepaint, const IntRect* oldBounds = 0)
+ : m_object(object)
+ , m_repaintContainer(0)
+ , m_checkForRepaint(checkForRepaint)
+ {
+ if (m_checkForRepaint) {
+ m_repaintContainer = m_object.containerForRepaint();
+ m_oldBounds = oldBounds ? *oldBounds : m_object.clippedOverflowRectForRepaint(m_repaintContainer);
+ m_oldOutlineBox = m_object.outlineBoundsForRepaint(m_repaintContainer);
+ }
+ }
+
+ // Return true if it repainted.
+ bool repaintAfterLayout()
+ {
+ return m_checkForRepaint ? m_object.repaintAfterLayoutIfNeeded(m_repaintContainer, m_oldBounds, m_oldOutlineBox) : false;
+ }
+
+ bool checkForRepaint() const { return m_checkForRepaint; }
+
+ private:
+ RenderObject& m_object;
+ RenderBoxModelObject* m_repaintContainer;
+ IntRect m_oldBounds;
+ IntRect m_oldOutlineBox;
+ bool m_checkForRepaint;
+ };
+
private:
+ RenderStyle* firstLineStyleSlowCase() const;
+ StyleDifference adjustStyleDifference(StyleDifference, unsigned contextSensitiveProperties) const;
+
RefPtr<RenderStyle> m_style;
Node* m_node;
@@ -944,9 +794,10 @@ private:
#ifndef NDEBUG
bool m_hasAXObject;
+ bool m_setNeedsLayoutForbidden : 1;
#endif
- mutable int m_verticalPosition;
+ // 32 bits have been used here. THERE ARE NO FREE BITS AVAILABLE.
bool m_needsLayout : 1;
bool m_needsPositionedMovementLayout :1;
bool m_normalChildNeedsLayout : 1;
@@ -961,6 +812,7 @@ private:
bool m_isAnonymous : 1;
bool m_isText : 1;
+ bool m_isBox : 1;
bool m_inline : 1;
bool m_replaced : 1;
bool m_isDragging : 1;
@@ -977,10 +829,147 @@ public:
bool m_everHadLayout : 1;
private:
+ // These bitfields are moved here from subclasses to pack them together
+ // from RenderBlock
+ bool m_childrenInline : 1;
+ bool m_topMarginQuirk : 1;
+ bool m_bottomMarginQuirk : 1;
+ bool m_hasMarkupTruncation : 1;
+ unsigned m_selectionState : 3; // SelectionState
+ bool m_hasColumns : 1;
+
+ // from RenderTableCell
+ bool m_cellWidthChanged : 1;
+
+ // from RenderReplaced
+ bool m_replacedHasOverflow : 1;
+
+private:
// Store state between styleWillChange and styleDidChange
static bool s_affectsParentBlock;
};
+inline bool RenderObject::documentBeingDestroyed() const
+{
+ return !document()->renderer();
+}
+
+inline void RenderObject::setNeedsLayout(bool b, bool markParents)
+{
+ bool alreadyNeededLayout = m_needsLayout;
+ m_needsLayout = b;
+ if (b) {
+ ASSERT(!isSetNeedsLayoutForbidden());
+ if (!alreadyNeededLayout) {
+ if (markParents)
+ markContainingBlocksForLayout();
+ if (hasLayer())
+ setLayerNeedsFullRepaint();
+ }
+ } else {
+ m_everHadLayout = true;
+ m_posChildNeedsLayout = false;
+ m_normalChildNeedsLayout = false;
+ m_needsPositionedMovementLayout = false;
+ }
+}
+
+inline void RenderObject::setChildNeedsLayout(bool b, bool markParents)
+{
+ bool alreadyNeededLayout = m_normalChildNeedsLayout;
+ m_normalChildNeedsLayout = b;
+ if (b) {
+ ASSERT(!isSetNeedsLayoutForbidden());
+ if (!alreadyNeededLayout && markParents)
+ markContainingBlocksForLayout();
+ } else {
+ m_posChildNeedsLayout = false;
+ m_normalChildNeedsLayout = false;
+ m_needsPositionedMovementLayout = false;
+ }
+}
+
+inline void RenderObject::setNeedsPositionedMovementLayout()
+{
+ bool alreadyNeededLayout = needsLayout();
+ m_needsPositionedMovementLayout = true;
+ if (!alreadyNeededLayout) {
+ markContainingBlocksForLayout();
+ if (hasLayer())
+ setLayerNeedsFullRepaint();
+ }
+}
+
+inline bool objectIsRelayoutBoundary(const RenderObject *obj)
+{
+ // FIXME: In future it may be possible to broaden this condition in order to improve performance.
+ // Table cells are excluded because even when their CSS height is fixed, their height()
+ // may depend on their contents.
+ return obj->isTextControl()
+ || (obj->hasOverflowClip() && !obj->style()->width().isIntrinsicOrAuto() && !obj->style()->height().isIntrinsicOrAuto() && !obj->style()->height().isPercent() && !obj->isTableCell())
+#if ENABLE(SVG)
+ || obj->isSVGRoot()
+#endif
+ ;
+}
+
+inline void RenderObject::markContainingBlocksForLayout(bool scheduleRelayout, RenderObject* newRoot)
+{
+ ASSERT(!scheduleRelayout || !newRoot);
+
+ RenderObject* o = container();
+ RenderObject* last = this;
+
+ while (o) {
+ // Don't mark the outermost object of an unrooted subtree. That object will be
+ // marked when the subtree is added to the document.
+ RenderObject* container = o->container();
+ if (!container && !o->isRenderView())
+ return;
+ if (!last->isText() && (last->style()->position() == FixedPosition || last->style()->position() == AbsolutePosition)) {
+ if ((last->style()->top().isAuto() && last->style()->bottom().isAuto()) || last->style()->top().isStatic()) {
+ RenderObject* parent = last->parent();
+ if (!parent->normalChildNeedsLayout()) {
+ parent->setChildNeedsLayout(true, false);
+ if (parent != newRoot)
+ parent->markContainingBlocksForLayout(scheduleRelayout, newRoot);
+ }
+ }
+ if (o->m_posChildNeedsLayout)
+ return;
+ o->m_posChildNeedsLayout = true;
+ ASSERT(!o->isSetNeedsLayoutForbidden());
+ } else {
+ if (o->m_normalChildNeedsLayout)
+ return;
+ o->m_normalChildNeedsLayout = true;
+ ASSERT(!o->isSetNeedsLayoutForbidden());
+ }
+
+ if (o == newRoot)
+ return;
+
+ last = o;
+ if (scheduleRelayout && objectIsRelayoutBoundary(last))
+ break;
+ o = container;
+ }
+
+ if (scheduleRelayout)
+ last->scheduleRelayout();
+}
+
+inline void makeMatrixRenderable(TransformationMatrix& matrix, bool has3DRendering)
+{
+#if !ENABLE(3D_RENDERING)
+ UNUSED_PARAM(has3DRendering);
+ matrix.makeAffine();
+#else
+ if (!has3DRendering)
+ matrix.makeAffine();
+#endif
+}
+
} // namespace WebCore
#ifndef NDEBUG
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderObjectChildList.cpp b/src/3rdparty/webkit/WebCore/rendering/RenderObjectChildList.cpp
new file mode 100644
index 0000000..32e856f
--- /dev/null
+++ b/src/3rdparty/webkit/WebCore/rendering/RenderObjectChildList.cpp
@@ -0,0 +1,426 @@
+/*
+ * Copyright (C) 2009 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``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 COMPUTER, INC. OR
+ * 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"
+#include "RenderObjectChildList.h"
+
+#include "AXObjectCache.h"
+#include "RenderBlock.h"
+#include "RenderCounter.h"
+#include "RenderImageGeneratedContent.h"
+#include "RenderInline.h"
+#include "RenderLayer.h"
+#include "RenderListItem.h"
+#include "RenderStyle.h"
+#include "RenderTextFragment.h"
+#include "RenderView.h"
+
+namespace WebCore {
+
+static void updateListMarkerNumbers(RenderObject* child)
+{
+ for (RenderObject* r = child; r; r = r->nextSibling()) {
+ if (r->isListItem())
+ static_cast<RenderListItem*>(r)->updateValue();
+ }
+}
+
+
+void RenderObjectChildList::destroyLeftoverChildren()
+{
+ while (firstChild()) {
+ if (firstChild()->isListMarker() || (firstChild()->style()->styleType() == FIRST_LETTER && !firstChild()->isText()))
+ firstChild()->remove(); // List markers are owned by their enclosing list and so don't get destroyed by this container. Similarly, first letters are destroyed by their remaining text fragment.
+ else {
+ // Destroy any anonymous children remaining in the render tree, as well as implicit (shadow) DOM elements like those used in the engine-based text fields.
+ if (firstChild()->node())
+ firstChild()->node()->setRenderer(0);
+ firstChild()->destroy();
+ }
+ }
+}
+
+RenderObject* RenderObjectChildList::removeChildNode(RenderObject* owner, RenderObject* oldChild, bool fullRemove)
+{
+ ASSERT(oldChild->parent() == owner);
+
+ // So that we'll get the appropriate dirty bit set (either that a normal flow child got yanked or
+ // that a positioned child got yanked). We also repaint, so that the area exposed when the child
+ // disappears gets repainted properly.
+ if (!owner->documentBeingDestroyed() && fullRemove && oldChild->m_everHadLayout) {
+ oldChild->setNeedsLayoutAndPrefWidthsRecalc();
+ oldChild->repaint();
+ }
+
+ // If we have a line box wrapper, delete it.
+ if (oldChild->isBox())
+ toRenderBox(oldChild)->deleteLineBoxWrapper();
+
+ if (!owner->documentBeingDestroyed() && fullRemove) {
+ // if we remove visible child from an invisible parent, we don't know the layer visibility any more
+ RenderLayer* layer = 0;
+ if (owner->style()->visibility() != VISIBLE && oldChild->style()->visibility() == VISIBLE && !oldChild->hasLayer()) {
+ layer = owner->enclosingLayer();
+ layer->dirtyVisibleContentStatus();
+ }
+
+ // Keep our layer hierarchy updated.
+ if (oldChild->firstChild() || oldChild->hasLayer()) {
+ if (!layer)
+ layer = owner->enclosingLayer();
+ oldChild->removeLayers(layer);
+ }
+
+ // renumber ordered lists
+ if (oldChild->isListItem())
+ updateListMarkerNumbers(oldChild->nextSibling());
+
+ if (oldChild->isPositioned() && owner->childrenInline())
+ owner->dirtyLinesFromChangedChild(oldChild);
+ }
+
+ // If oldChild is the start or end of the selection, then clear the selection to
+ // avoid problems of invalid pointers.
+ // FIXME: The SelectionController should be responsible for this when it
+ // is notified of DOM mutations.
+ if (!owner->documentBeingDestroyed() && oldChild->isSelectionBorder())
+ owner->view()->clearSelection();
+
+ // remove the child
+ if (oldChild->previousSibling())
+ oldChild->previousSibling()->setNextSibling(oldChild->nextSibling());
+ if (oldChild->nextSibling())
+ oldChild->nextSibling()->setPreviousSibling(oldChild->previousSibling());
+
+ if (firstChild() == oldChild)
+ setFirstChild(oldChild->nextSibling());
+ if (lastChild() == oldChild)
+ setLastChild(oldChild->previousSibling());
+
+ oldChild->setPreviousSibling(0);
+ oldChild->setNextSibling(0);
+ oldChild->setParent(0);
+
+ if (AXObjectCache::accessibilityEnabled())
+ owner->document()->axObjectCache()->childrenChanged(owner);
+
+ return oldChild;
+}
+
+void RenderObjectChildList::appendChildNode(RenderObject* owner, RenderObject* newChild, bool fullAppend)
+{
+ ASSERT(newChild->parent() == 0);
+ ASSERT(!owner->isBlockFlow() || (!newChild->isTableSection() && !newChild->isTableRow() && !newChild->isTableCell()));
+
+ newChild->setParent(owner);
+ RenderObject* lChild = lastChild();
+
+ if (lChild) {
+ newChild->setPreviousSibling(lChild);
+ lChild->setNextSibling(newChild);
+ } else
+ setFirstChild(newChild);
+
+ setLastChild(newChild);
+
+ if (fullAppend) {
+ // Keep our layer hierarchy updated. Optimize for the common case where we don't have any children
+ // and don't have a layer attached to ourselves.
+ RenderLayer* layer = 0;
+ if (newChild->firstChild() || newChild->hasLayer()) {
+ layer = owner->enclosingLayer();
+ newChild->addLayers(layer, newChild);
+ }
+
+ // if the new child is visible but this object was not, tell the layer it has some visible content
+ // that needs to be drawn and layer visibility optimization can't be used
+ if (owner->style()->visibility() != VISIBLE && newChild->style()->visibility() == VISIBLE && !newChild->hasLayer()) {
+ if (!layer)
+ layer = owner->enclosingLayer();
+ if (layer)
+ layer->setHasVisibleContent(true);
+ }
+
+ if (!newChild->isFloatingOrPositioned() && owner->childrenInline())
+ owner->dirtyLinesFromChangedChild(newChild);
+ }
+
+ newChild->setNeedsLayoutAndPrefWidthsRecalc(); // Goes up the containing block hierarchy.
+ if (!owner->normalChildNeedsLayout())
+ owner->setChildNeedsLayout(true); // We may supply the static position for an absolute positioned child.
+
+ if (AXObjectCache::accessibilityEnabled())
+ owner->document()->axObjectCache()->childrenChanged(owner);
+}
+
+void RenderObjectChildList::insertChildNode(RenderObject* owner, RenderObject* child, RenderObject* beforeChild, bool fullInsert)
+{
+ if (!beforeChild) {
+ appendChildNode(owner, child);
+ return;
+ }
+
+ ASSERT(!child->parent());
+ while (beforeChild->parent() != owner && beforeChild->parent()->isAnonymousBlock())
+ beforeChild = beforeChild->parent();
+ ASSERT(beforeChild->parent() == owner);
+
+ ASSERT(!owner->isBlockFlow() || (!child->isTableSection() && !child->isTableRow() && !child->isTableCell()));
+
+ if (beforeChild == firstChild())
+ setFirstChild(child);
+
+ RenderObject* prev = beforeChild->previousSibling();
+ child->setNextSibling(beforeChild);
+ beforeChild->setPreviousSibling(child);
+ if (prev)
+ prev->setNextSibling(child);
+ child->setPreviousSibling(prev);
+
+ child->setParent(owner);
+
+ if (fullInsert) {
+ // Keep our layer hierarchy updated. Optimize for the common case where we don't have any children
+ // and don't have a layer attached to ourselves.
+ RenderLayer* layer = 0;
+ if (child->firstChild() || child->hasLayer()) {
+ layer = owner->enclosingLayer();
+ child->addLayers(layer, child);
+ }
+
+ // if the new child is visible but this object was not, tell the layer it has some visible content
+ // that needs to be drawn and layer visibility optimization can't be used
+ if (owner->style()->visibility() != VISIBLE && child->style()->visibility() == VISIBLE && !child->hasLayer()) {
+ if (!layer)
+ layer = owner->enclosingLayer();
+ if (layer)
+ layer->setHasVisibleContent(true);
+ }
+
+
+ if (!child->isFloating() && owner->childrenInline())
+ owner->dirtyLinesFromChangedChild(child);
+ }
+
+ child->setNeedsLayoutAndPrefWidthsRecalc();
+ if (!owner->normalChildNeedsLayout())
+ owner->setChildNeedsLayout(true); // We may supply the static position for an absolute positioned child.
+
+ if (AXObjectCache::accessibilityEnabled())
+ owner->document()->axObjectCache()->childrenChanged(owner);
+}
+
+static RenderObject* beforeAfterContainer(RenderObject* container, PseudoId type)
+{
+ if (type == BEFORE) {
+ RenderObject* first = container;
+ do {
+ // Skip list markers.
+ first = first->firstChild();
+ while (first && first->isListMarker())
+ first = first->nextSibling();
+ } while (first && first->isAnonymous() && first->style()->styleType() == NOPSEUDO);
+ if (first && first->style()->styleType() != type)
+ return 0;
+ return first;
+ }
+ if (type == AFTER) {
+ RenderObject* last = container;
+ do {
+ last = last->lastChild();
+ } while (last && last->isAnonymous() && last->style()->styleType() == NOPSEUDO && !last->isListMarker());
+ if (last && last->style()->styleType() != type)
+ return 0;
+ return last;
+ }
+
+ ASSERT_NOT_REACHED();
+ return 0;
+}
+
+static RenderObject* findBeforeAfterParent(RenderObject* object)
+{
+ // Only table parts need to search for the :before or :after parent
+ if (!(object->isTable() || object->isTableSection() || object->isTableRow()))
+ return object;
+
+ RenderObject* beforeAfterParent = object;
+ while (beforeAfterParent && !(beforeAfterParent->isText() || beforeAfterParent->isImage()))
+ beforeAfterParent = beforeAfterParent->firstChild();
+ return beforeAfterParent;
+}
+
+static void invalidateCountersInContainer(RenderObject* container)
+{
+ if (!container)
+ return;
+ container = findBeforeAfterParent(container);
+ if (!container)
+ return;
+ for (RenderObject* content = container->firstChild(); content; content = content->nextSibling()) {
+ if (content->isCounter())
+ static_cast<RenderCounter*>(content)->invalidate();
+ }
+}
+
+void RenderObjectChildList::invalidateCounters(RenderObject* owner)
+{
+ ASSERT(!owner->documentBeingDestroyed());
+ invalidateCountersInContainer(beforeAfterContainer(owner, BEFORE));
+ invalidateCountersInContainer(beforeAfterContainer(owner, AFTER));
+}
+
+void RenderObjectChildList::updateBeforeAfterContent(RenderObject* owner, PseudoId type, RenderObject* styledObject)
+{
+ // Double check that the document did in fact use generated content rules. Otherwise we should not have been called.
+ ASSERT(owner->document()->usesBeforeAfterRules());
+
+ // In CSS2, before/after pseudo-content cannot nest. Check this first.
+ if (owner->style()->styleType() == BEFORE || owner->style()->styleType() == AFTER)
+ return;
+
+ if (!styledObject)
+ styledObject = owner;
+
+ RenderStyle* pseudoElementStyle = styledObject->getCachedPseudoStyle(type);
+ RenderObject* child = beforeAfterContainer(owner, type);
+
+ // Whether or not we currently have generated content attached.
+ bool oldContentPresent = child;
+
+ // Whether or not we now want generated content.
+ bool newContentWanted = pseudoElementStyle && pseudoElementStyle->display() != NONE;
+
+ // For <q><p/></q>, if this object is the inline continuation of the <q>, we only want to generate
+ // :after content and not :before content.
+ if (newContentWanted && type == BEFORE && owner->isRenderInline() && toRenderInline(owner)->isInlineContinuation())
+ newContentWanted = false;
+
+ // Similarly, if we're the beginning of a <q>, and there's an inline continuation for our object,
+ // then we don't generate the :after content.
+ if (newContentWanted && type == AFTER && owner->isRenderInline() && toRenderInline(owner)->continuation())
+ newContentWanted = false;
+
+ // If we don't want generated content any longer, or if we have generated content, but it's no longer
+ // identical to the new content data we want to build render objects for, then we nuke all
+ // of the old generated content.
+ if (!newContentWanted || (oldContentPresent && Node::diff(child->style(), pseudoElementStyle) == Node::Detach)) {
+ // Nuke the child.
+ if (child && child->style()->styleType() == type) {
+ oldContentPresent = false;
+ child->destroy();
+ child = (type == BEFORE) ? owner->virtualChildren()->firstChild() : owner->virtualChildren()->lastChild();
+ }
+ }
+
+ // If we have no pseudo-element style or if the pseudo-element style's display type is NONE, then we
+ // have no generated content and can now return.
+ if (!newContentWanted)
+ return;
+
+ if (owner->isRenderInline() && !pseudoElementStyle->isDisplayInlineType() && pseudoElementStyle->floating() == FNONE &&
+ !(pseudoElementStyle->position() == AbsolutePosition || pseudoElementStyle->position() == FixedPosition))
+ // According to the CSS2 spec (the end of section 12.1), the only allowed
+ // display values for the pseudo style are NONE and INLINE for inline flows.
+ // FIXME: CSS2.1 lifted this restriction, but block display types will crash.
+ // For now we at least relax the restriction to allow all inline types like inline-block
+ // and inline-table.
+ pseudoElementStyle->setDisplay(INLINE);
+
+ if (oldContentPresent) {
+ if (child && child->style()->styleType() == type) {
+ // We have generated content present still. We want to walk this content and update our
+ // style information with the new pseudo-element style.
+ child->setStyle(pseudoElementStyle);
+
+ RenderObject* beforeAfterParent = findBeforeAfterParent(child);
+ if (!beforeAfterParent)
+ return;
+
+ // Note that if we ever support additional types of generated content (which should be way off
+ // in the future), this code will need to be patched.
+ for (RenderObject* genChild = beforeAfterParent->firstChild(); genChild; genChild = genChild->nextSibling()) {
+ if (genChild->isText())
+ // Generated text content is a child whose style also needs to be set to the pseudo-element style.
+ genChild->setStyle(pseudoElementStyle);
+ else if (genChild->isImage()) {
+ // Images get an empty style that inherits from the pseudo.
+ RefPtr<RenderStyle> style = RenderStyle::create();
+ style->inheritFrom(pseudoElementStyle);
+ genChild->setStyle(style.release());
+ } else
+ // Must be a first-letter container. updateFirstLetter() will take care of it.
+ ASSERT(genChild->style()->styleType() == FIRST_LETTER);
+ }
+ }
+ return; // We've updated the generated content. That's all we needed to do.
+ }
+
+ RenderObject* insertBefore = (type == BEFORE) ? owner->virtualChildren()->firstChild() : 0;
+
+ // Generated content consists of a single container that houses multiple children (specified
+ // by the content property). This generated content container gets the pseudo-element style set on it.
+ RenderObject* generatedContentContainer = 0;
+
+ // Walk our list of generated content and create render objects for each.
+ for (const ContentData* content = pseudoElementStyle->contentData(); content; content = content->next()) {
+ RenderObject* renderer = 0;
+ switch (content->type()) {
+ case CONTENT_NONE:
+ break;
+ case CONTENT_TEXT:
+ renderer = new (owner->renderArena()) RenderTextFragment(owner->document() /* anonymous object */, content->text());
+ renderer->setStyle(pseudoElementStyle);
+ break;
+ case CONTENT_OBJECT: {
+ RenderImageGeneratedContent* image = new (owner->renderArena()) RenderImageGeneratedContent(owner->document()); // anonymous object
+ RefPtr<RenderStyle> style = RenderStyle::create();
+ style->inheritFrom(pseudoElementStyle);
+ image->setStyle(style.release());
+ if (StyleImage* styleImage = content->image())
+ image->setStyleImage(styleImage);
+ renderer = image;
+ break;
+ }
+ case CONTENT_COUNTER:
+ renderer = new (owner->renderArena()) RenderCounter(owner->document(), *content->counter());
+ renderer->setStyle(pseudoElementStyle);
+ break;
+ }
+
+ if (renderer) {
+ if (!generatedContentContainer) {
+ // Make a generated box that might be any display type now that we are able to drill down into children
+ // to find the original content properly.
+ generatedContentContainer = RenderObject::createObject(owner->document(), pseudoElementStyle);
+ generatedContentContainer->setStyle(pseudoElementStyle);
+ owner->addChild(generatedContentContainer, insertBefore);
+ }
+ generatedContentContainer->addChild(renderer);
+ }
+ }
+}
+
+} // namespace WebCore
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderObjectChildList.h b/src/3rdparty/webkit/WebCore/rendering/RenderObjectChildList.h
new file mode 100644
index 0000000..bf8800a
--- /dev/null
+++ b/src/3rdparty/webkit/WebCore/rendering/RenderObjectChildList.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2009 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``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 COMPUTER, INC. OR
+ * 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 RenderObjectChildList_h
+#define RenderObjectChildList_h
+
+#include "RenderStyleConstants.h"
+
+namespace WebCore {
+
+class RenderObject;
+
+class RenderObjectChildList {
+public:
+ RenderObjectChildList()
+ : m_firstChild(0)
+ , m_lastChild(0)
+ {
+ }
+
+ RenderObject* firstChild() const { return m_firstChild; }
+ RenderObject* lastChild() const { return m_lastChild; }
+
+ // FIXME: Temporary while RenderBox still exists. Eventually this will just happen during insert/append/remove methods on the child list, and nobody
+ // will need to manipulate firstChild or lastChild directly.
+ void setFirstChild(RenderObject* child) { m_firstChild = child; }
+ void setLastChild(RenderObject* child) { m_lastChild = child; }
+
+ void destroyLeftoverChildren();
+
+ RenderObject* removeChildNode(RenderObject* owner, RenderObject*, bool fullRemove = true);
+ void appendChildNode(RenderObject* owner, RenderObject*, bool fullAppend = true);
+ void insertChildNode(RenderObject* owner, RenderObject* child, RenderObject* before, bool fullInsert = true);
+
+ void updateBeforeAfterContent(RenderObject* owner, PseudoId type, RenderObject* styledObject = 0);
+ void invalidateCounters(RenderObject* owner);
+
+private:
+ RenderObject* m_firstChild;
+ RenderObject* m_lastChild;
+};
+
+} // namespace WebCore
+
+#endif // RenderObjectChildList_h
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderPart.cpp b/src/3rdparty/webkit/WebCore/rendering/RenderPart.cpp
index d840418..bcf9ef9 100644
--- a/src/3rdparty/webkit/WebCore/rendering/RenderPart.cpp
+++ b/src/3rdparty/webkit/WebCore/rendering/RenderPart.cpp
@@ -1,10 +1,8 @@
-/**
- * This file is part of the KDE project.
- *
+/*
* Copyright (C) 1999 Lars Knoll (knoll@kde.org)
* (C) 2000 Simon Hausmann <hausmann@kde.org>
* (C) 2000 Stefan Schimanski (1Stein@gmx.de)
- * Copyright (C) 2004, 2005, 2006 Apple Computer, Inc.
+ * Copyright (C) 2004, 2005, 2006, 2009 Apple Inc. 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
@@ -22,22 +20,16 @@
* Boston, MA 02110-1301, USA.
*
*/
+
#include "config.h"
#include "RenderPart.h"
-#include "Document.h"
#include "Frame.h"
-#include "FrameTree.h"
#include "FrameView.h"
-#include "HTMLFrameOwnerElement.h"
-#include "HTMLNames.h"
-#include "Page.h"
namespace WebCore {
-using namespace HTMLNames;
-
-RenderPart::RenderPart(HTMLFrameOwnerElement* node)
+RenderPart::RenderPart(Element* node)
: RenderWidget(node)
{
// init RenderObject attributes
@@ -46,71 +38,37 @@ RenderPart::RenderPart(HTMLFrameOwnerElement* node)
RenderPart::~RenderPart()
{
- // Since deref ends up calling setWidget back on us, need to make sure
- // that widget is already 0 so it won't do any work.
- Widget* widget = m_widget;
- m_widget = 0;
- if (widget && widget->isFrameView())
- static_cast<FrameView*>(widget)->deref();
- else
- delete widget;
+ clearWidget();
}
void RenderPart::setWidget(Widget* widget)
{
- if (widget != m_widget) {
- if (widget && widget->isFrameView())
- static_cast<FrameView*>(widget)->ref();
- RenderWidget::setWidget(widget);
+ if (widget == this->widget())
+ return;
- // make sure the scrollbars are set correctly for restore
- // ### find better fix
- viewCleared();
- }
-}
+ if (widget && widget->isFrameView())
+ static_cast<FrameView*>(widget)->ref();
+ RenderWidget::setWidget(widget);
-void RenderPart::viewCleared()
-{
+ // make sure the scrollbars are set correctly for restore
+ // ### find better fix
+ viewCleared();
}
-void RenderPart::deleteWidget()
+void RenderPart::viewCleared()
{
- if (m_widget && m_widget->isFrameView())
- static_cast<FrameView*>(m_widget)->deref();
- else
- delete m_widget;
}
-// FIXME: This should not be necessary. Remove this once WebKit knows to properly schedule
-// layouts using WebCore when objects resize.
-void RenderPart::updateWidgetPosition()
+void RenderPart::deleteWidget(Widget* widget)
{
- if (!m_widget)
- return;
-
- int width, height;
- FloatPoint absPos = localToAbsolute();
- absPos.move(borderLeft() + paddingLeft(), borderTop() + paddingTop());
- width = m_width - borderLeft() - borderRight() - paddingLeft() - paddingRight();
- height = m_height - borderTop() - borderBottom() - paddingTop() - paddingBottom();
- IntRect newBounds(absPos.x(), absPos.y(), width, height);
- bool boundsChanged = newBounds != m_widget->frameRect();
- if (boundsChanged) {
- // The widget changed positions. Update the frame geometry.
- RenderArena *arena = ref();
- element()->ref();
- m_widget->setFrameRect(newBounds);
- element()->deref();
- deref(arena);
- }
+ // Since deref ends up calling setWidget back on us, need to make sure
+ // that widget is already 0 so it won't do any work.
+ ASSERT(!this->widget());
- // if the frame bounds got changed, or if view needs layout (possibly indicating
- // content size is wrong) we have to do a layout to set the right widget size
- if (m_widget && m_widget->isFrameView()) {
- FrameView* frameView = static_cast<FrameView*>(m_widget);
- if (boundsChanged || frameView->needsLayout())
- frameView->layout();
- }
+ if (widget && widget->isFrameView())
+ static_cast<FrameView*>(widget)->deref();
+ else
+ delete widget;
}
}
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderPart.h b/src/3rdparty/webkit/WebCore/rendering/RenderPart.h
index e339468..e47ead0 100644
--- a/src/3rdparty/webkit/WebCore/rendering/RenderPart.h
+++ b/src/3rdparty/webkit/WebCore/rendering/RenderPart.h
@@ -1,9 +1,7 @@
/*
- * This file is part of the KDE project.
- *
* Copyright (C) 1999 Lars Knoll (knoll@kde.org)
* (C) 2000 Simon Hausmann <hausmann@kde.org>
- * Copyright (C) 2006 Apple Computer, Inc.
+ * Copyright (C) 2006, 2009 Apple Inc. 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
@@ -29,32 +27,24 @@
namespace WebCore {
-class Frame;
-class HTMLFrameOwnerElement;
-
class RenderPart : public RenderWidget {
public:
- RenderPart(HTMLFrameOwnerElement*);
+ RenderPart(Element*);
virtual ~RenderPart();
- virtual bool isRenderPart() const { return true; }
- virtual const char* renderName() const { return "RenderPart"; }
-
- virtual void setWidget(Widget*);
-
- // FIXME: This should not be necessary.
- // Remove this once WebKit knows to properly schedule layouts using WebCore when objects resize.
- virtual void updateWidgetPosition();
-
bool hasFallbackContent() const { return m_hasFallbackContent; }
+ virtual void setWidget(Widget*);
virtual void viewCleared();
protected:
bool m_hasFallbackContent;
private:
- virtual void deleteWidget();
+ virtual bool isRenderPart() const { return true; }
+ virtual const char* renderName() const { return "RenderPart"; }
+
+ virtual void deleteWidget(Widget*);
};
}
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderPartObject.cpp b/src/3rdparty/webkit/WebCore/rendering/RenderPartObject.cpp
index e5200e2..7a3aa64 100644
--- a/src/3rdparty/webkit/WebCore/rendering/RenderPartObject.cpp
+++ b/src/3rdparty/webkit/WebCore/rendering/RenderPartObject.cpp
@@ -2,7 +2,7 @@
* Copyright (C) 1999 Lars Knoll (knoll@kde.org)
* (C) 2000 Simon Hausmann <hausmann@kde.org>
* (C) 2000 Stefan Schimanski (1Stein@gmx.de)
- * Copyright (C) 2004, 2005, 2006, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2004, 2005, 2006, 2008, 2009 Apple Inc. 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
@@ -25,10 +25,7 @@
#include "RenderPartObject.h"
#include "Frame.h"
-#include "FrameLoader.h"
#include "FrameLoaderClient.h"
-#include "FrameTree.h"
-#include "FrameView.h"
#include "HTMLEmbedElement.h"
#include "HTMLIFrameElement.h"
#include "HTMLNames.h"
@@ -40,11 +37,15 @@
#include "RenderView.h"
#include "Text.h"
+#if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
+#include "HTMLVideoElement.h"
+#endif
+
namespace WebCore {
using namespace HTMLNames;
-RenderPartObject::RenderPartObject(HTMLFrameOwnerElement* element)
+RenderPartObject::RenderPartObject(Element* element)
: RenderPart(element)
{
// init RenderObject attributes
@@ -57,8 +58,8 @@ RenderPartObject::RenderPartObject(HTMLFrameOwnerElement* element)
RenderPartObject::~RenderPartObject()
{
- if (m_view)
- m_view->removeWidgetToUpdate(this);
+ if (frameView())
+ frameView()->removeWidgetToUpdate(this);
}
static bool isURLAllowed(Document* doc, const String& url)
@@ -80,46 +81,83 @@ static bool isURLAllowed(Document* doc, const String& url)
return true;
}
-static inline void mapClassIdToServiceType(const String& classId, String& serviceType, const PluginData* pluginData)
+typedef HashMap<String, String, CaseFoldingHash> ClassIdToTypeMap;
+
+static ClassIdToTypeMap* createClassIdToTypeMap()
+{
+ ClassIdToTypeMap* map = new ClassIdToTypeMap;
+ map->add("clsid:D27CDB6E-AE6D-11CF-96B8-444553540000", "application/x-shockwave-flash");
+ map->add("clsid:CFCDAA03-8BE4-11CF-B84B-0020AFBBCCFA", "audio/x-pn-realaudio-plugin");
+ map->add("clsid:02BF25D5-8C17-4B23-BC80-D3488ABDDC6B", "video/quicktime");
+ map->add("clsid:166B1BCA-3F9C-11CF-8075-444553540000", "application/x-director");
+#if ENABLE(ACTIVEX_TYPE_CONVERSION_WMPLAYER)
+ map->add("clsid:6BF52A52-394A-11D3-B153-00C04F79FAA6", "application/x-mplayer2");
+ map->add("clsid:22D6F312-B0F6-11D0-94AB-0080C74C7E95", "application/x-mplayer2");
+#endif
+ return map;
+}
+
+static const String& activeXType()
+{
+ DEFINE_STATIC_LOCAL(String, activeXType, ("application/x-oleobject"));
+ return activeXType;
+}
+
+static inline bool havePlugin(const PluginData* pluginData, const String& type)
+{
+ return pluginData && !type.isEmpty() && pluginData->supportsMimeType(type);
+}
+
+static String serviceTypeForClassId(const String& classId, const PluginData* pluginData)
{
// Return early if classId is empty (since we won't do anything below).
// Furthermore, if classId is null, calling get() below will crash.
if (classId.isEmpty())
- return;
-
- typedef HashMap<String, String, CaseFoldingHash> ServiceTypeHashMap;
- static ServiceTypeHashMap* serviceTypeFallbackForClassId = 0;
- if (!serviceTypeFallbackForClassId) {
- serviceTypeFallbackForClassId = new ServiceTypeHashMap;
- serviceTypeFallbackForClassId->add("clsid:D27CDB6E-AE6D-11CF-96B8-444553540000", "application/x-shockwave-flash");
- serviceTypeFallbackForClassId->add("clsid:CFCDAA03-8BE4-11CF-B84B-0020AFBBCCFA", "audio/x-pn-realaudio-plugin");
- serviceTypeFallbackForClassId->add("clsid:02BF25D5-8C17-4B23-BC80-D3488ABDDC6B", "video/quicktime");
- serviceTypeFallbackForClassId->add("clsid:166B1BCA-3F9C-11CF-8075-444553540000", "application/x-director");
-#if ENABLE(ACTIVEX_TYPE_CONVERSION_WMPLAYER)
- serviceTypeFallbackForClassId->add("clsid:6BF52A52-394A-11D3-B153-00C04F79FAA6", "application/x-mplayer2");
- serviceTypeFallbackForClassId->add("clsid:22D6F312-B0F6-11D0-94AB-0080C74C7E95", "application/x-mplayer2");
-#endif
- }
+ return String();
+
+ static ClassIdToTypeMap* map = createClassIdToTypeMap();
+ String type = map->get(classId);
- const String fallbackServiceType = serviceTypeFallbackForClassId->get(classId);
- if (pluginData->supportsMimeType(fallbackServiceType))
- serviceType = fallbackServiceType;
- else if (pluginData->supportsMimeType("application/x-oleobject"))
- serviceType = "application/x-oleobject";
+ // If we do have a plug-in that supports generic ActiveX content and don't have a plug-in
+ // for the MIME type we came up with, ignore the MIME type we came up with and just use
+ // the ActiveX type.
+ if (havePlugin(pluginData, activeXType()) && !havePlugin(pluginData, type))
+ return activeXType();
+
+ return type;
}
-static bool shouldUseChildEmbedOfObject(HTMLObjectElement* o, const PluginData* pluginData)
+static inline bool shouldUseEmbedDescendant(HTMLObjectElement* objectElement, const PluginData* pluginData)
{
- // An OBJECT tag with a classId is some kind of ActiveX control. The most
- // common controls have parallel plugin versions and thus possibly nested
- // EMBED tags. If this is the case, the OBJECT's classId should map to some
- // known plugin MIME type. If it doesn't, either the control is unlikely to
- // have a parallel plugin implementation (so there's no point looking
- // inside), or we've purposefully disabled conversion for this classId, in
- // which case we want to use the ActiveX OBJECT instead of the EMBED anyway.
- String serviceType;
- mapClassIdToServiceType(o->classId(), serviceType, pluginData);
- return serviceType != "application/x-oleobject";
+#if PLATFORM(MAC)
+ UNUSED_PARAM(objectElement);
+ UNUSED_PARAM(pluginData);
+ // On Mac, we always want to use the embed descendant.
+ return true;
+#else
+ // If we have both an <object> and <embed>, we always want to use the <embed> except when we have
+ // an ActiveX plug-in and plan to use it.
+ return !(havePlugin(pluginData, activeXType())
+ && serviceTypeForClassId(objectElement->classId(), pluginData) == activeXType());
+#endif
+}
+
+static void mapDataParamToSrc(Vector<String>* paramNames, Vector<String>* paramValues)
+{
+ // Some plugins don't understand the "data" attribute of the OBJECT tag (i.e. Real and WMP
+ // require "src" attribute).
+ int srcIndex = -1, dataIndex = -1;
+ for (unsigned int i = 0; i < paramNames->size(); ++i) {
+ if (equalIgnoringCase((*paramNames)[i], "src"))
+ srcIndex = i;
+ else if (equalIgnoringCase((*paramNames)[i], "data"))
+ dataIndex = i;
+ }
+
+ if (srcIndex == -1 && dataIndex != -1) {
+ paramNames->append("src");
+ paramValues->append((*paramValues)[dataIndex]);
+ }
}
void RenderPartObject::updateWidget(bool onlyCreateNonNetscapePlugins)
@@ -128,10 +166,10 @@ void RenderPartObject::updateWidget(bool onlyCreateNonNetscapePlugins)
String serviceType;
Vector<String> paramNames;
Vector<String> paramValues;
- Frame* frame = m_view->frame();
+ Frame* frame = frameView()->frame();
- if (element()->hasTagName(objectTag)) {
- HTMLObjectElement* o = static_cast<HTMLObjectElement*>(element());
+ if (node()->hasTagName(objectTag)) {
+ HTMLObjectElement* o = static_cast<HTMLObjectElement*>(node());
o->setNeedWidgetUpdate(false);
if (!o->isFinishedParsingChildren())
@@ -140,8 +178,8 @@ void RenderPartObject::updateWidget(bool onlyCreateNonNetscapePlugins)
// Check for a child EMBED tag.
HTMLEmbedElement* embed = 0;
const PluginData* pluginData = frame->page()->pluginData();
- if (pluginData && shouldUseChildEmbedOfObject(o, pluginData)) {
- for (Node* child = o->firstChild(); child;) {
+ if (shouldUseEmbedDescendant(o, pluginData)) {
+ for (Node* child = o->firstChild(); child; ) {
if (child->hasTagName(embedTag)) {
embed = static_cast<HTMLEmbedElement*>(child);
break;
@@ -206,7 +244,7 @@ void RenderPartObject::updateWidget(bool onlyCreateNonNetscapePlugins)
}
// Turn the attributes of either the EMBED tag or OBJECT tag into arrays, but don't override PARAM values.
- NamedAttrMap* attributes = embedOrObject->attributes();
+ NamedNodeMap* attributes = embedOrObject->attributes();
if (attributes) {
for (unsigned i = 0; i < attributes->length(); ++i) {
Attribute* it = attributes->attributeItem(i);
@@ -218,9 +256,11 @@ void RenderPartObject::updateWidget(bool onlyCreateNonNetscapePlugins)
}
}
+ mapDataParamToSrc(&paramNames, &paramValues);
+
// If we still don't have a type, try to map from a specific CLASSID to a type.
- if (pluginData && serviceType.isEmpty())
- mapClassIdToServiceType(o->classId(), serviceType, pluginData);
+ if (serviceType.isEmpty())
+ serviceType = serviceTypeForClassId(o->classId(), pluginData);
if (!isURLAllowed(document(), url))
return;
@@ -245,8 +285,8 @@ void RenderPartObject::updateWidget(bool onlyCreateNonNetscapePlugins)
bool success = frame->loader()->requestObject(this, url, AtomicString(o->name()), serviceType, paramNames, paramValues);
if (!success && m_hasFallbackContent)
o->renderFallbackContent();
- } else if (element()->hasTagName(embedTag)) {
- HTMLEmbedElement *o = static_cast<HTMLEmbedElement*>(element());
+ } else if (node()->hasTagName(embedTag)) {
+ HTMLEmbedElement *o = static_cast<HTMLEmbedElement*>(node());
o->setNeedWidgetUpdate(false);
url = o->url();
serviceType = o->serviceType();
@@ -257,7 +297,7 @@ void RenderPartObject::updateWidget(bool onlyCreateNonNetscapePlugins)
return;
// add all attributes set on the embed object
- NamedAttrMap* a = o->attributes();
+ NamedNodeMap* a = o->attributes();
if (a) {
for (unsigned i = 0; i < a->length(); ++i) {
Attribute* it = a->attributeItem(i);
@@ -278,6 +318,30 @@ void RenderPartObject::updateWidget(bool onlyCreateNonNetscapePlugins)
frame->loader()->requestObject(this, url, o->getAttribute(nameAttr), serviceType, paramNames, paramValues);
}
+#if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
+ else if (node()->hasTagName(videoTag) || node()->hasTagName(audioTag)) {
+ HTMLMediaElement* o = static_cast<HTMLMediaElement*>(node());
+
+ o->setNeedWidgetUpdate(false);
+ if (node()->hasTagName(videoTag)) {
+ HTMLVideoElement* vid = static_cast<HTMLVideoElement*>(node());
+ String poster = vid->poster();
+ if (!poster.isEmpty()) {
+ paramNames.append("_media_element_poster_");
+ paramValues.append(poster);
+ }
+ }
+
+ url = o->initialURL();
+ if (!url.isEmpty()) {
+ paramNames.append("_media_element_src_");
+ paramValues.append(url);
+ }
+
+ serviceType = "application/x-media-element-proxy-plugin";
+ frame->loader()->requestObject(this, url, nullAtom, serviceType, paramNames, paramValues);
+ }
+#endif
}
void RenderPartObject::layout()
@@ -286,24 +350,24 @@ void RenderPartObject::layout()
calcWidth();
calcHeight();
- adjustOverflowForBoxShadow();
+ adjustOverflowForBoxShadowAndReflect();
RenderPart::layout();
- if (!m_widget && m_view)
- m_view->addWidgetToUpdate(this);
+ if (!widget() && frameView())
+ frameView()->addWidgetToUpdate(this);
setNeedsLayout(false);
}
void RenderPartObject::viewCleared()
{
- if (element() && m_widget && m_widget->isFrameView()) {
- FrameView* view = static_cast<FrameView*>(m_widget);
+ if (node() && widget() && widget()->isFrameView()) {
+ FrameView* view = static_cast<FrameView*>(widget());
int marginw = -1;
int marginh = -1;
- if (element()->hasTagName(iframeTag)) {
- HTMLIFrameElement* frame = static_cast<HTMLIFrameElement*>(element());
+ if (node()->hasTagName(iframeTag)) {
+ HTMLIFrameElement* frame = static_cast<HTMLIFrameElement*>(node());
marginw = frame->getMarginWidth();
marginh = frame->getMarginHeight();
}
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderPartObject.h b/src/3rdparty/webkit/WebCore/rendering/RenderPartObject.h
index 98de5b9..2159d3c 100644
--- a/src/3rdparty/webkit/WebCore/rendering/RenderPartObject.h
+++ b/src/3rdparty/webkit/WebCore/rendering/RenderPartObject.h
@@ -1,9 +1,7 @@
/*
- * This file is part of the KDE project.
- *
* Copyright (C) 1999 Lars Knoll (knoll@kde.org)
* (C) 2000 Simon Hausmann <hausmann@kde.org>
- * Copyright (C) 2006 Apple Computer, Inc.
+ * Copyright (C) 2006, 2009 Apple Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -31,13 +29,15 @@ namespace WebCore {
class RenderPartObject : public RenderPart {
public:
- RenderPartObject(HTMLFrameOwnerElement*);
+ RenderPartObject(Element*);
virtual ~RenderPartObject();
+ void updateWidget(bool onlyCreateNonNetscapePlugins);
+
+private:
virtual const char* renderName() const { return "RenderPartObject"; }
virtual void layout();
- void updateWidget(bool onlyCreateNonNetscapePlugins);
virtual void viewCleared();
};
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderPath.cpp b/src/3rdparty/webkit/WebCore/rendering/RenderPath.cpp
index e595745..4a7662f 100644
--- a/src/3rdparty/webkit/WebCore/rendering/RenderPath.cpp
+++ b/src/3rdparty/webkit/WebCore/rendering/RenderPath.cpp
@@ -2,8 +2,7 @@
Copyright (C) 2004, 2005, 2007 Nikolas Zimmermann <zimmermann@kde.org>
2004, 2005, 2008 Rob Buis <buis@kde.org>
2005, 2007 Eric Seidel <eric@webkit.org>
-
- This file is part of the KDE project
+ 2009 Google, Inc.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
@@ -26,9 +25,8 @@
#if ENABLE(SVG)
#include "RenderPath.h"
-#include <math.h>
-
#include "FloatPoint.h"
+#include "FloatQuad.h"
#include "GraphicsContext.h"
#include "PointerEventsHitRules.h"
#include "RenderSVGContainer.h"
@@ -41,7 +39,6 @@
#include "SVGStyledTransformableElement.h"
#include "SVGTransformList.h"
#include "SVGURIReference.h"
-
#include <wtf/MathExtras.h>
namespace WebCore {
@@ -66,16 +63,14 @@ private:
RenderStyle* m_style;
};
-// RenderPath
-RenderPath::RenderPath(RenderStyle* style, SVGStyledTransformableElement* node)
- : RenderObject(node)
+RenderPath::RenderPath(SVGStyledTransformableElement* node)
+ : RenderSVGModelObject(node)
{
- ASSERT(style != 0);
- ASSERT(static_cast<SVGElement*>(node)->isStyledTransformable());
}
-RenderPath::~RenderPath()
+TransformationMatrix RenderPath::localToParentTransform() const
{
+ return m_localTransform;
}
TransformationMatrix RenderPath::localTransform() const
@@ -83,16 +78,6 @@ TransformationMatrix RenderPath::localTransform() const
return m_localTransform;
}
-FloatPoint RenderPath::mapAbsolutePointToLocal(const FloatPoint& point) const
-{
- // FIXME: does it make sense to map incoming points with the inverse of the
- // absolute transform?
- double localX;
- double localY;
- absoluteTransform().inverse().map(point.x(), point.y(), &localX, &localY);
- return FloatPoint::narrowPrecision(localX, localY);
-}
-
bool RenderPath::fillContains(const FloatPoint& point, bool requiresFill) const
{
if (m_path.isEmpty())
@@ -104,110 +89,74 @@ bool RenderPath::fillContains(const FloatPoint& point, bool requiresFill) const
return m_path.contains(point, style()->svgStyle()->fillRule());
}
-FloatRect RenderPath::relativeBBox(bool includeStroke) const
+bool RenderPath::strokeContains(const FloatPoint& point, bool requiresStroke) const
{
if (m_path.isEmpty())
- return FloatRect();
-
- if (includeStroke) {
- if (m_strokeBbox.isEmpty()) {
- if (style()->svgStyle()->hasStroke()) {
- BoundingRectStrokeStyleApplier strokeStyle(this, style());
- m_strokeBbox = m_path.strokeBoundingRect(&strokeStyle);
- } else {
- if (m_fillBBox.isEmpty())
- m_fillBBox = m_path.boundingRect();
-
- m_strokeBbox = m_fillBBox;
- }
- }
-
- return m_strokeBbox;
- }
+ return false;
- if (m_fillBBox.isEmpty())
- m_fillBBox = m_path.boundingRect();
+ if (requiresStroke && !SVGPaintServer::strokePaintServer(style(), this))
+ return false;
- return m_fillBBox;
+ BoundingRectStrokeStyleApplier strokeStyle(this, style());
+ return m_path.strokeContains(&strokeStyle, point);
}
-void RenderPath::setPath(const Path& newPath)
+FloatRect RenderPath::objectBoundingBox() const
{
- m_path = newPath;
- m_strokeBbox = FloatRect();
- m_fillBBox = FloatRect();
-}
+ if (m_path.isEmpty())
+ return FloatRect();
-const Path& RenderPath::path() const
-{
- return m_path;
-}
+ if (m_cachedLocalFillBBox.isEmpty())
+ m_cachedLocalFillBBox = m_path.boundingRect();
-bool RenderPath::calculateLocalTransform()
-{
- TransformationMatrix oldTransform = m_localTransform;
- m_localTransform = static_cast<SVGStyledTransformableElement*>(element())->animatedLocalTransform();
- return (m_localTransform != oldTransform);
+ return m_cachedLocalFillBBox;
}
-void RenderPath::layout()
+FloatRect RenderPath::repaintRectInLocalCoordinates() const
{
- IntRect oldBounds;
- IntRect oldOutlineBox;
- bool checkForRepaint = checkForRepaintDuringLayout() && selfNeedsLayout();
- if (checkForRepaint) {
- oldBounds = m_absoluteBounds;
- oldOutlineBox = absoluteOutlineBounds();
- }
-
- calculateLocalTransform();
-
- setPath(static_cast<SVGStyledTransformableElement*>(element())->toPathData());
+ if (m_path.isEmpty())
+ return FloatRect();
- m_absoluteBounds = absoluteClippedOverflowRect();
+ // If we already have a cached repaint rect, return that
+ if (!m_cachedLocalRepaintRect.isEmpty())
+ return m_cachedLocalRepaintRect;
- setWidth(m_absoluteBounds.width());
- setHeight(m_absoluteBounds.height());
+ if (!style()->svgStyle()->hasStroke())
+ m_cachedLocalRepaintRect = objectBoundingBox();
+ else {
+ BoundingRectStrokeStyleApplier strokeStyle(this, style());
+ m_cachedLocalRepaintRect = m_path.strokeBoundingRect(&strokeStyle);
+ }
- if (checkForRepaint)
- repaintAfterLayoutIfNeeded(oldBounds, oldOutlineBox);
+ // Markers and filters can paint outside of the stroke path
+ m_cachedLocalRepaintRect.unite(m_markerBounds);
+ m_cachedLocalRepaintRect.unite(filterBoundingBoxForRenderer(this));
- setNeedsLayout(false);
+ return m_cachedLocalRepaintRect;
}
-IntRect RenderPath::absoluteClippedOverflowRect()
+void RenderPath::setPath(const Path& newPath)
{
- FloatRect repaintRect = absoluteTransform().mapRect(relativeBBox(true));
-
- // Markers can expand the bounding box
- repaintRect.unite(m_markerBounds);
-
-#if ENABLE(SVG_FILTERS)
- // Filters can expand the bounding box
- SVGResourceFilter* filter = getFilterById(document(), style()->svgStyle()->filter());
- if (filter)
- repaintRect.unite(filter->filterBBoxForItemBBox(repaintRect));
-#endif
-
- if (!repaintRect.isEmpty())
- repaintRect.inflate(1); // inflate 1 pixel for antialiasing
-
- return enclosingIntRect(repaintRect);
+ m_path = newPath;
+ m_cachedLocalRepaintRect = FloatRect();
+ m_cachedLocalFillBBox = FloatRect();
}
-bool RenderPath::requiresLayer()
+const Path& RenderPath::path() const
{
- return false;
+ return m_path;
}
-int RenderPath::lineHeight(bool, bool) const
+void RenderPath::layout()
{
- return relativeBBox(true).height();
-}
+ LayoutRepainter repainter(*this, checkForRepaintDuringLayout() && selfNeedsLayout());
-int RenderPath::baselinePosition(bool, bool) const
-{
- return relativeBBox(true).height();
+ SVGStyledTransformableElement* element = static_cast<SVGStyledTransformableElement*>(node());
+ m_localTransform = element->animatedLocalTransform();
+ setPath(element->toPathData());
+
+ repainter.repaintAfterLayout();
+ setNeedsLayout(false);
}
static inline void fillAndStrokePath(const Path& path, GraphicsContext* context, RenderStyle* style, RenderPath* object)
@@ -233,23 +182,23 @@ void RenderPath::paint(PaintInfo& paintInfo, int, int)
return;
paintInfo.context->save();
- paintInfo.context->concatCTM(localTransform());
+ paintInfo.context->concatCTM(localToParentTransform());
SVGResourceFilter* filter = 0;
- FloatRect boundingBox = relativeBBox(true);
+ FloatRect boundingBox = repaintRectInLocalCoordinates();
if (paintInfo.phase == PaintPhaseForeground) {
PaintInfo savedInfo(paintInfo);
prepareToRenderSVGContent(this, paintInfo, boundingBox, filter);
if (style()->svgStyle()->shapeRendering() == SR_CRISPEDGES)
- paintInfo.context->setUseAntialiasing(false);
+ paintInfo.context->setShouldAntialias(false);
fillAndStrokePath(m_path, paintInfo.context, style(), this);
- if (static_cast<SVGStyledElement*>(element())->supportsMarkers())
+ if (static_cast<SVGStyledElement*>(node())->supportsMarkers())
m_markerBounds = drawMarkersIfNeeded(paintInfo.context, paintInfo.rect, m_path);
- finishRenderSVGContent(this, paintInfo, boundingBox, filter, savedInfo.context);
+ finishRenderSVGContent(this, paintInfo, filter, savedInfo.context);
}
if ((paintInfo.phase == PaintPhaseOutline || paintInfo.phase == PaintPhaseSelfOutline) && style()->outlineWidth())
@@ -259,37 +208,28 @@ void RenderPath::paint(PaintInfo& paintInfo, int, int)
paintInfo.context->restore();
}
+// This method is called from inside paintOutline() since we call paintOutline()
+// while transformed to our coord system, return local coords
void RenderPath::addFocusRingRects(GraphicsContext* graphicsContext, int, int)
{
- graphicsContext->addFocusRingRect(enclosingIntRect(relativeBBox(true)));
+ graphicsContext->addFocusRingRect(enclosingIntRect(repaintRectInLocalCoordinates()));
}
-void RenderPath::absoluteRects(Vector<IntRect>& rects, int, int, bool)
-{
- rects.append(absoluteClippedOverflowRect());
-}
-
-void RenderPath::absoluteQuads(Vector<FloatQuad>& quads, bool)
-{
- quads.append(absoluteClippedOverflowRect());
-}
-
-bool RenderPath::nodeAtPoint(const HitTestRequest&, HitTestResult& result, int _x, int _y, int, int, HitTestAction hitTestAction)
+bool RenderPath::nodeAtFloatPoint(const HitTestRequest&, HitTestResult& result, const FloatPoint& pointInParent, HitTestAction hitTestAction)
{
// We only draw in the forground phase, so we only hit-test then.
if (hitTestAction != HitTestForeground)
return false;
-
- IntPoint absolutePoint(_x, _y);
+
+ FloatPoint localPoint = localToParentTransform().inverse().mapPoint(pointInParent);
PointerEventsHitRules hitRules(PointerEventsHitRules::SVG_PATH_HITTESTING, style()->pointerEvents());
bool isVisible = (style()->visibility() == VISIBLE);
if (isVisible || !hitRules.requireVisible) {
- FloatPoint hitPoint = mapAbsolutePointToLocal(absolutePoint);
- if ((hitRules.canHitStroke && (style()->svgStyle()->hasStroke() || !hitRules.requireStroke) && strokeContains(hitPoint, hitRules.requireStroke))
- || (hitRules.canHitFill && (style()->svgStyle()->hasFill() || !hitRules.requireFill) && fillContains(hitPoint, hitRules.requireFill))) {
- updateHitTestResult(result, absolutePoint);
+ if ((hitRules.canHitStroke && (style()->svgStyle()->hasStroke() || !hitRules.requireStroke) && strokeContains(localPoint, hitRules.requireStroke))
+ || (hitRules.canHitFill && (style()->svgStyle()->hasFill() || !hitRules.requireFill) && fillContains(localPoint, hitRules.requireFill))) {
+ updateHitTestResult(result, roundedIntPoint(localPoint));
return true;
}
}
@@ -421,7 +361,7 @@ FloatRect RenderPath::drawMarkersIfNeeded(GraphicsContext* context, const FloatR
{
Document* doc = document();
- SVGElement* svgElement = static_cast<SVGElement*>(element());
+ SVGElement* svgElement = static_cast<SVGElement*>(node());
ASSERT(svgElement && svgElement->document() && svgElement->isStyled());
SVGStyledElement* styledElement = static_cast<SVGStyledElement*>(svgElement);
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderPath.h b/src/3rdparty/webkit/WebCore/rendering/RenderPath.h
index e96439d..a4aefed 100644
--- a/src/3rdparty/webkit/WebCore/rendering/RenderPath.h
+++ b/src/3rdparty/webkit/WebCore/rendering/RenderPath.h
@@ -3,8 +3,7 @@
2004, 2005 Rob Buis <buis@kde.org>
2005 Eric Seidel <eric@webkit.org>
2006 Apple Computer, Inc
-
- This file is part of the KDE project
+ 2009 Google, Inc.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
@@ -27,64 +26,51 @@
#if ENABLE(SVG)
-#include "TransformationMatrix.h"
#include "FloatRect.h"
-
-#include "RenderObject.h"
+#include "RenderSVGModelObject.h"
+#include "TransformationMatrix.h"
namespace WebCore {
class FloatPoint;
-class Path;
class RenderSVGContainer;
class SVGStyledTransformableElement;
-class RenderPath : public RenderObject
-{
+class RenderPath : public RenderSVGModelObject {
public:
- RenderPath(RenderStyle*, SVGStyledTransformableElement*);
- virtual ~RenderPath();
+ RenderPath(SVGStyledTransformableElement*);
// Hit-detection seperated for the fill and the stroke
bool fillContains(const FloatPoint&, bool requiresFill = true) const;
bool strokeContains(const FloatPoint&, bool requiresStroke = true) const;
- // Returns an unscaled bounding box (not even including localTransform()) for this vector path
- virtual FloatRect relativeBBox(bool includeStroke = true) const;
+ virtual FloatRect objectBoundingBox() const;
+ virtual FloatRect repaintRectInLocalCoordinates() const;
+
+ virtual TransformationMatrix localToParentTransform() const;
const Path& path() const;
- void setPath(const Path& newPath);
+ void setPath(const Path&);
virtual bool isRenderPath() const { return true; }
virtual const char* renderName() const { return "RenderPath"; }
-
- bool calculateLocalTransform();
- virtual TransformationMatrix localTransform() const;
-
+
virtual void layout();
- virtual IntRect absoluteClippedOverflowRect();
- virtual bool requiresLayer();
- virtual int lineHeight(bool b, bool isRootLineBox = false) const;
- virtual int baselinePosition(bool b, bool isRootLineBox = false) const;
virtual void paint(PaintInfo&, int parentX, int parentY);
-
- virtual void absoluteRects(Vector<IntRect>&, int tx, int ty, bool topLevel = true);
- virtual void absoluteQuads(Vector<FloatQuad>&, bool topLevel = true);
virtual void addFocusRingRects(GraphicsContext*, int tx, int ty);
- virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, int x, int y, int tx, int ty, HitTestAction);
+ virtual bool nodeAtFloatPoint(const HitTestRequest&, HitTestResult&, const FloatPoint& pointInParent, HitTestAction);
FloatRect drawMarkersIfNeeded(GraphicsContext*, const FloatRect&, const Path&) const;
-
+
private:
- FloatPoint mapAbsolutePointToLocal(const FloatPoint&) const;
+ virtual TransformationMatrix localTransform() const;
mutable Path m_path;
- mutable FloatRect m_fillBBox;
- mutable FloatRect m_strokeBbox;
+ mutable FloatRect m_cachedLocalFillBBox;
+ mutable FloatRect m_cachedLocalRepaintRect;
FloatRect m_markerBounds;
TransformationMatrix m_localTransform;
- IntRect m_absoluteBounds;
};
}
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderReplaced.cpp b/src/3rdparty/webkit/WebCore/rendering/RenderReplaced.cpp
index 79df0f1..e61ac8e 100644
--- a/src/3rdparty/webkit/WebCore/rendering/RenderReplaced.cpp
+++ b/src/3rdparty/webkit/WebCore/rendering/RenderReplaced.cpp
@@ -28,6 +28,7 @@
#include "RenderLayer.h"
#include "RenderTheme.h"
#include "RenderView.h"
+#include "VisiblePosition.h"
using namespace std;
@@ -42,8 +43,6 @@ const int cDefaultHeight = 150;
RenderReplaced::RenderReplaced(Node* node)
: RenderBox(node)
, m_intrinsicSize(cDefaultWidth, cDefaultHeight)
- , m_selectionState(SelectionNone)
- , m_hasOverflow(false)
{
setReplaced(true);
}
@@ -51,19 +50,17 @@ RenderReplaced::RenderReplaced(Node* node)
RenderReplaced::RenderReplaced(Node* node, const IntSize& intrinsicSize)
: RenderBox(node)
, m_intrinsicSize(intrinsicSize)
- , m_selectionState(SelectionNone)
- , m_hasOverflow(false)
{
setReplaced(true);
}
RenderReplaced::~RenderReplaced()
{
- if (m_hasOverflow)
+ if (replacedHasOverflow())
gOverflowRectMap->remove(this);
}
-void RenderReplaced::styleDidChange(RenderStyle::Diff diff, const RenderStyle* oldStyle)
+void RenderReplaced::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
{
RenderBox::styleDidChange(diff, oldStyle);
@@ -77,23 +74,16 @@ void RenderReplaced::layout()
{
ASSERT(needsLayout());
- IntRect oldBounds;
- IntRect oldOutlineBox;
- bool checkForRepaint = checkForRepaintDuringLayout();
- if (checkForRepaint) {
- oldBounds = absoluteClippedOverflowRect();
- oldOutlineBox = absoluteOutlineBounds();
- }
+ LayoutRepainter repainter(*this, checkForRepaintDuringLayout());
- m_height = minimumReplacedHeight();
+ setHeight(minimumReplacedHeight());
calcWidth();
calcHeight();
- adjustOverflowForBoxShadow();
-
- if (checkForRepaint)
- repaintAfterLayoutIfNeeded(oldBounds, oldOutlineBox);
+ adjustOverflowForBoxShadowAndReflect();
+ repainter.repaintAfterLayout();
+
setNeedsLayout(false);
}
@@ -110,8 +100,8 @@ void RenderReplaced::paint(PaintInfo& paintInfo, int tx, int ty)
if (!shouldPaint(paintInfo, tx, ty))
return;
- tx += m_x;
- ty += m_y;
+ tx += x();
+ ty += y();
if (hasBoxDecorations() && (paintInfo.phase == PaintPhaseForeground || paintInfo.phase == PaintPhaseSelection))
paintBoxDecorations(paintInfo, tx, ty);
@@ -137,8 +127,25 @@ void RenderReplaced::paint(PaintInfo& paintInfo, int tx, int ty)
drawSelectionTint = false;
}
+ bool clipToBorderRadius = style()->overflowX() != OVISIBLE && style()->hasBorderRadius();
+ if (clipToBorderRadius) {
+ // Push a clip if we have a border radius, since we want to round the foreground content that gets painted.
+ paintInfo.context->save();
+
+ IntSize topLeft, topRight, bottomLeft, bottomRight;
+ IntRect borderRect = IntRect(tx, ty, width(), height());
+ style()->getBorderRadiiForRect(borderRect, topLeft, topRight, bottomLeft, bottomRight);
+
+ paintInfo.context->addRoundedRectClip(borderRect, topLeft, topRight, bottomLeft, bottomRight);
+ }
+
paintReplaced(paintInfo, tx, ty);
-
+
+ if (clipToBorderRadius)
+ paintInfo.context->restore();
+
+ // The selection tint never gets clipped by border-radius rounding, since we want it to run right up to the edges of
+ // surrounding content.
if (drawSelectionTint) {
IntRect selectionPaintingRect = localSelectionRect();
selectionPaintingRect.move(tx, ty);
@@ -159,8 +166,8 @@ bool RenderReplaced::shouldPaint(PaintInfo& paintInfo, int& tx, int& ty)
if (style()->visibility() != VISIBLE)
return false;
- int currentTX = tx + m_x;
- int currentTY = ty + m_y;
+ int currentTX = tx + x();
+ int currentTY = ty + y();
// Early exit if the element touches the edges.
int top = currentTY + overflowTop();
@@ -215,11 +222,11 @@ unsigned RenderReplaced::caretMaxRenderedOffset() const
return 1;
}
-VisiblePosition RenderReplaced::positionForCoordinates(int x, int y)
+VisiblePosition RenderReplaced::positionForPoint(const IntPoint& point)
{
InlineBox* box = inlineBoxWrapper();
if (!box)
- return VisiblePosition(element(), 0, DOWNSTREAM);
+ return createVisiblePosition(0, DOWNSTREAM);
// FIXME: This code is buggy if the replaced element is relative positioned.
@@ -228,22 +235,22 @@ VisiblePosition RenderReplaced::positionForCoordinates(int x, int y)
int top = root->topOverflow();
int bottom = root->nextRootBox() ? root->nextRootBox()->topOverflow() : root->bottomOverflow();
- if (y + yPos() < top)
- return VisiblePosition(element(), caretMinOffset(), DOWNSTREAM); // coordinates are above
+ if (point.y() + y() < top)
+ return createVisiblePosition(caretMinOffset(), DOWNSTREAM); // coordinates are above
- if (y + yPos() >= bottom)
- return VisiblePosition(element(), caretMaxOffset(), DOWNSTREAM); // coordinates are below
+ if (point.y() + y() >= bottom)
+ return createVisiblePosition(caretMaxOffset(), DOWNSTREAM); // coordinates are below
- if (element()) {
- if (x <= width() / 2)
- return VisiblePosition(element(), 0, DOWNSTREAM);
- return VisiblePosition(element(), 1, DOWNSTREAM);
+ if (node()) {
+ if (point.x() <= width() / 2)
+ return createVisiblePosition(0, DOWNSTREAM);
+ return createVisiblePosition(1, DOWNSTREAM);
}
- return RenderBox::positionForCoordinates(x, y);
+ return RenderBox::positionForPoint(point);
}
-IntRect RenderReplaced::selectionRect(bool clipToVisibleContent)
+IntRect RenderReplaced::selectionRectForRepaint(RenderBoxModelObject* repaintContainer, bool clipToVisibleContent)
{
ASSERT(!needsLayout());
@@ -252,11 +259,9 @@ IntRect RenderReplaced::selectionRect(bool clipToVisibleContent)
IntRect rect = localSelectionRect();
if (clipToVisibleContent)
- computeAbsoluteRepaintRect(rect);
- else {
- FloatPoint absPos = localToAbsoluteForContent(FloatPoint());
- rect.move(absPos.x(), absPos.y());
- }
+ computeRectForRepaint(repaintContainer, rect);
+ else
+ rect = localToContainerQuad(FloatRect(rect), repaintContainer).enclosingBoundingBox();
return rect;
}
@@ -268,19 +273,19 @@ IntRect RenderReplaced::localSelectionRect(bool checkWhetherSelected) const
if (!m_inlineBoxWrapper)
// We're a block-level replaced element. Just return our own dimensions.
- return IntRect(0, 0, width(), height() + borderTopExtra() + borderBottomExtra());
+ return IntRect(0, 0, width(), height());
RenderBlock* cb = containingBlock();
if (!cb)
return IntRect();
RootInlineBox* root = m_inlineBoxWrapper->root();
- return IntRect(0, root->selectionTop() - yPos(), width(), root->selectionHeight());
+ return IntRect(0, root->selectionTop() - y(), width(), root->selectionHeight());
}
void RenderReplaced::setSelectionState(SelectionState s)
{
- m_selectionState = s;
+ RenderBox::setSelectionState(s);
if (m_inlineBoxWrapper) {
RootInlineBox* line = m_inlineBoxWrapper->root();
if (line)
@@ -303,7 +308,7 @@ bool RenderReplaced::isSelected() const
if (s == SelectionStart)
return selectionStart == 0;
- int end = element()->hasChildNodes() ? element()->childNodeCount() : 1;
+ int end = node()->hasChildNodes() ? node()->childNodeCount() : 1;
if (s == SelectionEnd)
return selectionEnd == end;
if (s == SelectionBoth)
@@ -323,31 +328,39 @@ void RenderReplaced::setIntrinsicSize(const IntSize& size)
m_intrinsicSize = size;
}
-void RenderReplaced::adjustOverflowForBoxShadow()
+void RenderReplaced::adjustOverflowForBoxShadowAndReflect()
{
IntRect overflow;
for (ShadowData* boxShadow = style()->boxShadow(); boxShadow; boxShadow = boxShadow->next) {
- IntRect shadow = borderBox();
+ IntRect shadow = borderBoxRect();
shadow.move(boxShadow->x, boxShadow->y);
shadow.inflate(boxShadow->blur);
overflow.unite(shadow);
}
+ // Now that we have an overflow rect including shadow, let's make sure that
+ // the reflection (which can also include the shadow) is also included.
+ if (hasReflection()) {
+ if (overflow.isEmpty())
+ overflow = borderBoxRect();
+ overflow.unite(reflectedRect(overflow));
+ }
+
if (!overflow.isEmpty()) {
if (!gOverflowRectMap)
gOverflowRectMap = new OverflowRectMap();
- overflow.unite(borderBox());
+ overflow.unite(borderBoxRect());
gOverflowRectMap->set(this, overflow);
- m_hasOverflow = true;
- } else if (m_hasOverflow) {
+ setReplacedHasOverflow(true);
+ } else if (replacedHasOverflow()) {
gOverflowRectMap->remove(this);
- m_hasOverflow = false;
+ setReplacedHasOverflow(false);
}
}
int RenderReplaced::overflowHeight(bool) const
{
- if (m_hasOverflow) {
+ if (replacedHasOverflow()) {
IntRect *r = &gOverflowRectMap->find(this)->second;
return r->height() + r->y();
}
@@ -357,7 +370,7 @@ int RenderReplaced::overflowHeight(bool) const
int RenderReplaced::overflowWidth(bool) const
{
- if (m_hasOverflow) {
+ if (replacedHasOverflow()) {
IntRect *r = &gOverflowRectMap->find(this)->second;
return r->width() + r->x();
}
@@ -367,7 +380,7 @@ int RenderReplaced::overflowWidth(bool) const
int RenderReplaced::overflowLeft(bool) const
{
- if (m_hasOverflow)
+ if (replacedHasOverflow())
return gOverflowRectMap->get(this).x();
return 0;
@@ -375,7 +388,7 @@ int RenderReplaced::overflowLeft(bool) const
int RenderReplaced::overflowTop(bool) const
{
- if (m_hasOverflow)
+ if (replacedHasOverflow())
return gOverflowRectMap->get(this).y();
return 0;
@@ -383,24 +396,27 @@ int RenderReplaced::overflowTop(bool) const
IntRect RenderReplaced::overflowRect(bool) const
{
- if (m_hasOverflow)
+ if (replacedHasOverflow())
return gOverflowRectMap->find(this)->second;
- return borderBox();
+ return borderBoxRect();
}
-IntRect RenderReplaced::absoluteClippedOverflowRect()
+IntRect RenderReplaced::clippedOverflowRectForRepaint(RenderBoxModelObject* repaintContainer)
{
if (style()->visibility() != VISIBLE && !enclosingLayer()->hasVisibleContent())
return IntRect();
- // The selectionRect can project outside of the overflowRect, so use
- // that for repainting to avoid selection painting glitches
- IntRect r = localSelectionRect(false);
+ // The selectionRect can project outside of the overflowRect, so take their union
+ // for repainting to avoid selection painting glitches.
+ IntRect r = unionRect(localSelectionRect(false), overflowRect(false));
RenderView* v = view();
- if (v)
+ if (v) {
+ // FIXME: layoutDelta needs to be applied in parts before/after transforms and
+ // repaint containers. https://bugs.webkit.org/show_bug.cgi?id=23308
r.move(v->layoutDelta());
+ }
if (style()) {
if (style()->hasAppearance())
@@ -409,7 +425,7 @@ IntRect RenderReplaced::absoluteClippedOverflowRect()
if (v)
r.inflate(style()->outlineSize());
}
- computeAbsoluteRepaintRect(r);
+ computeRectForRepaint(repaintContainer, r);
return r;
}
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderReplaced.h b/src/3rdparty/webkit/WebCore/rendering/RenderReplaced.h
index 3186718..4937446 100644
--- a/src/3rdparty/webkit/WebCore/rendering/RenderReplaced.h
+++ b/src/3rdparty/webkit/WebCore/rendering/RenderReplaced.h
@@ -34,6 +34,8 @@ public:
virtual const char* renderName() const { return "RenderReplaced"; }
+ virtual bool canHaveChildren() const { return false; }
+
virtual int lineHeight(bool firstLine, bool isRootLineBox = false) const;
virtual int baselinePosition(bool firstLine, bool isRootLineBox = false) const;
@@ -53,33 +55,29 @@ public:
virtual int overflowTop(bool includeInterior = true) const;
virtual IntRect overflowRect(bool includeInterior = true) const;
- virtual IntRect absoluteClippedOverflowRect();
+ virtual IntRect clippedOverflowRectForRepaint(RenderBoxModelObject* repaintContainer);
virtual unsigned caretMaxRenderedOffset() const;
- virtual VisiblePosition positionForCoordinates(int x, int y);
+ virtual VisiblePosition positionForPoint(const IntPoint&);
virtual bool canBeSelectionLeaf() const { return true; }
- virtual SelectionState selectionState() const { return static_cast<SelectionState>(m_selectionState); }
virtual void setSelectionState(SelectionState);
- virtual IntRect selectionRect(bool clipToVisibleContent = true);
+ virtual IntRect selectionRectForRepaint(RenderBoxModelObject* repaintContainer, bool clipToVisibleContent = true);
bool isSelected() const;
protected:
- virtual void styleDidChange(RenderStyle::Diff, const RenderStyle* oldStyle);
+ virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
void setIntrinsicSize(const IntSize&);
virtual void intrinsicSizeChanged();
bool shouldPaint(PaintInfo&, int& tx, int& ty);
- void adjustOverflowForBoxShadow();
+ void adjustOverflowForBoxShadowAndReflect();
IntRect localSelectionRect(bool checkWhetherSelected = true) const;
private:
IntSize m_intrinsicSize;
-
- unsigned m_selectionState : 3; // SelectionState
- bool m_hasOverflow : 1;
};
}
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderReplica.cpp b/src/3rdparty/webkit/WebCore/rendering/RenderReplica.cpp
index 9556980..5fa3c62 100644
--- a/src/3rdparty/webkit/WebCore/rendering/RenderReplica.cpp
+++ b/src/3rdparty/webkit/WebCore/rendering/RenderReplica.cpp
@@ -35,24 +35,26 @@ namespace WebCore {
RenderReplica::RenderReplica(Node* n)
: RenderBox(n)
-{}
+{
+ // This is a hack. Replicas are synthetic, and don't pick up the attributes of the
+ // renderers being replicated, so they always report that they are inline, non-replaced.
+ // However, we need transforms to be applied to replicas for reflections, so have to pass
+ // the if (!isInline() || isReplaced()) check before setHasTransform().
+ setReplaced(true);
+}
RenderReplica::~RenderReplica()
{}
void RenderReplica::layout()
{
- IntRect box = parent()->borderBox();
- m_x = box.x();
- m_y = box.y();
- m_width = box.width();
- m_height = box.height();
+ setFrameRect(parentBox()->borderBoxRect());
setNeedsLayout(false);
}
void RenderReplica::calcPrefWidths()
{
- m_minPrefWidth = parent()->width();
+ m_minPrefWidth = parentBox()->width();
m_maxPrefWidth = m_minPrefWidth;
setPrefWidthsDirty(false);
}
@@ -62,17 +64,16 @@ void RenderReplica::paint(PaintInfo& paintInfo, int tx, int ty)
if (paintInfo.phase != PaintPhaseForeground && paintInfo.phase != PaintPhaseMask)
return;
- tx += m_x;
- ty += m_y;
+ tx += x();
+ ty += y();
if (paintInfo.phase == PaintPhaseForeground)
// Turn around and paint the parent layer. Use temporary clipRects, so that the layer doesn't end up caching clip rects
// computing using the wrong rootLayer
layer()->parent()->paintLayer(layer()->transform() ? layer()->parent() : layer()->enclosingTransformedAncestor(),
paintInfo.context, paintInfo.rect,
- true, PaintRestrictionNone, 0,
- true, // appliedTransform
- true); // temporaryClipRects
+ PaintRestrictionNone, 0, 0,
+ RenderLayer::PaintLayerHaveTransparency | RenderLayer::PaintLayerAppliedTransform | RenderLayer::PaintLayerTemporaryClipRects | RenderLayer::PaintLayerPaintingReflection);
else if (paintInfo.phase == PaintPhaseMask)
paintMask(paintInfo, tx, ty);
}
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderReplica.h b/src/3rdparty/webkit/WebCore/rendering/RenderReplica.h
index d3a9026..d5db3b7 100644
--- a/src/3rdparty/webkit/WebCore/rendering/RenderReplica.h
+++ b/src/3rdparty/webkit/WebCore/rendering/RenderReplica.h
@@ -40,7 +40,7 @@ public:
virtual const char* renderName() const { return "RenderReplica"; }
- virtual bool requiresLayer() { return true; }
+ virtual bool requiresLayer() const { return true; }
virtual void layout();
virtual void calcPrefWidths();
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderSVGBlock.h b/src/3rdparty/webkit/WebCore/rendering/RenderSVGBlock.h
index d545fd0..f8afd0f 100644
--- a/src/3rdparty/webkit/WebCore/rendering/RenderSVGBlock.h
+++ b/src/3rdparty/webkit/WebCore/rendering/RenderSVGBlock.h
@@ -25,12 +25,13 @@
#if ENABLE(SVG)
#include "RenderBlock.h"
+#include "SVGRenderSupport.h"
namespace WebCore {
class SVGElement;
-class RenderSVGBlock : public RenderBlock {
+class RenderSVGBlock : public RenderBlock, protected SVGRenderBase {
public:
RenderSVGBlock(SVGElement*);
virtual void setStyle(PassRefPtr<RenderStyle>);
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderSVGContainer.cpp b/src/3rdparty/webkit/WebCore/rendering/RenderSVGContainer.cpp
index 2d6b57f..8a77d2e 100644
--- a/src/3rdparty/webkit/WebCore/rendering/RenderSVGContainer.cpp
+++ b/src/3rdparty/webkit/WebCore/rendering/RenderSVGContainer.cpp
@@ -2,8 +2,7 @@
Copyright (C) 2004, 2005, 2007 Nikolas Zimmermann <zimmermann@kde.org>
2004, 2005, 2007, 2008 Rob Buis <buis@kde.org>
2007 Eric Seidel <eric@webkit.org>
-
- This file is part of the KDE project
+ Copyright (C) 2009 Google, Inc. 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
@@ -27,6 +26,7 @@
#include "RenderSVGContainer.h"
#include "AXObjectCache.h"
+#include "FloatQuad.h"
#include "GraphicsContext.h"
#include "RenderView.h"
#include "SVGRenderSupport.h"
@@ -37,157 +37,15 @@
namespace WebCore {
RenderSVGContainer::RenderSVGContainer(SVGStyledElement* node)
- : RenderObject(node)
- , m_firstChild(0)
- , m_lastChild(0)
- , m_width(0)
- , m_height(0)
+ : RenderSVGModelObject(node)
, m_drawsContents(true)
{
- setReplaced(true);
}
RenderSVGContainer::~RenderSVGContainer()
{
}
-bool RenderSVGContainer::canHaveChildren() const
-{
- return true;
-}
-
-void RenderSVGContainer::addChild(RenderObject* newChild, RenderObject* beforeChild)
-{
- insertChildNode(newChild, beforeChild);
-}
-
-void RenderSVGContainer::removeChild(RenderObject* oldChild)
-{
- // We do this here instead of in removeChildNode, since the only extremely low-level uses of remove/appendChildNode
- // cannot affect the positioned object list, and the floating object list is irrelevant (since the list gets cleared on
- // layout anyway).
- oldChild->removeFromObjectLists();
-
- removeChildNode(oldChild);
-}
-
-void RenderSVGContainer::destroy()
-{
- destroyLeftoverChildren();
- RenderObject::destroy();
-}
-
-void RenderSVGContainer::destroyLeftoverChildren()
-{
- while (m_firstChild) {
- // Destroy any anonymous children remaining in the render tree, as well as implicit (shadow) DOM elements like those used in the engine-based text fields.
- if (m_firstChild->element())
- m_firstChild->element()->setRenderer(0);
-
- m_firstChild->destroy();
- }
-}
-
-RenderObject* RenderSVGContainer::removeChildNode(RenderObject* oldChild, bool fullRemove)
-{
- ASSERT(oldChild->parent() == this);
-
- // So that we'll get the appropriate dirty bit set (either that a normal flow child got yanked or
- // that a positioned child got yanked). We also repaint, so that the area exposed when the child
- // disappears gets repainted properly.
- if (!documentBeingDestroyed() && fullRemove) {
- oldChild->setNeedsLayoutAndPrefWidthsRecalc();
- oldChild->repaint();
- }
-
- // If we have a line box wrapper, delete it.
- oldChild->deleteLineBoxWrapper();
-
- if (!documentBeingDestroyed() && fullRemove) {
- // If oldChild is the start or end of the selection, then clear the selection to
- // avoid problems of invalid pointers.
- // FIXME: The SelectionController should be responsible for this when it
- // is notified of DOM mutations.
- if (oldChild->isSelectionBorder())
- view()->clearSelection();
- }
-
- // remove the child
- if (oldChild->previousSibling())
- oldChild->previousSibling()->setNextSibling(oldChild->nextSibling());
- if (oldChild->nextSibling())
- oldChild->nextSibling()->setPreviousSibling(oldChild->previousSibling());
-
- if (m_firstChild == oldChild)
- m_firstChild = oldChild->nextSibling();
- if (m_lastChild == oldChild)
- m_lastChild = oldChild->previousSibling();
-
- oldChild->setPreviousSibling(0);
- oldChild->setNextSibling(0);
- oldChild->setParent(0);
-
- if (AXObjectCache::accessibilityEnabled())
- document()->axObjectCache()->childrenChanged(this);
-
- return oldChild;
-}
-
-void RenderSVGContainer::appendChildNode(RenderObject* newChild, bool)
-{
- ASSERT(!newChild->parent());
- ASSERT(newChild->element()->isSVGElement());
-
- newChild->setParent(this);
- RenderObject* lChild = m_lastChild;
-
- if (lChild) {
- newChild->setPreviousSibling(lChild);
- lChild->setNextSibling(newChild);
- } else
- m_firstChild = newChild;
-
- m_lastChild = newChild;
-
- newChild->setNeedsLayoutAndPrefWidthsRecalc(); // Goes up the containing block hierarchy.
- if (!normalChildNeedsLayout())
- setChildNeedsLayout(true); // We may supply the static position for an absolute positioned child.
-
- if (AXObjectCache::accessibilityEnabled())
- document()->axObjectCache()->childrenChanged(this);
-}
-
-void RenderSVGContainer::insertChildNode(RenderObject* child, RenderObject* beforeChild, bool)
-{
- if (!beforeChild) {
- appendChildNode(child);
- return;
- }
-
- ASSERT(!child->parent());
- ASSERT(beforeChild->parent() == this);
- ASSERT(child->element()->isSVGElement());
-
- if (beforeChild == m_firstChild)
- m_firstChild = child;
-
- RenderObject* prev = beforeChild->previousSibling();
- child->setNextSibling(beforeChild);
- beforeChild->setPreviousSibling(child);
- if (prev)
- prev->setNextSibling(child);
- child->setPreviousSibling(prev);
-
- child->setParent(this);
-
- child->setNeedsLayoutAndPrefWidthsRecalc();
- if (!normalChildNeedsLayout())
- setChildNeedsLayout(true); // We may supply the static position for an absolute positioned child.
-
- if (AXObjectCache::accessibilityEnabled())
- document()->axObjectCache()->childrenChanged(this);
-}
-
bool RenderSVGContainer::drawsContents() const
{
return m_drawsContents;
@@ -198,49 +56,15 @@ void RenderSVGContainer::setDrawsContents(bool drawsContents)
m_drawsContents = drawsContents;
}
-TransformationMatrix RenderSVGContainer::localTransform() const
-{
- return m_localTransform;
-}
-
-bool RenderSVGContainer::requiresLayer()
-{
- // Only allow an <svg> element to generate a layer when it's positioned in a non-SVG context
- return false;
-}
-
-int RenderSVGContainer::lineHeight(bool, bool) const
-{
- return height() + marginTop() + marginBottom();
-}
-
-int RenderSVGContainer::baselinePosition(bool, bool) const
-{
- return height() + marginTop() + marginBottom();
-}
-
-bool RenderSVGContainer::calculateLocalTransform()
-{
- // subclasses can override this to add transform support
- return false;
-}
-
void RenderSVGContainer::layout()
{
ASSERT(needsLayout());
+ ASSERT(!view()->layoutStateEnabled()); // RenderSVGRoot disables layoutState for the SVG rendering tree.
- // Arbitrary affine transforms are incompatible with LayoutState.
- view()->disableLayoutState();
+ calcViewport(); // Allow RenderSVGViewportContainer to update its viewport
- IntRect oldBounds;
- IntRect oldOutlineBox;
- bool checkForRepaint = checkForRepaintDuringLayout() && selfWillPaint();
- if (checkForRepaint) {
- oldBounds = m_absoluteBounds;
- oldOutlineBox = absoluteOutlineBounds();
- }
-
- calculateLocalTransform();
+ LayoutRepainter repainter(*this, checkForRepaintDuringLayout() || selfWillPaint());
+ calculateLocalTransform(); // Allow RenderSVGTransformableContainer to update its transform
for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
// Only force our kids to layout if we're being asked to relayout as a result of a parent changing
@@ -253,67 +77,14 @@ void RenderSVGContainer::layout()
child->layoutIfNeeded();
ASSERT(!child->needsLayout());
}
+ repainter.repaintAfterLayout();
- calcBounds();
-
- if (checkForRepaint)
- repaintAfterLayoutIfNeeded(oldBounds, oldOutlineBox);
-
- view()->enableLayoutState();
setNeedsLayout(false);
}
-int RenderSVGContainer::calcReplacedWidth() const
-{
- switch (style()->width().type()) {
- case Fixed:
- return max(0, style()->width().value());
- case Percent:
- {
- const int cw = containingBlockWidth();
- return cw > 0 ? max(0, style()->width().calcMinValue(cw)) : 0;
- }
- default:
- return 0;
- }
-}
-
-int RenderSVGContainer::calcReplacedHeight() const
-{
- switch (style()->height().type()) {
- case Fixed:
- return max(0, style()->height().value());
- case Percent:
- {
- RenderBlock* cb = containingBlock();
- return style()->height().calcValue(cb->availableHeight());
- }
- default:
- return 0;
- }
-}
-
-void RenderSVGContainer::applyContentTransforms(PaintInfo& paintInfo)
-{
- if (!localTransform().isIdentity())
- paintInfo.context->concatCTM(localTransform());
-}
-
-void RenderSVGContainer::applyAdditionalTransforms(PaintInfo&)
-{
- // no-op
-}
-
-void RenderSVGContainer::calcBounds()
-{
- m_width = calcReplacedWidth();
- m_height = calcReplacedHeight();
- m_absoluteBounds = absoluteClippedOverflowRect();
-}
-
bool RenderSVGContainer::selfWillPaint() const
{
-#if ENABLE(SVG_FILTERS)
+#if ENABLE(FILTERS)
const SVGRenderStyle* svgStyle = style()->svgStyle();
SVGResourceFilter* filter = getFilterById(document(), svgStyle->filter());
if (filter)
@@ -330,98 +101,75 @@ void RenderSVGContainer::paint(PaintInfo& paintInfo, int, int)
// Spec: groups w/o children still may render filter content.
if (!firstChild() && !selfWillPaint())
return;
-
- paintInfo.context->save();
- applyContentTransforms(paintInfo);
- SVGResourceFilter* filter = 0;
- PaintInfo savedInfo(paintInfo);
+ PaintInfo childPaintInfo(paintInfo);
- FloatRect boundingBox = relativeBBox(true);
- if (paintInfo.phase == PaintPhaseForeground)
- prepareToRenderSVGContent(this, paintInfo, boundingBox, filter);
+ childPaintInfo.context->save();
+
+ // Let the RenderSVGViewportContainer subclass clip if necessary
+ applyViewportClip(childPaintInfo);
- applyAdditionalTransforms(paintInfo);
+ applyTransformToPaintInfo(childPaintInfo, localToParentTransform());
+
+ SVGResourceFilter* filter = 0;
+ FloatRect boundingBox = repaintRectInLocalCoordinates();
+ if (childPaintInfo.phase == PaintPhaseForeground)
+ prepareToRenderSVGContent(this, childPaintInfo, boundingBox, filter);
- // default implementation. Just pass paint through to the children
- PaintInfo childInfo(paintInfo);
- childInfo.paintingRoot = paintingRootForChildren(paintInfo);
+ childPaintInfo.paintingRoot = paintingRootForChildren(childPaintInfo);
for (RenderObject* child = firstChild(); child; child = child->nextSibling())
- child->paint(childInfo, 0, 0);
+ child->paint(childPaintInfo, 0, 0);
if (paintInfo.phase == PaintPhaseForeground)
- finishRenderSVGContent(this, paintInfo, boundingBox, filter, savedInfo.context);
+ finishRenderSVGContent(this, childPaintInfo, filter, paintInfo.context);
- paintInfo.context->restore();
-
+ childPaintInfo.context->restore();
+
+ // FIXME: This really should be drawn from local coordinates, but currently we hack it
+ // to avoid our clip killing our outline rect. Thus we translate our
+ // outline rect into parent coords before drawing.
+ // FIXME: This means our focus ring won't share our rotation like it should.
+ // We should instead disable our clip during PaintPhaseOutline
+ IntRect paintRectInParent = enclosingIntRect(localToParentTransform().mapRect(repaintRectInLocalCoordinates()));
if ((paintInfo.phase == PaintPhaseOutline || paintInfo.phase == PaintPhaseSelfOutline) && style()->outlineWidth() && style()->visibility() == VISIBLE)
- paintOutline(paintInfo.context, m_absoluteBounds.x(), m_absoluteBounds.y(), m_absoluteBounds.width(), m_absoluteBounds.height(), style());
+ paintOutline(paintInfo.context, paintRectInParent.x(), paintRectInParent.y(), paintRectInParent.width(), paintRectInParent.height(), style());
}
-TransformationMatrix RenderSVGContainer::viewportTransform() const
+// addFocusRingRects is called from paintOutline and needs to be in the same coordinates as the paintOuline call
+void RenderSVGContainer::addFocusRingRects(GraphicsContext* graphicsContext, int, int)
{
- return TransformationMatrix();
+ IntRect paintRectInParent = enclosingIntRect(localToParentTransform().mapRect(repaintRectInLocalCoordinates()));
+ graphicsContext->addFocusRingRect(paintRectInParent);
}
-IntRect RenderSVGContainer::absoluteClippedOverflowRect()
+FloatRect RenderSVGContainer::objectBoundingBox() const
{
- FloatRect repaintRect;
-
- for (RenderObject* current = firstChild(); current != 0; current = current->nextSibling())
- repaintRect.unite(current->absoluteClippedOverflowRect());
-
-#if ENABLE(SVG_FILTERS)
- // Filters can expand the bounding box
- SVGResourceFilter* filter = getFilterById(document(), style()->svgStyle()->filter());
- if (filter)
- repaintRect.unite(filter->filterBBoxForItemBBox(repaintRect));
-#endif
-
- if (!repaintRect.isEmpty())
- repaintRect.inflate(1); // inflate 1 pixel for antialiasing
-
- return enclosingIntRect(repaintRect);
+ return computeContainerBoundingBox(this, false);
}
-void RenderSVGContainer::addFocusRingRects(GraphicsContext* graphicsContext, int, int)
+// RenderSVGContainer is used for <g> elements which do not themselves have a
+// width or height, so we union all of our child rects as our repaint rect.
+FloatRect RenderSVGContainer::repaintRectInLocalCoordinates() const
{
- graphicsContext->addFocusRingRect(m_absoluteBounds);
-}
+ FloatRect repaintRect = computeContainerBoundingBox(this, true);
-void RenderSVGContainer::absoluteRects(Vector<IntRect>& rects, int, int, bool)
-{
- rects.append(absoluteClippedOverflowRect());
-}
+ // A filter on this container can paint outside of the union of the child repaint rects
+ repaintRect.unite(filterBoundingBoxForRenderer(this));
-void RenderSVGContainer::absoluteQuads(Vector<FloatQuad>& quads, bool)
-{
- quads.append(absoluteClippedOverflowRect());
+ return repaintRect;
}
-FloatRect RenderSVGContainer::relativeBBox(bool includeStroke) const
+bool RenderSVGContainer::nodeAtFloatPoint(const HitTestRequest& request, HitTestResult& result, const FloatPoint& pointInParent, HitTestAction hitTestAction)
{
- FloatRect rect;
-
- RenderObject* current = firstChild();
- for (; current != 0; current = current->nextSibling()) {
- FloatRect childBBox = current->relativeBBox(includeStroke);
- FloatRect mappedBBox = current->localTransform().mapRect(childBBox);
-
- // <svg> can have a viewBox contributing to the bbox
- if (current->isSVGContainer())
- mappedBBox = static_cast<RenderSVGContainer*>(current)->viewportTransform().mapRect(mappedBBox);
-
- rect.unite(mappedBBox);
- }
+ // Give RenderSVGViewportContainer a chance to apply its viewport clip
+ if (!pointIsInsideViewportClip(pointInParent))
+ return false;
- return rect;
-}
+ FloatPoint localPoint = localToParentTransform().inverse().mapPoint(pointInParent);
-bool RenderSVGContainer::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, int _x, int _y, int _tx, int _ty, HitTestAction hitTestAction)
-{
for (RenderObject* child = lastChild(); child; child = child->previousSibling()) {
- if (child->nodeAtPoint(request, result, _x, _y, _tx, _ty, hitTestAction)) {
- updateHitTestResult(result, IntPoint(_x - _tx, _y - _ty));
+ if (child->nodeAtFloatPoint(request, result, localPoint, hitTestAction)) {
+ updateHitTestResult(result, roundedIntPoint(localPoint));
return true;
}
}
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderSVGContainer.h b/src/3rdparty/webkit/WebCore/rendering/RenderSVGContainer.h
index 48f5694..4bb7e44 100644
--- a/src/3rdparty/webkit/WebCore/rendering/RenderSVGContainer.h
+++ b/src/3rdparty/webkit/WebCore/rendering/RenderSVGContainer.h
@@ -1,8 +1,7 @@
/*
Copyright (C) 2004, 2005, 2007 Nikolas Zimmermann <zimmermann@kde.org>
2004, 2005, 2007 Rob Buis <buis@kde.org>
-
- This file is part of the KDE project
+ Copyright (C) 2009 Google, Inc. 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
@@ -25,93 +24,52 @@
#if ENABLE(SVG)
-#include "RenderPath.h"
-#include "SVGPreserveAspectRatio.h"
+#include "RenderSVGModelObject.h"
namespace WebCore {
class SVGElement;
-class RenderSVGContainer : public RenderObject {
+class RenderSVGContainer : public RenderSVGModelObject {
public:
RenderSVGContainer(SVGStyledElement*);
~RenderSVGContainer();
- virtual RenderObject* firstChild() const { return m_firstChild; }
- virtual RenderObject* lastChild() const { return m_lastChild; }
-
- virtual int width() const { return m_width; }
- virtual int height() const { return m_height; }
-
- virtual bool canHaveChildren() const;
- virtual void addChild(RenderObject* newChild, RenderObject* beforeChild = 0);
- virtual void removeChild(RenderObject*);
-
- virtual void destroy();
- void destroyLeftoverChildren();
-
- virtual RenderObject* removeChildNode(RenderObject*, bool fullRemove = true);
- virtual void appendChildNode(RenderObject*, bool fullAppend = true);
- virtual void insertChildNode(RenderObject* child, RenderObject* before, bool fullInsert = true);
-
- // Designed for speed. Don't waste time doing a bunch of work like layer updating and repainting when we know that our
- // change in parentage is not going to affect anything.
- virtual void moveChildNode(RenderObject* child) { appendChildNode(child->parent()->removeChildNode(child, false), false); }
+ virtual RenderObjectChildList* virtualChildren() { return children(); }
+ virtual const RenderObjectChildList* virtualChildren() const { return children(); }
+ const RenderObjectChildList* children() const { return &m_children; }
+ RenderObjectChildList* children() { return &m_children; }
- virtual void calcPrefWidths() { setPrefWidthsDirty(false); }
-
- // Some containers do not want it's children
- // to be drawn, because they may be 'referenced'
- // Example: <marker> children in SVG
+ // <marker> uses these methods to only allow drawing children during a special marker draw time
void setDrawsContents(bool);
bool drawsContents() const;
virtual bool isSVGContainer() const { return true; }
virtual const char* renderName() const { return "RenderSVGContainer"; }
- virtual bool requiresLayer();
- virtual int lineHeight(bool b, bool isRootLineBox = false) const;
- virtual int baselinePosition(bool b, bool isRootLineBox = false) const;
-
virtual void layout();
virtual void paint(PaintInfo&, int parentX, int parentY);
-
- virtual IntRect absoluteClippedOverflowRect();
- virtual void absoluteRects(Vector<IntRect>& rects, int tx, int ty, bool topLevel = true);
- virtual void absoluteQuads(Vector<FloatQuad>&, bool topLevel = true);
virtual void addFocusRingRects(GraphicsContext*, int tx, int ty);
- FloatRect relativeBBox(bool includeStroke = true) const;
+ virtual FloatRect objectBoundingBox() const;
+ virtual FloatRect repaintRectInLocalCoordinates() const;
- virtual bool calculateLocalTransform();
- virtual TransformationMatrix localTransform() const;
- virtual TransformationMatrix viewportTransform() const;
-
- virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, int x, int y, int tx, int ty, HitTestAction);
+ virtual bool nodeAtFloatPoint(const HitTestRequest&, HitTestResult&, const FloatPoint& pointInParent, HitTestAction);
protected:
- virtual void applyContentTransforms(PaintInfo&);
- virtual void applyAdditionalTransforms(PaintInfo&);
+ // Allow RenderSVGTransformableContainer to hook in at the right time in layout()
+ virtual void calculateLocalTransform() { }
- void calcBounds();
+ // Allow RenderSVGViewportContainer to hook in at the right times in layout(), paint() and nodeAtFloatPoint()
+ virtual void calcViewport() { }
+ virtual void applyViewportClip(PaintInfo&) { }
+ virtual bool pointIsInsideViewportClip(const FloatPoint& /*pointInParent*/) { return true; }
private:
- int calcReplacedWidth() const;
- int calcReplacedHeight() const;
-
- RenderObject* m_firstChild;
- RenderObject* m_lastChild;
-
- int m_width;
- int m_height;
-
bool selfWillPaint() const;
+ RenderObjectChildList m_children;
bool m_drawsContents : 1;
-
-protected:
- IntRect m_absoluteBounds;
- TransformationMatrix m_localTransform;
};
} // namespace WebCore
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderSVGGradientStop.cpp b/src/3rdparty/webkit/WebCore/rendering/RenderSVGGradientStop.cpp
index d0dc881..b81e7f4 100644
--- a/src/3rdparty/webkit/WebCore/rendering/RenderSVGGradientStop.cpp
+++ b/src/3rdparty/webkit/WebCore/rendering/RenderSVGGradientStop.cpp
@@ -42,7 +42,7 @@ RenderSVGGradientStop::~RenderSVGGradientStop()
{
}
-void RenderSVGGradientStop::styleDidChange(RenderStyle::Diff diff, const RenderStyle* oldStyle)
+void RenderSVGGradientStop::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
{
RenderObject::styleDidChange(diff, oldStyle);
@@ -61,7 +61,7 @@ void RenderSVGGradientStop::layout()
SVGGradientElement* RenderSVGGradientStop::gradientElement() const
{
- Node* parentNode = element()->parent();
+ Node* parentNode = node()->parent();
if (parentNode->hasTagName(linearGradientTag) || parentNode->hasTagName(radialGradientTag))
return static_cast<SVGGradientElement*>(parentNode);
return 0;
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderSVGGradientStop.h b/src/3rdparty/webkit/WebCore/rendering/RenderSVGGradientStop.h
index 86de6d0..1d0858d 100644
--- a/src/3rdparty/webkit/WebCore/rendering/RenderSVGGradientStop.h
+++ b/src/3rdparty/webkit/WebCore/rendering/RenderSVGGradientStop.h
@@ -1,7 +1,6 @@
/*
- * This file is part of the WebKit project.
- *
* Copyright (C) 2007 Eric Seidel <eric@webkit.org>
+ * Copyright (C) 2009 Google, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -41,14 +40,15 @@ namespace WebCore {
virtual void layout();
- // This override is needed to prevent crashing on <svg><stop /></svg>
- // RenderObject's default impl asks the parent Object and RenderSVGRoot
- // asks all child RenderObjects for overflow rects, thus infinite loop.
+ // This overrides are needed to prevent ASSERTs on <svg><stop /></svg>
+ // RenderObject's default implementations ASSERT_NOT_REACHED()
// https://bugs.webkit.org/show_bug.cgi?id=20400
- virtual IntRect absoluteClippedOverflowRect() { return IntRect(); }
-
+ virtual IntRect clippedOverflowRectForRepaint(RenderBoxModelObject*) { return IntRect(); }
+ virtual FloatRect objectBoundingBox() const { return FloatRect(); }
+ virtual FloatRect repaintRectInLocalCoordinates() const { return FloatRect(); }
+
protected:
- virtual void styleDidChange(RenderStyle::Diff, const RenderStyle* oldStyle);
+ virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
private:
SVGGradientElement* gradientElement() const;
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderSVGHiddenContainer.cpp b/src/3rdparty/webkit/WebCore/rendering/RenderSVGHiddenContainer.cpp
index 4a7d6b2..f08c008 100644
--- a/src/3rdparty/webkit/WebCore/rendering/RenderSVGHiddenContainer.cpp
+++ b/src/3rdparty/webkit/WebCore/rendering/RenderSVGHiddenContainer.cpp
@@ -39,21 +39,6 @@ RenderSVGHiddenContainer::~RenderSVGHiddenContainer()
{
}
-bool RenderSVGHiddenContainer::requiresLayer()
-{
- return false;
-}
-
-int RenderSVGHiddenContainer::lineHeight(bool, bool) const
-{
- return 0;
-}
-
-int RenderSVGHiddenContainer::baselinePosition(bool, bool) const
-{
- return 0;
-}
-
void RenderSVGHiddenContainer::layout()
{
ASSERT(needsLayout());
@@ -76,37 +61,32 @@ void RenderSVGHiddenContainer::paint(PaintInfo&, int, int)
// This subtree does not paint.
}
-IntRect RenderSVGHiddenContainer::absoluteClippedOverflowRect()
+IntRect RenderSVGHiddenContainer::clippedOverflowRectForRepaint(RenderBoxModelObject* /*repaintContainer*/)
{
return IntRect();
}
-void RenderSVGHiddenContainer::absoluteRects(Vector<IntRect>&, int, int, bool)
+void RenderSVGHiddenContainer::absoluteRects(Vector<IntRect>&, int, int)
{
// This subtree does not take up space or paint
}
-void RenderSVGHiddenContainer::absoluteQuads(Vector<FloatQuad>&, bool)
+void RenderSVGHiddenContainer::absoluteQuads(Vector<FloatQuad>&)
{
// This subtree does not take up space or paint
}
-TransformationMatrix RenderSVGHiddenContainer::absoluteTransform() const
-{
- return TransformationMatrix();
-}
-
-TransformationMatrix RenderSVGHiddenContainer::localTransform() const
+bool RenderSVGHiddenContainer::nodeAtFloatPoint(const HitTestRequest&, HitTestResult&, const FloatPoint&, HitTestAction)
{
- return TransformationMatrix();
+ return false;
}
-bool RenderSVGHiddenContainer::nodeAtPoint(const HitTestRequest&, HitTestResult&, int, int, int, int, HitTestAction)
+FloatRect RenderSVGHiddenContainer::objectBoundingBox() const
{
- return false;
+ return FloatRect();
}
-FloatRect RenderSVGHiddenContainer::relativeBBox(bool) const
+FloatRect RenderSVGHiddenContainer::repaintRectInLocalCoordinates() const
{
return FloatRect();
}
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderSVGHiddenContainer.h b/src/3rdparty/webkit/WebCore/rendering/RenderSVGHiddenContainer.h
index 24c7ddd..5a208d0 100644
--- a/src/3rdparty/webkit/WebCore/rendering/RenderSVGHiddenContainer.h
+++ b/src/3rdparty/webkit/WebCore/rendering/RenderSVGHiddenContainer.h
@@ -37,29 +37,28 @@ namespace WebCore {
public:
RenderSVGHiddenContainer(SVGStyledElement*);
virtual ~RenderSVGHiddenContainer();
-
+
virtual bool isSVGContainer() const { return true; }
virtual bool isSVGHiddenContainer() const { return true; }
virtual const char* renderName() const { return "RenderSVGHiddenContainer"; }
-
- virtual bool requiresLayer();
-
- virtual int lineHeight(bool b, bool isRootLineBox = false) const;
- virtual int baselinePosition(bool b, bool isRootLineBox = false) const;
-
+
+ virtual bool requiresLayer() const { return false; }
+
virtual void layout();
virtual void paint(PaintInfo&, int parentX, int parentY);
- virtual IntRect absoluteClippedOverflowRect();
- virtual void absoluteRects(Vector<IntRect>& rects, int tx, int ty, bool topLevel = true);
- virtual void absoluteQuads(Vector<FloatQuad>&, bool topLevel = true);
-
- virtual TransformationMatrix absoluteTransform() const;
- virtual TransformationMatrix localTransform() const;
+ virtual IntRect clippedOverflowRectForRepaint(RenderBoxModelObject* repaintContainer);
+ virtual void absoluteRects(Vector<IntRect>& rects, int tx, int ty);
+ virtual void absoluteQuads(Vector<FloatQuad>&);
+
+ // FIXME: This override only exists to match existing LayoutTest results.
+ virtual TransformationMatrix absoluteTransform() const { return TransformationMatrix(); }
+
+ virtual FloatRect objectBoundingBox() const;
+ virtual FloatRect repaintRectInLocalCoordinates() const;
- virtual FloatRect relativeBBox(bool includeStroke = true) const;
- virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, int x, int y, int tx, int ty, HitTestAction);
+ virtual bool nodeAtFloatPoint(const HitTestRequest&, HitTestResult&, const FloatPoint& pointInParent, HitTestAction);
};
}
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderSVGImage.cpp b/src/3rdparty/webkit/WebCore/rendering/RenderSVGImage.cpp
index 61f65a0..b38352e 100644
--- a/src/3rdparty/webkit/WebCore/rendering/RenderSVGImage.cpp
+++ b/src/3rdparty/webkit/WebCore/rendering/RenderSVGImage.cpp
@@ -3,8 +3,7 @@
Copyright (C) 2006 Apple Computer, Inc.
Copyright (C) 2007 Nikolas Zimmermann <zimmermann@kde.org>
Copyright (C) 2007, 2008 Rob Buis <buis@kde.org>
-
- This file is part of the WebKit project
+ Copyright (C) 2009, Google, Inc.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
@@ -29,8 +28,10 @@
#include "Attr.h"
#include "FloatConversion.h"
+#include "FloatQuad.h"
#include "GraphicsContext.h"
#include "PointerEventsHitRules.h"
+#include "RenderLayer.h"
#include "SVGImageElement.h"
#include "SVGLength.h"
#include "SVGPreserveAspectRatio.h"
@@ -125,41 +126,25 @@ void RenderSVGImage::adjustRectsForAspectRatio(FloatRect& destRect, FloatRect& s
}
}
-bool RenderSVGImage::calculateLocalTransform()
-{
- TransformationMatrix oldTransform = m_localTransform;
- m_localTransform = static_cast<SVGStyledTransformableElement*>(element())->animatedLocalTransform();
- return (m_localTransform != oldTransform);
-}
-
void RenderSVGImage::layout()
{
ASSERT(needsLayout());
-
- IntRect oldBounds;
- IntRect oldOutlineBox;
- bool checkForRepaint = checkForRepaintDuringLayout();
- if (checkForRepaint) {
- oldBounds = absoluteClippedOverflowRect();
- oldOutlineBox = absoluteOutlineBounds();
- }
-
- calculateLocalTransform();
+
+ LayoutRepainter repainter(*this, checkForRepaintDuringLayout());
+
+ SVGImageElement* image = static_cast<SVGImageElement*>(node());
+ m_localTransform = image->animatedLocalTransform();
// minimum height
- m_height = errorOccurred() ? intrinsicSize().height() : 0;
+ setHeight(errorOccurred() ? intrinsicSize().height() : 0);
calcWidth();
calcHeight();
- SVGImageElement* image = static_cast<SVGImageElement*>(node());
m_localBounds = FloatRect(image->x().value(image), image->y().value(image), image->width().value(image), image->height().value(image));
- calculateAbsoluteBounds();
-
- if (checkForRepaint)
- repaintAfterLayoutIfNeeded(oldBounds, oldOutlineBox);
-
+ repainter.repaintAfterLayout();
+
setNeedsLayout(false);
}
@@ -169,7 +154,7 @@ void RenderSVGImage::paint(PaintInfo& paintInfo, int, int)
return;
paintInfo.context->save();
- paintInfo.context->concatCTM(localTransform());
+ paintInfo.context->concatCTM(localToParentTransform());
if (paintInfo.phase == PaintPhaseForeground) {
SVGResourceFilter* filter = 0;
@@ -186,14 +171,16 @@ void RenderSVGImage::paint(PaintInfo& paintInfo, int, int)
adjustRectsForAspectRatio(destRect, srcRect, imageElt->preserveAspectRatio());
paintInfo.context->drawImage(image(), destRect, srcRect);
-
- finishRenderSVGContent(this, paintInfo, m_localBounds, filter, savedInfo.context);
+ finishRenderSVGContent(this, paintInfo, filter, savedInfo.context);
}
-
+
+ if ((paintInfo.phase == PaintPhaseOutline || paintInfo.phase == PaintPhaseSelfOutline) && style()->outlineWidth())
+ paintOutline(paintInfo.context, 0, 0, width(), height(), style());
+
paintInfo.context->restore();
}
-bool RenderSVGImage::nodeAtPoint(const HitTestRequest&, HitTestResult& result, int _x, int _y, int, int, HitTestAction hitTestAction)
+bool RenderSVGImage::nodeAtFloatPoint(const HitTestRequest&, HitTestResult& result, const FloatPoint& pointInParent, HitTestAction hitTestAction)
{
// We only draw in the forground phase, so we only hit-test then.
if (hitTestAction != HitTestForeground)
@@ -203,12 +190,11 @@ bool RenderSVGImage::nodeAtPoint(const HitTestRequest&, HitTestResult& result, i
bool isVisible = (style()->visibility() == VISIBLE);
if (isVisible || !hitRules.requireVisible) {
- double localX, localY;
- absoluteTransform().inverse().map(_x, _y, &localX, &localY);
+ FloatPoint localPoint = localToParentTransform().inverse().mapPoint(pointInParent);
if (hitRules.canHitFill) {
- if (m_localBounds.contains(narrowPrecisionToFloat(localX), narrowPrecisionToFloat(localY))) {
- updateHitTestResult(result, IntPoint(_x, _y));
+ if (m_localBounds.contains(localPoint)) {
+ updateHitTestResult(result, roundedIntPoint(localPoint));
return true;
}
}
@@ -217,60 +203,63 @@ bool RenderSVGImage::nodeAtPoint(const HitTestRequest&, HitTestResult& result, i
return false;
}
-bool RenderSVGImage::requiresLayer()
+bool RenderSVGImage::nodeAtPoint(const HitTestRequest&, HitTestResult&, int, int, int, int, HitTestAction)
{
+ ASSERT_NOT_REACHED();
return false;
}
-FloatRect RenderSVGImage::relativeBBox(bool) const
+FloatRect RenderSVGImage::objectBoundingBox() const
{
return m_localBounds;
}
+FloatRect RenderSVGImage::repaintRectInLocalCoordinates() const
+{
+ FloatRect repaintRect = m_localBounds;
+
+ // Filters can paint outside the image content
+ repaintRect.unite(filterBoundingBoxForRenderer(this));
+
+ return repaintRect;
+}
+
void RenderSVGImage::imageChanged(WrappedImagePtr image, const IntRect* rect)
{
RenderImage::imageChanged(image, rect);
// We override to invalidate a larger rect, since SVG images can draw outside their "bounds"
- repaintRectangle(absoluteClippedOverflowRect());
+ repaintRectangle(absoluteClippedOverflowRect()); // FIXME: Isn't this just repaint()?
}
-void RenderSVGImage::calculateAbsoluteBounds()
+IntRect RenderSVGImage::clippedOverflowRectForRepaint(RenderBoxModelObject* repaintContainer)
{
- // FIXME: broken with CSS transforms
- FloatRect absoluteRect = absoluteTransform().mapRect(relativeBBox(true));
-
-#if ENABLE(SVG_FILTERS)
- // Filters can expand the bounding box
- SVGResourceFilter* filter = getFilterById(document(), style()->svgStyle()->filter());
- if (filter)
- absoluteRect.unite(filter->filterBBoxForItemBBox(absoluteRect));
-#endif
-
- if (!absoluteRect.isEmpty())
- absoluteRect.inflate(1); // inflate 1 pixel for antialiasing
+ return SVGRenderBase::clippedOverflowRectForRepaint(this, repaintContainer);
+}
- m_absoluteBounds = enclosingIntRect(absoluteRect);
+void RenderSVGImage::computeRectForRepaint(RenderBoxModelObject* repaintContainer, IntRect& repaintRect, bool fixed)
+{
+ SVGRenderBase::computeRectForRepaint(this, repaintContainer, repaintRect, fixed);
}
-IntRect RenderSVGImage::absoluteClippedOverflowRect()
+void RenderSVGImage::mapLocalToContainer(RenderBoxModelObject* repaintContainer, bool fixed , bool useTransforms, TransformState& transformState) const
{
- return m_absoluteBounds;
+ SVGRenderBase::mapLocalToContainer(this, repaintContainer, fixed, useTransforms, transformState);
}
void RenderSVGImage::addFocusRingRects(GraphicsContext* graphicsContext, int, int)
{
// this is called from paint() after the localTransform has already been applied
- IntRect contentRect = enclosingIntRect(relativeBBox());
+ IntRect contentRect = enclosingIntRect(repaintRectInLocalCoordinates());
graphicsContext->addFocusRingRect(contentRect);
}
-void RenderSVGImage::absoluteRects(Vector<IntRect>& rects, int, int, bool)
+void RenderSVGImage::absoluteRects(Vector<IntRect>& rects, int, int)
{
rects.append(absoluteClippedOverflowRect());
}
-void RenderSVGImage::absoluteQuads(Vector<FloatQuad>& quads, bool)
+void RenderSVGImage::absoluteQuads(Vector<FloatQuad>& quads)
{
quads.append(FloatRect(absoluteClippedOverflowRect()));
}
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderSVGImage.h b/src/3rdparty/webkit/WebCore/rendering/RenderSVGImage.h
index de8a2d3..01b8b65 100644
--- a/src/3rdparty/webkit/WebCore/rendering/RenderSVGImage.h
+++ b/src/3rdparty/webkit/WebCore/rendering/RenderSVGImage.h
@@ -2,8 +2,7 @@
Copyright (C) 2006 Alexander Kellett <lypanov@kde.org>
Copyright (C) 2006 Apple Computer, Inc.
Copyright (C) 2007 Rob Buis <buis@kde.org>
-
- This file is part of the WebKit project.
+ Copyright (C) 2009 Google, Inc.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
@@ -29,23 +28,33 @@
#include "TransformationMatrix.h"
#include "FloatRect.h"
#include "RenderImage.h"
+#include "SVGRenderSupport.h"
namespace WebCore {
class SVGImageElement;
class SVGPreserveAspectRatio;
- class RenderSVGImage : public RenderImage {
+ class RenderSVGImage : public RenderImage, SVGRenderBase {
public:
RenderSVGImage(SVGImageElement*);
virtual ~RenderSVGImage();
-
- virtual TransformationMatrix localTransform() const { return m_localTransform; }
-
- virtual FloatRect relativeBBox(bool includeStroke = true) const;
- virtual IntRect absoluteClippedOverflowRect();
- virtual void absoluteRects(Vector<IntRect>&, int tx, int ty, bool topLevel = true);
- virtual void absoluteQuads(Vector<FloatQuad>&, bool topLevel = true);
+
+ virtual const char* renderName() const { return "RenderSVGImage"; }
+ virtual bool isSVGImage() const { return true; }
+
+ virtual TransformationMatrix localToParentTransform() const { return m_localTransform; }
+
+ virtual FloatRect objectBoundingBox() const;
+ virtual FloatRect repaintRectInLocalCoordinates() const;
+
+ virtual IntRect clippedOverflowRectForRepaint(RenderBoxModelObject* repaintContainer);
+ virtual void computeRectForRepaint(RenderBoxModelObject* repaintContainer, IntRect&, bool fixed = false);
+
+ virtual void mapLocalToContainer(RenderBoxModelObject* repaintContainer, bool useTransforms, bool fixed, TransformState&) const;
+
+ virtual void absoluteRects(Vector<IntRect>&, int tx, int ty);
+ virtual void absoluteQuads(Vector<FloatQuad>&);
virtual void addFocusRingRects(GraphicsContext*, int tx, int ty);
virtual void imageChanged(WrappedImagePtr, const IntRect* = 0);
@@ -54,17 +63,16 @@ namespace WebCore {
virtual void layout();
virtual void paint(PaintInfo&, int parentX, int parentY);
- bool requiresLayer();
+ bool requiresLayer() const { return false; }
+ virtual bool nodeAtFloatPoint(const HitTestRequest&, HitTestResult&, const FloatPoint& pointInParent, HitTestAction);
virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, int _x, int _y, int _tx, int _ty, HitTestAction);
- bool calculateLocalTransform();
-
private:
- void calculateAbsoluteBounds();
+ virtual TransformationMatrix localTransform() const { return m_localTransform; }
+
TransformationMatrix m_localTransform;
FloatRect m_localBounds;
- IntRect m_absoluteBounds;
};
} // namespace WebCore
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderSVGInline.cpp b/src/3rdparty/webkit/WebCore/rendering/RenderSVGInline.cpp
index 11da004..3c44dd8 100644
--- a/src/3rdparty/webkit/WebCore/rendering/RenderSVGInline.cpp
+++ b/src/3rdparty/webkit/WebCore/rendering/RenderSVGInline.cpp
@@ -2,7 +2,7 @@
* This file is part of the WebKit project.
*
* Copyright (C) 2006 Oliver Hunt <ojh16@student.canterbury.ac.nz>
- * (C) 2006 Apple Computer Inc.
+ * Copyright (C) 2006 Apple Inc. 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
@@ -26,7 +26,11 @@
#if ENABLE(SVG)
#include "RenderSVGInline.h"
+#include "FloatQuad.h"
+#include "RenderBlock.h"
#include "SVGInlineFlowBox.h"
+#include "SVGInlineTextBox.h"
+#include "SVGRootInlineBox.h"
namespace WebCore {
@@ -35,22 +39,49 @@ RenderSVGInline::RenderSVGInline(Node* n)
{
}
-InlineBox* RenderSVGInline::createInlineBox(bool makePlaceHolderBox, bool isRootLineBox, bool isOnlyRun)
+InlineFlowBox* RenderSVGInline::createFlowBox()
{
- ASSERT(!(!isRootLineBox && (isReplaced() || makePlaceHolderBox)));
- ASSERT(isInlineFlow());
+ InlineFlowBox* box = new (renderArena()) SVGInlineFlowBox(this);
+ box->setIsSVG(true);
+ return box;
+}
+
+void RenderSVGInline::absoluteRects(Vector<IntRect>& rects, int, int)
+{
+ InlineRunBox* firstBox = firstLineBox();
+
+ SVGRootInlineBox* rootBox = firstBox ? static_cast<SVGInlineTextBox*>(firstBox)->svgRootInlineBox() : 0;
+ RenderBox* object = rootBox ? rootBox->block() : 0;
+
+ if (!object)
+ return;
+
+ int xRef = object->x();
+ int yRef = object->y();
+
+ for (InlineRunBox* curr = firstBox; curr; curr = curr->nextLineBox()) {
+ FloatRect rect(xRef + curr->x(), yRef + curr->y(), curr->width(), curr->height());
+ rects.append(enclosingIntRect(localToAbsoluteQuad(rect).boundingBox()));
+ }
+}
+
+void RenderSVGInline::absoluteQuads(Vector<FloatQuad>& quads)
+{
+ InlineRunBox* firstBox = firstLineBox();
+
+ SVGRootInlineBox* rootBox = firstBox ? static_cast<SVGInlineTextBox*>(firstBox)->svgRootInlineBox() : 0;
+ RenderBox* object = rootBox ? rootBox->block() : 0;
+
+ if (!object)
+ return;
- InlineFlowBox* flowBox = new (renderArena()) SVGInlineFlowBox(this);
+ int xRef = object->x();
+ int yRef = object->y();
- if (!m_firstLineBox)
- m_firstLineBox = m_lastLineBox = flowBox;
- else {
- m_lastLineBox->setNextLineBox(flowBox);
- flowBox->setPreviousLineBox(m_lastLineBox);
- m_lastLineBox = flowBox;
+ for (InlineRunBox* curr = firstBox; curr; curr = curr->nextLineBox()) {
+ FloatRect rect(xRef + curr->x(), yRef + curr->y(), curr->width(), curr->height());
+ quads.append(localToAbsoluteQuad(rect));
}
-
- return flowBox;
}
}
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderSVGInline.h b/src/3rdparty/webkit/WebCore/rendering/RenderSVGInline.h
index 42fdafc..1ff8d02 100644
--- a/src/3rdparty/webkit/WebCore/rendering/RenderSVGInline.h
+++ b/src/3rdparty/webkit/WebCore/rendering/RenderSVGInline.h
@@ -28,13 +28,21 @@
#include "RenderInline.h"
namespace WebCore {
+
class RenderSVGInline : public RenderInline {
public:
- RenderSVGInline(Node*);
- virtual const char* renderName() const { return "RenderSVGInline"; }
- virtual InlineBox* createInlineBox(bool makePlaceHolderBox, bool isRootLineBox, bool isOnlyRun = false);
- virtual bool requiresLayer() { return false; }
- };
+ RenderSVGInline(Node*);
+ virtual const char* renderName() const { return "RenderSVGInline"; }
+ virtual bool requiresLayer() const { return false; }
+
+ // These are shared between RenderSVGTSpan and RenderSVGTextPath
+ virtual void absoluteRects(Vector<IntRect>& rects, int tx, int ty);
+ virtual void absoluteQuads(Vector<FloatQuad>&);
+
+private:
+ virtual InlineFlowBox* createFlowBox();
+};
+
}
#endif // ENABLE(SVG)
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderSVGInlineText.cpp b/src/3rdparty/webkit/WebCore/rendering/RenderSVGInlineText.cpp
index 2212d78..b1a21d7 100644
--- a/src/3rdparty/webkit/WebCore/rendering/RenderSVGInlineText.cpp
+++ b/src/3rdparty/webkit/WebCore/rendering/RenderSVGInlineText.cpp
@@ -29,10 +29,12 @@
#include "RenderSVGInlineText.h"
#include "FloatConversion.h"
+#include "FloatQuad.h"
#include "RenderBlock.h"
#include "RenderSVGRoot.h"
#include "SVGInlineTextBox.h"
#include "SVGRootInlineBox.h"
+#include "VisiblePosition.h"
namespace WebCore {
@@ -53,27 +55,37 @@ RenderSVGInlineText::RenderSVGInlineText(Node* n, PassRefPtr<StringImpl> str)
{
}
-void RenderSVGInlineText::absoluteRects(Vector<IntRect>& rects, int, int, bool)
+
+void RenderSVGInlineText::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
+{
+ // Skip RenderText's possible layout scheduling on style change
+ RenderObject::styleDidChange(diff, oldStyle);
+
+ // FIXME: SVG text is apparently always transformed?
+ if (RefPtr<StringImpl> textToTransform = originalText())
+ setText(textToTransform.release(), true);
+}
+
+void RenderSVGInlineText::absoluteRects(Vector<IntRect>& rects, int, int)
{
- rects.append(computeAbsoluteRectForRange(0, textLength()));
+ rects.append(computeRepaintRectForRange(0, 0, textLength()));
}
-void RenderSVGInlineText::absoluteQuads(Vector<FloatQuad>& quads, bool)
+void RenderSVGInlineText::absoluteQuads(Vector<FloatQuad>& quads)
{
- quads.append(FloatRect(computeAbsoluteRectForRange(0, textLength())));
+ quads.append(computeRepaintQuadForRange(0, 0, textLength()));
}
-IntRect RenderSVGInlineText::selectionRect(bool)
+IntRect RenderSVGInlineText::selectionRectForRepaint(RenderBoxModelObject* repaintContainer, bool /*clipToVisibleContent*/)
{
ASSERT(!needsLayout());
- IntRect rect;
if (selectionState() == SelectionNone)
- return rect;
+ return IntRect();
// Early exit if we're ie. a <text> within a <defs> section.
if (isChildOfHiddenContainer(this))
- return rect;
+ return IntRect();
// Now calculate startPos and endPos for painting selection.
// We include a selection while endPos > 0
@@ -91,79 +103,83 @@ IntRect RenderSVGInlineText::selectionRect(bool)
}
if (startPos == endPos)
- return rect;
+ return IntRect();
- return computeAbsoluteRectForRange(startPos, endPos);
+ return computeRepaintRectForRange(repaintContainer, startPos, endPos);
}
-IntRect RenderSVGInlineText::computeAbsoluteRectForRange(int startPos, int endPos)
+IntRect RenderSVGInlineText::computeRepaintRectForRange(RenderBoxModelObject* repaintContainer, int startPos, int endPos)
{
- IntRect rect;
+ FloatQuad repaintQuad = computeRepaintQuadForRange(repaintContainer, startPos, endPos);
+ return enclosingIntRect(repaintQuad.boundingBox());
+}
+FloatQuad RenderSVGInlineText::computeRepaintQuadForRange(RenderBoxModelObject* repaintContainer, int startPos, int endPos)
+{
RenderBlock* cb = containingBlock();
if (!cb || !cb->container())
- return rect;
+ return FloatQuad();
RenderSVGRoot* root = findSVGRootObject(parent());
if (!root)
- return rect;
+ return FloatQuad();
+ IntRect rect;
for (InlineTextBox* box = firstTextBox(); box; box = box->nextTextBox())
rect.unite(box->selectionRect(0, 0, startPos, endPos));
- // Mimic RenderBox::computeAbsoluteRepaintRect() functionality. But only the subset needed for SVG and respecting SVG transformations.
- FloatPoint absPos = cb->container()->localToAbsolute();
-
- // Remove HTML parent translation offsets here! These need to be retrieved from the RenderSVGRoot object.
- // But do take the containingBlocks's container position into account, ie. SVG text in scrollable <div>.
- TransformationMatrix htmlParentCtm = root->RenderContainer::absoluteTransform();
-
- FloatRect fixedRect(narrowPrecisionToFloat(rect.x() + absPos.x() - xPos() - htmlParentCtm.e()),
- narrowPrecisionToFloat(rect.y() + absPos.y() - yPos() - htmlParentCtm.f()), rect.width(), rect.height());
- // FIXME: broken with CSS transforms
- return enclosingIntRect(absoluteTransform().mapRect(fixedRect));
+ return localToContainerQuad(FloatQuad(rect), repaintContainer);
}
-InlineTextBox* RenderSVGInlineText::createInlineTextBox()
+InlineTextBox* RenderSVGInlineText::createTextBox()
{
- return new (renderArena()) SVGInlineTextBox(this);
+ InlineTextBox* box = new (renderArena()) SVGInlineTextBox(this);
+ box->setIsSVG(true);
+ return box;
}
-IntRect RenderSVGInlineText::localCaretRect(InlineBox* inlineBox, int caretOffset, int* extraWidthToEndOfLine)
+IntRect RenderSVGInlineText::localCaretRect(InlineBox*, int, int*)
{
- // SVG doesn't have any editable content where a caret rect would be needed
+ // SVG doesn't have any editable content where a caret rect would be needed.
+ // FIXME: That's not sufficient. The localCaretRect function is also used for selection.
return IntRect();
}
-VisiblePosition RenderSVGInlineText::positionForCoordinates(int x, int y)
+VisiblePosition RenderSVGInlineText::positionForPoint(const IntPoint& point)
{
SVGInlineTextBox* textBox = static_cast<SVGInlineTextBox*>(firstTextBox());
if (!textBox || textLength() == 0)
- return VisiblePosition(element(), 0, DOWNSTREAM);
+ return createVisiblePosition(0, DOWNSTREAM);
SVGRootInlineBox* rootBox = textBox->svgRootInlineBox();
- RenderObject* object = rootBox ? rootBox->object() : 0;
+ RenderBlock* object = rootBox ? rootBox->block() : 0;
if (!object)
- return VisiblePosition(element(), 0, DOWNSTREAM);
+ return createVisiblePosition(0, DOWNSTREAM);
- int offset = 0;
+ int closestOffsetInBox = 0;
+ // FIXME: This approach is wrong. The correct code would first find the
+ // closest SVGInlineTextBox to the point, and *then* ask only that inline box
+ // what the closest text offset to that point is. This code instead walks
+ // through all boxes in order, so when you click "near" a box, you'll actually
+ // end up returning the nearest offset in the last box, even if the
+ // nearest offset to your click is contained in another box.
for (SVGInlineTextBox* box = textBox; box; box = static_cast<SVGInlineTextBox*>(box->nextTextBox())) {
- if (box->svgCharacterHitsPosition(x + object->xPos(), y + object->yPos(), offset)) {
+ if (box->svgCharacterHitsPosition(point.x() + object->x(), point.y() + object->y(), closestOffsetInBox)) {
// If we're not at the end/start of the box, stop looking for other selected boxes.
if (box->direction() == LTR) {
- if (offset <= (int) box->end() + 1)
+ if (closestOffsetInBox <= (int) box->end() + 1)
break;
} else {
- if (offset > (int) box->start())
+ if (closestOffsetInBox > (int) box->start())
break;
}
}
}
- return VisiblePosition(element(), offset, DOWNSTREAM);
+ return createVisiblePosition(closestOffsetInBox, DOWNSTREAM);
}
void RenderSVGInlineText::destroy()
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderSVGInlineText.h b/src/3rdparty/webkit/WebCore/rendering/RenderSVGInlineText.h
index cc37166..c4a096d 100644
--- a/src/3rdparty/webkit/WebCore/rendering/RenderSVGInlineText.h
+++ b/src/3rdparty/webkit/WebCore/rendering/RenderSVGInlineText.h
@@ -34,22 +34,25 @@ class RenderSVGInlineText : public RenderText {
public:
RenderSVGInlineText(Node*, PassRefPtr<StringImpl>);
virtual const char* renderName() const { return "RenderSVGInlineText"; }
+
+ virtual void styleDidChange(StyleDifference, const RenderStyle*);
- virtual void absoluteRects(Vector<IntRect>& rects, int tx, int ty, bool topLevel = true);
- virtual void absoluteQuads(Vector<FloatQuad>&, bool topLevel = true);
+ virtual void absoluteRects(Vector<IntRect>& rects, int tx, int ty);
+ virtual void absoluteQuads(Vector<FloatQuad>&);
- virtual bool requiresLayer() { return false; }
- virtual IntRect selectionRect(bool clipToVisibleContent = true);
+ virtual bool requiresLayer() const { return false; }
+ virtual IntRect selectionRectForRepaint(RenderBoxModelObject* repaintContainer, bool clipToVisibleContent = true);
virtual bool isSVGText() const { return true; }
- virtual InlineTextBox* createInlineTextBox();
virtual IntRect localCaretRect(InlineBox*, int caretOffset, int* extraWidthToEndOfLine = 0);
- virtual VisiblePosition positionForCoordinates(int x, int y);
+ virtual VisiblePosition positionForPoint(const IntPoint&);
virtual void destroy();
private:
- IntRect computeAbsoluteRectForRange(int startPos, int endPos);
+ virtual InlineTextBox* createTextBox();
+ IntRect computeRepaintRectForRange(RenderBoxModelObject* repaintContainer, int startPos, int endPos);
+ FloatQuad computeRepaintQuadForRange(RenderBoxModelObject* repaintContainer, int startPos, int endPos);
};
}
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderSVGModelObject.cpp b/src/3rdparty/webkit/WebCore/rendering/RenderSVGModelObject.cpp
new file mode 100644
index 0000000..3fab5a6
--- /dev/null
+++ b/src/3rdparty/webkit/WebCore/rendering/RenderSVGModelObject.cpp
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2009, Google 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:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * 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.
+ * * Neither the name of Google Inc. 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT
+ * OWNER OR 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(SVG)
+#include "RenderSVGModelObject.h"
+
+#include "GraphicsContext.h"
+#include "RenderLayer.h"
+#include "RenderView.h"
+#include "SVGStyledElement.h"
+
+#if ENABLE(FILTERS)
+#include "SVGResourceFilter.h"
+#endif
+
+namespace WebCore {
+
+RenderSVGModelObject::RenderSVGModelObject(SVGStyledElement* node)
+ : RenderObject(node)
+{
+}
+
+IntRect RenderSVGModelObject::clippedOverflowRectForRepaint(RenderBoxModelObject* repaintContainer)
+{
+ return SVGRenderBase::clippedOverflowRectForRepaint(this, repaintContainer);
+}
+
+void RenderSVGModelObject::computeRectForRepaint(RenderBoxModelObject* repaintContainer, IntRect& repaintRect, bool fixed)
+{
+ SVGRenderBase::computeRectForRepaint(this, repaintContainer, repaintRect, fixed);
+}
+
+void RenderSVGModelObject::mapLocalToContainer(RenderBoxModelObject* repaintContainer, bool fixed , bool useTransforms, TransformState& transformState) const
+{
+ SVGRenderBase::mapLocalToContainer(this, repaintContainer, fixed, useTransforms, transformState);
+}
+
+// Copied from RenderBox, this method likely requires further refactoring to work easily for both SVG and CSS Box Model content.
+// FIXME: This may also need to move into SVGRenderBase as the RenderBox version depends
+// on borderBoundingBox() which SVG RenderBox subclases (like SVGRenderBlock) do not implement.
+IntRect RenderSVGModelObject::outlineBoundsForRepaint(RenderBoxModelObject* repaintContainer) const
+{
+ IntRect box = enclosingIntRect(repaintRectInLocalCoordinates());
+ adjustRectForOutlineAndShadow(box);
+
+ FloatQuad containerRelativeQuad = localToContainerQuad(FloatRect(box), repaintContainer);
+ return containerRelativeQuad.enclosingBoundingBox();
+}
+
+void RenderSVGModelObject::absoluteRects(Vector<IntRect>& rects, int, int)
+{
+ rects.append(absoluteClippedOverflowRect());
+}
+
+void RenderSVGModelObject::absoluteQuads(Vector<FloatQuad>& quads)
+{
+ quads.append(absoluteClippedOverflowRect());
+}
+
+bool RenderSVGModelObject::nodeAtPoint(const HitTestRequest&, HitTestResult&, int, int, int, int, HitTestAction)
+{
+ ASSERT_NOT_REACHED();
+ return false;
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(SVG)
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderSVGModelObject.h b/src/3rdparty/webkit/WebCore/rendering/RenderSVGModelObject.h
new file mode 100644
index 0000000..0aa13ad
--- /dev/null
+++ b/src/3rdparty/webkit/WebCore/rendering/RenderSVGModelObject.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2009, Google 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:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * 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.
+ * * Neither the name of Google Inc. 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT
+ * OWNER OR 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 RenderSVGModelObject_h
+#define RenderSVGModelObject_h
+
+#if ENABLE(SVG)
+
+#include "RenderObject.h"
+#include "SVGRenderSupport.h"
+
+namespace WebCore {
+
+// Most renderers in the SVG rendering tree will inherit from this class
+// but not all. (e.g. RenderSVGForeignObject, RenderSVGBlock, RenderSVGImage) thus methods
+// required by SVG renders need to be declared on RenderObject, but shared
+// logic can go in this class or in SVGRenderBase.
+
+class SVGStyledElement;
+
+class RenderSVGModelObject : public RenderObject, protected SVGRenderBase {
+public:
+ RenderSVGModelObject(SVGStyledElement*);
+
+ virtual bool requiresLayer() const { return false; }
+
+ virtual IntRect clippedOverflowRectForRepaint(RenderBoxModelObject* repaintContainer);
+ virtual void computeRectForRepaint(RenderBoxModelObject* repaintContainer, IntRect&, bool fixed = false);
+ virtual IntRect outlineBoundsForRepaint(RenderBoxModelObject* repaintContainer) const;
+
+ virtual void absoluteRects(Vector<IntRect>& rects, int tx, int ty);
+ virtual void absoluteQuads(Vector<FloatQuad>&);
+
+ virtual void mapLocalToContainer(RenderBoxModelObject* repaintContainer, bool useTransforms, bool fixed, TransformState&) const;
+
+private:
+ // This method should never be called, SVG uses a different nodeAtPoint method
+ bool nodeAtPoint(const HitTestRequest& request, HitTestResult& result, int xInContainer, int yInContainer, int dxParentToContainer, int dyParentToContainer, HitTestAction hitTestAction);
+};
+
+}
+
+#endif // ENABLE(SVG)
+#endif
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderSVGRoot.cpp b/src/3rdparty/webkit/WebCore/rendering/RenderSVGRoot.cpp
index 457ac02..80c29dd 100644
--- a/src/3rdparty/webkit/WebCore/rendering/RenderSVGRoot.cpp
+++ b/src/3rdparty/webkit/WebCore/rendering/RenderSVGRoot.cpp
@@ -2,8 +2,7 @@
Copyright (C) 2004, 2005, 2007 Nikolas Zimmermann <zimmermann@kde.org>
2004, 2005, 2007, 2008, 2009 Rob Buis <buis@kde.org>
2007 Eric Seidel <eric@webkit.org>
-
- This file is part of the KDE project
+ 2009 Google, Inc.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
@@ -27,24 +26,24 @@
#include "RenderSVGRoot.h"
#include "GraphicsContext.h"
-#include "RenderPath.h"
#include "RenderSVGContainer.h"
#include "RenderView.h"
#include "SVGLength.h"
#include "SVGRenderSupport.h"
-#include "SVGResourceClipper.h"
-#include "SVGResourceFilter.h"
-#include "SVGResourceMasker.h"
#include "SVGSVGElement.h"
#include "SVGStyledElement.h"
-#include "SVGURIReference.h"
+#include "TransformState.h"
+
+#if ENABLE(FILTERS)
+#include "SVGResourceFilter.h"
+#endif
using namespace std;
namespace WebCore {
RenderSVGRoot::RenderSVGRoot(SVGStyledElement* node)
- : RenderContainer(node)
+ : RenderBox(node)
{
setReplaced(true);
}
@@ -86,69 +85,43 @@ void RenderSVGRoot::layout()
{
ASSERT(needsLayout());
- calcViewport();
-
// Arbitrary affine transforms are incompatible with LayoutState.
view()->disableLayoutState();
- IntRect oldBounds = m_absoluteBounds;
- IntRect oldOutlineBox;
- bool checkForRepaint = checkForRepaintDuringLayout() && selfNeedsLayout();
- if (checkForRepaint)
- oldOutlineBox = absoluteOutlineBounds();
+ LayoutRepainter repainter(*this, checkForRepaintDuringLayout() && selfNeedsLayout());
calcWidth();
calcHeight();
- m_absoluteBounds = absoluteClippedOverflowRect();
- SVGSVGElement* svg = static_cast<SVGSVGElement*>(element());
- m_width = static_cast<int>(m_width * svg->currentScale());
- m_height = static_cast<int>(m_height * svg->currentScale());
+ SVGSVGElement* svg = static_cast<SVGSVGElement*>(node());
+ setWidth(static_cast<int>(width() * svg->currentScale()));
+ setHeight(static_cast<int>(height() * svg->currentScale()));
+
+ calcViewport();
for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
if (selfNeedsLayout()) // either bounds or transform changed, force kids to relayout
- child->setNeedsLayout(true);
+ child->setNeedsLayout(true, false);
child->layoutIfNeeded();
ASSERT(!child->needsLayout());
}
- if (checkForRepaint)
- repaintAfterLayoutIfNeeded(oldBounds, oldOutlineBox);
+ repainter.repaintAfterLayout();
view()->enableLayoutState();
setNeedsLayout(false);
}
-void RenderSVGRoot::applyContentTransforms(PaintInfo& paintInfo, int parentX, int parentY)
+bool RenderSVGRoot::selfWillPaint() const
{
- // Translate from parent offsets (html renderers) to a relative transform (svg renderers)
- IntPoint origin;
- origin.move(parentX, parentY);
- origin.move(m_x, m_y);
- origin.move(borderLeft(), borderTop());
- origin.move(paddingLeft(), paddingTop());
-
- if (origin.x() || origin.y()) {
- paintInfo.context->concatCTM(TransformationMatrix().translate(origin.x(), origin.y()));
- paintInfo.rect.move(-origin.x(), -origin.y());
- }
-
- // Respect scroll offset caused by html parents
- TransformationMatrix ctm = RenderContainer::absoluteTransform();
- paintInfo.rect.move(static_cast<int>(ctm.e()), static_cast<int>(ctm.f()));
-
- SVGSVGElement* svg = static_cast<SVGSVGElement*>(element());
- paintInfo.context->concatCTM(TransformationMatrix().scale(svg->currentScale()));
-
- if (!viewport().isEmpty()) {
- if (style()->overflowX() != OVISIBLE)
- paintInfo.context->clip(enclosingIntRect(viewport())); // FIXME: Eventually we'll want float-precision clipping
-
- paintInfo.context->concatCTM(TransformationMatrix().translate(viewport().x(), viewport().y()));
- }
-
- paintInfo.context->concatCTM(TransformationMatrix().translate(svg->currentTranslate().x(), svg->currentTranslate().y()));
+#if ENABLE(FILTERS)
+ const SVGRenderStyle* svgStyle = style()->svgStyle();
+ SVGResourceFilter* filter = getFilterById(document(), svgStyle->filter());
+ if (filter)
+ return true;
+#endif
+ return false;
}
void RenderSVGRoot::paint(PaintInfo& paintInfo, int parentX, int parentY)
@@ -156,141 +129,131 @@ void RenderSVGRoot::paint(PaintInfo& paintInfo, int parentX, int parentY)
if (paintInfo.context->paintingDisabled())
return;
- calcViewport();
+ IntPoint parentOriginInContainer(parentX, parentY);
+ IntPoint borderBoxOriginInContainer = parentOriginInContainer + IntSize(x(), y());
+
+ if (hasBoxDecorations() && (paintInfo.phase == PaintPhaseForeground || paintInfo.phase == PaintPhaseSelection))
+ paintBoxDecorations(paintInfo, borderBoxOriginInContainer.x(), borderBoxOriginInContainer.y());
- SVGSVGElement* svg = static_cast<SVGSVGElement*>(element());
- // A value of zero disables rendering of the element.
- if (viewport().width() <= 0. || viewport().height() <= 0.)
+ // An empty viewport disables rendering. FIXME: Should we still render filters?
+ if (viewportSize().isEmpty())
return;
- // This should only exist for <svg> renderers
- if (hasBoxDecorations() && (paintInfo.phase == PaintPhaseForeground || paintInfo.phase == PaintPhaseSelection))
- paintBoxDecorations(paintInfo, m_x + parentX, m_y + parentY);
-
- if (!firstChild()) {
-#if ENABLE(SVG_FILTERS)
- // Spec: groups w/o children still may render filter content.
- const SVGRenderStyle* svgStyle = style()->svgStyle();
- SVGResourceFilter* filter = getFilterById(document(), svgStyle->filter());
- if (!filter)
-#endif
- return;
- }
+ // Don't paint if we don't have kids, except if we have filters we should paint those.
+ if (!firstChild() && !selfWillPaint())
+ return;
+ // Make a copy of the PaintInfo because applyTransformToPaintInfo will modify the damage rect.
RenderObject::PaintInfo childPaintInfo(paintInfo);
childPaintInfo.context->save();
-
- applyContentTransforms(childPaintInfo, parentX, parentY);
- SVGResourceFilter* filter = 0;
+ // SVG does not support independent x/y clipping
+ if (style()->overflowX() != OVISIBLE)
+ childPaintInfo.context->clip(overflowClipRect(borderBoxOriginInContainer.x(), borderBoxOriginInContainer.y()));
+
+ // Convert from container offsets (html renderers) to a relative transform (svg renderers).
+ // Transform from our paint container's coordinate system to our local coords.
+ applyTransformToPaintInfo(childPaintInfo, localToRepaintContainerTransform(parentOriginInContainer));
- FloatRect boundingBox = relativeBBox(true);
+ SVGResourceFilter* filter = 0;
+ FloatRect boundingBox = repaintRectInLocalCoordinates();
if (childPaintInfo.phase == PaintPhaseForeground)
- prepareToRenderSVGContent(this, childPaintInfo, boundingBox, filter);
+ prepareToRenderSVGContent(this, childPaintInfo, boundingBox, filter);
- childPaintInfo.context->concatCTM(svg->viewBoxToViewTransform(width(), height()));
- RenderContainer::paint(childPaintInfo, 0, 0);
+ RenderBox::paint(childPaintInfo, 0, 0);
if (childPaintInfo.phase == PaintPhaseForeground)
- finishRenderSVGContent(this, childPaintInfo, boundingBox, filter, paintInfo.context);
+ finishRenderSVGContent(this, childPaintInfo, filter, paintInfo.context);
childPaintInfo.context->restore();
-
- if ((childPaintInfo.phase == PaintPhaseOutline || childPaintInfo.phase == PaintPhaseSelfOutline) && style()->outlineWidth() && style()->visibility() == VISIBLE)
- paintOutline(childPaintInfo.context, m_absoluteBounds.x(), m_absoluteBounds.y(), m_absoluteBounds.width(), m_absoluteBounds.height(), style());
+
+ if ((paintInfo.phase == PaintPhaseOutline || paintInfo.phase == PaintPhaseSelfOutline) && style()->outlineWidth() && style()->visibility() == VISIBLE)
+ paintOutline(paintInfo.context, borderBoxOriginInContainer.x(), borderBoxOriginInContainer.y(), width(), height(), style());
}
-FloatRect RenderSVGRoot::viewport() const
+const FloatSize& RenderSVGRoot::viewportSize() const
{
- return m_viewport;
+ return m_viewportSize;
}
void RenderSVGRoot::calcViewport()
{
- SVGElement* svgelem = static_cast<SVGElement*>(element());
- if (svgelem->hasTagName(SVGNames::svgTag)) {
- SVGSVGElement* svg = static_cast<SVGSVGElement*>(element());
+ SVGSVGElement* svg = static_cast<SVGSVGElement*>(node());
- if (!selfNeedsLayout() && !svg->hasRelativeValues())
- return;
+ if (!selfNeedsLayout() && !svg->hasRelativeValues())
+ return;
- float w, h;
+ if (!svg->hasSetContainerSize()) {
+ // In the normal case of <svg> being stand-alone or in a CSSBoxModel object we use
+ // RenderBox::width()/height() (which pulls data from RenderStyle)
+ m_viewportSize = FloatSize(width(), height());
+ } else {
+ // In the SVGImage case grab the SVGLength values off of SVGSVGElement and use
+ // the special relativeWidthValue accessors which respect the specified containerSize
SVGLength width = svg->width();
- if (width.unitType() == LengthTypePercentage && svg->hasSetContainerSize())
- w = svg->relativeWidthValue();
- else
- w = width.value(svg);
-
SVGLength height = svg->height();
- if (height.unitType() == LengthTypePercentage && svg->hasSetContainerSize())
- h = svg->relativeHeightValue();
- else
- h = height.value(svg);
-
- m_viewport = FloatRect(0, 0, w, h);
+ float viewportWidth = (width.unitType() == LengthTypePercentage) ? svg->relativeWidthValue() : width.value(svg);
+ float viewportHeight = (height.unitType() == LengthTypePercentage) ? svg->relativeHeightValue() : height.value(svg);
+ m_viewportSize = FloatSize(viewportWidth, viewportHeight);
}
}
-IntRect RenderSVGRoot::absoluteClippedOverflowRect()
+// RenderBox methods will expect coordinates w/o any transforms in coordinates
+// relative to our borderBox origin. This method gives us exactly that.
+TransformationMatrix RenderSVGRoot::localToBorderBoxTransform() const
{
- IntRect repaintRect;
-
- for (RenderObject* current = firstChild(); current != 0; current = current->nextSibling())
- repaintRect.unite(current->absoluteClippedOverflowRect());
-
-#if ENABLE(SVG_FILTERS)
- // Filters can expand the bounding box
- SVGResourceFilter* filter = getFilterById(document(), style()->svgStyle()->filter());
- if (filter)
- repaintRect.unite(enclosingIntRect(filter->filterBBoxForItemBBox(repaintRect)));
-#endif
+ TransformationMatrix ctm;
+ IntSize borderAndPadding = borderOriginToContentBox();
+ ctm.translate(borderAndPadding.width(), borderAndPadding.height());
+ SVGSVGElement* svg = static_cast<SVGSVGElement*>(node());
+ ctm.scale(svg->currentScale());
+ ctm.translate(svg->currentTranslate().x(), svg->currentTranslate().y());
+ return svg->viewBoxToViewTransform(width(), height()) * ctm;
+}
- return repaintRect;
+IntSize RenderSVGRoot::parentOriginToBorderBox() const
+{
+ return IntSize(x(), y());
}
-void RenderSVGRoot::addFocusRingRects(GraphicsContext* graphicsContext, int, int)
+IntSize RenderSVGRoot::borderOriginToContentBox() const
{
- graphicsContext->addFocusRingRect(m_absoluteBounds);
+ return IntSize(borderLeft() + paddingLeft(), borderTop() + paddingTop());
}
-void RenderSVGRoot::absoluteRects(Vector<IntRect>& rects, int, int)
+TransformationMatrix RenderSVGRoot::localToRepaintContainerTransform(const IntPoint& parentOriginInContainer) const
{
- for (RenderObject* current = firstChild(); current != 0; current = current->nextSibling())
- current->absoluteRects(rects, 0, 0);
+ TransformationMatrix parentToContainer;
+ parentToContainer.translate(parentOriginInContainer.x(), parentOriginInContainer.y());
+ return localToParentTransform() * parentToContainer;
}
-void RenderSVGRoot::absoluteQuads(Vector<FloatQuad>& quads, bool)
+TransformationMatrix RenderSVGRoot::localToParentTransform() const
{
- for (RenderObject* current = firstChild(); current != 0; current = current->nextSibling())
- current->absoluteQuads(quads);
+ IntSize parentToBorderBoxOffset = parentOriginToBorderBox();
+
+ TransformationMatrix borderBoxOriginToParentOrigin;
+ borderBoxOriginToParentOrigin.translate(parentToBorderBoxOffset.width(), parentToBorderBoxOffset.height());
+
+ return localToBorderBoxTransform() * borderBoxOriginToParentOrigin;
}
+// FIXME: This method should be removed as soon as callers to RenderBox::absoluteTransform() can be removed.
TransformationMatrix RenderSVGRoot::absoluteTransform() const
{
- TransformationMatrix ctm = RenderContainer::absoluteTransform();
- ctm.translate(m_x, m_y);
- SVGSVGElement* svg = static_cast<SVGSVGElement*>(element());
- ctm.scale(svg->currentScale());
- ctm.translate(svg->currentTranslate().x(), svg->currentTranslate().y());
- ctm.translate(viewport().x(), viewport().y());
- return svg->viewBoxToViewTransform(width(), height()) * ctm;
+ // This would apply localTransform() twice if localTransform() were not the identity.
+ return localToParentTransform() * RenderBox::absoluteTransform();
}
-FloatRect RenderSVGRoot::relativeBBox(bool includeStroke) const
+FloatRect RenderSVGRoot::objectBoundingBox() const
{
- FloatRect rect;
-
- RenderObject* current = firstChild();
- for (; current != 0; current = current->nextSibling()) {
- FloatRect childBBox = current->relativeBBox(includeStroke);
- FloatRect mappedBBox = current->localTransform().mapRect(childBBox);
- // <svg> can have a viewBox contributing to the bbox
- if (current->isSVGContainer())
- mappedBBox = static_cast<RenderSVGContainer*>(current)->viewportTransform().mapRect(mappedBBox);
- rect.unite(mappedBBox);
- }
+ return computeContainerBoundingBox(this, false);
+}
- return rect;
+FloatRect RenderSVGRoot::repaintRectInLocalCoordinates() const
+{
+ // FIXME: This does not include the border but it should!
+ return computeContainerBoundingBox(this, true);
}
TransformationMatrix RenderSVGRoot::localTransform() const
@@ -298,48 +261,56 @@ TransformationMatrix RenderSVGRoot::localTransform() const
return TransformationMatrix();
}
+void RenderSVGRoot::computeRectForRepaint(RenderBoxModelObject* repaintContainer, IntRect& repaintRect, bool fixed)
+{
+ // Apply our local transforms (except for x/y translation) and call RenderBox's method to handle all the normal CSS Box model bits
+ repaintRect = localToBorderBoxTransform().mapRect(repaintRect);
+ RenderBox::computeRectForRepaint(repaintContainer, repaintRect, fixed);
+}
+
+void RenderSVGRoot::mapLocalToContainer(RenderBoxModelObject* repaintContainer, bool fixed , bool useTransforms, TransformState& transformState) const
+{
+ ASSERT(!fixed); // We should have no fixed content in the SVG rendering tree.
+ ASSERT(useTransforms); // mapping a point through SVG w/o respecting trasnforms is useless.
+
+ // Transform to our border box and let RenderBox transform the rest of the way.
+ transformState.applyTransform(localToBorderBoxTransform());
+ RenderBox::mapLocalToContainer(repaintContainer, fixed, useTransforms, transformState);
+}
+
bool RenderSVGRoot::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, int _x, int _y, int _tx, int _ty, HitTestAction hitTestAction)
{
- TransformationMatrix ctm = RenderContainer::absoluteTransform();
-
- int sx = (_tx - static_cast<int>(ctm.e())); // scroll offset
- int sy = (_ty - static_cast<int>(ctm.f())); // scroll offset
-
- if (!viewport().isEmpty()
- && style()->overflowX() == OHIDDEN
- && style()->overflowY() == OHIDDEN) {
- int tx = m_x - _tx + sx;
- int ty = m_y - _ty + sy;
-
- // Check if we need to do anything at all.
- IntRect overflowBox = overflowRect(false);
- overflowBox.move(tx, ty);
- ctm.translate(viewport().x(), viewport().y());
- double localX, localY;
- ctm.inverse().map(_x - _tx, _y - _ty, &localX, &localY);
- if (!overflowBox.contains((int)localX, (int)localY))
+ IntPoint pointInContainer(_x, _y);
+ IntSize containerToParentOffset(_tx, _ty);
+
+ IntPoint pointInParent = pointInContainer - containerToParentOffset;
+ IntPoint pointInBorderBox = pointInParent - parentOriginToBorderBox();
+
+ // Note: For now, we're ignoring hits to border and padding for <svg>
+
+ if (style()->overflowX() == OHIDDEN) {
+ // SVG doesn't support independent x/y overflow
+ ASSERT(style()->overflowY() == OHIDDEN);
+ IntPoint pointInContentBox = pointInBorderBox - borderOriginToContentBox();
+ if (!contentBoxRect().contains(pointInContentBox))
return false;
}
+ IntPoint localPoint = localToParentTransform().inverse().mapPoint(pointInParent);
+
for (RenderObject* child = lastChild(); child; child = child->previousSibling()) {
- if (child->nodeAtPoint(request, result, _x - sx, _y - sy, 0, 0, hitTestAction)) {
- updateHitTestResult(result, IntPoint(_x - _tx, _y - _ty));
+ if (child->nodeAtFloatPoint(request, result, localPoint, hitTestAction)) {
+ // FIXME: CSS/HTML assumes the local point is relative to the border box, right?
+ updateHitTestResult(result, pointInBorderBox);
return true;
}
}
-
- // Spec: Only graphical elements can be targeted by the mouse, period.
+
+ // Spec: Only graphical elements can be targeted by the mouse, so we don't check self here.
// 16.4: "If there are no graphics elements whose relevant graphics content is under the pointer (i.e., there is no target element), the event is not dispatched."
return false;
}
-void RenderSVGRoot::position(InlineBox* box)
-{
- RenderContainer::position(box);
- if (m_absoluteBounds.isEmpty())
- setNeedsLayout(true, false);
-}
-
}
#endif // ENABLE(SVG)
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderSVGRoot.h b/src/3rdparty/webkit/WebCore/rendering/RenderSVGRoot.h
index acac78b..50866d2 100644
--- a/src/3rdparty/webkit/WebCore/rendering/RenderSVGRoot.h
+++ b/src/3rdparty/webkit/WebCore/rendering/RenderSVGRoot.h
@@ -1,8 +1,7 @@
/*
Copyright (C) 2004, 2005, 2007 Nikolas Zimmermann <zimmermann@kde.org>
2004, 2005, 2007 Rob Buis <buis@kde.org>
-
- This file is part of the KDE project
+ Copyright (C) 2009 Google, Inc. 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
@@ -24,54 +23,66 @@
#define RenderSVGRoot_h
#if ENABLE(SVG)
-#include "RenderContainer.h"
+#include "RenderBox.h"
#include "FloatRect.h"
+#include "SVGRenderSupport.h"
namespace WebCore {
class SVGStyledElement;
class TransformationMatrix;
-class RenderSVGRoot : public RenderContainer {
+class RenderSVGRoot : public RenderBox, SVGRenderBase {
public:
RenderSVGRoot(SVGStyledElement*);
~RenderSVGRoot();
+ virtual RenderObjectChildList* virtualChildren() { return children(); }
+ virtual const RenderObjectChildList* virtualChildren() const { return children(); }
+ const RenderObjectChildList* children() const { return &m_children; }
+ RenderObjectChildList* children() { return &m_children; }
+
virtual bool isSVGRoot() const { return true; }
virtual const char* renderName() const { return "RenderSVGRoot"; }
virtual int lineHeight(bool b, bool isRootLineBox = false) const;
virtual int baselinePosition(bool b, bool isRootLineBox = false) const;
virtual void calcPrefWidths();
-
+
virtual void layout();
virtual void paint(PaintInfo&, int parentX, int parentY);
-
- virtual IntRect absoluteClippedOverflowRect();
- virtual void absoluteRects(Vector<IntRect>& rects, int tx, int ty);
- virtual void absoluteQuads(Vector<FloatQuad>&, bool topLevel = true);
- virtual void addFocusRingRects(GraphicsContext*, int tx, int ty);
- virtual TransformationMatrix absoluteTransform() const;
+ virtual TransformationMatrix localToParentTransform() const;
bool fillContains(const FloatPoint&) const;
bool strokeContains(const FloatPoint&) const;
- FloatRect relativeBBox(bool includeStroke = true) const;
-
+
+ virtual FloatRect objectBoundingBox() const;
+ virtual FloatRect repaintRectInLocalCoordinates() const;
+
+ // FIXME: Both of these overrides should be removed.
virtual TransformationMatrix localTransform() const;
-
- FloatRect viewport() const;
+ virtual TransformationMatrix absoluteTransform() const;
virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, int x, int y, int tx, int ty, HitTestAction);
- virtual void position(InlineBox*);
-
+ virtual void computeRectForRepaint(RenderBoxModelObject* repaintContainer, IntRect& repaintRect, bool fixed);
+
+ virtual void mapLocalToContainer(RenderBoxModelObject* repaintContainer, bool useTransforms, bool fixed, TransformState&) const;
+
private:
- void calcViewport();
- void applyContentTransforms(PaintInfo&, int parentX, int parentY);
+ void calcViewport();
+ const FloatSize& viewportSize() const;
+
+ bool selfWillPaint() const;
+
+ IntSize parentOriginToBorderBox() const;
+ IntSize borderOriginToContentBox() const;
+ TransformationMatrix localToRepaintContainerTransform(const IntPoint& parentOriginInContainer) const;
+ TransformationMatrix localToBorderBoxTransform() const;
- FloatRect m_viewport;
- IntRect m_absoluteBounds;
+ RenderObjectChildList m_children;
+ FloatSize m_viewportSize;
};
} // namespace WebCore
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderSVGTSpan.cpp b/src/3rdparty/webkit/WebCore/rendering/RenderSVGTSpan.cpp
index fd2d3dd..90ff36c 100644
--- a/src/3rdparty/webkit/WebCore/rendering/RenderSVGTSpan.cpp
+++ b/src/3rdparty/webkit/WebCore/rendering/RenderSVGTSpan.cpp
@@ -26,10 +26,6 @@
#if ENABLE(SVG)
#include "RenderSVGTSpan.h"
-#include "FloatRect.h"
-#include "SVGInlineTextBox.h"
-#include "SVGRootInlineBox.h"
-
namespace WebCore {
RenderSVGTSpan::RenderSVGTSpan(Node* n)
@@ -37,46 +33,6 @@ RenderSVGTSpan::RenderSVGTSpan(Node* n)
{
}
-void RenderSVGTSpan::absoluteRects(Vector<IntRect>& rects, int, int, bool)
-{
- InlineRunBox* firstBox = firstLineBox();
-
- SVGRootInlineBox* rootBox = firstBox ? static_cast<SVGInlineTextBox*>(firstBox)->svgRootInlineBox() : 0;
- RenderObject* object = rootBox ? rootBox->object() : 0;
-
- if (!object)
- return;
-
- int xRef = object->xPos() + xPos();
- int yRef = object->yPos() + yPos();
-
- for (InlineRunBox* curr = firstBox; curr; curr = curr->nextLineBox()) {
- FloatRect rect(xRef + curr->xPos(), yRef + curr->yPos(), curr->width(), curr->height());
- // FIXME: broken with CSS transforms
- rects.append(enclosingIntRect(absoluteTransform().mapRect(rect)));
- }
-}
-
-void RenderSVGTSpan::absoluteQuads(Vector<FloatQuad>& quads, bool)
-{
- InlineRunBox* firstBox = firstLineBox();
-
- SVGRootInlineBox* rootBox = firstBox ? static_cast<SVGInlineTextBox*>(firstBox)->svgRootInlineBox() : 0;
- RenderObject* object = rootBox ? rootBox->object() : 0;
-
- if (!object)
- return;
-
- int xRef = object->xPos() + xPos();
- int yRef = object->yPos() + yPos();
-
- for (InlineRunBox* curr = firstBox; curr; curr = curr->nextLineBox()) {
- FloatRect rect(xRef + curr->xPos(), yRef + curr->yPos(), curr->width(), curr->height());
- // FIXME: broken with CSS transforms
- quads.append(absoluteTransform().mapRect(rect));
- }
-}
-
}
#endif // ENABLE(SVG)
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderSVGTSpan.h b/src/3rdparty/webkit/WebCore/rendering/RenderSVGTSpan.h
index d34cd2f..652c5e3 100644
--- a/src/3rdparty/webkit/WebCore/rendering/RenderSVGTSpan.h
+++ b/src/3rdparty/webkit/WebCore/rendering/RenderSVGTSpan.h
@@ -1,8 +1,7 @@
/*
- * This file is part of the WebKit project.
- *
* Copyright (C) 2006 Oliver Hunt <ojh16@student.canterbury.ac.nz>
* (C) 2006 Apple Computer Inc.
+ * (C) 2009 Google Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -32,8 +31,12 @@ class RenderSVGTSpan : public RenderSVGInline {
public:
RenderSVGTSpan(Node*);
virtual const char* renderName() const { return "RenderSVGTSpan"; }
- virtual void absoluteRects(Vector<IntRect>& rects, int tx, int ty, bool topLevel = true);
- virtual void absoluteQuads(Vector<FloatQuad>&, bool topLevel = true);
+
+ // FIXME: These are incorrect, but have always behaved this way.
+ // These empty implementations prevent us from hitting RenderObject ASSERTS.
+ // tspan.getBBox() will be wrong, and repainting for tspans may not work correctly!
+ virtual FloatRect objectBoundingBox() const { return FloatRect(); }
+ virtual FloatRect repaintRectInLocalCoordinates() const { return FloatRect(); }
};
}
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderSVGText.cpp b/src/3rdparty/webkit/WebCore/rendering/RenderSVGText.cpp
index 1a1196b..9e9809d 100644
--- a/src/3rdparty/webkit/WebCore/rendering/RenderSVGText.cpp
+++ b/src/3rdparty/webkit/WebCore/rendering/RenderSVGText.cpp
@@ -30,16 +30,19 @@
#include "RenderSVGText.h"
#include "FloatConversion.h"
+#include "FloatQuad.h"
#include "GraphicsContext.h"
#include "PointerEventsHitRules.h"
+#include "RenderLayer.h"
#include "RenderSVGRoot.h"
-#include "SimpleFontData.h"
#include "SVGLengthList.h"
+#include "SVGRenderSupport.h"
#include "SVGResourceFilter.h"
#include "SVGRootInlineBox.h"
#include "SVGTextElement.h"
#include "SVGTransformList.h"
#include "SVGURIReference.h"
+#include "SimpleFontData.h"
namespace WebCore {
@@ -48,174 +51,145 @@ RenderSVGText::RenderSVGText(SVGTextElement* node)
{
}
-IntRect RenderSVGText::absoluteClippedOverflowRect()
+IntRect RenderSVGText::clippedOverflowRectForRepaint(RenderBoxModelObject* repaintContainer)
{
- FloatRect repaintRect = absoluteTransform().mapRect(relativeBBox(true));
-
-#if ENABLE(SVG_FILTERS)
- // Filters can expand the bounding box
- SVGResourceFilter* filter = getFilterById(document(), style()->svgStyle()->filter());
- if (filter)
- repaintRect.unite(filter->filterBBoxForItemBBox(repaintRect));
-#endif
-
- if (!repaintRect.isEmpty())
- repaintRect.inflate(1); // inflate 1 pixel for antialiasing
-
- return enclosingIntRect(repaintRect);
+ return SVGRenderBase::clippedOverflowRectForRepaint(this, repaintContainer);
}
-bool RenderSVGText::requiresLayer()
+void RenderSVGText::computeRectForRepaint(RenderBoxModelObject* repaintContainer, IntRect& repaintRect, bool fixed)
{
- return false;
+ SVGRenderBase::computeRectForRepaint(this, repaintContainer, repaintRect, fixed);
}
-bool RenderSVGText::calculateLocalTransform()
+void RenderSVGText::mapLocalToContainer(RenderBoxModelObject* repaintContainer, bool fixed , bool useTransforms, TransformState& transformState) const
{
- TransformationMatrix oldTransform = m_localTransform;
- m_localTransform = static_cast<SVGTextElement*>(element())->animatedLocalTransform();
- return (oldTransform != m_localTransform);
+ SVGRenderBase::mapLocalToContainer(this, repaintContainer, fixed, useTransforms, transformState);
}
void RenderSVGText::layout()
{
ASSERT(needsLayout());
-
+
// FIXME: This is a hack to avoid the RenderBlock::layout() partial repainting code which is not (yet) SVG aware
setNeedsLayout(true);
- IntRect oldBounds;
- IntRect oldOutlineBox;
- bool checkForRepaint = checkForRepaintDuringLayout();
- if (checkForRepaint) {
- oldBounds = m_absoluteBounds;
- oldOutlineBox = absoluteOutlineBounds();
- }
+ LayoutRepainter repainter(*this, checkForRepaintDuringLayout());
// Best guess for a relative starting point
- SVGTextElement* text = static_cast<SVGTextElement*>(element());
+ SVGTextElement* text = static_cast<SVGTextElement*>(node());
int xOffset = (int)(text->x()->getFirst().value(text));
int yOffset = (int)(text->y()->getFirst().value(text));
- setPos(xOffset, yOffset);
-
- calculateLocalTransform();
+ setLocation(xOffset, yOffset);
- RenderBlock::layout();
+ m_localTransform = text->animatedLocalTransform();
- m_absoluteBounds = absoluteClippedOverflowRect();
+ RenderBlock::layout();
- bool repainted = false;
- if (checkForRepaint)
- repainted = repaintAfterLayoutIfNeeded(oldBounds, oldOutlineBox);
-
+ repainter.repaintAfterLayout();
setNeedsLayout(false);
}
-InlineBox* RenderSVGText::createInlineBox(bool, bool, bool)
+RootInlineBox* RenderSVGText::createRootBox()
{
- ASSERT(!isInlineFlow());
- InlineFlowBox* flowBox = new (renderArena()) SVGRootInlineBox(this);
-
- if (!m_firstLineBox)
- m_firstLineBox = m_lastLineBox = flowBox;
- else {
- m_lastLineBox->setNextLineBox(flowBox);
- flowBox->setPreviousLineBox(m_lastLineBox);
- m_lastLineBox = flowBox;
- }
-
- return flowBox;
+ RootInlineBox* box = new (renderArena()) SVGRootInlineBox(this);
+ box->setIsSVG(true);
+ return box;
}
-bool RenderSVGText::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, int _x, int _y, int _tx, int _ty, HitTestAction hitTestAction)
+bool RenderSVGText::nodeAtFloatPoint(const HitTestRequest& request, HitTestResult& result, const FloatPoint& pointInParent, HitTestAction hitTestAction)
{
PointerEventsHitRules hitRules(PointerEventsHitRules::SVG_TEXT_HITTESTING, style()->pointerEvents());
bool isVisible = (style()->visibility() == VISIBLE);
if (isVisible || !hitRules.requireVisible) {
if ((hitRules.canHitStroke && (style()->svgStyle()->hasStroke() || !hitRules.requireStroke))
|| (hitRules.canHitFill && (style()->svgStyle()->hasFill() || !hitRules.requireFill))) {
- TransformationMatrix totalTransform = absoluteTransform();
- double localX, localY;
- totalTransform.inverse().map(_x, _y, &localX, &localY);
- FloatPoint hitPoint(_x, _y);
- return RenderBlock::nodeAtPoint(request, result, (int)localX, (int)localY, _tx, _ty, hitTestAction);
+ FloatPoint localPoint = localToParentTransform().inverse().mapPoint(pointInParent);
+ return RenderBlock::nodeAtPoint(request, result, (int)localPoint.x(), (int)localPoint.y(), 0, 0, hitTestAction);
}
}
return false;
}
-void RenderSVGText::absoluteRects(Vector<IntRect>& rects, int, int, bool)
+bool RenderSVGText::nodeAtPoint(const HitTestRequest&, HitTestResult&, int, int, int, int, HitTestAction)
+{
+ ASSERT_NOT_REACHED();
+ return false;
+}
+
+void RenderSVGText::absoluteRects(Vector<IntRect>& rects, int, int)
{
RenderSVGRoot* root = findSVGRootObject(parent());
if (!root)
return;
-
- FloatPoint absPos = localToAbsolute();
-
- TransformationMatrix htmlParentCtm = root->RenderContainer::absoluteTransform();
- // Don't use relativeBBox here, as it's unites the selection rects. Makes it hard
+ // Don't use objectBoundingBox here, as it's unites the selection rects. Makes it hard
// to spot errors, if there are any using WebInspector. Individually feed them into 'rects'.
for (InlineRunBox* runBox = firstLineBox(); runBox; runBox = runBox->nextLineBox()) {
ASSERT(runBox->isInlineFlowBox());
InlineFlowBox* flowBox = static_cast<InlineFlowBox*>(runBox);
for (InlineBox* box = flowBox->firstChild(); box; box = box->nextOnLine()) {
- FloatRect boxRect(box->xPos(), box->yPos(), box->width(), box->height());
- boxRect.move(narrowPrecisionToFloat(absPos.x() - htmlParentCtm.e()), narrowPrecisionToFloat(absPos.y() - htmlParentCtm.f()));
- // FIXME: broken with CSS transforms
- rects.append(enclosingIntRect(absoluteTransform().mapRect(boxRect)));
+ FloatRect boxRect(box->x(), box->y(), box->width(), box->height());
+ // FIXME: crawling up the parent chain to map each rect is very inefficient
+ // we should compute the absoluteTransform outside this loop first.
+ rects.append(enclosingIntRect(localToAbsoluteQuad(boxRect).boundingBox()));
}
}
}
-void RenderSVGText::absoluteQuads(Vector<FloatQuad>& quads, bool)
+void RenderSVGText::absoluteQuads(Vector<FloatQuad>& quads)
{
RenderSVGRoot* root = findSVGRootObject(parent());
if (!root)
return;
-
- FloatPoint absPos = localToAbsolute();
-
- TransformationMatrix htmlParentCtm = root->RenderContainer::absoluteTransform();
- // Don't use relativeBBox here, as it's unites the selection rects. Makes it hard
+ // Don't use objectBoundingBox here, as it's unites the selection rects. Makes it hard
// to spot errors, if there are any using WebInspector. Individually feed them into 'rects'.
for (InlineRunBox* runBox = firstLineBox(); runBox; runBox = runBox->nextLineBox()) {
ASSERT(runBox->isInlineFlowBox());
InlineFlowBox* flowBox = static_cast<InlineFlowBox*>(runBox);
for (InlineBox* box = flowBox->firstChild(); box; box = box->nextOnLine()) {
- FloatRect boxRect(box->xPos(), box->yPos(), box->width(), box->height());
- boxRect.move(narrowPrecisionToFloat(absPos.x() - htmlParentCtm.e()), narrowPrecisionToFloat(absPos.y() - htmlParentCtm.f()));
- // FIXME: broken with CSS transforms
- quads.append(absoluteTransform().mapRect(boxRect));
+ FloatRect boxRect(box->x(), box->y(), box->width(), box->height());
+ // FIXME: crawling up the parent chain to map each quad is very inefficient
+ // we should compute the absoluteTransform outside this loop first.
+ quads.append(localToAbsoluteQuad(boxRect));
}
}
}
void RenderSVGText::paint(PaintInfo& paintInfo, int, int)
{
- RenderObject::PaintInfo pi(paintInfo);
- pi.rect = absoluteTransform().inverse().mapRect(pi.rect);
+ PaintInfo pi(paintInfo);
+ pi.context->save();
+ applyTransformToPaintInfo(pi, localToParentTransform());
RenderBlock::paint(pi, 0, 0);
+ pi.context->restore();
}
-FloatRect RenderSVGText::relativeBBox(bool includeStroke) const
+FloatRect RenderSVGText::objectBoundingBox() const
{
- FloatRect repaintRect;
+ FloatRect boundingBox;
for (InlineRunBox* runBox = firstLineBox(); runBox; runBox = runBox->nextLineBox()) {
ASSERT(runBox->isInlineFlowBox());
InlineFlowBox* flowBox = static_cast<InlineFlowBox*>(runBox);
for (InlineBox* box = flowBox->firstChild(); box; box = box->nextOnLine())
- repaintRect.unite(FloatRect(box->xPos(), box->yPos(), box->width(), box->height()));
+ boundingBox.unite(FloatRect(box->x(), box->y(), box->width(), box->height()));
}
+ boundingBox.move(x(), y());
+ return boundingBox;
+}
+
+FloatRect RenderSVGText::repaintRectInLocalCoordinates() const
+{
+ FloatRect repaintRect = objectBoundingBox();
+
// SVG needs to include the strokeWidth(), not the textStrokeWidth().
- if (includeStroke && style()->svgStyle()->hasStroke()) {
+ if (style()->svgStyle()->hasStroke()) {
float strokeWidth = SVGRenderStyle::cssPrimitiveToLength(this, style()->svgStyle()->strokeWidth(), 0.0f);
#if ENABLE(SVG_FONTS)
@@ -231,7 +205,8 @@ FloatRect RenderSVGText::relativeBBox(bool includeStroke) const
repaintRect.inflate(strokeWidth);
}
- repaintRect.move(xPos(), yPos());
+ repaintRect.unite(filterBoundingBoxForRenderer(this));
+
return repaintRect;
}
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderSVGText.h b/src/3rdparty/webkit/WebCore/rendering/RenderSVGText.h
index d76d451..c1f1430 100644
--- a/src/3rdparty/webkit/WebCore/rendering/RenderSVGText.h
+++ b/src/3rdparty/webkit/WebCore/rendering/RenderSVGText.h
@@ -38,29 +38,36 @@ public:
RenderSVGText(SVGTextElement* node);
virtual const char* renderName() const { return "RenderSVGText"; }
-
+
virtual bool isSVGText() const { return true; }
-
- bool calculateLocalTransform();
- virtual TransformationMatrix localTransform() const { return m_localTransform; }
-
+
+ virtual TransformationMatrix localToParentTransform() const { return m_localTransform; }
+
virtual void paint(PaintInfo&, int tx, int ty);
virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, int x, int y, int tx, int ty, HitTestAction);
-
- virtual bool requiresLayer();
+ virtual bool nodeAtFloatPoint(const HitTestRequest&, HitTestResult&, const FloatPoint& pointInParent, HitTestAction);
+
+ virtual bool requiresLayer() const { return false; }
virtual void layout();
-
- virtual void absoluteRects(Vector<IntRect>&, int tx, int ty, bool topLevel = true);
- virtual void absoluteQuads(Vector<FloatQuad>&, bool topLevel = true);
- virtual IntRect absoluteClippedOverflowRect();
- virtual FloatRect relativeBBox(bool includeStroke = true) const;
-
- virtual InlineBox* createInlineBox(bool makePlaceHolderBox, bool isRootLineBox, bool isOnlyRun = false);
+ virtual void absoluteRects(Vector<IntRect>&, int tx, int ty);
+ virtual void absoluteQuads(Vector<FloatQuad>&);
+
+ virtual IntRect clippedOverflowRectForRepaint(RenderBoxModelObject* repaintContainer);
+ virtual void computeRectForRepaint(RenderBoxModelObject* repaintContainer, IntRect&, bool fixed = false);
+
+ virtual void mapLocalToContainer(RenderBoxModelObject* repaintContainer, bool useTransforms, bool fixed, TransformState&) const;
+
+ virtual FloatRect objectBoundingBox() const;
+ virtual FloatRect repaintRectInLocalCoordinates() const;
private:
+ // FIXME: This can be removed when localTransform() is removed from RenderObject
+ virtual TransformationMatrix localTransform() const { return m_localTransform; }
+
+ virtual RootInlineBox* createRootBox();
+
TransformationMatrix m_localTransform;
- IntRect m_absoluteBounds;
};
}
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderSVGTextPath.cpp b/src/3rdparty/webkit/WebCore/rendering/RenderSVGTextPath.cpp
index aa0209c..5d977f9 100644
--- a/src/3rdparty/webkit/WebCore/rendering/RenderSVGTextPath.cpp
+++ b/src/3rdparty/webkit/WebCore/rendering/RenderSVGTextPath.cpp
@@ -25,7 +25,8 @@
#if ENABLE(SVG)
#include "RenderSVGTextPath.h"
-#include "FloatRect.h"
+#include "FloatQuad.h"
+#include "RenderBlock.h"
#include "SVGInlineTextBox.h"
#include "SVGPathElement.h"
#include "SVGRootInlineBox.h"
@@ -44,7 +45,7 @@ RenderSVGTextPath::RenderSVGTextPath(Node* n)
Path RenderSVGTextPath::layoutPath() const
{
- SVGTextPathElement* textPathElement = static_cast<SVGTextPathElement*>(element());
+ SVGTextPathElement* textPathElement = static_cast<SVGTextPathElement*>(node());
String pathId = SVGURIReference::getTarget(textPathElement->href());
Element* targetElement = textPathElement->document()->getElementById(pathId);
if (!targetElement || !targetElement->hasTagName(SVGNames::pathTag))
@@ -64,57 +65,17 @@ Path RenderSVGTextPath::layoutPath() const
float RenderSVGTextPath::startOffset() const
{
- return static_cast<SVGTextPathElement*>(element())->startOffset().valueAsPercentage();
+ return static_cast<SVGTextPathElement*>(node())->startOffset().valueAsPercentage();
}
bool RenderSVGTextPath::exactAlignment() const
{
- return static_cast<SVGTextPathElement*>(element())->spacing() == SVG_TEXTPATH_SPACINGTYPE_EXACT;
+ return static_cast<SVGTextPathElement*>(node())->spacing() == SVG_TEXTPATH_SPACINGTYPE_EXACT;
}
bool RenderSVGTextPath::stretchMethod() const
{
- return static_cast<SVGTextPathElement*>(element())->method() == SVG_TEXTPATH_METHODTYPE_STRETCH;
-}
-
-void RenderSVGTextPath::absoluteRects(Vector<IntRect>& rects, int, int)
-{
- InlineRunBox* firstBox = firstLineBox();
-
- SVGRootInlineBox* rootBox = firstBox ? static_cast<SVGInlineTextBox*>(firstBox)->svgRootInlineBox() : 0;
- RenderObject* object = rootBox ? rootBox->object() : 0;
-
- if (!object)
- return;
-
- int xRef = object->xPos() + xPos();
- int yRef = object->yPos() + yPos();
-
- for (InlineRunBox* curr = firstBox; curr; curr = curr->nextLineBox()) {
- FloatRect rect(xRef + curr->xPos(), yRef + curr->yPos(), curr->width(), curr->height());
- // FIXME: broken with CSS transforms
- rects.append(enclosingIntRect(absoluteTransform().mapRect(rect)));
- }
-}
-
-void RenderSVGTextPath::absoluteQuads(Vector<FloatQuad>& quads, bool)
-{
- InlineRunBox* firstBox = firstLineBox();
-
- SVGRootInlineBox* rootBox = firstBox ? static_cast<SVGInlineTextBox*>(firstBox)->svgRootInlineBox() : 0;
- RenderObject* object = rootBox ? rootBox->object() : 0;
-
- if (!object)
- return;
-
- int xRef = object->xPos() + xPos();
- int yRef = object->yPos() + yPos();
-
- for (InlineRunBox* curr = firstBox; curr; curr = curr->nextLineBox()) {
- FloatRect rect(xRef + curr->xPos(), yRef + curr->yPos(), curr->width(), curr->height());
- // FIXME: broken with CSS transforms
- quads.append(absoluteTransform().mapRect(rect));
- }
+ return static_cast<SVGTextPathElement*>(node())->method() == SVG_TEXTPATH_METHODTYPE_STRETCH;
}
}
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderSVGTextPath.h b/src/3rdparty/webkit/WebCore/rendering/RenderSVGTextPath.h
index 4fd4cc3..efab659 100644
--- a/src/3rdparty/webkit/WebCore/rendering/RenderSVGTextPath.h
+++ b/src/3rdparty/webkit/WebCore/rendering/RenderSVGTextPath.h
@@ -38,8 +38,6 @@ namespace WebCore {
bool stretchMethod() const;
virtual const char* renderName() const { return "RenderSVGTextPath"; }
- virtual void absoluteRects(Vector<IntRect>& rects, int tx, int ty);
- virtual void absoluteQuads(Vector<FloatQuad>&, bool topLevel = true);
private:
float m_startOffset;
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderSVGTransformableContainer.cpp b/src/3rdparty/webkit/WebCore/rendering/RenderSVGTransformableContainer.cpp
index 17d64f3..2324eee 100644
--- a/src/3rdparty/webkit/WebCore/rendering/RenderSVGTransformableContainer.cpp
+++ b/src/3rdparty/webkit/WebCore/rendering/RenderSVGTransformableContainer.cpp
@@ -1,8 +1,7 @@
/*
Copyright (C) 2004, 2005 Nikolas Zimmermann <wildfox@kde.org>
- 2004, 2005, 2006 Rob Buis <buis@kde.org>
-
- This file is part of the KDE project
+ 2004, 2005, 2006 Rob Buis <buis@kde.org>
+ 2009 Google, Inc.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
@@ -35,11 +34,19 @@ RenderSVGTransformableContainer::RenderSVGTransformableContainer(SVGStyledTransf
{
}
-bool RenderSVGTransformableContainer::calculateLocalTransform()
+TransformationMatrix RenderSVGTransformableContainer::localToParentTransform() const
+{
+ return m_localTransform;
+}
+
+TransformationMatrix RenderSVGTransformableContainer::localTransform() const
+{
+ return m_localTransform;
+}
+
+void RenderSVGTransformableContainer::calculateLocalTransform()
{
- TransformationMatrix oldTransform = m_localTransform;
- m_localTransform = static_cast<SVGStyledTransformableElement*>(element())->animatedLocalTransform();
- return (m_localTransform != oldTransform);
+ m_localTransform = static_cast<SVGStyledTransformableElement*>(node())->animatedLocalTransform();
}
}
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderSVGTransformableContainer.h b/src/3rdparty/webkit/WebCore/rendering/RenderSVGTransformableContainer.h
index 897cc63..c929761 100644
--- a/src/3rdparty/webkit/WebCore/rendering/RenderSVGTransformableContainer.h
+++ b/src/3rdparty/webkit/WebCore/rendering/RenderSVGTransformableContainer.h
@@ -1,5 +1,6 @@
/*
- Copyright (C) 2007 Eric Seidel <eric@webkit.org
+ Copyright (C) 2007 Eric Seidel <eric@webkit.org>
+ 2009 Google, Inc.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
@@ -17,7 +18,6 @@
Boston, MA 02110-1301, USA.
*/
-
#ifndef RenderSVGTransformableContainer_h
#define RenderSVGTransformableContainer_h
@@ -30,8 +30,15 @@ namespace WebCore {
class RenderSVGTransformableContainer : public RenderSVGContainer {
public:
RenderSVGTransformableContainer(SVGStyledTransformableElement*);
-
- virtual bool calculateLocalTransform();
+
+ virtual TransformationMatrix localToParentTransform() const;
+
+ private:
+ virtual void calculateLocalTransform();
+ // FIXME: This can be made non-virtual once SVGRenderTreeAsText stops using localTransform()
+ virtual TransformationMatrix localTransform() const;
+
+ TransformationMatrix m_localTransform;
};
}
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderSVGViewportContainer.cpp b/src/3rdparty/webkit/WebCore/rendering/RenderSVGViewportContainer.cpp
index f6ac424..d208621 100644
--- a/src/3rdparty/webkit/WebCore/rendering/RenderSVGViewportContainer.cpp
+++ b/src/3rdparty/webkit/WebCore/rendering/RenderSVGViewportContainer.cpp
@@ -2,8 +2,7 @@
Copyright (C) 2004, 2005, 2007 Nikolas Zimmermann <zimmermann@kde.org>
2004, 2005, 2007 Rob Buis <buis@kde.org>
2007 Eric Seidel <eric@webkit.org>
-
- This file is part of the KDE project
+ 2009 Google, Inc.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
@@ -37,45 +36,12 @@ namespace WebCore {
RenderSVGViewportContainer::RenderSVGViewportContainer(SVGStyledElement* node)
: RenderSVGContainer(node)
{
- setReplaced(true);
}
RenderSVGViewportContainer::~RenderSVGViewportContainer()
{
}
-void RenderSVGViewportContainer::layout()
-{
- ASSERT(needsLayout());
-
- calcViewport();
-
- // Arbitrary affine transforms are incompatible with LayoutState.
- view()->disableLayoutState();
-
- IntRect oldBounds = m_absoluteBounds;
- IntRect oldOutlineBox;
- bool checkForRepaint = checkForRepaintDuringLayout() && selfNeedsLayout();
- if (checkForRepaint)
- oldOutlineBox = absoluteOutlineBounds();
-
- calcBounds();
-
- for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
- if (selfNeedsLayout())
- child->setNeedsLayout(true);
-
- child->layoutIfNeeded();
- ASSERT(!child->needsLayout());
- }
-
- if (checkForRepaint)
- repaintAfterLayoutIfNeeded(oldBounds, oldOutlineBox);
-
- view()->enableLayoutState();
- setNeedsLayout(false);
-}
-
void RenderSVGViewportContainer::paint(PaintInfo& paintInfo, int parentX, int parentY)
{
// A value of zero disables rendering of the element.
@@ -85,22 +51,10 @@ void RenderSVGViewportContainer::paint(PaintInfo& paintInfo, int parentX, int pa
RenderSVGContainer::paint(paintInfo, parentX, parentY);
}
-void RenderSVGViewportContainer::applyContentTransforms(PaintInfo& paintInfo)
-{
- if (!viewport().isEmpty()) {
- if (style()->overflowX() != OVISIBLE)
- paintInfo.context->clip(enclosingIntRect(viewport())); // FIXME: Eventually we'll want float-precision clipping
-
- paintInfo.context->concatCTM(TransformationMatrix().translate(viewport().x(), viewport().y()));
- }
-
- RenderSVGContainer::applyContentTransforms(paintInfo);
-}
-
-void RenderSVGViewportContainer::applyAdditionalTransforms(PaintInfo& paintInfo)
+void RenderSVGViewportContainer::applyViewportClip(PaintInfo& paintInfo)
{
- paintInfo.context->concatCTM(viewportTransform());
- RenderSVGContainer::applyAdditionalTransforms(paintInfo);
+ if (style()->overflowX() != OVISIBLE)
+ paintInfo.context->clip(enclosingIntRect(viewport())); // FIXME: Eventually we'll want float-precision clipping
}
FloatRect RenderSVGViewportContainer::viewport() const
@@ -110,9 +64,9 @@ FloatRect RenderSVGViewportContainer::viewport() const
void RenderSVGViewportContainer::calcViewport()
{
- SVGElement* svgelem = static_cast<SVGElement*>(element());
+ SVGElement* svgelem = static_cast<SVGElement*>(node());
if (svgelem->hasTagName(SVGNames::svgTag)) {
- SVGSVGElement* svg = static_cast<SVGSVGElement*>(element());
+ SVGSVGElement* svg = static_cast<SVGSVGElement*>(node());
if (!selfNeedsLayout() && !svg->hasRelativeValues())
return;
@@ -126,7 +80,7 @@ void RenderSVGViewportContainer::calcViewport()
if (!selfNeedsLayout())
return;
- SVGMarkerElement* svg = static_cast<SVGMarkerElement*>(element());
+ SVGMarkerElement* svg = static_cast<SVGMarkerElement*>(node());
float w = svg->markerWidth().value(svg);
float h = svg->markerHeight().value(svg);
m_viewport = FloatRect(0, 0, w, h);
@@ -135,60 +89,42 @@ void RenderSVGViewportContainer::calcViewport()
TransformationMatrix RenderSVGViewportContainer::viewportTransform() const
{
- if (element()->hasTagName(SVGNames::svgTag)) {
- SVGSVGElement* svg = static_cast<SVGSVGElement*>(element());
+ if (node()->hasTagName(SVGNames::svgTag)) {
+ SVGSVGElement* svg = static_cast<SVGSVGElement*>(node());
return svg->viewBoxToViewTransform(viewport().width(), viewport().height());
- } else if (element()->hasTagName(SVGNames::markerTag)) {
- SVGMarkerElement* marker = static_cast<SVGMarkerElement*>(element());
+ } else if (node()->hasTagName(SVGNames::markerTag)) {
+ SVGMarkerElement* marker = static_cast<SVGMarkerElement*>(node());
return marker->viewBoxToViewTransform(viewport().width(), viewport().height());
}
-
- return TransformationMatrix();
+
+ return TransformationMatrix();
}
+TransformationMatrix RenderSVGViewportContainer::localToParentTransform() const
+{
+ TransformationMatrix viewportTranslation;
+ viewportTranslation.translate(viewport().x(), viewport().y());
+ return viewportTransform() * viewportTranslation;
+ // If this class were ever given a localTransform(), then the above would read:
+ // return viewportTransform() * localTransform() * viewportTranslation;
+}
+
+// FIXME: This method should be removed as soon as callers to RenderBox::absoluteTransform() can be removed.
TransformationMatrix RenderSVGViewportContainer::absoluteTransform() const
{
- TransformationMatrix ctm = RenderObject::absoluteTransform();
- ctm.translate(viewport().x(), viewport().y());
- return viewportTransform() * ctm;
+ // This would apply localTransform() twice if localTransform() were not the identity.
+ return localToParentTransform() * RenderSVGContainer::absoluteTransform();
}
-bool RenderSVGViewportContainer::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, int _x, int _y, int _tx, int _ty, HitTestAction hitTestAction)
+bool RenderSVGViewportContainer::pointIsInsideViewportClip(const FloatPoint& pointInParent)
{
- if (!viewport().isEmpty()
- && style()->overflowX() == OHIDDEN
- && style()->overflowY() == OHIDDEN) {
- // Check if we need to do anything at all.
- IntRect overflowBox = overflowRect(false);
- overflowBox.move(_tx, _ty);
- TransformationMatrix ctm = RenderObject::absoluteTransform();
- ctm.translate(viewport().x(), viewport().y());
- double localX, localY;
- ctm.inverse().map(_x - _tx, _y - _ty, &localX, &localY);
- if (!overflowBox.contains((int)localX, (int)localY))
+ // Respect the viewport clip (which is in parent coords). SVG does not support separate x/y overflow rules.
+ if (style()->overflowX() == OHIDDEN) {
+ ASSERT(style()->overflowY() == OHIDDEN);
+ if (!viewport().contains(pointInParent))
return false;
}
-
- int sx = 0;
- int sy = 0;
-
- // Respect parent translation offset for non-outermost <svg> elements.
- // Outermost <svg> element is handled by RenderSVGRoot.
- if (element()->hasTagName(SVGNames::svgTag)) {
- sx = _tx;
- sy = _ty;
- }
-
- for (RenderObject* child = lastChild(); child; child = child->previousSibling()) {
- if (child->nodeAtPoint(request, result, _x - sx, _y - sy, _tx, _ty, hitTestAction)) {
- updateHitTestResult(result, IntPoint(_x - _tx, _y - _ty));
- return true;
- }
- }
-
- // Spec: Only graphical elements can be targeted by the mouse, period.
- // 16.4: "If there are no graphics elements whose relevant graphics content is under the pointer (i.e., there is no target element), the event is not dispatched."
- return false;
+ return true;
}
}
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderSVGViewportContainer.h b/src/3rdparty/webkit/WebCore/rendering/RenderSVGViewportContainer.h
index 2e4a49c..8657af4 100644
--- a/src/3rdparty/webkit/WebCore/rendering/RenderSVGViewportContainer.h
+++ b/src/3rdparty/webkit/WebCore/rendering/RenderSVGViewportContainer.h
@@ -1,8 +1,7 @@
/*
Copyright (C) 2004, 2005, 2007 Nikolas Zimmermann <zimmermann@kde.org>
2004, 2005, 2007 Rob Buis <buis@kde.org>
-
- This file is part of the KDE project
+ 2009 Google, Inc.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
@@ -29,6 +28,8 @@
namespace WebCore {
+// This is used for non-root <svg> elements and <marker> elements, neither of which are SVGTransformable
+// thus we inherit from RenderSVGContainer instead of RenderSVGTransformableContainer
class RenderSVGViewportContainer : public RenderSVGContainer {
public:
RenderSVGViewportContainer(SVGStyledElement*);
@@ -37,22 +38,24 @@ public:
virtual bool isSVGContainer() const { return true; }
virtual const char* renderName() const { return "RenderSVGViewportContainer"; }
- virtual void layout();
virtual void paint(PaintInfo&, int parentX, int parentY);
- virtual TransformationMatrix absoluteTransform() const;
- virtual TransformationMatrix viewportTransform() const;
+ virtual TransformationMatrix localToParentTransform() const;
- virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, int x, int y, int tx, int ty, HitTestAction);
+ // FIXME: This override should be removed once callers of RenderBox::absoluteTransform() can be removed.
+ virtual TransformationMatrix absoluteTransform() const;
FloatRect viewport() const;
+ // FIXME: This is only public for SVGResourceMarker::draw, likely the callsite should be changed.
+ TransformationMatrix viewportTransform() const;
+
private:
- void calcViewport();
+ virtual void calcViewport();
+
+ virtual void applyViewportClip(PaintInfo&);
+ virtual bool pointIsInsideViewportClip(const FloatPoint& pointInParent);
- virtual void applyContentTransforms(PaintInfo&);
- virtual void applyAdditionalTransforms(PaintInfo&);
-
FloatRect m_viewport;
};
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderScrollbar.cpp b/src/3rdparty/webkit/WebCore/rendering/RenderScrollbar.cpp
index b7045d6..db24a06 100644
--- a/src/3rdparty/webkit/WebCore/rendering/RenderScrollbar.cpp
+++ b/src/3rdparty/webkit/WebCore/rendering/RenderScrollbar.cpp
@@ -30,12 +30,12 @@
namespace WebCore {
-PassRefPtr<Scrollbar> RenderScrollbar::createCustomScrollbar(ScrollbarClient* client, ScrollbarOrientation orientation, RenderObject* renderer)
+PassRefPtr<Scrollbar> RenderScrollbar::createCustomScrollbar(ScrollbarClient* client, ScrollbarOrientation orientation, RenderBox* renderer)
{
return adoptRef(new RenderScrollbar(client, orientation, renderer));
}
-RenderScrollbar::RenderScrollbar(ScrollbarClient* client, ScrollbarOrientation orientation, RenderObject* renderer)
+RenderScrollbar::RenderScrollbar(ScrollbarClient* client, ScrollbarOrientation orientation, RenderBox* renderer)
: Scrollbar(client, orientation, RegularScrollbar, RenderScrollbarTheme::renderScrollbarTheme())
, m_owner(renderer)
{
@@ -50,7 +50,7 @@ void RenderScrollbar::setParent(ScrollView* parent)
{
Scrollbar::setParent(parent);
if (!parent) {
- // Destroy all of the scrollbar's RenderObjects.
+ // Destroy all of the scrollbar's RenderBoxes.
updateScrollbarParts(true);
}
}
@@ -117,7 +117,7 @@ ScrollbarPart RenderScrollbar::partForStyleResolve()
return s_styleResolvePart;
}
-PassRefPtr<RenderStyle> RenderScrollbar::getScrollbarPseudoStyle(ScrollbarPart partType, RenderStyle::PseudoId pseudoId)
+PassRefPtr<RenderStyle> RenderScrollbar::getScrollbarPseudoStyle(ScrollbarPart partType, PseudoId pseudoId)
{
s_styleResolvePart = partType;
s_styleResolveScrollbar = this;
@@ -158,23 +158,23 @@ void RenderScrollbar::updateScrollbarParts(bool destroy)
}
}
-static RenderStyle::PseudoId pseudoForScrollbarPart(ScrollbarPart part)
+static PseudoId pseudoForScrollbarPart(ScrollbarPart part)
{
switch (part) {
case BackButtonStartPart:
case ForwardButtonStartPart:
case BackButtonEndPart:
case ForwardButtonEndPart:
- return RenderStyle::SCROLLBAR_BUTTON;
+ return SCROLLBAR_BUTTON;
case BackTrackPart:
case ForwardTrackPart:
- return RenderStyle::SCROLLBAR_TRACK_PIECE;
+ return SCROLLBAR_TRACK_PIECE;
case ThumbPart:
- return RenderStyle::SCROLLBAR_THUMB;
+ return SCROLLBAR_THUMB;
case TrackBGPart:
- return RenderStyle::SCROLLBAR_TRACK;
+ return SCROLLBAR_TRACK;
default:
- return RenderStyle::SCROLLBAR;
+ return SCROLLBAR;
}
}
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderScrollbar.h b/src/3rdparty/webkit/WebCore/rendering/RenderScrollbar.h
index ad97001..245d750 100644
--- a/src/3rdparty/webkit/WebCore/rendering/RenderScrollbar.h
+++ b/src/3rdparty/webkit/WebCore/rendering/RenderScrollbar.h
@@ -26,23 +26,24 @@
#ifndef RenderScrollbar_h
#define RenderScrollbar_h
+#include "RenderStyleConstants.h"
#include "Scrollbar.h"
-#include "RenderStyle.h"
#include <wtf/HashMap.h>
namespace WebCore {
-class RenderObject;
+class RenderBox;
+class RenderStyle;
class RenderScrollbarPart;
class RenderStyle;
class RenderScrollbar : public Scrollbar {
protected:
- RenderScrollbar(ScrollbarClient*, ScrollbarOrientation, RenderObject*);
+ RenderScrollbar(ScrollbarClient*, ScrollbarOrientation, RenderBox*);
public:
friend class Scrollbar;
- static PassRefPtr<Scrollbar> createCustomScrollbar(ScrollbarClient*, ScrollbarOrientation, RenderObject*);
+ static PassRefPtr<Scrollbar> createCustomScrollbar(ScrollbarClient*, ScrollbarOrientation, RenderBox*);
virtual ~RenderScrollbar();
virtual void setParent(ScrollView*);
@@ -60,7 +61,7 @@ public:
virtual void styleChanged();
- RenderObject* owningRenderer() const { return m_owner; }
+ RenderBox* owningRenderer() const { return m_owner; }
void paintPart(GraphicsContext*, ScrollbarPart, const IntRect&);
@@ -69,12 +70,13 @@ public:
IntRect trackPieceRectWithMargins(ScrollbarPart, const IntRect&);
int minimumThumbLength();
+ virtual bool isCustomScrollbar() const { return true; }
private:
- PassRefPtr<RenderStyle> getScrollbarPseudoStyle(ScrollbarPart, RenderStyle::PseudoId);
+ PassRefPtr<RenderStyle> getScrollbarPseudoStyle(ScrollbarPart, PseudoId);
void updateScrollbarPart(ScrollbarPart, bool destroy = false);
- RenderObject* m_owner;
+ RenderBox* m_owner;
HashMap<unsigned, RenderScrollbarPart*> m_parts;
};
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderScrollbarPart.cpp b/src/3rdparty/webkit/WebCore/rendering/RenderScrollbarPart.cpp
index 3f69ba6..0f29aeb 100644
--- a/src/3rdparty/webkit/WebCore/rendering/RenderScrollbarPart.cpp
+++ b/src/3rdparty/webkit/WebCore/rendering/RenderScrollbarPart.cpp
@@ -45,14 +45,14 @@ RenderScrollbarPart::~RenderScrollbarPart()
void RenderScrollbarPart::layout()
{
- setPos(0, 0); // We don't worry about positioning ourselves. We're just determining our minimum width/height.
+ setLocation(IntPoint()); // We don't worry about positioning ourselves. We're just determining our minimum width/height.
if (m_scrollbar->orientation() == HorizontalScrollbar)
layoutHorizontalPart();
else
layoutVerticalPart();
- m_overflowWidth = max(m_width, m_overflowWidth);
- m_overflowHeight = max(m_height, m_overflowHeight);
+ m_overflowWidth = max(width(), m_overflowWidth);
+ m_overflowHeight = max(height(), m_overflowHeight);
setNeedsLayout(false);
}
@@ -60,11 +60,11 @@ void RenderScrollbarPart::layout()
void RenderScrollbarPart::layoutHorizontalPart()
{
if (m_part == ScrollbarBGPart) {
- m_width = m_scrollbar->width();
+ setWidth(m_scrollbar->width());
computeScrollbarHeight();
} else {
computeScrollbarWidth();
- m_height = m_scrollbar->height();
+ setHeight(m_scrollbar->height());
}
}
@@ -72,9 +72,9 @@ void RenderScrollbarPart::layoutVerticalPart()
{
if (m_part == ScrollbarBGPart) {
computeScrollbarWidth();
- m_height = m_scrollbar->height();
+ setHeight(m_scrollbar->height());
} else {
- m_width = m_scrollbar->width();
+ setWidth(m_scrollbar->width());
computeScrollbarHeight();
}
}
@@ -89,10 +89,10 @@ static int calcScrollbarThicknessUsing(const Length& l, int containingLength)
void RenderScrollbarPart::computeScrollbarWidth()
{
int visibleSize = m_scrollbar->owningRenderer()->width() - m_scrollbar->owningRenderer()->borderLeft() - m_scrollbar->owningRenderer()->borderRight();
- int width = calcScrollbarThicknessUsing(style()->width(), visibleSize);
+ int w = calcScrollbarThicknessUsing(style()->width(), visibleSize);
int minWidth = calcScrollbarThicknessUsing(style()->minWidth(), visibleSize);
- int maxWidth = style()->maxWidth().isUndefined() ? width : calcScrollbarThicknessUsing(style()->maxWidth(), visibleSize);
- m_width = max(minWidth, min(maxWidth, width));
+ int maxWidth = style()->maxWidth().isUndefined() ? w : calcScrollbarThicknessUsing(style()->maxWidth(), visibleSize);
+ setWidth(max(minWidth, min(maxWidth, w)));
// Buttons and track pieces can all have margins along the axis of the scrollbar.
m_marginLeft = style()->marginLeft().calcMinValue(visibleSize);
@@ -102,10 +102,10 @@ void RenderScrollbarPart::computeScrollbarWidth()
void RenderScrollbarPart::computeScrollbarHeight()
{
int visibleSize = m_scrollbar->owningRenderer()->height() - m_scrollbar->owningRenderer()->borderTop() - m_scrollbar->owningRenderer()->borderBottom();
- int height = calcScrollbarThicknessUsing(style()->height(), visibleSize);
+ int h = calcScrollbarThicknessUsing(style()->height(), visibleSize);
int minHeight = calcScrollbarThicknessUsing(style()->minHeight(), visibleSize);
- int maxHeight = style()->maxHeight().isUndefined() ? height : calcScrollbarThicknessUsing(style()->maxHeight(), visibleSize);
- m_height = max(minHeight, min(maxHeight, height));
+ int maxHeight = style()->maxHeight().isUndefined() ? h : calcScrollbarThicknessUsing(style()->maxHeight(), visibleSize);
+ setHeight(max(minHeight, min(maxHeight, h)));
// Buttons and track pieces can all have margins along the axis of the scrollbar.
m_marginTop = style()->marginTop().calcMinValue(visibleSize);
@@ -122,14 +122,20 @@ void RenderScrollbarPart::calcPrefWidths()
setPrefWidthsDirty(false);
}
-void RenderScrollbarPart::styleDidChange(RenderStyle::Diff diff, const RenderStyle* oldStyle)
+void RenderScrollbarPart::styleWillChange(StyleDifference diff, const RenderStyle* newStyle)
+{
+ RenderBlock::styleWillChange(diff, newStyle);
+ setInline(false);
+}
+
+void RenderScrollbarPart::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
{
RenderBlock::styleDidChange(diff, oldStyle);
setInline(false);
setPositioned(false);
setFloating(false);
setHasOverflowClip(false);
- if (oldStyle && m_scrollbar && m_part != NoPart && diff >= RenderStyle::Repaint)
+ if (oldStyle && m_scrollbar && m_part != NoPart && diff >= StyleDifferenceRepaint)
m_scrollbar->theme()->invalidatePart(m_scrollbar, m_part);
}
@@ -144,7 +150,7 @@ void RenderScrollbarPart::imageChanged(WrappedImagePtr image, const IntRect* rec
void RenderScrollbarPart::paintIntoRect(GraphicsContext* graphicsContext, int tx, int ty, const IntRect& rect)
{
// Make sure our dimensions match the rect.
- setPos(rect.x() - tx, rect.y() - ty);
+ setLocation(rect.x() - tx, rect.y() - ty);
setWidth(rect.width());
setHeight(rect.height());
setOverflowWidth(max(rect.width(), overflowWidth()));
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderScrollbarPart.h b/src/3rdparty/webkit/WebCore/rendering/RenderScrollbarPart.h
index 2010f97..114bbff 100644
--- a/src/3rdparty/webkit/WebCore/rendering/RenderScrollbarPart.h
+++ b/src/3rdparty/webkit/WebCore/rendering/RenderScrollbarPart.h
@@ -40,7 +40,7 @@ public:
virtual const char* renderName() const { return "RenderScrollbarPart"; }
- virtual bool requiresLayer() { return false; }
+ virtual bool requiresLayer() const { return false; }
virtual void layout();
virtual void calcPrefWidths();
@@ -48,7 +48,8 @@ public:
void paintIntoRect(GraphicsContext*, int tx, int ty, const IntRect&);
protected:
- virtual void styleDidChange(RenderStyle::Diff, const RenderStyle* oldStyle);
+ virtual void styleWillChange(StyleDifference diff, const RenderStyle* newStyle);
+ virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
virtual void imageChanged(WrappedImagePtr, const IntRect* = 0);
private:
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderSelectionInfo.h b/src/3rdparty/webkit/WebCore/rendering/RenderSelectionInfo.h
new file mode 100644
index 0000000..e7b7b78
--- /dev/null
+++ b/src/3rdparty/webkit/WebCore/rendering/RenderSelectionInfo.h
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2000 Lars Knoll (knoll@kde.org)
+ * (C) 2000 Antti Koivisto (koivisto@kde.org)
+ * (C) 2000 Dirk Mueller (mueller@kde.org)
+ * (C) 2004 Allan Sandfeld Jensen (kde@carewolf.com)
+ * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. 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
+ * 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 SelectionInfo_h
+#define SelectionInfo_h
+
+#include "IntRect.h"
+#include "RenderBox.h"
+
+namespace WebCore {
+
+class RenderSelectionInfoBase {
+public:
+ RenderSelectionInfoBase()
+ : m_object(0)
+ , m_repaintContainer(0)
+ , m_state(RenderObject::SelectionNone)
+ {
+ }
+
+ RenderSelectionInfoBase(RenderObject* o)
+ : m_object(o)
+ , m_repaintContainer(o->containerForRepaint())
+ , m_state(o->selectionState())
+ {
+ }
+
+ RenderObject* object() const { return m_object; }
+ RenderBoxModelObject* repaintContainer() const { return m_repaintContainer; }
+ RenderObject::SelectionState state() const { return m_state; }
+
+protected:
+ RenderObject* m_object;
+ RenderBoxModelObject* m_repaintContainer;
+ RenderObject::SelectionState m_state;
+};
+
+// This struct is used when the selection changes to cache the old and new state of the selection for each RenderObject.
+class RenderSelectionInfo : public RenderSelectionInfoBase {
+public:
+ RenderSelectionInfo(RenderObject* o, bool clipToVisibleContent)
+ : RenderSelectionInfoBase(o)
+ , m_rect(o->needsLayout() ? IntRect() : o->selectionRectForRepaint(m_repaintContainer, clipToVisibleContent))
+ {
+ }
+
+ void repaint()
+ {
+ m_object->repaintUsingContainer(m_repaintContainer, m_rect);
+ }
+
+ IntRect rect() const { return m_rect; }
+
+private:
+ IntRect m_rect; // relative to repaint container
+};
+
+
+// This struct is used when the selection changes to cache the old and new state of the selection for each RenderBlock.
+class RenderBlockSelectionInfo : public RenderSelectionInfoBase {
+public:
+ RenderBlockSelectionInfo(RenderBlock* b)
+ : RenderSelectionInfoBase(b)
+ , m_rects(b->needsLayout() ? GapRects() : block()->selectionGapRectsForRepaint(m_repaintContainer))
+ {
+ }
+
+ void repaint()
+ {
+ m_object->repaintUsingContainer(m_repaintContainer, m_rects);
+ }
+
+ RenderBlock* block() const { return toRenderBlock(m_object); }
+ GapRects rects() const { return m_rects; }
+
+private:
+ GapRects m_rects; // relative to repaint container
+};
+
+} // namespace WebCore
+
+
+#endif // SelectionInfo_h
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderSlider.cpp b/src/3rdparty/webkit/WebCore/rendering/RenderSlider.cpp
index 040fa31..610a060 100644
--- a/src/3rdparty/webkit/WebCore/rendering/RenderSlider.cpp
+++ b/src/3rdparty/webkit/WebCore/rendering/RenderSlider.cpp
@@ -1,6 +1,5 @@
-/**
- *
- * Copyright (C) 2006, 2007, 2008 Apple Computer, Inc.
+/*
+ * Copyright (C) 2006, 2007, 2008, 2009 Apple Inc. 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
@@ -31,8 +30,11 @@
#include "HTMLInputElement.h"
#include "HTMLDivElement.h"
#include "HTMLNames.h"
+#include "MediaControlElements.h"
#include "MouseEvent.h"
+#include "RenderLayer.h"
#include "RenderTheme.h"
+#include "RenderView.h"
#include <wtf/MathExtras.h>
using std::min;
@@ -41,44 +43,115 @@ namespace WebCore {
using namespace HTMLNames;
-const int defaultTrackLength = 129;
+static const int defaultTrackLength = 129;
+
+// FIXME: The SliderRange class and functions are entirely based on the DOM,
+// and could be put with HTMLInputElement (possibly with a new name) instead of here.
+struct SliderRange {
+ bool isIntegral;
+ double minimum;
+ double maximum;
+
+ explicit SliderRange(HTMLInputElement*);
+ double clampValue(double value);
+
+ // Map value into 0-1 range
+ double proportionFromValue(double value)
+ {
+ if (minimum == maximum)
+ return 0;
-class HTMLSliderThumbElement : public HTMLDivElement {
+ return (value - minimum) / (maximum - minimum);
+ }
+
+ // Map from 0-1 range to value
+ double valueFromProportion(double proportion)
+ {
+ return minimum + proportion * (maximum - minimum);
+ }
+
+ double valueFromElement(HTMLInputElement*, bool* wasClamped = 0);
+};
+
+SliderRange::SliderRange(HTMLInputElement* element)
+{
+ // FIXME: What's the right way to handle an integral range with non-integral minimum and maximum?
+ // Currently values are guaranteed to be integral but could be outside the range in that case.
+
+ isIntegral = !equalIgnoringCase(element->getAttribute(precisionAttr), "float");
+
+ // FIXME: This treats maximum strings that can't be parsed as 0, but perhaps 100 would be more appropriate.
+ const AtomicString& maxString = element->getAttribute(maxAttr);
+ maximum = maxString.isNull() ? 100.0 : maxString.toDouble();
+
+ // If the maximum is smaller, use it as the minimum.
+ minimum = min(element->getAttribute(minAttr).toDouble(), maximum);
+}
+
+double SliderRange::clampValue(double value)
+{
+ double clampedValue = max(minimum, min(value, maximum));
+ return isIntegral ? round(clampedValue) : clampedValue;
+}
+
+double SliderRange::valueFromElement(HTMLInputElement* element, bool* wasClamped)
+{
+ String valueString = element->value();
+ double oldValue = valueString.isNull() ? (minimum + maximum) / 2 : valueString.toDouble();
+ double newValue = clampValue(oldValue);
+
+ if (wasClamped)
+ *wasClamped = valueString.isNull() || newValue != oldValue;
+
+ return newValue;
+}
+
+// Returns a value between 0 and 1.
+// As with SliderRange, this could be on HTMLInputElement instead of here.
+static double sliderPosition(HTMLInputElement* element)
+{
+ SliderRange range(element);
+ return range.proportionFromValue(range.valueFromElement(element));
+}
+
+class SliderThumbElement : public HTMLDivElement {
public:
- HTMLSliderThumbElement(Document*, Node* shadowParent = 0);
-
+ SliderThumbElement(Document*, Node* shadowParent);
+
+ bool inDragMode() const { return m_inDragMode; }
+
virtual void defaultEventHandler(Event*);
+
+private:
virtual bool isShadowNode() const { return true; }
virtual Node* shadowParentNode() { return m_shadowParent; }
-
- bool inDragMode() const { return m_inDragMode; }
-private:
+
Node* m_shadowParent;
FloatPoint m_initialClickPoint; // initial click point in RenderSlider-local coordinates
int m_initialPosition;
bool m_inDragMode;
};
-HTMLSliderThumbElement::HTMLSliderThumbElement(Document* doc, Node* shadowParent)
- : HTMLDivElement(divTag, doc)
+SliderThumbElement::SliderThumbElement(Document* document, Node* shadowParent)
+ : HTMLDivElement(divTag, document)
, m_shadowParent(shadowParent)
- , m_initialClickPoint(IntPoint())
, m_initialPosition(0)
, m_inDragMode(false)
{
}
-void HTMLSliderThumbElement::defaultEventHandler(Event* event)
+void SliderThumbElement::defaultEventHandler(Event* event)
{
const AtomicString& eventType = event->type();
if (eventType == eventNames().mousedownEvent && event->isMouseEvent() && static_cast<MouseEvent*>(event)->button() == LeftButton) {
MouseEvent* mouseEvent = static_cast<MouseEvent*>(event);
RenderSlider* slider;
- if (document()->frame() && renderer() && renderer()->parent() &&
+ if (document()->frame() && renderer() &&
(slider = static_cast<RenderSlider*>(renderer()->parent())) &&
slider->mouseEventIsInThumb(mouseEvent)) {
+
// Cache the initial point where the mouse down occurred, in slider coordinates
- m_initialClickPoint = slider->absoluteToLocal(FloatPoint(mouseEvent->pageX(), mouseEvent->pageY()), false, true);
+ m_initialClickPoint = slider->absoluteToLocal(mouseEvent->absoluteLocation(), false, true);
// Cache the initial position of the thumb.
m_initialPosition = slider->currentPosition();
m_inDragMode = true;
@@ -101,16 +174,11 @@ void HTMLSliderThumbElement::defaultEventHandler(Event* event)
// Move the slider
MouseEvent* mouseEvent = static_cast<MouseEvent*>(event);
RenderSlider* slider = static_cast<RenderSlider*>(renderer()->parent());
- FloatPoint curPoint = slider->absoluteToLocal(FloatPoint(mouseEvent->pageX(), mouseEvent->pageY()), false, true);
- int newPosition = slider->positionForOffset(
- IntPoint(m_initialPosition + curPoint.x() - m_initialClickPoint.x()
- + (renderer()->width() / 2),
- m_initialPosition + curPoint.y() - m_initialClickPoint.y()
- + (renderer()->height() / 2)));
- if (slider->currentPosition() != newPosition) {
- slider->setCurrentPosition(newPosition);
- slider->valueChanged();
- }
+
+ FloatPoint curPoint = slider->absoluteToLocal(mouseEvent->absoluteLocation(), false, true);
+ IntPoint eventOffset(m_initialPosition + curPoint.x() - m_initialClickPoint.x() + renderBox()->width() / 2,
+ m_initialPosition + curPoint.y() - m_initialClickPoint.y() + renderBox()->height() / 2);
+ slider->setValueForPosition(slider->positionForOffset(eventOffset));
event->setDefaultHandled();
return;
}
@@ -121,7 +189,6 @@ void HTMLSliderThumbElement::defaultEventHandler(Event* event)
RenderSlider::RenderSlider(HTMLInputElement* element)
: RenderBlock(element)
- , m_thumb(0)
{
}
@@ -166,20 +233,20 @@ void RenderSlider::calcPrefWidths()
setPrefWidthsDirty(false);
}
-void RenderSlider::styleDidChange(RenderStyle::Diff diff, const RenderStyle* oldStyle)
+void RenderSlider::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
{
RenderBlock::styleDidChange(diff, oldStyle);
-
+
if (m_thumb)
- m_thumb->renderer()->setStyle(createThumbStyle(style(), m_thumb->renderer()->style()));
-
+ m_thumb->renderer()->setStyle(createThumbStyle(style()));
+
setReplaced(isInline());
}
-PassRefPtr<RenderStyle> RenderSlider::createThumbStyle(const RenderStyle* parentStyle, const RenderStyle* oldStyle)
+PassRefPtr<RenderStyle> RenderSlider::createThumbStyle(const RenderStyle* parentStyle)
{
RefPtr<RenderStyle> style;
- RenderStyle* pseudoStyle = getCachedPseudoStyle(RenderStyle::SLIDER_THUMB);
+ RenderStyle* pseudoStyle = getCachedPseudoStyle(SLIDER_THUMB);
if (pseudoStyle)
// We may be sharing style with another slider, but we must not share the thumb style.
style = RenderStyle::clone(pseudoStyle);
@@ -190,16 +257,11 @@ PassRefPtr<RenderStyle> RenderSlider::createThumbStyle(const RenderStyle* parent
style->inheritFrom(parentStyle);
style->setDisplay(BLOCK);
- style->setPosition(RelativePosition);
- if (oldStyle) {
- style->setLeft(oldStyle->left());
- style->setTop(oldStyle->top());
- }
if (parentStyle->appearance() == SliderVerticalPart)
- style->setAppearance(SliderThumbVerticalPart);
+ style->setAppearance(SliderThumbVerticalPart);
else if (parentStyle->appearance() == SliderHorizontalPart)
- style->setAppearance(SliderThumbHorizontalPart);
+ style->setAppearance(SliderThumbHorizontalPart);
else if (parentStyle->appearance() == MediaSliderPart)
style->setAppearance(MediaSliderThumbPart);
@@ -207,42 +269,97 @@ PassRefPtr<RenderStyle> RenderSlider::createThumbStyle(const RenderStyle* parent
}
void RenderSlider::layout()
-{
- bool relayoutChildren = false;
-
- if (m_thumb && m_thumb->renderer()) {
-
- int oldWidth = m_width;
- calcWidth();
- int oldHeight = m_height;
- calcHeight();
-
- if (oldWidth != m_width || oldHeight != m_height)
- relayoutChildren = true;
-
- // Allow the theme to set the size of the thumb
- if (m_thumb->renderer()->style()->hasAppearance())
- theme()->adjustSliderThumbSize(m_thumb->renderer());
+{
+ ASSERT(needsLayout());
+
+ RenderBox* thumb = m_thumb ? toRenderBox(m_thumb->renderer()) : 0;
+
+ IntSize baseSize(borderLeft() + paddingLeft() + paddingRight() + borderRight(),
+ borderTop() + paddingTop() + paddingBottom() + borderBottom());
+
+ if (thumb) {
+ // Allow the theme to set the size of the thumb.
+ if (thumb->style()->hasAppearance()) {
+ // FIXME: This should pass the style, not the renderer, to the theme.
+ theme()->adjustSliderThumbSize(thumb);
+ }
+
+ baseSize.expand(thumb->style()->width().calcMinValue(0), thumb->style()->height().calcMinValue(0));
+ }
+
+ LayoutRepainter repainter(*this, checkForRepaintDuringLayout());
+
+ IntSize oldSize = size();
+
+ setSize(baseSize);
+ calcWidth();
+ calcHeight();
+
+ IntRect overflowRect(IntPoint(), size());
+
+ if (thumb) {
+ if (oldSize != size())
+ thumb->setChildNeedsLayout(true, false);
+
+ LayoutStateMaintainer statePusher(view(), this, size());
+
+ IntRect oldThumbRect = thumb->frameRect();
+ thumb->layoutIfNeeded();
+
+ IntRect thumbRect;
+
+ thumbRect.setWidth(thumb->style()->width().calcMinValue(contentWidth()));
+ thumbRect.setHeight(thumb->style()->height().calcMinValue(contentHeight()));
+
+ double fraction = sliderPosition(static_cast<HTMLInputElement*>(node()));
+ IntRect contentRect = contentBoxRect();
if (style()->appearance() == SliderVerticalPart) {
- // FIXME: Handle percentage widths correctly. See http://bugs.webkit.org/show_bug.cgi?id=12104
- m_thumb->renderer()->style()->setLeft(Length(contentWidth() / 2 - m_thumb->renderer()->style()->width().value() / 2, Fixed));
+ thumbRect.setX(contentRect.x() + (contentRect.width() - thumbRect.width()) / 2);
+ thumbRect.setY(contentRect.y() + static_cast<int>(nextafter((contentRect.height() - thumbRect.height()) + 1, 0) * (1 - fraction)));
} else {
- // FIXME: Handle percentage heights correctly. See http://bugs.webkit.org/show_bug.cgi?id=12104
- m_thumb->renderer()->style()->setTop(Length(contentHeight() / 2 - m_thumb->renderer()->style()->height().value() / 2, Fixed));
+ thumbRect.setX(contentRect.x() + static_cast<int>(nextafter((contentRect.width() - thumbRect.width()) + 1, 0) * fraction));
+ thumbRect.setY(contentRect.y() + (contentRect.height() - thumbRect.height()) / 2);
}
- if (relayoutChildren)
- setPositionFromValue(true);
+ thumb->setFrameRect(thumbRect);
+
+ if (thumb->checkForRepaintDuringLayout())
+ thumb->repaintDuringLayoutIfMoved(oldThumbRect);
+
+ statePusher.pop();
+
+ IntRect thumbOverflowRect = thumb->overflowRect();
+ thumbOverflowRect.move(thumb->x(), thumb->y());
+ overflowRect.unite(thumbOverflowRect);
}
- RenderBlock::layoutBlock(relayoutChildren);
+ // FIXME: m_overflowWidth and m_overflowHeight should be renamed
+ // m_overflowRight and m_overflowBottom.
+ m_overflowLeft = overflowRect.x();
+ m_overflowTop = overflowRect.y();
+ m_overflowWidth = overflowRect.right();
+ m_overflowHeight = overflowRect.bottom();
+
+ repainter.repaintAfterLayout();
+
+ setNeedsLayout(false);
}
void RenderSlider::updateFromElement()
{
+ HTMLInputElement* element = static_cast<HTMLInputElement*>(node());
+
+ // Send the value back to the element if the range changes it.
+ SliderRange range(element);
+ bool clamped;
+ double value = range.valueFromElement(element, &clamped);
+ if (clamped)
+ element->setValueFromRenderer(String::number(value));
+
+ // Layout will take care of the thumb's size and position.
if (!m_thumb) {
- m_thumb = new HTMLSliderThumbElement(document(), node());
+ m_thumb = new SliderThumbElement(document(), node());
RefPtr<RenderStyle> thumbStyle = createThumbStyle(style());
m_thumb->setRenderer(m_thumb->createRenderer(renderArena(), thumbStyle.get()));
m_thumb->renderer()->setStyle(thumbStyle.release());
@@ -250,17 +367,23 @@ void RenderSlider::updateFromElement()
m_thumb->setInDocument(true);
addChild(m_thumb->renderer());
}
- setPositionFromValue();
- setNeedsLayout(true, false);
+ setNeedsLayout(true);
}
bool RenderSlider::mouseEventIsInThumb(MouseEvent* evt)
{
if (!m_thumb || !m_thumb->renderer())
return false;
-
- FloatPoint localPoint = m_thumb->renderer()->absoluteToLocal(FloatPoint(evt->pageX(), evt->pageY()), false, true);
- IntRect thumbBounds = m_thumb->renderer()->borderBox();
+
+#if ENABLE(VIDEO)
+ if (style()->appearance() == MediaSliderPart) {
+ MediaControlInputElement *sliderThumb = static_cast<MediaControlInputElement*>(m_thumb->renderer()->node());
+ return sliderThumb->hitTest(evt->absoluteLocation());
+ }
+#endif
+
+ FloatPoint localPoint = m_thumb->renderBox()->absoluteToLocal(evt->absoluteLocation(), false, true);
+ IntRect thumbBounds = m_thumb->renderBox()->borderBoxRect();
return thumbBounds.contains(roundedIntPoint(localPoint));
}
@@ -268,135 +391,79 @@ void RenderSlider::setValueForPosition(int position)
{
if (!m_thumb || !m_thumb->renderer())
return;
-
- const AtomicString& minStr = static_cast<HTMLInputElement*>(node())->getAttribute(minAttr);
- const AtomicString& maxStr = static_cast<HTMLInputElement*>(node())->getAttribute(maxAttr);
- const AtomicString& precision = static_cast<HTMLInputElement*>(node())->getAttribute(precisionAttr);
-
- double minVal = minStr.isNull() ? 0.0 : minStr.toDouble();
- double maxVal = maxStr.isNull() ? 100.0 : maxStr.toDouble();
- minVal = min(minVal, maxVal); // Make sure the range is sane.
-
- // Calculate the new value based on the position
- double factor = (double)position / (double)trackSize();
- if (style()->appearance() == SliderVerticalPart)
- factor = 1.0 - factor;
- double val = minVal + factor * (maxVal - minVal);
-
- val = max(minVal, min(val, maxVal)); // Make sure val is within min/max.
- // Force integer value if not float.
- if (!equalIgnoringCase(precision, "float"))
- val = lround(val);
-
- static_cast<HTMLInputElement*>(node())->setValueFromRenderer(String::number(val));
-
- if (position != currentPosition()) {
- setCurrentPosition(position);
- static_cast<HTMLInputElement*>(node())->onChange();
- }
-}
+ HTMLInputElement* element = static_cast<HTMLInputElement*>(node());
-double RenderSlider::setPositionFromValue(bool inLayout)
-{
- if (!m_thumb || !m_thumb->renderer())
- return 0;
-
- if (!inLayout)
- document()->updateLayout();
-
- String value = static_cast<HTMLInputElement*>(node())->value();
- const AtomicString& minStr = static_cast<HTMLInputElement*>(node())->getAttribute(minAttr);
- const AtomicString& maxStr = static_cast<HTMLInputElement*>(node())->getAttribute(maxAttr);
- const AtomicString& precision = static_cast<HTMLInputElement*>(node())->getAttribute(precisionAttr);
-
- double minVal = minStr.isNull() ? 0.0 : minStr.toDouble();
- double maxVal = maxStr.isNull() ? 100.0 : maxStr.toDouble();
- minVal = min(minVal, maxVal); // Make sure the range is sane.
-
- double oldVal = value.isNull() ? (maxVal + minVal)/2.0 : value.toDouble();
- double val = max(minVal, min(oldVal, maxVal)); // Make sure val is within min/max.
-
- // Force integer value if not float.
- if (!equalIgnoringCase(precision, "float"))
- val = lround(val);
-
- // Calculate the new position based on the value
- double factor = (val - minVal) / (maxVal - minVal);
+ // Calculate the new value based on the position, and send it to the element.
+ SliderRange range(element);
+ double fraction = static_cast<double>(position) / trackSize();
if (style()->appearance() == SliderVerticalPart)
- factor = 1.0 - factor;
+ fraction = 1 - fraction;
+ double value = range.clampValue(range.valueFromProportion(fraction));
+ element->setValueFromRenderer(String::number(value));
- setCurrentPosition((int)(factor * trackSize()));
-
- if (value.isNull() || val != oldVal)
- static_cast<HTMLInputElement*>(node())->setValueFromRenderer(String::number(val));
-
- return val;
+ // Also update the position if appropriate.
+ if (position != currentPosition()) {
+ setNeedsLayout(true);
+
+ // FIXME: It seems like this could send extra change events if the same value is set
+ // multiple times with no layout in between.
+ element->dispatchFormControlChangeEvent();
+ }
}
int RenderSlider::positionForOffset(const IntPoint& p)
{
if (!m_thumb || !m_thumb->renderer())
return 0;
-
+
int position;
if (style()->appearance() == SliderVerticalPart)
- position = p.y() - m_thumb->renderer()->height() / 2;
+ position = p.y() - m_thumb->renderBox()->height() / 2;
else
- position = p.x() - m_thumb->renderer()->width() / 2;
+ position = p.x() - m_thumb->renderBox()->width() / 2;
return max(0, min(position, trackSize()));
}
-void RenderSlider::valueChanged()
-{
- setValueForPosition(currentPosition());
- static_cast<HTMLInputElement*>(node())->onChange();
-}
-
int RenderSlider::currentPosition()
{
- if (!m_thumb || !m_thumb->renderer())
- return 0;
-
- if (style()->appearance() == SliderVerticalPart)
- return m_thumb->renderer()->style()->top().value();
- return m_thumb->renderer()->style()->left().value();
-}
-
-void RenderSlider::setCurrentPosition(int pos)
-{
- if (!m_thumb || !m_thumb->renderer())
- return;
+ ASSERT(m_thumb);
+ ASSERT(m_thumb->renderer());
if (style()->appearance() == SliderVerticalPart)
- m_thumb->renderer()->style()->setTop(Length(pos, Fixed));
- else
- m_thumb->renderer()->style()->setLeft(Length(pos, Fixed));
-
- m_thumb->renderer()->layer()->updateLayerPosition();
- repaint();
- m_thumb->renderer()->repaint();
+ return toRenderBox(m_thumb->renderer())->y() - contentBoxRect().y();
+ return toRenderBox(m_thumb->renderer())->x() - contentBoxRect().x();
}
int RenderSlider::trackSize()
{
- if (!m_thumb || !m_thumb->renderer())
- return 0;
+ ASSERT(m_thumb);
+ ASSERT(m_thumb->renderer());
if (style()->appearance() == SliderVerticalPart)
- return contentHeight() - m_thumb->renderer()->height();
- return contentWidth() - m_thumb->renderer()->width();
+ return contentHeight() - m_thumb->renderBox()->height();
+ return contentWidth() - m_thumb->renderBox()->width();
}
-void RenderSlider::forwardEvent(Event* evt)
+void RenderSlider::forwardEvent(Event* event)
{
- m_thumb->defaultEventHandler(evt);
+ if (event->isMouseEvent()) {
+ MouseEvent* mouseEvent = static_cast<MouseEvent*>(event);
+ if (event->type() == eventNames().mousedownEvent && mouseEvent->button() == LeftButton) {
+ if (!mouseEventIsInThumb(mouseEvent)) {
+ IntPoint eventOffset = roundedIntPoint(absoluteToLocal(mouseEvent->absoluteLocation(), false, true));
+ setValueForPosition(positionForOffset(eventOffset));
+ }
+ }
+ }
+
+ m_thumb->defaultEventHandler(event);
}
bool RenderSlider::inDragMode() const
{
- return m_thumb->inDragMode();
+ return m_thumb && m_thumb->inDragMode();
}
} // namespace WebCore
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderSlider.h b/src/3rdparty/webkit/WebCore/rendering/RenderSlider.h
index 2667672..f1eab9c 100644
--- a/src/3rdparty/webkit/WebCore/rendering/RenderSlider.h
+++ b/src/3rdparty/webkit/WebCore/rendering/RenderSlider.h
@@ -1,6 +1,5 @@
-/**
- *
- * Copyright (C) 2006 Apple Computer, Inc.
+/*
+ * Copyright (C) 2006, 2007, 2008, 2009 Apple Inc. 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
@@ -26,16 +25,19 @@
namespace WebCore {
- class HTMLDivElement;
class HTMLInputElement;
- class HTMLSliderThumbElement;
class MouseEvent;
+ class SliderThumbElement;
class RenderSlider : public RenderBlock {
public:
RenderSlider(HTMLInputElement*);
- ~RenderSlider();
+ virtual ~RenderSlider();
+
+ void forwardEvent(Event*);
+ bool inDragMode() const;
+ private:
virtual const char* renderName() const { return "RenderSlider"; }
virtual bool isSlider() const { return true; }
@@ -43,30 +45,25 @@ namespace WebCore {
virtual void calcPrefWidths();
virtual void layout();
virtual void updateFromElement();
-
+
bool mouseEventIsInThumb(MouseEvent*);
void setValueForPosition(int position);
- double setPositionFromValue(bool inLayout = false);
+ void setPositionFromValue();
int positionForOffset(const IntPoint&);
- void valueChanged();
-
int currentPosition();
- void setCurrentPosition(int pos);
-
- void forwardEvent(Event*);
- bool inDragMode() const;
- protected:
- virtual void styleDidChange(RenderStyle::Diff, const RenderStyle* oldStyle);
-
- private:
- PassRefPtr<RenderStyle> createThumbStyle(const RenderStyle* parentStyle, const RenderStyle* oldStyle = 0);
+ virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
+
+ PassRefPtr<RenderStyle> createThumbStyle(const RenderStyle* parentStyle);
+
int trackSize();
- RefPtr<HTMLSliderThumbElement> m_thumb;
-};
+ RefPtr<SliderThumbElement> m_thumb;
+
+ friend class SliderThumbElement;
+ };
} // namespace WebCore
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderTable.cpp b/src/3rdparty/webkit/WebCore/rendering/RenderTable.cpp
index 4561d57..48b0d1c 100644
--- a/src/3rdparty/webkit/WebCore/rendering/RenderTable.cpp
+++ b/src/3rdparty/webkit/WebCore/rendering/RenderTable.cpp
@@ -52,8 +52,6 @@ RenderTable::RenderTable(Node* node)
, m_firstBody(0)
, m_tableLayout(0)
, m_currentBorder(0)
- , m_frame(Void)
- , m_rules(None)
, m_hasColElements(false)
, m_needsSectionRecalc(0)
, m_hSpacing(0)
@@ -70,7 +68,7 @@ RenderTable::~RenderTable()
delete m_tableLayout;
}
-void RenderTable::styleDidChange(RenderStyle::Diff diff, const RenderStyle* oldStyle)
+void RenderTable::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
{
RenderBlock::styleDidChange(diff, oldStyle);
@@ -110,8 +108,7 @@ void RenderTable::addChild(RenderObject* child, RenderObject* beforeChild)
if (!beforeChild && isAfterContent(lastChild()))
beforeChild = lastChild();
- bool wrapInAnonymousSection = true;
- bool isTableElement = element() && element()->hasTagName(tableTag);
+ bool wrapInAnonymousSection = !child->isPositioned();
if (child->isRenderBlock() && child->style()->display() == TABLE_CAPTION) {
// First caption wins.
@@ -123,7 +120,7 @@ void RenderTable::addChild(RenderObject* child, RenderObject* beforeChild)
m_caption = 0;
}
if (!m_caption)
- m_caption = static_cast<RenderBlock*>(child);
+ m_caption = toRenderBlock(child);
wrapInAnonymousSection = false;
} else if (child->isTableCol()) {
m_hasColElements = true;
@@ -131,56 +128,44 @@ void RenderTable::addChild(RenderObject* child, RenderObject* beforeChild)
} else if (child->isTableSection()) {
switch (child->style()->display()) {
case TABLE_HEADER_GROUP:
- if (child->isTableSection()) {
- resetSectionPointerIfNotBefore(m_head, beforeChild);
- if (!m_head) {
- m_head = static_cast<RenderTableSection*>(child);
- } else {
- resetSectionPointerIfNotBefore(m_firstBody, beforeChild);
- if (!m_firstBody)
- m_firstBody = static_cast<RenderTableSection*>(child);
- }
+ resetSectionPointerIfNotBefore(m_head, beforeChild);
+ if (!m_head) {
+ m_head = static_cast<RenderTableSection*>(child);
+ } else {
+ resetSectionPointerIfNotBefore(m_firstBody, beforeChild);
+ if (!m_firstBody)
+ m_firstBody = static_cast<RenderTableSection*>(child);
}
wrapInAnonymousSection = false;
break;
case TABLE_FOOTER_GROUP:
- if (child->isTableSection()) {
- resetSectionPointerIfNotBefore(m_foot, beforeChild);
- if (!m_foot) {
- m_foot = static_cast<RenderTableSection*>(child);
- wrapInAnonymousSection = false;
- break;
- }
+ resetSectionPointerIfNotBefore(m_foot, beforeChild);
+ if (!m_foot) {
+ m_foot = static_cast<RenderTableSection*>(child);
+ wrapInAnonymousSection = false;
+ break;
}
// Fall through.
case TABLE_ROW_GROUP:
- if (child->isTableSection()) {
- resetSectionPointerIfNotBefore(m_firstBody, beforeChild);
- if (!m_firstBody)
- m_firstBody = static_cast<RenderTableSection*>(child);
- }
+ resetSectionPointerIfNotBefore(m_firstBody, beforeChild);
+ if (!m_firstBody)
+ m_firstBody = static_cast<RenderTableSection*>(child);
wrapInAnonymousSection = false;
break;
default:
ASSERT_NOT_REACHED();
}
- } else if (child->isTableCell() || child->isTableRow()) {
+ } else if (child->isTableCell() || child->isTableRow())
+ wrapInAnonymousSection = true;
+ else
wrapInAnonymousSection = true;
- } else {
- // Allow a form to just sit at the top level.
- wrapInAnonymousSection = !isTableElement || !child->element() || !(child->element()->hasTagName(formTag) && document()->isHTMLDocument());
-
- // FIXME: Allow the delete button container element to sit at the top level. This is needed until http://bugs.webkit.org/show_bug.cgi?id=11363 is fixed.
- if (wrapInAnonymousSection && child->element() && child->element()->isHTMLElement() && static_cast<HTMLElement*>(child->element())->id() == DeleteButtonController::containerElementIdentifier)
- wrapInAnonymousSection = false;
- }
if (!wrapInAnonymousSection) {
// If the next renderer is actually wrapped in an anonymous table section, we need to go up and find that.
while (beforeChild && !beforeChild->isTableSection() && !beforeChild->isTableCol() && beforeChild->style()->display() != TABLE_CAPTION)
beforeChild = beforeChild->parent();
- RenderContainer::addChild(child, beforeChild);
+ RenderBox::addChild(child, beforeChild);
return;
}
@@ -208,6 +193,12 @@ void RenderTable::addChild(RenderObject* child, RenderObject* beforeChild)
section->addChild(child);
}
+void RenderTable::removeChild(RenderObject* oldChild)
+{
+ RenderBox::removeChild(oldChild);
+ setNeedsSectionRecalc();
+}
+
void RenderTable::calcWidth()
{
if (isPositioned())
@@ -219,12 +210,12 @@ void RenderTable::calcWidth()
LengthType widthType = style()->width().type();
if (widthType > Relative && style()->width().isPositive()) {
// Percent or fixed table
- m_width = style()->width().calcMinValue(availableWidth);
- m_width = max(minPrefWidth(), m_width);
+ setWidth(style()->width().calcMinValue(availableWidth));
+ setWidth(max(minPrefWidth(), width()));
} else {
// An auto width table should shrink to fit within the line width if necessary in order to
// avoid overlapping floats.
- availableWidth = cb->lineWidth(m_y);
+ availableWidth = cb->lineWidth(y(), false);
// Subtract out any fixed margins from our available width for auto width tables.
int marginTotal = 0;
@@ -237,10 +228,10 @@ void RenderTable::calcWidth()
int availContentWidth = max(0, availableWidth - marginTotal);
// Ensure we aren't bigger than our max width or smaller than our min width.
- m_width = min(availContentWidth, maxPrefWidth());
+ setWidth(min(availContentWidth, maxPrefWidth()));
}
- m_width = max(m_width, minPrefWidth());
+ setWidth(max(width(), minPrefWidth()));
// Finally, with our true width determined, compute our margins for real.
m_marginRight = 0;
@@ -257,32 +248,25 @@ void RenderTable::layout()
recalcSectionsIfNeeded();
- IntRect oldBounds;
- IntRect oldOutlineBox;
- bool checkForRepaint = checkForRepaintDuringLayout();
- if (checkForRepaint) {
- oldBounds = absoluteClippedOverflowRect();
- oldOutlineBox = absoluteOutlineBounds();
- }
-
- LayoutStateMaintainer statePusher(view(), this, IntSize(m_x, m_y));
+ LayoutRepainter repainter(*this, checkForRepaintDuringLayout());
+ LayoutStateMaintainer statePusher(view(), this, IntSize(x(), y()));
- m_height = 0;
+ setHeight(0);
m_overflowHeight = 0;
m_overflowTop = 0;
initMaxMarginValues();
- int oldWidth = m_width;
+ int oldWidth = width();
calcWidth();
- if (m_caption && m_width != oldWidth)
+ if (m_caption && width() != oldWidth)
m_caption->setNeedsLayout(true, false);
// FIXME: The optimisation below doesn't work since the internal table
// layout could have changed. we need to add a flag to the table
// layout that tells us if something has changed in the min max
// calculations to do it correctly.
-// if ( oldWidth != m_width || columns.size() + 1 != columnPos.size() )
+// if ( oldWidth != width() || columns.size() + 1 != columnPos.size() )
m_tableLayout->layout();
setCellWidths();
@@ -294,18 +278,24 @@ void RenderTable::layout()
bool collapsing = collapseBorders();
for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
- // FIXME: What about a form that has a display value that makes it a table section?
- if (child->needsLayout() && !(child->element() && child->element()->hasTagName(formTag)))
- child->layout();
if (child->isTableSection()) {
+ child->layoutIfNeeded();
RenderTableSection* section = static_cast<RenderTableSection*>(child);
calculatedHeight += section->calcRowHeight();
if (collapsing)
section->recalcOuterBorder();
+ ASSERT(!section->needsLayout());
+ } else if (child->isTableCol()) {
+ child->layoutIfNeeded();
+ ASSERT(!child->needsLayout());
}
}
- m_overflowWidth = m_width + (collapsing ? outerBorderRight() - borderRight() : 0);
+ // Only lay out one caption, since it's the only one we're going to end up painting.
+ if (m_caption)
+ m_caption->layoutIfNeeded();
+
+ m_overflowWidth = width() + (collapsing ? outerBorderRight() - borderRight() : 0);
m_overflowLeft = collapsing ? borderLeft() - outerBorderLeft() : 0;
// If any table section moved vertically, we will just repaint everything from that
@@ -316,28 +306,28 @@ void RenderTable::layout()
// FIXME: Collapse caption margin.
if (m_caption && m_caption->style()->captionSide() != CAPBOTTOM) {
- IntRect captionRect(m_caption->xPos(), m_caption->yPos(), m_caption->width(), m_caption->height());
+ IntRect captionRect(m_caption->x(), m_caption->y(), m_caption->width(), m_caption->height());
- m_caption->setPos(m_caption->marginLeft(), m_height);
+ m_caption->setLocation(m_caption->marginLeft(), height());
if (!selfNeedsLayout() && m_caption->checkForRepaintDuringLayout())
m_caption->repaintDuringLayoutIfMoved(captionRect);
- m_height += m_caption->height() + m_caption->marginTop() + m_caption->marginBottom();
- m_overflowLeft = min(m_overflowLeft, m_caption->xPos() + m_caption->overflowLeft(false));
- m_overflowWidth = max(m_overflowWidth, m_caption->xPos() + m_caption->overflowWidth(false));
- m_overflowTop = min(m_overflowTop, m_caption->yPos() + m_caption->overflowTop(false));
- m_overflowHeight = max(m_overflowHeight, m_caption->yPos() + m_caption->overflowHeight(false));
+ setHeight(height() + m_caption->height() + m_caption->marginTop() + m_caption->marginBottom());
+ m_overflowLeft = min(m_overflowLeft, m_caption->x() + m_caption->overflowLeft(false));
+ m_overflowWidth = max(m_overflowWidth, m_caption->x() + m_caption->overflowWidth(false));
+ m_overflowTop = min(m_overflowTop, m_caption->y() + m_caption->overflowTop(false));
+ m_overflowHeight = max(m_overflowHeight, m_caption->y() + m_caption->overflowHeight(false));
- if (m_height != oldTableTop) {
+ if (height() != oldTableTop) {
sectionMoved = true;
- movedSectionTop = min(m_height, oldTableTop);
+ movedSectionTop = min(height(), oldTableTop);
}
}
int bpTop = borderTop() + (collapsing ? 0 : paddingTop());
int bpBottom = borderBottom() + (collapsing ? 0 : paddingBottom());
- m_height += bpTop;
+ setHeight(height() + bpTop);
if (!isPositioned())
calcHeight();
@@ -352,16 +342,15 @@ void RenderTable::layout()
th = max(0, th);
for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
- if (!child->isTableSection())
- continue;
- // FIXME: Distribute extra height between all table body sections instead of giving it all to the first one.
- static_cast<RenderTableSection*>(child)->layoutRows(child == m_firstBody ? max(0, th - calculatedHeight) : 0);
+ if (child->isTableSection())
+ // FIXME: Distribute extra height between all table body sections instead of giving it all to the first one.
+ static_cast<RenderTableSection*>(child)->layoutRows(child == m_firstBody ? max(0, th - calculatedHeight) : 0);
}
if (!m_firstBody && th > calculatedHeight && !style()->htmlHacks()) {
// Completely empty tables (with no sections or anything) should at least honor specified height
// in strict mode.
- m_height += th;
+ setHeight(height() + th);
}
int bl = borderLeft();
@@ -371,38 +360,38 @@ void RenderTable::layout()
// position the table sections
RenderTableSection* section = m_head ? m_head : (m_firstBody ? m_firstBody : m_foot);
while (section) {
- if (!sectionMoved && section->yPos() != m_height) {
+ if (!sectionMoved && section->y() != height()) {
sectionMoved = true;
- movedSectionTop = min(m_height, section->yPos()) + section->overflowTop(false);
+ movedSectionTop = min(height(), section->y()) + section->overflowTop(false);
}
- section->setPos(bl, m_height);
+ section->setLocation(bl, height());
- m_height += section->height();
- m_overflowLeft = min(m_overflowLeft, section->xPos() + section->overflowLeft(false));
- m_overflowWidth = max(m_overflowWidth, section->xPos() + section->overflowWidth(false));
- m_overflowTop = min(m_overflowTop, section->yPos() + section->overflowTop(false));
- m_overflowHeight = max(m_overflowHeight, section->yPos() + section->overflowHeight(false));
+ setHeight(height() + section->height());
+ m_overflowLeft = min(m_overflowLeft, section->x() + section->overflowLeft(false));
+ m_overflowWidth = max(m_overflowWidth, section->x() + section->overflowWidth(false));
+ m_overflowTop = min(m_overflowTop, section->y() + section->overflowTop(false));
+ m_overflowHeight = max(m_overflowHeight, section->y() + section->overflowHeight(false));
section = sectionBelow(section);
}
- m_height += bpBottom;
+ setHeight(height() + bpBottom);
if (m_caption && m_caption->style()->captionSide() == CAPBOTTOM) {
- IntRect captionRect(m_caption->xPos(), m_caption->yPos(), m_caption->width(), m_caption->height());
+ IntRect captionRect(m_caption->x(), m_caption->y(), m_caption->width(), m_caption->height());
- m_caption->setPos(m_caption->marginLeft(), m_height);
+ m_caption->setLocation(m_caption->marginLeft(), height());
if (!selfNeedsLayout() && m_caption->checkForRepaintDuringLayout())
m_caption->repaintDuringLayoutIfMoved(captionRect);
- m_height += m_caption->height() + m_caption->marginTop() + m_caption->marginBottom();
- m_overflowLeft = min(m_overflowLeft, m_caption->xPos() + m_caption->overflowLeft(false));
- m_overflowWidth = max(m_overflowWidth, m_caption->xPos() + m_caption->overflowWidth(false));
+ setHeight(height() + m_caption->height() + m_caption->marginTop() + m_caption->marginBottom());
+ m_overflowLeft = min(m_overflowLeft, m_caption->x() + m_caption->overflowLeft(false));
+ m_overflowWidth = max(m_overflowWidth, m_caption->x() + m_caption->overflowWidth(false));
}
if (isPositioned())
calcHeight();
- m_overflowHeight = max(m_overflowHeight, m_height);
+ m_overflowHeight = max(m_overflowHeight, height());
// table can be containing block of positioned elements.
// FIXME: Only pass true if width or height changed.
@@ -411,9 +400,9 @@ void RenderTable::layout()
if (!hasOverflowClip()) {
for (ShadowData* boxShadow = style()->boxShadow(); boxShadow; boxShadow = boxShadow->next) {
m_overflowLeft = min(m_overflowLeft, boxShadow->x - boxShadow->blur);
- m_overflowWidth = max(m_overflowWidth, m_width + boxShadow->x + boxShadow->blur);
+ m_overflowWidth = max(m_overflowWidth, width() + boxShadow->x + boxShadow->blur);
m_overflowTop = min(m_overflowTop, boxShadow->y - boxShadow->blur);
- m_overflowHeight = max(m_overflowHeight, m_height + boxShadow->y + boxShadow->blur);
+ m_overflowHeight = max(m_overflowHeight, height() + boxShadow->y + boxShadow->blur);
}
if (hasReflection()) {
@@ -427,10 +416,8 @@ void RenderTable::layout()
statePusher.pop();
- bool didFullRepaint = true;
+ bool didFullRepaint = repainter.repaintAfterLayout();
// Repaint with our new bounds if they are different from our old bounds.
- if (checkForRepaint)
- didFullRepaint = repaintAfterLayoutIfNeeded(oldBounds, oldOutlineBox);
if (!didFullRepaint && sectionMoved)
repaintRectangle(IntRect(m_overflowLeft, movedSectionTop, m_overflowWidth - m_overflowLeft, m_overflowHeight - movedSectionTop));
@@ -447,8 +434,8 @@ void RenderTable::setCellWidths()
void RenderTable::paint(PaintInfo& paintInfo, int tx, int ty)
{
- tx += xPos();
- ty += yPos();
+ tx += x();
+ ty += y();
PaintPhase paintPhase = paintInfo.phase;
@@ -458,6 +445,15 @@ void RenderTable::paint(PaintInfo& paintInfo, int tx, int ty)
if (tx + overflowLeft(false) >= paintInfo.rect.right() + os || tx + overflowWidth(false) <= paintInfo.rect.x() - os)
return;
+ bool pushedClip = pushContentsClip(paintInfo, tx, ty);
+ paintObject(paintInfo, tx, ty);
+ if (pushedClip)
+ popContentsClip(paintInfo, paintPhase, tx, ty);
+}
+
+void RenderTable::paintObject(PaintInfo& paintInfo, int tx, int ty)
+{
+ PaintPhase paintPhase = paintInfo.phase;
if ((paintPhase == PaintPhaseBlockBackground || paintPhase == PaintPhaseChildBlockBackground) && hasBoxDecorations() && style()->visibility() == VISIBLE)
paintBoxDecorations(paintInfo, tx, ty);
@@ -469,19 +465,20 @@ void RenderTable::paint(PaintInfo& paintInfo, int tx, int ty)
// We're done. We don't bother painting any children.
if (paintPhase == PaintPhaseBlockBackground)
return;
-
+
// We don't paint our own background, but we do let the kids paint their backgrounds.
if (paintPhase == PaintPhaseChildBlockBackgrounds)
paintPhase = PaintPhaseChildBlockBackground;
+
PaintInfo info(paintInfo);
info.phase = paintPhase;
info.paintingRoot = paintingRootForChildren(paintInfo);
for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
- if (!child->hasLayer() && (child->isTableSection() || child == m_caption))
+ if (child->isBox() && !toRenderBox(child)->hasSelfPaintingLayer() && (child->isTableSection() || child == m_caption))
child->paint(info, tx, ty);
}
-
+
if (collapseBorders() && paintPhase == PaintPhaseChildBlockBackground && style()->visibility() == VISIBLE) {
// Collect all the unique border styles that we want to paint in a sorted list. Once we
// have all the styles sorted, we then do individual passes, painting each style of border
@@ -517,16 +514,9 @@ void RenderTable::paintBoxDecorations(PaintInfo& paintInfo, int tx, int ty)
ty += captionHeight;
}
- int my = max(ty, paintInfo.rect.y());
- int mh;
- if (ty < paintInfo.rect.y())
- mh = max(0, h - (paintInfo.rect.y() - ty));
- else
- mh = min(paintInfo.rect.height(), h);
-
paintBoxShadow(paintInfo.context, tx, ty, w, h, style());
- paintFillLayers(paintInfo, style()->backgroundColor(), style()->backgroundLayers(), my, mh, tx, ty, w, h);
+ paintFillLayers(paintInfo, style()->backgroundColor(), style()->backgroundLayers(), tx, ty, w, h);
if (style()->hasBorder() && !collapseBorders())
paintBorder(paintInfo.context, tx, ty, w, h, style());
@@ -548,14 +538,7 @@ void RenderTable::paintMask(PaintInfo& paintInfo, int tx, int ty)
ty += captionHeight;
}
- int my = max(ty, paintInfo.rect.y());
- int mh;
- if (ty < paintInfo.rect.y())
- mh = max(0, h - (paintInfo.rect.y() - ty));
- else
- mh = min(paintInfo.rect.height(), h);
-
- paintMaskImages(paintInfo, my, mh, tx, ty, w, h);
+ paintMaskImages(paintInfo, tx, ty, w, h);
}
void RenderTable::calcPrefWidths()
@@ -664,7 +647,7 @@ void RenderTable::recalcSections() const
switch (child->style()->display()) {
case TABLE_CAPTION:
if (!m_caption && child->isRenderBlock()) {
- m_caption = static_cast<RenderBlock*>(child);
+ m_caption = toRenderBlock(child);
m_caption->setNeedsLayout(true);
}
break;
@@ -724,12 +707,6 @@ void RenderTable::recalcSections() const
m_needsSectionRecalc = false;
}
-RenderObject* RenderTable::removeChildNode(RenderObject* child, bool fullRemove)
-{
- setNeedsSectionRecalc();
- return RenderContainer::removeChildNode(child, fullRemove);
-}
-
int RenderTable::calcBorderLeft() const
{
if (collapseBorders()) {
@@ -1119,7 +1096,7 @@ void RenderTable::updateFirstLetter()
{
}
-int RenderTable::getBaselineOfFirstLineBox() const
+int RenderTable::firstLineBoxBaseline() const
{
RenderTableSection* firstNonEmptySection = m_head ? m_head : (m_firstBody ? m_firstBody : m_foot);
if (firstNonEmptySection && !firstNonEmptySection->numRows())
@@ -1128,12 +1105,12 @@ int RenderTable::getBaselineOfFirstLineBox() const
if (!firstNonEmptySection)
return -1;
- return firstNonEmptySection->yPos() + firstNonEmptySection->getBaselineOfFirstLineBox();
+ return firstNonEmptySection->y() + firstNonEmptySection->firstLineBoxBaseline();
}
-IntRect RenderTable::getOverflowClipRect(int tx, int ty)
+IntRect RenderTable::overflowClipRect(int tx, int ty)
{
- IntRect rect = RenderBlock::getOverflowClipRect(tx, ty);
+ IntRect rect = RenderBlock::overflowClipRect(tx, ty);
// If we have a caption, expand the clip to include the caption.
// FIXME: Technically this is wrong, but it's virtually impossible to fix this
@@ -1149,4 +1126,29 @@ IntRect RenderTable::getOverflowClipRect(int tx, int ty)
return rect;
}
+bool RenderTable::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, int xPos, int yPos, int tx, int ty, HitTestAction action)
+{
+ tx += x();
+ ty += y();
+
+ // Check kids first.
+ if (!hasOverflowClip() || overflowClipRect(tx, ty).contains(xPos, yPos)) {
+ for (RenderObject* child = lastChild(); child; child = child->previousSibling()) {
+ if (child->isBox() && !toRenderBox(child)->hasSelfPaintingLayer() && (child->isTableSection() || child == m_caption) &&
+ child->nodeAtPoint(request, result, xPos, yPos, tx, ty, action)) {
+ updateHitTestResult(result, IntPoint(xPos - tx, yPos - ty));
+ return true;
+ }
+ }
+ }
+
+ // Check our bounds next.
+ if (visibleToHitTesting() && (action == HitTestBlockBackground || action == HitTestChildBlockBackground) && IntRect(tx, ty, width(), height()).contains(xPos, yPos)) {
+ updateHitTestResult(result, IntPoint(xPos - tx, yPos - ty));
+ return true;
+ }
+
+ return false;
+}
+
}
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderTable.h b/src/3rdparty/webkit/WebCore/rendering/RenderTable.h
index 59cb00e..07e02b0 100644
--- a/src/3rdparty/webkit/WebCore/rendering/RenderTable.h
+++ b/src/3rdparty/webkit/WebCore/rendering/RenderTable.h
@@ -39,26 +39,6 @@ class TableLayout;
class RenderTable : public RenderBlock {
public:
- enum Rules {
- None = 0x00,
- RGroups = 0x01,
- CGroups = 0x02,
- Groups = 0x03,
- Rows = 0x05,
- Cols = 0x0a,
- All = 0x0f
- };
- enum Frame {
- Void = 0x00,
- Above = 0x01,
- Below = 0x02,
- Lhs = 0x04,
- Rhs = 0x08,
- Hsides = 0x03,
- Vsides = 0x0c,
- Box = 0x0f
- };
-
RenderTable(Node*);
~RenderTable();
@@ -79,8 +59,6 @@ public:
int borderTop() const;
int borderBottom() const;
- Rules getRules() const { return static_cast<Rules>(m_rules); }
-
const Color& bgColor() const { return style()->backgroundColor(); }
int outerBorderTop() const;
@@ -94,13 +72,17 @@ public:
// overrides
virtual void addChild(RenderObject* child, RenderObject* beforeChild = 0);
+ virtual void removeChild(RenderObject* oldChild);
+
virtual void paint(PaintInfo&, int tx, int ty);
+ virtual void paintObject(PaintInfo&, int tx, int ty);
virtual void paintBoxDecorations(PaintInfo&, int tx, int ty);
virtual void paintMask(PaintInfo& paintInfo, int tx, int ty);
virtual void layout();
virtual void calcPrefWidths();
-
- virtual int getBaselineOfFirstLineBox() const;
+ virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, int xPos, int yPos, int tx, int ty, HitTestAction);
+
+ virtual int firstLineBoxBaseline() const;
virtual RenderBlock* firstLineBlock() const;
virtual void updateFirstLetter();
@@ -169,8 +151,6 @@ public:
setNeedsLayout(true);
}
- virtual RenderObject* removeChildNode(RenderObject*, bool fullRemove = true);
-
RenderTableSection* sectionAbove(const RenderTableSection*, bool skipEmptySections = false) const;
RenderTableSection* sectionBelow(const RenderTableSection*, bool skipEmptySections = false) const;
@@ -183,7 +163,7 @@ public:
bool hasSections() const { return m_head || m_foot || m_firstBody; }
- virtual IntRect getOverflowClipRect(int tx, int ty);
+ virtual IntRect overflowClipRect(int tx, int ty);
void recalcSectionsIfNeeded() const
{
@@ -192,7 +172,7 @@ public:
}
protected:
- virtual void styleDidChange(RenderStyle::Diff, const RenderStyle* oldStyle);
+ virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
private:
void recalcSections() const;
@@ -209,9 +189,6 @@ private:
const CollapsedBorderValue* m_currentBorder;
- unsigned m_frame : 4; // Frame
- unsigned m_rules : 4; // Rules
-
mutable bool m_hasColElements : 1;
mutable bool m_needsSectionRecalc : 1;
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderTableCell.cpp b/src/3rdparty/webkit/WebCore/rendering/RenderTableCell.cpp
index 02e7729..9b02c9d 100644
--- a/src/3rdparty/webkit/WebCore/rendering/RenderTableCell.cpp
+++ b/src/3rdparty/webkit/WebCore/rendering/RenderTableCell.cpp
@@ -1,4 +1,4 @@
-/**
+/*
* Copyright (C) 1997 Martin Jones (mjones@kde.org)
* (C) 1997 Torben Weis (weis@kde.org)
* (C) 1998 Waldo Bastian (bastian@kde.org)
@@ -25,11 +25,13 @@
#include "config.h"
#include "RenderTableCell.h"
+#include "FloatQuad.h"
#include "GraphicsContext.h"
#include "HTMLNames.h"
#include "HTMLTableCellElement.h"
#include "RenderTableCol.h"
#include "RenderView.h"
+#include "TransformState.h"
using namespace std;
@@ -43,9 +45,8 @@ RenderTableCell::RenderTableCell(Node* node)
, m_column(-1)
, m_rowSpan(1)
, m_columnSpan(1)
- , m_topExtra(0)
- , m_bottomExtra(0)
- , m_widthChanged(false)
+ , m_intrinsicPaddingTop(0)
+ , m_intrinsicPaddingBottom(0)
, m_percentageHeight(0)
{
updateFromElement();
@@ -63,9 +64,9 @@ void RenderTableCell::destroy()
void RenderTableCell::updateFromElement()
{
- Node* node = element();
- if (node && (node->hasTagName(tdTag) || node->hasTagName(thTag))) {
- HTMLTableCellElement* tc = static_cast<HTMLTableCellElement*>(node);
+ Node* n = node();
+ if (n && (n->hasTagName(tdTag) || n->hasTagName(thTag))) {
+ HTMLTableCellElement* tc = static_cast<HTMLTableCellElement*>(n);
int oldRSpan = m_rowSpan;
int oldCSpan = m_columnSpan;
@@ -105,10 +106,10 @@ void RenderTableCell::calcPrefWidths()
table()->recalcSectionsIfNeeded();
RenderBlock::calcPrefWidths();
- if (element() && style()->autoWrap()) {
+ if (node() && style()->autoWrap()) {
// See if nowrap was set.
Length w = styleOrColWidth();
- String nowrap = static_cast<Element*>(element())->getAttribute(nowrapAttr);
+ String nowrap = static_cast<Element*>(node())->getAttribute(nowrapAttr);
if (!nowrap.isNull() && w.isFixed())
// Nowrap is set, but we didn't actually use it because of the
// fixed width set on the cell. Even so, it is a WinIE/Moz trait
@@ -123,28 +124,44 @@ void RenderTableCell::calcWidth()
{
}
-void RenderTableCell::setWidth(int width)
+void RenderTableCell::updateWidth(int w)
{
- if (width != m_width) {
- m_width = width;
- m_widthChanged = true;
+ if (w != width()) {
+ setWidth(w);
+ setCellWidthChanged(true);
}
}
void RenderTableCell::layout()
{
- layoutBlock(m_widthChanged);
- m_widthChanged = false;
+ layoutBlock(cellWidthChanged());
+ setCellWidthChanged(false);
}
-IntRect RenderTableCell::absoluteClippedOverflowRect()
+int RenderTableCell::paddingTop(bool includeIntrinsicPadding) const
+{
+ return RenderBlock::paddingTop() + (includeIntrinsicPadding ? intrinsicPaddingTop() : 0);
+}
+
+int RenderTableCell::paddingBottom(bool includeIntrinsicPadding) const
+{
+ return RenderBlock::paddingBottom() + (includeIntrinsicPadding ? intrinsicPaddingBottom() : 0);
+}
+
+void RenderTableCell::setOverrideSize(int size)
+{
+ clearIntrinsicPadding();
+ RenderBlock::setOverrideSize(size);
+}
+
+IntRect RenderTableCell::clippedOverflowRectForRepaint(RenderBoxModelObject* repaintContainer)
{
// If the table grid is dirty, we cannot get reliable information about adjoining cells,
// so we ignore outside borders. This should not be a problem because it means that
// the table is going to recalculate the grid, relayout and repaint its current rect, which
// includes any outside borders of this cell.
if (!table()->collapseBorders() || table()->needsSectionRecalc())
- return RenderBlock::absoluteClippedOverflowRect();
+ return RenderBlock::clippedOverflowRectForRepaint(repaintContainer);
bool rtl = table()->style()->direction() == RTL;
int outlineSize = style()->outlineSize();
@@ -152,13 +169,13 @@ IntRect RenderTableCell::absoluteClippedOverflowRect()
int right = max(borderHalfRight(true), outlineSize);
int top = max(borderHalfTop(true), outlineSize);
int bottom = max(borderHalfBottom(true), outlineSize);
- if (left && !rtl || right && rtl) {
+ if ((left && !rtl) || (right && rtl)) {
if (RenderTableCell* before = table()->cellBefore(this)) {
top = max(top, before->borderHalfTop(true));
bottom = max(bottom, before->borderHalfBottom(true));
}
}
- if (left && rtl || right && !rtl) {
+ if ((left && rtl) || (right && !rtl)) {
if (RenderTableCell* after = table()->cellAfter(this)) {
top = max(top, after->borderHalfTop(true));
bottom = max(bottom, after->borderHalfBottom(true));
@@ -177,69 +194,68 @@ IntRect RenderTableCell::absoluteClippedOverflowRect()
}
}
left = max(left, -overflowLeft(false));
- top = max(top, -overflowTop(false) - borderTopExtra());
- IntRect r(-left, -borderTopExtra() - top, left + max(width() + right, overflowWidth(false)), borderTopExtra() + top + max(height() + bottom + borderBottomExtra(), overflowHeight(false)));
+ top = max(top, -overflowTop(false));
+ IntRect r(-left, - top, left + max(width() + right, overflowWidth(false)), top + max(height() + bottom, overflowHeight(false)));
- if (RenderView* v = view())
+ if (RenderView* v = view()) {
+ // FIXME: layoutDelta needs to be applied in parts before/after transforms and
+ // repaint containers. https://bugs.webkit.org/show_bug.cgi?id=23308
r.move(v->layoutDelta());
-
- computeAbsoluteRepaintRect(r);
+ }
+ computeRectForRepaint(repaintContainer, r);
return r;
}
-void RenderTableCell::computeAbsoluteRepaintRect(IntRect& r, bool fixed)
+void RenderTableCell::computeRectForRepaint(RenderBoxModelObject* repaintContainer, IntRect& r, bool fixed)
{
- r.setY(r.y() + m_topExtra);
+ if (repaintContainer == this)
+ return;
+ r.setY(r.y());
RenderView* v = view();
- if ((!v || !v->layoutState()) && parent())
- r.move(-parent()->xPos(), -parent()->yPos()); // Rows are in the same coordinate space, so don't add their offset in.
- RenderBlock::computeAbsoluteRepaintRect(r, fixed);
+ if ((!v || !v->layoutStateEnabled()) && parent())
+ r.move(-parentBox()->x(), -parentBox()->y()); // Rows are in the same coordinate space, so don't add their offset in.
+ RenderBlock::computeRectForRepaint(repaintContainer, r, fixed);
}
-FloatPoint RenderTableCell::localToAbsolute(FloatPoint localPoint, bool fixed, bool useTransforms) const
+void RenderTableCell::mapLocalToContainer(RenderBoxModelObject* repaintContainer, bool fixed, bool useTransforms, TransformState& transformState) const
{
+ if (repaintContainer == this)
+ return;
+
RenderView* v = view();
- if ((!v || !v->layoutState()) && parent()) {
+ if ((!v || !v->layoutStateEnabled()) && parent()) {
// Rows are in the same coordinate space, so don't add their offset in.
- localPoint.move(-parent()->xPos(), -parent()->yPos());
+ // FIXME: this is wrong with transforms
+ transformState.move(-parentBox()->x(), -parentBox()->y());
}
- return RenderBlock::localToAbsolute(localPoint, fixed, useTransforms);
+ RenderBlock::mapLocalToContainer(repaintContainer, fixed, useTransforms, transformState);
}
-FloatPoint RenderTableCell::absoluteToLocal(FloatPoint containerPoint, bool fixed, bool useTransforms) const
+void RenderTableCell::mapAbsoluteToLocalPoint(bool fixed, bool useTransforms, TransformState& transformState) const
{
- FloatPoint localPoint = RenderBlock::absoluteToLocal(containerPoint, fixed, useTransforms);
+ RenderBlock::mapAbsoluteToLocalPoint(fixed, useTransforms, transformState);
if (parent()) {
// Rows are in the same coordinate space, so add their offset back in.
- localPoint.move(parent()->xPos(), parent()->yPos());
+ // FIXME: this is wrong with transforms
+ transformState.move(parentBox()->x(), parentBox()->y());
}
- return localPoint;
}
-FloatQuad RenderTableCell::localToAbsoluteQuad(const FloatQuad& localQuad, bool fixed) const
+int RenderTableCell::baselinePosition(bool firstLine, bool isRootLineBox) const
{
- FloatQuad quad = localQuad;
- if (parent()) {
- // Rows are in the same coordinate space, so don't add their offset in.
- quad.move(-parent()->xPos(), -parent()->yPos());
- }
- return RenderBlock::localToAbsoluteQuad(quad, fixed);
-}
+ if (isRootLineBox)
+ return RenderBox::baselinePosition(firstLine, isRootLineBox);
-int RenderTableCell::baselinePosition(bool /*firstLine*/, bool /*isRootLineBox*/) const
-{
// <http://www.w3.org/TR/2007/CR-CSS21-20070719/tables.html#height-layout>: The baseline of a cell is the baseline of
// the first in-flow line box in the cell, or the first in-flow table-row in the cell, whichever comes first. If there
// is no such line box or table-row, the baseline is the bottom of content edge of the cell box.
-
- int firstLineBaseline = getBaselineOfFirstLineBox();
+ int firstLineBaseline = firstLineBoxBaseline();
if (firstLineBaseline != -1)
return firstLineBaseline;
-
return paddingTop() + borderTop() + contentHeight();
}
-void RenderTableCell::styleWillChange(RenderStyle::Diff diff, const RenderStyle* newStyle)
+void RenderTableCell::styleWillChange(StyleDifference diff, const RenderStyle* newStyle)
{
if (parent() && section() && style() && style()->height() != newStyle->height())
section()->setNeedsCellRecalc();
@@ -249,17 +265,12 @@ void RenderTableCell::styleWillChange(RenderStyle::Diff diff, const RenderStyle*
RenderBlock::styleWillChange(diff, newStyle);
}
-void RenderTableCell::styleDidChange(RenderStyle::Diff diff, const RenderStyle* oldStyle)
+void RenderTableCell::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
{
RenderBlock::styleDidChange(diff, oldStyle);
setHasBoxDecorations(true);
}
-bool RenderTableCell::requiresLayer()
-{
- return isPositioned() || isTransparent() || hasOverflowClip() || hasTransform() || hasMask() || hasReflection();
-}
-
// The following rules apply for resolving conflicts and figuring out which border
// to use.
// (1) Borders with the 'border-style' of 'hidden' take precedence over all other conflicting
@@ -630,24 +641,17 @@ int RenderTableCell::borderHalfBottom(bool outer) const
void RenderTableCell::paint(PaintInfo& paintInfo, int tx, int ty)
{
- tx += m_x;
- ty += m_y;
-
- // check if we need to do anything at all...
- int os = 2 * maximalOutlineSize(paintInfo.phase);
-
if (paintInfo.phase == PaintPhaseCollapsedTableBorders && style()->visibility() == VISIBLE) {
- if (ty - table()->outerBorderTop() >= paintInfo.rect.bottom() + os ||
- ty + m_topExtra + m_height + m_bottomExtra + table()->outerBorderBottom() <= paintInfo.rect.y() - os)
- return;
- int w = width();
- int h = height() + borderTopExtra() + borderBottomExtra();
- paintCollapsedBorder(paintInfo.context, tx, ty, w, h);
- } else {
- if (ty + overflowTop(false) >= paintInfo.rect.bottom() + os || ty + m_topExtra + overflowHeight(false) + m_bottomExtra <= paintInfo.rect.y() - os)
- return;
- RenderBlock::paintObject(paintInfo, tx, ty + m_topExtra);
- }
+ tx += x();
+ ty += y();
+ int os = 2 * maximalOutlineSize(paintInfo.phase);
+ if (ty - table()->outerBorderTop() < paintInfo.rect.bottom() + os &&
+ ty + height() + table()->outerBorderBottom() > paintInfo.rect.y() - os)
+ paintCollapsedBorder(paintInfo.context, tx, ty, width(), height());
+ return;
+ }
+
+ RenderBlock::paint(paintInfo, tx, ty);
}
static EBorderStyle collapsedBorderStyle(EBorderStyle style)
@@ -661,7 +665,7 @@ static EBorderStyle collapsedBorderStyle(EBorderStyle style)
struct CollapsedBorder {
CollapsedBorderValue borderValue;
- RenderObject::BorderSide side;
+ BoxSide side;
bool shouldPaint;
int x1;
int y1;
@@ -677,7 +681,7 @@ public:
{
}
- void addBorder(const CollapsedBorderValue& borderValue, RenderObject::BorderSide borderSide, bool shouldPaint,
+ void addBorder(const CollapsedBorderValue& borderValue, BoxSide borderSide, bool shouldPaint,
int x1, int y1, int x2, int y2, EBorderStyle borderStyle)
{
if (borderValue.exists() && shouldPaint) {
@@ -789,8 +793,8 @@ void RenderTableCell::paintCollapsedBorder(GraphicsContext* graphicsContext, int
for (CollapsedBorder* border = borders.nextBorder(); border; border = borders.nextBorder()) {
if (border->borderValue == *table()->currentBorderStyle())
- drawBorder(graphicsContext, border->x1, border->y1, border->x2, border->y2, border->side,
- border->borderValue.color(), style()->color(), border->style, 0, 0);
+ drawLineForBoxSide(graphicsContext, border->x1, border->y1, border->x2, border->y2, border->side,
+ border->borderValue.color(), style()->color(), border->style, 0, 0);
}
}
@@ -807,17 +811,12 @@ void RenderTableCell::paintBackgroundsBehindCell(PaintInfo& paintInfo, int tx, i
return;
if (backgroundObject != this) {
- tx += m_x;
- ty += m_y + m_topExtra;
+ tx += x();
+ ty += y();
}
int w = width();
- int h = height() + borderTopExtra() + borderBottomExtra();
- ty -= borderTopExtra();
-
- int my = max(ty, paintInfo.rect.y());
- int end = min(paintInfo.rect.bottom(), ty + h);
- int mh = end - my;
+ int h = height();
Color c = backgroundObject->style()->backgroundColor();
const FillLayer* bgLayer = backgroundObject->style()->backgroundLayers();
@@ -832,7 +831,7 @@ void RenderTableCell::paintBackgroundsBehindCell(PaintInfo& paintInfo, int tx, i
paintInfo.context->save();
paintInfo.context->clip(clipRect);
}
- paintFillLayers(paintInfo, c, bgLayer, my, mh, tx, ty, w, h);
+ paintFillLayers(paintInfo, c, bgLayer, tx, ty, w, h);
if (shouldClip)
paintInfo.context->restore();
}
@@ -845,10 +844,10 @@ void RenderTableCell::paintBoxDecorations(PaintInfo& paintInfo, int tx, int ty)
return;
int w = width();
- int h = height() + borderTopExtra() + borderBottomExtra();
+ int h = height();
if (style()->boxShadow())
- paintBoxShadow(paintInfo.context, tx, ty - borderTopExtra(), w, h, style());
+ paintBoxShadow(paintInfo.context, tx, ty, w, h, style());
// Paint our cell background.
paintBackgroundsBehindCell(paintInfo, tx, ty, this);
@@ -856,7 +855,6 @@ void RenderTableCell::paintBoxDecorations(PaintInfo& paintInfo, int tx, int ty)
if (!style()->hasBorder() || tableElt->collapseBorders())
return;
- ty -= borderTopExtra();
paintBorder(paintInfo.context, tx, ty, w, h, style());
}
@@ -870,13 +868,9 @@ void RenderTableCell::paintMask(PaintInfo& paintInfo, int tx, int ty)
return;
int w = width();
- int h = height() + borderTopExtra() + borderBottomExtra();
+ int h = height();
- int my = max(ty, paintInfo.rect.y());
- int end = min(paintInfo.rect.bottom(), ty + h);
- int mh = end - my;
-
- paintMaskImages(paintInfo, my, mh, tx, ty, w, h);
+ paintMaskImages(paintInfo, tx, ty, w, h);
}
} // namespace WebCore
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderTableCell.h b/src/3rdparty/webkit/WebCore/rendering/RenderTableCell.h
index 20b7da7..a57b24b 100644
--- a/src/3rdparty/webkit/WebCore/rendering/RenderTableCell.h
+++ b/src/3rdparty/webkit/WebCore/rendering/RenderTableCell.h
@@ -59,13 +59,11 @@ public:
Length styleOrColWidth() const;
- virtual bool requiresLayer();
+ virtual bool requiresLayer() const { return isPositioned() || isTransparent() || hasOverflowClip() || hasTransform() || hasMask() || hasReflection(); }
virtual void calcPrefWidths();
virtual void calcWidth();
- virtual void setWidth(int);
-
- virtual bool expandsToEncloseOverhangingFloats() const { return true; }
+ void updateWidth(int);
int borderLeft() const;
int borderRight() const;
@@ -96,35 +94,38 @@ public:
void paintCollapsedBorder(GraphicsContext*, int x, int y, int w, int h);
void paintBackgroundsBehindCell(PaintInfo&, int tx, int ty, RenderObject* backgroundObject);
- // Lie about position to outside observers.
- virtual int yPos() const { return m_y + m_topExtra; }
-
- virtual IntRect absoluteClippedOverflowRect();
- virtual void computeAbsoluteRepaintRect(IntRect&, bool fixed = false);
- virtual FloatPoint localToAbsolute(FloatPoint localPoint = FloatPoint(), bool fixed = false, bool useTransforms = false) const;
- virtual FloatPoint absoluteToLocal(FloatPoint containerPoint, bool fixed = false, bool useTransforms = false) const;
- virtual FloatQuad localToAbsoluteQuad(const FloatQuad&, bool fixed = false) const;
+ virtual IntRect clippedOverflowRectForRepaint(RenderBoxModelObject* repaintContainer);
+ virtual void computeRectForRepaint(RenderBoxModelObject* repaintContainer, IntRect&, bool fixed = false);
virtual int baselinePosition(bool firstLine = false, bool isRootLineBox = false) const;
- void setCellTopExtra(int p) { m_topExtra = p; }
- void setCellBottomExtra(int p) { m_bottomExtra = p; }
+ void setIntrinsicPaddingTop(int p) { m_intrinsicPaddingTop = p; }
+ void setIntrinsicPaddingBottom(int p) { m_intrinsicPaddingBottom = p; }
+ void setIntrinsicPadding(int top, int bottom) { setIntrinsicPaddingTop(top); setIntrinsicPaddingBottom(bottom); }
+ void clearIntrinsicPadding() { setIntrinsicPadding(0, 0); }
+
+ int intrinsicPaddingTop() const { return m_intrinsicPaddingTop; }
+ int intrinsicPaddingBottom() const { return m_intrinsicPaddingBottom; }
- virtual int borderTopExtra() const { return m_topExtra; }
- virtual int borderBottomExtra() const { return m_bottomExtra; }
+ virtual int paddingTop(bool includeIntrinsicPadding = true) const;
+ virtual int paddingBottom(bool includeIntrinsicPadding = true) const;
+
+ virtual void setOverrideSize(int);
protected:
- virtual void styleWillChange(RenderStyle::Diff, const RenderStyle* newStyle);
- virtual void styleDidChange(RenderStyle::Diff, const RenderStyle* oldStyle);
+ virtual void styleWillChange(StyleDifference, const RenderStyle* newStyle);
+ virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
+
+ virtual void mapLocalToContainer(RenderBoxModelObject* repaintContainer, bool useTransforms, bool fixed, TransformState&) const;
+ virtual void mapAbsoluteToLocalPoint(bool fixed, bool useTransforms, TransformState&) const;
private:
int m_row;
int m_column;
int m_rowSpan;
int m_columnSpan;
- int m_topExtra : 31;
- int m_bottomExtra : 31;
- bool m_widthChanged : 1;
+ int m_intrinsicPaddingTop;
+ int m_intrinsicPaddingBottom;
int m_percentageHeight;
};
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderTableCol.cpp b/src/3rdparty/webkit/WebCore/rendering/RenderTableCol.cpp
index 5c2a049..d9a4172 100644
--- a/src/3rdparty/webkit/WebCore/rendering/RenderTableCol.cpp
+++ b/src/3rdparty/webkit/WebCore/rendering/RenderTableCol.cpp
@@ -37,7 +37,7 @@ namespace WebCore {
using namespace HTMLNames;
RenderTableCol::RenderTableCol(Node* node)
- : RenderContainer(node), m_span(1)
+ : RenderBox(node), m_span(1)
{
// init RenderObject attributes
setInline(true); // our object is not Inline
@@ -47,9 +47,9 @@ RenderTableCol::RenderTableCol(Node* node)
void RenderTableCol::updateFromElement()
{
int oldSpan = m_span;
- Node* node = element();
- if (node && (node->hasTagName(colTag) || node->hasTagName(colgroupTag))) {
- HTMLTableColElement* tc = static_cast<HTMLTableColElement*>(node);
+ Node* n = node();
+ if (n && (n->hasTagName(colTag) || n->hasTagName(colgroupTag))) {
+ HTMLTableColElement* tc = static_cast<HTMLTableColElement*>(n);
m_span = tc->span();
} else
m_span = !(style() && style()->display() == TABLE_COLUMN_GROUP);
@@ -69,16 +69,14 @@ bool RenderTableCol::canHaveChildren() const
return style()->display() == TABLE_COLUMN_GROUP;
}
-IntRect RenderTableCol::absoluteClippedOverflowRect()
+IntRect RenderTableCol::clippedOverflowRectForRepaint(RenderBoxModelObject* repaintContainer)
{
// For now, just repaint the whole table.
// FIXME: Find a better way to do this, e.g., need to repaint all the cells that we
// might have propagated a background color or borders into.
- RenderObject* table = parent();
- if (table && !table->isTable())
- table = table->parent();
- if (table && table->isTable())
- return table->absoluteClippedOverflowRect();
+ // FIXME: check for repaintContainer each time here?
+ if (RenderObject* parentTable = table())
+ return parentTable->clippedOverflowRectForRepaint(repaintContainer);
return IntRect();
}
@@ -89,4 +87,20 @@ void RenderTableCol::imageChanged(WrappedImagePtr, const IntRect*)
repaint();
}
+void RenderTableCol::calcPrefWidths()
+{
+ setPrefWidthsDirty(false);
+
+ for (RenderObject* child = firstChild(); child; child = child->nextSibling())
+ child->setPrefWidthsDirty(false);
+}
+
+RenderTable* RenderTableCol::table() const
+{
+ RenderObject* table = parent();
+ if (table && !table->isTable())
+ table = table->parent();
+ return table && table->isTable() ? static_cast<RenderTable*>(table) : 0;
+}
+
}
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderTableCol.h b/src/3rdparty/webkit/WebCore/rendering/RenderTableCol.h
index 6752bd8..6b17ec4 100644
--- a/src/3rdparty/webkit/WebCore/rendering/RenderTableCol.h
+++ b/src/3rdparty/webkit/WebCore/rendering/RenderTableCol.h
@@ -28,15 +28,21 @@
#ifndef RenderTableCol_h
#define RenderTableCol_h
-#include "RenderContainer.h"
+#include "RenderBox.h"
+#include "RenderTable.h"
namespace WebCore {
-class RenderTableCol : public RenderContainer
+class RenderTableCol : public RenderBox
{
public:
RenderTableCol(Node*);
+ virtual RenderObjectChildList* virtualChildren() { return children(); }
+ virtual const RenderObjectChildList* virtualChildren() const { return children(); }
+ const RenderObjectChildList* children() const { return &m_children; }
+ RenderObjectChildList* children() { return &m_children; }
+
virtual const char* renderName() const { return "RenderTableCol"; }
virtual bool isTableCol() const { return true; }
virtual int lineHeight(bool) const { return 0; }
@@ -44,15 +50,20 @@ public:
virtual bool isChildAllowed(RenderObject*, RenderStyle*) const;
virtual bool canHaveChildren() const;
- virtual bool requiresLayer() { return false; }
+ virtual bool requiresLayer() const { return false; }
- virtual IntRect absoluteClippedOverflowRect();
+ virtual IntRect clippedOverflowRectForRepaint(RenderBoxModelObject* repaintContainer);
virtual void imageChanged(WrappedImagePtr, const IntRect* = 0);
+ virtual void calcPrefWidths();
+
int span() const { return m_span; }
void setSpan(int s) { m_span = s; }
-
+
private:
+ RenderTable* table() const;
+
+ RenderObjectChildList m_children;
int m_span;
};
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderTableRow.cpp b/src/3rdparty/webkit/WebCore/rendering/RenderTableRow.cpp
index 21ba91a..33b2c39 100644
--- a/src/3rdparty/webkit/WebCore/rendering/RenderTableRow.cpp
+++ b/src/3rdparty/webkit/WebCore/rendering/RenderTableRow.cpp
@@ -33,16 +33,12 @@
#include "RenderTableCell.h"
#include "RenderView.h"
-#if ENABLE(WML)
-#include "WMLNames.h"
-#endif
-
namespace WebCore {
using namespace HTMLNames;
RenderTableRow::RenderTableRow(Node* node)
- : RenderContainer(node)
+ : RenderBox(node)
{
// init RenderObject attributes
setInline(false); // our object is not Inline
@@ -52,20 +48,20 @@ void RenderTableRow::destroy()
{
RenderTableSection* recalcSection = section();
- RenderContainer::destroy();
+ RenderBox::destroy();
if (recalcSection)
recalcSection->setNeedsCellRecalc();
}
-void RenderTableRow::styleWillChange(RenderStyle::Diff diff, const RenderStyle* newStyle)
+void RenderTableRow::styleWillChange(StyleDifference diff, const RenderStyle* newStyle)
{
if (section() && style() && style()->height() != newStyle->height())
section()->setNeedsCellRecalc();
ASSERT(newStyle->display() == TABLE_ROW);
- RenderContainer::styleWillChange(diff, newStyle);
+ RenderBox::styleWillChange(diff, newStyle);
}
void RenderTableRow::addChild(RenderObject* child, RenderObject* beforeChild)
@@ -74,19 +70,7 @@ void RenderTableRow::addChild(RenderObject* child, RenderObject* beforeChild)
if (!beforeChild && isAfterContent(lastChild()))
beforeChild = lastChild();
- bool isTableRow = element() && element()->hasTagName(trTag);
-
-#if ENABLE(WML)
- if (!isTableRow && element() && element()->isWMLElement())
- isTableRow = element()->hasTagName(WMLNames::trTag);
-#endif
-
if (!child->isTableCell()) {
- if (isTableRow && child->element() && child->element()->hasTagName(formTag) && document()->isHTMLDocument()) {
- RenderContainer::addChild(child, beforeChild);
- return;
- }
-
RenderObject* last = beforeChild;
if (!last)
last = lastChild();
@@ -121,8 +105,8 @@ void RenderTableRow::addChild(RenderObject* child, RenderObject* beforeChild)
if (parent())
section()->addCell(cell, this);
- ASSERT(!beforeChild || beforeChild->isTableCell() || isTableRow && beforeChild->element() && beforeChild->element()->hasTagName(formTag) && document()->isHTMLDocument());
- RenderContainer::addChild(cell, beforeChild);
+ ASSERT(!beforeChild || beforeChild->isTableCell());
+ RenderBox::addChild(cell, beforeChild);
if (beforeChild || nextSibling())
section()->setNeedsCellRecalc();
@@ -148,7 +132,7 @@ void RenderTableRow::layout()
// We only ever need to repaint if our cells didn't, which menas that they didn't need
// layout, so we know that our bounds didn't change. This code is just making up for
// the fact that we did not repaint in setStyle() because we had a layout hint.
- // We cannot call repaint() because our absoluteClippedOverflowRect() is taken from the
+ // We cannot call repaint() because our clippedOverflowRectForRepaint() is taken from the
// parent table, and being mid-layout, that is invalid. Instead, we repaint our cells.
if (selfNeedsLayout() && checkForRepaintDuringLayout()) {
for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
@@ -161,13 +145,14 @@ void RenderTableRow::layout()
setNeedsLayout(false);
}
-IntRect RenderTableRow::absoluteClippedOverflowRect()
+IntRect RenderTableRow::clippedOverflowRectForRepaint(RenderBoxModelObject* repaintContainer)
{
// For now, just repaint the whole table.
// FIXME: Find a better way to do this, e.g., need to repaint all the cells that we
// might have propagated a background color into.
+ // FIXME: do repaintContainer checks here
if (RenderTable* parentTable = table())
- return parentTable->absoluteClippedOverflowRect();
+ return parentTable->clippedOverflowRectForRepaint(repaintContainer);
return IntRect();
}
@@ -182,7 +167,7 @@ bool RenderTableRow::nodeAtPoint(const HitTestRequest& request, HitTestResult& r
// at the moment (a demoted inline <form> for example). If we ever implement a
// table-specific hit-test method (which we should do for performance reasons anyway),
// then we can remove this check.
- if (!child->hasLayer() && !child->isInlineFlow() && child->nodeAtPoint(request, result, x, y, tx, ty, action)) {
+ if (child->isTableCell() && !toRenderBox(child)->hasSelfPaintingLayer() && child->nodeAtPoint(request, result, x, y, tx, ty, action)) {
updateHitTestResult(result, IntPoint(x - tx, y - ty));
return true;
}
@@ -193,10 +178,9 @@ bool RenderTableRow::nodeAtPoint(const HitTestRequest& request, HitTestResult& r
void RenderTableRow::paint(PaintInfo& paintInfo, int tx, int ty)
{
- ASSERT(m_layer);
- if (!m_layer)
+ ASSERT(hasSelfPaintingLayer());
+ if (!layer())
return;
-
for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
if (child->isTableCell()) {
// Paint the row background behind the cell.
@@ -204,7 +188,7 @@ void RenderTableRow::paint(PaintInfo& paintInfo, int tx, int ty)
RenderTableCell* cell = static_cast<RenderTableCell*>(child);
cell->paintBackgroundsBehindCell(paintInfo, tx, ty, this);
}
- if (!child->hasLayer())
+ if (!toRenderBox(child)->hasSelfPaintingLayer())
child->paint(paintInfo, tx, ty);
}
}
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderTableRow.h b/src/3rdparty/webkit/WebCore/rendering/RenderTableRow.h
index a65d0e9..9622480 100644
--- a/src/3rdparty/webkit/WebCore/rendering/RenderTableRow.h
+++ b/src/3rdparty/webkit/WebCore/rendering/RenderTableRow.h
@@ -31,10 +31,15 @@
namespace WebCore {
-class RenderTableRow : public RenderContainer {
+class RenderTableRow : public RenderBox {
public:
RenderTableRow(Node*);
+ virtual RenderObjectChildList* virtualChildren() { return children(); }
+ virtual const RenderObjectChildList* virtualChildren() const { return children(); }
+ const RenderObjectChildList* children() const { return &m_children; }
+ RenderObjectChildList* children() { return &m_children; }
+
RenderTableSection* section() const { return static_cast<RenderTableSection*>(parent()); }
RenderTable* table() const { return static_cast<RenderTable*>(parent()->parent()); }
@@ -47,19 +52,21 @@ private:
virtual void addChild(RenderObject* child, RenderObject* beforeChild = 0);
virtual int lineHeight(bool, bool) const { return 0; }
- virtual void position(InlineBox*) { }
virtual void layout();
- virtual IntRect absoluteClippedOverflowRect();
+ virtual IntRect clippedOverflowRectForRepaint(RenderBoxModelObject* repaintContainer);
virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, int x, int y, int tx, int ty, HitTestAction);
// The only time rows get a layer is when they have transparency.
- virtual bool requiresLayer() { return isTransparent() || hasOverflowClip(); }
+ virtual bool requiresLayer() const { return isTransparent() || hasOverflowClip() || hasTransform() || hasMask(); }
virtual void paint(PaintInfo&, int tx, int ty);
+
virtual void imageChanged(WrappedImagePtr, const IntRect* = 0);
- virtual void styleWillChange(RenderStyle::Diff, const RenderStyle* newStyle);
+ virtual void styleWillChange(StyleDifference, const RenderStyle* newStyle);
+private:
+ RenderObjectChildList m_children;
};
} // namespace WebCore
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderTableSection.cpp b/src/3rdparty/webkit/WebCore/rendering/RenderTableSection.cpp
index be43ab8..27c230b 100644
--- a/src/3rdparty/webkit/WebCore/rendering/RenderTableSection.cpp
+++ b/src/3rdparty/webkit/WebCore/rendering/RenderTableSection.cpp
@@ -43,11 +43,10 @@ namespace WebCore {
using namespace HTMLNames;
RenderTableSection::RenderTableSection(Node* node)
- : RenderContainer(node)
+ : RenderBox(node)
, m_gridRows(0)
, m_cCol(0)
, m_cRow(-1)
- , m_needsCellRecalc(false)
, m_outerBorderLeft(0)
, m_outerBorderRight(0)
, m_outerBorderTop(0)
@@ -56,6 +55,7 @@ RenderTableSection::RenderTableSection(Node* node)
, m_overflowWidth(0)
, m_overflowTop(0)
, m_overflowHeight(0)
+ , m_needsCellRecalc(false)
, m_hasOverflowingCell(false)
{
// init RenderObject attributes
@@ -71,7 +71,7 @@ void RenderTableSection::destroy()
{
RenderTable* recalcTable = table();
- RenderContainer::destroy();
+ RenderBox::destroy();
// recalc cell info because RenderTable has unguarded pointers
// stored that point to this RenderTableSection.
@@ -85,14 +85,7 @@ void RenderTableSection::addChild(RenderObject* child, RenderObject* beforeChild
if (!beforeChild && isAfterContent(lastChild()))
beforeChild = lastChild();
- bool isTableSection = element() && (element()->hasTagName(theadTag) || element()->hasTagName(tbodyTag) || element()->hasTagName(tfootTag));
-
if (!child->isTableRow()) {
- if (isTableSection && child->element() && child->element()->hasTagName(formTag) && document()->isHTMLDocument()) {
- RenderContainer::addChild(child, beforeChild);
- return;
- }
-
RenderObject* last = beforeChild;
if (!last)
last = lastChild();
@@ -111,7 +104,7 @@ void RenderTableSection::addChild(RenderObject* child, RenderObject* beforeChild
return;
}
- RenderObject* row = new (renderArena()) RenderTableRow(document() /* anonymous table */);
+ RenderObject* row = new (renderArena()) RenderTableRow(document() /* anonymous table row */);
RefPtr<RenderStyle> newStyle = RenderStyle::create();
newStyle->inheritFrom(style());
newStyle->setDisplay(TABLE_ROW);
@@ -131,7 +124,7 @@ void RenderTableSection::addChild(RenderObject* child, RenderObject* beforeChild
if (!ensureRows(m_cRow + 1))
return;
- m_grid[m_cRow].rowRenderer = child;
+ m_grid[m_cRow].rowRenderer = static_cast<RenderTableRow*>(child);
if (!beforeChild) {
m_grid[m_cRow].height = child->style()->height();
@@ -143,8 +136,14 @@ void RenderTableSection::addChild(RenderObject* child, RenderObject* beforeChild
while (beforeChild && beforeChild->parent() != this)
beforeChild = beforeChild->parent();
- ASSERT(!beforeChild || beforeChild->isTableRow() || isTableSection && beforeChild->element() && beforeChild->element()->hasTagName(formTag) && document()->isHTMLDocument());
- RenderContainer::addChild(child, beforeChild);
+ ASSERT(!beforeChild || beforeChild->isTableRow());
+ RenderBox::addChild(child, beforeChild);
+}
+
+void RenderTableSection::removeChild(RenderObject* oldChild)
+{
+ setNeedsCellRecalc();
+ RenderBox::removeChild(oldChild);
}
bool RenderTableSection::ensureRows(int numRows)
@@ -174,7 +173,7 @@ bool RenderTableSection::ensureRows(int numRows)
return true;
}
-void RenderTableSection::addCell(RenderTableCell* cell, RenderObject* row)
+void RenderTableSection::addCell(RenderTableCell* cell, RenderTableRow* row)
{
int rSpan = cell->rowSpan();
int cSpan = cell->colSpan();
@@ -238,7 +237,7 @@ void RenderTableSection::addCell(RenderTableCell* cell, RenderObject* row)
for (int r = 0; r < rSpan; r++) {
CellStruct& c = cellAt(m_cRow + r, m_cCol);
- if (currentCell.cell && !c.cell)
+ if (!c.cell)
c.cell = currentCell.cell;
if (currentCell.inColSpan)
c.inColSpan = true;
@@ -248,10 +247,8 @@ void RenderTableSection::addCell(RenderTableCell* cell, RenderObject* row)
currentCell.cell = 0;
currentCell.inColSpan = true;
}
- if (cell) {
- cell->setRow(m_cRow);
- cell->setCol(table()->effColToCol(col));
- }
+ cell->setRow(m_cRow);
+ cell->setCol(table()->effColToCol(col));
}
void RenderTableSection::setCellWidths()
@@ -283,11 +280,11 @@ void RenderTableSection::setCellWidths()
if (!statePusher.didPush()) {
// Technically, we should also push state for the row, but since
// rows don't push a coordinate transform, that's not necessary.
- statePusher.push(this, IntSize(m_x, m_y));
+ statePusher.push(this, IntSize(x(), y()));
}
cell->repaint();
}
- cell->setWidth(w);
+ cell->updateWidth(w);
}
}
}
@@ -297,6 +294,12 @@ void RenderTableSection::setCellWidths()
int RenderTableSection::calcRowHeight()
{
+#ifndef NDEBUG
+ setNeedsLayoutIsForbidden(true);
+#endif
+
+ ASSERT(!needsLayout());
+
RenderTableCell* cell;
int spacing = table()->vBorderSpacing();
@@ -333,19 +336,23 @@ int RenderTableSection::calcRowHeight()
if (!statePusher.didPush()) {
// Technically, we should also push state for the row, but since
// rows don't push a coordinate transform, that's not necessary.
- statePusher.push(this, IntSize(m_x, m_y));
+ statePusher.push(this, IntSize(x(), y()));
}
cell->setOverrideSize(-1);
cell->setChildNeedsLayout(true, false);
cell->layoutIfNeeded();
}
+ int adjustedPaddingTop = cell->paddingTop() - cell->intrinsicPaddingTop();
+ int adjustedPaddingBottom = cell->paddingBottom() - cell->intrinsicPaddingBottom();
+ int adjustedHeight = cell->height() - (cell->intrinsicPaddingTop() + cell->intrinsicPaddingBottom());
+
// Explicit heights use the border box in quirks mode. In strict mode do the right
// thing and actually add in the border and padding.
ch = cell->style()->height().calcValue(0) +
- (cell->style()->htmlHacks() ? 0 : (cell->paddingTop() + cell->paddingBottom() +
+ (cell->style()->htmlHacks() ? 0 : (adjustedPaddingTop + adjustedPaddingBottom +
cell->borderTop() + cell->borderBottom()));
- ch = max(ch, cell->height());
+ ch = max(ch, adjustedHeight);
pos = m_rowPos[indx] + ch + (m_grid[r].rowRenderer ? spacing : 0);
@@ -356,8 +363,8 @@ int RenderTableSection::calcRowHeight()
if (va == BASELINE || va == TEXT_BOTTOM || va == TEXT_TOP || va == SUPER || va == SUB) {
int b = cell->baselinePosition();
if (b > cell->borderTop() + cell->paddingTop()) {
- baseline = max(baseline, b);
- bdesc = max(bdesc, m_rowPos[indx] + ch - b);
+ baseline = max(baseline, b - cell->intrinsicPaddingTop());
+ bdesc = max(bdesc, m_rowPos[indx] + ch - (b - cell->intrinsicPaddingTop()));
}
}
}
@@ -372,21 +379,48 @@ int RenderTableSection::calcRowHeight()
m_rowPos[r + 1] = max(m_rowPos[r + 1], m_rowPos[r]);
}
+#ifndef NDEBUG
+ setNeedsLayoutIsForbidden(false);
+#endif
+
+ ASSERT(!needsLayout());
+
statePusher.pop();
return m_rowPos[m_gridRows];
}
+void RenderTableSection::layout()
+{
+ ASSERT(needsLayout());
+
+ LayoutStateMaintainer statePusher(view(), this, IntSize(x(), y()));
+ for (RenderObject* child = children()->firstChild(); child; child = child->nextSibling()) {
+ if (child->isTableRow()) {
+ child->layoutIfNeeded();
+ ASSERT(!child->needsLayout());
+ }
+ }
+ statePusher.pop();
+ setNeedsLayout(false);
+}
+
int RenderTableSection::layoutRows(int toAdd)
{
+#ifndef NDEBUG
+ setNeedsLayoutIsForbidden(true);
+#endif
+
+ ASSERT(!needsLayout());
+
int rHeight;
int rindx;
int totalRows = m_gridRows;
// Set the width of our section now. The rows will also be this width.
- m_width = table()->contentWidth();
+ setWidth(table()->contentWidth());
m_overflowLeft = 0;
- m_overflowWidth = m_width;
+ m_overflowWidth = width();
m_overflowTop = 0;
m_overflowHeight = 0;
m_hasOverflowingCell = false;
@@ -454,13 +488,13 @@ int RenderTableSection::layoutRows(int toAdd)
int vspacing = table()->vBorderSpacing();
int nEffCols = table()->numEffCols();
- LayoutStateMaintainer statePusher(view(), this, IntSize(m_x, m_y));
+ LayoutStateMaintainer statePusher(view(), this, IntSize(x(), y()));
for (int r = 0; r < totalRows; r++) {
// Set the row's x/y position and width/height.
- if (RenderObject* rowRenderer = m_grid[r].rowRenderer) {
- rowRenderer->setPos(0, m_rowPos[r]);
- rowRenderer->setWidth(m_width);
+ if (RenderTableRow* rowRenderer = m_grid[r].rowRenderer) {
+ rowRenderer->setLocation(0, m_rowPos[r]);
+ rowRenderer->setWidth(width());
rowRenderer->setHeight(m_rowPos[r + 1] - m_rowPos[r] - vspacing);
}
@@ -494,19 +528,40 @@ int RenderTableSection::layoutRows(int toAdd)
(!table()->style()->height().isAuto() && rHeight != cell->height());
for (RenderObject* o = cell->firstChild(); o; o = o->nextSibling()) {
- if (!o->isText() && o->style()->height().isPercent() && (o->isReplaced() || o->scrollsOverflow() || flexAllChildren)) {
+ if (!o->isText() && o->style()->height().isPercent() && (flexAllChildren || o->isReplaced() || (o->isBox() && toRenderBox(o)->scrollsOverflow()))) {
// Tables with no sections do not flex.
if (!o->isTable() || static_cast<RenderTable*>(o)->hasSections()) {
o->setNeedsLayout(true, false);
- cell->setChildNeedsLayout(true, false);
cellChildrenFlex = true;
}
}
}
+
+ if (HashSet<RenderBox*>* percentHeightDescendants = cell->percentHeightDescendants()) {
+ HashSet<RenderBox*>::iterator end = percentHeightDescendants->end();
+ for (HashSet<RenderBox*>::iterator it = percentHeightDescendants->begin(); it != end; ++it) {
+ RenderBox* box = *it;
+ if (!box->isReplaced() && !box->scrollsOverflow() && !flexAllChildren)
+ continue;
+
+ while (box != cell) {
+ if (box->normalChildNeedsLayout())
+ break;
+ box->setChildNeedsLayout(true, false);
+ box = box->containingBlock();
+ ASSERT(box);
+ if (!box)
+ break;
+ }
+ cellChildrenFlex = true;
+ }
+ }
+
if (cellChildrenFlex) {
+ cell->setChildNeedsLayout(true, false);
// Alignment within a cell is based off the calculated
// height, which becomes irrelevant once the cell has
- // been resized based off its percentage. -dwh
+ // been resized based off its percentage.
cell->setOverrideSize(max(0,
rHeight - cell->borderTop() - cell->paddingTop() -
cell->borderBottom() - cell->paddingBottom()));
@@ -521,48 +576,57 @@ int RenderTableSection::layoutRows(int toAdd)
}
}
+ int oldTe = cell->intrinsicPaddingTop();
+ int oldBe = cell->intrinsicPaddingBottom();
+ int heightWithoutIntrinsicPadding = cell->height() - oldTe - oldBe;
+
int te = 0;
switch (cell->style()->verticalAlign()) {
case SUB:
case SUPER:
case TEXT_TOP:
case TEXT_BOTTOM:
- case BASELINE:
- te = getBaseline(r) - cell->baselinePosition();
+ case BASELINE: {
+ int b = cell->baselinePosition();
+ if (b > cell->borderTop() + cell->paddingTop())
+ te = getBaseline(r) - (b - oldTe);
break;
+ }
case TOP:
te = 0;
break;
case MIDDLE:
- te = (rHeight - cell->height()) / 2;
+ te = (rHeight - heightWithoutIntrinsicPadding) / 2;
break;
case BOTTOM:
- te = rHeight - cell->height();
+ te = rHeight - heightWithoutIntrinsicPadding;
break;
default:
break;
}
-
- int oldTe = cell->borderTopExtra();
- int oldBe = cell->borderBottomExtra();
-
- int be = rHeight - cell->height() - te;
- cell->setCellTopExtra(te);
- cell->setCellBottomExtra(be);
+
+ int be = rHeight - heightWithoutIntrinsicPadding - te;
+ cell->setIntrinsicPaddingTop(te);
+ cell->setIntrinsicPaddingBottom(be);
+ if (te != oldTe || be != oldBe) {
+ cell->setNeedsLayout(true, false);
+ cell->layoutIfNeeded();
+ }
+
if ((te != oldTe || be > oldBe) && !table()->selfNeedsLayout() && cell->checkForRepaintDuringLayout())
cell->repaint();
- IntRect oldCellRect(cell->xPos(), cell->yPos() - cell->borderTopExtra() , cell->width(), cell->height());
+ IntRect oldCellRect(cell->x(), cell->y() , cell->width(), cell->height());
if (style()->direction() == RTL) {
- cell->setPos(table()->columnPositions()[nEffCols] - table()->columnPositions()[table()->colToEffCol(cell->col() + cell->colSpan())] + hspacing, m_rowPos[rindx]);
+ cell->setLocation(table()->columnPositions()[nEffCols] - table()->columnPositions()[table()->colToEffCol(cell->col() + cell->colSpan())] + hspacing, m_rowPos[rindx]);
} else
- cell->setPos(table()->columnPositions()[c] + hspacing, m_rowPos[rindx]);
+ cell->setLocation(table()->columnPositions()[c] + hspacing, m_rowPos[rindx]);
- m_overflowLeft = min(m_overflowLeft, cell->xPos() + cell->overflowLeft(false));
- m_overflowWidth = max(m_overflowWidth, cell->xPos() + cell->overflowWidth(false));
- m_overflowTop = min(m_overflowTop, cell->yPos() + cell->overflowTop(false));
- m_overflowHeight = max(m_overflowHeight, cell->yPos() + cell->overflowHeight(false));
+ m_overflowLeft = min(m_overflowLeft, cell->x() + cell->overflowLeft(false));
+ m_overflowWidth = max(m_overflowWidth, cell->x() + cell->overflowWidth(false));
+ m_overflowTop = min(m_overflowTop, cell->y() + cell->overflowTop(false));
+ m_overflowHeight = max(m_overflowHeight, cell->y() + cell->overflowHeight(false));
m_hasOverflowingCell |= cell->overflowLeft(false) || cell->overflowWidth(false) > cell->width() || cell->overflowTop(false) || cell->overflowHeight(false) > cell->height();
// If the cell moved, we have to repaint it as well as any floating/positioned
@@ -573,23 +637,31 @@ int RenderTableSection::layoutRows(int toAdd)
}
}
+#ifndef NDEBUG
+ setNeedsLayoutIsForbidden(false);
+#endif
+
+ ASSERT(!needsLayout());
+
statePusher.pop();
- m_height = m_rowPos[totalRows];
- m_overflowHeight = max(m_overflowHeight, m_height);
- return m_height;
+ setHeight(m_rowPos[totalRows]);
+ m_overflowHeight = max(m_overflowHeight, height());
+ return height();
}
int RenderTableSection::lowestPosition(bool includeOverflowInterior, bool includeSelf) const
{
- int bottom = RenderContainer::lowestPosition(includeOverflowInterior, includeSelf);
+ int bottom = RenderBox::lowestPosition(includeOverflowInterior, includeSelf);
if (!includeOverflowInterior && hasOverflowClip())
return bottom;
for (RenderObject* row = firstChild(); row; row = row->nextSibling()) {
- for (RenderObject* cell = row->firstChild(); cell; cell = cell->nextSibling()) {
- if (cell->isTableCell())
- bottom = max(bottom, cell->yPos() + cell->lowestPosition(false));
+ for (RenderObject* curr = row->firstChild(); curr; curr = curr->nextSibling()) {
+ if (curr->isTableCell()) {
+ RenderTableCell* cell = static_cast<RenderTableCell*>(curr);
+ bottom = max(bottom, cell->y() + cell->lowestPosition(false));
+ }
}
}
@@ -598,14 +670,16 @@ int RenderTableSection::lowestPosition(bool includeOverflowInterior, bool includ
int RenderTableSection::rightmostPosition(bool includeOverflowInterior, bool includeSelf) const
{
- int right = RenderContainer::rightmostPosition(includeOverflowInterior, includeSelf);
+ int right = RenderBox::rightmostPosition(includeOverflowInterior, includeSelf);
if (!includeOverflowInterior && hasOverflowClip())
return right;
for (RenderObject* row = firstChild(); row; row = row->nextSibling()) {
- for (RenderObject* cell = row->firstChild(); cell; cell = cell->nextSibling()) {
- if (cell->isTableCell())
- right = max(right, cell->xPos() + cell->rightmostPosition(false));
+ for (RenderObject* curr = row->firstChild(); curr; curr = curr->nextSibling()) {
+ if (curr->isTableCell()) {
+ RenderTableCell* cell = static_cast<RenderTableCell*>(curr);
+ right = max(right, cell->x() + cell->rightmostPosition(false));
+ }
}
}
@@ -614,14 +688,16 @@ int RenderTableSection::rightmostPosition(bool includeOverflowInterior, bool inc
int RenderTableSection::leftmostPosition(bool includeOverflowInterior, bool includeSelf) const
{
- int left = RenderContainer::leftmostPosition(includeOverflowInterior, includeSelf);
+ int left = RenderBox::leftmostPosition(includeOverflowInterior, includeSelf);
if (!includeOverflowInterior && hasOverflowClip())
return left;
for (RenderObject* row = firstChild(); row; row = row->nextSibling()) {
- for (RenderObject* cell = row->firstChild(); cell; cell = cell->nextSibling()) {
- if (cell->isTableCell())
- left = min(left, cell->xPos() + cell->leftmostPosition(false));
+ for (RenderObject* curr = row->firstChild(); curr; curr = curr->nextSibling()) {
+ if (curr->isTableCell()) {
+ RenderTableCell* cell = static_cast<RenderTableCell*>(curr);
+ left = min(left, cell->x() + cell->leftmostPosition(false));
+ }
}
}
@@ -837,7 +913,7 @@ void RenderTableSection::recalcOuterBorder()
m_outerBorderRight = calcOuterBorderRight(rtl);
}
-int RenderTableSection::getBaselineOfFirstLineBox() const
+int RenderTableSection::firstLineBoxBaseline() const
{
if (!m_gridRows)
return -1;
@@ -851,7 +927,7 @@ int RenderTableSection::getBaselineOfFirstLineBox() const
for (size_t i = 0; i < firstRow->size(); ++i) {
RenderTableCell* cell = firstRow->at(i).cell;
if (cell)
- firstLineBaseline = max(firstLineBaseline, cell->yPos() + cell->paddingTop() + cell->borderTop() + cell->contentHeight());
+ firstLineBaseline = max(firstLineBaseline, cell->y() + cell->paddingTop() + cell->borderTop() + cell->contentHeight());
}
return firstLineBaseline;
@@ -871,11 +947,23 @@ void RenderTableSection::paint(PaintInfo& paintInfo, int tx, int ty)
if (!totalRows || !totalCols)
return;
- tx += m_x;
- ty += m_y;
+ tx += x();
+ ty += y();
+
+ PaintPhase phase = paintInfo.phase;
+ bool pushedClip = pushContentsClip(paintInfo, tx, ty);
+ paintObject(paintInfo, tx, ty);
+ if (pushedClip)
+ popContentsClip(paintInfo, phase, tx, ty);
+}
+void RenderTableSection::paintObject(PaintInfo& paintInfo, int tx, int ty)
+{
// Check which rows and cols are visible and only paint these.
// FIXME: Could use a binary search here.
+ unsigned totalRows = m_gridRows;
+ unsigned totalCols = table()->columns().size();
+
PaintPhase paintPhase = paintInfo.phase;
int x = paintInfo.rect.x();
int y = paintInfo.rect.y();
@@ -962,11 +1050,11 @@ void RenderTableSection::paint(PaintInfo& paintInfo, int tx, int ty)
// Paint the row next, but only if it doesn't have a layer. If a row has a layer, it will be responsible for
// painting the row background for the cell.
- if (!row->hasLayer())
+ if (!row->hasSelfPaintingLayer())
cell->paintBackgroundsBehindCell(paintInfo, tx, ty, row);
}
- if ((!cell->hasLayer() && !row->hasLayer()) || paintInfo.phase == PaintPhaseCollapsedTableBorders)
+ if ((!cell->hasSelfPaintingLayer() && !row->hasSelfPaintingLayer()) || paintInfo.phase == PaintPhaseCollapsedTableBorders)
cell->paint(paintInfo, tx, ty);
}
}
@@ -992,11 +1080,13 @@ void RenderTableSection::recalcCells()
m_cCol = 0;
if (!ensureRows(m_cRow + 1))
break;
- m_grid[m_cRow].rowRenderer = row;
+
+ RenderTableRow* tableRow = static_cast<RenderTableRow*>(row);
+ m_grid[m_cRow].rowRenderer = tableRow;
for (RenderObject* cell = row->firstChild(); cell; cell = cell->nextSibling()) {
if (cell->isTableCell())
- addCell(static_cast<RenderTableCell*>(cell), row);
+ addCell(static_cast<RenderTableCell*>(cell), tableRow);
}
}
}
@@ -1049,27 +1139,24 @@ void RenderTableSection::splitColumn(int pos, int newSize)
}
}
-RenderObject* RenderTableSection::removeChildNode(RenderObject* child, bool fullRemove)
-{
- setNeedsCellRecalc();
- return RenderContainer::removeChildNode(child, fullRemove);
-}
-
// Hit Testing
-bool RenderTableSection::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, int x, int y, int tx, int ty, HitTestAction action)
+bool RenderTableSection::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, int xPos, int yPos, int tx, int ty, HitTestAction action)
{
// Table sections cannot ever be hit tested. Effectively they do not exist.
// Just forward to our children always.
- tx += m_x;
- ty += m_y;
+ tx += x();
+ ty += y();
+
+ if (hasOverflowClip() && !overflowClipRect(tx, ty).contains(xPos, yPos))
+ return false;
for (RenderObject* child = lastChild(); child; child = child->previousSibling()) {
// FIXME: We have to skip over inline flows, since they can show up inside table rows
// at the moment (a demoted inline <form> for example). If we ever implement a
// table-specific hit-test method (which we should do for performance reasons anyway),
// then we can remove this check.
- if (!child->hasLayer() && !child->isInlineFlow() && child->nodeAtPoint(request, result, x, y, tx, ty, action)) {
- updateHitTestResult(result, IntPoint(x - tx, y - ty));
+ if (child->isBox() && !toRenderBox(child)->hasSelfPaintingLayer() && child->nodeAtPoint(request, result, xPos, yPos, tx, ty, action)) {
+ updateHitTestResult(result, IntPoint(xPos - tx, yPos - ty));
return true;
}
}
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderTableSection.h b/src/3rdparty/webkit/WebCore/rendering/RenderTableSection.h
index 8d460cb..30614f0 100644
--- a/src/3rdparty/webkit/WebCore/rendering/RenderTableSection.h
+++ b/src/3rdparty/webkit/WebCore/rendering/RenderTableSection.h
@@ -33,23 +33,32 @@
namespace WebCore {
class RenderTableCell;
+class RenderTableRow;
-class RenderTableSection : public RenderContainer {
+class RenderTableSection : public RenderBox {
public:
RenderTableSection(Node*);
~RenderTableSection();
+ virtual RenderObjectChildList* virtualChildren() { return children(); }
+ virtual const RenderObjectChildList* virtualChildren() const { return children(); }
+ const RenderObjectChildList* children() const { return &m_children; }
+ RenderObjectChildList* children() { return &m_children; }
+
virtual const char* renderName() const { return isAnonymous() ? "RenderTableSection (anonymous)" : "RenderTableSection"; }
virtual bool isTableSection() const { return true; }
virtual void destroy();
+ virtual void layout();
+
virtual void addChild(RenderObject* child, RenderObject* beforeChild = 0);
+ virtual void removeChild(RenderObject* oldChild);
- virtual int getBaselineOfFirstLineBox() const;
+ virtual int firstLineBoxBaseline() const;
- void addCell(RenderTableCell*, RenderObject* row);
+ void addCell(RenderTableCell*, RenderTableRow* row);
void setCellWidths();
int calcRowHeight();
@@ -66,7 +75,7 @@ public:
struct RowStruct {
Row* row;
- RenderObject* rowRenderer;
+ RenderTableRow* rowRenderer;
int baseline;
Length height;
};
@@ -77,9 +86,9 @@ public:
void appendColumn(int pos);
void splitColumn(int pos, int newSize);
- virtual int overflowWidth(bool includeInterior = true) const { return (!includeInterior && hasOverflowClip()) ? m_width : m_overflowWidth; }
+ virtual int overflowWidth(bool includeInterior = true) const { return (!includeInterior && hasOverflowClip()) ? width() : m_overflowWidth; }
virtual int overflowLeft(bool includeInterior = true) const { return (!includeInterior && hasOverflowClip()) ? 0 : m_overflowLeft; }
- virtual int overflowHeight(bool includeInterior = true) const { return (!includeInterior && hasOverflowClip()) ? m_height : m_overflowHeight; }
+ virtual int overflowHeight(bool includeInterior = true) const { return (!includeInterior && hasOverflowClip()) ? height() : m_overflowHeight; }
virtual int overflowTop(bool includeInterior = true) const { return (!includeInterior && hasOverflowClip()) ? 0 : m_overflowTop; }
virtual int lowestPosition(bool includeOverflowInterior, bool includeSelf) const;
@@ -98,6 +107,8 @@ public:
int outerBorderRight() const { return m_outerBorderRight; }
virtual void paint(PaintInfo&, int tx, int ty);
+ virtual void paintObject(PaintInfo&, int tx, int ty);
+
virtual void imageChanged(WrappedImagePtr, const IntRect* = 0);
int numRows() const { return m_gridRows; }
@@ -118,25 +129,24 @@ public:
int getBaseline(int row) { return m_grid[row].baseline; }
- virtual RenderObject* removeChildNode(RenderObject*, bool fullRemove = true);
-
virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, int x, int y, int tx, int ty, HitTestAction);
private:
virtual int lineHeight(bool, bool) const { return 0; }
- virtual void position(InlineBox*) { }
bool ensureRows(int);
void clearGrid();
+ RenderObjectChildList m_children;
+
Vector<RowStruct> m_grid;
- int m_gridRows;
Vector<int> m_rowPos;
+ int m_gridRows;
+
// the current insertion position
int m_cCol;
int m_cRow;
- bool m_needsCellRecalc;
int m_outerBorderLeft;
int m_outerBorderRight;
@@ -146,6 +156,8 @@ private:
int m_overflowWidth;
int m_overflowTop;
int m_overflowHeight;
+
+ bool m_needsCellRecalc;
bool m_hasOverflowingCell;
};
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderText.cpp b/src/3rdparty/webkit/WebCore/rendering/RenderText.cpp
index d7fdbb9..ada3961 100644
--- a/src/3rdparty/webkit/WebCore/rendering/RenderText.cpp
+++ b/src/3rdparty/webkit/WebCore/rendering/RenderText.cpp
@@ -1,4 +1,4 @@
-/**
+/*
* (C) 1999 Lars Knoll (knoll@kde.org)
* (C) 2000 Dirk Mueller (mueller@kde.org)
* Copyright (C) 2004, 2005, 2006, 2007 Apple Inc. All rights reserved.
@@ -26,6 +26,7 @@
#include "RenderText.h"
#include "CharacterNames.h"
+#include "FloatQuad.h"
#include "FrameView.h"
#include "InlineTextBox.h"
#include "Range.h"
@@ -35,6 +36,7 @@
#include "RenderView.h"
#include "Text.h"
#include "TextBreakIterator.h"
+#include "VisiblePosition.h"
#include "break_lines.h"
#include <wtf/AlwaysInline.h>
@@ -52,23 +54,26 @@ static inline bool charactersAreAllASCII(StringImpl* text)
RenderText::RenderText(Node* node, PassRefPtr<StringImpl> str)
: RenderObject(node)
- , m_text(str)
+ , m_minWidth(-1)
+ , m_text(document()->displayStringModifiedByEncoding(str))
, m_firstTextBox(0)
, m_lastTextBox(0)
- , m_minWidth(-1)
, m_maxWidth(-1)
, m_beginMinWidth(0)
, m_endMinWidth(0)
- , m_selectionState(SelectionNone)
, m_hasTab(false)
, m_linesDirty(false)
, m_containsReversedText(false)
, m_isAllASCII(charactersAreAllASCII(m_text.get()))
+ , m_knownNotToUseFallbackFonts(false)
{
ASSERT(m_text);
- setRenderText();
- m_text = m_text->replace('\\', backslashAsCurrencySymbol());
+ setIsText();
+
+ // FIXME: It would be better to call this only if !m_text->containsOnlyWhitespace().
+ // But that might slow things down, and maybe should only be done if visuallyNonEmpty
+ // is still false. Not making any change for now, but should consider in the future.
view()->frameView()->setIsVisuallyNonEmpty();
}
@@ -97,18 +102,21 @@ bool RenderText::isWordBreak() const
return false;
}
-void RenderText::styleDidChange(RenderStyle::Diff diff, const RenderStyle* oldStyle)
+void RenderText::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
{
- RenderObject::styleDidChange(diff, oldStyle);
+ // There is no need to ever schedule repaints from a style change of a text run, since
+ // we already did this for the parent of the text run.
+ // We do have to schedule layouts, though, since a style change can force us to
+ // need to relayout.
+ if (diff == StyleDifferenceLayout) {
+ setNeedsLayoutAndPrefWidthsRecalc();
+ m_knownNotToUseFallbackFonts = false;
+ }
ETextTransform oldTransform = oldStyle ? oldStyle->textTransform() : TTNONE;
ETextSecurity oldSecurity = oldStyle ? oldStyle->textSecurity() : TSNONE;
- if (oldTransform != style()->textTransform() || oldSecurity != style()->textSecurity()
-#if ENABLE(SVG)
- || isSVGText() /* All SVG text has to be transformed */
-#endif
- ) {
+ if (oldTransform != style()->textTransform() || oldSecurity != style()->textSecurity()) {
if (RefPtr<StringImpl> textToTransform = originalText())
setText(textToTransform.release(), true);
}
@@ -198,17 +206,17 @@ void RenderText::deleteTextBoxes()
PassRefPtr<StringImpl> RenderText::originalText() const
{
- Node* e = element();
+ Node* e = node();
return e ? static_cast<Text*>(e)->string() : 0;
}
-void RenderText::absoluteRects(Vector<IntRect>& rects, int tx, int ty, bool)
+void RenderText::absoluteRects(Vector<IntRect>& rects, int tx, int ty)
{
for (InlineTextBox* box = firstTextBox(); box; box = box->nextTextBox())
- rects.append(IntRect(tx + box->xPos(), ty + box->yPos(), box->width(), box->height()));
+ rects.append(IntRect(tx + box->x(), ty + box->y(), box->width(), box->height()));
}
-void RenderText::addLineBoxRects(Vector<IntRect>& rects, unsigned start, unsigned end, bool useSelectionHeight)
+void RenderText::absoluteRectsForRange(Vector<IntRect>& rects, unsigned start, unsigned end, bool useSelectionHeight)
{
// Work around signed/unsigned issues. This function takes unsigneds, and is often passed UINT_MAX
// to mean "all the way to the end". InlineTextBox coordinates are unsigneds, so changing this
@@ -220,12 +228,12 @@ void RenderText::addLineBoxRects(Vector<IntRect>& rects, unsigned start, unsigne
start = min(start, static_cast<unsigned>(INT_MAX));
end = min(end, static_cast<unsigned>(INT_MAX));
- FloatPoint absPos = localToAbsoluteForContent(FloatPoint());
+ FloatPoint absPos = localToAbsolute(FloatPoint());
for (InlineTextBox* box = firstTextBox(); box; box = box->nextTextBox()) {
// Note: box->end() returns the index of the last character, not the index past it
if (start <= box->start() && box->end() < end) {
- IntRect r = IntRect(absPos.x() + box->xPos(), absPos.y() + box->yPos(), box->width(), box->height());
+ IntRect r = IntRect(absPos.x() + box->x(), absPos.y() + box->y(), box->width(), box->height());
if (useSelectionHeight) {
IntRect selectionRect = box->selectionRect(absPos.x(), absPos.y(), start, end);
r.setHeight(selectionRect.height());
@@ -239,7 +247,7 @@ void RenderText::addLineBoxRects(Vector<IntRect>& rects, unsigned start, unsigne
if (!useSelectionHeight) {
// change the height and y position because selectionRect uses selection-specific values
r.setHeight(box->height());
- r.setY(absPos.y() + box->yPos());
+ r.setY(absPos.y() + box->y());
}
rects.append(r);
}
@@ -247,13 +255,13 @@ void RenderText::addLineBoxRects(Vector<IntRect>& rects, unsigned start, unsigne
}
}
-void RenderText::absoluteQuads(Vector<FloatQuad>& quads, bool)
+void RenderText::absoluteQuads(Vector<FloatQuad>& quads)
{
for (InlineTextBox* box = firstTextBox(); box; box = box->nextTextBox())
- quads.append(localToAbsoluteQuad(FloatRect(box->xPos(), box->yPos(), box->width(), box->height())));
+ quads.append(localToAbsoluteQuad(FloatRect(box->x(), box->y(), box->width(), box->height())));
}
-void RenderText::collectAbsoluteLineBoxQuads(Vector<FloatQuad>& quads, unsigned start, unsigned end, bool useSelectionHeight)
+void RenderText::absoluteQuadsForRange(Vector<FloatQuad>& quads, unsigned start, unsigned end, bool useSelectionHeight)
{
// Work around signed/unsigned issues. This function takes unsigneds, and is often passed UINT_MAX
// to mean "all the way to the end". InlineTextBox coordinates are unsigneds, so changing this
@@ -268,7 +276,7 @@ void RenderText::collectAbsoluteLineBoxQuads(Vector<FloatQuad>& quads, unsigned
for (InlineTextBox* box = firstTextBox(); box; box = box->nextTextBox()) {
// Note: box->end() returns the index of the last character, not the index past it
if (start <= box->start() && box->end() < end) {
- IntRect r = IntRect(box->xPos(), box->yPos(), box->width(), box->height());
+ IntRect r = IntRect(box->x(), box->y(), box->width(), box->height());
if (useSelectionHeight) {
IntRect selectionRect = box->selectionRect(0, 0, start, end);
r.setHeight(selectionRect.height());
@@ -282,7 +290,7 @@ void RenderText::collectAbsoluteLineBoxQuads(Vector<FloatQuad>& quads, unsigned
if (!useSelectionHeight) {
// change the height and y position because selectionRect uses selection-specific values
r.setHeight(box->height());
- r.setY(box->yPos());
+ r.setY(box->y());
}
quads.append(localToAbsoluteQuad(FloatRect(r)));
}
@@ -301,71 +309,71 @@ InlineTextBox* RenderText::findNextInlineTextBox(int offset, int& pos) const
return 0;
InlineTextBox* s = m_firstTextBox;
- int off = s->m_len;
+ int off = s->len();
while (offset > off && s->nextTextBox()) {
s = s->nextTextBox();
- off = s->m_start + s->m_len;
+ off = s->start() + s->len();
}
// we are now in the correct text run
- pos = (offset > off ? s->m_len : s->m_len - (off - offset) );
+ pos = (offset > off ? s->len() : s->len() - (off - offset) );
return s;
}
-VisiblePosition RenderText::positionForCoordinates(int x, int y)
+VisiblePosition RenderText::positionForPoint(const IntPoint& point)
{
if (!firstTextBox() || textLength() == 0)
- return VisiblePosition(element(), 0, DOWNSTREAM);
+ return createVisiblePosition(0, DOWNSTREAM);
// Get the offset for the position, since this will take rtl text into account.
int offset;
// FIXME: We should be able to roll these special cases into the general cases in the loop below.
- if (firstTextBox() && y < firstTextBox()->root()->bottomOverflow() && x < firstTextBox()->m_x) {
+ if (firstTextBox() && point.y() < firstTextBox()->root()->bottomOverflow() && point.x() < firstTextBox()->m_x) {
// at the y coordinate of the first line or above
// and the x coordinate is to the left of the first text box left edge
- offset = firstTextBox()->offsetForPosition(x);
- return VisiblePosition(element(), offset + firstTextBox()->m_start, DOWNSTREAM);
+ offset = firstTextBox()->offsetForPosition(point.x());
+ return createVisiblePosition(offset + firstTextBox()->start(), DOWNSTREAM);
}
- if (lastTextBox() && y >= lastTextBox()->root()->topOverflow() && x >= lastTextBox()->m_x + lastTextBox()->m_width) {
+ if (lastTextBox() && point.y() >= lastTextBox()->root()->topOverflow() && point.x() >= lastTextBox()->m_x + lastTextBox()->m_width) {
// at the y coordinate of the last line or below
// and the x coordinate is to the right of the last text box right edge
- offset = lastTextBox()->offsetForPosition(x);
- return VisiblePosition(element(), offset + lastTextBox()->m_start, DOWNSTREAM);
+ offset = lastTextBox()->offsetForPosition(point.x());
+ return createVisiblePosition(offset + lastTextBox()->start(), DOWNSTREAM);
}
InlineTextBox* lastBoxAbove = 0;
for (InlineTextBox* box = firstTextBox(); box; box = box->nextTextBox()) {
- if (y >= box->root()->topOverflow()) {
+ if (point.y() >= box->root()->topOverflow()) {
int bottom = box->root()->nextRootBox() ? box->root()->nextRootBox()->topOverflow() : box->root()->bottomOverflow();
- if (y < bottom) {
- offset = box->offsetForPosition(x);
+ if (point.y() < bottom) {
+ offset = box->offsetForPosition(point.x());
- if (x == box->m_x)
+ if (point.x() == box->m_x)
// the x coordinate is equal to the left edge of this box
// the affinity must be downstream so the position doesn't jump back to the previous line
- return VisiblePosition(element(), offset + box->m_start, DOWNSTREAM);
+ return createVisiblePosition(offset + box->start(), DOWNSTREAM);
- if (x < box->m_x + box->m_width)
+ if (point.x() < box->m_x + box->m_width)
// and the x coordinate is to the left of the right edge of this box
// check to see if position goes in this box
- return VisiblePosition(element(), offset + box->m_start, offset > 0 ? VP_UPSTREAM_IF_POSSIBLE : DOWNSTREAM);
+ return createVisiblePosition(offset + box->start(), offset > 0 ? VP_UPSTREAM_IF_POSSIBLE : DOWNSTREAM);
- if (!box->prevOnLine() && x < box->m_x)
+ if (!box->prevOnLine() && point.x() < box->m_x)
// box is first on line
// and the x coordinate is to the left of the first text box left edge
- return VisiblePosition(element(), offset + box->m_start, DOWNSTREAM);
+ return createVisiblePosition(offset + box->start(), DOWNSTREAM);
if (!box->nextOnLine())
// box is last on line
// and the x coordinate is to the right of the last text box right edge
// generate VisiblePosition, use UPSTREAM affinity if possible
- return VisiblePosition(element(), offset + box->m_start, offset > 0 ? VP_UPSTREAM_IF_POSSIBLE : DOWNSTREAM);
+ return createVisiblePosition(offset + box->start(), offset > 0 ? VP_UPSTREAM_IF_POSSIBLE : DOWNSTREAM);
}
lastBoxAbove = box;
}
}
- return VisiblePosition(element(), lastBoxAbove ? lastBoxAbove->m_start + lastBoxAbove->m_len : 0, DOWNSTREAM);
+ return createVisiblePosition(lastBoxAbove ? lastBoxAbove->start() + lastBoxAbove->len() : 0, DOWNSTREAM);
}
IntRect RenderText::localCaretRect(InlineBox* inlineBox, int caretOffset, int* extraWidthToEndOfLine)
@@ -384,7 +392,13 @@ IntRect RenderText::localCaretRect(InlineBox* inlineBox, int caretOffset, int* e
int left = box->positionForOffset(caretOffset);
- int rootLeft = box->root()->xPos();
+ // Distribute the caret's width to either side of the offset.
+ int caretWidthLeftOfOffset = caretWidth / 2;
+ left -= caretWidthLeftOfOffset;
+ int caretWidthRightOfOffset = caretWidth - caretWidthLeftOfOffset;
+
+ int rootLeft = box->root()->x();
+ int rootRight = rootLeft + box->root()->width();
// FIXME: should we use the width of the root inline box or the
// width of the containing block for this?
if (extraWidthToEndOfLine)
@@ -392,18 +406,28 @@ IntRect RenderText::localCaretRect(InlineBox* inlineBox, int caretOffset, int* e
RenderBlock* cb = containingBlock();
if (style()->autoWrap()) {
- int availableWidth = cb->lineWidth(top);
+ int availableWidth = cb->lineWidth(top, false);
if (box->direction() == LTR)
- left = min(left, rootLeft + availableWidth - 1);
+ left = min(left, rootLeft + availableWidth - caretWidthRightOfOffset);
else
+ left = max(left, cb->x());
+ } else {
+ // If there is no wrapping, the caret can leave its containing block, but not its root line box.
+ if (cb->style()->direction() == LTR) {
+ int rightEdge = max(cb->width(), rootRight);
+ left = min(left, rightEdge - caretWidthRightOfOffset);
left = max(left, rootLeft);
+ } else {
+ int leftEdge = min(cb->x(), rootLeft);
+ left = max(left, leftEdge);
+ left = min(left, rootRight - caretWidth);
+ }
}
- const int caretWidth = 1;
return IntRect(left, top, caretWidth, height);
}
-ALWAYS_INLINE int RenderText::widthFromCache(const Font& f, int start, int len, int xPos) const
+ALWAYS_INLINE int RenderText::widthFromCache(const Font& f, int start, int len, int xPos, HashSet<const SimpleFontData*>* fallbackFonts) const
{
if (f.isFixedPitch() && !f.isSmallCaps() && m_isAllASCII) {
int monospaceCharacterWidth = f.spaceWidth();
@@ -433,7 +457,7 @@ ALWAYS_INLINE int RenderText::widthFromCache(const Font& f, int start, int len,
return w;
}
- return f.width(TextRun(text()->characters() + start, len, allowTabs(), xPos));
+ return f.width(TextRun(text()->characters() + start, len, allowTabs(), xPos), fallbackFonts);
}
void RenderText::trimmedPrefWidths(int leadWidth,
@@ -502,7 +526,7 @@ void RenderText::trimmedPrefWidths(int leadWidth,
linelen++;
if (linelen) {
- endMaxW = widthFromCache(f, i, linelen, leadWidth + endMaxW);
+ endMaxW = widthFromCache(f, i, linelen, leadWidth + endMaxW, 0);
if (firstLine) {
firstLine = false;
leadWidth = 0;
@@ -546,7 +570,15 @@ int RenderText::maxPrefWidth() const
void RenderText::calcPrefWidths(int leadWidth)
{
- ASSERT(m_hasTab || prefWidthsDirty());
+ HashSet<const SimpleFontData*> fallbackFonts;
+ calcPrefWidths(leadWidth, fallbackFonts);
+ if (fallbackFonts.isEmpty())
+ m_knownNotToUseFallbackFonts = true;
+}
+
+void RenderText::calcPrefWidths(int leadWidth, HashSet<const SimpleFontData*>& fallbackFonts)
+{
+ ASSERT(m_hasTab || prefWidthsDirty() || !m_knownNotToUseFallbackFonts);
m_minWidth = 0;
m_beginMinWidth = 0;
@@ -618,7 +650,7 @@ void RenderText::calcPrefWidths(int leadWidth)
lastWordBoundary++;
continue;
} else if (c == softHyphen) {
- currMaxWidth += widthFromCache(f, lastWordBoundary, i - lastWordBoundary, leadWidth + currMaxWidth);
+ currMaxWidth += widthFromCache(f, lastWordBoundary, i - lastWordBoundary, leadWidth + currMaxWidth, &fallbackFonts);
lastWordBoundary = i + 1;
continue;
}
@@ -641,13 +673,13 @@ void RenderText::calcPrefWidths(int leadWidth)
int wordLen = j - i;
if (wordLen) {
- int w = widthFromCache(f, i, wordLen, leadWidth + currMaxWidth);
+ int w = widthFromCache(f, i, wordLen, leadWidth + currMaxWidth, &fallbackFonts);
currMinWidth += w;
if (betweenWords) {
if (lastWordBoundary == i)
currMaxWidth += w;
else
- currMaxWidth += widthFromCache(f, lastWordBoundary, j - lastWordBoundary, leadWidth + currMaxWidth);
+ currMaxWidth += widthFromCache(f, lastWordBoundary, j - lastWordBoundary, leadWidth + currMaxWidth, &fallbackFonts);
lastWordBoundary = j;
}
@@ -707,7 +739,7 @@ void RenderText::calcPrefWidths(int leadWidth)
}
}
- if (needsWordSpacing && len > 1 || ignoringSpaces && !firstWord)
+ if ((needsWordSpacing && len > 1) || (ignoringSpaces && !firstWord))
currMaxWidth += wordSpacing;
m_minWidth = max(currMinWidth, m_minWidth);
@@ -734,33 +766,26 @@ bool RenderText::containsOnlyWhitespace(unsigned from, unsigned len) const
return currPos >= (from + len);
}
-int RenderText::minXPos() const
+IntPoint RenderText::firstRunOrigin() const
{
- if (!m_firstTextBox)
- return 0;
-
- // FIXME: we should not use an arbitrary value like this. Perhaps we should use INT_MAX.
- int minXPos = 6666666;
- for (InlineTextBox* box = firstTextBox(); box; box = box->nextTextBox())
- minXPos = min(minXPos, static_cast<int>(box->m_x));
- return minXPos;
+ return IntPoint(firstRunX(), firstRunY());
}
-int RenderText::xPos() const
+int RenderText::firstRunX() const
{
return m_firstTextBox ? m_firstTextBox->m_x : 0;
}
-int RenderText::yPos() const
+int RenderText::firstRunY() const
{
return m_firstTextBox ? m_firstTextBox->m_y : 0;
}
-
+
void RenderText::setSelectionState(SelectionState state)
{
InlineTextBox* box;
- m_selectionState = state;
+ RenderObject::setSelectionState(state);
if (state == SelectionStart || state == SelectionEnd || state == SelectionBoth) {
int startPos, endPos;
selectionStartEnd(startPos, endPos);
@@ -846,6 +871,11 @@ void RenderText::setTextWithOffset(PassRefPtr<StringImpl> text, unsigned offset,
RootInlineBox* prev = firstRootBox->prevRootBox();
if (prev)
firstRootBox = prev;
+ } else if (lastTextBox()) {
+ ASSERT(!lastRootBox);
+ firstRootBox = lastTextBox()->root();
+ firstRootBox->markDirty();
+ dirtiedLines = true;
}
for (RootInlineBox* curr = firstRootBox; curr && curr != lastRootBox; curr = curr->nextRootBox()) {
if (curr->lineBreakObj() == this && curr->lineBreakPos() > end)
@@ -864,11 +894,11 @@ void RenderText::setTextWithOffset(PassRefPtr<StringImpl> text, unsigned offset,
static inline bool isInlineFlowOrEmptyText(RenderObject* o)
{
- if (o->isInlineFlow())
+ if (o->isRenderInline())
return true;
if (!o->isText())
return false;
- StringImpl* text = static_cast<RenderText*>(o)->text();
+ StringImpl* text = toRenderText(o)->text();
if (!text)
return true;
return !text->length();
@@ -883,18 +913,17 @@ UChar RenderText::previousCharacter()
break;
UChar prev = ' ';
if (previousText && previousText->isText())
- if (StringImpl* previousString = static_cast<RenderText*>(previousText)->text())
+ if (StringImpl* previousString = toRenderText(previousText)->text())
prev = (*previousString)[previousString->length() - 1];
return prev;
}
void RenderText::setTextInternal(PassRefPtr<StringImpl> text)
{
- m_text = text;
+ ASSERT(text);
+ m_text = document()->displayStringModifiedByEncoding(text);
ASSERT(m_text);
- m_text = m_text->replace('\\', backslashAsCurrencySymbol());
-
#if ENABLE(SVG)
if (isSVGText()) {
if (style() && style()->whiteSpace() == PRE) {
@@ -971,14 +1000,7 @@ void RenderText::setText(PassRefPtr<StringImpl> text, bool force)
setTextInternal(text);
setNeedsLayoutAndPrefWidthsRecalc();
-}
-
-int RenderText::height() const
-{
- int retval = 0;
- if (firstTextBox())
- retval = lastTextBox()->m_y + lastTextBox()->height() - firstTextBox()->m_y;
- return retval;
+ m_knownNotToUseFallbackFonts = false;
}
int RenderText::lineHeight(bool firstLine, bool) const
@@ -987,7 +1009,7 @@ int RenderText::lineHeight(bool firstLine, bool) const
return parent()->lineHeight(firstLine, true);
}
-void RenderText::dirtyLineBoxes(bool fullLayout, bool)
+void RenderText::dirtyLineBoxes(bool fullLayout)
{
if (fullLayout)
deleteTextBoxes();
@@ -998,15 +1020,14 @@ void RenderText::dirtyLineBoxes(bool fullLayout, bool)
m_linesDirty = false;
}
-InlineTextBox* RenderText::createInlineTextBox()
+InlineTextBox* RenderText::createTextBox()
{
return new (renderArena()) InlineTextBox(this);
}
-InlineBox* RenderText::createInlineBox(bool, bool isRootLineBox, bool)
+InlineTextBox* RenderText::createInlineTextBox()
{
- ASSERT(!isRootLineBox);
- InlineTextBox* textBox = createInlineTextBox();
+ InlineTextBox* textBox = createTextBox();
if (!m_firstTextBox)
m_firstTextBox = m_lastTextBox = textBox;
else {
@@ -1014,15 +1035,16 @@ InlineBox* RenderText::createInlineBox(bool, bool isRootLineBox, bool)
textBox->setPreviousLineBox(m_lastTextBox);
m_lastTextBox = textBox;
}
+ textBox->setIsText(true);
return textBox;
}
-void RenderText::position(InlineBox* box)
+void RenderText::positionLineBox(InlineBox* box)
{
InlineTextBox* s = static_cast<InlineTextBox*>(box);
// FIXME: should not be needed!!!
- if (!s->m_len) {
+ if (!s->len()) {
// We want the box to be destroyed.
s->remove();
s->destroy(renderArena());
@@ -1033,7 +1055,7 @@ void RenderText::position(InlineBox* box)
m_containsReversedText |= s->direction() == RTL;
}
-unsigned int RenderText::width(unsigned int from, unsigned int len, int xPos, bool firstLine) const
+unsigned RenderText::width(unsigned from, unsigned len, int xPos, bool firstLine, HashSet<const SimpleFontData*>* fallbackFonts) const
{
if (from >= textLength())
return 0;
@@ -1041,61 +1063,74 @@ unsigned int RenderText::width(unsigned int from, unsigned int len, int xPos, bo
if (from + len > textLength())
len = textLength() - from;
- return width(from, len, style(firstLine)->font(), xPos);
+ return width(from, len, style(firstLine)->font(), xPos, fallbackFonts);
}
-unsigned int RenderText::width(unsigned int from, unsigned int len, const Font& f, int xPos) const
+unsigned RenderText::width(unsigned from, unsigned len, const Font& f, int xPos, HashSet<const SimpleFontData*>* fallbackFonts) const
{
- if (!characters() || from > textLength())
+ ASSERT(from + len <= textLength());
+ if (!characters())
return 0;
- if (from + len > textLength())
- len = textLength() - from;
-
int w;
if (&f == &style()->font()) {
- if (!style()->preserveNewline() && !from && len == textLength())
- w = maxPrefWidth();
- else
- w = widthFromCache(f, from, len, xPos);
+ if (!style()->preserveNewline() && !from && len == textLength()) {
+ if (fallbackFonts) {
+ if (prefWidthsDirty() || !m_knownNotToUseFallbackFonts) {
+ const_cast<RenderText*>(this)->calcPrefWidths(0, *fallbackFonts);
+ if (fallbackFonts->isEmpty())
+ m_knownNotToUseFallbackFonts = true;
+ }
+ w = m_maxWidth;
+ } else
+ w = maxPrefWidth();
+ } else
+ w = widthFromCache(f, from, len, xPos, fallbackFonts);
} else
- w = f.width(TextRun(text()->characters() + from, len, allowTabs(), xPos));
+ w = f.width(TextRun(text()->characters() + from, len, allowTabs(), xPos), fallbackFonts);
return w;
}
-int RenderText::width() const
+IntRect RenderText::linesBoundingBox() const
{
- // FIXME: we should not use an arbitrary value like this. Perhaps we should use INT_MAX.
- int minx = 100000000;
- int maxx = 0;
- // slooow
- for (InlineTextBox* s = firstTextBox(); s; s = s->nextTextBox()) {
- if (s->m_x < minx)
- minx = s->m_x;
- if (s->m_x + s->m_width > maxx)
- maxx = s->m_x + s->m_width;
+ IntRect result;
+
+ ASSERT(!firstTextBox() == !lastTextBox()); // Either both are null or both exist.
+ if (firstTextBox() && lastTextBox()) {
+ // Return the width of the minimal left side and the maximal right side.
+ int leftSide = 0;
+ int rightSide = 0;
+ for (InlineTextBox* curr = firstTextBox(); curr; curr = curr->nextTextBox()) {
+ if (curr == firstTextBox() || curr->x() < leftSide)
+ leftSide = curr->x();
+ if (curr == firstTextBox() || curr->x() + curr->width() > rightSide)
+ rightSide = curr->x() + curr->width();
+ }
+ result.setWidth(rightSide - leftSide);
+ result.setX(leftSide);
+ result.setHeight(lastTextBox()->y() + lastTextBox()->height() - firstTextBox()->y());
+ result.setY(firstTextBox()->y());
}
- return max(0, maxx - minx);
+ return result;
}
-IntRect RenderText::absoluteClippedOverflowRect()
+IntRect RenderText::clippedOverflowRectForRepaint(RenderBoxModelObject* repaintContainer)
{
RenderObject* cb = containingBlock();
- return cb->absoluteClippedOverflowRect();
+ return cb->clippedOverflowRectForRepaint(repaintContainer);
}
-IntRect RenderText::selectionRect(bool clipToVisibleContent)
+IntRect RenderText::selectionRectForRepaint(RenderBoxModelObject* repaintContainer, bool clipToVisibleContent)
{
ASSERT(!needsLayout());
- IntRect rect;
if (selectionState() == SelectionNone)
- return rect;
+ return IntRect();
RenderBlock* cb = containingBlock();
if (!cb)
- return rect;
+ return IntRect();
// Now calculate startPos and endPos for painting selection.
// We include a selection while endPos > 0
@@ -1113,39 +1148,32 @@ IntRect RenderText::selectionRect(bool clipToVisibleContent)
}
if (startPos == endPos)
- return rect;
+ return IntRect();
+ IntRect rect;
for (InlineTextBox* box = firstTextBox(); box; box = box->nextTextBox())
rect.unite(box->selectionRect(0, 0, startPos, endPos));
if (clipToVisibleContent)
- computeAbsoluteRepaintRect(rect);
+ computeRectForRepaint(repaintContainer, rect);
else {
if (cb->hasColumns())
cb->adjustRectForColumns(rect);
- // FIXME: This doesn't work correctly with transforms.
- FloatPoint absPos = localToAbsolute();
- rect.move(absPos.x(), absPos.y());
+
+ rect = localToContainerQuad(FloatRect(rect), repaintContainer).enclosingBoundingBox();
}
return rect;
}
-int RenderText::verticalPositionHint(bool firstLine) const
-{
- if (parent()->isReplaced())
- return 0; // Treat inline blocks just like blocks. There can't be any vertical position hint.
- return parent()->verticalPositionHint(firstLine);
-}
-
int RenderText::caretMinOffset() const
{
InlineTextBox* box = firstTextBox();
if (!box)
return 0;
- int minOffset = box->m_start;
+ int minOffset = box->start();
for (box = box->nextTextBox(); box; box = box->nextTextBox())
- minOffset = min(minOffset, box->m_start);
+ minOffset = min<int>(minOffset, box->start());
return minOffset;
}
@@ -1154,9 +1182,9 @@ int RenderText::caretMaxOffset() const
InlineTextBox* box = lastTextBox();
if (!box)
return textLength();
- int maxOffset = box->m_start + box->m_len;
+ int maxOffset = box->start() + box->len();
for (box = box->prevTextBox(); box; box = box->prevTextBox())
- maxOffset = max(maxOffset, box->m_start + box->m_len);
+ maxOffset = max<int>(maxOffset, box->start() + box->len());
return maxOffset;
}
@@ -1164,14 +1192,14 @@ unsigned RenderText::caretMaxRenderedOffset() const
{
int l = 0;
for (InlineTextBox* box = firstTextBox(); box; box = box->nextTextBox())
- l += box->m_len;
+ l += box->len();
return l;
}
int RenderText::previousOffset(int current) const
{
StringImpl* si = m_text.get();
- TextBreakIterator* iterator = characterBreakIterator(si->characters(), si->length());
+ TextBreakIterator* iterator = cursorMovementIterator(si->characters(), si->length());
if (!iterator)
return current - 1;
@@ -1179,13 +1207,122 @@ int RenderText::previousOffset(int current) const
if (result == TextBreakDone)
result = current - 1;
+#ifdef BUILDING_ON_TIGER
+ // ICU 3.2 allows character breaks before a half-width Katakana voiced mark.
+ if (static_cast<unsigned>(result) < si->length()) {
+ UChar character = (*si)[result];
+ if (character == 0xFF9E || character == 0xFF9F)
+ --result;
+ }
+#endif
+
return result;
}
+#define HANGUL_CHOSEONG_START (0x1100)
+#define HANGUL_CHOSEONG_END (0x115F)
+#define HANGUL_JUNGSEONG_START (0x1160)
+#define HANGUL_JUNGSEONG_END (0x11A2)
+#define HANGUL_JONGSEONG_START (0x11A8)
+#define HANGUL_JONGSEONG_END (0x11F9)
+#define HANGUL_SYLLABLE_START (0xAC00)
+#define HANGUL_SYLLABLE_END (0xD7AF)
+#define HANGUL_JONGSEONG_COUNT (28)
+
+enum HangulState {
+ HangulStateL,
+ HangulStateV,
+ HangulStateT,
+ HangulStateLV,
+ HangulStateLVT,
+ HangulStateBreak
+};
+
+inline bool isHangulLVT(UChar32 character)
+{
+ return (character - HANGUL_SYLLABLE_START) % HANGUL_JONGSEONG_COUNT;
+}
+
+int RenderText::previousOffsetForBackwardDeletion(int current) const
+{
+#if PLATFORM(MAC)
+ UChar32 character;
+ while (current > 0) {
+ if (U16_IS_TRAIL((*m_text)[--current]))
+ --current;
+ if (current < 0)
+ break;
+
+ UChar32 character = m_text->characterStartingAt(current);
+
+ // We don't combine characters in Armenian ... Limbu range for backward deletion.
+ if ((character >= 0x0530) && (character < 0x1950))
+ break;
+
+ if (u_isbase(character) && (character != 0xFF9E) && (character != 0xFF9F))
+ break;
+ }
+
+ if (current <= 0)
+ return current;
+
+ // Hangul
+ character = m_text->characterStartingAt(current);
+ if (((character >= HANGUL_CHOSEONG_START) && (character <= HANGUL_JONGSEONG_END)) || ((character >= HANGUL_SYLLABLE_START) && (character <= HANGUL_SYLLABLE_END))) {
+ HangulState state;
+ HangulState initialState;
+
+ if (character < HANGUL_JUNGSEONG_START)
+ state = HangulStateL;
+ else if (character < HANGUL_JONGSEONG_START)
+ state = HangulStateV;
+ else if (character < HANGUL_SYLLABLE_START)
+ state = HangulStateT;
+ else
+ state = isHangulLVT(character) ? HangulStateLVT : HangulStateLV;
+
+ initialState = state;
+
+ while (current > 0 && ((character = m_text->characterStartingAt(current - 1)) >= HANGUL_CHOSEONG_START) && (character <= HANGUL_SYLLABLE_END) && ((character <= HANGUL_JONGSEONG_END) || (character >= HANGUL_SYLLABLE_START))) {
+ switch (state) {
+ case HangulStateV:
+ if (character <= HANGUL_CHOSEONG_END)
+ state = HangulStateL;
+ else if ((character >= HANGUL_SYLLABLE_START) && (character <= HANGUL_SYLLABLE_END) && !isHangulLVT(character))
+ state = HangulStateLV;
+ else if (character > HANGUL_JUNGSEONG_END)
+ state = HangulStateBreak;
+ break;
+ case HangulStateT:
+ if ((character >= HANGUL_JUNGSEONG_START) && (character <= HANGUL_JUNGSEONG_END))
+ state = HangulStateV;
+ else if ((character >= HANGUL_SYLLABLE_START) && (character <= HANGUL_SYLLABLE_END))
+ state = (isHangulLVT(character) ? HangulStateLVT : HangulStateLV);
+ else if (character < HANGUL_JUNGSEONG_START)
+ state = HangulStateBreak;
+ break;
+ default:
+ state = (character < HANGUL_JUNGSEONG_START) ? HangulStateL : HangulStateBreak;
+ break;
+ }
+ if (state == HangulStateBreak)
+ break;
+
+ --current;
+ }
+ }
+
+ return current;
+#else
+ // Platforms other than Mac delete by one code point.
+ return current - 1;
+#endif
+}
+
int RenderText::nextOffset(int current) const
{
StringImpl* si = m_text.get();
- TextBreakIterator* iterator = characterBreakIterator(si->characters(), si->length());
+ TextBreakIterator* iterator = cursorMovementIterator(si->characters(), si->length());
if (!iterator)
return current + 1;
@@ -1193,6 +1330,15 @@ int RenderText::nextOffset(int current) const
if (result == TextBreakDone)
result = current + 1;
+#ifdef BUILDING_ON_TIGER
+ // ICU 3.2 allows character breaks before a half-width Katakana voiced mark.
+ if (static_cast<unsigned>(result) < si->length()) {
+ UChar character = (*si)[result];
+ if (character == 0xFF9E || character == 0xFF9F)
+ ++result;
+ }
+#endif
+
return result;
}
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderText.h b/src/3rdparty/webkit/WebCore/rendering/RenderText.h
index 4c62638..2e04a9e 100644
--- a/src/3rdparty/webkit/WebCore/rendering/RenderText.h
+++ b/src/3rdparty/webkit/WebCore/rendering/RenderText.h
@@ -1,7 +1,7 @@
/*
* (C) 1999 Lars Knoll (knoll@kde.org)
* (C) 2000 Dirk Mueller (mueller@kde.org)
- * Copyright (C) 2004, 2005, 2006, 2007 Apple Inc. All rights reserved.
+ * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. 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
@@ -52,26 +52,23 @@ public:
StringImpl* text() const { return m_text.get(); }
- virtual InlineBox* createInlineBox(bool makePlaceHolderBox, bool isRootLineBox, bool isOnlyRun = false);
- virtual InlineTextBox* createInlineTextBox();
- virtual void dirtyLineBoxes(bool fullLayout, bool isRootInlineBox = false);
+ InlineTextBox* createInlineTextBox();
+ void dirtyLineBoxes(bool fullLayout);
- virtual void absoluteRects(Vector<IntRect>&, int tx, int ty, bool topLevel = true);
- virtual void addLineBoxRects(Vector<IntRect>&, unsigned startOffset = 0, unsigned endOffset = UINT_MAX, bool useSelectionHeight = false);
+ virtual void absoluteRects(Vector<IntRect>&, int tx, int ty);
+ void absoluteRectsForRange(Vector<IntRect>&, unsigned startOffset = 0, unsigned endOffset = UINT_MAX, bool useSelectionHeight = false);
- virtual void absoluteQuads(Vector<FloatQuad>&, bool topLevel = true);
- virtual void collectAbsoluteLineBoxQuads(Vector<FloatQuad>&, unsigned startOffset = 0, unsigned endOffset = UINT_MAX, bool useSelectionHeight = false);
+ virtual void absoluteQuads(Vector<FloatQuad>&);
+ void absoluteQuadsForRange(Vector<FloatQuad>&, unsigned startOffset = 0, unsigned endOffset = UINT_MAX, bool useSelectionHeight = false);
- virtual VisiblePosition positionForCoordinates(int x, int y);
+ virtual VisiblePosition positionForPoint(const IntPoint&);
const UChar* characters() const { return m_text->characters(); }
unsigned textLength() const { return m_text->length(); } // non virtual implementation of length()
- virtual void position(InlineBox*);
+ void positionLineBox(InlineBox*);
- virtual unsigned width(unsigned from, unsigned len, const Font&, int xPos) const;
- virtual unsigned width(unsigned from, unsigned len, int xPos, bool firstLine = false) const;
- virtual int width() const;
- virtual int height() const;
+ virtual unsigned width(unsigned from, unsigned len, const Font&, int xPos, HashSet<const SimpleFontData*>* fallbackFonts = 0) const;
+ virtual unsigned width(unsigned from, unsigned len, int xPos, bool firstLine = false, HashSet<const SimpleFontData*>* fallbackFonts = 0) const;
virtual int lineHeight(bool firstLine, bool isRootLineBox = false) const;
@@ -85,28 +82,24 @@ public:
int& beginMaxW, int& endMaxW,
int& minW, int& maxW, bool& stripFrontSpaces);
- // returns the minimum x position of all runs relative to the parent.
- // defaults to 0.
- int minXPos() const;
+ IntRect linesBoundingBox() const;
- virtual int xPos() const;
- virtual int yPos() const;
-
- virtual int verticalPositionHint(bool firstLine) const;
+ IntPoint firstRunOrigin() const;
+ int firstRunX() const;
+ int firstRunY() const;
void setText(PassRefPtr<StringImpl>, bool force = false);
void setTextWithOffset(PassRefPtr<StringImpl>, unsigned offset, unsigned len, bool force = false);
virtual bool canBeSelectionLeaf() const { return true; }
- virtual SelectionState selectionState() const { return static_cast<SelectionState>(m_selectionState); }
virtual void setSelectionState(SelectionState s);
- virtual IntRect selectionRect(bool clipToVisibleContent = true);
+ virtual IntRect selectionRectForRepaint(RenderBoxModelObject* repaintContainer, bool clipToVisibleContent = true);
virtual IntRect localCaretRect(InlineBox*, int caretOffset, int* extraWidthToEndOfLine = 0);
virtual int marginLeft() const { return style()->marginLeft().calcMinValue(0); }
virtual int marginRight() const { return style()->marginRight().calcMinValue(0); }
- virtual IntRect absoluteClippedOverflowRect();
+ virtual IntRect clippedOverflowRectForRepaint(RenderBoxModelObject* repaintContainer);
InlineTextBox* firstTextBox() const { return m_firstTextBox; }
InlineTextBox* lastTextBox() const { return m_lastTextBox; }
@@ -116,6 +109,7 @@ public:
virtual unsigned caretMaxRenderedOffset() const;
virtual int previousOffset(int current) const;
+ virtual int previousOffsetForBackwardDeletion(int current) const;
virtual int nextOffset(int current) const;
bool containsReversedText() const { return m_containsReversedText; }
@@ -126,14 +120,20 @@ public:
void checkConsistency() const;
+ virtual void calcPrefWidths(int leadWidth);
+
protected:
- virtual void styleDidChange(RenderStyle::Diff, const RenderStyle* oldStyle);
+ virtual void styleWillChange(StyleDifference, const RenderStyle*) { }
+ virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
virtual void setTextInternal(PassRefPtr<StringImpl>);
- virtual void calcPrefWidths(int leadWidth);
virtual UChar previousCharacter();
+
+ virtual InlineTextBox* createTextBox(); // Subclassed by SVG.
private:
+ void calcPrefWidths(int leadWidth, HashSet<const SimpleFontData*>& fallbackFonts);
+
// Make length() private so that callers that have a RenderText*
// will use the more efficient textLength() instead, while
// callers with a RenderObject* can continue to use length().
@@ -145,20 +145,20 @@ private:
void deleteTextBoxes();
bool containsOnlyWhitespace(unsigned from, unsigned len) const;
- int widthFromCache(const Font&, int start, int len, int xPos) const;
+ int widthFromCache(const Font&, int start, int len, int xPos, HashSet<const SimpleFontData*>* fallbackFonts) const;
bool isAllASCII() const { return m_isAllASCII; }
+ int m_minWidth; // here to minimize padding in 64-bit.
+
RefPtr<StringImpl> m_text;
InlineTextBox* m_firstTextBox;
InlineTextBox* m_lastTextBox;
- int m_minWidth;
int m_maxWidth;
int m_beginMinWidth;
int m_endMinWidth;
- unsigned m_selectionState : 3; // enums on Windows are signed, so this needs to be unsigned to prevent it turning negative.
bool m_hasBreakableChar : 1; // Whether or not we can be broken into multiple lines.
bool m_hasBreak : 1; // Whether or not we have a hard break (e.g., <pre> with '\n').
bool m_hasTab : 1; // Whether or not we have a variable width tab character (e.g., <pre> with '\t').
@@ -170,8 +170,24 @@ private:
// or removed).
bool m_containsReversedText : 1;
bool m_isAllASCII : 1;
+ mutable bool m_knownNotToUseFallbackFonts : 1;
};
+inline RenderText* toRenderText(RenderObject* o)
+{
+ ASSERT(!o || o->isText());
+ return static_cast<RenderText*>(o);
+}
+
+inline const RenderText* toRenderText(const RenderObject* o)
+{
+ ASSERT(!o || o->isText());
+ return static_cast<const RenderText*>(o);
+}
+
+// This will catch anyone doing an unnecessary cast.
+void toRenderText(const RenderText*);
+
#ifdef NDEBUG
inline void RenderText::checkConsistency() const
{
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderTextControl.cpp b/src/3rdparty/webkit/WebCore/rendering/RenderTextControl.cpp
index 8f853f8..29c8c8a 100644
--- a/src/3rdparty/webkit/WebCore/rendering/RenderTextControl.cpp
+++ b/src/3rdparty/webkit/WebCore/rendering/RenderTextControl.cpp
@@ -22,19 +22,21 @@
#include "config.h"
#include "RenderTextControl.h"
+#include "AXObjectCache.h"
#include "CharacterNames.h"
#include "Editor.h"
#include "Event.h"
#include "EventNames.h"
#include "Frame.h"
#include "HTMLBRElement.h"
-#include "HTMLFormControlElement.h"
#include "HTMLNames.h"
#include "HitTestResult.h"
+#include "RenderLayer.h"
+#include "RenderText.h"
#include "ScrollbarTheme.h"
#include "SelectionController.h"
-#include "TextControlInnerElements.h"
#include "Text.h"
+#include "TextControlInnerElements.h"
#include "TextIterator.h"
using namespace std;
@@ -79,12 +81,12 @@ RenderTextControl::~RenderTextControl()
m_innerText->detach();
}
-void RenderTextControl::styleDidChange(RenderStyle::Diff diff, const RenderStyle* oldStyle)
+void RenderTextControl::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
{
RenderBlock::styleDidChange(diff, oldStyle);
if (m_innerText) {
- RenderBlock* textBlockRenderer = static_cast<RenderBlock*>(m_innerText->renderer());
+ RenderBlock* textBlockRenderer = toRenderBlock(m_innerText->renderer());
RefPtr<RenderStyle> textBlockStyle = createInnerTextStyle(style());
// We may have set the width and the height in the old style in layout().
// Reset them now to avoid getting a spurious layout hint.
@@ -97,18 +99,32 @@ void RenderTextControl::styleDidChange(RenderStyle::Diff diff, const RenderStyle
}
}
- setHasOverflowClip(false);
setReplaced(isInline());
}
+static inline bool updateUserModifyProperty(Node* node, RenderStyle* style)
+{
+ bool isEnabled = true;
+ bool isReadOnlyControl = false;
+
+ if (node->isElementNode()) {
+ Element* element = static_cast<Element*>(node);
+ isEnabled = element->isEnabledFormControl();
+ isReadOnlyControl = element->isReadOnlyFormControl();
+ }
+
+ style->setUserModify((isReadOnlyControl || !isEnabled) ? READ_ONLY : READ_WRITE_PLAINTEXT_ONLY);
+ return !isEnabled;
+}
+
void RenderTextControl::adjustInnerTextStyle(const RenderStyle* startStyle, RenderStyle* textBlockStyle) const
{
// The inner block, if present, always has its direction set to LTR,
// so we need to inherit the direction from the element.
textBlockStyle->setDirection(style()->direction());
- textBlockStyle->setUserModify((node()->isReadOnlyControl() || !node()->isEnabled()) ? READ_ONLY : READ_WRITE_PLAINTEXT_ONLY);
- if (!node()->isEnabled())
+ bool disabled = updateUserModifyProperty(node(), textBlockStyle);
+ if (disabled)
textBlockStyle->setColor(disabledTextColor(textBlockStyle->color(), startStyle->backgroundColor()));
}
@@ -126,18 +142,18 @@ void RenderTextControl::createSubtreeIfNeeded(TextControlInnerElement* innerBloc
int RenderTextControl::textBlockHeight() const
{
- return m_height - paddingTop() - paddingBottom() - borderTop() - borderBottom();
+ return height() - paddingTop() - paddingBottom() - borderTop() - borderBottom();
}
int RenderTextControl::textBlockWidth() const
{
- return m_width - paddingLeft() - paddingRight() - borderLeft() - borderRight()
- - m_innerText->renderer()->paddingLeft() - m_innerText->renderer()->paddingRight();
+ return width() - paddingLeft() - paddingRight() - borderLeft() - borderRight()
+ - m_innerText->renderBox()->paddingLeft() - m_innerText->renderBox()->paddingRight();
}
void RenderTextControl::updateFromElement()
{
- m_innerText->renderer()->style()->setUserModify((node()->isReadOnlyControl() || !node()->isEnabled()) ? READ_ONLY : READ_WRITE_PLAINTEXT_ONLY);
+ updateUserModifyProperty(node(), m_innerText->renderer()->style());
}
void RenderTextControl::setInnerTextValue(const String& innerTextValue)
@@ -148,13 +164,17 @@ void RenderTextControl::setInnerTextValue(const String& innerTextValue)
value = "";
else {
value = innerTextValue;
- value = value.replace('\\', backslashAsCurrencySymbol());
+ value = document()->displayStringModifiedByEncoding(value);
}
if (value != text() || !m_innerText->hasChildNodes()) {
if (value != text()) {
- if (Frame* frame = document()->frame())
+ if (Frame* frame = document()->frame()) {
frame->editor()->clearUndoRedoOperations();
+
+ if (AXObjectCache::accessibilityEnabled())
+ document()->axObjectCache()->postNotification(this, "AXValueChanged", false);
+ }
}
ExceptionCode ec = 0;
@@ -170,7 +190,7 @@ void RenderTextControl::setInnerTextValue(const String& innerTextValue)
m_userEdited = false;
}
- formControlElement()->setValueMatchesRenderer();
+ static_cast<Element*>(node())->setFormControlValueMatchesRenderer(true);
}
void RenderTextControl::setUserEdited(bool isUserEdited)
@@ -217,7 +237,7 @@ void RenderTextControl::setSelectionRange(int start, int end)
document()->updateLayout();
- if (style()->visibility() == HIDDEN || !m_innerText || !m_innerText->renderer() || !m_innerText->renderer()->height()) {
+ if (style()->visibility() == HIDDEN || !m_innerText || !m_innerText->renderer() || !m_innerText->renderBox()->height()) {
cacheSelection(start, end);
return;
}
@@ -228,10 +248,12 @@ void RenderTextControl::setSelectionRange(int start, int end)
else
endPosition = visiblePositionForIndex(end);
- ASSERT(startPosition.isNotNull() && endPosition.isNotNull());
- ASSERT(startPosition.deepEquivalent().node()->shadowAncestorNode() == node() && endPosition.deepEquivalent().node()->shadowAncestorNode() == node());
-
- Selection newSelection = Selection(startPosition, endPosition);
+ // startPosition and endPosition can be null position for example when
+ // "-webkit-user-select: none" style attribute is specified.
+ if (startPosition.isNotNull() && endPosition.isNotNull()) {
+ ASSERT(startPosition.deepEquivalent().node()->shadowAncestorNode() == node() && endPosition.deepEquivalent().node()->shadowAncestorNode() == node());
+ }
+ VisibleSelection newSelection = VisibleSelection(startPosition, endPosition);
if (Frame* frame = document()->frame())
frame->selection()->setSelection(newSelection);
@@ -242,10 +264,10 @@ void RenderTextControl::setSelectionRange(int start, int end)
frame->setSelectionGranularity(CharacterGranularity);
}
-Selection RenderTextControl::selection(int start, int end) const
+VisibleSelection RenderTextControl::selection(int start, int end) const
{
- return Selection(VisiblePosition(m_innerText.get(), start, VP_DEFAULT_AFFINITY),
- VisiblePosition(m_innerText.get(), end, VP_DEFAULT_AFFINITY));
+ return VisibleSelection(VisiblePosition(m_innerText.get(), start, VP_DEFAULT_AFFINITY),
+ VisiblePosition(m_innerText.get(), end, VP_DEFAULT_AFFINITY));
}
VisiblePosition RenderTextControl::visiblePositionForIndex(int index)
@@ -274,7 +296,7 @@ int RenderTextControl::indexForVisiblePosition(const VisiblePosition& pos)
RefPtr<Range> range = Range::create(document());
range->setStart(m_innerText.get(), 0, ec);
ASSERT(!ec);
- range->setEnd(indexPosition.node(), indexPosition.offset(), ec);
+ range->setEnd(indexPosition.node(), indexPosition.deprecatedEditingOffset(), ec);
ASSERT(!ec);
return TextIterator::rangeLength(range.get());
}
@@ -293,14 +315,8 @@ String RenderTextControl::finishText(Vector<UChar>& result) const
result.shrink(--size);
// Convert backslash to currency symbol.
- UChar symbol = backslashAsCurrencySymbol();
- if (symbol != '\\') {
- for (size_t i = 0; i < size; ++i) {
- if (result[i] == '\\')
- result[i] = symbol;
- }
- }
-
+ document()->displayBufferModifiedByEncoding(result.data(), result.size());
+
return String::adopt(result);
}
@@ -349,6 +365,7 @@ static void getNextSoftBreak(RootInlineBox*& line, Node*& breakNode, unsigned& b
}
}
breakNode = 0;
+ breakOffset = 0;
}
String RenderTextControl::textWithHardLineBreaks()
@@ -365,7 +382,7 @@ String RenderTextControl::textWithHardLineBreaks()
if (!renderer)
return "";
- InlineBox* box = renderer->isText() ? static_cast<RenderText*>(renderer)->firstTextBox() : renderer->inlineBoxWrapper();
+ InlineBox* box = renderer->isText() ? toRenderText(renderer)->firstTextBox() : toRenderBox(renderer)->inlineBoxWrapper();
if (!box)
return "";
@@ -424,25 +441,26 @@ int RenderTextControl::scrollbarThickness() const
void RenderTextControl::calcHeight()
{
- m_height = m_innerText->renderer()->borderTop() + m_innerText->renderer()->borderBottom() +
- m_innerText->renderer()->paddingTop() + m_innerText->renderer()->paddingBottom() +
- m_innerText->renderer()->marginTop() + m_innerText->renderer()->marginBottom();
+ setHeight(m_innerText->renderBox()->borderTop() + m_innerText->renderBox()->borderBottom() +
+ m_innerText->renderBox()->paddingTop() + m_innerText->renderBox()->paddingBottom() +
+ m_innerText->renderBox()->marginTop() + m_innerText->renderBox()->marginBottom());
adjustControlHeightBasedOnLineHeight(m_innerText->renderer()->lineHeight(true, true));
- m_height += paddingTop() + paddingBottom() + borderTop() + borderBottom();
+ setHeight(height() + paddingTop() + paddingBottom() + borderTop() + borderBottom());
// We are able to have a horizontal scrollbar if the overflow style is scroll, or if its auto and there's no word wrap.
- if (m_innerText->renderer()->style()->overflowX() == OSCROLL || (m_innerText->renderer()->style()->overflowX() == OAUTO && m_innerText->renderer()->style()->wordWrap() == NormalWordWrap))
- m_height += scrollbarThickness();
+ if (style()->overflowX() == OSCROLL || (style()->overflowX() == OAUTO && m_innerText->renderer()->style()->wordWrap() == NormalWordWrap))
+ setHeight(height() + scrollbarThickness());
RenderBlock::calcHeight();
}
-void RenderTextControl::hitInnerTextBlock(HitTestResult& result, int x, int y, int tx, int ty)
+void RenderTextControl::hitInnerTextElement(HitTestResult& result, int xPos, int yPos, int tx, int ty)
{
result.setInnerNode(m_innerText.get());
- result.setLocalPoint(IntPoint(x - tx - m_x - m_innerText->renderer()->xPos(),
- y - ty - m_y - m_innerText->renderer()->yPos()));
+ result.setInnerNonSharedNode(m_innerText.get());
+ result.setLocalPoint(IntPoint(xPos - tx - x() - m_innerText->renderBox()->x(),
+ yPos - ty - y() - m_innerText->renderBox()->y()));
}
void RenderTextControl::forwardEvent(Event* event)
@@ -454,7 +472,7 @@ void RenderTextControl::forwardEvent(Event* event)
IntRect RenderTextControl::controlClipRect(int tx, int ty) const
{
- IntRect clipRect = contentBox();
+ IntRect clipRect = contentBoxRect();
clipRect.move(tx, ty);
return clipRect;
}
@@ -469,11 +487,9 @@ void RenderTextControl::calcPrefWidths()
if (style()->width().isFixed() && style()->width().value() > 0)
m_minPrefWidth = m_maxPrefWidth = calcContentBoxWidth(style()->width().value());
else {
- // Figure out how big a text control needs to be for a given number of characters
- // (using "0" as the nominal character).
- const UChar ch = '0';
- float charWidth = style()->font().floatWidth(TextRun(&ch, 1, false, 0, 0, false, false, false));
- m_maxPrefWidth = preferredContentWidth(charWidth) + m_innerText->renderer()->paddingLeft() + m_innerText->renderer()->paddingRight();
+ // Use average character width. Matches IE.
+ float charWidth = style()->font().primaryFont()->avgCharWidth();
+ m_maxPrefWidth = preferredContentWidth(charWidth) + m_innerText->renderBox()->paddingLeft() + m_innerText->renderBox()->paddingRight();
}
if (style()->minWidth().isFixed() && style()->minWidth().value() > 0) {
@@ -503,7 +519,7 @@ void RenderTextControl::selectionChanged(bool userTriggered)
if (Frame* frame = document()->frame()) {
if (frame->selection()->isRange() && userTriggered)
- static_cast<EventTargetNode*>(node())->dispatchEventForType(eventNames().selectEvent, true, false);
+ node()->dispatchEvent(eventNames().selectEvent, true, false);
}
}
@@ -512,80 +528,9 @@ void RenderTextControl::addFocusRingRects(GraphicsContext* graphicsContext, int
graphicsContext->addFocusRingRect(IntRect(tx, ty, width(), height()));
}
-void RenderTextControl::autoscroll()
-{
- RenderLayer* layer = m_innerText->renderer()->layer();
- if (layer)
- layer->autoscroll();
-}
-
-int RenderTextControl::scrollWidth() const
-{
- if (m_innerText)
- return m_innerText->scrollWidth();
- return RenderBlock::scrollWidth();
-}
-
-int RenderTextControl::scrollHeight() const
-{
- if (m_innerText)
- return m_innerText->scrollHeight();
- return RenderBlock::scrollHeight();
-}
-
-int RenderTextControl::scrollLeft() const
-{
- if (m_innerText)
- return m_innerText->scrollLeft();
- return RenderBlock::scrollLeft();
-}
-
-int RenderTextControl::scrollTop() const
-{
- if (m_innerText)
- return m_innerText->scrollTop();
- return RenderBlock::scrollTop();
-}
-
-void RenderTextControl::setScrollLeft(int newLeft)
-{
- if (m_innerText)
- m_innerText->setScrollLeft(newLeft);
-}
-
-void RenderTextControl::setScrollTop(int newTop)
-{
- if (m_innerText)
- m_innerText->setScrollTop(newTop);
-}
-
-bool RenderTextControl::scroll(ScrollDirection direction, ScrollGranularity granularity, float multiplier)
-{
- RenderLayer* layer = m_innerText->renderer()->layer();
- if (layer && layer->scroll(direction, granularity, multiplier))
- return true;
- return RenderObject::scroll(direction, granularity, multiplier);
-}
-
-bool RenderTextControl::isScrollable() const
-{
- if (m_innerText && m_innerText->renderer()->isScrollable())
- return true;
- return RenderObject::isScrollable();
-}
-
HTMLElement* RenderTextControl::innerTextElement() const
{
return m_innerText.get();
}
-FormControlElement* RenderTextControl::formControlElement() const
-{
- if (node()->isHTMLElement())
- return static_cast<HTMLFormControlElement*>(node());
-
- ASSERT_NOT_REACHED();
- return 0;
-}
-
} // namespace WebCore
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderTextControl.h b/src/3rdparty/webkit/WebCore/rendering/RenderTextControl.h
index 40f5116..bce9619 100644
--- a/src/3rdparty/webkit/WebCore/rendering/RenderTextControl.h
+++ b/src/3rdparty/webkit/WebCore/rendering/RenderTextControl.h
@@ -26,8 +26,7 @@
namespace WebCore {
-class FormControlElement;
-class Selection;
+class VisibleSelection;
class TextControlInnerElement;
class TextControlInnerTextElement;
@@ -36,6 +35,7 @@ public:
virtual ~RenderTextControl();
virtual const char* renderName() const { return "RenderTextControl"; }
+ virtual bool isTextControl() const { return true; }
virtual bool hasControlClip() const { return false; }
virtual IntRect controlClipRect(int tx, int ty) const;
virtual void calcHeight();
@@ -45,8 +45,8 @@ public:
virtual bool canHaveChildren() const { return false; }
virtual bool avoidsFloats() const { return true; }
- virtual bool isEdited() const { return m_edited; }
- virtual void setEdited(bool isEdited) { m_edited = isEdited; }
+ bool isEdited() const { return m_edited; }
+ void setEdited(bool isEdited) { m_edited = isEdited; }
bool isUserEdited() const { return m_userEdited; }
void setUserEdited(bool isUserEdited);
@@ -57,7 +57,7 @@ public:
void setSelectionEnd(int);
void select();
void setSelectionRange(int start, int end);
- Selection selection(int start, int end) const;
+ VisibleSelection selection(int start, int end) const;
virtual void subtreeHasChanged();
String text();
@@ -67,17 +67,6 @@ public:
virtual void addFocusRingRects(GraphicsContext*, int tx, int ty);
virtual bool canBeProgramaticallyScrolled(bool) const { return true; }
- virtual void autoscroll();
-
- // Subclassed to forward to our inner div.
- virtual int scrollLeft() const;
- virtual int scrollTop() const;
- virtual int scrollWidth() const;
- virtual int scrollHeight() const;
- virtual void setScrollLeft(int);
- virtual void setScrollTop(int);
- virtual bool scroll(ScrollDirection, ScrollGranularity, float multiplier = 1.0f);
- virtual bool isScrollable() const;
VisiblePosition visiblePositionForIndex(int index);
int indexForVisiblePosition(const VisiblePosition&);
@@ -89,10 +78,10 @@ protected:
void adjustInnerTextStyle(const RenderStyle* startStyle, RenderStyle* textBlockStyle) const;
void setInnerTextValue(const String&);
- virtual void styleDidChange(RenderStyle::Diff, const RenderStyle* oldStyle);
+ virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
void createSubtreeIfNeeded(TextControlInnerElement* innerBlock);
- void hitInnerTextBlock(HitTestResult&, int x, int y, int tx, int ty);
+ void hitInnerTextElement(HitTestResult&, int x, int y, int tx, int ty);
void forwardEvent(Event*);
int textBlockWidth() const;
@@ -106,8 +95,6 @@ protected:
friend class TextIterator;
HTMLElement* innerTextElement() const;
- FormControlElement* formControlElement() const;
-
private:
String finishText(Vector<UChar>&) const;
@@ -116,6 +103,21 @@ private:
RefPtr<TextControlInnerTextElement> m_innerText;
};
+inline RenderTextControl* toRenderTextControl(RenderObject* o)
+{
+ ASSERT(!o || o->isTextControl());
+ return static_cast<RenderTextControl*>(o);
+}
+
+inline const RenderTextControl* toRenderTextControl(const RenderObject* o)
+{
+ ASSERT(!o || o->isTextControl());
+ return static_cast<const RenderTextControl*>(o);
+}
+
+// This will catch anyone doing an unnecessary cast.
+void toRenderTextControl(const RenderTextControl*);
+
} // namespace WebCore
#endif // RenderTextControl_h
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderTextControlMultiLine.cpp b/src/3rdparty/webkit/WebCore/rendering/RenderTextControlMultiLine.cpp
index f860524..df31c2b 100644
--- a/src/3rdparty/webkit/WebCore/rendering/RenderTextControlMultiLine.cpp
+++ b/src/3rdparty/webkit/WebCore/rendering/RenderTextControlMultiLine.cpp
@@ -43,52 +43,27 @@ RenderTextControlMultiLine::~RenderTextControlMultiLine()
void RenderTextControlMultiLine::subtreeHasChanged()
{
RenderTextControl::subtreeHasChanged();
- formControlElement()->setValueMatchesRenderer(false);
+ static_cast<Element*>(node())->setFormControlValueMatchesRenderer(false);
if (!node()->focused())
return;
+ // Fire the "input" DOM event
+ node()->dispatchEvent(eventNames().inputEvent, true, false);
+
if (Frame* frame = document()->frame())
frame->textDidChangeInTextArea(static_cast<Element*>(node()));
}
-void RenderTextControlMultiLine::layout()
-{
- int oldHeight = m_height;
- calcHeight();
-
- int oldWidth = m_width;
- calcWidth();
-
- bool relayoutChildren = oldHeight != m_height || oldWidth != m_width;
- RenderObject* innerTextRenderer = innerTextElement()->renderer();
-
- // Set the text block height
- int desiredHeight = textBlockHeight();
- if (desiredHeight != innerTextRenderer->height())
- relayoutChildren = true;
- innerTextRenderer->style()->setHeight(Length(desiredHeight, Fixed));
-
- // Set the text block width
- int desiredWidth = textBlockWidth();
- if (desiredWidth != innerTextRenderer->width())
- relayoutChildren = true;
- innerTextRenderer->style()->setWidth(Length(desiredWidth, Fixed));
-
- RenderBlock::layoutBlock(relayoutChildren);
-}
-
bool RenderTextControlMultiLine::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, int x, int y, int tx, int ty, HitTestAction hitTestAction)
{
if (!RenderTextControl::nodeAtPoint(request, result, x, y, tx, ty, hitTestAction))
return false;
- if (result.innerNode() == element()) {
- hitInnerTextBlock(result, x, y, tx, ty);
- return true;
- }
+ if (result.innerNode() == node() || result.innerNode() == innerTextElement())
+ hitInnerTextElement(result, x, y, tx, ty);
- return false;
+ return true;
}
void RenderTextControlMultiLine::forwardEvent(Event* event)
@@ -104,7 +79,7 @@ int RenderTextControlMultiLine::preferredContentWidth(float charWidth) const
void RenderTextControlMultiLine::adjustControlHeightBasedOnLineHeight(int lineHeight)
{
- m_height += lineHeight * static_cast<HTMLTextAreaElement*>(node())->rows();
+ setHeight(height() + lineHeight * static_cast<HTMLTextAreaElement*>(node())->rows());
}
int RenderTextControlMultiLine::baselinePosition(bool, bool) const
@@ -132,10 +107,9 @@ PassRefPtr<RenderStyle> RenderTextControlMultiLine::createInnerTextStyle(const R
adjustInnerTextStyle(startStyle, textBlockStyle.get());
- // Forward overflow properties.
- textBlockStyle->setOverflowX(startStyle->overflowX() == OVISIBLE ? OAUTO : startStyle->overflowX());
- textBlockStyle->setOverflowY(startStyle->overflowY() == OVISIBLE ? OAUTO : startStyle->overflowY());
-
+ // FIXME: This code should just map wrap into CSS in the DOM code.
+ // Then here we should set the textBlockStyle appropriately based off this
+ // object's style()->whiteSpace() and style->wordWrap().
// Set word wrap property based on wrap attribute.
if (static_cast<HTMLTextAreaElement*>(node())->shouldWrapText()) {
textBlockStyle->setWhiteSpace(PRE_WRAP);
@@ -147,10 +121,6 @@ PassRefPtr<RenderStyle> RenderTextControlMultiLine::createInnerTextStyle(const R
textBlockStyle->setDisplay(BLOCK);
- // We're adding three extra pixels of padding to line textareas up with text fields.
- textBlockStyle->setPaddingLeft(Length(3, Fixed));
- textBlockStyle->setPaddingRight(Length(3, Fixed));
-
return textBlockStyle.release();
}
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderTextControlMultiLine.h b/src/3rdparty/webkit/WebCore/rendering/RenderTextControlMultiLine.h
index 591a65d..579047d 100644
--- a/src/3rdparty/webkit/WebCore/rendering/RenderTextControlMultiLine.h
+++ b/src/3rdparty/webkit/WebCore/rendering/RenderTextControlMultiLine.h
@@ -33,7 +33,6 @@ public:
virtual bool isTextArea() const { return true; }
virtual void subtreeHasChanged();
- virtual void layout();
virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, int x, int y, int tx, int ty, HitTestAction);
void forwardEvent(Event*);
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderTextControlSingleLine.cpp b/src/3rdparty/webkit/WebCore/rendering/RenderTextControlSingleLine.cpp
index 4f52527..a5db44e 100644
--- a/src/3rdparty/webkit/WebCore/rendering/RenderTextControlSingleLine.cpp
+++ b/src/3rdparty/webkit/WebCore/rendering/RenderTextControlSingleLine.cpp
@@ -30,6 +30,7 @@
#include "HitTestResult.h"
#include "HTMLInputElement.h"
#include "HTMLNames.h"
+#include "InputElement.h"
#include "LocalizedStrings.h"
#include "MouseEvent.h"
#include "PlatformKeyboardEvent.h"
@@ -38,6 +39,7 @@
#include "SearchPopupMenu.h"
#include "SelectionController.h"
#include "Settings.h"
+#include "SimpleFontData.h"
#include "TextControlInnerElements.h"
using namespace std;
@@ -69,7 +71,7 @@ RenderTextControlSingleLine::~RenderTextControlSingleLine()
bool RenderTextControlSingleLine::placeholderShouldBeVisible() const
{
- return static_cast<HTMLInputElement*>(node())->placeholderShouldBeVisible();
+ return inputElement()->placeholderShouldBeVisible();
}
void RenderTextControlSingleLine::updatePlaceholderVisibility()
@@ -90,6 +92,7 @@ void RenderTextControlSingleLine::updatePlaceholderVisibility()
void RenderTextControlSingleLine::addSearchResult()
{
+ ASSERT(node()->isHTMLElement());
HTMLInputElement* input = static_cast<HTMLInputElement*>(node());
if (input->maxResults() <= 0)
return;
@@ -121,11 +124,13 @@ void RenderTextControlSingleLine::addSearchResult()
void RenderTextControlSingleLine::stopSearchEventTimer()
{
+ ASSERT(node()->isHTMLElement());
m_searchEventTimer.stop();
}
void RenderTextControlSingleLine::showPopup()
{
+ ASSERT(node()->isHTMLElement());
if (m_searchPopupIsVisible)
return;
@@ -155,6 +160,7 @@ void RenderTextControlSingleLine::showPopup()
void RenderTextControlSingleLine::hidePopup()
{
+ ASSERT(node()->isHTMLElement());
if (m_searchPopup)
m_searchPopup->hide();
@@ -166,24 +172,24 @@ void RenderTextControlSingleLine::subtreeHasChanged()
bool wasEdited = isEdited();
RenderTextControl::subtreeHasChanged();
- HTMLInputElement* input = static_cast<HTMLInputElement*>(node());
+ InputElement* input = inputElement();
input->setValueFromRenderer(input->constrainValue(text()));
- if (RenderObject* cancelButtonRenderer = m_cancelButton ? m_cancelButton->renderer() : 0)
- updateCancelButtonVisibility(cancelButtonRenderer->style());
+ if (m_cancelButton)
+ updateCancelButtonVisibility();
// If the incremental attribute is set, then dispatch the search event
- if (!input->getAttribute(incrementalAttr).isNull())
+ if (input->searchEventsShouldBeDispatched())
startSearchEventTimer();
- if (!wasEdited && input->focused()) {
+ if (!wasEdited && node()->focused()) {
if (Frame* frame = document()->frame())
- frame->textFieldDidBeginEditing(input);
+ frame->textFieldDidBeginEditing(static_cast<Element*>(node()));
}
- if (input->focused()) {
+ if (node()->focused()) {
if (Frame* frame = document()->frame())
- frame->textDidChangeInTextField(input);
+ frame->textDidChangeInTextField(static_cast<Element*>(node()));
}
}
@@ -192,42 +198,37 @@ void RenderTextControlSingleLine::paint(PaintInfo& paintInfo, int tx, int ty)
RenderTextControl::paint(paintInfo, tx, ty);
if (paintInfo.phase == PaintPhaseBlockBackground && m_shouldDrawCapsLockIndicator) {
- IntRect contentsRect = contentBox();
+ IntRect contentsRect = contentBoxRect();
// Convert the rect into the coords used for painting the content
- contentsRect.move(tx + xPos(), ty + yPos());
+ contentsRect.move(tx + x(), ty + y());
theme()->paintCapsLockIndicator(this, paintInfo, contentsRect);
}
}
void RenderTextControlSingleLine::layout()
{
- int oldHeight = m_height;
+ int oldHeight = height();
calcHeight();
- int oldWidth = m_width;
+ int oldWidth = width();
calcWidth();
- bool relayoutChildren = oldHeight != m_height || oldWidth != m_width;
+ bool relayoutChildren = oldHeight != height() || oldWidth != width();
- RenderObject* innerTextRenderer = innerTextElement()->renderer();
- RenderObject* innerBlockRenderer = m_innerBlock ? m_innerBlock->renderer() : 0;
+ RenderBox* innerTextRenderer = innerTextElement()->renderBox();
+ RenderBox* innerBlockRenderer = m_innerBlock ? m_innerBlock->renderBox() : 0;
// Set the text block height
int desiredHeight = textBlockHeight();
int currentHeight = innerTextRenderer->height();
- if (m_innerBlock || currentHeight > m_height) {
+ if (currentHeight > height()) {
if (desiredHeight != currentHeight)
relayoutChildren = true;
innerTextRenderer->style()->setHeight(Length(desiredHeight, Fixed));
- }
-
- if (m_innerBlock) {
- ASSERT(innerBlockRenderer);
- if (desiredHeight != innerBlockRenderer->height())
- relayoutChildren = true;
- innerBlockRenderer->style()->setHeight(Length(desiredHeight, Fixed));
+ if (m_innerBlock)
+ innerBlockRenderer->style()->setHeight(Length(desiredHeight, Fixed));
}
// Set the text block width
@@ -237,7 +238,7 @@ void RenderTextControlSingleLine::layout()
innerTextRenderer->style()->setWidth(Length(desiredWidth, Fixed));
if (m_innerBlock) {
- int innerBlockWidth = m_width - paddingLeft() - paddingRight() - borderLeft() - borderRight();
+ int innerBlockWidth = width() - paddingLeft() - paddingRight() - borderLeft() - borderRight();
if (innerBlockWidth != innerBlockRenderer->width())
relayoutChildren = true;
innerBlockRenderer->style()->setWidth(Length(innerBlockWidth, Fixed));
@@ -245,16 +246,14 @@ void RenderTextControlSingleLine::layout()
RenderBlock::layoutBlock(relayoutChildren);
- // For text fields, center the inner text vertically
- // Don't do this for search fields, since we don't honor height for them
- if (!m_innerBlock) {
- currentHeight = innerTextRenderer->height();
- if (currentHeight < m_height)
- innerTextRenderer->setPos(innerTextRenderer->xPos(), (m_height - currentHeight) / 2);
- }
+ // Center the child block vertically
+ RenderBox* childBlock = innerBlockRenderer ? innerBlockRenderer : innerTextRenderer;
+ currentHeight = childBlock->height();
+ if (currentHeight < height())
+ childBlock->setLocation(childBlock->x(), (height() - currentHeight) / 2);
}
-bool RenderTextControlSingleLine::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, int x, int y, int tx, int ty, HitTestAction hitTestAction)
+bool RenderTextControlSingleLine::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, int xPos, int yPos, int tx, int ty, HitTestAction hitTestAction)
{
// If we're within the text control, we want to act as if we've hit the inner text block element, in case the point
// was on the control but not on the inner element (see Radar 4617841).
@@ -262,37 +261,39 @@ bool RenderTextControlSingleLine::nodeAtPoint(const HitTestRequest& request, Hit
// In a search field, we want to act as if we've hit the results block if we're to the left of the inner text block,
// and act as if we've hit the close block if we're to the right of the inner text block.
- if (!RenderTextControl::nodeAtPoint(request, result, x, y, tx, ty, hitTestAction))
+ if (!RenderTextControl::nodeAtPoint(request, result, xPos, yPos, tx, ty, hitTestAction))
return false;
- if (result.innerNode() != element() && result.innerNode() != m_innerBlock.get())
- return false;
-
- hitInnerTextBlock(result, x, y, tx, ty);
+ // If we hit a node inside the inner text element, say that we hit that element,
+ // and if we hit our node (e.g. we're over the border or padding), also say that we hit the
+ // inner text element so that it gains focus.
+ if (result.innerNode()->isDescendantOf(innerTextElement()) || result.innerNode() == node())
+ hitInnerTextElement(result, xPos, yPos, tx, ty);
- if (!m_innerBlock)
+ // If we're not a search field, or we already found the results or cancel buttons, we're done.
+ if (!m_innerBlock || result.innerNode() == m_resultsButton || result.innerNode() == m_cancelButton)
return true;
Node* innerNode = 0;
- RenderObject* innerBlockRenderer = m_innerBlock->renderer();
- RenderObject* innerTextRenderer = innerTextElement()->renderer();
+ RenderBox* innerBlockRenderer = m_innerBlock->renderBox();
+ RenderBox* innerTextRenderer = innerTextElement()->renderBox();
IntPoint localPoint = result.localPoint();
- localPoint.move(-innerBlockRenderer->xPos(), -innerBlockRenderer->yPos());
+ localPoint.move(-innerBlockRenderer->x(), -innerBlockRenderer->y());
- int textLeft = tx + m_x + innerBlockRenderer->xPos() + innerTextRenderer->xPos();
- if (m_resultsButton && m_resultsButton->renderer() && x < textLeft)
+ int textLeft = tx + x() + innerBlockRenderer->x() + innerTextRenderer->x();
+ if (m_resultsButton && m_resultsButton->renderer() && xPos < textLeft)
innerNode = m_resultsButton.get();
if (!innerNode) {
int textRight = textLeft + innerTextRenderer->width();
- if (m_cancelButton && m_cancelButton->renderer() && x > textRight)
+ if (m_cancelButton && m_cancelButton->renderer() && xPos > textRight)
innerNode = m_cancelButton.get();
}
if (innerNode) {
result.setInnerNode(innerNode);
- localPoint.move(-innerNode->renderer()->xPos(), -innerNode->renderer()->yPos());
+ localPoint.move(-innerNode->renderBox()->x(), -innerNode->renderBox()->y());
}
result.setLocalPoint(localPoint);
@@ -301,7 +302,7 @@ bool RenderTextControlSingleLine::nodeAtPoint(const HitTestRequest& request, Hit
void RenderTextControlSingleLine::forwardEvent(Event* event)
{
- RenderObject* innerTextRenderer = innerTextElement()->renderer();
+ RenderBox* innerTextRenderer = innerTextElement()->renderBox();
if (event->type() == eventNames().blurEvent) {
if (innerTextRenderer) {
@@ -318,16 +319,16 @@ void RenderTextControlSingleLine::forwardEvent(Event* event)
return;
}
- FloatPoint localPoint = innerTextRenderer->absoluteToLocal(FloatPoint(static_cast<MouseEvent*>(event)->pageX(), static_cast<MouseEvent*>(event)->pageY()), false, true);
- if (m_resultsButton && localPoint.x() < innerTextRenderer->borderBox().x())
+ FloatPoint localPoint = innerTextRenderer->absoluteToLocal(static_cast<MouseEvent*>(event)->absoluteLocation(), false, true);
+ if (m_resultsButton && localPoint.x() < innerTextRenderer->borderBoxRect().x())
m_resultsButton->defaultEventHandler(event);
- else if (m_cancelButton && localPoint.x() > innerTextRenderer->borderBox().right())
+ else if (m_cancelButton && localPoint.x() > innerTextRenderer->borderBoxRect().right())
m_cancelButton->defaultEventHandler(event);
else
RenderTextControl::forwardEvent(event);
}
-void RenderTextControlSingleLine::styleDidChange(RenderStyle::Diff diff, const RenderStyle* oldStyle)
+void RenderTextControlSingleLine::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
{
RenderTextControl::styleDidChange(diff, oldStyle);
@@ -344,6 +345,8 @@ void RenderTextControlSingleLine::styleDidChange(RenderStyle::Diff diff, const R
if (RenderObject* cancelRenderer = m_cancelButton ? m_cancelButton->renderer() : 0)
cancelRenderer->setStyle(createCancelButtonStyle(style()));
+
+ setHasOverflowClip(false);
}
void RenderTextControlSingleLine::capsLockStateMayHaveChanged()
@@ -359,7 +362,7 @@ void RenderTextControlSingleLine::capsLockStateMayHaveChanged()
bool shouldDrawCapsLockIndicator = false;
if (Frame* frame = document()->frame())
- shouldDrawCapsLockIndicator = static_cast<HTMLInputElement*>(node())->inputType() == HTMLInputElement::PASSWORD
+ shouldDrawCapsLockIndicator = inputElement()->isPasswordField()
&& frame->selection()->isFocusedAndActive()
&& document()->focusedNode() == node()
&& PlatformKeyboardEvent::currentCapsLockState();
@@ -374,14 +377,14 @@ int RenderTextControlSingleLine::textBlockWidth() const
{
int width = RenderTextControl::textBlockWidth();
- if (RenderObject* resultsRenderer = m_resultsButton ? m_resultsButton->renderer() : 0) {
+ if (RenderBox* resultsRenderer = m_resultsButton ? m_resultsButton->renderBox() : 0) {
resultsRenderer->calcWidth();
- width -= resultsRenderer->width();
+ width -= resultsRenderer->width() + resultsRenderer->marginLeft() + resultsRenderer->marginRight();
}
- if (RenderObject* cancelRenderer = m_cancelButton ? m_cancelButton->renderer() : 0) {
+ if (RenderBox* cancelRenderer = m_cancelButton ? m_cancelButton->renderBox() : 0) {
cancelRenderer->calcWidth();
- width -= cancelRenderer->width();
+ width -= cancelRenderer->width() + cancelRenderer->marginLeft() + cancelRenderer->marginRight();
}
return width;
@@ -389,17 +392,20 @@ int RenderTextControlSingleLine::textBlockWidth() const
int RenderTextControlSingleLine::preferredContentWidth(float charWidth) const
{
- int factor = static_cast<HTMLInputElement*>(node())->size();
+ int factor = inputElement()->size();
if (factor <= 0)
factor = 20;
int result = static_cast<int>(ceilf(charWidth * factor));
- if (RenderObject* resultsRenderer = m_resultsButton ? m_resultsButton->renderer() : 0)
+ // For text inputs, IE adds some extra width.
+ result += style()->font().primaryFont()->maxCharWidth() - charWidth;
+
+ if (RenderBox* resultsRenderer = m_resultsButton ? m_resultsButton->renderBox() : 0)
result += resultsRenderer->borderLeft() + resultsRenderer->borderRight() +
resultsRenderer->paddingLeft() + resultsRenderer->paddingRight();
- if (RenderObject* cancelRenderer = m_cancelButton ? m_cancelButton->renderer() : 0)
+ if (RenderBox* cancelRenderer = m_cancelButton ? m_cancelButton->renderBox() : 0)
result += cancelRenderer->borderLeft() + cancelRenderer->borderRight() +
cancelRenderer->paddingLeft() + cancelRenderer->paddingRight();
@@ -408,30 +414,30 @@ int RenderTextControlSingleLine::preferredContentWidth(float charWidth) const
void RenderTextControlSingleLine::adjustControlHeightBasedOnLineHeight(int lineHeight)
{
- if (RenderObject* resultsRenderer = m_resultsButton ? m_resultsButton->renderer() : 0) {
- static_cast<RenderBlock*>(resultsRenderer)->calcHeight();
- m_height = max(m_height,
- resultsRenderer->borderTop() + resultsRenderer->borderBottom() +
- resultsRenderer->paddingTop() + resultsRenderer->paddingBottom() +
- resultsRenderer->marginTop() + resultsRenderer->marginBottom());
+ if (RenderBox* resultsRenderer = m_resultsButton ? m_resultsButton->renderBox() : 0) {
+ toRenderBlock(resultsRenderer)->calcHeight();
+ setHeight(max(height(),
+ resultsRenderer->borderTop() + resultsRenderer->borderBottom() +
+ resultsRenderer->paddingTop() + resultsRenderer->paddingBottom() +
+ resultsRenderer->marginTop() + resultsRenderer->marginBottom()));
lineHeight = max(lineHeight, resultsRenderer->height());
}
- if (RenderObject* cancelRenderer = m_cancelButton ? m_cancelButton->renderer() : 0) {
- static_cast<RenderBlock*>(cancelRenderer)->calcHeight();
- m_height = max(m_height,
- cancelRenderer->borderTop() + cancelRenderer->borderBottom() +
- cancelRenderer->paddingTop() + cancelRenderer->paddingBottom() +
- cancelRenderer->marginTop() + cancelRenderer->marginBottom());
+ if (RenderBox* cancelRenderer = m_cancelButton ? m_cancelButton->renderBox() : 0) {
+ toRenderBlock(cancelRenderer)->calcHeight();
+ setHeight(max(height(),
+ cancelRenderer->borderTop() + cancelRenderer->borderBottom() +
+ cancelRenderer->paddingTop() + cancelRenderer->paddingBottom() +
+ cancelRenderer->marginTop() + cancelRenderer->marginBottom()));
lineHeight = max(lineHeight, cancelRenderer->height());
}
- m_height += lineHeight;
+ setHeight(height() + lineHeight);
}
void RenderTextControlSingleLine::createSubtreeIfNeeded()
{
- if (!static_cast<HTMLInputElement*>(node())->isSearchField()) {
+ if (!inputElement()->isSearchField()) {
RenderTextControl::createSubtreeIfNeeded(m_innerBlock.get());
return;
}
@@ -466,17 +472,15 @@ void RenderTextControlSingleLine::updateFromElement()
bool placeholderVisibilityShouldChange = m_placeholderVisible != placeholderShouldBeVisible();
m_placeholderVisible = placeholderShouldBeVisible();
- if (RenderObject* cancelButtonRenderer = m_cancelButton ? m_cancelButton->renderer() : 0)
- updateCancelButtonVisibility(cancelButtonRenderer->style());
-
- HTMLInputElement* element = static_cast<HTMLInputElement*>(node());
+ if (m_cancelButton)
+ updateCancelButtonVisibility();
if (m_placeholderVisible) {
ExceptionCode ec = 0;
- innerTextElement()->setInnerText(element->getAttribute(placeholderAttr), ec);
- ASSERT(ec == 0);
- } else if (!formControlElement()->valueMatchesRenderer() || placeholderVisibilityShouldChange)
- setInnerTextValue(element->value());
+ innerTextElement()->setInnerText(inputElement()->placeholder(), ec);
+ ASSERT(!ec);
+ } else if (!static_cast<Element*>(node())->formControlValueMatchesRenderer() || placeholderVisibilityShouldChange)
+ setInnerTextValue(inputElement()->value());
if (m_searchPopupIsVisible)
m_searchPopup->updateFromElement();
@@ -484,16 +488,17 @@ void RenderTextControlSingleLine::updateFromElement()
void RenderTextControlSingleLine::cacheSelection(int start, int end)
{
- static_cast<HTMLInputElement*>(node())->cacheSelection(start, end);
+ inputElement()->cacheSelection(start, end);
}
PassRefPtr<RenderStyle> RenderTextControlSingleLine::createInnerTextStyle(const RenderStyle* startStyle) const
{
RefPtr<RenderStyle> textBlockStyle;
if (placeholderShouldBeVisible()) {
- RenderStyle* pseudoStyle = getCachedPseudoStyle(RenderStyle::INPUT_PLACEHOLDER);
- textBlockStyle = RenderStyle::clone(pseudoStyle);
- } else {
+ if (RenderStyle* pseudoStyle = getCachedPseudoStyle(INPUT_PLACEHOLDER))
+ textBlockStyle = RenderStyle::clone(pseudoStyle);
+ }
+ if (!textBlockStyle) {
textBlockStyle = RenderStyle::create();
textBlockStyle->inheritFrom(startStyle);
}
@@ -527,6 +532,8 @@ PassRefPtr<RenderStyle> RenderTextControlSingleLine::createInnerTextStyle(const
PassRefPtr<RenderStyle> RenderTextControlSingleLine::createInnerBlockStyle(const RenderStyle* startStyle) const
{
+ ASSERT(node()->isHTMLElement());
+
RefPtr<RenderStyle> innerBlockStyle = RenderStyle::create();
innerBlockStyle->inheritFrom(startStyle);
@@ -541,15 +548,16 @@ PassRefPtr<RenderStyle> RenderTextControlSingleLine::createInnerBlockStyle(const
PassRefPtr<RenderStyle> RenderTextControlSingleLine::createResultsButtonStyle(const RenderStyle* startStyle) const
{
+ ASSERT(node()->isHTMLElement());
HTMLInputElement* input = static_cast<HTMLInputElement*>(node());
RefPtr<RenderStyle> resultsBlockStyle;
if (input->maxResults() < 0)
- resultsBlockStyle = getCachedPseudoStyle(RenderStyle::SEARCH_DECORATION);
+ resultsBlockStyle = getCachedPseudoStyle(SEARCH_DECORATION);
else if (!input->maxResults())
- resultsBlockStyle = getCachedPseudoStyle(RenderStyle::SEARCH_RESULTS_DECORATION);
+ resultsBlockStyle = getCachedPseudoStyle(SEARCH_RESULTS_DECORATION);
else
- resultsBlockStyle = getCachedPseudoStyle(RenderStyle::SEARCH_RESULTS_BUTTON);
+ resultsBlockStyle = getCachedPseudoStyle(SEARCH_RESULTS_BUTTON);
if (!resultsBlockStyle)
resultsBlockStyle = RenderStyle::create();
@@ -562,9 +570,10 @@ PassRefPtr<RenderStyle> RenderTextControlSingleLine::createResultsButtonStyle(co
PassRefPtr<RenderStyle> RenderTextControlSingleLine::createCancelButtonStyle(const RenderStyle* startStyle) const
{
+ ASSERT(node()->isHTMLElement());
RefPtr<RenderStyle> cancelBlockStyle;
- if (RefPtr<RenderStyle> pseudoStyle = getCachedPseudoStyle(RenderStyle::SEARCH_CANCEL_BUTTON))
+ if (RefPtr<RenderStyle> pseudoStyle = getCachedPseudoStyle(SEARCH_CANCEL_BUTTON))
// We may be sharing style with another search field, but we must not share the cancel button style.
cancelBlockStyle = RenderStyle::clone(pseudoStyle.get());
else
@@ -573,14 +582,30 @@ PassRefPtr<RenderStyle> RenderTextControlSingleLine::createCancelButtonStyle(con
if (startStyle)
cancelBlockStyle->inheritFrom(startStyle);
- updateCancelButtonVisibility(cancelBlockStyle.get());
+ cancelBlockStyle->setVisibility(visibilityForCancelButton());
return cancelBlockStyle.release();
}
-void RenderTextControlSingleLine::updateCancelButtonVisibility(RenderStyle* style) const
+void RenderTextControlSingleLine::updateCancelButtonVisibility() const
{
+ if (!m_cancelButton->renderer())
+ return;
+
+ const RenderStyle* curStyle = m_cancelButton->renderer()->style();
+ EVisibility buttonVisibility = visibilityForCancelButton();
+ if (curStyle->visibility() == buttonVisibility)
+ return;
+
+ RefPtr<RenderStyle> cancelButtonStyle = RenderStyle::clone(curStyle);
+ cancelButtonStyle->setVisibility(buttonVisibility);
+ m_cancelButton->renderer()->setStyle(cancelButtonStyle);
+}
+
+EVisibility RenderTextControlSingleLine::visibilityForCancelButton() const
+{
+ ASSERT(node()->isHTMLElement());
HTMLInputElement* input = static_cast<HTMLInputElement*>(node());
- style->setVisibility(input->value().isEmpty() ? HIDDEN : VISIBLE);
+ return input->value().isEmpty() ? HIDDEN : VISIBLE;
}
const AtomicString& RenderTextControlSingleLine::autosaveName() const
@@ -590,6 +615,7 @@ const AtomicString& RenderTextControlSingleLine::autosaveName() const
void RenderTextControlSingleLine::startSearchEventTimer()
{
+ ASSERT(node()->isHTMLElement());
unsigned length = text().length();
// If there's no text, fire the event right away.
@@ -606,12 +632,14 @@ void RenderTextControlSingleLine::startSearchEventTimer()
void RenderTextControlSingleLine::searchEventTimerFired(Timer<RenderTextControlSingleLine>*)
{
+ ASSERT(node()->isHTMLElement());
static_cast<HTMLInputElement*>(node())->onSearch();
}
// PopupMenuClient methods
void RenderTextControlSingleLine::valueChanged(unsigned listIndex, bool fireEvents)
{
+ ASSERT(node()->isHTMLElement());
ASSERT(static_cast<int>(listIndex) < listSize());
HTMLInputElement* input = static_cast<HTMLInputElement*>(node());
if (static_cast<int>(listIndex) == (listSize() - 1)) {
@@ -662,7 +690,7 @@ PopupMenuStyle RenderTextControlSingleLine::itemStyle(unsigned) const
PopupMenuStyle RenderTextControlSingleLine::menuStyle() const
{
- return PopupMenuStyle(style()->color(), style()->backgroundColor(), style()->font(), style()->visibility() == VISIBLE);
+ return PopupMenuStyle(style()->color(), style()->backgroundColor(), style()->font(), style()->visibility() == VISIBLE, style()->textIndent(), style()->direction());
}
int RenderTextControlSingleLine::clientInsetLeft() const
@@ -682,9 +710,9 @@ int RenderTextControlSingleLine::clientInsetRight() const
int RenderTextControlSingleLine::clientPaddingLeft() const
{
- int padding = clientPaddingLeft();
+ int padding = paddingLeft();
- if (RenderObject* resultsRenderer = m_resultsButton ? m_resultsButton->renderer() : 0)
+ if (RenderBox* resultsRenderer = m_resultsButton ? m_resultsButton->renderBox() : 0)
padding += resultsRenderer->width();
return padding;
@@ -692,9 +720,9 @@ int RenderTextControlSingleLine::clientPaddingLeft() const
int RenderTextControlSingleLine::clientPaddingRight() const
{
- int padding = clientPaddingRight();
+ int padding = paddingRight();
- if (RenderObject* cancelRenderer = m_cancelButton ? m_cancelButton->renderer() : 0)
+ if (RenderBox* cancelRenderer = m_cancelButton ? m_cancelButton->renderBox() : 0)
padding += cancelRenderer->width();
return padding;
@@ -732,6 +760,7 @@ bool RenderTextControlSingleLine::itemIsSelected(unsigned) const
void RenderTextControlSingleLine::setTextFromItem(unsigned listIndex)
{
+ ASSERT(node()->isHTMLElement());
static_cast<HTMLInputElement*>(node())->setValue(itemText(listIndex));
}
@@ -745,10 +774,65 @@ HostWindow* RenderTextControlSingleLine::hostWindow() const
return document()->view()->hostWindow();
}
+void RenderTextControlSingleLine::autoscroll()
+{
+ RenderLayer* layer = innerTextElement()->renderBox()->layer();
+ if (layer)
+ layer->autoscroll();
+}
+
+int RenderTextControlSingleLine::scrollWidth() const
+{
+ if (innerTextElement())
+ return innerTextElement()->scrollWidth();
+ return RenderBlock::scrollWidth();
+}
+
+int RenderTextControlSingleLine::scrollHeight() const
+{
+ if (innerTextElement())
+ return innerTextElement()->scrollHeight();
+ return RenderBlock::scrollHeight();
+}
+
+int RenderTextControlSingleLine::scrollLeft() const
+{
+ if (innerTextElement())
+ return innerTextElement()->scrollLeft();
+ return RenderBlock::scrollLeft();
+}
+
+int RenderTextControlSingleLine::scrollTop() const
+{
+ if (innerTextElement())
+ return innerTextElement()->scrollTop();
+ return RenderBlock::scrollTop();
+}
+
+void RenderTextControlSingleLine::setScrollLeft(int newLeft)
+{
+ if (innerTextElement())
+ innerTextElement()->setScrollLeft(newLeft);
+}
+
+void RenderTextControlSingleLine::setScrollTop(int newTop)
+{
+ if (innerTextElement())
+ innerTextElement()->setScrollTop(newTop);
+}
+
+bool RenderTextControlSingleLine::scroll(ScrollDirection direction, ScrollGranularity granularity, float multiplier)
+{
+ RenderLayer* layer = innerTextElement()->renderBox()->layer();
+ if (layer && layer->scroll(direction, granularity, multiplier))
+ return true;
+ return RenderBlock::scroll(direction, granularity, multiplier);
+}
+
PassRefPtr<Scrollbar> RenderTextControlSingleLine::createScrollbar(ScrollbarClient* client, ScrollbarOrientation orientation, ScrollbarControlSize controlSize)
{
RefPtr<Scrollbar> widget;
- bool hasCustomScrollbarStyle = style()->hasPseudoStyle(RenderStyle::SCROLLBAR);
+ bool hasCustomScrollbarStyle = style()->hasPseudoStyle(SCROLLBAR);
if (hasCustomScrollbarStyle)
widget = RenderScrollbar::createCustomScrollbar(client, orientation, this);
else
@@ -756,4 +840,9 @@ PassRefPtr<Scrollbar> RenderTextControlSingleLine::createScrollbar(ScrollbarClie
return widget.release();
}
+InputElement* RenderTextControlSingleLine::inputElement() const
+{
+ return toInputElement(static_cast<Element*>(node()));
+}
+
}
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderTextControlSingleLine.h b/src/3rdparty/webkit/WebCore/rendering/RenderTextControlSingleLine.h
index a0d8d68..23352b4 100644
--- a/src/3rdparty/webkit/WebCore/rendering/RenderTextControlSingleLine.h
+++ b/src/3rdparty/webkit/WebCore/rendering/RenderTextControlSingleLine.h
@@ -27,6 +27,7 @@
namespace WebCore {
+class InputElement;
class SearchFieldCancelButtonElement;
class SearchFieldResultsButtonElement;
class SearchPopupMenu;
@@ -58,9 +59,20 @@ public:
virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, int x, int y, int tx, int ty, HitTestAction);
void forwardEvent(Event*);
-private:
- virtual void capsLockStateMayHaveChanged();
+ void capsLockStateMayHaveChanged();
+
+ virtual void autoscroll();
+
+ // Subclassed to forward to our inner div.
+ virtual int scrollLeft() const;
+ virtual int scrollTop() const;
+ virtual int scrollWidth() const;
+ virtual int scrollHeight() const;
+ virtual void setScrollLeft(int);
+ virtual void setScrollTop(int);
+ virtual bool scroll(ScrollDirection, ScrollGranularity, float multiplier = 1.0f);
+private:
int textBlockWidth() const;
virtual int preferredContentWidth(float charWidth) const;
virtual void adjustControlHeightBasedOnLineHeight(int lineHeight);
@@ -68,14 +80,15 @@ private:
void createSubtreeIfNeeded();
virtual void updateFromElement();
virtual void cacheSelection(int start, int end);
- virtual void styleDidChange(RenderStyle::Diff, const RenderStyle* oldStyle);
+ virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
virtual PassRefPtr<RenderStyle> createInnerTextStyle(const RenderStyle* startStyle) const;
PassRefPtr<RenderStyle> createInnerBlockStyle(const RenderStyle* startStyle) const;
PassRefPtr<RenderStyle> createResultsButtonStyle(const RenderStyle* startStyle) const;
PassRefPtr<RenderStyle> createCancelButtonStyle(const RenderStyle* startStyle) const;
- void updateCancelButtonVisibility(RenderStyle*) const;
+ void updateCancelButtonVisibility() const;
+ EVisibility visibilityForCancelButton() const;
const AtomicString& autosaveName() const;
void startSearchEventTimer();
@@ -104,6 +117,8 @@ private:
virtual HostWindow* hostWindow() const;
virtual PassRefPtr<Scrollbar> createScrollbar(ScrollbarClient*, ScrollbarOrientation, ScrollbarControlSize);
+ InputElement* inputElement() const;
+
private:
bool m_placeholderVisible;
bool m_searchPopupIsVisible;
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderTextFragment.cpp b/src/3rdparty/webkit/WebCore/rendering/RenderTextFragment.cpp
index c8beba0..7da9e5a 100644
--- a/src/3rdparty/webkit/WebCore/rendering/RenderTextFragment.cpp
+++ b/src/3rdparty/webkit/WebCore/rendering/RenderTextFragment.cpp
@@ -46,7 +46,7 @@ RenderTextFragment::RenderTextFragment(Node* node, StringImpl* str)
PassRefPtr<StringImpl> RenderTextFragment::originalText() const
{
- Node* e = element();
+ Node* e = node();
RefPtr<StringImpl> result = (e ? static_cast<Text*>(e)->string() : contentString());
if (result && (start() > 0 || start() < result->length()))
result = result->substring(start(), end());
@@ -75,7 +75,7 @@ void RenderTextFragment::setTextInternal(PassRefPtr<StringImpl> text)
UChar RenderTextFragment::previousCharacter()
{
if (start()) {
- Node* e = element();
+ Node* e = node();
StringImpl* original = (e ? static_cast<Text*>(e)->string() : contentString());
if (original)
return (*original)[start() - 1];
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderTheme.cpp b/src/3rdparty/webkit/WebCore/rendering/RenderTheme.cpp
index aa18407..517d911 100644
--- a/src/3rdparty/webkit/WebCore/rendering/RenderTheme.cpp
+++ b/src/3rdparty/webkit/WebCore/rendering/RenderTheme.cpp
@@ -62,7 +62,7 @@ void RenderTheme::adjustStyle(CSSStyleSelector* selector, RenderStyle* style, El
else if (style->display() == COMPACT || style->display() == RUN_IN || style->display() == LIST_ITEM || style->display() == TABLE)
style->setDisplay(BLOCK);
- if (UAHasAppearance && theme()->isControlStyled(style, border, background, backgroundColor)) {
+ if (UAHasAppearance && isControlStyled(style, border, background, backgroundColor)) {
if (part == MenulistPart) {
style->setAppearance(MenulistButtonPart);
part = MenulistButtonPart;
@@ -268,6 +268,12 @@ bool RenderTheme::paint(RenderObject* o, const RenderObject::PaintInfo& paintInf
if (o->parent()->isSlider())
return paintMediaSliderThumb(o, paintInfo, r);
break;
+ case MediaTimeRemainingPart:
+ return paintMediaTimeRemaining(o, paintInfo, r);
+ case MediaCurrentTimePart:
+ return paintMediaCurrentTime(o, paintInfo, r);
+ case MediaTimelineContainerPart:
+ return paintMediaTimelineContainer(o, paintInfo, r);
case MenulistButtonPart:
case TextFieldPart:
case TextAreaPart:
@@ -365,24 +371,68 @@ bool RenderTheme::paintDecorations(RenderObject* o, const RenderObject::PaintInf
#if ENABLE(VIDEO)
bool RenderTheme::hitTestMediaControlPart(RenderObject* o, const IntPoint& absPoint)
{
- FloatPoint localPoint = o->absoluteToLocal(absPoint, false, true); // respect transforms
+ if (!o->isBox())
+ return false;
- return o->borderBox().contains(roundedIntPoint(localPoint));
+ FloatPoint localPoint = o->absoluteToLocal(absPoint, false, true); // respect transforms
+ return toRenderBox(o)->borderBoxRect().contains(roundedIntPoint(localPoint));
}
#endif
Color RenderTheme::activeSelectionBackgroundColor() const
{
- if (!m_activeSelectionColor.isValid())
- m_activeSelectionColor = platformActiveSelectionBackgroundColor().blendWithWhite();
- return m_activeSelectionColor;
+ if (!m_activeSelectionBackgroundColor.isValid())
+ m_activeSelectionBackgroundColor = platformActiveSelectionBackgroundColor().blendWithWhite();
+ return m_activeSelectionBackgroundColor;
}
Color RenderTheme::inactiveSelectionBackgroundColor() const
{
- if (!m_inactiveSelectionColor.isValid())
- m_inactiveSelectionColor = platformInactiveSelectionBackgroundColor().blendWithWhite();
- return m_inactiveSelectionColor;
+ if (!m_inactiveSelectionBackgroundColor.isValid())
+ m_inactiveSelectionBackgroundColor = platformInactiveSelectionBackgroundColor().blendWithWhite();
+ return m_inactiveSelectionBackgroundColor;
+}
+
+Color RenderTheme::activeSelectionForegroundColor() const
+{
+ if (!m_activeSelectionForegroundColor.isValid() && supportsSelectionForegroundColors())
+ m_activeSelectionForegroundColor = platformActiveSelectionForegroundColor();
+ return m_activeSelectionForegroundColor;
+}
+
+Color RenderTheme::inactiveSelectionForegroundColor() const
+{
+ if (!m_inactiveSelectionForegroundColor.isValid() && supportsSelectionForegroundColors())
+ m_inactiveSelectionForegroundColor = platformInactiveSelectionForegroundColor();
+ return m_inactiveSelectionForegroundColor;
+}
+
+Color RenderTheme::activeListBoxSelectionBackgroundColor() const
+{
+ if (!m_activeListBoxSelectionBackgroundColor.isValid())
+ m_activeListBoxSelectionBackgroundColor = platformActiveListBoxSelectionBackgroundColor();
+ return m_activeListBoxSelectionBackgroundColor;
+}
+
+Color RenderTheme::inactiveListBoxSelectionBackgroundColor() const
+{
+ if (!m_inactiveListBoxSelectionBackgroundColor.isValid())
+ m_inactiveListBoxSelectionBackgroundColor = platformInactiveListBoxSelectionBackgroundColor();
+ return m_inactiveListBoxSelectionBackgroundColor;
+}
+
+Color RenderTheme::activeListBoxSelectionForegroundColor() const
+{
+ if (!m_activeListBoxSelectionForegroundColor.isValid() && supportsListBoxSelectionForegroundColors())
+ m_activeListBoxSelectionForegroundColor = platformActiveListBoxSelectionForegroundColor();
+ return m_activeListBoxSelectionForegroundColor;
+}
+
+Color RenderTheme::inactiveListBoxSelectionForegroundColor() const
+{
+ if (!m_inactiveListBoxSelectionForegroundColor.isValid() && supportsListBoxSelectionForegroundColors())
+ m_inactiveListBoxSelectionForegroundColor = platformInactiveListBoxSelectionForegroundColor();
+ return m_inactiveListBoxSelectionForegroundColor;
}
Color RenderTheme::platformActiveSelectionBackgroundColor() const
@@ -391,50 +441,56 @@ Color RenderTheme::platformActiveSelectionBackgroundColor() const
return Color(0, 0, 255);
}
-Color RenderTheme::platformInactiveSelectionBackgroundColor() const
+Color RenderTheme::platformActiveSelectionForegroundColor() const
{
- // Use a grey color by default if the platform theme doesn't define anything.
- return Color(128, 128, 128);
+ // Use a white color by default if the platform theme doesn't define anything.
+ return Color::white;
}
-Color RenderTheme::platformActiveSelectionForegroundColor() const
+Color RenderTheme::platformInactiveSelectionBackgroundColor() const
{
- return Color();
+ // Use a grey color by default if the platform theme doesn't define anything.
+ // This color matches Firefox's inactive color.
+ return Color(176, 176, 176);
}
Color RenderTheme::platformInactiveSelectionForegroundColor() const
{
- return Color();
+ // Use a black color by default.
+ return Color::black;
}
-Color RenderTheme::activeListBoxSelectionBackgroundColor() const
+Color RenderTheme::platformActiveListBoxSelectionBackgroundColor() const
{
- return activeSelectionBackgroundColor();
+ return platformActiveSelectionBackgroundColor();
}
-Color RenderTheme::activeListBoxSelectionForegroundColor() const
+Color RenderTheme::platformActiveListBoxSelectionForegroundColor() const
{
- // Use a white color by default if the platform theme doesn't define anything.
- return Color(255, 255, 255);
+ return platformActiveSelectionForegroundColor();
}
-Color RenderTheme::inactiveListBoxSelectionBackgroundColor() const
+Color RenderTheme::platformInactiveListBoxSelectionBackgroundColor() const
{
- return inactiveSelectionBackgroundColor();
+ return platformInactiveSelectionBackgroundColor();
}
-Color RenderTheme::inactiveListBoxSelectionForegroundColor() const
+Color RenderTheme::platformInactiveListBoxSelectionForegroundColor() const
{
- // Use a black color by default if the platform theme doesn't define anything.
- return Color(0, 0, 0);
+ return platformInactiveSelectionForegroundColor();
}
int RenderTheme::baselinePosition(const RenderObject* o) const
{
+ if (!o->isBox())
+ return 0;
+
+ const RenderBox* box = toRenderBox(o);
+
#if USE(NEW_THEME)
- return o->height() + o->marginTop() + m_theme->baselinePositionAdjustment(o->style()->appearance()) * o->style()->effectiveZoom();
+ return box->height() + box->marginTop() + m_theme->baselinePositionAdjustment(o->style()->appearance()) * o->style()->effectiveZoom();
#else
- return o->height() + o->marginTop();
+ return box->height() + box->marginTop();
#endif
}
@@ -521,7 +577,7 @@ ControlStates RenderTheme::controlStatesForRenderer(const RenderObject* o) const
bool RenderTheme::isActive(const RenderObject* o) const
{
- Node* node = o->element();
+ Node* node = o->node();
if (!node)
return false;
@@ -538,28 +594,39 @@ bool RenderTheme::isActive(const RenderObject* o) const
bool RenderTheme::isChecked(const RenderObject* o) const
{
- if (!o->element())
+ if (!o->node() || !o->node()->isElementNode())
+ return false;
+
+ InputElement* inputElement = toInputElement(static_cast<Element*>(o->node()));
+ if (!inputElement)
return false;
- return o->element()->isChecked();
+
+ return inputElement->isChecked();
}
bool RenderTheme::isIndeterminate(const RenderObject* o) const
{
- if (!o->element())
+ if (!o->node() || !o->node()->isElementNode())
+ return false;
+
+ InputElement* inputElement = toInputElement(static_cast<Element*>(o->node()));
+ if (!inputElement)
return false;
- return o->element()->isIndeterminate();
+
+ return inputElement->isIndeterminate();
}
bool RenderTheme::isEnabled(const RenderObject* o) const
{
- if (!o->element())
+ Node* node = o->node();
+ if (!node || !node->isElementNode())
return true;
- return o->element()->isEnabled();
+ return static_cast<Element*>(node)->isEnabledFormControl();
}
bool RenderTheme::isFocused(const RenderObject* o) const
{
- Node* node = o->element();
+ Node* node = o->node();
if (!node)
return false;
Document* document = node->document();
@@ -569,23 +636,24 @@ bool RenderTheme::isFocused(const RenderObject* o) const
bool RenderTheme::isPressed(const RenderObject* o) const
{
- if (!o->element())
+ if (!o->node())
return false;
- return o->element()->active();
+ return o->node()->active();
}
bool RenderTheme::isReadOnlyControl(const RenderObject* o) const
{
- if (!o->element())
+ Node* node = o->node();
+ if (!node || !node->isElementNode())
return false;
- return o->element()->isReadOnlyControl();
+ return static_cast<Element*>(node)->isReadOnlyFormControl();
}
bool RenderTheme::isHovered(const RenderObject* o) const
{
- if (!o->element())
+ if (!o->node())
return false;
- return o->element()->hovered();
+ return o->node()->hovered();
}
bool RenderTheme::isDefault(const RenderObject* o) const
@@ -661,10 +729,6 @@ void RenderTheme::adjustMenuListButtonStyle(CSSStyleSelector*, RenderStyle*, Ele
{
}
-void RenderTheme::adjustButtonInnerStyle(RenderStyle*) const
-{
-}
-
void RenderTheme::adjustSliderTrackStyle(CSSStyleSelector*, RenderStyle*, Element*) const
{
}
@@ -699,8 +763,15 @@ void RenderTheme::adjustSearchFieldResultsButtonStyle(CSSStyleSelector*, RenderS
void RenderTheme::platformColorsDidChange()
{
- m_activeSelectionColor = Color();
- m_inactiveSelectionColor = Color();
+ m_activeSelectionForegroundColor = Color();
+ m_inactiveSelectionForegroundColor = Color();
+ m_activeSelectionBackgroundColor = Color();
+ m_inactiveSelectionBackgroundColor = Color();
+
+ m_activeListBoxSelectionForegroundColor = Color();
+ m_inactiveListBoxSelectionForegroundColor = Color();
+ m_activeListBoxSelectionBackgroundColor = Color();
+ m_inactiveListBoxSelectionForegroundColor = Color();
}
Color RenderTheme::systemColor(int cssValueId) const
@@ -768,9 +839,19 @@ Color RenderTheme::systemColor(int cssValueId) const
return Color();
}
-Color RenderTheme::platformTextSearchHighlightColor() const
+Color RenderTheme::platformActiveTextSearchHighlightColor() const
+{
+ return Color(255, 150, 50); // Orange.
+}
+
+Color RenderTheme::platformInactiveTextSearchHighlightColor() const
+{
+ return Color(255, 255, 0); // Yellow.
+}
+
+Color RenderTheme::focusRingColor() const
{
- return Color(255, 255, 0);
+ return Color(0, 0, 0); // Black.
}
} // namespace WebCore
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderTheme.h b/src/3rdparty/webkit/WebCore/rendering/RenderTheme.h
index f948936..a1519ce 100644
--- a/src/3rdparty/webkit/WebCore/rendering/RenderTheme.h
+++ b/src/3rdparty/webkit/WebCore/rendering/RenderTheme.h
@@ -23,12 +23,16 @@
#ifndef RenderTheme_h
#define RenderTheme_h
-#include "RenderObject.h"
#if USE(NEW_THEME)
#include "Theme.h"
#else
#include "ThemeTypes.h"
#endif
+#include "RenderObject.h"
+#include "RenderTheme.h"
+#include "ScrollTypes.h"
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefCounted.h>
namespace WebCore {
@@ -37,11 +41,24 @@ class PopupMenu;
class RenderMenuList;
class CSSStyleSheet;
-class RenderTheme {
-public:
+class RenderTheme : public RefCounted<RenderTheme> {
+protected:
RenderTheme();
+
+public:
virtual ~RenderTheme() { }
+ // This function is to be implemented in your platform-specific theme implementation to hand back the
+ // appropriate platform theme. When the theme is needed in non-page dependent code, a default theme is
+ // used as fallback, which is returned for a nulled page, so the platform code needs to account for this.
+ static PassRefPtr<RenderTheme> themeForPage(Page* page);
+
+ // When the theme is needed in non-page dependent code, the defaultTheme() is used as fallback.
+ static inline PassRefPtr<RenderTheme> defaultTheme()
+ {
+ return themeForPage(0);
+ };
+
// This method is called whenever style has been computed for an element and the appearance
// property has been set to a value other than "none". The theme should map in all of the appropriate
// metrics and defaults given the contents of the style. This includes sophisticated operations like
@@ -104,23 +121,23 @@ public:
// A method asking if the theme's controls actually care about redrawing when hovered.
virtual bool supportsHover(const RenderStyle*) const { return false; }
- // The selection color.
+ // Text selection colors.
Color activeSelectionBackgroundColor() const;
Color inactiveSelectionBackgroundColor() const;
+ Color activeSelectionForegroundColor() const;
+ Color inactiveSelectionForegroundColor() const;
- virtual Color platformTextSearchHighlightColor() const;
+ // List box selection colors
+ Color activeListBoxSelectionBackgroundColor() const;
+ Color activeListBoxSelectionForegroundColor() const;
+ Color inactiveListBoxSelectionBackgroundColor() const;
+ Color inactiveListBoxSelectionForegroundColor() const;
- // The platform selection color.
- virtual Color platformActiveSelectionBackgroundColor() const;
- virtual Color platformInactiveSelectionBackgroundColor() const;
- virtual Color platformActiveSelectionForegroundColor() const;
- virtual Color platformInactiveSelectionForegroundColor() const;
+ // Highlighting colors for TextMatches.
+ virtual Color platformActiveTextSearchHighlightColor() const;
+ virtual Color platformInactiveTextSearchHighlightColor() const;
- // List Box selection color
- virtual Color activeListBoxSelectionBackgroundColor() const;
- virtual Color activeListBoxSelectionForegroundColor() const;
- virtual Color inactiveListBoxSelectionBackgroundColor() const;
- virtual Color inactiveListBoxSelectionForegroundColor() const;
+ virtual Color focusRingColor() const;
virtual void platformColorsDidChange();
@@ -132,22 +149,44 @@ public:
virtual int minimumMenuListSize(RenderStyle*) const { return 0; }
- virtual void adjustButtonInnerStyle(RenderStyle*) const;
virtual void adjustSliderThumbSize(RenderObject*) const;
virtual int popupInternalPaddingLeft(RenderStyle*) const { return 0; }
virtual int popupInternalPaddingRight(RenderStyle*) const { return 0; }
virtual int popupInternalPaddingTop(RenderStyle*) const { return 0; }
virtual int popupInternalPaddingBottom(RenderStyle*) const { return 0; }
-
+ virtual bool popupOptionSupportsTextIndent() const { return false; }
+
+ virtual int buttonInternalPaddingLeft() const { return 0; }
+ virtual int buttonInternalPaddingRight() const { return 0; }
+ virtual int buttonInternalPaddingTop() const { return 0; }
+ virtual int buttonInternalPaddingBottom() const { return 0; }
+
+ virtual ScrollbarControlSize scrollbarControlSizeForPart(ControlPart) { return RegularScrollbar; }
+
// Method for painting the caps lock indicator
virtual bool paintCapsLockIndicator(RenderObject*, const RenderObject::PaintInfo&, const IntRect&) { return 0; };
#if ENABLE(VIDEO)
+ // Media controls
virtual bool hitTestMediaControlPart(RenderObject*, const IntPoint& absPoint);
#endif
protected:
+ // The platform selection color.
+ virtual Color platformActiveSelectionBackgroundColor() const;
+ virtual Color platformInactiveSelectionBackgroundColor() const;
+ virtual Color platformActiveSelectionForegroundColor() const;
+ virtual Color platformInactiveSelectionForegroundColor() const;
+
+ virtual Color platformActiveListBoxSelectionBackgroundColor() const;
+ virtual Color platformInactiveListBoxSelectionBackgroundColor() const;
+ virtual Color platformActiveListBoxSelectionForegroundColor() const;
+ virtual Color platformInactiveListBoxSelectionForegroundColor() const;
+
+ virtual bool supportsSelectionForegroundColors() const { return true; }
+ virtual bool supportsListBoxSelectionForegroundColors() const { return true; }
+
#if !USE(NEW_THEME)
// Methods for each appearance value.
virtual void adjustCheckboxStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
@@ -203,6 +242,9 @@ protected:
virtual bool paintMediaSeekForwardButton(RenderObject*, const RenderObject::PaintInfo&, const IntRect&) { return true; }
virtual bool paintMediaSliderTrack(RenderObject*, const RenderObject::PaintInfo&, const IntRect&) { return true; }
virtual bool paintMediaSliderThumb(RenderObject*, const RenderObject::PaintInfo&, const IntRect&) { return true; }
+ virtual bool paintMediaTimelineContainer(RenderObject*, const RenderObject::PaintInfo&, const IntRect&) { return true; }
+ virtual bool paintMediaCurrentTime(RenderObject*, const RenderObject::PaintInfo&, const IntRect&) { return true; }
+ virtual bool paintMediaTimeRemaining(RenderObject*, const RenderObject::PaintInfo&, const IntRect&) { return true; }
public:
// Methods for state querying
@@ -218,17 +260,21 @@ public:
bool isDefault(const RenderObject*) const;
private:
- mutable Color m_activeSelectionColor;
- mutable Color m_inactiveSelectionColor;
+ mutable Color m_activeSelectionBackgroundColor;
+ mutable Color m_inactiveSelectionBackgroundColor;
+ mutable Color m_activeSelectionForegroundColor;
+ mutable Color m_inactiveSelectionForegroundColor;
+
+ mutable Color m_activeListBoxSelectionBackgroundColor;
+ mutable Color m_inactiveListBoxSelectionBackgroundColor;
+ mutable Color m_activeListBoxSelectionForegroundColor;
+ mutable Color m_inactiveListBoxSelectionForegroundColor;
+
#if USE(NEW_THEME)
Theme* m_theme; // The platform-specific theme.
#endif
};
-// Function to obtain the theme. This is implemented in your platform-specific theme implementation to hand
-// back the appropriate platform theme.
-RenderTheme* theme();
-
} // namespace WebCore
#endif // RenderTheme_h
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderThemeChromiumLinux.cpp b/src/3rdparty/webkit/WebCore/rendering/RenderThemeChromiumLinux.cpp
new file mode 100644
index 0000000..c4020d3
--- /dev/null
+++ b/src/3rdparty/webkit/WebCore/rendering/RenderThemeChromiumLinux.cpp
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2007 Apple Inc.
+ * Copyright (C) 2007 Alp Toker <alp@atoker.com>
+ * Copyright (C) 2008 Collabora Ltd.
+ * Copyright (C) 2008, 2009 Google Inc.
+ * Copyright (C) 2009 Kenneth Rohde Christiansen
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "RenderThemeChromiumLinux.h"
+
+#include "Color.h"
+#include "CSSValueKeywords.h"
+#include "RenderObject.h"
+#include "UserAgentStyleSheets.h"
+
+namespace WebCore {
+
+PassRefPtr<RenderTheme> RenderThemeChromiumLinux::create()
+{
+ return adoptRef(new RenderThemeChromiumLinux());
+}
+
+PassRefPtr<RenderTheme> RenderTheme::themeForPage(Page* page)
+{
+ static RenderTheme* rt = RenderThemeChromiumLinux::create().releaseRef();
+ return rt;
+}
+
+RenderThemeChromiumLinux::RenderThemeChromiumLinux()
+{
+}
+
+RenderThemeChromiumLinux::~RenderThemeChromiumLinux()
+{
+}
+
+Color RenderThemeChromiumLinux::systemColor(int cssValueId) const
+{
+ static const Color linuxButtonGrayColor(0xffdddddd);
+
+ if (cssValueId == CSSValueButtonface)
+ return linuxButtonGrayColor;
+ return RenderTheme::systemColor(cssValueId);
+}
+
+String RenderThemeChromiumLinux::extraDefaultStyleSheet()
+{
+ return RenderThemeChromiumSkia::extraDefaultStyleSheet() +
+ String(themeChromiumLinuxUserAgentStyleSheet, sizeof(themeChromiumLinuxUserAgentStyleSheet));
+}
+
+bool RenderThemeChromiumLinux::controlSupportsTints(const RenderObject* o) const
+{
+ return isEnabled(o);
+}
+
+Color RenderThemeChromiumLinux::activeListBoxSelectionBackgroundColor() const
+{
+ return Color(0x28, 0x28, 0x28);
+}
+
+Color RenderThemeChromiumLinux::activeListBoxSelectionForegroundColor() const
+{
+ return Color::black;
+}
+
+Color RenderThemeChromiumLinux::inactiveListBoxSelectionBackgroundColor() const
+{
+ return Color(0xc8, 0xc8, 0xc8);
+}
+
+Color RenderThemeChromiumLinux::inactiveListBoxSelectionForegroundColor() const
+{
+ return Color(0x32, 0x32, 0x32);
+}
+
+bool RenderThemeChromiumLinux::supportsControlTints() const
+{
+ return true;
+}
+
+} // namespace WebCore
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderThemeChromiumLinux.h b/src/3rdparty/webkit/WebCore/rendering/RenderThemeChromiumLinux.h
new file mode 100644
index 0000000..e75ddd5
--- /dev/null
+++ b/src/3rdparty/webkit/WebCore/rendering/RenderThemeChromiumLinux.h
@@ -0,0 +1,62 @@
+/*
+ * This file is part of the WebKit project.
+ *
+ * Copyright (C) 2006 Apple Computer, Inc.
+ * Copyright (C) 2006 Michael Emmel mike.emmel@gmail.com
+ * Copyright (C) 2007 Holger Hans Peter Freyther
+ * Copyright (C) 2007 Alp Toker <alp@atoker.com>
+ * Copyright (C) 2008, 2009 Google, Inc.
+ * All rights reserved.
+ * Copyright (C) 2009 Kenneth Rohde Christiansen
+ *
+ * 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 RenderThemeChromiumLinux_h
+#define RenderThemeChromiumLinux_h
+
+#include "RenderThemeChromiumSkia.h"
+
+namespace WebCore {
+
+ class RenderThemeChromiumLinux : public RenderThemeChromiumSkia {
+ public:
+ static PassRefPtr<RenderTheme> create();
+ virtual String extraDefaultStyleSheet();
+
+ virtual Color systemColor(int cssValidId) const;
+
+ // A method asking if the control changes its tint when the window has focus or not.
+ virtual bool controlSupportsTints(const RenderObject*) const;
+
+ // List Box selection color
+ virtual Color activeListBoxSelectionBackgroundColor() const;
+ virtual Color activeListBoxSelectionForegroundColor() const;
+ virtual Color inactiveListBoxSelectionBackgroundColor() const;
+ virtual Color inactiveListBoxSelectionForegroundColor() const;
+
+ private:
+ RenderThemeChromiumLinux();
+ virtual ~RenderThemeChromiumLinux();
+
+ // A general method asking if any control tinting is supported at all.
+ virtual bool supportsControlTints() const;
+ };
+
+} // namespace WebCore
+
+#endif // RenderThemeChromiumLinux_h
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderThemeChromiumMac.h b/src/3rdparty/webkit/WebCore/rendering/RenderThemeChromiumMac.h
new file mode 100644
index 0000000..5497d52
--- /dev/null
+++ b/src/3rdparty/webkit/WebCore/rendering/RenderThemeChromiumMac.h
@@ -0,0 +1,220 @@
+/*
+ * This file is part of the theme implementation for form controls in WebCore.
+ *
+ * Copyright (C) 2005 Apple Computer, Inc.
+ * Copyright (C) 2008, 2009 Google, Inc.
+ * Copyright (C) 2009 Kenneth Rohde Christiansen
+ *
+ * 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 RenderThemeChromiumMac_h
+#define RenderThemeChromiumMac_h
+
+#import "RenderTheme.h"
+#import <AppKit/AppKit.h>
+#import <wtf/HashMap.h>
+#import <wtf/RetainPtr.h>
+
+#ifdef __OBJC__
+@class WebCoreRenderThemeNotificationObserver;
+#else
+class WebCoreRenderThemeNotificationObserver;
+#endif
+
+namespace WebCore {
+
+ class RenderStyle;
+
+ class RenderThemeChromiumMac : public RenderTheme {
+ public:
+ static PassRefPtr<RenderTheme> create();
+
+ // A method to obtain the baseline position for a "leaf" control. This will only be used if a baseline
+ // position cannot be determined by examining child content. Checkboxes and radio buttons are examples of
+ // controls that need to do this.
+ virtual int baselinePosition(const RenderObject*) const;
+
+ // A method asking if the control changes its tint when the window has focus or not.
+ virtual bool controlSupportsTints(const RenderObject*) const;
+
+ // A general method asking if any control tinting is supported at all.
+ virtual bool supportsControlTints() const { return true; }
+
+ virtual void adjustRepaintRect(const RenderObject*, IntRect&);
+
+ virtual bool isControlStyled(const RenderStyle*, const BorderData&,
+ const FillLayer&, const Color& backgroundColor) const;
+
+ virtual Color platformActiveSelectionBackgroundColor() const;
+ virtual Color platformInactiveSelectionBackgroundColor() const;
+ virtual Color activeListBoxSelectionBackgroundColor() const;
+
+ virtual Color focusRingColor() const;
+
+ virtual void platformColorsDidChange();
+
+ // System fonts.
+ virtual void systemFont(int cssValueId, FontDescription&) const;
+
+ virtual int minimumMenuListSize(RenderStyle*) const;
+
+ virtual void adjustSliderThumbSize(RenderObject*) const;
+
+ virtual int popupInternalPaddingLeft(RenderStyle*) const;
+ virtual int popupInternalPaddingRight(RenderStyle*) const;
+ virtual int popupInternalPaddingTop(RenderStyle*) const;
+ virtual int popupInternalPaddingBottom(RenderStyle*) const;
+
+ virtual ScrollbarControlSize scrollbarControlSizeForPart(ControlPart) { return SmallScrollbar; }
+
+ virtual bool paintCapsLockIndicator(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+
+ virtual Color systemColor(int cssValueId) const;
+
+ protected:
+ virtual bool supportsSelectionForegroundColors() const { return false; }
+
+ // Methods for each appearance value.
+ virtual bool paintCheckbox(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+ virtual void setCheckboxSize(RenderStyle*) const;
+
+ virtual bool paintRadio(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+ virtual void setRadioSize(RenderStyle*) const;
+
+ virtual void adjustButtonStyle(CSSStyleSelector*, RenderStyle*, WebCore::Element*) const;
+ virtual bool paintButton(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+ virtual void setButtonSize(RenderStyle*) const;
+
+ virtual bool paintTextField(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+ virtual void adjustTextFieldStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+
+ virtual bool paintTextArea(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+ virtual void adjustTextAreaStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+
+ virtual bool paintMenuList(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+ virtual void adjustMenuListStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+
+ virtual bool paintMenuListButton(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+ virtual void adjustMenuListButtonStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+
+ virtual bool paintSliderTrack(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+ virtual void adjustSliderTrackStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+
+ virtual bool paintSliderThumb(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+ virtual void adjustSliderThumbStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+
+ virtual bool paintSearchField(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+ virtual void adjustSearchFieldStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+
+ virtual void adjustSearchFieldCancelButtonStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+ virtual bool paintSearchFieldCancelButton(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+
+ virtual void adjustSearchFieldDecorationStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+ virtual bool paintSearchFieldDecoration(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+
+ virtual void adjustSearchFieldResultsDecorationStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+ virtual bool paintSearchFieldResultsDecoration(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+
+ virtual void adjustSearchFieldResultsButtonStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+ virtual bool paintSearchFieldResultsButton(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+
+ virtual bool paintMediaFullscreenButton(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+ virtual bool paintMediaPlayButton(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+ virtual bool paintMediaMuteButton(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+ virtual bool paintMediaSeekBackButton(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+ virtual bool paintMediaSeekForwardButton(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+ virtual bool paintMediaSliderTrack(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+ virtual bool paintMediaSliderThumb(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+
+ private:
+ RenderThemeChromiumMac();
+ virtual ~RenderThemeChromiumMac();
+
+ IntRect inflateRect(const IntRect&, const IntSize&, const int* margins, float zoomLevel = 1.0f) const;
+
+ // Get the control size based off the font. Used by some of the controls (like buttons).
+ NSControlSize controlSizeForFont(RenderStyle*) const;
+ NSControlSize controlSizeForSystemFont(RenderStyle*) const;
+ void setControlSize(NSCell*, const IntSize* sizes, const IntSize& minSize, float zoomLevel = 1.0f);
+ void setSizeFromFont(RenderStyle*, const IntSize* sizes) const;
+ IntSize sizeForFont(RenderStyle*, const IntSize* sizes) const;
+ IntSize sizeForSystemFont(RenderStyle*, const IntSize* sizes) const;
+ void setFontFromControlSize(CSSStyleSelector*, RenderStyle*, NSControlSize) const;
+
+ void updateCheckedState(NSCell*, const RenderObject*);
+ void updateEnabledState(NSCell*, const RenderObject*);
+ void updateFocusedState(NSCell*, const RenderObject*);
+ void updatePressedState(NSCell*, const RenderObject*);
+
+ // Helpers for adjusting appearance and for painting
+ const IntSize* checkboxSizes() const;
+ const int* checkboxMargins() const;
+ void setCheckboxCellState(const RenderObject*, const IntRect&);
+
+ const IntSize* radioSizes() const;
+ const int* radioMargins() const;
+ void setRadioCellState(const RenderObject*, const IntRect&);
+
+ void setButtonPaddingFromControlSize(RenderStyle*, NSControlSize) const;
+ const IntSize* buttonSizes() const;
+ const int* buttonMargins() const;
+ void setButtonCellState(const RenderObject*, const IntRect&);
+
+ void setPopupButtonCellState(const RenderObject*, const IntRect&);
+ const IntSize* popupButtonSizes() const;
+ const int* popupButtonMargins() const;
+ const int* popupButtonPadding(NSControlSize) const;
+ void paintMenuListButtonGradients(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+ const IntSize* menuListSizes() const;
+
+ const IntSize* searchFieldSizes() const;
+ const IntSize* cancelButtonSizes() const;
+ const IntSize* resultsButtonSizes() const;
+ void setSearchCellState(RenderObject*, const IntRect&);
+ void setSearchFieldSize(RenderStyle*) const;
+
+ NSButtonCell* checkbox() const;
+ NSButtonCell* radio() const;
+ NSButtonCell* button() const;
+ NSPopUpButtonCell* popupButton() const;
+ NSSearchFieldCell* search() const;
+ NSMenu* searchMenuTemplate() const;
+ NSSliderCell* sliderThumbHorizontal() const;
+ NSSliderCell* sliderThumbVertical() const;
+
+ private:
+ mutable RetainPtr<NSButtonCell> m_checkbox;
+ mutable RetainPtr<NSButtonCell> m_radio;
+ mutable RetainPtr<NSButtonCell> m_button;
+ mutable RetainPtr<NSPopUpButtonCell> m_popupButton;
+ mutable RetainPtr<NSSearchFieldCell> m_search;
+ mutable RetainPtr<NSMenu> m_searchMenuTemplate;
+ mutable RetainPtr<NSSliderCell> m_sliderThumbHorizontal;
+ mutable RetainPtr<NSSliderCell> m_sliderThumbVertical;
+
+ bool m_isSliderThumbHorizontalPressed;
+ bool m_isSliderThumbVerticalPressed;
+
+ mutable HashMap<int, RGBA32> m_systemColorCache;
+
+ RetainPtr<WebCoreRenderThemeNotificationObserver> m_notificationObserver;
+ };
+
+} // namespace WebCore
+
+#endif
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderThemeChromiumMac.mm b/src/3rdparty/webkit/WebCore/rendering/RenderThemeChromiumMac.mm
new file mode 100644
index 0000000..bd90831
--- /dev/null
+++ b/src/3rdparty/webkit/WebCore/rendering/RenderThemeChromiumMac.mm
@@ -0,0 +1,2016 @@
+/*
+ * Copyright (C) 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2008, 2009 Google, Inc.
+ * Copyright (C) 2009 Kenneth Rohde Christiansen
+ *
+ * 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.
+ */
+
+// FIXME: we still need to figure out if passing a null view to the cell
+// drawing routines will work. I expect not, and if that's the case we'll have
+// to figure out something else. For now, at least leave the lines commented
+// in, but the procurement of the view if 0'd.
+
+#import "config.h"
+#import "RenderThemeChromiumMac.h"
+
+#import <Carbon/Carbon.h>
+#import <Cocoa/Cocoa.h>
+#import <math.h>
+
+#import "BitmapImage.h"
+#import "ChromiumBridge.h"
+#import "ColorMac.h"
+#import "CSSStyleSelector.h"
+#import "CSSValueKeywords.h"
+#import "Element.h"
+#import "FoundationExtras.h"
+#import "FrameView.h"
+#import "GraphicsContext.h"
+#import "HTMLInputElement.h"
+#import "HTMLMediaElement.h"
+#import "HTMLNames.h"
+#import "Image.h"
+#import "LocalCurrentGraphicsContext.h"
+#import "MediaControlElements.h"
+#import "RenderSlider.h"
+#import "RenderView.h"
+#import "SharedBuffer.h"
+#import "WebCoreSystemInterface.h"
+#import <wtf/RetainPtr.h>
+
+#ifdef BUILDING_ON_TIGER
+typedef int NSInteger;
+typedef unsigned NSUInteger;
+#endif
+
+using std::min;
+
+// The methods in this file are specific to the Mac OS X platform.
+
+// FIXME: The platform-independent code in this class should be factored out and merged with RenderThemeSafari.
+
+@interface WebCoreRenderThemeNotificationObserver : NSObject
+{
+ WebCore::RenderTheme *_theme;
+}
+
+- (id)initWithTheme:(WebCore::RenderTheme *)theme;
+- (void)systemColorsDidChange:(NSNotification *)notification;
+
+@end
+
+@implementation WebCoreRenderThemeNotificationObserver
+
+- (id)initWithTheme:(WebCore::RenderTheme *)theme
+{
+ [super init];
+ _theme = theme;
+
+ return self;
+}
+
+- (void)systemColorsDidChange:(NSNotification *)notification
+{
+ ASSERT([[notification name] isEqualToString:NSSystemColorsDidChangeNotification]);
+ _theme->platformColorsDidChange();
+}
+
+@end
+
+namespace WebCore {
+
+using namespace HTMLNames;
+
+enum {
+ TopMargin,
+ RightMargin,
+ BottomMargin,
+ LeftMargin
+};
+
+enum {
+ TopPadding,
+ RightPadding,
+ BottomPadding,
+ LeftPadding
+};
+
+// In our Mac port, we don't define PLATFORM(MAC) and thus don't pick up the
+// |operator NSRect()| on WebCore::IntRect and FloatRect. This substitues for
+// that missing conversion operator.
+NSRect IntRectToNSRect(const IntRect & rect)
+{
+ return NSMakeRect(rect.x(), rect.y(), rect.width(), rect.height());
+}
+
+NSRect FloatRectToNSRect(const FloatRect & rect)
+{
+ return NSMakeRect(rect.x(), rect.y(), rect.width(), rect.height());
+}
+
+IntRect NSRectToIntRect(const NSRect & rect)
+{
+ return IntRect(rect.origin.x, rect.origin.y, rect.size.width, rect.size.height);
+}
+
+PassRefPtr<RenderTheme> RenderThemeChromiumMac::create()
+{
+ return adoptRef(new RenderThemeChromiumMac);
+}
+
+PassRefPtr<RenderTheme> RenderTheme::themeForPage(Page* page)
+{
+ static RenderTheme* rt = RenderThemeChromiumMac::create().releaseRef();
+ return rt;
+}
+
+RenderThemeChromiumMac::RenderThemeChromiumMac()
+ : m_isSliderThumbHorizontalPressed(false)
+ , m_isSliderThumbVerticalPressed(false)
+ , m_notificationObserver(AdoptNS, [[WebCoreRenderThemeNotificationObserver alloc] initWithTheme:this])
+{
+ [[NSNotificationCenter defaultCenter] addObserver:m_notificationObserver.get()
+ selector:@selector(systemColorsDidChange:)
+ name:NSSystemColorsDidChangeNotification
+ object:nil];
+}
+
+RenderThemeChromiumMac::~RenderThemeChromiumMac()
+{
+ [[NSNotificationCenter defaultCenter] removeObserver:m_notificationObserver.get()];
+}
+
+Color RenderThemeChromiumMac::platformActiveSelectionBackgroundColor() const
+{
+ NSColor* color = [[NSColor selectedTextBackgroundColor] colorUsingColorSpaceName:NSDeviceRGBColorSpace];
+ return Color(static_cast<int>(255.0 * [color redComponent]), static_cast<int>(255.0 * [color greenComponent]), static_cast<int>(255.0 * [color blueComponent]));
+}
+
+Color RenderThemeChromiumMac::platformInactiveSelectionBackgroundColor() const
+{
+ NSColor* color = [[NSColor secondarySelectedControlColor] colorUsingColorSpaceName:NSDeviceRGBColorSpace];
+ return Color(static_cast<int>(255.0 * [color redComponent]), static_cast<int>(255.0 * [color greenComponent]), static_cast<int>(255.0 * [color blueComponent]));
+}
+
+Color RenderThemeChromiumMac::activeListBoxSelectionBackgroundColor() const
+{
+ NSColor* color = [[NSColor alternateSelectedControlColor] colorUsingColorSpaceName:NSDeviceRGBColorSpace];
+ return Color(static_cast<int>(255.0 * [color redComponent]), static_cast<int>(255.0 * [color greenComponent]), static_cast<int>(255.0 * [color blueComponent]));
+}
+
+Color RenderThemeChromiumMac::focusRingColor() const
+{
+ if (ChromiumBridge::layoutTestMode())
+ return oldAquaFocusRingColor();
+
+ return systemColor(CSSValueWebkitFocusRingColor);
+}
+
+static FontWeight toFontWeight(NSInteger appKitFontWeight)
+{
+ ASSERT(appKitFontWeight > 0 && appKitFontWeight < 15);
+ if (appKitFontWeight > 14)
+ appKitFontWeight = 14;
+ else if (appKitFontWeight < 1)
+ appKitFontWeight = 1;
+
+ static FontWeight fontWeights[] = {
+ FontWeight100,
+ FontWeight100,
+ FontWeight200,
+ FontWeight300,
+ FontWeight400,
+ FontWeight500,
+ FontWeight600,
+ FontWeight600,
+ FontWeight700,
+ FontWeight800,
+ FontWeight800,
+ FontWeight900,
+ FontWeight900,
+ FontWeight900
+ };
+ return fontWeights[appKitFontWeight - 1];
+}
+
+void RenderThemeChromiumMac::systemFont(int cssValueId, FontDescription& fontDescription) const
+{
+ static FontDescription systemFont;
+ static FontDescription smallSystemFont;
+ static FontDescription menuFont;
+ static FontDescription labelFont;
+ static FontDescription miniControlFont;
+ static FontDescription smallControlFont;
+ static FontDescription controlFont;
+
+ FontDescription* cachedDesc;
+ NSFont* font = nil;
+ switch (cssValueId) {
+ case CSSValueSmallCaption:
+ cachedDesc = &smallSystemFont;
+ if (!smallSystemFont.isAbsoluteSize())
+ font = [NSFont systemFontOfSize:[NSFont smallSystemFontSize]];
+ break;
+ case CSSValueMenu:
+ cachedDesc = &menuFont;
+ if (!menuFont.isAbsoluteSize())
+ font = [NSFont menuFontOfSize:[NSFont systemFontSize]];
+ break;
+ case CSSValueStatusBar:
+ cachedDesc = &labelFont;
+ if (!labelFont.isAbsoluteSize())
+ font = [NSFont labelFontOfSize:[NSFont labelFontSize]];
+ break;
+ case CSSValueWebkitMiniControl:
+ cachedDesc = &miniControlFont;
+ if (!miniControlFont.isAbsoluteSize())
+ font = [NSFont systemFontOfSize:[NSFont systemFontSizeForControlSize:NSMiniControlSize]];
+ break;
+ case CSSValueWebkitSmallControl:
+ cachedDesc = &smallControlFont;
+ if (!smallControlFont.isAbsoluteSize())
+ font = [NSFont systemFontOfSize:[NSFont systemFontSizeForControlSize:NSSmallControlSize]];
+ break;
+ case CSSValueWebkitControl:
+ cachedDesc = &controlFont;
+ if (!controlFont.isAbsoluteSize())
+ font = [NSFont systemFontOfSize:[NSFont systemFontSizeForControlSize:NSRegularControlSize]];
+ break;
+ default:
+ cachedDesc = &systemFont;
+ if (!systemFont.isAbsoluteSize())
+ font = [NSFont systemFontOfSize:[NSFont systemFontSize]];
+ }
+
+ if (font) {
+ NSFontManager *fontManager = [NSFontManager sharedFontManager];
+ cachedDesc->setIsAbsoluteSize(true);
+ cachedDesc->setGenericFamily(FontDescription::NoFamily);
+ cachedDesc->firstFamily().setFamily([font familyName]);
+ cachedDesc->setSpecifiedSize([font pointSize]);
+ cachedDesc->setWeight(toFontWeight([fontManager weightOfFont:font]));
+ cachedDesc->setItalic([fontManager traitsOfFont:font] & NSItalicFontMask);
+ }
+ fontDescription = *cachedDesc;
+}
+
+static RGBA32 convertNSColorToColor(NSColor *color)
+{
+ NSColor *colorInColorSpace = [color colorUsingColorSpaceName:NSCalibratedRGBColorSpace];
+ if (colorInColorSpace) {
+ static const double scaleFactor = nextafter(256.0, 0.0);
+ return makeRGB(static_cast<int>(scaleFactor * [colorInColorSpace redComponent]),
+ static_cast<int>(scaleFactor * [colorInColorSpace greenComponent]),
+ static_cast<int>(scaleFactor * [colorInColorSpace blueComponent]));
+ }
+
+ // This conversion above can fail if the NSColor in question is an NSPatternColor
+ // (as many system colors are). These colors are actually a repeating pattern
+ // not just a solid color. To work around this we simply draw a 1x1 image of
+ // the color and use that pixel's color. It might be better to use an average of
+ // the colors in the pattern instead.
+ NSBitmapImageRep *offscreenRep = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:nil
+ pixelsWide:1
+ pixelsHigh:1
+ bitsPerSample:8
+ samplesPerPixel:4
+ hasAlpha:YES
+ isPlanar:NO
+ colorSpaceName:NSCalibratedRGBColorSpace
+ bytesPerRow:4
+ bitsPerPixel:32];
+
+ [NSGraphicsContext saveGraphicsState];
+ [NSGraphicsContext setCurrentContext:[NSGraphicsContext graphicsContextWithBitmapImageRep:offscreenRep]];
+ NSEraseRect(NSMakeRect(0, 0, 1, 1));
+ [color drawSwatchInRect:NSMakeRect(0, 0, 1, 1)];
+ [NSGraphicsContext restoreGraphicsState];
+
+ NSUInteger pixel[4];
+ [offscreenRep getPixel:pixel atX:0 y:0];
+
+ [offscreenRep release];
+
+ return makeRGB(pixel[0], pixel[1], pixel[2]);
+}
+
+static RGBA32 menuBackgroundColor()
+{
+ NSBitmapImageRep *offscreenRep = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:nil
+ pixelsWide:1
+ pixelsHigh:1
+ bitsPerSample:8
+ samplesPerPixel:4
+ hasAlpha:YES
+ isPlanar:NO
+ colorSpaceName:NSCalibratedRGBColorSpace
+ bytesPerRow:4
+ bitsPerPixel:32];
+
+ CGContextRef context = static_cast<CGContextRef>([[NSGraphicsContext graphicsContextWithBitmapImageRep:offscreenRep] graphicsPort]);
+ CGRect rect = CGRectMake(0, 0, 1, 1);
+ HIThemeMenuDrawInfo drawInfo;
+ drawInfo.version = 0;
+ drawInfo.menuType = kThemeMenuTypePopUp;
+ HIThemeDrawMenuBackground(&rect, &drawInfo, context, kHIThemeOrientationInverted);
+
+ NSUInteger pixel[4];
+ [offscreenRep getPixel:pixel atX:0 y:0];
+
+ [offscreenRep release];
+
+ return makeRGB(pixel[0], pixel[1], pixel[2]);
+}
+
+void RenderThemeChromiumMac::platformColorsDidChange()
+{
+ m_systemColorCache.clear();
+ RenderTheme::platformColorsDidChange();
+}
+
+Color RenderThemeChromiumMac::systemColor(int cssValueId) const
+{
+ if (m_systemColorCache.contains(cssValueId))
+ return m_systemColorCache.get(cssValueId);
+
+ Color color;
+ switch (cssValueId) {
+ case CSSValueActiveborder:
+ color = convertNSColorToColor([NSColor keyboardFocusIndicatorColor]);
+ break;
+ case CSSValueActivecaption:
+ color = convertNSColorToColor([NSColor windowFrameTextColor]);
+ break;
+ case CSSValueAppworkspace:
+ color = convertNSColorToColor([NSColor headerColor]);
+ break;
+ case CSSValueBackground:
+ // Use theme independent default
+ break;
+ case CSSValueButtonface:
+ // We use this value instead of NSColor's controlColor to avoid website incompatibilities.
+ // We may want to change this to use the NSColor in future.
+ color = 0xFFC0C0C0;
+ break;
+ case CSSValueButtonhighlight:
+ color = convertNSColorToColor([NSColor controlHighlightColor]);
+ break;
+ case CSSValueButtonshadow:
+ color = convertNSColorToColor([NSColor controlShadowColor]);
+ break;
+ case CSSValueButtontext:
+ color = convertNSColorToColor([NSColor controlTextColor]);
+ break;
+ case CSSValueCaptiontext:
+ color = convertNSColorToColor([NSColor textColor]);
+ break;
+ case CSSValueGraytext:
+ color = convertNSColorToColor([NSColor disabledControlTextColor]);
+ break;
+ case CSSValueHighlight:
+ color = convertNSColorToColor([NSColor selectedTextBackgroundColor]);
+ break;
+ case CSSValueHighlighttext:
+ color = convertNSColorToColor([NSColor selectedTextColor]);
+ break;
+ case CSSValueInactiveborder:
+ color = convertNSColorToColor([NSColor controlBackgroundColor]);
+ break;
+ case CSSValueInactivecaption:
+ color = convertNSColorToColor([NSColor controlBackgroundColor]);
+ break;
+ case CSSValueInactivecaptiontext:
+ color = convertNSColorToColor([NSColor textColor]);
+ break;
+ case CSSValueInfobackground:
+ // There is no corresponding NSColor for this so we use a hard coded value.
+ color = 0xFFFBFCC5;
+ break;
+ case CSSValueInfotext:
+ color = convertNSColorToColor([NSColor textColor]);
+ break;
+ case CSSValueMenu:
+ color = menuBackgroundColor();
+ break;
+ case CSSValueMenutext:
+ color = convertNSColorToColor([NSColor selectedMenuItemTextColor]);
+ break;
+ case CSSValueScrollbar:
+ color = convertNSColorToColor([NSColor scrollBarColor]);
+ break;
+ case CSSValueText:
+ color = convertNSColorToColor([NSColor textColor]);
+ break;
+ case CSSValueThreeddarkshadow:
+ color = convertNSColorToColor([NSColor controlDarkShadowColor]);
+ break;
+ case CSSValueThreedshadow:
+ color = convertNSColorToColor([NSColor shadowColor]);
+ break;
+ case CSSValueThreedface:
+ // We use this value instead of NSColor's controlColor to avoid website incompatibilities.
+ // We may want to change this to use the NSColor in future.
+ color = 0xFFC0C0C0;
+ break;
+ case CSSValueThreedhighlight:
+ color = convertNSColorToColor([NSColor highlightColor]);
+ break;
+ case CSSValueThreedlightshadow:
+ color = convertNSColorToColor([NSColor controlLightHighlightColor]);
+ break;
+ case CSSValueWebkitFocusRingColor:
+ color = convertNSColorToColor([NSColor keyboardFocusIndicatorColor]);
+ break;
+ case CSSValueWindow:
+ color = convertNSColorToColor([NSColor windowBackgroundColor]);
+ break;
+ case CSSValueWindowframe:
+ color = convertNSColorToColor([NSColor windowFrameColor]);
+ break;
+ case CSSValueWindowtext:
+ color = convertNSColorToColor([NSColor windowFrameTextColor]);
+ break;
+ }
+
+ if (!color.isValid())
+ color = RenderTheme::systemColor(cssValueId);
+
+ if (color.isValid())
+ m_systemColorCache.set(cssValueId, color.rgb());
+
+ return color;
+}
+
+bool RenderThemeChromiumMac::isControlStyled(const RenderStyle* style, const BorderData& border,
+ const FillLayer& background, const Color& backgroundColor) const
+{
+ if (style->appearance() == TextFieldPart || style->appearance() == TextAreaPart || style->appearance() == ListboxPart)
+ return style->border() != border;
+
+ // FIXME: This is horrible, but there is not much else that can be done. Menu lists cannot draw properly when
+ // scaled. They can't really draw properly when transformed either. We can't detect the transform case at style
+ // adjustment time so that will just have to stay broken. We can however detect that we're zooming. If zooming
+ // is in effect we treat it like the control is styled.
+ if (style->appearance() == MenulistPart && style->effectiveZoom() != 1.0f)
+ return true;
+
+ return RenderTheme::isControlStyled(style, border, background, backgroundColor);
+}
+
+// FIXME: Use the code from the old upstream version, before it was converted to the new theme API in r37731.
+void RenderThemeChromiumMac::adjustRepaintRect(const RenderObject* o, IntRect& r)
+{
+ float zoomLevel = o->style()->effectiveZoom();
+
+ switch (o->style()->appearance()) {
+ case CheckboxPart: {
+ // Since we query the prototype cell, we need to update its state to match.
+ setCheckboxCellState(o, r);
+
+ // We inflate the rect as needed to account for padding included in the cell to accommodate the checkbox
+ // shadow" and the check. We don't consider this part of the bounds of the control in WebKit.
+ IntSize size = checkboxSizes()[[checkbox() controlSize]];
+ size.setHeight(size.height() * zoomLevel);
+ size.setWidth(size.width() * zoomLevel);
+ r = inflateRect(r, size, checkboxMargins(), zoomLevel);
+ break;
+ }
+ case RadioPart: {
+ // Since we query the prototype cell, we need to update its state to match.
+ setRadioCellState(o, r);
+
+ // We inflate the rect as needed to account for padding included in the cell to accommodate the checkbox
+ // shadow" and the check. We don't consider this part of the bounds of the control in WebKit.
+ IntSize size = radioSizes()[[radio() controlSize]];
+ size.setHeight(size.height() * zoomLevel);
+ size.setWidth(size.width() * zoomLevel);
+ r = inflateRect(r, size, radioMargins(), zoomLevel);
+ break;
+ }
+ case PushButtonPart:
+ case DefaultButtonPart:
+ case ButtonPart: {
+ // Since we query the prototype cell, we need to update its state to match.
+ setButtonCellState(o, r);
+
+ // We inflate the rect as needed to account for padding included in the cell to accommodate the checkbox
+ // shadow" and the check. We don't consider this part of the bounds of the control in WebKit.
+ if ([button() bezelStyle] == NSRoundedBezelStyle) {
+ IntSize size = buttonSizes()[[button() controlSize]];
+ size.setHeight(size.height() * zoomLevel);
+ size.setWidth(r.width());
+ r = inflateRect(r, size, buttonMargins(), zoomLevel);
+ }
+ break;
+ }
+ case MenulistPart: {
+ setPopupButtonCellState(o, r);
+ IntSize size = popupButtonSizes()[[popupButton() controlSize]];
+ size.setHeight(size.height() * zoomLevel);
+ size.setWidth(r.width());
+ r = inflateRect(r, size, popupButtonMargins(), zoomLevel);
+ break;
+ }
+ default:
+ break;
+ }
+}
+
+IntRect RenderThemeChromiumMac::inflateRect(const IntRect& r, const IntSize& size, const int* margins, float zoomLevel) const
+{
+ // Only do the inflation if the available width/height are too small. Otherwise try to
+ // fit the glow/check space into the available box's width/height.
+ int widthDelta = r.width() - (size.width() + margins[LeftMargin] * zoomLevel + margins[RightMargin] * zoomLevel);
+ int heightDelta = r.height() - (size.height() + margins[TopMargin] * zoomLevel + margins[BottomMargin] * zoomLevel);
+ IntRect result(r);
+ if (widthDelta < 0) {
+ result.setX(result.x() - margins[LeftMargin] * zoomLevel);
+ result.setWidth(result.width() - widthDelta);
+ }
+ if (heightDelta < 0) {
+ result.setY(result.y() - margins[TopMargin] * zoomLevel);
+ result.setHeight(result.height() - heightDelta);
+ }
+ return result;
+}
+
+void RenderThemeChromiumMac::updateCheckedState(NSCell* cell, const RenderObject* o)
+{
+ bool oldIndeterminate = [cell state] == NSMixedState;
+ bool indeterminate = isIndeterminate(o);
+ bool checked = isChecked(o);
+
+ if (oldIndeterminate != indeterminate) {
+ [cell setState:indeterminate ? NSMixedState : (checked ? NSOnState : NSOffState)];
+ return;
+ }
+
+ bool oldChecked = [cell state] == NSOnState;
+ if (checked != oldChecked)
+ [cell setState:checked ? NSOnState : NSOffState];
+}
+
+void RenderThemeChromiumMac::updateEnabledState(NSCell* cell, const RenderObject* o)
+{
+ bool oldEnabled = [cell isEnabled];
+ bool enabled = isEnabled(o);
+ if (enabled != oldEnabled)
+ [cell setEnabled:enabled];
+}
+
+void RenderThemeChromiumMac::updateFocusedState(NSCell* cell, const RenderObject* o)
+{
+ bool oldFocused = [cell showsFirstResponder];
+ bool focused = isFocused(o) && o->style()->outlineStyleIsAuto();
+ if (focused != oldFocused)
+ [cell setShowsFirstResponder:focused];
+}
+
+void RenderThemeChromiumMac::updatePressedState(NSCell* cell, const RenderObject* o)
+{
+ bool oldPressed = [cell isHighlighted];
+ bool pressed = (o->node() && o->node()->active());
+ if (pressed != oldPressed)
+ [cell setHighlighted:pressed];
+}
+
+// FIXME: This used to be in the upstream version until it was converted to the new theme API in r37731.
+int RenderThemeChromiumMac::baselinePosition(const RenderObject* o) const
+{
+ if (!o->isBox())
+ return 0;
+
+ if (o->style()->appearance() == CheckboxPart || o->style()->appearance() == RadioPart) {
+ const RenderBox* box = toRenderBox(o);
+ return box->marginTop() + box->height() - 2 * o->style()->effectiveZoom(); // The baseline is 2px up from the bottom of the checkbox/radio in AppKit.
+ }
+ return RenderTheme::baselinePosition(o);
+}
+
+bool RenderThemeChromiumMac::controlSupportsTints(const RenderObject* o) const
+{
+ // An alternate way to implement this would be to get the appropriate cell object
+ // and call the private _needRedrawOnWindowChangedKeyState method. An advantage of
+ // that would be that we would match AppKit behavior more closely, but a disadvantage
+ // would be that we would rely on an AppKit SPI method.
+
+ if (!isEnabled(o))
+ return false;
+
+ // Checkboxes only have tint when checked.
+ if (o->style()->appearance() == CheckboxPart)
+ return isChecked(o);
+
+ // For now assume other controls have tint if enabled.
+ return true;
+}
+
+NSControlSize RenderThemeChromiumMac::controlSizeForFont(RenderStyle* style) const
+{
+ int fontSize = style->fontSize();
+ if (fontSize >= 16)
+ return NSRegularControlSize;
+ if (fontSize >= 11)
+ return NSSmallControlSize;
+ return NSMiniControlSize;
+}
+
+void RenderThemeChromiumMac::setControlSize(NSCell* cell, const IntSize* sizes, const IntSize& minSize, float zoomLevel)
+{
+ NSControlSize size;
+ if (minSize.width() >= static_cast<int>(sizes[NSRegularControlSize].width() * zoomLevel) &&
+ minSize.height() >= static_cast<int>(sizes[NSRegularControlSize].height() * zoomLevel))
+ size = NSRegularControlSize;
+ else if (minSize.width() >= static_cast<int>(sizes[NSSmallControlSize].width() * zoomLevel) &&
+ minSize.height() >= static_cast<int>(sizes[NSSmallControlSize].height() * zoomLevel))
+ size = NSSmallControlSize;
+ else
+ size = NSMiniControlSize;
+ if (size != [cell controlSize]) // Only update if we have to, since AppKit does work even if the size is the same.
+ [cell setControlSize:size];
+}
+
+IntSize RenderThemeChromiumMac::sizeForFont(RenderStyle* style, const IntSize* sizes) const
+{
+ if (style->effectiveZoom() != 1.0f) {
+ IntSize result = sizes[controlSizeForFont(style)];
+ return IntSize(result.width() * style->effectiveZoom(), result.height() * style->effectiveZoom());
+ }
+ return sizes[controlSizeForFont(style)];
+}
+
+IntSize RenderThemeChromiumMac::sizeForSystemFont(RenderStyle* style, const IntSize* sizes) const
+{
+ if (style->effectiveZoom() != 1.0f) {
+ IntSize result = sizes[controlSizeForSystemFont(style)];
+ return IntSize(result.width() * style->effectiveZoom(), result.height() * style->effectiveZoom());
+ }
+ return sizes[controlSizeForSystemFont(style)];
+}
+
+void RenderThemeChromiumMac::setSizeFromFont(RenderStyle* style, const IntSize* sizes) const
+{
+ // FIXME: Check is flawed, since it doesn't take min-width/max-width into account.
+ IntSize size = sizeForFont(style, sizes);
+ if (style->width().isIntrinsicOrAuto() && size.width() > 0)
+ style->setWidth(Length(size.width(), Fixed));
+ if (style->height().isAuto() && size.height() > 0)
+ style->setHeight(Length(size.height(), Fixed));
+}
+
+void RenderThemeChromiumMac::setFontFromControlSize(CSSStyleSelector* selector, RenderStyle* style, NSControlSize controlSize) const
+{
+ FontDescription fontDescription;
+ fontDescription.setIsAbsoluteSize(true);
+ fontDescription.setGenericFamily(FontDescription::SerifFamily);
+
+ NSFont* font = [NSFont systemFontOfSize:[NSFont systemFontSizeForControlSize:controlSize]];
+ fontDescription.firstFamily().setFamily([font familyName]);
+ fontDescription.setComputedSize([font pointSize] * style->effectiveZoom());
+ fontDescription.setSpecifiedSize([font pointSize] * style->effectiveZoom());
+
+ // Reset line height
+ style->setLineHeight(RenderStyle::initialLineHeight());
+
+ if (style->setFontDescription(fontDescription))
+ style->font().update(0);
+}
+
+NSControlSize RenderThemeChromiumMac::controlSizeForSystemFont(RenderStyle* style) const
+{
+ int fontSize = style->fontSize();
+ if (fontSize >= [NSFont systemFontSizeForControlSize:NSRegularControlSize])
+ return NSRegularControlSize;
+ if (fontSize >= [NSFont systemFontSizeForControlSize:NSSmallControlSize])
+ return NSSmallControlSize;
+ return NSMiniControlSize;
+}
+
+// FIXME: This used to be in the upstream version until it was converted to the new theme API in r37731.
+bool RenderThemeChromiumMac::paintCheckbox(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
+{
+ LocalCurrentGraphicsContext localContext(paintInfo.context);
+
+ // Determine the width and height needed for the control and prepare the cell for painting.
+ setCheckboxCellState(o, r);
+
+ paintInfo.context->save();
+
+ float zoomLevel = o->style()->effectiveZoom();
+
+ // We inflate the rect as needed to account for padding included in the cell to accommodate the checkbox
+ // shadow" and the check. We don't consider this part of the bounds of the control in WebKit.
+ NSButtonCell* checkbox = this->checkbox();
+ IntSize size = checkboxSizes()[[checkbox controlSize]];
+ size.setWidth(size.width() * zoomLevel);
+ size.setHeight(size.height() * zoomLevel);
+ IntRect inflatedRect = inflateRect(r, size, checkboxMargins(), zoomLevel);
+
+ if (zoomLevel != 1.0f) {
+ inflatedRect.setWidth(inflatedRect.width() / zoomLevel);
+ inflatedRect.setHeight(inflatedRect.height() / zoomLevel);
+ paintInfo.context->translate(inflatedRect.x(), inflatedRect.y());
+ paintInfo.context->scale(FloatSize(zoomLevel, zoomLevel));
+ paintInfo.context->translate(-inflatedRect.x(), -inflatedRect.y());
+ }
+
+ [checkbox drawWithFrame:NSRect(IntRectToNSRect(inflatedRect)) inView:nil];
+ [checkbox setControlView:nil];
+
+ paintInfo.context->restore();
+
+ return false;
+}
+
+// FIXME: This used to be in the upstream version until it was converted to the new theme API in r37731.
+const IntSize* RenderThemeChromiumMac::checkboxSizes() const
+{
+ static const IntSize sizes[3] = { IntSize(14, 14), IntSize(12, 12), IntSize(10, 10) };
+ return sizes;
+}
+
+// FIXME: This used to be in the upstream version until it was converted to the new theme API in r37731.
+const int* RenderThemeChromiumMac::checkboxMargins() const
+{
+ static const int margins[3][4] =
+ {
+ { 3, 4, 4, 2 },
+ { 4, 3, 3, 3 },
+ { 4, 3, 3, 3 },
+ };
+ return margins[[checkbox() controlSize]];
+}
+
+// FIXME: This used to be in the upstream version until it was converted to the new theme API in r37731.
+void RenderThemeChromiumMac::setCheckboxCellState(const RenderObject* o, const IntRect& r)
+{
+ NSButtonCell* checkbox = this->checkbox();
+
+ // Set the control size based off the rectangle we're painting into.
+ setControlSize(checkbox, checkboxSizes(), r.size(), o->style()->effectiveZoom());
+
+ // Update the various states we respond to.
+ updateCheckedState(checkbox, o);
+ updateEnabledState(checkbox, o);
+ updatePressedState(checkbox, o);
+ updateFocusedState(checkbox, o);
+}
+
+// FIXME: This used to be in the upstream version until it was converted to the new theme API in r37731.
+void RenderThemeChromiumMac::setCheckboxSize(RenderStyle* style) const
+{
+ // If the width and height are both specified, then we have nothing to do.
+ if (!style->width().isIntrinsicOrAuto() && !style->height().isAuto())
+ return;
+
+ // Use the font size to determine the intrinsic width of the control.
+ setSizeFromFont(style, checkboxSizes());
+}
+
+// FIXME: This used to be in the upstream version until it was converted to the new theme API in r37731.
+bool RenderThemeChromiumMac::paintRadio(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
+{
+ LocalCurrentGraphicsContext localContext(paintInfo.context);
+
+ // Determine the width and height needed for the control and prepare the cell for painting.
+ setRadioCellState(o, r);
+
+ paintInfo.context->save();
+
+ float zoomLevel = o->style()->effectiveZoom();
+
+ // We inflate the rect as needed to account for padding included in the cell to accommodate the checkbox
+ // shadow" and the check. We don't consider this part of the bounds of the control in WebKit.
+ NSButtonCell* radio = this->radio();
+ IntSize size = radioSizes()[[radio controlSize]];
+ size.setWidth(size.width() * zoomLevel);
+ size.setHeight(size.height() * zoomLevel);
+ IntRect inflatedRect = inflateRect(r, size, radioMargins(), zoomLevel);
+
+ if (zoomLevel != 1.0f) {
+ inflatedRect.setWidth(inflatedRect.width() / zoomLevel);
+ inflatedRect.setHeight(inflatedRect.height() / zoomLevel);
+ paintInfo.context->translate(inflatedRect.x(), inflatedRect.y());
+ paintInfo.context->scale(FloatSize(zoomLevel, zoomLevel));
+ paintInfo.context->translate(-inflatedRect.x(), -inflatedRect.y());
+ }
+
+ [radio drawWithFrame:NSRect(IntRectToNSRect(inflatedRect)) inView:nil];
+ [radio setControlView:nil];
+
+ paintInfo.context->restore();
+
+ return false;
+}
+
+// FIXME: This used to be in the upstream version until it was converted to the new theme API in r37731.
+const IntSize* RenderThemeChromiumMac::radioSizes() const
+{
+ static const IntSize sizes[3] = { IntSize(14, 15), IntSize(12, 13), IntSize(10, 10) };
+ return sizes;
+}
+
+// FIXME: This used to be in the upstream version until it was converted to the new theme API in r37731.
+const int* RenderThemeChromiumMac::radioMargins() const
+{
+ static const int margins[3][4] =
+ {
+ { 2, 2, 4, 2 },
+ { 3, 2, 3, 2 },
+ { 1, 0, 2, 0 },
+ };
+ return margins[[radio() controlSize]];
+}
+
+// FIXME: This used to be in the upstream version until it was converted to the new theme API in r37731.
+void RenderThemeChromiumMac::setRadioCellState(const RenderObject* o, const IntRect& r)
+{
+ NSButtonCell* radio = this->radio();
+
+ // Set the control size based off the rectangle we're painting into.
+ setControlSize(radio, radioSizes(), r.size(), o->style()->effectiveZoom());
+
+ // Update the various states we respond to.
+ updateCheckedState(radio, o);
+ updateEnabledState(radio, o);
+ updatePressedState(radio, o);
+ updateFocusedState(radio, o);
+}
+
+// FIXME: This used to be in the upstream version until it was converted to the new theme API in r37731.
+void RenderThemeChromiumMac::setRadioSize(RenderStyle* style) const
+{
+ // If the width and height are both specified, then we have nothing to do.
+ if (!style->width().isIntrinsicOrAuto() && !style->height().isAuto())
+ return;
+
+ // Use the font size to determine the intrinsic width of the control.
+ setSizeFromFont(style, radioSizes());
+}
+
+// FIXME: This used to be in the upstream version until it was converted to the new theme API in r37731.
+void RenderThemeChromiumMac::setButtonPaddingFromControlSize(RenderStyle* style, NSControlSize size) const
+{
+ // Just use 8px. AppKit wants to use 11px for mini buttons, but that padding is just too large
+ // for real-world Web sites (creating a huge necessary minimum width for buttons whose space is
+ // by definition constrained, since we select mini only for small cramped environments.
+ // This also guarantees the HTML4 <button> will match our rendering by default, since we're using a consistent
+ // padding.
+ const int padding = 8 * style->effectiveZoom();
+ style->setPaddingLeft(Length(padding, Fixed));
+ style->setPaddingRight(Length(padding, Fixed));
+ style->setPaddingTop(Length(0, Fixed));
+ style->setPaddingBottom(Length(0, Fixed));
+}
+
+// FIXME: This used to be in the upstream version until it was converted to the new theme API in r37731.
+void RenderThemeChromiumMac::adjustButtonStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
+{
+ // There are three appearance constants for buttons.
+ // (1) Push-button is the constant for the default Aqua system button. Push buttons will not scale vertically and will not allow
+ // custom fonts or colors. <input>s use this constant. This button will allow custom colors and font weights/variants but won't
+ // scale vertically.
+ // (2) square-button is the constant for the square button. This button will allow custom fonts and colors and will scale vertically.
+ // (3) Button is the constant that means "pick the best button as appropriate." <button>s use this constant. This button will
+ // also scale vertically and allow custom fonts and colors. It will attempt to use Aqua if possible and will make this determination
+ // solely on the rectangle of the control.
+
+ // Determine our control size based off our font.
+ NSControlSize controlSize = controlSizeForFont(style);
+
+ if (style->appearance() == PushButtonPart) {
+ // Ditch the border.
+ style->resetBorder();
+
+ // Height is locked to auto.
+ style->setHeight(Length(Auto));
+
+ // White-space is locked to pre
+ style->setWhiteSpace(PRE);
+
+ // Set the button's vertical size.
+ setButtonSize(style);
+
+ // Add in the padding that we'd like to use.
+ setButtonPaddingFromControlSize(style, controlSize);
+
+ // Our font is locked to the appropriate system font size for the control. To clarify, we first use the CSS-specified font to figure out
+ // a reasonable control size, but once that control size is determined, we throw that font away and use the appropriate
+ // system font for the control size instead.
+ setFontFromControlSize(selector, style, controlSize);
+ } else {
+ // Set a min-height so that we can't get smaller than the mini button.
+ style->setMinHeight(Length(static_cast<int>(15 * style->effectiveZoom()), Fixed));
+
+ // Reset the top and bottom borders.
+ style->resetBorderTop();
+ style->resetBorderBottom();
+ }
+
+ style->setBoxShadow(0);
+}
+
+// FIXME: This used to be in the upstream version until it was converted to the new theme API in r37731.
+const IntSize* RenderThemeChromiumMac::buttonSizes() const
+{
+ static const IntSize sizes[3] = { IntSize(0, 21), IntSize(0, 18), IntSize(0, 15) };
+ return sizes;
+}
+
+// FIXME: This used to be in the upstream version until it was converted to the new theme API in r37731.
+const int* RenderThemeChromiumMac::buttonMargins() const
+{
+ static const int margins[3][4] =
+ {
+ { 4, 6, 7, 6 },
+ { 4, 5, 6, 5 },
+ { 0, 1, 1, 1 },
+ };
+ return margins[[button() controlSize]];
+}
+
+// FIXME: This used to be in the upstream version until it was converted to the new theme API in r37731.
+void RenderThemeChromiumMac::setButtonSize(RenderStyle* style) const
+{
+ // If the width and height are both specified, then we have nothing to do.
+ if (!style->width().isIntrinsicOrAuto() && !style->height().isAuto())
+ return;
+
+ // Use the font size to determine the intrinsic width of the control.
+ setSizeFromFont(style, buttonSizes());
+}
+
+// FIXME: This used to be in the upstream version until it was converted to the new theme API in r37731.
+void RenderThemeChromiumMac::setButtonCellState(const RenderObject* o, const IntRect& r)
+{
+ NSButtonCell* button = this->button();
+
+ // Set the control size based off the rectangle we're painting into.
+ if (o->style()->appearance() == SquareButtonPart ||
+ r.height() > buttonSizes()[NSRegularControlSize].height() * o->style()->effectiveZoom()) {
+ // Use the square button
+ if ([button bezelStyle] != NSShadowlessSquareBezelStyle)
+ [button setBezelStyle:NSShadowlessSquareBezelStyle];
+ } else if ([button bezelStyle] != NSRoundedBezelStyle)
+ [button setBezelStyle:NSRoundedBezelStyle];
+
+ setControlSize(button, buttonSizes(), r.size(), o->style()->effectiveZoom());
+
+ NSWindow *window = [nil window];
+ BOOL isDefaultButton = (isDefault(o) && [window isKeyWindow]);
+ [button setKeyEquivalent:(isDefaultButton ? @"\r" : @"")];
+
+ // Update the various states we respond to.
+ updateCheckedState(button, o);
+ updateEnabledState(button, o);
+ updatePressedState(button, o);
+ updateFocusedState(button, o);
+}
+
+// FIXME: This used to be in the upstream version until it was converted to the new theme API in r37731.
+bool RenderThemeChromiumMac::paintButton(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
+{
+ NSButtonCell* button = this->button();
+ LocalCurrentGraphicsContext localContext(paintInfo.context);
+
+ // Determine the width and height needed for the control and prepare the cell for painting.
+ setButtonCellState(o, r);
+
+ paintInfo.context->save();
+
+ // We inflate the rect as needed to account for padding included in the cell to accommodate the button
+ // shadow. We don't consider this part of the bounds of the control in WebKit.
+ float zoomLevel = o->style()->effectiveZoom();
+ IntSize size = buttonSizes()[[button controlSize]];
+ size.setWidth(r.width());
+ size.setHeight(size.height() * zoomLevel);
+ IntRect inflatedRect = r;
+ if ([button bezelStyle] == NSRoundedBezelStyle) {
+ // Center the button within the available space.
+ if (inflatedRect.height() > size.height()) {
+ inflatedRect.setY(inflatedRect.y() + (inflatedRect.height() - size.height()) / 2);
+ inflatedRect.setHeight(size.height());
+ }
+
+ // Now inflate it to account for the shadow.
+ inflatedRect = inflateRect(inflatedRect, size, buttonMargins(), zoomLevel);
+
+ if (zoomLevel != 1.0f) {
+ inflatedRect.setWidth(inflatedRect.width() / zoomLevel);
+ inflatedRect.setHeight(inflatedRect.height() / zoomLevel);
+ paintInfo.context->translate(inflatedRect.x(), inflatedRect.y());
+ paintInfo.context->scale(FloatSize(zoomLevel, zoomLevel));
+ paintInfo.context->translate(-inflatedRect.x(), -inflatedRect.y());
+ }
+ }
+
+ NSView *view = nil;
+ NSWindow *window = [view window];
+ NSButtonCell *previousDefaultButtonCell = [window defaultButtonCell];
+
+ if (isDefault(o) && [window isKeyWindow]) {
+ [window setDefaultButtonCell:button];
+ wkAdvanceDefaultButtonPulseAnimation(button);
+ } else if ([previousDefaultButtonCell isEqual:button])
+ [window setDefaultButtonCell:nil];
+
+ [button drawWithFrame:NSRect(IntRectToNSRect(inflatedRect)) inView:view];
+ [button setControlView:nil];
+
+ if (![previousDefaultButtonCell isEqual:button])
+ [window setDefaultButtonCell:previousDefaultButtonCell];
+
+ paintInfo.context->restore();
+
+ return false;
+}
+
+bool RenderThemeChromiumMac::paintTextField(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
+{
+ LocalCurrentGraphicsContext localContext(paintInfo.context);
+ wkDrawBezeledTextFieldCell(IntRectToNSRect(r), isEnabled(o) && !isReadOnlyControl(o));
+ return false;
+}
+
+void RenderThemeChromiumMac::adjustTextFieldStyle(CSSStyleSelector*, RenderStyle*, Element*) const
+{
+}
+
+bool RenderThemeChromiumMac::paintCapsLockIndicator(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
+{
+ if (paintInfo.context->paintingDisabled())
+ return true;
+
+ LocalCurrentGraphicsContext localContext(paintInfo.context);
+ wkDrawCapsLockIndicator(paintInfo.context->platformContext(), r);
+
+ return false;
+}
+
+bool RenderThemeChromiumMac::paintTextArea(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
+{
+ LocalCurrentGraphicsContext localContext(paintInfo.context);
+ wkDrawBezeledTextArea(IntRectToNSRect(r), isEnabled(o) && !isReadOnlyControl(o));
+ return false;
+}
+
+void RenderThemeChromiumMac::adjustTextAreaStyle(CSSStyleSelector*, RenderStyle*, Element*) const
+{
+}
+
+const int* RenderThemeChromiumMac::popupButtonMargins() const
+{
+ static const int margins[3][4] =
+ {
+ { 0, 3, 1, 3 },
+ { 0, 3, 2, 3 },
+ { 0, 1, 0, 1 }
+ };
+ return margins[[popupButton() controlSize]];
+}
+
+const IntSize* RenderThemeChromiumMac::popupButtonSizes() const
+{
+ static const IntSize sizes[3] = { IntSize(0, 21), IntSize(0, 18), IntSize(0, 15) };
+ return sizes;
+}
+
+const int* RenderThemeChromiumMac::popupButtonPadding(NSControlSize size) const
+{
+ static const int padding[3][4] =
+ {
+ { 2, 26, 3, 8 },
+ { 2, 23, 3, 8 },
+ { 2, 22, 3, 10 }
+ };
+ return padding[size];
+}
+
+bool RenderThemeChromiumMac::paintMenuList(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
+{
+ LocalCurrentGraphicsContext localContext(paintInfo.context);
+
+ setPopupButtonCellState(o, r);
+
+ NSPopUpButtonCell* popupButton = this->popupButton();
+
+ float zoomLevel = o->style()->effectiveZoom();
+ IntSize size = popupButtonSizes()[[popupButton controlSize]];
+ size.setHeight(size.height() * zoomLevel);
+ size.setWidth(r.width());
+
+ // Now inflate it to account for the shadow.
+ IntRect inflatedRect = r;
+ if (r.width() >= minimumMenuListSize(o->style()))
+ inflatedRect = inflateRect(inflatedRect, size, popupButtonMargins(), zoomLevel);
+
+ paintInfo.context->save();
+
+#ifndef BUILDING_ON_TIGER
+ // On Leopard, the cell will draw outside of the given rect, so we have to clip to the rect
+ paintInfo.context->clip(inflatedRect);
+#endif
+
+ if (zoomLevel != 1.0f) {
+ inflatedRect.setWidth(inflatedRect.width() / zoomLevel);
+ inflatedRect.setHeight(inflatedRect.height() / zoomLevel);
+ paintInfo.context->translate(inflatedRect.x(), inflatedRect.y());
+ paintInfo.context->scale(FloatSize(zoomLevel, zoomLevel));
+ paintInfo.context->translate(-inflatedRect.x(), -inflatedRect.y());
+ }
+
+ [popupButton drawWithFrame:IntRectToNSRect(inflatedRect) inView:nil];
+ [popupButton setControlView:nil];
+
+ paintInfo.context->restore();
+
+ return false;
+}
+
+static const float baseFontSize = 11.0f;
+static const float baseArrowHeight = 4.0f;
+static const float baseArrowWidth = 5.0f;
+static const float baseSpaceBetweenArrows = 2.0f;
+static const int arrowPaddingLeft = 6;
+static const int arrowPaddingRight = 6;
+static const int paddingBeforeSeparator = 4;
+static const int baseBorderRadius = 5;
+static const int styledPopupPaddingLeft = 8;
+static const int styledPopupPaddingTop = 1;
+static const int styledPopupPaddingBottom = 2;
+
+static void TopGradientInterpolate(void* info, const CGFloat* inData, CGFloat* outData)
+{
+ static float dark[4] = { 1.0f, 1.0f, 1.0f, 0.4f };
+ static float light[4] = { 1.0f, 1.0f, 1.0f, 0.15f };
+ float a = inData[0];
+ int i = 0;
+ for (i = 0; i < 4; i++)
+ outData[i] = (1.0f - a) * dark[i] + a * light[i];
+}
+
+static void BottomGradientInterpolate(void* info, const CGFloat* inData, CGFloat* outData)
+{
+ static float dark[4] = { 1.0f, 1.0f, 1.0f, 0.0f };
+ static float light[4] = { 1.0f, 1.0f, 1.0f, 0.3f };
+ float a = inData[0];
+ int i = 0;
+ for (i = 0; i < 4; i++)
+ outData[i] = (1.0f - a) * dark[i] + a * light[i];
+}
+
+static void MainGradientInterpolate(void* info, const CGFloat* inData, CGFloat* outData)
+{
+ static float dark[4] = { 0.0f, 0.0f, 0.0f, 0.15f };
+ static float light[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
+ float a = inData[0];
+ int i = 0;
+ for (i = 0; i < 4; i++)
+ outData[i] = (1.0f - a) * dark[i] + a * light[i];
+}
+
+static void TrackGradientInterpolate(void* info, const CGFloat* inData, CGFloat* outData)
+{
+ static float dark[4] = { 0.0f, 0.0f, 0.0f, 0.678f };
+ static float light[4] = { 0.0f, 0.0f, 0.0f, 0.13f };
+ float a = inData[0];
+ int i = 0;
+ for (i = 0; i < 4; i++)
+ outData[i] = (1.0f - a) * dark[i] + a * light[i];
+}
+
+void RenderThemeChromiumMac::paintMenuListButtonGradients(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
+{
+ CGContextRef context = paintInfo.context->platformContext();
+
+ paintInfo.context->save();
+
+ int radius = o->style()->borderTopLeftRadius().width();
+
+ RetainPtr<CGColorSpaceRef> cspace(AdoptCF, CGColorSpaceCreateDeviceRGB());
+
+ FloatRect topGradient(r.x(), r.y(), r.width(), r.height() / 2.0f);
+ struct CGFunctionCallbacks topCallbacks = { 0, TopGradientInterpolate, NULL };
+ RetainPtr<CGFunctionRef> topFunction(AdoptCF, CGFunctionCreate(NULL, 1, NULL, 4, NULL, &topCallbacks));
+ RetainPtr<CGShadingRef> topShading(AdoptCF, CGShadingCreateAxial(cspace.get(), CGPointMake(topGradient.x(), topGradient.y()), CGPointMake(topGradient.x(), topGradient.bottom()), topFunction.get(), false, false));
+
+ FloatRect bottomGradient(r.x() + radius, r.y() + r.height() / 2.0f, r.width() - 2.0f * radius, r.height() / 2.0f);
+ struct CGFunctionCallbacks bottomCallbacks = { 0, BottomGradientInterpolate, NULL };
+ RetainPtr<CGFunctionRef> bottomFunction(AdoptCF, CGFunctionCreate(NULL, 1, NULL, 4, NULL, &bottomCallbacks));
+ RetainPtr<CGShadingRef> bottomShading(AdoptCF, CGShadingCreateAxial(cspace.get(), CGPointMake(bottomGradient.x(), bottomGradient.y()), CGPointMake(bottomGradient.x(), bottomGradient.bottom()), bottomFunction.get(), false, false));
+
+ struct CGFunctionCallbacks mainCallbacks = { 0, MainGradientInterpolate, NULL };
+ RetainPtr<CGFunctionRef> mainFunction(AdoptCF, CGFunctionCreate(NULL, 1, NULL, 4, NULL, &mainCallbacks));
+ RetainPtr<CGShadingRef> mainShading(AdoptCF, CGShadingCreateAxial(cspace.get(), CGPointMake(r.x(), r.y()), CGPointMake(r.x(), r.bottom()), mainFunction.get(), false, false));
+
+ RetainPtr<CGShadingRef> leftShading(AdoptCF, CGShadingCreateAxial(cspace.get(), CGPointMake(r.x(), r.y()), CGPointMake(r.x() + radius, r.y()), mainFunction.get(), false, false));
+
+ RetainPtr<CGShadingRef> rightShading(AdoptCF, CGShadingCreateAxial(cspace.get(), CGPointMake(r.right(), r.y()), CGPointMake(r.right() - radius, r.y()), mainFunction.get(), false, false));
+ paintInfo.context->save();
+ CGContextClipToRect(context, r);
+ paintInfo.context->addRoundedRectClip(r,
+ o->style()->borderTopLeftRadius(), o->style()->borderTopRightRadius(),
+ o->style()->borderBottomLeftRadius(), o->style()->borderBottomRightRadius());
+ CGContextDrawShading(context, mainShading.get());
+ paintInfo.context->restore();
+
+ paintInfo.context->save();
+ CGContextClipToRect(context, topGradient);
+ paintInfo.context->addRoundedRectClip(enclosingIntRect(topGradient),
+ o->style()->borderTopLeftRadius(), o->style()->borderTopRightRadius(),
+ IntSize(), IntSize());
+ CGContextDrawShading(context, topShading.get());
+ paintInfo.context->restore();
+
+ paintInfo.context->save();
+ CGContextClipToRect(context, bottomGradient);
+ paintInfo.context->addRoundedRectClip(enclosingIntRect(bottomGradient),
+ IntSize(), IntSize(),
+ o->style()->borderBottomLeftRadius(), o->style()->borderBottomRightRadius());
+ CGContextDrawShading(context, bottomShading.get());
+ paintInfo.context->restore();
+
+ paintInfo.context->save();
+ CGContextClipToRect(context, r);
+ paintInfo.context->addRoundedRectClip(r,
+ o->style()->borderTopLeftRadius(), o->style()->borderTopRightRadius(),
+ o->style()->borderBottomLeftRadius(), o->style()->borderBottomRightRadius());
+ CGContextDrawShading(context, leftShading.get());
+ CGContextDrawShading(context, rightShading.get());
+ paintInfo.context->restore();
+
+ paintInfo.context->restore();
+}
+
+bool RenderThemeChromiumMac::paintMenuListButton(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
+{
+ paintInfo.context->save();
+
+ IntRect bounds = IntRect(r.x() + o->style()->borderLeftWidth(),
+ r.y() + o->style()->borderTopWidth(),
+ r.width() - o->style()->borderLeftWidth() - o->style()->borderRightWidth(),
+ r.height() - o->style()->borderTopWidth() - o->style()->borderBottomWidth());
+ // Draw the gradients to give the styled popup menu a button appearance
+ paintMenuListButtonGradients(o, paintInfo, bounds);
+
+ // Since we actually know the size of the control here, we restrict the font scale to make sure the arrows will fit vertically in the bounds
+ float fontScale = min(o->style()->fontSize() / baseFontSize, bounds.height() / (baseArrowHeight * 2 + baseSpaceBetweenArrows));
+ float centerY = bounds.y() + bounds.height() / 2.0f;
+ float arrowHeight = baseArrowHeight * fontScale;
+ float arrowWidth = baseArrowWidth * fontScale;
+ float leftEdge = bounds.right() - arrowPaddingRight * o->style()->effectiveZoom() - arrowWidth;
+ float spaceBetweenArrows = baseSpaceBetweenArrows * fontScale;
+
+ if (bounds.width() < arrowWidth + arrowPaddingLeft * o->style()->effectiveZoom())
+ return false;
+
+ paintInfo.context->setFillColor(o->style()->color());
+ paintInfo.context->setStrokeStyle(NoStroke);
+
+ FloatPoint arrow1[3];
+ arrow1[0] = FloatPoint(leftEdge, centerY - spaceBetweenArrows / 2.0f);
+ arrow1[1] = FloatPoint(leftEdge + arrowWidth, centerY - spaceBetweenArrows / 2.0f);
+ arrow1[2] = FloatPoint(leftEdge + arrowWidth / 2.0f, centerY - spaceBetweenArrows / 2.0f - arrowHeight);
+
+ // Draw the top arrow
+ paintInfo.context->drawConvexPolygon(3, arrow1, true);
+
+ FloatPoint arrow2[3];
+ arrow2[0] = FloatPoint(leftEdge, centerY + spaceBetweenArrows / 2.0f);
+ arrow2[1] = FloatPoint(leftEdge + arrowWidth, centerY + spaceBetweenArrows / 2.0f);
+ arrow2[2] = FloatPoint(leftEdge + arrowWidth / 2.0f, centerY + spaceBetweenArrows / 2.0f + arrowHeight);
+
+ // Draw the bottom arrow
+ paintInfo.context->drawConvexPolygon(3, arrow2, true);
+
+ Color leftSeparatorColor(0, 0, 0, 40);
+ Color rightSeparatorColor(255, 255, 255, 40);
+
+ // FIXME: Should the separator thickness and space be scaled up by fontScale?
+ int separatorSpace = 2; // Deliberately ignores zoom since it looks nicer if it stays thin.
+ int leftEdgeOfSeparator = static_cast<int>(leftEdge - arrowPaddingLeft * o->style()->effectiveZoom()); // FIXME: Round?
+
+ // Draw the separator to the left of the arrows
+ paintInfo.context->setStrokeThickness(1.0f); // Deliberately ignores zoom since it looks nicer if it stays thin.
+ paintInfo.context->setStrokeStyle(SolidStroke);
+ paintInfo.context->setStrokeColor(leftSeparatorColor);
+ paintInfo.context->drawLine(IntPoint(leftEdgeOfSeparator, bounds.y()),
+ IntPoint(leftEdgeOfSeparator, bounds.bottom()));
+
+ paintInfo.context->setStrokeColor(rightSeparatorColor);
+ paintInfo.context->drawLine(IntPoint(leftEdgeOfSeparator + separatorSpace, bounds.y()),
+ IntPoint(leftEdgeOfSeparator + separatorSpace, bounds.bottom()));
+
+ paintInfo.context->restore();
+ return false;
+}
+
+static const IntSize* menuListButtonSizes()
+{
+ static const IntSize sizes[3] = { IntSize(0, 21), IntSize(0, 18), IntSize(0, 15) };
+ return sizes;
+}
+
+void RenderThemeChromiumMac::adjustMenuListStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
+{
+ NSControlSize controlSize = controlSizeForFont(style);
+
+ style->resetBorder();
+ style->resetPadding();
+
+ // Height is locked to auto.
+ style->setHeight(Length(Auto));
+
+ // White-space is locked to pre
+ style->setWhiteSpace(PRE);
+
+ // Set the foreground color to black or gray when we have the aqua look.
+ // Cast to RGB32 is to work around a compiler bug.
+ style->setColor(e && e->isEnabledFormControl() ? static_cast<RGBA32>(Color::black) : Color::darkGray);
+
+ // Set the button's vertical size.
+ setSizeFromFont(style, menuListButtonSizes());
+
+ // Our font is locked to the appropriate system font size for the control. To clarify, we first use the CSS-specified font to figure out
+ // a reasonable control size, but once that control size is determined, we throw that font away and use the appropriate
+ // system font for the control size instead.
+ setFontFromControlSize(selector, style, controlSize);
+
+ style->setBoxShadow(0);
+}
+
+int RenderThemeChromiumMac::popupInternalPaddingLeft(RenderStyle* style) const
+{
+ if (style->appearance() == MenulistPart)
+ return popupButtonPadding(controlSizeForFont(style))[LeftPadding] * style->effectiveZoom();
+ if (style->appearance() == MenulistButtonPart)
+ return styledPopupPaddingLeft * style->effectiveZoom();
+ return 0;
+}
+
+int RenderThemeChromiumMac::popupInternalPaddingRight(RenderStyle* style) const
+{
+ if (style->appearance() == MenulistPart)
+ return popupButtonPadding(controlSizeForFont(style))[RightPadding] * style->effectiveZoom();
+ if (style->appearance() == MenulistButtonPart) {
+ float fontScale = style->fontSize() / baseFontSize;
+ float arrowWidth = baseArrowWidth * fontScale;
+ return static_cast<int>(ceilf(arrowWidth + (arrowPaddingLeft + arrowPaddingRight + paddingBeforeSeparator) * style->effectiveZoom()));
+ }
+ return 0;
+}
+
+int RenderThemeChromiumMac::popupInternalPaddingTop(RenderStyle* style) const
+{
+ if (style->appearance() == MenulistPart)
+ return popupButtonPadding(controlSizeForFont(style))[TopPadding] * style->effectiveZoom();
+ if (style->appearance() == MenulistButtonPart)
+ return styledPopupPaddingTop * style->effectiveZoom();
+ return 0;
+}
+
+int RenderThemeChromiumMac::popupInternalPaddingBottom(RenderStyle* style) const
+{
+ if (style->appearance() == MenulistPart)
+ return popupButtonPadding(controlSizeForFont(style))[BottomPadding] * style->effectiveZoom();
+ if (style->appearance() == MenulistButtonPart)
+ return styledPopupPaddingBottom * style->effectiveZoom();
+ return 0;
+}
+
+void RenderThemeChromiumMac::adjustMenuListButtonStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
+{
+ float fontScale = style->fontSize() / baseFontSize;
+
+ style->resetPadding();
+ style->setBorderRadius(IntSize(int(baseBorderRadius + fontScale - 1), int(baseBorderRadius + fontScale - 1))); // FIXME: Round up?
+
+ const int minHeight = 15;
+ style->setMinHeight(Length(minHeight, Fixed));
+
+ style->setLineHeight(RenderStyle::initialLineHeight());
+}
+
+void RenderThemeChromiumMac::setPopupButtonCellState(const RenderObject* o, const IntRect& r)
+{
+ NSPopUpButtonCell* popupButton = this->popupButton();
+
+ // Set the control size based off the rectangle we're painting into.
+ setControlSize(popupButton, popupButtonSizes(), r.size(), o->style()->effectiveZoom());
+
+ // Update the various states we respond to.
+ updateCheckedState(popupButton, o);
+ updateEnabledState(popupButton, o);
+ updatePressedState(popupButton, o);
+ updateFocusedState(popupButton, o);
+}
+
+const IntSize* RenderThemeChromiumMac::menuListSizes() const
+{
+ static const IntSize sizes[3] = { IntSize(9, 0), IntSize(5, 0), IntSize(0, 0) };
+ return sizes;
+}
+
+int RenderThemeChromiumMac::minimumMenuListSize(RenderStyle* style) const
+{
+ return sizeForSystemFont(style, menuListSizes()).width();
+}
+
+static const int trackWidth = 5;
+static const int trackRadius = 2;
+
+void RenderThemeChromiumMac::adjustSliderTrackStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
+{
+ style->setBoxShadow(0);
+}
+
+bool RenderThemeChromiumMac::paintSliderTrack(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
+{
+ IntRect bounds = r;
+ float zoomLevel = o->style()->effectiveZoom();
+ float zoomedTrackWidth = trackWidth * zoomLevel;
+
+ if (o->style()->appearance() == SliderHorizontalPart || o->style()->appearance() == MediaSliderPart) {
+ bounds.setHeight(zoomedTrackWidth);
+ bounds.setY(r.y() + r.height() / 2 - zoomedTrackWidth / 2);
+ } else if (o->style()->appearance() == SliderVerticalPart) {
+ bounds.setWidth(zoomedTrackWidth);
+ bounds.setX(r.x() + r.width() / 2 - zoomedTrackWidth / 2);
+ }
+
+ LocalCurrentGraphicsContext localContext(paintInfo.context);
+ CGContextRef context = paintInfo.context->platformContext();
+ RetainPtr<CGColorSpaceRef> cspace(AdoptCF, CGColorSpaceCreateDeviceRGB());
+
+ paintInfo.context->save();
+ CGContextClipToRect(context, bounds);
+
+ struct CGFunctionCallbacks mainCallbacks = { 0, TrackGradientInterpolate, NULL };
+ RetainPtr<CGFunctionRef> mainFunction(AdoptCF, CGFunctionCreate(NULL, 1, NULL, 4, NULL, &mainCallbacks));
+ RetainPtr<CGShadingRef> mainShading;
+ if (o->style()->appearance() == SliderVerticalPart)
+ mainShading.adoptCF(CGShadingCreateAxial(cspace.get(), CGPointMake(bounds.x(), bounds.bottom()), CGPointMake(bounds.right(), bounds.bottom()), mainFunction.get(), false, false));
+ else
+ mainShading.adoptCF(CGShadingCreateAxial(cspace.get(), CGPointMake(bounds.x(), bounds.y()), CGPointMake(bounds.x(), bounds.bottom()), mainFunction.get(), false, false));
+
+ IntSize radius(trackRadius, trackRadius);
+ paintInfo.context->addRoundedRectClip(bounds,
+ radius, radius,
+ radius, radius);
+ CGContextDrawShading(context, mainShading.get());
+ paintInfo.context->restore();
+
+ return false;
+}
+
+void RenderThemeChromiumMac::adjustSliderThumbStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
+{
+ style->setBoxShadow(0);
+}
+
+static const float verticalSliderHeightPadding = 0.1f;
+
+bool RenderThemeChromiumMac::paintSliderThumb(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
+{
+ ASSERT(o->parent()->isSlider());
+
+ NSSliderCell* sliderThumbCell = o->style()->appearance() == SliderThumbVerticalPart
+ ? sliderThumbVertical()
+ : sliderThumbHorizontal();
+
+ LocalCurrentGraphicsContext localContext(paintInfo.context);
+
+ // Update the various states we respond to.
+ updateEnabledState(sliderThumbCell, o->parent());
+ updateFocusedState(sliderThumbCell, o->parent());
+
+ // Update the pressed state using the NSCell tracking methods, since that's how NSSliderCell keeps track of it.
+ bool oldPressed;
+ if (o->style()->appearance() == SliderThumbVerticalPart)
+ oldPressed = m_isSliderThumbVerticalPressed;
+ else
+ oldPressed = m_isSliderThumbHorizontalPressed;
+
+ bool pressed = static_cast<RenderSlider*>(o->parent())->inDragMode();
+
+ if (o->style()->appearance() == SliderThumbVerticalPart)
+ m_isSliderThumbVerticalPressed = pressed;
+ else
+ m_isSliderThumbHorizontalPressed = pressed;
+
+ if (pressed != oldPressed) {
+ if (pressed)
+ [sliderThumbCell startTrackingAt:NSPoint() inView:nil];
+ else
+ [sliderThumbCell stopTracking:NSPoint() at:NSPoint() inView:nil mouseIsUp:YES];
+ }
+
+ FloatRect bounds = r;
+ // Make the height of the vertical slider slightly larger so NSSliderCell will draw a vertical slider.
+ if (o->style()->appearance() == SliderThumbVerticalPart)
+ bounds.setHeight(bounds.height() + verticalSliderHeightPadding * o->style()->effectiveZoom());
+
+ paintInfo.context->save();
+ float zoomLevel = o->style()->effectiveZoom();
+
+ FloatRect unzoomedRect = bounds;
+ if (zoomLevel != 1.0f) {
+ unzoomedRect.setWidth(unzoomedRect.width() / zoomLevel);
+ unzoomedRect.setHeight(unzoomedRect.height() / zoomLevel);
+ paintInfo.context->translate(unzoomedRect.x(), unzoomedRect.y());
+ paintInfo.context->scale(FloatSize(zoomLevel, zoomLevel));
+ paintInfo.context->translate(-unzoomedRect.x(), -unzoomedRect.y());
+ }
+
+ [sliderThumbCell drawWithFrame:FloatRectToNSRect(unzoomedRect) inView:nil];
+ [sliderThumbCell setControlView:nil];
+
+ paintInfo.context->restore();
+
+ return false;
+}
+
+const int sliderThumbWidth = 15;
+const int sliderThumbHeight = 15;
+const int mediaSliderThumbWidth = 13;
+const int mediaSliderThumbHeight = 14;
+
+void RenderThemeChromiumMac::adjustSliderThumbSize(RenderObject* o) const
+{
+ float zoomLevel = o->style()->effectiveZoom();
+ if (o->style()->appearance() == SliderThumbHorizontalPart || o->style()->appearance() == SliderThumbVerticalPart) {
+ o->style()->setWidth(Length(static_cast<int>(sliderThumbWidth * zoomLevel), Fixed));
+ o->style()->setHeight(Length(static_cast<int>(sliderThumbHeight * zoomLevel), Fixed));
+ } else if (o->style()->appearance() == MediaSliderThumbPart) {
+ o->style()->setWidth(Length(mediaSliderThumbWidth, Fixed));
+ o->style()->setHeight(Length(mediaSliderThumbHeight, Fixed));
+ }
+}
+
+bool RenderThemeChromiumMac::paintSearchField(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
+{
+ NSSearchFieldCell* search = this->search();
+ LocalCurrentGraphicsContext localContext(paintInfo.context);
+
+ setSearchCellState(o, r);
+
+ paintInfo.context->save();
+
+ float zoomLevel = o->style()->effectiveZoom();
+
+ IntRect unzoomedRect = r;
+
+ if (zoomLevel != 1.0f) {
+ unzoomedRect.setWidth(unzoomedRect.width() / zoomLevel);
+ unzoomedRect.setHeight(unzoomedRect.height() / zoomLevel);
+ paintInfo.context->translate(unzoomedRect.x(), unzoomedRect.y());
+ paintInfo.context->scale(FloatSize(zoomLevel, zoomLevel));
+ paintInfo.context->translate(-unzoomedRect.x(), -unzoomedRect.y());
+ }
+
+ // Set the search button to nil before drawing. Then reset it so we can draw it later.
+ [search setSearchButtonCell:nil];
+
+ [search drawWithFrame:NSRect(IntRectToNSRect(unzoomedRect)) inView:nil];
+#ifdef BUILDING_ON_TIGER
+ if ([search showsFirstResponder])
+ wkDrawTextFieldCellFocusRing(search, NSRect(unzoomedRect));
+#endif
+
+ [search setControlView:nil];
+ [search resetSearchButtonCell];
+
+ paintInfo.context->restore();
+
+ return false;
+}
+
+void RenderThemeChromiumMac::setSearchCellState(RenderObject* o, const IntRect& r)
+{
+ NSSearchFieldCell* search = this->search();
+
+ [search setControlSize:controlSizeForFont(o->style())];
+
+ // Update the various states we respond to.
+ updateEnabledState(search, o);
+ updateFocusedState(search, o);
+}
+
+const IntSize* RenderThemeChromiumMac::searchFieldSizes() const
+{
+ static const IntSize sizes[3] = { IntSize(0, 22), IntSize(0, 19), IntSize(0, 17) };
+ return sizes;
+}
+
+void RenderThemeChromiumMac::setSearchFieldSize(RenderStyle* style) const
+{
+ // If the width and height are both specified, then we have nothing to do.
+ if (!style->width().isIntrinsicOrAuto() && !style->height().isAuto())
+ return;
+
+ // Use the font size to determine the intrinsic width of the control.
+ setSizeFromFont(style, searchFieldSizes());
+}
+
+void RenderThemeChromiumMac::adjustSearchFieldStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
+{
+ // Override border.
+ style->resetBorder();
+ const short borderWidth = 2 * style->effectiveZoom();
+ style->setBorderLeftWidth(borderWidth);
+ style->setBorderLeftStyle(INSET);
+ style->setBorderRightWidth(borderWidth);
+ style->setBorderRightStyle(INSET);
+ style->setBorderBottomWidth(borderWidth);
+ style->setBorderBottomStyle(INSET);
+ style->setBorderTopWidth(borderWidth);
+ style->setBorderTopStyle(INSET);
+
+ // Override height.
+ style->setHeight(Length(Auto));
+ setSearchFieldSize(style);
+
+ // Override padding size to match AppKit text positioning.
+ const int padding = 1 * style->effectiveZoom();
+ style->setPaddingLeft(Length(padding, Fixed));
+ style->setPaddingRight(Length(padding, Fixed));
+ style->setPaddingTop(Length(padding, Fixed));
+ style->setPaddingBottom(Length(padding, Fixed));
+
+ NSControlSize controlSize = controlSizeForFont(style);
+ setFontFromControlSize(selector, style, controlSize);
+
+ style->setBoxShadow(0);
+}
+
+bool RenderThemeChromiumMac::paintSearchFieldCancelButton(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
+{
+ LocalCurrentGraphicsContext localContext(paintInfo.context);
+
+ Node* input = o->node()->shadowAncestorNode();
+ setSearchCellState(input->renderer(), r);
+
+ NSSearchFieldCell* search = this->search();
+
+ updatePressedState([search cancelButtonCell], o);
+
+ paintInfo.context->save();
+
+ float zoomLevel = o->style()->effectiveZoom();
+
+ NSRect bounds = [search cancelButtonRectForBounds:NSRect(IntRectToNSRect(input->renderer()->absoluteBoundingBoxRect()))];
+
+ IntRect unzoomedRect(NSRectToIntRect(bounds));
+ if (zoomLevel != 1.0f) {
+ unzoomedRect.setWidth(unzoomedRect.width() / zoomLevel);
+ unzoomedRect.setHeight(unzoomedRect.height() / zoomLevel);
+ paintInfo.context->translate(unzoomedRect.x(), unzoomedRect.y());
+ paintInfo.context->scale(FloatSize(zoomLevel, zoomLevel));
+ paintInfo.context->translate(-unzoomedRect.x(), -unzoomedRect.y());
+ }
+
+ [[search cancelButtonCell] drawWithFrame:IntRectToNSRect(unzoomedRect) inView:nil];
+ [[search cancelButtonCell] setControlView:nil];
+
+ paintInfo.context->restore();
+ return false;
+}
+
+const IntSize* RenderThemeChromiumMac::cancelButtonSizes() const
+{
+ static const IntSize sizes[3] = { IntSize(16, 13), IntSize(13, 11), IntSize(13, 9) };
+ return sizes;
+}
+
+void RenderThemeChromiumMac::adjustSearchFieldCancelButtonStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
+{
+ IntSize size = sizeForSystemFont(style, cancelButtonSizes());
+ style->setWidth(Length(size.width(), Fixed));
+ style->setHeight(Length(size.height(), Fixed));
+ style->setBoxShadow(0);
+}
+
+const IntSize* RenderThemeChromiumMac::resultsButtonSizes() const
+{
+ static const IntSize sizes[3] = { IntSize(19, 13), IntSize(17, 11), IntSize(17, 9) };
+ return sizes;
+}
+
+static const int emptyResultsOffset = 9;
+void RenderThemeChromiumMac::adjustSearchFieldDecorationStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
+{
+ IntSize size = sizeForSystemFont(style, resultsButtonSizes());
+ style->setWidth(Length(size.width() - emptyResultsOffset, Fixed));
+ style->setHeight(Length(size.height(), Fixed));
+ style->setBoxShadow(0);
+}
+
+bool RenderThemeChromiumMac::paintSearchFieldDecoration(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
+{
+ return false;
+}
+
+void RenderThemeChromiumMac::adjustSearchFieldResultsDecorationStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
+{
+ IntSize size = sizeForSystemFont(style, resultsButtonSizes());
+ style->setWidth(Length(size.width(), Fixed));
+ style->setHeight(Length(size.height(), Fixed));
+ style->setBoxShadow(0);
+}
+
+bool RenderThemeChromiumMac::paintSearchFieldResultsDecoration(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
+{
+ LocalCurrentGraphicsContext localContext(paintInfo.context);
+
+ Node* input = o->node()->shadowAncestorNode();
+ setSearchCellState(input->renderer(), r);
+
+ NSSearchFieldCell* search = this->search();
+
+ if ([search searchMenuTemplate] != nil)
+ [search setSearchMenuTemplate:nil];
+
+ NSRect bounds = [search searchButtonRectForBounds:NSRect(IntRectToNSRect(input->renderer()->absoluteBoundingBoxRect()))];
+ [[search searchButtonCell] drawWithFrame:bounds inView:nil];
+ [[search searchButtonCell] setControlView:nil];
+ return false;
+}
+
+static const int resultsArrowWidth = 5;
+void RenderThemeChromiumMac::adjustSearchFieldResultsButtonStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
+{
+ IntSize size = sizeForSystemFont(style, resultsButtonSizes());
+ style->setWidth(Length(size.width() + resultsArrowWidth, Fixed));
+ style->setHeight(Length(size.height(), Fixed));
+ style->setBoxShadow(0);
+}
+
+bool RenderThemeChromiumMac::paintSearchFieldResultsButton(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
+{
+ LocalCurrentGraphicsContext localContext(paintInfo.context);
+
+ Node* input = o->node()->shadowAncestorNode();
+ setSearchCellState(input->renderer(), r);
+
+ NSSearchFieldCell* search = this->search();
+
+ if (![search searchMenuTemplate])
+ [search setSearchMenuTemplate:searchMenuTemplate()];
+
+ paintInfo.context->save();
+
+ float zoomLevel = o->style()->effectiveZoom();
+
+ NSRect bounds = [search searchButtonRectForBounds:NSRect(IntRectToNSRect(input->renderer()->absoluteBoundingBoxRect()))];
+
+ IntRect unzoomedRect(NSRectToIntRect(bounds));
+ if (zoomLevel != 1.0f) {
+ unzoomedRect.setWidth(unzoomedRect.width() / zoomLevel);
+ unzoomedRect.setHeight(unzoomedRect.height() / zoomLevel);
+ paintInfo.context->translate(unzoomedRect.x(), unzoomedRect.y());
+ paintInfo.context->scale(FloatSize(zoomLevel, zoomLevel));
+ paintInfo.context->translate(-unzoomedRect.x(), -unzoomedRect.y());
+ }
+
+ [[search searchButtonCell] drawWithFrame:IntRectToNSRect(unzoomedRect) inView:nil];
+ [[search searchButtonCell] setControlView:nil];
+
+ paintInfo.context->restore();
+
+ return false;
+}
+
+#if ENABLE(VIDEO)
+// FIXME: This enum is lifted from RenderThemeMac.mm We need to decide which theme to use for the default controls, or decide to avoid wkDrawMediaUIPart and render our own.
+typedef enum {
+ MediaControllerThemeClassic = 1,
+ MediaControllerThemeQT = 2
+} MediaControllerThemeStyle;
+#endif
+
+bool RenderThemeChromiumMac::paintMediaFullscreenButton(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
+{
+#if ENABLE(VIDEO)
+ Node* node = o->node();
+ if (!node)
+ return false;
+
+ LocalCurrentGraphicsContext localContext(paintInfo.context);
+ wkDrawMediaUIPart(MediaFullscreenButton, MediaControllerThemeClassic, paintInfo.context->platformContext(), r, node->active());
+#endif
+ return false;
+}
+
+bool RenderThemeChromiumMac::paintMediaMuteButton(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
+{
+#if ENABLE(VIDEO)
+ Node* node = o->node();
+ Node* mediaNode = node ? node->shadowAncestorNode() : 0;
+ if (!mediaNode || (!mediaNode->hasTagName(videoTag) && !mediaNode->hasTagName(audioTag)))
+ return false;
+
+ HTMLMediaElement* mediaElement = static_cast<HTMLMediaElement*>(mediaNode);
+ if (!mediaElement)
+ return false;
+
+ LocalCurrentGraphicsContext localContext(paintInfo.context);
+ wkDrawMediaUIPart(mediaElement->muted() ? MediaUnMuteButton : MediaMuteButton, MediaControllerThemeClassic, paintInfo.context->platformContext(), r, node->active());
+#endif
+ return false;
+}
+
+bool RenderThemeChromiumMac::paintMediaPlayButton(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
+{
+#if ENABLE(VIDEO)
+ Node* node = o->node();
+ Node* mediaNode = node ? node->shadowAncestorNode() : 0;
+ if (!mediaNode || (!mediaNode->hasTagName(videoTag) && !mediaNode->hasTagName(audioTag)))
+ return false;
+
+ HTMLMediaElement* mediaElement = static_cast<HTMLMediaElement*>(mediaNode);
+ if (!mediaElement)
+ return false;
+
+ LocalCurrentGraphicsContext localContext(paintInfo.context);
+ wkDrawMediaUIPart(mediaElement->canPlay() ? MediaPlayButton : MediaPauseButton, MediaControllerThemeClassic, paintInfo.context->platformContext(), r, node->active());
+#endif
+ return false;
+}
+
+bool RenderThemeChromiumMac::paintMediaSeekBackButton(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
+{
+#if ENABLE(VIDEO)
+ Node* node = o->node();
+ if (!node)
+ return false;
+
+ LocalCurrentGraphicsContext localContext(paintInfo.context);
+ wkDrawMediaUIPart(MediaSeekBackButton, MediaControllerThemeClassic, paintInfo.context->platformContext(), r, node->active());
+#endif
+ return false;
+}
+
+bool RenderThemeChromiumMac::paintMediaSeekForwardButton(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
+{
+#if ENABLE(VIDEO)
+ Node* node = o->node();
+ if (!node)
+ return false;
+
+ LocalCurrentGraphicsContext localContext(paintInfo.context);
+ wkDrawMediaUIPart(MediaSeekForwardButton, MediaControllerThemeClassic, paintInfo.context->platformContext(), r, node->active());
+#endif
+ return false;
+}
+
+bool RenderThemeChromiumMac::paintMediaSliderTrack(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
+{
+#if ENABLE(VIDEO)
+ Node* node = o->node();
+ Node* mediaNode = node ? node->shadowAncestorNode() : 0;
+ if (!mediaNode || (!mediaNode->hasTagName(videoTag) && !mediaNode->hasTagName(audioTag)))
+ return false;
+
+ HTMLMediaElement* mediaElement = static_cast<HTMLMediaElement*>(mediaNode);
+ if (!mediaElement)
+ return false;
+
+ float timeLoaded = 0;
+ float currentTime = 0;
+ float duration = 0;
+ if (MediaPlayer* player = mediaElement->player()) {
+ duration = player->duration();
+ timeLoaded = player->maxTimeBuffered();
+ currentTime = player->currentTime();
+ }
+
+ wkDrawMediaSliderTrack(MediaControllerThemeClassic, paintInfo.context->platformContext(), r, timeLoaded, currentTime, duration);
+#endif
+ return false;
+}
+
+bool RenderThemeChromiumMac::paintMediaSliderThumb(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
+{
+#if ENABLE(VIDEO)
+ Node* node = o->node();
+ if (!node)
+ return false;
+
+ LocalCurrentGraphicsContext localContext(paintInfo.context);
+ wkDrawMediaUIPart(MediaSliderThumb, MediaControllerThemeClassic, paintInfo.context->platformContext(), r, node->active());
+#endif
+ return false;
+}
+
+// FIXME: This used to be in the upstream version until it was converted to the new theme API in r37731.
+NSButtonCell* RenderThemeChromiumMac::checkbox() const
+{
+ if (!m_checkbox) {
+ m_checkbox.adoptNS([[NSButtonCell alloc] init]);
+ [m_checkbox.get() setButtonType:NSSwitchButton];
+ [m_checkbox.get() setTitle:nil];
+ [m_checkbox.get() setAllowsMixedState:YES];
+ [m_checkbox.get() setFocusRingType:NSFocusRingTypeExterior];
+ }
+
+ return m_checkbox.get();
+}
+
+// FIXME: This used to be in the upstream version until it was converted to the new theme API in r37731.
+NSButtonCell* RenderThemeChromiumMac::radio() const
+{
+ if (!m_radio) {
+ m_radio.adoptNS([[NSButtonCell alloc] init]);
+ [m_radio.get() setButtonType:NSRadioButton];
+ [m_radio.get() setTitle:nil];
+ [m_radio.get() setFocusRingType:NSFocusRingTypeExterior];
+ }
+
+ return m_radio.get();
+}
+
+// FIXME: This used to be in the upstream version until it was converted to the new theme API in r37731.
+NSButtonCell* RenderThemeChromiumMac::button() const
+{
+ if (!m_button) {
+ m_button.adoptNS([[NSButtonCell alloc] init]);
+ [m_button.get() setTitle:nil];
+ [m_button.get() setButtonType:NSMomentaryPushInButton];
+ }
+
+ return m_button.get();
+}
+
+NSPopUpButtonCell* RenderThemeChromiumMac::popupButton() const
+{
+ if (!m_popupButton) {
+ m_popupButton.adoptNS([[NSPopUpButtonCell alloc] initTextCell:@"" pullsDown:NO]);
+ [m_popupButton.get() setUsesItemFromMenu:NO];
+ [m_popupButton.get() setFocusRingType:NSFocusRingTypeExterior];
+ }
+
+ return m_popupButton.get();
+}
+
+NSSearchFieldCell* RenderThemeChromiumMac::search() const
+{
+ if (!m_search) {
+ m_search.adoptNS([[NSSearchFieldCell alloc] initTextCell:@""]);
+ [m_search.get() setBezelStyle:NSTextFieldRoundedBezel];
+ [m_search.get() setBezeled:YES];
+ [m_search.get() setEditable:YES];
+ [m_search.get() setFocusRingType:NSFocusRingTypeExterior];
+ }
+
+ return m_search.get();
+}
+
+NSMenu* RenderThemeChromiumMac::searchMenuTemplate() const
+{
+ if (!m_searchMenuTemplate)
+ m_searchMenuTemplate.adoptNS([[NSMenu alloc] initWithTitle:@""]);
+
+ return m_searchMenuTemplate.get();
+}
+
+NSSliderCell* RenderThemeChromiumMac::sliderThumbHorizontal() const
+{
+ if (!m_sliderThumbHorizontal) {
+ m_sliderThumbHorizontal.adoptNS([[NSSliderCell alloc] init]);
+ [m_sliderThumbHorizontal.get() setTitle:nil];
+ [m_sliderThumbHorizontal.get() setSliderType:NSLinearSlider];
+ [m_sliderThumbHorizontal.get() setControlSize:NSSmallControlSize];
+ [m_sliderThumbHorizontal.get() setFocusRingType:NSFocusRingTypeExterior];
+ }
+
+ return m_sliderThumbHorizontal.get();
+}
+
+NSSliderCell* RenderThemeChromiumMac::sliderThumbVertical() const
+{
+ if (!m_sliderThumbVertical) {
+ m_sliderThumbVertical.adoptNS([[NSSliderCell alloc] init]);
+ [m_sliderThumbVertical.get() setTitle:nil];
+ [m_sliderThumbVertical.get() setSliderType:NSLinearSlider];
+ [m_sliderThumbVertical.get() setControlSize:NSSmallControlSize];
+ [m_sliderThumbVertical.get() setFocusRingType:NSFocusRingTypeExterior];
+ }
+
+ return m_sliderThumbVertical.get();
+}
+
+} // namespace WebCore
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderThemeChromiumSkia.cpp b/src/3rdparty/webkit/WebCore/rendering/RenderThemeChromiumSkia.cpp
new file mode 100644
index 0000000..1fb0cb2
--- /dev/null
+++ b/src/3rdparty/webkit/WebCore/rendering/RenderThemeChromiumSkia.cpp
@@ -0,0 +1,619 @@
+/*
+ * Copyright (C) 2007 Apple Inc.
+ * Copyright (C) 2007 Alp Toker <alp@atoker.com>
+ * Copyright (C) 2008 Collabora Ltd.
+ * Copyright (C) 2008, 2009 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "RenderThemeChromiumSkia.h"
+
+#include "ChromiumBridge.h"
+#include "CSSValueKeywords.h"
+#include "GraphicsContext.h"
+#include "HTMLMediaElement.h"
+#include "HTMLNames.h"
+#include "Image.h"
+#include "MediaControlElements.h"
+#include "PlatformContextSkia.h"
+#include "RenderBox.h"
+#include "RenderObject.h"
+#include "ScrollbarTheme.h"
+#include "TransformationMatrix.h"
+#include "UserAgentStyleSheets.h"
+
+#include "SkShader.h"
+#include "SkGradientShader.h"
+
+namespace WebCore {
+
+enum PaddingType {
+ TopPadding,
+ RightPadding,
+ BottomPadding,
+ LeftPadding
+};
+
+static const int styledMenuListInternalPadding[4] = { 1, 4, 1, 4 };
+
+// The background for the media player controls should be a 60% opaque black rectangle. This
+// matches the UI mockups for the default UI theme.
+static const float defaultMediaControlOpacity = 0.6f;
+
+// These values all match Safari/Win.
+static const float defaultControlFontPixelSize = 13;
+static const float defaultCancelButtonSize = 9;
+static const float minCancelButtonSize = 5;
+static const float maxCancelButtonSize = 21;
+static const float defaultSearchFieldResultsDecorationSize = 13;
+static const float minSearchFieldResultsDecorationSize = 9;
+static const float maxSearchFieldResultsDecorationSize = 30;
+static const float defaultSearchFieldResultsButtonWidth = 18;
+
+static void setSizeIfAuto(RenderStyle* style, const IntSize& size)
+{
+ if (style->width().isIntrinsicOrAuto())
+ style->setWidth(Length(size.width(), Fixed));
+ if (style->height().isAuto())
+ style->setHeight(Length(size.height(), Fixed));
+}
+
+#if ENABLE(VIDEO)
+// Attempt to retrieve a HTMLMediaElement from a Node. Returns NULL if one cannot be found.
+static HTMLMediaElement* mediaElementParent(Node* node)
+{
+ if (!node)
+ return 0;
+ Node* mediaNode = node->shadowAncestorNode();
+ if (!mediaNode || (!mediaNode->hasTagName(HTMLNames::videoTag) && !mediaNode->hasTagName(HTMLNames::audioTag)))
+ return 0;
+
+ return static_cast<HTMLMediaElement*>(mediaNode);
+}
+#endif
+
+// We aim to match IE here.
+// -IE uses a font based on the encoding as the default font for form controls.
+// -Gecko uses MS Shell Dlg (actually calls GetStockObject(DEFAULT_GUI_FONT),
+// which returns MS Shell Dlg)
+// -Safari uses Lucida Grande.
+//
+// FIXME: The only case where we know we don't match IE is for ANSI encodings.
+// IE uses MS Shell Dlg there, which we render incorrectly at certain pixel
+// sizes (e.g. 15px). So, for now we just use Arial.
+const String& RenderThemeChromiumSkia::defaultGUIFont()
+{
+ DEFINE_STATIC_LOCAL(String, fontFace, ("Arial"));
+ return fontFace;
+}
+
+float RenderThemeChromiumSkia::defaultFontSize = 16.0;
+
+RenderThemeChromiumSkia::RenderThemeChromiumSkia()
+{
+}
+
+RenderThemeChromiumSkia::~RenderThemeChromiumSkia()
+{
+}
+
+// Use the Windows style sheets to match their metrics.
+String RenderThemeChromiumSkia::extraDefaultStyleSheet()
+{
+ return String(themeWinUserAgentStyleSheet, sizeof(themeWinUserAgentStyleSheet));
+}
+
+String RenderThemeChromiumSkia::extraQuirksStyleSheet()
+{
+ return String(themeWinQuirksUserAgentStyleSheet, sizeof(themeWinQuirksUserAgentStyleSheet));
+}
+
+#if ENABLE(VIDEO)
+String RenderThemeChromiumSkia::extraMediaControlsStyleSheet()
+{
+ return String(mediaControlsChromiumUserAgentStyleSheet, sizeof(mediaControlsChromiumUserAgentStyleSheet));
+}
+#endif
+
+bool RenderThemeChromiumSkia::supportsHover(const RenderStyle* style) const
+{
+ return true;
+}
+
+bool RenderThemeChromiumSkia::supportsFocusRing(const RenderStyle* style) const
+{
+ // This causes WebKit to draw the focus rings for us.
+ return false;
+}
+
+Color RenderThemeChromiumSkia::platformActiveSelectionBackgroundColor() const
+{
+ return Color(0x1e, 0x90, 0xff);
+}
+
+Color RenderThemeChromiumSkia::platformInactiveSelectionBackgroundColor() const
+{
+ return Color(0xc8, 0xc8, 0xc8);
+}
+
+Color RenderThemeChromiumSkia::platformActiveSelectionForegroundColor() const
+{
+ return Color::black;
+}
+
+Color RenderThemeChromiumSkia::platformInactiveSelectionForegroundColor() const
+{
+ return Color(0x32, 0x32, 0x32);
+}
+
+Color RenderThemeChromiumSkia::focusRingColor() const
+{
+ static Color focusRingColor(229, 151, 0, 255);
+ return focusRingColor;
+}
+
+double RenderThemeChromiumSkia::caretBlinkInterval() const
+{
+ // Disable the blinking caret in layout test mode, as it introduces
+ // a race condition for the pixel tests. http://b/1198440
+ if (ChromiumBridge::layoutTestMode())
+ return 0;
+
+ return caretBlinkIntervalInternal();
+}
+
+void RenderThemeChromiumSkia::systemFont(int propId, FontDescription& fontDescription) const
+{
+ float fontSize = defaultFontSize;
+
+ switch (propId) {
+ case CSSValueWebkitMiniControl:
+ case CSSValueWebkitSmallControl:
+ case CSSValueWebkitControl:
+ // Why 2 points smaller? Because that's what Gecko does. Note that we
+ // are assuming a 96dpi screen, which is the default that we use on
+ // Windows.
+ static const float pointsPerInch = 72.0f;
+ static const float pixelsPerInch = 96.0f;
+ fontSize -= (2.0f / pointsPerInch) * pixelsPerInch;
+ break;
+ }
+
+ fontDescription.firstFamily().setFamily(defaultGUIFont());
+ fontDescription.setSpecifiedSize(fontSize);
+ fontDescription.setIsAbsoluteSize(true);
+ fontDescription.setGenericFamily(FontDescription::NoFamily);
+ fontDescription.setWeight(FontWeightNormal);
+ fontDescription.setItalic(false);
+}
+
+int RenderThemeChromiumSkia::minimumMenuListSize(RenderStyle* style) const
+{
+ return 0;
+}
+
+bool RenderThemeChromiumSkia::paintCheckbox(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& rect)
+{
+ static Image* const checkedImage = Image::loadPlatformResource("linuxCheckboxOn").releaseRef();
+ static Image* const uncheckedImage = Image::loadPlatformResource("linuxCheckboxOff").releaseRef();
+
+ Image* image = this->isChecked(o) ? checkedImage : uncheckedImage;
+ i.context->drawImage(image, rect);
+ return false;
+}
+
+void RenderThemeChromiumSkia::setCheckboxSize(RenderStyle* style) const
+{
+ // If the width and height are both specified, then we have nothing to do.
+ if (!style->width().isIntrinsicOrAuto() && !style->height().isAuto())
+ return;
+
+ // FIXME: A hard-coded size of 13 is used. This is wrong but necessary
+ // for now. It matches Firefox. At different DPI settings on Windows,
+ // querying the theme gives you a larger size that accounts for the higher
+ // DPI. Until our entire engine honors a DPI setting other than 96, we
+ // can't rely on the theme's metrics.
+ const IntSize size(13, 13);
+ setSizeIfAuto(style, size);
+}
+
+bool RenderThemeChromiumSkia::paintRadio(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& rect)
+{
+ static Image* const checkedImage = Image::loadPlatformResource("linuxRadioOn").releaseRef();
+ static Image* const uncheckedImage = Image::loadPlatformResource("linuxRadioOff").releaseRef();
+
+ Image* image = this->isChecked(o) ? checkedImage : uncheckedImage;
+ i.context->drawImage(image, rect);
+ return false;
+}
+
+void RenderThemeChromiumSkia::setRadioSize(RenderStyle* style) const
+{
+ // Use same sizing for radio box as checkbox.
+ setCheckboxSize(style);
+}
+
+static SkColor brightenColor(double h, double s, double l, float brightenAmount)
+{
+ l += brightenAmount;
+ if (l > 1.0)
+ l = 1.0;
+ if (l < 0.0)
+ l = 0.0;
+
+ return makeRGBAFromHSLA(h, s, l, 1.0);
+}
+
+static void paintButtonLike(RenderTheme* theme, RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& rect)
+{
+ SkCanvas* const canvas = i.context->platformContext()->canvas();
+ SkPaint paint;
+ SkRect skrect;
+ const int right = rect.x() + rect.width();
+ const int bottom = rect.y() + rect.height();
+ SkColor baseColor = SkColorSetARGB(0xff, 0xdd, 0xdd, 0xdd);
+ if (o->style()->hasBackground())
+ baseColor = o->style()->backgroundColor().rgb();
+ double h, s, l;
+ Color(baseColor).getHSL(h, s, l);
+ // Our standard gradient is from 0xdd to 0xf8. This is the amount of
+ // increased luminance between those values.
+ SkColor lightColor(brightenColor(h, s, l, 0.105));
+
+ // If the button is too small, fallback to drawing a single, solid color
+ if (rect.width() < 5 || rect.height() < 5) {
+ paint.setColor(baseColor);
+ skrect.set(rect.x(), rect.y(), right, bottom);
+ canvas->drawRect(skrect, paint);
+ return;
+ }
+
+ const int borderAlpha = theme->isHovered(o) ? 0x80 : 0x55;
+ paint.setARGB(borderAlpha, 0, 0, 0);
+ canvas->drawLine(rect.x() + 1, rect.y(), right - 1, rect.y(), paint);
+ canvas->drawLine(right - 1, rect.y() + 1, right - 1, bottom - 1, paint);
+ canvas->drawLine(rect.x() + 1, bottom - 1, right - 1, bottom - 1, paint);
+ canvas->drawLine(rect.x(), rect.y() + 1, rect.x(), bottom - 1, paint);
+
+ paint.setARGB(0xff, 0, 0, 0);
+ SkPoint p[2];
+ const int lightEnd = theme->isPressed(o) ? 1 : 0;
+ const int darkEnd = !lightEnd;
+ p[lightEnd].set(SkIntToScalar(rect.x()), SkIntToScalar(rect.y()));
+ p[darkEnd].set(SkIntToScalar(rect.x()), SkIntToScalar(bottom - 1));
+ SkColor colors[2];
+ colors[0] = lightColor;
+ colors[1] = baseColor;
+
+ SkShader* shader = SkGradientShader::CreateLinear(
+ p, colors, NULL, 2, SkShader::kClamp_TileMode, NULL);
+ paint.setStyle(SkPaint::kFill_Style);
+ paint.setShader(shader);
+ shader->unref();
+
+ skrect.set(rect.x() + 1, rect.y() + 1, right - 1, bottom - 1);
+ canvas->drawRect(skrect, paint);
+
+ paint.setShader(NULL);
+ paint.setColor(brightenColor(h, s, l, -0.0588));
+ canvas->drawPoint(rect.x() + 1, rect.y() + 1, paint);
+ canvas->drawPoint(right - 2, rect.y() + 1, paint);
+ canvas->drawPoint(rect.x() + 1, bottom - 2, paint);
+ canvas->drawPoint(right - 2, bottom - 2, paint);
+}
+
+bool RenderThemeChromiumSkia::paintButton(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& rect)
+{
+ paintButtonLike(this, o, i, rect);
+ return false;
+}
+
+bool RenderThemeChromiumSkia::paintTextField(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& rect)
+{
+ return true;
+}
+
+bool RenderThemeChromiumSkia::paintTextArea(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& r)
+{
+ return paintTextField(o, i, r);
+}
+
+bool RenderThemeChromiumSkia::paintSearchField(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& r)
+{
+ return paintTextField(o, i, r);
+}
+
+void RenderThemeChromiumSkia::adjustSearchFieldCancelButtonStyle(CSSStyleSelector*, RenderStyle* style, Element*) const
+{
+ // Scale the button size based on the font size
+ float fontScale = style->fontSize() / defaultControlFontPixelSize;
+ int cancelButtonSize = lroundf(std::min(std::max(minCancelButtonSize, defaultCancelButtonSize * fontScale), maxCancelButtonSize));
+ style->setWidth(Length(cancelButtonSize, Fixed));
+ style->setHeight(Length(cancelButtonSize, Fixed));
+}
+
+bool RenderThemeChromiumSkia::paintSearchFieldCancelButton(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& r)
+{
+ IntRect bounds = r;
+ ASSERT(o->parent());
+ if (!o->parent() || !o->parent()->isBox())
+ return false;
+
+ RenderBox* parentRenderBox = toRenderBox(o->parent());
+
+ IntRect parentBox = parentRenderBox->absoluteContentBox();
+
+ // Make sure the scaled button stays square and will fit in its parent's box
+ bounds.setHeight(std::min(parentBox.width(), std::min(parentBox.height(), bounds.height())));
+ bounds.setWidth(bounds.height());
+
+ // Center the button vertically. Round up though, so if it has to be one pixel off-center, it will
+ // be one pixel closer to the bottom of the field. This tends to look better with the text.
+ bounds.setY(parentBox.y() + (parentBox.height() - bounds.height() + 1) / 2);
+
+ static Image* cancelImage = Image::loadPlatformResource("searchCancel").releaseRef();
+ static Image* cancelPressedImage = Image::loadPlatformResource("searchCancelPressed").releaseRef();
+ i.context->drawImage(isPressed(o) ? cancelPressedImage : cancelImage, bounds);
+ return false;
+}
+
+void RenderThemeChromiumSkia::adjustSearchFieldDecorationStyle(CSSStyleSelector*, RenderStyle* style, Element*) const
+{
+ IntSize emptySize(1, 11);
+ style->setWidth(Length(emptySize.width(), Fixed));
+ style->setHeight(Length(emptySize.height(), Fixed));
+}
+
+void RenderThemeChromiumSkia::adjustSearchFieldResultsDecorationStyle(CSSStyleSelector*, RenderStyle* style, Element*) const
+{
+ // Scale the decoration size based on the font size
+ float fontScale = style->fontSize() / defaultControlFontPixelSize;
+ int magnifierSize = lroundf(std::min(std::max(minSearchFieldResultsDecorationSize, defaultSearchFieldResultsDecorationSize * fontScale),
+ maxSearchFieldResultsDecorationSize));
+ style->setWidth(Length(magnifierSize, Fixed));
+ style->setHeight(Length(magnifierSize, Fixed));
+}
+
+bool RenderThemeChromiumSkia::paintSearchFieldResultsDecoration(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& r)
+{
+ IntRect bounds = r;
+ ASSERT(o->parent());
+ if (!o->parent() || !o->parent()->isBox())
+ return false;
+
+ RenderBox* parentRenderBox = toRenderBox(o->parent());
+ IntRect parentBox = parentRenderBox->absoluteContentBox();
+
+ // Make sure the scaled decoration stays square and will fit in its parent's box
+ bounds.setHeight(std::min(parentBox.width(), std::min(parentBox.height(), bounds.height())));
+ bounds.setWidth(bounds.height());
+
+ // Center the decoration vertically. Round up though, so if it has to be one pixel off-center, it will
+ // be one pixel closer to the bottom of the field. This tends to look better with the text.
+ bounds.setY(parentBox.y() + (parentBox.height() - bounds.height() + 1) / 2);
+
+ static Image* magnifierImage = Image::loadPlatformResource("searchMagnifier").releaseRef();
+ i.context->drawImage(magnifierImage, bounds);
+ return false;
+}
+
+void RenderThemeChromiumSkia::adjustSearchFieldResultsButtonStyle(CSSStyleSelector*, RenderStyle* style, Element*) const
+{
+ // Scale the button size based on the font size
+ float fontScale = style->fontSize() / defaultControlFontPixelSize;
+ int magnifierHeight = lroundf(std::min(std::max(minSearchFieldResultsDecorationSize, defaultSearchFieldResultsDecorationSize * fontScale),
+ maxSearchFieldResultsDecorationSize));
+ int magnifierWidth = lroundf(magnifierHeight * defaultSearchFieldResultsButtonWidth / defaultSearchFieldResultsDecorationSize);
+ style->setWidth(Length(magnifierWidth, Fixed));
+ style->setHeight(Length(magnifierHeight, Fixed));
+}
+
+bool RenderThemeChromiumSkia::paintSearchFieldResultsButton(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& r)
+{
+ IntRect bounds = r;
+ ASSERT(o->parent());
+ if (!o->parent())
+ return false;
+ if (!o->parent() || !o->parent()->isBox())
+ return false;
+
+ RenderBox* parentRenderBox = toRenderBox(o->parent());
+ IntRect parentBox = parentRenderBox->absoluteContentBox();
+
+ // Make sure the scaled decoration will fit in its parent's box
+ bounds.setHeight(std::min(parentBox.height(), bounds.height()));
+ bounds.setWidth(std::min(parentBox.width(), static_cast<int>(bounds.height() * defaultSearchFieldResultsButtonWidth / defaultSearchFieldResultsDecorationSize)));
+
+ // Center the button vertically. Round up though, so if it has to be one pixel off-center, it will
+ // be one pixel closer to the bottom of the field. This tends to look better with the text.
+ bounds.setY(parentBox.y() + (parentBox.height() - bounds.height() + 1) / 2);
+
+ static Image* magnifierImage = Image::loadPlatformResource("searchMagnifierResults").releaseRef();
+ i.context->drawImage(magnifierImage, bounds);
+ return false;
+}
+
+bool RenderThemeChromiumSkia::paintMediaButtonInternal(GraphicsContext* context, const IntRect& rect, Image* image)
+{
+ context->beginTransparencyLayer(defaultMediaControlOpacity);
+
+ // Draw background.
+ Color oldFill = context->fillColor();
+ Color oldStroke = context->strokeColor();
+
+ context->setFillColor(Color::black);
+ context->setStrokeColor(Color::black);
+ context->drawRect(rect);
+
+ context->setFillColor(oldFill);
+ context->setStrokeColor(oldStroke);
+
+ // Create a destination rectangle for the image that is centered in the drawing rectangle, rounded left, and down.
+ IntRect imageRect = image->rect();
+ imageRect.setY(rect.y() + (rect.height() - image->height() + 1) / 2);
+ imageRect.setX(rect.x() + (rect.width() - image->width() + 1) / 2);
+
+ context->drawImage(image, imageRect, CompositeSourceAtop);
+ context->endTransparencyLayer();
+
+ return false;
+}
+
+bool RenderThemeChromiumSkia::paintMediaPlayButton(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& rect)
+{
+#if ENABLE(VIDEO)
+ HTMLMediaElement* mediaElement = mediaElementParent(o->node());
+ if (!mediaElement)
+ return false;
+
+ static Image* mediaPlay = Image::loadPlatformResource("mediaPlay").releaseRef();
+ static Image* mediaPause = Image::loadPlatformResource("mediaPause").releaseRef();
+
+ return paintMediaButtonInternal(paintInfo.context, rect, mediaElement->paused() ? mediaPlay : mediaPause);
+#else
+ return false;
+#endif
+}
+
+bool RenderThemeChromiumSkia::paintMediaMuteButton(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& rect)
+{
+#if ENABLE(VIDEO)
+ HTMLMediaElement* mediaElement = mediaElementParent(o->node());
+ if (!mediaElement)
+ return false;
+
+ static Image* soundFull = Image::loadPlatformResource("mediaSoundFull").releaseRef();
+ static Image* soundNone = Image::loadPlatformResource("mediaSoundNone").releaseRef();
+
+ return paintMediaButtonInternal(paintInfo.context, rect, mediaElement->muted() ? soundNone: soundFull);
+#else
+ return false;
+#endif
+}
+
+void RenderThemeChromiumSkia::adjustMenuListStyle(CSSStyleSelector* selector, RenderStyle* style, WebCore::Element* e) const
+{
+ // Height is locked to auto on all browsers.
+ style->setLineHeight(RenderStyle::initialLineHeight());
+}
+
+bool RenderThemeChromiumSkia::paintMenuList(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& rect)
+{
+ SkCanvas* const canvas = i.context->platformContext()->canvas();
+ const int right = rect.x() + rect.width();
+ const int middle = rect.y() + rect.height() / 2;
+
+ paintButtonLike(this, o, i, rect);
+
+ SkPaint paint;
+ paint.setARGB(0xff, 0, 0, 0);
+ paint.setAntiAlias(true);
+ paint.setStyle(SkPaint::kFill_Style);
+
+ SkPath path;
+ path.moveTo(right - 13, middle - 3);
+ path.rLineTo(6, 0);
+ path.rLineTo(-3, 6);
+ path.close();
+ canvas->drawPath(path, paint);
+
+ return false;
+}
+
+void RenderThemeChromiumSkia::adjustMenuListButtonStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
+{
+ adjustMenuListStyle(selector, style, e);
+}
+
+// Used to paint styled menulists (i.e. with a non-default border)
+bool RenderThemeChromiumSkia::paintMenuListButton(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& rect)
+{
+ return paintMenuList(o, i, rect);
+}
+
+int RenderThemeChromiumSkia::popupInternalPaddingLeft(RenderStyle* style) const
+{
+ return menuListInternalPadding(style, LeftPadding);
+}
+
+int RenderThemeChromiumSkia::popupInternalPaddingRight(RenderStyle* style) const
+{
+ return menuListInternalPadding(style, RightPadding);
+}
+
+int RenderThemeChromiumSkia::popupInternalPaddingTop(RenderStyle* style) const
+{
+ return menuListInternalPadding(style, TopPadding);
+}
+
+int RenderThemeChromiumSkia::popupInternalPaddingBottom(RenderStyle* style) const
+{
+ return menuListInternalPadding(style, BottomPadding);
+}
+
+int RenderThemeChromiumSkia::buttonInternalPaddingLeft() const
+{
+ return 3;
+}
+
+int RenderThemeChromiumSkia::buttonInternalPaddingRight() const
+{
+ return 3;
+}
+
+int RenderThemeChromiumSkia::buttonInternalPaddingTop() const
+{
+ return 1;
+}
+
+int RenderThemeChromiumSkia::buttonInternalPaddingBottom() const
+{
+ return 1;
+}
+
+// static
+void RenderThemeChromiumSkia::setDefaultFontSize(int fontSize)
+{
+ defaultFontSize = static_cast<float>(fontSize);
+}
+
+double RenderThemeChromiumSkia::caretBlinkIntervalInternal() const
+{
+ return RenderTheme::caretBlinkInterval();
+}
+
+int RenderThemeChromiumSkia::menuListInternalPadding(RenderStyle* style, int paddingType) const
+{
+ // This internal padding is in addition to the user-supplied padding.
+ // Matches the FF behavior.
+ int padding = styledMenuListInternalPadding[paddingType];
+
+ // Reserve the space for right arrow here. The rest of the padding is
+ // set by adjustMenuListStyle, since PopMenuWin.cpp uses the padding from
+ // RenderMenuList to lay out the individual items in the popup.
+ // If the MenuList actually has appearance "NoAppearance", then that means
+ // we don't draw a button, so don't reserve space for it.
+ const int barType = style->direction() == LTR ? RightPadding : LeftPadding;
+ if (paddingType == barType && style->appearance() != NoControlPart)
+ padding += ScrollbarTheme::nativeTheme()->scrollbarThickness();
+
+ return padding;
+}
+
+} // namespace WebCore
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderThemeChromiumSkia.h b/src/3rdparty/webkit/WebCore/rendering/RenderThemeChromiumSkia.h
new file mode 100644
index 0000000..b81d4fa
--- /dev/null
+++ b/src/3rdparty/webkit/WebCore/rendering/RenderThemeChromiumSkia.h
@@ -0,0 +1,144 @@
+/*
+ * This file is part of the WebKit project.
+ *
+ * Copyright (C) 2006 Apple Computer, Inc.
+ * Copyright (C) 2006 Michael Emmel mike.emmel@gmail.com
+ * Copyright (C) 2007 Holger Hans Peter Freyther
+ * Copyright (C) 2007 Alp Toker <alp@atoker.com>
+ * Copyright (C) 2008, 2009 Google, Inc.
+ * 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
+ * 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 RenderThemeChromiumSkia_h
+#define RenderThemeChromiumSkia_h
+
+#include "RenderTheme.h"
+
+namespace WebCore {
+
+ class RenderThemeChromiumSkia : public RenderTheme {
+ public:
+ RenderThemeChromiumSkia();
+ virtual ~RenderThemeChromiumSkia();
+
+ virtual String extraDefaultStyleSheet();
+ virtual String extraQuirksStyleSheet();
+#if ENABLE(VIDEO)
+ virtual String extraMediaControlsStyleSheet();
+#endif
+
+ // A method asking if the theme's controls actually care about redrawing when hovered.
+ virtual bool supportsHover(const RenderStyle*) const;
+
+ // A method asking if the theme is able to draw the focus ring.
+ virtual bool supportsFocusRing(const RenderStyle*) const;
+
+ // The platform selection color.
+ virtual Color platformActiveSelectionBackgroundColor() const;
+ virtual Color platformInactiveSelectionBackgroundColor() const;
+ virtual Color platformActiveSelectionForegroundColor() const;
+ virtual Color platformInactiveSelectionForegroundColor() const;
+ virtual Color focusRingColor() const;
+
+ // To change the blink interval, override caretBlinkIntervalInternal instead of this one so that we may share layout test code an intercepts.
+ virtual double caretBlinkInterval() const;
+
+ // System fonts.
+ virtual void systemFont(int propId, FontDescription&) const;
+
+ virtual int minimumMenuListSize(RenderStyle*) const;
+
+ virtual bool paintCheckbox(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+ virtual void setCheckboxSize(RenderStyle*) const;
+
+ virtual bool paintRadio(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+ virtual void setRadioSize(RenderStyle*) const;
+
+ virtual bool paintButton(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+
+ virtual bool paintTextField(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+
+ virtual bool paintTextArea(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+
+ virtual bool paintSearchField(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+
+ virtual void adjustSearchFieldCancelButtonStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+ virtual bool paintSearchFieldCancelButton(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+
+ virtual void adjustSearchFieldDecorationStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+
+ virtual void adjustSearchFieldResultsDecorationStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+ virtual bool paintSearchFieldResultsDecoration(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+
+ virtual void adjustSearchFieldResultsButtonStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+ virtual bool paintSearchFieldResultsButton(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+
+ virtual bool paintMediaPlayButton(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+ virtual bool paintMediaMuteButton(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+
+ // MenuList refers to an unstyled menulist (meaning a menulist without
+ // background-color or border set) and MenuListButton refers to a styled
+ // menulist (a menulist with background-color or border set). They have
+ // this distinction to support showing aqua style themes whenever they
+ // possibly can, which is something we don't want to replicate.
+ //
+ // In short, we either go down the MenuList code path or the MenuListButton
+ // codepath. We never go down both. And in both cases, they render the
+ // entire menulist.
+ virtual void adjustMenuListStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+ virtual bool paintMenuList(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+ virtual void adjustMenuListButtonStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+ virtual bool paintMenuListButton(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+
+ // These methods define the padding for the MenuList's inner block.
+ virtual int popupInternalPaddingLeft(RenderStyle*) const;
+ virtual int popupInternalPaddingRight(RenderStyle*) const;
+ virtual int popupInternalPaddingTop(RenderStyle*) const;
+ virtual int popupInternalPaddingBottom(RenderStyle*) const;
+
+ virtual int buttonInternalPaddingLeft() const;
+ virtual int buttonInternalPaddingRight() const;
+ virtual int buttonInternalPaddingTop() const;
+ virtual int buttonInternalPaddingBottom() const;
+
+ // Provide a way to pass the default font size from the Settings object
+ // to the render theme. FIXME: http://b/1129186 A cleaner way would be
+ // to remove the default font size from this object and have callers
+ // that need the value to get it directly from the appropriate Settings
+ // object.
+ static void setDefaultFontSize(int);
+
+ protected:
+ static const String& defaultGUIFont();
+
+ // The default variable-width font size. We use this as the default font
+ // size for the "system font", and as a base size (which we then shrink) for
+ // form control fonts.
+ static float defaultFontSize;
+
+ virtual double caretBlinkIntervalInternal() const;
+
+ private:
+ int menuListInternalPadding(RenderStyle*, int paddingType) const;
+ bool paintMediaButtonInternal(GraphicsContext*, const IntRect&, Image*);
+ };
+
+} // namespace WebCore
+
+#endif // RenderThemeChromiumSkia_h
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderThemeChromiumWin.cpp b/src/3rdparty/webkit/WebCore/rendering/RenderThemeChromiumWin.cpp
new file mode 100644
index 0000000..4ed8d88
--- /dev/null
+++ b/src/3rdparty/webkit/WebCore/rendering/RenderThemeChromiumWin.cpp
@@ -0,0 +1,581 @@
+/*
+ * This file is part of the WebKit project.
+ *
+ * Copyright (C) 2006 Apple Computer, Inc.
+ * Copyright (C) 2008, 2009 Google, Inc.
+ * Copyright (C) 2009 Kenneth Rohde Christiansen
+ *
+ * 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., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include "config.h"
+#include "RenderThemeChromiumWin.h"
+
+#include <windows.h>
+#include <uxtheme.h>
+#include <vssym32.h>
+
+#include "ChromiumBridge.h"
+#include "CSSValueKeywords.h"
+#include "FontSelector.h"
+#include "FontUtilsChromiumWin.h"
+#include "GraphicsContext.h"
+#include "HTMLMediaElement.h"
+#include "HTMLNames.h"
+#include "MediaControlElements.h"
+#include "RenderBox.h"
+#include "RenderSlider.h"
+#include "ScrollbarTheme.h"
+#include "TransparencyWin.h"
+#include "WindowsVersion.h"
+
+// FIXME: This dependency should eventually be removed.
+#include <skia/ext/skia_utils_win.h>
+
+#define SIZEOF_STRUCT_WITH_SPECIFIED_LAST_MEMBER(structName, member) \
+ offsetof(structName, member) + \
+ (sizeof static_cast<structName*>(0)->member)
+#define NONCLIENTMETRICS_SIZE_PRE_VISTA \
+ SIZEOF_STRUCT_WITH_SPECIFIED_LAST_MEMBER(NONCLIENTMETRICS, lfMessageFont)
+
+namespace WebCore {
+
+namespace {
+class ThemePainter : public TransparencyWin {
+public:
+ ThemePainter(GraphicsContext* context, const IntRect& r)
+ {
+ TransformMode transformMode = getTransformMode(context->getCTM());
+ init(context, getLayerMode(context, transformMode), transformMode, r);
+ }
+
+ ~ThemePainter()
+ {
+ composite();
+ }
+
+private:
+ static bool canvasHasMultipleLayers(const SkCanvas* canvas)
+ {
+ SkCanvas::LayerIter iter(const_cast<SkCanvas*>(canvas), false);
+ iter.next(); // There is always at least one layer.
+ return !iter.done(); // There is > 1 layer if the the iterator can stil advance.
+ }
+
+ static LayerMode getLayerMode(GraphicsContext* context, TransformMode transformMode)
+ {
+ if (context->platformContext()->isDrawingToImageBuffer()) // Might have transparent background.
+ return WhiteLayer;
+ else if (canvasHasMultipleLayers(context->platformContext()->canvas())) // Needs antialiasing help.
+ return OpaqueCompositeLayer;
+ else // Nothing interesting.
+ return transformMode == KeepTransform ? NoLayer : OpaqueCompositeLayer;
+ }
+
+ static TransformMode getTransformMode(const TransformationMatrix& matrix)
+ {
+ if (matrix.b() != 0 || matrix.c() != 0) // Skew.
+ return Untransform;
+ else if (matrix.a() != 1.0 || matrix.d() != 1.0) // Scale.
+ return ScaleTransform;
+ else // Nothing interesting.
+ return KeepTransform;
+ }
+};
+
+} // namespace
+
+static void getNonClientMetrics(NONCLIENTMETRICS* metrics)
+{
+ static UINT size = WebCore::isVistaOrNewer() ?
+ sizeof(NONCLIENTMETRICS) : NONCLIENTMETRICS_SIZE_PRE_VISTA;
+ metrics->cbSize = size;
+ bool success = !!SystemParametersInfo(SPI_GETNONCLIENTMETRICS, size, metrics, 0);
+ ASSERT(success);
+}
+
+static FontDescription smallSystemFont;
+static FontDescription menuFont;
+static FontDescription labelFont;
+
+// Internal static helper functions. We don't put them in an anonymous
+// namespace so they have easier access to the WebCore namespace.
+
+static bool supportsFocus(ControlPart appearance)
+{
+ switch (appearance) {
+ case PushButtonPart:
+ case ButtonPart:
+ case DefaultButtonPart:
+ case SearchFieldPart:
+ case TextFieldPart:
+ case TextAreaPart:
+ return true;
+ }
+ return false;
+}
+
+// Return the height of system font |font| in pixels. We use this size by
+// default for some non-form-control elements.
+static float systemFontSize(const LOGFONT& font)
+{
+ float size = -font.lfHeight;
+ if (size < 0) {
+ HFONT hFont = CreateFontIndirect(&font);
+ if (hFont) {
+ HDC hdc = GetDC(0); // What about printing? Is this the right DC?
+ if (hdc) {
+ HGDIOBJ hObject = SelectObject(hdc, hFont);
+ TEXTMETRIC tm;
+ GetTextMetrics(hdc, &tm);
+ SelectObject(hdc, hObject);
+ ReleaseDC(0, hdc);
+ size = tm.tmAscent;
+ }
+ DeleteObject(hFont);
+ }
+ }
+
+ // The "codepage 936" bit here is from Gecko; apparently this helps make
+ // fonts more legible in Simplified Chinese where the default font size is
+ // too small.
+ //
+ // FIXME: http://b/1119883 Since this is only used for "small caption",
+ // "menu", and "status bar" objects, I'm not sure how much this even
+ // matters. Plus the Gecko patch went in back in 2002, and maybe this
+ // isn't even relevant anymore. We should investigate whether this should
+ // be removed, or perhaps broadened to be "any CJK locale".
+ //
+ return ((size < 12.0f) && (GetACP() == 936)) ? 12.0f : size;
+}
+
+// Converts |points| to pixels. One point is 1/72 of an inch.
+static float pointsToPixels(float points)
+{
+ static float pixelsPerInch = 0.0f;
+ if (!pixelsPerInch) {
+ HDC hdc = GetDC(0); // What about printing? Is this the right DC?
+ if (hdc) { // Can this ever actually be NULL?
+ pixelsPerInch = GetDeviceCaps(hdc, LOGPIXELSY);
+ ReleaseDC(0, hdc);
+ } else {
+ pixelsPerInch = 96.0f;
+ }
+ }
+
+ static const float pointsPerInch = 72.0f;
+ return points / pointsPerInch * pixelsPerInch;
+}
+
+static double querySystemBlinkInterval(double defaultInterval)
+{
+ UINT blinkTime = GetCaretBlinkTime();
+ if (blinkTime == 0)
+ return defaultInterval;
+ if (blinkTime == INFINITE)
+ return 0;
+ return blinkTime / 1000.0;
+}
+
+PassRefPtr<RenderTheme> RenderThemeChromiumWin::create()
+{
+ return adoptRef(new RenderThemeChromiumWin);
+}
+
+PassRefPtr<RenderTheme> RenderTheme::themeForPage(Page* page)
+{
+ static RenderTheme* rt = RenderThemeChromiumWin::create().releaseRef();
+ return rt;
+}
+
+bool RenderThemeChromiumWin::supportsFocusRing(const RenderStyle* style) const
+{
+ // Let webkit draw one of its halo rings around any focused element,
+ // except push buttons. For buttons we use the windows PBS_DEFAULTED
+ // styling to give it a blue border.
+ return style->appearance() == ButtonPart
+ || style->appearance() == PushButtonPart;
+}
+
+Color RenderThemeChromiumWin::platformActiveSelectionBackgroundColor() const
+{
+ if (ChromiumBridge::layoutTestMode())
+ return Color(0x00, 0x00, 0xff); // Royal blue.
+ COLORREF color = GetSysColor(COLOR_HIGHLIGHT);
+ return Color(GetRValue(color), GetGValue(color), GetBValue(color), 0xff);
+}
+
+Color RenderThemeChromiumWin::platformInactiveSelectionBackgroundColor() const
+{
+ if (ChromiumBridge::layoutTestMode())
+ return Color(0x99, 0x99, 0x99); // Medium gray.
+ COLORREF color = GetSysColor(COLOR_GRAYTEXT);
+ return Color(GetRValue(color), GetGValue(color), GetBValue(color), 0xff);
+}
+
+Color RenderThemeChromiumWin::platformActiveSelectionForegroundColor() const
+{
+ if (ChromiumBridge::layoutTestMode())
+ return Color(0xff, 0xff, 0xcc); // Pale yellow.
+ COLORREF color = GetSysColor(COLOR_HIGHLIGHTTEXT);
+ return Color(GetRValue(color), GetGValue(color), GetBValue(color), 0xff);
+}
+
+Color RenderThemeChromiumWin::platformInactiveSelectionForegroundColor() const
+{
+ return Color::white;
+}
+
+Color RenderThemeChromiumWin::platformActiveTextSearchHighlightColor() const
+{
+ return Color(0xff, 0x96, 0x32); // Orange.
+}
+
+Color RenderThemeChromiumWin::platformInactiveTextSearchHighlightColor() const
+{
+ return Color(0xff, 0xff, 0x96); // Yellow.
+}
+
+void RenderThemeChromiumWin::systemFont(int propId, FontDescription& fontDescription) const
+{
+ // This logic owes much to RenderThemeSafari.cpp.
+ FontDescription* cachedDesc = 0;
+ AtomicString faceName;
+ float fontSize = 0;
+ switch (propId) {
+ case CSSValueSmallCaption:
+ cachedDesc = &smallSystemFont;
+ if (!smallSystemFont.isAbsoluteSize()) {
+ NONCLIENTMETRICS metrics;
+ getNonClientMetrics(&metrics);
+ faceName = AtomicString(metrics.lfSmCaptionFont.lfFaceName, wcslen(metrics.lfSmCaptionFont.lfFaceName));
+ fontSize = systemFontSize(metrics.lfSmCaptionFont);
+ }
+ break;
+ case CSSValueMenu:
+ cachedDesc = &menuFont;
+ if (!menuFont.isAbsoluteSize()) {
+ NONCLIENTMETRICS metrics;
+ getNonClientMetrics(&metrics);
+ faceName = AtomicString(metrics.lfMenuFont.lfFaceName, wcslen(metrics.lfMenuFont.lfFaceName));
+ fontSize = systemFontSize(metrics.lfMenuFont);
+ }
+ break;
+ case CSSValueStatusBar:
+ cachedDesc = &labelFont;
+ if (!labelFont.isAbsoluteSize()) {
+ NONCLIENTMETRICS metrics;
+ getNonClientMetrics(&metrics);
+ faceName = metrics.lfStatusFont.lfFaceName;
+ fontSize = systemFontSize(metrics.lfStatusFont);
+ }
+ break;
+ case CSSValueWebkitMiniControl:
+ case CSSValueWebkitSmallControl:
+ case CSSValueWebkitControl:
+ faceName = defaultGUIFont();
+ // Why 2 points smaller? Because that's what Gecko does.
+ fontSize = defaultFontSize - pointsToPixels(2);
+ break;
+ default:
+ faceName = defaultGUIFont();
+ fontSize = defaultFontSize;
+ break;
+ }
+
+ if (!cachedDesc)
+ cachedDesc = &fontDescription;
+
+ if (fontSize) {
+ cachedDesc->firstFamily().setFamily(faceName);
+ cachedDesc->setIsAbsoluteSize(true);
+ cachedDesc->setGenericFamily(FontDescription::NoFamily);
+ cachedDesc->setSpecifiedSize(fontSize);
+ cachedDesc->setWeight(FontWeightNormal);
+ cachedDesc->setItalic(false);
+ }
+ fontDescription = *cachedDesc;
+}
+
+void RenderThemeChromiumWin::adjustSliderThumbSize(RenderObject* o) const
+{
+ // These sizes match what WinXP draws for various menus.
+ const int sliderThumbAlongAxis = 11;
+ const int sliderThumbAcrossAxis = 21;
+ if (o->style()->appearance() == SliderThumbHorizontalPart || o->style()->appearance() == MediaSliderThumbPart) {
+ o->style()->setWidth(Length(sliderThumbAlongAxis, Fixed));
+ o->style()->setHeight(Length(sliderThumbAcrossAxis, Fixed));
+ } else if (o->style()->appearance() == SliderThumbVerticalPart) {
+ o->style()->setWidth(Length(sliderThumbAcrossAxis, Fixed));
+ o->style()->setHeight(Length(sliderThumbAlongAxis, Fixed));
+ }
+}
+
+bool RenderThemeChromiumWin::paintCheckbox(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& r)
+{
+ return paintButton(o, i, r);
+}
+bool RenderThemeChromiumWin::paintRadio(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& r)
+{
+ return paintButton(o, i, r);
+}
+
+bool RenderThemeChromiumWin::paintButton(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& r)
+{
+ const ThemeData& themeData = getThemeData(o);
+
+ WebCore::ThemePainter painter(i.context, r);
+ ChromiumBridge::paintButton(painter.context(),
+ themeData.m_part,
+ themeData.m_state,
+ themeData.m_classicState,
+ painter.drawRect());
+ return false;
+}
+
+bool RenderThemeChromiumWin::paintTextField(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& r)
+{
+ return paintTextFieldInternal(o, i, r, true);
+}
+
+bool RenderThemeChromiumWin::paintSliderTrack(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& r)
+{
+ const ThemeData& themeData = getThemeData(o);
+
+ WebCore::ThemePainter painter(i.context, r);
+ ChromiumBridge::paintTrackbar(painter.context(),
+ themeData.m_part,
+ themeData.m_state,
+ themeData.m_classicState,
+ painter.drawRect());
+ return false;
+}
+
+bool RenderThemeChromiumWin::paintSliderThumb(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& r)
+{
+ return paintSliderTrack(o, i, r);
+}
+
+// Used to paint unstyled menulists (i.e. with the default border)
+bool RenderThemeChromiumWin::paintMenuList(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& r)
+{
+ if (!o->isBox())
+ return false;
+
+ const RenderBox* box = toRenderBox(o);
+ int borderRight = box->borderRight();
+ int borderLeft = box->borderLeft();
+ int borderTop = box->borderTop();
+ int borderBottom = box->borderBottom();
+
+ // If all the borders are 0, then tell skia not to paint the border on the
+ // textfield. FIXME: http://b/1210017 Figure out how to get Windows to not
+ // draw individual borders and then pass that to skia so we can avoid
+ // drawing any borders that are set to 0. For non-zero borders, we draw the
+ // border, but webkit just draws over it.
+ bool drawEdges = !(borderRight == 0 && borderLeft == 0 && borderTop == 0 && borderBottom == 0);
+
+ paintTextFieldInternal(o, i, r, drawEdges);
+
+ // Take padding and border into account. If the MenuList is smaller than
+ // the size of a button, make sure to shrink it appropriately and not put
+ // its x position to the left of the menulist.
+ const int buttonWidth = GetSystemMetrics(SM_CXVSCROLL);
+ int spacingLeft = borderLeft + box->paddingLeft();
+ int spacingRight = borderRight + box->paddingRight();
+ int spacingTop = borderTop + box->paddingTop();
+ int spacingBottom = borderBottom + box->paddingBottom();
+
+ int buttonX;
+ if (r.right() - r.x() < buttonWidth)
+ buttonX = r.x();
+ else
+ buttonX = o->style()->direction() == LTR ? r.right() - spacingRight - buttonWidth : r.x() + spacingLeft;
+
+ // Compute the rectangle of the button in the destination image.
+ IntRect rect(buttonX,
+ r.y() + spacingTop,
+ std::min(buttonWidth, r.right() - r.x()),
+ r.height() - (spacingTop + spacingBottom));
+
+ // Get the correct theme data for a textfield and paint the menu.
+ WebCore::ThemePainter painter(i.context, rect);
+ ChromiumBridge::paintMenuList(painter.context(),
+ CP_DROPDOWNBUTTON,
+ determineState(o),
+ determineClassicState(o),
+ painter.drawRect());
+ return false;
+}
+
+// static
+void RenderThemeChromiumWin::setDefaultFontSize(int fontSize)
+{
+ RenderThemeChromiumSkia::setDefaultFontSize(fontSize);
+
+ // Reset cached fonts.
+ smallSystemFont = menuFont = labelFont = FontDescription();
+}
+
+double RenderThemeChromiumWin::caretBlinkIntervalInternal() const
+{
+ // This involves a system call, so we cache the result.
+ static double blinkInterval = querySystemBlinkInterval(RenderTheme::caretBlinkInterval());
+ return blinkInterval;
+}
+
+unsigned RenderThemeChromiumWin::determineState(RenderObject* o)
+{
+ unsigned result = TS_NORMAL;
+ ControlPart appearance = o->style()->appearance();
+ if (!isEnabled(o))
+ result = TS_DISABLED;
+ else if (isReadOnlyControl(o) && (TextFieldPart == appearance || TextAreaPart == appearance || SearchFieldPart == appearance))
+ result = ETS_READONLY; // Readonly is supported on textfields.
+ else if (isPressed(o)) // Active overrides hover and focused.
+ result = TS_PRESSED;
+ else if (supportsFocus(appearance) && isFocused(o))
+ result = ETS_FOCUSED;
+ else if (isHovered(o))
+ result = TS_HOT;
+ if (isChecked(o))
+ result += 4; // 4 unchecked states, 4 checked states.
+ return result;
+}
+
+unsigned RenderThemeChromiumWin::determineSliderThumbState(RenderObject* o)
+{
+ unsigned result = TUS_NORMAL;
+ if (!isEnabled(o->parent()))
+ result = TUS_DISABLED;
+ else if (supportsFocus(o->style()->appearance()) && isFocused(o->parent()))
+ result = TUS_FOCUSED;
+ else if (static_cast<RenderSlider*>(o->parent())->inDragMode())
+ result = TUS_PRESSED;
+ else if (isHovered(o))
+ result = TUS_HOT;
+ return result;
+}
+
+unsigned RenderThemeChromiumWin::determineClassicState(RenderObject* o)
+{
+ unsigned result = 0;
+ if (!isEnabled(o))
+ result = DFCS_INACTIVE;
+ else if (isPressed(o)) // Active supersedes hover
+ result = DFCS_PUSHED;
+ else if (isHovered(o))
+ result = DFCS_HOT;
+ if (isChecked(o))
+ result |= DFCS_CHECKED;
+ return result;
+}
+
+ThemeData RenderThemeChromiumWin::getThemeData(RenderObject* o)
+{
+ ThemeData result;
+ switch (o->style()->appearance()) {
+ case CheckboxPart:
+ result.m_part = BP_CHECKBOX;
+ result.m_state = determineState(o);
+ result.m_classicState = DFCS_BUTTONCHECK;
+ break;
+ case RadioPart:
+ result.m_part = BP_RADIOBUTTON;
+ result.m_state = determineState(o);
+ result.m_classicState = DFCS_BUTTONRADIO;
+ break;
+ case PushButtonPart:
+ case ButtonPart:
+ result.m_part = BP_PUSHBUTTON;
+ result.m_state = determineState(o);
+ result.m_classicState = DFCS_BUTTONPUSH;
+ break;
+ case SliderHorizontalPart:
+ result.m_part = TKP_TRACK;
+ result.m_state = TRS_NORMAL;
+ break;
+ case SliderVerticalPart:
+ result.m_part = TKP_TRACKVERT;
+ result.m_state = TRVS_NORMAL;
+ break;
+ case SliderThumbHorizontalPart:
+ result.m_part = TKP_THUMBBOTTOM;
+ result.m_state = determineSliderThumbState(o);
+ break;
+ case SliderThumbVerticalPart:
+ result.m_part = TKP_THUMBVERT;
+ result.m_state = determineSliderThumbState(o);
+ break;
+ case ListboxPart:
+ case MenulistPart:
+ case SearchFieldPart:
+ case TextFieldPart:
+ case TextAreaPart:
+ result.m_part = EP_EDITTEXT;
+ result.m_state = determineState(o);
+ break;
+ }
+
+ result.m_classicState |= determineClassicState(o);
+
+ return result;
+}
+
+bool RenderThemeChromiumWin::paintTextFieldInternal(RenderObject* o,
+ const RenderObject::PaintInfo& i,
+ const IntRect& r,
+ bool drawEdges)
+{
+ // Nasty hack to make us not paint the border on text fields with a
+ // border-radius. Webkit paints elements with border-radius for us.
+ // FIXME: Get rid of this if-check once we can properly clip rounded
+ // borders: http://b/1112604 and http://b/1108635
+ // FIXME: make sure we do the right thing if css background-clip is set.
+ if (o->style()->hasBorderRadius())
+ return false;
+
+ const ThemeData& themeData = getThemeData(o);
+
+ // Fallback to white if the specified color object is invalid.
+ Color backgroundColor(Color::white);
+ if (o->style()->backgroundColor().isValid()) {
+ backgroundColor = o->style()->backgroundColor();
+ }
+
+ // If we have background-image, don't fill the content area to expose the
+ // parent's background. Also, we shouldn't fill the content area if the
+ // alpha of the color is 0. The API of Windows GDI ignores the alpha.
+ //
+ // Note that we should paint the content area white if we have neither the
+ // background color nor background image explicitly specified to keep the
+ // appearance of select element consistent with other browsers.
+ bool fillContentArea = !o->style()->hasBackgroundImage() && backgroundColor.alpha() != 0;
+
+ WebCore::ThemePainter painter(i.context, r);
+ ChromiumBridge::paintTextField(painter.context(),
+ themeData.m_part,
+ themeData.m_state,
+ themeData.m_classicState,
+ painter.drawRect(),
+ backgroundColor,
+ fillContentArea,
+ drawEdges);
+ return false;
+}
+
+} // namespace WebCore
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderThemeChromiumWin.h b/src/3rdparty/webkit/WebCore/rendering/RenderThemeChromiumWin.h
new file mode 100644
index 0000000..5e98c9b
--- /dev/null
+++ b/src/3rdparty/webkit/WebCore/rendering/RenderThemeChromiumWin.h
@@ -0,0 +1,106 @@
+/*
+ * This file is part of the WebKit project.
+ *
+ * Copyright (C) 2006 Apple Computer, Inc.
+ * Copyright (C) 2008, 2009 Google, Inc.
+ *
+ * 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 RenderThemeChromiumWin_h
+#define RenderThemeChromiumWin_h
+
+#include "RenderThemeChromiumSkia.h"
+
+#if WIN32
+typedef void* HANDLE;
+typedef struct HINSTANCE__* HINSTANCE;
+typedef HINSTANCE HMODULE;
+#endif
+
+namespace WebCore {
+
+ struct ThemeData {
+ ThemeData() : m_part(0), m_state(0), m_classicState(0) {}
+
+ unsigned m_part;
+ unsigned m_state;
+ unsigned m_classicState;
+ };
+
+ class RenderThemeChromiumWin : public RenderThemeChromiumSkia {
+ public:
+ static PassRefPtr<RenderTheme> create();
+
+ // A method asking if the theme is able to draw the focus ring.
+ virtual bool supportsFocusRing(const RenderStyle*) const;
+
+ // The platform selection color.
+ virtual Color platformActiveSelectionBackgroundColor() const;
+ virtual Color platformInactiveSelectionBackgroundColor() const;
+ virtual Color platformActiveSelectionForegroundColor() const;
+ virtual Color platformInactiveSelectionForegroundColor() const;
+ virtual Color platformActiveTextSearchHighlightColor() const;
+ virtual Color platformInactiveTextSearchHighlightColor() const;
+
+ // System fonts.
+ virtual void systemFont(int propId, FontDescription&) const;
+
+ virtual void adjustSliderThumbSize(RenderObject*) const;
+
+ // Various paint functions.
+ virtual bool paintCheckbox(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+ virtual bool paintRadio(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+ virtual bool paintButton(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+ virtual bool paintTextField(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+ virtual bool paintSliderTrack(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+ virtual bool paintSliderThumb(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+
+ // MenuList refers to an unstyled menulist (meaning a menulist without
+ // background-color or border set) and MenuListButton refers to a styled
+ // menulist (a menulist with background-color or border set). They have
+ // this distinction to support showing aqua style themes whenever they
+ // possibly can, which is something we don't want to replicate.
+ //
+ // In short, we either go down the MenuList code path or the MenuListButton
+ // codepath. We never go down both. And in both cases, they render the
+ // entire menulist.
+ virtual bool paintMenuList(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+
+ // Override RenderThemeChromiumSkia's setDefaultFontSize method to also reset the local font property caches.
+ // See comment in RenderThemeChromiumSkia::setDefaultFontSize() regarding ugliness of this hack.
+ static void setDefaultFontSize(int);
+
+ protected:
+ virtual double caretBlinkIntervalInternal() const;
+
+ private:
+ RenderThemeChromiumWin() { }
+ virtual ~RenderThemeChromiumWin() { }
+
+ unsigned determineState(RenderObject*);
+ unsigned determineSliderThumbState(RenderObject*);
+ unsigned determineClassicState(RenderObject*);
+
+ ThemeData getThemeData(RenderObject*);
+
+ bool paintTextFieldInternal(RenderObject*, const RenderObject::PaintInfo&, const IntRect&, bool);
+ };
+
+} // namespace WebCore
+
+#endif
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderThemeMac.h b/src/3rdparty/webkit/WebCore/rendering/RenderThemeMac.h
index a1da7ff..ba32105 100644
--- a/src/3rdparty/webkit/WebCore/rendering/RenderThemeMac.h
+++ b/src/3rdparty/webkit/WebCore/rendering/RenderThemeMac.h
@@ -39,8 +39,7 @@ class RenderStyle;
class RenderThemeMac : public RenderTheme {
public:
- RenderThemeMac();
- virtual ~RenderThemeMac();
+ static PassRefPtr<RenderTheme> create();
// A method asking if the control changes its tint when the window has focus or not.
virtual bool controlSupportsTints(const RenderObject*) const;
@@ -55,7 +54,13 @@ public:
virtual Color platformActiveSelectionBackgroundColor() const;
virtual Color platformInactiveSelectionBackgroundColor() const;
- virtual Color activeListBoxSelectionBackgroundColor() const;
+ virtual Color platformActiveListBoxSelectionBackgroundColor() const;
+ virtual Color platformActiveListBoxSelectionForegroundColor() const;
+ virtual Color platformInactiveListBoxSelectionBackgroundColor() const;
+ virtual Color platformInactiveListBoxSelectionForegroundColor() const;
+ virtual Color focusRingColor() const;
+
+ virtual ScrollbarControlSize scrollbarControlSizeForPart(ControlPart) { return SmallScrollbar; }
virtual void platformColorsDidChange();
@@ -76,6 +81,8 @@ public:
virtual Color systemColor(int cssValueId) const;
protected:
+ virtual bool supportsSelectionForegroundColors() const { return false; }
+
virtual bool paintTextField(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
virtual void adjustTextFieldStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
@@ -109,6 +116,7 @@ protected:
virtual void adjustSearchFieldResultsButtonStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
virtual bool paintSearchFieldResultsButton(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+#if ENABLE(VIDEO)
virtual bool paintMediaFullscreenButton(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
virtual bool paintMediaPlayButton(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
virtual bool paintMediaMuteButton(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
@@ -116,8 +124,19 @@ protected:
virtual bool paintMediaSeekForwardButton(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
virtual bool paintMediaSliderTrack(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
virtual bool paintMediaSliderThumb(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+ virtual bool paintMediaTimelineContainer(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+ virtual bool paintMediaCurrentTime(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+ virtual bool paintMediaTimeRemaining(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+
+ // Media controls
+ virtual bool hitTestMediaControlPart(RenderObject*, const IntPoint& absPoint);
+ virtual String extraMediaControlsStyleSheet();
+#endif
private:
+ RenderThemeMac();
+ virtual ~RenderThemeMac();
+
IntRect inflateRect(const IntRect&, const IntSize&, const int* margins, float zoomLevel = 1.0f) const;
FloatRect convertToPaintingRect(const RenderObject* inputRenderer, const RenderObject* partRenderer, const FloatRect& inputRect, const IntRect& r) const;
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderThemeSafari.cpp b/src/3rdparty/webkit/WebCore/rendering/RenderThemeSafari.cpp
index 31315bc..914f7ee 100644
--- a/src/3rdparty/webkit/WebCore/rendering/RenderThemeSafari.cpp
+++ b/src/3rdparty/webkit/WebCore/rendering/RenderThemeSafari.cpp
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2007, 2008 Apple Inc.
+ * Copyright (C) 2009 Kenneth Rohde Christiansen
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -34,6 +35,7 @@
#include "HTMLInputElement.h"
#include "HTMLMediaElement.h"
#include "HTMLNames.h"
+#include "RenderMediaControls.h"
#include "RenderSlider.h"
#include "RenderView.h"
#include "RetainPtr.h"
@@ -64,13 +66,22 @@ enum {
leftPadding
};
-RenderTheme* theme()
+PassRefPtr<RenderTheme> RenderThemeSafari::create()
{
- static RenderThemeSafari safariTheme;
- static RenderThemeWin windowsTheme;
+ return adoptRef(new RenderThemeSafari);
+}
+
+PassRefPtr<RenderTheme> RenderTheme::themeForPage(Page* page)
+{
+ static RenderTheme* safariTheme = RenderThemeSafari::create().releaseRef();
+ static RenderTheme* windowsTheme = RenderThemeWin::create().releaseRef();
+
+ // FIXME: This is called before Settings has been initialized by WebKit, so will return a
+ // potentially wrong answer the very first time it's called (see
+ // <https://bugs.webkit.org/show_bug.cgi?id=26493>).
if (Settings::shouldPaintNativeControls())
- return &windowsTheme;
- return &safariTheme;
+ return windowsTheme; // keep the reference of one.
+ return safariTheme; // keep the reference of one.
}
#if !defined(NDEBUG) && defined(USE_DEBUG_SAFARI_THEME)
@@ -83,6 +94,17 @@ SOFT_LINK(SafariTheme, paintThemePart, void, __stdcall, (ThemePart part, CGConte
#if defined(SAFARI_THEME_VERSION) && SAFARI_THEME_VERSION >= 2
SOFT_LINK(SafariTheme, STPaintProgressIndicator, void, APIENTRY, (ProgressIndicatorType type, CGContextRef context, const CGRect& rect, NSControlSize size, ThemeControlState state, float value), (type, context, rect, size, state, value))
#endif
+SOFT_LINK_OPTIONAL(SafariTheme, STCopyThemeColor, CGColorRef, APIENTRY, (unsigned color, SafariTheme::ThemeControlState));
+
+static const unsigned stFocusRingColorID = 4;
+
+static const unsigned aquaFocusRingColor = 0xFF7DADD9;
+
+static RGBA32 makeRGBAFromCGColor(CGColorRef color)
+{
+ const CGFloat* components = CGColorGetComponents(color);
+ return makeRGBA(255 * components[0], 255 * components[1], 255 * components[2], 255 * components[3]);
+}
ThemeControlState RenderThemeSafari::determineState(RenderObject* o) const
{
@@ -138,6 +160,22 @@ Color RenderThemeSafari::activeListBoxSelectionBackgroundColor() const
return Color(56, 117, 215);
}
+Color RenderThemeSafari::focusRingColor() const
+{
+ static Color focusRingColor;
+
+ if (!focusRingColor.isValid()) {
+ if (STCopyThemeColorPtr()) {
+ RetainPtr<CGColorRef> color(AdoptCF, STCopyThemeColorPtr()(stFocusRingColorID, SafariTheme::ActiveState));
+ focusRingColor = makeRGBAFromCGColor(color.get());
+ }
+ if (!focusRingColor.isValid())
+ focusRingColor = aquaFocusRingColor;
+ }
+
+ return focusRingColor;
+}
+
static float systemFontSizeForControlSize(NSControlSize controlSize)
{
static float sizes[] = { 13.0f, 11.0f, 9.0f };
@@ -272,8 +310,14 @@ IntRect RenderThemeSafari::inflateRect(const IntRect& r, const IntSize& size, co
int RenderThemeSafari::baselinePosition(const RenderObject* o) const
{
- if (o->style()->appearance() == CheckboxPart || o->style()->appearance() == RadioPart)
- return o->marginTop() + o->height() - 2; // The baseline is 2px up from the bottom of the checkbox/radio in AppKit.
+ if (!o->isBox())
+ return 0;
+
+ if (o->style()->appearance() == CheckboxPart || o->style()->appearance() == RadioPart) {
+ const RenderBox* box = toRenderBox(o);
+ return box->marginTop() + box->height() - 2; // The baseline is 2px up from the bottom of the checkbox/radio in AppKit.
+ }
+
return RenderTheme::baselinePosition(o);
}
@@ -828,7 +872,7 @@ void RenderThemeSafari::adjustMenuListStyle(CSSStyleSelector* selector, RenderSt
// Set the foreground color to black or gray when we have the aqua look.
// Cast to RGB32 is to work around a compiler bug.
- style->setColor(e->isEnabled() ? static_cast<RGBA32>(Color::black) : Color::darkGray);
+ style->setColor(e && e->isEnabledFormControl() ? static_cast<RGBA32>(Color::black) : Color::darkGray);
// Set the button's vertical size.
setButtonSize(style);
@@ -909,8 +953,7 @@ bool RenderThemeSafari::paintSliderTrack(RenderObject* o, const RenderObject::Pa
{
IntRect bounds = r;
- if (o->style()->appearance() == SliderHorizontalPart ||
- o->style()->appearance() == MediaSliderPart) {
+ if (o->style()->appearance() == SliderHorizontalPart) {
bounds.setHeight(trackWidth);
bounds.setY(r.y() + r.height() / 2 - trackWidth / 2);
} else if (o->style()->appearance() == SliderVerticalPart) {
@@ -967,19 +1010,17 @@ bool RenderThemeSafari::paintSliderThumb(RenderObject* o, const RenderObject::Pa
const int sliderThumbWidth = 15;
const int sliderThumbHeight = 15;
-const int mediaSliderThumbWidth = 13;
-const int mediaSliderThumbHeight = 14;
void RenderThemeSafari::adjustSliderThumbSize(RenderObject* o) const
{
if (o->style()->appearance() == SliderThumbHorizontalPart || o->style()->appearance() == SliderThumbVerticalPart) {
o->style()->setWidth(Length(sliderThumbWidth, Fixed));
o->style()->setHeight(Length(sliderThumbHeight, Fixed));
- } else if (o->style()->appearance() == MediaSliderThumbPart) {
- o->style()->setWidth(Length(mediaSliderThumbWidth, Fixed));
- o->style()->setHeight(Length(mediaSliderThumbHeight, Fixed));
- }
-
+ }
+#if ENABLE(VIDEO)
+ else if (o->style()->appearance() == MediaSliderThumbPart)
+ RenderMediaControls::adjustMediaSliderThumbSize(o);
+#endif
}
bool RenderThemeSafari::paintSearchField(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
@@ -1129,104 +1170,37 @@ bool RenderThemeSafari::paintSearchFieldResultsButton(RenderObject* o, const Ren
#if ENABLE(VIDEO)
bool RenderThemeSafari::paintMediaFullscreenButton(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
{
-#if defined(SAFARI_THEME_VERSION) && SAFARI_THEME_VERSION >= 2
- ASSERT(SafariThemeLibrary());
- paintThemePart(SafariTheme::MediaFullscreenButtonPart, paintInfo.context->platformContext(), r, NSRegularControlSize, determineState(o));
-#endif
-
- return false;
+ return RenderMediaControls::paintMediaControlsPart(MediaFullscreenButton, o, paintInfo, r);
}
bool RenderThemeSafari::paintMediaMuteButton(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
{
- Node* node = o->element();
- Node* mediaNode = node ? node->shadowAncestorNode() : 0;
- if (!mediaNode || (!mediaNode->hasTagName(videoTag) && !mediaNode->hasTagName(audioTag)))
- return false;
-
- HTMLMediaElement* mediaElement = static_cast<HTMLMediaElement*>(mediaNode);
- if (!mediaElement)
- return false;
-
-#if defined(SAFARI_THEME_VERSION) && SAFARI_THEME_VERSION >= 2
- ASSERT(SafariThemeLibrary());
- paintThemePart(mediaElement->muted() ? SafariTheme::MediaUnMuteButtonPart : SafariTheme::MediaMuteButtonPart, paintInfo.context->platformContext(), r, NSRegularControlSize, determineState(o));
-#endif
-
- return false;
+ return RenderMediaControls::paintMediaControlsPart(MediaMuteButton, o, paintInfo, r);
}
bool RenderThemeSafari::paintMediaPlayButton(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
{
- Node* node = o->element();
- Node* mediaNode = node ? node->shadowAncestorNode() : 0;
- if (!mediaNode || (!mediaNode->hasTagName(videoTag) && !mediaNode->hasTagName(audioTag)))
- return false;
-
- HTMLMediaElement* mediaElement = static_cast<HTMLMediaElement*>(mediaNode);
- if (!mediaElement)
- return false;
-
-#if defined(SAFARI_THEME_VERSION) && SAFARI_THEME_VERSION >= 2
- ASSERT(SafariThemeLibrary());
- paintThemePart(mediaElement->canPlay() ? SafariTheme::MediaPlayButtonPart : SafariTheme::MediaPauseButtonPart, paintInfo.context->platformContext(), r, NSRegularControlSize, determineState(o));
-#endif
-
- return false;
+ return RenderMediaControls::paintMediaControlsPart(MediaPlayButton, o, paintInfo, r);
}
bool RenderThemeSafari::paintMediaSeekBackButton(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
{
-#if defined(SAFARI_THEME_VERSION) && SAFARI_THEME_VERSION >= 2
- ASSERT(SafariThemeLibrary());
- paintThemePart(SafariTheme::MediaSeekBackButtonPart, paintInfo.context->platformContext(), r, NSRegularControlSize, determineState(o));
-#endif
-
- return false;
+ return RenderMediaControls::paintMediaControlsPart(MediaSeekBackButton, o, paintInfo, r);
}
bool RenderThemeSafari::paintMediaSeekForwardButton(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
{
-#if defined(SAFARI_THEME_VERSION) && SAFARI_THEME_VERSION >= 2
- ASSERT(SafariThemeLibrary());
- paintThemePart(SafariTheme::MediaSeekForwardButtonPart, paintInfo.context->platformContext(), r, NSRegularControlSize, determineState(o));
-#endif
-
- return false;
+ return RenderMediaControls::paintMediaControlsPart(MediaSeekForwardButton, o, paintInfo, r);
}
bool RenderThemeSafari::paintMediaSliderTrack(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
{
- Node* node = o->element();
- Node* mediaNode = node ? node->shadowAncestorNode() : 0;
- if (!mediaNode || (!mediaNode->hasTagName(videoTag) && !mediaNode->hasTagName(audioTag)))
- return false;
-
- HTMLMediaElement* mediaElement = static_cast<HTMLMediaElement*>(mediaNode);
- if (!mediaElement)
- return false;
-
- float percentLoaded = 0;
- if (MediaPlayer* player = mediaElement->player())
- if (player->duration())
- percentLoaded = player->maxTimeBuffered() / player->duration();
-
-#if defined(SAFARI_THEME_VERSION) && SAFARI_THEME_VERSION >= 2
- ASSERT(SafariThemeLibrary());
- STPaintProgressIndicator(SafariTheme::MediaType, paintInfo.context->platformContext(), r, NSRegularControlSize, 0, percentLoaded);
-#endif
- return false;
+ return RenderMediaControls::paintMediaControlsPart(MediaSlider, o, paintInfo, r);
}
bool RenderThemeSafari::paintMediaSliderThumb(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
{
- ASSERT(SafariThemeLibrary());
-
-#if defined(SAFARI_THEME_VERSION) && SAFARI_THEME_VERSION >= 2
- paintThemePart(SafariTheme::MediaSliderThumbPart, paintInfo.context->platformContext(), r, NSRegularControlSize, determineState(o));
-#endif
-
- return false;
+ return RenderMediaControls::paintMediaControlsPart(MediaSliderThumb, o, paintInfo, r);
}
#endif
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderThemeSafari.h b/src/3rdparty/webkit/WebCore/rendering/RenderThemeSafari.h
index 8ac5acf..4685238 100644
--- a/src/3rdparty/webkit/WebCore/rendering/RenderThemeSafari.h
+++ b/src/3rdparty/webkit/WebCore/rendering/RenderThemeSafari.h
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2007, 2008 Apple Inc.
+ * Copyright (C) 2009 Kenneth Rohde Christiansen
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -46,8 +47,7 @@ class RenderStyle;
class RenderThemeSafari : public RenderTheme {
public:
- RenderThemeSafari();
- virtual ~RenderThemeSafari();
+ static PassRefPtr<RenderTheme> create();
// A method to obtain the baseline position for a "leaf" control. This will only be used if a baseline
// position cannot be determined by examining child content. Checkboxes and radio buttons are examples of
@@ -69,6 +69,8 @@ public:
virtual Color platformInactiveSelectionBackgroundColor() const;
virtual Color activeListBoxSelectionBackgroundColor() const;
+ virtual Color focusRingColor() const;
+
// System fonts.
virtual void systemFont(int propId, FontDescription&) const;
@@ -137,6 +139,9 @@ protected:
#endif
private:
+ RenderThemeSafari();
+ virtual ~RenderThemeSafari();
+
IntRect inflateRect(const IntRect&, const IntSize&, const int* margins) const;
// Get the control size based off the font. Used by some of the controls (like buttons).
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderThemeWin.cpp b/src/3rdparty/webkit/WebCore/rendering/RenderThemeWin.cpp
index fd07b54..9491aae 100644
--- a/src/3rdparty/webkit/WebCore/rendering/RenderThemeWin.cpp
+++ b/src/3rdparty/webkit/WebCore/rendering/RenderThemeWin.cpp
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2006, 2007 Apple Inc.
+ * Copyright (C) 2009 Kenneth Rohde Christiansen
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -21,17 +22,20 @@
#include "config.h"
#include "RenderThemeWin.h"
-#include "CSSStyleSheet.h"
#include "CSSValueKeywords.h"
-#include "Document.h"
+#include "Element.h"
+#include "Frame.h"
#include "GraphicsContext.h"
-#include "HTMLElement.h"
-#include "HTMLSelectElement.h"
-#include "Icon.h"
#include "RenderSlider.h"
+#include "Settings.h"
#include "SoftLinking.h"
+#include "SystemInfo.h"
#include "UserAgentStyleSheets.h"
+#if ENABLE(VIDEO)
+#include "RenderMediaControls.h"
+#endif
+
#include <tchar.h>
/*
@@ -54,10 +58,14 @@
// Textfield constants
#define TFP_TEXTFIELD 1
+#define EP_EDITBORDER_NOSCROLL 6
#define TFS_READONLY 6
-// ComboBox constants (from tmschema.h)
+// ComboBox constants (from vsstyle.h)
#define CP_DROPDOWNBUTTON 1
+#define CP_BORDER 4
+#define CP_READONLY 5
+#define CP_DROPDOWNBUTTONRIGHT 6
// TrackBar (slider) parts
#define TKP_TRACK 1
@@ -83,14 +91,6 @@
#define PBS_DISABLED 4
#define PBS_DEFAULTED 5
-// This is the fixed width IE and Firefox use for buttons on dropdown menus
-static const int dropDownButtonWidth = 17;
-
-static const int shell32MagnifierIconIndex = 22;
-
-// Default font size to match Firefox.
-static const float defaultControlFontPixelSize = 13;
-
SOFT_LINK_LIBRARY(uxtheme)
SOFT_LINK(uxtheme, OpenThemeData, HANDLE, WINAPI, (HWND hwnd, LPCWSTR pszClassList), (hwnd, pszClassList))
SOFT_LINK(uxtheme, CloseThemeData, HRESULT, WINAPI, (HANDLE hTheme), (hTheme))
@@ -100,20 +100,51 @@ SOFT_LINK(uxtheme, IsThemeBackgroundPartiallyTransparent, BOOL, WINAPI, (HANDLE
static bool haveTheme;
+static const unsigned vistaMenuListButtonOutset = 1;
+
+using namespace std;
+
namespace WebCore {
+// This is the fixed width IE and Firefox use for buttons on dropdown menus
+static const int dropDownButtonWidth = 17;
+
+static const int shell32MagnifierIconIndex = 22;
+
+// Default font size to match Firefox.
+static const float defaultControlFontPixelSize = 13;
+
+static const float defaultCancelButtonSize = 9;
+static const float minCancelButtonSize = 5;
+static const float maxCancelButtonSize = 21;
+static const float defaultSearchFieldResultsDecorationSize = 13;
+static const float minSearchFieldResultsDecorationSize = 9;
+static const float maxSearchFieldResultsDecorationSize = 30;
+static const float defaultSearchFieldResultsButtonWidth = 18;
+
static bool gWebKitIsBeingUnloaded;
+static bool documentIsInApplicationChromeMode(const Document* document)
+{
+ Settings* settings = document->settings();
+ return settings && settings->inApplicationChromeMode();
+}
+
void RenderThemeWin::setWebKitIsBeingUnloaded()
{
gWebKitIsBeingUnloaded = true;
}
+PassRefPtr<RenderTheme> RenderThemeWin::create()
+{
+ return adoptRef(new RenderThemeWin);
+}
+
#if !USE(SAFARI_THEME)
-RenderTheme* theme()
+PassRefPtr<RenderTheme> RenderTheme::themeForPage(Page* page)
{
- static RenderThemeWin winTheme;
- return &winTheme;
+ static RenderTheme* winTheme = RenderThemeWin::create().releaseRef();
+ return winTheme;
}
#endif
@@ -202,24 +233,24 @@ bool RenderThemeWin::supportsHover(const RenderStyle*) const
Color RenderThemeWin::platformActiveSelectionBackgroundColor() const
{
COLORREF color = GetSysColor(COLOR_HIGHLIGHT);
- return Color(GetRValue(color), GetGValue(color), GetBValue(color), 255);
+ return Color(GetRValue(color), GetGValue(color), GetBValue(color));
}
Color RenderThemeWin::platformInactiveSelectionBackgroundColor() const
{
- COLORREF color = GetSysColor(COLOR_GRAYTEXT);
- return Color(GetRValue(color), GetGValue(color), GetBValue(color), 255);
+ // This color matches Firefox.
+ return Color(176, 176, 176);
}
Color RenderThemeWin::platformActiveSelectionForegroundColor() const
{
COLORREF color = GetSysColor(COLOR_HIGHLIGHTTEXT);
- return Color(GetRValue(color), GetGValue(color), GetBValue(color), 255);
+ return Color(GetRValue(color), GetGValue(color), GetBValue(color));
}
Color RenderThemeWin::platformInactiveSelectionForegroundColor() const
{
- return Color::white;
+ return platformActiveSelectionForegroundColor();
}
static void fillFontDescription(FontDescription& fontDescription, LOGFONT& logFont, float fontSize)
@@ -319,22 +350,23 @@ void RenderThemeWin::systemFont(int propId, FontDescription& fontDescription) co
}
}
-bool RenderThemeWin::supportsFocus(ControlPart appearance)
+bool RenderThemeWin::supportsFocus(ControlPart appearance) const
{
switch (appearance) {
case PushButtonPart:
case ButtonPart:
case DefaultButtonPart:
- case TextFieldPart:
- case TextAreaPart:
return true;
- case MenulistPart:
- return false;
default:
return false;
}
}
+bool RenderThemeWin::supportsFocusRing(const RenderStyle* style) const
+{
+ return supportsFocus(style->appearance());
+}
+
unsigned RenderThemeWin::determineClassicState(RenderObject* o)
{
unsigned state = 0;
@@ -376,7 +408,7 @@ unsigned RenderThemeWin::determineState(RenderObject* o)
ControlPart appearance = o->style()->appearance();
if (!isEnabled(o))
result = TS_DISABLED;
- else if (isReadOnlyControl(o) && (TextFieldPart == appearance || TextAreaPart == appearance))
+ else if (isReadOnlyControl(o) && (TextFieldPart == appearance || TextAreaPart == appearance || SearchFieldPart == appearance))
result = TFS_READONLY; // Readonly is supported on textfields.
else if (isPressed(o)) // Active overrides hover and focused.
result = TS_ACTIVE;
@@ -435,6 +467,7 @@ ThemeData RenderThemeWin::getClassicThemeData(RenderObject* o)
result.m_part = DFC_SCROLL;
result.m_state = determineClassicState(o);
break;
+ case SearchFieldPart:
case TextFieldPart:
case TextAreaPart:
result.m_part = TFP_TEXTFIELD;
@@ -481,16 +514,22 @@ ThemeData RenderThemeWin::getThemeData(RenderObject* o)
break;
case MenulistPart:
case MenulistButtonPart:
- result.m_part = CP_DROPDOWNBUTTON;
- result.m_state = determineState(o);
+ result.m_part = isRunningOnVistaOrLater() ? CP_DROPDOWNBUTTONRIGHT : CP_DROPDOWNBUTTON;
+ if (isRunningOnVistaOrLater() && documentIsInApplicationChromeMode(o->document())) {
+ // The "readonly" look we use in application chrome mode
+ // only uses a "normal" look for the drop down button.
+ result.m_state = TS_NORMAL;
+ } else
+ result.m_state = determineState(o);
break;
case RadioPart:
result.m_part = BP_RADIO;
result.m_state = determineState(o);
break;
+ case SearchFieldPart:
case TextFieldPart:
case TextAreaPart:
- result.m_part = TFP_TEXTFIELD;
+ result.m_part = isRunningOnVistaOrLater() ? EP_EDITBORDER_NOSCROLL : TFP_TEXTFIELD;
result.m_state = determineState(o);
break;
case SliderHorizontalPart:
@@ -602,8 +641,20 @@ bool RenderThemeWin::paintTextField(RenderObject* o, const RenderObject::PaintIn
bool RenderThemeWin::paintMenuList(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& r)
{
- // The outer box of a menu list is just a text field. Paint it first.
- drawControl(i.context, o, textFieldTheme(), ThemeData(TFP_TEXTFIELD, determineState(o)), r);
+ HANDLE theme;
+ int part;
+ if (haveTheme && isRunningOnVistaOrLater()) {
+ theme = menuListTheme();
+ if (documentIsInApplicationChromeMode(o->document()))
+ part = CP_READONLY;
+ else
+ part = CP_BORDER;
+ } else {
+ theme = textFieldTheme();
+ part = TFP_TEXTFIELD;
+ }
+
+ drawControl(i.context, o, theme, ThemeData(part, determineState(o)), r);
return paintMenuListButton(o, i, r);
}
@@ -656,6 +707,13 @@ bool RenderThemeWin::paintMenuListButton(RenderObject* o, const RenderObject::Pa
buttonRect.setX(buttonRect.right() - dropDownButtonWidth);
buttonRect.setWidth(dropDownButtonWidth);
+ if (isRunningOnVistaOrLater()) {
+ // Outset the top, right, and bottom borders of the button so that they coincide with the <select>'s border.
+ buttonRect.setY(buttonRect.y() - vistaMenuListButtonOutset);
+ buttonRect.setHeight(buttonRect.height() + 2 * vistaMenuListButtonOutset);
+ buttonRect.setWidth(buttonRect.width() + vistaMenuListButtonOutset);
+ }
+
drawControl(i.context, o, menuListTheme(), getThemeData(o), buttonRect);
return false;
@@ -697,15 +755,30 @@ void RenderThemeWin::adjustSliderThumbSize(RenderObject* o) const
o->style()->setWidth(Length(sliderThumbWidth, Fixed));
o->style()->setHeight(Length(sliderThumbHeight, Fixed));
}
+#if ENABLE(VIDEO)
+ else if (o->style()->appearance() == MediaSliderThumbPart)
+ RenderMediaControls::adjustMediaSliderThumbSize(o);
+#endif
}
-void RenderThemeWin::adjustButtonInnerStyle(RenderStyle* style) const
+int RenderThemeWin::buttonInternalPaddingLeft() const
{
- // This inner padding matches Firefox.
- style->setPaddingTop(Length(1, Fixed));
- style->setPaddingRight(Length(3, Fixed));
- style->setPaddingBottom(Length(1, Fixed));
- style->setPaddingLeft(Length(3, Fixed));
+ return 3;
+}
+
+int RenderThemeWin::buttonInternalPaddingRight() const
+{
+ return 3;
+}
+
+int RenderThemeWin::buttonInternalPaddingTop() const
+{
+ return 1;
+}
+
+int RenderThemeWin::buttonInternalPaddingBottom() const
+{
+ return 1;
}
bool RenderThemeWin::paintSearchField(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& r)
@@ -714,44 +787,49 @@ bool RenderThemeWin::paintSearchField(RenderObject* o, const RenderObject::Paint
}
void RenderThemeWin::adjustSearchFieldStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
-{
- // Override padding size to match AppKit text positioning.
+{
+ // Override paddingSize to match AppKit text positioning.
const int padding = 1;
style->setPaddingLeft(Length(padding, Fixed));
style->setPaddingRight(Length(padding, Fixed));
style->setPaddingTop(Length(padding, Fixed));
style->setPaddingBottom(Length(padding, Fixed));
+ if (e && e->focused() && e->document()->frame()->selection()->isFocusedAndActive())
+ style->setOutlineOffset(-2);
}
bool RenderThemeWin::paintSearchFieldCancelButton(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
{
- Color buttonColor = (o->element() && o->element()->active()) ? Color(138, 138, 138) : Color(186, 186, 186);
-
- IntSize cancelSize(10, 10);
- IntSize cancelRadius(cancelSize.width() / 2, cancelSize.height() / 2);
- int x = r.x() + (r.width() - cancelSize.width()) / 2;
- int y = r.y() + (r.height() - cancelSize.height()) / 2 + 1;
- IntRect cancelBounds(IntPoint(x, y), cancelSize);
- paintInfo.context->save();
- paintInfo.context->addRoundedRectClip(cancelBounds, cancelRadius, cancelRadius, cancelRadius, cancelRadius);
- paintInfo.context->fillRect(cancelBounds, buttonColor);
-
- // Draw the 'x'
- IntSize xSize(3, 3);
- IntRect xBounds(cancelBounds.location() + IntSize(3, 3), xSize);
- paintInfo.context->setStrokeColor(Color::white);
- paintInfo.context->drawLine(xBounds.location(), xBounds.location() + xBounds.size());
- paintInfo.context->drawLine(IntPoint(xBounds.right(), xBounds.y()), IntPoint(xBounds.x(), xBounds.bottom()));
-
- paintInfo.context->restore();
+ IntRect bounds = r;
+ ASSERT(o->parent());
+ if (!o->parent() || !o->parent()->isBox())
+ return false;
+
+ RenderBox* parentRenderBox = toRenderBox(o->parent());
+
+ IntRect parentBox = parentRenderBox->absoluteContentBox();
+
+ // Make sure the scaled button stays square and will fit in its parent's box
+ bounds.setHeight(min(parentBox.width(), min(parentBox.height(), bounds.height())));
+ bounds.setWidth(bounds.height());
+
+ // Center the button vertically. Round up though, so if it has to be one pixel off-center, it will
+ // be one pixel closer to the bottom of the field. This tends to look better with the text.
+ bounds.setY(parentBox.y() + (parentBox.height() - bounds.height() + 1) / 2);
+
+ static Image* cancelImage = Image::loadPlatformResource("searchCancel").releaseRef();
+ static Image* cancelPressedImage = Image::loadPlatformResource("searchCancelPressed").releaseRef();
+ paintInfo.context->drawImage(isPressed(o) ? cancelPressedImage : cancelImage, bounds);
return false;
}
void RenderThemeWin::adjustSearchFieldCancelButtonStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
{
- IntSize cancelSize(13, 11);
- style->setWidth(Length(cancelSize.width(), Fixed));
- style->setHeight(Length(cancelSize.height(), Fixed));
+ // Scale the button size based on the font size
+ float fontScale = style->fontSize() / defaultControlFontPixelSize;
+ int cancelButtonSize = lroundf(min(max(minCancelButtonSize, defaultCancelButtonSize * fontScale), maxCancelButtonSize));
+ style->setWidth(Length(cancelButtonSize, Fixed));
+ style->setHeight(Length(cancelButtonSize, Fixed));
}
void RenderThemeWin::adjustSearchFieldDecorationStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
@@ -760,46 +838,73 @@ void RenderThemeWin::adjustSearchFieldDecorationStyle(CSSStyleSelector* selector
style->setWidth(Length(emptySize.width(), Fixed));
style->setHeight(Length(emptySize.height(), Fixed));
}
-
+
void RenderThemeWin::adjustSearchFieldResultsDecorationStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
{
- IntSize magnifierSize(15, 11);
- style->setWidth(Length(magnifierSize.width(), Fixed));
- style->setHeight(Length(magnifierSize.height(), Fixed));
+ // Scale the decoration size based on the font size
+ float fontScale = style->fontSize() / defaultControlFontPixelSize;
+ int magnifierSize = lroundf(min(max(minSearchFieldResultsDecorationSize, defaultSearchFieldResultsDecorationSize * fontScale),
+ maxSearchFieldResultsDecorationSize));
+ style->setWidth(Length(magnifierSize, Fixed));
+ style->setHeight(Length(magnifierSize, Fixed));
}
bool RenderThemeWin::paintSearchFieldResultsDecoration(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
{
IntRect bounds = r;
+ ASSERT(o->parent());
+ if (!o->parent() || !o->parent()->isBox())
+ return false;
+
+ RenderBox* parentRenderBox = toRenderBox(o->parent());
+ IntRect parentBox = parentRenderBox->absoluteContentBox();
+
+ // Make sure the scaled decoration stays square and will fit in its parent's box
+ bounds.setHeight(min(parentBox.width(), min(parentBox.height(), bounds.height())));
bounds.setWidth(bounds.height());
- TCHAR buffer[MAX_PATH];
- UINT length = ::GetSystemDirectory(buffer, ARRAYSIZE(buffer));
- if (!length)
- return 0;
+ // Center the decoration vertically. Round up though, so if it has to be one pixel off-center, it will
+ // be one pixel closer to the bottom of the field. This tends to look better with the text.
+ bounds.setY(parentBox.y() + (parentBox.height() - bounds.height() + 1) / 2);
- if (_tcscat_s(buffer, TEXT("\\shell32.dll")))
- return 0;
-
- HICON hIcon;
- if (!::ExtractIconEx(buffer, shell32MagnifierIconIndex, 0, &hIcon, 1))
- return 0;
-
- RefPtr<Icon> icon = Icon::create(hIcon);
- icon->paint(paintInfo.context, bounds);
+ static Image* magnifierImage = Image::loadPlatformResource("searchMagnifier").releaseRef();
+ paintInfo.context->drawImage(magnifierImage, bounds);
return false;
}
void RenderThemeWin::adjustSearchFieldResultsButtonStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
{
- IntSize magnifierSize(15, 11);
- style->setWidth(Length(magnifierSize.width(), Fixed));
- style->setHeight(Length(magnifierSize.height(), Fixed));
+ // Scale the button size based on the font size
+ float fontScale = style->fontSize() / defaultControlFontPixelSize;
+ int magnifierHeight = lroundf(min(max(minSearchFieldResultsDecorationSize, defaultSearchFieldResultsDecorationSize * fontScale),
+ maxSearchFieldResultsDecorationSize));
+ int magnifierWidth = lroundf(magnifierHeight * defaultSearchFieldResultsButtonWidth / defaultSearchFieldResultsDecorationSize);
+ style->setWidth(Length(magnifierWidth, Fixed));
+ style->setHeight(Length(magnifierHeight, Fixed));
}
bool RenderThemeWin::paintSearchFieldResultsButton(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
{
- paintSearchFieldResultsDecoration(o, paintInfo, r);
+ IntRect bounds = r;
+ ASSERT(o->parent());
+ if (!o->parent())
+ return false;
+ if (!o->parent() || !o->parent()->isBox())
+ return false;
+
+ RenderBox* parentRenderBox = toRenderBox(o->parent());
+ IntRect parentBox = parentRenderBox->absoluteContentBox();
+
+ // Make sure the scaled decoration will fit in its parent's box
+ bounds.setHeight(min(parentBox.height(), bounds.height()));
+ bounds.setWidth(min(parentBox.width(), static_cast<int>(bounds.height() * defaultSearchFieldResultsButtonWidth / defaultSearchFieldResultsDecorationSize)));
+
+ // Center the button vertically. Round up though, so if it has to be one pixel off-center, it will
+ // be one pixel closer to the bottom of the field. This tends to look better with the text.
+ bounds.setY(parentBox.y() + (parentBox.height() - bounds.height() + 1) / 2);
+
+ static Image* magnifierImage = Image::loadPlatformResource("searchMagnifierResults").releaseRef();
+ paintInfo.context->drawImage(magnifierImage, bounds);
return false;
}
@@ -849,4 +954,41 @@ Color RenderThemeWin::systemColor(int cssValueId) const
return Color(GetRValue(color), GetGValue(color), GetBValue(color));
}
+#if ENABLE(VIDEO)
+bool RenderThemeWin::paintMediaFullscreenButton(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
+{
+ return RenderMediaControls::paintMediaControlsPart(MediaFullscreenButton, o, paintInfo, r);
+}
+
+bool RenderThemeWin::paintMediaMuteButton(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
+{
+ return RenderMediaControls::paintMediaControlsPart(MediaMuteButton, o, paintInfo, r);
+}
+
+bool RenderThemeWin::paintMediaPlayButton(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
+{
+ return RenderMediaControls::paintMediaControlsPart(MediaPlayButton, o, paintInfo, r);
+}
+
+bool RenderThemeWin::paintMediaSeekBackButton(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
+{
+ return RenderMediaControls::paintMediaControlsPart(MediaSeekBackButton, o, paintInfo, r);
+}
+
+bool RenderThemeWin::paintMediaSeekForwardButton(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
+{
+ return RenderMediaControls::paintMediaControlsPart(MediaSeekForwardButton, o, paintInfo, r);
+}
+
+bool RenderThemeWin::paintMediaSliderTrack(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
+{
+ return RenderMediaControls::paintMediaControlsPart(MediaSlider, o, paintInfo, r);
+}
+
+bool RenderThemeWin::paintMediaSliderThumb(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
+{
+ return RenderMediaControls::paintMediaControlsPart(MediaSliderThumb, o, paintInfo, r);
+}
+#endif
+
}
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderThemeWin.h b/src/3rdparty/webkit/WebCore/rendering/RenderThemeWin.h
index 8562b22..99c2004 100644
--- a/src/3rdparty/webkit/WebCore/rendering/RenderThemeWin.h
+++ b/src/3rdparty/webkit/WebCore/rendering/RenderThemeWin.h
@@ -2,6 +2,7 @@
* This file is part of the WebKit project.
*
* Copyright (C) 2006, 2008 Apple Computer, Inc.
+ * Copyright (C) 2009 Kenneth Rohde Christiansen
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -48,8 +49,7 @@ struct ThemeData {
class RenderThemeWin : public RenderTheme {
public:
- RenderThemeWin();
- ~RenderThemeWin();
+ static PassRefPtr<RenderTheme> create();
virtual String extraDefaultStyleSheet();
virtual String extraQuirksStyleSheet();
@@ -92,7 +92,12 @@ public:
virtual bool paintSliderThumb(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& r);
virtual void adjustSliderThumbSize(RenderObject*) const;
- virtual void adjustButtonInnerStyle(RenderStyle*) const;
+ virtual bool popupOptionSupportsTextIndent() const { return true; }
+
+ virtual int buttonInternalPaddingLeft() const;
+ virtual int buttonInternalPaddingRight() const;
+ virtual int buttonInternalPaddingTop() const;
+ virtual int buttonInternalPaddingBottom() const;
virtual void adjustSearchFieldStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
virtual bool paintSearchField(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
@@ -117,7 +122,22 @@ public:
static void setWebKitIsBeingUnloaded();
+ virtual bool supportsFocusRing(const RenderStyle*) const;
+
+#if ENABLE(VIDEO)
+ virtual bool paintMediaFullscreenButton(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+ virtual bool paintMediaPlayButton(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+ virtual bool paintMediaMuteButton(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+ virtual bool paintMediaSeekBackButton(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+ virtual bool paintMediaSeekForwardButton(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+ virtual bool paintMediaSliderTrack(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+ virtual bool paintMediaSliderThumb(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+#endif
+
private:
+ RenderThemeWin();
+ ~RenderThemeWin();
+
void addIntrinsicMargins(RenderStyle*) const;
void close();
@@ -126,7 +146,7 @@ private:
unsigned determineSliderThumbState(RenderObject*);
unsigned determineButtonState(RenderObject*);
- bool supportsFocus(ControlPart);
+ bool supportsFocus(ControlPart) const;
ThemeData getThemeData(RenderObject*);
ThemeData getClassicThemeData(RenderObject* o);
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderTreeAsText.cpp b/src/3rdparty/webkit/WebCore/rendering/RenderTreeAsText.cpp
index f46ff20..79d1724 100644
--- a/src/3rdparty/webkit/WebCore/rendering/RenderTreeAsText.cpp
+++ b/src/3rdparty/webkit/WebCore/rendering/RenderTreeAsText.cpp
@@ -26,6 +26,7 @@
#include "config.h"
#include "RenderTreeAsText.h"
+#include "CSSMutableStyleDeclaration.h"
#include "CharacterNames.h"
#include "Document.h"
#include "Frame.h"
@@ -34,6 +35,7 @@
#include "HTMLNames.h"
#include "InlineTextBox.h"
#include "RenderBR.h"
+#include "RenderInline.h"
#include "RenderListMarker.h"
#include "RenderTableCell.h"
#include "RenderView.h"
@@ -43,9 +45,11 @@
#include <wtf/Vector.h>
#if ENABLE(SVG)
-#include "RenderSVGRoot.h"
+#include "RenderPath.h"
#include "RenderSVGContainer.h"
+#include "RenderSVGImage.h"
#include "RenderSVGInlineText.h"
+#include "RenderSVGRoot.h"
#include "RenderSVGText.h"
#include "SVGRenderTreeAsText.h"
#endif
@@ -69,7 +73,7 @@ static void writeIndent(TextStream& ts, int indent)
ts << " ";
}
-static void printBorderStyle(TextStream& ts, const RenderObject& o, const EBorderStyle borderStyle)
+static void printBorderStyle(TextStream& ts, const EBorderStyle borderStyle)
{
switch (borderStyle) {
case BNONE:
@@ -169,18 +173,46 @@ static TextStream &operator<<(TextStream& ts, const RenderObject& o)
if (o.style() && o.style()->zIndex())
ts << " zI: " << o.style()->zIndex();
- if (o.element()) {
- String tagName = getTagName(o.element());
+ if (o.node()) {
+ String tagName = getTagName(o.node());
if (!tagName.isEmpty()) {
ts << " {" << tagName << "}";
// flag empty or unstyled AppleStyleSpan because we never
// want to leave them in the DOM
- if (isEmptyOrUnstyledAppleStyleSpan(o.element()))
+ if (isEmptyOrUnstyledAppleStyleSpan(o.node()))
ts << " *empty or unstyled AppleStyleSpan*";
}
}
- IntRect r(o.xPos(), o.yPos(), o.width(), o.height());
+ bool adjustForTableCells = o.containingBlock()->isTableCell();
+
+ IntRect r;
+ if (o.isText()) {
+ // FIXME: Would be better to dump the bounding box x and y rather than the first run's x and y, but that would involve updating
+ // many test results.
+ const RenderText& text = *toRenderText(&o);
+ IntRect linesBox = text.linesBoundingBox();
+ r = IntRect(text.firstRunX(), text.firstRunY(), linesBox.width(), linesBox.height());
+ if (adjustForTableCells && !text.firstTextBox())
+ adjustForTableCells = false;
+ } else if (o.isRenderInline()) {
+ // FIXME: Would be better not to just dump 0, 0 as the x and y here.
+ const RenderInline& inlineFlow = *toRenderInline(&o);
+ r = IntRect(0, 0, inlineFlow.linesBoundingBox().width(), inlineFlow.linesBoundingBox().height());
+ adjustForTableCells = false;
+ } else if (o.isTableCell()) {
+ // FIXME: Deliberately dump the "inner" box of table cells, since that is what current results reflect. We'd like
+ // to clean up the results to dump both the outer box and the intrinsic padding so that both bits of information are
+ // captured by the results.
+ const RenderTableCell& cell = static_cast<const RenderTableCell&>(o);
+ r = IntRect(cell.x(), cell.y() + cell.intrinsicPaddingTop(), cell.width(), cell.height() - cell.intrinsicPaddingTop() - cell.intrinsicPaddingBottom());
+ } else if (o.isBox())
+ r = toRenderBox(&o)->frameRect();
+
+ // FIXME: Temporary in order to ensure compatibility with existing layout test results.
+ if (adjustForTableCells)
+ r.move(0, -static_cast<RenderTableCell*>(o.containingBlock())->intrinsicPaddingTop());
+
ts << " " << r;
if (!(o.isText() && !o.isBR())) {
@@ -206,17 +238,21 @@ static TextStream &operator<<(TextStream& ts, const RenderObject& o)
o.style()->textStrokeWidth() > 0)
ts << " [textStrokeWidth=" << o.style()->textStrokeWidth() << "]";
- if (o.borderTop() || o.borderRight() || o.borderBottom() || o.borderLeft()) {
+ if (!o.isBoxModelObject())
+ return ts;
+
+ const RenderBoxModelObject& box = *toRenderBoxModelObject(&o);
+ if (box.borderTop() || box.borderRight() || box.borderBottom() || box.borderLeft()) {
ts << " [border:";
BorderValue prevBorder;
if (o.style()->borderTop() != prevBorder) {
prevBorder = o.style()->borderTop();
- if (!o.borderTop())
+ if (!box.borderTop())
ts << " none";
else {
- ts << " (" << o.borderTop() << "px ";
- printBorderStyle(ts, o, o.style()->borderTopStyle());
+ ts << " (" << box.borderTop() << "px ";
+ printBorderStyle(ts, o.style()->borderTopStyle());
Color col = o.style()->borderTopColor();
if (!col.isValid())
col = o.style()->color();
@@ -226,11 +262,11 @@ static TextStream &operator<<(TextStream& ts, const RenderObject& o)
if (o.style()->borderRight() != prevBorder) {
prevBorder = o.style()->borderRight();
- if (!o.borderRight())
+ if (!box.borderRight())
ts << " none";
else {
- ts << " (" << o.borderRight() << "px ";
- printBorderStyle(ts, o, o.style()->borderRightStyle());
+ ts << " (" << box.borderRight() << "px ";
+ printBorderStyle(ts, o.style()->borderRightStyle());
Color col = o.style()->borderRightColor();
if (!col.isValid())
col = o.style()->color();
@@ -239,12 +275,12 @@ static TextStream &operator<<(TextStream& ts, const RenderObject& o)
}
if (o.style()->borderBottom() != prevBorder) {
- prevBorder = o.style()->borderBottom();
- if (!o.borderBottom())
+ prevBorder = box.style()->borderBottom();
+ if (!box.borderBottom())
ts << " none";
else {
- ts << " (" << o.borderBottom() << "px ";
- printBorderStyle(ts, o, o.style()->borderBottomStyle());
+ ts << " (" << box.borderBottom() << "px ";
+ printBorderStyle(ts, o.style()->borderBottomStyle());
Color col = o.style()->borderBottomColor();
if (!col.isValid())
col = o.style()->color();
@@ -254,11 +290,11 @@ static TextStream &operator<<(TextStream& ts, const RenderObject& o)
if (o.style()->borderLeft() != prevBorder) {
prevBorder = o.style()->borderLeft();
- if (!o.borderLeft())
+ if (!box.borderLeft())
ts << " none";
else {
- ts << " (" << o.borderLeft() << "px ";
- printBorderStyle(ts, o, o.style()->borderLeftStyle());
+ ts << " (" << box.borderLeft() << "px ";
+ printBorderStyle(ts, o.style()->borderLeftStyle());
Color col = o.style()->borderLeftColor();
if (!col.isValid())
col = o.style()->color();
@@ -304,14 +340,18 @@ static TextStream &operator<<(TextStream& ts, const RenderObject& o)
static void writeTextRun(TextStream& ts, const RenderText& o, const InlineTextBox& run)
{
- ts << "text run at (" << run.m_x << "," << run.m_y << ") width " << run.m_width;
+ // FIXME: Table cell adjustment is temporary until results can be updated.
+ int y = run.m_y;
+ if (o.containingBlock()->isTableCell())
+ y -= static_cast<RenderTableCell*>(o.containingBlock())->intrinsicPaddingTop();
+ ts << "text run at (" << run.m_x << "," << y << ") width " << run.m_width;
if (run.direction() == RTL || run.m_dirOverride) {
ts << (run.direction() == RTL ? " RTL" : " LTR");
if (run.m_dirOverride)
ts << " override";
}
ts << ": "
- << quoteAndEscapeNonPrintables(String(o.text()).substring(run.m_start, run.m_len))
+ << quoteAndEscapeNonPrintables(String(o.text()).substring(run.start(), run.len()))
<< "\n";
}
@@ -337,6 +377,10 @@ void write(TextStream& ts, const RenderObject& o, int indent)
write(ts, static_cast<const RenderSVGInlineText&>(o), indent);
return;
}
+ if (o.isSVGImage()) {
+ write(ts, static_cast<const RenderSVGImage&>(o), indent);
+ return;
+ }
#endif
writeIndent(ts, indent);
@@ -344,7 +388,7 @@ void write(TextStream& ts, const RenderObject& o, int indent)
ts << o << "\n";
if (o.isText() && !o.isBR()) {
- const RenderText& text = static_cast<const RenderText&>(o);
+ const RenderText& text = *toRenderText(&o);
for (InlineTextBox* box = text.firstTextBox(); box; box = box->nextTextBox()) {
writeIndent(ts, indent + 1);
writeTextRun(ts, text, *box);
@@ -361,12 +405,12 @@ void write(TextStream& ts, const RenderObject& o, int indent)
Widget* widget = static_cast<const RenderWidget&>(o).widget();
if (widget && widget->isFrameView()) {
FrameView* view = static_cast<FrameView*>(widget);
- RenderObject* root = view->frame()->contentRenderer();
+ RenderView* root = view->frame()->contentRenderer();
if (root) {
view->layout();
RenderLayer* l = root->layer();
if (l)
- writeLayers(ts, l, l, IntRect(l->xPos(), l->yPos(), l->width(), l->height()), indent + 1);
+ writeLayers(ts, l, l, IntRect(l->x(), l->y(), l->width(), l->height()), indent + 1);
}
}
}
@@ -394,9 +438,9 @@ static void write(TextStream& ts, RenderLayer& l,
ts << " scrollX " << l.scrollXOffset();
if (l.scrollYOffset())
ts << " scrollY " << l.scrollYOffset();
- if (l.renderer()->clientWidth() != l.scrollWidth())
+ if (l.renderBox() && l.renderBox()->clientWidth() != l.scrollWidth())
ts << " scrollWidth " << l.scrollWidth();
- if (l.renderer()->clientHeight() != l.scrollHeight())
+ if (l.renderBox() && l.renderBox()->clientHeight() != l.scrollHeight())
ts << " scrollHeight " << l.scrollHeight();
}
@@ -420,7 +464,7 @@ static void writeLayers(TextStream& ts, const RenderLayer* rootLayer, RenderLaye
// Ensure our lists are up-to-date.
l->updateZOrderLists();
- l->updateOverflowList();
+ l->updateNormalFlowList();
bool shouldPaint = l->intersectsDamageRect(layerBounds, damageRect, rootLayer);
Vector<RenderLayer*>* negList = l->negZOrderList();
@@ -435,10 +479,10 @@ static void writeLayers(TextStream& ts, const RenderLayer* rootLayer, RenderLaye
if (shouldPaint)
write(ts, *l, layerBounds, damageRect, clipRectToApply, outlineRect, negList && negList->size() > 0, indent);
- Vector<RenderLayer*>* overflowList = l->overflowList();
- if (overflowList) {
- for (unsigned i = 0; i != overflowList->size(); ++i)
- writeLayers(ts, rootLayer, overflowList->at(i), paintDirtyRect, indent);
+ Vector<RenderLayer*>* normalFlowList = l->normalFlowList();
+ if (normalFlowList) {
+ for (unsigned i = 0; i != normalFlowList->size(); ++i)
+ writeLayers(ts, rootLayer, normalFlowList->at(i), paintDirtyRect, indent);
}
Vector<RenderLayer*>* posList = l->posZOrderList();
@@ -470,7 +514,7 @@ static String nodePosition(Node* node)
static void writeSelection(TextStream& ts, const RenderObject* o)
{
- Node* n = o->element();
+ Node* n = o->node();
if (!n || !n->isDocumentNode())
return;
@@ -479,15 +523,15 @@ static void writeSelection(TextStream& ts, const RenderObject* o)
if (!frame)
return;
- Selection selection = frame->selection()->selection();
+ VisibleSelection selection = frame->selection()->selection();
if (selection.isCaret()) {
- ts << "caret: position " << selection.start().offset() << " of " << nodePosition(selection.start().node());
+ ts << "caret: position " << selection.start().deprecatedEditingOffset() << " of " << nodePosition(selection.start().node());
if (selection.affinity() == UPSTREAM)
ts << " (upstream affinity)";
ts << "\n";
} else if (selection.isRange())
- ts << "selection start: position " << selection.start().offset() << " of " << nodePosition(selection.start().node()) << "\n"
- << "selection end: position " << selection.end().offset() << " of " << nodePosition(selection.end().node()) << "\n";
+ ts << "selection start: position " << selection.start().deprecatedEditingOffset() << " of " << nodePosition(selection.start().node()) << "\n"
+ << "selection end: position " << selection.end().deprecatedEditingOffset() << " of " << nodePosition(selection.end().node()) << "\n";
}
String externalRepresentation(RenderObject* o)
@@ -501,9 +545,9 @@ String externalRepresentation(RenderObject* o)
#endif
if (o->view()->frameView())
o->view()->frameView()->layout();
- RenderLayer* l = o->layer();
- if (l) {
- writeLayers(ts, l, l, IntRect(l->xPos(), l->yPos(), l->width(), l->height()));
+ if (o->hasLayer()) {
+ RenderLayer* l = toRenderBox(o)->layer();
+ writeLayers(ts, l, l, IntRect(l->x(), l->y(), l->width(), l->height()));
writeSelection(ts, o);
}
return ts.release();
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderVideo.cpp b/src/3rdparty/webkit/WebCore/rendering/RenderVideo.cpp
index 3d9cb3d..246d0c0 100644
--- a/src/3rdparty/webkit/WebCore/rendering/RenderVideo.cpp
+++ b/src/3rdparty/webkit/WebCore/rendering/RenderVideo.cpp
@@ -35,15 +35,35 @@
#include "HTMLVideoElement.h"
#include "MediaPlayer.h"
+#if USE(ACCELERATED_COMPOSITING)
+#include "RenderLayer.h"
+#include "RenderLayerBacking.h"
+#endif
+
using namespace std;
namespace WebCore {
using namespace HTMLNames;
+static const int cDefaultWidth = 300;
+static const int cDefaultHeight = 150;
+
RenderVideo::RenderVideo(HTMLMediaElement* video)
- : RenderMedia(video, video->player() ? video->player()->naturalSize() : IntSize(300, 150))
+ : RenderMedia(video)
{
+ if (video->player())
+ setIntrinsicSize(video->player()->naturalSize());
+ else {
+ // Video in standalone media documents should not use the default 300x150
+ // size since they also have audio thrown at them. By setting the intrinsic
+ // size to 300x1 the video will resize itself in these cases, and audio will
+ // have the correct height (it needs to be > 0 for controls to render properly).
+ if (video->ownerDocument() && video->ownerDocument()->isMediaDocument())
+ setIntrinsicSize(IntSize(cDefaultWidth, 1));
+ else
+ setIntrinsicSize(IntSize(cDefaultWidth, cDefaultHeight));
+ }
}
RenderVideo::~RenderVideo()
@@ -68,7 +88,7 @@ void RenderVideo::videoSizeChanged()
IntRect RenderVideo::videoBox() const
{
- IntRect contentRect = contentBox();
+ IntRect contentRect = contentBoxRect();
if (intrinsicSize().isEmpty() || contentRect.isEmpty())
return IntRect();
@@ -124,13 +144,14 @@ void RenderVideo::updatePlayer()
mediaPlayer->setVisible(false);
return;
}
+
+#if USE(ACCELERATED_COMPOSITING)
+ layer()->rendererContentChanged();
+#endif
- // FIXME: This doesn't work correctly with transforms.
- FloatPoint absPos = localToAbsolute();
IntRect videoBounds = videoBox();
- videoBounds.move(absPos.x(), absPos.y());
mediaPlayer->setFrameView(document()->view());
- mediaPlayer->setRect(videoBounds);
+ mediaPlayer->setSize(IntSize(videoBounds.width(), videoBounds.height()));
mediaPlayer->setVisible(true);
}
@@ -234,6 +255,32 @@ void RenderVideo::calcPrefWidths()
setPrefWidthsDirty(false);
}
+#if USE(ACCELERATED_COMPOSITING)
+bool RenderVideo::supportsAcceleratedRendering() const
+{
+ MediaPlayer* p = player();
+ if (p)
+ return p->supportsAcceleratedRendering();
+
+ return false;
+}
+
+void RenderVideo::acceleratedRenderingStateChanged()
+{
+ MediaPlayer* p = player();
+ if (p)
+ p->acceleratedRenderingStateChanged();
+}
+
+GraphicsLayer* RenderVideo::videoGraphicsLayer() const
+{
+ if (hasLayer() && layer()->isComposited())
+ return layer()->backing()->graphicsLayer();
+
+ return 0;
+}
+#endif // USE(ACCELERATED_COMPOSITING)
+
} // namespace WebCore
#endif
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderVideo.h b/src/3rdparty/webkit/WebCore/rendering/RenderVideo.h
index 43c1e7b..1c7b259 100644
--- a/src/3rdparty/webkit/WebCore/rendering/RenderVideo.h
+++ b/src/3rdparty/webkit/WebCore/rendering/RenderVideo.h
@@ -33,6 +33,9 @@
namespace WebCore {
class HTMLMediaElement;
+#if USE(ACCELERATED_COMPOSITING)
+class GraphicsLayer;
+#endif
class RenderVideo : public RenderMedia {
public:
@@ -41,6 +44,9 @@ public:
virtual const char* renderName() const { return "RenderVideo"; }
+ virtual bool requiresLayer() const { return true; }
+ virtual bool isVideo() const { return true; }
+
virtual void paintReplaced(PaintInfo& paintInfo, int tx, int ty);
virtual void layout();
@@ -51,9 +57,16 @@ public:
virtual void calcPrefWidths();
void videoSizeChanged();
+ IntRect videoBox() const;
void updateFromElement();
+#if USE(ACCELERATED_COMPOSITING)
+ bool supportsAcceleratedRendering() const;
+ virtual void acceleratedRenderingStateChanged();
+ GraphicsLayer* videoGraphicsLayer() const;
+#endif
+
protected:
virtual void intrinsicSizeChanged() { videoSizeChanged(); }
@@ -64,8 +77,6 @@ private:
bool isWidthSpecified() const;
bool isHeightSpecified() const;
- IntRect videoBox() const;
-
void updatePlayer();
};
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderView.cpp b/src/3rdparty/webkit/WebCore/rendering/RenderView.cpp
index 1715509..05d40bc 100644
--- a/src/3rdparty/webkit/WebCore/rendering/RenderView.cpp
+++ b/src/3rdparty/webkit/WebCore/rendering/RenderView.cpp
@@ -1,8 +1,6 @@
-/**
- * This file is part of the HTML widget for KDE.
- *
+/*
* Copyright (C) 1999 Lars Knoll (knoll@kde.org)
- * Copyright (C) 2004, 2005, 2006 Apple Computer, Inc.
+ * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. 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
@@ -25,10 +23,19 @@
#include "Document.h"
#include "Element.h"
+#include "FloatQuad.h"
#include "Frame.h"
#include "FrameView.h"
#include "GraphicsContext.h"
+#include "HitTestResult.h"
#include "RenderLayer.h"
+#include "RenderSelectionInfo.h"
+#include "RenderWidget.h"
+#include "TransformState.h"
+
+#if USE(ACCELERATED_COMPOSITING)
+#include "RenderLayerCompositor.h"
+#endif
namespace WebCore {
@@ -50,10 +57,7 @@ RenderView::RenderView(Node* node, FrameView* view)
// init RenderObject attributes
setInline(false);
-
- // try to contrain the width to the views width
- m_width = 0;
- m_height = 0;
+
m_minPrefWidth = 0;
m_maxPrefWidth = 0;
@@ -73,13 +77,13 @@ RenderView::~RenderView()
void RenderView::calcHeight()
{
if (!printing() && m_frameView)
- m_height = viewHeight();
+ setHeight(viewHeight());
}
void RenderView::calcWidth()
{
if (!printing() && m_frameView)
- m_width = viewWidth();
+ setWidth(viewWidth());
m_marginLeft = 0;
m_marginRight = 0;
}
@@ -96,10 +100,10 @@ void RenderView::calcPrefWidths()
void RenderView::layout()
{
if (printing())
- m_minPrefWidth = m_maxPrefWidth = m_width;
+ m_minPrefWidth = m_maxPrefWidth = width();
// Use calcWidth/Height to get the new width/height, since this will take the full page zoom factor into account.
- bool relayoutChildren = !printing() && (!m_frameView || m_width != viewWidth() || m_height != viewHeight());
+ bool relayoutChildren = !printing() && (!m_frameView || width() != viewWidth() || height() != viewHeight());
if (relayoutChildren) {
setChildNeedsLayout(true, false);
for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
@@ -117,10 +121,10 @@ void RenderView::layout()
if (needsLayout())
RenderBlock::layout();
- // Ensure that docWidth() >= width() and docHeight() >= height().
- setOverflowWidth(m_width);
- setOverflowHeight(m_height);
-
+ // Reset overflowWidth and overflowHeight, since they act as a lower bound for docWidth() and docHeight().
+ setOverflowWidth(width());
+ setOverflowHeight(height());
+
setOverflowWidth(docWidth());
setOverflowHeight(docHeight());
@@ -131,29 +135,20 @@ void RenderView::layout()
setNeedsLayout(false);
}
-FloatPoint RenderView::localToAbsolute(FloatPoint localPoint, bool fixed, bool) const
+void RenderView::mapLocalToContainer(RenderBoxModelObject* repaintContainer, bool fixed, bool /*useTransforms*/, TransformState& transformState) const
{
- if (fixed && m_frameView)
- localPoint += m_frameView->scrollOffset();
+ // If a container was specified, and was not 0 or the RenderView,
+ // then we should have found it by now.
+ ASSERT_UNUSED(repaintContainer, !repaintContainer || repaintContainer == this);
- return localPoint;
-}
-
-FloatPoint RenderView::absoluteToLocal(FloatPoint containerPoint, bool fixed, bool) const
-{
if (fixed && m_frameView)
- containerPoint -= m_frameView->scrollOffset();
-
- return containerPoint;
+ transformState.move(m_frameView->scrollOffset());
}
-FloatQuad RenderView::localToAbsoluteQuad(const FloatQuad& localQuad, bool fixed) const
+void RenderView::mapAbsoluteToLocalPoint(bool fixed, bool /*useTransforms*/, TransformState& transformState) const
{
- FloatQuad quad = localQuad;
if (fixed && m_frameView)
- quad += m_frameView->scrollOffset();
-
- return quad;
+ transformState.move(-m_frameView->scrollOffset());
}
void RenderView::paint(PaintInfo& paintInfo, int tx, int ty)
@@ -212,12 +207,20 @@ void RenderView::paintBoxDecorations(PaintInfo& paintInfo, int, int)
}
}
-void RenderView::repaintViewRectangle(const IntRect& ur, bool immediate)
+bool RenderView::shouldRepaint(const IntRect& r) const
{
- if (printing() || ur.width() == 0 || ur.height() == 0)
- return;
+ if (printing() || r.width() == 0 || r.height() == 0)
+ return false;
if (!m_frameView)
+ return false;
+
+ return true;
+}
+
+void RenderView::repaintViewRectangle(const IntRect& ur, bool immediate)
+{
+ if (!shouldRepaint(ur))
return;
// We always just invalidate the root view, since we could be an iframe that is clipped out
@@ -225,7 +228,7 @@ void RenderView::repaintViewRectangle(const IntRect& ur, bool immediate)
Element* elt = document()->ownerElement();
if (!elt)
m_frameView->repaintContentRectangle(ur, immediate);
- else if (RenderObject* obj = elt->renderer()) {
+ else if (RenderBox* obj = elt->renderBox()) {
IntRect vr = viewRect();
IntRect r = intersection(ur, vr);
@@ -240,8 +243,30 @@ void RenderView::repaintViewRectangle(const IntRect& ur, bool immediate)
}
}
-void RenderView::computeAbsoluteRepaintRect(IntRect& rect, bool fixed)
+void RenderView::repaintRectangleInViewAndCompositedLayers(const IntRect& ur, bool immediate)
{
+ if (!shouldRepaint(ur))
+ return;
+
+ repaintViewRectangle(ur, immediate);
+
+#if USE(ACCELERATED_COMPOSITING)
+ // If we're a frame, repaintViewRectangle will have repainted via a RenderObject in the
+ // parent document.
+ if (document()->ownerElement())
+ return;
+
+ if (compositor()->inCompositingMode())
+ compositor()->repaintCompositedLayersAbsoluteRect(ur);
+#endif
+}
+
+void RenderView::computeRectForRepaint(RenderBoxModelObject* repaintContainer, IntRect& rect, bool fixed)
+{
+ // If a container was specified, and was not 0 or the RenderView,
+ // then we should have found it by now.
+ ASSERT_UNUSED(repaintContainer, !repaintContainer || repaintContainer == this);
+
if (printing())
return;
@@ -253,17 +278,17 @@ void RenderView::computeAbsoluteRepaintRect(IntRect& rect, bool fixed)
rect = m_layer->transform()->mapRect(rect);
}
-void RenderView::absoluteRects(Vector<IntRect>& rects, int tx, int ty, bool)
+void RenderView::absoluteRects(Vector<IntRect>& rects, int tx, int ty)
{
rects.append(IntRect(tx, ty, m_layer->width(), m_layer->height()));
}
-void RenderView::absoluteQuads(Vector<FloatQuad>& quads, bool)
+void RenderView::absoluteQuads(Vector<FloatQuad>& quads)
{
quads.append(FloatRect(0, 0, m_layer->width(), m_layer->height()));
}
-RenderObject* rendererAfterPosition(RenderObject* object, unsigned offset)
+static RenderObject* rendererAfterPosition(RenderObject* object, unsigned offset)
{
if (!object)
return 0;
@@ -272,21 +297,11 @@ RenderObject* rendererAfterPosition(RenderObject* object, unsigned offset)
return child ? child : object->nextInPreOrderAfterChildren();
}
-IntRect RenderView::selectionRect(bool clipToVisibleContent)
-{
- // The virtual selectionRect() should never be called on the RenderView.
- // We assert because there used to be ambiguity between
- // RenderView::selectionRect(bool) and
- // virtual RenderObject::selectionRect(bool) const
- ASSERT_NOT_REACHED();
- return RenderBlock::selectionRect(clipToVisibleContent);
-}
-
IntRect RenderView::selectionBounds(bool clipToVisibleContent) const
{
- document()->updateRendering();
+ document()->updateStyleIfNeeded();
- typedef HashMap<RenderObject*, SelectionInfo*> SelectionMap;
+ typedef HashMap<RenderObject*, RenderSelectionInfo*> SelectionMap;
SelectionMap selectedObjects;
RenderObject* os = m_selectionStart;
@@ -294,13 +309,13 @@ IntRect RenderView::selectionBounds(bool clipToVisibleContent) const
while (os && os != stop) {
if ((os->canBeSelectionLeaf() || os == m_selectionStart || os == m_selectionEnd) && os->selectionState() != SelectionNone) {
// Blocks are responsible for painting line gaps and margin gaps. They must be examined as well.
- selectedObjects.set(os, new SelectionInfo(os, clipToVisibleContent));
+ selectedObjects.set(os, new RenderSelectionInfo(os, clipToVisibleContent));
RenderBlock* cb = os->containingBlock();
while (cb && !cb->isRenderView()) {
- SelectionInfo* blockInfo = selectedObjects.get(cb);
+ RenderSelectionInfo* blockInfo = selectedObjects.get(cb);
if (blockInfo)
break;
- selectedObjects.set(cb, new SelectionInfo(cb, clipToVisibleContent));
+ selectedObjects.set(cb, new RenderSelectionInfo(cb, clipToVisibleContent));
cb = cb->containingBlock();
}
}
@@ -312,14 +327,29 @@ IntRect RenderView::selectionBounds(bool clipToVisibleContent) const
IntRect selRect;
SelectionMap::iterator end = selectedObjects.end();
for (SelectionMap::iterator i = selectedObjects.begin(); i != end; ++i) {
- SelectionInfo* info = i->second;
+ RenderSelectionInfo* info = i->second;
selRect.unite(info->rect());
delete info;
}
return selRect;
}
-void RenderView::setSelection(RenderObject* start, int startPos, RenderObject* end, int endPos)
+#if USE(ACCELERATED_COMPOSITING)
+// Compositing layer dimensions take outline size into account, so we have to recompute layer
+// bounds when it changes.
+// FIXME: This is ugly; it would be nice to have a better way to do this.
+void RenderView::setMaximalOutlineSize(int o)
+{
+ if (o != m_maximalOutlineSize) {
+ m_maximalOutlineSize = o;
+
+ if (m_frameView)
+ m_frameView->updateCompositingLayers(FrameView::ForcedCompositingUpdate);
+ }
+}
+#endif
+
+void RenderView::setSelection(RenderObject* start, int startPos, RenderObject* end, int endPos, SelectionRepaintMode blockRepaintMode)
{
// Make sure both our start and end objects are defined.
// Check www.msnbc.com and try clicking around to find the case where this happened.
@@ -337,14 +367,14 @@ void RenderView::setSelection(RenderObject* start, int startPos, RenderObject* e
int oldEndPos = m_selectionEndPos;
// Objects each have a single selection rect to examine.
- typedef HashMap<RenderObject*, SelectionInfo*> SelectedObjectMap;
+ typedef HashMap<RenderObject*, RenderSelectionInfo*> SelectedObjectMap;
SelectedObjectMap oldSelectedObjects;
SelectedObjectMap newSelectedObjects;
// Blocks contain selected objects and fill gaps between them, either on the left, right, or in between lines and blocks.
// In order to get the repaint rect right, we have to examine left, middle, and right rects individually, since otherwise
// the union of those rects might remain the same even when changes have occurred.
- typedef HashMap<RenderBlock*, BlockSelectionInfo*> SelectedBlockMap;
+ typedef HashMap<RenderBlock*, RenderBlockSelectionInfo*> SelectedBlockMap;
SelectedBlockMap oldSelectedBlocks;
SelectedBlockMap newSelectedBlocks;
@@ -353,13 +383,13 @@ void RenderView::setSelection(RenderObject* start, int startPos, RenderObject* e
while (os && os != stop) {
if ((os->canBeSelectionLeaf() || os == m_selectionStart || os == m_selectionEnd) && os->selectionState() != SelectionNone) {
// Blocks are responsible for painting line gaps and margin gaps. They must be examined as well.
- oldSelectedObjects.set(os, new SelectionInfo(os, true));
+ oldSelectedObjects.set(os, new RenderSelectionInfo(os, true));
RenderBlock* cb = os->containingBlock();
while (cb && !cb->isRenderView()) {
- BlockSelectionInfo* blockInfo = oldSelectedBlocks.get(cb);
+ RenderBlockSelectionInfo* blockInfo = oldSelectedBlocks.get(cb);
if (blockInfo)
break;
- oldSelectedBlocks.set(cb, new BlockSelectionInfo(cb));
+ oldSelectedBlocks.set(cb, new RenderBlockSelectionInfo(cb));
cb = cb->containingBlock();
}
}
@@ -397,18 +427,22 @@ void RenderView::setSelection(RenderObject* start, int startPos, RenderObject* e
o = o->nextInPreOrder();
}
+ m_cachedSelectionBounds = IntRect();
+
// Now that the selection state has been updated for the new objects, walk them again and
// put them in the new objects list.
o = start;
while (o && o != stop) {
if ((o->canBeSelectionLeaf() || o == start || o == end) && o->selectionState() != SelectionNone) {
- newSelectedObjects.set(o, new SelectionInfo(o, true));
+ newSelectedObjects.set(o, new RenderSelectionInfo(o, true));
RenderBlock* cb = o->containingBlock();
while (cb && !cb->isRenderView()) {
- BlockSelectionInfo* blockInfo = newSelectedBlocks.get(cb);
+ RenderBlockSelectionInfo* blockInfo = newSelectedBlocks.get(cb);
if (blockInfo)
break;
- newSelectedBlocks.set(cb, new BlockSelectionInfo(cb));
+ blockInfo = new RenderBlockSelectionInfo(cb);
+ newSelectedBlocks.set(cb, blockInfo);
+ m_cachedSelectionBounds.unite(blockInfo->rects());
cb = cb->containingBlock();
}
}
@@ -429,14 +463,14 @@ void RenderView::setSelection(RenderObject* start, int startPos, RenderObject* e
// Have any of the old selected objects changed compared to the new selection?
for (SelectedObjectMap::iterator i = oldSelectedObjects.begin(); i != oldObjectsEnd; ++i) {
RenderObject* obj = i->first;
- SelectionInfo* newInfo = newSelectedObjects.get(obj);
- SelectionInfo* oldInfo = i->second;
+ RenderSelectionInfo* newInfo = newSelectedObjects.get(obj);
+ RenderSelectionInfo* oldInfo = i->second;
if (!newInfo || oldInfo->rect() != newInfo->rect() || oldInfo->state() != newInfo->state() ||
(m_selectionStart == obj && oldStartPos != m_selectionStartPos) ||
(m_selectionEnd == obj && oldEndPos != m_selectionEndPos)) {
- repaintViewRectangle(oldInfo->rect());
+ oldInfo->repaint();
if (newInfo) {
- repaintViewRectangle(newInfo->rect());
+ newInfo->repaint();
newSelectedObjects.remove(obj);
delete newInfo;
}
@@ -447,8 +481,8 @@ void RenderView::setSelection(RenderObject* start, int startPos, RenderObject* e
// Any new objects that remain were not found in the old objects dict, and so they need to be updated.
SelectedObjectMap::iterator newObjectsEnd = newSelectedObjects.end();
for (SelectedObjectMap::iterator i = newSelectedObjects.begin(); i != newObjectsEnd; ++i) {
- SelectionInfo* newInfo = i->second;
- repaintViewRectangle(newInfo->rect());
+ RenderSelectionInfo* newInfo = i->second;
+ newInfo->repaint();
delete newInfo;
}
@@ -456,12 +490,13 @@ void RenderView::setSelection(RenderObject* start, int startPos, RenderObject* e
SelectedBlockMap::iterator oldBlocksEnd = oldSelectedBlocks.end();
for (SelectedBlockMap::iterator i = oldSelectedBlocks.begin(); i != oldBlocksEnd; ++i) {
RenderBlock* block = i->first;
- BlockSelectionInfo* newInfo = newSelectedBlocks.get(block);
- BlockSelectionInfo* oldInfo = i->second;
+ RenderBlockSelectionInfo* newInfo = newSelectedBlocks.get(block);
+ RenderBlockSelectionInfo* oldInfo = i->second;
if (!newInfo || oldInfo->rects() != newInfo->rects() || oldInfo->state() != newInfo->state()) {
- repaintViewRectangle(oldInfo->rects());
+ if (blockRepaintMode == RepaintNewXOROld)
+ oldInfo->repaint();
if (newInfo) {
- repaintViewRectangle(newInfo->rects());
+ newInfo->repaint();
newSelectedBlocks.remove(block);
delete newInfo;
}
@@ -472,15 +507,16 @@ void RenderView::setSelection(RenderObject* start, int startPos, RenderObject* e
// Any new blocks that remain were not found in the old blocks dict, and so they need to be updated.
SelectedBlockMap::iterator newBlocksEnd = newSelectedBlocks.end();
for (SelectedBlockMap::iterator i = newSelectedBlocks.begin(); i != newBlocksEnd; ++i) {
- BlockSelectionInfo* newInfo = i->second;
- repaintViewRectangle(newInfo->rects());
+ RenderBlockSelectionInfo* newInfo = i->second;
+ newInfo->repaint();
delete newInfo;
}
}
void RenderView::clearSelection()
{
- setSelection(0, -1, 0, -1);
+ repaintViewRectangle(m_cachedSelectionBounds);
+ setSelection(0, -1, 0, -1, RepaintNewMinusOld);
}
void RenderView::selectionStartEnd(int& startPos, int& endPos) const
@@ -496,17 +532,17 @@ bool RenderView::printing() const
void RenderView::updateWidgetPositions()
{
- RenderObjectSet::iterator end = m_widgets.end();
- for (RenderObjectSet::iterator it = m_widgets.begin(); it != end; ++it)
+ RenderWidgetSet::iterator end = m_widgets.end();
+ for (RenderWidgetSet::iterator it = m_widgets.begin(); it != end; ++it)
(*it)->updateWidgetPosition();
}
-void RenderView::addWidget(RenderObject* o)
+void RenderView::addWidget(RenderWidget* o)
{
m_widgets.add(o);
}
-void RenderView::removeWidget(RenderObject* o)
+void RenderView::removeWidget(RenderWidget* o)
{
m_widgets.remove(o);
}
@@ -514,7 +550,7 @@ void RenderView::removeWidget(RenderObject* o)
IntRect RenderView::viewRect() const
{
if (printing())
- return IntRect(0, 0, m_width, m_height);
+ return IntRect(0, 0, width(), height());
if (m_frameView)
return m_frameView->visibleContentRect();
return IntRect();
@@ -522,16 +558,13 @@ IntRect RenderView::viewRect() const
int RenderView::docHeight() const
{
- int h = m_height;
- int lowestPos = lowestPosition();
- if (lowestPos > h)
- h = lowestPos;
+ int h = lowestPosition();
// FIXME: This doesn't do any margin collapsing.
// Instead of this dh computation we should keep the result
// when we call RenderBlock::layout.
int dh = 0;
- for (RenderObject* c = firstChild(); c; c = c->nextSibling())
+ for (RenderBox* c = firstChildBox(); c; c = c->nextSiblingBox())
dh += c->height() + c->marginTop() + c->marginBottom();
if (dh > h)
@@ -542,12 +575,9 @@ int RenderView::docHeight() const
int RenderView::docWidth() const
{
- int w = m_width;
- int rightmostPos = rightmostPosition();
- if (rightmostPos > w)
- w = rightmostPos;
+ int w = rightmostPosition();
- for (RenderObject *c = firstChild(); c; c = c->nextSibling()) {
+ for (RenderBox* c = firstChildBox(); c; c = c->nextSiblingBox()) {
int dw = c->width() + c->marginLeft() + c->marginRight();
if (dw > w)
w = dw;
@@ -576,9 +606,17 @@ int RenderView::viewWidth() const
return width;
}
+float RenderView::zoomFactor() const
+{
+ if (m_frameView->frame() && m_frameView->frame()->shouldApplyPageZoom())
+ return m_frameView->frame()->zoomFactor();
+
+ return 1.0f;
+}
+
// The idea here is to take into account what object is moving the pagination point, and
// thus choose the best place to chop it.
-void RenderView::setBestTruncatedAt(int y, RenderObject* forRenderer, bool forcedBreak)
+void RenderView::setBestTruncatedAt(int y, RenderBoxModelObject* forRenderer, bool forcedBreak)
{
// Nobody else can set a page break once we have a forced break.
if (m_forcedPageBreak)
@@ -591,21 +629,66 @@ void RenderView::setBestTruncatedAt(int y, RenderObject* forRenderer, bool force
return;
}
- // prefer the widest object who tries to move the pagination point
- int width = forRenderer->width();
- if (width > m_truncatorWidth) {
- m_truncatorWidth = width;
+ // Prefer the widest object that tries to move the pagination point
+ IntRect boundingBox = forRenderer->borderBoundingBox();
+ if (boundingBox.width() > m_truncatorWidth) {
+ m_truncatorWidth = boundingBox.width();
m_bestTruncatedAt = y;
}
}
void RenderView::pushLayoutState(RenderObject* root)
{
- ASSERT(!m_frameView->needsFullRepaint());
+ ASSERT(!doingFullRepaint());
ASSERT(m_layoutStateDisableCount == 0);
ASSERT(m_layoutState == 0);
m_layoutState = new (renderArena()) LayoutState(root);
}
+void RenderView::updateHitTestResult(HitTestResult& result, const IntPoint& point)
+{
+ if (result.innerNode())
+ return;
+
+ Node* node = document()->documentElement();
+ if (node) {
+ result.setInnerNode(node);
+ if (!result.innerNonSharedNode())
+ result.setInnerNonSharedNode(node);
+ result.setLocalPoint(point);
+ }
+}
+
+#if USE(ACCELERATED_COMPOSITING)
+bool RenderView::usesCompositing() const
+{
+ return m_compositor && m_compositor->inCompositingMode();
+}
+
+RenderLayerCompositor* RenderView::compositor()
+{
+ if (!m_compositor)
+ m_compositor.set(new RenderLayerCompositor(this));
+
+ return m_compositor.get();
+}
+#endif
+
+void RenderView::didMoveOnscreen()
+{
+#if USE(ACCELERATED_COMPOSITING)
+ if (m_compositor)
+ m_compositor->didMoveOnscreen();
+#endif
+}
+
+void RenderView::willMoveOffscreen()
+{
+#if USE(ACCELERATED_COMPOSITING)
+ if (m_compositor)
+ m_compositor->willMoveOffscreen();
+#endif
+}
+
} // namespace WebCore
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderView.h b/src/3rdparty/webkit/WebCore/rendering/RenderView.h
index 96597de..b0de7dd 100644
--- a/src/3rdparty/webkit/WebCore/rendering/RenderView.h
+++ b/src/3rdparty/webkit/WebCore/rendering/RenderView.h
@@ -25,12 +25,18 @@
#define RenderView_h
#include "FrameView.h"
-#include "Frame.h"
#include "LayoutState.h"
#include "RenderBlock.h"
+#include <wtf/OwnPtr.h>
namespace WebCore {
+class RenderWidget;
+
+#if USE(ACCELERATED_COMPOSITING)
+class RenderLayerCompositor;
+#endif
+
class RenderView : public RenderBlock {
public:
RenderView(Node*, FrameView*);
@@ -44,30 +50,26 @@ public:
virtual void calcWidth();
virtual void calcHeight();
virtual void calcPrefWidths();
- virtual FloatPoint localToAbsolute(FloatPoint localPoint = FloatPoint(), bool fixed = false, bool useTransforms = false) const;
- virtual FloatPoint absoluteToLocal(FloatPoint containerPoint, bool fixed = false, bool useTransforms = false) const;
- virtual FloatQuad localToAbsoluteQuad(const FloatQuad&, bool fixed = false) const;
-
- int docHeight() const;
- int docWidth() const;
// The same as the FrameView's layoutHeight/layoutWidth but with null check guards.
int viewHeight() const;
int viewWidth() const;
-
- float zoomFactor() const { return m_frameView->frame() && m_frameView->frame()->shouldApplyPageZoom() ? m_frameView->frame()->zoomFactor() : 1.0f; }
- FrameView* frameView() const { return m_frameView; }
+ float zoomFactor() const;
- virtual bool hasOverhangingFloats() { return false; }
+ FrameView* frameView() const { return m_frameView; }
- virtual void computeAbsoluteRepaintRect(IntRect&, bool fixed = false);
+ virtual void computeRectForRepaint(RenderBoxModelObject* repaintContainer, IntRect&, bool fixed = false);
virtual void repaintViewRectangle(const IntRect&, bool immediate = false);
+ // Repaint the view, and all composited layers that intersect the given absolute rectangle.
+ // FIXME: ideally we'd never have to do this, if all repaints are container-relative.
+ virtual void repaintRectangleInViewAndCompositedLayers(const IntRect&, bool immediate = false);
virtual void paint(PaintInfo&, int tx, int ty);
virtual void paintBoxDecorations(PaintInfo&, int tx, int ty);
- void setSelection(RenderObject* start, int startPos, RenderObject* end, int endPos);
+ enum SelectionRepaintMode { RepaintNewXOROld, RepaintNewMinusOld };
+ void setSelection(RenderObject* start, int startPos, RenderObject* end, int endPos, SelectionRepaintMode = RepaintNewXOROld);
void clearSelection();
virtual RenderObject* selectionStart() const { return m_selectionStart; }
virtual RenderObject* selectionEnd() const { return m_selectionEnd; }
@@ -76,39 +78,54 @@ public:
void setPrintImages(bool enable) { m_printImages = enable; }
bool printImages() const { return m_printImages; }
void setTruncatedAt(int y) { m_truncatedAt = y; m_bestTruncatedAt = m_truncatorWidth = 0; m_forcedPageBreak = false; }
- void setBestTruncatedAt(int y, RenderObject *forRenderer, bool forcedBreak = false);
+ void setBestTruncatedAt(int y, RenderBoxModelObject* forRenderer, bool forcedBreak = false);
int bestTruncatedAt() const { return m_bestTruncatedAt; }
int truncatedAt() const { return m_truncatedAt; }
- virtual void absoluteRects(Vector<IntRect>&, int tx, int ty, bool topLevel = true);
- virtual void absoluteQuads(Vector<FloatQuad>&, bool topLevel = true);
+ virtual void absoluteRects(Vector<IntRect>&, int tx, int ty);
+ virtual void absoluteQuads(Vector<FloatQuad>&);
IntRect selectionBounds(bool clipToVisibleContent = true) const;
+#if USE(ACCELERATED_COMPOSITING)
+ void setMaximalOutlineSize(int o);
+#else
void setMaximalOutlineSize(int o) { m_maximalOutlineSize = o; }
+#endif
int maximalOutlineSize() const { return m_maximalOutlineSize; }
virtual IntRect viewRect() const;
- virtual void selectionStartEnd(int& startPos, int& endPos) const;
+ void selectionStartEnd(int& startPos, int& endPos) const;
IntRect printRect() const { return m_printRect; }
void setPrintRect(const IntRect& r) { m_printRect = r; }
void updateWidgetPositions();
- void addWidget(RenderObject*);
- void removeWidget(RenderObject*);
+ void addWidget(RenderWidget*);
+ void removeWidget(RenderWidget*);
// layoutDelta is used transiently during layout to store how far an object has moved from its
- // last layout location, in order to repaint correctly
- const IntSize& layoutDelta() const { return m_layoutDelta; }
- void addLayoutDelta(const IntSize& delta) { m_layoutDelta += delta; }
+ // last layout location, in order to repaint correctly.
+ // If we're doing a full repaint m_layoutState will be 0, but in that case layoutDelta doesn't matter.
+ IntSize layoutDelta() const
+ {
+ return m_layoutState ? m_layoutState->m_layoutDelta : IntSize();
+ }
+ void addLayoutDelta(const IntSize& delta)
+ {
+ if (m_layoutState)
+ m_layoutState->m_layoutDelta += delta;
+ }
+
+ bool doingFullRepaint() const { return m_frameView->needsFullRepaint(); }
void pushLayoutState(RenderBox* renderer, const IntSize& offset)
{
- if (m_layoutStateDisableCount || m_frameView->needsFullRepaint())
+ if (doingFullRepaint())
return;
+ // We push LayoutState even if layoutState is disabled because it stores layoutDelta too.
m_layoutState = new (renderArena()) LayoutState(m_layoutState, renderer, offset);
}
@@ -116,24 +133,45 @@ public:
void popLayoutState()
{
- if (m_layoutStateDisableCount || m_frameView->needsFullRepaint())
+ if (doingFullRepaint())
return;
LayoutState* state = m_layoutState;
m_layoutState = state->m_next;
state->destroy(renderArena());
}
- LayoutState* layoutState() const { return m_layoutStateDisableCount ? 0 : m_layoutState; }
+ // Returns true if layoutState should be used for its cached offset and clip.
+ bool layoutStateEnabled() const { return m_layoutStateDisableCount == 0 && m_layoutState; }
+ LayoutState* layoutState() const { return m_layoutState; }
// Suspends the LayoutState optimization. Used under transforms that cannot be represented by
// LayoutState (common in SVG) and when manipulating the render tree during layout in ways
// that can trigger repaint of a non-child (e.g. when a list item moves its list marker around).
+ // Note that even when disabled, LayoutState is still used to store layoutDelta.
void disableLayoutState() { m_layoutStateDisableCount++; }
void enableLayoutState() { ASSERT(m_layoutStateDisableCount > 0); m_layoutStateDisableCount--; }
+ virtual void updateHitTestResult(HitTestResult&, const IntPoint&);
+
+ // Notifications that this view became visible in a window, or will be
+ // removed from the window.
+ void didMoveOnscreen();
+ void willMoveOffscreen();
+
+#if USE(ACCELERATED_COMPOSITING)
+ RenderLayerCompositor* compositor();
+ bool usesCompositing() const;
+#endif
+
+protected:
+ virtual void mapLocalToContainer(RenderBoxModelObject* repaintContainer, bool useTransforms, bool fixed, TransformState&) const;
+ virtual void mapAbsoluteToLocalPoint(bool fixed, bool useTransforms, TransformState&) const;
+
private:
- // selectionRect should never be called on a RenderView
- virtual IntRect selectionRect(bool);
+ bool shouldRepaint(const IntRect& r) const;
+
+ int docHeight() const;
+ int docWidth() const;
protected:
FrameView* m_frameView;
@@ -150,26 +188,46 @@ protected:
int m_maximalOutlineSize; // Used to apply a fudge factor to dirty-rect checks on blocks/tables.
IntRect m_printRect; // Used when printing.
- typedef HashSet<RenderObject*> RenderObjectSet;
+ typedef HashSet<RenderWidget*> RenderWidgetSet;
- RenderObjectSet m_widgets;
+ RenderWidgetSet m_widgets;
private:
+ IntRect m_cachedSelectionBounds;
+
int m_bestTruncatedAt;
int m_truncatorWidth;
bool m_forcedPageBreak;
- IntSize m_layoutDelta;
LayoutState* m_layoutState;
unsigned m_layoutStateDisableCount;
+#if USE(ACCELERATED_COMPOSITING)
+ OwnPtr<RenderLayerCompositor> m_compositor;
+#endif
};
+inline RenderView* toRenderView(RenderObject* o)
+{
+ ASSERT(!o || o->isRenderView());
+ return static_cast<RenderView*>(o);
+}
+
+inline const RenderView* toRenderView(const RenderObject* o)
+{
+ ASSERT(!o || o->isRenderView());
+ return static_cast<const RenderView*>(o);
+}
+
+// This will catch anyone doing an unnecessary cast.
+void toRenderView(const RenderView*);
+
+
// Stack-based class to assist with LayoutState push/pop
class LayoutStateMaintainer : Noncopyable {
public:
// ctor to push now
- LayoutStateMaintainer(RenderView* view, RenderBox* root, IntSize offset, bool shouldPush = true)
+ LayoutStateMaintainer(RenderView* view, RenderBox* root, IntSize offset, bool disableState = false)
: m_view(view)
- , m_shouldPushPop(shouldPush)
+ , m_disabled(disableState)
, m_didStart(false)
, m_didEnd(false)
{
@@ -179,7 +237,7 @@ public:
// ctor to maybe push later
LayoutStateMaintainer(RenderView* view)
: m_view(view)
- , m_shouldPushPop(true)
+ , m_disabled(false)
, m_didStart(false)
, m_didEnd(false)
{
@@ -190,33 +248,32 @@ public:
ASSERT(m_didStart == m_didEnd); // if this fires, it means that someone did a push(), but forgot to pop().
}
+ void push(RenderBox* root, IntSize offset)
+ {
+ ASSERT(!m_didStart);
+ // We push state even if disabled, because we still need to store layoutDelta
+ m_view->pushLayoutState(root, offset);
+ if (m_disabled)
+ m_view->disableLayoutState();
+ m_didStart = true;
+ }
+
void pop()
{
if (m_didStart) {
ASSERT(!m_didEnd);
- if (m_shouldPushPop)
- m_view->popLayoutState();
- else
+ m_view->popLayoutState();
+ if (m_disabled)
m_view->enableLayoutState();
m_didEnd = true;
}
}
- void push(RenderBox* root, IntSize offset)
- {
- ASSERT(!m_didStart);
- if (m_shouldPushPop)
- m_view->pushLayoutState(root, offset);
- else
- m_view->disableLayoutState();
- m_didStart = true;
- }
-
bool didPush() const { return m_didStart; }
private:
RenderView* m_view;
- bool m_shouldPushPop : 1; // true if we should push/pop, rather than disable/enable
+ bool m_disabled : 1; // true if the offset and clip part of layoutState is disabled
bool m_didStart : 1; // true if we did a push or disable
bool m_didEnd : 1; // true if we popped or re-enabled
};
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderWidget.cpp b/src/3rdparty/webkit/WebCore/rendering/RenderWidget.cpp
index 1a9744a..ec2ee6a 100644
--- a/src/3rdparty/webkit/WebCore/rendering/RenderWidget.cpp
+++ b/src/3rdparty/webkit/WebCore/rendering/RenderWidget.cpp
@@ -1,9 +1,7 @@
-/**
- * This file is part of the HTML widget for KDE.
- *
+/*
* Copyright (C) 1999 Lars Knoll (knoll@kde.org)
* Copyright (C) 2000 Dirk Mueller (mueller@kde.org)
- * Copyright (C) 2004, 2006 Apple Computer, Inc.
+ * Copyright (C) 2004, 2006, 2009 Apple Inc. 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
@@ -27,13 +25,8 @@
#include "AnimationController.h"
#include "AXObjectCache.h"
-#include "Document.h"
-#include "Element.h"
-#include "Event.h"
-#include "FrameView.h"
#include "GraphicsContext.h"
#include "HitTestResult.h"
-#include "RenderLayer.h"
#include "RenderView.h"
using namespace std;
@@ -47,14 +40,11 @@ static HashMap<const Widget*, RenderWidget*>& widgetRendererMap()
}
RenderWidget::RenderWidget(Node* node)
- : RenderReplaced(node)
- , m_widget(0)
- , m_refCount(0)
+ : RenderReplaced(node)
+ , m_widget(0)
+ , m_frameView(node->document()->view())
+ , m_refCount(0)
{
- // a replaced element doesn't support being anonymous
- ASSERT(node);
- m_view = node->document()->view();
-
view()->addWidget(this);
// Reference counting is used to prevent the widget from being
@@ -75,14 +65,15 @@ void RenderWidget::destroy()
if (RenderView* v = view())
v->removeWidget(this);
- if (AXObjectCache::accessibilityEnabled())
+ if (AXObjectCache::accessibilityEnabled()) {
+ document()->axObjectCache()->childrenChanged(this->parent());
document()->axObjectCache()->remove(this);
-
+ }
remove();
if (m_widget) {
- if (m_view)
- m_view->removeChild(m_widget);
+ if (m_frameView)
+ m_frameView->removeChild(m_widget);
widgetRendererMap().remove(m_widget);
}
@@ -90,33 +81,33 @@ void RenderWidget::destroy()
if (hasOverrideSize())
setOverrideSize(-1);
- RenderLayer* layer = m_layer;
- RenderArena* arena = renderArena();
-
- if (layer)
- layer->clearClipRects();
-
if (style() && (style()->height().isPercent() || style()->minHeight().isPercent() || style()->maxHeight().isPercent()))
RenderBlock::removePercentHeightDescendant(this);
+ if (hasLayer()) {
+ layer()->clearClipRects();
+ setHasLayer(false);
+ destroyLayer();
+ }
+
+ // Grab the arena from node()->document()->renderArena() before clearing the node pointer.
+ // Clear the node before deref-ing, as this may be deleted when deref is called.
+ RenderArena* arena = renderArena();
setNode(0);
deref(arena);
-
- if (layer)
- layer->destroy(arena);
}
RenderWidget::~RenderWidget()
{
ASSERT(m_refCount <= 0);
- deleteWidget();
+ clearWidget();
}
void RenderWidget::setWidgetGeometry(const IntRect& frame)
{
- if (element() && m_widget->frameRect() != frame) {
+ if (node() && m_widget->frameRect() != frame) {
RenderArena* arena = ref();
- RefPtr<Node> protectedElement(element());
+ RefPtr<Node> protectedElement(node());
m_widget->setFrameRect(frame);
deref(arena);
}
@@ -128,7 +119,7 @@ void RenderWidget::setWidget(Widget* widget)
if (m_widget) {
m_widget->removeFromParent();
widgetRendererMap().remove(m_widget);
- deleteWidget();
+ clearWidget();
}
m_widget = widget;
if (m_widget) {
@@ -144,7 +135,7 @@ void RenderWidget::setWidget(Widget* widget)
else
m_widget->show();
}
- m_view->addChild(m_widget);
+ m_frameView->addChild(m_widget);
}
}
}
@@ -156,7 +147,7 @@ void RenderWidget::layout()
setNeedsLayout(false);
}
-void RenderWidget::styleDidChange(RenderStyle::Diff diff, const RenderStyle* oldStyle)
+void RenderWidget::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
{
RenderReplaced::styleDidChange(diff, oldStyle);
if (m_widget) {
@@ -172,8 +163,8 @@ void RenderWidget::paint(PaintInfo& paintInfo, int tx, int ty)
if (!shouldPaint(paintInfo, tx, ty))
return;
- tx += m_x;
- ty += m_y;
+ tx += x();
+ ty += y();
if (hasBoxDecorations() && (paintInfo.phase == PaintPhaseForeground || paintInfo.phase == PaintPhaseSelection))
paintBoxDecorations(paintInfo, tx, ty);
@@ -183,14 +174,26 @@ void RenderWidget::paint(PaintInfo& paintInfo, int tx, int ty)
return;
}
- if (!m_view || paintInfo.phase != PaintPhaseForeground || style()->visibility() != VISIBLE)
+ if (!m_frameView || paintInfo.phase != PaintPhaseForeground || style()->visibility() != VISIBLE)
return;
#if PLATFORM(MAC)
if (style()->highlight() != nullAtom && !paintInfo.context->paintingDisabled())
- paintCustomHighlight(tx - m_x, ty - m_y, style()->highlight(), true);
+ paintCustomHighlight(tx - x(), ty - y(), style()->highlight(), true);
#endif
+ bool clipToBorderRadius = style()->overflowX() != OVISIBLE && style()->hasBorderRadius();
+ if (clipToBorderRadius) {
+ // Push a clip if we have a border radius, since we want to round the foreground content that gets painted.
+ paintInfo.context->save();
+
+ IntSize topLeft, topRight, bottomLeft, bottomRight;
+ IntRect borderRect = IntRect(tx, ty, width(), height());
+ style()->getBorderRadiiForRect(borderRect, topLeft, topRight, bottomLeft, bottomRight);
+
+ paintInfo.context->addRoundedRectClip(borderRect, topLeft, topRight, bottomLeft, bottomRight);
+ }
+
if (m_widget) {
// Move the widget if necessary. We normally move and resize widgets during layout, but sometimes
// widgets can move without layout occurring (most notably when you scroll a document that
@@ -200,11 +203,28 @@ void RenderWidget::paint(PaintInfo& paintInfo, int tx, int ty)
// Tell the widget to paint now. This is the only time the widget is allowed
// to paint itself. That way it will composite properly with z-indexed layers.
m_widget->paint(paintInfo.context, paintInfo.rect);
+
+ if (m_widget->isFrameView() && paintInfo.overlapTestRequests && !static_cast<FrameView*>(m_widget)->useSlowRepaints()) {
+ ASSERT(!paintInfo.overlapTestRequests->contains(this));
+ paintInfo.overlapTestRequests->set(this, m_widget->frameRect());
+ }
}
+ if (clipToBorderRadius)
+ paintInfo.context->restore();
+
// Paint a partially transparent wash over selected widgets.
- if (isSelected() && !document()->printing())
+ if (isSelected() && !document()->printing()) {
+ // FIXME: selectionRect() is in absolute, not painting coordinates.
paintInfo.context->fillRect(selectionRect(), selectionBackgroundColor());
+ }
+}
+
+void RenderWidget::setOverlapTestResult(bool isOverlapped)
+{
+ ASSERT(m_widget);
+ ASSERT(m_widget->isFrameView());
+ static_cast<FrameView*>(m_widget)->setIsOverlapped(isOverlapped);
}
void RenderWidget::deref(RenderArena *arena)
@@ -222,27 +242,27 @@ void RenderWidget::updateWidgetPosition()
FloatPoint absPos = localToAbsolute();
absPos.move(borderLeft() + paddingLeft(), borderTop() + paddingTop());
- int width = m_width - borderLeft() - borderRight() - paddingLeft() - paddingRight();
- int height = m_height - borderTop() - borderBottom() - paddingTop() - paddingBottom();
+ int w = width() - borderLeft() - borderRight() - paddingLeft() - paddingRight();
+ int h = height() - borderTop() - borderBottom() - paddingTop() - paddingBottom();
- IntRect newBounds(absPos.x(), absPos.y(), width, height);
+ IntRect newBounds(absPos.x(), absPos.y(), w, h);
IntRect oldBounds(m_widget->frameRect());
- if (newBounds != oldBounds) {
- // The widget changed positions. Update the frame geometry.
- if (checkForRepaintDuringLayout()) {
- RenderView* v = view();
- if (!v->printing()) {
- v->repaintViewRectangle(oldBounds);
- v->repaintViewRectangle(newBounds);
- }
- }
-
+ bool boundsChanged = newBounds != oldBounds;
+ if (boundsChanged) {
RenderArena* arena = ref();
- element()->ref();
+ node()->ref();
m_widget->setFrameRect(newBounds);
- element()->deref();
+ node()->deref();
deref(arena);
}
+
+ // if the frame bounds got changed, or if view needs layout (possibly indicating
+ // content size is wrong) we have to do a layout to set the right widget size
+ if (m_widget->isFrameView()) {
+ FrameView* frameView = static_cast<FrameView*>(m_widget);
+ if (boundsChanged || frameView->needsLayout())
+ frameView->layout();
+ }
}
void RenderWidget::setSelectionState(SelectionState state)
@@ -254,9 +274,17 @@ void RenderWidget::setSelectionState(SelectionState state)
}
}
-void RenderWidget::deleteWidget()
+void RenderWidget::clearWidget()
+{
+ Widget* widget = m_widget;
+ m_widget = 0;
+ if (widget)
+ deleteWidget(widget);
+}
+
+void RenderWidget::deleteWidget(Widget* widget)
{
- delete m_widget;
+ delete widget;
}
RenderWidget* RenderWidget::find(const Widget* widget)
@@ -270,8 +298,8 @@ bool RenderWidget::nodeAtPoint(const HitTestRequest& request, HitTestResult& res
bool inside = RenderReplaced::nodeAtPoint(request, result, x, y, tx, ty, action);
// Check to see if we are really over the widget itself (and not just in the border/padding area).
- if (inside && !hadResult && result.innerNode() == element())
- result.setIsOverWidget(contentBox().contains(result.localPoint()));
+ if (inside && !hadResult && result.innerNode() == node())
+ result.setIsOverWidget(contentBoxRect().contains(result.localPoint()));
return inside;
}
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderWidget.h b/src/3rdparty/webkit/WebCore/rendering/RenderWidget.h
index a64bb54..d23dbb3 100644
--- a/src/3rdparty/webkit/WebCore/rendering/RenderWidget.h
+++ b/src/3rdparty/webkit/WebCore/rendering/RenderWidget.h
@@ -1,8 +1,6 @@
/*
- * This file is part of the HTML widget for KDE.
- *
* Copyright (C) 1999 Lars Knoll (knoll@kde.org)
- * Copyright (C) 2004, 2005, 2006 Apple Computer, Inc.
+ * Copyright (C) 2004, 2005, 2006, 2009 Apple Inc. 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
@@ -24,51 +22,51 @@
#ifndef RenderWidget_h
#define RenderWidget_h
+#include "OverlapTestRequestClient.h"
#include "RenderReplaced.h"
namespace WebCore {
class Widget;
-class RenderWidget : public RenderReplaced {
+class RenderWidget : public RenderReplaced, private OverlapTestRequestClient {
public:
- RenderWidget(Node*);
virtual ~RenderWidget();
- virtual bool isWidget() const { return true; }
+ Widget* widget() const { return m_widget; }
+ virtual void setWidget(Widget*);
- virtual void paint(PaintInfo&, int tx, int ty);
+ static RenderWidget* find(const Widget*);
- virtual void destroy();
- virtual void layout();
+ void updateWidgetPosition();
- Widget* widget() const { return m_widget; }
- static RenderWidget* find(const Widget*);
+protected:
+ RenderWidget(Node*);
- RenderArena* ref() { ++m_refCount; return renderArena(); }
- void deref(RenderArena*);
+ FrameView* frameView() const { return m_frameView; }
- virtual void setSelectionState(SelectionState);
+ void clearWidget();
- virtual void updateWidgetPosition();
+ virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
+ virtual void layout();
- virtual void setWidget(Widget*);
+private:
+ virtual bool isWidget() const { return true; }
+ virtual void paint(PaintInfo&, int x, int y);
+ virtual void destroy();
+ virtual void setSelectionState(SelectionState);
virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, int x, int y, int tx, int ty, HitTestAction);
+ virtual void deleteWidget(Widget*);
+ virtual void setOverlapTestResult(bool);
-protected:
- virtual void styleDidChange(RenderStyle::Diff, const RenderStyle* oldStyle);
-
-private:
void setWidgetGeometry(const IntRect&);
- virtual void deleteWidget();
+ RenderArena* ref() { ++m_refCount; return renderArena(); }
+ void deref(RenderArena*);
-protected:
Widget* m_widget;
- FrameView* m_view;
-
-private:
+ FrameView* m_frameView;
int m_refCount;
};
diff --git a/src/3rdparty/webkit/WebCore/rendering/RootInlineBox.cpp b/src/3rdparty/webkit/WebCore/rendering/RootInlineBox.cpp
index bb88f24..ed125ee 100644
--- a/src/3rdparty/webkit/WebCore/rendering/RootInlineBox.cpp
+++ b/src/3rdparty/webkit/WebCore/rendering/RootInlineBox.cpp
@@ -74,10 +74,15 @@ void RootInlineBox::detachEllipsisBox(RenderArena* arena)
}
}
+RenderLineBoxList* RootInlineBox::rendererLineBoxes() const
+{
+ return block()->lineBoxes();
+}
+
void RootInlineBox::clearTruncation()
{
if (m_hasEllipsisBox) {
- detachEllipsisBox(m_object->renderArena());
+ detachEllipsisBox(renderer()->renderArena());
InlineFlowBox::clearTruncation();
}
}
@@ -94,13 +99,13 @@ bool RootInlineBox::canAccommodateEllipsis(bool ltr, int blockEdge, int lineBoxE
return InlineFlowBox::canAccommodateEllipsis(ltr, blockEdge, ellipsisWidth);
}
-void RootInlineBox::placeEllipsis(const AtomicString& ellipsisStr, bool ltr, int blockEdge, int ellipsisWidth,
+void RootInlineBox::placeEllipsis(const AtomicString& ellipsisStr, bool ltr, int blockLeftEdge, int blockRightEdge, int ellipsisWidth,
InlineBox* markupBox)
{
// Create an ellipsis box.
- EllipsisBox* ellipsisBox = new (m_object->renderArena()) EllipsisBox(m_object, ellipsisStr, this,
- ellipsisWidth - (markupBox ? markupBox->width() : 0),
- yPos(), height(), baseline(), !prevRootBox(),
+ EllipsisBox* ellipsisBox = new (renderer()->renderArena()) EllipsisBox(renderer(), ellipsisStr, this,
+ ellipsisWidth - (markupBox ? markupBox->width() : 0), height(),
+ y(), !prevRootBox(),
markupBox);
if (!gEllipsisBoxMap)
@@ -108,8 +113,9 @@ void RootInlineBox::placeEllipsis(const AtomicString& ellipsisStr, bool ltr, in
gEllipsisBoxMap->add(this, ellipsisBox);
m_hasEllipsisBox = true;
- if (ltr && (xPos() + width() + ellipsisWidth) <= blockEdge) {
- ellipsisBox->m_x = xPos() + width();
+ // FIXME: Do we need an RTL version of this?
+ if (ltr && (x() + width() + ellipsisWidth) <= blockRightEdge) {
+ ellipsisBox->m_x = x() + width();
return;
}
@@ -117,20 +123,20 @@ void RootInlineBox::placeEllipsis(const AtomicString& ellipsisStr, bool ltr, in
// of that glyph. Mark all of the objects that intersect the ellipsis box as not painting (as being
// truncated).
bool foundBox = false;
- ellipsisBox->m_x = placeEllipsisBox(ltr, blockEdge, ellipsisWidth, foundBox);
+ ellipsisBox->m_x = placeEllipsisBox(ltr, blockLeftEdge, blockRightEdge, ellipsisWidth, foundBox);
}
-int RootInlineBox::placeEllipsisBox(bool ltr, int blockEdge, int ellipsisWidth, bool& foundBox)
+int RootInlineBox::placeEllipsisBox(bool ltr, int blockLeftEdge, int blockRightEdge, int ellipsisWidth, bool& foundBox)
{
- int result = InlineFlowBox::placeEllipsisBox(ltr, blockEdge, ellipsisWidth, foundBox);
+ int result = InlineFlowBox::placeEllipsisBox(ltr, blockLeftEdge, blockRightEdge, ellipsisWidth, foundBox);
if (result == -1)
- result = ltr ? blockEdge - ellipsisWidth : blockEdge;
+ result = ltr ? blockRightEdge - ellipsisWidth : blockLeftEdge;
return result;
}
void RootInlineBox::paintEllipsisBox(RenderObject::PaintInfo& paintInfo, int tx, int ty) const
{
- if (m_hasEllipsisBox && object()->shouldPaintWithinRoot(paintInfo) && object()->style()->visibility() == VISIBLE &&
+ if (m_hasEllipsisBox && renderer()->shouldPaintWithinRoot(paintInfo) && renderer()->style()->visibility() == VISIBLE &&
paintInfo.phase == PaintPhaseForeground)
ellipsisBox()->paint(paintInfo, tx, ty);
}
@@ -139,7 +145,7 @@ void RootInlineBox::paintEllipsisBox(RenderObject::PaintInfo& paintInfo, int tx,
void RootInlineBox::addHighlightOverflow()
{
- Frame* frame = object()->document()->frame();
+ Frame* frame = renderer()->document()->frame();
if (!frame)
return;
Page* page = frame->page();
@@ -148,17 +154,17 @@ void RootInlineBox::addHighlightOverflow()
// Highlight acts as a selection inflation.
FloatRect rootRect(0, selectionTop(), width(), selectionHeight());
- IntRect inflatedRect = enclosingIntRect(page->chrome()->client()->customHighlightRect(object()->node(), object()->style()->highlight(), rootRect));
+ IntRect inflatedRect = enclosingIntRect(page->chrome()->client()->customHighlightRect(renderer()->node(), renderer()->style()->highlight(), rootRect));
setHorizontalOverflowPositions(min(leftOverflow(), inflatedRect.x()), max(rightOverflow(), inflatedRect.right()));
setVerticalOverflowPositions(min(topOverflow(), inflatedRect.y()), max(bottomOverflow(), inflatedRect.bottom()));
}
void RootInlineBox::paintCustomHighlight(RenderObject::PaintInfo& paintInfo, int tx, int ty, const AtomicString& highlightType)
{
- if (!object()->shouldPaintWithinRoot(paintInfo) || object()->style()->visibility() != VISIBLE || paintInfo.phase != PaintPhaseForeground)
+ if (!renderer()->shouldPaintWithinRoot(paintInfo) || renderer()->style()->visibility() != VISIBLE || paintInfo.phase != PaintPhaseForeground)
return;
- Frame* frame = object()->document()->frame();
+ Frame* frame = renderer()->document()->frame();
if (!frame)
return;
Page* page = frame->page();
@@ -166,10 +172,10 @@ void RootInlineBox::paintCustomHighlight(RenderObject::PaintInfo& paintInfo, int
return;
// Get the inflated rect so that we can properly hit test.
- FloatRect rootRect(tx + xPos(), ty + selectionTop(), width(), selectionHeight());
- FloatRect inflatedRect = page->chrome()->client()->customHighlightRect(object()->node(), highlightType, rootRect);
+ FloatRect rootRect(tx + x(), ty + selectionTop(), width(), selectionHeight());
+ FloatRect inflatedRect = page->chrome()->client()->customHighlightRect(renderer()->node(), highlightType, rootRect);
if (inflatedRect.intersects(paintInfo.rect))
- page->chrome()->client()->paintCustomHighlight(object()->node(), highlightType, rootRect, rootRect, false, true);
+ page->chrome()->client()->paintCustomHighlight(renderer()->node(), highlightType, rootRect, rootRect, false, true);
}
#endif
@@ -179,7 +185,7 @@ void RootInlineBox::paint(RenderObject::PaintInfo& paintInfo, int tx, int ty)
InlineFlowBox::paint(paintInfo, tx, ty);
paintEllipsisBox(paintInfo, tx, ty);
#if PLATFORM(MAC)
- RenderStyle* styleToUse = object()->style(m_firstLine);
+ RenderStyle* styleToUse = renderer()->style(m_firstLine);
if (styleToUse->highlight() != nullAtom && !paintInfo.context->paintingDisabled())
paintCustomHighlight(paintInfo, tx, ty, styleToUse->highlight());
#endif
@@ -189,7 +195,7 @@ bool RootInlineBox::nodeAtPoint(const HitTestRequest& request, HitTestResult& re
{
if (m_hasEllipsisBox && visibleToHitTesting()) {
if (ellipsisBox()->nodeAtPoint(request, result, x, y, tx, ty)) {
- object()->updateHitTestResult(result, IntPoint(x - tx, y - ty));
+ renderer()->updateHitTestResult(result, IntPoint(x - tx, y - ty));
return true;
}
}
@@ -210,10 +216,10 @@ void RootInlineBox::adjustPosition(int dx, int dy)
void RootInlineBox::childRemoved(InlineBox* box)
{
- if (box->object() == m_lineBreakObj)
+ if (box->renderer() == m_lineBreakObj)
setLineBreakInfo(0, 0, BidiStatus());
- for (RootInlineBox* prev = prevRootBox(); prev && prev->lineBreakObj() == box->object(); prev = prev->prevRootBox()) {
+ for (RootInlineBox* prev = prevRootBox(); prev && prev->lineBreakObj() == box->renderer(); prev = prev->prevRootBox()) {
prev->setLineBreakInfo(0, 0, BidiStatus());
prev->markDirty();
}
@@ -232,26 +238,36 @@ GapRects RootInlineBox::fillLineSelectionGap(int selTop, int selHeight, RenderBl
InlineBox* firstBox = firstSelectedBox();
InlineBox* lastBox = lastSelectedBox();
if (leftGap)
- result.uniteLeft(block()->fillLeftSelectionGap(firstBox->parent()->object(),
- firstBox->xPos(), selTop, selHeight,
+ result.uniteLeft(block()->fillLeftSelectionGap(firstBox->parent()->renderer(),
+ firstBox->x(), selTop, selHeight,
rootBlock, blockX, blockY, tx, ty, paintInfo));
if (rightGap)
- result.uniteRight(block()->fillRightSelectionGap(lastBox->parent()->object(),
- lastBox->xPos() + lastBox->width(), selTop, selHeight,
+ result.uniteRight(block()->fillRightSelectionGap(lastBox->parent()->renderer(),
+ lastBox->x() + lastBox->width(), selTop, selHeight,
rootBlock, blockX, blockY, tx, ty, paintInfo));
+ // When dealing with bidi text, a non-contiguous selection region is possible.
+ // e.g. The logical text aaaAAAbbb (capitals denote RTL text and non-capitals LTR) is layed out
+ // visually as 3 text runs |aaa|bbb|AAA| if we select 4 characters from the start of the text the
+ // selection will look like (underline denotes selection):
+ // |aaa|bbb|AAA|
+ // ___ _
+ // We can see that the |bbb| run is not part of the selection while the runs around it are.
if (firstBox && firstBox != lastBox) {
// Now fill in any gaps on the line that occurred between two selected elements.
- int lastX = firstBox->xPos() + firstBox->width();
+ int lastX = firstBox->x() + firstBox->width();
+ bool isPreviousBoxSelected = firstBox->selectionState() != RenderObject::SelectionNone;
for (InlineBox* box = firstBox->nextLeafChild(); box; box = box->nextLeafChild()) {
if (box->selectionState() != RenderObject::SelectionNone) {
- result.uniteCenter(block()->fillHorizontalSelectionGap(box->parent()->object(),
- lastX + tx, selTop + ty,
- box->xPos() - lastX, selHeight, paintInfo));
- lastX = box->xPos() + box->width();
+ if (isPreviousBoxSelected) // VisibleSelection may be non-contiguous, see comment above.
+ result.uniteCenter(block()->fillHorizontalSelectionGap(box->parent()->renderer(),
+ lastX + tx, selTop + ty,
+ box->x() - lastX, selHeight, paintInfo));
+ lastX = box->x() + box->width();
}
if (box == lastBox)
break;
+ isPreviousBoxSelected = box->selectionState() != RenderObject::SelectionNone;
}
}
@@ -316,10 +332,10 @@ int RootInlineBox::selectionTop()
// This line has actually been moved further down, probably from a large line-height, but possibly because the
// line was forced to clear floats. If so, let's check the offsets, and only be willing to use the previous
// line's bottom overflow if the offsets are greater on both sides.
- int prevLeft = block()->leftOffset(prevBottom);
- int prevRight = block()->rightOffset(prevBottom);
- int newLeft = block()->leftOffset(selectionTop);
- int newRight = block()->rightOffset(selectionTop);
+ int prevLeft = block()->leftOffset(prevBottom, !prevRootBox());
+ int prevRight = block()->rightOffset(prevBottom, !prevRootBox());
+ int newLeft = block()->leftOffset(selectionTop, !prevRootBox());
+ int newRight = block()->rightOffset(selectionTop, !prevRootBox());
if (prevLeft > newLeft || prevRight < newRight)
return selectionTop;
}
@@ -329,12 +345,12 @@ int RootInlineBox::selectionTop()
RenderBlock* RootInlineBox::block() const
{
- return static_cast<RenderBlock*>(m_object);
+ return toRenderBlock(renderer());
}
-bool isEditableLeaf(InlineBox* leaf)
+static bool isEditableLeaf(InlineBox* leaf)
{
- return leaf && leaf->object() && leaf->object()->element() && leaf->object()->element()->isContentEditable();
+ return leaf && leaf->renderer() && leaf->renderer()->node() && leaf->renderer()->node()->isContentEditable();
}
InlineBox* RootInlineBox::closestLeafChildForXPos(int x, bool onlyEditableLeaves)
@@ -345,19 +361,19 @@ InlineBox* RootInlineBox::closestLeafChildForXPos(int x, bool onlyEditableLeaves
return firstLeaf;
// Avoid returning a list marker when possible.
- if (x <= firstLeaf->m_x && !firstLeaf->object()->isListMarker() && (!onlyEditableLeaves || isEditableLeaf(firstLeaf)))
+ if (x <= firstLeaf->m_x && !firstLeaf->renderer()->isListMarker() && (!onlyEditableLeaves || isEditableLeaf(firstLeaf)))
// The x coordinate is less or equal to left edge of the firstLeaf.
// Return it.
return firstLeaf;
- if (x >= lastLeaf->m_x + lastLeaf->m_width && !lastLeaf->object()->isListMarker() && (!onlyEditableLeaves || isEditableLeaf(lastLeaf)))
+ if (x >= lastLeaf->m_x + lastLeaf->m_width && !lastLeaf->renderer()->isListMarker() && (!onlyEditableLeaves || isEditableLeaf(lastLeaf)))
// The x coordinate is greater or equal to right edge of the lastLeaf.
// Return it.
return lastLeaf;
InlineBox* closestLeaf = 0;
for (InlineBox* leaf = firstLeaf; leaf; leaf = leaf->nextLeafChild()) {
- if (!leaf->object()->isListMarker() && (!onlyEditableLeaves || isEditableLeaf(leaf))) {
+ if (!leaf->renderer()->isListMarker() && (!onlyEditableLeaves || isEditableLeaf(leaf))) {
closestLeaf = leaf;
if (x < leaf->m_x + leaf->m_width)
// The x coordinate is less than the right edge of the box.
@@ -394,12 +410,28 @@ EllipsisBox* RootInlineBox::ellipsisBox() const
void RootInlineBox::setVerticalOverflowPositions(int top, int bottom)
{
if (!m_overflow) {
- if (top == m_y && bottom == m_y + m_height)
+ const Font& font = renderer()->style(m_firstLine)->font();
+ if (top == m_y && bottom == m_y + font.height())
return;
- m_overflow = new (m_object->renderArena()) Overflow(this);
+ m_overflow = new (renderer()->renderArena()) Overflow(this);
}
m_overflow->m_topOverflow = top;
m_overflow->m_bottomOverflow = bottom;
}
+void RootInlineBox::removeLineBoxFromRenderObject()
+{
+ block()->lineBoxes()->removeLineBox(this);
+}
+
+void RootInlineBox::extractLineBoxFromRenderObject()
+{
+ block()->lineBoxes()->extractLineBox(this);
+}
+
+void RootInlineBox::attachLineBoxToRenderObject()
+{
+ block()->lineBoxes()->attachLineBox(this);
+}
+
} // namespace WebCore
diff --git a/src/3rdparty/webkit/WebCore/rendering/RootInlineBox.h b/src/3rdparty/webkit/WebCore/rendering/RootInlineBox.h
index 4724110..171be9d 100644
--- a/src/3rdparty/webkit/WebCore/rendering/RootInlineBox.h
+++ b/src/3rdparty/webkit/WebCore/rendering/RootInlineBox.h
@@ -28,9 +28,10 @@
namespace WebCore {
-class BidiStatus;
class EllipsisBox;
class HitTestResult;
+
+struct BidiStatus;
struct GapRects;
class RootInlineBox : public InlineFlowBox {
@@ -43,7 +44,7 @@ public:
{
}
- virtual bool isRootInlineBox() { return true; }
+ virtual bool isRootInlineBox() const { return true; }
virtual void destroy(RenderArena*);
void detachEllipsisBox(RenderArena*);
@@ -53,16 +54,18 @@ public:
virtual void adjustPosition(int dx, int dy);
- virtual int topOverflow() { return m_overflow ? m_overflow->m_topOverflow : m_y; }
- virtual int bottomOverflow() { return m_overflow ? m_overflow->m_bottomOverflow : m_y + m_height; }
- virtual int leftOverflow() { return m_overflow ? m_overflow->m_leftOverflow : m_x; }
- virtual int rightOverflow() { return m_overflow ? m_overflow->m_rightOverflow : m_x + m_width; }
+ virtual int topOverflow() const { return m_overflow ? m_overflow->m_topOverflow : m_y; }
+ virtual int bottomOverflow() const { return m_overflow ? m_overflow->m_bottomOverflow : m_y + m_renderer->style(m_firstLine)->font().height(); }
+ virtual int leftOverflow() const { return m_overflow ? m_overflow->m_leftOverflow : m_x; }
+ virtual int rightOverflow() const { return m_overflow ? m_overflow->m_rightOverflow : m_x + m_width; }
virtual void setVerticalOverflowPositions(int top, int bottom);
void setHorizontalOverflowPositions(int left, int right);
virtual void setVerticalSelectionPositions(int top, int bottom);
+ virtual RenderLineBoxList* rendererLineBoxes() const;
+
#if ENABLE(SVG)
virtual void computePerCharacterLayoutInformation() { }
#endif
@@ -83,8 +86,8 @@ public:
void childRemoved(InlineBox* box);
bool canAccommodateEllipsis(bool ltr, int blockEdge, int lineBoxEdge, int ellipsisWidth);
- void placeEllipsis(const AtomicString& ellipsisStr, bool ltr, int blockEdge, int ellipsisWidth, InlineBox* markupBox = 0);
- virtual int placeEllipsisBox(bool ltr, int blockEdge, int ellipsisWidth, bool& foundBox);
+ void placeEllipsis(const AtomicString& ellipsisStr, bool ltr, int blockLeftEdge, int blockRightEdge, int ellipsisWidth, InlineBox* markupBox = 0);
+ virtual int placeEllipsisBox(bool ltr, int blockLeftEdge, int blockRightEdge, int ellipsisWidth, bool& foundBox);
EllipsisBox* ellipsisBox() const;
@@ -114,20 +117,24 @@ public:
RenderBlock* block() const;
int selectionTop();
- int selectionBottom() { return m_overflow ? m_overflow->m_selectionBottom : m_y + m_height; }
+ int selectionBottom() { return m_overflow ? m_overflow->m_selectionBottom : m_y + height(); }
int selectionHeight() { return max(0, selectionBottom() - selectionTop()); }
InlineBox* closestLeafChildForXPos(int x, bool onlyEditableLeaves = false);
- Vector<RenderObject*>& floats()
+ Vector<RenderBox*>& floats()
{
ASSERT(!isDirty());
if (!m_overflow)
- m_overflow = new (m_object->renderArena()) Overflow(this);
+ m_overflow = new (m_renderer->renderArena()) Overflow(this);
return m_overflow->floats;
}
- Vector<RenderObject*>* floatsPtr() { ASSERT(!isDirty()); return m_overflow ? &m_overflow->floats : 0; }
+ Vector<RenderBox*>* floatsPtr() { ASSERT(!isDirty()); return m_overflow ? &m_overflow->floats : 0; }
+
+ virtual void extractLineBoxFromRenderObject();
+ virtual void attachLineBoxToRenderObject();
+ virtual void removeLineBoxFromRenderObject();
protected:
// Normally we are only as tall as the style on our block dictates, but we might have content
@@ -138,11 +145,11 @@ protected:
struct Overflow {
Overflow(RootInlineBox* box)
: m_topOverflow(box->m_y)
- , m_bottomOverflow(box->m_y + box->m_height)
+ , m_bottomOverflow(box->m_y + box->height())
, m_leftOverflow(box->m_x)
, m_rightOverflow(box->m_x + box->m_width)
, m_selectionTop(box->m_y)
- , m_selectionBottom(box->m_y + box->m_height)
+ , m_selectionBottom(box->m_y + box->height())
{
}
@@ -158,7 +165,7 @@ protected:
int m_selectionBottom;
// Floats hanging off the line are pushed into this vector during layout. It is only
// good for as long as the line has not been marked dirty.
- Vector<RenderObject*> floats;
+ Vector<RenderBox*> floats;
private:
void* operator new(size_t) throw();
};
@@ -184,7 +191,7 @@ inline void RootInlineBox::setHorizontalOverflowPositions(int left, int right)
if (!m_overflow) {
if (left == m_x && right == m_x + m_width)
return;
- m_overflow = new (m_object->renderArena()) Overflow(this);
+ m_overflow = new (m_renderer->renderArena()) Overflow(this);
}
m_overflow->m_leftOverflow = left;
m_overflow->m_rightOverflow = right;
@@ -193,9 +200,10 @@ inline void RootInlineBox::setHorizontalOverflowPositions(int left, int right)
inline void RootInlineBox::setVerticalSelectionPositions(int top, int bottom)
{
if (!m_overflow) {
- if (top == m_y && bottom == m_y + m_height)
+ const Font& font = m_renderer->style(m_firstLine)->font();
+ if (top == m_y && bottom == m_y + font.height())
return;
- m_overflow = new (m_object->renderArena()) Overflow(this);
+ m_overflow = new (m_renderer->renderArena()) Overflow(this);
}
m_overflow->m_selectionTop = top;
m_overflow->m_selectionBottom = bottom;
diff --git a/src/3rdparty/webkit/WebCore/rendering/SVGCharacterLayoutInfo.cpp b/src/3rdparty/webkit/WebCore/rendering/SVGCharacterLayoutInfo.cpp
index 89bab2d..8871a75 100644
--- a/src/3rdparty/webkit/WebCore/rendering/SVGCharacterLayoutInfo.cpp
+++ b/src/3rdparty/webkit/WebCore/rendering/SVGCharacterLayoutInfo.cpp
@@ -274,7 +274,7 @@ void SVGCharacterLayoutInfo::addLayoutInformation(InlineFlowBox* flowBox, float
angleStack.isEmpty() && baselineShiftStack.isEmpty() &&
curx == 0.0f && cury == 0.0f;
- RenderSVGTextPath* textPath = static_cast<RenderSVGTextPath*>(flowBox->object());
+ RenderSVGTextPath* textPath = static_cast<RenderSVGTextPath*>(flowBox->renderer());
Path path = textPath->layoutPath();
float baselineShift = calculateBaselineShift(textPath);
@@ -521,7 +521,7 @@ TransformationMatrix SVGChar::characterTransform() const
ctm.rotate(angle);
if (pathData) {
- ctm.scale(pathData->xScale, pathData->yScale);
+ ctm.scaleNonUniform(pathData->xScale, pathData->yScale);
ctm.translate(pathData->xShift, pathData->yShift);
ctm.rotate(pathData->orientationAngle);
}
diff --git a/src/3rdparty/webkit/WebCore/rendering/SVGInlineFlowBox.cpp b/src/3rdparty/webkit/WebCore/rendering/SVGInlineFlowBox.cpp
index 3ea1193..2649664 100644
--- a/src/3rdparty/webkit/WebCore/rendering/SVGInlineFlowBox.cpp
+++ b/src/3rdparty/webkit/WebCore/rendering/SVGInlineFlowBox.cpp
@@ -43,9 +43,10 @@ int SVGInlineFlowBox::placeBoxesHorizontally(int, int&, int&, bool&)
return 0;
}
-void SVGInlineFlowBox::verticallyAlignBoxes(int&)
+int SVGInlineFlowBox::verticallyAlignBoxes(int)
{
// no-op
+ return 0;
}
} // namespace WebCore
diff --git a/src/3rdparty/webkit/WebCore/rendering/SVGInlineFlowBox.h b/src/3rdparty/webkit/WebCore/rendering/SVGInlineFlowBox.h
index 96c5d4a..1aa2637 100644
--- a/src/3rdparty/webkit/WebCore/rendering/SVGInlineFlowBox.h
+++ b/src/3rdparty/webkit/WebCore/rendering/SVGInlineFlowBox.h
@@ -33,12 +33,19 @@ class SVGInlineFlowBox : public InlineFlowBox {
public:
SVGInlineFlowBox(RenderObject* obj)
: InlineFlowBox(obj)
+ , m_height(0)
{
}
+ virtual int svgBoxHeight() const { return m_height; }
+ void setHeight(int h) { m_height = h; }
+
virtual void paint(RenderObject::PaintInfo&, int tx, int ty);
virtual int placeBoxesHorizontally(int x, int& leftPosition, int& rightPosition, bool& needsWordSpacing);
- virtual void verticallyAlignBoxes(int& heightOfBlock);
+ virtual int verticallyAlignBoxes(int heightOfBlock);
+
+private:
+ int m_height;
};
} // namespace WebCore
diff --git a/src/3rdparty/webkit/WebCore/rendering/SVGInlineTextBox.cpp b/src/3rdparty/webkit/WebCore/rendering/SVGInlineTextBox.cpp
index 5f59700..d0fa9ae 100644
--- a/src/3rdparty/webkit/WebCore/rendering/SVGInlineTextBox.cpp
+++ b/src/3rdparty/webkit/WebCore/rendering/SVGInlineTextBox.cpp
@@ -38,12 +38,11 @@
#include <float.h>
-using std::max;
-
namespace WebCore {
SVGInlineTextBox::SVGInlineTextBox(RenderObject* obj)
: InlineTextBox(obj)
+ , m_height(0)
{
}
@@ -77,7 +76,7 @@ SVGRootInlineBox* SVGInlineTextBox::svgRootInlineBox() const
float SVGInlineTextBox::calculateGlyphWidth(RenderStyle* style, int offset, int extraCharsAvailable, int& charsConsumed, String& glyphName) const
{
ASSERT(style);
- return style->font().floatWidth(svgTextRunForInlineTextBox(textObject()->text()->characters() + offset, 1, style, this, 0), extraCharsAvailable, charsConsumed, glyphName);
+ return style->font().floatWidth(svgTextRunForInlineTextBox(textRenderer()->text()->characters() + offset, 1, style, this, 0), extraCharsAvailable, charsConsumed, glyphName);
}
float SVGInlineTextBox::calculateGlyphHeight(RenderStyle* style, int, int) const
@@ -125,14 +124,14 @@ struct SVGInlineTextBoxClosestCharacterToPositionWalker {
, m_distance(FLT_MAX)
, m_x(x)
, m_y(y)
- , m_offset(0)
+ , m_offsetOfHitCharacter(0)
{
}
void chunkPortionCallback(SVGInlineTextBox* textBox, int startOffset, const TransformationMatrix& chunkCtm,
const Vector<SVGChar>::iterator& start, const Vector<SVGChar>::iterator& end)
{
- RenderStyle* style = textBox->textObject()->style();
+ RenderStyle* style = textBox->textRenderer()->style();
Vector<SVGChar>::iterator closestCharacter = 0;
unsigned int closestOffset = UINT_MAX;
@@ -164,7 +163,7 @@ struct SVGInlineTextBoxClosestCharacterToPositionWalker {
if (closestOffset != UINT_MAX) {
// Record current chunk, if it contains the current closest character next to the mouse.
m_character = closestCharacter;
- m_offset = closestOffset;
+ m_offsetOfHitCharacter = closestOffset;
}
}
@@ -173,12 +172,12 @@ struct SVGInlineTextBoxClosestCharacterToPositionWalker {
return m_character;
}
- int offset() const
+ int offsetOfHitCharacter() const
{
if (!m_character)
return 0;
- return m_offset;
+ return m_offsetOfHitCharacter;
}
private:
@@ -187,7 +186,7 @@ private:
int m_x;
int m_y;
- int m_offset;
+ int m_offsetOfHitCharacter;
};
// Helper class for selectionRect()
@@ -199,7 +198,7 @@ struct SVGInlineTextBoxSelectionRectWalker {
void chunkPortionCallback(SVGInlineTextBox* textBox, int startOffset, const TransformationMatrix& chunkCtm,
const Vector<SVGChar>::iterator& start, const Vector<SVGChar>::iterator& end)
{
- RenderStyle* style = textBox->textObject()->style();
+ RenderStyle* style = textBox->textRenderer()->style();
for (Vector<SVGChar>::iterator it = start; it != end; ++it) {
if (it->isHidden())
@@ -221,7 +220,7 @@ private:
FloatRect m_selectionRect;
};
-SVGChar* SVGInlineTextBox::closestCharacterToPosition(int x, int y, int& offset) const
+SVGChar* SVGInlineTextBox::closestCharacterToPosition(int x, int y, int& offsetOfHitCharacter) const
{
SVGRootInlineBox* rootBox = svgRootInlineBox();
if (!rootBox)
@@ -232,25 +231,30 @@ SVGChar* SVGInlineTextBox::closestCharacterToPosition(int x, int y, int& offset)
rootBox->walkTextChunks(&walker, this);
- offset = walkerCallback.offset();
+ offsetOfHitCharacter = walkerCallback.offsetOfHitCharacter();
return walkerCallback.character();
}
-bool SVGInlineTextBox::svgCharacterHitsPosition(int x, int y, int& offset) const
+bool SVGInlineTextBox::svgCharacterHitsPosition(int x, int y, int& closestOffsetInBox) const
{
- SVGChar* charAtPosPtr = closestCharacterToPosition(x, y, offset);
+ int offsetOfHitCharacter = 0;
+ SVGChar* charAtPosPtr = closestCharacterToPosition(x, y, offsetOfHitCharacter);
if (!charAtPosPtr)
return false;
SVGChar& charAtPos = *charAtPosPtr;
- RenderStyle* style = textObject()->style(m_firstLine);
- FloatRect glyphRect = calculateGlyphBoundaries(style, offset, charAtPos);
+ RenderStyle* style = textRenderer()->style(m_firstLine);
+ FloatRect glyphRect = calculateGlyphBoundaries(style, offsetOfHitCharacter, charAtPos);
+ // FIXME: Why?
if (direction() == RTL)
- offset++;
+ offsetOfHitCharacter++;
+
+ // The caller actually the closest offset before/after the hit char
+ // closestCharacterToPosition returns us offsetOfHitCharacter.
+ closestOffsetInBox = offsetOfHitCharacter;
- // FIXME: todo list
- // (#13910) This code does not handle bottom-to-top/top-to-bottom vertical text.
+ // FIXME: (bug 13910) This code does not handle bottom-to-top/top-to-bottom vertical text.
// Check whether y position hits the current character
if (y < charAtPos.y - glyphRect.height() || y > charAtPos.y)
@@ -258,21 +262,21 @@ bool SVGInlineTextBox::svgCharacterHitsPosition(int x, int y, int& offset) const
// Check whether x position hits the current character
if (x < charAtPos.x) {
- if (offset > 0 && direction() == LTR)
+ if (closestOffsetInBox > 0 && direction() == LTR)
return true;
- else if (offset < (int) end() && direction() == RTL)
+ else if (closestOffsetInBox < (int) end() && direction() == RTL)
return true;
return false;
}
- // If we are past the last glyph of this box, don't mark it as 'hit' anymore.
- if (x >= charAtPos.x + glyphRect.width() && offset == (int) end())
- return false;
-
- // Snap to character at half of it's advance
+ // Adjust the closest offset to after the char if x was after the char midpoint
if (x >= charAtPos.x + glyphRect.width() / 2.0)
- offset += direction() == RTL ? -1 : 1;
+ closestOffsetInBox += direction() == RTL ? -1 : 1;
+
+ // If we are past the last glyph of this box, don't mark it as 'hit'
+ if (x >= charAtPos.x + glyphRect.width() && closestOffsetInBox == (int) end())
+ return false;
return true;
}
@@ -296,8 +300,8 @@ bool SVGInlineTextBox::nodeAtPoint(const HitTestRequest&, HitTestResult& result,
ASSERT(!isLineBreak());
IntRect rect = selectionRect(0, 0, 0, len());
- if (object()->style()->visibility() == VISIBLE && rect.contains(x, y)) {
- object()->updateHitTestResult(result, IntPoint(x - tx, y - ty));
+ if (renderer()->style()->visibility() == VISIBLE && rect.contains(x, y)) {
+ renderer()->updateHitTestResult(result, IntPoint(x - tx, y - ty));
return true;
}
@@ -324,12 +328,12 @@ IntRect SVGInlineTextBox::selectionRect(int, int, int startPos, int endPos)
void SVGInlineTextBox::paintCharacters(RenderObject::PaintInfo& paintInfo, int tx, int ty, const SVGChar& svgChar, const UChar* chars, int length, SVGPaintServer* activePaintServer)
{
- if (object()->style()->visibility() != VISIBLE || paintInfo.phase == PaintPhaseOutline)
+ if (renderer()->style()->visibility() != VISIBLE || paintInfo.phase == PaintPhaseOutline)
return;
ASSERT(paintInfo.phase != PaintPhaseSelfOutline && paintInfo.phase != PaintPhaseChildOutlines);
- RenderText* text = textObject();
+ RenderText* text = textRenderer();
ASSERT(text);
bool isPrinting = text->document()->printing();
@@ -346,9 +350,7 @@ void SVGInlineTextBox::paintCharacters(RenderObject::PaintInfo& paintInfo, int t
// Set our font
RenderStyle* styleToUse = text->style(isFirstLineStyle());
- const Font* font = &styleToUse->font();
- if (*font != paintInfo.context->font())
- paintInfo.context->setFont(*font);
+ const Font& font = styleToUse->font();
TransformationMatrix ctm = svgChar.characterTransform();
if (!ctm.isIdentity())
@@ -365,8 +367,8 @@ void SVGInlineTextBox::paintCharacters(RenderObject::PaintInfo& paintInfo, int t
if (containsComposition && !useCustomUnderlines)
paintCompositionBackground(paintInfo.context, tx, ty, styleToUse, font,
- text->document()->frame()->editor()->compositionStart(),
- text->document()->frame()->editor()->compositionEnd());
+ text->document()->frame()->editor()->compositionStart(),
+ text->document()->frame()->editor()->compositionEnd());
paintDocumentMarkers(paintInfo.context, tx, ty, styleToUse, font, true);
@@ -395,7 +397,7 @@ void SVGInlineTextBox::paintCharacters(RenderObject::PaintInfo& paintInfo, int t
run.setActivePaintServer(activePaintServer);
#endif
- paintInfo.context->drawText(run, origin);
+ paintInfo.context->drawText(font, run, origin);
if (paintInfo.phase != PaintPhaseSelection) {
paintDocumentMarkers(paintInfo.context, tx, ty, styleToUse, font, false);
@@ -434,7 +436,7 @@ void SVGInlineTextBox::paintCharacters(RenderObject::PaintInfo& paintInfo, int t
paintInfo.context->concatCTM(ctm.inverse());
}
-void SVGInlineTextBox::paintSelection(int boxStartOffset, const SVGChar& svgChar, const UChar*, int length, GraphicsContext* p, RenderStyle* style, const Font* f)
+void SVGInlineTextBox::paintSelection(int boxStartOffset, const SVGChar& svgChar, const UChar*, int length, GraphicsContext* p, RenderStyle* style, const Font& font)
{
if (selectionState() == RenderObject::SelectionNone)
return;
@@ -446,7 +448,7 @@ void SVGInlineTextBox::paintSelection(int boxStartOffset, const SVGChar& svgChar
return;
Color textColor = style->color();
- Color color = object()->selectionBackgroundColor();
+ Color color = renderer()->selectionBackgroundColor();
if (!color.isValid() || color.alpha() == 0)
return;
@@ -473,9 +475,9 @@ void SVGInlineTextBox::paintSelection(int boxStartOffset, const SVGChar& svgChar
p->save();
int adjust = startPos >= boxStartOffset ? boxStartOffset : 0;
- p->drawHighlightForText(svgTextRunForInlineTextBox(textObject()->text()->characters() + start() + boxStartOffset, length, style, this, svgChar.x),
- IntPoint((int) svgChar.x, (int) svgChar.y - f->ascent()),
- f->ascent() + f->descent(), color, startPos - adjust, endPos - adjust);
+ p->drawHighlightForText(font, svgTextRunForInlineTextBox(textRenderer()->text()->characters() + start() + boxStartOffset, length, style, this, svgChar.x),
+ IntPoint((int) svgChar.x, (int) svgChar.y - font.ascent()),
+ font.ascent() + font.descent(), color, startPos - adjust, endPos - adjust);
p->restore();
}
@@ -498,7 +500,7 @@ static inline Path pathForDecoration(ETextDecoration decoration, RenderObject* o
void SVGInlineTextBox::paintDecoration(ETextDecoration decoration, GraphicsContext* context, int tx, int ty, int width, const SVGChar& svgChar, const SVGTextDecorationInfo& info)
{
- if (object()->style()->visibility() != VISIBLE)
+ if (renderer()->style()->visibility() != VISIBLE)
return;
// This function does NOT accept combinated text decorations. It's meant to be invoked for just one.
@@ -510,10 +512,11 @@ void SVGInlineTextBox::paintDecoration(ETextDecoration decoration, GraphicsConte
if (!isFilled && !isStroked)
return;
+ int baseline = renderer()->style(m_firstLine)->font().ascent();
if (decoration == UNDERLINE)
- ty += m_baseline;
+ ty += baseline;
else if (decoration == LINE_THROUGH)
- ty += 2 * m_baseline / 3;
+ ty += 2 * baseline / 3;
context->save();
context->beginPath();
diff --git a/src/3rdparty/webkit/WebCore/rendering/SVGInlineTextBox.h b/src/3rdparty/webkit/WebCore/rendering/SVGInlineTextBox.h
index 1ddc23a..410218d 100644
--- a/src/3rdparty/webkit/WebCore/rendering/SVGInlineTextBox.h
+++ b/src/3rdparty/webkit/WebCore/rendering/SVGInlineTextBox.h
@@ -29,14 +29,18 @@
namespace WebCore {
- class SVGChar;
class SVGRootInlineBox;
- class SVGTextDecorationInfo;
+
+ struct SVGChar;
+ struct SVGTextDecorationInfo;
class SVGInlineTextBox : public InlineTextBox {
public:
SVGInlineTextBox(RenderObject* obj);
+ virtual int svgBoxHeight() const { return m_height; }
+ void setHeight(int h) { m_height = h; }
+
virtual int selectionTop();
virtual int selectionHeight();
@@ -50,7 +54,7 @@ namespace WebCore {
void paintCharacters(RenderObject::PaintInfo&, int tx, int ty, const SVGChar&, const UChar* chars, int length, SVGPaintServer*);
// SVGs custom paint selection method
- void paintSelection(int boxStartOffset, const SVGChar&, const UChar*, int length, GraphicsContext*, RenderStyle*, const Font*);
+ void paintSelection(int boxStartOffset, const SVGChar&, const UChar*, int length, GraphicsContext*, RenderStyle*, const Font&);
// SVGs custom paint decoration method
void paintDecoration(ETextDecoration, GraphicsContext*, int tx, int ty, int width, const SVGChar&, const SVGTextDecorationInfo&);
@@ -67,6 +71,8 @@ namespace WebCore {
private:
friend class RenderSVGInlineText;
bool svgCharacterHitsPosition(int x, int y, int& offset) const;
+
+ int m_height;
};
} // namespace WebCore
diff --git a/src/3rdparty/webkit/WebCore/rendering/SVGRenderSupport.cpp b/src/3rdparty/webkit/WebCore/rendering/SVGRenderSupport.cpp
index c88e8e8..f3f2b8c 100644
--- a/src/3rdparty/webkit/WebCore/rendering/SVGRenderSupport.cpp
+++ b/src/3rdparty/webkit/WebCore/rendering/SVGRenderSupport.cpp
@@ -2,6 +2,7 @@
* Copyright (C) 2007, 2008 Rob Buis <buis@kde.org>
* (C) 2007 Nikolas Zimmermann <zimmermann@kde.org>
* (C) 2007 Eric Seidel <eric@webkit.org>
+ * Copyright (C) 2009 Google, Inc. 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
@@ -25,7 +26,6 @@
#if ENABLE(SVG)
#include "SVGRenderSupport.h"
-#include "TransformationMatrix.h"
#include "ImageBuffer.h"
#include "RenderObject.h"
#include "RenderSVGContainer.h"
@@ -35,14 +35,50 @@
#include "SVGResourceMasker.h"
#include "SVGStyledElement.h"
#include "SVGURIReference.h"
+#include "TransformState.h"
+#include "TransformationMatrix.h"
+#include <wtf/UnusedParam.h>
namespace WebCore {
-void prepareToRenderSVGContent(RenderObject* object, RenderObject::PaintInfo& paintInfo, const FloatRect& boundingBox, SVGResourceFilter*& filter, SVGResourceFilter* rootFilter)
-{
- SVGElement* svgElement = static_cast<SVGElement*>(object->element());
- ASSERT(svgElement && svgElement->document() && svgElement->isStyled());
+IntRect SVGRenderBase::clippedOverflowRectForRepaint(RenderObject* object, RenderBoxModelObject* repaintContainer)
+{
+ // Return early for any cases where we don't actually paint
+ if (object->style()->visibility() != VISIBLE && !object->enclosingLayer()->hasVisibleContent())
+ return IntRect();
+
+ // Pass our local paint rect to computeRectForRepaint() which will
+ // map to parent coords and recurse up the parent chain.
+ IntRect repaintRect = enclosingIntRect(object->repaintRectInLocalCoordinates());
+ object->computeRectForRepaint(repaintContainer, repaintRect);
+ return repaintRect;
+}
+
+void SVGRenderBase::computeRectForRepaint(RenderObject* object, RenderBoxModelObject* repaintContainer, IntRect& repaintRect, bool fixed)
+{
+ // Translate to coords in our parent renderer, and then call computeRectForRepaint on our parent
+ repaintRect = object->localToParentTransform().mapRect(repaintRect);
+ object->parent()->computeRectForRepaint(repaintContainer, repaintRect, fixed);
+}
+
+void SVGRenderBase::mapLocalToContainer(const RenderObject* object, RenderBoxModelObject* repaintContainer, bool fixed , bool useTransforms, TransformState& transformState)
+{
+ ASSERT(!fixed); // We should have no fixed content in the SVG rendering tree.
+ ASSERT(useTransforms); // mapping a point through SVG w/o respecting trasnforms is useless.
+ transformState.applyTransform(object->localToParentTransform());
+ object->parent()->mapLocalToContainer(repaintContainer, fixed, useTransforms, transformState);
+}
+
+void SVGRenderBase::prepareToRenderSVGContent(RenderObject* object, RenderObject::PaintInfo& paintInfo, const FloatRect& boundingBox, SVGResourceFilter*& filter, SVGResourceFilter* rootFilter)
+{
+#if !ENABLE(FILTERS)
+ UNUSED_PARAM(filter);
+ UNUSED_PARAM(rootFilter);
+#endif
+
ASSERT(object);
+ SVGElement* svgElement = static_cast<SVGElement*>(object->node());
+ ASSERT(svgElement && svgElement->document() && svgElement->isStyled());
SVGStyledElement* styledElement = static_cast<SVGStyledElement*>(svgElement);
const RenderStyle* style = object->style();
@@ -58,7 +94,7 @@ void prepareToRenderSVGContent(RenderObject* object, RenderObject::PaintInfo& pa
paintInfo.context->beginTransparencyLayer(opacity);
}
-#if ENABLE(SVG_FILTERS)
+#if ENABLE(FILTERS)
AtomicString filterId(svgStyle->filter());
#endif
@@ -67,7 +103,7 @@ void prepareToRenderSVGContent(RenderObject* object, RenderObject::PaintInfo& pa
Document* document = object->document();
-#if ENABLE(SVG_FILTERS)
+#if ENABLE(FILTERS)
SVGResourceFilter* newFilter = getFilterById(document, filterId);
if (newFilter == rootFilter) {
// Catch <text filter="url(#foo)">Test<tspan filter="url(#foo)">123</tspan></text>.
@@ -81,10 +117,10 @@ void prepareToRenderSVGContent(RenderObject* object, RenderObject::PaintInfo& pa
SVGResourceClipper* clipper = getClipperById(document, clipperId);
SVGResourceMasker* masker = getMaskerById(document, maskerId);
-#if ENABLE(SVG_FILTERS)
+#if ENABLE(FILTERS)
if (filter) {
filter->addClient(styledElement);
- filter->prepareFilter(paintInfo.context, boundingBox);
+ filter->prepareFilter(paintInfo.context, object);
} else if (!filterId.isEmpty())
svgElement->document()->accessSVGExtensions()->addPendingResource(filterId, styledElement);
#endif
@@ -102,16 +138,21 @@ void prepareToRenderSVGContent(RenderObject* object, RenderObject::PaintInfo& pa
svgElement->document()->accessSVGExtensions()->addPendingResource(maskerId, styledElement);
}
-void finishRenderSVGContent(RenderObject* object, RenderObject::PaintInfo& paintInfo, const FloatRect& boundingBox, SVGResourceFilter*& filter, GraphicsContext* savedContext)
+void SVGRenderBase::finishRenderSVGContent(RenderObject* object, RenderObject::PaintInfo& paintInfo, SVGResourceFilter*& filter, GraphicsContext* savedContext)
{
+#if !ENABLE(FILTERS)
+ UNUSED_PARAM(filter);
+ UNUSED_PARAM(savedContext);
+#endif
+
ASSERT(object);
const RenderStyle* style = object->style();
ASSERT(style);
-#if ENABLE(SVG_FILTERS)
+#if ENABLE(FILTERS)
if (filter) {
- filter->applyFilter(paintInfo.context, boundingBox);
+ filter->applyFilter(paintInfo.context, object);
paintInfo.context = savedContext;
}
#endif
@@ -143,17 +184,13 @@ void renderSubtreeToImage(ImageBuffer* image, RenderObject* item)
svgContainer->setDrawsContents(false);
}
-void clampImageBufferSizeToViewport(RenderObject* object, IntSize& size)
+void clampImageBufferSizeToViewport(FrameView* frameView, IntSize& size)
{
- if (!object || !object->isRenderView())
+ if (!frameView)
return;
- RenderView* view = static_cast<RenderView*>(object);
- if (!view->frameView())
- return;
-
- int viewWidth = view->frameView()->visibleWidth();
- int viewHeight = view->frameView()->visibleHeight();
+ int viewWidth = frameView->visibleWidth();
+ int viewHeight = frameView->visibleHeight();
if (size.width() > viewWidth)
size.setWidth(viewWidth);
@@ -162,6 +199,41 @@ void clampImageBufferSizeToViewport(RenderObject* object, IntSize& size)
size.setHeight(viewHeight);
}
+FloatRect SVGRenderBase::computeContainerBoundingBox(const RenderObject* container, bool includeAllPaintedContent)
+{
+ FloatRect boundingBox;
+
+ RenderObject* current = container->firstChild();
+ for (; current != 0; current = current->nextSibling()) {
+ FloatRect childBBox = includeAllPaintedContent ? current->repaintRectInLocalCoordinates() : current->objectBoundingBox();
+ FloatRect childBBoxInLocalCoords = current->localToParentTransform().mapRect(childBBox);
+ boundingBox.unite(childBBoxInLocalCoords);
+ }
+
+ return boundingBox;
+}
+
+FloatRect SVGRenderBase::filterBoundingBoxForRenderer(const RenderObject* object)
+{
+#if ENABLE(FILTERS)
+ SVGResourceFilter* filter = getFilterById(object->document(), object->style()->svgStyle()->filter());
+ if (filter)
+ return filter->filterBBoxForItemBBox(object->objectBoundingBox());
+#else
+ UNUSED_PARAM(object);
+#endif
+ return FloatRect();
+}
+
+void applyTransformToPaintInfo(RenderObject::PaintInfo& paintInfo, const TransformationMatrix& localToAncestorTransform)
+{
+ if (localToAncestorTransform.isIdentity())
+ return;
+
+ paintInfo.context->concatCTM(localToAncestorTransform);
+ paintInfo.rect = localToAncestorTransform.inverse().mapRect(paintInfo.rect);
+}
+
} // namespace WebCore
#endif // ENABLE(SVG)
diff --git a/src/3rdparty/webkit/WebCore/rendering/SVGRenderSupport.h b/src/3rdparty/webkit/WebCore/rendering/SVGRenderSupport.h
index 7fdfcf8..da2bf59 100644
--- a/src/3rdparty/webkit/WebCore/rendering/SVGRenderSupport.h
+++ b/src/3rdparty/webkit/WebCore/rendering/SVGRenderSupport.h
@@ -1,9 +1,8 @@
/**
- * This file is part of the DOM implementation for WebKit.
- *
* Copyright (C) 2007 Rob Buis <buis@kde.org>
* (C) 2007 Nikolas Zimmermann <zimmermann@kde.org>
* (C) 2007 Eric Seidel <eric@webkit.org>
+ * Copyright (C) 2009 Google, Inc. 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
@@ -22,21 +21,53 @@
*
*/
+#ifndef SVGRenderBase_h
+#define SVGRenderBase_h
+
#if ENABLE(SVG)
#include "RenderObject.h"
namespace WebCore {
-class SVGResourceFilter;
-void prepareToRenderSVGContent(RenderObject*, RenderObject::PaintInfo&, const FloatRect& boundingBox, SVGResourceFilter*&, SVGResourceFilter* rootFilter = 0);
-void finishRenderSVGContent(RenderObject*, RenderObject::PaintInfo&, const FloatRect& boundingBox, SVGResourceFilter*&, GraphicsContext* savedContext);
+ class SVGResourceFilter;
+ class ImageBuffer;
+
+ // SVGRendererBase is an abstract base class which all SVG renderers inherit
+ // from in order to share SVG renderer code.
+ // FIXME: This code can all move into RenderSVGModelObject once
+ // all SVG renderers inherit from RenderSVGModelObject.
+ class SVGRenderBase {
+ public:
+ // FIXME: These are only public for SVGRootInlineBox.
+ // It's unclear if these should be exposed or not. SVGRootInlineBox may
+ // pass the wrong RenderObject* and boundingBox to these functions.
+ static void prepareToRenderSVGContent(RenderObject*, RenderObject::PaintInfo&, const FloatRect& boundingBox, SVGResourceFilter*&, SVGResourceFilter* rootFilter = 0);
+ static void finishRenderSVGContent(RenderObject*, RenderObject::PaintInfo&, SVGResourceFilter*&, GraphicsContext* savedContext);
+
+ protected:
+ static IntRect clippedOverflowRectForRepaint(RenderObject*, RenderBoxModelObject* repaintContainer);
+ static void computeRectForRepaint(RenderObject*, RenderBoxModelObject* repaintContainer, IntRect&, bool fixed);
+
+ static void mapLocalToContainer(const RenderObject*, RenderBoxModelObject* repaintContainer, bool useTransforms, bool fixed, TransformState&);
+
+ // Used to share the "walk all the children" logic between objectBoundingBox
+ // and repaintRectInLocalCoordinates in RenderSVGRoot and RenderSVGContainer
+ static FloatRect computeContainerBoundingBox(const RenderObject* container, bool includeAllPaintedContent);
+
+ // returns the filter bounding box (or the empty rect if no filter) in local coordinates
+ static FloatRect filterBoundingBoxForRenderer(const RenderObject*);
+ };
+
+ // FIXME: This should move to RenderObject or PaintInfo
+ // Used for transforming the GraphicsContext and damage rect before passing PaintInfo to child renderers.
+ void applyTransformToPaintInfo(RenderObject::PaintInfo&, const TransformationMatrix& localToChildTransform);
-// This offers a way to render parts of a WebKit rendering tree into a ImageBuffer.
-class ImageBuffer;
-void renderSubtreeToImage(ImageBuffer*, RenderObject*);
+ // This offers a way to render parts of a WebKit rendering tree into a ImageBuffer.
+ void renderSubtreeToImage(ImageBuffer*, RenderObject*);
-void clampImageBufferSizeToViewport(RenderObject*, IntSize&);
+ void clampImageBufferSizeToViewport(FrameView*, IntSize& imageBufferSize);
+} // namespace WebCore
-}
+#endif // ENABLE(SVG)
-#endif
+#endif // SVGRenderBase_h
diff --git a/src/3rdparty/webkit/WebCore/rendering/SVGRenderTreeAsText.cpp b/src/3rdparty/webkit/WebCore/rendering/SVGRenderTreeAsText.cpp
index eff2fff..33baeba 100644
--- a/src/3rdparty/webkit/WebCore/rendering/SVGRenderTreeAsText.cpp
+++ b/src/3rdparty/webkit/WebCore/rendering/SVGRenderTreeAsText.cpp
@@ -33,7 +33,9 @@
#include "GraphicsTypes.h"
#include "InlineTextBox.h"
#include "HTMLNames.h"
+#include "RenderPath.h"
#include "RenderSVGContainer.h"
+#include "RenderSVGImage.h"
#include "RenderSVGInlineText.h"
#include "RenderSVGText.h"
#include "RenderSVGRoot.h"
@@ -78,6 +80,31 @@ TextStream& operator<<(TextStream& ts, TextStreamSeparator& sep)
return ts;
}
+template<typename ValueType>
+static void writeNameValuePair(TextStream& ts, const char* name, ValueType value)
+{
+ ts << " [" << name << "=" << value << "]";
+}
+
+template<typename ValueType>
+static void writeNameAndQuotedValue(TextStream& ts, const char* name, ValueType value)
+{
+ ts << " [" << name << "=\"" << value << "\"]";
+}
+
+static void writeIfNotEmpty(TextStream& ts, const char* name, const String& value)
+{
+ if (!value.isEmpty())
+ writeNameValuePair(ts, name, value);
+}
+
+template<typename ValueType>
+static void writeIfNotDefault(TextStream& ts, const char* name, ValueType value, ValueType defaultValue)
+{
+ if (value != defaultValue)
+ writeNameValuePair(ts, name, value);
+}
+
TextStream& operator<<(TextStream& ts, const IntPoint& p)
{
return ts << "(" << p.x() << "," << p.y() << ")";
@@ -88,7 +115,7 @@ TextStream& operator<<(TextStream& ts, const IntRect& r)
return ts << "at (" << r.x() << "," << r.y() << ") size " << r.width() << "x" << r.height();
}
-bool hasFractions(double val)
+static bool hasFractions(double val)
{
double epsilon = 0.0001;
int ival = static_cast<int>(val);
@@ -232,11 +259,9 @@ static void writeStyle(TextStream& ts, const RenderObject& object)
const SVGRenderStyle* svgStyle = style->svgStyle();
if (!object.localTransform().isIdentity())
- ts << " [transform=" << object.localTransform() << "]";
- if (svgStyle->imageRendering() != SVGRenderStyle::initialImageRendering())
- ts << " [image rendering=" << svgStyle->imageRendering() << "]";
- if (style->opacity() != RenderStyle::initialOpacity())
- ts << " [opacity=" << style->opacity() << "]";
+ writeNameValuePair(ts, "transform", object.localTransform());
+ writeIfNotDefault(ts, "image rendering", svgStyle->imageRendering(), SVGRenderStyle::initialImageRendering());
+ writeIfNotDefault(ts, "opacity", style->opacity(), RenderStyle::initialOpacity());
if (object.isRenderPath()) {
const RenderPath& path = static_cast<const RenderPath&>(object);
SVGPaintServer* strokePaintServer = SVGPaintServer::strokePaintServer(style, &path);
@@ -250,20 +275,15 @@ static void writeStyle(TextStream& ts, const RenderObject& object)
const DashArray& dashArray = dashArrayFromRenderingStyle(style);
double strokeWidth = SVGRenderStyle::cssPrimitiveToLength(&path, svgStyle->strokeWidth(), 1.0f);
- if (svgStyle->strokeOpacity() != 1.0f)
- ts << s << "[opacity=" << svgStyle->strokeOpacity() << "]";
- if (strokeWidth != 1.0f)
- ts << s << "[stroke width=" << strokeWidth << "]";
- if (svgStyle->strokeMiterLimit() != 4)
- ts << s << "[miter limit=" << svgStyle->strokeMiterLimit() << "]";
- if (svgStyle->capStyle() != 0)
- ts << s << "[line cap=" << svgStyle->capStyle() << "]";
- if (svgStyle->joinStyle() != 0)
- ts << s << "[line join=" << svgStyle->joinStyle() << "]";
- if (dashOffset != 0.0f)
- ts << s << "[dash offset=" << dashOffset << "]";
+ writeIfNotDefault(ts, "opacity", svgStyle->strokeOpacity(), 1.0f);
+ writeIfNotDefault(ts, "stroke width", strokeWidth, 1.0);
+ writeIfNotDefault(ts, "miter limit", svgStyle->strokeMiterLimit(), 4.0f);
+ writeIfNotDefault(ts, "line cap", svgStyle->capStyle(), ButtCap);
+ writeIfNotDefault(ts, "line join", svgStyle->joinStyle(), MiterJoin);
+ writeIfNotDefault(ts, "dash offset", dashOffset, 0.0);
if (!dashArray.isEmpty())
- ts << s << "[dash array=" << dashArray << "]";
+ writeNameValuePair(ts, "dash array", dashArray);
+
ts << "}]";
}
SVGPaintServer* fillPaintServer = SVGPaintServer::fillPaintServer(style, &path);
@@ -273,52 +293,47 @@ static void writeStyle(TextStream& ts, const RenderObject& object)
if (fillPaintServer)
ts << s << *fillPaintServer;
- if (style->svgStyle()->fillOpacity() != 1.0f)
- ts << s << "[opacity=" << style->svgStyle()->fillOpacity() << "]";
- if (style->svgStyle()->fillRule() != RULE_NONZERO)
- ts << s << "[fill rule=" << style->svgStyle()->fillRule() << "]";
+ writeIfNotDefault(ts, "opacity", svgStyle->fillOpacity(), 1.0f);
+ writeIfNotDefault(ts, "fill rule", svgStyle->fillRule(), RULE_NONZERO);
ts << "}]";
}
}
+
if (!svgStyle->clipPath().isEmpty())
- ts << " [clip path=\"" << svgStyle->clipPath() << "\"]";
- if (!svgStyle->startMarker().isEmpty())
- ts << " [start marker=" << svgStyle->startMarker() << "]";
- if (!svgStyle->midMarker().isEmpty())
- ts << " [middle marker=" << svgStyle->midMarker() << "]";
- if (!svgStyle->endMarker().isEmpty())
- ts << " [end marker=" << svgStyle->endMarker() << "]";
- if (!svgStyle->filter().isEmpty())
- ts << " [filter=" << svgStyle->filter() << "]";
+ writeNameAndQuotedValue(ts, "clip path", svgStyle->clipPath());
+ writeIfNotEmpty(ts, "start marker", svgStyle->startMarker());
+ writeIfNotEmpty(ts, "middle marker", svgStyle->midMarker());
+ writeIfNotEmpty(ts, "end marker", svgStyle->endMarker());
+ writeIfNotEmpty(ts, "filter", svgStyle->filter());
}
-static TextStream& operator<<(TextStream& ts, const RenderPath& path)
+static TextStream& writePositionAndStyle(TextStream& ts, const RenderObject& object)
{
- ts << " " << path.absoluteTransform().mapRect(path.relativeBBox());
-
- writeStyle(ts, path);
-
- ts << " [data=\"" << path.path().debugString() << "\"]";
+ ts << " " << object.absoluteTransform().mapRect(object.repaintRectInLocalCoordinates());
+ writeStyle(ts, object);
+ return ts;
+}
+static TextStream& operator<<(TextStream& ts, const RenderPath& path)
+{
+ writePositionAndStyle(ts, path);
+ writeNameAndQuotedValue(ts, "data", path.path().debugString());
return ts;
}
static TextStream& operator<<(TextStream& ts, const RenderSVGContainer& container)
{
- ts << " " << container.absoluteTransform().mapRect(container.relativeBBox());
-
- writeStyle(ts, container);
-
- return ts;
+ return writePositionAndStyle(ts, container);
}
static TextStream& operator<<(TextStream& ts, const RenderSVGRoot& root)
{
- ts << " " << root.absoluteTransform().mapRect(root.relativeBBox());
-
- writeStyle(ts, root);
+ return writePositionAndStyle(ts, root);
+}
- return ts;
+static TextStream& operator<<(TextStream& ts, const RenderSVGImage& root)
+{
+ return writePositionAndStyle(ts, root);
}
static TextStream& operator<<(TextStream& ts, const RenderSVGText& text)
@@ -329,10 +344,10 @@ static TextStream& operator<<(TextStream& ts, const RenderSVGText& text)
return ts;
Vector<SVGTextChunk>& chunks = const_cast<Vector<SVGTextChunk>& >(box->svgTextChunks());
- ts << " at (" << text.xPos() << "," << text.yPos() << ") size " << box->width() << "x" << box->height() << " contains " << chunks.size() << " chunk(s)";
+ ts << " at (" << text.x() << "," << text.y() << ") size " << box->width() << "x" << box->height() << " contains " << chunks.size() << " chunk(s)";
if (text.parent() && (text.parent()->style()->color() != text.style()->color()))
- ts << " [color=" << text.style()->color().name() << "]";
+ writeNameValuePair(ts, "color", text.style()->color().name());
return ts;
}
@@ -430,7 +445,7 @@ static inline void writeSVGInlineTextBox(TextStream& ts, SVGInlineTextBox* textB
ts << " override";
}
- ts << ": " << quoteAndEscapeNonPrintables(String(textBox->textObject()->text()).substring(textBox->start() + range.startOffset, offset)) << "\n";
+ ts << ": " << quoteAndEscapeNonPrintables(String(textBox->textRenderer()->text()).substring(textBox->start() + range.startOffset, offset)) << "\n";
j++;
}
@@ -445,93 +460,63 @@ static inline void writeSVGInlineText(TextStream& ts, const RenderSVGInlineText&
writeSVGInlineTextBox(ts, static_cast<SVGInlineTextBox*>(box), indent);
}
-static String getTagName(SVGStyledElement* elem)
+static void writeStandardPrefix(TextStream& ts, const RenderObject& object, int indent)
{
- if (elem)
- return elem->nodeName();
- return "";
+ writeIndent(ts, indent);
+ ts << object.renderName();
+
+ if (object.node())
+ ts << " {" << object.node()->nodeName() << "}";
}
-void write(TextStream& ts, const RenderSVGContainer& container, int indent)
+static void writeChildren(TextStream& ts, const RenderObject& object, int indent)
{
- writeIndent(ts, indent);
- ts << container.renderName();
-
- if (container.element()) {
- String tagName = getTagName(static_cast<SVGStyledElement*>(container.element()));
- if (!tagName.isEmpty())
- ts << " {" << tagName << "}";
- }
+ for (RenderObject* child = object.firstChild(); child; child = child->nextSibling())
+ write(ts, *child, indent + 1);
+}
+void write(TextStream& ts, const RenderSVGContainer& container, int indent)
+{
+ writeStandardPrefix(ts, container, indent);
ts << container << "\n";
-
- for (RenderObject* child = container.firstChild(); child; child = child->nextSibling())
- write(ts, *child, indent + 1);
+ writeChildren(ts, container, indent);
}
void write(TextStream& ts, const RenderSVGRoot& root, int indent)
{
- writeIndent(ts, indent);
- ts << root.renderName();
-
- if (root.element()) {
- String tagName = getTagName(static_cast<SVGStyledElement*>(root.element()));
- if (!tagName.isEmpty())
- ts << " {" << tagName << "}";
- }
-
+ writeStandardPrefix(ts, root, indent);
ts << root << "\n";
-
- for (RenderObject* child = root.firstChild(); child; child = child->nextSibling())
- write(ts, *child, indent + 1);
+ writeChildren(ts, root, indent);
}
void write(TextStream& ts, const RenderSVGText& text, int indent)
{
- writeIndent(ts, indent);
- ts << text.renderName();
-
- if (text.element()) {
- String tagName = getTagName(static_cast<SVGStyledElement*>(text.element()));
- if (!tagName.isEmpty())
- ts << " {" << tagName << "}";
- }
-
+ writeStandardPrefix(ts, text, indent);
ts << text << "\n";
-
- for (RenderObject* child = text.firstChild(); child; child = child->nextSibling())
- write(ts, *child, indent + 1);
+ writeChildren(ts, text, indent);
}
void write(TextStream& ts, const RenderSVGInlineText& text, int indent)
{
- writeIndent(ts, indent);
- ts << text.renderName();
-
- if (text.element()) {
- String tagName = getTagName(static_cast<SVGStyledElement*>(text.element()));
- if (!tagName.isEmpty())
- ts << " {" << tagName << "}";
- }
+ writeStandardPrefix(ts, text, indent);
- ts << " at (" << text.xPos() << "," << text.yPos() << ") size " << text.width() << "x" << text.height() << "\n";
+ // Why not just linesBoundingBox()?
+ ts << " " << FloatRect(text.firstRunOrigin(), text.linesBoundingBox().size()) << "\n";
writeSVGInlineText(ts, text, indent);
}
void write(TextStream& ts, const RenderPath& path, int indent)
{
- writeIndent(ts, indent);
- ts << path.renderName();
-
- if (path.element()) {
- String tagName = getTagName(static_cast<SVGStyledElement*>(path.element()));
- if (!tagName.isEmpty())
- ts << " {" << tagName << "}";
- }
-
+ writeStandardPrefix(ts, path, indent);
ts << path << "\n";
}
+void write(TextStream& ts, const RenderSVGImage& image, int indent)
+{
+ writeStandardPrefix(ts, image, indent);
+ ts << image << "\n";
+}
+
void writeRenderResources(TextStream& ts, Node* parent)
{
ASSERT(parent);
@@ -549,6 +534,7 @@ void writeRenderResources(TextStream& ts, Node* parent)
continue;
String elementId = svgElement->getAttribute(HTMLNames::idAttr);
+ // FIXME: These names are lies!
if (resource->isPaintServer()) {
RefPtr<SVGPaintServer> paintServer = WTF::static_pointer_cast<SVGPaintServer>(resource);
ts << "KRenderingPaintServer {id=\"" << elementId << "\" " << *paintServer << "}" << "\n";
diff --git a/src/3rdparty/webkit/WebCore/rendering/SVGRenderTreeAsText.h b/src/3rdparty/webkit/WebCore/rendering/SVGRenderTreeAsText.h
index c4d832d..35c3d5c 100644
--- a/src/3rdparty/webkit/WebCore/rendering/SVGRenderTreeAsText.h
+++ b/src/3rdparty/webkit/WebCore/rendering/SVGRenderTreeAsText.h
@@ -45,13 +45,15 @@ namespace WebCore {
class RenderSVGInlineText;
class RenderSVGRoot;
class RenderSVGText;
+ class RenderSVGImage;
// functions used by the main RenderTreeAsText code
void write(TextStream&, const RenderPath&, int indent = 0);
void write(TextStream&, const RenderSVGContainer&, int indent = 0);
-void write(TextStream&, const RenderSVGInlineText&, int ident = 0);
+void write(TextStream&, const RenderSVGInlineText&, int indent = 0);
void write(TextStream&, const RenderSVGRoot&, int indent = 0);
-void write(TextStream&, const RenderSVGText&, int ident = 0);
+void write(TextStream&, const RenderSVGText&, int indent = 0);
+void write(TextStream&, const RenderSVGImage&, int indent = 0);
void writeRenderResources(TextStream&, Node* parent);
diff --git a/src/3rdparty/webkit/WebCore/rendering/SVGRootInlineBox.cpp b/src/3rdparty/webkit/WebCore/rendering/SVGRootInlineBox.cpp
index f7623ba..d92f54c 100644
--- a/src/3rdparty/webkit/WebCore/rendering/SVGRootInlineBox.cpp
+++ b/src/3rdparty/webkit/WebCore/rendering/SVGRootInlineBox.cpp
@@ -30,6 +30,7 @@
#include "Editor.h"
#include "Frame.h"
#include "GraphicsContext.h"
+#include "RenderBlock.h"
#include "RenderSVGRoot.h"
#include "SVGInlineFlowBox.h"
#include "SVGInlineTextBox.h"
@@ -343,7 +344,7 @@ struct SVGRootInlineBoxPaintWalker {
, m_chunkStarted(false)
, m_paintInfo(paintInfo)
, m_savedInfo(paintInfo)
- , m_boundingBox(tx + rootBox->xPos(), ty + rootBox->yPos(), rootBox->width(), rootBox->height())
+ , m_boundingBox(tx + rootBox->x(), ty + rootBox->y(), rootBox->width(), rootBox->height())
, m_filter(0)
, m_rootFilter(rootFilter)
, m_fillPaintServer(0)
@@ -395,21 +396,15 @@ struct SVGRootInlineBoxPaintWalker {
InlineFlowBox* flowBox = box->parent();
// Initialize text rendering
- RenderObject* object = flowBox->object();
+ RenderObject* object = flowBox->renderer();
ASSERT(object);
m_savedInfo = m_paintInfo;
m_paintInfo.context->save();
+ // FIXME: Why is this done here instead of in RenderSVGText?
if (!flowBox->isRootInlineBox())
- m_paintInfo.context->concatCTM(m_rootBox->object()->localTransform());
-
- m_paintInfo.context->concatCTM(object->localTransform());
-
- if (!flowBox->isRootInlineBox()) {
- prepareToRenderSVGContent(object, m_paintInfo, m_boundingBox, m_filter, m_rootFilter);
- m_paintInfo.rect = object->localTransform().inverse().mapRect(m_paintInfo.rect);
- }
+ SVGRenderBase::prepareToRenderSVGContent(object, m_paintInfo, m_boundingBox, m_filter, m_rootFilter);
}
void chunkEndCallback(InlineBox* box)
@@ -419,7 +414,7 @@ struct SVGRootInlineBoxPaintWalker {
InlineFlowBox* flowBox = box->parent();
- RenderObject* object = flowBox->object();
+ RenderObject* object = flowBox->renderer();
ASSERT(object);
// Clean up last used paint server
@@ -428,7 +423,7 @@ struct SVGRootInlineBoxPaintWalker {
// Finalize text rendering
if (!flowBox->isRootInlineBox()) {
- finishRenderSVGContent(object, m_paintInfo, m_boundingBox, m_filter, m_savedInfo.context);
+ SVGRenderBase::finishRenderSVGContent(object, m_paintInfo, m_filter, m_savedInfo.context);
m_filter = 0;
}
@@ -442,7 +437,7 @@ struct SVGRootInlineBoxPaintWalker {
InlineFlowBox* flowBox = box->parent();
// Setup fill paint server
- RenderObject* object = flowBox->object();
+ RenderObject* object = flowBox->renderer();
ASSERT(object);
ASSERT(!m_strokePaintServer);
@@ -463,7 +458,7 @@ struct SVGRootInlineBoxPaintWalker {
InlineFlowBox* flowBox = box->parent();
// Setup stroke paint server
- RenderObject* object = flowBox->object();
+ RenderObject* object = flowBox->renderer();
ASSERT(object);
// If we're both stroked & filled, teardown fill paint server before stroking.
@@ -484,7 +479,7 @@ struct SVGRootInlineBoxPaintWalker {
void chunkPortionCallback(SVGInlineTextBox* textBox, int startOffset, const TransformationMatrix& chunkCtm,
const Vector<SVGChar>::iterator& start, const Vector<SVGChar>::iterator& end)
{
- RenderText* text = textBox->textObject();
+ RenderText* text = textBox->textRenderer();
ASSERT(text);
RenderStyle* styleToUse = text->style(textBox->isFirstLineStyle());
@@ -580,12 +575,10 @@ void SVGRootInlineBox::paint(RenderObject::PaintInfo& paintInfo, int tx, int ty)
paintInfo.context->save();
SVGResourceFilter* filter = 0;
- FloatRect boundingBox(tx + xPos(), ty + yPos(), width(), height());
+ FloatRect boundingBox(tx + x(), ty + y(), width(), height());
// Initialize text rendering
- paintInfo.context->concatCTM(object()->localTransform());
- prepareToRenderSVGContent(object(), paintInfo, boundingBox, filter);
- paintInfo.context->concatCTM(object()->localTransform().inverse());
+ SVGRenderBase::prepareToRenderSVGContent(renderer(), paintInfo, boundingBox, filter);
// Render text, chunk-by-chunk
SVGRootInlineBoxPaintWalker walkerCallback(this, filter, paintInfo, tx, ty);
@@ -599,7 +592,7 @@ void SVGRootInlineBox::paint(RenderObject::PaintInfo& paintInfo, int tx, int ty)
walkTextChunks(&walker);
// Finalize text rendering
- finishRenderSVGContent(object(), paintInfo, boundingBox, filter, savedInfo.context);
+ SVGRenderBase::finishRenderSVGContent(renderer(), paintInfo, filter, savedInfo.context);
paintInfo.context->restore();
}
@@ -611,10 +604,10 @@ int SVGRootInlineBox::placeBoxesHorizontally(int, int& leftPosition, int& rightP
return 0;
}
-void SVGRootInlineBox::verticallyAlignBoxes(int& heightOfBlock)
+int SVGRootInlineBox::verticallyAlignBoxes(int)
{
// height is set by layoutInlineBoxes.
- heightOfBlock = height();
+ return height();
}
float cummulatedWidthOfInlineBoxCharacterRange(SVGInlineBoxCharacterRange& range)
@@ -624,7 +617,7 @@ float cummulatedWidthOfInlineBoxCharacterRange(SVGInlineBoxCharacterRange& range
ASSERT(range.box->isInlineTextBox());
InlineTextBox* textBox = static_cast<InlineTextBox*>(range.box);
- RenderText* text = textBox->textObject();
+ RenderText* text = textBox->textRenderer();
RenderStyle* style = text->style();
return style->font().floatWidth(svgTextRunForInlineTextBox(text->characters() + textBox->start() + range.startOffset, range.endOffset - range.startOffset, style, textBox, 0));
@@ -637,7 +630,7 @@ float cummulatedHeightOfInlineBoxCharacterRange(SVGInlineBoxCharacterRange& rang
ASSERT(range.box->isInlineTextBox());
InlineTextBox* textBox = static_cast<InlineTextBox*>(range.box);
- RenderText* text = textBox->textObject();
+ RenderText* text = textBox->textRenderer();
const Font& font = text->style()->font();
return (range.endOffset - range.startOffset) * (font.ascent() + font.descent());
@@ -651,7 +644,7 @@ TextRun svgTextRunForInlineTextBox(const UChar* c, int len, RenderStyle* style,
TextRun run(c, len, false, static_cast<int>(xPos), textBox->toAdd(), textBox->direction() == RTL, textBox->m_dirOverride || style->visuallyOrdered());
#if ENABLE(SVG_FONTS)
- run.setReferencingRenderObject(textBox->textObject()->parent());
+ run.setReferencingRenderObject(textBox->textRenderer()->parent());
#endif
// We handle letter & word spacing ourselves
@@ -671,7 +664,7 @@ static float cummulatedWidthOrHeightOfTextChunk(SVGTextChunk& chunk, bool calcWi
SVGInlineBoxCharacterRange& range = *it;
SVGInlineTextBox* box = static_cast<SVGInlineTextBox*>(range.box);
- RenderStyle* style = box->object()->style();
+ RenderStyle* style = box->renderer()->style();
for (int i = range.startOffset; i < range.endOffset; ++i) {
ASSERT(charIt <= chunk.end);
@@ -790,13 +783,12 @@ static void applyTextAnchorToTextChunk(SVGTextChunk& chunk)
InlineBox* curBox = range.box;
ASSERT(curBox->isInlineTextBox());
- ASSERT(curBox->parent() && (curBox->parent()->isRootInlineBox() || curBox->parent()->isInlineFlowBox()));
// Move target box
if (chunk.isVerticalText)
- curBox->setYPos(curBox->yPos() + static_cast<int>(shift));
+ curBox->setY(curBox->y() + static_cast<int>(shift));
else
- curBox->setXPos(curBox->xPos() + static_cast<int>(shift));
+ curBox->setX(curBox->x() + static_cast<int>(shift));
}
}
@@ -819,9 +811,9 @@ static float calculateTextLengthCorrectionForTextChunk(SVGTextChunk& chunk, ELen
if (lengthAdjust == SVGTextContentElement::LENGTHADJUST_SPACINGANDGLYPHS) {
if (chunk.isVerticalText)
- chunk.ctm.scale(1.0f, chunk.textLength / computedLength);
+ chunk.ctm.scaleNonUniform(1.0f, chunk.textLength / computedLength);
else
- chunk.ctm.scale(chunk.textLength / computedLength, 1.0f);
+ chunk.ctm.scaleNonUniform(chunk.textLength / computedLength, 1.0f);
return 0.0f;
}
@@ -887,7 +879,7 @@ void SVGRootInlineBox::computePerCharacterLayoutInformation()
// Finally the top left position of our box is known.
// Propogate this knownledge to our RenderSVGText parent.
FloatPoint topLeft = topLeftPositionOfCharacterRange(m_svgChars);
- object()->setPos((int) floorf(topLeft.x()), (int) floorf(topLeft.y()));
+ block()->setLocation((int) floorf(topLeft.x()), (int) floorf(topLeft.y()));
// Layout all InlineText/Flow boxes
// BEWARE: This requires the root top/left position to be set correctly before!
@@ -897,9 +889,9 @@ void SVGRootInlineBox::computePerCharacterLayoutInformation()
void SVGRootInlineBox::buildLayoutInformation(InlineFlowBox* start, SVGCharacterLayoutInfo& info)
{
if (start->isRootInlineBox()) {
- ASSERT(start->object()->element()->hasTagName(SVGNames::textTag));
+ ASSERT(start->renderer()->node()->hasTagName(SVGNames::textTag));
- SVGTextPositioningElement* positioningElement = static_cast<SVGTextPositioningElement*>(start->object()->element());
+ SVGTextPositioningElement* positioningElement = static_cast<SVGTextPositioningElement*>(start->renderer()->node());
ASSERT(positioningElement);
ASSERT(positioningElement->parentNode());
@@ -909,20 +901,20 @@ void SVGRootInlineBox::buildLayoutInformation(InlineFlowBox* start, SVGCharacter
LastGlyphInfo lastGlyph;
for (InlineBox* curr = start->firstChild(); curr; curr = curr->nextOnLine()) {
- if (curr->object()->isText())
+ if (curr->renderer()->isText())
buildLayoutInformationForTextBox(info, static_cast<InlineTextBox*>(curr), lastGlyph);
else {
ASSERT(curr->isInlineFlowBox());
InlineFlowBox* flowBox = static_cast<InlineFlowBox*>(curr);
- if (!flowBox->object()->element())
+ if (!flowBox->renderer()->node())
continue; // Skip generated content.
- bool isAnchor = flowBox->object()->element()->hasTagName(SVGNames::aTag);
- bool isTextPath = flowBox->object()->element()->hasTagName(SVGNames::textPathTag);
+ bool isAnchor = flowBox->renderer()->node()->hasTagName(SVGNames::aTag);
+ bool isTextPath = flowBox->renderer()->node()->hasTagName(SVGNames::textPathTag);
if (!isTextPath && !isAnchor) {
- SVGTextPositioningElement* positioningElement = static_cast<SVGTextPositioningElement*>(flowBox->object()->element());
+ SVGTextPositioningElement* positioningElement = static_cast<SVGTextPositioningElement*>(flowBox->renderer()->node());
ASSERT(positioningElement);
ASSERT(positioningElement->parentNode());
@@ -932,13 +924,13 @@ void SVGRootInlineBox::buildLayoutInformation(InlineFlowBox* start, SVGCharacter
// Handle text-anchor/textLength on path, which is special.
SVGTextContentElement* textContent = 0;
- Node* node = flowBox->object()->element();
+ Node* node = flowBox->renderer()->node();
if (node && node->isSVGElement())
textContent = static_cast<SVGTextContentElement*>(node);
ASSERT(textContent);
ELengthAdjust lengthAdjust = (ELengthAdjust) textContent->lengthAdjust();
- ETextAnchor anchor = flowBox->object()->style()->svgStyle()->textAnchor();
+ ETextAnchor anchor = flowBox->renderer()->style()->svgStyle()->textAnchor();
float textAnchorStartOffset = 0.0f;
// Initialize sub-layout. We need to create text chunks from the textPath
@@ -1007,10 +999,8 @@ void SVGRootInlineBox::layoutInlineBoxes()
void SVGRootInlineBox::layoutInlineBoxes(InlineFlowBox* start, Vector<SVGChar>::iterator& it, int& lowX, int& highX, int& lowY, int& highY)
{
for (InlineBox* curr = start->firstChild(); curr; curr = curr->nextOnLine()) {
- RenderStyle* style = curr->object()->style();
- const Font& font = style->font();
-
- if (curr->object()->isText()) {
+ RenderStyle* style = curr->renderer()->style();
+ if (curr->renderer()->isText()) {
SVGInlineTextBox* textBox = static_cast<SVGInlineTextBox*>(curr);
unsigned length = textBox->len();
@@ -1038,12 +1028,11 @@ void SVGRootInlineBox::layoutInlineBoxes(InlineFlowBox* start, Vector<SVGChar>::
int minY = enclosedStringRect.y();
int maxY = minY + enclosedStringRect.height();
- curr->setXPos(minX - object()->xPos());
+ curr->setX(minX - block()->x());
curr->setWidth(enclosedStringRect.width());
- curr->setYPos(minY - object()->yPos());
- curr->setBaseline(font.ascent());
- curr->setHeight(enclosedStringRect.height());
+ curr->setY(minY - block()->y());
+ textBox->setHeight(enclosedStringRect.height());
if (minX < lowX)
lowX = minX;
@@ -1066,17 +1055,16 @@ void SVGRootInlineBox::layoutInlineBoxes(InlineFlowBox* start, Vector<SVGChar>::
InlineFlowBox* flowBox = static_cast<InlineFlowBox*>(curr);
- if (!flowBox->object()->element())
+ if (!flowBox->renderer()->node())
continue; // Skip generated content.
layoutInlineBoxes(flowBox, it, minX, maxX, minY, maxY);
- curr->setXPos(minX - object()->xPos());
+ curr->setX(minX - block()->x());
curr->setWidth(maxX - minX);
- curr->setYPos(minY - object()->yPos());
- curr->setBaseline(font.ascent());
- curr->setHeight(maxY - minY);
+ curr->setY(minY - block()->y());
+ static_cast<SVGInlineFlowBox*>(curr)->setHeight(maxY - minY);
if (minX < lowX)
lowX = minX;
@@ -1092,15 +1080,15 @@ void SVGRootInlineBox::layoutInlineBoxes(InlineFlowBox* start, Vector<SVGChar>::
}
}
- if (start->isRootInlineBox()) {
- int top = lowY - object()->yPos();
- int bottom = highY - object()->yPos();
+ if (start->isSVGRootInlineBox()) {
+ int top = lowY - block()->y();
+ int bottom = highY - block()->y();
- start->setXPos(lowX - object()->xPos());
- start->setYPos(top);
+ start->setX(lowX - block()->x());
+ start->setY(top);
start->setWidth(highX - lowX);
- start->setHeight(highY - lowY);
+ static_cast<SVGRootInlineBox*>(start)->setHeight(highY - lowY);
start->setVerticalOverflowPositions(top, bottom);
start->setVerticalSelectionPositions(top, bottom);
@@ -1109,7 +1097,7 @@ void SVGRootInlineBox::layoutInlineBoxes(InlineFlowBox* start, Vector<SVGChar>::
void SVGRootInlineBox::buildLayoutInformationForTextBox(SVGCharacterLayoutInfo& info, InlineTextBox* textBox, LastGlyphInfo& lastGlyph)
{
- RenderText* text = textBox->textObject();
+ RenderText* text = textBox->textRenderer();
ASSERT(text);
RenderStyle* style = text->style(textBox->isFirstLineStyle());
@@ -1140,11 +1128,11 @@ void SVGRootInlineBox::buildLayoutInformationForTextBox(SVGCharacterLayoutInfo&
if (textBox->direction() == RTL) {
glyphWidth = svgTextBox->calculateGlyphWidth(style, textBox->end() - i, extraCharsAvailable, charsConsumed, glyphName);
glyphHeight = svgTextBox->calculateGlyphHeight(style, textBox->end() - i, extraCharsAvailable);
- unicodeStr = String(textBox->textObject()->text()->characters() + textBox->end() - i, charsConsumed);
+ unicodeStr = String(textBox->textRenderer()->text()->characters() + textBox->end() - i, charsConsumed);
} else {
glyphWidth = svgTextBox->calculateGlyphWidth(style, textBox->start() + i, extraCharsAvailable, charsConsumed, glyphName);
glyphHeight = svgTextBox->calculateGlyphHeight(style, textBox->start() + i, extraCharsAvailable);
- unicodeStr = String(textBox->textObject()->text()->characters() + textBox->start() + i, charsConsumed);
+ unicodeStr = String(textBox->textRenderer()->text()->characters() + textBox->start() + i, charsConsumed);
}
bool assignedX = false;
@@ -1194,7 +1182,7 @@ void SVGRootInlineBox::buildLayoutInformationForTextBox(SVGCharacterLayoutInfo&
}
// Take letter & word spacing and kerning into account
- float spacing = font.letterSpacing() + calculateKerning(textBox->object()->element()->renderer());
+ float spacing = font.letterSpacing() + calculateKerning(textBox->renderer()->node()->renderer());
const UChar* currentCharacter = text->characters() + (textBox->direction() == RTL ? textBox->end() - i : textBox->start() + i);
const UChar* lastCharacter = 0;
@@ -1369,7 +1357,7 @@ void SVGRootInlineBox::buildTextChunks(Vector<SVGChar>& svgChars, InlineFlowBox*
#endif
for (InlineBox* curr = start->firstChild(); curr; curr = curr->nextOnLine()) {
- if (curr->object()->isText()) {
+ if (curr->renderer()->isText()) {
InlineTextBox* textBox = static_cast<InlineTextBox*>(curr);
unsigned length = textBox->len();
@@ -1381,12 +1369,12 @@ void SVGRootInlineBox::buildTextChunks(Vector<SVGChar>& svgChars, InlineFlowBox*
textBox, length, textBox->start(), textBox->end(), (int) info.handlingTextPath);
#endif
- RenderText* text = textBox->textObject();
+ RenderText* text = textBox->textRenderer();
ASSERT(text);
- ASSERT(text->element());
+ ASSERT(text->node());
SVGTextContentElement* textContent = 0;
- Node* node = text->element()->parent();
+ Node* node = text->node()->parent();
while (node && node->isSVGElement() && !textContent) {
if (static_cast<SVGElement*>(node)->isTextContent())
textContent = static_cast<SVGTextContentElement*>(node);
@@ -1524,10 +1512,10 @@ void SVGRootInlineBox::buildTextChunks(Vector<SVGChar>& svgChars, InlineFlowBox*
ASSERT(curr->isInlineFlowBox());
InlineFlowBox* flowBox = static_cast<InlineFlowBox*>(curr);
- if (!flowBox->object()->element())
+ if (!flowBox->renderer()->node())
continue; // Skip generated content.
- bool isTextPath = flowBox->object()->element()->hasTagName(SVGNames::textPathTag);
+ bool isTextPath = flowBox->renderer()->node()->hasTagName(SVGNames::textPathTag);
#if DEBUG_CHUNK_BUILDING > 1
fprintf(stderr, " -> Handle inline flow box (%p), isTextPath=%i\n", flowBox, (int) isTextPath);
diff --git a/src/3rdparty/webkit/WebCore/rendering/SVGRootInlineBox.h b/src/3rdparty/webkit/WebCore/rendering/SVGRootInlineBox.h
index 800664b..735f755 100644
--- a/src/3rdparty/webkit/WebCore/rendering/SVGRootInlineBox.h
+++ b/src/3rdparty/webkit/WebCore/rendering/SVGRootInlineBox.h
@@ -47,15 +47,19 @@ class SVGRootInlineBox : public RootInlineBox {
public:
SVGRootInlineBox(RenderObject* obj)
: RootInlineBox(obj)
+ , m_height(0)
{
}
virtual bool isSVGRootInlineBox() { return true; }
+ virtual int svgBoxHeight() const { return m_height; }
+ void setHeight(int h) { m_height = h; }
+
virtual void paint(RenderObject::PaintInfo&, int tx, int ty);
virtual int placeBoxesHorizontally(int x, int& leftPosition, int& rightPosition, bool& needsWordSpacing);
- virtual void verticallyAlignBoxes(int& heightOfBlock);
+ virtual int verticallyAlignBoxes(int heightOfBlock);
virtual void computePerCharacterLayoutInformation();
@@ -80,6 +84,7 @@ private:
SVGTextDecorationInfo retrievePaintServersForTextDecoration(RenderObject* start);
private:
+ int m_height;
Vector<SVGChar> m_svgChars;
Vector<SVGTextChunk> m_svgTextChunks;
};
diff --git a/src/3rdparty/webkit/WebCore/rendering/ScrollBehavior.cpp b/src/3rdparty/webkit/WebCore/rendering/ScrollBehavior.cpp
new file mode 100644
index 0000000..232ea19
--- /dev/null
+++ b/src/3rdparty/webkit/WebCore/rendering/ScrollBehavior.cpp
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * Portions are Copyright (C) 1998 Netscape Communications Corporation.
+ *
+ * Other contributors:
+ * Robert O'Callahan <roc+@cs.cmu.edu>
+ * David Baron <dbaron@fas.harvard.edu>
+ * Christian Biesinger <cbiesinger@web.de>
+ * Randall Jesup <rjesup@wgate.com>
+ * Roland Mainz <roland.mainz@informatik.med.uni-giessen.de>
+ * Josh Soref <timeless@mac.com>
+ * Boris Zbarsky <bzbarsky@mit.edu>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Alternatively, the contents of this file may be used under the terms
+ * of either the Mozilla Public License Version 1.1, found at
+ * http://www.mozilla.org/MPL/ (the "MPL") or the GNU General Public
+ * License Version 2.0, found at http://www.fsf.org/copyleft/gpl.html
+ * (the "GPL"), in which case the provisions of the MPL or the GPL are
+ * applicable instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of one of those two
+ * licenses (the MPL or the GPL) and not to allow others to use your
+ * version of this file under the LGPL, indicate your decision by
+ * deletingthe provisions above and replace them with the notice and
+ * other provisions required by the MPL or the GPL, as the case may be.
+ * If you do not delete the provisions above, a recipient may use your
+ * version of this file under any of the LGPL, the MPL or the GPL.
+ */
+
+#include "config.h"
+#include "ScrollBehavior.h"
+
+namespace WebCore {
+
+const ScrollAlignment ScrollAlignment::alignCenterIfNeeded = { noScroll, alignCenter, alignToClosestEdge };
+const ScrollAlignment ScrollAlignment::alignToEdgeIfNeeded = { noScroll, alignToClosestEdge, alignToClosestEdge };
+const ScrollAlignment ScrollAlignment::alignCenterAlways = { alignCenter, alignCenter, alignCenter };
+const ScrollAlignment ScrollAlignment::alignTopAlways = { alignTop, alignTop, alignTop };
+const ScrollAlignment ScrollAlignment::alignBottomAlways = { alignBottom, alignBottom, alignBottom };
+
+}; // namespace WebCore
diff --git a/src/3rdparty/webkit/WebCore/rendering/ScrollBehavior.h b/src/3rdparty/webkit/WebCore/rendering/ScrollBehavior.h
new file mode 100644
index 0000000..390c68a
--- /dev/null
+++ b/src/3rdparty/webkit/WebCore/rendering/ScrollBehavior.h
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2003, 2009 Apple Inc. All rights reserved.
+ *
+ * Portions are Copyright (C) 1998 Netscape Communications Corporation.
+ *
+ * Other contributors:
+ * Robert O'Callahan <roc+@cs.cmu.edu>
+ * David Baron <dbaron@fas.harvard.edu>
+ * Christian Biesinger <cbiesinger@web.de>
+ * Randall Jesup <rjesup@wgate.com>
+ * Roland Mainz <roland.mainz@informatik.med.uni-giessen.de>
+ * Josh Soref <timeless@mac.com>
+ * Boris Zbarsky <bzbarsky@mit.edu>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Alternatively, the contents of this file may be used under the terms
+ * of either the Mozilla Public License Version 1.1, found at
+ * http://www.mozilla.org/MPL/ (the "MPL") or the GNU General Public
+ * License Version 2.0, found at http://www.fsf.org/copyleft/gpl.html
+ * (the "GPL"), in which case the provisions of the MPL or the GPL are
+ * applicable instead of those above. If you wish to allow use of your
+ * version of this file only under the terms of one of those two
+ * licenses (the MPL or the GPL) and not to allow others to use your
+ * version of this file under the LGPL, indicate your decision by
+ * deletingthe provisions above and replace them with the notice and
+ * other provisions required by the MPL or the GPL, as the case may be.
+ * If you do not delete the provisions above, a recipient may use your
+ * version of this file under any of the LGPL, the MPL or the GPL.
+ */
+
+#ifndef ScrollBehavior_h
+#define ScrollBehavior_h
+
+namespace WebCore {
+
+enum ScrollBehavior {
+ noScroll,
+ alignCenter,
+ alignTop,
+ alignBottom,
+ alignLeft,
+ alignRight,
+ alignToClosestEdge
+};
+
+struct ScrollAlignment {
+ static ScrollBehavior getVisibleBehavior(const ScrollAlignment& s) { return s.m_rectVisible; }
+ static ScrollBehavior getPartialBehavior(const ScrollAlignment& s) { return s.m_rectPartial; }
+ static ScrollBehavior getHiddenBehavior(const ScrollAlignment& s) { return s.m_rectHidden; }
+
+ static const ScrollAlignment alignCenterIfNeeded;
+ static const ScrollAlignment alignToEdgeIfNeeded;
+ static const ScrollAlignment alignCenterAlways;
+ static const ScrollAlignment alignTopAlways;
+ static const ScrollAlignment alignBottomAlways;
+
+ ScrollBehavior m_rectVisible;
+ ScrollBehavior m_rectHidden;
+ ScrollBehavior m_rectPartial;
+};
+
+
+}; // namespace WebCore
+
+#endif // ScrollBehavior_h
diff --git a/src/3rdparty/webkit/WebCore/rendering/TextControlInnerElements.cpp b/src/3rdparty/webkit/WebCore/rendering/TextControlInnerElements.cpp
index 452333c..cd067de 100644
--- a/src/3rdparty/webkit/WebCore/rendering/TextControlInnerElements.cpp
+++ b/src/3rdparty/webkit/WebCore/rendering/TextControlInnerElements.cpp
@@ -35,15 +35,19 @@
#include "HTMLNames.h"
#include "HTMLTextAreaElement.h"
#include "MouseEvent.h"
+#include "RenderLayer.h"
#include "RenderTextControlSingleLine.h"
namespace WebCore {
class RenderTextControlInnerBlock : public RenderBlock {
public:
- RenderTextControlInnerBlock(Node* node) : RenderBlock(node) { }
+ RenderTextControlInnerBlock(Node* node, bool isMultiLine) : RenderBlock(node), m_multiLine(isMultiLine) { }
virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, int x, int y, int tx, int ty, HitTestAction);
+ virtual VisiblePosition positionForPoint(const IntPoint&);
+ private:
+ bool m_multiLine;
};
bool RenderTextControlInnerBlock::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, int x, int y, int tx, int ty, HitTestAction hitTestAction)
@@ -57,6 +61,22 @@ bool RenderTextControlInnerBlock::nodeAtPoint(const HitTestRequest& request, Hit
return RenderBlock::nodeAtPoint(request, result, x, y, tx, ty, placeholderIsVisible ? HitTestBlockBackground : hitTestAction);
}
+VisiblePosition RenderTextControlInnerBlock::positionForPoint(const IntPoint& point)
+{
+ int contentsX = point.x();
+ int contentsY = point.y();
+
+ // Multiline text controls have the scroll on shadowAncestorNode, so we need to take that
+ // into account here.
+ if (m_multiLine) {
+ RenderTextControl* renderer = static_cast<RenderTextControl*>(node()->shadowAncestorNode()->renderer());
+ if (renderer->hasOverflowClip())
+ renderer->layer()->addScrolledContentOffset(contentsX, contentsY);
+ }
+
+ return RenderBlock::positionForPoint(IntPoint(contentsX, contentsY));
+}
+
TextControlInnerElement::TextControlInnerElement(Document* doc, Node* shadowParent)
: HTMLDivElement(HTMLNames::divTag, doc)
, m_shadowParent(shadowParent)
@@ -98,14 +118,15 @@ void TextControlInnerTextElement::defaultEventHandler(Event* evt)
// FIXME: In the future, we should add a way to have default event listeners. Then we would add one to the text field's inner div, and we wouldn't need this subclass.
Node* shadowAncestor = shadowAncestorNode();
if (shadowAncestor && shadowAncestor->renderer()) {
- ASSERT(shadowAncestor->renderer()->isTextField() || shadowAncestor->renderer()->isTextArea());
- if (evt->isBeforeTextInsertedEvent())
+ ASSERT(shadowAncestor->renderer()->isTextControl());
+ if (evt->isBeforeTextInsertedEvent()) {
if (shadowAncestor->renderer()->isTextField())
static_cast<HTMLInputElement*>(shadowAncestor)->defaultEventHandler(evt);
else
static_cast<HTMLTextAreaElement*>(shadowAncestor)->defaultEventHandler(evt);
+ }
if (evt->type() == eventNames().webkitEditableContentChangedEvent)
- static_cast<RenderTextControl*>(shadowAncestor->renderer())->subtreeHasChanged();
+ toRenderTextControl(shadowAncestor->renderer())->subtreeHasChanged();
}
if (!evt->defaultHandled())
HTMLDivElement::defaultEventHandler(evt);
@@ -113,7 +134,13 @@ void TextControlInnerTextElement::defaultEventHandler(Event* evt)
RenderObject* TextControlInnerTextElement::createRenderer(RenderArena* arena, RenderStyle*)
{
- return new (arena) RenderTextControlInnerBlock(this);
+ bool multiLine = false;
+ Node* shadowAncestor = shadowAncestorNode();
+ if (shadowAncestor && shadowAncestor->renderer()) {
+ ASSERT(shadowAncestor->renderer()->isTextField() || shadowAncestor->renderer()->isTextArea());
+ multiLine = shadowAncestor->renderer()->isTextArea();
+ }
+ return new (arena) RenderTextControlInnerBlock(this, multiLine);
}
SearchFieldResultsButtonElement::SearchFieldResultsButtonElement(Document* doc)
diff --git a/src/3rdparty/webkit/WebCore/rendering/TransformState.cpp b/src/3rdparty/webkit/WebCore/rendering/TransformState.cpp
new file mode 100644
index 0000000..a9e68f4
--- /dev/null
+++ b/src/3rdparty/webkit/WebCore/rendering/TransformState.cpp
@@ -0,0 +1,169 @@
+/*
+ * Copyright (C) 2009 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``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 COMPUTER, INC. OR
+ * 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"
+#include "TransformState.h"
+
+namespace WebCore {
+
+void TransformState::move(int x, int y, TransformAccumulation accumulate)
+{
+ if (m_accumulatingTransform && m_accumulatedTransform) {
+ // If we're accumulating into an existing transform, apply the translation.
+ if (m_direction == ApplyTransformDirection)
+ m_accumulatedTransform->translateRight(x, y);
+ else
+ m_accumulatedTransform->translate(-x, -y); // We're unapplying, so negate
+
+ // Then flatten if necessary.
+ if (accumulate == FlattenTransform)
+ flatten();
+ } else {
+ // Just move the point and, optionally, the quad.
+ m_lastPlanarPoint.move(x, y);
+ if (m_mapQuad)
+ m_lastPlanarQuad.move(x, y);
+ }
+ m_accumulatingTransform = accumulate == AccumulateTransform;
+}
+
+void TransformState::applyTransform(const TransformationMatrix& transformFromContainer, TransformAccumulation accumulate)
+{
+ // If we have an accumulated transform from last time, multiply in this transform
+ if (m_accumulatedTransform) {
+ if (m_direction == ApplyTransformDirection)
+ m_accumulatedTransform->multiply(transformFromContainer);
+ else
+ m_accumulatedTransform->multLeft(transformFromContainer);
+ } else if (accumulate == AccumulateTransform) {
+ // Make one if we started to accumulate
+ m_accumulatedTransform.set(new TransformationMatrix(transformFromContainer));
+ }
+
+ if (accumulate == FlattenTransform) {
+ const TransformationMatrix* finalTransform = m_accumulatedTransform ? m_accumulatedTransform.get() : &transformFromContainer;
+ flattenWithTransform(*finalTransform);
+ }
+ m_accumulatingTransform = accumulate == AccumulateTransform;
+}
+
+void TransformState::flatten()
+{
+ if (!m_accumulatedTransform) {
+ m_accumulatingTransform = false;
+ return;
+ }
+
+ flattenWithTransform(*m_accumulatedTransform);
+}
+
+FloatPoint TransformState::mappedPoint() const
+{
+ if (!m_accumulatedTransform)
+ return m_lastPlanarPoint;
+
+ if (m_direction == ApplyTransformDirection)
+ return m_accumulatedTransform->mapPoint(m_lastPlanarPoint);
+
+ return m_accumulatedTransform->inverse().projectPoint(m_lastPlanarPoint);
+}
+
+FloatQuad TransformState::mappedQuad() const
+{
+ if (!m_accumulatedTransform)
+ return m_lastPlanarQuad;
+
+ if (m_direction == ApplyTransformDirection)
+ return m_accumulatedTransform->mapQuad(m_lastPlanarQuad);
+
+ return m_accumulatedTransform->inverse().projectQuad(m_lastPlanarQuad);
+}
+
+void TransformState::flattenWithTransform(const TransformationMatrix& t)
+{
+ if (m_direction == ApplyTransformDirection) {
+ m_lastPlanarPoint = t.mapPoint(m_lastPlanarPoint);
+ if (m_mapQuad)
+ m_lastPlanarQuad = t.mapQuad(m_lastPlanarQuad);
+ } else {
+ TransformationMatrix inverseTransform = t.inverse();
+ m_lastPlanarPoint = inverseTransform.projectPoint(m_lastPlanarPoint);
+ if (m_mapQuad)
+ m_lastPlanarQuad = inverseTransform.projectQuad(m_lastPlanarQuad);
+ }
+
+ // We could throw away m_accumulatedTransform if we wanted to here, but that
+ // would cause thrash when traversing hierarachies with alternating
+ // preserve-3d and flat elements.
+ if (m_accumulatedTransform)
+ m_accumulatedTransform->makeIdentity();
+ m_accumulatingTransform = false;
+}
+
+// HitTestingTransformState methods
+void HitTestingTransformState::translate(int x, int y, TransformAccumulation accumulate)
+{
+ m_accumulatedTransform.translate(x, y);
+ if (accumulate == FlattenTransform)
+ flattenWithTransform(m_accumulatedTransform);
+
+ m_accumulatingTransform = accumulate == AccumulateTransform;
+}
+
+void HitTestingTransformState::applyTransform(const TransformationMatrix& transformFromContainer, TransformAccumulation accumulate)
+{
+ m_accumulatedTransform.multLeft(transformFromContainer);
+ if (accumulate == FlattenTransform)
+ flattenWithTransform(m_accumulatedTransform);
+
+ m_accumulatingTransform = accumulate == AccumulateTransform;
+}
+
+void HitTestingTransformState::flatten()
+{
+ flattenWithTransform(m_accumulatedTransform);
+}
+
+void HitTestingTransformState::flattenWithTransform(const TransformationMatrix& t)
+{
+ TransformationMatrix inverseTransform = t.inverse();
+ m_lastPlanarPoint = inverseTransform.projectPoint(m_lastPlanarPoint);
+ m_lastPlanarQuad = inverseTransform.projectQuad(m_lastPlanarQuad);
+
+ m_accumulatedTransform.makeIdentity();
+ m_accumulatingTransform = false;
+}
+
+FloatPoint HitTestingTransformState::mappedPoint() const
+{
+ return m_accumulatedTransform.inverse().projectPoint(m_lastPlanarPoint);
+}
+
+FloatQuad HitTestingTransformState::mappedQuad() const
+{
+ return m_accumulatedTransform.inverse().projectQuad(m_lastPlanarQuad);
+}
+
+} // namespace WebCore
diff --git a/src/3rdparty/webkit/WebCore/rendering/TransformState.h b/src/3rdparty/webkit/WebCore/rendering/TransformState.h
new file mode 100644
index 0000000..92275f9
--- /dev/null
+++ b/src/3rdparty/webkit/WebCore/rendering/TransformState.h
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2009 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``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 COMPUTER, INC. OR
+ * 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 TransformState_h
+#define TransformState_h
+
+#include "FloatPoint.h"
+#include "FloatQuad.h"
+#include "IntSize.h"
+#include "TransformationMatrix.h"
+#include <wtf/Noncopyable.h>
+#include <wtf/PassRefPtr.h>
+#include <wtf/OwnPtr.h>
+#include <wtf/RefCounted.h>
+
+namespace WebCore {
+
+class TransformState : Noncopyable {
+public:
+ enum TransformDirection { ApplyTransformDirection, UnapplyInverseTransformDirection };
+ enum TransformAccumulation { FlattenTransform, AccumulateTransform };
+
+ // If quad is non-null, it will be mapped
+ TransformState(TransformDirection mappingDirection, const FloatPoint& p, const FloatQuad* quad = 0)
+ : m_lastPlanarPoint(p)
+ , m_accumulatingTransform(false)
+ , m_mapQuad(quad != 0)
+ , m_direction(mappingDirection)
+ {
+ if (quad)
+ m_lastPlanarQuad = *quad;
+ }
+
+ void move(const IntSize& s, TransformAccumulation accumulate = FlattenTransform)
+ {
+ move(s.width(), s.height(), accumulate);
+ }
+
+ void move(int x, int y, TransformAccumulation = FlattenTransform);
+ void applyTransform(const TransformationMatrix& transformFromContainer, TransformAccumulation = FlattenTransform);
+ void flatten();
+
+ // Return the coords of the point or quad in the last flattened layer
+ FloatPoint lastPlanarPoint() const { return m_lastPlanarPoint; }
+ FloatQuad lastPlanarQuad() const { return m_lastPlanarQuad; }
+
+ // Return the point or quad mapped through the current transform
+ FloatPoint mappedPoint() const;
+ FloatQuad mappedQuad() const;
+
+private:
+ void flattenWithTransform(const TransformationMatrix&);
+
+ FloatPoint m_lastPlanarPoint;
+ FloatQuad m_lastPlanarQuad;
+
+ // We only allocate the transform if we need to
+ OwnPtr<TransformationMatrix> m_accumulatedTransform;
+ bool m_accumulatingTransform;
+ bool m_mapQuad;
+ TransformDirection m_direction;
+};
+
+class HitTestingTransformState : public RefCounted<HitTestingTransformState> {
+public:
+ static PassRefPtr<HitTestingTransformState> create(const FloatPoint& p, const FloatQuad& quad)
+ {
+ return adoptRef(new HitTestingTransformState(p, quad));
+ }
+
+ static PassRefPtr<HitTestingTransformState> create(const HitTestingTransformState& other)
+ {
+ return adoptRef(new HitTestingTransformState(other));
+ }
+
+ enum TransformAccumulation { FlattenTransform, AccumulateTransform };
+ void translate(int x, int y, TransformAccumulation);
+ void applyTransform(const TransformationMatrix& transformFromContainer, TransformAccumulation);
+
+ FloatPoint mappedPoint() const;
+ FloatQuad mappedQuad() const;
+ void flatten();
+
+ FloatPoint m_lastPlanarPoint;
+ FloatQuad m_lastPlanarQuad;
+ TransformationMatrix m_accumulatedTransform;
+ bool m_accumulatingTransform;
+
+private:
+ HitTestingTransformState(const FloatPoint& p, const FloatQuad& quad)
+ : m_lastPlanarPoint(p)
+ , m_lastPlanarQuad(quad)
+ , m_accumulatingTransform(false)
+ {
+ }
+
+ HitTestingTransformState(const HitTestingTransformState& other)
+ : RefCounted<HitTestingTransformState>()
+ , m_lastPlanarPoint(other.m_lastPlanarPoint)
+ , m_lastPlanarQuad(other.m_lastPlanarQuad)
+ , m_accumulatedTransform(other.m_accumulatedTransform)
+ , m_accumulatingTransform(other.m_accumulatingTransform)
+ {
+ }
+
+ void flattenWithTransform(const TransformationMatrix&);
+};
+
+} // namespace WebCore
+
+#endif // TransformState_h
diff --git a/src/3rdparty/webkit/WebCore/rendering/bidi.cpp b/src/3rdparty/webkit/WebCore/rendering/bidi.cpp
index 6ff2d59..635ad9a 100644
--- a/src/3rdparty/webkit/WebCore/rendering/bidi.cpp
+++ b/src/3rdparty/webkit/WebCore/rendering/bidi.cpp
@@ -29,6 +29,7 @@
#include "InlineTextBox.h"
#include "Logging.h"
#include "RenderArena.h"
+#include "RenderInline.h"
#include "RenderLayer.h"
#include "RenderListMarker.h"
#include "RenderView.h"
@@ -77,18 +78,7 @@ public:
int nextBreakablePosition;
};
-// Midpoint globals. The goal is not to do any allocation when dealing with
-// these midpoints, so we just keep an array around and never clear it. We track
-// the number of items and position using the two other variables.
-static Vector<InlineIterator>* smidpoints;
-static unsigned sNumMidpoints;
-static unsigned sCurrMidpoint;
-static bool betweenMidpoints;
-
-static bool isLineEmpty = true;
-static bool previousLineBrokeCleanly = true;
-
-static int getBorderPaddingMargin(RenderObject* child, bool endOfInline)
+static int getBorderPaddingMargin(RenderBoxModelObject* child, bool endOfInline)
{
bool leftSide = (child->style()->direction() == LTR) ? !endOfInline : endOfInline;
if (leftSide)
@@ -102,10 +92,10 @@ static int inlineWidth(RenderObject* child, bool start = true, bool end = true)
int extraWidth = 0;
RenderObject* parent = child->parent();
while (parent->isInline() && !parent->isInlineBlockOrInlineTable() && lineDepth++ < cMaxLineDepth) {
- if (start && parent->firstChild() == child)
- extraWidth += getBorderPaddingMargin(parent, false);
- if (end && parent->lastChild() == child)
- extraWidth += getBorderPaddingMargin(parent, true);
+ if (start && !child->previousSibling())
+ extraWidth += getBorderPaddingMargin(toRenderBoxModelObject(parent), false);
+ if (end && !child->nextSibling())
+ extraWidth += getBorderPaddingMargin(toRenderBoxModelObject(parent), true);
child = parent;
parent = child->parent();
}
@@ -172,9 +162,9 @@ static inline RenderObject* bidiNext(RenderBlock* block, RenderObject* current,
while (current) {
next = 0;
- if (!oldEndOfInline && !current->isFloating() && !current->isReplaced() && !current->isPositioned()) {
+ if (!oldEndOfInline && !current->isFloating() && !current->isReplaced() && !current->isPositioned() && !current->isText()) {
next = current->firstChild();
- if (next && resolver && next->isInlineFlow()) {
+ if (next && resolver && next->isRenderInline()) {
EUnicodeBidi ub = next->style()->unicodeBidi();
if (ub != UBNormal) {
TextDirection dir = next->style()->direction();
@@ -187,19 +177,19 @@ static inline RenderObject* bidiNext(RenderBlock* block, RenderObject* current,
}
if (!next) {
- if (!skipInlines && !oldEndOfInline && current->isInlineFlow()) {
+ if (!skipInlines && !oldEndOfInline && current->isRenderInline()) {
next = current;
endOfInline = true;
break;
}
while (current && current != block) {
- if (resolver && current->isInlineFlow() && current->style()->unicodeBidi() != UBNormal)
+ if (resolver && current->isRenderInline() && current->style()->unicodeBidi() != UBNormal)
resolver->embed(PopDirectionalFormat);
next = current->nextSibling();
if (next) {
- if (resolver && next->isInlineFlow()) {
+ if (resolver && next->isRenderInline()) {
EUnicodeBidi ub = next->style()->unicodeBidi();
if (ub != UBNormal) {
TextDirection dir = next->style()->direction();
@@ -213,7 +203,7 @@ static inline RenderObject* bidiNext(RenderBlock* block, RenderObject* current,
}
current = current->parent();
- if (!skipInlines && current && current != block && current->isInlineFlow()) {
+ if (!skipInlines && current && current != block && current->isRenderInline()) {
next = current;
endOfInline = true;
break;
@@ -226,7 +216,7 @@ static inline RenderObject* bidiNext(RenderBlock* block, RenderObject* current,
if (next->isText() || next->isFloating() || next->isReplaced() || next->isPositioned()
|| ((!skipInlines || !next->firstChild()) // Always return EMPTY inlines.
- && next->isInlineFlow()))
+ && next->isRenderInline()))
break;
current = next;
}
@@ -243,7 +233,7 @@ static RenderObject* bidiFirst(RenderBlock* block, InlineBidiResolver* resolver,
return 0;
RenderObject* o = block->firstChild();
- if (o->isInlineFlow()) {
+ if (o->isRenderInline()) {
if (resolver) {
EUnicodeBidi ub = o->style()->unicodeBidi();
if (ub != UBNormal) {
@@ -278,7 +268,7 @@ inline void InlineIterator::increment(InlineBidiResolver* resolver)
return;
if (obj->isText()) {
pos++;
- if (pos >= static_cast<RenderText*>(obj)->textLength()) {
+ if (pos >= toRenderText(obj)->textLength()) {
obj = bidiNext(block, obj, resolver);
pos = 0;
nextBreakablePosition = -1;
@@ -306,7 +296,7 @@ inline UChar InlineIterator::current() const
if (!obj || !obj->isText())
return 0;
- RenderText* text = static_cast<RenderText*>(obj);
+ RenderText* text = toRenderText(obj);
if (pos >= text->textLength())
return 0;
@@ -326,44 +316,44 @@ ALWAYS_INLINE Direction InlineIterator::direction() const
// -------------------------------------------------------------------------------------------------
-static void chopMidpointsAt(RenderObject* obj, unsigned pos)
+static void chopMidpointsAt(LineMidpointState& lineMidpointState, RenderObject* obj, unsigned pos)
{
- if (!sNumMidpoints)
+ if (!lineMidpointState.numMidpoints)
return;
- InlineIterator* midpoints = smidpoints->data();
- for (int i = sNumMidpoints - 1; i >= 0; i--) {
+ InlineIterator* midpoints = lineMidpointState.midpoints.data();
+ for (int i = lineMidpointState.numMidpoints - 1; i >= 0; i--) {
const InlineIterator& point = midpoints[i];
if (point.obj == obj && point.pos == pos) {
- sNumMidpoints = i;
+ lineMidpointState.numMidpoints = i;
break;
}
}
}
-static void checkMidpoints(InlineIterator& lBreak)
+static void checkMidpoints(LineMidpointState& lineMidpointState, InlineIterator& lBreak)
{
// Check to see if our last midpoint is a start point beyond the line break. If so,
// shave it off the list, and shave off a trailing space if the previous end point doesn't
// preserve whitespace.
- if (lBreak.obj && sNumMidpoints && sNumMidpoints % 2 == 0) {
- InlineIterator* midpoints = smidpoints->data();
- InlineIterator& endpoint = midpoints[sNumMidpoints-2];
- const InlineIterator& startpoint = midpoints[sNumMidpoints-1];
+ if (lBreak.obj && lineMidpointState.numMidpoints && !(lineMidpointState.numMidpoints % 2)) {
+ InlineIterator* midpoints = lineMidpointState.midpoints.data();
+ InlineIterator& endpoint = midpoints[lineMidpointState.numMidpoints - 2];
+ const InlineIterator& startpoint = midpoints[lineMidpointState.numMidpoints - 1];
InlineIterator currpoint = endpoint;
while (!currpoint.atEnd() && currpoint != startpoint && currpoint != lBreak)
currpoint.increment();
if (currpoint == lBreak) {
// We hit the line break before the start point. Shave off the start point.
- sNumMidpoints--;
+ lineMidpointState.numMidpoints--;
if (endpoint.obj->style()->collapseWhiteSpace()) {
if (endpoint.obj->isText()) {
// Don't shave a character off the endpoint if it was from a soft hyphen.
- RenderText* textObj = static_cast<RenderText*>(endpoint.obj);
+ RenderText* textObj = toRenderText(endpoint.obj);
if (endpoint.pos + 1 < textObj->textLength()) {
if (textObj->characters()[endpoint.pos+1] == softHyphen)
return;
} else if (startpoint.obj->isText()) {
- RenderText *startText = static_cast<RenderText*>(startpoint.obj);
+ RenderText *startText = toRenderText(startpoint.obj);
if (startText->textLength() && startText->characters()[0] == softHyphen)
return;
}
@@ -374,33 +364,34 @@ static void checkMidpoints(InlineIterator& lBreak)
}
}
-static void addMidpoint(const InlineIterator& midpoint)
+static void addMidpoint(LineMidpointState& lineMidpointState, const InlineIterator& midpoint)
{
- if (smidpoints->size() <= sNumMidpoints)
- smidpoints->grow(sNumMidpoints + 10);
+ if (lineMidpointState.midpoints.size() <= lineMidpointState.numMidpoints)
+ lineMidpointState.midpoints.grow(lineMidpointState.numMidpoints + 10);
- InlineIterator* midpoints = smidpoints->data();
- midpoints[sNumMidpoints++] = midpoint;
+ InlineIterator* midpoints = lineMidpointState.midpoints.data();
+ midpoints[lineMidpointState.numMidpoints++] = midpoint;
}
static void appendRunsForObject(int start, int end, RenderObject* obj, InlineBidiResolver& resolver)
{
if (start > end || obj->isFloating() ||
- (obj->isPositioned() && !obj->hasStaticX() && !obj->hasStaticY() && !obj->container()->isInlineFlow()))
+ (obj->isPositioned() && !obj->style()->hasStaticX() && !obj->style()->hasStaticY() && !obj->container()->isRenderInline()))
return;
- bool haveNextMidpoint = (sCurrMidpoint < sNumMidpoints);
+ LineMidpointState& lineMidpointState = resolver.midpointState();
+ bool haveNextMidpoint = (lineMidpointState.currentMidpoint < lineMidpointState.numMidpoints);
InlineIterator nextMidpoint;
if (haveNextMidpoint)
- nextMidpoint = smidpoints->at(sCurrMidpoint);
- if (betweenMidpoints) {
+ nextMidpoint = lineMidpointState.midpoints[lineMidpointState.currentMidpoint];
+ if (lineMidpointState.betweenMidpoints) {
if (!(haveNextMidpoint && nextMidpoint.obj == obj))
return;
// This is a new start point. Stop ignoring objects and
// adjust our start.
- betweenMidpoints = false;
+ lineMidpointState.betweenMidpoints = false;
start = nextMidpoint.pos;
- sCurrMidpoint++;
+ lineMidpointState.currentMidpoint++;
if (start < end)
return appendRunsForObject(start, end, obj, resolver);
} else {
@@ -412,8 +403,8 @@ static void appendRunsForObject(int start, int end, RenderObject* obj, InlineBid
// An end midpoint has been encountered within our object. We
// need to go ahead and append a run with our endpoint.
if (static_cast<int>(nextMidpoint.pos + 1) <= end) {
- betweenMidpoints = true;
- sCurrMidpoint++;
+ lineMidpointState.betweenMidpoints = true;
+ lineMidpointState.currentMidpoint++;
if (nextMidpoint.pos != UINT_MAX) { // UINT_MAX means stop at the object and don't include any of it.
if (static_cast<int>(nextMidpoint.pos + 1) > start)
resolver.addRun(new (obj->renderArena())
@@ -455,7 +446,37 @@ void InlineBidiResolver::appendRun()
m_status.eor = OtherNeutral;
}
-InlineFlowBox* RenderBlock::createLineBoxes(RenderObject* obj)
+static inline InlineBox* createInlineBoxForRenderer(RenderObject* obj, bool isRootLineBox, bool isOnlyRun = false)
+{
+ if (isRootLineBox)
+ return toRenderBlock(obj)->createRootInlineBox();
+
+ if (obj->isText()) {
+ InlineTextBox* textBox = toRenderText(obj)->createInlineTextBox();
+ // We only treat a box as text for a <br> if we are on a line by ourself or in strict mode
+ // (Note the use of strict mode. In "almost strict" mode, we don't treat the box for <br> as text.)
+ if (obj->isBR())
+ textBox->setIsText(isOnlyRun || obj->document()->inStrictMode());
+ return textBox;
+ }
+
+ if (obj->isBox())
+ return toRenderBox(obj)->createInlineBox();
+
+ return toRenderInline(obj)->createInlineFlowBox();
+}
+
+static inline void dirtyLineBoxesForRenderer(RenderObject* o, bool fullLayout)
+{
+ if (o->isText()) {
+ if (o->prefWidthsDirty() && o->isCounter())
+ toRenderText(o)->calcPrefWidths(0); // FIXME: Counters depend on this hack. No clue why. Should be investigated and removed.
+ toRenderText(o)->dirtyLineBoxes(fullLayout);
+ } else
+ toRenderInline(o)->dirtyLineBoxes(fullLayout);
+}
+
+InlineFlowBox* RenderBlock::createLineBoxes(RenderObject* obj, bool firstLine)
{
// See if we have an unconstructed line box for this object that is also
// the last item on the line.
@@ -464,11 +485,10 @@ InlineFlowBox* RenderBlock::createLineBoxes(RenderObject* obj)
InlineFlowBox* parentBox = 0;
InlineFlowBox* result = 0;
do {
- ASSERT(obj->isInlineFlow() || obj == this);
- RenderFlow* flow = static_cast<RenderFlow*>(obj);
-
+ ASSERT(obj->isRenderInline() || obj == this);
+
// Get the last box we made for this render object.
- parentBox = flow->lastLineBox();
+ parentBox = obj->isRenderInline() ? toRenderInline(obj)->lastLineBox() : toRenderBlock(obj)->lastLineBox();
// If this box is constructed then it is from a previous line, and we need
// to make a new box for our line. If this box is unconstructed but it has
@@ -479,10 +499,10 @@ InlineFlowBox* RenderBlock::createLineBoxes(RenderObject* obj)
if (!parentBox || parentBox->isConstructed() || parentBox->nextOnLine()) {
// 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 = obj->createInlineBox(false, obj == this);
+ InlineBox* newBox = createInlineBoxForRenderer(obj, obj == this);
ASSERT(newBox->isInlineFlowBox());
parentBox = static_cast<InlineFlowBox*>(newBox);
- parentBox->setFirstLineStyleBit(m_firstLine);
+ parentBox->setFirstLineStyleBit(firstLine);
constructedNewBox = true;
}
@@ -509,7 +529,7 @@ InlineFlowBox* RenderBlock::createLineBoxes(RenderObject* obj)
return result;
}
-RootInlineBox* RenderBlock::constructLine(unsigned runCount, BidiRun* firstRun, BidiRun* lastRun, bool lastLine, RenderObject* endObject)
+RootInlineBox* RenderBlock::constructLine(unsigned runCount, BidiRun* firstRun, BidiRun* lastRun, bool firstLine, bool lastLine, RenderObject* endObject)
{
ASSERT(firstRun);
@@ -520,29 +540,31 @@ RootInlineBox* RenderBlock::constructLine(unsigned runCount, BidiRun* firstRun,
if (runCount == 2 && !r->m_object->isListMarker())
isOnlyRun = ((style()->direction() == RTL) ? lastRun : firstRun)->m_object->isListMarker();
- InlineBox* box = r->m_object->createInlineBox(r->m_object->isPositioned(), false, isOnlyRun);
+ InlineBox* box = createInlineBoxForRenderer(r->m_object, false, isOnlyRun);
r->m_box = box;
- if (box) {
- // If we have no parent box yet, or if the run is not simply a sibling,
- // then we need to construct inline boxes as necessary to properly enclose the
- // run's inline box.
- if (!parentBox || parentBox->object() != r->m_object->parent())
- // Create new inline boxes all the way back to the appropriate insertion point.
- parentBox = createLineBoxes(r->m_object->parent());
-
- // Append the inline box to this line.
- parentBox->addToLine(box);
-
- bool visuallyOrdered = r->m_object->style()->visuallyOrdered();
- box->setBidiLevel(visuallyOrdered ? 0 : r->level());
-
- if (box->isInlineTextBox()) {
- InlineTextBox* text = static_cast<InlineTextBox*>(box);
- text->setStart(r->m_start);
- text->setLen(r->m_stop - r->m_start);
- text->m_dirOverride = r->dirOverride(visuallyOrdered);
- }
+ ASSERT(box);
+ if (!box)
+ continue;
+
+ // If we have no parent box yet, or if the run is not simply a sibling,
+ // then we need to construct inline boxes as necessary to properly enclose the
+ // run's inline box.
+ if (!parentBox || parentBox->renderer() != r->m_object->parent())
+ // Create new inline boxes all the way back to the appropriate insertion point.
+ parentBox = createLineBoxes(r->m_object->parent(), firstLine);
+
+ // Append the inline box to this line.
+ parentBox->addToLine(box);
+
+ bool visuallyOrdered = r->m_object->style()->visuallyOrdered();
+ box->setBidiLevel(visuallyOrdered ? 0 : r->level());
+
+ if (box->isInlineTextBox()) {
+ InlineTextBox* text = static_cast<InlineTextBox*>(box);
+ text->setStart(r->m_start);
+ text->setLen(r->m_stop - r->m_start);
+ text->m_dirOverride = r->dirOverride(visuallyOrdered);
}
}
@@ -563,10 +585,10 @@ RootInlineBox* RenderBlock::constructLine(unsigned runCount, BidiRun* firstRun,
return lastRootBox();
}
-void RenderBlock::computeHorizontalPositionsForLine(RootInlineBox* lineBox, BidiRun* firstRun, BidiRun* trailingSpaceRun, bool reachedEnd)
+void RenderBlock::computeHorizontalPositionsForLine(RootInlineBox* lineBox, bool firstLine, BidiRun* firstRun, BidiRun* trailingSpaceRun, bool reachedEnd)
{
// First determine our total width.
- int availableWidth = lineWidth(m_height);
+ int availableWidth = lineWidth(height(), firstLine);
int totWidth = lineBox->getFlowSpacingWidth();
bool needsWordSpacing = false;
unsigned numSpaces = 0;
@@ -578,7 +600,7 @@ void RenderBlock::computeHorizontalPositionsForLine(RootInlineBox* lineBox, Bidi
// correct static x position. They have no effect on the width.
// Similarly, line break boxes have no effect on the width.
if (r->m_object->isText()) {
- RenderText* rt = static_cast<RenderText*>(r->m_object);
+ RenderText* rt = toRenderText(r->m_object);
if (textAlign == JUSTIFY && r != trailingSpaceRun) {
const UChar* characters = rt->characters();
@@ -590,28 +612,35 @@ void RenderBlock::computeHorizontalPositionsForLine(RootInlineBox* lineBox, Bidi
}
if (int length = rt->textLength()) {
- if (!r->m_compact && !r->m_start && needsWordSpacing && isSpaceOrNewline(rt->characters()[r->m_start]))
- totWidth += rt->style(m_firstLine)->font().wordSpacing();
+ if (!r->m_start && needsWordSpacing && isSpaceOrNewline(rt->characters()[r->m_start]))
+ totWidth += rt->style(firstLine)->font().wordSpacing();
needsWordSpacing = !isSpaceOrNewline(rt->characters()[r->m_stop - 1]) && r->m_stop == length;
}
- r->m_box->setWidth(rt->width(r->m_start, r->m_stop - r->m_start, totWidth, m_firstLine));
- } else if (!r->m_object->isInlineFlow()) {
- r->m_object->calcWidth();
- r->m_box->setWidth(r->m_object->width());
- if (!r->m_compact)
- totWidth += r->m_object->marginLeft() + r->m_object->marginRight();
+ HashSet<const SimpleFontData*> fallbackFonts;
+ r->m_box->setWidth(rt->width(r->m_start, r->m_stop - r->m_start, totWidth, firstLine, &fallbackFonts));
+ if (!fallbackFonts.isEmpty()
+#if ENABLE(SVG)
+ && !isSVGText()
+#endif
+ ) {
+ ASSERT(r->m_box->isText());
+ static_cast<InlineTextBox*>(r->m_box)->setFallbackFonts(fallbackFonts);
+ }
+ } else if (!r->m_object->isRenderInline()) {
+ RenderBox* renderBox = toRenderBox(r->m_object);
+ renderBox->calcWidth();
+ r->m_box->setWidth(renderBox->width());
+ totWidth += renderBox->marginLeft() + renderBox->marginRight();
}
- // Compacts don't contribute to the width of the line, since they are placed in the margin.
- if (!r->m_compact)
- totWidth += r->m_box->width();
+ totWidth += r->m_box->width();
}
// Armed with the total width of the line (without justification),
// we now examine our text-align property in order to determine where to position the
// objects horizontally. The total width of the line can be increased if we end up
// justifying text.
- int x = leftOffset(m_height);
+ int x = leftOffset(height(), firstLine);
switch(textAlign) {
case LEFT:
case WEBKIT_LEFT:
@@ -619,7 +648,7 @@ void RenderBlock::computeHorizontalPositionsForLine(RootInlineBox* lineBox, Bidi
// particular with RTL blocks, wide lines should still spill out to the left.
if (style()->direction() == LTR) {
if (totWidth > availableWidth && trailingSpaceRun)
- trailingSpaceRun->m_box->setWidth(trailingSpaceRun->m_box->width() - totWidth + availableWidth);
+ trailingSpaceRun->m_box->setWidth(max(0, trailingSpaceRun->m_box->width() - totWidth + availableWidth));
} else {
if (trailingSpaceRun)
trailingSpaceRun->m_box->setWidth(0);
@@ -641,7 +670,7 @@ void RenderBlock::computeHorizontalPositionsForLine(RootInlineBox* lineBox, Bidi
// for right to left fall through to right aligned
if (style()->direction() == LTR) {
if (totWidth > availableWidth && trailingSpaceRun)
- trailingSpaceRun->m_box->setWidth(trailingSpaceRun->m_box->width() - totWidth + availableWidth);
+ trailingSpaceRun->m_box->setWidth(max(0, trailingSpaceRun->m_box->width() - totWidth + availableWidth));
break;
}
case RIGHT:
@@ -658,7 +687,7 @@ void RenderBlock::computeHorizontalPositionsForLine(RootInlineBox* lineBox, Bidi
x += availableWidth - totWidth;
} else {
if (totWidth > availableWidth && trailingSpaceRun) {
- trailingSpaceRun->m_box->setWidth(trailingSpaceRun->m_box->width() - totWidth + availableWidth);
+ trailingSpaceRun->m_box->setWidth(max(0, trailingSpaceRun->m_box->width() - totWidth + availableWidth));
totWidth -= trailingSpaceRun->m_box->width();
} else
x += availableWidth - totWidth;
@@ -670,7 +699,7 @@ void RenderBlock::computeHorizontalPositionsForLine(RootInlineBox* lineBox, Bidi
if (trailingSpaceRun) {
totWidth -= trailingSpaceRun->m_box->width();
trailingSpaceWidth = min(trailingSpaceRun->m_box->width(), (availableWidth - totWidth + 1) / 2);
- trailingSpaceRun->m_box->setWidth(trailingSpaceWidth);
+ trailingSpaceRun->m_box->setWidth(max(0, trailingSpaceWidth));
}
if (style()->direction() == LTR)
x += max((availableWidth - totWidth) / 2, 0);
@@ -685,9 +714,9 @@ void RenderBlock::computeHorizontalPositionsForLine(RootInlineBox* lineBox, Bidi
continue;
int spaceAdd = 0;
- if (r->m_object->isText() && !r->m_compact) {
+ if (r->m_object->isText()) {
unsigned spaces = 0;
- const UChar* characters = static_cast<RenderText*>(r->m_object)->characters();
+ const UChar* characters = toRenderText(r->m_object)->characters();
for (int i = r->m_start; i < r->m_stop; i++) {
UChar c = characters[i];
if (c == ' ' || c == '\n' || c == '\t')
@@ -720,27 +749,31 @@ void RenderBlock::computeHorizontalPositionsForLine(RootInlineBox* lineBox, Bidi
void RenderBlock::computeVerticalPositionsForLine(RootInlineBox* lineBox, BidiRun* firstRun)
{
- lineBox->verticallyAlignBoxes(m_height);
- lineBox->setBlockHeight(m_height);
+ setHeight(lineBox->verticallyAlignBoxes(height()));
+ lineBox->setBlockHeight(height());
// See if the line spilled out. If so set overflow height accordingly.
int bottomOfLine = lineBox->bottomOverflow();
- if (bottomOfLine > m_height && bottomOfLine > m_overflowHeight)
+ if (bottomOfLine > height() && bottomOfLine > m_overflowHeight)
m_overflowHeight = bottomOfLine;
// Now make sure we place replaced render objects correctly.
for (BidiRun* r = firstRun; r; r = r->next()) {
+ ASSERT(r->m_box);
if (!r->m_box)
continue; // Skip runs with no line boxes.
// Align positioned boxes with the top of the line box. This is
// a reasonable approximation of an appropriate y position.
if (r->m_object->isPositioned())
- r->m_box->setYPos(m_height);
+ r->m_box->setY(height());
// Position is used to properly position both replaced elements and
// to update the static normal flow x/y of positioned elements.
- r->m_object->position(r->m_box);
+ if (r->m_object->isText())
+ toRenderText(r->m_object)->positionLineBox(r->m_box);
+ else if (r->m_object->isBox())
+ toRenderBox(r->m_object)->positionLineBox(r->m_box);
}
// Positioned objects and zero-length text nodes destroy their boxes in
// position(), which unnecessarily dirties the line.
@@ -748,39 +781,11 @@ void RenderBlock::computeVerticalPositionsForLine(RootInlineBox* lineBox, BidiRu
}
// collects one line of the paragraph and transforms it to visual order
-void RenderBlock::bidiReorderLine(InlineBidiResolver& resolver, const InlineIterator& end)
+void RenderBlock::bidiReorderLine(InlineBidiResolver& resolver, const InlineIterator& end, bool previousLineBrokeCleanly)
{
resolver.createBidiRunsForLine(end, style()->visuallyOrdered(), previousLineBrokeCleanly);
}
-static void buildCompactRuns(RenderObject* compactObj, InlineBidiResolver& resolver)
-{
- ASSERT(compactObj->isRenderBlock());
- ASSERT(!resolver.firstRun());
-
- // Format the compact like it is its own single line. We build up all the runs for
- // the little compact and then reorder them for bidi.
- RenderBlock* compactBlock = static_cast<RenderBlock*>(compactObj);
-
- InlineIterator start(compactBlock, bidiFirst(compactBlock, &resolver), 0);
- resolver.setPosition(start);
-
- betweenMidpoints = false;
- isLineEmpty = true;
- previousLineBrokeCleanly = true;
-
- InlineIterator end = compactBlock->findNextLineBreak(resolver);
- if (!isLineEmpty)
- compactBlock->bidiReorderLine(resolver, end);
-
- for (BidiRun* run = resolver.firstRun(); run; run = run->next())
- run->m_compact = true;
-
- sNumMidpoints = 0;
- sCurrMidpoint = 0;
- betweenMidpoints = false;
-}
-
static inline bool isCollapsibleSpace(UChar character, RenderText* renderer)
{
if (character == ' ' || character == '\t' || character == softHyphen)
@@ -795,12 +800,10 @@ static inline bool isCollapsibleSpace(UChar character, RenderText* renderer)
void RenderBlock::layoutInlineChildren(bool relayoutChildren, int& repaintTop, int& repaintBottom)
{
bool useRepaintBounds = false;
-
- invalidateVerticalPosition();
m_overflowHeight = 0;
- m_height = borderTop() + paddingTop();
+ setHeight(borderTop() + paddingTop());
int toAdd = borderBottom() + paddingBottom() + horizontalScrollbarHeight();
// Figure out if we should clear out our line boxes.
@@ -808,7 +811,7 @@ void RenderBlock::layoutInlineChildren(bool relayoutChildren, int& repaintTop, i
// FIXME: Do something better when floats are present.
bool fullLayout = !firstLineBox() || !firstChild() || selfNeedsLayout() || relayoutChildren;
if (fullLayout)
- deleteLineBoxes();
+ lineBoxes()->deleteLineBoxes(renderArena());
// Text truncation only kicks in if your overflow isn't visible and your text-overflow-mode isn't
// clip.
@@ -826,10 +829,10 @@ void RenderBlock::layoutInlineChildren(bool relayoutChildren, int& repaintTop, i
bool endOfInline = false;
RenderObject* o = bidiFirst(this, 0, false);
Vector<FloatWithRect> floats;
- int containerWidth = max(0, containingBlockWidth());
while (o) {
- o->invalidateVerticalPosition();
if (o->isReplaced() || o->isFloating() || o->isPositioned()) {
+ RenderBox* box = toRenderBox(o);
+
if (relayoutChildren || o->style()->width().isPercent() || o->style()->height().isPercent())
o->setChildNeedsLayout(true, false);
@@ -838,23 +841,21 @@ void RenderBlock::layoutInlineChildren(bool relayoutChildren, int& repaintTop, i
o->setPrefWidthsDirty(true, false);
if (o->isPositioned())
- o->containingBlock()->insertPositionedObject(o);
+ o->containingBlock()->insertPositionedObject(box);
else {
if (o->isFloating())
- floats.append(FloatWithRect(o));
+ floats.append(FloatWithRect(box));
else if (fullLayout || o->needsLayout()) // Replaced elements
- o->dirtyLineBoxes(fullLayout);
+ toRenderBox(o)->dirtyLineBoxes(fullLayout);
o->layoutIfNeeded();
}
- } else if (o->isText() || (o->isInlineFlow() && !endOfInline)) {
+ } else if (o->isText() || (o->isRenderInline() && !endOfInline)) {
if (fullLayout || o->selfNeedsLayout())
- o->dirtyLineBoxes(fullLayout);
-
- // Calculate margins of inline flows so that they can be used later by line layout.
- if (o->isInlineFlow())
- static_cast<RenderFlow*>(o)->calcMargins(containerWidth);
+ dirtyLineBoxesForRenderer(o, fullLayout);
o->setNeedsLayout(false);
+ if (!o->isText())
+ toRenderInline(o)->invalidateVerticalPosition(); // FIXME: Should do better here and not always invalidate everything.
}
o = bidiNext(this, o, 0, false, &endOfInline);
}
@@ -862,29 +863,26 @@ void RenderBlock::layoutInlineChildren(bool relayoutChildren, int& repaintTop, i
// We want to skip ahead to the first dirty line
InlineBidiResolver resolver;
unsigned floatIndex;
- RootInlineBox* startLine = determineStartPosition(fullLayout, resolver, floats, floatIndex);
+ bool firstLine = true;
+ bool previousLineBrokeCleanly = true;
+ RootInlineBox* startLine = determineStartPosition(firstLine, fullLayout, previousLineBrokeCleanly, resolver, floats, floatIndex);
if (fullLayout && !selfNeedsLayout()) {
setNeedsLayout(true, false); // Mark ourselves as needing a full layout. This way we'll repaint like
// we're supposed to.
- if (!document()->view()->needsFullRepaint() && m_layer) {
+ RenderView* v = view();
+ if (v && !v->doingFullRepaint() && hasLayer()) {
// Because we waited until we were already inside layout to discover
// that the block really needed a full layout, we missed our chance to repaint the layer
// before layout started. Luckily the layer has cached the repaint rect for its original
// position and size, and so we can use that to make a repaint happen now.
- RenderView* c = view();
- if (c && !c->printing())
- c->repaintViewRectangle(m_layer->repaintRect());
+ repaintUsingContainer(containerForRepaint(), layer()->repaintRect());
}
}
FloatingObject* lastFloat = m_floatingObjects ? m_floatingObjects->last() : 0;
- if (!smidpoints)
- smidpoints = new Vector<InlineIterator>();
-
- sNumMidpoints = 0;
- sCurrMidpoint = 0;
+ LineMidpointState& lineMidpointState = resolver.midpointState();
// We also find the first clean line and extract these lines. We will add them back
// if we determine that we're able to synchronize after handling all our dirty lines.
@@ -896,8 +894,8 @@ void RenderBlock::layoutInlineChildren(bool relayoutChildren, int& repaintTop, i
if (startLine) {
useRepaintBounds = true;
- repaintTop = m_height;
- repaintBottom = m_height;
+ repaintTop = height();
+ repaintBottom = height();
RenderArena* arena = renderArena();
RootInlineBox* box = startLine;
while (box) {
@@ -916,9 +914,9 @@ void RenderBlock::layoutInlineChildren(bool relayoutChildren, int& repaintTop, i
// adjust the height accordingly.
// A line break can be either the first or the last object on a line, depending on its direction.
if (InlineBox* lastLeafChild = lastRootBox()->lastLeafChild()) {
- RenderObject* lastObject = lastLeafChild->object();
+ RenderObject* lastObject = lastLeafChild->renderer();
if (!lastObject->isBR())
- lastObject = lastRootBox()->firstLeafChild()->object();
+ lastObject = lastRootBox()->firstLeafChild()->renderer();
if (lastObject->isBR()) {
EClear clear = lastObject->style()->clear();
if (clear != CNONE)
@@ -930,21 +928,21 @@ void RenderBlock::layoutInlineChildren(bool relayoutChildren, int& repaintTop, i
bool endLineMatched = false;
bool checkForEndLineMatch = endLine;
bool checkForFloatsFromLastLine = false;
- int lastHeight = m_height;
+ int lastHeight = height();
+
+ bool isLineEmpty = true;
while (!end.atEnd()) {
// FIXME: Is this check necessary before the first iteration or can it be moved to the end?
if (checkForEndLineMatch && (endLineMatched = matchedEndLine(resolver, cleanLineStart, cleanLineBidiStatus, endLine, endLineYPos, repaintBottom, repaintTop)))
break;
- betweenMidpoints = false;
+ lineMidpointState.reset();
+
isLineEmpty = true;
- if (m_firstLine && firstChild()->isCompact() && firstChild()->isRenderBlock()) {
- buildCompactRuns(firstChild(), resolver);
- resolver.setPosition(InlineIterator(this, firstChild()->nextSibling(), 0));
- }
+
EClear clear = CNONE;
- end = findNextLineBreak(resolver, &clear);
+ end = findNextLineBreak(resolver, firstLine, isLineEmpty, previousLineBrokeCleanly, &clear);
if (resolver.position().atEnd()) {
resolver.deleteRuns();
checkForFloatsFromLastLine = true;
@@ -953,15 +951,16 @@ void RenderBlock::layoutInlineChildren(bool relayoutChildren, int& repaintTop, i
ASSERT(end != resolver.position());
if (!isLineEmpty) {
- bidiReorderLine(resolver, end);
+ bidiReorderLine(resolver, end, previousLineBrokeCleanly);
ASSERT(resolver.position() == end);
BidiRun* trailingSpaceRun = 0;
- if (!previousLineBrokeCleanly && resolver.runCount() && resolver.logicallyLastRun()->m_object->style()->breakOnlyAfterWhiteSpace()) {
+ 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 = static_cast<RenderText*>(lastObject);
+ RenderText* lastText = toRenderText(lastObject);
const UChar* characters = lastText->characters();
int firstSpace = trailingSpaceRun->stop();
while (firstSpace > trailingSpaceRun->start()) {
@@ -976,26 +975,18 @@ void RenderBlock::layoutInlineChildren(bool relayoutChildren, int& repaintTop, i
TextDirection direction = style()->direction();
bool shouldReorder = trailingSpaceRun != (direction == LTR ? resolver.lastRun() : resolver.firstRun());
if (firstSpace != trailingSpaceRun->start()) {
- ETextAlign textAlign = style()->textAlign();
- // If the trailing white space is at the right hand side of a left-aligned line, then computeHorizontalPositionsForLine()
- // does not care if trailingSpaceRun includes non-spaces at the beginning. In all other cases, trailingSpaceRun has to
- // contain only the spaces, either because we re-order them or because computeHorizontalPositionsForLine() needs to know
- // their width.
- bool shouldSeparateSpaces = textAlign != LEFT && textAlign != WEBKIT_LEFT && textAlign != TAAUTO || trailingSpaceRun->m_level % 2 || direction == RTL || shouldReorder;
- if (shouldSeparateSpaces) {
- 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;
- }
+ 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) {
@@ -1017,12 +1008,12 @@ void RenderBlock::layoutInlineChildren(bool relayoutChildren, int& repaintTop, i
RootInlineBox* lineBox = 0;
if (resolver.runCount()) {
- lineBox = constructLine(resolver.runCount(), resolver.firstRun(), resolver.lastRun(), !end.obj, end.obj && !end.pos ? end.obj : 0);
+ lineBox = constructLine(resolver.runCount(), resolver.firstRun(), resolver.lastRun(), firstLine, !end.obj, end.obj && !end.pos ? end.obj : 0);
if (lineBox) {
lineBox->setEndsWithBreak(previousLineBrokeCleanly);
// Now we position all of our text runs horizontally.
- computeHorizontalPositionsForLine(lineBox, resolver.firstRun(), trailingSpaceRun, end.atEnd());
+ computeHorizontalPositionsForLine(lineBox, firstLine, resolver.firstRun(), trailingSpaceRun, end.atEnd());
// Now position our text runs vertically.
computeVerticalPositionsForLine(lineBox, resolver.firstRun());
@@ -1050,7 +1041,7 @@ void RenderBlock::layoutInlineChildren(bool relayoutChildren, int& repaintTop, i
}
}
- m_firstLine = false;
+ firstLine = false;
newLine(clear);
}
@@ -1073,16 +1064,15 @@ void RenderBlock::layoutInlineChildren(bool relayoutChildren, int& repaintTop, i
lastFloat = m_floatingObjects->last();
}
- lastHeight = m_height;
- sNumMidpoints = 0;
- sCurrMidpoint = 0;
+ lastHeight = height();
+ lineMidpointState.reset();
resolver.setPosition(end);
}
if (endLine) {
if (endLineMatched) {
// Attach all the remaining lines, and then adjust their y-positions as needed.
- int delta = m_height - endLineYPos;
+ int delta = height() - endLineYPos;
for (RootInlineBox* line = endLine; line; line = line->nextRootBox()) {
line->attachLine();
if (delta) {
@@ -1090,17 +1080,17 @@ void RenderBlock::layoutInlineChildren(bool relayoutChildren, int& repaintTop, i
repaintBottom = max(repaintBottom, line->bottomOverflow() + max(delta, 0));
line->adjustPosition(0, delta);
}
- if (Vector<RenderObject*>* cleanLineFloats = line->floatsPtr()) {
- Vector<RenderObject*>::iterator end = cleanLineFloats->end();
- for (Vector<RenderObject*>::iterator f = cleanLineFloats->begin(); f != end; ++f) {
- int floatTop = (*f)->yPos() - (*f)->marginTop();
+ if (Vector<RenderBox*>* cleanLineFloats = line->floatsPtr()) {
+ Vector<RenderBox*>::iterator end = cleanLineFloats->end();
+ for (Vector<RenderBox*>::iterator f = cleanLineFloats->begin(); f != end; ++f) {
+ int floatTop = (*f)->y() - (*f)->marginTop();
insertFloatingObject(*f);
- m_height = floatTop + delta;
+ setHeight(floatTop + delta);
positionNewFloats();
}
}
}
- m_height = lastRootBox()->blockHeight();
+ setHeight(lastRootBox()->blockHeight());
} else {
// Delete all the remaining lines.
InlineRunBox* line = endLine;
@@ -1132,20 +1122,17 @@ void RenderBlock::layoutInlineChildren(bool relayoutChildren, int& repaintTop, i
}
}
- sNumMidpoints = 0;
- sCurrMidpoint = 0;
-
// Now add in the bottom border/padding.
- m_height += toAdd;
+ setHeight(height() + toAdd);
// Always make sure this is at least our height.
- m_overflowHeight = max(m_height, m_overflowHeight);
+ m_overflowHeight = max(height(), m_overflowHeight);
// See if any lines spill out of the block. If so, we need to update our overflow width.
checkLinesForOverflow();
if (!firstLineBox() && hasLineIfEmpty())
- m_height += lineHeight(true, true);
+ setHeight(height() + lineHeight(true, true));
// See if we have any lines that spill out of our block. If we do, then we will possibly need to
// truncate text.
@@ -1153,7 +1140,8 @@ void RenderBlock::layoutInlineChildren(bool relayoutChildren, int& repaintTop, i
checkLinesForTextOverflow();
}
-RootInlineBox* RenderBlock::determineStartPosition(bool& fullLayout, InlineBidiResolver& resolver, Vector<FloatWithRect>& floats, unsigned& numCleanFloats)
+RootInlineBox* RenderBlock::determineStartPosition(bool& firstLine, bool& fullLayout, bool& previousLineBrokeCleanly,
+ InlineBidiResolver& resolver, Vector<FloatWithRect>& floats, unsigned& numCleanFloats)
{
RootInlineBox* curr = 0;
RootInlineBox* last = 0;
@@ -1162,10 +1150,10 @@ RootInlineBox* RenderBlock::determineStartPosition(bool& fullLayout, InlineBidiR
if (!fullLayout) {
size_t floatIndex = 0;
for (curr = firstRootBox(); curr && !curr->isDirty(); curr = curr->nextRootBox()) {
- if (Vector<RenderObject*>* cleanLineFloats = curr->floatsPtr()) {
- Vector<RenderObject*>::iterator end = cleanLineFloats->end();
- for (Vector<RenderObject*>::iterator o = cleanLineFloats->begin(); o != end; ++o) {
- RenderObject* f = *o;
+ if (Vector<RenderBox*>* cleanLineFloats = curr->floatsPtr()) {
+ Vector<RenderBox*>::iterator end = cleanLineFloats->end();
+ for (Vector<RenderBox*>::iterator o = cleanLineFloats->begin(); o != end; ++o) {
+ RenderBox* f = *o;
IntSize newSize(f->width() + f->marginLeft() +f->marginRight(), f->height() + f->marginTop() + f->marginBottom());
ASSERT(floatIndex < floats.size());
if (floats[floatIndex].object != f) {
@@ -1209,7 +1197,7 @@ RootInlineBox* RenderBlock::determineStartPosition(bool& fullLayout, InlineBidiR
// We have a dirty line.
if (RootInlineBox* prevRootBox = curr->prevRootBox()) {
// We have a previous line.
- if (!dirtiedByFloat && (!prevRootBox->endsWithBreak() || prevRootBox->lineBreakObj()->isText() && prevRootBox->lineBreakPos() >= static_cast<RenderText*>(prevRootBox->lineBreakObj())->textLength()))
+ if (!dirtiedByFloat && (!prevRootBox->endsWithBreak() || (prevRootBox->lineBreakObj()->isText() && prevRootBox->lineBreakPos() >= toRenderText(prevRootBox->lineBreakObj())->textLength())))
// The previous line didn't break cleanly or broke at a newline
// that has been deleted, so treat it as dirty too.
curr = prevRootBox;
@@ -1227,15 +1215,15 @@ RootInlineBox* RenderBlock::determineStartPosition(bool& fullLayout, InlineBidiR
numCleanFloats = 0;
if (!floats.isEmpty()) {
- int savedHeight = m_height;
+ int savedHeight = height();
// Restore floats from clean lines.
RootInlineBox* line = firstRootBox();
while (line != curr) {
- if (Vector<RenderObject*>* cleanLineFloats = line->floatsPtr()) {
- Vector<RenderObject*>::iterator end = cleanLineFloats->end();
- for (Vector<RenderObject*>::iterator f = cleanLineFloats->begin(); f != end; ++f) {
+ if (Vector<RenderBox*>* cleanLineFloats = line->floatsPtr()) {
+ Vector<RenderBox*>::iterator end = cleanLineFloats->end();
+ for (Vector<RenderBox*>::iterator f = cleanLineFloats->begin(); f != end; ++f) {
insertFloatingObject(*f);
- m_height = (*f)->yPos() - (*f)->marginTop();
+ setHeight((*f)->y() - (*f)->marginTop());
positionNewFloats();
ASSERT(floats[numCleanFloats].object == *f);
numCleanFloats++;
@@ -1243,16 +1231,16 @@ RootInlineBox* RenderBlock::determineStartPosition(bool& fullLayout, InlineBidiR
}
line = line->nextRootBox();
}
- m_height = savedHeight;
+ setHeight(savedHeight);
}
- m_firstLine = !last;
+ firstLine = !last;
previousLineBrokeCleanly = !last || last->endsWithBreak();
RenderObject* startObj;
int pos = 0;
if (last) {
- m_height = last->blockHeight();
+ setHeight(last->blockHeight());
startObj = last->lineBreakObj();
pos = last->lineBreakPos();
resolver.setStatus(last->lineBreakBidiStatus());
@@ -1263,12 +1251,12 @@ RootInlineBox* RenderBlock::determineStartPosition(bool& fullLayout, InlineBidiR
#endif
;
- BidiContext* context = new BidiContext(ltr ? 0 : 1, ltr ? LeftToRight : RightToLeft, style()->unicodeBidi() == Override);
+ Direction direction = ltr ? LeftToRight : RightToLeft;
+ resolver.setLastStrongDir(direction);
+ resolver.setLastDir(direction);
+ resolver.setEorDir(direction);
+ resolver.setContext(BidiContext::create(ltr ? 0 : 1, direction, style()->unicodeBidi() == Override));
- resolver.setLastStrongDir(context->dir());
- resolver.setLastDir(context->dir());
- resolver.setEorDir(context->dir());
- resolver.setContext(context);
startObj = bidiFirst(this, &resolver);
}
@@ -1312,12 +1300,12 @@ bool RenderBlock::matchedEndLine(const InlineBidiResolver& resolver, const Inlin
if (resolver.status() != endLineStatus)
return false;
- int delta = m_height - endYPos;
+ int delta = height() - endYPos;
if (!delta || !m_floatingObjects)
return true;
// See if any floats end in the range along which we want to shift the lines vertically.
- int top = min(m_height, endYPos);
+ int top = min(height(), endYPos);
RootInlineBox* lastLine = endLine;
while (RootInlineBox* nextLine = lastLine->nextRootBox())
@@ -1348,10 +1336,10 @@ bool RenderBlock::matchedEndLine(const InlineBidiResolver& resolver, const Inlin
if (result)
endYPos = line->blockHeight();
- int delta = m_height - endYPos;
+ int delta = height() - endYPos;
if (delta && m_floatingObjects) {
// See if any floats end in the range along which we want to shift the lines vertically.
- int top = min(m_height, endYPos);
+ int top = min(height(), endYPos);
RootInlineBox* lastLine = endLine;
while (RootInlineBox* nextLine = lastLine->nextRootBox())
@@ -1384,7 +1372,7 @@ bool RenderBlock::matchedEndLine(const InlineBidiResolver& resolver, const Inlin
return false;
}
-static inline bool skipNonBreakingSpace(const InlineIterator& it)
+static inline bool skipNonBreakingSpace(const InlineIterator& it, bool isLineEmpty, bool previousLineBrokeCleanly)
{
if (it.obj->style()->nbspMode() != SPACE || it.current() != noBreakSpace)
return false;
@@ -1400,7 +1388,7 @@ static inline bool skipNonBreakingSpace(const InlineIterator& it)
return true;
}
-static inline bool shouldCollapseWhiteSpace(const RenderStyle* style)
+static inline bool shouldCollapseWhiteSpace(const RenderStyle* style, bool isLineEmpty, bool previousLineBrokeCleanly)
{
return style->collapseWhiteSpace() || (style->whiteSpace() == PRE_WRAP && (!isLineEmpty || !previousLineBrokeCleanly));
}
@@ -1415,35 +1403,36 @@ static inline bool shouldPreserveNewline(RenderObject* object)
return object->style()->preserveNewline();
}
-static bool inlineFlowRequiresLineBox(RenderObject* flow)
+static bool inlineFlowRequiresLineBox(RenderInline* flow)
{
// FIXME: Right now, we only allow line boxes for inlines that are truly empty.
// We need to fix this, though, because at the very least, inlines containing only
// ignorable whitespace should should also have line boxes.
- return flow->isInlineFlow() && !flow->firstChild() && flow->hasHorizontalBordersPaddingOrMargin();
+ return !flow->firstChild() && flow->hasHorizontalBordersPaddingOrMargin();
}
-static inline bool requiresLineBox(const InlineIterator& it)
+static inline bool requiresLineBox(const InlineIterator& it, bool isLineEmpty, bool previousLineBrokeCleanly)
{
if (it.obj->isFloatingOrPositioned())
return false;
- if (it.obj->isInlineFlow() && !inlineFlowRequiresLineBox(it.obj))
+ if (it.obj->isRenderInline() && !inlineFlowRequiresLineBox(toRenderInline(it.obj)))
return false;
- if (!shouldCollapseWhiteSpace(it.obj->style()) || it.obj->isBR())
+ if (!shouldCollapseWhiteSpace(it.obj->style(), isLineEmpty, previousLineBrokeCleanly) || it.obj->isBR())
return true;
UChar current = it.current();
- return current != ' ' && current != '\t' && current != softHyphen && (current != '\n' || shouldPreserveNewline(it.obj)) && !skipNonBreakingSpace(it);
+ return current != ' ' && current != '\t' && current != softHyphen && (current != '\n' || shouldPreserveNewline(it.obj))
+ && !skipNonBreakingSpace(it, isLineEmpty, previousLineBrokeCleanly);
}
-bool RenderBlock::generatesLineBoxesForInlineChild(RenderObject* inlineObj)
+bool RenderBlock::generatesLineBoxesForInlineChild(RenderObject* inlineObj, bool isLineEmpty, bool previousLineBrokeCleanly)
{
ASSERT(inlineObj->parent() == this);
InlineIterator it(this, inlineObj, 0);
- while (!it.atEnd() && !requiresLineBox(it))
+ while (!it.atEnd() && !requiresLineBox(it, isLineEmpty, previousLineBrokeCleanly))
it.increment();
return !it.atEnd();
@@ -1455,68 +1444,70 @@ bool RenderBlock::generatesLineBoxesForInlineChild(RenderObject* inlineObj)
// object iteration process.
// NB. this function will insert any floating elements that would otherwise
// be skipped but it will not position them.
-void RenderBlock::skipTrailingWhitespace(InlineIterator& iterator)
+void RenderBlock::skipTrailingWhitespace(InlineIterator& iterator, bool isLineEmpty, bool previousLineBrokeCleanly)
{
- while (!iterator.atEnd() && !requiresLineBox(iterator)) {
+ while (!iterator.atEnd() && !requiresLineBox(iterator, isLineEmpty, previousLineBrokeCleanly)) {
RenderObject* object = iterator.obj;
if (object->isFloating()) {
- insertFloatingObject(object);
+ insertFloatingObject(toRenderBox(object));
} else if (object->isPositioned()) {
// FIXME: The math here is actually not really right. It's a best-guess approximation that
// will work for the common cases
RenderObject* c = object->container();
- if (c->isInlineFlow()) {
+ if (c->isRenderInline()) {
// A relative positioned inline encloses us. In this case, we also have to determine our
// position as though we were an inline. Set |staticX| and |staticY| on the relative positioned
// inline so that we can obtain the value later.
- c->setStaticX(style()->direction() == LTR ? leftOffset(m_height) : rightOffset(m_height));
- c->setStaticY(m_height);
+ toRenderInline(c)->layer()->setStaticX(style()->direction() == LTR ? leftOffset(height(), false) : rightOffset(height(), false));
+ toRenderInline(c)->layer()->setStaticY(height());
}
- if (object->hasStaticX()) {
- if (object->style()->isOriginalDisplayInlineType())
- object->setStaticX(style()->direction() == LTR ? leftOffset(m_height) : width() - rightOffset(m_height));
+ RenderBox* box = toRenderBox(object);
+ if (box->style()->hasStaticX()) {
+ if (box->style()->isOriginalDisplayInlineType())
+ box->layer()->setStaticX(style()->direction() == LTR ? leftOffset(height(), false) : width() - rightOffset(height(), false));
else
- object->setStaticX(style()->direction() == LTR ? borderLeft() + paddingLeft() : borderRight() + paddingRight());
+ box->layer()->setStaticX(style()->direction() == LTR ? borderLeft() + paddingLeft() : borderRight() + paddingRight());
}
- if (object->hasStaticY())
- object->setStaticY(m_height);
+ if (box->style()->hasStaticY())
+ box->layer()->setStaticY(height());
}
iterator.increment();
}
}
-int RenderBlock::skipLeadingWhitespace(InlineBidiResolver& resolver)
+int RenderBlock::skipLeadingWhitespace(InlineBidiResolver& resolver, bool firstLine, bool isLineEmpty, bool previousLineBrokeCleanly)
{
- int availableWidth = lineWidth(m_height);
- while (!resolver.position().atEnd() && !requiresLineBox(resolver.position())) {
+ int availableWidth = lineWidth(height(), firstLine);
+ while (!resolver.position().atEnd() && !requiresLineBox(resolver.position(), isLineEmpty, previousLineBrokeCleanly)) {
RenderObject* object = resolver.position().obj;
if (object->isFloating()) {
- insertFloatingObject(object);
+ insertFloatingObject(toRenderBox(object));
positionNewFloats();
- availableWidth = lineWidth(m_height);
+ availableWidth = lineWidth(height(), firstLine);
} else if (object->isPositioned()) {
// FIXME: The math here is actually not really right. It's a best-guess approximation that
// will work for the common cases
RenderObject* c = object->container();
- if (c->isInlineFlow()) {
+ if (c->isRenderInline()) {
// A relative positioned inline encloses us. In this case, we also have to determine our
// position as though we were an inline. Set |staticX| and |staticY| on the relative positioned
// inline so that we can obtain the value later.
- c->setStaticX(style()->direction() == LTR ? leftOffset(m_height) : rightOffset(m_height));
- c->setStaticY(m_height);
+ toRenderInline(c)->layer()->setStaticX(style()->direction() == LTR ? leftOffset(height(), firstLine) : rightOffset(height(), firstLine));
+ toRenderInline(c)->layer()->setStaticY(height());
}
- if (object->hasStaticX()) {
- if (object->style()->isOriginalDisplayInlineType())
- object->setStaticX(style()->direction() == LTR ? leftOffset(m_height) : width() - rightOffset(m_height));
+ RenderBox* box = toRenderBox(object);
+ if (box->style()->hasStaticX()) {
+ if (box->style()->isOriginalDisplayInlineType())
+ box->layer()->setStaticX(style()->direction() == LTR ? leftOffset(height(), firstLine) : width() - rightOffset(height(), firstLine));
else
- object->setStaticX(style()->direction() == LTR ? borderLeft() + paddingLeft() : borderRight() + paddingRight());
+ box->layer()->setStaticX(style()->direction() == LTR ? borderLeft() + paddingLeft() : borderRight() + paddingRight());
}
- if (object->hasStaticY())
- object->setStaticY(m_height);
+ if (box->style()->hasStaticY())
+ box->layer()->setStaticY(height());
}
resolver.increment();
}
@@ -1526,14 +1517,14 @@ int RenderBlock::skipLeadingWhitespace(InlineBidiResolver& resolver)
// This is currently just used for list markers and inline flows that have line boxes. Neither should
// have an effect on whitespace at the start of the line.
-static bool shouldSkipWhitespaceAfterStartObject(RenderBlock* block, RenderObject* o)
+static bool shouldSkipWhitespaceAfterStartObject(RenderBlock* block, RenderObject* o, LineMidpointState& lineMidpointState)
{
RenderObject* next = bidiNext(block, o);
- if (next && !next->isBR() && next->isText() && static_cast<RenderText*>(next)->textLength() > 0) {
- RenderText* nextText = static_cast<RenderText*>(next);
+ if (next && !next->isBR() && next->isText() && toRenderText(next)->textLength() > 0) {
+ RenderText* nextText = toRenderText(next);
UChar nextChar = nextText->characters()[0];
if (nextText->style()->isCollapsibleWhiteSpace(nextChar)) {
- addMidpoint(InlineIterator(0, o, 0));
+ addMidpoint(lineMidpointState, InlineIterator(0, o, 0));
return true;
}
}
@@ -1541,37 +1532,46 @@ static bool shouldSkipWhitespaceAfterStartObject(RenderBlock* block, RenderObjec
return false;
}
-void RenderBlock::fitBelowFloats(int widthToFit, int& availableWidth)
+void RenderBlock::fitBelowFloats(int widthToFit, bool firstLine, int& availableWidth)
{
ASSERT(widthToFit > availableWidth);
int floatBottom;
- int lastFloatBottom = m_height;
+ int lastFloatBottom = height();
int newLineWidth = availableWidth;
while (true) {
floatBottom = nextFloatBottomBelow(lastFloatBottom);
if (!floatBottom)
break;
- newLineWidth = lineWidth(floatBottom);
+ newLineWidth = lineWidth(floatBottom, firstLine);
lastFloatBottom = floatBottom;
if (newLineWidth >= widthToFit)
break;
}
if (newLineWidth > availableWidth) {
- m_height = lastFloatBottom;
+ setHeight(lastFloatBottom);
availableWidth = newLineWidth;
}
}
-InlineIterator RenderBlock::findNextLineBreak(InlineBidiResolver& resolver, EClear* clear)
+static inline unsigned textWidth(RenderText* text, unsigned from, unsigned len, const Font& font, int xPos, bool isFixedPitch, bool collapseWhiteSpace)
+{
+ if (isFixedPitch || (!from && len == text->textLength()))
+ return text->width(from, len, font, xPos);
+ return font.width(TextRun(text->characters() + from, len, !collapseWhiteSpace, xPos));
+}
+
+InlineIterator RenderBlock::findNextLineBreak(InlineBidiResolver& resolver, bool firstLine, bool& isLineEmpty, bool& previousLineBrokeCleanly,
+ EClear* clear)
{
ASSERT(resolver.position().block == this);
bool appliedStartWidth = resolver.position().pos > 0;
-
- int width = skipLeadingWhitespace(resolver);
+ LineMidpointState& lineMidpointState = resolver.midpointState();
+
+ int width = skipLeadingWhitespace(resolver, firstLine, isLineEmpty, previousLineBrokeCleanly);
int w = 0;
int tmpW = 0;
@@ -1653,22 +1653,24 @@ InlineIterator RenderBlock::findNextLineBreak(InlineBidiResolver& resolver, ECle
if (o->isFloatingOrPositioned()) {
// add to special objects...
if (o->isFloating()) {
- insertFloatingObject(o);
+ RenderBox* floatBox = toRenderBox(o);
+ insertFloatingObject(floatBox);
// 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 && o->width() + o->marginLeft() + o->marginRight() + w + tmpW <= width) {
+ if (floatsFitOnLine && floatBox->width() + floatBox->marginLeft() + floatBox->marginRight() + w + tmpW <= width) {
positionNewFloats();
- width = lineWidth(m_height);
+ width = lineWidth(height(), firstLine);
} else
floatsFitOnLine = false;
} else if (o->isPositioned()) {
// If our original display wasn't an inline type, then we can
// go ahead and determine our static x position now.
- bool isInlineType = o->style()->isOriginalDisplayInlineType();
- bool needToSetStaticX = o->hasStaticX();
- if (o->hasStaticX() && !isInlineType) {
- o->setStaticX(o->parent()->style()->direction() == LTR ?
+ RenderBox* box = toRenderBox(o);
+ bool isInlineType = box->style()->isOriginalDisplayInlineType();
+ bool needToSetStaticX = box->style()->hasStaticX();
+ if (box->style()->hasStaticX() && !isInlineType) {
+ box->layer()->setStaticX(o->parent()->style()->direction() == LTR ?
borderLeft() + paddingLeft() :
borderRight() + paddingRight());
needToSetStaticX = false;
@@ -1676,15 +1678,15 @@ InlineIterator RenderBlock::findNextLineBreak(InlineBidiResolver& resolver, ECle
// If our original display was an INLINE type, then we can go ahead
// and determine our static y position now.
- bool needToSetStaticY = o->hasStaticY();
- if (o->hasStaticY() && isInlineType) {
- o->setStaticY(m_height);
+ bool needToSetStaticY = box->style()->hasStaticY();
+ if (box->style()->hasStaticY() && isInlineType) {
+ box->layer()->setStaticY(height());
needToSetStaticY = false;
}
bool needToCreateLineBox = needToSetStaticX || needToSetStaticY;
RenderObject* c = o->container();
- if (c->isInlineFlow() && (!needToSetStaticX || !needToSetStaticY))
+ if (c->isRenderInline() && (!needToSetStaticX || !needToSetStaticY))
needToCreateLineBox = true;
// If we're ignoring spaces, we have to stop and include this object and
@@ -1694,28 +1696,30 @@ InlineIterator RenderBlock::findNextLineBreak(InlineBidiResolver& resolver, ECle
ignoreStart.obj = o;
ignoreStart.pos = 0;
if (ignoringSpaces) {
- addMidpoint(ignoreStart); // Stop ignoring spaces.
- addMidpoint(ignoreStart); // Start ignoring again.
+ addMidpoint(lineMidpointState, ignoreStart); // Stop ignoring spaces.
+ addMidpoint(lineMidpointState, ignoreStart); // Start ignoring again.
}
}
}
- } else if (o->isInlineFlow()) {
+ } else if (o->isRenderInline()) {
// Right now, we should only encounter empty inlines here.
ASSERT(!o->firstChild());
+ RenderInline* flowBox = toRenderInline(o);
+
// Now that some inline flows have line boxes, if we are already ignoring spaces, we need
// to make sure that we stop to include this object and then start ignoring spaces again.
// If this object is at the start of the line, we need to behave like list markers and
// start ignoring spaces.
- if (inlineFlowRequiresLineBox(o)) {
+ if (inlineFlowRequiresLineBox(flowBox)) {
isLineEmpty = false;
if (ignoringSpaces) {
trailingSpaceObject = 0;
- addMidpoint(InlineIterator(0, o, 0)); // Stop ignoring spaces.
- addMidpoint(InlineIterator(0, o, 0)); // Start ignoring again.
+ addMidpoint(lineMidpointState, InlineIterator(0, o, 0)); // Stop ignoring spaces.
+ addMidpoint(lineMidpointState, InlineIterator(0, o, 0)); // Start ignoring again.
} else if (style()->collapseWhiteSpace() && resolver.position().obj == o
- && shouldSkipWhitespaceAfterStartObject(this, o)) {
+ && shouldSkipWhitespaceAfterStartObject(this, o, lineMidpointState)) {
// Like with list markers, we start ignoring spaces to make sure that any
// additional spaces we see will be discarded.
currentCharacterIsSpace = true;
@@ -1724,9 +1728,11 @@ InlineIterator RenderBlock::findNextLineBreak(InlineBidiResolver& resolver, ECle
}
}
- tmpW += o->marginLeft() + o->borderLeft() + o->paddingLeft() +
- o->marginRight() + o->borderRight() + o->paddingRight();
+ tmpW += flowBox->marginLeft() + flowBox->borderLeft() + flowBox->paddingLeft() +
+ flowBox->marginRight() + flowBox->borderRight() + flowBox->paddingRight();
} 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;
@@ -1737,7 +1743,7 @@ InlineIterator RenderBlock::findNextLineBreak(InlineBidiResolver& resolver, ECle
}
if (ignoringSpaces)
- addMidpoint(InlineIterator(0, o, 0));
+ addMidpoint(lineMidpointState, InlineIterator(0, o, 0));
isLineEmpty = false;
ignoringSpaces = false;
@@ -1748,7 +1754,7 @@ InlineIterator RenderBlock::findNextLineBreak(InlineBidiResolver& resolver, ECle
// Optimize for a common case. If we can't find whitespace after the list
// item, then this is all moot. -dwh
if (o->isListMarker() && !static_cast<RenderListMarker*>(o)->isInside()) {
- if (style()->collapseWhiteSpace() && shouldSkipWhitespaceAfterStartObject(this, o)) {
+ if (style()->collapseWhiteSpace() && shouldSkipWhitespaceAfterStartObject(this, o, lineMidpointState)) {
// Like with inline flows, we start ignoring spaces to make sure that any
// additional spaces we see will be discarded.
currentCharacterIsSpace = true;
@@ -1756,18 +1762,19 @@ InlineIterator RenderBlock::findNextLineBreak(InlineBidiResolver& resolver, ECle
ignoringSpaces = true;
}
} else
- tmpW += o->width() + o->marginLeft() + o->marginRight() + inlineWidth(o);
+ tmpW += replacedBox->width() + replacedBox->marginLeft() + replacedBox->marginRight() + inlineWidth(o);
} else if (o->isText()) {
if (!pos)
appliedStartWidth = false;
- RenderText* t = static_cast<RenderText*>(o);
+ RenderText* t = toRenderText(o);
int strlen = t->textLength();
int len = strlen - pos;
const UChar* str = t->characters();
- const Font& f = t->style(m_firstLine)->font();
+ const Font& f = t->style(firstLine)->font();
+ bool isFixedPitch = f.isFixedPitch();
int lastSpace = pos;
int wordSpacing = o->style()->wordSpacing();
@@ -1808,24 +1815,25 @@ InlineIterator RenderBlock::findNextLineBreak(InlineBidiResolver& resolver, ECle
if (pos)
beforeSoftHyphen = InlineIterator(0, o, pos - 1);
else
- beforeSoftHyphen = InlineIterator(0, last, last->isText() ? static_cast<RenderText*>(last)->textLength() - 1 : 0);
+ beforeSoftHyphen = InlineIterator(0, last, last->isText() ? toRenderText(last)->textLength() - 1 : 0);
// Two consecutive soft hyphens. Avoid overlapping midpoints.
- if (sNumMidpoints && smidpoints->at(sNumMidpoints - 1).obj == o && smidpoints->at(sNumMidpoints - 1).pos == pos)
- sNumMidpoints--;
+ if (lineMidpointState.numMidpoints && lineMidpointState.midpoints[lineMidpointState.numMidpoints - 1].obj == o &&
+ lineMidpointState.midpoints[lineMidpointState.numMidpoints - 1].pos == pos)
+ lineMidpointState.numMidpoints--;
else
- addMidpoint(beforeSoftHyphen);
+ addMidpoint(lineMidpointState, beforeSoftHyphen);
// Add the width up to but not including the hyphen.
- tmpW += t->width(lastSpace, pos - lastSpace, f, w + tmpW) + lastSpaceWordSpacing;
+ tmpW += textWidth(t, lastSpace, pos - lastSpace, f, w + tmpW, isFixedPitch, collapseWhiteSpace) + lastSpaceWordSpacing;
// For wrapping text only, include the hyphen. We need to ensure it will fit
// on the line if it shows when we break.
if (autoWrap)
- tmpW += t->width(pos, 1, f, w + tmpW);
+ tmpW += textWidth(t, pos, 1, f, w + tmpW, isFixedPitch, collapseWhiteSpace);
InlineIterator afterSoftHyphen(0, o, pos);
afterSoftHyphen.increment();
- addMidpoint(afterSoftHyphen);
+ addMidpoint(lineMidpointState, afterSoftHyphen);
}
pos++;
@@ -1841,7 +1849,7 @@ InlineIterator RenderBlock::findNextLineBreak(InlineBidiResolver& resolver, ECle
if ((breakAll || breakWords) && !midWordBreak) {
wrapW += charWidth;
- charWidth = t->width(pos, 1, f, w + wrapW);
+ charWidth = textWidth(t, pos, 1, f, w + wrapW, isFixedPitch, collapseWhiteSpace);
midWordBreak = w + wrapW + charWidth > width;
}
@@ -1856,7 +1864,7 @@ InlineIterator RenderBlock::findNextLineBreak(InlineBidiResolver& resolver, ECle
ignoringSpaces = false;
lastSpaceWordSpacing = 0;
lastSpace = pos; // e.g., "Foo goo", don't add in any of the ignored spaces.
- addMidpoint(InlineIterator(0, o, pos));
+ addMidpoint(lineMidpointState, InlineIterator(0, o, pos));
stoppedIgnoringSpaces = true;
} else {
// Just keep ignoring these spaces.
@@ -1866,7 +1874,7 @@ InlineIterator RenderBlock::findNextLineBreak(InlineBidiResolver& resolver, ECle
}
}
- int additionalTmpW = t->width(lastSpace, pos - lastSpace, f, w+tmpW) + lastSpaceWordSpacing;
+ int additionalTmpW = textWidth(t, lastSpace, pos - lastSpace, f, w + tmpW, isFixedPitch, collapseWhiteSpace) + lastSpaceWordSpacing;
tmpW += additionalTmpW;
if (!appliedStartWidth) {
tmpW += inlineWidth(o, true, false);
@@ -1876,14 +1884,14 @@ InlineIterator RenderBlock::findNextLineBreak(InlineBidiResolver& resolver, ECle
applyWordSpacing = wordSpacing && currentCharacterIsSpace && !previousCharacterIsSpace;
if (!w && autoWrap && tmpW > width)
- fitBelowFloats(tmpW, width);
+ fitBelowFloats(tmpW, firstLine, width);
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 = t->width(pos, 1, f, w + tmpW) + (applyWordSpacing ? wordSpacing : 0);
+ int charWidth = textWidth(t, pos, 1, f, w + tmpW, 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,
@@ -1894,15 +1902,15 @@ InlineIterator RenderBlock::findNextLineBreak(InlineBidiResolver& resolver, ECle
lBreak.obj = o;
lBreak.pos = pos;
lBreak.nextBreakablePosition = nextBreakable;
- skipTrailingWhitespace(lBreak);
+ skipTrailingWhitespace(lBreak, isLineEmpty, previousLineBrokeCleanly);
}
}
if (lineWasTooWide || w + tmpW > width) {
- if (lBreak.obj && shouldPreserveNewline(lBreak.obj) && lBreak.obj->isText() && !static_cast<RenderText*>(lBreak.obj)->isWordBreak() && static_cast<RenderText*>(lBreak.obj)->characters()[lBreak.pos] == '\n') {
+ if (lBreak.obj && shouldPreserveNewline(lBreak.obj) && lBreak.obj->isText() && !toRenderText(lBreak.obj)->isWordBreak() && toRenderText(lBreak.obj)->characters()[lBreak.pos] == '\n') {
if (!stoppedIgnoringSpaces && pos > 0) {
// We need to stop right before the newline and then start up again.
- addMidpoint(InlineIterator(0, o, pos - 1)); // Stop
- addMidpoint(InlineIterator(0, o, pos)); // Start
+ addMidpoint(lineMidpointState, InlineIterator(0, o, pos - 1)); // Stop
+ addMidpoint(lineMidpointState, InlineIterator(0, o, pos)); // Start
}
lBreak.increment();
previousLineBrokeCleanly = true;
@@ -1913,15 +1921,15 @@ InlineIterator RenderBlock::findNextLineBreak(InlineBidiResolver& resolver, ECle
tmpW -= additionalTmpW;
if (pos > 0 && str[pos-1] == softHyphen)
// Subtract the width of the soft hyphen out since we fit on a line.
- tmpW -= t->width(pos-1, 1, f, w+tmpW);
+ tmpW -= textWidth(t, pos - 1, 1, f, w + tmpW, isFixedPitch, collapseWhiteSpace);
}
}
if (c == '\n' && preserveNewline) {
if (!stoppedIgnoringSpaces && pos > 0) {
// We need to stop right before the newline and then start up again.
- addMidpoint(InlineIterator(0, o, pos - 1)); // Stop
- addMidpoint(InlineIterator(0, o, pos)); // Start
+ addMidpoint(lineMidpointState, InlineIterator(0, o, pos - 1)); // Stop
+ addMidpoint(lineMidpointState, InlineIterator(0, o, pos)); // Start
}
lBreak.obj = o;
lBreak.pos = pos;
@@ -1967,7 +1975,7 @@ InlineIterator RenderBlock::findNextLineBreak(InlineBidiResolver& resolver, ECle
// We just entered a mode where we are ignoring
// spaces. Create a midpoint to terminate the run
// before the second space.
- addMidpoint(ignoreStart);
+ addMidpoint(lineMidpointState, ignoreStart);
}
}
} else if (ignoringSpaces) {
@@ -1976,7 +1984,7 @@ InlineIterator RenderBlock::findNextLineBreak(InlineBidiResolver& resolver, ECle
ignoringSpaces = false;
lastSpaceWordSpacing = applyWordSpacing ? wordSpacing : 0;
lastSpace = pos; // e.g., "Foo goo", don't add in any of the ignored spaces.
- addMidpoint(InlineIterator(0, o, pos));
+ addMidpoint(lineMidpointState, InlineIterator(0, o, pos));
}
if (currentCharacterIsSpace && !previousCharacterIsSpace) {
@@ -2004,7 +2012,7 @@ InlineIterator RenderBlock::findNextLineBreak(InlineBidiResolver& resolver, ECle
// IMPORTANT: pos is > length here!
if (!ignoringSpaces)
- tmpW += t->width(lastSpace, pos - lastSpace, f, w+tmpW) + lastSpaceWordSpacing;
+ tmpW += textWidth(t, lastSpace, pos - lastSpace, f, w + tmpW, isFixedPitch, collapseWhiteSpace) + lastSpaceWordSpacing;
tmpW += inlineWidth(o, !appliedStartWidth, true);
} else
ASSERT_NOT_REACHED();
@@ -2019,7 +2027,7 @@ InlineIterator RenderBlock::findNextLineBreak(InlineBidiResolver& resolver, ECle
checkForBreak = true;
else {
checkForBreak = false;
- RenderText* nextText = static_cast<RenderText*>(next);
+ RenderText* nextText = toRenderText(next);
if (nextText->textLength()) {
UChar c = nextText->characters()[0];
if (c == ' ' || c == '\t' || (c == '\n' && !shouldPreserveNewline(next)))
@@ -2031,7 +2039,7 @@ InlineIterator RenderBlock::findNextLineBreak(InlineBidiResolver& resolver, ECle
checkForBreak = true;
bool willFitOnLine = w + tmpW <= width;
if (!willFitOnLine && !w) {
- fitBelowFloats(tmpW, width);
+ fitBelowFloats(tmpW, firstLine, width);
willFitOnLine = tmpW <= width;
}
bool canPlaceOnLine = willFitOnLine || !autoWrapWasEverTrueOnLine;
@@ -2054,7 +2062,7 @@ InlineIterator RenderBlock::findNextLineBreak(InlineBidiResolver& resolver, ECle
if (w)
goto end;
- fitBelowFloats(tmpW, width);
+ fitBelowFloats(tmpW, firstLine, width);
// |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
@@ -2094,8 +2102,7 @@ InlineIterator RenderBlock::findNextLineBreak(InlineBidiResolver& resolver, ECle
}
end:
-
- if (lBreak == resolver.position() && !lBreak.obj->isBR()) {
+ if (lBreak == resolver.position() && (!lBreak.obj || !lBreak.obj->isBR())) {
// we just add as much as possible
if (style()->whiteSpace() == PRE) {
// FIXME: Don't really understand this case.
@@ -2129,25 +2136,25 @@ InlineIterator RenderBlock::findNextLineBreak(InlineBidiResolver& resolver, ECle
lBreak.increment();
// Sanity check our midpoints.
- checkMidpoints(lBreak);
+ checkMidpoints(lineMidpointState, lBreak);
if (trailingSpaceObject) {
// This object is either going to be part of the last midpoint, or it is going
// to be the actual endpoint. In both cases we just decrease our pos by 1 level to
// exclude the space, allowing it to - in effect - collapse into the newline.
- if (sNumMidpoints%2==1) {
- InlineIterator* midpoints = smidpoints->data();
- midpoints[sNumMidpoints-1].pos--;
+ if (lineMidpointState.numMidpoints % 2) {
+ InlineIterator* midpoints = lineMidpointState.midpoints.data();
+ midpoints[lineMidpointState.numMidpoints - 1].pos--;
}
//else if (lBreak.pos > 0)
// lBreak.pos--;
else if (lBreak.obj == 0 && trailingSpaceObject->isText()) {
// Add a new end midpoint that stops right at the very end.
- RenderText* text = static_cast<RenderText *>(trailingSpaceObject);
+ RenderText* text = toRenderText(trailingSpaceObject);
unsigned length = text->textLength();
unsigned pos = length >= 2 ? length - 2 : UINT_MAX;
InlineIterator endMid(0, trailingSpaceObject, pos);
- addMidpoint(endMid);
+ addMidpoint(lineMidpointState, endMid);
}
}
@@ -2163,9 +2170,9 @@ InlineIterator RenderBlock::findNextLineBreak(InlineBidiResolver& resolver, ECle
if (lBreak.obj && lBreak.pos >= 2 && lBreak.obj->isText()) {
// For soft hyphens on line breaks, we have to chop out the midpoints that made us
// ignore the hyphen so that it will render at the end of the line.
- UChar c = static_cast<RenderText*>(lBreak.obj)->characters()[lBreak.pos-1];
+ UChar c = toRenderText(lBreak.obj)->characters()[lBreak.pos - 1];
if (c == softHyphen)
- chopMidpointsAt(lBreak.obj, lBreak.pos-2);
+ chopMidpointsAt(lineMidpointState, lBreak.obj, lBreak.pos - 2);
}
return lBreak;
@@ -2173,7 +2180,7 @@ InlineIterator RenderBlock::findNextLineBreak(InlineBidiResolver& resolver, ECle
void RenderBlock::checkLinesForOverflow()
{
- m_overflowWidth = m_width;
+ m_overflowWidth = width();
for (RootInlineBox* curr = firstRootBox(); curr; curr = curr->nextRootBox()) {
m_overflowLeft = min(curr->leftOverflow(), m_overflowLeft);
m_overflowTop = min(curr->topOverflow(), m_overflowTop);
@@ -2205,16 +2212,18 @@ void RenderBlock::checkLinesForTextOverflow()
// Include the scrollbar for overflow blocks, which means we want to use "contentWidth()"
bool ltr = style()->direction() == LTR;
for (RootInlineBox* curr = firstRootBox(); curr; curr = curr->nextRootBox()) {
- int blockEdge = ltr ? rightOffset(curr->yPos()) : leftOffset(curr->yPos());
- int lineBoxEdge = ltr ? curr->xPos() + curr->width() : curr->xPos();
- if ((ltr && lineBoxEdge > blockEdge) || (!ltr && lineBoxEdge < blockEdge)) {
+ int blockRightEdge = rightOffset(curr->y(), curr == firstRootBox());
+ int blockLeftEdge = leftOffset(curr->y(), curr == firstRootBox());
+ int lineBoxEdge = ltr ? curr->x() + curr->width() : curr->x();
+ if ((ltr && lineBoxEdge > blockRightEdge) || (!ltr && lineBoxEdge < blockLeftEdge)) {
// This line spills out of our box in the appropriate direction. Now we need to see if the line
// can be truncated. In order for truncation to be possible, the line must have sufficient space to
// accommodate our truncation string, and no replaced elements (images, tables) can overlap the ellipsis
// space.
int width = curr == firstRootBox() ? firstLineEllipsisWidth : ellipsisWidth;
+ int blockEdge = ltr ? blockRightEdge : blockLeftEdge;
if (curr->canAccommodateEllipsis(ltr, blockEdge, lineBoxEdge, width))
- curr->placeEllipsis(ellipsisStr, ltr, blockEdge, width);
+ curr->placeEllipsis(ellipsisStr, ltr, blockLeftEdge, blockRightEdge, width);
}
}
}
diff --git a/src/3rdparty/webkit/WebCore/rendering/bidi.h b/src/3rdparty/webkit/WebCore/rendering/bidi.h
index fc6de5b..9058eeb 100644
--- a/src/3rdparty/webkit/WebCore/rendering/bidi.h
+++ b/src/3rdparty/webkit/WebCore/rendering/bidi.h
@@ -38,7 +38,6 @@ struct BidiRun : BidiCharacterRun {
: BidiCharacterRun(start, stop, context, dir)
, m_object(object)
, m_box(0)
- , m_compact(false)
{
}
@@ -59,7 +58,6 @@ private:
public:
RenderObject* m_object;
InlineBox* m_box;
- bool m_compact;
};
} // namespace WebCore
diff --git a/src/3rdparty/webkit/WebCore/rendering/break_lines.cpp b/src/3rdparty/webkit/WebCore/rendering/break_lines.cpp
index 05748ac..9b46cd2 100644
--- a/src/3rdparty/webkit/WebCore/rendering/break_lines.cpp
+++ b/src/3rdparty/webkit/WebCore/rendering/break_lines.cpp
@@ -68,7 +68,7 @@ static inline bool needsLineBreakIterator(UChar ch)
return ch > 0x7F && ch != noBreakSpace;
}
-#ifdef BUILDING_ON_TIGER
+#if PLATFORM(MAC) && defined(BUILDING_ON_TIGER)
static inline TextBreakLocatorRef lineBreakLocator()
{
TextBreakLocatorRef locator = 0;
@@ -79,7 +79,7 @@ static inline TextBreakLocatorRef lineBreakLocator()
int nextBreakablePosition(const UChar* str, int pos, int len, bool treatNoBreakSpaceAsBreak)
{
-#ifndef BUILDING_ON_TIGER
+#if !PLATFORM(MAC) || !defined(BUILDING_ON_TIGER)
TextBreakIterator* breakIterator = 0;
#endif
int nextBreak = -1;
@@ -93,7 +93,7 @@ int nextBreakablePosition(const UChar* str, int pos, int len, bool treatNoBreakS
if (needsLineBreakIterator(ch) || needsLineBreakIterator(lastCh)) {
if (nextBreak < i && i) {
-#ifndef BUILDING_ON_TIGER
+#if !PLATFORM(MAC) || !defined(BUILDING_ON_TIGER)
if (!breakIterator)
breakIterator = lineBreakIterator(str, len);
if (breakIterator)
diff --git a/src/3rdparty/webkit/WebCore/rendering/style/ContentData.cpp b/src/3rdparty/webkit/WebCore/rendering/style/ContentData.cpp
index b38cc49..410cad4 100644
--- a/src/3rdparty/webkit/WebCore/rendering/style/ContentData.cpp
+++ b/src/3rdparty/webkit/WebCore/rendering/style/ContentData.cpp
@@ -30,22 +30,9 @@ namespace WebCore {
void ContentData::clear()
{
- switch (m_type) {
- case CONTENT_NONE:
- break;
- case CONTENT_OBJECT:
- m_content.m_image->deref();
- break;
- case CONTENT_TEXT:
- m_content.m_text->deref();
- break;
- case CONTENT_COUNTER:
- delete m_content.m_counter;
- break;
- }
+ deleteContent();
ContentData* n = m_next;
- m_type = CONTENT_NONE;
m_next = 0;
// Reverse the list so we can delete without recursing.
@@ -63,4 +50,47 @@ void ContentData::clear()
}
}
+bool ContentData::dataEquivalent(const ContentData& other) const
+{
+ if (type() != other.type())
+ return false;
+
+ switch (type()) {
+ case CONTENT_NONE:
+ return true;
+ break;
+ case CONTENT_TEXT:
+ return equal(text(), other.text());
+ break;
+ case CONTENT_OBJECT:
+ return StyleImage::imagesEquivalent(image(), other.image());
+ break;
+ case CONTENT_COUNTER:
+ return *counter() == *other.counter();
+ break;
+ }
+
+ ASSERT_NOT_REACHED();
+ return false;
+}
+
+void ContentData::deleteContent()
+{
+ switch (m_type) {
+ case CONTENT_NONE:
+ break;
+ case CONTENT_OBJECT:
+ m_content.m_image->deref();
+ break;
+ case CONTENT_TEXT:
+ m_content.m_text->deref();
+ break;
+ case CONTENT_COUNTER:
+ delete m_content.m_counter;
+ break;
+ }
+
+ m_type = CONTENT_NONE;
+}
+
} // namespace WebCore
diff --git a/src/3rdparty/webkit/WebCore/rendering/style/ContentData.h b/src/3rdparty/webkit/WebCore/rendering/style/ContentData.h
index d924d1a..24d5f86 100644
--- a/src/3rdparty/webkit/WebCore/rendering/style/ContentData.h
+++ b/src/3rdparty/webkit/WebCore/rendering/style/ContentData.h
@@ -25,16 +25,18 @@
#ifndef ContentData_h
#define ContentData_h
+#include "PlatformString.h"
#include "RenderStyleConstants.h"
+#include "StringImpl.h"
+#include "StyleImage.h"
#include <wtf/Noncopyable.h>
namespace WebCore {
class CounterContent;
-class StringImpl;
-class StyleImage;
struct ContentData : Noncopyable {
+public:
ContentData()
: m_type(CONTENT_NONE)
, m_next(0)
@@ -48,7 +50,49 @@ struct ContentData : Noncopyable {
void clear();
- ContentType m_type;
+ bool isCounter() const { return m_type == CONTENT_COUNTER; }
+ bool isImage() const { return m_type == CONTENT_OBJECT; }
+ bool isNone() const { return m_type == CONTENT_NONE; }
+ bool isText() const { return m_type == CONTENT_TEXT; }
+
+ StyleContentType type() const { return m_type; }
+
+ bool dataEquivalent(const ContentData&) const;
+
+ StyleImage* image() const { return m_content.m_image; }
+ void setImage(PassRefPtr<StyleImage> image)
+ {
+ deleteContent();
+ m_type = CONTENT_OBJECT;
+ m_content.m_image = image.releaseRef();
+ }
+
+ StringImpl* text() const { return m_content.m_text; }
+ void setText(PassRefPtr<StringImpl> text)
+ {
+ deleteContent();
+ m_type = CONTENT_TEXT;
+ m_content.m_text = text.releaseRef();
+ }
+
+ CounterContent* counter() const { return m_content.m_counter; }
+ void setCounter(CounterContent* counter)
+ {
+ deleteContent();
+ m_type = CONTENT_COUNTER;
+ m_content.m_counter = counter;
+ }
+
+ ContentData* next() const { return m_next; }
+ void setNext(ContentData* next)
+ {
+ m_next = next;
+ }
+
+private:
+ void deleteContent();
+
+ StyleContentType m_type;
union {
StyleImage* m_image;
StringImpl* m_text;
diff --git a/src/3rdparty/webkit/WebCore/rendering/style/CounterContent.h b/src/3rdparty/webkit/WebCore/rendering/style/CounterContent.h
index 06440ad..cf11813 100644
--- a/src/3rdparty/webkit/WebCore/rendering/style/CounterContent.h
+++ b/src/3rdparty/webkit/WebCore/rendering/style/CounterContent.h
@@ -49,11 +49,11 @@ private:
AtomicString m_separator;
};
-static inline bool operator!=(const CounterContent& a, const CounterContent& b)
+static inline bool operator==(const CounterContent& a, const CounterContent& b)
{
- return a.identifier() != b.identifier()
- || a.listStyle() != b.listStyle()
- || a.separator() != b.separator();
+ return a.identifier() == b.identifier()
+ && a.listStyle() == b.listStyle()
+ && a.separator() == b.separator();
}
diff --git a/src/3rdparty/webkit/WebCore/rendering/style/RenderStyle.cpp b/src/3rdparty/webkit/WebCore/rendering/style/RenderStyle.cpp
index 872ee9c..e4027db 100644
--- a/src/3rdparty/webkit/WebCore/rendering/style/RenderStyle.cpp
+++ b/src/3rdparty/webkit/WebCore/rendering/style/RenderStyle.cpp
@@ -32,9 +32,9 @@
#include <wtf/StdLibExtras.h>
#include <algorithm>
-namespace WebCore {
+using namespace std;
-TransformOperations RenderStyle::s_initialTransform;
+namespace WebCore {
inline RenderStyle* defaultStyle()
{
@@ -58,14 +58,7 @@ PassRefPtr<RenderStyle> RenderStyle::clone(const RenderStyle* other)
}
RenderStyle::RenderStyle()
- : box(defaultStyle()->box)
- , visual(defaultStyle()->visual)
- , background(defaultStyle()->background)
- , surround(defaultStyle()->surround)
- , rareNonInheritedData(defaultStyle()->rareNonInheritedData)
- , rareInheritedData(defaultStyle()->rareInheritedData)
- , inherited(defaultStyle()->inherited)
- , m_pseudoState(PseudoUnknown)
+ : m_pseudoState(PseudoUnknown)
, m_affectedByAttributeSelectors(false)
, m_unique(false)
, m_affectedByEmpty(false)
@@ -78,6 +71,13 @@ RenderStyle::RenderStyle()
, m_firstChildState(false)
, m_lastChildState(false)
, m_childIndex(0)
+ , box(defaultStyle()->box)
+ , visual(defaultStyle()->visual)
+ , background(defaultStyle()->background)
+ , surround(defaultStyle()->surround)
+ , rareNonInheritedData(defaultStyle()->rareNonInheritedData)
+ , rareInheritedData(defaultStyle()->rareInheritedData)
+ , inherited(defaultStyle()->inherited)
#if ENABLE(SVG)
, m_svgStyle(defaultStyle()->m_svgStyle)
#endif
@@ -121,15 +121,6 @@ RenderStyle::RenderStyle(bool)
RenderStyle::RenderStyle(const RenderStyle& o)
: RefCounted<RenderStyle>()
- , inherited_flags(o.inherited_flags)
- , noninherited_flags(o.noninherited_flags)
- , box(o.box)
- , visual(o.visual)
- , background(o.background)
- , surround(o.surround)
- , rareNonInheritedData(o.rareNonInheritedData)
- , rareInheritedData(o.rareInheritedData)
- , inherited(o.inherited)
, m_pseudoState(o.m_pseudoState)
, m_affectedByAttributeSelectors(false)
, m_unique(false)
@@ -143,9 +134,18 @@ RenderStyle::RenderStyle(const RenderStyle& o)
, m_firstChildState(false)
, m_lastChildState(false)
, m_childIndex(0)
+ , box(o.box)
+ , visual(o.visual)
+ , background(o.background)
+ , surround(o.surround)
+ , rareNonInheritedData(o.rareNonInheritedData)
+ , rareInheritedData(o.rareInheritedData)
+ , inherited(o.inherited)
#if ENABLE(SVG)
, m_svgStyle(o.m_svgStyle)
#endif
+ , inherited_flags(o.inherited_flags)
+ , noninherited_flags(o.noninherited_flags)
{
}
@@ -187,7 +187,7 @@ bool RenderStyle::isStyleAvailable() const
return this != CSSStyleSelector::styleNotYetAvailable();
}
-static inline int pseudoBit(RenderStyle::PseudoId pseudo)
+static inline int pseudoBit(PseudoId pseudo)
{
return 1 << (pseudo - 1);
}
@@ -206,7 +206,7 @@ void RenderStyle::setHasPseudoStyle(PseudoId pseudo)
noninherited_flags._pseudoBits |= pseudoBit(pseudo);
}
-RenderStyle* RenderStyle::getCachedPseudoStyle(PseudoId pid)
+RenderStyle* RenderStyle::getCachedPseudoStyle(PseudoId pid) const
{
if (!m_cachedPseudoStyle || styleType() != NOPSEUDO)
return 0;
@@ -225,7 +225,7 @@ RenderStyle* RenderStyle::addCachedPseudoStyle(PassRefPtr<RenderStyle> pseudo)
return m_cachedPseudoStyle.get();
}
-bool RenderStyle::inheritedNotEqual(RenderStyle* other) const
+bool RenderStyle::inheritedNotEqual(const RenderStyle* other) const
{
return inherited_flags != other->inherited_flags ||
inherited != other->inherited ||
@@ -235,7 +235,7 @@ bool RenderStyle::inheritedNotEqual(RenderStyle* other) const
rareInheritedData != other->rareInheritedData;
}
-bool positionedObjectMoved(const LengthBox& a, const LengthBox& b)
+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.
@@ -273,14 +273,16 @@ bool positionedObjectMoved(const LengthBox& a, const LengthBox& b)
optimisations are unimplemented, and currently result in the
worst case result causing a relayout of the containing block.
*/
-RenderStyle::Diff RenderStyle::diff(const RenderStyle* other) const
+StyleDifference RenderStyle::diff(const RenderStyle* other, unsigned& changedContextSensitiveProperties) const
{
+ changedContextSensitiveProperties = ContextSensitivePropertyNone;
+
#if ENABLE(SVG)
// This is horribly inefficient. Eventually we'll have to integrate
// this more directly by calling: Diff svgDiff = svgStyle->diff(other)
// and then checking svgDiff and returning from the appropriate places below.
if (m_svgStyle != other->m_svgStyle)
- return Layout;
+ return StyleDifferenceLayout;
#endif
if (box->width != other->box->width ||
@@ -289,19 +291,19 @@ RenderStyle::Diff RenderStyle::diff(const RenderStyle* other) const
box->height != other->box->height ||
box->min_height != other->box->min_height ||
box->max_height != other->box->max_height)
- return Layout;
+ return StyleDifferenceLayout;
if (box->vertical_align != other->box->vertical_align || noninherited_flags._vertical_align != other->noninherited_flags._vertical_align)
- return Layout;
+ return StyleDifferenceLayout;
if (box->boxSizing != other->box->boxSizing)
- return Layout;
+ return StyleDifferenceLayout;
if (surround->margin != other->surround->margin)
- return Layout;
+ return StyleDifferenceLayout;
if (surround->padding != other->surround->padding)
- return Layout;
+ return StyleDifferenceLayout;
if (rareNonInheritedData.get() != other->rareNonInheritedData.get()) {
if (rareNonInheritedData->m_appearance != other->rareNonInheritedData->m_appearance ||
@@ -309,30 +311,47 @@ RenderStyle::Diff RenderStyle::diff(const RenderStyle* other) const
rareNonInheritedData->marginBottomCollapse != other->rareNonInheritedData->marginBottomCollapse ||
rareNonInheritedData->lineClamp != other->rareNonInheritedData->lineClamp ||
rareNonInheritedData->textOverflow != other->rareNonInheritedData->textOverflow)
- return Layout;
+ return StyleDifferenceLayout;
if (rareNonInheritedData->flexibleBox.get() != other->rareNonInheritedData->flexibleBox.get() &&
*rareNonInheritedData->flexibleBox.get() != *other->rareNonInheritedData->flexibleBox.get())
- return Layout;
+ return StyleDifferenceLayout;
if (!rareNonInheritedData->shadowDataEquivalent(*other->rareNonInheritedData.get()))
- return Layout;
+ return StyleDifferenceLayout;
if (!rareNonInheritedData->reflectionDataEquivalent(*other->rareNonInheritedData.get()))
- return Layout;
+ return StyleDifferenceLayout;
if (rareNonInheritedData->m_multiCol.get() != other->rareNonInheritedData->m_multiCol.get() &&
*rareNonInheritedData->m_multiCol.get() != *other->rareNonInheritedData->m_multiCol.get())
- return Layout;
+ return StyleDifferenceLayout;
if (rareNonInheritedData->m_transform.get() != other->rareNonInheritedData->m_transform.get() &&
- *rareNonInheritedData->m_transform.get() != *other->rareNonInheritedData->m_transform.get())
- return Layout;
+ *rareNonInheritedData->m_transform.get() != *other->rareNonInheritedData->m_transform.get()) {
+#if USE(ACCELERATED_COMPOSITING)
+ changedContextSensitiveProperties |= ContextSensitivePropertyTransform;
+ // Don't return; keep looking for another change
+#else
+ return StyleDifferenceLayout;
+#endif
+ }
+
+#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)
+ return StyleDifferenceLayout;
+ }
+#endif
#if ENABLE(DASHBOARD_SUPPORT)
// If regions change, trigger a relayout to re-calc regions.
if (rareNonInheritedData->m_dashboardRegions != other->rareNonInheritedData->m_dashboardRegions)
- return Layout;
+ return StyleDifferenceLayout;
#endif
}
@@ -344,13 +363,13 @@ RenderStyle::Diff RenderStyle::diff(const RenderStyle* other) const
rareInheritedData->nbspMode != other->rareInheritedData->nbspMode ||
rareInheritedData->khtmlLineBreak != other->rareInheritedData->khtmlLineBreak ||
rareInheritedData->textSecurity != other->rareInheritedData->textSecurity)
- return Layout;
+ return StyleDifferenceLayout;
if (!rareInheritedData->shadowDataEquivalent(*other->rareInheritedData.get()))
- return Layout;
+ return StyleDifferenceLayout;
if (textStrokeWidth() != other->textStrokeWidth())
- return Layout;
+ return StyleDifferenceLayout;
}
if (inherited->indent != other->inherited->indent ||
@@ -365,7 +384,7 @@ RenderStyle::Diff RenderStyle::diff(const RenderStyle* other) const
noninherited_flags._position != other->noninherited_flags._position ||
noninherited_flags._floating != other->noninherited_flags._floating ||
noninherited_flags._originalDisplay != other->noninherited_flags._originalDisplay)
- return Layout;
+ return StyleDifferenceLayout;
if (((int)noninherited_flags._effectiveDisplay) >= TABLE) {
@@ -373,26 +392,26 @@ RenderStyle::Diff RenderStyle::diff(const RenderStyle* other) const
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 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))
- return Layout;
+ ((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)
- return Layout;
+ return StyleDifferenceLayout;
}
if (inherited_flags._text_align != other->inherited_flags._text_align ||
@@ -400,12 +419,12 @@ RenderStyle::Diff RenderStyle::diff(const RenderStyle* other) const
inherited_flags._direction != other->inherited_flags._direction ||
inherited_flags._white_space != other->inherited_flags._white_space ||
noninherited_flags._clear != other->noninherited_flags._clear)
- return Layout;
+ return StyleDifferenceLayout;
// Overflow returns a layout hint.
if (noninherited_flags._overflowX != other->noninherited_flags._overflowX ||
noninherited_flags._overflowY != other->noninherited_flags._overflowY)
- return Layout;
+ return StyleDifferenceLayout;
// If our border widths change, then we need to layout. Other changes to borders
// only necessitate a repaint.
@@ -413,19 +432,19 @@ RenderStyle::Diff RenderStyle::diff(const RenderStyle* other) const
borderTopWidth() != other->borderTopWidth() ||
borderBottomWidth() != other->borderBottomWidth() ||
borderRightWidth() != other->borderRightWidth())
- return Layout;
+ return StyleDifferenceLayout;
// If the counter directives change, trigger a relayout to re-calculate counter values and rebuild the counter node tree.
const CounterDirectiveMap* mapA = rareNonInheritedData->m_counterDirectives.get();
const CounterDirectiveMap* mapB = other->rareNonInheritedData->m_counterDirectives.get();
if (!(mapA == mapB || (mapA && mapB && *mapA == *mapB)))
- return Layout;
+ return StyleDifferenceLayout;
if (visual->counterIncrement != other->visual->counterIncrement ||
visual->counterReset != other->visual->counterReset)
- return Layout;
+ return StyleDifferenceLayout;
if (inherited->m_effectiveZoom != other->inherited->m_effectiveZoom)
- return Layout;
+ return StyleDifferenceLayout;
// Make sure these left/top/right/bottom checks stay below all layout checks and above
// all visible checks.
@@ -433,7 +452,7 @@ RenderStyle::Diff RenderStyle::diff(const RenderStyle* other) const
if (surround->offset != other->surround->offset) {
// Optimize for the case where a positioned layer is moving but not changing size.
if (position() == AbsolutePosition && positionedObjectMoved(surround->offset, other->surround->offset))
- return LayoutPositionedMovementOnly;
+ return StyleDifferenceLayoutPositionedMovementOnly;
// FIXME: We will need to do a bit of work in RenderObject/Box::setStyle before we
// can stop doing a layout when relative positioned objects move. In particular, we'll need
@@ -441,16 +460,24 @@ RenderStyle::Diff RenderStyle::diff(const RenderStyle* other) const
//if (other->position() == RelativePosition)
// return RepaintLayer;
//else
- return Layout;
+ return StyleDifferenceLayout;
} else if (box->z_index != other->box->z_index || box->z_auto != other->box->z_auto ||
visual->clip != other->visual->clip || visual->hasClip != other->visual->hasClip)
- return RepaintLayer;
+ return StyleDifferenceRepaintLayer;
+ }
+
+ if (rareNonInheritedData->opacity != other->rareNonInheritedData->opacity) {
+#if USE(ACCELERATED_COMPOSITING)
+ changedContextSensitiveProperties |= ContextSensitivePropertyOpacity;
+ // Don't return; keep looking for another change.
+#else
+ return StyleDifferenceRepaintLayer;
+#endif
}
- if (rareNonInheritedData->opacity != other->rareNonInheritedData->opacity ||
- rareNonInheritedData->m_mask != other->rareNonInheritedData->m_mask ||
+ if (rareNonInheritedData->m_mask != other->rareNonInheritedData->m_mask ||
rareNonInheritedData->m_maskBoxImage != other->rareNonInheritedData->m_maskBoxImage)
- return RepaintLayer;
+ return StyleDifferenceRepaintLayer;
if (inherited->color != other->inherited->color ||
inherited_flags._visibility != other->inherited_flags._visibility ||
@@ -465,19 +492,30 @@ RenderStyle::Diff RenderStyle::diff(const RenderStyle* other) const
rareNonInheritedData->m_borderFit != other->rareNonInheritedData->m_borderFit ||
rareInheritedData->textFillColor != other->rareInheritedData->textFillColor ||
rareInheritedData->textStrokeColor != other->rareInheritedData->textStrokeColor)
- return Repaint;
+ 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)
+ return StyleDifferenceRecompositeLayer;
+ }
+#endif
// Cursors are not checked, since they will be set appropriately in response to mouse events,
// so they don't need to cause any repaint or layout.
// Animations don't need to be checked either. We always set the new style on the RenderObject, so we will get a chance to fire off
// the resulting transition properly.
- return Equal;
+ return StyleDifferenceEqual;
}
void RenderStyle::setClip(Length top, Length right, Length bottom, Length left)
{
- StyleVisualData *data = visual.access();
+ StyleVisualData* data = visual.access();
data->clip.m_top = top;
data->clip.m_right = right;
data->clip.m_bottom = bottom;
@@ -501,40 +539,8 @@ void RenderStyle::setCursorList(PassRefPtr<CursorList> other)
void RenderStyle::clearCursorList()
{
- inherited.access()->cursorData = CursorList::create();
-}
-
-bool RenderStyle::contentDataEquivalent(const RenderStyle* otherStyle) const
-{
- ContentData* c1 = rareNonInheritedData->m_content.get();
- ContentData* c2 = otherStyle->rareNonInheritedData->m_content.get();
-
- while (c1 && c2) {
- if (c1->m_type != c2->m_type)
- return false;
-
- switch (c1->m_type) {
- case CONTENT_NONE:
- break;
- case CONTENT_TEXT:
- if (!equal(c1->m_content.m_text, c2->m_content.m_text))
- return false;
- break;
- case CONTENT_OBJECT:
- if (!StyleImage::imagesEquivalent(c1->m_content.m_image, c2->m_content.m_image))
- return false;
- break;
- case CONTENT_COUNTER:
- if (*c1->m_content.m_counter != *c2->m_content.m_counter)
- return false;
- break;
- }
-
- c1 = c1->m_next;
- c2 = c2->m_next;
- }
-
- return !c1 && !c2;
+ if (inherited->cursorData)
+ inherited.access()->cursorData = 0;
}
void RenderStyle::clearContent()
@@ -550,8 +556,8 @@ void RenderStyle::setContent(PassRefPtr<StyleImage> image, bool add)
OwnPtr<ContentData>& content = rareNonInheritedData.access()->m_content;
ContentData* lastContent = content.get();
- while (lastContent && lastContent->m_next)
- lastContent = lastContent->m_next;
+ while (lastContent && lastContent->next())
+ lastContent = lastContent->next();
bool reuseContent = !add;
ContentData* newContentData;
@@ -562,34 +568,30 @@ void RenderStyle::setContent(PassRefPtr<StyleImage> image, bool add)
newContentData = new ContentData;
if (lastContent && !reuseContent)
- lastContent->m_next = newContentData;
+ lastContent->setNext(newContentData);
else
content.set(newContentData);
- newContentData->m_content.m_image = image.releaseRef();
- newContentData->m_type = CONTENT_OBJECT;
+ newContentData->setImage(image);
}
-void RenderStyle::setContent(StringImpl* s, bool add)
+void RenderStyle::setContent(PassRefPtr<StringImpl> s, bool add)
{
if (!s)
return; // The string is null. Nothing to do. Just bail.
OwnPtr<ContentData>& content = rareNonInheritedData.access()->m_content;
ContentData* lastContent = content.get();
- while (lastContent && lastContent->m_next)
- lastContent = lastContent->m_next;
+ while (lastContent && lastContent->next())
+ lastContent = lastContent->next();
bool reuseContent = !add;
if (add && lastContent) {
- if (lastContent->m_type == CONTENT_TEXT) {
+ if (lastContent->isText()) {
// We can augment the existing string and share this ContentData node.
- StringImpl* oldStr = lastContent->m_content.m_text;
- String newStr = oldStr;
- newStr.append(s);
- newStr.impl()->ref();
- oldStr->deref();
- lastContent->m_content.m_text = newStr.impl();
+ String newStr = lastContent->text();
+ newStr.append(s.get());
+ lastContent->setText(newStr.impl());
return;
}
}
@@ -602,13 +604,11 @@ void RenderStyle::setContent(StringImpl* s, bool add)
newContentData = new ContentData;
if (lastContent && !reuseContent)
- lastContent->m_next = newContentData;
+ lastContent->setNext(newContentData);
else
content.set(newContentData);
- newContentData->m_content.m_text = s;
- newContentData->m_content.m_text->ref();
- newContentData->m_type = CONTENT_TEXT;
+ newContentData->setText(s);
}
void RenderStyle::setContent(CounterContent* c, bool add)
@@ -618,8 +618,8 @@ void RenderStyle::setContent(CounterContent* c, bool add)
OwnPtr<ContentData>& content = rareNonInheritedData.access()->m_content;
ContentData* lastContent = content.get();
- while (lastContent && lastContent->m_next)
- lastContent = lastContent->m_next;
+ while (lastContent && lastContent->next())
+ lastContent = lastContent->next();
bool reuseContent = !add;
ContentData* newContentData = 0;
@@ -630,15 +630,14 @@ void RenderStyle::setContent(CounterContent* c, bool add)
newContentData = new ContentData;
if (lastContent && !reuseContent)
- lastContent->m_next = newContentData;
+ lastContent->setNext(newContentData);
else
content.set(newContentData);
- newContentData->m_content.m_counter = c;
- newContentData->m_type = CONTENT_COUNTER;
+ newContentData->setCounter(c);
}
-void RenderStyle::applyTransform(TransformationMatrix& transform, const IntSize& borderBoxSize, bool includeTransformOrigin) const
+void RenderStyle::applyTransform(TransformationMatrix& transform, const IntSize& borderBoxSize, ApplyTransformOrigin applyOrigin) const
{
// transform-origin brackets the transform with translate operations.
// Optimize for the case where the only transform is a translation, since the transform-origin is irrelevant
@@ -646,26 +645,31 @@ void RenderStyle::applyTransform(TransformationMatrix& transform, const IntSize&
bool applyTransformOrigin = false;
unsigned s = rareNonInheritedData->m_transform->m_operations.operations().size();
unsigned i;
- if (includeTransformOrigin) {
+ 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 &&
+ type != TransformOperation::TRANSLATE_Z &&
+ type != TransformOperation::TRANSLATE_3D
+ ) {
applyTransformOrigin = true;
break;
}
}
}
- if (applyTransformOrigin)
- transform.translate(transformOriginX().calcFloatValue(borderBoxSize.width()), transformOriginY().calcFloatValue(borderBoxSize.height()));
+ if (applyTransformOrigin) {
+ transform.translate3d(transformOriginX().calcFloatValue(borderBoxSize.width()), transformOriginY().calcFloatValue(borderBoxSize.height()), transformOriginZ());
+ }
for (i = 0; i < s; i++)
rareNonInheritedData->m_transform->m_operations.operations()[i]->apply(transform, borderBoxSize);
- if (applyTransformOrigin)
- transform.translate(-transformOriginX().calcFloatValue(borderBoxSize.width()), -transformOriginY().calcFloatValue(borderBoxSize.height()));
+ if (applyTransformOrigin) {
+ transform.translate3d(-transformOriginX().calcFloatValue(borderBoxSize.width()), -transformOriginY().calcFloatValue(borderBoxSize.height()), -transformOriginZ());
+ }
}
#if ENABLE(XBL)
@@ -707,6 +711,58 @@ void RenderStyle::setBoxShadow(ShadowData* shadowData, bool add)
rareData->m_boxShadow.set(shadowData);
}
+void RenderStyle::getBorderRadiiForRect(const IntRect& r, IntSize& topLeft, IntSize& topRight, IntSize& bottomLeft, IntSize& bottomRight) const
+{
+ topLeft = surround->border.topLeft;
+ topRight = surround->border.topRight;
+
+ bottomLeft = surround->border.bottomLeft;
+ bottomRight = surround->border.bottomRight;
+
+ // Constrain corner radii using CSS3 rules:
+ // http://www.w3.org/TR/css3-background/#the-border-radius
+
+ float factor = 1;
+ unsigned radiiSum;
+
+ // top
+ radiiSum = static_cast<unsigned>(topLeft.width()) + static_cast<unsigned>(topRight.width()); // Casts to avoid integer overflow.
+ if (radiiSum > static_cast<unsigned>(r.width()))
+ factor = min(static_cast<float>(r.width()) / radiiSum, factor);
+
+ // bottom
+ radiiSum = static_cast<unsigned>(bottomLeft.width()) + static_cast<unsigned>(bottomRight.width());
+ if (radiiSum > static_cast<unsigned>(r.width()))
+ factor = min(static_cast<float>(r.width()) / radiiSum, factor);
+
+ // left
+ radiiSum = static_cast<unsigned>(topLeft.height()) + static_cast<unsigned>(bottomLeft.height());
+ if (radiiSum > static_cast<unsigned>(r.height()))
+ factor = min(static_cast<float>(r.height()) / radiiSum, factor);
+
+ // right
+ radiiSum = static_cast<unsigned>(topRight.height()) + static_cast<unsigned>(bottomRight.height());
+ if (radiiSum > static_cast<unsigned>(r.height()))
+ factor = min(static_cast<float>(r.height()) / radiiSum, factor);
+
+ // Scale all radii by f if necessary.
+ if (factor < 1) {
+ // If either radius on a corner becomes zero, reset both radii on that corner.
+ topLeft.scale(factor);
+ if (!topLeft.width() || !topLeft.height())
+ topLeft = IntSize();
+ topRight.scale(factor);
+ if (!topRight.width() || !topRight.height())
+ topRight = IntSize();
+ bottomLeft.scale(factor);
+ if (!bottomLeft.width() || !bottomLeft.height())
+ bottomLeft = IntSize();
+ bottomRight.scale(factor);
+ if (!bottomRight.width() || !bottomRight.height())
+ bottomRight = IntSize();
+ }
+}
+
const CounterDirectiveMap* RenderStyle::counterDirectives() const
{
return rareNonInheritedData->m_counterDirectives.get();
@@ -753,7 +809,7 @@ void RenderStyle::adjustAnimations()
if (!animationList)
return;
- // get rid of empty transitions and anything beyond them
+ // Get rid of empty animations and anything beyond them
for (size_t i = 0; i < animationList->size(); ++i) {
if (animationList->animation(i)->isEmpty()) {
animationList->resize(i);
@@ -776,7 +832,7 @@ void RenderStyle::adjustTransitions()
if (!transitionList)
return;
- // get rid of empty transitions and anything beyond them
+ // Get rid of empty transitions and anything beyond them
for (size_t i = 0; i < transitionList->size(); ++i) {
if (transitionList->animation(i)->isEmpty()) {
transitionList->resize(i);
@@ -819,7 +875,7 @@ AnimationList* RenderStyle::accessTransitions()
return rareNonInheritedData->m_transitions.get();
}
-const Animation* RenderStyle::transitionForProperty(int property)
+const Animation* RenderStyle::transitionForProperty(int property) const
{
if (transitions()) {
for (size_t i = 0; i < transitions()->size(); ++i) {
diff --git a/src/3rdparty/webkit/WebCore/rendering/style/RenderStyle.h b/src/3rdparty/webkit/WebCore/rendering/style/RenderStyle.h
index f38f943..46c91cd 100644
--- a/src/3rdparty/webkit/WebCore/rendering/style/RenderStyle.h
+++ b/src/3rdparty/webkit/WebCore/rendering/style/RenderStyle.h
@@ -106,20 +106,46 @@ class StyleImage;
class RenderStyle: public RefCounted<RenderStyle> {
friend class CSSStyleSelector;
+protected:
-public:
- // static pseudo styles. Dynamic ones are produced on the fly.
- enum PseudoId { NOPSEUDO, FIRST_LINE, FIRST_LETTER, BEFORE, AFTER, SELECTION, FIRST_LINE_INHERITED, SCROLLBAR, FILE_UPLOAD_BUTTON, INPUT_PLACEHOLDER,
- SLIDER_THUMB, SEARCH_CANCEL_BUTTON, SEARCH_DECORATION, SEARCH_RESULTS_DECORATION, SEARCH_RESULTS_BUTTON, MEDIA_CONTROLS_PANEL,
- MEDIA_CONTROLS_PLAY_BUTTON, MEDIA_CONTROLS_MUTE_BUTTON, MEDIA_CONTROLS_TIMELINE, MEDIA_CONTROLS_TIME_DISPLAY,
- MEDIA_CONTROLS_SEEK_BACK_BUTTON, MEDIA_CONTROLS_SEEK_FORWARD_BUTTON , MEDIA_CONTROLS_FULLSCREEN_BUTTON,
- SCROLLBAR_THUMB, SCROLLBAR_BUTTON, SCROLLBAR_TRACK, SCROLLBAR_TRACK_PIECE, SCROLLBAR_CORNER, RESIZER };
- static const int FIRST_INTERNAL_PSEUDOID = FILE_UPLOAD_BUTTON;
+ // The following bitfield is 32-bits long, which optimizes padding with the
+ // int refCount in the base class. Beware when adding more bits.
+ unsigned m_pseudoState : 3; // PseudoState
+ bool m_affectedByAttributeSelectors : 1;
+ bool m_unique : 1;
-private:
- static TransformOperations s_initialTransform;
+ // Bits for dynamic child matching.
+ bool m_affectedByEmpty : 1;
+ bool m_emptyState : 1;
-protected:
+ // We optimize for :first-child and :last-child. The other positional child selectors like nth-child or
+ // *-child-of-type, we will just give up and re-evaluate whenever children change at all.
+ bool m_childrenAffectedByFirstChildRules : 1;
+ bool m_childrenAffectedByLastChildRules : 1;
+ bool m_childrenAffectedByDirectAdjacentRules : 1;
+ bool m_childrenAffectedByForwardPositionalRules : 1;
+ bool m_childrenAffectedByBackwardPositionalRules : 1;
+ bool m_firstChildState : 1;
+ bool m_lastChildState : 1;
+ unsigned m_childIndex : 18; // Plenty of bits to cache an index.
+
+ // non-inherited attributes
+ DataRef<StyleBoxData> box;
+ DataRef<StyleVisualData> visual;
+ DataRef<StyleBackgroundData> background;
+ DataRef<StyleSurroundData> surround;
+ DataRef<StyleRareNonInheritedData> rareNonInheritedData;
+
+ // inherited attributes
+ DataRef<StyleRareInheritedData> rareInheritedData;
+ DataRef<StyleInheritedData> inherited;
+
+ // list of associated pseudo styles
+ RefPtr<RenderStyle> m_cachedPseudoStyle;
+
+#if ENABLE(SVG)
+ DataRef<SVGRenderStyle> m_svgStyle;
+#endif
// !START SYNC!: Keep this in sync with the copy constructor in RenderStyle.cpp
@@ -162,12 +188,14 @@ protected:
bool _border_collapse : 1 ;
unsigned _white_space : 3; // EWhiteSpace
unsigned _box_direction : 1; // EBoxDirection (CSS3 box_direction property, flexible box layout module)
-
+ // 32 bits
+
// non CSS2 inherited
bool _visuallyOrdered : 1;
- bool _htmlHacks :1;
+ bool _htmlHacks : 1;
bool _force_backgrounds_to_white : 1;
unsigned _pointerEvents : 4; // EPointerEvents
+ // 39 bits
} inherited_flags;
// don't inherit
@@ -214,45 +242,9 @@ protected:
bool _affectedByDrag : 1;
unsigned _pseudoBits : 7;
unsigned _unicodeBidi : 2; // EUnicodeBidi
+ // 48 bits
} noninherited_flags;
- // non-inherited attributes
- DataRef<StyleBoxData> box;
- DataRef<StyleVisualData> visual;
- DataRef<StyleBackgroundData> background;
- DataRef<StyleSurroundData> surround;
- DataRef<StyleRareNonInheritedData> rareNonInheritedData;
-
- // inherited attributes
- DataRef<StyleRareInheritedData> rareInheritedData;
- DataRef<StyleInheritedData> inherited;
-
- // list of associated pseudo styles
- RefPtr<RenderStyle> m_cachedPseudoStyle;
-
- unsigned m_pseudoState : 3; // PseudoState
- bool m_affectedByAttributeSelectors : 1;
- bool m_unique : 1;
-
- // Bits for dynamic child matching.
- bool m_affectedByEmpty : 1;
- bool m_emptyState : 1;
-
- // We optimize for :first-child and :last-child. The other positional child selectors like nth-child or
- // *-child-of-type, we will just give up and re-evaluate whenever children change at all.
- bool m_childrenAffectedByFirstChildRules : 1;
- bool m_childrenAffectedByLastChildRules : 1;
- bool m_childrenAffectedByDirectAdjacentRules : 1;
- bool m_childrenAffectedByForwardPositionalRules : 1;
- bool m_childrenAffectedByBackwardPositionalRules : 1;
- bool m_firstChildState : 1;
- bool m_lastChildState : 1;
- unsigned m_childIndex : 18; // Plenty of bits to cache an index.
-
-#if ENABLE(SVG)
- DataRef<SVGRenderStyle> m_svgStyle;
-#endif
-
// !END SYNC!
protected:
@@ -309,10 +301,10 @@ public:
void inheritFrom(const RenderStyle* inheritParent);
- PseudoId styleType() { return static_cast<PseudoId>(noninherited_flags._styleType); }
+ PseudoId styleType() const { return static_cast<PseudoId>(noninherited_flags._styleType); }
void setStyleType(PseudoId styleType) { noninherited_flags._styleType = styleType; }
- RenderStyle* getCachedPseudoStyle(PseudoId);
+ RenderStyle* getCachedPseudoStyle(PseudoId) const;
RenderStyle* addCachedPseudoStyle(PassRefPtr<RenderStyle>);
bool affectedByHoverRules() const { return noninherited_flags._affectedByHover; }
@@ -337,6 +329,7 @@ public:
return true;
return background->m_background.hasImage();
}
+ bool hasBackgroundImage() const { return background->m_background.hasImage(); }
bool hasFixedBackgroundImage() const { return background->m_background.hasFixedImage(); }
bool hasAppearance() const { return appearance() != NoControlPart; }
@@ -358,6 +351,11 @@ public:
Length top() const { return surround->offset.top(); }
Length bottom() const { return surround->offset.bottom(); }
+ // Whether or not a positioned element requires normal flow x/y to be computed
+ // to determine its position.
+ bool hasStaticX() const { return (left().isAuto() && right().isAuto()) || left().isStatic() || right().isStatic(); }
+ bool hasStaticY() const { return (top().isAuto() && bottom().isAuto()) || top().isStatic(); }
+
EPosition position() const { return static_cast<EPosition>(noninherited_flags._position); }
EFloat floating() const { return static_cast<EFloat>(noninherited_flags._floating); }
@@ -448,6 +446,19 @@ public:
TextDirection direction() const { return static_cast<TextDirection>(inherited_flags._direction); }
Length lineHeight() const { return inherited->line_height; }
+ int computedLineHeight() const
+ {
+ Length lh = lineHeight();
+
+ // Negative value means the line height is not set. Use the font's built-in spacing.
+ if (lh.isNegative())
+ return font().lineSpacing();
+
+ if (lh.isPercent())
+ return lh.calcMinValue(fontSize());
+
+ return lh.value();
+ }
EWhiteSpace whiteSpace() const { return static_cast<EWhiteSpace>(inherited_flags._white_space); }
static bool autoWrap(EWhiteSpace ws)
@@ -630,8 +641,16 @@ public:
const TransformOperations& transform() const { return rareNonInheritedData->m_transform->m_operations; }
Length transformOriginX() const { return rareNonInheritedData->m_transform->m_x; }
Length transformOriginY() const { return rareNonInheritedData->m_transform->m_y; }
+ float transformOriginZ() const { return rareNonInheritedData->m_transform->m_z; }
bool hasTransform() const { return !rareNonInheritedData->m_transform->m_operations.operations().isEmpty(); }
- void applyTransform(TransformationMatrix&, const IntSize& borderBoxSize, bool includeTransformOrigin = true) const;
+
+ // Return true if any transform related property (currently transform, transformStyle3D or perspective)
+ // indicates that we are transforming
+ bool hasTransformRelatedProperty() const { return hasTransform() || preserves3D() || hasPerspective(); }
+
+ enum ApplyTransformOrigin { IncludeTransformOrigin, ExcludeTransformOrigin };
+ void applyTransform(TransformationMatrix&, const IntSize& borderBoxSize, ApplyTransformOrigin = IncludeTransformOrigin) const;
+
bool hasMask() const { return rareNonInheritedData->m_mask.hasImage() || rareNonInheritedData->m_maskBoxImage.hasImage(); }
// End CSS3 Getters
@@ -647,7 +666,21 @@ public:
bool hasTransitions() const { return rareNonInheritedData->m_transitions && rareNonInheritedData->m_transitions->size() > 0; }
// return the first found Animation (including 'all' transitions)
- const Animation* transitionForProperty(int property);
+ const Animation* transitionForProperty(int property) const;
+
+ ETransformStyle3D transformStyle3D() const { return rareNonInheritedData->m_transformStyle3D; }
+ bool preserves3D() const { return rareNonInheritedData->m_transformStyle3D == TransformStyle3DPreserve3D; }
+
+ EBackfaceVisibility backfaceVisibility() const { return rareNonInheritedData->m_backfaceVisibility; }
+ float perspective() const { return rareNonInheritedData->m_perspective; }
+ bool hasPerspective() const { return rareNonInheritedData->m_perspective > 0; }
+ Length perspectiveOriginX() const { return rareNonInheritedData->m_perspectiveOriginX; }
+ Length perspectiveOriginY() const { return rareNonInheritedData->m_perspectiveOriginY; }
+
+#if USE(ACCELERATED_COMPOSITING)
+ // When set, this ensures that styles compare as different. Used during accelerated animations.
+ bool isRunningAcceleratedAnimation() const { return rareNonInheritedData->m_runningAcceleratedAnimation; }
+#endif
int lineClamp() const { return rareNonInheritedData->lineClamp; }
bool textSizeAdjust() const { return rareInheritedData->textSizeAdjust; }
@@ -708,6 +741,10 @@ public:
void setBackgroundColor(const Color& v) { SET_VAR(background, m_color, v) }
+ void setBackgroundXPosition(Length l) { SET_VAR(background, m_background.m_xPosition, l) }
+ void setBackgroundYPosition(Length l) { SET_VAR(background, m_background.m_yPosition, l) }
+ void setBackgroundSize(LengthSize l) { SET_VAR(background, m_background.m_size, l) }
+
void setBorderImage(const NinePieceImage& b) { SET_VAR(surround, border.image, b) }
void setBorderTopLeftRadius(const IntSize& s) { SET_VAR(surround, border.topLeft, s) }
@@ -722,6 +759,8 @@ public:
setBorderBottomLeftRadius(s);
setBorderBottomRightRadius(s);
}
+
+ void getBorderRadiiForRect(const IntRect&, IntSize& topLeft, IntSize& topRight, IntSize& bottomLeft, IntSize& bottomRight) const;
void setBorderLeftWidth(unsigned short v) { SET_VAR(surround, border.left.width, v) }
void setBorderLeftStyle(EBorderStyle v) { SET_VAR(surround, border.left.m_style, v) }
@@ -815,6 +854,9 @@ public:
}
void setMaskBoxImage(const NinePieceImage& b) { SET_VAR(rareNonInheritedData, m_maskBoxImage, b) }
+ void setMaskXPosition(Length l) { SET_VAR(rareNonInheritedData, m_mask.m_xPosition, l) }
+ void setMaskYPosition(Length l) { SET_VAR(rareNonInheritedData, m_mask.m_yPosition, l) }
+ void setMaskSize(LengthSize l) { SET_VAR(rareNonInheritedData, m_mask.m_size, l) }
void setBorderCollapse(bool collapse) { inherited_flags._border_collapse = collapse; }
void setHorizontalBorderSpacing(short v) { SET_VAR(inherited, horizontal_border_spacing, v) }
@@ -924,6 +966,7 @@ public:
void setTransform(const TransformOperations& ops) { SET_VAR(rareNonInheritedData.access()->m_transform, m_operations, ops); }
void setTransformOriginX(Length l) { SET_VAR(rareNonInheritedData.access()->m_transform, m_x, l); }
void setTransformOriginY(Length l) { SET_VAR(rareNonInheritedData.access()->m_transform, m_y, l); }
+ void setTransformOriginZ(float f) { SET_VAR(rareNonInheritedData.access()->m_transform, m_z, f); }
// End CSS3 Setters
// Apple-specific property setters
@@ -944,6 +987,16 @@ public:
void adjustAnimations();
void adjustTransitions();
+ void setTransformStyle3D(ETransformStyle3D b) { SET_VAR(rareNonInheritedData, m_transformStyle3D, b); }
+ void setBackfaceVisibility(EBackfaceVisibility b) { SET_VAR(rareNonInheritedData, m_backfaceVisibility, b); }
+ void setPerspective(float p) { SET_VAR(rareNonInheritedData, m_perspective, p); }
+ void setPerspectiveOriginX(Length l) { SET_VAR(rareNonInheritedData, m_perspectiveOriginX, l); }
+ void setPerspectiveOriginY(Length l) { SET_VAR(rareNonInheritedData, m_perspectiveOriginY, l); }
+
+#if USE(ACCELERATED_COMPOSITING)
+ void setIsRunningAcceleratedAnimation(bool b = true) { SET_VAR(rareNonInheritedData, m_runningAcceleratedAnimation, b); }
+#endif
+
void setLineClamp(int c) { SET_VAR(rareNonInheritedData, lineClamp, c); }
void setTextSizeAdjust(bool b) { SET_VAR(rareInheritedData, textSizeAdjust, b); }
void setTextSecurity(ETextSecurity aTextSecurity) { SET_VAR(rareInheritedData, textSecurity, aTextSecurity); }
@@ -963,24 +1016,18 @@ public:
#endif
const ContentData* contentData() const { return rareNonInheritedData->m_content.get(); }
- bool contentDataEquivalent(const RenderStyle* otherStyle) const;
+ bool contentDataEquivalent(const RenderStyle* otherStyle) const { return const_cast<RenderStyle*>(this)->rareNonInheritedData->contentDataEquivalent(*const_cast<RenderStyle*>(otherStyle)->rareNonInheritedData); }
void clearContent();
- void setContent(StringImpl*, bool add = false);
+ void setContent(PassRefPtr<StringImpl>, bool add = false);
void setContent(PassRefPtr<StyleImage>, bool add = false);
void setContent(CounterContent*, bool add = false);
const CounterDirectiveMap* counterDirectives() const;
CounterDirectiveMap& accessCounterDirectives();
- bool inheritedNotEqual(RenderStyle*) const;
+ bool inheritedNotEqual(const RenderStyle*) const;
- // The difference between two styles. The following values are used:
- // (1) Equal - The two styles are identical
- // (2) Repaint - The object just needs to be repainted.
- // (3) RepaintLayer - The layer and its descendant layers needs to be repainted.
- // (4) Layout - A layout is required.
- enum Diff { Equal, Repaint, RepaintLayer, LayoutPositionedMovementOnly, Layout };
- Diff diff(const RenderStyle*) const;
+ StyleDifference diff(const RenderStyle*, unsigned& changedContextSensitiveProperties) const;
bool isDisplayReplacedType() const
{
@@ -1109,10 +1156,16 @@ public:
static bool initialVisuallyOrdered() { return false; }
static float initialTextStrokeWidth() { return 0; }
static unsigned short initialColumnCount() { return 1; }
- static const TransformOperations& initialTransform() { return s_initialTransform; }
+ static const TransformOperations& initialTransform() { DEFINE_STATIC_LOCAL(TransformOperations, ops, ()); return ops; }
static Length initialTransformOriginX() { return Length(50.0, Percent); }
static Length initialTransformOriginY() { return Length(50.0, Percent); }
static EPointerEvents initialPointerEvents() { return PE_AUTO; }
+ static float initialTransformOriginZ() { return 0; }
+ static ETransformStyle3D initialTransformStyle3D() { return TransformStyle3DFlat; }
+ static EBackfaceVisibility initialBackfaceVisibility() { return BackfaceVisibilityVisible; }
+ static float initialPerspective() { return 0; }
+ static Length initialPerspectiveOriginX() { return Length(50.0, Percent); }
+ static Length initialPerspectiveOriginY() { return Length(50.0, Percent); }
// Keep these at the end.
static int initialLineClamp() { return -1; }
diff --git a/src/3rdparty/webkit/WebCore/rendering/style/RenderStyleConstants.h b/src/3rdparty/webkit/WebCore/rendering/style/RenderStyleConstants.h
index 40ad3cc..405cf7c 100644
--- a/src/3rdparty/webkit/WebCore/rendering/style/RenderStyleConstants.h
+++ b/src/3rdparty/webkit/WebCore/rendering/style/RenderStyleConstants.h
@@ -36,6 +36,44 @@ namespace WebCore {
* and produce invalid results.
*/
+// The difference between two styles. The following values are used:
+// (1) StyleDifferenceEqual - The two styles are identical
+// (2) StyleDifferenceRecompositeLayer - The layer needs its position and transform updated, but no repaint
+// (3) StyleDifferenceRepaint - The object just needs to be repainted.
+// (4) StyleDifferenceRepaintLayer - The layer and its descendant layers needs to be repainted.
+// (5) StyleDifferenceLayout - A layout is required.
+enum StyleDifference {
+ StyleDifferenceEqual,
+#if USE(ACCELERATED_COMPOSITING)
+ StyleDifferenceRecompositeLayer,
+#endif
+ StyleDifferenceRepaint,
+ StyleDifferenceRepaintLayer,
+ StyleDifferenceLayoutPositionedMovementOnly,
+ StyleDifferenceLayout
+};
+
+// When some style properties change, different amounts of work have to be done depending on
+// context (e.g. whether the property is changing on an element which has a compositing layer).
+// A simple StyleDifference does not provide enough information so we return a bit mask of
+// StyleDifferenceContextSensitiveProperties from RenderStyle::diff() too.
+enum StyleDifferenceContextSensitiveProperty {
+ ContextSensitivePropertyNone = 0,
+ ContextSensitivePropertyTransform = (1 << 0),
+ ContextSensitivePropertyOpacity = (1 << 1)
+};
+
+// Static pseudo styles. Dynamic ones are produced on the fly.
+enum PseudoId {
+ NOPSEUDO, FIRST_LINE, FIRST_LETTER, BEFORE, AFTER, SELECTION, FIRST_LINE_INHERITED, SCROLLBAR, FILE_UPLOAD_BUTTON, INPUT_PLACEHOLDER,
+ SLIDER_THUMB, SEARCH_CANCEL_BUTTON, SEARCH_DECORATION, SEARCH_RESULTS_DECORATION, SEARCH_RESULTS_BUTTON, MEDIA_CONTROLS_PANEL,
+ MEDIA_CONTROLS_PLAY_BUTTON, MEDIA_CONTROLS_MUTE_BUTTON, MEDIA_CONTROLS_TIMELINE, MEDIA_CONTROLS_TIMELINE_CONTAINER,
+ MEDIA_CONTROLS_CURRENT_TIME_DISPLAY, MEDIA_CONTROLS_TIME_REMAINING_DISPLAY, MEDIA_CONTROLS_SEEK_BACK_BUTTON,
+ MEDIA_CONTROLS_SEEK_FORWARD_BUTTON, MEDIA_CONTROLS_FULLSCREEN_BUTTON,
+ SCROLLBAR_THUMB, SCROLLBAR_BUTTON, SCROLLBAR_TRACK, SCROLLBAR_TRACK_PIECE, SCROLLBAR_CORNER, RESIZER,
+
+ FIRST_INTERNAL_PSEUDOID = FILE_UPLOAD_BUTTON
+};
// These have been defined in the order of their precedence for border-collapsing. Do
// not change this order!
@@ -163,7 +201,7 @@ enum EListStyleType {
HIRAGANA, KATAKANA, HIRAGANA_IROHA, KATAKANA_IROHA, LNONE
};
-enum ContentType {
+enum StyleContentType {
CONTENT_NONE, CONTENT_OBJECT, CONTENT_TEXT, CONTENT_COUNTER
};
@@ -171,11 +209,6 @@ enum EBorderFit { BorderFitBorder, BorderFitLines };
enum ETimingFunctionType { LinearTimingFunction, CubicBezierTimingFunction };
-enum EAnimPlayState {
- AnimPlayStatePlaying = 0x0,
- AnimPlayStatePaused = 0x1
-};
-
enum EWhiteSpace {
NORMAL, PRE, PRE_WRAP, PRE_LINE, NOWRAP, KHTML_NOWRAP
};
@@ -263,6 +296,14 @@ enum EPointerEvents {
PE_VISIBLE_STROKE, PE_VISIBLE_FILL, PE_VISIBLE_PAINTED, PE_ALL
};
+enum ETransformStyle3D {
+ TransformStyle3DFlat, TransformStyle3DPreserve3D
+};
+
+enum EBackfaceVisibility {
+ BackfaceVisibilityVisible, BackfaceVisibilityHidden
+};
+
} // namespace WebCore
#endif // RenderStyleConstants_h
diff --git a/src/3rdparty/webkit/WebCore/rendering/style/SVGRenderStyle.cpp b/src/3rdparty/webkit/WebCore/rendering/style/SVGRenderStyle.cpp
index 1749978..c5f0648 100644
--- a/src/3rdparty/webkit/WebCore/rendering/style/SVGRenderStyle.cpp
+++ b/src/3rdparty/webkit/WebCore/rendering/style/SVGRenderStyle.cpp
@@ -128,7 +128,7 @@ float SVGRenderStyle::cssPrimitiveToLength(const RenderObject* item, CSSValue* v
return defaultValue;
if (cssType == CSSPrimitiveValue::CSS_PERCENTAGE) {
- SVGStyledElement* element = static_cast<SVGStyledElement*>(item->element());
+ SVGStyledElement* element = static_cast<SVGStyledElement*>(item->node());
SVGElement* viewportElement = (element ? element->viewportElement() : 0);
if (viewportElement) {
float result = primitive->getFloatValue() / 100.0f;
diff --git a/src/3rdparty/webkit/WebCore/rendering/style/StyleGeneratedImage.cpp b/src/3rdparty/webkit/WebCore/rendering/style/StyleGeneratedImage.cpp
index fa361e8..610e73d 100644
--- a/src/3rdparty/webkit/WebCore/rendering/style/StyleGeneratedImage.cpp
+++ b/src/3rdparty/webkit/WebCore/rendering/style/StyleGeneratedImage.cpp
@@ -34,11 +34,26 @@ PassRefPtr<CSSValue> StyleGeneratedImage::cssValue()
return m_generator;
}
-IntSize StyleGeneratedImage::imageSize(const RenderObject* renderer, float /* multiplier */) const
+IntSize StyleGeneratedImage::imageSize(const RenderObject* renderer, float multiplier) const
{
- // We can ignore the multiplier, since we always store a raw zoomed size.
- if (m_fixedSize)
- return m_generator->fixedSize(renderer);
+ if (m_fixedSize) {
+ IntSize fixedSize = m_generator->fixedSize(renderer);
+ if (multiplier == 1.0f)
+ return fixedSize;
+
+ int width = fixedSize.width() * multiplier;
+ int height = fixedSize.height() * multiplier;
+
+ // Don't let images that have a width/height >= 1 shrink below 1 when zoomed.
+ if (fixedSize.width() > 0)
+ width = max(1, width);
+
+ if (fixedSize.height() > 0)
+ height = max(1, height);
+
+ return IntSize(width, height);
+ }
+
return m_containerSize;
}
diff --git a/src/3rdparty/webkit/WebCore/rendering/style/StyleInheritedData.cpp b/src/3rdparty/webkit/WebCore/rendering/style/StyleInheritedData.cpp
index 56d2686..f59c0c2 100644
--- a/src/3rdparty/webkit/WebCore/rendering/style/StyleInheritedData.cpp
+++ b/src/3rdparty/webkit/WebCore/rendering/style/StyleInheritedData.cpp
@@ -66,7 +66,7 @@ static bool cursorDataEquivalent(const CursorList* c1, const CursorList* c2)
{
if (c1 == c2)
return true;
- if (!c1 && c2 || c1 && !c2)
+ if ((!c1 && c2) || (c1 && !c2))
return false;
return (*c1 == *c2);
}
diff --git a/src/3rdparty/webkit/WebCore/rendering/style/StyleRareInheritedData.cpp b/src/3rdparty/webkit/WebCore/rendering/style/StyleRareInheritedData.cpp
index b8fb2dd..ce21720 100644
--- a/src/3rdparty/webkit/WebCore/rendering/style/StyleRareInheritedData.cpp
+++ b/src/3rdparty/webkit/WebCore/rendering/style/StyleRareInheritedData.cpp
@@ -80,12 +80,13 @@ bool StyleRareInheritedData::operator==(const StyleRareInheritedData& o) const
&& nbspMode == o.nbspMode
&& khtmlLineBreak == o.khtmlLineBreak
&& textSizeAdjust == o.textSizeAdjust
+ && resize == o.resize
&& userSelect == o.userSelect;
}
bool StyleRareInheritedData::shadowDataEquivalent(const StyleRareInheritedData& o) const
{
- if (!textShadow && o.textShadow || textShadow && !o.textShadow)
+ if ((!textShadow && o.textShadow) || (textShadow && !o.textShadow))
return false;
if (textShadow && o.textShadow && (*textShadow != *o.textShadow))
return false;
diff --git a/src/3rdparty/webkit/WebCore/rendering/style/StyleRareNonInheritedData.cpp b/src/3rdparty/webkit/WebCore/rendering/style/StyleRareNonInheritedData.cpp
index e8ceeeb..401c04f 100644
--- a/src/3rdparty/webkit/WebCore/rendering/style/StyleRareNonInheritedData.cpp
+++ b/src/3rdparty/webkit/WebCore/rendering/style/StyleRareNonInheritedData.cpp
@@ -23,7 +23,10 @@
#include "StyleRareNonInheritedData.h"
#include "CSSStyleSelector.h"
+#include "ContentData.h"
+#include "RenderCounter.h"
#include "RenderStyle.h"
+#include "StyleImage.h"
namespace WebCore {
@@ -39,10 +42,18 @@ StyleRareNonInheritedData::StyleRareNonInheritedData()
, matchNearestMailBlockquoteColor(RenderStyle::initialMatchNearestMailBlockquoteColor())
, m_appearance(RenderStyle::initialAppearance())
, m_borderFit(RenderStyle::initialBorderFit())
+#if USE(ACCELERATED_COMPOSITING)
+ , m_runningAcceleratedAnimation(false)
+#endif
, m_boxShadow(0)
, m_animations(0)
, m_transitions(0)
, m_mask(FillLayer(MaskFillLayer))
+ , m_transformStyle3D(RenderStyle::initialTransformStyle3D())
+ , m_backfaceVisibility(RenderStyle::initialBackfaceVisibility())
+ , m_perspective(RenderStyle::initialPerspective())
+ , m_perspectiveOriginX(RenderStyle::initialPerspectiveOriginX())
+ , m_perspectiveOriginY(RenderStyle::initialPerspectiveOriginY())
#if ENABLE(XBL)
, bindingURI(0)
#endif
@@ -66,12 +77,20 @@ StyleRareNonInheritedData::StyleRareNonInheritedData(const StyleRareNonInherited
, matchNearestMailBlockquoteColor(o.matchNearestMailBlockquoteColor)
, m_appearance(o.m_appearance)
, m_borderFit(o.m_borderFit)
+#if USE(ACCELERATED_COMPOSITING)
+ , m_runningAcceleratedAnimation(o.m_runningAcceleratedAnimation)
+#endif
, m_boxShadow(o.m_boxShadow ? new ShadowData(*o.m_boxShadow) : 0)
, m_boxReflect(o.m_boxReflect)
, m_animations(o.m_animations ? new AnimationList(*o.m_animations) : 0)
, m_transitions(o.m_transitions ? new AnimationList(*o.m_transitions) : 0)
, m_mask(o.m_mask)
, m_maskBoxImage(o.m_maskBoxImage)
+ , m_transformStyle3D(o.m_transformStyle3D)
+ , m_backfaceVisibility(o.m_backfaceVisibility)
+ , m_perspective(o.m_perspective)
+ , m_perspectiveOriginX(o.m_perspectiveOriginX)
+ , m_perspectiveOriginY(o.m_perspectiveOriginY)
#if ENABLE(XBL)
, bindingURI(o.bindingURI ? o.bindingURI->copy() : 0)
#endif
@@ -105,7 +124,7 @@ bool StyleRareNonInheritedData::operator==(const StyleRareNonInheritedData& o) c
&& marquee == o.marquee
&& m_multiCol == o.m_multiCol
&& m_transform == o.m_transform
- && m_content == o.m_content
+ && contentDataEquivalent(o)
&& m_counterDirectives == o.m_counterDirectives
&& userDrag == o.userDrag
&& textOverflow == o.textOverflow
@@ -114,6 +133,9 @@ bool StyleRareNonInheritedData::operator==(const StyleRareNonInheritedData& o) c
&& matchNearestMailBlockquoteColor == o.matchNearestMailBlockquoteColor
&& m_appearance == o.m_appearance
&& m_borderFit == o.m_borderFit
+#if USE(ACCELERATED_COMPOSITING)
+ && !m_runningAcceleratedAnimation && !o.m_runningAcceleratedAnimation
+#endif
&& shadowDataEquivalent(o)
&& reflectionDataEquivalent(o)
&& animationDataEquivalent(o)
@@ -123,12 +145,32 @@ bool StyleRareNonInheritedData::operator==(const StyleRareNonInheritedData& o) c
#if ENABLE(XBL)
&& bindingsEquivalent(o)
#endif
+ && (m_transformStyle3D == o.m_transformStyle3D)
+ && (m_backfaceVisibility == o.m_backfaceVisibility)
+ && (m_perspective == o.m_perspective)
+ && (m_perspectiveOriginX == o.m_perspectiveOriginX)
+ && (m_perspectiveOriginY == o.m_perspectiveOriginY)
;
}
+bool StyleRareNonInheritedData::contentDataEquivalent(const StyleRareNonInheritedData& o) const
+{
+ ContentData* c1 = m_content.get();
+ ContentData* c2 = o.m_content.get();
+
+ while (c1 && c2) {
+ if (!c1->dataEquivalent(*c2))
+ return false;
+ c1 = c1->next();
+ c2 = c2->next();
+ }
+
+ return !c1 && !c2;
+}
+
bool StyleRareNonInheritedData::shadowDataEquivalent(const StyleRareNonInheritedData& o) const
{
- if (!m_boxShadow && o.m_boxShadow || m_boxShadow && !o.m_boxShadow)
+ if ((!m_boxShadow && o.m_boxShadow) || (m_boxShadow && !o.m_boxShadow))
return false;
if (m_boxShadow && o.m_boxShadow && (*m_boxShadow != *o.m_boxShadow))
return false;
@@ -148,7 +190,7 @@ bool StyleRareNonInheritedData::reflectionDataEquivalent(const StyleRareNonInher
bool StyleRareNonInheritedData::animationDataEquivalent(const StyleRareNonInheritedData& o) const
{
- if (!m_animations && o.m_animations || m_animations && !o.m_animations)
+ if ((!m_animations && o.m_animations) || (m_animations && !o.m_animations))
return false;
if (m_animations && o.m_animations && (*m_animations != *o.m_animations))
return false;
@@ -157,7 +199,7 @@ bool StyleRareNonInheritedData::animationDataEquivalent(const StyleRareNonInheri
bool StyleRareNonInheritedData::transitionDataEquivalent(const StyleRareNonInheritedData& o) const
{
- if (!m_transitions && o.m_transitions || m_transitions && !o.m_transitions)
+ if ((!m_transitions && o.m_transitions) || (m_transitions && !o.m_transitions))
return false;
if (m_transitions && o.m_transitions && (*m_transitions != *o.m_transitions))
return false;
diff --git a/src/3rdparty/webkit/WebCore/rendering/style/StyleRareNonInheritedData.h b/src/3rdparty/webkit/WebCore/rendering/style/StyleRareNonInheritedData.h
index 6ce6a33..8dd22b3 100644
--- a/src/3rdparty/webkit/WebCore/rendering/style/StyleRareNonInheritedData.h
+++ b/src/3rdparty/webkit/WebCore/rendering/style/StyleRareNonInheritedData.h
@@ -30,6 +30,7 @@
#include "DataRef.h"
#include "FillLayer.h"
#include "NinePieceImage.h"
+#include "StyleTransformData.h"
#include <wtf/OwnPtr.h>
#include <wtf/PassRefPtr.h>
#include <wtf/Vector.h>
@@ -69,7 +70,8 @@ public:
bool operator==(const StyleRareNonInheritedData&) const;
bool operator!=(const StyleRareNonInheritedData& o) const { return !(*this == o); }
-
+
+ bool contentDataEquivalent(const StyleRareNonInheritedData& o) const;
bool shadowDataEquivalent(const StyleRareNonInheritedData& o) const;
bool reflectionDataEquivalent(const StyleRareNonInheritedData& o) const;
bool animationDataEquivalent(const StyleRareNonInheritedData&) const;
@@ -96,6 +98,9 @@ public:
unsigned matchNearestMailBlockquoteColor : 1; // EMatchNearestMailBlockquoteColor, FIXME: This property needs to be eliminated. It should never have been added.
unsigned m_appearance : 6; // EAppearance
unsigned m_borderFit : 1; // EBorderFit
+#if USE(ACCELERATED_COMPOSITING)
+ bool m_runningAcceleratedAnimation : 1;
+#endif
OwnPtr<ShadowData> m_boxShadow; // For box-shadow decorations.
RefPtr<StyleReflection> m_boxReflect;
@@ -106,6 +111,12 @@ public:
FillLayer m_mask;
NinePieceImage m_maskBoxImage;
+ ETransformStyle3D m_transformStyle3D;
+ EBackfaceVisibility m_backfaceVisibility;
+ float m_perspective;
+ Length m_perspectiveOriginX;
+ Length m_perspectiveOriginY;
+
#if ENABLE(XBL)
OwnPtr<BindingURI> bindingURI; // The XBL binding URI list.
#endif
diff --git a/src/3rdparty/webkit/WebCore/rendering/style/StyleTransformData.cpp b/src/3rdparty/webkit/WebCore/rendering/style/StyleTransformData.cpp
index de20e77..2baebf9 100644
--- a/src/3rdparty/webkit/WebCore/rendering/style/StyleTransformData.cpp
+++ b/src/3rdparty/webkit/WebCore/rendering/style/StyleTransformData.cpp
@@ -30,6 +30,7 @@ StyleTransformData::StyleTransformData()
: m_operations(RenderStyle::initialTransform())
, m_x(RenderStyle::initialTransformOriginX())
, m_y(RenderStyle::initialTransformOriginY())
+ , m_z(RenderStyle::initialTransformOriginZ())
{
}
@@ -38,12 +39,13 @@ StyleTransformData::StyleTransformData(const StyleTransformData& o)
, m_operations(o.m_operations)
, m_x(o.m_x)
, m_y(o.m_y)
+ , m_z(o.m_z)
{
}
bool StyleTransformData::operator==(const StyleTransformData& o) const
{
- return m_x == o.m_x && m_y == o.m_y && m_operations == o.m_operations;
+ return m_x == o.m_x && m_y == o.m_y && m_z == o.m_z && m_operations == o.m_operations;
}
} // namespace WebCore
diff --git a/src/3rdparty/webkit/WebCore/rendering/style/StyleTransformData.h b/src/3rdparty/webkit/WebCore/rendering/style/StyleTransformData.h
index 157e600..6039824 100644
--- a/src/3rdparty/webkit/WebCore/rendering/style/StyleTransformData.h
+++ b/src/3rdparty/webkit/WebCore/rendering/style/StyleTransformData.h
@@ -46,6 +46,7 @@ public:
TransformOperations m_operations;
Length m_x;
Length m_y;
+ float m_z;
private:
StyleTransformData();