summaryrefslogtreecommitdiffstats
path: root/WebCore/rendering
diff options
context:
space:
mode:
authorThe Android Open Source Project <initial-contribution@android.com>2009-03-05 14:34:32 -0800
committerThe Android Open Source Project <initial-contribution@android.com>2009-03-05 14:34:32 -0800
commit635860845790a19bf50bbc51ba8fb66a96dde068 (patch)
treeef6ad9ff73a5b57f65249d4232a202fa77e6a140 /WebCore/rendering
parent8e35f3cfc7fba1d1c829dc557ebad6409cbe16a2 (diff)
downloadexternal_webkit-635860845790a19bf50bbc51ba8fb66a96dde068.zip
external_webkit-635860845790a19bf50bbc51ba8fb66a96dde068.tar.gz
external_webkit-635860845790a19bf50bbc51ba8fb66a96dde068.tar.bz2
auto import from //depot/cupcake/@136594
Diffstat (limited to 'WebCore/rendering')
-rw-r--r--WebCore/rendering/EllipsisBox.cpp7
-rw-r--r--WebCore/rendering/FixedTableLayout.cpp2
-rw-r--r--WebCore/rendering/GapRects.h4
-rw-r--r--WebCore/rendering/HitTestResult.cpp44
-rw-r--r--WebCore/rendering/InlineBox.cpp9
-rw-r--r--WebCore/rendering/InlineBox.h7
-rw-r--r--WebCore/rendering/InlineFlowBox.cpp71
-rw-r--r--WebCore/rendering/InlineFlowBox.h16
-rw-r--r--WebCore/rendering/InlineRunBox.h4
-rw-r--r--WebCore/rendering/InlineTextBox.cpp72
-rw-r--r--WebCore/rendering/InlineTextBox.h48
-rw-r--r--WebCore/rendering/LayoutState.cpp39
-rw-r--r--WebCore/rendering/LayoutState.h11
-rw-r--r--WebCore/rendering/MediaControlElements.cpp53
-rw-r--r--WebCore/rendering/MediaControlElements.h27
-rw-r--r--WebCore/rendering/PointerEventsHitRules.cpp6
-rw-r--r--WebCore/rendering/PointerEventsHitRules.h8
-rw-r--r--WebCore/rendering/RenderApplet.cpp10
-rw-r--r--WebCore/rendering/RenderArena.cpp11
-rw-r--r--WebCore/rendering/RenderArena.h4
-rw-r--r--WebCore/rendering/RenderBR.cpp2
-rw-r--r--WebCore/rendering/RenderBlock.cpp851
-rw-r--r--WebCore/rendering/RenderBlock.h86
-rw-r--r--WebCore/rendering/RenderBox.cpp1132
-rw-r--r--WebCore/rendering/RenderBox.h235
-rw-r--r--WebCore/rendering/RenderButton.cpp34
-rw-r--r--WebCore/rendering/RenderButton.h1
-rw-r--r--WebCore/rendering/RenderContainer.cpp115
-rw-r--r--WebCore/rendering/RenderContainer.h7
-rw-r--r--WebCore/rendering/RenderCounter.cpp3
-rw-r--r--WebCore/rendering/RenderFieldset.cpp55
-rw-r--r--WebCore/rendering/RenderFieldset.h7
-rw-r--r--WebCore/rendering/RenderFileUploadControl.cpp13
-rw-r--r--WebCore/rendering/RenderFlexibleBox.cpp187
-rw-r--r--WebCore/rendering/RenderFlexibleBox.h4
-rw-r--r--WebCore/rendering/RenderFlow.cpp214
-rw-r--r--WebCore/rendering/RenderFlow.h15
-rw-r--r--WebCore/rendering/RenderForeignObject.cpp25
-rw-r--r--WebCore/rendering/RenderForeignObject.h12
-rw-r--r--WebCore/rendering/RenderFrame.cpp8
-rw-r--r--WebCore/rendering/RenderFrameSet.cpp51
-rw-r--r--WebCore/rendering/RenderHTMLCanvas.cpp15
-rw-r--r--WebCore/rendering/RenderImage.cpp64
-rw-r--r--WebCore/rendering/RenderImage.h4
-rw-r--r--WebCore/rendering/RenderInline.cpp155
-rw-r--r--WebCore/rendering/RenderInline.h22
-rw-r--r--WebCore/rendering/RenderLayer.cpp577
-rw-r--r--WebCore/rendering/RenderLayer.h112
-rw-r--r--WebCore/rendering/RenderLegend.cpp4
-rw-r--r--WebCore/rendering/RenderLegend.h4
-rw-r--r--WebCore/rendering/RenderListBox.cpp71
-rw-r--r--WebCore/rendering/RenderListBox.h1
-rw-r--r--WebCore/rendering/RenderListItem.cpp21
-rw-r--r--WebCore/rendering/RenderListMarker.cpp40
-rw-r--r--WebCore/rendering/RenderListMarker.h2
-rw-r--r--WebCore/rendering/RenderMarquee.cpp2
-rw-r--r--WebCore/rendering/RenderMedia.cpp134
-rw-r--r--WebCore/rendering/RenderMedia.h12
-rw-r--r--WebCore/rendering/RenderMenuList.cpp55
-rw-r--r--WebCore/rendering/RenderMenuList.h8
-rw-r--r--WebCore/rendering/RenderObject.cpp761
-rw-r--r--WebCore/rendering/RenderObject.h303
-rw-r--r--WebCore/rendering/RenderPart.cpp12
-rw-r--r--WebCore/rendering/RenderPartObject.cpp394
-rw-r--r--WebCore/rendering/RenderPath.cpp100
-rw-r--r--WebCore/rendering/RenderPath.h24
-rw-r--r--WebCore/rendering/RenderReplaced.cpp105
-rw-r--r--WebCore/rendering/RenderReplaced.h5
-rw-r--r--WebCore/rendering/RenderReplica.cpp21
-rw-r--r--WebCore/rendering/RenderReplica.h2
-rw-r--r--WebCore/rendering/RenderSVGContainer.cpp47
-rw-r--r--WebCore/rendering/RenderSVGContainer.h17
-rw-r--r--WebCore/rendering/RenderSVGHiddenContainer.cpp30
-rw-r--r--WebCore/rendering/RenderSVGHiddenContainer.h9
-rw-r--r--WebCore/rendering/RenderSVGImage.cpp31
-rw-r--r--WebCore/rendering/RenderSVGImage.h13
-rw-r--r--WebCore/rendering/RenderSVGInline.cpp15
-rw-r--r--WebCore/rendering/RenderSVGInline.h2
-rw-r--r--WebCore/rendering/RenderSVGInlineText.cpp36
-rw-r--r--WebCore/rendering/RenderSVGInlineText.h9
-rw-r--r--WebCore/rendering/RenderSVGRoot.cpp61
-rw-r--r--WebCore/rendering/RenderSVGRoot.h11
-rw-r--r--WebCore/rendering/RenderSVGTSpan.cpp30
-rw-r--r--WebCore/rendering/RenderSVGTSpan.h1
-rw-r--r--WebCore/rendering/RenderSVGText.cpp60
-rw-r--r--WebCore/rendering/RenderSVGText.h12
-rw-r--r--WebCore/rendering/RenderSVGTextPath.cpp30
-rw-r--r--WebCore/rendering/RenderSVGTextPath.h1
-rw-r--r--WebCore/rendering/RenderSVGTransformableContainer.cpp2
-rw-r--r--WebCore/rendering/RenderSVGViewportContainer.cpp17
-rw-r--r--WebCore/rendering/RenderSVGViewportContainer.h4
-rw-r--r--WebCore/rendering/RenderScrollbar.cpp6
-rw-r--r--WebCore/rendering/RenderScrollbar.h10
-rw-r--r--WebCore/rendering/RenderScrollbarPart.cpp38
-rw-r--r--WebCore/rendering/RenderScrollbarPart.h5
-rw-r--r--WebCore/rendering/RenderScrollbarTheme.cpp3
-rw-r--r--WebCore/rendering/RenderSlider.cpp62
-rw-r--r--WebCore/rendering/RenderSlider.h2
-rw-r--r--WebCore/rendering/RenderTable.cpp104
-rw-r--r--WebCore/rendering/RenderTableCell.cpp133
-rw-r--r--WebCore/rendering/RenderTableCell.h38
-rw-r--r--WebCore/rendering/RenderTableCol.cpp5
-rw-r--r--WebCore/rendering/RenderTableCol.h6
-rw-r--r--WebCore/rendering/RenderTableRow.cpp24
-rw-r--r--WebCore/rendering/RenderTableRow.h16
-rw-r--r--WebCore/rendering/RenderTableSection.cpp194
-rw-r--r--WebCore/rendering/RenderTableSection.h17
-rw-r--r--WebCore/rendering/RenderText.cpp206
-rw-r--r--WebCore/rendering/RenderText.h41
-rw-r--r--WebCore/rendering/RenderTextControl.cpp892
-rw-r--r--WebCore/rendering/RenderTextControl.h114
-rw-r--r--WebCore/rendering/RenderTextControlMultiLine.cpp171
-rw-r--r--WebCore/rendering/RenderTextControlMultiLine.h54
-rw-r--r--WebCore/rendering/RenderTextControlSingleLine.cpp787
-rw-r--r--WebCore/rendering/RenderTextControlSingleLine.h126
-rw-r--r--WebCore/rendering/RenderTheme.cpp164
-rw-r--r--WebCore/rendering/RenderTheme.h71
-rw-r--r--WebCore/rendering/RenderThemeChromiumGtk.cpp532
-rw-r--r--WebCore/rendering/RenderThemeChromiumGtk.h136
-rw-r--r--WebCore/rendering/RenderThemeChromiumMac.h210
-rw-r--r--WebCore/rendering/RenderThemeChromiumMac.mm1973
-rw-r--r--WebCore/rendering/RenderThemeChromiumWin.cpp614
-rw-r--r--WebCore/rendering/RenderThemeChromiumWin.h136
-rw-r--r--WebCore/rendering/RenderThemeMac.h20
-rw-r--r--WebCore/rendering/RenderThemeMac.mm308
-rw-r--r--WebCore/rendering/RenderThemeSafari.cpp10
-rw-r--r--WebCore/rendering/RenderThemeWin.cpp217
-rw-r--r--WebCore/rendering/RenderThemeWin.h11
-rw-r--r--WebCore/rendering/RenderTreeAsText.cpp85
-rw-r--r--WebCore/rendering/RenderVideo.cpp14
-rw-r--r--WebCore/rendering/RenderView.cpp144
-rw-r--r--WebCore/rendering/RenderView.h103
-rw-r--r--WebCore/rendering/RenderWidget.cpp29
-rw-r--r--WebCore/rendering/RootInlineBox.cpp20
-rw-r--r--WebCore/rendering/RootInlineBox.h6
-rw-r--r--WebCore/rendering/SVGCharacterLayoutInfo.cpp4
-rw-r--r--WebCore/rendering/SVGCharacterLayoutInfo.h12
-rw-r--r--WebCore/rendering/SVGInlineFlowBox.cpp7
-rw-r--r--WebCore/rendering/SVGInlineFlowBox.h2
-rw-r--r--WebCore/rendering/SVGInlineTextBox.cpp38
-rw-r--r--WebCore/rendering/SVGInlineTextBox.h2
-rw-r--r--WebCore/rendering/SVGRenderSupport.cpp16
-rw-r--r--WebCore/rendering/SVGRenderTreeAsText.cpp16
-rw-r--r--WebCore/rendering/SVGRenderTreeAsText.h4
-rw-r--r--WebCore/rendering/SVGRootInlineBox.cpp37
-rw-r--r--WebCore/rendering/SVGRootInlineBox.h2
-rw-r--r--WebCore/rendering/TextControlInnerElements.cpp27
-rw-r--r--WebCore/rendering/bidi.cpp268
-rw-r--r--WebCore/rendering/bidi.h2
-rw-r--r--WebCore/rendering/style/Animation.cpp128
-rw-r--r--WebCore/rendering/style/Animation.h133
-rw-r--r--WebCore/rendering/style/AnimationList.cpp57
-rw-r--r--WebCore/rendering/style/AnimationList.h60
-rw-r--r--WebCore/rendering/style/FillLayer.h4
-rw-r--r--WebCore/rendering/style/IdentityTransformOperation.h67
-rw-r--r--WebCore/rendering/style/MatrixTransformOperation.cpp50
-rw-r--r--WebCore/rendering/style/MatrixTransformOperation.h82
-rw-r--r--WebCore/rendering/style/RenderStyle.cpp16
-rw-r--r--WebCore/rendering/style/RenderStyle.h29
-rw-r--r--WebCore/rendering/style/RenderStyleConstants.h5
-rw-r--r--WebCore/rendering/style/RotateTransformOperation.cpp40
-rw-r--r--WebCore/rendering/style/RotateTransformOperation.h74
-rw-r--r--WebCore/rendering/style/SVGRenderStyle.h4
-rw-r--r--WebCore/rendering/style/SVGRenderStyleDefs.h5
-rw-r--r--WebCore/rendering/style/ScaleTransformOperation.cpp41
-rw-r--r--WebCore/rendering/style/ScaleTransformOperation.h74
-rw-r--r--WebCore/rendering/style/SkewTransformOperation.cpp41
-rw-r--r--WebCore/rendering/style/SkewTransformOperation.h74
-rw-r--r--WebCore/rendering/style/StyleCachedImage.cpp2
-rw-r--r--WebCore/rendering/style/StyleImage.h2
-rw-r--r--WebCore/rendering/style/TimingFunction.h74
-rw-r--r--WebCore/rendering/style/TransformOperation.h64
-rw-r--r--WebCore/rendering/style/TransformOperations.cpp49
-rw-r--r--WebCore/rendering/style/TransformOperations.h59
-rw-r--r--WebCore/rendering/style/TranslateTransformOperation.cpp41
-rw-r--r--WebCore/rendering/style/TranslateTransformOperation.h75
176 files changed, 10387 insertions, 6235 deletions
diff --git a/WebCore/rendering/EllipsisBox.cpp b/WebCore/rendering/EllipsisBox.cpp
index 7f563d5..fcce87d 100644
--- a/WebCore/rendering/EllipsisBox.cpp
+++ b/WebCore/rendering/EllipsisBox.cpp
@@ -32,9 +32,6 @@ 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());
-
Color textColor = style->color();
if (textColor != context->fillColor())
context->setFillColor(textColor);
@@ -46,7 +43,7 @@ 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 + m_baseline));
if (setShadow)
context->clearShadow();
@@ -74,7 +71,7 @@ bool EllipsisBox::nodeAtPoint(const HitTestRequest& request, HitTestResult& resu
}
}
- if (object()->style()->visibility() == VISIBLE && IntRect(tx, ty, m_width, m_height).contains(x, y)) {
+ if (visibleToHitTesting() && IntRect(tx, ty, m_width, m_height).contains(x, y)) {
object()->updateHitTestResult(result, IntPoint(x - tx, y - ty));
return true;
}
diff --git a/WebCore/rendering/FixedTableLayout.cpp b/WebCore/rendering/FixedTableLayout.cpp
index 1dc66a9..d7c1293 100644
--- a/WebCore/rendering/FixedTableLayout.cpp
+++ b/WebCore/rendering/FixedTableLayout.cpp
@@ -79,7 +79,7 @@ FixedTableLayout::FixedTableLayout(RenderTable* table)
{
}
-int FixedTableLayout::calcWidthArray(int tableWidth)
+int FixedTableLayout::calcWidthArray(int)
{
int usedWidth = 0;
diff --git a/WebCore/rendering/GapRects.h b/WebCore/rendering/GapRects.h
index bf53d70..a762ae5 100644
--- a/WebCore/rendering/GapRects.h
+++ b/WebCore/rendering/GapRects.h
@@ -1,7 +1,5 @@
/*
- This file is part of the KDE libraries
-
- Copyright (C) 2005, 2006 Apple Computer, Inc.
+ Copyright (C) 2005, 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
diff --git a/WebCore/rendering/HitTestResult.cpp b/WebCore/rendering/HitTestResult.cpp
index 53b376d..8126fc7 100644
--- a/WebCore/rendering/HitTestResult.cpp
+++ b/WebCore/rendering/HitTestResult.cpp
@@ -36,6 +36,11 @@
#include "XLinkNames.h"
#endif
+#if ENABLE(WML)
+#include "WMLImageElement.h"
+#include "WMLNames.h"
+#endif
+
namespace WebCore {
using namespace HTMLNames;
@@ -172,9 +177,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
@@ -192,6 +195,13 @@ String HitTestResult::altDisplayString() const
return displayString(input->alt(), m_innerNonSharedNode.get());
}
+#if ENABLE(WML)
+ if (m_innerNonSharedNode->hasTagName(WMLNames::imgTag)) {
+ WMLImageElement* image = static_cast<WMLImageElement*>(m_innerNonSharedNode.get());
+ return displayString(image->altText(), m_innerNonSharedNode.get());
+ }
+#endif
+
return String();
}
@@ -214,7 +224,7 @@ IntRect HitTestResult::imageRect() const
{
if (!image())
return IntRect();
- return m_innerNonSharedNode->renderer()->absoluteContentBox();
+ return m_innerNonSharedNode->renderBox()->absoluteContentBox();
}
KURL HitTestResult::absoluteImageURL() const
@@ -226,18 +236,22 @@ KURL HitTestResult::absoluteImageURL() const
return KURL();
AtomicString urlString;
- if (m_innerNonSharedNode->hasTagName(imgTag) || m_innerNonSharedNode->hasTagName(inputTag))
- urlString = static_cast<Element*>(m_innerNonSharedNode.get())->getAttribute(srcAttr);
+ if (m_innerNonSharedNode->hasTagName(embedTag)
+ || m_innerNonSharedNode->hasTagName(imgTag)
+ || m_innerNonSharedNode->hasTagName(inputTag)
+ || m_innerNonSharedNode->hasTagName(objectTag)
#if ENABLE(SVG)
- else if (m_innerNonSharedNode->hasTagName(SVGNames::imageTag))
- urlString = static_cast<Element*>(m_innerNonSharedNode.get())->getAttribute(XLinkNames::hrefAttr);
+ || m_innerNonSharedNode->hasTagName(SVGNames::imageTag)
+#endif
+#if ENABLE(WML)
+ || m_innerNonSharedNode->hasTagName(WMLNames::imgTag)
#endif
- else if (m_innerNonSharedNode->hasTagName(embedTag) || m_innerNonSharedNode->hasTagName(objectTag)) {
+ ) {
Element* element = static_cast<Element*>(m_innerNonSharedNode.get());
urlString = element->getAttribute(element->imageSourceAttributeName());
} else
return KURL();
-
+
return m_innerNonSharedNode->document()->completeURL(parseURL(urlString));
}
@@ -253,6 +267,10 @@ KURL HitTestResult::absoluteLinkURL() const
else if (m_innerURLElement->hasTagName(SVGNames::aTag))
urlString = m_innerURLElement->getAttribute(XLinkNames::hrefAttr);
#endif
+#if ENABLE(WML)
+ else if (m_innerURLElement->hasTagName(WMLNames::aTag))
+ urlString = m_innerURLElement->getAttribute(hrefAttr);
+#endif
else
return KURL();
@@ -270,7 +288,11 @@ bool HitTestResult::isLiveLink() const
if (m_innerURLElement->hasTagName(SVGNames::aTag))
return m_innerURLElement->isLink();
#endif
-
+#if ENABLE(WML)
+ if (m_innerURLElement->hasTagName(WMLNames::aTag))
+ return m_innerURLElement->isLink();
+#endif
+
return false;
}
diff --git a/WebCore/rendering/InlineBox.cpp b/WebCore/rendering/InlineBox.cpp
index 5dc1f47..6f7324a 100644
--- a/WebCore/rendering/InlineBox.cpp
+++ b/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;
@@ -129,8 +130,10 @@ 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_object->isReplaced()) {
+ RenderBox* box = toRenderBox(m_object);
+ box->move(dx, dy);
+ }
}
void InlineBox::paint(RenderObject::PaintInfo& paintInfo, int tx, int ty)
@@ -239,7 +242,7 @@ bool InlineBox::canAccommodateEllipsis(bool ltr, int blockEdge, int ellipsisWidt
return !(boxRect.intersects(ellipsisRect));
}
-int InlineBox::placeEllipsisBox(bool ltr, int blockEdge, int ellipsisWidth, bool&)
+int InlineBox::placeEllipsisBox(bool, int, int, bool&)
{
// Use -1 to mean "we didn't set the position."
return -1;
diff --git a/WebCore/rendering/InlineBox.h b/WebCore/rendering/InlineBox.h
index 48aab77..e17b6e8 100644
--- a/WebCore/rendering/InlineBox.h
+++ b/WebCore/rendering/InlineBox.h
@@ -21,7 +21,7 @@
#ifndef InlineBox_h
#define InlineBox_h
-#include "RenderObject.h" // needed for RenderObject::PaintInfo
+#include "RenderBox.h"
#include "TextDirection.h"
namespace WebCore {
@@ -237,6 +237,11 @@ public:
int toAdd() const { return m_toAdd; }
+ bool visibleToHitTesting() const { return object()->style()->visibility() == VISIBLE && object()->style()->pointerEvents() != PE_NONE; }
+
+ // Use with caution! The type is not checked!
+ RenderBox* renderBox() const { return toRenderBox(m_object); }
+
public:
RenderObject* m_object;
diff --git a/WebCore/rendering/InlineFlowBox.cpp b/WebCore/rendering/InlineFlowBox.cpp
index 5f37ad6..74f4151 100644
--- a/WebCore/rendering/InlineFlowBox.cpp
+++ b/WebCore/rendering/InlineFlowBox.cpp
@@ -66,7 +66,7 @@ int InlineFlowBox::marginLeft()
return 0;
if (margin.isFixed())
return margin.value();
- return object()->marginLeft();
+ return renderBox()->marginLeft();
}
int InlineFlowBox::marginRight()
@@ -79,7 +79,7 @@ int InlineFlowBox::marginRight()
return 0;
if (margin.isFixed())
return margin.value();
- return object()->marginRight();
+ return renderBox()->marginRight();
}
int InlineFlowBox::marginBorderPaddingLeft()
@@ -249,11 +249,11 @@ void InlineFlowBox::determineSpacingForFlowBoxes(bool lastLine, RenderObject* en
if (!flow->lastLineBox()->isConstructed()) {
if (ltr) {
if (!nextLineBox() &&
- ((lastLine && !object()->continuation()) || nextOnLineExists() || onEndChain(endObject)))
+ ((lastLine && !flow->continuation()) || nextOnLineExists() || onEndChain(endObject)))
includeRightEdge = true;
} else {
if ((!prevLineBox() || prevLineBox()->isConstructed()) &&
- ((lastLine && !object()->continuation()) || prevOnLineExists() || onEndChain(endObject)))
+ ((lastLine && !flow->continuation()) || prevOnLineExists() || onEndChain(endObject)))
includeLeftEdge = true;
}
}
@@ -289,7 +289,7 @@ int InlineFlowBox::placeBoxesHorizontally(int x, int& leftPosition, int& rightPo
for (InlineBox* curr = firstChild(); curr; curr = curr->nextOnLine()) {
if (curr->object()->isText()) {
InlineTextBox* text = static_cast<InlineTextBox*>(curr);
- RenderText* rt = static_cast<RenderText*>(text->object());
+ RenderText* rt = toRenderText(text->object());
if (rt->textLength()) {
if (needsWordSpacing && isSpaceOrNewline(rt->characters()[text->start()]))
x += rt->style(m_firstLine)->font().wordSpacing();
@@ -325,25 +325,20 @@ int InlineFlowBox::placeBoxesHorizontally(int x, int& leftPosition, int& rightPo
// 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->setXPos(root()->block()->width()-x);
continue; // The positioned object has no effect on the width.
}
- if (curr->object()->isInlineFlow()) {
+ if (curr->object()->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();
+ x += flow->marginLeft();
+ x = flow->placeBoxesHorizontally(x, leftPosition, rightPosition, needsWordSpacing);
+ x += flow->marginRight();
+ } else if (!curr->object()->isListMarker() || static_cast<RenderListMarker*>(curr->object())->isInside()) {
+ x += curr->renderBox()->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();
+ leftPosition = min(x + curr->renderBox()->overflowLeft(false), leftPosition);
+ rightPosition = max(x + curr->renderBox()->overflowWidth(false), rightPosition);
+ x += curr->width() + curr->renderBox()->marginRight();
}
}
}
@@ -355,7 +350,7 @@ int InlineFlowBox::placeBoxesHorizontally(int x, int& leftPosition, int& rightPo
return x;
}
-void InlineFlowBox::verticallyAlignBoxes(int& heightOfBlock)
+int InlineFlowBox::verticallyAlignBoxes(int heightOfBlock)
{
int maxPositionTop = 0;
int maxPositionBottom = 0;
@@ -389,6 +384,8 @@ void InlineFlowBox::verticallyAlignBoxes(int& heightOfBlock)
shrinkBoxesWithNoTextChildren(topPosition, bottomPosition);
heightOfBlock += maxHeight;
+
+ return heightOfBlock;
}
void InlineFlowBox::adjustMaxAscentAndDescent(int& maxAscent, int& maxDescent,
@@ -456,7 +453,7 @@ void InlineFlowBox::computeLogicalBoxHeights(int& maxPositionTop, int& maxPositi
if (maxPositionBottom < curr->height())
maxPositionBottom = curr->height();
}
- else if (curr->hasTextChildren() || curr->object()->hasHorizontalBordersOrPadding() || strictMode) {
+ else if (curr->hasTextChildren() || curr->renderBox()->hasHorizontalBordersOrPadding() || strictMode) {
int ascent = curr->baseline() - curr->yPos();
int descent = curr->height() - ascent;
if (maxAscent < ascent)
@@ -491,7 +488,7 @@ void InlineFlowBox::placeBoxesVertically(int y, int maxHeight, int maxAscent, bo
else if (curr->yPos() == PositionBottom)
curr->setYPos(y + maxHeight - curr->height());
else {
- if (!curr->hasTextChildren() && !curr->object()->hasHorizontalBordersOrPadding() && !strictMode)
+ if (!curr->hasTextChildren() && !curr->renderBox()->hasHorizontalBordersOrPadding() && !strictMode)
childAffectsTopBottomPos = false;
curr->setYPos(curr->yPos() + y + maxAscent - curr->baseline());
}
@@ -522,21 +519,21 @@ void InlineFlowBox::placeBoxesVertically(int y, int maxHeight, int maxAscent, bo
}
if (curr->object()->hasReflection()) {
- overflowTop = min(overflowTop, curr->object()->reflectionBox().y());
- overflowBottom = max(overflowBottom, curr->object()->reflectionBox().bottom());
+ overflowTop = min(overflowTop, curr->renderBox()->reflectionBox().y());
+ overflowBottom = max(overflowBottom, curr->renderBox()->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();
+ newHeight += curr->renderBox()->borderTop() + curr->renderBox()->paddingTop() +
+ curr->renderBox()->borderBottom() + curr->renderBox()->paddingBottom();
+ newY -= curr->renderBox()->borderTop() + curr->renderBox()->paddingTop();
+ newBaseline += curr->renderBox()->borderTop() + curr->renderBox()->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;
+ newY += curr->renderBox()->marginTop();
+ newHeight = curr->height() - (curr->renderBox()->marginTop() + curr->renderBox()->marginBottom());
+ overflowTop = curr->renderBox()->overflowTop(false);
+ overflowBottom = curr->renderBox()->overflowHeight(false) - newHeight;
}
curr->setYPos(newY);
@@ -575,7 +572,7 @@ void InlineFlowBox::shrinkBoxesWithNoTextChildren(int topPos, int 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 (!hasTextChildren() && !renderBox()->hasHorizontalBordersOrPadding()) {
if (yPos() < topPos)
setYPos(topPos);
if (yPos() + height() > bottomPos)
@@ -597,7 +594,7 @@ bool InlineFlowBox::nodeAtPoint(const HitTestRequest& request, HitTestResult& re
// Now check ourselves.
IntRect rect(tx + m_x, ty + m_y, m_width, m_height);
- if (object()->style()->visibility() == VISIBLE && rect.contains(x, y)) {
+ 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.
return true;
}
@@ -628,7 +625,7 @@ void InlineFlowBox::paint(RenderObject::PaintInfo& paintInfo, int tx, int ty)
// 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 ((flowObject()->continuation() || object()->isInlineContinuation()) && !object()->hasLayer()) {
// Add ourselves to the containing block of the entire continuation so that it can
// paint us atomically.
RenderBlock* block = object()->containingBlock()->containingBlock();
@@ -855,7 +852,7 @@ 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())
diff --git a/WebCore/rendering/InlineFlowBox.h b/WebCore/rendering/InlineFlowBox.h
index 9589603..62f8f69 100644
--- a/WebCore/rendering/InlineFlowBox.h
+++ b/WebCore/rendering/InlineFlowBox.h
@@ -97,10 +97,10 @@ public:
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; }
+ int borderLeft() { if (includeLeftEdge()) return renderBox()->borderLeft(); return 0; }
+ int borderRight() { if (includeRightEdge()) return renderBox()->borderRight(); return 0; }
+ int paddingLeft() { if (includeLeftEdge()) return renderBox()->paddingLeft(); return 0; }
+ int paddingRight() { if (includeRightEdge()) return renderBox()->paddingRight(); return 0; }
bool includeLeftEdge() { return m_includeLeftEdge; }
bool includeRightEdge() { return m_includeRightEdge; }
@@ -115,7 +115,7 @@ 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,
@@ -124,8 +124,8 @@ public:
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) { }
+ virtual void setVerticalOverflowPositions(int /*top*/, int /*bottom*/) { }
+ virtual void setVerticalSelectionPositions(int /*top*/, int /*bottom*/) { }
int maxHorizontalVisualOverflow() const { return m_maxHorizontalVisualOverflow; }
void removeChild(InlineBox* child);
@@ -165,7 +165,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/WebCore/rendering/InlineRunBox.h b/WebCore/rendering/InlineRunBox.h
index a624a5b..0f7c29b 100644
--- a/WebCore/rendering/InlineRunBox.h
+++ b/WebCore/rendering/InlineRunBox.h
@@ -41,8 +41,8 @@ public:
void setNextLineBox(InlineRunBox* n) { m_nextLine = n; }
void setPreviousLineBox(InlineRunBox* p) { m_prevLine = p; }
- virtual void paintBoxDecorations(RenderObject::PaintInfo&, int tx, int ty) { }
- virtual void paintTextDecorations(RenderObject::PaintInfo&, int tx, int ty, bool paintedChildren = false) { }
+ virtual void paintBoxDecorations(RenderObject::PaintInfo&, int /*tx*/, int /*ty*/) { }
+ virtual void paintTextDecorations(RenderObject::PaintInfo&, int /*tx*/, int /*ty*/, bool /*paintedChildren*/ = false) { }
protected:
InlineRunBox* m_prevLine; // The previous box that also uses our RenderObject
diff --git a/WebCore/rendering/InlineTextBox.cpp b/WebCore/rendering/InlineTextBox.cpp
index a30920a..744c4c7 100644
--- a/WebCore/rendering/InlineTextBox.cpp
+++ b/WebCore/rendering/InlineTextBox.cpp
@@ -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(m_object)->removeTextBox(this);
destroy(arena);
}
@@ -117,7 +117,7 @@ void InlineTextBox::extractLine()
if (m_extracted)
return;
- static_cast<RenderText*>(m_object)->extractTextBox(this);
+ toRenderText(m_object)->extractTextBox(this);
}
void InlineTextBox::attachLine()
@@ -125,7 +125,7 @@ void InlineTextBox::attachLine()
if (!m_extracted)
return;
- static_cast<RenderText*>(m_object)->attachTextBox(this);
+ toRenderText(m_object)->attachTextBox(this);
}
int InlineTextBox::placeEllipsisBox(bool ltr, int blockEdge, int ellipsisWidth, bool& foundBox)
@@ -162,7 +162,7 @@ int InlineTextBox::placeEllipsisBox(bool ltr, int blockEdge, int ellipsisWidth,
// 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);
+ return m_x + toRenderText(m_object)->width(m_start, offset, textPos(), m_firstLine);
}
}
else {
@@ -219,20 +219,20 @@ bool InlineTextBox::isLineBreak() const
return object()->isBR() || (object()->style()->preserveNewline() && len() == 1 && (*textObject()->text())[start()] == '\n');
}
-bool InlineTextBox::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, int x, int y, int tx, int ty)
+bool InlineTextBox::nodeAtPoint(const HitTestRequest&, HitTestResult& result, int x, int y, int tx, int ty)
{
if (isLineBreak())
return false;
IntRect rect(tx + m_x, ty + m_y, m_width, m_height);
- if (m_truncation != cFullTruncation && object()->style()->visibility() == VISIBLE && rect.contains(x, y)) {
+ if (m_truncation != cFullTruncation && visibleToHitTesting() && rect.contains(x, y)) {
object()->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 +256,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)
@@ -306,9 +306,7 @@ void InlineTextBox::paint(RenderObject::PaintInfo& paintInfo, int tx, int ty)
// Set our font.
RenderStyle* styleToUse = object()->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.
@@ -419,9 +417,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 +431,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();
@@ -493,7 +491,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* f)
+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;
@@ -527,12 +525,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(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->restore();
}
-void InlineTextBox::paintCompositionBackground(GraphicsContext* context, int tx, int ty, RenderStyle* style, const Font* f, 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);
@@ -549,8 +548,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(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->restore();
}
@@ -583,7 +583,7 @@ void InlineTextBox::paintDecoration(GraphicsContext* context, int tx, int ty, in
return;
int width = (m_truncation == cNoTruncation) ? m_width
- : static_cast<RenderText*>(m_object)->width(m_start, m_truncation, textPos(), m_firstLine);
+ : toRenderText(m_object)->width(m_start, m_truncation, textPos(), m_firstLine);
// Get the text decoration colors.
Color underline, overline, linethrough;
@@ -648,7 +648,7 @@ 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())
@@ -681,7 +681,7 @@ void InlineTextBox::paintSpellingOrGrammarMarker(GraphicsContext* pt, int tx, in
TextRun run(textObject()->text()->characters() + m_start, m_len, textObject()->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();
@@ -710,7 +710,7 @@ void InlineTextBox::paintSpellingOrGrammarMarker(GraphicsContext* pt, int tx, in
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.
@@ -723,7 +723,7 @@ void InlineTextBox::paintTextMatchMarker(GraphicsContext* pt, int tx, int ty, Do
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));
+ IntRect markerRect = enclosingIntRect(font.selectionRectForText(run, startPoint, h, sPos, ePos));
object()->document()->setRenderedRectForMarker(object()->node(), marker, markerRect);
// Optionally highlight the text
@@ -732,12 +732,12 @@ void InlineTextBox::paintTextMatchMarker(GraphicsContext* pt, int tx, int ty, Do
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::paintDocumentMarkers(GraphicsContext* pt, int tx, int ty, RenderStyle* style, const Font& font, bool background)
{
Vector<DocumentMarker> markers = object()->document()->markersForNode(object()->node());
Vector<DocumentMarker>::iterator markerIt = markers.begin();
@@ -776,13 +776,13 @@ 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;
default:
ASSERT_NOT_REACHED();
@@ -808,7 +808,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(m_object)->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);
@@ -819,7 +819,7 @@ 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(m_object)->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.
@@ -869,7 +869,7 @@ int InlineTextBox::offsetForPosition(int _x, bool includePartialGlyphs) const
if (isLineBreak())
return 0;
- RenderText* text = static_cast<RenderText*>(m_object);
+ RenderText* text = toRenderText(m_object);
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()),
@@ -884,7 +884,7 @@ int InlineTextBox::positionForOffset(int offset) const
if (isLineBreak())
return m_x;
- RenderText* text = static_cast<RenderText*>(m_object);
+ RenderText* text = toRenderText(m_object);
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;
diff --git a/WebCore/rendering/InlineTextBox.h b/WebCore/rendering/InlineTextBox.h
index d8a250b..0c2dd8a 100644
--- a/WebCore/rendering/InlineTextBox.h
+++ b/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 textObject() 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; }
+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);
+public:
RenderText* textObject() 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);
+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; }
+
+public:
virtual bool isText() const { return m_treatAsText; }
void setIsText(bool b) { m_treatAsText = b; }
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,23 @@ 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&);
};
inline RenderText* InlineTextBox::textObject() const
{
- return static_cast<RenderText*>(m_object);
+ return toRenderText(m_object);
}
} // namespace WebCore
diff --git a/WebCore/rendering/LayoutState.cpp b/WebCore/rendering/LayoutState.cpp
index b473f99..6c196ac 100644
--- a/WebCore/rendering/LayoutState.cpp
+++ b/WebCore/rendering/LayoutState.cpp
@@ -33,27 +33,24 @@
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) {
- int fixedX = 0;
- int fixedY = 0;
- renderer->view()->absolutePosition(fixedX, fixedY, true);
- m_offset = IntSize(fixedX, fixedY) + offset;
+ // FIXME: This doesn't work correctly with transforms.
+ FloatPoint fixedOffset = renderer->view()->localToAbsolute(FloatPoint(), true);
+ m_offset = IntSize(fixedOffset.x(), fixedOffset.y()) + offset;
} else
m_offset = prev->m_offset + offset;
if (renderer->isRelPositioned()) {
- if (renderer->hasLayer()) {
- int relX = 0;
- int relY = 0;
- renderer->layer()->relativePositionOffset(relX, relY);
- m_offset += IntSize(relX, relY);
- }
+ if (renderer->hasLayer())
+ m_offset += renderer->layer()->relativePositionOffset();
} else if (renderer->isPositioned() && !fixed) {
if (RenderObject* container = renderer->container())
m_offset += renderer->offsetForPositionedInContainer(container);
@@ -74,21 +71,25 @@ LayoutState::LayoutState(LayoutState* prev, RenderBox* renderer, const IntSize&
m_clipRect = clipRect;
m_clipped = true;
}
- layer->subtractScrollOffset(x, y);
+ 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();
- int x = 0;
- int y = 0;
- container->absolutePositionForContent(x, y);
- m_offset = IntSize(x, y);
- m_next = 0;
+ FloatPoint absContentPoint = container->localToAbsolute(FloatPoint(), false, true);
+ m_offset = IntSize(absContentPoint.x(), absContentPoint.y());
}
#ifndef NDEBUG
diff --git a/WebCore/rendering/LayoutState.h b/WebCore/rendering/LayoutState.h
index 551c74a..afa2952 100644
--- a/WebCore/rendering/LayoutState.h
+++ b/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/WebCore/rendering/MediaControlElements.cpp b/WebCore/rendering/MediaControlElements.cpp
index 6164585..8ad2bd6 100644
--- a/WebCore/rendering/MediaControlElements.cpp
+++ b/WebCore/rendering/MediaControlElements.cpp
@@ -38,7 +38,10 @@
#include "FloatConversion.h"
#include "Frame.h"
#include "HTMLNames.h"
+#include "MouseEvent.h"
+#include "RenderMedia.h"
#include "RenderSlider.h"
+#include "RenderTheme.h"
namespace WebCore {
@@ -50,7 +53,7 @@ static const float cStepTime = 0.07f;
static const float cSeekTime = 0.2f;
MediaControlShadowRootElement::MediaControlShadowRootElement(Document* doc, HTMLMediaElement* mediaElement)
- : HTMLDivElement(doc)
+ : HTMLDivElement(divTag, doc)
, m_mediaElement(mediaElement)
{
RefPtr<RenderStyle> rootStyle = RenderStyle::create();
@@ -67,8 +70,42 @@ MediaControlShadowRootElement::MediaControlShadowRootElement(Document* doc, HTML
// ----------------------------
+MediaTextDisplayElement::MediaTextDisplayElement(Document* doc, RenderStyle::PseudoId pseudo, HTMLMediaElement* mediaElement)
+ : HTMLDivElement(divTag, doc)
+ , m_mediaElement(mediaElement)
+{
+ RenderStyle* style = m_mediaElement->renderer()->getCachedPseudoStyle(pseudo);
+ RenderObject* renderer = createRenderer(m_mediaElement->renderer()->renderArena(), style);
+ if (renderer) {
+ setRenderer(renderer);
+ renderer->setStyle(style);
+ }
+ setAttached();
+ setInDocument(true);
+}
+
+void MediaTextDisplayElement::attachToParent(Element* parent)
+{
+ parent->addChild(this);
+ if (renderer())
+ parent->renderer()->addChild(renderer());
+}
+
+void MediaTextDisplayElement::update()
+{
+ if (renderer())
+ renderer()->updateFromElement();
+}
+
+MediaTimeDisplayElement::MediaTimeDisplayElement(Document* doc, HTMLMediaElement* element, bool currentTime)
+ : MediaTextDisplayElement(doc, currentTime ? RenderStyle::MEDIA_CONTROLS_CURRENT_TIME_DISPLAY : RenderStyle::MEDIA_CONTROLS_TIME_REMAINING_DISPLAY, element)
+{
+}
+
+// ----------------------------
+
MediaControlInputElement::MediaControlInputElement(Document* doc, RenderStyle::PseudoId pseudo, const String& type, HTMLMediaElement* mediaElement)
- : HTMLInputElement(doc)
+ : HTMLInputElement(inputTag, doc)
, m_mediaElement(mediaElement)
{
setInputType(type);
@@ -94,6 +131,14 @@ void MediaControlInputElement::update()
renderer()->updateFromElement();
}
+bool MediaControlInputElement::hitTest(const IntPoint& absPoint)
+{
+ if (renderer() && renderer()->style()->hasAppearance())
+ return theme()->hitTestMediaControlPart(renderer(), absPoint);
+
+ return false;
+}
+
// ----------------------------
MediaControlMuteButtonElement::MediaControlMuteButtonElement(Document* doc, HTMLMediaElement* element)
@@ -202,6 +247,7 @@ void MediaControlTimelineElement::defaultEventHandler(Event* event)
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.
@@ -209,10 +255,13 @@ void MediaControlTimelineElement::defaultEventHandler(Event* event)
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);
+ if (inDragMode)
+ static_cast<RenderMedia*>(m_mediaElement->renderer())->updateTimeDisplay();
}
void MediaControlTimelineElement::update(bool updateDuration)
diff --git a/WebCore/rendering/MediaControlElements.h b/WebCore/rendering/MediaControlElements.h
index 8ff726b..c1c9574 100644
--- a/WebCore/rendering/MediaControlElements.h
+++ b/WebCore/rendering/MediaControlElements.h
@@ -43,6 +43,13 @@ namespace WebCore {
class Event;
class Frame;
+enum MediaControlElements {
+ MediaFullscreenButton, MediaMuteButton, MediaPlayButton,
+ MediaSeekBackButton, MediaSeekForwardButton, MediaSlider, MediaSliderThumb,
+ MediaUnMuteButton, MediaPauseButton, MediaTimelineContainer, MediaCurrentTimeDisplay,
+ MediaTimeRemainingDisplay, MediaControlsPanel
+};
+
class MediaControlShadowRootElement : public HTMLDivElement {
public:
MediaControlShadowRootElement(Document*, HTMLMediaElement*);
@@ -54,6 +61,25 @@ private:
HTMLMediaElement* m_mediaElement;
};
+ // ----------------------------
+
+class MediaTextDisplayElement : public HTMLDivElement
+{
+public:
+ MediaTextDisplayElement(Document*, RenderStyle::PseudoId, HTMLMediaElement*);
+ void attachToParent(Element*);
+ void update();
+protected:
+ HTMLMediaElement* m_mediaElement;
+};
+
+// ----------------------------
+
+class MediaTimeDisplayElement : public MediaTextDisplayElement {
+public:
+ MediaTimeDisplayElement(Document*, HTMLMediaElement*, bool currentTime);
+};
+
// ----------------------------
class MediaControlInputElement : public HTMLInputElement {
@@ -61,6 +87,7 @@ public:
MediaControlInputElement(Document*, RenderStyle::PseudoId, const String& type, HTMLMediaElement*);
void attachToParent(Element*);
void update();
+ bool hitTest(const IntPoint& absPoint);
protected:
HTMLMediaElement* m_mediaElement;
};
diff --git a/WebCore/rendering/PointerEventsHitRules.cpp b/WebCore/rendering/PointerEventsHitRules.cpp
index bee13af..214fb09 100644
--- a/WebCore/rendering/PointerEventsHitRules.cpp
+++ b/WebCore/rendering/PointerEventsHitRules.cpp
@@ -20,12 +20,11 @@
*/
#include "config.h"
-#if ENABLE(SVG)
#include "PointerEventsHitRules.h"
namespace WebCore {
-PointerEventsHitRules::PointerEventsHitRules(ESVGHitTesting hitTesting, EPointerEvents pointerEvents)
+PointerEventsHitRules::PointerEventsHitRules(EHitTesting hitTesting, EPointerEvents pointerEvents)
: requireVisible(false)
, requireFill(false)
, requireStroke(false)
@@ -36,6 +35,7 @@ PointerEventsHitRules::PointerEventsHitRules(ESVGHitTesting hitTesting, EPointer
switch (pointerEvents)
{
case PE_VISIBLE_PAINTED:
+ case PE_AUTO: // "auto" is like "visiblePainted" when in SVG content
requireFill = true;
requireStroke = true;
case PE_VISIBLE:
@@ -72,6 +72,7 @@ PointerEventsHitRules::PointerEventsHitRules(ESVGHitTesting hitTesting, EPointer
switch (pointerEvents)
{
case PE_VISIBLE_PAINTED:
+ case PE_AUTO: // "auto" is like "visiblePainted" when in SVG content
requireVisible = true;
requireFill = true;
requireStroke = true;
@@ -107,4 +108,3 @@ PointerEventsHitRules::PointerEventsHitRules(ESVGHitTesting hitTesting, EPointer
}
// vim:ts=4:noet
-#endif // ENABLE(SVG)
diff --git a/WebCore/rendering/PointerEventsHitRules.h b/WebCore/rendering/PointerEventsHitRules.h
index 825cae8..e2dae3b 100644
--- a/WebCore/rendering/PointerEventsHitRules.h
+++ b/WebCore/rendering/PointerEventsHitRules.h
@@ -21,21 +21,20 @@
#ifndef PointerEventsHitRules_h
#define PointerEventsHitRules_h
-#if ENABLE(SVG)
-#include "SVGRenderStyle.h"
+#include "RenderStyle.h"
namespace WebCore {
class PointerEventsHitRules {
public:
- enum ESVGHitTesting {
+ enum EHitTesting {
SVG_IMAGE_HITTESTING,
SVG_PATH_HITTESTING,
SVG_TEXT_HITTESTING
};
- PointerEventsHitRules(ESVGHitTesting, EPointerEvents);
+ PointerEventsHitRules(EHitTesting, EPointerEvents);
bool requireVisible;
bool requireFill;
@@ -46,7 +45,6 @@ public:
}
-#endif // ENABLE(SVG)
#endif
// vim:ts=4:noet
diff --git a/WebCore/rendering/RenderApplet.cpp b/WebCore/rendering/RenderApplet.cpp
index 7483943..8a5088a 100644
--- a/WebCore/rendering/RenderApplet.cpp
+++ b/WebCore/rendering/RenderApplet.cpp
@@ -66,10 +66,10 @@ void RenderApplet::createWidgetIfNecessary()
// 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 +80,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/WebCore/rendering/RenderArena.cpp b/WebCore/rendering/RenderArena.cpp
index 69d08a5..c490d2b 100644
--- a/WebCore/rendering/RenderArena.cpp
+++ b/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);
@@ -132,4 +132,11 @@ void RenderArena::free(size_t size, void* ptr)
#endif
}
+#ifdef ANDROID_INSTRUMENT
+size_t RenderArena::reportPoolSize() const
+{
+ return ReportPoolSize(&m_pool);
+}
+#endif
+
} // namespace WebCore
diff --git a/WebCore/rendering/RenderArena.h b/WebCore/rendering/RenderArena.h
index 3c27d15..ca35361 100644
--- a/WebCore/rendering/RenderArena.h
+++ b/WebCore/rendering/RenderArena.h
@@ -50,6 +50,10 @@ public:
void* allocate(size_t);
void free(size_t, void*);
+#ifdef ANDROID_INSTRUMENT
+ size_t reportPoolSize() const;
+#endif
+
private:
// Underlying arena pool
ArenaPool m_pool;
diff --git a/WebCore/rendering/RenderBR.cpp b/WebCore/rendering/RenderBR.cpp
index 82b008a..2532c5b 100644
--- a/WebCore/rendering/RenderBR.cpp
+++ b/WebCore/rendering/RenderBR.cpp
@@ -56,7 +56,7 @@ int RenderBR::baselinePosition(bool firstLine, bool isRootLineBox) const
return RenderText::baselinePosition(firstLine, isRootLineBox);
}
-int RenderBR::lineHeight(bool firstLine, bool isRootLineBox) const
+int RenderBR::lineHeight(bool firstLine, bool /*isRootLineBox*/) const
{
if (firstTextBox() && !firstTextBox()->isText())
return 0;
diff --git a/WebCore/rendering/RenderBlock.cpp b/WebCore/rendering/RenderBlock.cpp
index 9dabacd..6d18ba1 100644
--- a/WebCore/rendering/RenderBlock.cpp
+++ b/WebCore/rendering/RenderBlock.cpp
@@ -32,6 +32,7 @@
#include "HitTestResult.h"
#include "InlineTextBox.h"
#include "RenderImage.h"
+#include "RenderInline.h"
#include "RenderMarquee.h"
#include "RenderReplica.h"
#include "RenderTableCell.h"
@@ -39,6 +40,7 @@
#include "RenderTheme.h"
#include "RenderView.h"
#include "SelectionController.h"
+#include <wtf/StdLibExtras.h>
#ifdef ANDROID_LAYOUT
#include "Settings.h"
@@ -74,6 +76,8 @@ static PercentHeightDescendantsMap* gPercentHeightDescendantsMap = 0;
typedef WTF::HashMap<const RenderBox*, HashSet<RenderBlock*>*> PercentHeightContainerMap;
static PercentHeightContainerMap* gPercentHeightContainerMap = 0;
+
+typedef WTF::HashMap<RenderBlock*, ListHashSet<RenderFlow*>*> ContinuationOutlineTableMap;
// Our MarginInfo state used when laying out block children.
RenderBlock::MarginInfo::MarginInfo(RenderBlock* block, int top, int bottom)
@@ -153,6 +157,29 @@ RenderBlock::~RenderBlock()
void RenderBlock::styleWillChange(RenderStyle::Diff diff, const RenderStyle* newStyle)
{
setReplaced(newStyle->isDisplayReplacedType());
+
+ if (style() && parent() && diff == RenderStyle::Layout && 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())
+ static_cast<RenderBlock*>(cb)->removePositionedObjects(this);
+ }
+ }
+
RenderFlow::styleWillChange(diff, newStyle);
}
@@ -173,7 +200,7 @@ void RenderBlock::styleDidChange(RenderStyle::Diff diff, const RenderStyle* oldS
m_lineHeight = -1;
// Update pseudos for :before and :after now.
- if (!isAnonymous() && canHaveChildren()) {
+ if (!isAnonymous() && document()->usesBeforeAfterRules() && canHaveChildren()) {
updateBeforeAfterContent(RenderStyle::BEFORE);
updateBeforeAfterContent(RenderStyle::AFTER);
}
@@ -373,7 +400,7 @@ void RenderBlock::removeChild(RenderObject *oldChild)
RenderObject* prev = oldChild->previousSibling();
RenderObject* next = oldChild->nextSibling();
bool canDeleteAnonymousBlocks = !documentBeingDestroyed() && !isInline() && !oldChild->isInline() &&
- !oldChild->continuation() &&
+ !oldChild->virtualContinuation() &&
(!prev || (prev->isAnonymousBlock() && prev->childrenInline())) &&
(!next || (next->isAnonymousBlock() && next->childrenInline()));
if (canDeleteAnonymousBlocks && prev && next) {
@@ -423,10 +450,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;
}
@@ -437,10 +464,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;
}
@@ -476,7 +503,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;
@@ -509,10 +536,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
@@ -523,7 +550,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)
@@ -548,7 +575,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())
@@ -571,8 +598,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;
}
@@ -593,16 +620,12 @@ void RenderBlock::layoutBlock(bool relayoutChildren)
bool checkForRepaint = m_everHadLayout && checkForRepaintDuringLayout();
if (checkForRepaint) {
oldBounds = absoluteClippedOverflowRect();
- oldOutlineBox = absoluteOutlineBox();
+ oldOutlineBox = absoluteOutlineBounds();
}
- bool hadColumns = m_hasColumns;
- if (!hadColumns && !hasReflection())
- view()->pushLayoutState(this, IntSize(xPos(), yPos()));
- else
- view()->disableLayoutState();
+ LayoutStateMaintainer statePusher(view(), this, IntSize(x(), y()), m_hasColumns || hasTransform() || hasReflection());
- int oldWidth = m_width;
+ int oldWidth = width();
int oldColumnWidth = desiredColumnWidth();
#ifdef ANDROID_LAYOUT
@@ -612,10 +635,10 @@ void RenderBlock::layoutBlock(bool relayoutChildren)
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;
#ifdef ANDROID_LAYOUT
@@ -628,8 +651,9 @@ void RenderBlock::layoutBlock(bool relayoutChildren)
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
@@ -675,25 +699,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);
+ if (block->floatBottom() + block->y() > height())
+ addOverhangingFloats(block, -block->x(), -block->y(), false);
}
}
}
@@ -701,21 +724,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());
@@ -724,15 +740,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()) {
@@ -741,10 +757,7 @@ void RenderBlock::layoutBlock(bool relayoutChildren)
}
}
- if (!hadColumns && !hasReflection())
- view()->popLayoutState();
- else
- view()->enableLayoutState();
+ statePusher.pop();
// Update our scroll information if we're overflow:auto/scroll/hidden now that we know if
// we overflow or not.
@@ -767,12 +780,12 @@ void RenderBlock::layoutBlock(bool relayoutChildren)
// Adjust repaint rect for scroll offset
int x = repaintRect.x();
int y = repaintRect.y();
- layer()->subtractScrollOffset(x, y);
+ layer()->subtractScrolledContentOffset(x, y);
repaintRect.setX(x);
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
@@ -785,7 +798,12 @@ void RenderBlock::layoutBlock(bool relayoutChildren)
setNeedsLayout(false);
}
-void RenderBlock::adjustPositionedBlock(RenderObject* child, const MarginInfo& marginInfo)
+bool RenderBlock::expandsToEncloseOverhangingFloats() const
+{
+ return isInlineBlockOrInlineTable() || isFloatingOrPositioned() || hasOverflowClip() || (parent() && parent()->isFlexibleBox()) || m_hasColumns || isTableCell() || isFieldset();
+}
+
+void RenderBlock::adjustPositionedBlock(RenderBox* child, const MarginInfo& marginInfo)
{
if (child->hasStaticX()) {
if (style()->direction() == LTR)
@@ -795,7 +813,7 @@ void RenderBlock::adjustPositionedBlock(RenderObject* child, const MarginInfo& m
}
if (child->hasStaticY()) {
- int y = m_height;
+ int y = height();
if (!marginInfo.canCollapseWithTop()) {
child->calcVerticalMargins();
int marginTop = child->marginTop();
@@ -830,143 +848,99 @@ 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)
+RenderBox* RenderBlock::handleSpecialChild(RenderBox* child, const MarginInfo& marginInfo, bool& handled)
{
// Handle positioned children first.
- RenderObject* next = handlePositionedChild(child, marginInfo, handled);
+ RenderBox* 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);
}
-RenderObject* RenderBlock::handlePositionedChild(RenderObject* child, const MarginInfo& marginInfo, bool& handled)
+RenderBox* RenderBlock::handlePositionedChild(RenderBox* child, const MarginInfo& marginInfo, bool& handled)
{
if (child->isPositioned()) {
handled = true;
child->containingBlock()->insertPositionedObject(child);
adjustPositionedBlock(child, marginInfo);
- return child->nextSibling();
+ return child->nextSiblingBox();
}
return 0;
}
-RenderObject* RenderBlock::handleFloatingChild(RenderObject* child, const MarginInfo& marginInfo, bool& handled)
+RenderBox* RenderBlock::handleFloatingChild(RenderBox* child, const MarginInfo& marginInfo, bool& handled)
{
if (child->isFloating()) {
handled = true;
insertFloatingObject(child);
adjustFloatingBlock(marginInfo);
- return child->nextSibling();
+ return child->nextSiblingBox();
}
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();
- }
-}
-
-RenderObject* RenderBlock::handleRunInChild(RenderObject* child, bool& handled)
+RenderBox* RenderBlock::handleRunInChild(RenderBox* blockRunIn, bool& handled)
{
// 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())) {
+ if (blockRunIn->isRunIn() && (blockRunIn->childrenInline() || blockRunIn->isReplaced())) {
// Get the next non-positioned/non-floating RenderBlock.
- RenderObject* curr = child->nextSibling();
+ RenderObject* curr = blockRunIn->nextSibling();
while (curr && curr->isFloatingOrPositioned())
curr = curr->nextSibling();
- if (curr && (curr->isRenderBlock() && curr->childrenInline() && !curr->isCompact() && !curr->isRunIn())) {
+ if (curr && (curr->isRenderBlock() && curr->childrenInline() && !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);
+ // Remove the old child.
+ RenderBox* next = blockRunIn->nextSiblingBox();
+ removeChildNode(blockRunIn);
+
+ // Create an inline.
+ RenderInline* inlineRunIn = new (renderArena()) RenderInline(blockRunIn->node());
+ inlineRunIn->setStyle(blockRunIn->style());
+
+ // 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 (runInChild->style()->styleType() != RenderStyle::BEFORE && runInChild->style()->styleType() != RenderStyle::AFTER) {
+ blockRunIn->removeChildNode(runInChild, false);
+ inlineRunIn->addChild(runInChild); // Use addChild instead of appendChildNode since it handles correct placement of the children relative to :after-generated content.
+ }
+ }
+
+ // Now insert the new child under |curr|.
+ curr->insertChildNode(inlineRunIn, curr->firstChild());
+
+ // If the run-in had an element, we need to set the new renderer.
+ if (blockRunIn->element())
+ blockRunIn->element()->setRenderer(inlineRunIn);
- // Now insert the child under |curr|.
- curr->insertChildNode(child, curr->firstChild());
+ // Destroy the block run-in.
+ blockRunIn->destroy();
+
return next;
}
}
return 0;
}
-void RenderBlock::collapseMargins(RenderObject* child, MarginInfo& marginInfo, int yPosEstimate)
+void RenderBlock::collapseMargins(RenderBox* child, MarginInfo& marginInfo, int yPosEstimate)
{
// Get our max pos and neg top margins.
int posTop = child->maxTopMargin(true);
@@ -1011,7 +985,7 @@ void RenderBlock::collapseMargins(RenderObject* child, MarginInfo& marginInfo, i
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,
@@ -1030,20 +1004,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));
@@ -1056,7 +1030,7 @@ void RenderBlock::collapseMargins(RenderObject* child, MarginInfo& marginInfo, i
}
view()->addLayoutDelta(IntSize(0, yPosEstimate - ypos));
- child->setPos(child->xPos(), ypos);
+ child->setLocation(child->x(), ypos);
if (ypos != yPosEstimate) {
if (child->shrinkToAvoidFloats())
// The child's width depends on the line width.
@@ -1066,14 +1040,14 @@ void RenderBlock::collapseMargins(RenderObject* child, MarginInfo& marginInfo, i
child->setChildNeedsLayout(true, false);
if (!child->avoidsFloats() && child->containsFloats())
- child->markAllDescendantsWithFloatsForLayout();
+ static_cast<RenderBlock*>(child)->markAllDescendantsWithFloatsForLayout();
// Our guess was wrong. Make the child lay itself out again.
child->layoutIfNeeded();
}
}
-void RenderBlock::clearFloatsIfNeeded(RenderObject* child, MarginInfo& marginInfo, int oldTopPosMargin, int oldTopNegMargin)
+void RenderBlock::clearFloatsIfNeeded(RenderBox* child, MarginInfo& marginInfo, int oldTopPosMargin, int oldTopNegMargin)
{
int heightIncrease = getClearDelta(child);
if (!heightIncrease)
@@ -1081,7 +1055,7 @@ void RenderBlock::clearFloatsIfNeeded(RenderObject* child, MarginInfo& marginInf
// 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);
+ child->setLocation(child->x(), child->y() + heightIncrease);
if (child->isSelfCollapsingBlock()) {
// For self-collapsing blocks that clear, they can still collapse their
@@ -1091,7 +1065,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
@@ -1099,7 +1073,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
@@ -1121,15 +1095,15 @@ void RenderBlock::clearFloatsIfNeeded(RenderObject* child, MarginInfo& marginInf
// So go ahead and mark the item as dirty.
child->setChildNeedsLayout(true, false);
if (!child->avoidsFloats() && child->containsFloats())
- child->markAllDescendantsWithFloatsForLayout();
+ static_cast<RenderBlock*>(child)->markAllDescendantsWithFloatsForLayout();
child->layoutIfNeeded();
}
-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);
@@ -1137,7 +1111,7 @@ int RenderBlock::estimateVerticalPosition(RenderObject* child, const MarginInfo&
return yPosEstimate;
}
-void RenderBlock::determineHorizontalPosition(RenderObject* child)
+void RenderBlock::determineHorizontalPosition(RenderBox* child)
{
if (style()->direction() == LTR) {
int xPos = borderLeft() + paddingLeft();
@@ -1148,7 +1122,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());
if (style()->textAlign() != WEBKIT_CENTER && child->style()->marginLeft().type() != Auto) {
if (child->marginLeft() < 0)
leftOff += child->marginLeft();
@@ -1160,17 +1134,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()));
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());
if (style()->textAlign() != WEBKIT_CENTER && child->style()->marginRight().type() != Auto) {
if (child->marginRight() < 0)
rightOff -= child->marginRight();
@@ -1181,12 +1155,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()));
+ toRenderBox(child)->calcHorizontalMargins(child->style()->marginLeft(), child->style()->marginRight(), lineWidth(child->y()));
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());
}
}
@@ -1225,17 +1199,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);
@@ -1264,11 +1238,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.
@@ -1277,10 +1251,10 @@ void RenderBlock::layoutBlockChildren(bool relayoutChildren, int& maxFloatBottom
int previousFloatBottom = 0;
maxFloatBottom = 0;
- RenderObject* child = firstChild();
+ RenderBox* child = firstChildBox();
while (child) {
if (legend == child) {
- child = child->nextSibling();
+ child = child->nextSiblingBox();
continue; // Skip the legend, since it has already been positioned up in the fieldset's border.
}
@@ -1300,7 +1274,7 @@ 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);
+ RenderBox* next = handleSpecialChild(child, marginInfo, handled);
if (handled) {
child = next;
continue;
@@ -1321,11 +1295,13 @@ 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())
@@ -1334,12 +1310,12 @@ void RenderBlock::layoutBlockChildren(bool relayoutChildren, int& maxFloatBottom
// 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 > height() || fb > yPosEstimate)
markDescendantsWithFloats = true;
}
if (markDescendantsWithFloats)
- child->markAllDescendantsWithFloatsForLayout();
+ static_cast<RenderBlock*>(child)->markAllDescendantsWithFloatsForLayout();
if (child->isRenderBlock())
previousFloatBottom = max(previousFloatBottom, oldRect.y() + static_cast<RenderBlock*>(child)->floatBottom());
@@ -1365,25 +1341,22 @@ 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));
+ maxFloatBottom = max(maxFloatBottom, addOverhangingFloats(static_cast<RenderBlock*>(child), -child->x(), -child->y(), !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);
+ 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);
@@ -1397,7 +1370,8 @@ void RenderBlock::layoutBlockChildren(bool relayoutChildren, int& maxFloatBottom
if (!childHadLayout && child->checkForRepaintDuringLayout())
child->repaint();
- child = child->nextSibling();
+ ASSERT(oldLayoutDelta == view()->layoutDelta());
+ child = child->nextSiblingBox();
}
// Now do the handling of the bottom of the block, adding in our bottom border/padding and
@@ -1410,10 +1384,7 @@ bool RenderBlock::layoutOnlyPositionedObjects()
if (!posChildNeedsLayout() || normalChildNeedsLayout() || selfNeedsLayout())
return false;
- if (!m_hasColumns)
- view()->pushLayoutState(this, IntSize(xPos(), yPos()));
- else
- view()->disableLayoutState();
+ LayoutStateMaintainer statePusher(view(), this, IntSize(x(), y()), m_hasColumns || hasTransform() || hasReflection());
if (needsPositionedMovementLayout()) {
tryLayoutDoingPositionedMovementOnly();
@@ -1424,10 +1395,7 @@ bool RenderBlock::layoutOnlyPositionedObjects()
// All we have to is lay out our positioned objects.
layoutPositionedObjects(false);
- if (!m_hasColumns)
- view()->popLayoutState();
- else
- view()->enableLayoutState();
+ statePusher.pop();
if (hasOverflowClip())
m_layer->updateScrollInfoAfterLayout();
@@ -1439,7 +1407,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;
@@ -1466,7 +1434,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;
@@ -1495,7 +1463,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->hasLayer()) {
r->m_renderer->repaint();
r->m_renderer->repaintOverhangingFloats();
}
@@ -1506,15 +1474,15 @@ void RenderBlock::repaintOverhangingFloats(bool paintAllDescendants)
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);
@@ -1642,12 +1610,12 @@ 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;
}
@@ -1656,28 +1624,29 @@ void RenderBlock::paintChildren(PaintInfo& paintInfo, int tx, int 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;
}
}
}
-void RenderBlock::paintCaret(PaintInfo& paintInfo, CaretType type)
+void RenderBlock::paintCaret(PaintInfo& paintInfo, int tx, int ty, CaretType type)
{
SelectionController* selection = type == CursorCaret ? document()->frame()->selection() : document()->frame()->dragCaretController();
- Node* caretNode = selection->start().node();
- RenderObject* renderer = caretNode ? caretNode->renderer() : 0;
- if (!renderer)
- return;
- // if caretNode is a block and caret is inside it then caret should be painted by that block
- bool cursorInsideBlockCaretNode = renderer->isBlockFlow() && selection->isInsideNode();
- if ((cursorInsideBlockCaretNode ? renderer : renderer->containingBlock()) == this && selection->isContentEditable()) {
+
+ // Ask the SelectionController if the caret should be painted by this block
+ RenderObject* caretPainter = selection->caretRenderer();
+ if (caretPainter == this && selection->isContentEditable()) {
+ // Convert the painting offset into the local coordinate system of this renderer,
+ // to match the localCaretRect computed by the SelectionController
+ offsetForContents(tx, ty);
+
if (type == CursorCaret)
- document()->frame()->paintCaret(paintInfo.context, paintInfo.rect);
+ document()->frame()->paintCaret(paintInfo.context, tx, ty, paintInfo.rect);
else
- document()->frame()->paintDragCaret(paintInfo.context, paintInfo.rect);
+ document()->frame()->paintDragCaret(paintInfo.context, tx, ty, paintInfo.rect);
}
}
@@ -1685,12 +1654,8 @@ 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) &&
+ if ((paintPhase == PaintPhaseBlockBackground || paintPhase == PaintPhaseChildBlockBackground) &&
hasBoxDecorations() && style()->visibility() == VISIBLE) {
paintBoxDecorations(paintInfo, tx, ty);
}
@@ -1708,7 +1673,7 @@ void RenderBlock::paintObject(PaintInfo& paintInfo, int tx, int ty)
int scrolledX = tx;
int scrolledY = ty;
if (hasOverflowClip())
- m_layer->subtractScrollOffset(scrolledX, scrolledY);
+ m_layer->subtractScrolledContentOffset(scrolledX, scrolledY);
// 2. paint contents
if (paintPhase != PaintPhaseSelfOutline) {
@@ -1721,11 +1686,11 @@ 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 && !m_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 (paintPhase == PaintPhaseFloat || paintPhase == PaintPhaseSelection || paintPhase == PaintPhaseTextClip) {
if (m_hasColumns)
paintColumns(paintInfo, scrolledX, scrolledY, true);
else
@@ -1733,18 +1698,18 @@ void RenderBlock::paintObject(PaintInfo& paintInfo, int tx, int ty)
}
// 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)
+ RenderBox::paintOutline(paintInfo.context, tx, ty, width(), height(), style());
// 6. paint continuation outlines.
- if (!inlineFlow && (paintPhase == PaintPhaseOutline || paintPhase == PaintPhaseChildOutlines)) {
+ if ((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());
+ inlineFlow->paintOutline(paintInfo.context, tx - x() + inlineFlow->containingBlock()->x(),
+ ty - y() + inlineFlow->containingBlock()->y());
}
paintContinuationOutlines(paintInfo, tx, ty);
}
@@ -1752,9 +1717,9 @@ 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) {
- paintCaret(paintInfo, CursorCaret);
- paintCaret(paintInfo, DragCaret);
+ if (paintPhase == PaintPhaseForeground) {
+ paintCaret(paintInfo, scrolledX, scrolledY, CursorCaret);
+ paintCaret(paintInfo, scrolledX, scrolledY, DragCaret);
}
}
@@ -1770,8 +1735,8 @@ void RenderBlock::paintFloats(PaintInfo& paintInfo, int tx, int ty, bool preserv
if (r->m_shouldPaint && !r->m_renderer->hasLayer()) {
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;
@@ -1812,9 +1777,9 @@ void RenderBlock::paintEllipsisBoxes(PaintInfo& paintInfo, int tx, int ty)
}
}
-HashMap<RenderBlock*, RenderFlowSequencedSet*>* continuationOutlineTable()
+static ContinuationOutlineTableMap* continuationOutlineTable()
{
- static HashMap<RenderBlock*, RenderFlowSequencedSet*> table;
+ DEFINE_STATIC_LOCAL(ContinuationOutlineTableMap, table, ());
return &table;
}
@@ -1824,10 +1789,10 @@ void RenderBlock::addContinuationWithOutline(RenderFlow* flow)
// way of painting.
ASSERT(!flow->layer());
- HashMap<RenderBlock*, RenderFlowSequencedSet*>* table = continuationOutlineTable();
- RenderFlowSequencedSet* continuations = table->get(this);
+ ContinuationOutlineTableMap* table = continuationOutlineTable();
+ ListHashSet<RenderFlow*>* continuations = table->get(this);
if (!continuations) {
- continuations = new RenderFlowSequencedSet;
+ continuations = new ListHashSet<RenderFlow*>;
table->set(this, continuations);
}
@@ -1836,23 +1801,23 @@ void RenderBlock::addContinuationWithOutline(RenderFlow* flow)
void RenderBlock::paintContinuationOutlines(PaintInfo& info, int tx, int ty)
{
- HashMap<RenderBlock*, RenderFlowSequencedSet*>* table = continuationOutlineTable();
+ ContinuationOutlineTableMap* table = continuationOutlineTable();
if (table->isEmpty())
return;
- RenderFlowSequencedSet* continuations = table->get(this);
+ ListHashSet<RenderFlow*>* 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<RenderFlow*>::iterator end = continuations->end();
+ for (ListHashSet<RenderFlow*>::iterator it = continuations->begin(); it != end; ++it) {
// Need to add in the coordinates of the intervening blocks.
RenderFlow* 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);
@@ -1917,22 +1882,22 @@ GapRects RenderBlock::selectionGapRects()
if (!shouldPaintSelectionGaps())
return GapRects();
- int tx, ty;
- absolutePositionForContent(tx, ty);
+ // FIXME: this is broken with transforms
+ FloatPoint absContentPoint = localToAbsolute(FloatPoint());
if (hasOverflowClip())
- layer()->subtractScrollOffset(tx, ty);
+ absContentPoint -= layer()->scrolledContentOffset();
- int lastTop = -borderTopExtra();
+ int lastTop = 0;
int lastLeft = leftSelectionOffset(this, lastTop);
int lastRight = rightSelectionOffset(this, lastTop);
- return fillSelectionGaps(this, tx, ty, tx, ty, lastTop, lastLeft, lastRight);
+ return fillSelectionGaps(this, absContentPoint.x(), absContentPoint.y(), absContentPoint.x(), absContentPoint.y(), lastTop, lastLeft, lastRight);
}
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();
@@ -1941,15 +1906,15 @@ void RenderBlock::paintSelection(PaintInfo& paintInfo, int tx, int ty)
}
}
-static void clipOutPositionedObjects(const RenderObject::PaintInfo* paintInfo, int tx, int ty, ListHashSet<RenderObject*>* positionedObjects)
+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()));
}
}
@@ -1963,7 +1928,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();
@@ -2006,7 +1971,7 @@ GapRects RenderBlock::fillSelectionGaps(RenderBlock* rootBlock, int blockX, int
// 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(),
+ result.uniteCenter(fillVerticalSelectionGap(lastTop, lastLeft, lastRight, ty + height(),
rootBlock, blockX, blockY, paintInfo));
return result;
}
@@ -2068,10 +2033,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;
@@ -2082,10 +2047,8 @@ GapRects RenderBlock::fillBlockSelectionGaps(RenderBlock* rootBlock, int blockX,
if (curr->isRelPositioned() && curr->hasLayer()) {
// If the relposition offset is anything other than 0, then treat this just like an absolute positioned element.
// Just disregard it completely.
- int x = 0;
- int y = 0;
- curr->layer()->relativePositionOffset(x, y);
- if (x || y)
+ IntSize relOffset = curr->layer()->relativePositionOffset();
+ if (relOffset.width() || relOffset.height())
continue;
}
@@ -2096,7 +2059,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.
@@ -2108,19 +2071,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(static_cast<RenderBlock*>(curr)->fillSelectionGaps(rootBlock, blockX, blockY, tx + curr->x(), ty + curr->y(),
lastTop, lastLeft, lastRight, paintInfo));
}
return result;
@@ -2158,7 +2121,7 @@ IntRect RenderBlock::fillVerticalSelectionGap(int lastTop, int lastLeft, int las
}
IntRect RenderBlock::fillLeftSelectionGap(RenderObject* selObj, int xPos, int yPos, int height, RenderBlock* rootBlock,
- int blockX, int blockY, int tx, int ty, const PaintInfo* paintInfo)
+ int blockX, int /*blockY*/, int tx, int ty, const PaintInfo* paintInfo)
{
int top = yPos + ty;
int left = blockX + max(leftSelectionOffset(rootBlock, yPos), leftSelectionOffset(rootBlock, yPos + height));
@@ -2174,7 +2137,7 @@ IntRect RenderBlock::fillLeftSelectionGap(RenderObject* selObj, int xPos, int yP
}
IntRect RenderBlock::fillRightSelectionGap(RenderObject* selObj, int xPos, int yPos, int height, RenderBlock* rootBlock,
- int blockX, int blockY, int tx, int ty, const PaintInfo* paintInfo)
+ int blockX, int /*blockY*/, int tx, int ty, const PaintInfo* paintInfo)
{
int left = max(xPos + tx, blockX + max(leftSelectionOffset(rootBlock, yPos), leftSelectionOffset(rootBlock, yPos + height)));
int top = yPos + ty;
@@ -2200,19 +2163,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);
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();
}
}
@@ -2220,35 +2183,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);
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);
@@ -2259,11 +2222,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;
@@ -2287,7 +2250,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());
@@ -2321,7 +2284,7 @@ void RenderBlock::insertFloatingObject(RenderObject *o)
m_floatingObjects->append(newObj);
}
-void RenderBlock::removeFloatingObject(RenderObject *o)
+void RenderBlock::removeFloatingObject(RenderBox* o)
{
if (m_floatingObjects) {
DeprecatedPtrListIterator<FloatingObject> it(*m_floatingObjects);
@@ -2356,7 +2319,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)
@@ -2371,7 +2334,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.
@@ -2380,7 +2343,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);
@@ -2397,7 +2360,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;
@@ -2407,7 +2370,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;
@@ -2440,8 +2403,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)
@@ -2526,13 +2489,12 @@ RenderBlock::leftRelOffset(int y, int fixedOffset, bool applyTextIndent,
}
if (applyTextIndent && m_firstLine && style()->direction() == LTR) {
- int cw=0;
+ int cw = 0;
if (style()->textIndent().isPercent())
cw = containingBlock()->availableWidth();
left += style()->textIndent().calcMinValue(cw);
}
- //kdDebug( 6040 ) << "leftOffset(" << y << ") = " << left << endl;
return left;
}
@@ -2564,20 +2526,18 @@ RenderBlock::rightRelOffset(int y, int fixedOffset, bool applyTextIndent,
}
if (applyTextIndent && m_firstLine && style()->direction() == RTL) {
- int cw=0;
+ int cw = 0;
if (style()->textIndent().isPercent())
cw = containingBlock()->availableWidth();
right -= style()->textIndent().calcMinValue(cw);
}
- //kdDebug( 6040 ) << "rightOffset(" << y << ") = " << right << endl;
return right;
}
int
RenderBlock::lineWidth(int y) const
{
- //kdDebug( 6040 ) << "lineWidth(" << y << ")=" << rightOffset(y) - leftOffset(y) << endl;
int result = rightOffset(y) - leftOffset(y);
return (result < 0) ? 0 : result;
}
@@ -2631,7 +2591,23 @@ 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.
+ for (RenderObject* c = firstChild(); c; c = c->nextSibling()) {
+ if (!c->isFloatingOrPositioned() && !c->isText() && !c->isRenderInline())
+ bottom = max(bottom, toRenderBox(c)->y() + c->lowestPosition(false));
+ }
+ }
+
+ if (includeSelf && isRelPositioned())
+ bottom += relativePositionOffsetY();
if (!includeOverflowInterior && hasOverflowClip())
return bottom;
@@ -2641,7 +2617,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;
@@ -2651,8 +2627,8 @@ 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);
}
}
@@ -2677,7 +2653,6 @@ int RenderBlock::lowestPosition(bool includeOverflowInterior, bool includeSelf)
}
}
-
if (!includeSelf && lastLineBox()) {
int lp = lastLineBox()->yPos() + lastLineBox()->height();
bottom = max(bottom, lp);
@@ -2688,7 +2663,25 @@ 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() && !c->isRenderInline())
+ right = max(right, toRenderBox(c)->x() + c->rightmostPosition(false));
+ }
+ }
+
+ if (includeSelf && isRelPositioned())
+ right += relativePositionOffsetX();
+
if (!includeOverflowInterior && hasOverflowClip())
return right;
@@ -2698,7 +2691,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;
@@ -2708,8 +2701,8 @@ 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);
}
}
@@ -2750,7 +2743,24 @@ 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() && !c->isRenderInline())
+ left = min(left, toRenderBox(c)->x() + c->leftmostPosition(false));
+ }
+ }
+
+ if (includeSelf && isRelPositioned())
+ left += relativePositionOffsetX();
+
if (!includeOverflowInterior && hasOverflowClip())
return left;
@@ -2760,7 +2770,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;
@@ -2770,8 +2780,8 @@ 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);
}
}
@@ -2875,31 +2885,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->isBox() || !prev->isRenderBlock() || prev->avoidsFloats() || prev->isFloatingOrPositioned())) {
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 = static_cast<RenderBlock *>(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;
+ if (!prev || !prev->isRenderBlock())
+ return;
+
RenderBlock* block = static_cast<RenderBlock *>(prev);
-
if (block->m_floatingObjects && block->floatBottom() > offset)
addIntrudingFloats(block, xoffset, offset);
@@ -2954,7 +2966,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()) {
@@ -3067,9 +3079,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);
@@ -3077,14 +3089,14 @@ 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() &&
+ if (child->isRenderBlock() && !child->isFloatingOrPositioned() &&
((floatToRemove ? child->containsFloat(floatToRemove) : child->containsFloats()) || child->shrinkToAvoidFloats()))
- child->markAllDescendantsWithFloatsForLayout(floatToRemove);
+ static_cast<RenderBlock*>(child)->markAllDescendantsWithFloatsForLayout(floatToRemove, inLayout);
}
}
}
-int RenderBlock::getClearDelta(RenderObject *child)
+int RenderBlock::getClearDelta(RenderBox* child)
{
// There is no need to compute clearance if we have no floats.
if (!containsFloats())
@@ -3112,11 +3124,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 - child->y()) : 0;
if (!result && child->avoidsFloats() && child->style()->width().isFixed() &&
- child->minPrefWidth() > lineWidth(child->yPos()) && child->minPrefWidth() <= availableWidth() &&
+ child->minPrefWidth() > lineWidth(child->y()) && child->minPrefWidth() <= availableWidth() &&
document()->inStrictMode())
- result = max(0, floatBottom() - child->yPos());
+ result = max(0, floatBottom() - child->y());
return result;
}
@@ -3130,7 +3142,7 @@ void RenderBlock::addVisualOverflow(const IntRect& r)
m_overflowHeight = max(m_overflowHeight, r.bottom());
}
-bool RenderBlock::isPointInOverflowControl(HitTestResult& result, int _x, int _y, int _tx, int _ty)
+bool RenderBlock::isPointInOverflowControl(HitTestResult& result, int, int, int, int)
{
if (!scrollsOverflow())
return false;
@@ -3140,12 +3152,10 @@ bool RenderBlock::isPointInOverflowControl(HitTestResult& result, int _x, int _y
bool RenderBlock::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, int _x, int _y, int _tx, int _ty, HitTestAction hitTestAction)
{
- bool inlineFlow = isInlineFlow();
+ int tx = _tx + x();
+ int ty = _ty + y();
- int tx = _tx + m_x;
- int ty = _ty + m_y + borderTopExtra();
-
- if (!inlineFlow && !isRenderView()) {
+ if (!isRenderView()) {
// Check if we need to do anything at all.
IntRect overflowBox = overflowRect(false);
overflowBox.move(tx, ty);
@@ -3167,7 +3177,7 @@ bool RenderBlock::nodeAtPoint(const HitTestRequest& request, HitTestResult& resu
int scrolledX = tx;
int scrolledY = ty;
if (hasOverflowClip())
- m_layer->subtractScrollOffset(scrolledX, scrolledY);
+ m_layer->subtractScrolledContentOffset(scrolledX, scrolledY);
// Hit test contents if we don't have columns.
if (!m_hasColumns && hitTestContents(request, result, _x, _y, scrolledX, scrolledY, hitTestAction))
@@ -3188,8 +3198,8 @@ bool RenderBlock::nodeAtPoint(const HitTestRequest& request, HitTestResult& resu
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();
+ 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;
@@ -3199,12 +3209,11 @@ 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 (style()->visibility() == VISIBLE && boundsRect.contains(_x, _y)) {
- updateHitTestResult(result, IntPoint(_x - tx, _y - ty + topExtra));
+ // Now hit test our background
+ if (hitTestAction == HitTestBlockBackground || hitTestAction == HitTestChildBlockBackground) {
+ IntRect boundsRect(tx, ty, width(), height());
+ if (visibleToHitTesting() && boundsRect.contains(_x, _y)) {
+ updateHitTestResult(result, IntPoint(_x - tx, _y - ty));
return true;
}
}
@@ -3262,7 +3271,7 @@ bool RenderBlock::hitTestContents(const HitTestRequest& request, HitTestResult&
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)) {
+ if (!child->hasLayer() && !child->isFloating() && !child->isRenderInline() && child->nodeAtPoint(request, result, x, y, tx, ty, childHitTest)) {
updateHitTestResult(result, IntPoint(x - tx, y - ty));
return true;
}
@@ -3312,7 +3321,7 @@ VisiblePosition RenderBlock::positionForCoordinates(int x, int y)
return RenderFlow::positionForCoordinates(x, y);
int top = borderTop();
- int bottom = top + borderTopExtra() + paddingTop() + contentHeight() + paddingBottom() + borderBottomExtra();
+ int bottom = top + paddingTop() + contentHeight() + paddingBottom();
int left = borderLeft();
int right = left + paddingLeft() + contentWidth() + paddingRight();
@@ -3320,15 +3329,8 @@ VisiblePosition RenderBlock::positionForCoordinates(int x, int y)
Node* n = element();
int contentsX = x;
- int contentsY = y - borderTopExtra();
- if (hasOverflowClip())
- m_layer->scrollOffset(contentsX, contentsY);
- if (m_hasColumns) {
- IntPoint contentsPoint(contentsX, contentsY);
- adjustPointToColumnContents(contentsPoint);
- contentsX = contentsPoint.x();
- contentsY = contentsPoint.y();
- }
+ int contentsY = y;
+ offsetForContents(contentsX, contentsY);
if (isReplaced()) {
if (y < 0 || y < height() && x < 0)
@@ -3345,8 +3347,8 @@ VisiblePosition RenderBlock::positionForCoordinates(int x, int y)
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 (RenderBox* c = firstChildBox()) { // FIXME: This code doesn't make any sense. This child could be an inline or a positioned element or a float, etc.
+ VisiblePosition p = c->positionForCoordinates(contentsX - c->x(), contentsY - c->y());
if (p.isNotNull())
return p;
}
@@ -3361,8 +3363,8 @@ VisiblePosition RenderBlock::positionForCoordinates(int x, int y)
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 (RenderBox* c = lastChildBox()) { // FIXME: This code doesn't make any sense. This child could be an inline or a positioned element or a float, etc.
+ VisiblePosition p = c->positionForCoordinates(contentsX - c->x(), contentsY - c->y());
if (p.isNotNull())
return p;
}
@@ -3409,25 +3411,38 @@ VisiblePosition RenderBlock::positionForCoordinates(int x, int y)
}
// See if any child blocks exist at this y coordinate.
- if (firstChild() && contentsY < firstChild()->yPos())
+ if (firstChildBox() && contentsY < firstChildBox()->y())
return VisiblePosition(n, 0, DOWNSTREAM);
- for (RenderObject* renderer = firstChild(); renderer; renderer = renderer->nextSibling()) {
+ for (RenderBox* renderer = firstChildBox(); renderer; renderer = renderer->nextSiblingBox()) {
if (renderer->height() == 0 || renderer->style()->visibility() != VISIBLE || renderer->isFloatingOrPositioned())
continue;
- RenderObject* next = renderer->nextSibling();
+ RenderBox* next = renderer->nextSiblingBox();
while (next && next->isFloatingOrPositioned())
- next = next->nextSibling();
+ next = next->nextSiblingBox();
if (next)
- bottom = next->yPos();
+ bottom = next->y();
else
bottom = top + scrollHeight();
- if (contentsY >= renderer->yPos() && contentsY < bottom)
- return renderer->positionForCoordinates(contentsX - renderer->xPos(), contentsY - renderer->yPos());
+ if (contentsY >= renderer->y() && contentsY < bottom)
+ return renderer->positionForCoordinates(contentsX - renderer->x(), contentsY - renderer->y());
}
return RenderFlow::positionForCoordinates(x, y);
}
+void RenderBlock::offsetForContents(int& tx, int& ty) const
+{
+ if (hasOverflowClip())
+ m_layer->addScrolledContentOffset(tx, ty);
+
+ if (m_hasColumns) {
+ IntPoint contentsPoint(tx, ty);
+ adjustPointToColumnContents(contentsPoint);
+ tx = contentsPoint.x();
+ ty = contentsPoint.y();
+ }
+}
+
int RenderBlock::availableWidth() const
{
// If we have multiple columns, then the available width is reduced to our column width.
@@ -3625,14 +3640,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);
@@ -3793,7 +3808,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;
@@ -3803,7 +3818,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;
@@ -3814,7 +3829,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;
@@ -3833,7 +3848,7 @@ static int getBPMWidth(int childValue, Length cssUnit)
return 0;
}
-static int getBorderPaddingMargin(const RenderObject* child, bool endOfInline)
+static int getBorderPaddingMargin(const RenderBox* child, bool endOfInline)
{
RenderStyle* cstyle = child->style();
int result = 0;
@@ -3853,7 +3868,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));
@@ -3933,10 +3948,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(static_cast<RenderFlow*>(child), childIterator.endOfInline);
childMin += bpm;
childMax += bpm;
@@ -4019,7 +4034,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);
@@ -4114,7 +4129,7 @@ void RenderBlock::calcInlinePrefWidths()
}
oldAutoWrap = autoWrap;
- if (!child->isInlineFlow())
+ if (!child->isRenderInline())
previousLeaf = child;
}
@@ -4285,11 +4300,11 @@ int RenderBlock::getBaselineOfFirstLineBox() const
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();
if (result != -1)
- return curr->yPos() + result; // Translate to our coordinate space.
+ return curr->y() + result; // Translate to our coordinate space.
}
}
}
@@ -4311,12 +4326,12 @@ int RenderBlock::getBaselineOfLastLineBox() const
}
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();
if (result != -1)
- return curr->yPos() + result; // Translate to our coordinate space.
+ return curr->y() + result; // Translate to our coordinate space.
}
}
if (!haveNormalFlowChild && hasLineIfEmpty())
@@ -4326,9 +4341,20 @@ int RenderBlock::getBaselineOfLastLineBox() const
return -1;
}
+bool RenderBlock::containsNonZeroBidiLevel() const
+{
+ for (RootInlineBox* root = firstRootBox(); root; root = root->nextRootBox()) {
+ for (InlineBox* box = root->firstLeafChild(); box; box = box->nextLeafChild()) {
+ if (box->bidiLevel())
+ return true;
+ }
+ }
+ return false;
+}
+
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);
@@ -4338,13 +4364,14 @@ RenderBlock* RenderBlock::firstLineBlock() const
if (firstLineBlock->isReplaced() || firstLineBlock->isFloating() ||
!parentBlock || parentBlock->firstChild() != firstLineBlock || !parentBlock->isBlockFlow())
break;
- firstLineBlock = parentBlock;
+ ASSERT(parentBlock->isRenderBlock());
+ firstLineBlock = static_cast<RenderBlock*>(parentBlock);
}
if (!hasPseudo)
return 0;
- return (RenderBlock*)(firstLineBlock);
+ return firstLineBlock;
}
void RenderBlock::updateFirstLetter()
@@ -4415,7 +4442,7 @@ void RenderBlock::updateFirstLetter()
// 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,
@@ -4486,7 +4513,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);
}
@@ -4513,7 +4540,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()) {
@@ -4523,18 +4550,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);
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();
}
}
@@ -4582,14 +4609,14 @@ void RenderBlock::adjustForBorderFit(int x, int& left, int& right) const
}
}
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);
+ static_cast<RenderBlock*>(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());
}
}
}
@@ -4601,7 +4628,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);
@@ -4687,8 +4714,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/WebCore/rendering/RenderBlock.h b/WebCore/rendering/RenderBlock.h
index d38de16..2e74e41 100644
--- a/WebCore/rendering/RenderBlock.h
+++ b/WebCore/rendering/RenderBlock.h
@@ -56,7 +56,6 @@ 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; }
@@ -112,9 +111,9 @@ 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*);
@@ -124,17 +123,17 @@ public:
virtual void borderFitAdjust(int& x, int& w) const; // Shrink the box in which the border paints if border-fit is set.
// Called to lay out the legend for a fieldset.
- virtual RenderObject* layoutLegend(bool relayoutChildren) { return 0; };
+ 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;
};
@@ -167,17 +166,17 @@ public:
void paintChildren(PaintInfo&, int tx, int ty);
void paintEllipsisBoxes(PaintInfo&, int tx, int ty);
void paintSelection(PaintInfo&, int tx, int ty);
- void paintCaret(PaintInfo&, CaretType);
+ 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);
+ void markAllDescendantsWithFloatsForLayout(RenderBox* floatToRemove = 0, bool inLayout = true);
void markPositionedObjectsForLayout();
virtual bool containsFloats() { return m_floatingObjects && !m_floatingObjects->isEmpty(); }
@@ -185,7 +184,7 @@ public:
virtual bool avoidsFloats() const;
- virtual bool hasOverhangingFloats() { return !hasColumns() && floatBottom() > m_height; }
+ virtual bool hasOverhangingFloats() { return !hasColumns() && floatBottom() > height(); }
void addIntrudingFloats(RenderBlock* prev, int xoffset, int yoffset);
int addOverhangingFloats(RenderBlock* child, int xoffset, int yoffset, bool makeChildPaintOtherFloats);
@@ -229,6 +228,8 @@ public:
RootInlineBox* firstRootBox() const { return static_cast<RootInlineBox*>(firstLineBox()); }
RootInlineBox* lastRootBox() const { return static_cast<RootInlineBox*>(lastLineBox()); }
+ bool containsNonZeroBidiLevel() const;
+
// Obtains the nearest enclosing block (including this block) that contributes a first-line style to our inline
// children.
virtual RenderBlock* firstLineBlock() const;
@@ -321,10 +322,14 @@ protected:
private:
Position positionForBox(InlineBox*, bool start = true) const;
Position positionForRenderer(RenderObject*, bool start = true) const;
-// columGap() is used by WebKit when hit-testing columns. It's called by
-// CacheBuilder when it duplicates the hit-testing logic.
+
+ // Adjust tx and ty from painting offsets to the local coords of this renderer
+ void offsetForContents(int& tx, int& ty) const;
+
+ // columGap() is used by WebKit when hit-testing columns. It's called by
+ // CacheBuilder when it duplicates the hit-testing logic.
#ifdef ANDROID_EXPOSE_COLUMN_GAP
-public:
+ public:
#endif
int columnGap() const;
#ifdef ANDROID_EXPOSE_COLUMN_GAP
@@ -333,6 +338,8 @@ private:
void calcColumnWidth();
int layoutColumns(int endOfContent = -1);
+ bool expandsToEncloseOverhangingFloats() const;
+
protected:
struct FloatingObject {
enum Type {
@@ -354,7 +361,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;
@@ -364,25 +371,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;
@@ -449,26 +437,24 @@ 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);
+ RenderBox* handleSpecialChild(RenderBox* child, const MarginInfo&, bool& handled);
+ RenderBox* handleFloatingChild(RenderBox* child, const MarginInfo&, bool& handled);
+ RenderBox* handlePositionedChild(RenderBox* child, const MarginInfo&, bool& handled);
+ RenderBox* handleRunInChild(RenderBox* child, bool& handled);
+ void collapseMargins(RenderBox* child, MarginInfo&, int yPosEstimate);
+ void clearFloatsIfNeeded(RenderBox* child, MarginInfo&, int oldTopPosMargin, int oldTopNegMargin);
+ 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;
// Allocated only when some of these fields have non-default values
struct MaxMargin {
diff --git a/WebCore/rendering/RenderBox.cpp b/WebCore/rendering/RenderBox.cpp
index 40b0e93..7711f5e 100644
--- a/WebCore/rendering/RenderBox.cpp
+++ b/WebCore/rendering/RenderBox.cpp
@@ -33,10 +33,12 @@
#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"
@@ -48,6 +50,10 @@
#include <algorithm>
#include <math.h>
+#if ENABLE(WML)
+#include "WMLNames.h"
+#endif
+
using namespace std;
namespace WebCore {
@@ -63,13 +69,9 @@ bool RenderBox::s_hadOverflowClip = false;
RenderBox::RenderBox(Node* node)
: RenderObject(node)
- , m_width(0)
- , m_height(0)
#ifdef ANDROID_LAYOUT
, m_visibleWidth(0)
#endif
- , m_x(0)
- , m_y(0)
, m_marginLeft(0)
, m_marginRight(0)
, m_marginTop(0)
@@ -79,6 +81,7 @@ RenderBox::RenderBox(Node* node)
, m_layer(0)
, m_inlineBoxWrapper(0)
{
+ setIsBox();
}
RenderBox::~RenderBox()
@@ -95,7 +98,7 @@ void RenderBox::destroy()
// This must be done before we destroy the RenderObject.
if (m_layer)
- m_layer->clearClipRect();
+ m_layer->clearClipRects();
if (style() && (style()->height().isPercent() || style()->minHeight().isPercent() || style()->maxHeight().isPercent()))
RenderBlock::removePercentHeightDescendant(this);
@@ -108,18 +111,85 @@ void RenderBox::styleWillChange(RenderStyle::Diff diff, const RenderStyle* newSt
s_wasFloating = isFloating();
s_hadOverflowClip = hasOverflowClip();
+ if (style()) {
+ // If our z-index changes value or our visibility changes,
+ // we need to dirty our stacking context's z-order list.
+ if (newStyle) {
+ 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();
+ }
+ }
+
+ // 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 (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 (!(style()->clip() == newStyle->clip()))
+ layer()->clearClipRectsIncludingDescendants();
+ } else if (diff == RenderStyle::Repaint || newStyle->outlineSize() < 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 (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();
+ }
+
+ // 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 (parent() && style()->position() != newStyle->position()) {
+ markContainingBlocksForLayout();
+ if (style()->position() == StaticPosition)
+ repaint();
+ if (isFloating() && !isPositioned() && (newStyle->position() == AbsolutePosition || newStyle->position() == FixedPosition))
+ removeFromObjectLists();
+ }
+ }
+ }
+
RenderObject::styleWillChange(diff, newStyle);
}
void RenderBox::styleDidChange(RenderStyle::Diff diff, const RenderStyle* oldStyle)
{
+ // We need to ensure that view->maximalOutlineSize() is valid for any repaints that happen
+ // during the style change (it's used by clippedOverflowRectForRepaint()).
+ if (style()->outlineWidth() > 0 && style()->outlineSize() > maximalOutlineSize(PaintPhaseOutline))
+ static_cast<RenderView*>(document()->renderer())->setMaximalOutlineSize(style()->outlineSize());
+
RenderObject::styleDidChange(diff, oldStyle);
if (needsLayout() && oldStyle && (oldStyle->height().isPercent() || oldStyle->minHeight().isPercent() || oldStyle->maxHeight().isPercent()))
RenderBlock::removePercentHeightDescendant(this);
+ bool isRootObject = isRoot();
+ bool isViewObject = isRenderView();
+
// The root and the RenderView always paint their backgrounds/borders.
- if (isRoot() || isRenderView())
+ if (isRootObject || isViewObject)
setHasBoxDecorations(true);
setInline(style()->isDisplayInlineType());
@@ -141,7 +211,7 @@ void RenderBox::styleDidChange(RenderStyle::Diff diff, const RenderStyle* oldSty
}
// 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.
@@ -177,7 +247,7 @@ void RenderBox::styleDidChange(RenderStyle::Diff diff, const RenderStyle* oldSty
if (parent() && !needsLayout() && containingBlock())
m_layer->updateLayerPositions();
}
- } else if (m_layer && !isRoot() && !isRenderView()) {
+ } else if (m_layer && !isRootObject && !isViewObject) {
ASSERT(m_layer->parent());
RenderLayer* layer = m_layer;
m_layer = 0;
@@ -210,9 +280,347 @@ void RenderBox::styleDidChange(RenderStyle::Diff diff, const RenderStyle* oldSty
// Set the text color if we're the body.
if (isBody())
document()->setTextColor(style()->color());
+}
- if (style()->outlineWidth() > 0 && style()->outlineSize() > maximalOutlineSize(PaintPhaseOutline))
- static_cast<RenderView*>(document()->renderer())->setMaximalOutlineSize(style()->outlineSize());
+
+int RenderBox::offsetLeft() const
+{
+ RenderBox* offsetPar = offsetParent();
+ if (!offsetPar)
+ return 0;
+ int xPos = x() - 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->isBody() && !offsetPar->isRelPositioned() && !offsetPar->isPositioned())
+ xPos += offsetPar->x();
+ }
+ return xPos;
+}
+
+int RenderBox::offsetTop() const
+{
+ RenderBox* offsetPar = offsetParent();
+ if (!offsetPar)
+ return 0;
+ int yPos = y() - 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->isBody() && !offsetPar->isRelPositioned() && !offsetPar->isPositioned())
+ yPos += offsetPar->y();
+ }
+ return yPos;
+}
+
+RenderBox* RenderBox::offsetParent() 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;
+ curr = curr->parent();
+ }
+ return curr && curr->isBox() ? toRenderBox(curr) : 0;
+}
+
+// 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();
+}
+
+int RenderBox::clientHeight() const
+{
+ return height() - borderTop() - borderBottom() - horizontalScrollbarHeight();
+}
+
+// scrollWidth/scrollHeight will be the same as overflowWidth/overflowHeight unless the
+// object has overflow:hidden/scroll/auto specified and also has overflow.
+// FIXME: It's not completely clear how scrollWidth/Height should behave for
+// objects with visible overflow.
+int RenderBox::scrollWidth() const
+{
+ if (hasOverflowClip())
+ return m_layer->scrollWidth();
+ return overflowWidth();
+}
+
+int RenderBox::scrollHeight() const
+{
+ if (hasOverflowClip())
+ return m_layer->scrollHeight();
+ return overflowHeight();
+}
+
+int RenderBox::scrollLeft() const
+{
+ return hasOverflowClip() ? m_layer->scrollXOffset() : 0;
+}
+
+int RenderBox::scrollTop() const
+{
+ return hasOverflowClip() ? m_layer->scrollYOffset() : 0;
+}
+
+void RenderBox::setScrollLeft(int newLeft)
+{
+ if (hasOverflowClip())
+ m_layer->scrollToXOffset(newLeft);
+}
+
+void RenderBox::setScrollTop(int newTop)
+{
+ if (hasOverflowClip())
+ m_layer->scrollToYOffset(newTop);
+}
+
+int RenderBox::paddingTop(bool) const
+{
+ int w = 0;
+ Length padding = style()->paddingTop();
+ if (padding.isPercent())
+ w = containingBlock()->availableWidth();
+ return padding.calcMinValue(w);
+}
+
+int RenderBox::paddingBottom(bool) const
+{
+ int w = 0;
+ Length padding = style()->paddingBottom();
+ if (padding.isPercent())
+ w = containingBlock()->availableWidth();
+ return padding.calcMinValue(w);
+}
+
+int RenderBox::paddingLeft(bool) const
+{
+ int w = 0;
+ Length padding = style()->paddingLeft();
+ if (padding.isPercent())
+ w = containingBlock()->availableWidth();
+ return padding.calcMinValue(w);
+}
+
+int RenderBox::paddingRight(bool) const
+{
+ int w = 0;
+ Length padding = style()->paddingRight();
+ if (padding.isPercent())
+ w = containingBlock()->availableWidth();
+ return padding.calcMinValue(w);
+}
+
+void RenderBox::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).
+ RenderFlow* continuation = virtualContinuation();
+ if (topLevel && continuation) {
+ rects.append(IntRect(tx, ty - collapsedMarginTop(),
+ width(), height() + collapsedMarginTop() + collapsedMarginBottom()));
+ continuation->absoluteRects(rects,
+ tx - x() + continuation->containingBlock()->x(),
+ ty - y() + continuation->containingBlock()->y(), topLevel);
+ } else
+ rects.append(IntRect(tx, ty, width(), height()));
+}
+
+void RenderBox::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).
+ RenderFlow* continuation = virtualContinuation();
+ 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())));
+}
+
+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(RenderBox* /*repaintContainer*/) const
+{
+ IntRect box = borderBoundingBox();
+ adjustRectForOutlineAndShadow(box);
+
+ FloatQuad absOutlineQuad = localToAbsoluteQuad(FloatRect(box));
+ box = absOutlineQuad.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)
+{
+ // 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).
+ RenderFlow* continuation = virtualContinuation();
+ if (continuation) {
+ graphicsContext->addFocusRingRect(IntRect(tx, ty - collapsedMarginTop(), width(), height() + collapsedMarginTop() + collapsedMarginBottom()));
+ continuation->addFocusRingRects(graphicsContext,
+ tx - x() + continuation->containingBlock()->x(),
+ ty - y() + continuation->containingBlock()->y());
+ } else
+ 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
@@ -255,22 +663,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
@@ -304,10 +702,10 @@ 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()) {
@@ -315,16 +713,16 @@ bool RenderBox::nodeAtPoint(const HitTestRequest& request, HitTestResult& result
// 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->isRenderInline() && 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 (style()->visibility() == VISIBLE && 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;
}
@@ -335,8 +733,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);
@@ -402,8 +800,7 @@ 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).
@@ -444,8 +841,7 @@ 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).
@@ -490,7 +886,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;
@@ -562,10 +958,12 @@ IntSize RenderBox::calculateBackgroundSize(const FillLayer* bgLayer, int scaledW
return bg->imageSize(this, style()->effectiveZoom());
}
-void RenderBox::imageChanged(WrappedImagePtr image)
+void RenderBox::imageChanged(WrappedImagePtr image, const IntRect*)
{
- if (isInlineFlow() ||
- style()->borderImage().image() && style()->borderImage().image()->data() == image ||
+ if (!parent())
+ return;
+
+ if (isRenderInline() || style()->borderImage().image() && style()->borderImage().image()->data() == image ||
style()->maskBoxImage().image() && style()->maskBoxImage().image()->data() == image) {
repaint();
return;
@@ -579,7 +977,7 @@ void RenderBox::imageChanged(WrappedImagePtr image)
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()) {
@@ -601,24 +999,22 @@ bool RenderBox::repaintLayerRectsForImage(WrappedImagePtr image, const FillLayer
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;
}
}
@@ -894,10 +1290,10 @@ void RenderBox::paintCustomHighlight(int tx, int ty, const AtomicString& type, b
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 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);
}
}
@@ -914,8 +1310,8 @@ 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) {
@@ -930,26 +1326,26 @@ IntRect RenderBox::getClipRect(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);
}
@@ -960,13 +1356,13 @@ int RenderBox::containingBlockWidth() const
if (!cb)
return 0;
if (shrinkToAvoidFloats())
- return cb->lineWidth(m_y);
+ return cb->lineWidth(y());
return cb->availableWidth();
}
IntSize RenderBox::offsetForPositionedInContainer(RenderObject* container) const
{
- if (!container->isRelPositioned() || !container->isInlineFlow())
+ if (!container->isRelPositioned() || !container->isRenderInline())
return IntSize();
// When we have an enclosing relpositioned inline, we need to add in the offset of the first line
@@ -1001,15 +1397,17 @@ IntSize RenderBox::offsetForPositionedInContainer(RenderObject* container) const
return offset;
}
-bool RenderBox::absolutePosition(int& xPos, int& yPos, bool fixed) const
+FloatPoint RenderBox::localToAbsolute(FloatPoint localPoint, bool fixed, bool useTransforms) const
{
if (RenderView* v = view()) {
- if (LayoutState* layoutState = v->layoutState()) {
- xPos = layoutState->m_offset.width() + m_x;
- yPos = layoutState->m_offset.height() + m_y;
+ if (v->layoutStateEnabled()) {
+ LayoutState* layoutState = v->layoutState();
+ IntSize offset = layoutState->m_offset;
+ offset.expand(x(), y());
+ localPoint += offset;
if (style()->position() == RelativePosition && m_layer)
- m_layer->relativePositionOffset(xPos, yPos);
- return true;
+ localPoint += m_layer->relativePositionOffset();
+ return localPoint;
}
}
@@ -1017,41 +1415,91 @@ bool RenderBox::absolutePosition(int& xPos, int& yPos, bool fixed) const
fixed = true;
RenderObject* o = container();
- if (o && o->absolutePositionForContent(xPos, yPos, fixed)) {
- if (style()->position() == AbsolutePosition) {
- IntSize offset = offsetForPositionedInContainer(o);
- xPos += offset.width();
- yPos += offset.height();
+ 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->hasOverflowClip())
- o->layer()->subtractScrollOffset(xPos, yPos);
-
- 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->adjustRectForColumns(rect);
- xPos += rect.x();
- yPos += rect.y();
- } else {
- xPos += m_x;
- yPos += m_y;
- }
- }
+ localPoint += offsetFromContainer(o);
- if (isRelPositioned()) {
- xPos += relativePositionOffsetX();
- yPos += relativePositionOffsetY();
+ return o->localToAbsolute(localPoint, fixed, useTransforms);
+ }
+
+ return FloatPoint();
+}
+
+FloatPoint RenderBox::absoluteToLocal(FloatPoint containerPoint, bool fixed, bool useTransforms) const
+{
+ // We don't expect absoluteToLocal() to be called during layout (yet)
+ 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);
+ localPoint -= offsetFromContainer(o);
+ if (useTransforms && m_layer && m_layer->transform())
+ localPoint = m_layer->transform()->inverse().mapPoint(localPoint);
+ return localPoint;
+ }
+
+ return FloatPoint();
+}
+
+FloatQuad RenderBox::localToContainerQuad(const FloatQuad& localQuad, RenderBox* repaintContainer, bool fixed) const
+{
+ if (repaintContainer == this)
+ return localQuad;
+
+ 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);
}
+ quad += offsetFromContainer(o);
+ return o->localToContainerQuad(quad, repaintContainer, fixed);
+ }
+
+ return FloatQuad();
+}
- return true;
- } else {
- xPos = 0;
- yPos = 0;
- return false;
+IntSize RenderBox::offsetFromContainer(RenderObject* o) const
+{
+ ASSERT(o == container());
+
+ IntSize offset;
+ if (isRelPositioned())
+ offset += relativePositionOffset();
+
+ if (!isInline() || isReplaced()) {
+ RenderBlock* cb;
+ if (o->isBlockFlow() && style()->position() != AbsolutePosition && style()->position() != FixedPosition
+ && (cb = static_cast<RenderBlock*>(o))->hasColumns()) {
+ IntRect rect(x(), y(), 1, 1);
+ cb->adjustRectForColumns(rect);
+ offset.expand(rect.x(), rect.y());
+ } else
+ offset.expand(x(), y());
}
+
+ if (o->hasOverflowClip())
+ offset -= toRenderBox(o)->layer()->scrolledContentOffset();
+
+ if (style()->position() == AbsolutePosition)
+ offset += offsetForPositionedInContainer(o);
+
+ return offset;
}
void RenderBox::dirtyLineBoxes(bool fullLayout, bool /*isRootLineBox*/)
@@ -1089,8 +1537,7 @@ void RenderBox::position(InlineBox* box)
box->remove();
box->destroy(renderArena());
} else if (isReplaced()) {
- m_x = box->xPos();
- m_y = box->yPos();
+ setLocation(box->xPos(), box->yPos());
m_inlineBoxWrapper = box;
}
}
@@ -1105,42 +1552,46 @@ void RenderBox::deleteLineBoxWrapper()
}
}
-IntRect RenderBox::absoluteClippedOverflowRect()
+IntRect RenderBox::clippedOverflowRectForRepaint(RenderBox* repaintContainer)
{
if (style()->visibility() != VISIBLE && !enclosingLayer()->hasVisibleContent())
return IntRect();
IntRect r = overflowRect(false);
- if (RenderView* v = view())
+ RenderView* v = view();
+ 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.
theme()->adjustRepaintRect(this, r);
- // FIXME: Technically the outline inflation could fit within the theme inflation.
- if (!isInline() && continuation())
- r.inflate(continuation()->style()->outlineSize());
- else
- r.inflate(style()->outlineSize());
+ // We have to use maximalOutlineSize() because a child might have an outline
+ // that projects outside of our overflowRect.
+ if (v) {
+ ASSERT(style()->outlineSize() <= v->maximalOutlineSize());
+ r.inflate(v->maximalOutlineSize());
+ }
}
- computeAbsoluteRepaintRect(r);
+ computeRectForRepaint(r, repaintContainer);
return r;
}
-void RenderBox::computeAbsoluteRepaintRect(IntRect& rect, bool fixed)
+void RenderBox::computeRectForRepaint(IntRect& rect, RenderBox* repaintContainer, bool fixed)
{
if (RenderView* v = view()) {
- if (LayoutState* layoutState = v->layoutState()) {
- if (style()->position() == RelativePosition && m_layer) {
- int relX = 0;
- int relY = 0;
- m_layer->relativePositionOffset(relX, relY);
- rect.move(relX, relY);
- }
- rect.move(m_x, m_y);
+ // LayoutState is only valid for root-relative repainting
+ if (v->layoutStateEnabled() && !repaintContainer) {
+ LayoutState* layoutState = v->layoutState();
+ if (style()->position() == RelativePosition && m_layer)
+ rect.move(m_layer->relativePositionOffset());
+
+ rect.move(x(), y());
rect.move(layoutState->m_offset);
if (layoutState->m_clipped)
rect.intersect(layoutState->m_clipRect);
@@ -1148,97 +1599,86 @@ void RenderBox::computeAbsoluteRepaintRect(IntRect& rect, bool fixed)
}
}
- // FIXME: This is really a hack. If the reflection caused the repaint, we don't have to
- // do this (and yet we do). If there are nested reflections, then the single static is insufficient.
- static bool invalidatingReflection;
- if (hasReflection() && !invalidatingReflection) {
- invalidatingReflection = true;
- layer()->reflection()->repaintRectangle(rect);
- invalidatingReflection = false;
- }
+ if (hasReflection())
+ rect.unite(reflectedRect(rect));
+
+ if (repaintContainer == this)
+ return;
- int x = rect.x() + m_x;
- int y = rect.y() + m_y;
+ RenderObject* o = container();
+ if (!o)
+ return;
- // 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().
- if (style()->position() == RelativePosition && m_layer)
- m_layer->relativePositionOffset(x, y);
+ IntPoint topLeft = rect.location();
+ topLeft.move(x(), y());
if (style()->position() == FixedPosition)
fixed = true;
-
- RenderObject* o = container();
- if (o) {
- if (o->isBlockFlow() && style()->position() != AbsolutePosition && style()->position() != FixedPosition) {
- RenderBlock* cb = static_cast<RenderBlock*>(o);
- if (cb->hasColumns()) {
- IntRect repaintRect(x, y, rect.width(), rect.height());
- cb->adjustRectForColumns(repaintRect);
- x = repaintRect.x();
- y = repaintRect.y();
- rect = repaintRect;
- }
- }
- if (style()->position() == AbsolutePosition) {
- IntSize offset = offsetForPositionedInContainer(o);
- x += offset.width();
- y += offset.height();
- }
-
- // 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()) {
- fixed = false;
- rect = m_layer->transform()->mapRect(rect);
- x = rect.x() + m_x;
- y = rect.y() + m_y;
+ if (o->isBlockFlow() && style()->position() != AbsolutePosition && style()->position() != FixedPosition) {
+ RenderBlock* cb = static_cast<RenderBlock*>(o);
+ if (cb->hasColumns()) {
+ IntRect repaintRect(topLeft, rect.size());
+ cb->adjustRectForColumns(repaintRect);
+ topLeft = repaintRect.location();
+ rect = repaintRect;
}
+ }
- // 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()) {
- // 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());
- o->layer()->subtractScrollOffset(x, y); // For overflow:auto/scroll/hidden.
- IntRect repaintRect(x, y, rect.width(), rect.height());
- rect = intersection(repaintRect, boxRect);
- if (rect.isEmpty())
- return;
- } else {
- rect.setX(x);
- rect.setY(y);
- }
-
- o->computeAbsoluteRepaintRect(rect, 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()) {
+ fixed = false;
+ rect = m_layer->transform()->mapRect(rect);
+ // FIXME: this clobbers topLeft adjustment done for multicol above
+ topLeft = rect.location();
+ topLeft.move(x(), y());
+ }
+
+ if (style()->position() == AbsolutePosition)
+ topLeft += offsetForPositionedInContainer(o);
+ else if (style()->position() == RelativePosition && m_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();
}
+
+ // 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(rect, repaintContainer, 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);
}
@@ -1293,7 +1733,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;
}
@@ -1301,7 +1741,7 @@ 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());
@@ -1313,52 +1753,57 @@ void RenderBox::calcWidth()
// just calculate margins
m_marginLeft = marginLeft.calcMinValue(containerWidth);
m_marginRight = marginRight.calcMinValue(containerWidth);
+#ifdef ANDROID_LAYOUT
+ if (treatAsReplaced) {
+#else
if (treatAsReplaced)
- m_width = max(width.value() + borderLeft() + borderRight() + paddingLeft() + paddingRight(), minPrefWidth());
+#endif
+ setWidth(max(w.value() + borderLeft() + borderRight() + paddingLeft() + paddingRight(), minPrefWidth()));
#ifdef ANDROID_LAYOUT
- // in SSR mode with replaced box, if the box width is wider than the container width,
- // it will be shrinked to fit to the container.
- if (containerWidth && (m_width+m_marginLeft+m_marginRight) > containerWidth &&
- document()->frame()->settings()->layoutAlgorithm() == Settings::kLayoutSSR) {
- m_marginLeft = m_marginRight = 0;
- m_width = m_minPrefWidth = m_maxPrefWidth = containerWidth;
+ // in SSR mode with replaced box, if the box width is wider than the container width,
+ // it will be shrinked to fit to the container.
+ if (containerWidth && (width() + m_marginLeft + m_marginRight) > containerWidth &&
+ document()->frame()->settings()->layoutAlgorithm() == Settings::kLayoutSSR) {
+ m_marginLeft = m_marginRight = 0;
+ setWidth(containerWidth);
+ m_minPrefWidth = m_maxPrefWidth = containerWidth;
+ }
}
-#endif
-
+#endif
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 {
@@ -1371,28 +1816,29 @@ void RenderBox::calcWidth()
// If the box width is wider than the container width, it will be shrinked to fit to the container.
if (containerWidth && !treatAsReplaced &&
document()->settings()->layoutAlgorithm() == Settings::kLayoutSSR) {
- m_width += m_marginLeft + m_marginRight;
+ setWidth(width() + m_marginLeft + m_marginRight);
m_marginLeft = m_marginLeft > ANDROID_SSR_MARGIN_PADDING ? ANDROID_SSR_MARGIN_PADDING : m_marginLeft;
m_marginRight = m_marginRight > ANDROID_SSR_MARGIN_PADDING ? ANDROID_SSR_MARGIN_PADDING : m_marginRight;
- if (m_width > containerWidth)
- m_width = m_minPrefWidth = m_maxPrefWidth = containerWidth-(m_marginLeft + m_marginRight);
- else
- m_width -= (m_marginLeft + m_marginRight);
+ if (width() > containerWidth) {
+ m_minPrefWidth = m_maxPrefWidth = containerWidth-(m_marginLeft + m_marginRight);
+ setWidth(m_minPrefWidth);
+ } else
+ setWidth(width() -(m_marginLeft + m_marginRight));
}
#endif
- 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();
@@ -1405,24 +1851,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
@@ -1457,20 +1902,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);
}
@@ -1512,36 +1957,36 @@ 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) {
#ifdef ANDROID_LAYOUT
// in SSR mode, ignore CSS height as layout is so different
if (document()->settings()->layoutAlgorithm() == Settings::kLayoutSSR)
- height = m_height;
+ heightResult = -1;
else
#endif
- 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);
+ 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
@@ -1550,12 +1995,12 @@ void RenderBox::calcHeight()
int margins = collapsedMarginTop() + collapsedMarginBottom();
int visHeight = 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));
}
}
}
@@ -1626,7 +2071,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();
@@ -1707,7 +2152,7 @@ int RenderBox::calcReplacedHeightUsing(Length height) const
return calcContentBoxHeight(height.calcValue(newHeight));
}
- int availableHeight = isPositioned() ? containingBlockHeightForPositioned(cb) : cb->availableHeight();
+ int availableHeight = isPositioned() ? containingBlockHeightForPositioned(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
@@ -1806,7 +2251,7 @@ void RenderBox::setStaticY(int staticY)
int RenderBox::containingBlockWidthForPositioned(const RenderObject* containingBlock) const
{
- if (containingBlock->isInlineFlow()) {
+ if (containingBlock->isRenderInline()) {
ASSERT(containingBlock->isRelPositioned());
const RenderFlow* flow = static_cast<const RenderFlow*>(containingBlock);
@@ -1830,12 +2275,22 @@ int RenderBox::containingBlockWidthForPositioned(const RenderObject* containingB
return max(0, (fromRight - fromLeft));
}
- return containingBlock->width() - containingBlock->borderLeft() - containingBlock->borderRight() - containingBlock->verticalScrollbarWidth();
+ const RenderBox* containingBlockBox = toRenderBox(containingBlock);
+ return containingBlockBox->width() - containingBlockBox->borderLeft() - containingBlockBox->borderRight() - containingBlockBox->verticalScrollbarWidth();
}
int RenderBox::containingBlockHeightForPositioned(const RenderObject* containingBlock) const
{
- return containingBlock->height() - containingBlock->borderTop() - containingBlock->borderBottom();
+ const RenderBox* containingBlockBox = toRenderBox(containingBlock);
+
+ int heightResult;
+ if (containingBlock->isRenderInline()) {
+ ASSERT(containingBlock->isRelPositioned());
+ heightResult = static_cast<const RenderInline*>(containingBlock)->linesBoundingBox().height();
+ } else
+ heightResult = containingBlockBox->height();
+
+ return heightResult - containingBlockBox->borderTop() - containingBlockBox->borderBottom();
}
void RenderBox::calcAbsoluteHorizontal()
@@ -1860,7 +2315,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
@@ -1872,8 +2327,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 RenderBox* containerBlock = toRenderBox(container());
+
const int containerWidth = containingBlockWidthForPositioned(containerBlock);
// To match WinIE, in quirks mode use the parent's 'direction' property
@@ -1916,24 +2371,28 @@ void RenderBox::calcAbsoluteHorizontal()
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();
+ for (RenderBox* po = parentBox(); po && po != containerBlock; po = po->parentBox())
+ staticPosition += po->x();
left.setValue(Fixed, staticPosition);
} else {
- RenderObject* po = parent();
+ RenderBox* po = parentBox();
// '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();
+ for (; po && po != containerBlock; po = po->parentBox())
+ staticPosition -= 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()) {
@@ -1947,11 +2406,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);
}
}
@@ -1967,25 +2426,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 RenderBox* 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)
@@ -2172,7 +2634,7 @@ void RenderBox::calcAbsoluteVertical()
// We don't use containingBlock(), since we may be positioned by an enclosing relpositioned inline.
- const RenderObject* containerBlock = container();
+ const RenderBox* containerBlock = toRenderBox(container());
const int containerHeight = containingBlockHeightForPositioned(containerBlock);
@@ -2204,20 +2666,22 @@ void RenderBox::calcAbsoluteVertical()
if (top.isAuto() && bottom.isAuto()) {
// staticY should already have been set through layout of the parent()
int staticTop = staticY() - containerBlock->borderTop();
- for (RenderObject* po = parent(); po && po != containerBlock; po = po->parent()) {
+ for (RenderBox* po = parentBox(); po && po != containerBlock; po = po->parentBox()) {
if (!po->isTableRow())
- staticTop += po->yPos();
+ staticTop += 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
@@ -2233,11 +2697,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);
}
}
@@ -2252,19 +2716,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 RenderBox* 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)
@@ -2273,17 +2737,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;
}
@@ -2299,7 +2763,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);
@@ -2366,7 +2830,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)
@@ -2374,7 +2838,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);
}
}
@@ -2393,7 +2857,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 RenderBox* containerBlock = toRenderBox(container());
const int containerWidth = containingBlockWidthForPositioned(containerBlock);
@@ -2415,8 +2879,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'
@@ -2429,15 +2893,15 @@ void RenderBox::calcAbsoluteHorizontalReplaced()
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();
+ for (RenderBox* po = parentBox(); po && po != containerBlock; po = po->parentBox())
+ staticPosition += po->x();
left.setValue(Fixed, staticPosition);
} else {
- RenderObject* po = parent();
+ RenderBox* po = parentBox();
// '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();
+ for (; po && po != containerBlock; po = po->parentBox())
+ staticPosition -= po->x();
right.setValue(Fixed, staticPosition);
}
}
@@ -2534,7 +2998,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,12 +3013,12 @@ void RenderBox::calcAbsoluteHorizontalReplaced()
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->xPos() - firstLine->xPos()));
return;
}
}
- m_x = leftValue + m_marginLeft + containerBlock->borderLeft();
+ m_frameRect.setX(leftValue + m_marginLeft + containerBlock->borderLeft());
}
void RenderBox::calcAbsoluteVerticalReplaced()
@@ -2566,7 +3030,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 RenderBox* containerBlock = toRenderBox(container());
const int containerHeight = containingBlockHeightForPositioned(containerBlock);
@@ -2584,8 +3048,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'
@@ -2595,9 +3059,9 @@ void RenderBox::calcAbsoluteVerticalReplaced()
if (top.isAuto() && bottom.isAuto()) {
// staticY should already have been set through layout of the parent().
int staticTop = staticY() - containerBlock->borderTop();
- for (RenderObject* po = parent(); po && po != containerBlock; po = po->parent()) {
+ for (RenderBox* po = parentBox(); po && po != containerBlock; po = po->parentBox()) {
if (!po->isTableRow())
- staticTop += po->yPos();
+ staticTop += po->y();
}
top.setValue(Fixed, staticTop);
}
@@ -2686,10 +3150,10 @@ 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::caretRect(InlineBox* box, int caretOffset, int* extraWidthToEndOfLine)
+IntRect RenderBox::localCaretRect(InlineBox* box, int caretOffset, int* extraWidthToEndOfLine)
{
// VisiblePositions at offsets inside containers either a) refer to the positions before/after
// those containers (tables and select elements) or b) refer to the position inside an empty block.
@@ -2698,11 +3162,11 @@ IntRect RenderBox::caretRect(InlineBox* box, int caretOffset, int* extraWidthToE
// 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();
@@ -2723,47 +3187,51 @@ IntRect RenderBox::caretRect(InlineBox* box, int caretOffset, int* extraWidthToE
if (fontHeight > rect.height() || !isReplaced() && !isTable())
rect.setHeight(fontHeight);
- RenderObject* cb = containingBlock();
- int cbx, cby;
- if (!cb || !cb->absolutePosition(cbx, cby))
- // No point returning a relative position.
- return IntRect();
-
if (extraWidthToEndOfLine)
- *extraWidthToEndOfLine = xPos() + m_width - rect.right();
+ *extraWidthToEndOfLine = x() + width() - rect.right();
- rect.move(cbx, cby);
+ // Move to local coords
+ rect.move(-x(), -y());
return rect;
}
-int RenderBox::lowestPosition(bool includeOverflowInterior, bool includeSelf) const
+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;
}
-int RenderBox::rightmostPosition(bool includeOverflowInterior, bool includeSelf) const
+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;
}
-int RenderBox::leftmostPosition(bool includeOverflowInterior, bool includeSelf) const
+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;
}
+#if ENABLE(SVG)
+
+TransformationMatrix RenderBox::localTransform() const
+{
+ return TransformationMatrix(1, 0, 0, 1, x(), y());
+}
+
+#endif
+
} // namespace WebCore
diff --git a/WebCore/rendering/RenderBox.h b/WebCore/rendering/RenderBox.h
index 133ae37..33e7411 100644
--- a/WebCore/rendering/RenderBox.h
+++ b/WebCore/rendering/RenderBox.h
@@ -24,10 +24,11 @@
#define RenderBox_h
#include "RenderObject.h"
+#include "ScrollTypes.h"
namespace WebCore {
- enum WidthType { Width, MinWidth, MaxWidth };
+enum WidthType { Width, MinWidth, MaxWidth };
class RenderBox : public RenderObject {
public:
@@ -36,6 +37,129 @@ public:
virtual const char* renderName() const { return "RenderBox"; }
+ int x() const { return m_frameRect.x(); }
+ int y() const { return m_frameRect.y(); }
+ int width() const { ASSERT(!isRenderInline()); return m_frameRect.width(); }
+ int height() const { ASSERT(!isRenderInline()); 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 { ASSERT(!isRenderInline()); 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 { ASSERT(!isRenderInline()); 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(); } // This will work on inlines to return the bounding box of all of the lines' border boxes.
+
+ // 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(RenderBox* /*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(); }
+ virtual int offsetLeft() const;
+ virtual int offsetTop() const;
+ virtual RenderBox* 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);
+
+ bool hasHorizontalBordersPaddingOrMargin() const { return hasHorizontalBordersOrPadding() || marginLeft() != 0 || marginRight() != 0; }
+ bool hasHorizontalBordersOrPadding() const { return borderLeft() != 0 || borderRight() != 0 || paddingLeft() != 0 || paddingRight() != 0; }
+
+ int marginTop() const { return m_marginTop; }
+ int marginBottom() const { return m_marginBottom; }
+ int marginLeft() const { return m_marginLeft; }
+ int marginRight() const { return m_marginRight; }
+
+ // 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(); }
+
+ // 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 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 bool isTopMarginQuirk() const { return false; }
+ virtual bool isBottomMarginQuirk() const { return 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, bool topLevel = true);
+ virtual void absoluteQuads(Vector<FloatQuad>&, bool topLevel = true);
+
+ 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 paint(PaintInfo&, int tx, int ty);
virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, int x, int y, int tx, int ty, HitTestAction);
@@ -49,30 +173,17 @@ public:
virtual int overrideHeight() const;
virtual void setOverrideSize(int);
- virtual bool absolutePosition(int& x, int& y, bool fixed = false) 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()); }
+ 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 IntSize offsetFromContainer(RenderObject*) const;
+
int calcBorderBoxWidth(int width) const;
int calcBorderBoxHeight(int height) const;
int calcContentBoxWidth(int width) const;
int calcContentBoxHeight(int height) const;
- virtual void borderFitAdjust(int& x, int& w) const {}; // Shrink the box in which the border paints if border-fit is set.
+ virtual void borderFitAdjust(int& /*x*/, int& /*w*/) const { } // Shrink the box in which the border paints if border-fit is set.
// This method is now public so that centered objects like tables that are
// shifted right by left-aligned floats can recompute their left and
@@ -95,9 +206,10 @@ public:
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);
+ virtual IntRect clippedOverflowRectForRepaint(RenderBox* repaintContainer);
+ virtual void computeRectForRepaint(IntRect&, RenderBox* repaintContainer, bool fixed = false);
IntSize offsetForPositionedInContainer(RenderObject*) const;
+ virtual FloatQuad localToContainerQuad(const FloatQuad&, RenderBox* repaintContainer, bool fixed = false) const;
virtual void repaintDuringLayoutIfMoved(const IntRect&);
@@ -128,6 +240,8 @@ 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;
@@ -135,10 +249,25 @@ public:
int relativePositionOffsetX() const;
int relativePositionOffsetY() const;
-
- virtual RenderLayer* layer() const { return m_layer; }
-
- virtual IntRect caretRect(InlineBox*, int caretOffset, int* extraWidthToEndOfLine = 0);
+ IntSize relativePositionOffset() const { return IntSize(relativePositionOffsetX(), relativePositionOffsetY()); }
+
+ RenderLayer* layer() const { return m_layer; }
+ virtual bool requiresLayer() const { return isRoot() || isPositioned() || isRelPositioned() || isTransparent() || hasOverflowClip() || hasTransform() || hasMask() || hasReflection(); }
+
+ 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 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);
@@ -154,23 +283,27 @@ public:
virtual void paintBoxDecorations(PaintInfo&, int tx, int ty);
virtual void paintMask(PaintInfo& paintInfo, int tx, int ty);
- virtual void imageChanged(WrappedImagePtr);
+ virtual void imageChanged(WrappedImagePtr, const IntRect* = 0);
// Called when a positioned object moves but doesn't change size. A simplified layout is done
// 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();
+#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);
@@ -189,6 +322,9 @@ protected:
virtual bool shouldCalculateSizeAsReplaced() const { return isReplaced() && !isInlineBlockOrInlineTable(); }
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);
@@ -199,11 +335,11 @@ private:
int containingBlockHeightForPositioned(const RenderObject* containingBlock) const;
void calcAbsoluteVertical();
- void calcAbsoluteHorizontalValues(Length width, const RenderObject* cb, TextDirection containerDirection,
+ void calcAbsoluteHorizontalValues(Length width, const RenderBox* 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 RenderBox* cb,
int containerHeight, int bordersPlusPadding,
Length top, Length bottom, Length marginTop, Length marginBottom,
int& heightValue, int& marginTopValue, int& marginBottomValue, int& yPos);
@@ -216,18 +352,16 @@ private:
// These include tables, positioned objects, floats and flexible boxes.
virtual void calcPrefWidths() = 0;
+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:
- // The width/height of the contents + borders + padding.
- int m_width;
- int m_height;
#ifdef ANDROID_LAYOUT
int m_visibleWidth;
#endif
- int m_x;
- int m_y;
-
int m_marginLeft;
int m_marginRight;
int m_marginTop;
@@ -251,6 +385,33 @@ private:
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);
+}
+
+inline RenderBox* RenderBox::previousSiblingBox() const
+{
+ return toRenderBox(previousSibling());
+}
+
+inline RenderBox* RenderBox::nextSiblingBox() const
+{
+ return toRenderBox(nextSibling());
+}
+
+inline RenderBox* RenderBox::parentBox() const
+{
+ return toRenderBox(parent());
+}
+
} // namespace WebCore
#endif // RenderBox_h
diff --git a/WebCore/rendering/RenderButton.cpp b/WebCore/rendering/RenderButton.cpp
index cbde565..f7ccd0c 100644
--- a/WebCore/rendering/RenderButton.cpp
+++ b/WebCore/rendering/RenderButton.cpp
@@ -30,6 +30,11 @@
#include "RenderTextFragment.h"
#include "RenderTheme.h"
+#if ENABLE(WML)
+#include "WMLDoElement.h"
+#include "WMLNames.h"
+#endif
+
namespace WebCore {
using namespace HTMLNames;
@@ -48,7 +53,7 @@ void RenderButton::addChild(RenderObject* newChild, RenderObject* beforeChild)
// Create an anonymous block.
ASSERT(!firstChild());
m_inner = createAnonymousBlock();
- m_inner->style()->setBoxFlex(1.0f);
+ setupInnerStyle(m_inner->style());
RenderFlexibleBox::addChild(m_inner);
}
@@ -83,7 +88,7 @@ void RenderButton::styleDidChange(RenderStyle::Diff diff, const RenderStyle* old
if (m_buttonText)
m_buttonText->setStyle(style());
if (m_inner) // RenderBlock handled updating the anonymous block's style.
- m_inner->style()->setBoxFlex(1.0f);
+ setupInnerStyle(m_inner->style());
setReplaced(isInline());
if (!m_default && theme()->isDefault(this)) {
@@ -97,6 +102,16 @@ void RenderButton::styleDidChange(RenderStyle::Diff diff, const RenderStyle* old
}
}
+void RenderButton::setupInnerStyle(RenderStyle* innerStyle)
+{
+ ASSERT(innerStyle->refCount() == 1);
+ // RenderBlock::createAnonymousBlock creates a new RenderStyle, so this is
+ // safe to modify.
+ innerStyle->setBoxFlex(1.0f);
+ if (style()->hasAppearance())
+ theme()->adjustButtonInnerStyle(innerStyle);
+}
+
void RenderButton::updateFromElement()
{
// If we're an input element, we may need to change our button text.
@@ -105,6 +120,19 @@ void RenderButton::updateFromElement()
String value = input->valueWithDefault();
setText(value);
}
+
+
+#if ENABLE(WML)
+ else if (element()->hasTagName(WMLNames::doTag)) {
+ WMLDoElement* doElement = static_cast<WMLDoElement*>(element());
+
+ String value = doElement->label();
+ if (value.isEmpty())
+ value = doElement->name();
+
+ setText(value);
+ }
+#endif
}
bool RenderButton::canHaveChildren() const
@@ -144,7 +172,7 @@ void RenderButton::updateBeforeAfterContent(RenderStyle::PseudoId 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>*)
diff --git a/WebCore/rendering/RenderButton.h b/WebCore/rendering/RenderButton.h
index a176c8d..24e4767 100644
--- a/WebCore/rendering/RenderButton.h
+++ b/WebCore/rendering/RenderButton.h
@@ -45,6 +45,7 @@ public:
virtual void removeLeftoverAnonymousBlock(RenderBlock*) { }
virtual bool createsAnonymousWrapper() const { return true; }
+ void setupInnerStyle(RenderStyle*);
virtual void updateFromElement();
virtual void updateBeforeAfterContent(RenderStyle::PseudoId);
diff --git a/WebCore/rendering/RenderContainer.cpp b/WebCore/rendering/RenderContainer.cpp
index 947acac..dd39d9f 100644
--- a/WebCore/rendering/RenderContainer.cpp
+++ b/WebCore/rendering/RenderContainer.cpp
@@ -30,6 +30,7 @@
#include "Document.h"
#include "RenderCounter.h"
#include "RenderImageGeneratedContent.h"
+#include "RenderInline.h"
#include "RenderLayer.h"
#include "RenderListItem.h"
#include "RenderTable.h"
@@ -126,9 +127,9 @@ void RenderContainer::addChild(RenderObject* newChild, RenderObject* beforeChild
}
if (newChild->isText() && newChild->style()->textTransform() == CAPITALIZE) {
- RefPtr<StringImpl> textToTransform = static_cast<RenderText*>(newChild)->originalText();
+ RefPtr<StringImpl> textToTransform = toRenderText(newChild)->originalText();
if (textToTransform)
- static_cast<RenderText*>(newChild)->setText(textToTransform.release(), true);
+ toRenderText(newChild)->setText(textToTransform.release(), true);
}
}
@@ -257,6 +258,9 @@ static RenderObject* findBeforeAfterParent(RenderObject* object)
void RenderContainer::updateBeforeAfterContentForContainer(RenderStyle::PseudoId type, RenderContainer* styledObject)
{
+ // Double check that the document did in fact use generated content rules. Otherwise we should not have been called.
+ ASSERT(document()->usesBeforeAfterRules());
+
// In CSS2, before/after pseudo-content cannot nest. Check this first.
if (style()->styleType() == RenderStyle::BEFORE || style()->styleType() == RenderStyle::AFTER)
return;
@@ -277,7 +281,7 @@ void RenderContainer::updateBeforeAfterContentForContainer(RenderStyle::PseudoId
// 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())
+ if (newContentWanted && type == RenderStyle::AFTER && isRenderInline() && static_cast<RenderInline*>(this)->continuation())
newContentWanted = false;
// If we don't want generated content any longer, or if we have generated content, but it's no longer
@@ -297,7 +301,7 @@ void RenderContainer::updateBeforeAfterContentForContainer(RenderStyle::PseudoId
if (!newContentWanted)
return;
- if (isInlineFlow() && !pseudoElementStyle->isDisplayInlineType() && pseudoElementStyle->floating() == FNONE &&
+ if (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.
@@ -520,7 +524,7 @@ void RenderContainer::layout()
{
ASSERT(needsLayout());
- view()->pushLayoutState(this, IntSize(m_x, m_y));
+ LayoutStateMaintainer statePusher(view(), this, IntSize(x(), y()));
RenderObject* child = m_firstChild;
while (child) {
@@ -529,7 +533,7 @@ void RenderContainer::layout()
child = child->nextSibling();
}
- view()->popLayoutState();
+ statePusher.pop();
setNeedsLayout(false);
}
@@ -576,7 +580,7 @@ void RenderContainer::removeLeftoverAnonymousBlock(RenderBlock* child)
child->destroy();
}
-VisiblePosition RenderContainer::positionForCoordinates(int x, int y)
+VisiblePosition RenderContainer::positionForCoordinates(int xPos, int yPos)
{
// no children...return this render object's element, if there is one, and offset 0
if (!m_firstChild)
@@ -586,8 +590,8 @@ VisiblePosition RenderContainer::positionForCoordinates(int x, int y)
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)
+ if (xPos < 0 || xPos > right || yPos < 0 || yPos > bottom) {
+ if (xPos <= right / 2)
return VisiblePosition(Position(element(), 0));
else
return VisiblePosition(Position(element(), maxDeepOffset(element())));
@@ -596,55 +600,60 @@ VisiblePosition RenderContainer::positionForCoordinates(int x, int y)
// Pass off to the closest child.
int minDist = INT_MAX;
- RenderObject* closestRenderer = 0;
- int newX = x;
- int newY = y;
+ RenderBox* closestRenderer = 0;
+ int newX = xPos;
+ int newY = yPos;
if (isTableRow()) {
- newX += xPos();
- newY += yPos();
+ newX += x();
+ newY += y();
}
- for (RenderObject* renderer = m_firstChild; renderer; renderer = renderer->nextSibling()) {
- if (!renderer->firstChild() && !renderer->isInline() && !renderer->isBlockFlow()
- || renderer->style()->visibility() != VISIBLE)
+ for (RenderObject* renderObject = m_firstChild; renderObject; renderObject = renderObject->nextSibling()) {
+ if (!renderObject->firstChild() && !renderObject->isInline() && !renderObject->isBlockFlow()
+ || renderObject->style()->visibility() != VISIBLE)
+ continue;
+
+ if (!renderObject->isBox())
continue;
- int top = borderTop() + paddingTop() + (isTableRow() ? 0 : renderer->yPos());
+ RenderBox* renderer = toRenderBox(renderObject);
+
+ int top = borderTop() + paddingTop() + (isTableRow() ? 0 : renderer->y());
int bottom = top + renderer->contentHeight();
- int left = borderLeft() + paddingLeft() + (isTableRow() ? 0 : renderer->xPos());
+ int left = borderLeft() + paddingLeft() + (isTableRow() ? 0 : renderer->x());
int right = left + renderer->contentWidth();
- if (x <= right && x >= left && y <= top && y >= bottom) {
+ if (xPos <= right && xPos >= left && yPos <= top && yPos >= bottom) {
if (renderer->isTableRow())
- return renderer->positionForCoordinates(x + newX - renderer->xPos(), y + newY - renderer->yPos());
- return renderer->positionForCoordinates(x - renderer->xPos(), y - renderer->yPos());
+ 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 (x > right) {
- if (y < top)
+ if (xPos > right) {
+ if (yPos < top)
cmp = IntPoint(right, top);
- else if (y > bottom)
+ else if (yPos > bottom)
cmp = IntPoint(right, bottom);
else
- cmp = IntPoint(right, y);
- } else if (x < left) {
- if (y < top)
+ cmp = IntPoint(right, yPos);
+ } else if (xPos < left) {
+ if (yPos < top)
cmp = IntPoint(left, top);
- else if (y > bottom)
+ else if (yPos > bottom)
cmp = IntPoint(left, bottom);
else
- cmp = IntPoint(left, y);
+ cmp = IntPoint(left, yPos);
} else {
- if (y < top)
- cmp = IntPoint(x, top);
+ if (yPos < top)
+ cmp = IntPoint(xPos, top);
else
- cmp = IntPoint(x, bottom);
+ cmp = IntPoint(xPos, bottom);
}
- int x1minusx2 = cmp.x() - x;
- int y1minusy2 = cmp.y() - y;
+ int x1minusx2 = cmp.x() - xPos;
+ int y1minusy2 = cmp.y() - yPos;
int dist = x1minusx2 * x1minusx2 + y1minusy2 * y1minusy2;
if (dist < minDist) {
@@ -654,7 +663,7 @@ VisiblePosition RenderContainer::positionForCoordinates(int x, int y)
}
if (closestRenderer)
- return closestRenderer->positionForCoordinates(newX - closestRenderer->xPos(), newY - closestRenderer->yPos());
+ return closestRenderer->positionForCoordinates(newX - closestRenderer->x(), newY - closestRenderer->y());
return VisiblePosition(element(), 0, DOWNSTREAM);
}
@@ -662,9 +671,8 @@ VisiblePosition RenderContainer::positionForCoordinates(int x, int y)
void RenderContainer::addLineBoxRects(Vector<IntRect>& rects, unsigned start, unsigned end, bool)
{
if (!m_firstChild && (isInline() || isAnonymousBlock())) {
- int x, y;
- absolutePositionForContent(x, y);
- absoluteRects(rects, x, y);
+ FloatPoint absPos = localToAbsolute(FloatPoint());
+ absoluteRects(rects, absPos.x(), absPos.y());
return;
}
@@ -674,24 +682,39 @@ void RenderContainer::addLineBoxRects(Vector<IntRect>& rects, unsigned start, un
unsigned offset = start;
for (RenderObject* child = childAt(start); child && offset < end; child = child->nextSibling(), ++offset) {
if (child->isText() || child->isInline() || child->isAnonymousBlock()) {
- int x, y;
- child->absolutePositionForContent(x, y);
- child->absoluteRects(rects, x, y);
+ FloatPoint absPos = child->localToAbsolute(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);
+ }
+}
+
#ifdef ANDROID_LAYOUT
bool RenderContainer::hasChildTable() const
{
if (!firstChild())
return false;
- for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
+ for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
if (child->isTable()) {
- return true;
+ return true;
} else if (child->hasChildTable() == true) {
- return true;
+ return true;
}
}
return false;
diff --git a/WebCore/rendering/RenderContainer.h b/WebCore/rendering/RenderContainer.h
index 174aa17..8ae5296 100644
--- a/WebCore/rendering/RenderContainer.h
+++ b/WebCore/rendering/RenderContainer.h
@@ -34,6 +34,10 @@ public:
virtual RenderObject* firstChild() const { return m_firstChild; }
virtual RenderObject* lastChild() const { return m_lastChild; }
+ // Use this with caution! No type checking is done!
+ RenderBox* firstChildBox() const { ASSERT(!firstChild() || firstChild()->isBox()); return toRenderBox(m_firstChild); }
+ RenderBox* lastChildBox() const { ASSERT(!lastChild() || lastChild()->isBox()); return toRenderBox(m_lastChild); }
+
virtual bool canHaveChildren() const;
virtual void addChild(RenderObject* newChild, RenderObject* beforeChild = 0);
virtual void removeChild(RenderObject*);
@@ -66,8 +70,9 @@ public:
#endif
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:
+protected:
RenderObject* m_firstChild;
RenderObject* m_lastChild;
};
diff --git a/WebCore/rendering/RenderCounter.cpp b/WebCore/rendering/RenderCounter.cpp
index 4b6deed..598f40d 100644
--- a/WebCore/rendering/RenderCounter.cpp
+++ b/WebCore/rendering/RenderCounter.cpp
@@ -29,6 +29,7 @@
#include "RenderListItem.h"
#include "RenderListMarker.h"
#include "RenderStyle.h"
+#include <wtf/StdLibExtras.h>
namespace WebCore {
@@ -41,7 +42,7 @@ static CounterNode* counter(RenderObject*, const AtomicString& counterName, bool
static CounterMaps& counterMaps()
{
- static CounterMaps staticCounterMaps;
+ DEFINE_STATIC_LOCAL(CounterMaps, staticCounterMaps, ());
return staticCounterMaps;
}
diff --git a/WebCore/rendering/RenderFieldset.cpp b/WebCore/rendering/RenderFieldset.cpp
index d16495b..5baca3e 100644
--- a/WebCore/rendering/RenderFieldset.cpp
+++ b/WebCore/rendering/RenderFieldset.cpp
@@ -26,10 +26,13 @@
#include "config.h"
#include "RenderFieldset.h"
-#include "HTMLFormControlElement.h"
#include "HTMLNames.h"
#include "GraphicsContext.h"
+#if ENABLE(WML)
+#include "WMLNames.h"
+#endif
+
using std::min;
using std::max;
@@ -37,7 +40,7 @@ namespace WebCore {
using namespace HTMLNames;
-RenderFieldset::RenderFieldset(HTMLFormControlElement* element)
+RenderFieldset::RenderFieldset(Node* element)
: RenderBlock(element)
{
}
@@ -45,7 +48,7 @@ RenderFieldset::RenderFieldset(HTMLFormControlElement* element)
void RenderFieldset::calcPrefWidths()
{
RenderBlock::calcPrefWidths();
- if (RenderObject* legend = findLegend()) {
+ if (RenderBox* legend = findLegend()) {
int legendMinWidth = legend->minPrefWidth();
Length legendMarginLeft = legend->style()->marginLeft();
@@ -63,7 +66,7 @@ void RenderFieldset::calcPrefWidths()
RenderObject* RenderFieldset::layoutLegend(bool relayoutChildren)
{
- RenderObject* legend = findLegend();
+ RenderBox* legend = findLegend();
if (legend) {
if (relayoutChildren)
legend->setNeedsLayout(true);
@@ -76,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();
@@ -95,18 +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))
- return legend;
+ legend->element()->hasTagName(legendTag)
+#if ENABLE(WML)
+ || legend->element()->hasTagName(WMLNames::insertedLegendTag)
+#endif
+ )
+ return toRenderBox(legend);
}
return 0;
}
@@ -114,15 +121,15 @@ 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();
+ ty += yOff;
int my = max(ty, paintInfo.rect.y());
int end = min(paintInfo.rect.bottom(), ty + h);
@@ -137,7 +144,7 @@ void RenderFieldset::paintBoxDecorations(PaintInfo& paintInfo, int tx, int ty)
// 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
@@ -147,7 +154,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);
@@ -160,14 +167,14 @@ 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();
+ ty += yOff;
int my = max(ty, paintInfo.rect.y());
int end = min(paintInfo.rect.bottom(), ty + h);
diff --git a/WebCore/rendering/RenderFieldset.h b/WebCore/rendering/RenderFieldset.h
index 87652fd..38f3236 100644
--- a/WebCore/rendering/RenderFieldset.h
+++ b/WebCore/rendering/RenderFieldset.h
@@ -30,11 +30,9 @@
namespace WebCore {
-class HTMLFormControlElement;
-
class RenderFieldset : public RenderBlock {
public:
- RenderFieldset(HTMLFormControlElement*);
+ RenderFieldset(Node*);
virtual const char* renderName() const { return "RenderFieldSet"; }
virtual bool isFieldset() const { return true; }
@@ -43,10 +41,9 @@ 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);
diff --git a/WebCore/rendering/RenderFileUploadControl.cpp b/WebCore/rendering/RenderFileUploadControl.cpp
index fe9772e..cbf1409 100644
--- a/WebCore/rendering/RenderFileUploadControl.cpp
+++ b/WebCore/rendering/RenderFileUploadControl.cpp
@@ -151,7 +151,7 @@ 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));
}
@@ -194,7 +194,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)
@@ -207,20 +207,19 @@ void RenderFileUploadControl::paintObject(PaintInfo& paintInfo, int tx, int ty)
+ 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));
@@ -294,7 +293,7 @@ String RenderFileUploadControl::fileTextValue()
}
HTMLFileUploadInnerButtonElement::HTMLFileUploadInnerButtonElement(Document* doc, Node* shadowParent)
- : HTMLInputElement(doc)
+ : HTMLInputElement(inputTag, doc)
, m_shadowParent(shadowParent)
{
}
diff --git a/WebCore/rendering/RenderFlexibleBox.cpp b/WebCore/rendering/RenderFlexibleBox.cpp
index f39bf74..e6dd91a 100644
--- a/WebCore/rendering/RenderFlexibleBox.cpp
+++ b/WebCore/rendering/RenderFlexibleBox.cpp
@@ -28,6 +28,7 @@
#include "CharacterNames.h"
#include "RenderLayer.h"
#include "RenderView.h"
+#include <wtf/StdLibExtras.h>
#ifdef ANDROID_LAYOUT
#include "Document.h"
@@ -49,11 +50,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();
}
}
@@ -65,29 +66,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 ||
@@ -97,7 +97,7 @@ public:
private:
RenderFlexibleBox* box;
- RenderObject* current;
+ RenderBox* current;
bool forward;
unsigned int currentOrdinal;
unsigned int lastOrdinal;
@@ -116,13 +116,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.
@@ -138,21 +135,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.
@@ -170,8 +161,6 @@ void RenderFlexibleBox::calcVerticalPrefWidths()
w = child->maxPrefWidth() + margin;
m_maxPrefWidth = max(w, m_maxPrefWidth);
-
- child = child->nextSibling();
}
}
@@ -221,26 +210,23 @@ void RenderFlexibleBox::layoutBlock(bool relayoutChildren)
bool checkForRepaint = checkForRepaintDuringLayout();
if (checkForRepaint) {
oldBounds = absoluteClippedOverflowRect();
- oldOutlineBox = absoluteOutlineBox();
+ oldOutlineBox = absoluteOutlineBounds();
}
- if (!hasReflection())
- view()->pushLayoutState(this, IntSize(m_x, m_y));
- else
- view()->disableLayoutState();
+ LayoutStateMaintainer statePusher(view(), this, IntSize(x(), y()), hasTransform() || hasReflection());
- int previousWidth = m_width;
- int previousHeight = m_height;
+ int previousWidth = width();
+ int previousHeight = height();
-#ifdef ANDROID_LAYOUT
+ #ifdef ANDROID_LAYOUT
int previousVisibleWidth = m_visibleWidth;
#endif
-
+
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;
@@ -252,8 +238,8 @@ void RenderFlexibleBox::layoutBlock(bool relayoutChildren)
&& settings->layoutAlgorithm() == Settings::kLayoutFitColumnToScreen)
relayoutChildren = true;
#endif
+ setHeight(0);
- m_height = 0;
m_overflowHeight = 0;
m_flexingChildren = m_stretchingChildren = false;
@@ -272,21 +258,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.
@@ -305,15 +291,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()) {
@@ -325,10 +311,7 @@ void RenderFlexibleBox::layoutBlock(bool relayoutChildren)
}
}
- if (!hasReflection())
- view()->popLayoutState();
- else
- view()->enableLayoutState();
+ statePusher.pop();
// Update our scrollbars if we're overflow:auto/scroll/hidden now that we know if
// we overflow or not.
@@ -354,11 +337,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) {
@@ -383,8 +366,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
@@ -422,28 +405,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.
@@ -467,7 +450,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();
+ toRenderBox(child)->calcHeight();
if (oldChildHeight != child->height())
child->setChildNeedsLayout(true, false);
child->layoutIfNeeded();
@@ -500,7 +483,7 @@ void RenderFlexibleBox::layoutHorizontalBox(bool relayoutChildren)
static_cast<RenderBlock*>(child)->addVisualOverflow(static_cast<RenderBlock*>(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();
@@ -641,7 +624,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();
}
}
@@ -656,7 +639,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();
}
}
@@ -668,20 +651,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)
@@ -689,7 +672,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;
@@ -701,7 +684,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) {
@@ -794,7 +777,7 @@ void RenderFlexibleBox::layoutVerticalBox(bool relayoutChildren)
continue;
const UChar ellipsisAndSpace[2] = { horizontalEllipsis, ' ' };
- static AtomicString ellipsisAndSpaceStr(ellipsisAndSpace, 2);
+ DEFINE_STATIC_LOCAL(AtomicString, ellipsisAndSpaceStr, (ellipsisAndSpace, 2));
const Font& font = style(numVisibleLines == 1)->font();
int ellipsisAndSpaceWidth = font.width(TextRun(ellipsisAndSpace, 2));
@@ -830,9 +813,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) {
@@ -850,7 +833,7 @@ void RenderFlexibleBox::layoutVerticalBox(bool relayoutChildren)
child->setStaticX(borderRight()+paddingRight());
}
if (child->hasStaticY())
- child->setStaticY(m_height);
+ child->setStaticY(height());
child = iterator.next();
continue;
}
@@ -859,7 +842,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();
@@ -886,39 +869,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());
// 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;
@@ -1050,7 +1033,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();
}
}
@@ -1065,7 +1048,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();
}
}
@@ -1077,28 +1060,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
@@ -1107,7 +1090,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/WebCore/rendering/RenderFlexibleBox.h b/WebCore/rendering/RenderFlexibleBox.h
index f48caf5..a0f84ce 100644
--- a/WebCore/rendering/RenderFlexibleBox.h
+++ b/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/WebCore/rendering/RenderFlow.cpp b/WebCore/rendering/RenderFlow.cpp
index eb689cf..94ec124 100644
--- a/WebCore/rendering/RenderFlow.cpp
+++ b/WebCore/rendering/RenderFlow.cpp
@@ -246,7 +246,7 @@ void RenderFlow::destroy()
void RenderFlow::dirtyLinesFromChangedChild(RenderObject* child)
{
- if (!parent() || (selfNeedsLayout() && !isInlineFlow()) || isTable())
+ if (!parent() || (selfNeedsLayout() && !isRenderInline()) || isTable())
return;
// If we have no first line box, then just bail early.
@@ -272,10 +272,10 @@ void RenderFlow::dirtyLinesFromChangedChild(RenderObject* child)
if (wrapper)
box = wrapper->root();
} else if (curr->isText()) {
- InlineTextBox* textBox = static_cast<RenderText*>(curr)->lastTextBox();
+ InlineTextBox* textBox = toRenderText(curr)->lastTextBox();
if (textBox)
box = textBox->root();
- } else if (curr->isInlineFlow()) {
+ } else if (curr->isRenderInline()) {
InlineRunBox* runBox = static_cast<RenderFlow*>(curr)->lastLineBox();
if (runBox)
box = runBox->root();
@@ -310,9 +310,9 @@ void RenderFlow::dirtyLinesFromChangedChild(RenderObject* child)
}
}
-int RenderFlow::lineHeight(bool firstLine, bool isRootLineBox) const
+int RenderFlow::lineHeight(bool firstLine, bool /*isRootLineBox*/) const
{
- if (firstLine) {
+ if (firstLine && document()->usesFirstLineRules()) {
RenderStyle* s = style(firstLine);
Length lh = s->lineHeight();
if (lh.isNegative()) {
@@ -346,7 +346,7 @@ void RenderFlow::dirtyLineBoxes(bool fullLayout, bool isRootLineBox)
}
}
-InlineBox* RenderFlow::createInlineBox(bool makePlaceHolderBox, bool isRootLineBox, bool isOnlyRun)
+InlineBox* RenderFlow::createInlineBox(bool makePlaceHolderBox, bool isRootLineBox, bool /*isOnlyRun*/)
{
checkConsistency();
@@ -355,7 +355,7 @@ InlineBox* RenderFlow::createInlineBox(bool makePlaceHolderBox, bool isRootLineB
return RenderContainer::createInlineBox(false, isRootLineBox); // (or positioned element placeholders).
InlineFlowBox* flowBox = 0;
- if (isInlineFlow())
+ if (isRenderInline())
flowBox = new (renderArena()) InlineFlowBox(this);
else
flowBox = new (renderArena()) RootInlineBox(this);
@@ -381,9 +381,9 @@ void RenderFlow::paintLines(PaintInfo& paintInfo, int tx, int ty)
&& paintInfo.phase != PaintPhaseMask)
return;
- bool inlineFlow = isInlineFlow();
+ bool inlineFlow = isRenderInline();
if (inlineFlow)
- ASSERT(m_layer); // The only way a compact/run-in/inline could paint like this is if it has a layer.
+ ASSERT(m_layer); // 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())
@@ -400,7 +400,7 @@ void RenderFlow::paintLines(PaintInfo& paintInfo, int tx, int ty)
return;
PaintInfo info(paintInfo);
- RenderFlowSequencedSet outlineObjects;
+ ListHashSet<RenderFlow*> outlineObjects;
info.outlineObjects = &outlineObjects;
// See if our root lines intersect with the dirty rect. If so, then we paint
@@ -435,8 +435,8 @@ void RenderFlow::paintLines(PaintInfo& paintInfo, int tx, int 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) {
+ ListHashSet<RenderFlow*>::iterator end = info.outlineObjects->end();
+ for (ListHashSet<RenderFlow*>::iterator it = info.outlineObjects->begin(); it != end; ++it) {
RenderFlow* flow = *it;
flow->paintOutline(info.context, tx, ty);
}
@@ -449,9 +449,9 @@ bool RenderFlow::hitTestLines(const HitTestRequest& request, HitTestResult& resu
if (hitTestAction != HitTestForeground)
return false;
- bool inlineFlow = isInlineFlow();
+ bool inlineFlow = isRenderInline();
if (inlineFlow)
- ASSERT(m_layer); // The only way a compact/run-in/inline could paint like this is if it has a layer.
+ ASSERT(m_layer); // The only way an inline can hit test like this is if it has a layer.
// If we have no lines then we have no work to do.
if (!firstLineBox())
@@ -480,151 +480,11 @@ bool RenderFlow::hitTestLines(const HitTestRequest& request, HitTestResult& resu
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()->subtractScrollOffset(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::caretRect(InlineBox* inlineBox, int caretOffset, int* extraWidthToEndOfLine)
+IntRect RenderFlow::localCaretRect(InlineBox* inlineBox, int caretOffset, int* extraWidthToEndOfLine)
{
// Do the normal calculation in most cases.
if (firstChild() || style()->display() == INLINE)
- return RenderContainer::caretRect(inlineBox, caretOffset, extraWidthToEndOfLine);
+ 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
@@ -684,20 +544,17 @@ IntRect RenderFlow::caretRect(InlineBox* inlineBox, int caretOffset, int* extraW
// So *extraWidthToEndOfLine will always be 0 here.
int myRight = x + caretWidth;
- int ignore;
- absolutePositionForContent(myRight, ignore);
+ // FIXME: why call localToAbsoluteForContent() twice here, too?
+ FloatPoint absRightPoint = localToAbsolute(FloatPoint(myRight, 0));
- int containerRight = containingBlock()->xPos() + containingBlockWidth();
- absolutePositionForContent(containerRight, ignore);
+ int containerRight = containingBlock()->x() + containingBlockWidth();
+ FloatPoint absContainerPoint = localToAbsolute(FloatPoint(containerRight, 0));
- *extraWidthToEndOfLine = containerRight - myRight;
+ *extraWidthToEndOfLine = absContainerPoint.x() - absRightPoint.x();
}
}
- int absx, absy;
- absolutePositionForContent(absx, absy);
- x += absx;
- int y = absy + paddingTop() + borderTop();
+ int y = paddingTop() + borderTop();
return IntRect(x, y, caretWidth, height);
}
@@ -722,28 +579,27 @@ void RenderFlow::addFocusRingRects(GraphicsContext* graphicsContext, int tx, int
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()) {
- int x = 0;
- int y = 0;
- if (curr->layer())
- curr->absolutePosition(x, y);
- else {
- x = tx + curr->xPos();
- y = ty + curr->yPos();
- }
- curr->addFocusRingRects(graphicsContext, x, y);
+ 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 (continuation()) {
if (isInline())
continuation()->addFocusRingRects(graphicsContext,
- tx - containingBlock()->xPos() + continuation()->xPos(),
- ty - containingBlock()->yPos() + continuation()->yPos());
+ tx - containingBlock()->x() + continuation()->x(),
+ ty - containingBlock()->y() + continuation()->y());
else
continuation()->addFocusRingRects(graphicsContext,
- tx - xPos() + continuation()->containingBlock()->xPos(),
- ty - yPos() + continuation()->containingBlock()->yPos());
+ tx - x() + continuation()->containingBlock()->x(),
+ ty - y() + continuation()->containingBlock()->y());
}
}
diff --git a/WebCore/rendering/RenderFlow.h b/WebCore/rendering/RenderFlow.h
index c284ed8..897e40a 100644
--- a/WebCore/rendering/RenderFlow.h
+++ b/WebCore/rendering/RenderFlow.h
@@ -52,13 +52,15 @@ public:
, m_selectionState(SelectionNone)
, m_hasColumns(false)
, m_isContinuation(false)
+ , m_cellWidthChanged(false)
{
}
#ifndef NDEBUG
virtual ~RenderFlow();
#endif
- virtual RenderFlow* continuation() const { return m_continuation; }
+ virtual RenderFlow* virtualContinuation() const { return continuation(); }
+ RenderFlow* continuation() const { return m_continuation; }
void setContinuation(RenderFlow* c) { m_continuation = c; }
RenderFlow* continuationBefore(RenderObject* beforeChild);
@@ -87,13 +89,7 @@ public:
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 caretRect(InlineBox*, int caretOffset, int* extraWidthToEndOfLine = 0);
+ 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);
@@ -133,6 +129,9 @@ protected:
// from RenderInline
bool m_isContinuation : 1; // Whether or not we're a continuation of an inline.
+
+ // from RenderTableCell
+ bool m_cellWidthChanged : 1;
};
#ifdef NDEBUG
diff --git a/WebCore/rendering/RenderForeignObject.cpp b/WebCore/rendering/RenderForeignObject.cpp
index 5070b97..523601c 100644
--- a/WebCore/rendering/RenderForeignObject.cpp
+++ b/WebCore/rendering/RenderForeignObject.cpp
@@ -38,10 +38,10 @@ RenderForeignObject::RenderForeignObject(SVGForeignObjectElement* node)
{
}
-AffineTransform RenderForeignObject::translationForAttributes()
+TransformationMatrix RenderForeignObject::translationForAttributes()
{
SVGForeignObjectElement* foreign = static_cast<SVGForeignObjectElement*>(element());
- return AffineTransform().translate(foreign->x().value(foreign), foreign->y().value(foreign));
+ return TransformationMatrix().translate(foreign->x().value(foreign), foreign->y().value(foreign));
}
void RenderForeignObject::paint(PaintInfo& paintInfo, int parentX, int parentY)
@@ -50,7 +50,7 @@ void RenderForeignObject::paint(PaintInfo& paintInfo, int parentX, int parentY)
return;
paintInfo.context->save();
- paintInfo.context->concatCTM(AffineTransform().translate(parentX, parentY));
+ paintInfo.context->concatCTM(TransformationMatrix().translate(parentX, parentY));
paintInfo.context->concatCTM(localTransform());
paintInfo.context->concatCTM(translationForAttributes());
paintInfo.context->clip(getClipRect(parentX, parentY));
@@ -70,22 +70,17 @@ void RenderForeignObject::paint(PaintInfo& paintInfo, int parentX, int parentY)
paintInfo.context->restore();
}
-void RenderForeignObject::computeAbsoluteRepaintRect(IntRect& r, bool f)
+void RenderForeignObject::computeRectForRepaint(IntRect& rect, RenderBox* repaintContainer, bool fixed)
{
- AffineTransform transform = translationForAttributes() * localTransform();
- r = transform.mapRect(r);
+ TransformationMatrix transform = translationForAttributes() * localTransform();
+ rect = transform.mapRect(rect);
- RenderBlock::computeAbsoluteRepaintRect(r, f);
-}
-
-bool RenderForeignObject::requiresLayer()
-{
- return false;
+ RenderBlock::computeRectForRepaint(rect, repaintContainer, fixed);
}
bool RenderForeignObject::calculateLocalTransform()
{
- AffineTransform oldTransform = m_localTransform;
+ TransformationMatrix oldTransform = m_localTransform;
m_localTransform = static_cast<SVGForeignObjectElement*>(element())->animatedLocalTransform();
return (oldTransform != m_localTransform);
}
@@ -102,7 +97,7 @@ void RenderForeignObject::layout()
bool checkForRepaint = checkForRepaintDuringLayout();
if (checkForRepaint) {
oldBounds = m_absoluteBounds;
- oldOutlineBox = absoluteOutlineBox();
+ oldOutlineBox = absoluteOutlineBounds();
}
calculateLocalTransform();
@@ -120,7 +115,7 @@ void RenderForeignObject::layout()
bool RenderForeignObject::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, int x, int y, int tx, int ty, HitTestAction hitTestAction)
{
- AffineTransform totalTransform = absoluteTransform();
+ TransformationMatrix totalTransform = absoluteTransform();
totalTransform *= translationForAttributes();
double localX, localY;
totalTransform.inverse().map(x, y, &localX, &localY);
diff --git a/WebCore/rendering/RenderForeignObject.h b/WebCore/rendering/RenderForeignObject.h
index b624683..28f4ddb 100644
--- a/WebCore/rendering/RenderForeignObject.h
+++ b/WebCore/rendering/RenderForeignObject.h
@@ -24,7 +24,7 @@
#define RenderForeignObject_h
#if ENABLE(SVG) && ENABLE(SVG_FOREIGN_OBJECT)
-#include "AffineTransform.h"
+#include "TransformationMatrix.h"
#include "RenderSVGBlock.h"
namespace WebCore {
@@ -39,19 +39,19 @@ public:
virtual void paint(PaintInfo&, int parentX, int parentY);
- virtual AffineTransform localTransform() const { return m_localTransform; }
+ virtual TransformationMatrix localTransform() const { return m_localTransform; }
virtual bool calculateLocalTransform();
- virtual void computeAbsoluteRepaintRect(IntRect&, bool fixed);
- virtual bool requiresLayer();
+ virtual void computeRectForRepaint(IntRect&, RenderBox* repaintContainer, bool fixed = false);
+ virtual bool requiresLayer() const { return false; }
virtual void layout();
virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, int x, int y, int tx, int ty, HitTestAction);
private:
- AffineTransform translationForAttributes();
+ TransformationMatrix translationForAttributes();
- AffineTransform m_localTransform;
+ TransformationMatrix m_localTransform;
IntRect m_absoluteBounds;
};
diff --git a/WebCore/rendering/RenderFrame.cpp b/WebCore/rendering/RenderFrame.cpp
index c996138..9e1d92b 100644
--- a/WebCore/rendering/RenderFrame.cpp
+++ b/WebCore/rendering/RenderFrame.cpp
@@ -76,17 +76,17 @@ void RenderFrame::layout()
root = static_cast<RenderView*>(view->frame()->document()->renderer());
if (root) {
// Resize the widget so that the RenderView will layout according to those dimensions.
- view->resize(m_width, m_height);
+ view->resize(width(), height());
view->layout();
// We can only grow in width and height because if positionFrames gives us a width and we become smaller,
// then the fixup process of forcing the frame to fill extra space will fail.
- if (m_width > root->docWidth()) {
+ if (width() > root->docWidth()) {
view->resize(root->docWidth(), 0);
view->layout();
}
// Honor the height set by RenderFrameSet::positionFrames unless our document height is larger.
- m_height = max(root->docHeight(), m_height);
- m_width = max(root->docWidth(), m_width);
+ setHeight(max(root->docHeight(), height()));
+ setWidth(max(root->docWidth(), width()));
}
}
setNeedsLayout(false);
diff --git a/WebCore/rendering/RenderFrameSet.cpp b/WebCore/rendering/RenderFrameSet.cpp
index 2b74d8a..f6cd4df 100644
--- a/WebCore/rendering/RenderFrameSet.cpp
+++ b/WebCore/rendering/RenderFrameSet.cpp
@@ -129,8 +129,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();
@@ -464,8 +464,8 @@ void RenderFrameSet::layout()
// Force a grid recalc.
m_gridCalculated = false;
#endif
- m_width = view()->viewWidth();
- m_height = view()->viewHeight();
+ setWidth(view()->viewWidth());
+ setHeight(view()->viewHeight());
}
size_t cols = frameSet()->totalCols();
@@ -490,8 +490,8 @@ void RenderFrameSet::layout()
}
#endif
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);
#ifdef FLATTEN_FRAMESET
}
#endif
@@ -514,7 +514,7 @@ void RenderFrameSet::layout()
void RenderFrameSet::positionFrames()
{
- RenderObject* child = firstChild();
+ RenderBox* child = firstChildBox();
if (!child)
return;
@@ -539,7 +539,8 @@ void RenderFrameSet::positionFrames()
rowHeight = l.value();
}
for (int c = 0; c < cols && child; c++) {
- child->setPos(xPos, yPos);
+ child->setX(xPos);
+ child->setY(yPos);
child->setWidth(m_cols.m_sizes[c]);
child->setHeight(height);
int colWidth = -1;
@@ -560,7 +561,7 @@ void RenderFrameSet::positionFrames()
height = max(child->height(), height);
xPos += child->width() + borderThickness;
- child = child->nextSibling();
+ child = (RenderBox*)child->nextSibling();
}
ASSERT(height >= m_rows.m_sizes[r]);
m_rows.m_sizes[r] = height;
@@ -574,10 +575,10 @@ void RenderFrameSet::positionFrames()
int newHeight = yPos - borderThickness;
// Distribute the extra width and height evenly across the grid.
- int dWidth = (m_width - newWidth) / cols;
- int dHeight = (m_height - newHeight) / rows;
+ int dWidth = (width() - newWidth) / cols;
+ int dHeight = (height() - newHeight) / rows;
if (dWidth > 0) {
- int availableWidth = m_width - (cols - 1) * borderThickness;
+ int availableWidth = width() - (cols - 1) * borderThickness;
for (int c = 0; c < cols; c++)
availableWidth -= m_cols.m_sizes[c] += dWidth;
// If the extra width did not distribute evenly, add the remainder to
@@ -586,7 +587,7 @@ void RenderFrameSet::positionFrames()
m_cols.m_sizes[cols - 1] += availableWidth;
}
if (dHeight > 0) {
- int availableHeight = m_height - (rows - 1) * borderThickness;
+ int availableHeight = height() - (rows - 1) * borderThickness;
for (int r = 0; r < rows; r++)
availableHeight -= m_rows.m_sizes[r] += dHeight;
// If the extra height did not distribute evenly, add the remainder to
@@ -596,9 +597,9 @@ void RenderFrameSet::positionFrames()
}
// Ensure the rows and columns are filled by falling through to the normal
// layout
- m_height = max(m_height, newHeight);
- m_width = max(m_width, newWidth);
- child = firstChild();
+ setHeight(max(height(), newHeight));
+ setWidth(max(width(), newWidth));
+ child = (RenderBox*)firstChild();
yPos = 0;
#endif // FLATTEN_FRAMESET
@@ -606,7 +607,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
@@ -619,7 +620,7 @@ void RenderFrameSet::positionFrames()
xPos += width + borderThickness;
- child = child->nextSibling();
+ child = child->nextSiblingBox();
if (!child)
return;
}
@@ -627,7 +628,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);
@@ -666,8 +667,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->pageX() - pos.x());
+ startResizing(m_rows, evt->pageY() - pos.y());
if (m_cols.m_splitBeingResized != noSplit || m_rows.m_splitBeingResized != noSplit) {
setIsResizing(true);
return true;
@@ -675,8 +677,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->pageX() - pos.x());
+ continueResizing(m_rows, evt->pageY() - pos.y());
if (evt->type() == eventNames().mouseupEvent && evt->button() == LeftButton) {
setIsResizing(false);
return true;
@@ -763,7 +766,7 @@ int RenderFrameSet::hitTestSplit(const GridAxis& axis, int position) const
return noSplit;
}
-bool RenderFrameSet::isChildAllowed(RenderObject* child, RenderStyle* style) const
+bool RenderFrameSet::isChildAllowed(RenderObject* child, RenderStyle*) const
{
return child->isFrame() || child->isFrameSet();
}
diff --git a/WebCore/rendering/RenderHTMLCanvas.cpp b/WebCore/rendering/RenderHTMLCanvas.cpp
index cc8c2c1..f4d88d8 100644
--- a/WebCore/rendering/RenderHTMLCanvas.cpp
+++ b/WebCore/rendering/RenderHTMLCanvas.cpp
@@ -39,32 +39,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/WebCore/rendering/RenderImage.cpp b/WebCore/rendering/RenderImage.cpp
index 604c407..e67a4ca 100644
--- a/WebCore/rendering/RenderImage.cpp
+++ b/WebCore/rendering/RenderImage.cpp
@@ -28,6 +28,7 @@
#include "BitmapImage.h"
#include "Document.h"
+#include "FrameView.h"
#include "GraphicsContext.h"
#include "HTMLImageElement.h"
#include "HTMLInputElement.h"
@@ -36,11 +37,16 @@
#include "HitTestResult.h"
#include "Page.h"
#include "RenderView.h"
+#include <wtf/CurrentTime.h>
+
#ifdef ANDROID_LAYOUT
#include "Settings.h"
#endif
-#include "SystemTime.h"
+#if ENABLE(WML)
+#include "WMLImageElement.h"
+#include "WMLNames.h"
+#endif
using namespace std;
@@ -169,7 +175,7 @@ bool RenderImageScaleObserver::shouldImagePaintAtLowQuality(RenderImage* image,
HashMap<RenderImage*, RenderImageScaleData*>* RenderImageScaleObserver::gImages = 0;
-void RenderImage::highQualityRepaintTimerFired(Timer<RenderImage>* timer)
+void RenderImage::highQualityRepaintTimerFired(Timer<RenderImage>*)
{
RenderImageScaleObserver::highQualityRepaintTimerFired(this);
}
@@ -181,6 +187,8 @@ RenderImage::RenderImage(Node* node)
, m_cachedImage(0)
{
updateAltText();
+
+ view()->frameView()->setIsVisuallyNonEmpty();
}
RenderImage::~RenderImage()
@@ -248,13 +256,13 @@ bool RenderImage::setImageSizeForAltText(CachedImage* newImage /* = 0 */)
return true;
}
-void RenderImage::imageChanged(WrappedImagePtr newImage)
+void RenderImage::imageChanged(WrappedImagePtr newImage, const IntRect* rect)
{
if (documentBeingDestroyed())
return;
if (hasBoxDecorations() || hasMask())
- RenderReplaced::imageChanged(newImage);
+ RenderReplaced::imageChanged(newImage, rect);
if (newImage != imagePtr() || !newImage)
return;
@@ -277,28 +285,36 @@ void RenderImage::imageChanged(WrappedImagePtr newImage)
// 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);
}
}
if (shouldRepaint) {
- // FIXME: We always just do a complete repaint, since we always pass in the full image
- // rect at the moment anyway.
- repaintRectangle(contentBox());
+ IntRect repaintRect;
+ 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)), contentBoxRect()));
+ // Guard against too-large changed rects.
+ repaintRect.intersect(contentBoxRect());
+ } else
+ repaintRect = contentBoxRect();
+
+ repaintRectangle(repaintRect);
}
}
@@ -359,9 +375,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;
@@ -374,9 +388,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) {
@@ -386,7 +400,7 @@ 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);
@@ -414,8 +428,8 @@ bool RenderImage::nodeAtPoint(const HitTestRequest& request, HitTestResult& resu
bool inside = RenderReplaced::nodeAtPoint(request, result, _x, _y, _tx, _ty, hitTestAction);
if (inside && element()) {
- int tx = _tx + m_x;
- int ty = _ty + m_y;
+ int tx = _tx + x();
+ int ty = _ty + y();
HTMLMapElement* map = imageMap();
if (map) {
@@ -437,6 +451,10 @@ void RenderImage::updateAltText()
m_altText = static_cast<HTMLInputElement*>(element())->altText();
else if (element()->hasTagName(imgTag))
m_altText = static_cast<HTMLImageElement*>(element())->altText();
+#if ENABLE(WML)
+ else if (element()->hasTagName(WMLNames::imgTag))
+ m_altText = static_cast<WMLImageElement*>(element())->altText();
+#endif
}
bool RenderImage::isWidthSpecified() const
@@ -476,8 +494,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/WebCore/rendering/RenderImage.h b/WebCore/rendering/RenderImage.h
index 477fdeb..71896d6 100644
--- a/WebCore/rendering/RenderImage.h
+++ b/WebCore/rendering/RenderImage.h
@@ -47,7 +47,7 @@ public:
virtual int minimumReplacedHeight() const;
- virtual void imageChanged(WrappedImagePtr);
+ virtual void imageChanged(WrappedImagePtr, const IntRect* = 0);
bool setImageSizeForAltText(CachedImage* newImage = 0);
@@ -72,7 +72,7 @@ public:
void highQualityRepaintTimerFired(Timer<RenderImage>*);
protected:
- virtual Image* image(int w = 0, int h = 0) { return m_cachedImage ? m_cachedImage->image() : nullImage(); }
+ virtual Image* image(int /*w*/ = 0, int /*h*/ = 0) { return m_cachedImage ? m_cachedImage->image() : nullImage(); }
virtual bool errorOccurred() const { return m_cachedImage && m_cachedImage->errorOccurred(); }
virtual bool usesImageContainerSize() const { return m_cachedImage ? m_cachedImage->usesImageContainerSize() : false; }
virtual void setImageContainerSize(const IntSize& size) const { if (m_cachedImage) m_cachedImage->setImageContainerSize(size); }
diff --git a/WebCore/rendering/RenderInline.cpp b/WebCore/rendering/RenderInline.cpp
index 79d914f..4f4412d 100644
--- a/WebCore/rendering/RenderInline.cpp
+++ b/WebCore/rendering/RenderInline.cpp
@@ -25,9 +25,10 @@
#include "config.h"
#include "RenderInline.h"
-#include "Document.h"
+#include "FloatQuad.h"
#include "RenderArena.h"
#include "RenderBlock.h"
+#include "RenderView.h"
#include "VisiblePosition.h"
namespace WebCore {
@@ -68,7 +69,7 @@ void RenderInline::styleDidChange(RenderStyle::Diff diff, const RenderStyle* old
m_lineHeight = -1;
// Update pseudos for :before and :after now.
- if (!isAnonymous()) {
+ if (!isAnonymous() && document()->usesBeforeAfterRules()) {
updateBeforeAfterContent(RenderStyle::BEFORE);
updateBeforeAfterContent(RenderStyle::AFTER);
}
@@ -115,7 +116,8 @@ void RenderInline::addChildToFlow(RenderObject* newChild, RenderObject* beforeCh
// 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())
+ updateBeforeAfterContent(RenderStyle::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.
@@ -187,7 +189,8 @@ void RenderInline::splitInlines(RenderBlock* fromBlock, RenderBlock* toBlock,
// 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())
+ curr->updateBeforeAfterContent(RenderStyle::AFTER);
// Now we need to take all of the children starting from the first child
// *after* currChild and append them all to the clone.
@@ -290,46 +293,33 @@ void RenderInline::absoluteRects(Vector<IntRect>& rects, int tx, int ty, bool to
rects.append(IntRect(tx + curr->xPos(), ty + curr->yPos(), curr->width(), curr->height()));
for (RenderObject* curr = firstChild(); curr; curr = curr->nextSibling()) {
- if (!curr->isText())
- curr->absoluteRects(rects, tx + curr->xPos(), ty + curr->yPos(), false);
+ if (curr->isBox()) {
+ RenderBox* box = toRenderBox(curr);
+ curr->absoluteRects(rects, tx + box->x(), ty + box->y(), false);
+ }
}
if (continuation() && topLevel)
continuation()->absoluteRects(rects,
- tx - containingBlock()->xPos() + continuation()->xPos(),
- ty - containingBlock()->yPos() + continuation()->yPos(),
+ tx - containingBlock()->x() + continuation()->x(),
+ ty - containingBlock()->y() + continuation()->y(),
topLevel);
}
-bool RenderInline::requiresLayer()
-{
- return isRelPositioned() || isTransparent() || hasMask();
-}
-
-int RenderInline::width() const
+void RenderInline::absoluteQuads(Vector<FloatQuad>& quads, bool topLevel)
{
- // 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();
+ 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);
}
- return rightSide - leftSide;
-}
-
-int RenderInline::height() const
-{
- // See <rdar://problem/5289721>, for an unknown reason the linked list here is sometimes inconsistent, first is non-zero and last is zero. We have been
- // unable to reproduce this at all (and consequently unable to figure ot why this is happening). The assert will hopefully catch the problem in debug
- // builds and help us someday figure out why. We also put in a redundant check of lastLineBox() to avoid the crash for now.
- ASSERT(!firstLineBox() == !lastLineBox()); // Either both are null or both exist.
- if (firstLineBox() && lastLineBox())
- return lastLineBox()->yPos() + lastLineBox()->height() - firstLineBox()->yPos();
- return 0;
+ if (continuation() && topLevel)
+ continuation()->absoluteQuads(quads, topLevel);
}
int RenderInline::offsetLeft() const
@@ -354,6 +344,8 @@ const char* RenderInline::renderName() const
return "RenderInline (relative positioned)";
if (isAnonymous())
return "RenderInline (generated)";
+ if (isRunIn())
+ return "RenderInline (run-in)";
return "RenderInline";
}
@@ -367,17 +359,104 @@ VisiblePosition RenderInline::positionForCoordinates(int x, int y)
{
// Translate the coords from the pre-anonymous block to the post-anonymous block.
RenderBlock* cb = containingBlock();
- int parentBlockX = cb->xPos() + x;
- int parentBlockY = cb->yPos() + y;
- for (RenderObject* c = continuation(); c; c = c->continuation()) {
- RenderObject* contBlock = c;
+ int parentBlockX = cb->x() + x;
+ int parentBlockY = cb->y() + y;
+ for (RenderFlow* c = continuation(); c; c = c->continuation()) {
+ RenderFlow* contBlock = c;
if (c->isInline())
contBlock = c->containingBlock();
if (c->isInline() || c->firstChild())
- return c->positionForCoordinates(parentBlockX - contBlock->xPos(), parentBlockY - contBlock->yPos());
+ return c->positionForCoordinates(parentBlockX - contBlock->x(), parentBlockY - contBlock->y());
}
return RenderFlow::positionForCoordinates(x, y);
}
+IntRect RenderInline::linesBoundingBox() const
+{
+ IntRect result;
+
+ // See <rdar://problem/5289721>, for an unknown reason the linked list here is sometimes inconsistent, first is non-zero and last is zero. We have been
+ // unable to reproduce this at all (and consequently unable to figure ot why this is happening). The assert will hopefully catch the problem in debug
+ // builds and help us someday figure out why. We also put in a redundant check of lastLineBox() to avoid the crash for now.
+ ASSERT(!firstLineBox() == !lastLineBox()); // Either both are null or both exist.
+ if (firstLineBox() && lastLineBox()) {
+ // Return the width of the minimal left side and the maximal right side.
+ int leftSide = 0;
+ int rightSide = 0;
+ for (InlineRunBox* curr = firstLineBox(); curr; curr = curr->nextLineBox()) {
+ if (curr == firstLineBox() || curr->xPos() < leftSide)
+ leftSide = curr->xPos();
+ if (curr == firstLineBox() || curr->xPos() + curr->width() > rightSide)
+ rightSide = curr->xPos() + curr->width();
+ }
+ result.setWidth(rightSide - leftSide);
+ result.setX(leftSide);
+ result.setHeight(lastLineBox()->yPos() + lastLineBox()->height() - firstLineBox()->yPos());
+ result.setY(firstLineBox()->yPos());
+ }
+
+ return result;
+}
+
+IntRect RenderInline::clippedOverflowRectForRepaint(RenderBox* repaintContainer)
+{
+ // Only run-ins are allowed in here during layout.
+ ASSERT(!view() || !view()->layoutStateEnabled() || isRunIn());
+
+ if (!firstLineBox() && !continuation())
+ return IntRect();
+
+ // Find our leftmost position.
+ IntRect boundingBox(linesBoundingBox());
+ int left = boundingBox.x();
+ int top = boundingBox.y();
+
+ // Now invalidate a rectangle.
+ int ow = style() ? style()->outlineSize() : 0;
+
+ // We need to add in the relative position offsets of any inlines (including us) up to our
+ // containing block.
+ RenderBlock* cb = containingBlock();
+ for (RenderObject* inlineFlow = this; inlineFlow && inlineFlow->isRenderInline() && inlineFlow != cb;
+ inlineFlow = inlineFlow->parent()) {
+ if (inlineFlow->style()->position() == RelativePosition && inlineFlow->hasLayer())
+ toRenderBox(inlineFlow)->layer()->relativePositionOffset(left, top);
+ }
+
+ IntRect r(-ow + left, -ow + top, boundingBox.width() + ow * 2, boundingBox.height() + ow * 2);
+ if (cb->hasColumns())
+ cb->adjustRectForColumns(r);
+
+ if (cb->hasOverflowClip()) {
+ // cb->height() is inaccurate if we're in the middle of a layout of |cb|, so use the
+ // layer's size instead. Even if the layer's size is wrong, the layer itself will repaint
+ // anyway if its size does change.
+ int x = r.x();
+ int y = r.y();
+ IntRect boxRect(0, 0, cb->layer()->width(), cb->layer()->height());
+ cb->layer()->subtractScrolledContentOffset(x, y); // For overflow:auto/scroll/hidden.
+ IntRect repaintRect(x, y, r.width(), r.height());
+ r = intersection(repaintRect, boxRect);
+ }
+ ASSERT(repaintContainer != this);
+ cb->computeRectForRepaint(r, repaintContainer);
+
+ if (ow) {
+ for (RenderObject* curr = firstChild(); curr; curr = curr->nextSibling()) {
+ if (!curr->isText()) {
+ IntRect childRect = curr->rectWithOutlineForRepaint(repaintContainer, ow);
+ r.unite(childRect);
+ }
+ }
+
+ if (continuation() && !continuation()->isInline()) {
+ IntRect contRect = continuation()->rectWithOutlineForRepaint(repaintContainer, ow);
+ r.unite(contRect);
+ }
+ }
+
+ return r;
+}
+
} // namespace WebCore
diff --git a/WebCore/rendering/RenderInline.h b/WebCore/rendering/RenderInline.h
index 36cb864..83b8506 100644
--- a/WebCore/rendering/RenderInline.h
+++ b/WebCore/rendering/RenderInline.h
@@ -39,7 +39,6 @@ public:
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;
@@ -56,21 +55,28 @@ public:
virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, int x, int y, int tx, int ty, HitTestAction);
- // overrides RenderObject
- virtual bool requiresLayer();
+ virtual bool requiresLayer() const { return isRelPositioned() || isTransparent() || hasMask(); }
- virtual int width() const;
- virtual int height() const;
-
- // 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(); }
void absoluteRects(Vector<IntRect>&, int tx, int ty, bool topLevel = true);
+ virtual void absoluteQuads(Vector<FloatQuad>&, bool topLevel = true);
+
+ virtual IntRect clippedOverflowRectForRepaint(RenderBox* repaintContainer);
virtual VisiblePosition positionForCoordinates(int x, int y);
+ IntRect linesBoundingBox() const;
+
+ virtual IntRect borderBoundingBox() const
+ {
+ IntRect boundingBox = linesBoundingBox();
+ return IntRect(0, 0, boundingBox.width(), boundingBox.height());
+ }
+
protected:
virtual void styleDidChange(RenderStyle::Diff, const RenderStyle* oldStyle);
diff --git a/WebCore/rendering/RenderLayer.cpp b/WebCore/rendering/RenderLayer.cpp
index 93efde1..1a538c6 100644
--- a/WebCore/rendering/RenderLayer.cpp
+++ b/WebCore/rendering/RenderLayer.cpp
@@ -74,6 +74,7 @@
#include "ScrollbarTheme.h"
#include "SelectionController.h"
#include "TranslateTransformOperation.h"
+#include <wtf/StdLibExtras.h>
#if ENABLE(SVG)
#include "SVGNames.h"
@@ -115,8 +116,8 @@ void ClipRects::destroy(RenderArena* renderArena)
renderArena->free(*(size_t *)this, this);
}
-RenderLayer::RenderLayer(RenderObject* object)
- : m_object(object)
+RenderLayer::RenderLayer(RenderBox* renderer)
+ : m_renderer(renderer)
, m_parent(0)
, m_previous(0)
, m_next(0)
@@ -139,6 +140,9 @@ RenderLayer::RenderLayer(RenderObject* object)
, m_negZOrderList(0)
, m_overflowList(0)
, m_clipRects(0)
+#ifndef NDEBUG
+ , m_clipRectsRoot(0)
+#endif
, m_scrollDimensionsDirty(true)
, m_zOrderListsDirty(true)
, m_overflowListDirty(true)
@@ -160,9 +164,9 @@ RenderLayer::RenderLayer(RenderObject* object)
, 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;
}
}
@@ -203,7 +207,7 @@ RenderLayer::~RenderLayer()
void RenderLayer::updateLayerPositions(bool doFullRepaint, bool checkForRepaint)
{
if (doFullRepaint) {
- m_object->repaint();
+ renderer()->repaint();
checkForRepaint = doFullRepaint = false;
}
@@ -221,14 +225,14 @@ 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->absoluteOutlineBox();
+ IntRect newRect = renderer()->absoluteClippedOverflowRect();
+ IntRect newOutlineBox = renderer()->absoluteOutlineBounds();
if (checkForRepaint) {
if (view && !view->printing()) {
if (m_needsFullRepaint) {
@@ -236,7 +240,7 @@ void RenderLayer::updateLayerPositions(bool doFullRepaint, bool checkForRepaint)
if (newRect != m_repaintRect)
view->repaintViewRectangle(newRect);
} else
- m_object->repaintAfterLayoutIfNeeded(m_repaintRect, m_outlineBox);
+ renderer()->repaintAfterLayoutIfNeeded(m_repaintRect, m_outlineBox);
}
}
m_repaintRect = newRect;
@@ -266,14 +270,14 @@ void RenderLayer::updateTransform()
bool hadTransform = m_transform;
if (hasTransform != hadTransform) {
if (hasTransform)
- m_transform.set(new AffineTransform);
+ m_transform.set(new TransformationMatrix);
else
m_transform.clear();
}
if (hasTransform) {
m_transform->reset();
- renderer()->style()->applyTransform(*m_transform, renderer()->borderBox().size());
+ renderer()->style()->applyTransform(*m_transform, renderer()->borderBoxRect().size());
}
}
@@ -285,7 +289,7 @@ void RenderLayer::setHasVisibleContent(bool b)
m_hasVisibleContent = b;
if (m_hasVisibleContent) {
m_repaintRect = renderer()->absoluteClippedOverflowRect();
- m_outlineBox = renderer()->absoluteOutlineBox();
+ m_outlineBox = renderer()->absoluteOutlineBounds();
if (!isOverflowOnly())
dirtyStackingContextZOrderLists();
}
@@ -338,12 +342,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;
@@ -356,7 +360,7 @@ void RenderLayer::updateVisibilityStatus()
else {
do {
r = r->parent();
- if (r==m_object)
+ if (r==renderer())
r = 0;
} while (r && !r->nextSibling());
if (r)
@@ -371,72 +375,80 @@ void RenderLayer::updateVisibilityStatus()
void RenderLayer::updateLayerPosition()
{
// Clear our cached clip rect information.
- clearClipRect();
+ clearClipRects();
- int x = m_object->xPos();
- int y = m_object->yPos() - m_object->borderTopExtra();
+ int x = renderer()->x();
+ int y = renderer()->y();
- 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();
+ RenderBox* curr = renderer()->parentBox();
while (curr && !curr->hasLayer()) {
if (!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();
+ x += curr->x();
+ y += curr->y();
}
- curr = curr->parent();
+ curr = curr->parentBox();
}
- y += curr->borderTopExtra();
if (curr->isTableRow()) {
// Put ourselves into the row coordinate space.
- x -= curr->xPos();
- y -= curr->yPos();
+ x -= curr->x();
+ y -= curr->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 = toRenderBox(renderer())->relativePositionOffsetX();
+ m_relY = toRenderBox(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->subtractScrollOffset(x, y);
+ positionedParent->subtractScrolledContentOffset(x, y);
- if (m_object->isPositioned()) {
- IntSize offset = static_cast<RenderBox*>(m_object)->offsetForPositionedInContainer(positionedParent->renderer());
+ if (renderer()->isPositioned()) {
+ IntSize offset = toRenderBox(renderer())->offsetForPositionedInContainer(positionedParent->renderer());
x += offset.width();
y += offset.height();
}
} else if (parent())
- parent()->subtractScrollOffset(x, y);
+ 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());
+ setPos(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 = static_cast<RenderInline*>(renderer());
+ IntRect lineBox = inlineFlow->linesBoundingBox();
+ setWidth(lineBox.width());
+ setHeight(lineBox.height());
+ } else {
+ setWidth(renderer()->width());
+ setHeight(renderer()->height());
+
+ if (!renderer()->hasOverflowClip()) {
+ if (renderer()->overflowWidth() > renderer()->width())
+ setWidth(renderer()->overflowWidth());
+ if (renderer()->overflowHeight() > renderer()->height())
+ setHeight(renderer()->overflowHeight());
+ }
}
}
RenderLayer *RenderLayer::stackingContext() const
{
RenderLayer* curr = parent();
- for ( ; curr && !curr->m_object->isRenderView() && !curr->m_object->isRoot() &&
- curr->m_object->style()->hasAutoZIndex();
+ for ( ; curr && !curr->renderer()->isRenderView() && !curr->renderer()->isRoot() &&
+ curr->renderer()->style()->hasAutoZIndex();
curr = curr->parent()) { }
return curr;
}
@@ -444,7 +456,7 @@ RenderLayer *RenderLayer::stackingContext() const
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;
}
@@ -452,11 +464,17 @@ 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;
}
+IntPoint RenderLayer::absoluteToContents(const IntPoint& absolutePoint) const
+{
+ // We don't use convertToLayerCoords because it doesn't know about transforms
+ return roundedIntPoint(renderer()->absoluteToLocal(absolutePoint, false, true));
+}
+
bool RenderLayer::requiresSlowRepaints() const
{
if (isTransparent() || hasReflection() || hasTransform())
@@ -469,10 +487,10 @@ bool RenderLayer::requiresSlowRepaints() const
bool RenderLayer::isTransparent() const
{
#if ENABLE(SVG)
- if (m_object->node()->namespaceURI() == SVGNames::svgNamespaceURI)
+ if (renderer()->node()->namespaceURI() == SVGNames::svgNamespaceURI)
return false;
#endif
- return m_object->isTransparent() || m_object->hasMask();
+ return renderer()->isTransparent() || renderer()->hasMask();
}
RenderLayer*
@@ -483,20 +501,20 @@ RenderLayer::transparentAncestor()
return curr;
}
-static IntRect transparencyClipBox(const AffineTransform& enclosingTransform, const RenderLayer* l, const RenderLayer* rootLayer)
+static IntRect transparencyClipBox(const TransformationMatrix& enclosingTransform, const RenderLayer* l, const RenderLayer* rootLayer)
{
// FIXME: Although this function completely ignores CSS-imposed clipping, we did already intersect with the
// paintDirtyRect, and that should cut down on the amount we have to paint. Still it
// would be better to respect clips.
- AffineTransform* t = l->transform();
+ TransformationMatrix* t = l->transform();
if (t && rootLayer != l) {
// 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);
- AffineTransform transform;
+ TransformationMatrix transform;
transform.translate(x, y);
transform = *t * transform;
transform = transform * enclosingTransform;
@@ -542,7 +560,7 @@ void RenderLayer::beginTransparencyLayers(GraphicsContext* p, const RenderLayer*
if (isTransparent()) {
m_usedTransparency = true;
p->save();
- p->clip(transparencyClipBox(AffineTransform(), this, rootLayer));
+ p->clip(transparencyClipBox(TransformationMatrix(), this, rootLayer));
p->beginTransparencyLayer(renderer()->opacity());
}
}
@@ -637,7 +655,7 @@ void RenderLayer::removeOnlyThisLayer()
return;
// Dirty the clip rects.
- clearClipRects();
+ clearClipRectsIncludingDescendants();
// Remove us from the parent.
RenderLayer* parent = m_parent;
@@ -676,7 +694,7 @@ void RenderLayer::insertOnlyThisLayer()
curr->moveLayers(m_parent, this);
// Clear out all the clip rects.
- clearClipRects();
+ clearClipRectsIncludingDescendants();
}
void
@@ -685,18 +703,17 @@ RenderLayer::convertToLayerCoords(const RenderLayer* ancestorLayer, int& x, int&
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
- // absolutePosition() on the RenderView.
- int xOff, yOff;
- m_object->absolutePosition(xOff, yOff, true);
- x += xOff;
- y += yOff;
+ // localToAbsolute() on the RenderView.
+ FloatPoint absPos = renderer()->localToAbsolute(FloatPoint(), true);
+ x += absPos.x();
+ y += absPos.y();
return;
}
RenderLayer* parentLayer;
- if (m_object->style()->position() == AbsolutePosition)
+ if (renderer()->style()->position() == AbsolutePosition)
parentLayer = enclosingPositionedAncestor();
else
parentLayer = parent();
@@ -749,10 +766,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);
@@ -760,26 +777,26 @@ 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));
}
void
-RenderLayer::scrollOffset(int& x, int& y)
+RenderLayer::addScrolledContentOffset(int& x, int& y) const
{
x += scrollXOffset() + m_scrollLeftOverflow;
y += scrollYOffset();
}
void
-RenderLayer::subtractScrollOffset(int& x, int& y)
+RenderLayer::subtractScrolledContentOffset(int& x, int& y) const
{
x -= scrollXOffset() + m_scrollLeftOverflow;
y -= scrollYOffset();
@@ -793,8 +810,8 @@ void RenderLayer::scrollToOffset(int x, int y, bool updateScrollbars, bool repai
// 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() - renderer()->clientWidth();
+ int maxY = scrollHeight() - renderer()->clientHeight();
if (x > maxX) x = maxX;
if (y > maxY) y = maxY;
@@ -805,7 +822,10 @@ void RenderLayer::scrollToOffset(int x, int y, bool updateScrollbars, bool repai
// complicated (since it will involve testing whether our layer
// is either occluded by another layer or clipped by an enclosing
// layer or contains fixed backgrounds, etc.).
- m_scrollX = x - m_scrollOriginX;
+ int newScrollX = x - m_scrollOriginX;
+ if (m_scrollY == y && m_scrollX == newScrollX)
+ return;
+ m_scrollX = newScrollX;
m_scrollY = y;
// Update the positions of our child layers.
@@ -826,9 +846,14 @@ void RenderLayer::scrollToOffset(int x, int y, bool updateScrollbars, bool repai
view->updateWidgetPositions();
}
+ // The caret rect needs to be invalidated after scrolling
+ Frame* frame = renderer()->document()->frame();
+ if (frame)
+ frame->invalidateSelection();
+
// Just schedule a full repaint of our object.
if (repaint)
- m_object->repaint();
+ renderer()->repaint();
if (updateScrollbars) {
if (m_hBar)
@@ -851,31 +876,29 @@ 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.
- int x, y;
- m_object->absolutePosition(x, y);
- x += m_object->borderLeft();
- y += m_object->borderTop();
+ FloatPoint absPos = renderer()->localToAbsolute();
+ absPos.move(renderer()->borderLeft(), renderer()->borderTop());
- IntRect layerBounds = IntRect(x + scrollXOffset(), y + scrollYOffset(), m_object->clientWidth(), m_object->clientHeight());
+ IntRect layerBounds = IntRect(absPos.x() + scrollXOffset(), absPos.y() + scrollYOffset(), renderer()->clientWidth(), renderer()->clientHeight());
IntRect exposeRect = IntRect(rect.x() + scrollXOffset(), rect.y() + scrollYOffset(), rect.width(), rect.height());
IntRect r = getRectToExpose(layerBounds, exposeRect, alignX, alignY);
- xOffset = r.x() - x;
- yOffset = r.y() - y;
+ xOffset = r.x() - absPos.x();
+ yOffset = r.y() - absPos.y();
// Adjust offsets if they're outside of the allowable range.
xOffset = max(0, min(scrollWidth() - layerBounds.width(), xOffset));
yOffset = max(0, min(scrollHeight() - layerBounds.height(), yOffset));
@@ -891,7 +914,7 @@ void RenderLayer::scrollRectToVisible(const IntRect &rect, bool scrollToAnchor,
}
} else if (!parentLayer && renderer()->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);
@@ -902,7 +925,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 {
@@ -1014,13 +1037,13 @@ void RenderLayer::autoscroll()
void RenderLayer::resize(const PlatformMouseEvent& evt, const IntSize& oldOffset)
{
- if (!inResizeMode() || !m_object->hasOverflowClip())
+ if (!inResizeMode() || !renderer()->hasOverflowClip())
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)
@@ -1156,7 +1179,7 @@ static IntRect resizerCornerRect(const RenderLayer* layer, const IntRect& bounds
bool RenderLayer::scrollbarCornerPresent() const
{
- return !scrollCornerRect(this, m_object->borderBox()).isEmpty();
+ return !scrollCornerRect(this, renderer()->borderBoxRect()).isEmpty();
}
void RenderLayer::invalidateScrollbarRect(Scrollbar* scrollbar, const IntRect& rect)
@@ -1172,12 +1195,12 @@ void RenderLayer::invalidateScrollbarRect(Scrollbar* scrollbar, const IntRect& r
PassRefPtr<Scrollbar> RenderLayer::createScrollbar(ScrollbarOrientation orientation)
{
RefPtr<Scrollbar> widget;
- bool hasCustomScrollbarStyle = m_object->node()->shadowAncestorNode()->renderer()->style()->hasPseudoStyle(RenderStyle::SCROLLBAR);
+ bool hasCustomScrollbarStyle = renderer()->node()->shadowAncestorNode()->renderer()->style()->hasPseudoStyle(RenderStyle::SCROLLBAR);
if (hasCustomScrollbarStyle)
- widget = RenderScrollbar::createCustomScrollbar(this, orientation, m_object->node()->shadowAncestorNode()->renderer());
+ widget = RenderScrollbar::createCustomScrollbar(this, orientation, renderer()->node()->shadowAncestorNode()->renderBox());
else
widget = Scrollbar::createNativeScrollbar(this, orientation, RegularScrollbar);
- m_object->document()->view()->addChild(widget.get());
+ renderer()->document()->view()->addChild(widget.get());
return widget.release();
}
@@ -1209,8 +1232,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
}
@@ -1232,8 +1255,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
}
@@ -1251,39 +1274,38 @@ int RenderLayer::horizontalScrollbarHeight() const
return m_hBar->height();
}
-IntSize RenderLayer::offsetFromResizeCorner(const IntPoint& p) const
+IntSize RenderLayer::offsetFromResizeCorner(const IntPoint& absolutePoint) const
{
// Currently the resize corner is always the bottom right corner
- int x = width();
- int y = height();
- convertToLayerCoords(root(), x, y);
- return p - IntPoint(x, y);
+ IntPoint bottomRight(width(), height());
+ IntPoint localPoint = absoluteToContents(absolutePoint);
+ return localPoint - bottomRight;
}
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();
+ IntRect borderBox = renderer()->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() - renderer()->borderRight() - m_vBar->width(),
+ absBounds.y() + renderer()->borderTop(),
m_vBar->width(),
- absBounds.height() - (m_object->borderTop() + m_object->borderBottom()) - scrollCorner.height()));
+ absBounds.height() - (renderer()->borderTop() + renderer()->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() + renderer()->borderLeft(),
+ absBounds.bottom() - renderer()->borderBottom() - m_hBar->height(),
+ absBounds.width() - (renderer()->borderLeft() + renderer()->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()
@@ -1304,17 +1326,17 @@ void RenderLayer::computeScrollDimensions(bool* needHBar, bool* needVBar)
{
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 = renderer()->clientWidth();
+ int clientHeight = renderer()->clientHeight();
- m_scrollLeftOverflow = ltr ? 0 : min(0, m_object->leftmostPosition(true, false) - m_object->borderLeft());
+ m_scrollLeftOverflow = ltr ? 0 : min(0, renderer()->leftmostPosition(true, false) - renderer()->borderLeft());
int rightPos = ltr ?
- m_object->rightmostPosition(true, false) - m_object->borderLeft() :
+ renderer()->rightmostPosition(true, false) - renderer()->borderLeft() :
clientWidth - m_scrollLeftOverflow;
- int bottomPos = m_object->lowestPosition(true, false) - m_object->borderTop();
+ int bottomPos = renderer()->lowestPosition(true, false) - renderer()->borderTop();
m_scrollWidth = max(rightPos, clientWidth);
m_scrollHeight = max(bottomPos, clientHeight);
@@ -1344,9 +1366,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()));
+ EventTargetNodeCast(renderer()->element()));
}
}
}
@@ -1359,13 +1381,13 @@ RenderLayer::updateScrollInfoAfterLayout()
bool horizontalOverflow, verticalOverflow;
computeScrollDimensions(&horizontalOverflow, &verticalOverflow);
- if (m_object->style()->overflowX() != OMARQUEE) {
+ if (renderer()->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() - renderer()->clientWidth()));
+ int newY = max(0, min(m_scrollY, scrollHeight() - renderer()->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.
@@ -1382,58 +1404,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 = (renderer()->hasAutoHorizontalScrollbar() && haveHorizontalBar != horizontalOverflow) ||
+ (renderer()->hasAutoVerticalScrollbar() && haveVerticalBar != verticalOverflow);
if (scrollbarsChanged) {
- if (m_object->hasAutoHorizontalScrollbar())
+ if (renderer()->hasAutoHorizontalScrollbar())
setHasHorizontalScrollbar(horizontalOverflow);
- if (m_object->hasAutoVerticalScrollbar())
+ if (renderer()->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())
+ static_cast<RenderBlock*>(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 && renderer()->hasAutoHorizontalScrollbar())
m_hBar->setEnabled(true);
- if (m_vBar && m_object->hasAutoVerticalScrollbar())
+ if (m_vBar && renderer()->hasAutoVerticalScrollbar())
m_vBar->setEnabled(true);
// Set up the range (and page step/line step).
if (m_hBar) {
- int clientWidth = m_object->clientWidth();
+ int clientWidth = renderer()->clientWidth();
int pageStep = (clientWidth - cAmountToKeepWhenPaging);
if (pageStep < 0) pageStep = clientWidth;
m_hBar->setSteps(cScrollbarPixelsPerLineStep, pageStep);
@@ -1441,21 +1463,21 @@ RenderLayer::updateScrollInfoAfterLayout()
m_hBar->setValue(scrollXOffset());
}
if (m_vBar) {
- int clientHeight = m_object->clientHeight();
+ int clientHeight = renderer()->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()->element() && 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
@@ -1479,7 +1501,7 @@ 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());
+ IntRect cornerRect = scrollCornerRect(this, renderer()->borderBoxRect());
IntRect absRect = IntRect(cornerRect.x() + tx, cornerRect.y() + ty, cornerRect.width(), cornerRect.height());
if (!absRect.intersects(damageRect))
return;
@@ -1499,10 +1521,10 @@ 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());
+ IntRect cornerRect = resizerCornerRect(this, renderer()->borderBoxRect());
IntRect absRect = IntRect(cornerRect.x() + tx, cornerRect.y() + ty, cornerRect.width(), cornerRect.height());
if (!absRect.intersects(damageRect))
return;
@@ -1518,9 +1540,7 @@ void RenderLayer::paintResizer(GraphicsContext* context, int tx, int ty, const I
}
// Paint the resizer control.
- static RefPtr<Image> resizeCornerImage;
- if (!resizeCornerImage)
- resizeCornerImage = Image::loadPlatformResource("textAreaResizeCorner");
+ DEFINE_STATIC_LOCAL(RefPtr<Image>, resizeCornerImage, (Image::loadPlatformResource("textAreaResizeCorner")));
IntPoint imagePoint(absRect.right() - resizeCornerImage->width(), absRect.bottom() - resizeCornerImage->height());
context->drawImage(resizeCornerImage.get(), imagePoint);
@@ -1538,16 +1558,15 @@ void RenderLayer::paintResizer(GraphicsContext* context, int tx, int ty, const I
}
}
-bool RenderLayer::isPointInResizeControl(const IntPoint& point)
+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;
- int x = 0;
- int y = 0;
- convertToLayerCoords(root(), x, y);
- IntRect absBounds(x, y, m_object->width(), m_object->height());
- return resizerCornerRect(this, absBounds).contains(point);
+ IntPoint localPoint = absoluteToContents(absolutePoint);
+
+ IntRect localBounds(0, 0, renderer()->width(), renderer()->height());
+ return resizerCornerRect(this, localBounds).contains(localPoint);
}
bool RenderLayer::hitTestOverflowControls(HitTestResult& result)
@@ -1633,7 +1652,7 @@ static void restoreClip(GraphicsContext* p, const IntRect& paintDirtyRect, const
void
RenderLayer::paintLayer(RenderLayer* rootLayer, GraphicsContext* p,
const IntRect& paintDirtyRect, bool haveTransparency, PaintRestriction paintRestriction,
- RenderObject* paintingRoot, bool appliedTransform)
+ RenderObject* paintingRoot, bool appliedTransform, bool temporaryClipRects)
{
// 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
@@ -1642,7 +1661,7 @@ 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())
@@ -1662,8 +1681,14 @@ RenderLayer::paintLayer(RenderLayer* rootLayer, GraphicsContext* p,
// Make sure the parent's clip rects have been calculated.
IntRect clipRect = paintDirtyRect;
if (parent()) {
- parent()->calculateClipRects(rootLayer);
- clipRect = parent()->clipRects()->overflowClipRect();
+ if (temporaryClipRects) {
+ ClipRects parentClipRects;
+ parent()->calculateClipRects(rootLayer, parentClipRects);
+ clipRect = parentClipRects.overflowClipRect();
+ } else {
+ parent()->updateClipRects(rootLayer);
+ clipRect = parent()->clipRects()->overflowClipRect();
+ }
clipRect.intersect(paintDirtyRect);
}
@@ -1675,7 +1700,7 @@ RenderLayer::paintLayer(RenderLayer* rootLayer, GraphicsContext* p,
int x = 0;
int y = 0;
convertToLayerCoords(rootLayer, x, y);
- AffineTransform transform;
+ TransformationMatrix transform;
transform.translate(x, y);
transform = *m_transform * transform;
@@ -1684,7 +1709,7 @@ 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);
+ paintLayer(this, p, transform.inverse().mapRect(paintDirtyRect), haveTransparency, paintRestriction, paintingRoot, true, temporaryClipRects);
p->restore();
@@ -1698,17 +1723,17 @@ RenderLayer::paintLayer(RenderLayer* rootLayer, GraphicsContext* p,
if (m_reflection && !m_paintingInsideReflection && (!m_transform || appliedTransform)) {
// Mark that we are now inside replica painting.
m_paintingInsideReflection = true;
- reflectionLayer()->paintLayer(rootLayer, p, paintDirtyRect, haveTransparency, paintRestriction, paintingRoot);
+ reflectionLayer()->paintLayer(rootLayer, p, paintDirtyRect, haveTransparency, paintRestriction, paintingRoot, false, temporaryClipRects);
m_paintingInsideReflection = false;
}
// Calculate the clip rects we should use.
IntRect layerBounds, damageRect, clipRectToApply, outlineRect;
- calculateRects(rootLayer, paintDirtyRect, layerBounds, damageRect, clipRectToApply, outlineRect);
+ calculateRects(rootLayer, paintDirtyRect, layerBounds, damageRect, clipRectToApply, outlineRect, temporaryClipRects);
int x = layerBounds.x();
int y = layerBounds.y();
- int tx = x - renderer()->xPos();
- int ty = y - renderer()->yPos() + renderer()->borderTopExtra();
+ int tx = x - renderer()->x();
+ int ty = y - renderer()->y();
// Ensure our lists are up-to-date.
updateZOrderLists();
@@ -1722,7 +1747,7 @@ 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;
// We want to paint our layer, but only if we intersect the damage rect.
@@ -1752,7 +1777,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);
+ it[0]->paintLayer(rootLayer, p, paintDirtyRect, haveTransparency, paintRestriction, paintingRoot, false, temporaryClipRects);
// Now establish the appropriate clip and paint our child RenderObjects.
if (shouldPaint && !clipRectToApply.isEmpty()) {
@@ -1790,12 +1815,12 @@ 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);
+ it[0]->paintLayer(rootLayer, p, paintDirtyRect, haveTransparency, paintRestriction, paintingRoot, false, temporaryClipRects);
// 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);
+ it[0]->paintLayer(rootLayer, p, paintDirtyRect, haveTransparency, paintRestriction, paintingRoot, false, temporaryClipRects);
if (renderer()->hasMask() && shouldPaint && !selectionOnly && !damageRect.isEmpty()) {
setClip(p, paintDirtyRect, damageRect);
@@ -1873,7 +1898,7 @@ RenderLayer* RenderLayer::hitTestLayer(RenderLayer* rootLayer, const HitTestRequ
// Make sure the parent's clip rects have been calculated.
if (parent()) {
- parent()->calculateClipRects(rootLayer);
+ parent()->updateClipRects(rootLayer);
// Go ahead and test the enclosing clip now.
IntRect clipRect = parent()->clipRects()->overflowClipRect();
@@ -1886,7 +1911,7 @@ RenderLayer* RenderLayer::hitTestLayer(RenderLayer* rootLayer, const HitTestRequ
int x = 0;
int y = 0;
convertToLayerCoords(rootLayer, x, y);
- AffineTransform transform;
+ TransformationMatrix transform;
transform.translate(x, y);
transform = *m_transform * transform;
@@ -1931,8 +1956,8 @@ RenderLayer* RenderLayer::hitTestLayer(RenderLayer* rootLayer, const HitTestRequ
// 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(),
+ layerBounds.x() - renderer()->x(),
+ layerBounds.y() - renderer()->y(),
HitTestDescendants)) {
// For positioned generated content, we might still not have a
// node by the time we get to the layer level, since none of
@@ -1961,8 +1986,8 @@ RenderLayer* RenderLayer::hitTestLayer(RenderLayer* rootLayer, const HitTestRequ
// 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(),
+ layerBounds.x() - renderer()->x(),
+ layerBounds.y() - renderer()->y(),
HitTestSelf)) {
if (!result.innerNode() || !result.innerNonSharedNode()) {
Node* e = enclosingElement();
@@ -1986,16 +2011,38 @@ RenderLayer* RenderLayer::hitTestLayer(RenderLayer* rootLayer, const HitTestRequ
return 0;
}
-void RenderLayer::calculateClipRects(const RenderLayer* rootLayer)
+void RenderLayer::updateClipRects(const RenderLayer* rootLayer)
{
- if (m_clipRects)
+ if (m_clipRects) {
+ ASSERT(rootLayer == m_clipRectsRoot);
return; // We have the correct cached value.
+ }
+
+ // For transformed layers, the root layer was shifted to be us, so there is no need to
+ // examine the parent. We want to cache clip rects with us as the root.
+ RenderLayer* parentLayer = rootLayer != this ? parent() : 0;
+ if (parentLayer)
+ parentLayer->updateClipRects(rootLayer);
+ ClipRects clipRects;
+ calculateClipRects(rootLayer, clipRects, true);
+
+ if (parentLayer && parentLayer->clipRects() && clipRects == *parentLayer->clipRects())
+ m_clipRects = parentLayer->clipRects();
+ else
+ m_clipRects = new (renderer()->renderArena()) ClipRects(clipRects);
+ m_clipRects->ref();
+#ifndef NDEBUG
+ m_clipRectsRoot = rootLayer;
+#endif
+}
+
+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.
- m_clipRects = new (m_object->renderArena()) ClipRects(infiniteRect);
- m_clipRects->ref();
+ clipRects.reset(infiniteRect);
return;
}
@@ -2004,100 +2051,95 @@ void RenderLayer::calculateClipRects(const RenderLayer* rootLayer)
RenderLayer* parentLayer = rootLayer != this ? parent() : 0;
// Ensure that our parent's clip has been calculated so that we can examine the values.
- if (parentLayer)
- parentLayer->calculateClipRects(rootLayer);
-
- // Set up our three rects to initially match the parent rects.
- IntRect posClipRect(parentLayer ? parentLayer->clipRects()->posClipRect() : infiniteRect);
- IntRect overflowClipRect(parentLayer ? parentLayer->clipRects()->overflowClipRect() : infiniteRect);
- IntRect fixedClipRect(parentLayer ? parentLayer->clipRects()->fixedClipRect() : infiniteRect);
- bool fixed = parentLayer ? parentLayer->clipRects()->fixed() : false;
+ if (parentLayer) {
+ if (useCached && parentLayer->clipRects())
+ clipRects = *parentLayer->clipRects();
+ else
+ parentLayer->calculateClipRects(rootLayer, clipRects);
+ }
+ else
+ clipRects.reset(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) {
- posClipRect = fixedClipRect;
- overflowClipRect = fixedClipRect;
- fixed = true;
+ if (renderer()->style()->position() == FixedPosition) {
+ clipRects.setPosClipRect(clipRects.fixedClipRect());
+ clipRects.setOverflowClipRect(clipRects.fixedClipRect());
+ clipRects.setFixed(true);
}
- else if (m_object->style()->position() == RelativePosition)
- posClipRect = overflowClipRect;
- else if (m_object->style()->position() == AbsolutePosition)
- overflowClipRect = posClipRect;
+ else if (renderer()->style()->position() == RelativePosition)
+ clipRects.setPosClipRect(clipRects.overflowClipRect());
+ 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;
convertToLayerCoords(rootLayer, x, y);
RenderView* view = renderer()->view();
ASSERT(view);
- if (view && fixed && rootLayer->renderer() == view) {
+ if (view && clipRects.fixed() && rootLayer->renderer() == view) {
x -= view->frameView()->scrollX();
y -= view->frameView()->scrollY();
}
- if (m_object->hasOverflowClip()) {
- IntRect newOverflowClip = m_object->getOverflowClipRect(x,y);
- overflowClipRect.intersect(newOverflowClip);
- if (m_object->isPositioned() || m_object->isRelPositioned())
- posClipRect.intersect(newOverflowClip);
+ if (renderer()->hasOverflowClip()) {
+ IntRect newOverflowClip = renderer()->getOverflowClipRect(x,y);
+ clipRects.setOverflowClipRect(intersection(newOverflowClip, clipRects.overflowClipRect()));
+ if (renderer()->isPositioned() || renderer()->isRelPositioned())
+ clipRects.setPosClipRect(intersection(newOverflowClip, clipRects.posClipRect()));
}
- if (m_object->hasClip()) {
- IntRect newPosClip = m_object->getClipRect(x,y);
- posClipRect.intersect(newPosClip);
- overflowClipRect.intersect(newPosClip);
- fixedClipRect.intersect(newPosClip);
+ if (renderer()->hasClip()) {
+ IntRect newPosClip = renderer()->getClipRect(x,y);
+ clipRects.setPosClipRect(intersection(newPosClip, clipRects.posClipRect()));
+ clipRects.setOverflowClipRect(intersection(newPosClip, clipRects.overflowClipRect()));
+ clipRects.setFixedClipRect(intersection(newPosClip, clipRects.fixedClipRect()));
}
}
-
- // If our clip rects match our parent's clip, then we can just share its data structure and
- // ref count.
- if (parent()->clipRects() &&
- fixed == parent()->clipRects()->fixed() &&
- posClipRect == parent()->clipRects()->posClipRect() &&
- overflowClipRect == parent()->clipRects()->overflowClipRect() &&
- fixedClipRect == parent()->clipRects()->fixedClipRect())
- m_clipRects = parent()->clipRects();
- else
- m_clipRects = new (m_object->renderArena()) ClipRects(overflowClipRect, fixedClipRect, posClipRect, fixed);
- m_clipRects->ref();
}
void RenderLayer::calculateRects(const RenderLayer* rootLayer, const IntRect& paintDirtyRect, IntRect& layerBounds,
- IntRect& backgroundRect, IntRect& foregroundRect, IntRect& outlineRect) const
+ IntRect& backgroundRect, IntRect& foregroundRect, IntRect& outlineRect, bool temporaryClipRects) const
{
if (rootLayer != this && parent()) {
- parent()->calculateClipRects(rootLayer);
+ ClipRects parentClipRects;
+ if (temporaryClipRects)
+ parent()->calculateClipRects(rootLayer, parentClipRects);
+ else {
+ parent()->updateClipRects(rootLayer);
+ parentClipRects = *parent()->clipRects();
+ }
- backgroundRect = m_object->style()->position() == FixedPosition ? parent()->clipRects()->fixedClipRect() :
- (m_object->isPositioned() ? parent()->clipRects()->posClipRect() :
- parent()->clipRects()->overflowClipRect());
+ backgroundRect = renderer()->style()->position() == FixedPosition ? parentClipRects.fixedClipRect() :
+ (renderer()->isPositioned() ? parentClipRects.posClipRect() :
+ parentClipRects.overflowClipRect());
RenderView* view = renderer()->view();
ASSERT(view);
- if (view && parent()->clipRects()->fixed() && rootLayer->renderer() == view)
+ if (view && parentClipRects.fixed() && rootLayer->renderer() == view)
backgroundRect.move(view->frameView()->scrollX(), view->frameView()->scrollY());
backgroundRect.intersect(paintDirtyRect);
} else
backgroundRect = paintDirtyRect;
+
foregroundRect = backgroundRect;
outlineRect = backgroundRect;
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(renderer()->getOverflowClipRect(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 = renderer()->getClipRect(x,y);
backgroundRect.intersect(newPosClip);
foregroundRect.intersect(newPosClip);
outlineRect.intersect(newPosClip);
@@ -2122,7 +2164,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;
@@ -2130,7 +2172,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;
@@ -2148,7 +2190,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))
@@ -2172,7 +2214,7 @@ 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());
InlineFlowBox* firstBox = inlineFlow->firstLineBox();
@@ -2183,16 +2225,14 @@ IntRect RenderLayer::boundingBox(const RenderLayer* rootLayer) const
int left = firstBox->xPos();
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);
+ result = IntRect(m_x + left, m_y + (top - renderer()->y()), 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());
if (bbox != overflowRect)
result.unite(overflowRect);
}
@@ -2202,7 +2242,7 @@ IntRect RenderLayer::boundingBox(const RenderLayer* rootLayer) const
if (renderer()->hasMask())
result = renderer()->maskClipRect();
else {
- IntRect bbox = renderer()->borderBox();
+ IntRect bbox = renderer()->borderBoxRect();
result = bbox;
IntRect overflowRect = renderer()->overflowRect(false);
if (bbox != overflowRect)
@@ -2210,11 +2250,7 @@ IntRect RenderLayer::boundingBox(const RenderLayer* rootLayer) const
}
// 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());
+ result.move(m_x, m_y);
}
// Convert the bounding box to an absolute position. We can do this easily by looking at the delta
@@ -2230,22 +2266,25 @@ IntRect RenderLayer::boundingBox(const RenderLayer* rootLayer) const
return result;
}
-void RenderLayer::clearClipRects()
+void RenderLayer::clearClipRectsIncludingDescendants()
{
if (!m_clipRects)
return;
- clearClipRect();
+ clearClipRects();
for (RenderLayer* l = firstChild(); l; l = l->nextSibling())
- l->clearClipRects();
+ l->clearClipRectsIncludingDescendants();
}
-void RenderLayer::clearClipRect()
+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;
+#endif
}
}
@@ -2425,7 +2464,7 @@ void RenderLayer::collectLayers(Vector<RenderLayer*>*& posBuffer, Vector<RenderL
void RenderLayer::repaintIncludingDescendants()
{
- m_object->repaint();
+ renderer()->repaint();
for (RenderLayer* curr = firstChild(); curr; curr = curr->nextSibling())
curr->repaintIncludingDescendants();
}
@@ -2439,7 +2478,7 @@ bool RenderLayer::shouldBeOverflowOnly() const
!isTransparent();
}
-void RenderLayer::styleChanged(RenderStyle::Diff, const RenderStyle* oldStyle)
+void RenderLayer::styleChanged(RenderStyle::Diff, const RenderStyle*)
{
bool isOverflowOnly = shouldBeOverflowOnly();
if (isOverflowOnly != m_isOverflowOnly) {
@@ -2450,7 +2489,7 @@ void RenderLayer::styleChanged(RenderStyle::Diff, const RenderStyle* oldStyle)
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();
@@ -2481,12 +2520,12 @@ void RenderLayer::styleChanged(RenderStyle::Diff, const RenderStyle* oldStyle)
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()->isElementNode() ? renderer()->node()->shadowAncestorNode()->renderer() : renderer();
+ RefPtr<RenderStyle> corner = renderer()->hasOverflowClip() ? actualRenderer->getUncachedPseudoStyle(RenderStyle::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) {
@@ -2497,12 +2536,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()->isElementNode() ? renderer()->node()->shadowAncestorNode()->renderer() : renderer();
+ RefPtr<RenderStyle> resizer = renderer()->hasOverflowClip() ? actualRenderer->getUncachedPseudoStyle(RenderStyle::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) {
diff --git a/WebCore/rendering/RenderLayer.h b/WebCore/rendering/RenderLayer.h
index f946b5f..54c15e9 100644
--- a/WebCore/rendering/RenderLayer.h
+++ b/WebCore/rendering/RenderLayer.h
@@ -45,18 +45,17 @@
#define RenderLayer_h
#include "ScrollbarClient.h"
-#include "RenderObject.h"
+#include "RenderBox.h"
#include "Timer.h"
#include <wtf/OwnPtr.h>
namespace WebCore {
-class AffineTransform;
+class TransformationMatrix;
class CachedResource;
class HitTestResult;
class RenderFrameSet;
class RenderMarquee;
-class RenderObject;
class RenderReplica;
class RenderScrollbarPart;
class RenderStyle;
@@ -69,6 +68,12 @@ struct HitTestRequest;
class ClipRects {
public:
+ ClipRects()
+ : m_refCnt(0)
+ , m_fixed(false)
+ {
+ }
+
ClipRects(const IntRect& r)
: m_overflowClipRect(r)
, m_fixedClipRect(r)
@@ -78,19 +83,34 @@ public:
{
}
- ClipRects(const IntRect& overflowRect, const IntRect& fixedRect, const IntRect& posRect, bool fixed)
- : m_overflowClipRect(overflowRect)
- , m_fixedClipRect(fixedRect)
- , m_posClipRect(posRect)
+ ClipRects(const ClipRects& other)
+ : m_overflowClipRect(other.overflowClipRect())
+ , m_fixedClipRect(other.fixedClipRect())
+ , m_posClipRect(other.posClipRect())
, m_refCnt(0)
- , m_fixed(fixed)
+ , m_fixed(other.fixed())
{
}
- const IntRect& overflowClipRect() { return m_overflowClipRect; }
- const IntRect& fixedClipRect() { return m_fixedClipRect; }
- const IntRect& posClipRect() { return m_posClipRect; }
+ void reset(const IntRect& r)
+ {
+ m_overflowClipRect = r;
+ m_fixedClipRect = r;
+ m_posClipRect = r;
+ m_fixed = false;
+ }
+
+ const IntRect& overflowClipRect() const { return m_overflowClipRect; }
+ void setOverflowClipRect(const IntRect& r) { m_overflowClipRect = r; }
+
+ const IntRect& fixedClipRect() const { return m_fixedClipRect; }
+ void setFixedClipRect(const IntRect&r) { m_fixedClipRect = r; }
+
+ const IntRect& posClipRect() const { return m_posClipRect; }
+ void setPosClipRect(const IntRect& r) { m_posClipRect = r; }
+
bool fixed() const { return m_fixed; }
+ void setFixed(bool fixed) { m_fixed = fixed; }
void ref() { m_refCnt++; }
void deref(RenderArena* renderArena) { if (--m_refCnt == 0) destroy(renderArena); }
@@ -102,6 +122,23 @@ public:
// Overridden to prevent the normal delete from being called.
void operator delete(void*, size_t);
+
+ bool operator==(const ClipRects& other) const
+ {
+ return m_overflowClipRect == other.overflowClipRect() &&
+ m_fixedClipRect == other.fixedClipRect() &&
+ m_posClipRect == other.posClipRect() &&
+ m_fixed == other.fixed();
+ }
+
+ ClipRects& operator=(const ClipRects& other)
+ {
+ m_overflowClipRect = other.overflowClipRect();
+ m_fixedClipRect = other.fixedClipRect();
+ m_posClipRect = other.posClipRect();
+ m_fixed = other.fixed();
+ return *this;
+ }
private:
// The normal operator new is disallowed on all render objects.
@@ -145,10 +182,10 @@ public:
static ScrollBehavior getPartialBehavior(const ScrollAlignment& s) { return s.m_rectPartial; }
static ScrollBehavior getHiddenBehavior(const ScrollAlignment& s) { return s.m_rectHidden; }
- RenderLayer(RenderObject*);
+ RenderLayer(RenderBox*);
~RenderLayer();
- RenderObject* renderer() const { return m_object; }
+ RenderBox* renderer() const { return m_renderer; }
RenderLayer* parent() const { return m_parent; }
RenderLayer* previousSibling() const { return m_previous; }
RenderLayer* nextSibling() const { return m_next; }
@@ -176,7 +213,7 @@ public:
RenderLayer* transparentAncestor();
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;
@@ -208,10 +245,13 @@ public:
// Scrolling methods for layers that can scroll their overflow.
void scrollByRecursively(int xDelta, int yDelta);
- void scrollOffset(int& x, int& y);
- void subtractScrollOffset(int& x, int& y);
+ void addScrolledContentOffset(int& x, int& y) const;
+ void subtractScrolledContentOffset(int& x, int& y) const;
+ IntSize scrolledContentOffset() const { return IntSize(scrollXOffset() + m_scrollLeftOverflow, scrollYOffset()); }
+
int scrollXOffset() const { return m_scrollX + m_scrollOriginX; }
int scrollYOffset() const { return m_scrollY; }
+
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); }
@@ -232,9 +272,9 @@ public:
int horizontalScrollbarHeight() const;
void positionOverflowControls(int tx, int ty);
- bool isPointInResizeControl(const IntPoint&);
+ bool isPointInResizeControl(const IntPoint& absolutePoint) const;
bool hitTestOverflowControls(HitTestResult&);
- IntSize offsetFromResizeCorner(const IntPoint&) const;
+ IntSize offsetFromResizeCorner(const IntPoint& absolutePoint) const;
void paintOverflowControls(GraphicsContext*, int tx, int ty, const IntRect& damageRect);
void paintScrollCorner(GraphicsContext*, int tx, int ty, const IntRect& damageRect);
@@ -254,10 +294,11 @@ public:
void updateTransform();
- void relativePositionOffset(int& relX, int& relY) { relX += m_relX; relY += m_relY; }
+ void relativePositionOffset(int& relX, int& relY) const { relX += m_relX; relY += m_relY; }
+ IntSize relativePositionOffset() const { return IntSize(m_relX, m_relY); }
+ void clearClipRectsIncludingDescendants();
void clearClipRects();
- void clearClipRect();
// Get the enclosing stacking context for this layer. A stacking context is a layer
// that has a non-auto z-index.
@@ -298,9 +339,15 @@ public:
// |rootLayer}. It also computes our background and foreground clip rects
// for painting/event handling.
void calculateRects(const RenderLayer* rootLayer, const IntRect& paintDirtyRect, IntRect& layerBounds,
- IntRect& backgroundRect, IntRect& foregroundRect, IntRect& outlineRect) const;
- void calculateClipRects(const RenderLayer* rootLayer);
+ IntRect& backgroundRect, IntRect& foregroundRect, IntRect& outlineRect, bool temporaryClipRects = false) const;
+
+ // Compute and cache clip rects computed with the given layer as the root
+ void updateClipRects(const RenderLayer* rootLayer);
+ // Compute and return the clip rects. If useCached is true, will used previously computed clip rects on ancestors
+ // (rather than computing them all from scratch up the parent chain).
+ void calculateClipRects(const RenderLayer* rootLayer, ClipRects&, bool useCached = false) const;
ClipRects* clipRects() const { return m_clipRects; }
+
IntRect childrenClipRect() const; // Returns the foreground clip rect of the layer in the document's coordinate space.
IntRect selfClipRect() const; // Returns the background clip rect of the layer in the document's coordinate space.
@@ -319,8 +366,8 @@ public:
void setStaticX(int staticX) { m_staticX = staticX; }
void setStaticY(int staticY) { m_staticY = staticY; }
- bool hasTransform() const { return m_object->hasTransform(); }
- AffineTransform* transform() const { return m_transform.get(); }
+ bool hasTransform() const { return renderer()->hasTransform(); }
+ TransformationMatrix* transform() const { return m_transform.get(); }
void destroy(RenderArena*);
@@ -345,7 +392,8 @@ private:
void collectLayers(Vector<RenderLayer*>*&, Vector<RenderLayer*>*&);
void paintLayer(RenderLayer* rootLayer, GraphicsContext*, const IntRect& paintDirtyRect,
- bool haveTransparency, PaintRestriction, RenderObject* paintingRoot, bool appliedTransform = false);
+ 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);
void computeScrollDimensions(bool* needHBar = 0, bool* needVBar = 0);
@@ -370,11 +418,14 @@ private:
RenderLayer* enclosingTransformedAncestor() const;
+ // Convert a point in absolute coords into layer coords, taking transforms into account
+ IntPoint absoluteToContents(const IntPoint&) const;
+
void updateScrollCornerStyle();
void updateResizerStyle();
protected:
- RenderObject* m_object;
+ RenderBox* m_renderer;
RenderLayer* m_parent;
RenderLayer* m_previous;
@@ -400,8 +451,8 @@ protected:
// Our scroll offsets if the view is scrolled.
int m_scrollX;
int m_scrollY;
- int m_scrollOriginX;
- int m_scrollLeftOverflow;
+ int m_scrollOriginX; // only non-zero for rtl content
+ int m_scrollLeftOverflow; // only non-zero for rtl content
// The width/height of our scrolled area.
int m_scrollWidth;
@@ -426,6 +477,9 @@ protected:
Vector<RenderLayer*>* m_overflowList;
ClipRects* m_clipRects; // Cached clip rects used when painting and hit testing.
+#ifndef NDEBUG
+ const RenderLayer* m_clipRectsRoot; // Root layer used to compute clip rects.
+#endif
bool m_scrollDimensionsDirty : 1;
bool m_zOrderListsDirty : 1;
@@ -453,7 +507,7 @@ protected:
int m_staticX;
int m_staticY;
- OwnPtr<AffineTransform> m_transform;
+ OwnPtr<TransformationMatrix> m_transform;
// May ultimately be extended to many replicas (with their own paint order).
RenderReplica* m_reflection;
diff --git a/WebCore/rendering/RenderLegend.cpp b/WebCore/rendering/RenderLegend.cpp
index b4cf291..1fac53f 100644
--- a/WebCore/rendering/RenderLegend.cpp
+++ b/WebCore/rendering/RenderLegend.cpp
@@ -26,11 +26,9 @@
#include "config.h"
#include "RenderLegend.h"
-#include "HTMLFormControlElement.h"
-
namespace WebCore {
-RenderLegend::RenderLegend(HTMLFormControlElement* element)
+RenderLegend::RenderLegend(Node* element)
: RenderBlock(element)
{
}
diff --git a/WebCore/rendering/RenderLegend.h b/WebCore/rendering/RenderLegend.h
index fa8b249..649f132 100644
--- a/WebCore/rendering/RenderLegend.h
+++ b/WebCore/rendering/RenderLegend.h
@@ -30,11 +30,9 @@
namespace WebCore {
- class HTMLFormControlElement;
-
class RenderLegend : public RenderBlock {
public:
- RenderLegend(HTMLFormControlElement*);
+ RenderLegend(Node*);
virtual const char* renderName() const { return "RenderLegend"; }
};
diff --git a/WebCore/rendering/RenderListBox.cpp b/WebCore/rendering/RenderListBox.cpp
index c435ff4..3dddc13 100644
--- a/WebCore/rendering/RenderListBox.cpp
+++ b/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,10 +42,10 @@
#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"
@@ -103,10 +104,10 @@ void RenderListBox::updateFromElement()
HTMLElement* 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());
@@ -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();
@@ -237,7 +238,7 @@ void RenderListBox::calcHeight()
}
}
-int RenderListBox::baselinePosition(bool b, bool isRootLineBox) const
+int RenderListBox::baselinePosition(bool, bool) const
{
return height() + marginTop() + marginBottom() - baselineAdjustment;
}
@@ -295,13 +296,14 @@ void RenderListBox::paintItemForeground(PaintInfo& paintInfo, int tx, int ty, in
HTMLSelectElement* select = static_cast<HTMLSelectElement*>(node());
const Vector<HTMLElement*>& listItems = select->listItems();
HTMLElement* 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
@@ -328,15 +330,14 @@ void RenderListBox::paintItemForeground(PaintInfo& paintInfo, int tx, int ty, in
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)
@@ -344,9 +345,10 @@ void RenderListBox::paintItemBackground(PaintInfo& paintInfo, int tx, int ty, in
HTMLSelectElement* select = static_cast<HTMLSelectElement*>(node());
const Vector<HTMLElement*>& listItems = select->listItems();
HTMLElement* 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());
@@ -401,9 +403,8 @@ void RenderListBox::panScroll(const IntPoint& panStartMousePosition)
const int iconRadius = 7;
const int speedReducer = 4;
- int offsetX;
- int offsetY;
- absolutePosition(offsetX, offsetY);
+ // FIXME: This doesn't work correctly with transforms.
+ FloatPoint absOffset = localToAbsolute();
IntPoint currentMousePosition = document()->frame()->eventHandler()->currentMousePosition();
// We need to check if the current mouse position is out of the window. When the mouse is out of the window, the position is incoherent
@@ -423,7 +424,7 @@ void RenderListBox::panScroll(const IntPoint& panStartMousePosition)
if (yDelta > 0)
//offsetY = view()->viewHeight();
- offsetY += listHeight();
+ absOffset.move(0, listHeight());
else if (yDelta < 0)
yDelta--;
@@ -431,7 +432,7 @@ void RenderListBox::panScroll(const IntPoint& panStartMousePosition)
yDelta /= speedReducer;
IntPoint scrollPoint(0,0);
- scrollPoint.setY(offsetY + yDelta);
+ scrollPoint.setY(absOffset.y() + yDelta);
int newOffset = scrollToward(scrollPoint);
if (newOffset < 0)
return;
@@ -444,11 +445,10 @@ void RenderListBox::panScroll(const IntPoint& panStartMousePosition)
int RenderListBox::scrollToward(const IntPoint& destination)
{
- int rx = 0;
- int ry = 0;
- absolutePosition(rx, ry);
- int offsetX = destination.x() - rx;
- int offsetY = destination.y() - ry;
+ // FIXME: This doesn't work correctly with transforms.
+ FloatPoint absPos = localToAbsolute();
+ int offsetX = destination.x() - absPos.x();
+ int offsetY = destination.y() - absPos.y();
int rows = numVisibleItems();
int offset = m_indexOffset;
@@ -581,7 +581,7 @@ void RenderListBox::setScrollTop(int newTop)
IntRect RenderListBox::controlClipRect(int tx, int ty) const
{
- IntRect clipRect = contentBox();
+ IntRect clipRect = contentBoxRect();
clipRect.move(tx, ty);
return clipRect;
}
@@ -599,13 +599,6 @@ 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;
diff --git a/WebCore/rendering/RenderListBox.h b/WebCore/rendering/RenderListBox.h
index ccc6847..b9cfcb1 100644
--- a/WebCore/rendering/RenderListBox.h
+++ b/WebCore/rendering/RenderListBox.h
@@ -58,7 +58,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;
diff --git a/WebCore/rendering/RenderListItem.cpp b/WebCore/rendering/RenderListItem.cpp
index b69612e..47158b6 100644
--- a/WebCore/rendering/RenderListItem.cpp
+++ b/WebCore/rendering/RenderListItem.cpp
@@ -31,6 +31,7 @@
#include "HTMLOListElement.h"
#include "RenderListMarker.h"
#include "RenderView.h"
+#include <wtf/StdLibExtras.h>
using namespace std;
@@ -143,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())
@@ -234,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;
@@ -266,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());
+ markerRect.move(-o->x(), -o->y());
} while (o != this);
}
}
@@ -279,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);
@@ -289,7 +290,7 @@ const String& RenderListItem::markerText() const
{
if (m_marker)
return m_marker->text();
- static String staticNullString;
+ DEFINE_STATIC_LOCAL(String, staticNullString, ());
return staticNullString;
}
diff --git a/WebCore/rendering/RenderListMarker.cpp b/WebCore/rendering/RenderListMarker.cpp
index b2937b9..340db50 100644
--- a/WebCore/rendering/RenderListMarker.cpp
+++ b/WebCore/rendering/RenderListMarker.cpp
@@ -506,9 +506,9 @@ void RenderListMarker::styleDidChange(RenderStyle::Diff diff, const RenderStyle*
}
}
-InlineBox* RenderListMarker::createInlineBox(bool, bool isRootLineBox, bool)
+InlineBox* RenderListMarker::createInlineBox(bool, bool unusedIsRootLineBox, bool)
{
- ASSERT(!isRootLineBox);
+ ASSERT_UNUSED(unusedIsRootLineBox, !unusedIsRootLineBox);
ListMarkerBox* box = new (renderArena()) ListMarkerBox(this);
m_inlineBoxWrapper = box;
return box;
@@ -530,7 +530,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 +539,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)
@@ -619,15 +618,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 +636,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;
@@ -656,13 +655,13 @@ void RenderListMarker::layout()
setNeedsLayout(false);
}
-void RenderListMarker::imageChanged(WrappedImagePtr o)
+void RenderListMarker::imageChanged(WrappedImagePtr o, const IntRect*)
{
// A list marker can't have a background or border image, so no need to call the base class method.
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 +829,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 +839,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 +866,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();
@@ -890,14 +889,13 @@ 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 {
- int absx, absy;
- absolutePosition(absx, absy);
- rect.move(absx, absy);
+ FloatPoint absPos = localToAbsolute();
+ rect.move(absPos.x(), absPos.y());
}
return rect;
diff --git a/WebCore/rendering/RenderListMarker.h b/WebCore/rendering/RenderListMarker.h
index 3c5224c..738427c 100644
--- a/WebCore/rendering/RenderListMarker.h
+++ b/WebCore/rendering/RenderListMarker.h
@@ -47,7 +47,7 @@ public:
virtual void layout();
virtual void calcPrefWidths();
- virtual void imageChanged(WrappedImagePtr);
+ virtual void imageChanged(WrappedImagePtr, const IntRect* = 0);
virtual InlineBox* createInlineBox(bool, bool, bool);
diff --git a/WebCore/rendering/RenderMarquee.cpp b/WebCore/rendering/RenderMarquee.cpp
index 96d26ea..2b4dcfd 100644
--- a/WebCore/rendering/RenderMarquee.cpp
+++ b/WebCore/rendering/RenderMarquee.cpp
@@ -105,7 +105,7 @@ bool RenderMarquee::isHorizontal() const
int RenderMarquee::computePosition(EMarqueeDirection dir, bool stopAtContentEdge)
{
- RenderObject* o = m_layer->renderer();
+ RenderBox* o = m_layer->renderer();
RenderStyle* s = o->style();
if (isHorizontal()) {
bool ltr = s->direction() == LTR;
diff --git a/WebCore/rendering/RenderMedia.cpp b/WebCore/rendering/RenderMedia.cpp
index 4953a35..80bf586 100644
--- a/WebCore/rendering/RenderMedia.cpp
+++ b/WebCore/rendering/RenderMedia.cpp
@@ -35,11 +35,12 @@
#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;
@@ -81,6 +82,11 @@ 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();
}
@@ -99,16 +105,16 @@ MediaPlayer* RenderMedia::player() const
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);
@@ -145,7 +151,7 @@ void RenderMedia::createPanel()
{
ASSERT(!m_panel);
RenderStyle* style = getCachedPseudoStyle(RenderStyle::MEDIA_CONTROLS_PANEL);
- m_panel = new HTMLDivElement(document());
+ m_panel = new HTMLDivElement(HTMLNames::divTag, document());
RenderObject* renderer = m_panel->createRenderer(renderArena(), style);
if (renderer) {
m_panel->setRenderer(renderer);
@@ -185,27 +191,41 @@ void RenderMedia::createSeekForwardButton()
m_seekForwardButton->attachToParent(m_panel.get());
}
+void RenderMedia::createTimelineContainer()
+{
+ ASSERT(!m_timelineContainer);
+ RenderStyle* style = getCachedPseudoStyle(RenderStyle::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->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(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()
@@ -229,10 +249,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;
}
@@ -247,17 +269,23 @@ void RenderMedia::updateControls()
createPanel();
createMuteButton();
createPlayButton();
+ createTimelineContainer();
createTimeline();
createSeekBackButton();
createSeekForwardButton();
- createTimeDisplay();
+ createCurrentTimeDisplay();
+ createTimeRemainingDisplay();
createFullscreenButton();
}
-
- if (media->paused() || media->ended() || media->networkState() < HTMLMediaElement::LOADED_METADATA)
- m_timeUpdateTimer.stop();
- else
+
+ if (media->paused() || media->ended() || media->networkState() < HTMLMediaElement::LOADED_METADATA) {
+ 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();
@@ -286,30 +314,45 @@ 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())
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);
if (visible == (m_opacityAnimationTo > 0))
@@ -319,7 +362,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;
}
@@ -355,23 +398,28 @@ void RenderMedia::opacityAnimationTimerFired(Timer<RenderMedia>*)
float opacity = narrowPrecisionToFloat(m_opacityAnimationFrom + (m_opacityAnimationTo - m_opacityAnimationFrom) * time / cOpacityAnimationDuration);
changeOpacity(m_panel.get(), opacity);
}
-
+
void RenderMedia::forwardEvent(Event* event)
{
if (event->isMouseEvent() && m_controlsShadowRoot) {
MouseEvent* mouseEvent = static_cast<MouseEvent*>(event);
IntPoint point(mouseEvent->pageX(), mouseEvent->pageY());
- if (m_muteButton && m_muteButton->renderer() && m_muteButton->renderer()->absoluteBoundingBoxRect().contains(point))
+ if (m_muteButton && m_muteButton->hitTest(point))
m_muteButton->defaultEventHandler(event);
- if (m_playButton && m_playButton->renderer() && m_playButton->renderer()->absoluteBoundingBoxRect().contains(point))
+
+ if (m_playButton && m_playButton->hitTest(point))
m_playButton->defaultEventHandler(event);
- if (m_seekBackButton && m_seekBackButton->renderer() && m_seekBackButton->renderer()->absoluteBoundingBoxRect().contains(point))
+
+ if (m_seekBackButton && m_seekBackButton->hitTest(point))
m_seekBackButton->defaultEventHandler(event);
- if (m_seekForwardButton && m_seekForwardButton->renderer() && m_seekForwardButton->renderer()->absoluteBoundingBoxRect().contains(point))
+
+ if (m_seekForwardButton && m_seekForwardButton->hitTest(point))
m_seekForwardButton->defaultEventHandler(event);
- if (m_timeline && m_timeline->renderer() && m_timeline->renderer()->absoluteBoundingBoxRect().contains(point))
+
+ if (m_timeline && m_timeline->hitTest(point))
m_timeline->defaultEventHandler(event);
- if (m_fullscreenButton && m_fullscreenButton->renderer() && m_fullscreenButton->renderer()->absoluteBoundingBoxRect().contains(point))
+
+ if (m_fullscreenButton && m_fullscreenButton->hitTest(point))
m_fullscreenButton->defaultEventHandler(event);
if (event->type() == eventNames().mouseoverEvent) {
@@ -392,7 +440,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->renderer()->lowestPosition(includeOverflowInterior, includeSelf));
}
int RenderMedia::rightmostPosition(bool includeOverflowInterior, bool includeSelf) const
@@ -401,7 +449,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->renderer()->rightmostPosition(includeOverflowInterior, includeSelf));
}
int RenderMedia::leftmostPosition(bool includeOverflowInterior, bool includeSelf) const
@@ -410,7 +458,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->renderer()->leftmostPosition(includeOverflowInterior, includeSelf));
}
} // namespace WebCore
diff --git a/WebCore/rendering/RenderMedia.h b/WebCore/rendering/RenderMedia.h
index 8f48caf..a4670e9 100644
--- a/WebCore/rendering/RenderMedia.h
+++ b/WebCore/rendering/RenderMedia.h
@@ -40,6 +40,7 @@ class MediaControlPlayButtonElement;
class MediaControlSeekButtonElement;
class MediaControlTimelineElement;
class MediaControlFullscreenButtonElement;
+class MediaTimeDisplayElement;
class MediaPlayer;
class RenderMedia : public RenderReplaced {
@@ -66,6 +67,7 @@ public:
void updateFromElement();
void updatePlayer();
void updateControls();
+ void updateTimeDisplay();
void forwardEvent(Event*);
@@ -75,17 +77,19 @@ 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);
@@ -99,7 +103,9 @@ private:
RefPtr<MediaControlSeekButtonElement> m_seekForwardButton;
RefPtr<MediaControlTimelineElement> m_timeline;
RefPtr<MediaControlFullscreenButtonElement> m_fullscreenButton;
- RefPtr<HTMLElement> m_timeDisplay;
+ RefPtr<HTMLElement> m_timelineContainer;
+ RefPtr<MediaTimeDisplayElement> m_currentTimeDisplay;
+ RefPtr<MediaTimeDisplayElement> m_timeRemainingDisplay;
EventTargetNode* m_lastUnderNode;
EventTargetNode* m_nodeUnderMouse;
diff --git a/WebCore/rendering/RenderMenuList.cpp b/WebCore/rendering/RenderMenuList.cpp
index 469a73d..71e9e15 100644
--- a/WebCore/rendering/RenderMenuList.cpp
+++ b/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 <math.h>
using namespace std;
@@ -141,11 +138,13 @@ void RenderMenuList::updateOptionsWidth()
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();
- if (!text.isEmpty())
- maxOptionWidth = max(maxOptionWidth, style()->font().floatWidth(text));
- }
+ OptionElement* optionElement = toOptionElement(element);
+ if (!optionElement)
+ continue;
+
+ String text = optionElement->textIndentedToRespectGroupLabel();
+ if (!text.isEmpty())
+ maxOptionWidth = max(maxOptionWidth, style()->font().floatWidth(text));
}
int width = static_cast<int>(ceilf(maxOptionWidth));
@@ -178,10 +177,10 @@ void RenderMenuList::setTextFromOption(int optionIndex)
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 +223,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());
@@ -275,7 +274,13 @@ void RenderMenuList::showPopup()
m_popup = PopupMenu::create(this);
HTMLSelectElement* select = static_cast<HTMLSelectElement*>(node());
m_popupIsVisible = true;
- m_popup->show(absoluteBoundingBoxRect(), document()->view(),
+
+ // Compute the top left taking transforms into account, but use
+ // the actual width of the element to size the popup.
+ FloatPoint absTopLeft = localToAbsolute(FloatPoint(), false, true);
+ IntRect absBounds = absoluteBoundingBoxRect();
+ absBounds.setLocation(roundedIntPoint(absTopLeft));
+ m_popup->show(absBounds, document()->view(),
select->optionToListIndex(select->selectedIndex()));
}
@@ -296,10 +301,10 @@ 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();
+ if (OptionGroupElement* optionGroupElement = toOptionGroupElement(element))
+ return optionGroupElement->groupLabelText();
+ else if (OptionElement* optionElement = toOptionElement(element))
+ return optionElement->textIndentedToRespectGroupLabel();
return String();
}
@@ -418,7 +423,9 @@ 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();
+ if (OptionElement* optionElement = toOptionElement(element))
+ return optionElement->selected();
+ return false;
}
void RenderMenuList::setTextFromItem(unsigned listIndex)
diff --git a/WebCore/rendering/RenderMenuList.h b/WebCore/rendering/RenderMenuList.h
index f31ef32..a7530fa 100644
--- a/WebCore/rendering/RenderMenuList.h
+++ b/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
@@ -36,6 +36,7 @@ namespace WebCore {
class HTMLSelectElement;
class PopupMenu;
+class RenderText;
class RenderMenuList : public RenderFlexibleBox, private PopupMenuClient {
public:
@@ -44,6 +45,7 @@ public:
HTMLSelectElement* selectElement();
+private:
virtual bool isMenuList() const { return true; }
virtual void addChild(RenderObject* newChild, RenderObject* beforeChild = 0);
@@ -60,6 +62,7 @@ public:
virtual void calcPrefWidths();
+public:
bool popupIsVisible() const { return m_popupIsVisible; }
void showPopup();
void hidePopup();
@@ -68,10 +71,9 @@ public:
String text() const;
-protected:
+private:
virtual void styleDidChange(RenderStyle::Diff, const RenderStyle* oldStyle);
-private:
// PopupMenuClient methods
virtual String itemText(unsigned listIndex) const;
virtual bool itemIsEnabled(unsigned listIndex) const;
diff --git a/WebCore/rendering/RenderObject.cpp b/WebCore/rendering/RenderObject.cpp
index 56fb7df..ea84f33 100644
--- a/WebCore/rendering/RenderObject.cpp
+++ b/WebCore/rendering/RenderObject.cpp
@@ -26,26 +26,13 @@
#include "RenderObject.h"
#include "AXObjectCache.h"
-#include "AffineTransform.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 "Frame.h"
+#include "FloatQuad.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,11 +42,8 @@
#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 <algorithm>
#ifdef ANDROID_LAYOUT
#include "Settings.h"
@@ -67,6 +51,10 @@
#include <stdio.h>
#include <wtf/RefCountedLeakCounter.h>
+#if ENABLE(WML)
+#include "WMLNames.h"
+#endif
+
using namespace std;
namespace WebCore {
@@ -174,6 +162,7 @@ RenderObject::RenderObject(Node* node)
, m_next(0)
#ifndef NDEBUG
, m_hasAXObject(false)
+ , m_setNeedsLayoutForbidden(false)
#endif
, m_verticalPosition(PositionUndefined)
, m_needsLayout(false)
@@ -187,6 +176,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)
@@ -241,11 +231,6 @@ bool RenderObject::canHaveChildren() const
return false;
}
-RenderFlow* RenderObject::continuation() const
-{
- return 0;
-}
-
bool RenderObject::isInlineContinuation() const
{
return false;
@@ -321,9 +306,9 @@ RenderObject* RenderObject::nextInPreOrderAfterChildren(RenderObject* stayWithin
if (!(o = nextSibling())) {
o = parent();
while (o && !o->nextSibling()) {
- o = o->parent();
if (o == stayWithin)
return 0;
+ o = o->parent();
}
if (o)
o = o->nextSibling();
@@ -355,7 +340,7 @@ bool RenderObject::isEditable() const
{
RenderText* textRenderer = 0;
if (isText())
- textRenderer = static_cast<RenderText*>(const_cast<RenderObject*>(this));
+ textRenderer = toRenderText(const_cast<RenderObject*>(this));
return style()->visibility() == VISIBLE &&
element() && element()->isContentEditable() &&
@@ -402,7 +387,7 @@ static void addLayers(RenderObject* obj, RenderLayer* parentLayer, RenderObject*
beforeChild = newObject->parent()->findNextLayer(parentLayer, newObject);
newObject = 0;
}
- parentLayer->addChild(obj->layer(), beforeChild);
+ parentLayer->addChild(toRenderBox(obj)->layer(), beforeChild);
return;
}
@@ -426,7 +411,7 @@ void RenderObject::removeLayers(RenderLayer* parentLayer)
return;
if (hasLayer()) {
- parentLayer->removeChild(layer());
+ parentLayer->removeChild(toRenderBox(this)->layer());
return;
}
@@ -440,9 +425,10 @@ void RenderObject::moveLayers(RenderLayer* oldParent, RenderLayer* newParent)
return;
if (hasLayer()) {
+ RenderLayer* layer = toRenderBox(this)->layer();
if (oldParent)
- oldParent->removeChild(layer());
- newParent->addChild(layer());
+ oldParent->removeChild(layer);
+ newParent->addChild(layer);
return;
}
@@ -458,7 +444,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() ? toRenderBox(this)->layer() : 0;
if (ourLayer && ourLayer->parent() == parentLayer)
return ourLayer;
@@ -490,7 +476,7 @@ RenderLayer* RenderObject::enclosingLayer() const
{
const RenderObject* curr = this;
while (curr) {
- RenderLayer* layer = curr->layer();
+ RenderLayer* layer = curr->hasLayer() ? toRenderBox(curr)->layer() : 0;
if (layer)
return layer;
curr = curr->parent();
@@ -498,168 +484,22 @@ RenderLayer* RenderObject::enclosingLayer() const
return 0;
}
-bool RenderObject::requiresLayer()
+RenderBox* RenderObject::enclosingBox() 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;
-#ifdef ANDROID_FIX
- // This is to fix https://bugs.webkit.org/show_bug.cgi?id=23178.
- int y = yPos() - borderTopExtra() + offsetPar->borderTopExtra() - offsetPar->borderTop();
-#else
- int y = yPos() - borderTopExtra() - offsetPar->borderTop();
-#endif
- 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();
- }
- return y;
-}
-
-RenderObject* RenderObject::offsetParent() 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()))) {
- if (!skipTables && curr->element() && (curr->element()->hasTagName(tableTag) ||
- curr->element()->hasTagName(tdTag) || curr->element()->hasTagName(thTag)))
- 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 scrollToAnchor) const
-{
- if (!layer())
- return false;
-
- return (hasOverflowClip() && (scrollsOverflow() || (node() && node()->isContentEditable()))) || (node() && node()->isDocumentNode());
-}
-
-void RenderObject::autoscroll()
-{
- layer()->autoscroll();
+ ASSERT_NOT_REACHED();
+ return 0;
}
-void RenderObject::panScroll(const IntPoint& source)
+RenderBlock* RenderObject::firstLineBlock() const
{
- layer()->panScrollFromPoint(source);
+ return 0;
}
bool RenderObject::hasStaticX() const
@@ -672,10 +512,6 @@ bool RenderObject::hasStaticY() const
return (style()->top().isAuto() && style()->bottom().isAuto()) || style()->top().isStatic();
}
-void RenderObject::markAllDescendantsWithFloatsForLayout(RenderObject*)
-{
-}
-
void RenderObject::setPrefWidthsDirty(bool b, bool markParents)
{
bool alreadyDirty = m_prefWidthsDirty;
@@ -704,11 +540,12 @@ 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())
- layer()->setNeedsFullRepaint();
+ toRenderBox(this)->layer()->setNeedsFullRepaint();
}
} else {
m_everHadLayout = true;
@@ -723,6 +560,7 @@ void RenderObject::setChildNeedsLayout(bool b, bool markParents)
bool alreadyNeededLayout = m_normalChildNeedsLayout;
m_normalChildNeedsLayout = b;
if (b) {
+ ASSERT(!isSetNeedsLayoutForbidden());
if (!alreadyNeededLayout && markParents)
markContainingBlocksForLayout();
} else {
@@ -739,7 +577,7 @@ void RenderObject::setNeedsPositionedMovementLayout()
if (!alreadyNeededLayout) {
markContainingBlocksForLayout();
if (hasLayer())
- layer()->setNeedsFullRepaint();
+ toRenderBox(this)->layer()->setNeedsFullRepaint();
}
}
@@ -776,10 +614,12 @@ void RenderObject::markContainingBlocksForLayout(bool scheduleRelayout, RenderOb
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)
@@ -1693,59 +1533,6 @@ void RenderObject::paintBoxShadow(GraphicsContext* context, int tx, int ty, int
}
}
-void RenderObject::addLineBoxRects(Vector<IntRect>&, unsigned startOffset, unsigned endOffset, bool useSelectionHeight)
-{
-}
-
-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()));
-}
-
-IntRect RenderObject::absoluteBoundingBoxRect()
-{
- int x, y;
- absolutePosition(x, y);
- Vector<IntRect> rects;
- absoluteRects(rects, x, y);
-
- size_t n = rects.size();
- if (!n)
- return IntRect();
-
- IntRect result = rects[0];
- for (size_t i = 1; i < n; ++i)
- result.unite(rects[i]);
- return result;
-}
-
-void RenderObject::addAbsoluteRectForLayer(IntRect& result)
-{
- if (hasLayer())
- result.unite(absoluteBoundingBoxRect());
- for (RenderObject* current = firstChild(); current; current = current->nextSibling())
- current->addAbsoluteRectForLayer(result);
-}
-
-IntRect RenderObject::paintingRootRect(IntRect& topLevelRect)
-{
- IntRect result = absoluteBoundingBoxRect();
- topLevelRect = result;
- for (RenderObject* current = firstChild(); current; current = current->nextSibling())
- current->addAbsoluteRectForLayer(result);
- return result;
-}
-
void RenderObject::addPDFURLRect(GraphicsContext* context, const IntRect& rect)
{
if (rect.isEmpty())
@@ -1759,28 +1546,12 @@ void RenderObject::addPDFURLRect(GraphicsContext* context, const IntRect& rect)
context->setURLForRect(node->document()->completeURL(href), rect);
}
-
-void RenderObject::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 (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)
{
if (!hasOutline())
return;
int ow = style->outlineWidth();
-
EBorderStyle os = style->outlineStyle();
Color oc = style->outlineColor();
@@ -1826,10 +1597,67 @@ void RenderObject::paintOutline(GraphicsContext* graphicsContext, int tx, int ty
BSBottom, Color(oc), style->color(), os, ow, ow);
}
+void RenderObject::addLineBoxRects(Vector<IntRect>&, unsigned, unsigned, bool)
+{
+}
+
+IntRect RenderObject::absoluteBoundingBoxRect(bool useTransforms)
+{
+ if (useTransforms) {
+ Vector<FloatQuad> quads;
+ absoluteQuads(quads);
+
+ size_t n = quads.size();
+ if (!n)
+ return IntRect();
+
+ IntRect result = quads[0].enclosingBoundingBox();
+ for (size_t i = 1; i < n; ++i)
+ result.unite(quads[i].enclosingBoundingBox());
+ return result;
+ }
+
+ FloatPoint absPos = localToAbsolute();
+ Vector<IntRect> rects;
+ absoluteRects(rects, absPos.x(), absPos.y());
+
+ size_t n = rects.size();
+ if (!n)
+ return IntRect();
+
+ IntRect result = rects[0];
+ for (size_t i = 1; i < n; ++i)
+ result.unite(rects[i]);
+ return result;
+}
+
+void RenderObject::addAbsoluteRectForLayer(IntRect& result)
+{
+ if (hasLayer())
+ result.unite(absoluteBoundingBoxRect());
+ for (RenderObject* current = firstChild(); current; current = current->nextSibling())
+ current->addAbsoluteRectForLayer(result);
+}
+
+IntRect RenderObject::paintingRootRect(IntRect& topLevelRect)
+{
+ IntRect result = absoluteBoundingBoxRect();
+ topLevelRect = result;
+ for (RenderObject* current = firstChild(); current; current = current->nextSibling())
+ current->addAbsoluteRectForLayer(result);
+ return result;
+}
+
void RenderObject::paint(PaintInfo& /*paintInfo*/, int /*tx*/, int /*ty*/)
{
}
+RenderBox* RenderObject::containerForRepaint() const
+{
+ // For now, all repaints are root-relative.
+ return 0;
+}
+
void RenderObject::repaint(bool immediate)
{
// Can't use view(), since we might be unrooted.
@@ -1838,9 +1666,11 @@ void RenderObject::repaint(bool immediate)
o = o->parent();
if (!o->isRenderView())
return;
+
RenderView* view = static_cast<RenderView*>(o);
if (view->printing())
return; // Don't repaint if we're printing.
+
view->repaintViewRectangle(absoluteClippedOverflowRect(), immediate);
}
@@ -1852,11 +1682,17 @@ void RenderObject::repaintRectangle(const IntRect& r, bool immediate)
o = o->parent();
if (!o->isRenderView())
return;
+
RenderView* view = static_cast<RenderView*>(o);
if (view->printing())
return; // Don't repaint if we're printing.
+
IntRect absRect(r);
+
+ // FIXME: layoutDelta needs to be applied in parts before/after transforms and
+ // repaint containers. https://bugs.webkit.org/show_bug.cgi?id=23308
absRect.move(view->layoutDelta());
+
computeAbsoluteRepaintRect(absRect);
view->repaintViewRectangle(absRect, immediate);
}
@@ -1875,7 +1711,7 @@ bool RenderObject::repaintAfterLayoutIfNeeded(const IntRect& oldBounds, const In
if (!fullRepaint && style()->borderFit() == BorderFitLines)
fullRepaint = true;
if (!fullRepaint) {
- newOutlineBox = absoluteOutlineBox();
+ newOutlineBox = absoluteOutlineBounds();
if (newOutlineBox.location() != oldOutlineBox.location() || (mustRepaintBackgroundOrBorder() && (newBounds != oldBounds || newOutlineBox != oldOutlineBox)))
fullRepaint = true;
}
@@ -1918,7 +1754,8 @@ bool RenderObject::repaintAfterLayoutIfNeeded(const IntRect& oldBounds, const In
// 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();
+ RenderFlow* continuation = virtualContinuation();
+ RenderStyle* outlineStyle = !isInline() && continuation ? continuation->style() : style();
int ow = outlineStyle->outlineSize();
ShadowData* boxShadow = style()->boxShadow();
int width = abs(newOutlineBox.width() - oldOutlineBox.width());
@@ -1927,7 +1764,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,
@@ -1944,7 +1782,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()),
@@ -1958,11 +1797,11 @@ bool RenderObject::repaintAfterLayoutIfNeeded(const IntRect& oldBounds, const In
return false;
}
-void RenderObject::repaintDuringLayoutIfMoved(const IntRect& rect)
+void RenderObject::repaintDuringLayoutIfMoved(const IntRect&)
{
}
-void RenderObject::repaintOverhangingFloats(bool paintAllDescendants)
+void RenderObject::repaintOverhangingFloats(bool)
{
}
@@ -1974,33 +1813,36 @@ bool RenderObject::checkForRepaintDuringLayout() const
return !document()->view()->needsFullRepaint() && !hasLayer();
}
-IntRect RenderObject::getAbsoluteRepaintRectWithOutline(int ow)
+IntRect RenderObject::rectWithOutlineForRepaint(RenderBox* repaintContainer, int outlineWidth)
{
- IntRect r(absoluteClippedOverflowRect());
- r.inflate(ow);
+ IntRect r(clippedOverflowRectForRepaint(repaintContainer));
+ r.inflate(outlineWidth);
- if (continuation() && !isInline())
- r.inflateY(collapsedMarginTop());
+ if (virtualContinuation() && !isInline())
+ r.inflateY(toRenderBox(this)->collapsedMarginTop());
- if (isInlineFlow()) {
+ if (isRenderInline()) {
for (RenderObject* curr = firstChild(); curr; curr = curr->nextSibling()) {
if (!curr->isText())
- r.unite(curr->getAbsoluteRepaintRectWithOutline(ow));
+ r.unite(curr->rectWithOutlineForRepaint(repaintContainer, outlineWidth));
}
}
return r;
}
-IntRect RenderObject::absoluteClippedOverflowRect()
+IntRect RenderObject::clippedOverflowRectForRepaint(RenderBox* repaintContainer)
{
if (parent())
- return parent()->absoluteClippedOverflowRect();
+ return parent()->clippedOverflowRectForRepaint(repaintContainer);
return IntRect();
}
-void RenderObject::computeAbsoluteRepaintRect(IntRect& rect, bool fixed)
+void RenderObject::computeRectForRepaint(IntRect& rect, RenderBox* repaintContainer, bool fixed)
{
+ if (repaintContainer == this)
+ return;
+
if (RenderObject* o = parent()) {
if (o->isBlockFlow()) {
RenderBlock* cb = static_cast<RenderBlock*>(o);
@@ -2012,21 +1854,23 @@ 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()->subtractScrollOffset(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(rect, repaintContainer, fixed);
}
}
-void RenderObject::dirtyLinesFromChangedChild(RenderObject* child)
+void RenderObject::dirtyLinesFromChangedChild(RenderObject*)
{
}
@@ -2068,8 +1912,8 @@ Color RenderObject::selectionForegroundColor() const
color = pseudoStyle->color();
} else
color = document()->frame()->selection()->isFocusedAndActive() ?
- theme()->platformActiveSelectionForegroundColor() :
- theme()->platformInactiveSelectionForegroundColor();
+ theme()->activeSelectionForegroundColor() :
+ theme()->inactiveSelectionForegroundColor();
return color;
}
@@ -2138,7 +1982,7 @@ void RenderObject::handleDynamicFloatPositionChange()
RenderInline* parentInline = static_cast<RenderInline*>(parent());
RenderBlock* newBox = parentInline->createAnonymousBlock();
- RenderFlow* oldContinuation = parent()->continuation();
+ RenderFlow* oldContinuation = parentInline->continuation();
parentInline->setContinuation(newBox);
RenderObject* beforeChild = nextSibling();
@@ -2213,15 +2057,7 @@ void RenderObject::styleWillChange(RenderStyle::Diff diff, const RenderStyle* ne
document()->setDashboardRegionsDirty(true);
#endif
- 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)
@@ -2235,62 +2071,8 @@ void RenderObject::styleWillChange(RenderStyle::Diff diff, const RenderStyle* ne
}
}
- // 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()->clearClipRects();
- } else if (diff == RenderStyle::Repaint || newStyle->outlineSize() < m_style->outlineSize())
- repaint();
- }
-
- // When a layout hint happens, we go ahead and do a repaint of the layer, since the layer could
- // end up being destroyed.
- if (diff == RenderStyle::Layout && hasLayer() &&
- (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()))
- layer()->repaintIncludingDescendants();
-
- // 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 == RenderStyle::Repaint || 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.
@@ -2302,7 +2084,7 @@ void RenderObject::styleWillChange(RenderStyle::Diff diff, const RenderStyle* ne
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) {
@@ -2331,22 +2113,21 @@ void RenderObject::styleWillChange(RenderStyle::Diff diff, const RenderStyle* ne
}
}
-void RenderObject::styleDidChange(RenderStyle::Diff diff, const RenderStyle* oldStyle)
+void RenderObject::styleDidChange(RenderStyle::Diff 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 == RenderStyle::Layout)
setNeedsLayoutAndPrefWidthsRecalc();
- else if (diff == RenderStyle::LayoutPositionedMovementOnly && m_parent && !isText())
+ else if (diff == RenderStyle::LayoutPositionedMovementOnly)
setNeedsPositionedMovementLayout();
- else if (m_parent && !isText() && (diff == RenderStyle::RepaintLayer || diff == RenderStyle::Repaint))
+ else if (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();
@@ -2380,87 +2161,63 @@ IntRect RenderObject::viewRect() const
return view()->viewRect();
}
-bool RenderObject::absolutePosition(int& xPos, int& yPos, bool f) const
+FloatPoint RenderObject::localToAbsolute(FloatPoint localPoint, bool fixed, bool useTransforms) const
{
RenderObject* o = parent();
if (o) {
- o->absolutePosition(xPos, yPos, f);
- yPos += o->borderTopExtra();
if (o->hasOverflowClip())
- o->layer()->subtractScrollOffset(xPos, yPos);
- return true;
- } else {
- xPos = yPos = 0;
- return false;
+ localPoint -= toRenderBox(o)->layer()->scrolledContentOffset();
+ return o->localToAbsolute(localPoint, fixed, useTransforms);
}
-}
-
-IntRect RenderObject::caretRect(InlineBox* inlineBox, int caretOffset, int* extraWidthToEndOfLine)
-{
- if (extraWidthToEndOfLine)
- *extraWidthToEndOfLine = 0;
- return IntRect();
+ return FloatPoint();
}
-int RenderObject::paddingTop() const
+FloatPoint RenderObject::absoluteToLocal(FloatPoint containerPoint, bool fixed, bool useTransforms) const
{
- int w = 0;
- Length padding = m_style->paddingTop();
- if (padding.isPercent())
- w = containingBlock()->availableWidth();
-#ifdef ANDROID_LAYOUT
- // in SSR mode, we use ANDROID_SSR_MARGIN_PADDING for padding.
- if (document()->settings()->layoutAlgorithm() == Settings::kLayoutSSR &&
- padding.calcMinValue(w) > ANDROID_SSR_MARGIN_PADDING)
- return ANDROID_SSR_MARGIN_PADDING;
-#endif
- return padding.calcMinValue(w);
+ RenderObject* o = parent();
+ if (o) {
+ FloatPoint localPoint = o->absoluteToLocal(containerPoint, fixed, useTransforms);
+ if (o->hasOverflowClip())
+ localPoint += toRenderBox(o)->layer()->scrolledContentOffset();
+ return localPoint;
+ }
+ return FloatPoint();
}
-int RenderObject::paddingBottom() const
+FloatQuad RenderObject::localToContainerQuad(const FloatQuad& localQuad, RenderBox* repaintContainer, bool fixed) const
{
- int w = 0;
- Length padding = style()->paddingBottom();
- if (padding.isPercent())
- w = containingBlock()->availableWidth();
-#ifdef ANDROID_LAYOUT
- // in SSR mode, we use ANDROID_SSR_MARGIN_PADDING for padding.
- if (document()->settings()->layoutAlgorithm() == Settings::kLayoutSSR &&
- padding.calcMinValue(w) > ANDROID_SSR_MARGIN_PADDING)
- return ANDROID_SSR_MARGIN_PADDING;
-#endif
- return padding.calcMinValue(w);
+ if (repaintContainer == this)
+ return localQuad;
+
+ RenderObject* o = parent();
+ if (o) {
+ FloatQuad quad = localQuad;
+ if (o->hasOverflowClip())
+ quad -= toRenderBox(o)->layer()->scrolledContentOffset();
+ return o->localToContainerQuad(quad, repaintContainer, fixed);
+ }
+
+ return FloatQuad();
}
-int RenderObject::paddingLeft() const
+IntSize RenderObject::offsetFromContainer(RenderObject* o) const
{
- int w = 0;
- Length padding = style()->paddingLeft();
- if (padding.isPercent())
- w = containingBlock()->availableWidth();
-#ifdef ANDROID_LAYOUT
- // in SSR mode, we use ANDROID_SSR_MARGIN_PADDING for padding.
- if (document()->settings()->layoutAlgorithm() == Settings::kLayoutSSR &&
- padding.calcMinValue(w) > ANDROID_SSR_MARGIN_PADDING)
- return ANDROID_SSR_MARGIN_PADDING;
-#endif
- return padding.calcMinValue(w);
+ ASSERT(o == container());
+
+ IntSize offset;
+ if (o->hasOverflowClip())
+ offset -= toRenderBox(o)->layer()->scrolledContentOffset();
+
+ return offset;
}
-int RenderObject::paddingRight() const
+IntRect RenderObject::localCaretRect(InlineBox*, int, int* extraWidthToEndOfLine)
{
- int w = 0;
- Length padding = style()->paddingRight();
- if (padding.isPercent())
- w = containingBlock()->availableWidth();
-#ifdef ANDROID_LAYOUT
- // in SSR mode, we use ANDROID_SSR_MARGIN_PADDING for padding.
- if (document()->settings()->layoutAlgorithm() == Settings::kLayoutSSR &&
- padding.calcMinValue(w) > ANDROID_SSR_MARGIN_PADDING)
- return ANDROID_SSR_MARGIN_PADDING;
-#endif
- return padding.calcMinValue(w);
+ if (extraWidthToEndOfLine)
+ *extraWidthToEndOfLine = 0;
+
+ return IntRect();
}
RenderView* RenderObject::view() const
@@ -2497,6 +2254,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) {
@@ -2514,7 +2273,7 @@ RenderObject* RenderObject::container() const
// 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();
+ return (!isInline() && virtualContinuation()) ? virtualContinuation() : parent();
}
bool RenderObject::isSelectionBorder() const
@@ -2536,14 +2295,14 @@ void RenderObject::removeFromObjectLists()
}
if (outermostBlock)
- outermostBlock->markAllDescendantsWithFloatsForLayout(this);
+ outermostBlock->markAllDescendantsWithFloatsForLayout(toRenderBox(this), false);
}
if (isPositioned()) {
RenderObject* p;
for (p = parent(); p; p = p->parent()) {
if (p->isRenderBlock())
- static_cast<RenderBlock*>(p)->removePositionedObject(this);
+ static_cast<RenderBlock*>(p)->removePositionedObject(toRenderBox(this));
}
}
}
@@ -2562,9 +2321,10 @@ void RenderObject::destroy()
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
@@ -2573,11 +2333,11 @@ void RenderObject::destroy()
remove();
+ // FIXME: Would like to do this in RenderBox, but the timing is so complicated that this can't easily
+ // be moved into RenderBox::destroy.
RenderArena* arena = renderArena();
-
if (hasLayer())
- layer()->destroy(arena);
-
+ toRenderBox(this)->layer()->destroy(arena);
arenaDelete(arena, this);
}
@@ -2614,11 +2374,16 @@ void RenderObject::arenaDelete(RenderArena* arena, void* base)
arena->free(*(size_t*)base, base);
}
-VisiblePosition RenderObject::positionForCoordinates(int x, int y)
+VisiblePosition RenderObject::positionForCoordinates(int, int)
{
return VisiblePosition(element(), caretMinOffset(), DOWNSTREAM);
}
+VisiblePosition RenderObject::positionForPoint(const IntPoint& point)
+{
+ return positionForCoordinates(point.x(), point.y());
+}
+
void RenderObject::updateDragState(bool dragOn)
{
bool valueChanged = (dragOn != m_isDragging);
@@ -2627,8 +2392,9 @@ void RenderObject::updateDragState(bool dragOn)
element()->setChanged();
for (RenderObject* curr = firstChild(); curr; curr = curr->nextSibling())
curr->updateDragState(dragOn);
- if (continuation())
- continuation()->updateDragState(dragOn);
+ RenderFlow* continuation = virtualContinuation();
+ if (continuation)
+ continuation->updateDragState(dragOn);
}
bool RenderObject::hitTest(const HitTestRequest& request, HitTestResult& result, const IntPoint& point, int tx, int ty, HitTestFilter hitTestFilter)
@@ -2663,24 +2429,24 @@ void RenderObject::updateHitTestResult(HitTestResult& result, const IntPoint& po
IntPoint localPoint(point);
if (isRenderView())
node = document()->documentElement();
- else if (!isInline() && continuation())
+ else if (!isInline() && virtualContinuation())
// 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();
+ node = virtualContinuation()->element();
if (node) {
- if (node->renderer() && node->renderer()->continuation() && node->renderer() != this) {
+ if (node->renderer() && node->renderer()->virtualContinuation() && 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();
+ RenderBlock* firstBlock = node->renderer()->containingBlock();
// Get our containing block.
- RenderObject* block = this;
+ RenderBox* block = toRenderBox(this);
if (isInline())
block = containingBlock();
- localPoint.move(block->xPos() - firstBlock->xPos(), block->yPos() - firstBlock->yPos());
+ localPoint.move(block->x() - firstBlock->x(), block->y() - firstBlock->y());
}
result.setInnerNode(node);
@@ -2792,9 +2558,9 @@ void RenderObject::removeLeftoverAnonymousBlock(RenderBlock*)
{
}
-InlineBox* RenderObject::createInlineBox(bool, bool isRootLineBox, bool)
+InlineBox* RenderObject::createInlineBox(bool, bool unusedIsRootLineBox, bool)
{
- ASSERT(!isRootLineBox);
+ ASSERT_UNUSED(unusedIsRootLineBox, !unusedIsRootLineBox);
return new (renderArena()) InlineBox(this);
}
@@ -2826,7 +2592,7 @@ RenderStyle* RenderObject::firstLineStyle() const
RenderBlock* firstLineBlock = obj->firstLineBlock();
if (firstLineBlock)
s = firstLineBlock->getCachedPseudoStyle(RenderStyle::FIRST_LINE, style());
- } else if (!obj->isAnonymous() && obj->isInlineFlow()) {
+ } else if (!obj->isAnonymous() && obj->isRenderInline()) {
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
@@ -2915,8 +2681,8 @@ void RenderObject::getTextDecorationColors(int decorations, Color& underline, Co
}
}
curr = curr->parent();
- if (curr && curr->isRenderBlock() && curr->continuation())
- curr = curr->continuation();
+ if (curr && curr->isRenderBlock() && curr->virtualContinuation())
+ curr = curr->virtualContinuation();
} while (curr && decorations && (!quirksMode || !curr->element() ||
(!curr->element()->hasTagName(aTag) && !curr->element()->hasTagName(fontTag))));
@@ -2939,16 +2705,18 @@ void RenderObject::updateWidgetPosition()
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;
@@ -2965,10 +2733,9 @@ void RenderObject::addDashboardRegions(Vector<DashboardRegionValue>& regions)
region.clip.setWidth(0);
}
- int x, y;
- absolutePosition(x, y);
- region.bounds.setX(x + styleRegion.offset.left().value());
- region.bounds.setY(y + styleRegion.offset.top().value());
+ FloatPoint absPos = localToAbsolute();
+ region.bounds.setX(absPos.x() + styleRegion.offset.left().value());
+ region.bounds.setY(absPos.y() + styleRegion.offset.top().value());
if (document()->frame()) {
float pageScaleFactor = document()->frame()->page()->chrome()->scaleFactor();
@@ -3012,15 +2779,6 @@ bool RenderObject::shrinkToAvoidFloats() const
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).
@@ -3068,34 +2826,9 @@ int RenderObject::nextOffset(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();
- int x, y;
- absolutePositionForContent(x, y);
- rect.move(x, y);
- return rect;
-}
-
void RenderObject::adjustRectForOutlineAndShadow(IntRect& rect) const
{
- int outlineSize = !isInline() && continuation() ? continuation()->style()->outlineSize() : style()->outlineSize();
+ int outlineSize = !isInline() && virtualContinuation() ? virtualContinuation()->style()->outlineSize() : style()->outlineSize();
if (ShadowData* boxShadow = style()->boxShadow()) {
int shadowLeft = 0;
int shadowRight = 0;
@@ -3118,64 +2851,14 @@ void RenderObject::adjustRectForOutlineAndShadow(IntRect& rect) const
rect.inflate(outlineSize);
}
-IntRect RenderObject::absoluteOutlineBox() const
-{
- IntRect box = borderBox();
- int x, y;
- absolutePosition(x, y);
- box.move(x, y);
- box.move(view()->layoutDelta());
- adjustRectForOutlineAndShadow(box);
- return box;
-}
-
-bool RenderObject::isScrollable() const
-{
- RenderLayer* l = enclosingLayer();
- return l && (l->verticalScrollbar() || l->horizontalScrollbar());
-}
-
AnimationController* RenderObject::animation() const
{
return document()->frame()->animation();
}
-void RenderObject::imageChanged(CachedImage* image)
-{
- imageChanged(static_cast<WrappedImagePtr>(image));
-}
-
-IntRect RenderObject::reflectionBox() 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);
- break;
- }
- return result;
-}
-
-int RenderObject::reflectionOffset() const
+void RenderObject::imageChanged(CachedImage* image, const IntRect* rect)
{
- 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());
+ imageChanged(static_cast<WrappedImagePtr>(image), rect);
}
#if ENABLE(SVG)
@@ -3185,12 +2868,12 @@ FloatRect RenderObject::relativeBBox(bool) const
return FloatRect();
}
-AffineTransform RenderObject::localTransform() const
+TransformationMatrix RenderObject::localTransform() const
{
- return AffineTransform(1, 0, 0, 1, xPos(), yPos());
+ return TransformationMatrix();
}
-AffineTransform RenderObject::absoluteTransform() const
+TransformationMatrix RenderObject::absoluteTransform() const
{
if (parent())
return localTransform() * parent()->absoluteTransform();
diff --git a/WebCore/rendering/RenderObject.h b/WebCore/rendering/RenderObject.h
index b904c41..889ce9b 100644
--- a/WebCore/rendering/RenderObject.h
+++ b/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
@@ -26,38 +26,20 @@
#define RenderObject_h
#include "CachedResourceClient.h"
+#include "FloatQuad.h"
#include "Document.h"
#include "RenderStyle.h"
-#include "ScrollTypes.h"
-#include "VisiblePosition.h"
-#include <wtf/HashMap.h>
namespace WebCore {
-class AffineTransform;
class AnimationController;
-class Color;
-class Document;
-class Element;
-class Event;
-class FloatRect;
-class FrameView;
-class HTMLAreaElement;
class HitTestResult;
class InlineBox;
class InlineFlowBox;
-class Position;
-class RenderArena;
class RenderBlock;
class RenderFlow;
-class RenderFrameSet;
class RenderLayer;
-class RenderTable;
-class RenderText;
-class RenderView;
-class String;
-
-struct HitTestRequest;
+class VisiblePosition;
/*
* The painting of a layer occurs in three distinct phases. Each phase involves
@@ -103,11 +85,10 @@ enum HitTestAction {
HitTestForeground
};
-enum VerticalPositionHint {
- PositionTop = -0x7fffffff,
- PositionBottom = 0x7fffffff,
- PositionUndefined = static_cast<int>(0x80000000)
-};
+// Values for verticalPosition.
+const int PositionTop = -0x7fffffff;
+const int PositionBottom = 0x7fffffff;
+const int PositionUndefined = 0x80000000;
#if ENABLE(DASHBOARD_SUPPORT)
struct DashboardRegionValue {
@@ -127,15 +108,11 @@ 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 RenderLayer;
+ 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.
@@ -163,15 +140,18 @@ public:
RenderObject* firstLeafChild() const;
RenderObject* lastLeafChild() const;
- virtual RenderLayer* layer() const { return 0; }
+ // The following five 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;
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();
+ // Convenience function for getting to the nearest enclosing box of a RenderObject.
+ RenderBox* enclosingBox() const;
+
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(); }
@@ -187,6 +167,8 @@ public:
#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
@@ -269,7 +251,6 @@ public:
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; }
@@ -290,7 +271,6 @@ public:
virtual bool isTextField() const { return false; }
virtual bool isWidget() const { return false; }
-
bool isRoot() const { return document()->documentElement() == node(); }
bool isBody() const;
bool isHR() const;
@@ -300,7 +280,7 @@ public:
virtual bool childrenInline() const { return false; }
virtual void setChildrenInline(bool) { }
- virtual RenderFlow* continuation() const;
+ virtual RenderFlow* virtualContinuation() const { return 0; }
#if ENABLE(SVG)
virtual bool isSVGRoot() const { return false; }
@@ -311,8 +291,8 @@ public:
virtual FloatRect relativeBBox(bool includeStroke = true) const;
- virtual AffineTransform localTransform() const;
- virtual AffineTransform absoluteTransform() const;
+ virtual TransformationMatrix localTransform() const;
+ virtual TransformationMatrix absoluteTransform() const;
#endif
virtual bool isEditable() const;
@@ -328,8 +308,8 @@ public:
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)
@@ -338,9 +318,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; }
@@ -357,23 +334,8 @@ public:
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); }
public:
// The pseudo element style can be cached or uncached. Use the cached method if the pseudo element doesn't respect
@@ -401,7 +363,6 @@ public:
RenderObject* container() const;
RenderObject* hoverAncestor() 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);
@@ -421,7 +382,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; }
@@ -457,7 +419,7 @@ public:
*/
struct PaintInfo {
PaintInfo(GraphicsContext* newContext, const IntRect& newRect, PaintPhase newPhase, bool newForceBlackText,
- RenderObject* newPaintingRoot, RenderFlowSequencedSet* newOutlineObjects)
+ RenderObject* newPaintingRoot, ListHashSet<RenderFlow*>* newOutlineObjects)
: context(newContext)
, rect(newRect)
, phase(newPhase)
@@ -472,23 +434,21 @@ 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<RenderFlow*>* outlineObjects; // used to list outlines that should be painted by a block with inline children
};
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 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* box = 0, CompositeOperator = CompositeSourceOver) { }
+ 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)
@@ -518,11 +478,6 @@ 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)
@@ -535,7 +490,7 @@ public:
void updateHitTestResult(HitTestResult&, const IntPoint&);
virtual VisiblePosition positionForCoordinates(int x, int y);
- VisiblePosition positionForPoint(const IntPoint& point) { return positionForCoordinates(point.x(), point.y()); }
+ VisiblePosition positionForPoint(const IntPoint&);
virtual void dirtyLinesFromChangedChild(RenderObject*);
@@ -559,142 +514,41 @@ public:
// return just the height of the containing block
virtual int containingBlockHeight() const;
- // content area (box minus padding/border)
- IntRect contentBox() const;
- IntRect absoluteContentBox() 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; }
-
- // calculate client position of box
- virtual bool absolutePosition(int& x, int& y, bool fixed = false) const;
+ // 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;
- // 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.
- bool absolutePositionForContent(int& xPos, int& yPos, bool fixed = false) const
+ // Convert a local quad to absolute coordinates, taking transforms into account.
+ FloatQuad localToAbsoluteQuad(const FloatQuad& quad, bool fixed = false) const
{
- bool result = absolutePosition(xPos, yPos, fixed);
- yPos += borderTopExtra();
- return result;
+ return localToContainerQuad(quad, 0, fixed);
}
+ // Convert a local quad into the coordinate system of container, taking transforms into account.
+ virtual FloatQuad localToContainerQuad(const FloatQuad&, RenderBox* repaintContainer, bool fixed = false) 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()); }
- IntRect absoluteOutlineBox() 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(); }
+ // Return the offset from the container() renderer (excluding transforms)
+ virtual IntSize offsetFromContainer(RenderObject*) const;
virtual void addLineBoxRects(Vector<IntRect>&, unsigned startOffset = 0, unsigned endOffset = UINT_MAX, bool useSelectionHeight = false);
+
+ virtual void absoluteRects(Vector<IntRect>&, int, int, bool = true) { }
+ // FIXME: useTransforms should go away eventually
+ IntRect absoluteBoundingBoxRect(bool useTransforms = false);
- virtual void absoluteRects(Vector<IntRect>&, int tx, int ty, bool topLevel = true);
- IntRect absoluteBoundingBoxRect();
+ // 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) { }
// 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; }
@@ -717,6 +571,11 @@ public:
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.
+ RenderBox* containerForRepaint() const;
+
// 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);
@@ -737,13 +596,23 @@ 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(RenderBox* repaintContainer);
+
+ IntRect rectWithOutlineForRepaint(RenderBox* 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(r, 0, 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(IntRect&, RenderBox* repaintContainer, bool fixed = false);
virtual unsigned int length() const { return 1; }
@@ -751,9 +620,6 @@ public:
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;
@@ -765,8 +631,6 @@ public:
float opacity() const { return style()->opacity(); }
bool hasReflection() const { return m_hasReflection; }
- IntRect reflectionBox() const;
- int reflectionOffset() const;
// Applied as a "slop" to dirty rect checks during the outline painting phase's dirty-rect checks.
int maximalOutlineSize(PaintPhase) const;
@@ -830,14 +694,12 @@ public:
Node* draggableNode(bool dhtmlOK, bool uaOK, int x, int y, bool& dhtmlWillDrag) const;
/**
- * Returns the content coordinates of the caret within this render object.
- * @param offset zero-based offset determining position within the render object.
- * @param override @p true if input overrides existing characters,
- * @p false if it inserts them. The width of the caret depends on this one.
+ * Returns the local coordinates of the caret within this render object.
+ * @param caretOffset zero-based offset determining position within the render object.
* @param extraWidthToEndOfLine optional out arg to give extra width to end of line -
* useful for character range rect computations
*/
- virtual IntRect caretRect(InlineBox*, int caretOffset, int* extraWidthToEndOfLine = 0);
+ 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; }
@@ -857,9 +719,6 @@ 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;
@@ -867,8 +726,8 @@ public:
virtual int previousOffset(int current) const;
virtual int nextOffset(int current) const;
- virtual void imageChanged(CachedImage* image);
- virtual void imageChanged(WrappedImagePtr data) { };
+ 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;
@@ -900,6 +759,15 @@ public:
AnimationController* animation() const;
+ bool visibleToHitTesting() const { return style()->visibility() == VISIBLE && style()->pointerEvents() != PE_NONE; }
+
+ virtual void addFocusRingRects(GraphicsContext*, int /*tx*/, int /*ty*/) { };
+
+ IntRect absoluteOutlineBounds() const
+ {
+ return outlineBoundsForRepaint(0);
+ }
+
protected:
// Overrides should call the superclass at the end
virtual void styleWillChange(RenderStyle::Diff, const RenderStyle* newStyle);
@@ -908,6 +776,9 @@ protected:
virtual void printBoxDecorations(GraphicsContext*, int /*x*/, int /*y*/, int /*w*/, int /*h*/, int /*tx*/, int /*ty*/) { }
+ void paintOutline(GraphicsContext*, int tx, int ty, int w, int h, const RenderStyle*);
+ void addPDFURLRect(GraphicsContext*, const IntRect&);
+
virtual IntRect viewRect() const;
int getVerticalPosition(bool firstLine) const;
@@ -916,6 +787,8 @@ protected:
void arenaDelete(RenderArena*, void* objectBase);
+ virtual IntRect outlineBoundsForRepaint(RenderBox* /*repaintContainer*/) const { return IntRect(); }
+
private:
RefPtr<RenderStyle> m_style;
@@ -927,6 +800,7 @@ private:
#ifndef NDEBUG
bool m_hasAXObject;
+ bool m_setNeedsLayoutForbidden : 1;
#endif
mutable int m_verticalPosition;
@@ -944,6 +818,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;
diff --git a/WebCore/rendering/RenderPart.cpp b/WebCore/rendering/RenderPart.cpp
index a9a821e..6f79a00 100644
--- a/WebCore/rendering/RenderPart.cpp
+++ b/WebCore/rendering/RenderPart.cpp
@@ -88,13 +88,11 @@ void RenderPart::updateWidgetPosition()
if (!m_widget)
return;
- int x, y, width, height;
- absolutePosition(x, y);
- x += borderLeft() + paddingLeft();
- y += borderTop() + paddingTop();
- width = m_width - borderLeft() - borderRight() - paddingLeft() - paddingRight();
- height = m_height - borderTop() - borderBottom() - paddingTop() - paddingBottom();
- IntRect newBounds(x,y,width,height);
+ FloatPoint absPos = localToAbsolute();
+ absPos.move(borderLeft() + paddingLeft(), borderTop() + paddingTop());
+ int w = width() - borderLeft() - borderRight() - paddingLeft() - paddingRight();
+ int h = height() - borderTop() - borderBottom() - paddingTop() - paddingBottom();
+ IntRect newBounds(absPos.x(), absPos.y(), w, h);
bool boundsChanged = newBounds != m_widget->frameRect();
if (boundsChanged) {
// The widget changed positions. Update the frame geometry.
diff --git a/WebCore/rendering/RenderPartObject.cpp b/WebCore/rendering/RenderPartObject.cpp
index 75ecdec..86cb2ad 100644
--- a/WebCore/rendering/RenderPartObject.cpp
+++ b/WebCore/rendering/RenderPartObject.cpp
@@ -36,6 +36,8 @@
#include "HTMLParamElement.h"
#include "MIMETypeRegistry.h"
#include "Page.h"
+#include "PluginData.h"
+#include "RenderView.h"
#include "Text.h"
#ifdef FLATTEN_IFRAME
@@ -52,6 +54,9 @@ RenderPartObject::RenderPartObject(HTMLFrameOwnerElement* element)
// init RenderObject attributes
setInline(true);
m_hasFallbackContent = false;
+
+ if (element->hasTagName(embedTag) || element->hasTagName(objectTag))
+ view()->frameView()->setIsVisuallyNonEmpty();
}
RenderPartObject::~RenderPartObject()
@@ -79,183 +84,216 @@ static bool isURLAllowed(Document* doc, const String& url)
return true;
}
-static inline void mapClassIdToServiceType(const String& classId, String& serviceType)
+typedef HashMap<String, String, CaseFoldingHash> ClassIdToTypeMap;
+
+static ClassIdToTypeMap* createClassIdToTypeMap()
{
- // It is ActiveX, but the nsplugin system handling
- // should also work, that's why we don't override the
- // serviceType with application/x-activex-handler
- // but let the KTrader in khtmlpart::createPart() detect
- // the user's preference: launch with activex viewer or
- // with nspluginviewer (Niko)
- if (classId.contains("D27CDB6E-AE6D-11cf-96B8-444553540000"))
- serviceType = "application/x-shockwave-flash";
- else if (classId.contains("CFCDAA03-8BE4-11cf-B84B-0020AFBBCCFA"))
- serviceType = "audio/x-pn-realaudio-plugin";
- else if (classId.contains("02BF25D5-8C17-4B23-BC80-D3488ABDDC6B"))
- serviceType = "video/quicktime";
- else if (classId.contains("166B1BCA-3F9C-11CF-8075-444553540000"))
- serviceType = "application/x-director";
- else if (classId.contains("6BF52A52-394A-11d3-B153-00C04F79FAA6"))
- serviceType = "application/x-mplayer2";
- else if (!classId.isEmpty()) {
- // We have a clsid, means this is Active X (Niko)
- serviceType = "application/x-activex-handler";
- }
+ 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 String();
+
+ static ClassIdToTypeMap* map = createClassIdToTypeMap();
+ String type = map->get(classId);
+
+ // 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 inline bool shouldUseEmbedDescendant(HTMLObjectElement* objectElement, const PluginData* pluginData)
+{
+ // 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());
}
void RenderPartObject::updateWidget(bool onlyCreateNonNetscapePlugins)
{
- String url;
- String serviceType;
- Vector<String> paramNames;
- Vector<String> paramValues;
- Frame* frame = m_view->frame();
-
- if (element()->hasTagName(objectTag)) {
-
- HTMLObjectElement* o = static_cast<HTMLObjectElement*>(element());
-
- o->setNeedWidgetUpdate(false);
- if (!o->isFinishedParsingChildren())
- return;
- // Check for a child EMBED tag.
- HTMLEmbedElement* embed = 0;
- for (Node* child = o->firstChild(); child;) {
- if (child->hasTagName(embedTag)) {
- embed = static_cast<HTMLEmbedElement*>(child);
- break;
- } else if (child->hasTagName(objectTag))
- child = child->nextSibling(); // Don't descend into nested OBJECT tags
- else
- child = child->traverseNextNode(o); // Otherwise descend (EMBEDs may be inside COMMENT tags)
- }
-
- // Use the attributes from the EMBED tag instead of the OBJECT tag including WIDTH and HEIGHT.
- HTMLElement *embedOrObject;
- if (embed) {
- embedOrObject = (HTMLElement *)embed;
- url = embed->url();
- serviceType = embed->serviceType();
- } else
- embedOrObject = (HTMLElement *)o;
-
- // If there was no URL or type defined in EMBED, try the OBJECT tag.
- if (url.isEmpty())
- url = o->url();
- if (serviceType.isEmpty())
- serviceType = o->serviceType();
-
- HashSet<StringImpl*, CaseFoldingHash> uniqueParamNames;
-
- // Scan the PARAM children.
- // Get the URL and type from the params if we don't already have them.
- // Get the attributes from the params if there is no EMBED tag.
- Node *child = o->firstChild();
- while (child && (url.isEmpty() || serviceType.isEmpty() || !embed)) {
- if (child->hasTagName(paramTag)) {
- HTMLParamElement* p = static_cast<HTMLParamElement*>(child);
- String name = p->name();
- if (url.isEmpty() && (equalIgnoringCase(name, "src") || equalIgnoringCase(name, "movie") || equalIgnoringCase(name, "code") || equalIgnoringCase(name, "url")))
- url = p->value();
- if (serviceType.isEmpty() && equalIgnoringCase(name, "type")) {
- serviceType = p->value();
- int pos = serviceType.find(";");
- if (pos != -1)
- serviceType = serviceType.left(pos);
- }
- if (!embed && !name.isEmpty()) {
- uniqueParamNames.add(name.impl());
- paramNames.append(p->name());
- paramValues.append(p->value());
- }
- }
- child = child->nextSibling();
- }
-
- // When OBJECT is used for an applet via Sun's Java plugin, the CODEBASE attribute in the tag
- // points to the Java plugin itself (an ActiveX component) while the actual applet CODEBASE is
- // in a PARAM tag. See <http://java.sun.com/products/plugin/1.2/docs/tags.html>. This means
- // we have to explicitly suppress the tag's CODEBASE attribute if there is none in a PARAM,
- // else our Java plugin will misinterpret it. [4004531]
- String codebase;
- if (!embed && MIMETypeRegistry::isJavaAppletMIMEType(serviceType)) {
- codebase = "codebase";
- uniqueParamNames.add(codebase.impl()); // pretend we found it in a PARAM already
- }
-
- // Turn the attributes of either the EMBED tag or OBJECT tag into arrays, but don't override PARAM values.
- NamedAttrMap* attributes = embedOrObject->attributes();
- if (attributes) {
- for (unsigned i = 0; i < attributes->length(); ++i) {
- Attribute* it = attributes->attributeItem(i);
- const AtomicString& name = it->name().localName();
- if (embed || !uniqueParamNames.contains(name.impl())) {
- paramNames.append(name.string());
- paramValues.append(it->value().string());
- }
- }
- }
-
- // If we still don't have a type, try to map from a specific CLASSID to a type.
- if (serviceType.isEmpty() && !o->classId().isEmpty())
- mapClassIdToServiceType(o->classId(), serviceType);
-
- if (!isURLAllowed(document(), url))
+ String url;
+ String serviceType;
+ Vector<String> paramNames;
+ Vector<String> paramValues;
+ Frame* frame = m_view->frame();
+
+ if (element()->hasTagName(objectTag)) {
+ HTMLObjectElement* o = static_cast<HTMLObjectElement*>(element());
+
+ o->setNeedWidgetUpdate(false);
+ if (!o->isFinishedParsingChildren())
return;
- // Find out if we support fallback content.
- m_hasFallbackContent = false;
- for (Node *child = o->firstChild(); child && !m_hasFallbackContent; child = child->nextSibling()) {
- if ((!child->isTextNode() && !child->hasTagName(embedTag) && !child->hasTagName(paramTag)) || // Discount <embed> and <param>
- (child->isTextNode() && !static_cast<Text*>(child)->containsOnlyWhitespace()))
- m_hasFallbackContent = true;
- }
-
- if (onlyCreateNonNetscapePlugins) {
- KURL completedURL;
- if (!url.isEmpty())
- completedURL = frame->loader()->completeURL(url);
+ // Check for a child EMBED tag.
+ HTMLEmbedElement* embed = 0;
+ const PluginData* pluginData = frame->page()->pluginData();
+ if (shouldUseEmbedDescendant(o, pluginData)) {
+ for (Node* child = o->firstChild(); child; ) {
+ if (child->hasTagName(embedTag)) {
+ embed = static_cast<HTMLEmbedElement*>(child);
+ break;
+ } else if (child->hasTagName(objectTag))
+ child = child->nextSibling(); // Don't descend into nested OBJECT tags
+ else
+ child = child->traverseNextNode(o); // Otherwise descend (EMBEDs may be inside COMMENT tags)
+ }
+ }
+
+ // Use the attributes from the EMBED tag instead of the OBJECT tag including WIDTH and HEIGHT.
+ HTMLElement *embedOrObject;
+ if (embed) {
+ embedOrObject = (HTMLElement *)embed;
+ url = embed->url();
+ serviceType = embed->serviceType();
+ } else
+ embedOrObject = (HTMLElement *)o;
+
+ // If there was no URL or type defined in EMBED, try the OBJECT tag.
+ if (url.isEmpty())
+ url = o->url();
+ if (serviceType.isEmpty())
+ serviceType = o->serviceType();
+
+ HashSet<StringImpl*, CaseFoldingHash> uniqueParamNames;
+
+ // Scan the PARAM children.
+ // Get the URL and type from the params if we don't already have them.
+ // Get the attributes from the params if there is no EMBED tag.
+ Node *child = o->firstChild();
+ while (child && (url.isEmpty() || serviceType.isEmpty() || !embed)) {
+ if (child->hasTagName(paramTag)) {
+ HTMLParamElement* p = static_cast<HTMLParamElement*>(child);
+ String name = p->name();
+ if (url.isEmpty() && (equalIgnoringCase(name, "src") || equalIgnoringCase(name, "movie") || equalIgnoringCase(name, "code") || equalIgnoringCase(name, "url")))
+ url = p->value();
+ if (serviceType.isEmpty() && equalIgnoringCase(name, "type")) {
+ serviceType = p->value();
+ int pos = serviceType.find(";");
+ if (pos != -1)
+ serviceType = serviceType.left(pos);
+ }
+ if (!embed && !name.isEmpty()) {
+ uniqueParamNames.add(name.impl());
+ paramNames.append(p->name());
+ paramValues.append(p->value());
+ }
+ }
+ child = child->nextSibling();
+ }
+
+ // When OBJECT is used for an applet via Sun's Java plugin, the CODEBASE attribute in the tag
+ // points to the Java plugin itself (an ActiveX component) while the actual applet CODEBASE is
+ // in a PARAM tag. See <http://java.sun.com/products/plugin/1.2/docs/tags.html>. This means
+ // we have to explicitly suppress the tag's CODEBASE attribute if there is none in a PARAM,
+ // else our Java plugin will misinterpret it. [4004531]
+ String codebase;
+ if (!embed && MIMETypeRegistry::isJavaAppletMIMEType(serviceType)) {
+ codebase = "codebase";
+ uniqueParamNames.add(codebase.impl()); // pretend we found it in a PARAM already
+ }
- if (frame->loader()->client()->objectContentType(completedURL, serviceType) == ObjectContentNetscapePlugin)
- return;
- }
-
- 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());
- o->setNeedWidgetUpdate(false);
- url = o->url();
- serviceType = o->serviceType();
-
- if (url.isEmpty() && serviceType.isEmpty())
- return;
- if (!isURLAllowed(document(), url))
- return;
-
- // add all attributes set on the embed object
- NamedAttrMap* a = o->attributes();
- if (a) {
- for (unsigned i = 0; i < a->length(); ++i) {
- Attribute* it = a->attributeItem(i);
- paramNames.append(it->name().localName().string());
- paramValues.append(it->value().string());
- }
- }
-
- if (onlyCreateNonNetscapePlugins) {
- KURL completedURL;
- if (!url.isEmpty())
- completedURL = frame->loader()->completeURL(url);
-
- if (frame->loader()->client()->objectContentType(completedURL, serviceType) == ObjectContentNetscapePlugin)
- return;
-
- }
-
- frame->loader()->requestObject(this, url, o->getAttribute(nameAttr), serviceType, paramNames, paramValues);
- }
+ // Turn the attributes of either the EMBED tag or OBJECT tag into arrays, but don't override PARAM values.
+ NamedAttrMap* attributes = embedOrObject->attributes();
+ if (attributes) {
+ for (unsigned i = 0; i < attributes->length(); ++i) {
+ Attribute* it = attributes->attributeItem(i);
+ const AtomicString& name = it->name().localName();
+ if (embed || !uniqueParamNames.contains(name.impl())) {
+ paramNames.append(name.string());
+ paramValues.append(it->value().string());
+ }
+ }
+ }
+
+ // If we still don't have a type, try to map from a specific CLASSID to a type.
+ if (serviceType.isEmpty())
+ serviceType = serviceTypeForClassId(o->classId(), pluginData);
+
+ if (!isURLAllowed(document(), url))
+ return;
+
+ // Find out if we support fallback content.
+ m_hasFallbackContent = false;
+ for (Node *child = o->firstChild(); child && !m_hasFallbackContent; child = child->nextSibling()) {
+ if ((!child->isTextNode() && !child->hasTagName(embedTag) && !child->hasTagName(paramTag)) || // Discount <embed> and <param>
+ (child->isTextNode() && !static_cast<Text*>(child)->containsOnlyWhitespace()))
+ m_hasFallbackContent = true;
+ }
+
+ if (onlyCreateNonNetscapePlugins) {
+ KURL completedURL;
+ if (!url.isEmpty())
+ completedURL = frame->loader()->completeURL(url);
+
+ if (frame->loader()->client()->objectContentType(completedURL, serviceType) == ObjectContentNetscapePlugin)
+ return;
+ }
+
+ 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());
+ o->setNeedWidgetUpdate(false);
+ url = o->url();
+ serviceType = o->serviceType();
+
+ if (url.isEmpty() && serviceType.isEmpty())
+ return;
+ if (!isURLAllowed(document(), url))
+ return;
+
+ // add all attributes set on the embed object
+ NamedAttrMap* a = o->attributes();
+ if (a) {
+ for (unsigned i = 0; i < a->length(); ++i) {
+ Attribute* it = a->attributeItem(i);
+ paramNames.append(it->name().localName().string());
+ paramValues.append(it->value().string());
+ }
+ }
+
+ if (onlyCreateNonNetscapePlugins) {
+ KURL completedURL;
+ if (!url.isEmpty())
+ completedURL = frame->loader()->completeURL(url);
+
+ if (frame->loader()->client()->objectContentType(completedURL, serviceType) == ObjectContentNetscapePlugin)
+ return;
+
+ }
+
+ frame->loader()->requestObject(this, url, o->getAttribute(nameAttr), serviceType, paramNames, paramValues);
+ }
}
void RenderPartObject::layout()
@@ -268,8 +306,10 @@ void RenderPartObject::layout()
#ifdef FLATTEN_IFRAME
// Some IFrames have a width and/or height of 1 when they are meant to be
// hidden. If that is the case, don't try to expand.
+ int w = width();
+ int h = height();
if (m_widget && m_widget->isFrameView() &&
- m_width > 1 && m_height > 1) {
+ w > 1 && h > 1) {
FrameView* view = static_cast<FrameView*>(m_widget);
RenderView* root = NULL;
if (view->frame() && view->frame()->document() &&
@@ -280,12 +320,12 @@ void RenderPartObject::layout()
updateWidgetPosition();
// Use the preferred width if it is larger.
- m_width = max(m_width, root->minPrefWidth());
+ setWidth(max(w, root->minPrefWidth()));
int extraWidth = paddingLeft() + paddingRight() + borderLeft() + borderRight();
int extraHeight = paddingTop() + paddingBottom() + borderTop() + borderBottom();
// Resize the view to recalc the height.
- int height = m_height - extraHeight;
- int width = m_width - extraWidth;
+ int height = h - extraHeight;
+ int width = w - extraWidth;
if (width > view->width())
height = 0;
if (width != view->width() || height != view->height()) {
@@ -298,9 +338,9 @@ void RenderPartObject::layout()
int contentHeight = view->contentsHeight();
int contentWidth = view->contentsWidth();
// Do not shrink iframes with specified sizes
- if (contentHeight > m_height || style()->height().isAuto())
- m_height = contentHeight;
- m_width = std::min(contentWidth, 800);
+ if (contentHeight > h || style()->height().isAuto())
+ setHeight(contentHeight);
+ setWidth(std::min(contentWidth, 800));
}
}
#endif
@@ -310,7 +350,7 @@ void RenderPartObject::layout()
if (!m_widget && m_view)
m_view->addWidgetToUpdate(this);
-
+
setNeedsLayout(false);
}
diff --git a/WebCore/rendering/RenderPath.cpp b/WebCore/rendering/RenderPath.cpp
index e825f76..1f73c70 100644
--- a/WebCore/rendering/RenderPath.cpp
+++ b/WebCore/rendering/RenderPath.cpp
@@ -26,12 +26,12 @@
#if ENABLE(SVG)
#include "RenderPath.h"
-#include <math.h>
-
#include "FloatPoint.h"
+#include "FloatQuad.h"
#include "GraphicsContext.h"
#include "PointerEventsHitRules.h"
#include "RenderSVGContainer.h"
+#include "StrokeStyleApplier.h"
#include "SVGPaintServer.h"
#include "SVGRenderSupport.h"
#include "SVGResourceFilter.h"
@@ -40,24 +40,37 @@
#include "SVGStyledTransformableElement.h"
#include "SVGTransformList.h"
#include "SVGURIReference.h"
-
#include <wtf/MathExtras.h>
namespace WebCore {
+class BoundingRectStrokeStyleApplier : public StrokeStyleApplier {
+public:
+ BoundingRectStrokeStyleApplier(const RenderObject* object, RenderStyle* style)
+ : m_object(object)
+ , m_style(style)
+ {
+ ASSERT(style);
+ ASSERT(object);
+ }
+
+ void strokeStyle(GraphicsContext* gc)
+ {
+ applyStrokeStyleToContext(gc, m_style, m_object);
+ }
+
+private:
+ const RenderObject* m_object;
+ RenderStyle* m_style;
+};
+
// RenderPath
-RenderPath::RenderPath(RenderStyle* style, SVGStyledTransformableElement* node)
+RenderPath::RenderPath(SVGStyledTransformableElement* node)
: RenderObject(node)
{
- ASSERT(style != 0);
- ASSERT(static_cast<SVGElement*>(node)->isStyledTransformable());
}
-RenderPath::~RenderPath()
-{
-}
-
-AffineTransform RenderPath::localTransform() const
+TransformationMatrix RenderPath::localTransform() const
{
return m_localTransform;
}
@@ -83,14 +96,35 @@ bool RenderPath::fillContains(const FloatPoint& point, bool requiresFill) const
return m_path.contains(point, style()->svgStyle()->fillRule());
}
+bool RenderPath::strokeContains(const FloatPoint& point, bool requiresStroke) const
+{
+ if (m_path.isEmpty())
+ return false;
+
+ if (requiresStroke && !SVGPaintServer::strokePaintServer(style(), this))
+ return false;
+
+ BoundingRectStrokeStyleApplier strokeStyle(this, style());
+ return m_path.strokeContains(&strokeStyle, point);
+}
+
FloatRect RenderPath::relativeBBox(bool includeStroke) const
{
if (m_path.isEmpty())
return FloatRect();
if (includeStroke) {
- if (m_strokeBbox.isEmpty())
- m_strokeBbox = strokeBBox();
+ 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;
}
@@ -115,7 +149,7 @@ const Path& RenderPath::path() const
bool RenderPath::calculateLocalTransform()
{
- AffineTransform oldTransform = m_localTransform;
+ TransformationMatrix oldTransform = m_localTransform;
m_localTransform = static_cast<SVGStyledTransformableElement*>(element())->animatedLocalTransform();
return (m_localTransform != oldTransform);
}
@@ -127,7 +161,7 @@ void RenderPath::layout()
bool checkForRepaint = checkForRepaintDuringLayout() && selfNeedsLayout();
if (checkForRepaint) {
oldBounds = m_absoluteBounds;
- oldOutlineBox = absoluteOutlineBox();
+ oldOutlineBox = absoluteOutlineBounds();
}
calculateLocalTransform();
@@ -136,17 +170,15 @@ void RenderPath::layout()
m_absoluteBounds = absoluteClippedOverflowRect();
- setWidth(m_absoluteBounds.width());
- setHeight(m_absoluteBounds.height());
-
if (checkForRepaint)
repaintAfterLayoutIfNeeded(oldBounds, oldOutlineBox);
setNeedsLayout(false);
}
-IntRect RenderPath::absoluteClippedOverflowRect()
+IntRect RenderPath::clippedOverflowRectForRepaint(RenderBox* /*repaintContainer*/)
{
+ // FIXME: handle non-root repaintContainer
FloatRect repaintRect = absoluteTransform().mapRect(relativeBBox(true));
// Markers can expand the bounding box
@@ -165,17 +197,12 @@ IntRect RenderPath::absoluteClippedOverflowRect()
return enclosingIntRect(repaintRect);
}
-bool RenderPath::requiresLayer()
-{
- return false;
-}
-
-int RenderPath::lineHeight(bool b, bool isRootLineBox) const
+int RenderPath::lineHeight(bool, bool) const
{
return relativeBBox(true).height();
}
-int RenderPath::baselinePosition(bool b, bool isRootLineBox) const
+int RenderPath::baselinePosition(bool, bool) const
{
return relativeBBox(true).height();
}
@@ -213,7 +240,7 @@ void RenderPath::paint(PaintInfo& paintInfo, int, int)
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())
@@ -239,7 +266,12 @@ void RenderPath::absoluteRects(Vector<IntRect>& rects, int, int, bool)
rects.append(absoluteClippedOverflowRect());
}
-bool RenderPath::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, int _x, int _y, int, int, HitTestAction hitTestAction)
+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)
{
// We only draw in the forground phase, so we only hit-test then.
if (hitTestAction != HitTestForeground)
@@ -247,7 +279,7 @@ bool RenderPath::nodeAtPoint(const HitTestRequest& request, HitTestResult& resul
IntPoint absolutePoint(_x, _y);
- PointerEventsHitRules hitRules(PointerEventsHitRules::SVG_PATH_HITTESTING, style()->svgStyle()->pointerEvents());
+ PointerEventsHitRules hitRules(PointerEventsHitRules::SVG_PATH_HITTESTING, style()->pointerEvents());
bool isVisible = (style()->visibility() == VISIBLE);
if (isVisible || !hitRules.requireVisible) {
@@ -382,7 +414,7 @@ static void drawStartAndMidMarkers(void* info, const PathElement* element)
data.elementIndex++;
}
-FloatRect RenderPath::drawMarkersIfNeeded(GraphicsContext* context, const FloatRect& rect, const Path& path) const
+FloatRect RenderPath::drawMarkersIfNeeded(GraphicsContext* context, const FloatRect&, const Path& path) const
{
Document* doc = document();
@@ -444,6 +476,14 @@ FloatRect RenderPath::drawMarkersIfNeeded(GraphicsContext* context, const FloatR
return bounds;
}
+IntRect RenderPath::outlineBoundsForRepaint(RenderBox* /*repaintContainer*/) const
+{
+ // FIXME: handle non-root repaintContainer
+ IntRect result = m_absoluteBounds;
+ adjustRectForOutlineAndShadow(result);
+ return result;
+}
+
}
#endif // ENABLE(SVG)
diff --git a/WebCore/rendering/RenderPath.h b/WebCore/rendering/RenderPath.h
index ab966e4..81b5c52 100644
--- a/WebCore/rendering/RenderPath.h
+++ b/WebCore/rendering/RenderPath.h
@@ -27,7 +27,7 @@
#if ENABLE(SVG)
-#include "AffineTransform.h"
+#include "TransformationMatrix.h"
#include "FloatRect.h"
#include "RenderObject.h"
@@ -35,19 +35,16 @@
namespace WebCore {
class FloatPoint;
-class Path;
class RenderSVGContainer;
class SVGStyledTransformableElement;
-class RenderPath : public RenderObject
-{
+class RenderPath : public RenderObject {
public:
- RenderPath(RenderStyle*, SVGStyledTransformableElement*);
- virtual ~RenderPath();
+ RenderPath(SVGStyledTransformableElement*);
// Hit-detection seperated for the fill and the stroke
- virtual bool fillContains(const FloatPoint&, bool requiresFill = true) const;
- virtual bool strokeContains(const FloatPoint&, bool requiresStroke = true) const;
+ 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;
@@ -59,31 +56,32 @@ public:
virtual const char* renderName() const { return "RenderPath"; }
bool calculateLocalTransform();
- virtual AffineTransform localTransform() const;
+ virtual TransformationMatrix localTransform() const;
virtual void layout();
- virtual IntRect absoluteClippedOverflowRect();
- virtual bool requiresLayer();
+ virtual IntRect clippedOverflowRectForRepaint(RenderBox* repaintContainer);
+ virtual bool requiresLayer() const { return false; }
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);
FloatRect drawMarkersIfNeeded(GraphicsContext*, const FloatRect&, const Path&) const;
- virtual FloatRect strokeBBox() const;
private:
FloatPoint mapAbsolutePointToLocal(const FloatPoint&) const;
+ virtual IntRect outlineBoundsForRepaint(RenderBox* repaintContainer) const;
mutable Path m_path;
mutable FloatRect m_fillBBox;
mutable FloatRect m_strokeBbox;
FloatRect m_markerBounds;
- AffineTransform m_localTransform;
+ TransformationMatrix m_localTransform;
IntRect m_absoluteBounds;
};
diff --git a/WebCore/rendering/RenderReplaced.cpp b/WebCore/rendering/RenderReplaced.cpp
index 52267d5..e74e227 100644
--- a/WebCore/rendering/RenderReplaced.cpp
+++ b/WebCore/rendering/RenderReplaced.cpp
@@ -26,6 +26,8 @@
#include "GraphicsContext.h"
#include "RenderBlock.h"
#include "RenderLayer.h"
+#include "RenderTheme.h"
+#include "RenderView.h"
using namespace std;
@@ -80,10 +82,10 @@ void RenderReplaced::layout()
bool checkForRepaint = checkForRepaintDuringLayout();
if (checkForRepaint) {
oldBounds = absoluteClippedOverflowRect();
- oldOutlineBox = absoluteOutlineBox();
+ oldOutlineBox = absoluteOutlineBounds();
}
- m_height = minimumReplacedHeight();
+ setHeight(minimumReplacedHeight());
calcWidth();
calcHeight();
@@ -108,8 +110,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 +139,11 @@ void RenderReplaced::paint(PaintInfo& paintInfo, int tx, int ty)
paintReplaced(paintInfo, tx, ty);
- if (drawSelectionTint)
- paintInfo.context->fillRect(selectionRect(), selectionBackgroundColor());
+ if (drawSelectionTint) {
+ IntRect selectionPaintingRect = localSelectionRect();
+ selectionPaintingRect.move(tx, ty);
+ paintInfo.context->fillRect(selectionPaintingRect, selectionBackgroundColor());
+ }
}
bool RenderReplaced::shouldPaint(PaintInfo& paintInfo, int& tx, int& ty)
@@ -154,8 +159,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();
@@ -210,7 +215,7 @@ unsigned RenderReplaced::caretMaxRenderedOffset() const
return 1;
}
-VisiblePosition RenderReplaced::positionForCoordinates(int x, int y)
+VisiblePosition RenderReplaced::positionForCoordinates(int xPos, int yPos)
{
InlineBox* box = inlineBoxWrapper();
if (!box)
@@ -223,19 +228,19 @@ VisiblePosition RenderReplaced::positionForCoordinates(int x, int y)
int top = root->topOverflow();
int bottom = root->nextRootBox() ? root->nextRootBox()->topOverflow() : root->bottomOverflow();
- if (y + yPos() < top)
+ if (yPos + y() < top)
return VisiblePosition(element(), caretMinOffset(), DOWNSTREAM); // coordinates are above
- if (y + yPos() >= bottom)
+ if (yPos + y() >= bottom)
return VisiblePosition(element(), caretMaxOffset(), DOWNSTREAM); // coordinates are below
if (element()) {
- if (x <= width() / 2)
+ if (xPos <= width() / 2)
return VisiblePosition(element(), 0, DOWNSTREAM);
return VisiblePosition(element(), 1, DOWNSTREAM);
}
- return RenderBox::positionForCoordinates(x, y);
+ return RenderBox::positionForCoordinates(xPos, yPos);
}
IntRect RenderReplaced::selectionRect(bool clipToVisibleContent)
@@ -244,26 +249,33 @@ IntRect RenderReplaced::selectionRect(bool clipToVisibleContent)
if (!isSelected())
return IntRect();
+
+ IntRect rect = localSelectionRect();
+ if (clipToVisibleContent)
+ computeAbsoluteRepaintRect(rect);
+ else {
+ FloatPoint absPos = localToAbsolute(FloatPoint());
+ rect.move(absPos.x(), absPos.y());
+ }
+
+ return rect;
+}
+
+IntRect RenderReplaced::localSelectionRect(bool checkWhetherSelected) const
+{
+ if (checkWhetherSelected && !isSelected())
+ return IntRect();
+
if (!m_inlineBoxWrapper)
// We're a block-level replaced element. Just return our own dimensions.
- return absoluteBoundingBoxRect();
+ return IntRect(0, 0, width(), height());
RenderBlock* cb = containingBlock();
if (!cb)
return IntRect();
RootInlineBox* root = m_inlineBoxWrapper->root();
- IntRect rect(0, root->selectionTop() - yPos(), width(), root->selectionHeight());
-
- if (clipToVisibleContent)
- computeAbsoluteRepaintRect(rect);
- else {
- int absx, absy;
- absolutePositionForContent(absx, absy);
- rect.move(absx, absy);
- }
-
- return rect;
+ return IntRect(0, root->selectionTop() - y(), width(), root->selectionHeight());
}
void RenderReplaced::setSelectionState(SelectionState s)
@@ -315,7 +327,7 @@ void RenderReplaced::adjustOverflowForBoxShadow()
{
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);
@@ -324,7 +336,7 @@ void RenderReplaced::adjustOverflowForBoxShadow()
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) {
@@ -333,7 +345,7 @@ void RenderReplaced::adjustOverflowForBoxShadow()
}
}
-int RenderReplaced::overflowHeight(bool includeInterior) const
+int RenderReplaced::overflowHeight(bool) const
{
if (m_hasOverflow) {
IntRect *r = &gOverflowRectMap->find(this)->second;
@@ -343,7 +355,7 @@ int RenderReplaced::overflowHeight(bool includeInterior) const
return height();
}
-int RenderReplaced::overflowWidth(bool includeInterior) const
+int RenderReplaced::overflowWidth(bool) const
{
if (m_hasOverflow) {
IntRect *r = &gOverflowRectMap->find(this)->second;
@@ -353,7 +365,7 @@ int RenderReplaced::overflowWidth(bool includeInterior) const
return width();
}
-int RenderReplaced::overflowLeft(bool includeInterior) const
+int RenderReplaced::overflowLeft(bool) const
{
if (m_hasOverflow)
return gOverflowRectMap->get(this).x();
@@ -361,7 +373,7 @@ int RenderReplaced::overflowLeft(bool includeInterior) const
return 0;
}
-int RenderReplaced::overflowTop(bool includeInterior) const
+int RenderReplaced::overflowTop(bool) const
{
if (m_hasOverflow)
return gOverflowRectMap->get(this).y();
@@ -369,12 +381,39 @@ int RenderReplaced::overflowTop(bool includeInterior) const
return 0;
}
-IntRect RenderReplaced::overflowRect(bool includeInterior) const
+IntRect RenderReplaced::overflowRect(bool) const
{
if (m_hasOverflow)
return gOverflowRectMap->find(this)->second;
- return borderBox();
+ return borderBoxRect();
+}
+
+IntRect RenderReplaced::clippedOverflowRectForRepaint(RenderBox* 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);
+
+ RenderView* v = view();
+ 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.
+ theme()->adjustRepaintRect(this, r);
+ if (v)
+ r.inflate(style()->outlineSize());
+ }
+ computeRectForRepaint(r, repaintContainer);
+ return r;
}
}
diff --git a/WebCore/rendering/RenderReplaced.h b/WebCore/rendering/RenderReplaced.h
index f1ee32b..c87db58 100644
--- a/WebCore/rendering/RenderReplaced.h
+++ b/WebCore/rendering/RenderReplaced.h
@@ -43,7 +43,7 @@ public:
virtual int minimumReplacedHeight() const { return 0; }
virtual void paint(PaintInfo&, int tx, int ty);
- virtual void paintReplaced(PaintInfo&, int tx, int ty) { }
+ virtual void paintReplaced(PaintInfo&, int /*tx*/, int /*ty*/) { }
virtual IntSize intrinsicSize() const;
@@ -53,6 +53,8 @@ public:
virtual int overflowTop(bool includeInterior = true) const;
virtual IntRect overflowRect(bool includeInterior = true) const;
+ virtual IntRect clippedOverflowRectForRepaint(RenderBox* repaintContainer);
+
virtual unsigned caretMaxRenderedOffset() const;
virtual VisiblePosition positionForCoordinates(int x, int y);
@@ -71,6 +73,7 @@ protected:
bool shouldPaint(PaintInfo&, int& tx, int& ty);
void adjustOverflowForBoxShadow();
+ IntRect localSelectionRect(bool checkWhetherSelected = true) const;
private:
IntSize m_intrinsicSize;
diff --git a/WebCore/rendering/RenderReplica.cpp b/WebCore/rendering/RenderReplica.cpp
index be28171..183dd2e 100644
--- a/WebCore/rendering/RenderReplica.cpp
+++ b/WebCore/rendering/RenderReplica.cpp
@@ -42,17 +42,13 @@ 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,12 +58,17 @@ 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.
- layer()->parent()->paintLayer(layer()->transform() ? layer()->parent() : layer()->enclosingTransformedAncestor(), paintInfo.context, paintInfo.rect, true, PaintRestrictionNone, 0, true);
+ // 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
else if (paintInfo.phase == PaintPhaseMask)
paintMask(paintInfo, tx, ty);
}
diff --git a/WebCore/rendering/RenderReplica.h b/WebCore/rendering/RenderReplica.h
index d3a9026..d5db3b7 100644
--- a/WebCore/rendering/RenderReplica.h
+++ b/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/WebCore/rendering/RenderSVGContainer.cpp b/WebCore/rendering/RenderSVGContainer.cpp
index c9c3cac..6e17c05 100644
--- a/WebCore/rendering/RenderSVGContainer.cpp
+++ b/WebCore/rendering/RenderSVGContainer.cpp
@@ -27,6 +27,7 @@
#include "RenderSVGContainer.h"
#include "AXObjectCache.h"
+#include "FloatQuad.h"
#include "GraphicsContext.h"
#include "RenderView.h"
#include "SVGRenderSupport.h"
@@ -44,7 +45,6 @@ RenderSVGContainer::RenderSVGContainer(SVGStyledElement* node)
, m_height(0)
, m_drawsContents(true)
{
- setReplaced(true);
}
RenderSVGContainer::~RenderSVGContainer()
@@ -198,25 +198,19 @@ void RenderSVGContainer::setDrawsContents(bool drawsContents)
m_drawsContents = drawsContents;
}
-AffineTransform RenderSVGContainer::localTransform() const
+TransformationMatrix RenderSVGContainer::localTransform() const
{
return m_localTransform;
}
-bool RenderSVGContainer::requiresLayer()
+int RenderSVGContainer::lineHeight(bool, bool) const
{
- // Only allow an <svg> element to generate a layer when it's positioned in a non-SVG context
- return false;
+ return height();
}
-int RenderSVGContainer::lineHeight(bool b, bool isRootLineBox) const
+int RenderSVGContainer::baselinePosition(bool, bool) const
{
- return height() + marginTop() + marginBottom();
-}
-
-int RenderSVGContainer::baselinePosition(bool b, bool isRootLineBox) const
-{
- return height() + marginTop() + marginBottom();
+ return height();
}
bool RenderSVGContainer::calculateLocalTransform()
@@ -237,7 +231,7 @@ void RenderSVGContainer::layout()
bool checkForRepaint = checkForRepaintDuringLayout() && selfWillPaint();
if (checkForRepaint) {
oldBounds = m_absoluteBounds;
- oldOutlineBox = absoluteOutlineBox();
+ oldOutlineBox = absoluteOutlineBounds();
}
calculateLocalTransform();
@@ -299,7 +293,7 @@ void RenderSVGContainer::applyContentTransforms(PaintInfo& paintInfo)
paintInfo.context->concatCTM(localTransform());
}
-void RenderSVGContainer::applyAdditionalTransforms(PaintInfo& paintInfo)
+void RenderSVGContainer::applyAdditionalTransforms(PaintInfo&)
{
// no-op
}
@@ -322,7 +316,7 @@ bool RenderSVGContainer::selfWillPaint() const
return false;
}
-void RenderSVGContainer::paint(PaintInfo& paintInfo, int parentX, int parentY)
+void RenderSVGContainer::paint(PaintInfo& paintInfo, int, int)
{
if (paintInfo.context->paintingDisabled() || !drawsContents())
return;
@@ -358,17 +352,17 @@ void RenderSVGContainer::paint(PaintInfo& paintInfo, int parentX, int parentY)
paintOutline(paintInfo.context, m_absoluteBounds.x(), m_absoluteBounds.y(), m_absoluteBounds.width(), m_absoluteBounds.height(), style());
}
-AffineTransform RenderSVGContainer::viewportTransform() const
+TransformationMatrix RenderSVGContainer::viewportTransform() const
{
- return AffineTransform();
+ return TransformationMatrix();
}
-IntRect RenderSVGContainer::absoluteClippedOverflowRect()
+IntRect RenderSVGContainer::clippedOverflowRectForRepaint(RenderBox* repaintContainer)
{
FloatRect repaintRect;
for (RenderObject* current = firstChild(); current != 0; current = current->nextSibling())
- repaintRect.unite(current->absoluteClippedOverflowRect());
+ repaintRect.unite(current->clippedOverflowRectForRepaint(repaintContainer));
#if ENABLE(SVG_FILTERS)
// Filters can expand the bounding box
@@ -383,7 +377,7 @@ IntRect RenderSVGContainer::absoluteClippedOverflowRect()
return enclosingIntRect(repaintRect);
}
-void RenderSVGContainer::addFocusRingRects(GraphicsContext* graphicsContext, int tx, int ty)
+void RenderSVGContainer::addFocusRingRects(GraphicsContext* graphicsContext, int, int)
{
graphicsContext->addFocusRingRect(m_absoluteBounds);
}
@@ -393,6 +387,11 @@ void RenderSVGContainer::absoluteRects(Vector<IntRect>& rects, int, int, bool)
rects.append(absoluteClippedOverflowRect());
}
+void RenderSVGContainer::absoluteQuads(Vector<FloatQuad>& quads, bool)
+{
+ quads.append(absoluteClippedOverflowRect());
+}
+
FloatRect RenderSVGContainer::relativeBBox(bool includeStroke) const
{
FloatRect rect;
@@ -426,6 +425,14 @@ bool RenderSVGContainer::nodeAtPoint(const HitTestRequest& request, HitTestResul
return false;
}
+IntRect RenderSVGContainer::outlineBoundsForRepaint(RenderBox* /*repaintContainer*/) const
+{
+ // FIXME: handle non-root repaintContainer
+ IntRect result = m_absoluteBounds;
+ adjustRectForOutlineAndShadow(result);
+ return result;
+}
+
}
#endif // ENABLE(SVG)
diff --git a/WebCore/rendering/RenderSVGContainer.h b/WebCore/rendering/RenderSVGContainer.h
index 06751a3..e498a8a 100644
--- a/WebCore/rendering/RenderSVGContainer.h
+++ b/WebCore/rendering/RenderSVGContainer.h
@@ -40,8 +40,8 @@ public:
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; }
+ int width() const { return m_width; }
+ int height() const { return m_height; }
virtual bool canHaveChildren() const;
virtual void addChild(RenderObject* newChild, RenderObject* beforeChild = 0);
@@ -69,22 +69,23 @@ public:
virtual bool isSVGContainer() const { return true; }
virtual const char* renderName() const { return "RenderSVGContainer"; }
- virtual bool requiresLayer();
+ virtual bool requiresLayer() const { return false; }
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 IntRect clippedOverflowRectForRepaint(RenderBox* repaintContainer);
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 bool calculateLocalTransform();
- virtual AffineTransform localTransform() const;
- virtual AffineTransform viewportTransform() const;
+ virtual TransformationMatrix localTransform() const;
+ virtual TransformationMatrix viewportTransform() const;
virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, int x, int y, int tx, int ty, HitTestAction);
@@ -94,6 +95,8 @@ protected:
void calcBounds();
+ virtual IntRect outlineBoundsForRepaint(RenderBox* /*repaintContainer*/) const;
+
private:
int calcReplacedWidth() const;
int calcReplacedHeight() const;
@@ -110,7 +113,7 @@ private:
protected:
IntRect m_absoluteBounds;
- AffineTransform m_localTransform;
+ TransformationMatrix m_localTransform;
};
} // namespace WebCore
diff --git a/WebCore/rendering/RenderSVGHiddenContainer.cpp b/WebCore/rendering/RenderSVGHiddenContainer.cpp
index bc758e5..23ae13e 100644
--- a/WebCore/rendering/RenderSVGHiddenContainer.cpp
+++ b/WebCore/rendering/RenderSVGHiddenContainer.cpp
@@ -39,17 +39,12 @@ RenderSVGHiddenContainer::~RenderSVGHiddenContainer()
{
}
-bool RenderSVGHiddenContainer::requiresLayer()
-{
- return false;
-}
-
-int RenderSVGHiddenContainer::lineHeight(bool b, bool isRootLineBox) const
+int RenderSVGHiddenContainer::lineHeight(bool, bool) const
{
return 0;
}
-int RenderSVGHiddenContainer::baselinePosition(bool b, bool isRootLineBox) const
+int RenderSVGHiddenContainer::baselinePosition(bool, bool) const
{
return 0;
}
@@ -76,32 +71,37 @@ void RenderSVGHiddenContainer::paint(PaintInfo&, int, int)
// This subtree does not paint.
}
-IntRect RenderSVGHiddenContainer::absoluteClippedOverflowRect()
+IntRect RenderSVGHiddenContainer::clippedOverflowRectForRepaint(RenderBox* /*repaintContainer*/)
{
return IntRect();
}
-void RenderSVGHiddenContainer::absoluteRects(Vector<IntRect>& rects, int, int, bool)
+void RenderSVGHiddenContainer::absoluteRects(Vector<IntRect>&, int, int, bool)
+{
+ // This subtree does not take up space or paint
+}
+
+void RenderSVGHiddenContainer::absoluteQuads(Vector<FloatQuad>&, bool)
{
// This subtree does not take up space or paint
}
-AffineTransform RenderSVGHiddenContainer::absoluteTransform() const
+TransformationMatrix RenderSVGHiddenContainer::absoluteTransform() const
{
- return AffineTransform();
+ return TransformationMatrix();
}
-AffineTransform RenderSVGHiddenContainer::localTransform() const
+TransformationMatrix RenderSVGHiddenContainer::localTransform() const
{
- return AffineTransform();
+ return TransformationMatrix();
}
-bool RenderSVGHiddenContainer::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, int _x, int _y, int _tx, int _ty, HitTestAction hitTestAction)
+bool RenderSVGHiddenContainer::nodeAtPoint(const HitTestRequest&, HitTestResult&, int, int, int, int, HitTestAction)
{
return false;
}
-FloatRect RenderSVGHiddenContainer::relativeBBox(bool includeStroke) const
+FloatRect RenderSVGHiddenContainer::relativeBBox(bool) const
{
return FloatRect();
}
diff --git a/WebCore/rendering/RenderSVGHiddenContainer.h b/WebCore/rendering/RenderSVGHiddenContainer.h
index c428a79..282e3f3 100644
--- a/WebCore/rendering/RenderSVGHiddenContainer.h
+++ b/WebCore/rendering/RenderSVGHiddenContainer.h
@@ -43,7 +43,7 @@ namespace WebCore {
virtual const char* renderName() const { return "RenderSVGHiddenContainer"; }
- virtual bool requiresLayer();
+ virtual bool requiresLayer() const { return false; }
virtual int lineHeight(bool b, bool isRootLineBox = false) const;
virtual int baselinePosition(bool b, bool isRootLineBox = false) const;
@@ -51,11 +51,12 @@ namespace WebCore {
virtual void layout();
virtual void paint(PaintInfo&, int parentX, int parentY);
- virtual IntRect absoluteClippedOverflowRect();
+ virtual IntRect clippedOverflowRectForRepaint(RenderBox* repaintContainer);
virtual void absoluteRects(Vector<IntRect>& rects, int tx, int ty, bool topLevel = true);
+ virtual void absoluteQuads(Vector<FloatQuad>&, bool topLevel = true);
- virtual AffineTransform absoluteTransform() const;
- virtual AffineTransform localTransform() const;
+ virtual TransformationMatrix absoluteTransform() const;
+ virtual TransformationMatrix localTransform() const;
virtual FloatRect relativeBBox(bool includeStroke = true) const;
virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, int x, int y, int tx, int ty, HitTestAction);
diff --git a/WebCore/rendering/RenderSVGImage.cpp b/WebCore/rendering/RenderSVGImage.cpp
index 345e79f..503663a 100644
--- a/WebCore/rendering/RenderSVGImage.cpp
+++ b/WebCore/rendering/RenderSVGImage.cpp
@@ -29,6 +29,7 @@
#include "Attr.h"
#include "FloatConversion.h"
+#include "FloatQuad.h"
#include "GraphicsContext.h"
#include "PointerEventsHitRules.h"
#include "SVGImageElement.h"
@@ -127,7 +128,7 @@ void RenderSVGImage::adjustRectsForAspectRatio(FloatRect& destRect, FloatRect& s
bool RenderSVGImage::calculateLocalTransform()
{
- AffineTransform oldTransform = m_localTransform;
+ TransformationMatrix oldTransform = m_localTransform;
m_localTransform = static_cast<SVGStyledTransformableElement*>(element())->animatedLocalTransform();
return (m_localTransform != oldTransform);
}
@@ -141,13 +142,13 @@ void RenderSVGImage::layout()
bool checkForRepaint = checkForRepaintDuringLayout();
if (checkForRepaint) {
oldBounds = absoluteClippedOverflowRect();
- oldOutlineBox = absoluteOutlineBox();
+ oldOutlineBox = absoluteOutlineBounds();
}
calculateLocalTransform();
// minimum height
- m_height = errorOccurred() ? intrinsicSize().height() : 0;
+ setHeight(errorOccurred() ? intrinsicSize().height() : 0);
calcWidth();
calcHeight();
@@ -193,13 +194,13 @@ void RenderSVGImage::paint(PaintInfo& paintInfo, int, int)
paintInfo.context->restore();
}
-bool RenderSVGImage::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, int _x, int _y, int, int, HitTestAction hitTestAction)
+bool RenderSVGImage::nodeAtPoint(const HitTestRequest&, HitTestResult& result, int _x, int _y, int, int, HitTestAction hitTestAction)
{
// We only draw in the forground phase, so we only hit-test then.
if (hitTestAction != HitTestForeground)
return false;
- PointerEventsHitRules hitRules(PointerEventsHitRules::SVG_IMAGE_HITTESTING, style()->svgStyle()->pointerEvents());
+ PointerEventsHitRules hitRules(PointerEventsHitRules::SVG_IMAGE_HITTESTING, style()->pointerEvents());
bool isVisible = (style()->visibility() == VISIBLE);
if (isVisible || !hitRules.requireVisible) {
@@ -217,19 +218,14 @@ bool RenderSVGImage::nodeAtPoint(const HitTestRequest& request, HitTestResult& r
return false;
}
-bool RenderSVGImage::requiresLayer()
-{
- return false;
-}
-
FloatRect RenderSVGImage::relativeBBox(bool) const
{
return m_localBounds;
}
-void RenderSVGImage::imageChanged(WrappedImagePtr image)
+void RenderSVGImage::imageChanged(WrappedImagePtr image, const IntRect* rect)
{
- RenderImage::imageChanged(image);
+ RenderImage::imageChanged(image, rect);
// We override to invalidate a larger rect, since SVG images can draw outside their "bounds"
repaintRectangle(absoluteClippedOverflowRect());
@@ -237,6 +233,7 @@ void RenderSVGImage::imageChanged(WrappedImagePtr image)
void RenderSVGImage::calculateAbsoluteBounds()
{
+ // FIXME: broken with CSS transforms
FloatRect absoluteRect = absoluteTransform().mapRect(relativeBBox(true));
#if ENABLE(SVG_FILTERS)
@@ -252,12 +249,13 @@ void RenderSVGImage::calculateAbsoluteBounds()
m_absoluteBounds = enclosingIntRect(absoluteRect);
}
-IntRect RenderSVGImage::absoluteClippedOverflowRect()
+IntRect RenderSVGImage::clippedOverflowRectForRepaint(RenderBox* /*repaintContainer*/)
{
+ // FIXME: handle non-root repaintContainer
return m_absoluteBounds;
}
-void RenderSVGImage::addFocusRingRects(GraphicsContext* graphicsContext, int tx, int ty)
+void RenderSVGImage::addFocusRingRects(GraphicsContext* graphicsContext, int, int)
{
// this is called from paint() after the localTransform has already been applied
IntRect contentRect = enclosingIntRect(relativeBBox());
@@ -269,6 +267,11 @@ void RenderSVGImage::absoluteRects(Vector<IntRect>& rects, int, int, bool)
rects.append(absoluteClippedOverflowRect());
}
+void RenderSVGImage::absoluteQuads(Vector<FloatQuad>& quads, bool)
+{
+ quads.append(FloatRect(absoluteClippedOverflowRect()));
+}
+
}
#endif // ENABLE(SVG)
diff --git a/WebCore/rendering/RenderSVGImage.h b/WebCore/rendering/RenderSVGImage.h
index 4891306..cb440d2 100644
--- a/WebCore/rendering/RenderSVGImage.h
+++ b/WebCore/rendering/RenderSVGImage.h
@@ -26,7 +26,7 @@
#if ENABLE(SVG)
-#include "AffineTransform.h"
+#include "TransformationMatrix.h"
#include "FloatRect.h"
#include "RenderImage.h"
@@ -40,20 +40,21 @@ namespace WebCore {
RenderSVGImage(SVGImageElement*);
virtual ~RenderSVGImage();
- virtual AffineTransform localTransform() const { return m_localTransform; }
+ virtual TransformationMatrix localTransform() const { return m_localTransform; }
virtual FloatRect relativeBBox(bool includeStroke = true) const;
- virtual IntRect absoluteClippedOverflowRect();
+ virtual IntRect clippedOverflowRectForRepaint(RenderBox* repaintContainer);
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 void imageChanged(WrappedImagePtr);
+ virtual void imageChanged(WrappedImagePtr, const IntRect* = 0);
void adjustRectsForAspectRatio(FloatRect& destRect, FloatRect& srcRect, SVGPreserveAspectRatio*);
virtual void layout();
virtual void paint(PaintInfo&, int parentX, int parentY);
- bool requiresLayer();
+ bool requiresLayer() const { return false; }
virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, int _x, int _y, int _tx, int _ty, HitTestAction);
@@ -61,7 +62,7 @@ namespace WebCore {
private:
void calculateAbsoluteBounds();
- AffineTransform m_localTransform;
+ TransformationMatrix m_localTransform;
FloatRect m_localBounds;
IntRect m_absoluteBounds;
};
diff --git a/WebCore/rendering/RenderSVGInline.cpp b/WebCore/rendering/RenderSVGInline.cpp
index 11da004..81e0924 100644
--- a/WebCore/rendering/RenderSVGInline.cpp
+++ b/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
@@ -27,6 +27,7 @@
#include "RenderSVGInline.h"
#include "SVGInlineFlowBox.h"
+#include <wtf/UnusedParam.h>
namespace WebCore {
@@ -35,10 +36,16 @@ RenderSVGInline::RenderSVGInline(Node* n)
{
}
-InlineBox* RenderSVGInline::createInlineBox(bool makePlaceHolderBox, bool isRootLineBox, bool isOnlyRun)
+InlineBox* RenderSVGInline::createInlineBox(bool unusedMakePlaceHolderBox, bool unusedIsRootLineBox, bool)
{
- ASSERT(!(!isRootLineBox && (isReplaced() || makePlaceHolderBox)));
- ASSERT(isInlineFlow());
+#if ASSERT_DISABLED
+ UNUSED_PARAM(unusedIsRootLineBox);
+ UNUSED_PARAM(unusedMakePlaceHolderBox);
+#endif
+
+ ASSERT(!(!unusedIsRootLineBox && (isReplaced() || unusedMakePlaceHolderBox)));
+
+ ASSERT(isRenderInline());
InlineFlowBox* flowBox = new (renderArena()) SVGInlineFlowBox(this);
diff --git a/WebCore/rendering/RenderSVGInline.h b/WebCore/rendering/RenderSVGInline.h
index 42fdafc..060ba58 100644
--- a/WebCore/rendering/RenderSVGInline.h
+++ b/WebCore/rendering/RenderSVGInline.h
@@ -33,7 +33,7 @@ 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; }
+ virtual bool requiresLayer() const { return false; }
};
}
diff --git a/WebCore/rendering/RenderSVGInlineText.cpp b/WebCore/rendering/RenderSVGInlineText.cpp
index 33a984c..215e9fe 100644
--- a/WebCore/rendering/RenderSVGInlineText.cpp
+++ b/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,11 +55,27 @@ RenderSVGInlineText::RenderSVGInlineText(Node* n, PassRefPtr<StringImpl> str)
{
}
+
+void RenderSVGInlineText::styleDidChange(RenderStyle::Diff diff, const RenderStyle* oldStyle)
+{
+ // Skip RenderText's work.
+ RenderObject::styleDidChange(diff, oldStyle);
+
+ // SVG text is apparently always transformed.
+ if (RefPtr<StringImpl> textToTransform = originalText())
+ setText(textToTransform.release(), true);
+}
+
void RenderSVGInlineText::absoluteRects(Vector<IntRect>& rects, int, int, bool)
{
rects.append(computeAbsoluteRectForRange(0, textLength()));
}
+void RenderSVGInlineText::absoluteQuads(Vector<FloatQuad>& quads, bool)
+{
+ quads.append(FloatRect(computeAbsoluteRectForRange(0, textLength())));
+}
+
IntRect RenderSVGInlineText::selectionRect(bool)
{
ASSERT(!needsLayout());
@@ -107,14 +125,15 @@ IntRect RenderSVGInlineText::computeAbsoluteRectForRange(int startPos, int endPo
rect.unite(box->selectionRect(0, 0, startPos, endPos));
// Mimic RenderBox::computeAbsoluteRepaintRect() functionality. But only the subset needed for SVG and respecting SVG transformations.
- int x, y;
- cb->container()->absolutePosition(x, y);
+ 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>.
- AffineTransform htmlParentCtm = root->RenderContainer::absoluteTransform();
+ TransformationMatrix htmlParentCtm = root->RenderContainer::absoluteTransform();
- FloatRect fixedRect(narrowPrecisionToFloat(rect.x() + x - xPos() - htmlParentCtm.e()), narrowPrecisionToFloat(rect.y() + y - yPos() - htmlParentCtm.f()), rect.width(), rect.height());
+ FloatRect fixedRect(narrowPrecisionToFloat(rect.x() + absPos.x() - (firstTextBox() ? firstTextBox()->xPos() : 0) - htmlParentCtm.e()),
+ narrowPrecisionToFloat(rect.y() + absPos.y() - (firstTextBox() ? firstTextBox()->yPos() : 0) - htmlParentCtm.f()), rect.width(), rect.height());
+ // FIXME: broken with CSS transforms
return enclosingIntRect(absoluteTransform().mapRect(fixedRect));
}
@@ -123,9 +142,10 @@ InlineTextBox* RenderSVGInlineText::createInlineTextBox()
return new (renderArena()) SVGInlineTextBox(this);
}
-IntRect RenderSVGInlineText::caretRect(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();
}
@@ -137,7 +157,7 @@ VisiblePosition RenderSVGInlineText::positionForCoordinates(int x, int y)
return VisiblePosition(element(), 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);
@@ -145,7 +165,7 @@ VisiblePosition RenderSVGInlineText::positionForCoordinates(int x, int y)
int offset = 0;
for (SVGInlineTextBox* box = textBox; box; box = static_cast<SVGInlineTextBox*>(box->nextTextBox())) {
- if (box->svgCharacterHitsPosition(x + object->xPos(), y + object->yPos(), offset)) {
+ if (box->svgCharacterHitsPosition(x + object->x(), y + object->y(), offset)) {
// 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)
diff --git a/WebCore/rendering/RenderSVGInlineText.h b/WebCore/rendering/RenderSVGInlineText.h
index 786ba31..55fd838 100644
--- a/WebCore/rendering/RenderSVGInlineText.h
+++ b/WebCore/rendering/RenderSVGInlineText.h
@@ -34,13 +34,18 @@ class RenderSVGInlineText : public RenderText {
public:
RenderSVGInlineText(Node*, PassRefPtr<StringImpl>);
virtual const char* renderName() const { return "RenderSVGInlineText"; }
+
+ virtual void styleDidChange(RenderStyle::Diff, const RenderStyle*);
+
virtual void absoluteRects(Vector<IntRect>& rects, int tx, int ty, bool topLevel = true);
- virtual bool requiresLayer() { return false; }
+ virtual void absoluteQuads(Vector<FloatQuad>&, bool topLevel = true);
+
+ virtual bool requiresLayer() const { return false; }
virtual IntRect selectionRect(bool clipToVisibleContent = true);
virtual bool isSVGText() const { return true; }
virtual InlineTextBox* createInlineTextBox();
- virtual IntRect caretRect(InlineBox*, int caretOffset, int* extraWidthToEndOfLine = 0);
+ virtual IntRect localCaretRect(InlineBox*, int caretOffset, int* extraWidthToEndOfLine = 0);
virtual VisiblePosition positionForCoordinates(int x, int y);
virtual void destroy();
diff --git a/WebCore/rendering/RenderSVGRoot.cpp b/WebCore/rendering/RenderSVGRoot.cpp
index 1c59450..54a30df 100644
--- a/WebCore/rendering/RenderSVGRoot.cpp
+++ b/WebCore/rendering/RenderSVGRoot.cpp
@@ -1,6 +1,6 @@
/*
Copyright (C) 2004, 2005, 2007 Nikolas Zimmermann <zimmermann@kde.org>
- 2004, 2005, 2007, 2008 Rob Buis <buis@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
@@ -53,12 +53,12 @@ RenderSVGRoot::~RenderSVGRoot()
{
}
-int RenderSVGRoot::lineHeight(bool b, bool isRootLineBox) const
+int RenderSVGRoot::lineHeight(bool, bool) const
{
return height() + marginTop() + marginBottom();
}
-int RenderSVGRoot::baselinePosition(bool b, bool isRootLineBox) const
+int RenderSVGRoot::baselinePosition(bool, bool) const
{
return height() + marginTop() + marginBottom();
}
@@ -95,19 +95,19 @@ void RenderSVGRoot::layout()
IntRect oldOutlineBox;
bool checkForRepaint = checkForRepaintDuringLayout() && selfNeedsLayout();
if (checkForRepaint)
- oldOutlineBox = absoluteOutlineBox();
+ oldOutlineBox = absoluteOutlineBounds();
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());
+ setWidth(static_cast<int>(width() * svg->currentScale()));
+ setHeight(static_cast<int>(height() * svg->currentScale()));
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());
@@ -125,30 +125,30 @@ void RenderSVGRoot::applyContentTransforms(PaintInfo& paintInfo, int parentX, in
// 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(x(), y());
origin.move(borderLeft(), borderTop());
origin.move(paddingLeft(), paddingTop());
if (origin.x() || origin.y()) {
- paintInfo.context->concatCTM(AffineTransform().translate(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
- AffineTransform ctm = RenderContainer::absoluteTransform();
+ 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(AffineTransform().scale(svg->currentScale()));
+ 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(AffineTransform().translate(viewport().x(), viewport().y()));
+ paintInfo.context->concatCTM(TransformationMatrix().translate(viewport().x(), viewport().y()));
}
- paintInfo.context->concatCTM(AffineTransform().translate(svg->currentTranslate().x(), svg->currentTranslate().y()));
+ paintInfo.context->concatCTM(TransformationMatrix().translate(svg->currentTranslate().x(), svg->currentTranslate().y()));
}
void RenderSVGRoot::paint(PaintInfo& paintInfo, int parentX, int parentY)
@@ -165,7 +165,7 @@ void RenderSVGRoot::paint(PaintInfo& paintInfo, int parentX, int parentY)
// This should only exist for <svg> renderers
if (hasBoxDecorations() && (paintInfo.phase == PaintPhaseForeground || paintInfo.phase == PaintPhaseSelection))
- paintBoxDecorations(paintInfo, m_x + parentX, m_y + parentY);
+ paintBoxDecorations(paintInfo, x() + parentX, y() + parentY);
if (!firstChild()) {
#if ENABLE(SVG_FILTERS)
@@ -231,12 +231,12 @@ void RenderSVGRoot::calcViewport()
}
}
-IntRect RenderSVGRoot::absoluteClippedOverflowRect()
+IntRect RenderSVGRoot::clippedOverflowRectForRepaint(RenderBox* repaintContainer)
{
IntRect repaintRect;
for (RenderObject* current = firstChild(); current != 0; current = current->nextSibling())
- repaintRect.unite(current->absoluteClippedOverflowRect());
+ repaintRect.unite(current->clippedOverflowRectForRepaint(repaintContainer));
#if ENABLE(SVG_FILTERS)
// Filters can expand the bounding box
@@ -259,10 +259,16 @@ void RenderSVGRoot::absoluteRects(Vector<IntRect>& rects, int, int)
current->absoluteRects(rects, 0, 0);
}
-AffineTransform RenderSVGRoot::absoluteTransform() const
+void RenderSVGRoot::absoluteQuads(Vector<FloatQuad>& quads, bool)
{
- AffineTransform ctm = RenderContainer::absoluteTransform();
- ctm.translate(m_x, m_y);
+ for (RenderObject* current = firstChild(); current != 0; current = current->nextSibling())
+ current->absoluteQuads(quads);
+}
+
+TransformationMatrix RenderSVGRoot::absoluteTransform() const
+{
+ TransformationMatrix ctm = RenderContainer::absoluteTransform();
+ ctm.translate(x(), y());
SVGSVGElement* svg = static_cast<SVGSVGElement*>(element());
ctm.scale(svg->currentScale());
ctm.translate(svg->currentTranslate().x(), svg->currentTranslate().y());
@@ -287,14 +293,14 @@ FloatRect RenderSVGRoot::relativeBBox(bool includeStroke) const
return rect;
}
-AffineTransform RenderSVGRoot::localTransform() const
+TransformationMatrix RenderSVGRoot::localTransform() const
{
- return AffineTransform();
+ return TransformationMatrix();
}
bool RenderSVGRoot::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, int _x, int _y, int _tx, int _ty, HitTestAction hitTestAction)
{
- AffineTransform ctm = RenderContainer::absoluteTransform();
+ TransformationMatrix ctm = RenderContainer::absoluteTransform();
int sx = (_tx - static_cast<int>(ctm.e())); // scroll offset
int sy = (_ty - static_cast<int>(ctm.f())); // scroll offset
@@ -302,8 +308,8 @@ bool RenderSVGRoot::nodeAtPoint(const HitTestRequest& request, HitTestResult& re
if (!viewport().isEmpty()
&& style()->overflowX() == OHIDDEN
&& style()->overflowY() == OHIDDEN) {
- int tx = m_x - _tx + sx;
- int ty = m_y - _ty + sy;
+ int tx = x() - _tx + sx;
+ int ty = y() - _ty + sy;
// Check if we need to do anything at all.
IntRect overflowBox = overflowRect(false);
@@ -327,6 +333,13 @@ bool RenderSVGRoot::nodeAtPoint(const HitTestRequest& request, HitTestResult& re
return false;
}
+void RenderSVGRoot::position(InlineBox* box)
+{
+ RenderContainer::position(box);
+ if (m_absoluteBounds.isEmpty())
+ setNeedsLayout(true, false);
+}
+
}
#endif // ENABLE(SVG)
diff --git a/WebCore/rendering/RenderSVGRoot.h b/WebCore/rendering/RenderSVGRoot.h
index 58359fd..048fc8b 100644
--- a/WebCore/rendering/RenderSVGRoot.h
+++ b/WebCore/rendering/RenderSVGRoot.h
@@ -30,7 +30,7 @@
namespace WebCore {
class SVGStyledElement;
-class AffineTransform;
+class TransformationMatrix;
class RenderSVGRoot : public RenderContainer {
public:
@@ -47,21 +47,24 @@ public:
virtual void layout();
virtual void paint(PaintInfo&, int parentX, int parentY);
- virtual IntRect absoluteClippedOverflowRect();
+ virtual IntRect clippedOverflowRectForRepaint(RenderBox* repaintContainer);
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 AffineTransform absoluteTransform() const;
+ virtual TransformationMatrix absoluteTransform() const;
bool fillContains(const FloatPoint&) const;
bool strokeContains(const FloatPoint&) const;
FloatRect relativeBBox(bool includeStroke = true) const;
- virtual AffineTransform localTransform() const;
+ virtual TransformationMatrix localTransform() const;
FloatRect viewport() const;
virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, int x, int y, int tx, int ty, HitTestAction);
+
+ virtual void position(InlineBox*);
private:
void calcViewport();
diff --git a/WebCore/rendering/RenderSVGTSpan.cpp b/WebCore/rendering/RenderSVGTSpan.cpp
index a8d6c57..49c45df 100644
--- a/WebCore/rendering/RenderSVGTSpan.cpp
+++ b/WebCore/rendering/RenderSVGTSpan.cpp
@@ -26,7 +26,8 @@
#if ENABLE(SVG)
#include "RenderSVGTSpan.h"
-#include "FloatRect.h"
+#include "FloatQuad.h"
+#include "RenderBlock.h"
#include "SVGInlineTextBox.h"
#include "SVGRootInlineBox.h"
@@ -42,20 +43,41 @@ 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;
+ RenderBox* object = rootBox ? rootBox->block() : 0;
if (!object)
return;
- int xRef = object->xPos() + xPos();
- int yRef = object->yPos() + yPos();
+ int xRef = object->x() + x();
+ int yRef = object->y() + y();
for (InlineRunBox* curr = firstBox; curr; curr = curr->nextLineBox()) {
FloatRect rect(xRef + curr->xPos(), yRef + curr->yPos(), curr->width(), curr->height());
+ // FIXME: broken with CSS transforms
rects.append(enclosingIntRect(absoluteTransform().mapRect(rect)));
}
}
+void RenderSVGTSpan::absoluteQuads(Vector<FloatQuad>& quads, bool)
+{
+ 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() + x();
+ int yRef = object->y() + y();
+
+ for (InlineRunBox* curr = firstBox; curr; curr = curr->nextLineBox()) {
+ FloatRect rect(xRef + curr->xPos(), yRef + curr->yPos(), curr->width(), curr->height());
+ // FIXME: broken with CSS transforms
+ quads.append(absoluteTransform().mapRect(rect));
+ }
+}
+
}
#endif // ENABLE(SVG)
diff --git a/WebCore/rendering/RenderSVGTSpan.h b/WebCore/rendering/RenderSVGTSpan.h
index cabf2ef..d34cd2f 100644
--- a/WebCore/rendering/RenderSVGTSpan.h
+++ b/WebCore/rendering/RenderSVGTSpan.h
@@ -33,6 +33,7 @@ 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);
};
}
diff --git a/WebCore/rendering/RenderSVGText.cpp b/WebCore/rendering/RenderSVGText.cpp
index 2f0e2d6..ee5ab34 100644
--- a/WebCore/rendering/RenderSVGText.cpp
+++ b/WebCore/rendering/RenderSVGText.cpp
@@ -30,16 +30,17 @@
#include "RenderSVGText.h"
#include "FloatConversion.h"
+#include "FloatQuad.h"
#include "GraphicsContext.h"
#include "PointerEventsHitRules.h"
#include "RenderSVGRoot.h"
-#include "SimpleFontData.h"
#include "SVGLengthList.h"
#include "SVGResourceFilter.h"
#include "SVGRootInlineBox.h"
#include "SVGTextElement.h"
#include "SVGTransformList.h"
#include "SVGURIReference.h"
+#include "SimpleFontData.h"
namespace WebCore {
@@ -48,8 +49,9 @@ RenderSVGText::RenderSVGText(SVGTextElement* node)
{
}
-IntRect RenderSVGText::absoluteClippedOverflowRect()
+IntRect RenderSVGText::clippedOverflowRectForRepaint(RenderBox* /*repaintContainer*/)
{
+ // FIXME: handle non-root repaintContainer
FloatRect repaintRect = absoluteTransform().mapRect(relativeBBox(true));
#if ENABLE(SVG_FILTERS)
@@ -65,14 +67,9 @@ IntRect RenderSVGText::absoluteClippedOverflowRect()
return enclosingIntRect(repaintRect);
}
-bool RenderSVGText::requiresLayer()
-{
- return false;
-}
-
bool RenderSVGText::calculateLocalTransform()
{
- AffineTransform oldTransform = m_localTransform;
+ TransformationMatrix oldTransform = m_localTransform;
m_localTransform = static_cast<SVGTextElement*>(element())->animatedLocalTransform();
return (oldTransform != m_localTransform);
}
@@ -89,14 +86,14 @@ void RenderSVGText::layout()
bool checkForRepaint = checkForRepaintDuringLayout();
if (checkForRepaint) {
oldBounds = m_absoluteBounds;
- oldOutlineBox = absoluteOutlineBox();
+ oldOutlineBox = absoluteOutlineBounds();
}
// Best guess for a relative starting point
SVGTextElement* text = static_cast<SVGTextElement*>(element());
int xOffset = (int)(text->x()->getFirst().value(text));
int yOffset = (int)(text->y()->getFirst().value(text));
- setPos(xOffset, yOffset);
+ setLocation(xOffset, yOffset);
calculateLocalTransform();
@@ -111,9 +108,9 @@ void RenderSVGText::layout()
setNeedsLayout(false);
}
-InlineBox* RenderSVGText::createInlineBox(bool makePlaceHolderBox, bool isRootLineBox, bool isOnlyRun)
+InlineBox* RenderSVGText::createInlineBox(bool, bool, bool)
{
- ASSERT(!isInlineFlow());
+ ASSERT(!isRenderInline());
InlineFlowBox* flowBox = new (renderArena()) SVGRootInlineBox(this);
if (!m_firstLineBox)
@@ -129,12 +126,12 @@ InlineBox* RenderSVGText::createInlineBox(bool makePlaceHolderBox, bool isRootLi
bool RenderSVGText::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, int _x, int _y, int _tx, int _ty, HitTestAction hitTestAction)
{
- PointerEventsHitRules hitRules(PointerEventsHitRules::SVG_TEXT_HITTESTING, style()->svgStyle()->pointerEvents());
+ 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))) {
- AffineTransform totalTransform = absoluteTransform();
+ TransformationMatrix totalTransform = absoluteTransform();
double localX, localY;
totalTransform.inverse().map(_x, _y, &localX, &localY);
FloatPoint hitPoint(_x, _y);
@@ -151,10 +148,9 @@ void RenderSVGText::absoluteRects(Vector<IntRect>& rects, int, int, bool)
if (!root)
return;
- int x, y;
- absolutePosition(x, y);
+ FloatPoint absPos = localToAbsolute();
- AffineTransform htmlParentCtm = root->RenderContainer::absoluteTransform();
+ TransformationMatrix htmlParentCtm = root->RenderContainer::absoluteTransform();
// Don't use relativeBBox here, as it's unites the selection rects. Makes it hard
// to spot errors, if there are any using WebInspector. Individually feed them into 'rects'.
@@ -164,12 +160,38 @@ void RenderSVGText::absoluteRects(Vector<IntRect>& rects, int, int, bool)
InlineFlowBox* flowBox = static_cast<InlineFlowBox*>(runBox);
for (InlineBox* box = flowBox->firstChild(); box; box = box->nextOnLine()) {
FloatRect boxRect(box->xPos(), box->yPos(), box->width(), box->height());
- boxRect.move(narrowPrecisionToFloat(x - htmlParentCtm.e()), narrowPrecisionToFloat(y - htmlParentCtm.f()));
+ boxRect.move(narrowPrecisionToFloat(absPos.x() - htmlParentCtm.e()), narrowPrecisionToFloat(absPos.y() - htmlParentCtm.f()));
+ // FIXME: broken with CSS transforms
rects.append(enclosingIntRect(absoluteTransform().mapRect(boxRect)));
}
}
}
+void RenderSVGText::absoluteQuads(Vector<FloatQuad>& quads, bool)
+{
+ 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
+ // 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));
+ }
+ }
+}
+
void RenderSVGText::paint(PaintInfo& paintInfo, int, int)
{
RenderObject::PaintInfo pi(paintInfo);
@@ -206,7 +228,7 @@ FloatRect RenderSVGText::relativeBBox(bool includeStroke) const
repaintRect.inflate(strokeWidth);
}
- repaintRect.move(xPos(), yPos());
+ repaintRect.move(x(), y());
return repaintRect;
}
diff --git a/WebCore/rendering/RenderSVGText.h b/WebCore/rendering/RenderSVGText.h
index ceadc82..4592f4e 100644
--- a/WebCore/rendering/RenderSVGText.h
+++ b/WebCore/rendering/RenderSVGText.h
@@ -26,7 +26,7 @@
#if ENABLE(SVG)
-#include "AffineTransform.h"
+#include "TransformationMatrix.h"
#include "RenderSVGBlock.h"
namespace WebCore {
@@ -42,22 +42,24 @@ public:
virtual bool isSVGText() const { return true; }
bool calculateLocalTransform();
- virtual AffineTransform localTransform() const { return m_localTransform; }
+ virtual TransformationMatrix localTransform() 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 requiresLayer() const { return false; }
virtual void layout();
virtual void absoluteRects(Vector<IntRect>&, int tx, int ty, bool topLevel = true);
- virtual IntRect absoluteClippedOverflowRect();
+ virtual void absoluteQuads(Vector<FloatQuad>&, bool topLevel = true);
+
+ virtual IntRect clippedOverflowRectForRepaint(RenderBox* repaintContainer);
virtual FloatRect relativeBBox(bool includeStroke = true) const;
virtual InlineBox* createInlineBox(bool makePlaceHolderBox, bool isRootLineBox, bool isOnlyRun = false);
private:
- AffineTransform m_localTransform;
+ TransformationMatrix m_localTransform;
IntRect m_absoluteBounds;
};
diff --git a/WebCore/rendering/RenderSVGTextPath.cpp b/WebCore/rendering/RenderSVGTextPath.cpp
index 53aa937..2d2894f 100644
--- a/WebCore/rendering/RenderSVGTextPath.cpp
+++ b/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"
@@ -82,20 +83,41 @@ 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;
+ RenderBlock* object = rootBox ? rootBox->block() : 0;
if (!object)
return;
- int xRef = object->xPos() + xPos();
- int yRef = object->yPos() + yPos();
+ int xRef = object->x() + x();
+ int yRef = object->y() + y();
for (InlineRunBox* curr = firstBox; curr; curr = curr->nextLineBox()) {
FloatRect rect(xRef + curr->xPos(), yRef + curr->yPos(), curr->width(), curr->height());
+ // FIXME: broken with CSS transforms
rects.append(enclosingIntRect(absoluteTransform().mapRect(rect)));
}
}
+void RenderSVGTextPath::absoluteQuads(Vector<FloatQuad>& quads, bool)
+{
+ InlineRunBox* firstBox = firstLineBox();
+
+ SVGRootInlineBox* rootBox = firstBox ? static_cast<SVGInlineTextBox*>(firstBox)->svgRootInlineBox() : 0;
+ RenderBlock* object = rootBox ? rootBox->block() : 0;
+
+ if (!object)
+ return;
+
+ int xRef = object->x() + x();
+ int yRef = object->y() + y();
+
+ for (InlineRunBox* curr = firstBox; curr; curr = curr->nextLineBox()) {
+ FloatRect rect(xRef + curr->xPos(), yRef + curr->yPos(), curr->width(), curr->height());
+ // FIXME: broken with CSS transforms
+ quads.append(absoluteTransform().mapRect(rect));
+ }
+}
+
}
#endif // ENABLE(SVG)
diff --git a/WebCore/rendering/RenderSVGTextPath.h b/WebCore/rendering/RenderSVGTextPath.h
index 2a66f65..4fd4cc3 100644
--- a/WebCore/rendering/RenderSVGTextPath.h
+++ b/WebCore/rendering/RenderSVGTextPath.h
@@ -39,6 +39,7 @@ namespace WebCore {
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/WebCore/rendering/RenderSVGTransformableContainer.cpp b/WebCore/rendering/RenderSVGTransformableContainer.cpp
index 98eaab0..17d64f3 100644
--- a/WebCore/rendering/RenderSVGTransformableContainer.cpp
+++ b/WebCore/rendering/RenderSVGTransformableContainer.cpp
@@ -37,7 +37,7 @@ RenderSVGTransformableContainer::RenderSVGTransformableContainer(SVGStyledTransf
bool RenderSVGTransformableContainer::calculateLocalTransform()
{
- AffineTransform oldTransform = m_localTransform;
+ TransformationMatrix oldTransform = m_localTransform;
m_localTransform = static_cast<SVGStyledTransformableElement*>(element())->animatedLocalTransform();
return (m_localTransform != oldTransform);
}
diff --git a/WebCore/rendering/RenderSVGViewportContainer.cpp b/WebCore/rendering/RenderSVGViewportContainer.cpp
index b6d527b..4282efc 100644
--- a/WebCore/rendering/RenderSVGViewportContainer.cpp
+++ b/WebCore/rendering/RenderSVGViewportContainer.cpp
@@ -37,7 +37,6 @@ namespace WebCore {
RenderSVGViewportContainer::RenderSVGViewportContainer(SVGStyledElement* node)
: RenderSVGContainer(node)
{
- setReplaced(true);
}
RenderSVGViewportContainer::~RenderSVGViewportContainer()
@@ -57,7 +56,7 @@ void RenderSVGViewportContainer::layout()
IntRect oldOutlineBox;
bool checkForRepaint = checkForRepaintDuringLayout() && selfNeedsLayout();
if (checkForRepaint)
- oldOutlineBox = absoluteOutlineBox();
+ oldOutlineBox = absoluteOutlineBounds();
calcBounds();
@@ -91,7 +90,7 @@ void RenderSVGViewportContainer::applyContentTransforms(PaintInfo& paintInfo)
if (style()->overflowX() != OVISIBLE)
paintInfo.context->clip(enclosingIntRect(viewport())); // FIXME: Eventually we'll want float-precision clipping
- paintInfo.context->concatCTM(AffineTransform().translate(viewport().x(), viewport().y()));
+ paintInfo.context->concatCTM(TransformationMatrix().translate(viewport().x(), viewport().y()));
}
RenderSVGContainer::applyContentTransforms(paintInfo);
@@ -133,7 +132,7 @@ void RenderSVGViewportContainer::calcViewport()
}
}
-AffineTransform RenderSVGViewportContainer::viewportTransform() const
+TransformationMatrix RenderSVGViewportContainer::viewportTransform() const
{
if (element()->hasTagName(SVGNames::svgTag)) {
SVGSVGElement* svg = static_cast<SVGSVGElement*>(element());
@@ -143,12 +142,12 @@ AffineTransform RenderSVGViewportContainer::viewportTransform() const
return marker->viewBoxToViewTransform(viewport().width(), viewport().height());
}
- return AffineTransform();
+ return TransformationMatrix();
}
-AffineTransform RenderSVGViewportContainer::absoluteTransform() const
+TransformationMatrix RenderSVGViewportContainer::absoluteTransform() const
{
- AffineTransform ctm = RenderObject::absoluteTransform();
+ TransformationMatrix ctm = RenderObject::absoluteTransform();
ctm.translate(viewport().x(), viewport().y());
return viewportTransform() * ctm;
}
@@ -159,9 +158,9 @@ bool RenderSVGViewportContainer::nodeAtPoint(const HitTestRequest& request, HitT
&& style()->overflowX() == OHIDDEN
&& style()->overflowY() == OHIDDEN) {
// Check if we need to do anything at all.
- IntRect overflowBox = overflowRect(false);
+ IntRect overflowBox = IntRect(0, 0, width(), height());
overflowBox.move(_tx, _ty);
- AffineTransform ctm = RenderObject::absoluteTransform();
+ TransformationMatrix ctm = RenderObject::absoluteTransform();
ctm.translate(viewport().x(), viewport().y());
double localX, localY;
ctm.inverse().map(_x - _tx, _y - _ty, &localX, &localY);
diff --git a/WebCore/rendering/RenderSVGViewportContainer.h b/WebCore/rendering/RenderSVGViewportContainer.h
index 23a885f..2e4a49c 100644
--- a/WebCore/rendering/RenderSVGViewportContainer.h
+++ b/WebCore/rendering/RenderSVGViewportContainer.h
@@ -40,8 +40,8 @@ public:
virtual void layout();
virtual void paint(PaintInfo&, int parentX, int parentY);
- virtual AffineTransform absoluteTransform() const;
- virtual AffineTransform viewportTransform() const;
+ virtual TransformationMatrix absoluteTransform() const;
+ virtual TransformationMatrix viewportTransform() const;
virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, int x, int y, int tx, int ty, HitTestAction);
diff --git a/WebCore/rendering/RenderScrollbar.cpp b/WebCore/rendering/RenderScrollbar.cpp
index b7045d6..d6dd9cc 100644
--- a/WebCore/rendering/RenderScrollbar.cpp
+++ b/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);
}
}
diff --git a/WebCore/rendering/RenderScrollbar.h b/WebCore/rendering/RenderScrollbar.h
index ad97001..cc43a00 100644
--- a/WebCore/rendering/RenderScrollbar.h
+++ b/WebCore/rendering/RenderScrollbar.h
@@ -32,17 +32,17 @@
namespace WebCore {
-class RenderObject;
+class RenderBox;
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 +60,7 @@ public:
virtual void styleChanged();
- RenderObject* owningRenderer() const { return m_owner; }
+ RenderBox* owningRenderer() const { return m_owner; }
void paintPart(GraphicsContext*, ScrollbarPart, const IntRect&);
@@ -74,7 +74,7 @@ private:
PassRefPtr<RenderStyle> getScrollbarPseudoStyle(ScrollbarPart, RenderStyle::PseudoId);
void updateScrollbarPart(ScrollbarPart, bool destroy = false);
- RenderObject* m_owner;
+ RenderBox* m_owner;
HashMap<unsigned, RenderScrollbarPart*> m_parts;
};
diff --git a/WebCore/rendering/RenderScrollbarPart.cpp b/WebCore/rendering/RenderScrollbarPart.cpp
index d5e72e9..6749d8c 100644
--- a/WebCore/rendering/RenderScrollbarPart.cpp
+++ b/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,6 +122,12 @@ void RenderScrollbarPart::calcPrefWidths()
setPrefWidthsDirty(false);
}
+void RenderScrollbarPart::styleWillChange(RenderStyle::Diff diff, const RenderStyle* newStyle)
+{
+ RenderBlock::styleWillChange(diff, newStyle);
+ setInline(false);
+}
+
void RenderScrollbarPart::styleDidChange(RenderStyle::Diff diff, const RenderStyle* oldStyle)
{
RenderBlock::styleDidChange(diff, oldStyle);
@@ -133,18 +139,18 @@ void RenderScrollbarPart::styleDidChange(RenderStyle::Diff diff, const RenderSty
m_scrollbar->theme()->invalidatePart(m_scrollbar, m_part);
}
-void RenderScrollbarPart::imageChanged(WrappedImagePtr image)
+void RenderScrollbarPart::imageChanged(WrappedImagePtr image, const IntRect* rect)
{
if (m_scrollbar && m_part != NoPart)
m_scrollbar->theme()->invalidatePart(m_scrollbar, m_part);
else
- RenderBlock::imageChanged(image);
+ RenderBlock::imageChanged(image, rect);
}
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/WebCore/rendering/RenderScrollbarPart.h b/WebCore/rendering/RenderScrollbarPart.h
index fa13774..7dae6e7 100644
--- a/WebCore/rendering/RenderScrollbarPart.h
+++ b/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,8 +48,9 @@ public:
void paintIntoRect(GraphicsContext*, int tx, int ty, const IntRect&);
protected:
+ virtual void styleWillChange(RenderStyle::Diff diff, const RenderStyle* newStyle);
virtual void styleDidChange(RenderStyle::Diff, const RenderStyle* oldStyle);
- virtual void imageChanged(WrappedImagePtr);
+ virtual void imageChanged(WrappedImagePtr, const IntRect* = 0);
private:
void layoutHorizontalPart();
diff --git a/WebCore/rendering/RenderScrollbarTheme.cpp b/WebCore/rendering/RenderScrollbarTheme.cpp
index 2b375d0..d7cfb2b 100644
--- a/WebCore/rendering/RenderScrollbarTheme.cpp
+++ b/WebCore/rendering/RenderScrollbarTheme.cpp
@@ -26,12 +26,13 @@
#include "config.h"
#include "RenderScrollbarTheme.h"
#include "RenderScrollbar.h"
+#include <wtf/StdLibExtras.h>
namespace WebCore {
RenderScrollbarTheme* RenderScrollbarTheme::renderScrollbarTheme()
{
- static RenderScrollbarTheme theme;
+ DEFINE_STATIC_LOCAL(RenderScrollbarTheme, theme, ());
return &theme;
}
diff --git a/WebCore/rendering/RenderSlider.cpp b/WebCore/rendering/RenderSlider.cpp
index 221b0a2..25f3e40 100644
--- a/WebCore/rendering/RenderSlider.cpp
+++ b/WebCore/rendering/RenderSlider.cpp
@@ -31,6 +31,7 @@
#include "HTMLInputElement.h"
#include "HTMLDivElement.h"
#include "HTMLNames.h"
+#include "MediaControlElements.h"
#include "MouseEvent.h"
#include "RenderTheme.h"
#include <wtf/MathExtras.h>
@@ -58,13 +59,13 @@ public:
bool inDragMode() const { return m_inDragMode; }
private:
Node* m_shadowParent;
- IntPoint m_initialClickPoint;
+ FloatPoint m_initialClickPoint; // initial click point in RenderSlider-local coordinates
int m_initialPosition;
bool m_inDragMode;
};
HTMLSliderThumbElement::HTMLSliderThumbElement(Document* doc, Node* shadowParent)
- : HTMLDivElement(doc)
+ : HTMLDivElement(divTag, doc)
, m_shadowParent(shadowParent)
, m_initialClickPoint(IntPoint())
, m_initialPosition(0)
@@ -77,12 +78,14 @@ void HTMLSliderThumbElement::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);
- if (document()->frame() && renderer() && renderer()->parent()
- && static_cast<RenderSlider*>(renderer()->parent())->mouseEventIsInThumb(mouseEvent)) {
- // Cache the initial point where the mouse down occurred.
- m_initialClickPoint = IntPoint(mouseEvent->pageX(), mouseEvent->pageY());
+ RenderSlider* slider;
+ if (document()->frame() && renderer() && renderer()->parent() &&
+ (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);
// Cache the initial position of the thumb.
- m_initialPosition = static_cast<RenderSlider*>(renderer()->parent())->currentPosition();
+ m_initialPosition = slider->currentPosition();
m_inDragMode = true;
document()->frame()->eventHandler()->setCapturingMouseEventsNode(m_shadowParent);
@@ -103,11 +106,12 @@ 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 + mouseEvent->pageX() - m_initialClickPoint.x()
- + (renderer()->width() / 2),
- m_initialPosition + mouseEvent->pageY() - m_initialClickPoint.y()
- + (renderer()->height() / 2)));
+ IntPoint(m_initialPosition + curPoint.x() - m_initialClickPoint.x()
+ + (renderBox()->width() / 2),
+ m_initialPosition + curPoint.y() - m_initialClickPoint.y()
+ + (renderBox()->height() / 2)));
if (slider->currentPosition() != newPosition) {
slider->setCurrentPosition(newPosition);
slider->valueChanged();
@@ -132,7 +136,7 @@ RenderSlider::~RenderSlider()
m_thumb->detach();
}
-int RenderSlider::baselinePosition(bool b, bool isRootLineBox) const
+int RenderSlider::baselinePosition(bool, bool) const
{
return height() + marginTop();
}
@@ -217,12 +221,12 @@ void RenderSlider::layout()
int oldVisibleWidth = m_visibleWidth;
#endif
- int oldWidth = m_width;
+ int oldWidth = width();
calcWidth();
- int oldHeight = m_height;
+ int oldHeight = height();
calcHeight();
- if (oldWidth != m_width || oldHeight != m_height)
+ if (oldWidth != width() || oldHeight != height())
relayoutChildren = true;
#ifdef ANDROID_LAYOUT
@@ -264,16 +268,26 @@ void RenderSlider::updateFromElement()
addChild(m_thumb->renderer());
}
setPositionFromValue();
- setNeedsLayout(true);
+ setNeedsLayout(true, false);
}
bool RenderSlider::mouseEventIsInThumb(MouseEvent* evt)
{
if (!m_thumb || !m_thumb->renderer())
return false;
-
- IntRect thumbBounds = m_thumb->renderer()->absoluteBoundingBoxRect();
- return thumbBounds.contains(evt->pageX(), evt->pageY());
+
+#if ENABLE(VIDEO)
+ if (style()->appearance() == MediaSliderPart) {
+ MediaControlInputElement *sliderThumb = static_cast<MediaControlInputElement*>(m_thumb->renderer()->node());
+ IntPoint absPoint(evt->pageX(), evt->pageY());
+ return sliderThumb->hitTest(absPoint);
+ } else
+#endif
+ {
+ FloatPoint localPoint = m_thumb->renderBox()->absoluteToLocal(FloatPoint(evt->pageX(), evt->pageY()), false, true);
+ IntRect thumbBounds = m_thumb->renderBox()->borderBoxRect();
+ return thumbBounds.contains(roundedIntPoint(localPoint));
+ }
}
void RenderSlider::setValueForPosition(int position)
@@ -353,9 +367,9 @@ int RenderSlider::positionForOffset(const IntPoint& p)
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()));
}
@@ -386,7 +400,7 @@ void RenderSlider::setCurrentPosition(int pos)
else
m_thumb->renderer()->style()->setLeft(Length(pos, Fixed));
- m_thumb->renderer()->layer()->updateLayerPosition();
+ m_thumb->renderBox()->layer()->updateLayerPosition();
repaint();
m_thumb->renderer()->repaint();
}
@@ -397,8 +411,8 @@ int RenderSlider::trackSize()
return 0;
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)
diff --git a/WebCore/rendering/RenderSlider.h b/WebCore/rendering/RenderSlider.h
index 2667672..95ceb0b 100644
--- a/WebCore/rendering/RenderSlider.h
+++ b/WebCore/rendering/RenderSlider.h
@@ -44,7 +44,7 @@ namespace WebCore {
virtual void layout();
virtual void updateFromElement();
- bool mouseEventIsInThumb(MouseEvent*);
+ virtual bool mouseEventIsInThumb(MouseEvent*);
void setValueForPosition(int position);
double setPositionFromValue(bool inLayout = false);
diff --git a/WebCore/rendering/RenderTable.cpp b/WebCore/rendering/RenderTable.cpp
index b18ee3e..784a59a 100644
--- a/WebCore/rendering/RenderTable.cpp
+++ b/WebCore/rendering/RenderTable.cpp
@@ -235,12 +235,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());
// Subtract out any fixed margins from our available width for auto width tables.
int marginTotal = 0;
@@ -253,10 +253,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;
@@ -283,12 +283,12 @@ void RenderTable::layout()
bool checkForRepaint = checkForRepaintDuringLayout();
if (checkForRepaint) {
oldBounds = absoluteClippedOverflowRect();
- oldOutlineBox = absoluteOutlineBox();
+ oldOutlineBox = absoluteOutlineBounds();
}
- view()->pushLayoutState(this, IntSize(m_x, m_y));
+ LayoutStateMaintainer statePusher(view(), this, IntSize(x(), y()));
- m_height = 0;
+ setHeight(0);
m_overflowHeight = 0;
m_overflowTop = 0;
initMaxMarginValues();
@@ -298,7 +298,7 @@ void RenderTable::layout()
int oldVisibleWidth = m_visibleWidth;
#endif
- int oldWidth = m_width;
+ int oldWidth = width();
calcWidth();
#ifdef ANDROID_LAYOUT
@@ -309,10 +309,10 @@ void RenderTable::layout()
// if the width of a table is wider than its container width, or it has a nested table,
// we will render it with single column.
int cw = containingBlockWidth();
- if (m_width > cw || hasChildTable()) {
+ if (width() > cw || hasChildTable()) {
m_singleColumn = true;
- if (m_width > cw)
- m_width = cw;
+ if (width() > cw)
+ setWidth(cw);
if (m_minPrefWidth > cw)
m_minPrefWidth = cw;
if (m_maxPrefWidth > cw)
@@ -320,14 +320,14 @@ void RenderTable::layout()
}
}
#endif
- 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();
@@ -347,7 +347,7 @@ void RenderTable::layout()
child->layout();
}
#else
- if (child->needsLayout() && !(child->element() && child->element()->hasTagName(formTag)))
+ if (child->needsLayout() && !(child->element() && child->element()->hasTagName(formTag) && !child->isTableSection()))
child->layout();
#endif
if (child->isTableSection()) {
@@ -355,10 +355,11 @@ void RenderTable::layout()
calculatedHeight += section->calcRowHeight();
if (collapsing)
section->recalcOuterBorder();
+ ASSERT(!section->needsLayout());
}
}
- m_overflowWidth = m_width + (collapsing ? outerBorderRight() - borderRight() : 0);
+ 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
@@ -369,28 +370,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();
@@ -405,16 +406,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();
@@ -424,38 +424,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.
@@ -464,9 +464,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()) {
@@ -478,7 +478,7 @@ void RenderTable::layout()
}
}
- view()->popLayoutState();
+ statePusher.pop();
bool didFullRepaint = true;
// Repaint with our new bounds if they are different from our old bounds.
@@ -500,8 +500,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;
@@ -1181,7 +1181,7 @@ int RenderTable::getBaselineOfFirstLineBox() const
if (!firstNonEmptySection)
return -1;
- return firstNonEmptySection->yPos() + firstNonEmptySection->getBaselineOfFirstLineBox();
+ return firstNonEmptySection->y() + firstNonEmptySection->getBaselineOfFirstLineBox();
}
IntRect RenderTable::getOverflowClipRect(int tx, int ty)
diff --git a/WebCore/rendering/RenderTableCell.cpp b/WebCore/rendering/RenderTableCell.cpp
index f8043ee..f5bf358 100644
--- a/WebCore/rendering/RenderTableCell.cpp
+++ b/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,6 +25,7 @@
#include "config.h"
#include "RenderTableCell.h"
+#include "FloatQuad.h"
#include "GraphicsContext.h"
#include "HTMLNames.h"
#include "HTMLTableCellElement.h"
@@ -48,9 +49,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();
@@ -137,28 +137,44 @@ void RenderTableCell::calcWidth()
#endif
}
-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);
+ m_cellWidthChanged = true;
}
}
void RenderTableCell::layout()
{
- layoutBlock(m_widthChanged);
- m_widthChanged = false;
+ layoutBlock(m_cellWidthChanged);
+ m_cellWidthChanged = 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(RenderBox* 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();
@@ -191,34 +207,60 @@ 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(r, repaintContainer);
return r;
}
-void RenderTableCell::computeAbsoluteRepaintRect(IntRect& r, bool fixed)
+void RenderTableCell::computeRectForRepaint(IntRect& r, RenderBox* repaintContainer, 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(r, repaintContainer, fixed);
}
-bool RenderTableCell::absolutePosition(int& xPos, int& yPos, bool fixed) const
+FloatPoint RenderTableCell::localToAbsolute(FloatPoint localPoint, bool fixed, bool useTransforms) const
{
- bool result = RenderBlock::absolutePosition(xPos, yPos, fixed);
RenderView* v = view();
- if ((!v || !v->layoutState()) && parent()) {
- xPos -= parent()->xPos(); // Rows are in the same coordinate space, so don't add their offset in.
- yPos -= parent()->yPos();
+ if ((!v || !v->layoutStateEnabled()) && parent()) {
+ // Rows are in the same coordinate space, so don't add their offset in.
+ localPoint.move(-parentBox()->x(), -parentBox()->y());
}
- return result;
+ return RenderBlock::localToAbsolute(localPoint, fixed, useTransforms);
+}
+
+FloatPoint RenderTableCell::absoluteToLocal(FloatPoint containerPoint, bool fixed, bool useTransforms) const
+{
+ FloatPoint localPoint = RenderBlock::absoluteToLocal(containerPoint, fixed, useTransforms);
+ if (parent()) {
+ // Rows are in the same coordinate space, so add their offset back in.
+ localPoint.move(parentBox()->x(), parentBox()->y());
+ }
+ return localPoint;
+}
+
+FloatQuad RenderTableCell::localToContainerQuad(const FloatQuad& localQuad, RenderBox* repaintContainer, bool fixed) const
+{
+ if (repaintContainer == this)
+ return localQuad;
+
+ FloatQuad quad = localQuad;
+ if (parent()) {
+ // Rows are in the same coordinate space, so don't add their offset in.
+ quad.move(-parentBox()->x(), -parentBox()->y());
+ }
+ return RenderBlock::localToContainerQuad(quad, repaintContainer, fixed);
}
int RenderTableCell::baselinePosition(bool /*firstLine*/, bool /*isRootLineBox*/) const
@@ -226,11 +268,9 @@ int RenderTableCell::baselinePosition(bool /*firstLine*/, bool /*isRootLineBox*/
// <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();
if (firstLineBaseline != -1)
return firstLineBaseline;
-
return paddingTop() + borderTop() + contentHeight();
}
@@ -250,11 +290,6 @@ void RenderTableCell::styleDidChange(RenderStyle::Diff diff, const RenderStyle*
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
@@ -625,23 +660,21 @@ int RenderTableCell::borderHalfBottom(bool outer) const
void RenderTableCell::paint(PaintInfo& paintInfo, int tx, int ty)
{
- tx += m_x;
- ty += m_y;
+ tx += x();
+ ty += 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)
+ ty + height() + table()->outerBorderBottom() <= paintInfo.rect.y() - os)
return;
- int w = width();
- int h = height() + borderTopExtra() + borderBottomExtra();
- paintCollapsedBorder(paintInfo.context, tx, ty, w, h);
+ paintCollapsedBorder(paintInfo.context, tx, ty, width(), height());
} else {
- if (ty + overflowTop(false) >= paintInfo.rect.bottom() + os || ty + m_topExtra + overflowHeight(false) + m_bottomExtra <= paintInfo.rect.y() - os)
+ if (ty + overflowTop(false) >= paintInfo.rect.bottom() + os || ty + overflowHeight(false) <= paintInfo.rect.y() - os)
return;
- RenderBlock::paintObject(paintInfo, tx, ty + m_topExtra);
+ RenderBlock::paintObject(paintInfo, tx, ty);
}
}
@@ -815,13 +848,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 h = height();
int my = max(ty, paintInfo.rect.y());
int end = min(paintInfo.rect.bottom(), ty + h);
@@ -853,10 +885,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);
@@ -864,7 +896,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());
}
@@ -878,7 +909,7 @@ 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);
diff --git a/WebCore/rendering/RenderTableCell.h b/WebCore/rendering/RenderTableCell.h
index eb093fb..97e2dda 100644
--- a/WebCore/rendering/RenderTableCell.h
+++ b/WebCore/rendering/RenderTableCell.h
@@ -59,18 +59,16 @@ 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);
-
#ifdef ANDROID_LAYOUT
// RenderTableSection needs to access this in setCellWidths()
int getVisibleWidth() { return m_visibleWidth; }
#endif
- virtual bool expandsToEncloseOverhangingFloats() const { return true; }
+ void updateWidth(int);
int borderLeft() const;
int borderRight() const;
@@ -101,33 +99,39 @@ 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 bool absolutePosition(int& x, int& y, bool fixed = false) const;
+ virtual IntRect clippedOverflowRectForRepaint(RenderBox* repaintContainer);
+ virtual void computeRectForRepaint(IntRect&, RenderBox* repaintContainer, 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 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 FloatQuad localToContainerQuad(const FloatQuad&, RenderBox* repaintContainer, bool fixed = false) 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/WebCore/rendering/RenderTableCol.cpp b/WebCore/rendering/RenderTableCol.cpp
index 0d714da..19538fa 100644
--- a/WebCore/rendering/RenderTableCol.cpp
+++ b/WebCore/rendering/RenderTableCol.cpp
@@ -69,11 +69,12 @@ bool RenderTableCol::canHaveChildren() const
return style()->display() == TABLE_COLUMN_GROUP;
}
-IntRect RenderTableCol::absoluteClippedOverflowRect()
+IntRect RenderTableCol::clippedOverflowRectForRepaint(RenderBox* /*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.
+ // FIXME: check for repaintContainer each time here?
RenderObject* table = parent();
if (table && !table->isTable())
table = table->parent();
@@ -83,7 +84,7 @@ IntRect RenderTableCol::absoluteClippedOverflowRect()
return IntRect();
}
-void RenderTableCol::imageChanged(WrappedImagePtr image)
+void RenderTableCol::imageChanged(WrappedImagePtr, const IntRect*)
{
// FIXME: Repaint only the rect the image paints in.
repaint();
diff --git a/WebCore/rendering/RenderTableCol.h b/WebCore/rendering/RenderTableCol.h
index 9d46e2b..3472965 100644
--- a/WebCore/rendering/RenderTableCol.h
+++ b/WebCore/rendering/RenderTableCol.h
@@ -44,10 +44,10 @@ 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 void imageChanged(WrappedImagePtr);
+ virtual IntRect clippedOverflowRectForRepaint(RenderBox* repaintContainer);
+ virtual void imageChanged(WrappedImagePtr, const IntRect* = 0);
int span() const { return m_span; }
void setSpan(int s) { m_span = s; }
diff --git a/WebCore/rendering/RenderTableRow.cpp b/WebCore/rendering/RenderTableRow.cpp
index 4e9323d..6b83769 100644
--- a/WebCore/rendering/RenderTableRow.cpp
+++ b/WebCore/rendering/RenderTableRow.cpp
@@ -33,6 +33,10 @@
#include "RenderTableCell.h"
#include "RenderView.h"
+#if ENABLE(WML)
+#include "WMLNames.h"
+#endif
+
namespace WebCore {
using namespace HTMLNames;
@@ -71,7 +75,12 @@ void RenderTableRow::addChild(RenderObject* child, RenderObject* beforeChild)
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);
@@ -124,7 +133,7 @@ void RenderTableRow::layout()
ASSERT(needsLayout());
// Table rows do not add translation.
- view()->pushLayoutState(this, IntSize());
+ LayoutStateMaintainer statePusher(view(), this, IntSize());
for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
if (child->isTableCell()) {
@@ -148,17 +157,18 @@ void RenderTableRow::layout()
}
}
- view()->popLayoutState();
+ statePusher.pop();
setNeedsLayout(false);
}
-IntRect RenderTableRow::absoluteClippedOverflowRect()
+IntRect RenderTableRow::clippedOverflowRectForRepaint(RenderBox* 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();
}
@@ -173,7 +183,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->hasLayer() && !child->isRenderInline() && child->nodeAtPoint(request, result, x, y, tx, ty, action)) {
updateHitTestResult(result, IntPoint(x - tx, y - ty));
return true;
}
@@ -201,7 +211,7 @@ void RenderTableRow::paint(PaintInfo& paintInfo, int tx, int ty)
}
}
-void RenderTableRow::imageChanged(WrappedImagePtr image)
+void RenderTableRow::imageChanged(WrappedImagePtr, const IntRect*)
{
// FIXME: Examine cells and repaint only the rect the image paints in.
repaint();
diff --git a/WebCore/rendering/RenderTableRow.h b/WebCore/rendering/RenderTableRow.h
index 99482be..79d32d8 100644
--- a/WebCore/rendering/RenderTableRow.h
+++ b/WebCore/rendering/RenderTableRow.h
@@ -35,29 +35,29 @@ class RenderTableRow : public RenderContainer {
public:
RenderTableRow(Node*);
+ RenderTableSection* section() const { return static_cast<RenderTableSection*>(parent()); }
+ RenderTable* table() const { return static_cast<RenderTable*>(parent()->parent()); }
+
+private:
virtual const char* renderName() const { return isAnonymous() ? "RenderTableRow (anonymous)" : "RenderTableRow"; }
virtual bool isTableRow() const { return true; }
virtual void destroy();
- RenderTableSection* section() const { return static_cast<RenderTableSection*>(parent()); }
- RenderTable* table() const { return static_cast<RenderTable*>(parent()->parent()); }
-
virtual void addChild(RenderObject* child, RenderObject* beforeChild = 0);
- virtual int lineHeight(bool firstLine, bool isRootLineBox = false) const { return 0; }
+ virtual int lineHeight(bool, bool) const { return 0; }
virtual void position(InlineBox*) { }
virtual void layout();
- virtual IntRect absoluteClippedOverflowRect();
+ virtual IntRect clippedOverflowRectForRepaint(RenderBox* 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(); }
virtual void paint(PaintInfo&, int tx, int ty);
- virtual void imageChanged(WrappedImagePtr);
+ virtual void imageChanged(WrappedImagePtr, const IntRect* = 0);
-protected:
virtual void styleWillChange(RenderStyle::Diff, const RenderStyle* newStyle);
};
diff --git a/WebCore/rendering/RenderTableSection.cpp b/WebCore/rendering/RenderTableSection.cpp
index acc5596..ad2bfaf 100644
--- a/WebCore/rendering/RenderTableSection.cpp
+++ b/WebCore/rendering/RenderTableSection.cpp
@@ -135,7 +135,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();
@@ -178,7 +178,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();
@@ -261,8 +261,9 @@ void RenderTableSection::addCell(RenderTableCell* cell, RenderObject* row)
void RenderTableSection::setCellWidths()
{
Vector<int>& columnPos = table()->columnPositions();
- bool pushedLayoutState = false;
+ LayoutStateMaintainer statePusher(view());
+
#ifdef ANDROID_LAYOUT
int visibleWidth = 0;
if (view()->frameView()) {
@@ -304,38 +305,41 @@ void RenderTableSection::setCellWidths()
#endif
cell->setNeedsLayout(true);
if (!table()->selfNeedsLayout() && cell->checkForRepaintDuringLayout()) {
- if (!pushedLayoutState) {
+ 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.
- view()->pushLayoutState(this, IntSize(m_x, m_y));
- pushedLayoutState = true;
+ statePusher.push(this, IntSize(x(), y()));
}
cell->repaint();
}
#ifdef ANDROID_LAYOUT
if (w != oldWidth)
- cell->setWidth(w);
-#else
- cell->setWidth(w);
#endif
+ cell->updateWidth(w);
}
}
}
- if (pushedLayoutState)
- view()->popLayoutState();
+ statePusher.pop(); // only pops if we pushed
}
int RenderTableSection::calcRowHeight()
{
+#ifndef NDEBUG
+ setNeedsLayoutIsForbidden(true);
+#endif
+
+ ASSERT(!needsLayout());
#ifdef ANDROID_LAYOUT
if (table()->isSingleColumn())
return m_rowPos[m_gridRows];
#endif
+
RenderTableCell* cell;
int spacing = table()->vBorderSpacing();
- bool pushedLayoutState = false;
+
+ LayoutStateMaintainer statePusher(view());
m_rowPos.resize(m_gridRows + 1);
m_rowPos[0] = spacing;
@@ -364,23 +368,26 @@ int RenderTableSection::calcRowHeight()
int indx = max(r - cell->rowSpan() + 1, 0);
if (cell->overrideSize() != -1) {
- if (!pushedLayoutState) {
+ 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.
- view()->pushLayoutState(this, IntSize(m_x, m_y));
- pushedLayoutState = true;
+ 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);
@@ -391,8 +398,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()));
}
}
}
@@ -407,14 +414,24 @@ int RenderTableSection::calcRowHeight()
m_rowPos[r + 1] = max(m_rowPos[r + 1], m_rowPos[r]);
}
- if (pushedLayoutState)
- view()->popLayoutState();
+#ifndef NDEBUG
+ setNeedsLayoutIsForbidden(false);
+#endif
+
+ ASSERT(!needsLayout());
+
+ statePusher.pop();
return m_rowPos[m_gridRows];
}
int RenderTableSection::layoutRows(int toAdd)
{
+#ifndef NDEBUG
+ setNeedsLayoutIsForbidden(true);
+#endif
+
+ ASSERT(!needsLayout());
#ifdef ANDROID_LAYOUT
if (table()->isSingleColumn()) {
int totalRows = m_gridRows;
@@ -435,40 +452,45 @@ int RenderTableSection::layoutRows(int toAdd)
if (r > 0 && (cellAt(r-1, c).cell == cell))
continue;
- cell->setCellTopExtra(0);
- cell->setCellBottomExtra(0);
+// cell->setCellTopExtra(0);
+// cell->setCellBottomExtra(0);
- int oldCellX = cell->xPos();
- int oldCellY = cell->yPos();
+ int oldCellX = cell->x();
+ int oldCellY = cell->y();
- if (style()->direction() == RTL)
- cell->setPos(table()->width(), rHeight);
- else
- cell->setPos(leftOffset, rHeight);
-
+ if (style()->direction() == RTL) {
+ cell->setX(table()->width());
+ cell->setY(rHeight);
+ } else {
+ cell->setX(leftOffset);
+ cell->setY(rHeight);
+ }
+
// If the cell 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
// repaint ourselves (and the cell) anyway.
if (!table()->selfNeedsLayout() && cell->checkForRepaintDuringLayout()) {
- IntRect cellRect(oldCellX, oldCellY - cell->borderTopExtra() , cell->width(), cell->height());
+// IntRect cellRect(oldCellX, oldCellY - cell->borderTopExtra() , cell->width(), cell->height());
+ IntRect cellRect(oldCellX, oldCellY, cell->width(), cell->height());
cell->repaintDuringLayoutIfMoved(cellRect);
}
rHeight += cell->height() + vspacing;
}
}
- m_height = rHeight;
- return m_height;
+ setHeight(rHeight);
+ return height();
}
#endif
+
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;
@@ -536,13 +558,13 @@ int RenderTableSection::layoutRows(int toAdd)
int vspacing = table()->vBorderSpacing();
int nEffCols = table()->numEffCols();
- view()->pushLayoutState(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);
}
@@ -576,7 +598,7 @@ 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() && (o->isReplaced() || (o->isBox() && toRenderBox(o)->scrollsOverflow()) || flexAllChildren)) {
// Tables with no sections do not flex.
if (!o->isTable() || static_cast<RenderTable*>(o)->hasSections()) {
o->setNeedsLayout(true, false);
@@ -585,10 +607,11 @@ int RenderTableSection::layoutRows(int toAdd)
}
}
}
+
if (cellChildrenFlex) {
// 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()));
@@ -603,48 +626,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
@@ -655,11 +687,17 @@ int RenderTableSection::layoutRows(int toAdd)
}
}
- view()->popLayoutState();
+#ifndef NDEBUG
+ setNeedsLayoutIsForbidden(false);
+#endif
- m_height = m_rowPos[totalRows];
- m_overflowHeight = max(m_overflowHeight, m_height);
- return m_height;
+ ASSERT(!needsLayout());
+
+ statePusher.pop();
+
+ setHeight(m_rowPos[totalRows]);
+ m_overflowHeight = max(m_overflowHeight, height());
+ return height();
}
int RenderTableSection::lowestPosition(bool includeOverflowInterior, bool includeSelf) const
@@ -671,7 +709,7 @@ int RenderTableSection::lowestPosition(bool includeOverflowInterior, bool includ
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));
+ bottom = max(bottom, static_cast<RenderTableCell*>(cell)->y() + cell->lowestPosition(false));
}
}
@@ -687,7 +725,7 @@ int RenderTableSection::rightmostPosition(bool includeOverflowInterior, bool inc
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));
+ right = max(right, static_cast<RenderTableCell*>(cell)->x() + cell->rightmostPosition(false));
}
}
@@ -703,7 +741,7 @@ int RenderTableSection::leftmostPosition(bool includeOverflowInterior, bool incl
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));
+ left = min(left, static_cast<RenderTableCell*>(cell)->x() + cell->leftmostPosition(false));
}
}
@@ -933,7 +971,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;
@@ -953,8 +991,8 @@ void RenderTableSection::paint(PaintInfo& paintInfo, int tx, int ty)
if (!totalRows || !totalCols)
return;
- tx += m_x;
- ty += m_y;
+ tx += x();
+ ty += y();
// Check which rows and cols are visible and only paint these.
// FIXME: Could use a binary search here.
@@ -1074,7 +1112,7 @@ void RenderTableSection::paint(PaintInfo& paintInfo, int tx, int ty)
}
}
-void RenderTableSection::imageChanged(WrappedImagePtr image)
+void RenderTableSection::imageChanged(WrappedImagePtr, const IntRect*)
{
// FIXME: Examine cells and repaint only the rect the image paints in.
repaint();
@@ -1093,11 +1131,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);
}
}
}
@@ -1157,20 +1197,20 @@ RenderObject* RenderTableSection::removeChildNode(RenderObject* child, bool full
}
// 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();
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->isRenderInline() && child->nodeAtPoint(request, result, xPos, yPos, tx, ty, action)) {
+ updateHitTestResult(result, IntPoint(xPos - tx, yPos - ty));
return true;
}
}
diff --git a/WebCore/rendering/RenderTableSection.h b/WebCore/rendering/RenderTableSection.h
index 1866fd5..71839d1 100644
--- a/WebCore/rendering/RenderTableSection.h
+++ b/WebCore/rendering/RenderTableSection.h
@@ -33,6 +33,7 @@
namespace WebCore {
class RenderTableCell;
+class RenderTableRow;
class RenderTableSection : public RenderContainer {
public:
@@ -47,12 +48,9 @@ public:
virtual void addChild(RenderObject* child, RenderObject* beforeChild = 0);
- virtual int lineHeight(bool firstLine, bool isRootLineBox = false) const { return 0; }
- virtual void position(InlineBox*) { }
-
virtual int getBaselineOfFirstLineBox() const;
- void addCell(RenderTableCell*, RenderObject* row);
+ void addCell(RenderTableCell*, RenderTableRow* row);
void setCellWidths();
int calcRowHeight();
@@ -69,7 +67,7 @@ public:
struct RowStruct {
Row* row;
- RenderObject* rowRenderer;
+ RenderTableRow* rowRenderer;
int baseline;
Length height;
};
@@ -80,9 +78,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;
@@ -101,7 +99,7 @@ public:
int outerBorderRight() const { return m_outerBorderRight; }
virtual void paint(PaintInfo&, int tx, int ty);
- virtual void imageChanged(WrappedImagePtr);
+ virtual void imageChanged(WrappedImagePtr, const IntRect* = 0);
int numRows() const { return m_gridRows; }
int numColumns() const;
@@ -126,6 +124,9 @@ public:
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();
diff --git a/WebCore/rendering/RenderText.cpp b/WebCore/rendering/RenderText.cpp
index be8e337..084be71 100644
--- a/WebCore/rendering/RenderText.cpp
+++ b/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,11 +26,14 @@
#include "RenderText.h"
#include "CharacterNames.h"
+#include "FloatQuad.h"
+#include "FrameView.h"
#include "InlineTextBox.h"
#include "Range.h"
#include "RenderArena.h"
#include "RenderBlock.h"
#include "RenderLayer.h"
+#include "RenderView.h"
#include "Text.h"
#include "TextBreakIterator.h"
#include "break_lines.h"
@@ -55,6 +58,8 @@ RenderText::RenderText(Node* node, PassRefPtr<StringImpl> str)
, m_lastTextBox(0)
, m_minWidth(-1)
, m_maxWidth(-1)
+ , m_beginMinWidth(0)
+ , m_endMinWidth(0)
, m_selectionState(SelectionNone)
, m_hasTab(false)
, m_linesDirty(false)
@@ -62,8 +67,10 @@ RenderText::RenderText(Node* node, PassRefPtr<StringImpl> str)
, m_isAllASCII(charactersAreAllASCII(m_text.get()))
{
ASSERT(m_text);
- setRenderText();
- m_text = m_text->replace('\\', backslashAsCurrencySymbol());
+ setIsText();
+ m_text = document()->displayStringModifiedByEncoding(PassRefPtr<StringImpl>(m_text));
+
+ view()->frameView()->setIsVisuallyNonEmpty();
}
#ifndef NDEBUG
@@ -93,16 +100,17 @@ bool RenderText::isWordBreak() const
void RenderText::styleDidChange(RenderStyle::Diff 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 == RenderStyle::Layout)
+ setNeedsLayoutAndPrefWidthsRecalc();
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);
}
@@ -214,27 +222,26 @@ 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));
- int x, y;
- absolutePositionForContent(x, y);
+ 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(x + box->xPos(), y + box->yPos(), box->width(), box->height());
+ IntRect r = IntRect(absPos.x() + box->xPos(), absPos.y() + box->yPos(), box->width(), box->height());
if (useSelectionHeight) {
- IntRect selectionRect = box->selectionRect(x, y, start, end);
+ IntRect selectionRect = box->selectionRect(absPos.x(), absPos.y(), start, end);
r.setHeight(selectionRect.height());
r.setY(selectionRect.y());
}
rects.append(r);
} else {
unsigned realEnd = min(box->end() + 1, end);
- IntRect r = box->selectionRect(x, y, start, realEnd);
+ IntRect r = box->selectionRect(absPos.x(), absPos.y(), start, realEnd);
if (!r.isEmpty()) {
if (!useSelectionHeight) {
// change the height and y position because selectionRect uses selection-specific values
r.setHeight(box->height());
- r.setY(y + box->yPos());
+ r.setY(absPos.y() + box->yPos());
}
rects.append(r);
}
@@ -242,6 +249,49 @@ void RenderText::addLineBoxRects(Vector<IntRect>& rects, unsigned start, unsigne
}
}
+void RenderText::absoluteQuads(Vector<FloatQuad>& quads, bool)
+{
+ for (InlineTextBox* box = firstTextBox(); box; box = box->nextTextBox())
+ quads.append(localToAbsoluteQuad(FloatRect(box->xPos(), box->yPos(), box->width(), box->height())));
+}
+
+void RenderText::collectAbsoluteLineBoxQuads(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
+ // function to take ints causes various internal mismatches. But selectionRect takes ints, and
+ // passing UINT_MAX to it causes trouble. Ideally we'd change selectionRect to take unsigneds, but
+ // that would cause many ripple effects, so for now we'll just clamp our unsigned parameters to INT_MAX.
+ ASSERT(end == UINT_MAX || end <= INT_MAX);
+ ASSERT(start <= INT_MAX);
+ start = min(start, static_cast<unsigned>(INT_MAX));
+ end = min(end, static_cast<unsigned>(INT_MAX));
+
+ 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());
+ if (useSelectionHeight) {
+ IntRect selectionRect = box->selectionRect(0, 0, start, end);
+ r.setHeight(selectionRect.height());
+ r.setY(selectionRect.y());
+ }
+ quads.append(localToAbsoluteQuad(FloatRect(r)));
+ } else {
+ unsigned realEnd = min(box->end() + 1, end);
+ IntRect r = box->selectionRect(0, 0, start, realEnd);
+ if (!r.isEmpty()) {
+ if (!useSelectionHeight) {
+ // change the height and y position because selectionRect uses selection-specific values
+ r.setHeight(box->height());
+ r.setY(box->yPos());
+ }
+ quads.append(localToAbsoluteQuad(FloatRect(r)));
+ }
+ }
+ }
+}
+
InlineTextBox* RenderText::findNextInlineTextBox(int offset, int& pos) const
{
// The text runs point to parts of the RenderText's m_text
@@ -253,13 +303,13 @@ 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;
}
@@ -276,13 +326,13 @@ VisiblePosition RenderText::positionForCoordinates(int x, int y)
// 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);
+ return VisiblePosition(element(), offset + firstTextBox()->start(), DOWNSTREAM);
}
if (lastTextBox() && y >= lastTextBox()->root()->topOverflow() && 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);
+ return VisiblePosition(element(), offset + lastTextBox()->start(), DOWNSTREAM);
}
InlineTextBox* lastBoxAbove = 0;
@@ -295,32 +345,32 @@ VisiblePosition RenderText::positionForCoordinates(int x, int y)
if (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 VisiblePosition(element(), offset + box->start(), DOWNSTREAM);
if (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 VisiblePosition(element(), offset + box->start(), offset > 0 ? VP_UPSTREAM_IF_POSSIBLE : DOWNSTREAM);
if (!box->prevOnLine() && 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 VisiblePosition(element(), 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 VisiblePosition(element(), 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 VisiblePosition(element(), lastBoxAbove ? lastBoxAbove->start() + lastBoxAbove->len() : 0, DOWNSTREAM);
}
-IntRect RenderText::caretRect(InlineBox* inlineBox, int caretOffset, int* extraWidthToEndOfLine)
+IntRect RenderText::localCaretRect(InlineBox* inlineBox, int caretOffset, int* extraWidthToEndOfLine)
{
if (!inlineBox)
return IntRect();
@@ -342,21 +392,17 @@ IntRect RenderText::caretRect(InlineBox* inlineBox, int caretOffset, int* extraW
if (extraWidthToEndOfLine)
*extraWidthToEndOfLine = (box->root()->width() + rootLeft) - (left + 1);
- int absx, absy;
- absolutePositionForContent(absx, absy);
- left += absx;
- top += absy;
-
RenderBlock* cb = containingBlock();
if (style()->autoWrap()) {
int availableWidth = cb->lineWidth(top);
if (box->direction() == LTR)
- left = min(left, absx + rootLeft + availableWidth - 1);
+ left = min(left, rootLeft + availableWidth - 1);
else
- left = max(left, absx + rootLeft);
+ left = max(left, rootLeft);
}
- return IntRect(left, top, 1, height);
+ 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
@@ -690,28 +736,16 @@ bool RenderText::containsOnlyWhitespace(unsigned from, unsigned len) const
return currPos >= (from + len);
}
-int RenderText::minXPos() 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;
-}
-
-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;
@@ -820,11 +854,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();
@@ -839,7 +873,7 @@ 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;
}
@@ -849,8 +883,7 @@ void RenderText::setTextInternal(PassRefPtr<StringImpl> text)
m_text = text;
ASSERT(m_text);
- m_text = m_text->replace('\\', backslashAsCurrencySymbol());
-
+ m_text = document()->displayStringModifiedByEncoding(PassRefPtr<StringImpl>(m_text));
#if ENABLE(SVG)
if (isSVGText()) {
if (style() && style()->whiteSpace() == PRE) {
@@ -929,14 +962,6 @@ void RenderText::setText(PassRefPtr<StringImpl> text, bool force)
setNeedsLayoutAndPrefWidthsRecalc();
}
-int RenderText::height() const
-{
- int retval = 0;
- if (firstTextBox())
- retval = lastTextBox()->m_y + lastTextBox()->height() - firstTextBox()->m_y;
- return retval;
-}
-
int RenderText::lineHeight(bool firstLine, bool) const
{
// Always use the interior line height of the parent (e.g., if our parent is an inline block).
@@ -959,9 +984,10 @@ InlineTextBox* RenderText::createInlineTextBox()
return new (renderArena()) InlineTextBox(this);
}
-InlineBox* RenderText::createInlineBox(bool, bool isRootLineBox, bool)
+InlineBox* RenderText::createInlineBox(bool, bool unusedIsRootLineBox, bool)
{
- ASSERT(!isRootLineBox);
+ ASSERT_UNUSED(unusedIsRootLineBox, !unusedIsRootLineBox);
+
InlineTextBox* textBox = createInlineTextBox();
if (!m_firstTextBox)
m_firstTextBox = m_lastTextBox = textBox;
@@ -978,7 +1004,7 @@ void RenderText::position(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());
@@ -1020,26 +1046,34 @@ unsigned int RenderText::width(unsigned int from, unsigned int len, const Font&
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->xPos() < leftSide)
+ leftSide = curr->xPos();
+ if (curr == firstTextBox() || curr->xPos() + curr->width() > rightSide)
+ rightSide = curr->xPos() + curr->width();
+ }
+ result.setWidth(rightSide - leftSide);
+ result.setX(leftSide);
+ result.setHeight(lastTextBox()->yPos() + lastTextBox()->height() - firstTextBox()->yPos());
+ result.setY(firstTextBox()->yPos());
}
- return max(0, maxx - minx);
+ return result;
}
-IntRect RenderText::absoluteClippedOverflowRect()
+IntRect RenderText::clippedOverflowRectForRepaint(RenderBox* repaintContainer)
{
RenderObject* cb = containingBlock();
- return cb->absoluteClippedOverflowRect();
+ return cb->clippedOverflowRectForRepaint(repaintContainer);
}
IntRect RenderText::selectionRect(bool clipToVisibleContent)
@@ -1079,9 +1113,9 @@ IntRect RenderText::selectionRect(bool clipToVisibleContent)
else {
if (cb->hasColumns())
cb->adjustRectForColumns(rect);
- int absx, absy;
- absolutePosition(absx, absy);
- rect.move(absx, absy);
+ // FIXME: This doesn't work correctly with transforms.
+ FloatPoint absPos = localToAbsolute();
+ rect.move(absPos.x(), absPos.y());
}
return rect;
@@ -1099,9 +1133,9 @@ 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;
}
@@ -1110,9 +1144,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;
}
@@ -1120,7 +1154,7 @@ unsigned RenderText::caretMaxRenderedOffset() const
{
int l = 0;
for (InlineTextBox* box = firstTextBox(); box; box = box->nextTextBox())
- l += box->m_len;
+ l += box->len();
return l;
}
diff --git a/WebCore/rendering/RenderText.h b/WebCore/rendering/RenderText.h
index a68ba57..6a09605 100644
--- a/WebCore/rendering/RenderText.h
+++ b/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
@@ -56,14 +56,12 @@ public:
virtual InlineTextBox* createInlineTextBox();
virtual void dirtyLineBoxes(bool fullLayout, bool isRootInlineBox = false);
- virtual void paint(PaintInfo&, int tx, int ty) { ASSERT_NOT_REACHED(); }
- virtual void layout() { ASSERT_NOT_REACHED(); }
-
- virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, int, int, int, int, HitTestAction) { ASSERT_NOT_REACHED(); return false; }
-
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 absoluteQuads(Vector<FloatQuad>&, bool topLevel = true);
+ virtual void collectAbsoluteLineBoxQuads(Vector<FloatQuad>&, unsigned startOffset = 0, unsigned endOffset = UINT_MAX, bool useSelectionHeight = false);
+
virtual VisiblePosition positionForCoordinates(int x, int y);
const UChar* characters() const { return m_text->characters(); }
@@ -72,8 +70,6 @@ public:
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 int lineHeight(bool firstLine, bool isRootLineBox = false) const;
@@ -87,12 +83,10 @@ 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;
+ int firstRunX() const;
+ int firstRunY() const;
virtual int verticalPositionHint(bool firstLine) const;
@@ -103,12 +97,12 @@ public:
virtual SelectionState selectionState() const { return static_cast<SelectionState>(m_selectionState); }
virtual void setSelectionState(SelectionState s);
virtual IntRect selectionRect(bool clipToVisibleContent = true);
- virtual IntRect caretRect(InlineBox*, int caretOffset, int* extraWidthToEndOfLine = 0);
+ 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(RenderBox* repaintContainer);
InlineTextBox* firstTextBox() const { return m_firstTextBox; }
InlineTextBox* lastTextBox() const { return m_lastTextBox; }
@@ -129,6 +123,7 @@ public:
void checkConsistency() const;
protected:
+ virtual void styleWillChange(RenderStyle::Diff, const RenderStyle*) { }
virtual void styleDidChange(RenderStyle::Diff, const RenderStyle* oldStyle);
virtual void setTextInternal(PassRefPtr<StringImpl>);
@@ -141,6 +136,10 @@ private:
// callers with a RenderObject* can continue to use length().
virtual unsigned length() const { return textLength(); }
+ virtual void paint(PaintInfo&, int, int) { ASSERT_NOT_REACHED(); }
+ virtual void layout() { ASSERT_NOT_REACHED(); }
+ virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, int, int, int, int, HitTestAction) { ASSERT_NOT_REACHED(); return false; }
+
void deleteTextBoxes();
bool containsOnlyWhitespace(unsigned from, unsigned len) const;
int widthFromCache(const Font&, int start, int len, int xPos) const;
@@ -170,6 +169,18 @@ private:
bool m_isAllASCII : 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);
+}
+
#ifdef NDEBUG
inline void RenderText::checkConsistency() const
{
diff --git a/WebCore/rendering/RenderTextControl.cpp b/WebCore/rendering/RenderTextControl.cpp
index a971028..642ef1f 100644
--- a/WebCore/rendering/RenderTextControl.cpp
+++ b/WebCore/rendering/RenderTextControl.cpp
@@ -1,5 +1,6 @@
/**
* Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
+ * (C) 2008 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
@@ -22,35 +23,20 @@
#include "RenderTextControl.h"
#include "CharacterNames.h"
-#include "CSSStyleSelector.h"
-#include "Document.h"
#include "Editor.h"
-#include "EditorClient.h"
#include "Event.h"
#include "EventNames.h"
-#include "FontSelector.h"
#include "Frame.h"
-#include "FrameView.h"
#include "HTMLBRElement.h"
-#include "HTMLInputElement.h"
+#include "HTMLFormControlElement.h"
#include "HTMLNames.h"
-#include "HTMLTextAreaElement.h"
#include "HitTestResult.h"
-#include "LocalizedStrings.h"
-#include "MouseEvent.h"
-#include "PlatformKeyboardEvent.h"
-#include "RenderScrollbar.h"
-#include "RenderTheme.h"
+#include "RenderText.h"
#include "ScrollbarTheme.h"
-#include "SearchPopupMenu.h"
#include "SelectionController.h"
-#include "Settings.h"
-#include "Text.h"
#include "TextControlInnerElements.h"
+#include "Text.h"
#include "TextIterator.h"
-#include "htmlediting.h"
-#include "visible_units.h"
-#include <math.h>
#ifdef ANDROID_LAYOUT
#include "FrameView.h"
@@ -84,50 +70,29 @@ static Color disabledTextColor(const Color& textColor, const Color& backgroundCo
return disabledColor;
}
-RenderTextControl::RenderTextControl(Node* node, bool multiLine)
+RenderTextControl::RenderTextControl(Node* node)
: RenderBlock(node)
- , m_dirty(false)
- , m_multiLine(multiLine)
- , m_placeholderVisible(false)
+ , m_edited(false)
, m_userEdited(false)
- , m_shouldDrawCapsLockIndicator(false)
- , m_searchPopup(0)
- , m_searchPopupIsVisible(false)
- , m_searchEventTimer(this, &RenderTextControl::searchEventTimerFired)
{
}
RenderTextControl::~RenderTextControl()
{
- if (m_searchPopup) {
- m_searchPopup->disconnectClient();
- m_searchPopup = 0;
- }
- if (m_multiLine && node())
- static_cast<HTMLTextAreaElement*>(node())->rendererWillBeDestroyed();
// The children renderers have already been destroyed by destroyLeftoverChildren
- if (m_innerBlock)
- m_innerBlock->detach();
- else if (m_innerText)
+ if (m_innerText)
m_innerText->detach();
}
void RenderTextControl::styleDidChange(RenderStyle::Diff diff, const RenderStyle* oldStyle)
{
RenderBlock::styleDidChange(diff, oldStyle);
- if (m_innerBlock) {
- // 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.
- m_innerBlock->renderer()->style()->setHeight(Length());
- m_innerBlock->renderer()->style()->setWidth(Length());
- m_innerBlock->renderer()->setStyle(createInnerBlockStyle(style()));
- }
if (m_innerText) {
RenderBlock* textBlockRenderer = static_cast<RenderBlock*>(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.
+ // 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.
textBlockRenderer->style()->setHeight(Length());
textBlockRenderer->style()->setWidth(Length());
textBlockRenderer->setStyle(textBlockStyle);
@@ -136,214 +101,81 @@ void RenderTextControl::styleDidChange(RenderStyle::Diff diff, const RenderStyle
n->renderer()->setStyle(textBlockStyle);
}
}
- if (m_resultsButton && m_resultsButton->renderer())
- m_resultsButton->renderer()->setStyle(createResultsButtonStyle(style()));
-
- if (m_cancelButton && m_cancelButton->renderer())
- m_cancelButton->renderer()->setStyle(createCancelButtonStyle(style()));
setHasOverflowClip(false);
setReplaced(isInline());
}
-PassRefPtr<RenderStyle> RenderTextControl::createInnerBlockStyle(const RenderStyle* startStyle)
+void RenderTextControl::adjustInnerTextStyle(const RenderStyle* startStyle, RenderStyle* textBlockStyle) const
{
- RefPtr<RenderStyle> innerBlockStyle = RenderStyle::create();
-
- innerBlockStyle->inheritFrom(startStyle);
- innerBlockStyle->setDisplay(BLOCK);
- innerBlockStyle->setDirection(LTR);
- // We don't want the shadow dom to be editable, so we set this block to read-only in case the input itself is editable.
- innerBlockStyle->setUserModify(READ_ONLY);
-
- return innerBlockStyle.release();
-}
-
-PassRefPtr<RenderStyle> RenderTextControl::createInnerTextStyle(const RenderStyle* startStyle)
-{
- HTMLFormControlElement* element = static_cast<HTMLFormControlElement*>(node());
- bool placeholderShouldBeVisible = !m_multiLine && static_cast<HTMLInputElement*>(element)->placeholderShouldBeVisible();
-
- RefPtr<RenderStyle> textBlockStyle;
- if (placeholderShouldBeVisible) {
- RenderStyle* pseudoStyle = getCachedPseudoStyle(RenderStyle::INPUT_PLACEHOLDER);
- textBlockStyle = RenderStyle::clone(pseudoStyle);
- } else {
- textBlockStyle = RenderStyle::create();
- textBlockStyle->inheritFrom(startStyle);
- }
-
// 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(element->isReadOnlyControl() || element->disabled() ? READ_ONLY : READ_WRITE_PLAINTEXT_ONLY);
- if (m_innerBlock)
- textBlockStyle->setDisplay(INLINE_BLOCK);
- else
- textBlockStyle->setDisplay(BLOCK);
-
- if (m_multiLine) {
- // Forward overflow properties.
- textBlockStyle->setOverflowX(startStyle->overflowX() == OVISIBLE ? OAUTO : startStyle->overflowX());
- textBlockStyle->setOverflowY(startStyle->overflowY() == OVISIBLE ? OAUTO : startStyle->overflowY());
-
- // Set word wrap property based on wrap attribute.
- if (!static_cast<HTMLTextAreaElement*>(element)->shouldWrapText()) {
- textBlockStyle->setWhiteSpace(PRE);
- textBlockStyle->setWordWrap(NormalWordWrap);
- } else {
- textBlockStyle->setWhiteSpace(PRE_WRAP);
- textBlockStyle->setWordWrap(BreakWordWrap);
- }
- } else {
- textBlockStyle->setWhiteSpace(PRE);
- textBlockStyle->setWordWrap(NormalWordWrap);
- textBlockStyle->setOverflowX(OHIDDEN);
- textBlockStyle->setOverflowY(OHIDDEN);
-
- // Do not allow line-height to be smaller than our default.
- if (textBlockStyle->font().lineSpacing() > lineHeight(true, true))
- textBlockStyle->setLineHeight(Length(-100.0f, Percent));
- }
+ textBlockStyle->setUserModify((node()->isReadOnlyControl() || !node()->isEnabled()) ? READ_ONLY : READ_WRITE_PLAINTEXT_ONLY);
- if (!m_multiLine) {
- // We're adding one extra pixel of padding to match WinIE.
- textBlockStyle->setPaddingLeft(Length(1, Fixed));
- textBlockStyle->setPaddingRight(Length(1, Fixed));
- } else {
- // 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));
- }
-
- // When the placeholder is going to be displayed, temporarily override the text security to be "none".
- // After this, updateFromElement will immediately update the text displayed.
- // When the placeholder is no longer visible, updatePlaceholderVisiblity will reset the style,
- // and the text security mode will be set back to the computed value correctly.
- if (!m_multiLine && static_cast<HTMLInputElement*>(element)->placeholderShouldBeVisible())
- textBlockStyle->setTextSecurity(TSNONE);
-
- if (!element->isEnabled())
+ if (!node()->isEnabled())
textBlockStyle->setColor(disabledTextColor(textBlockStyle->color(), startStyle->backgroundColor()));
-
- return textBlockStyle.release();
}
-PassRefPtr<RenderStyle> RenderTextControl::createResultsButtonStyle(const RenderStyle* startStyle)
+void RenderTextControl::createSubtreeIfNeeded(TextControlInnerElement* innerBlock)
{
- ASSERT(!m_multiLine);
- HTMLInputElement* input = static_cast<HTMLInputElement*>(node());
- RefPtr<RenderStyle> resultsBlockStyle;
- if (input->maxResults() < 0)
- resultsBlockStyle = getCachedPseudoStyle(RenderStyle::SEARCH_DECORATION);
- else if (!input->maxResults())
- resultsBlockStyle = getCachedPseudoStyle(RenderStyle::SEARCH_RESULTS_DECORATION);
- else
- resultsBlockStyle = getCachedPseudoStyle(RenderStyle::SEARCH_RESULTS_BUTTON);
-
- if (!resultsBlockStyle)
- resultsBlockStyle = RenderStyle::create();
-
- if (startStyle)
- resultsBlockStyle->inheritFrom(startStyle);
-
- return resultsBlockStyle.release();
+ if (!m_innerText) {
+ // Create the text block element
+ // For non-search fields, there is no intermediate innerBlock as the shadow node.
+ // m_innerText will be the shadow node in that case.
+ RenderStyle* parentStyle = innerBlock ? innerBlock->renderer()->style() : style();
+ m_innerText = new TextControlInnerTextElement(document(), innerBlock ? 0 : node());
+ m_innerText->attachInnerElement(innerBlock ? innerBlock : node(), createInnerTextStyle(parentStyle), renderArena());
+ }
}
-PassRefPtr<RenderStyle> RenderTextControl::createCancelButtonStyle(const RenderStyle* startStyle)
+int RenderTextControl::textBlockHeight() const
{
- RefPtr<RenderStyle> cancelBlockStyle;
-
- if (RefPtr<RenderStyle> pseudoStyle = getCachedPseudoStyle(RenderStyle::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
- cancelBlockStyle = RenderStyle::create();
-
- if (startStyle)
- cancelBlockStyle->inheritFrom(startStyle);
-
- updateCancelButtonVisibility(cancelBlockStyle.get());
-
- return cancelBlockStyle.release();
+ return height() - paddingTop() - paddingBottom() - borderTop() - borderBottom();
}
-void RenderTextControl::createSubtreeIfNeeded()
+int RenderTextControl::textBlockWidth() const
{
- bool isSearchField = !m_multiLine && static_cast<HTMLInputElement*>(node())->isSearchField();
- if (isSearchField && !m_innerBlock) {
- // Create the inner block element
- m_innerBlock = new TextControlInnerElement(document(), node());
- m_innerBlock->attachInnerElement(node(), createInnerBlockStyle(style()), renderArena());
- }
- if (isSearchField && !m_resultsButton) {
- // Create the search results button element
- m_resultsButton = new SearchFieldResultsButtonElement(document());
- m_resultsButton->attachInnerElement(m_innerBlock.get(), createResultsButtonStyle(m_innerBlock->renderer()->style()), renderArena());
- }
- if (!m_innerText) {
- // Create the text block element
- // For non-search fields, there is no intermediate m_innerBlock as the shadow node.
- // m_innerText will be the shadow node in that case.
-
- RenderStyle* parentStyle = style();
- if (m_innerBlock)
- parentStyle = m_innerBlock->renderer()->style();
- m_innerText = new TextControlInnerTextElement(document(), m_innerBlock ? 0 : node());
- m_innerText->attachInnerElement(m_innerBlock ? m_innerBlock.get() : node(), createInnerTextStyle(parentStyle), renderArena());
- }
- if (isSearchField && !m_cancelButton) {
- // Create the cancel button element
- m_cancelButton = new SearchFieldCancelButtonElement(document());
- m_cancelButton->attachInnerElement(m_innerBlock.get(), createCancelButtonStyle(m_innerBlock->renderer()->style()), renderArena());
- }
+ return width() - paddingLeft() - paddingRight() - borderLeft() - borderRight()
+ - m_innerText->renderBox()->paddingLeft() - m_innerText->renderBox()->paddingRight();
}
void RenderTextControl::updateFromElement()
{
- HTMLFormControlElement* element = static_cast<HTMLFormControlElement*>(node());
+ m_innerText->renderer()->style()->setUserModify((node()->isReadOnlyControl() || !node()->isEnabled()) ? READ_ONLY : READ_WRITE_PLAINTEXT_ONLY);
+}
- bool placeholderShouldBeVisible = !m_multiLine && static_cast<HTMLInputElement*>(element)->placeholderShouldBeVisible();
- bool placeholderVisibilityShouldChange = m_placeholderVisible != placeholderShouldBeVisible;
- m_placeholderVisible = placeholderShouldBeVisible;
+void RenderTextControl::setInnerTextValue(const String& innerTextValue)
+{
+ String value;
- createSubtreeIfNeeded();
+ if (innerTextValue.isNull())
+ value = "";
+ else {
+ value = innerTextValue;
+ value = document()->displayStringModifiedByEncoding(value);
+ }
- if (m_cancelButton && m_cancelButton->renderer())
- updateCancelButtonVisibility(m_cancelButton->renderer()->style());
+ if (value != text() || !m_innerText->hasChildNodes()) {
+ if (value != text()) {
+ if (Frame* frame = document()->frame())
+ frame->editor()->clearUndoRedoOperations();
+ }
- m_innerText->renderer()->style()->setUserModify(element->isReadOnlyControl() || element->disabled() ? READ_ONLY : READ_WRITE_PLAINTEXT_ONLY);
-
- if (m_placeholderVisible) {
- ExceptionCode ec;
- m_innerText->setInnerText(static_cast<HTMLInputElement*>(element)->getAttribute(placeholderAttr), ec);
- } else if (!element->valueMatchesRenderer() || m_multiLine || placeholderVisibilityShouldChange) {
- String value;
- if (m_multiLine)
- value = static_cast<HTMLTextAreaElement*>(element)->value();
- else
- value = static_cast<HTMLInputElement*>(element)->value();
- if (value.isNull())
- value = "";
- else
- value = value.replace('\\', backslashAsCurrencySymbol());
- if (value != text() || !m_innerText->hasChildNodes()) {
- if (value != text()) {
- if (Frame* frame = document()->frame())
- frame->editor()->clearUndoRedoOperations();
- }
- ExceptionCode ec = 0;
- m_innerText->setInnerText(value, ec);
- if (value.endsWith("\n") || value.endsWith("\r"))
- m_innerText->appendChild(new HTMLBRElement(document()), ec);
- m_dirty = false;
- m_userEdited = false;
+ ExceptionCode ec = 0;
+ m_innerText->setInnerText(value, ec);
+ ASSERT(!ec);
+
+ if (value.endsWith("\n") || value.endsWith("\r")) {
+ m_innerText->appendChild(new HTMLBRElement(brTag, document()), ec);
+ ASSERT(!ec);
}
- element->setValueMatchesRenderer();
+
+ m_edited = false;
+ m_userEdited = false;
}
- if (m_searchPopupIsVisible)
- m_searchPopup->updateFromElement();
+ formControlElement()->setValueMatchesRenderer();
}
void RenderTextControl::setUserEdited(bool isUserEdited)
@@ -390,11 +222,8 @@ void RenderTextControl::setSelectionRange(int start, int end)
document()->updateLayout();
- if (style()->visibility() == HIDDEN || !m_innerText || !m_innerText->renderer() || !m_innerText->renderer()->height()) {
- if (m_multiLine)
- static_cast<HTMLTextAreaElement*>(node())->cacheSelection(start, end);
- else
- static_cast<HTMLInputElement*>(node())->cacheSelection(start, end);
+ if (style()->visibility() == HIDDEN || !m_innerText || !m_innerText->renderer() || !m_innerText->renderBox()->height()) {
+ cacheSelection(start, end);
return;
}
VisiblePosition startPosition = visiblePositionForIndex(start);
@@ -431,9 +260,14 @@ VisiblePosition RenderTextControl::visiblePositionForIndex(int index)
ExceptionCode ec = 0;
RefPtr<Range> range = Range::create(document());
range->selectNodeContents(m_innerText.get(), ec);
+ ASSERT(!ec);
CharacterIterator it(range.get());
it.advance(index - 1);
- return VisiblePosition(it.range()->endContainer(ec), it.range()->endOffset(ec), UPSTREAM);
+ Node* endContainer = it.range()->endContainer(ec);
+ ASSERT(!ec);
+ int endOffset = it.range()->endOffset(ec);
+ ASSERT(!ec);
+ return VisiblePosition(endContainer, endOffset, UPSTREAM);
}
int RenderTextControl::indexForVisiblePosition(const VisiblePosition& pos)
@@ -444,50 +278,16 @@ int RenderTextControl::indexForVisiblePosition(const VisiblePosition& pos)
ExceptionCode ec = 0;
RefPtr<Range> range = Range::create(document());
range->setStart(m_innerText.get(), 0, ec);
+ ASSERT(!ec);
range->setEnd(indexPosition.node(), indexPosition.offset(), ec);
+ ASSERT(!ec);
return TextIterator::rangeLength(range.get());
}
-void RenderTextControl::updateCancelButtonVisibility(RenderStyle* style)
-{
- ASSERT(!m_multiLine);
- HTMLInputElement* input = static_cast<HTMLInputElement*>(node());
- if (input->value().isEmpty())
- style->setVisibility(HIDDEN);
- else
- style->setVisibility(VISIBLE);
-}
-
void RenderTextControl::subtreeHasChanged()
{
- bool wasDirty = m_dirty;
- m_dirty = true;
+ m_edited = true;
m_userEdited = true;
- HTMLFormControlElement* element = static_cast<HTMLFormControlElement*>(node());
- if (m_multiLine) {
- element->setValueMatchesRenderer(false);
- if (element->focused())
- if (Frame* frame = document()->frame())
- frame->textDidChangeInTextArea(element);
- } else {
- HTMLInputElement* input = static_cast<HTMLInputElement*>(element);
- input->setValueFromRenderer(input->constrainValue(text()));
- if (m_cancelButton && m_cancelButton->renderer())
- updateCancelButtonVisibility(m_cancelButton->renderer()->style());
-
- // If the incremental attribute is set, then dispatch the search event
- if (!input->getAttribute(incrementalAttr).isNull())
- startSearchEventTimer();
-
- if (!wasDirty) {
- if (input->focused())
- if (Frame* frame = document()->frame())
- frame->textFieldDidBeginEditing(input);
- }
- if (input->focused())
- if (Frame* frame = document()->frame())
- frame->textDidChangeInTextField(input);
- }
}
String RenderTextControl::finishText(Vector<UChar>& result) const
@@ -501,22 +301,11 @@ 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);
}
-HTMLElement* RenderTextControl::innerTextElement() const
-{
- return m_innerText.get();
-}
-
String RenderTextControl::text()
{
if (!m_innerText)
@@ -528,7 +317,9 @@ String RenderTextControl::text()
Vector<UChar> result;
for (Node* n = m_innerText.get(); n; n = n->traverseNextNode(m_innerText.get())) {
- if (n->isTextNode()) {
+ if (n->hasTagName(brTag))
+ result.append(&newlineCharacter, 1);
+ else if (n->isTextNode()) {
Text* text = static_cast<Text*>(n);
String data = text->data();
unsigned length = data.length();
@@ -576,7 +367,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() : renderer->inlineBoxWrapper();
if (!box)
return "";
@@ -627,210 +418,49 @@ String RenderTextControl::textWithHardLineBreaks()
return finishText(result);
}
-void RenderTextControl::calcHeight()
+int RenderTextControl::scrollbarThickness() const
{
- int rows = 1;
- if (m_multiLine)
- rows = static_cast<HTMLTextAreaElement*>(node())->rows();
+ // FIXME: We should get the size of the scrollbar from the RenderTheme instead.
+ return ScrollbarTheme::nativeTheme()->scrollbarThickness();
+}
- int line = m_innerText->renderer()->lineHeight(true, true);
- int toAdd = paddingTop() + paddingBottom() + borderTop() + borderBottom();
+void RenderTextControl::calcHeight()
+{
+ 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());
- int innerToAdd = m_innerText->renderer()->borderTop() + m_innerText->renderer()->borderBottom() +
- m_innerText->renderer()->paddingTop() + m_innerText->renderer()->paddingBottom() +
- m_innerText->renderer()->marginTop() + m_innerText->renderer()->marginBottom();
-
- if (m_resultsButton && m_resultsButton->renderer()) {
- static_cast<RenderBlock*>(m_resultsButton->renderer())->calcHeight();
- innerToAdd = max(innerToAdd,
- m_resultsButton->renderer()->borderTop() + m_resultsButton->renderer()->borderBottom() +
- m_resultsButton->renderer()->paddingTop() + m_resultsButton->renderer()->paddingBottom() +
- m_resultsButton->renderer()->marginTop() + m_resultsButton->renderer()->marginBottom());
- line = max(line, m_resultsButton->renderer()->height());
- }
- if (m_cancelButton && m_cancelButton->renderer()) {
- static_cast<RenderBlock*>(m_cancelButton->renderer())->calcHeight();
- innerToAdd = max(innerToAdd,
- m_cancelButton->renderer()->borderTop() + m_cancelButton->renderer()->borderBottom() +
- m_cancelButton->renderer()->paddingTop() + m_cancelButton->renderer()->paddingBottom() +
- m_cancelButton->renderer()->marginTop() + m_cancelButton->renderer()->marginBottom());
- line = max(line, m_cancelButton->renderer()->height());
- }
- toAdd += innerToAdd;
+ adjustControlHeightBasedOnLineHeight(m_innerText->renderer()->lineHeight(true, true));
+ setHeight(height() + paddingTop() + paddingBottom() + borderTop() + borderBottom());
- // FIXME: We should get the size of the scrollbar from the RenderTheme instead.
- int scrollbarSize = 0;
// 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))
- scrollbarSize = ScrollbarTheme::nativeTheme()->scrollbarThickness();
-
- m_height = line * rows + toAdd + scrollbarSize;
+ setHeight(height() + scrollbarThickness());
RenderBlock::calcHeight();
}
-int RenderTextControl::baselinePosition(bool b, bool isRootLineBox) const
+void RenderTextControl::hitInnerTextBlock(HitTestResult& result, int xPos, int yPos, int tx, int ty)
{
- if (m_multiLine)
- return height() + marginTop() + marginBottom();
- return RenderBlock::baselinePosition(b, isRootLineBox);
+ result.setInnerNode(m_innerText.get());
+ result.setLocalPoint(IntPoint(xPos - tx - x() - m_innerText->renderBox()->x(),
+ yPos - ty - y() - m_innerText->renderBox()->y()));
}
-bool RenderTextControl::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, int x, int y, int tx, int ty, HitTestAction hitTestAction)
+void RenderTextControl::forwardEvent(Event* event)
{
- // 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).
-
- // 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 (RenderBlock::nodeAtPoint(request, result, x, y, tx, ty, hitTestAction) &&
- (result.innerNode() == element() || result.innerNode() == m_innerBlock)) {
- IntPoint localPoint = IntPoint(x - tx - m_x, y - ty - m_y);
- if (m_innerBlock) {
- int textLeft = tx + m_x + m_innerBlock->renderer()->xPos() + m_innerText->renderer()->xPos();
- int textRight = textLeft + m_innerText->renderer()->width();
- if (m_resultsButton && m_resultsButton->renderer() && x < textLeft) {
- result.setInnerNode(m_resultsButton.get());
- result.setLocalPoint(IntPoint(localPoint.x() - m_innerText->renderer()->xPos() - m_innerBlock->renderer()->xPos() - m_resultsButton->renderer()->xPos(),
- localPoint.y() - m_innerText->renderer()->yPos() - m_innerBlock->renderer()->yPos() - m_resultsButton->renderer()->yPos()));
- return true;
- }
- if (m_cancelButton && m_cancelButton->renderer() && x > textRight) {
- result.setInnerNode(m_cancelButton.get());
- result.setLocalPoint(IntPoint(localPoint.x() - m_innerText->renderer()->xPos() - m_innerBlock->renderer()->xPos() - m_cancelButton->renderer()->xPos(),
- localPoint.y() - m_innerText->renderer()->yPos() - m_innerBlock->renderer()->yPos() - m_cancelButton->renderer()->yPos()));
- return true;
- }
- }
-
- // Hit the inner text block.
- result.setInnerNode(m_innerText.get());
- result.setLocalPoint(IntPoint(localPoint.x() - m_innerText->renderer()->xPos() - (m_innerBlock.get() ? m_innerBlock->renderer()->xPos() : 0),
- localPoint.y() - m_innerText->renderer()->yPos() - (m_innerBlock.get() ? m_innerBlock->renderer()->yPos() : 0)));
-
- return true;
- }
-
- return false;
+ if (event->type() == eventNames().blurEvent || event->type() == eventNames().focusEvent)
+ return;
+ m_innerText->defaultEventHandler(event);
}
IntRect RenderTextControl::controlClipRect(int tx, int ty) const
{
- IntRect clipRect = contentBox();
+ IntRect clipRect = contentBoxRect();
clipRect.move(tx, ty);
return clipRect;
}
-void RenderTextControl::layout()
-{
- int oldHeight = m_height;
- calcHeight();
- bool relayoutChildren = oldHeight != m_height;
-
- // Set the text block's height
- int textBlockHeight = m_height - paddingTop() - paddingBottom() - borderTop() - borderBottom();
- int currentTextBlockHeight = m_innerText->renderer()->height();
- if (m_multiLine || m_innerBlock || currentTextBlockHeight > m_height) {
- if (textBlockHeight != currentTextBlockHeight)
- relayoutChildren = true;
- m_innerText->renderer()->style()->setHeight(Length(textBlockHeight, Fixed));
- }
- if (m_innerBlock) {
- if (textBlockHeight != m_innerBlock->renderer()->height())
- relayoutChildren = true;
- m_innerBlock->renderer()->style()->setHeight(Length(textBlockHeight, Fixed));
- }
-
-#ifdef ANDROID_LAYOUT
- int oldVisibleWidth = m_visibleWidth;
-#endif
-
- int oldWidth = m_width;
- calcWidth();
-
- // FIXME: This causes cnn.com loading way slow. Comment it out for now
-//#ifdef ANDROID_LAYOUT
-#if 0
- Frame* frame = document()->frame();
- if (frame && frame->settings()->layoutAlgorithm() == Settings::kLayoutFitColumnToScreen) {
- int maxWidth = frame->view()->visibleWidth() - 2 * ANDROID_FCTS_MARGIN_PADDING;
- if (maxWidth > 0 && maxWidth < m_width) {
- m_width = maxWidth;
- // not only modify the control's width, we also need to modify its
- // parent (even grandparent) width if it is not auto
- Length styleWidth = style()->width();
- if (styleWidth.isFixed()) {
- // now we need to get max style width
- maxWidth -= borderLeft() + borderRight() + paddingLeft() + paddingRight();
- style()->setWidth(Length(maxWidth, Fixed));
- } else if (styleWidth.isPercent()) {
- RenderObject* o = this;
- while (RenderBox* p = (RenderBox*)(o->parent())) {
- int maxParentWidth = (int)(maxWidth * 100 / styleWidth.percent());
- if (p->width() <= maxParentWidth)
- break;
- p->setWidth(maxParentWidth);
- styleWidth = p->style()->width();
- if (!styleWidth.isPercent())
- break;
- o = p;
- maxWidth = maxParentWidth;
- }
- }
- }
- }
-#endif
- if (oldWidth != m_width)
- relayoutChildren = true;
-
-#ifdef ANDROID_LAYOUT
- if (oldVisibleWidth != m_visibleWidth
- && document()->settings()->layoutAlgorithm() == Settings::kLayoutFitColumnToScreen)
- relayoutChildren = true;
-#endif
-
- int searchExtrasWidth = 0;
- if (m_resultsButton && m_resultsButton->renderer()) {
- m_resultsButton->renderer()->calcWidth();
- searchExtrasWidth += m_resultsButton->renderer()->width();
- }
- if (m_cancelButton && m_cancelButton->renderer()) {
- m_cancelButton->renderer()->calcWidth();
- searchExtrasWidth += m_cancelButton->renderer()->width();
- }
-
- // Set the text block's width
- int textBlockWidth = m_width - paddingLeft() - paddingRight() - borderLeft() - borderRight() -
- m_innerText->renderer()->paddingLeft() - m_innerText->renderer()->paddingRight() - searchExtrasWidth;
- if (textBlockWidth != m_innerText->renderer()->width())
- relayoutChildren = true;
- m_innerText->renderer()->style()->setWidth(Length(textBlockWidth, Fixed));
- if (m_innerBlock) {
- int innerBlockWidth = m_width - paddingLeft() - paddingRight() - borderLeft() - borderRight();
- if (innerBlockWidth != m_innerBlock->renderer()->width())
- relayoutChildren = true;
- m_innerBlock->renderer()->style()->setWidth(Length(innerBlockWidth, Fixed));
- }
-
- 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_multiLine) {
- currentTextBlockHeight = m_innerText->renderer()->height();
- if (!m_innerBlock && currentTextBlockHeight < m_height)
- m_innerText->renderer()->setPos(m_innerText->renderer()->xPos(), (m_height - currentTextBlockHeight) / 2);
- }
-}
-
-void RenderTextControl::paint(PaintInfo& paintInfo, int tx, int ty)
-{
- RenderBlock::paint(paintInfo, tx, ty);
- if (paintInfo.phase == PaintPhaseBlockBackground && m_shouldDrawCapsLockIndicator)
- theme()->paintCapsLockIndicator(this, paintInfo, absoluteContentBox());
-}
-
void RenderTextControl::calcPrefWidths()
{
ASSERT(prefWidthsDirty());
@@ -845,27 +475,7 @@ void RenderTextControl::calcPrefWidths()
// (using "0" as the nominal character).
const UChar ch = '0';
float charWidth = style()->font().floatWidth(TextRun(&ch, 1, false, 0, 0, false, false, false));
- int factor;
- int scrollbarSize = 0;
- if (m_multiLine) {
- factor = static_cast<HTMLTextAreaElement*>(node())->cols();
- // FIXME: We should get the size of the scrollbar from the RenderTheme instead.
- if (m_innerText->renderer()->style()->overflowY() != OHIDDEN)
- scrollbarSize = ScrollbarTheme::nativeTheme()->scrollbarThickness();
- } else {
- factor = static_cast<HTMLInputElement*>(node())->size();
- if (factor <= 0)
- factor = 20;
- }
- m_maxPrefWidth = static_cast<int>(ceilf(charWidth * factor)) + scrollbarSize +
- m_innerText->renderer()->paddingLeft() + m_innerText->renderer()->paddingRight();
-
- if (m_resultsButton && m_resultsButton->renderer())
- m_maxPrefWidth += m_resultsButton->renderer()->borderLeft() + m_resultsButton->renderer()->borderRight() +
- m_resultsButton->renderer()->paddingLeft() + m_resultsButton->renderer()->paddingRight();
- if (m_cancelButton && m_cancelButton->renderer())
- m_maxPrefWidth += m_cancelButton->renderer()->borderLeft() + m_cancelButton->renderer()->borderRight() +
- m_cancelButton->renderer()->paddingLeft() + m_cancelButton->renderer()->paddingRight();
+ m_maxPrefWidth = preferredContentWidth(charWidth) + m_innerText->renderBox()->paddingLeft() + m_innerText->renderBox()->paddingRight();
}
if (style()->minWidth().isFixed() && style()->minWidth().value() > 0) {
@@ -901,43 +511,24 @@ void RenderTextControl::calcPrefWidths()
setPrefWidthsDirty(false);
}
-void RenderTextControl::forwardEvent(Event* evt)
+void RenderTextControl::selectionChanged(bool userTriggered)
{
- if (evt->type() == eventNames().blurEvent) {
- RenderObject* innerRenderer = m_innerText->renderer();
- if (innerRenderer) {
- RenderLayer* innerLayer = innerRenderer->layer();
- if (innerLayer && !m_multiLine)
- innerLayer->scrollToOffset(style()->direction() == RTL ? innerLayer->scrollWidth() : 0, 0);
- }
- capsLockStateMayHaveChanged();
- } else if (evt->type() == eventNames().focusEvent)
- capsLockStateMayHaveChanged();
- else {
- if (evt->isMouseEvent() && m_resultsButton && static_cast<MouseEvent*>(evt)->x() < m_innerText->renderer()->absoluteBoundingBoxRect().x())
- m_resultsButton->defaultEventHandler(evt);
- else if (evt->isMouseEvent() && m_cancelButton && static_cast<MouseEvent*>(evt)->x() > m_innerText->renderer()->absoluteBoundingBoxRect().right())
- m_cancelButton->defaultEventHandler(evt);
- else
- m_innerText->defaultEventHandler(evt);
+ cacheSelection(selectionStart(), selectionEnd());
+
+ if (Frame* frame = document()->frame()) {
+ if (frame->selection()->isRange() && userTriggered)
+ static_cast<EventTargetNode*>(node())->dispatchEventForType(eventNames().selectEvent, true, false);
}
}
-void RenderTextControl::selectionChanged(bool userTriggered)
+void RenderTextControl::addFocusRingRects(GraphicsContext* graphicsContext, int tx, int ty)
{
- HTMLFormControlElement* element = static_cast<HTMLFormControlElement*>(node());
- if (m_multiLine)
- static_cast<HTMLTextAreaElement*>(element)->cacheSelection(selectionStart(), selectionEnd());
- else
- static_cast<HTMLInputElement*>(element)->cacheSelection(selectionStart(), selectionEnd());
- if (Frame* frame = document()->frame())
- if (frame->selection()->isRange() && userTriggered)
- element->dispatchEventForType(eventNames().selectEvent, true, false);
+ graphicsContext->addFocusRingRect(IntRect(tx, ty, width(), height()));
}
void RenderTextControl::autoscroll()
{
- RenderLayer* layer = m_innerText->renderer()->layer();
+ RenderLayer* layer = m_innerText->renderBox()->layer();
if (layer)
layer->autoscroll();
}
@@ -982,291 +573,22 @@ void RenderTextControl::setScrollTop(int newTop)
m_innerText->setScrollTop(newTop);
}
-const AtomicString& RenderTextControl::autosaveName() const
-{
- return static_cast<Element*>(node())->getAttribute(autosaveAttr);
-}
-
-void RenderTextControl::addSearchResult()
-{
- ASSERT(!m_multiLine);
-
- HTMLInputElement* input = static_cast<HTMLInputElement*>(node());
- if (input->maxResults() <= 0)
- return;
-
- String value = input->value();
- if (value.isEmpty())
- return;
-
- Settings* settings = document()->settings();
- if (!settings || settings->privateBrowsingEnabled())
- return;
-
- int size = static_cast<int>(m_recentSearches.size());
- for (int i = size - 1; i >= 0; --i)
- if (m_recentSearches[i] == value)
- m_recentSearches.remove(i);
-
- m_recentSearches.insert(0, value);
- while (static_cast<int>(m_recentSearches.size()) > input->maxResults())
- m_recentSearches.removeLast();
-
- const AtomicString& name = autosaveName();
- if (!m_searchPopup)
- m_searchPopup = SearchPopupMenu::create(this);
- m_searchPopup->saveRecentSearches(name, m_recentSearches);
-}
-
-void RenderTextControl::showPopup()
-{
- if (m_searchPopupIsVisible)
- return;
-
- if (!m_searchPopup)
- m_searchPopup = SearchPopupMenu::create(this);
-
- if (!m_searchPopup->enabled())
- return;
-
- m_searchPopupIsVisible = true;
-
- const AtomicString& name = autosaveName();
- m_searchPopup->loadRecentSearches(name, m_recentSearches);
-
- // Trim the recent searches list if the maximum size has changed since we last saved.
- HTMLInputElement* input = static_cast<HTMLInputElement*>(node());
- if (static_cast<int>(m_recentSearches.size()) > input->maxResults()) {
- do
- m_recentSearches.removeLast();
- while (static_cast<int>(m_recentSearches.size()) > input->maxResults());
- m_searchPopup->saveRecentSearches(name, m_recentSearches);
- }
-
- m_searchPopup->show(absoluteBoundingBoxRect(), document()->view(), -1);
-}
-
-void RenderTextControl::hidePopup()
-{
- if (m_searchPopup)
- m_searchPopup->hide();
- m_searchPopupIsVisible = false;
-}
-
-void RenderTextControl::valueChanged(unsigned listIndex, bool fireEvents)
-{
- ASSERT(static_cast<int>(listIndex) < listSize());
- HTMLInputElement* input = static_cast<HTMLInputElement*>(node());
- if (static_cast<int>(listIndex) == (listSize() - 1)) {
- if (fireEvents) {
- m_recentSearches.clear();
- const AtomicString& name = autosaveName();
- if (!name.isEmpty()) {
- if (!m_searchPopup)
- m_searchPopup = SearchPopupMenu::create(this);
- m_searchPopup->saveRecentSearches(name, m_recentSearches);
- }
- }
- } else {
- input->setValue(itemText(listIndex));
- if (fireEvents)
- input->onSearch();
- input->select();
- }
-}
-
-String RenderTextControl::itemText(unsigned listIndex) const
-{
- int size = listSize();
- if (size == 1) {
- ASSERT(!listIndex);
- return searchMenuNoRecentSearchesText();
- }
- if (!listIndex)
- return searchMenuRecentSearchesText();
- if (itemIsSeparator(listIndex))
- return String();
- if (static_cast<int>(listIndex) == (size - 1))
- return searchMenuClearRecentSearchesText();
- return m_recentSearches[listIndex - 1];
-}
-
-bool RenderTextControl::itemIsEnabled(unsigned listIndex) const
-{
- if (!listIndex || itemIsSeparator(listIndex))
- return false;
- return true;
-}
-
-PopupMenuStyle RenderTextControl::itemStyle(unsigned listIndex) const
-{
- return menuStyle();
-}
-
-PopupMenuStyle RenderTextControl::menuStyle() const
-{
- return PopupMenuStyle(style()->color(), style()->backgroundColor(), style()->font(), style()->visibility() == VISIBLE);
-}
-
-HostWindow* RenderTextControl::hostWindow() const
-{
- return document()->view()->hostWindow();
-}
-
-PassRefPtr<Scrollbar> RenderTextControl::createScrollbar(ScrollbarClient* client, ScrollbarOrientation orientation, ScrollbarControlSize controlSize)
-{
- RefPtr<Scrollbar> widget;
- bool hasCustomScrollbarStyle = style()->hasPseudoStyle(RenderStyle::SCROLLBAR);
- if (hasCustomScrollbarStyle)
- widget = RenderScrollbar::createCustomScrollbar(client, orientation, this);
- else
- widget = Scrollbar::createNativeScrollbar(client, orientation, controlSize);
- return widget.release();
-}
-
-int RenderTextControl::clientInsetLeft() const
-{
- // Inset the menu by the radius of the cap on the left so that
- // it only runs along the straight part of the bezel.
- return height() / 2;
-}
-
-int RenderTextControl::clientInsetRight() const
-{
- // Inset the menu by the radius of the cap on the right so that
- // it only runs along the straight part of the bezel (unless it needs
- // to be wider).
- return height() / 2;
-}
-
-int RenderTextControl::clientPaddingLeft() const
-{
- int padding = paddingLeft();
- if (m_resultsButton->renderer())
- padding += m_resultsButton->renderer()->width();
- return padding;
-}
-
-int RenderTextControl::clientPaddingRight() const
-{
- int padding = paddingRight();
- if (m_cancelButton->renderer())
- padding += m_cancelButton->renderer()->width();
- return padding;
-}
-
-int RenderTextControl::listSize() const
-{
- // If there are no recent searches, then our menu will have 1 "No recent searches" item.
- if (!m_recentSearches.size())
- return 1;
- // Otherwise, leave room in the menu for a header, a separator, and the "Clear recent searches" item.
- return m_recentSearches.size() + 3;
-}
-
-int RenderTextControl::selectedIndex() const
-{
- return -1;
-}
-
-bool RenderTextControl::itemIsSeparator(unsigned listIndex) const
-{
- // The separator will be the second to last item in our list.
- return static_cast<int>(listIndex) == (listSize() - 2);
-}
-
-bool RenderTextControl::itemIsLabel(unsigned listIndex) const
-{
- return listIndex == 0;
-}
-
-bool RenderTextControl::itemIsSelected(unsigned listIndex) const
-{
- return false;
-}
-
-void RenderTextControl::setTextFromItem(unsigned listIndex)
-{
- static_cast<HTMLInputElement*>(node())->setValue(itemText(listIndex));
-}
-
bool RenderTextControl::scroll(ScrollDirection direction, ScrollGranularity granularity, float multiplier)
{
- RenderLayer* layer = m_innerText->renderer()->layer();
+ RenderLayer* layer = m_innerText->renderBox()->layer();
if (layer && layer->scroll(direction, granularity, multiplier))
return true;
- return RenderObject::scroll(direction, granularity, multiplier);
-}
-
-void RenderTextControl::searchEventTimerFired(Timer<RenderTextControl>*)
-{
- static_cast<HTMLInputElement*>(node())->onSearch();
+ return RenderBlock::scroll(direction, granularity, multiplier);
}
-void RenderTextControl::stopSearchEventTimer()
-{
- m_searchEventTimer.stop();
-}
-
-void RenderTextControl::startSearchEventTimer()
-{
- unsigned length = text().length();
-
- // If there's no text, fire the event right away.
- if (!length) {
- m_searchEventTimer.stop();
- static_cast<HTMLInputElement*>(node())->onSearch();
- return;
- }
-
- // After typing the first key, we wait 0.5 seconds.
- // After the second key, 0.4 seconds, then 0.3, then 0.2 from then on.
- m_searchEventTimer.startOneShot(max(0.2, 0.6 - 0.1 * length));
-}
-
-bool RenderTextControl::isScrollable() const
-{
- if (m_innerText && m_innerText->renderer()->isScrollable())
- return true;
- return RenderObject::isScrollable();
-}
-
-FontSelector* RenderTextControl::fontSelector() const
-{
- return document()->styleSelector()->fontSelector();
-}
-
-void RenderTextControl::updatePlaceholderVisibility()
+HTMLElement* RenderTextControl::innerTextElement() const
{
- RenderStyle* parentStyle = m_innerBlock ? m_innerBlock->renderer()->style() : style();
- RefPtr<RenderStyle> textBlockStyle = createInnerTextStyle(parentStyle);
- m_innerText->renderer()->setStyle(textBlockStyle);
- for (Node* n = m_innerText->firstChild(); n; n = n->traverseNextNode(m_innerText.get())) {
- if (n->renderer())
- n->renderer()->setStyle(textBlockStyle);
- }
- updateFromElement();
+ return m_innerText.get();
}
-void RenderTextControl::capsLockStateMayHaveChanged()
+FormControlElement* RenderTextControl::formControlElement() const
{
- // Only draw the caps lock indicator if these things are true:
- // 1) The field is a password field
- // 2) The frame is active
- // 3) The element is focused
- // 4) The caps lock is on
-
- bool shouldDrawCapsLockIndicator = false;
- if (Node* n = node())
- if (Document* d = document())
- if (Frame* f = d->frame())
- shouldDrawCapsLockIndicator = !m_multiLine && static_cast<HTMLInputElement*>(n)->inputType() == HTMLInputElement::PASSWORD &&
- f->selection()->isFocusedAndActive() && d->focusedNode() == n && PlatformKeyboardEvent::currentCapsLockState();
-
- if (shouldDrawCapsLockIndicator != m_shouldDrawCapsLockIndicator) {
- m_shouldDrawCapsLockIndicator = shouldDrawCapsLockIndicator;
- repaint();
- }
+ return toFormControlElement(static_cast<Element*>(node()));
}
} // namespace WebCore
diff --git a/WebCore/rendering/RenderTextControl.h b/WebCore/rendering/RenderTextControl.h
index 74fdd26..86d3f8a 100644
--- a/WebCore/rendering/RenderTextControl.h
+++ b/WebCore/rendering/RenderTextControl.h
@@ -1,5 +1,6 @@
/*
- * Copyright (C) 2006, 2007 Apple Inc. All rights reserved.s
+ * Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
+ * (C) 2008 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
@@ -21,45 +22,32 @@
#ifndef RenderTextControl_h
#define RenderTextControl_h
-#include "PopupMenuClient.h"
#include "RenderBlock.h"
-#include "Timer.h"
namespace WebCore {
-class FontSelector;
-class SearchFieldCancelButtonElement;
-class SearchFieldResultsButtonElement;
-class SearchPopupMenu;
+class FormControlElement;
class Selection;
class TextControlInnerElement;
class TextControlInnerTextElement;
-class RenderTextControl : public RenderBlock, private PopupMenuClient {
+class RenderTextControl : public RenderBlock {
public:
- RenderTextControl(Node*, bool multiLine);
virtual ~RenderTextControl();
virtual const char* renderName() const { return "RenderTextControl"; }
-
- virtual bool hasControlClip() const { return m_cancelButton; }
+ virtual bool hasControlClip() const { return false; }
virtual IntRect controlClipRect(int tx, int ty) const;
virtual void calcHeight();
virtual void calcPrefWidths();
virtual void removeLeftoverAnonymousBlock(RenderBlock*) { }
virtual void updateFromElement();
virtual bool canHaveChildren() const { return false; }
- virtual int baselinePosition(bool firstLine, bool isRootLineBox) const;
- virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, int x, int y, int tx, int ty, HitTestAction);
- virtual void layout();
virtual bool avoidsFloats() const { return true; }
- virtual void paint(PaintInfo&, int tx, int ty);
-
- virtual bool isEdited() const { return m_dirty; }
- virtual void setEdited(bool isEdited) { m_dirty = isEdited; }
- virtual bool isTextField() const { return !m_multiLine; }
- virtual bool isTextArea() const { return m_multiLine; }
+ virtual bool isEdited() const { return m_edited; }
+ virtual void setEdited(bool isEdited) { m_edited = isEdited; }
+
bool isUserEdited() const { return m_userEdited; }
void setUserEdited(bool isUserEdited);
@@ -71,12 +59,13 @@ public:
void setSelectionRange(int start, int end);
Selection selection(int start, int end) const;
- void subtreeHasChanged();
+ virtual void subtreeHasChanged();
String text();
String textWithHardLineBreaks();
- void forwardEvent(Event*);
void selectionChanged(bool userTriggered);
+ virtual void addFocusRingRects(GraphicsContext*, int tx, int ty);
+
virtual bool canBeProgramaticallyScrolled(bool) const { return true; }
virtual void autoscroll();
@@ -88,81 +77,42 @@ public:
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&);
- void addSearchResult();
+protected:
+ RenderTextControl(Node*);
- bool popupIsVisible() const { return m_searchPopupIsVisible; }
- void showPopup();
- void hidePopup();
+ int scrollbarThickness() const;
+ void adjustInnerTextStyle(const RenderStyle* startStyle, RenderStyle* textBlockStyle) const;
+ void setInnerTextValue(const String&);
- void stopSearchEventTimer();
-
- bool placeholderIsVisible() const { return m_placeholderVisible; }
- void updatePlaceholderVisibility();
+ virtual void styleDidChange(RenderStyle::Diff, const RenderStyle* oldStyle);
- virtual void capsLockStateMayHaveChanged();
+ void createSubtreeIfNeeded(TextControlInnerElement* innerBlock);
+ void hitInnerTextBlock(HitTestResult&, int x, int y, int tx, int ty);
+ void forwardEvent(Event*);
-protected:
- virtual void styleDidChange(RenderStyle::Diff, const RenderStyle* oldStyle);
+ int textBlockWidth() const;
+ int textBlockHeight() const;
-private:
- // PopupMenuClient methods
- virtual void valueChanged(unsigned listIndex, bool fireEvents = true);
- virtual String itemText(unsigned listIndex) const;
- virtual bool itemIsEnabled(unsigned listIndex) const;
- virtual PopupMenuStyle itemStyle(unsigned listIndex) const;
- virtual PopupMenuStyle menuStyle() const;
- virtual int clientInsetLeft() const;
- virtual int clientInsetRight() const;
- virtual int clientPaddingLeft() const;
- virtual int clientPaddingRight() const;
- virtual int listSize() const;
- virtual int selectedIndex() const;
- virtual bool itemIsSeparator(unsigned listIndex) const;
- virtual bool itemIsLabel(unsigned listIndex) const;
- virtual bool itemIsSelected(unsigned listIndex) const;
- virtual void setTextFromItem(unsigned listIndex);
- virtual bool shouldPopOver() const { return false; }
- virtual bool valueShouldChangeOnHotTrack() const { return false; }
- virtual FontSelector* fontSelector() const;
- virtual HostWindow* hostWindow() const;
- virtual PassRefPtr<Scrollbar> createScrollbar(ScrollbarClient*, ScrollbarOrientation, ScrollbarControlSize);
-
- PassRefPtr<RenderStyle> createInnerBlockStyle(const RenderStyle* startStyle);
- PassRefPtr<RenderStyle> createInnerTextStyle(const RenderStyle* startStyle);
- PassRefPtr<RenderStyle> createCancelButtonStyle(const RenderStyle* startStyle);
- PassRefPtr<RenderStyle> createResultsButtonStyle(const RenderStyle* startStyle);
-
- void createSubtreeIfNeeded();
- void updateCancelButtonVisibility(RenderStyle*);
- const AtomicString& autosaveName() const;
- void startSearchEventTimer();
- void searchEventTimerFired(Timer<RenderTextControl>*);
- String finishText(Vector<UChar>&) const;
+ virtual int preferredContentWidth(float charWidth) const = 0;
+ virtual void adjustControlHeightBasedOnLineHeight(int lineHeight) = 0;
+ virtual void cacheSelection(int start, int end) = 0;
+ virtual PassRefPtr<RenderStyle> createInnerTextStyle(const RenderStyle* startStyle) const = 0;
friend class TextIterator;
HTMLElement* innerTextElement() const;
- RefPtr<TextControlInnerElement> m_innerBlock;
- RefPtr<TextControlInnerTextElement> m_innerText;
- RefPtr<SearchFieldResultsButtonElement> m_resultsButton;
- RefPtr<SearchFieldCancelButtonElement> m_cancelButton;
+ FormControlElement* formControlElement() const;
- bool m_dirty;
- bool m_multiLine;
- bool m_placeholderVisible;
- bool m_userEdited;
- bool m_shouldDrawCapsLockIndicator;
-
- RefPtr<SearchPopupMenu> m_searchPopup;
- bool m_searchPopupIsVisible;
- mutable Vector<String> m_recentSearches;
+private:
+ String finishText(Vector<UChar>&) const;
- Timer<RenderTextControl> m_searchEventTimer;
+ bool m_edited;
+ bool m_userEdited;
+ RefPtr<TextControlInnerTextElement> m_innerText;
};
} // namespace WebCore
diff --git a/WebCore/rendering/RenderTextControlMultiLine.cpp b/WebCore/rendering/RenderTextControlMultiLine.cpp
new file mode 100644
index 0000000..253f53f
--- /dev/null
+++ b/WebCore/rendering/RenderTextControlMultiLine.cpp
@@ -0,0 +1,171 @@
+/**
+ * Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
+ * (C) 2008 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
+ * 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 "RenderTextControlMultiLine.h"
+
+#include "EventNames.h"
+#include "Frame.h"
+#include "HitTestResult.h"
+#include "HTMLTextAreaElement.h"
+#ifdef ANDROID_LAYOUT
+#include "Settings.h"
+#endif
+
+namespace WebCore {
+
+RenderTextControlMultiLine::RenderTextControlMultiLine(Node* node)
+ : RenderTextControl(node)
+{
+}
+
+RenderTextControlMultiLine::~RenderTextControlMultiLine()
+{
+ if (node())
+ static_cast<HTMLTextAreaElement*>(node())->rendererWillBeDestroyed();
+}
+
+void RenderTextControlMultiLine::subtreeHasChanged()
+{
+ RenderTextControl::subtreeHasChanged();
+ formControlElement()->setValueMatchesRenderer(false);
+
+ if (!node()->focused())
+ return;
+
+ if (Frame* frame = document()->frame())
+ frame->textDidChangeInTextArea(static_cast<Element*>(node()));
+}
+
+void RenderTextControlMultiLine::layout()
+{
+ int oldHeight = height();
+ calcHeight();
+
+#ifdef ANDROID_LAYOUT
+ int oldVisibleWidth = m_visibleWidth;
+#endif
+
+ int oldWidth = width();
+ calcWidth();
+
+ bool relayoutChildren = oldHeight != height() || oldWidth != width();
+#ifdef ANDROID_LAYOUT
+ if (oldVisibleWidth != m_visibleWidth
+ && document()->settings()->layoutAlgorithm() == Settings::kLayoutFitColumnToScreen) {
+ relayoutChildren = true;
+ }
+#endif
+
+ RenderBox* innerTextRenderer = innerTextElement()->renderBox();
+
+ // 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;
+ }
+
+ return false;
+}
+
+void RenderTextControlMultiLine::forwardEvent(Event* event)
+{
+ RenderTextControl::forwardEvent(event);
+}
+
+int RenderTextControlMultiLine::preferredContentWidth(float charWidth) const
+{
+ int factor = static_cast<HTMLTextAreaElement*>(node())->cols();
+ return static_cast<int>(ceilf(charWidth * factor)) + scrollbarThickness();
+}
+
+void RenderTextControlMultiLine::adjustControlHeightBasedOnLineHeight(int lineHeight)
+{
+ setHeight(height() + lineHeight * static_cast<HTMLTextAreaElement*>(node())->rows());
+}
+
+int RenderTextControlMultiLine::baselinePosition(bool, bool) const
+{
+ return height() + marginTop() + marginBottom();
+}
+
+void RenderTextControlMultiLine::updateFromElement()
+{
+ createSubtreeIfNeeded(0);
+ RenderTextControl::updateFromElement();
+
+ setInnerTextValue(static_cast<HTMLTextAreaElement*>(node())->value());
+}
+
+void RenderTextControlMultiLine::cacheSelection(int start, int end)
+{
+ static_cast<HTMLTextAreaElement*>(node())->cacheSelection(start, end);
+}
+
+PassRefPtr<RenderStyle> RenderTextControlMultiLine::createInnerTextStyle(const RenderStyle* startStyle) const
+{
+ RefPtr<RenderStyle> textBlockStyle = RenderStyle::create();
+ textBlockStyle->inheritFrom(startStyle);
+
+ adjustInnerTextStyle(startStyle, textBlockStyle.get());
+
+ // Forward overflow properties.
+ textBlockStyle->setOverflowX(startStyle->overflowX() == OVISIBLE ? OAUTO : startStyle->overflowX());
+ textBlockStyle->setOverflowY(startStyle->overflowY() == OVISIBLE ? OAUTO : startStyle->overflowY());
+
+ // Set word wrap property based on wrap attribute.
+ if (static_cast<HTMLTextAreaElement*>(node())->shouldWrapText()) {
+ textBlockStyle->setWhiteSpace(PRE_WRAP);
+ textBlockStyle->setWordWrap(BreakWordWrap);
+ } else {
+ textBlockStyle->setWhiteSpace(PRE);
+ textBlockStyle->setWordWrap(NormalWordWrap);
+ }
+
+ 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/WebCore/rendering/RenderTextControlMultiLine.h b/WebCore/rendering/RenderTextControlMultiLine.h
new file mode 100644
index 0000000..591a65d
--- /dev/null
+++ b/WebCore/rendering/RenderTextControlMultiLine.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2008 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
+ * 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 RenderTextControlMultiLine_h
+#define RenderTextControlMultiLine_h
+
+#include "RenderTextControl.h"
+
+namespace WebCore {
+
+class RenderTextControlMultiLine : public RenderTextControl {
+public:
+ RenderTextControlMultiLine(Node*);
+ virtual ~RenderTextControlMultiLine();
+
+ 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*);
+
+private:
+ virtual int preferredContentWidth(float charWidth) const;
+ virtual void adjustControlHeightBasedOnLineHeight(int lineHeight);
+ virtual int baselinePosition(bool firstLine, bool isRootLineBox) const;
+
+ virtual void updateFromElement();
+ virtual void cacheSelection(int start, int end);
+
+ virtual PassRefPtr<RenderStyle> createInnerTextStyle(const RenderStyle* startStyle) const;
+};
+
+}
+
+#endif
diff --git a/WebCore/rendering/RenderTextControlSingleLine.cpp b/WebCore/rendering/RenderTextControlSingleLine.cpp
new file mode 100644
index 0000000..fccea00
--- /dev/null
+++ b/WebCore/rendering/RenderTextControlSingleLine.cpp
@@ -0,0 +1,787 @@
+/**
+ * Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
+ * (C) 2008 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
+ * 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 "RenderTextControlSingleLine.h"
+
+#include "CSSStyleSelector.h"
+#include "Event.h"
+#include "EventNames.h"
+#include "Frame.h"
+#include "FrameView.h"
+#include "HitTestResult.h"
+#include "HTMLInputElement.h"
+#include "HTMLNames.h"
+#include "InputElement.h"
+#include "LocalizedStrings.h"
+#include "MouseEvent.h"
+#include "PlatformKeyboardEvent.h"
+#include "RenderScrollbar.h"
+#include "RenderTheme.h"
+#include "SearchPopupMenu.h"
+#include "SelectionController.h"
+#include "Settings.h"
+#include "TextControlInnerElements.h"
+
+using namespace std;
+
+namespace WebCore {
+
+using namespace HTMLNames;
+
+RenderTextControlSingleLine::RenderTextControlSingleLine(Node* node)
+ : RenderTextControl(node)
+ , m_placeholderVisible(false)
+ , m_searchPopupIsVisible(false)
+ , m_shouldDrawCapsLockIndicator(false)
+ , m_searchEventTimer(this, &RenderTextControlSingleLine::searchEventTimerFired)
+ , m_searchPopup(0)
+{
+}
+
+RenderTextControlSingleLine::~RenderTextControlSingleLine()
+{
+ if (m_searchPopup) {
+ m_searchPopup->disconnectClient();
+ m_searchPopup = 0;
+ }
+
+ if (m_innerBlock)
+ m_innerBlock->detach();
+}
+
+bool RenderTextControlSingleLine::placeholderShouldBeVisible() const
+{
+ return inputElement()->placeholderShouldBeVisible();
+}
+
+void RenderTextControlSingleLine::updatePlaceholderVisibility()
+{
+ RenderStyle* parentStyle = m_innerBlock ? m_innerBlock->renderer()->style() : style();
+
+ RefPtr<RenderStyle> textBlockStyle = createInnerTextStyle(parentStyle);
+ HTMLElement* innerText = innerTextElement();
+ innerText->renderer()->setStyle(textBlockStyle);
+
+ for (Node* n = innerText->firstChild(); n; n = n->traverseNextNode(innerText)) {
+ if (RenderObject* renderer = n->renderer())
+ renderer->setStyle(textBlockStyle);
+ }
+
+ updateFromElement();
+}
+
+void RenderTextControlSingleLine::addSearchResult()
+{
+ ASSERT(node()->isHTMLElement());
+ HTMLInputElement* input = static_cast<HTMLInputElement*>(node());
+ if (input->maxResults() <= 0)
+ return;
+
+ String value = input->value();
+ if (value.isEmpty())
+ return;
+
+ Settings* settings = document()->settings();
+ if (!settings || settings->privateBrowsingEnabled())
+ return;
+
+ int size = static_cast<int>(m_recentSearches.size());
+ for (int i = size - 1; i >= 0; --i) {
+ if (m_recentSearches[i] == value)
+ m_recentSearches.remove(i);
+ }
+
+ m_recentSearches.insert(0, value);
+ while (static_cast<int>(m_recentSearches.size()) > input->maxResults())
+ m_recentSearches.removeLast();
+
+ const AtomicString& name = autosaveName();
+ if (!m_searchPopup)
+ m_searchPopup = SearchPopupMenu::create(this);
+
+ m_searchPopup->saveRecentSearches(name, m_recentSearches);
+}
+
+void RenderTextControlSingleLine::stopSearchEventTimer()
+{
+ ASSERT(node()->isHTMLElement());
+ m_searchEventTimer.stop();
+}
+
+void RenderTextControlSingleLine::showPopup()
+{
+ ASSERT(node()->isHTMLElement());
+ if (m_searchPopupIsVisible)
+ return;
+
+ if (!m_searchPopup)
+ m_searchPopup = SearchPopupMenu::create(this);
+
+ if (!m_searchPopup->enabled())
+ return;
+
+ m_searchPopupIsVisible = true;
+
+ const AtomicString& name = autosaveName();
+ m_searchPopup->loadRecentSearches(name, m_recentSearches);
+
+ // Trim the recent searches list if the maximum size has changed since we last saved.
+ HTMLInputElement* input = static_cast<HTMLInputElement*>(node());
+ if (static_cast<int>(m_recentSearches.size()) > input->maxResults()) {
+ do {
+ m_recentSearches.removeLast();
+ } while (static_cast<int>(m_recentSearches.size()) > input->maxResults());
+
+ m_searchPopup->saveRecentSearches(name, m_recentSearches);
+ }
+
+ m_searchPopup->show(absoluteBoundingBoxRect(true), document()->view(), -1);
+}
+
+void RenderTextControlSingleLine::hidePopup()
+{
+ ASSERT(node()->isHTMLElement());
+ if (m_searchPopup)
+ m_searchPopup->hide();
+
+ m_searchPopupIsVisible = false;
+}
+
+void RenderTextControlSingleLine::subtreeHasChanged()
+{
+ bool wasEdited = isEdited();
+ RenderTextControl::subtreeHasChanged();
+
+ InputElement* input = inputElement();
+ input->setValueFromRenderer(input->constrainValue(text()));
+
+ if (RenderObject* cancelButtonRenderer = m_cancelButton ? m_cancelButton->renderer() : 0)
+ updateCancelButtonVisibility(cancelButtonRenderer->style());
+
+ // If the incremental attribute is set, then dispatch the search event
+ if (input->searchEventsShouldBeDispatched())
+ startSearchEventTimer();
+
+ if (!wasEdited && node()->focused()) {
+ if (Frame* frame = document()->frame())
+ frame->textFieldDidBeginEditing(static_cast<Element*>(node()));
+ }
+
+ if (node()->focused()) {
+ if (Frame* frame = document()->frame())
+ frame->textDidChangeInTextField(static_cast<Element*>(node()));
+ }
+}
+
+void RenderTextControlSingleLine::paint(PaintInfo& paintInfo, int tx, int ty)
+{
+ RenderTextControl::paint(paintInfo, tx, ty);
+
+ if (paintInfo.phase == PaintPhaseBlockBackground && m_shouldDrawCapsLockIndicator) {
+ IntRect contentsRect = contentBoxRect();
+
+ // Convert the rect into the coords used for painting the content
+ contentsRect.move(tx + x(), ty + y());
+ theme()->paintCapsLockIndicator(this, paintInfo, contentsRect);
+ }
+}
+
+void RenderTextControlSingleLine::layout()
+{
+ int oldHeight = height();
+ calcHeight();
+
+#ifdef ANDROID_LAYOUT
+ int oldVisibleWidth = m_visibleWidth;
+#endif
+
+ int oldWidth = width();
+ calcWidth();
+
+ bool relayoutChildren = oldHeight != height() || oldWidth != width();
+
+#ifdef ANDROID_LAYOUT
+ if (oldVisibleWidth != m_visibleWidth
+ && document()->settings()->layoutAlgorithm() == Settings::kLayoutFitColumnToScreen) {
+ relayoutChildren = true;
+ }
+#endif
+
+ 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 > 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));
+ }
+
+ // Set the text block width
+ int desiredWidth = textBlockWidth();
+ if (desiredWidth != innerTextRenderer->width())
+ relayoutChildren = true;
+ innerTextRenderer->style()->setWidth(Length(desiredWidth, Fixed));
+
+ if (m_innerBlock) {
+ int innerBlockWidth = width() - paddingLeft() - paddingRight() - borderLeft() - borderRight();
+ if (innerBlockWidth != innerBlockRenderer->width())
+ relayoutChildren = true;
+ innerBlockRenderer->style()->setWidth(Length(innerBlockWidth, Fixed));
+ }
+
+ 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 < height())
+ innerTextRenderer->setLocation(innerTextRenderer->x(), (height() - currentHeight) / 2);
+ }
+}
+
+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).
+
+ // 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, xPos, yPos, tx, ty, hitTestAction))
+ return false;
+
+ if (result.innerNode() != element() && result.innerNode() != m_innerBlock.get())
+ return false;
+
+ hitInnerTextBlock(result, xPos, yPos, tx, ty);
+
+ if (!m_innerBlock)
+ return true;
+
+ Node* innerNode = 0;
+ RenderBox* innerBlockRenderer = m_innerBlock->renderBox();
+ RenderBox* innerTextRenderer = innerTextElement()->renderBox();
+
+ IntPoint localPoint = result.localPoint();
+ localPoint.move(-innerBlockRenderer->x(), -innerBlockRenderer->y());
+
+ 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() && xPos > textRight)
+ innerNode = m_cancelButton.get();
+ }
+
+ if (innerNode) {
+ result.setInnerNode(innerNode);
+ localPoint.move(-innerNode->renderBox()->x(), -innerNode->renderBox()->y());
+ }
+
+ result.setLocalPoint(localPoint);
+ return true;
+}
+
+void RenderTextControlSingleLine::forwardEvent(Event* event)
+{
+ RenderBox* innerTextRenderer = innerTextElement()->renderBox();
+
+ if (event->type() == eventNames().blurEvent) {
+ if (innerTextRenderer) {
+ if (RenderLayer* innerLayer = innerTextRenderer->layer())
+ innerLayer->scrollToOffset(style()->direction() == RTL ? innerLayer->scrollWidth() : 0, 0);
+ }
+
+ capsLockStateMayHaveChanged();
+ } else if (event->type() == eventNames().focusEvent)
+ capsLockStateMayHaveChanged();
+
+ if (!event->isMouseEvent()) {
+ RenderTextControl::forwardEvent(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->borderBoxRect().x())
+ m_resultsButton->defaultEventHandler(event);
+ 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)
+{
+ RenderTextControl::styleDidChange(diff, oldStyle);
+
+ if (RenderObject* innerBlockRenderer = m_innerBlock ? m_innerBlock->renderer() : 0) {
+ // 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.
+ innerBlockRenderer->style()->setHeight(Length());
+ innerBlockRenderer->style()->setWidth(Length());
+ innerBlockRenderer->setStyle(createInnerBlockStyle(style()));
+ }
+
+ if (RenderObject* resultsRenderer = m_resultsButton ? m_resultsButton->renderer() : 0)
+ resultsRenderer->setStyle(createResultsButtonStyle(style()));
+
+ if (RenderObject* cancelRenderer = m_cancelButton ? m_cancelButton->renderer() : 0)
+ cancelRenderer->setStyle(createCancelButtonStyle(style()));
+}
+
+void RenderTextControlSingleLine::capsLockStateMayHaveChanged()
+{
+ if (!node() || !document())
+ return;
+
+ // Only draw the caps lock indicator if these things are true:
+ // 1) The field is a password field
+ // 2) The frame is active
+ // 3) The element is focused
+ // 4) The caps lock is on
+ bool shouldDrawCapsLockIndicator = false;
+
+ if (Frame* frame = document()->frame())
+ shouldDrawCapsLockIndicator = inputElement()->isPasswordField()
+ && frame->selection()->isFocusedAndActive()
+ && document()->focusedNode() == node()
+ && PlatformKeyboardEvent::currentCapsLockState();
+
+ if (shouldDrawCapsLockIndicator != m_shouldDrawCapsLockIndicator) {
+ m_shouldDrawCapsLockIndicator = shouldDrawCapsLockIndicator;
+ repaint();
+ }
+}
+
+int RenderTextControlSingleLine::textBlockWidth() const
+{
+ int width = RenderTextControl::textBlockWidth();
+
+ if (RenderBox* resultsRenderer = m_resultsButton ? m_resultsButton->renderBox() : 0) {
+ resultsRenderer->calcWidth();
+ width -= resultsRenderer->width() + resultsRenderer->marginLeft() + resultsRenderer->marginRight();
+ }
+
+ if (RenderBox* cancelRenderer = m_cancelButton ? m_cancelButton->renderBox() : 0) {
+ cancelRenderer->calcWidth();
+ width -= cancelRenderer->width() + cancelRenderer->marginLeft() + cancelRenderer->marginRight();
+ }
+
+ return width;
+}
+
+int RenderTextControlSingleLine::preferredContentWidth(float charWidth) const
+{
+ int factor = inputElement()->size();
+ if (factor <= 0)
+ factor = 20;
+
+ int result = static_cast<int>(ceilf(charWidth * factor));
+
+ if (RenderBox* resultsRenderer = m_resultsButton ? m_resultsButton->renderBox() : 0)
+ result += resultsRenderer->borderLeft() + resultsRenderer->borderRight() +
+ resultsRenderer->paddingLeft() + resultsRenderer->paddingRight();
+
+ if (RenderBox* cancelRenderer = m_cancelButton ? m_cancelButton->renderBox() : 0)
+ result += cancelRenderer->borderLeft() + cancelRenderer->borderRight() +
+ cancelRenderer->paddingLeft() + cancelRenderer->paddingRight();
+
+ return result;
+}
+
+void RenderTextControlSingleLine::adjustControlHeightBasedOnLineHeight(int lineHeight)
+{
+ if (RenderBox* resultsRenderer = m_resultsButton ? m_resultsButton->renderBox() : 0) {
+ static_cast<RenderBlock*>(resultsRenderer)->calcHeight();
+ setHeight(max(height(),
+ resultsRenderer->borderTop() + resultsRenderer->borderBottom() +
+ resultsRenderer->paddingTop() + resultsRenderer->paddingBottom() +
+ resultsRenderer->marginTop() + resultsRenderer->marginBottom()));
+ lineHeight = max(lineHeight, resultsRenderer->height());
+ }
+
+ if (RenderBox* cancelRenderer = m_cancelButton ? m_cancelButton->renderBox() : 0) {
+ static_cast<RenderBlock*>(cancelRenderer)->calcHeight();
+ setHeight(max(height(),
+ cancelRenderer->borderTop() + cancelRenderer->borderBottom() +
+ cancelRenderer->paddingTop() + cancelRenderer->paddingBottom() +
+ cancelRenderer->marginTop() + cancelRenderer->marginBottom()));
+ lineHeight = max(lineHeight, cancelRenderer->height());
+ }
+
+ setHeight(height() + lineHeight);
+}
+
+void RenderTextControlSingleLine::createSubtreeIfNeeded()
+{
+ if (!inputElement()->isSearchField()) {
+ RenderTextControl::createSubtreeIfNeeded(m_innerBlock.get());
+ return;
+ }
+
+ if (!m_innerBlock) {
+ // Create the inner block element
+ m_innerBlock = new TextControlInnerElement(document(), node());
+ m_innerBlock->attachInnerElement(node(), createInnerBlockStyle(style()), renderArena());
+ }
+
+ if (!m_resultsButton) {
+ // Create the search results button element
+ m_resultsButton = new SearchFieldResultsButtonElement(document());
+ m_resultsButton->attachInnerElement(m_innerBlock.get(), createResultsButtonStyle(m_innerBlock->renderer()->style()), renderArena());
+ }
+
+ // Create innerText element before adding the cancel button
+ RenderTextControl::createSubtreeIfNeeded(m_innerBlock.get());
+
+ if (!m_cancelButton) {
+ // Create the cancel button element
+ m_cancelButton = new SearchFieldCancelButtonElement(document());
+ m_cancelButton->attachInnerElement(m_innerBlock.get(), createCancelButtonStyle(m_innerBlock->renderer()->style()), renderArena());
+ }
+}
+
+void RenderTextControlSingleLine::updateFromElement()
+{
+ createSubtreeIfNeeded();
+ RenderTextControl::updateFromElement();
+
+ bool placeholderVisibilityShouldChange = m_placeholderVisible != placeholderShouldBeVisible();
+ m_placeholderVisible = placeholderShouldBeVisible();
+
+ if (RenderObject* cancelButtonRenderer = m_cancelButton ? m_cancelButton->renderer() : 0)
+ updateCancelButtonVisibility(cancelButtonRenderer->style());
+
+ if (m_placeholderVisible) {
+ ExceptionCode ec = 0;
+ innerTextElement()->setInnerText(inputElement()->placeholderValue(), ec);
+ ASSERT(!ec);
+ } else if (!formControlElement()->valueMatchesRenderer() || placeholderVisibilityShouldChange)
+ setInnerTextValue(inputElement()->value());
+
+ if (m_searchPopupIsVisible)
+ m_searchPopup->updateFromElement();
+}
+
+void RenderTextControlSingleLine::cacheSelection(int start, int 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 {
+ textBlockStyle = RenderStyle::create();
+ textBlockStyle->inheritFrom(startStyle);
+ }
+
+ adjustInnerTextStyle(startStyle, textBlockStyle.get());
+
+ textBlockStyle->setWhiteSpace(PRE);
+ textBlockStyle->setWordWrap(NormalWordWrap);
+ textBlockStyle->setOverflowX(OHIDDEN);
+ textBlockStyle->setOverflowY(OHIDDEN);
+
+ // Do not allow line-height to be smaller than our default.
+ if (textBlockStyle->font().lineSpacing() > lineHeight(true, true))
+ textBlockStyle->setLineHeight(Length(-100.0f, Percent));
+
+ textBlockStyle->setDisplay(m_innerBlock ? INLINE_BLOCK : BLOCK);
+
+ // We're adding one extra pixel of padding to match WinIE.
+ textBlockStyle->setPaddingLeft(Length(1, Fixed));
+ textBlockStyle->setPaddingRight(Length(1, Fixed));
+
+ // When the placeholder is going to be displayed, temporarily override the text security to be "none".
+ // After this, updateFromElement will immediately update the text displayed.
+ // When the placeholder is no longer visible, updatePlaceholderVisiblity will reset the style,
+ // and the text security mode will be set back to the computed value correctly.
+ if (placeholderShouldBeVisible())
+ textBlockStyle->setTextSecurity(TSNONE);
+
+ return textBlockStyle.release();
+}
+
+PassRefPtr<RenderStyle> RenderTextControlSingleLine::createInnerBlockStyle(const RenderStyle* startStyle) const
+{
+ ASSERT(node()->isHTMLElement());
+
+ RefPtr<RenderStyle> innerBlockStyle = RenderStyle::create();
+ innerBlockStyle->inheritFrom(startStyle);
+
+ innerBlockStyle->setDisplay(BLOCK);
+ innerBlockStyle->setDirection(LTR);
+
+ // We don't want the shadow dom to be editable, so we set this block to read-only in case the input itself is editable.
+ innerBlockStyle->setUserModify(READ_ONLY);
+
+ return innerBlockStyle.release();
+}
+
+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);
+ else if (!input->maxResults())
+ resultsBlockStyle = getCachedPseudoStyle(RenderStyle::SEARCH_RESULTS_DECORATION);
+ else
+ resultsBlockStyle = getCachedPseudoStyle(RenderStyle::SEARCH_RESULTS_BUTTON);
+
+ if (!resultsBlockStyle)
+ resultsBlockStyle = RenderStyle::create();
+
+ if (startStyle)
+ resultsBlockStyle->inheritFrom(startStyle);
+
+ return resultsBlockStyle.release();
+}
+
+PassRefPtr<RenderStyle> RenderTextControlSingleLine::createCancelButtonStyle(const RenderStyle* startStyle) const
+{
+ ASSERT(node()->isHTMLElement());
+ RefPtr<RenderStyle> cancelBlockStyle;
+
+ if (RefPtr<RenderStyle> pseudoStyle = getCachedPseudoStyle(RenderStyle::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
+ cancelBlockStyle = RenderStyle::create();
+
+ if (startStyle)
+ cancelBlockStyle->inheritFrom(startStyle);
+
+ updateCancelButtonVisibility(cancelBlockStyle.get());
+ return cancelBlockStyle.release();
+}
+
+void RenderTextControlSingleLine::updateCancelButtonVisibility(RenderStyle* style) const
+{
+ ASSERT(node()->isHTMLElement());
+ HTMLInputElement* input = static_cast<HTMLInputElement*>(node());
+ style->setVisibility(input->value().isEmpty() ? HIDDEN : VISIBLE);
+}
+
+const AtomicString& RenderTextControlSingleLine::autosaveName() const
+{
+ return static_cast<Element*>(node())->getAttribute(autosaveAttr);
+}
+
+void RenderTextControlSingleLine::startSearchEventTimer()
+{
+ ASSERT(node()->isHTMLElement());
+ unsigned length = text().length();
+
+ // If there's no text, fire the event right away.
+ if (!length) {
+ stopSearchEventTimer();
+ static_cast<HTMLInputElement*>(node())->onSearch();
+ return;
+ }
+
+ // After typing the first key, we wait 0.5 seconds.
+ // After the second key, 0.4 seconds, then 0.3, then 0.2 from then on.
+ m_searchEventTimer.startOneShot(max(0.2, 0.6 - 0.1 * length));
+}
+
+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)) {
+ if (fireEvents) {
+ m_recentSearches.clear();
+ const AtomicString& name = autosaveName();
+ if (!name.isEmpty()) {
+ if (!m_searchPopup)
+ m_searchPopup = SearchPopupMenu::create(this);
+ m_searchPopup->saveRecentSearches(name, m_recentSearches);
+ }
+ }
+ } else {
+ input->setValue(itemText(listIndex));
+ if (fireEvents)
+ input->onSearch();
+ input->select();
+ }
+}
+
+String RenderTextControlSingleLine::itemText(unsigned listIndex) const
+{
+ int size = listSize();
+ if (size == 1) {
+ ASSERT(!listIndex);
+ return searchMenuNoRecentSearchesText();
+ }
+ if (!listIndex)
+ return searchMenuRecentSearchesText();
+ if (itemIsSeparator(listIndex))
+ return String();
+ if (static_cast<int>(listIndex) == (size - 1))
+ return searchMenuClearRecentSearchesText();
+ return m_recentSearches[listIndex - 1];
+}
+
+bool RenderTextControlSingleLine::itemIsEnabled(unsigned listIndex) const
+{
+ if (!listIndex || itemIsSeparator(listIndex))
+ return false;
+ return true;
+}
+
+PopupMenuStyle RenderTextControlSingleLine::itemStyle(unsigned) const
+{
+ return menuStyle();
+}
+
+PopupMenuStyle RenderTextControlSingleLine::menuStyle() const
+{
+ return PopupMenuStyle(style()->color(), style()->backgroundColor(), style()->font(), style()->visibility() == VISIBLE);
+}
+
+int RenderTextControlSingleLine::clientInsetLeft() const
+{
+ // Inset the menu by the radius of the cap on the left so that
+ // it only runs along the straight part of the bezel.
+ return height() / 2;
+}
+
+int RenderTextControlSingleLine::clientInsetRight() const
+{
+ // Inset the menu by the radius of the cap on the right so that
+ // it only runs along the straight part of the bezel (unless it needs
+ // to be wider).
+ return height() / 2;
+}
+
+int RenderTextControlSingleLine::clientPaddingLeft() const
+{
+ int padding = paddingLeft();
+
+ if (RenderBox* resultsRenderer = m_resultsButton ? m_resultsButton->renderBox() : 0)
+ padding += resultsRenderer->width();
+
+ return padding;
+}
+
+int RenderTextControlSingleLine::clientPaddingRight() const
+{
+ int padding = paddingRight();
+
+ if (RenderBox* cancelRenderer = m_cancelButton ? m_cancelButton->renderBox() : 0)
+ padding += cancelRenderer->width();
+
+ return padding;
+}
+
+int RenderTextControlSingleLine::listSize() const
+{
+ // If there are no recent searches, then our menu will have 1 "No recent searches" item.
+ if (!m_recentSearches.size())
+ return 1;
+ // Otherwise, leave room in the menu for a header, a separator, and the "Clear recent searches" item.
+ return m_recentSearches.size() + 3;
+}
+
+int RenderTextControlSingleLine::selectedIndex() const
+{
+ return -1;
+}
+
+bool RenderTextControlSingleLine::itemIsSeparator(unsigned listIndex) const
+{
+ // The separator will be the second to last item in our list.
+ return static_cast<int>(listIndex) == (listSize() - 2);
+}
+
+bool RenderTextControlSingleLine::itemIsLabel(unsigned listIndex) const
+{
+ return listIndex == 0;
+}
+
+bool RenderTextControlSingleLine::itemIsSelected(unsigned) const
+{
+ return false;
+}
+
+void RenderTextControlSingleLine::setTextFromItem(unsigned listIndex)
+{
+ ASSERT(node()->isHTMLElement());
+ static_cast<HTMLInputElement*>(node())->setValue(itemText(listIndex));
+}
+
+FontSelector* RenderTextControlSingleLine::fontSelector() const
+{
+ return document()->styleSelector()->fontSelector();
+}
+
+HostWindow* RenderTextControlSingleLine::hostWindow() const
+{
+ return document()->view()->hostWindow();
+}
+
+PassRefPtr<Scrollbar> RenderTextControlSingleLine::createScrollbar(ScrollbarClient* client, ScrollbarOrientation orientation, ScrollbarControlSize controlSize)
+{
+ RefPtr<Scrollbar> widget;
+ bool hasCustomScrollbarStyle = style()->hasPseudoStyle(RenderStyle::SCROLLBAR);
+ if (hasCustomScrollbarStyle)
+ widget = RenderScrollbar::createCustomScrollbar(client, orientation, this);
+ else
+ widget = Scrollbar::createNativeScrollbar(client, orientation, controlSize);
+ return widget.release();
+}
+
+InputElement* RenderTextControlSingleLine::inputElement() const
+{
+ return toInputElement(static_cast<Element*>(node()));
+}
+
+}
diff --git a/WebCore/rendering/RenderTextControlSingleLine.h b/WebCore/rendering/RenderTextControlSingleLine.h
new file mode 100644
index 0000000..a7b58e1
--- /dev/null
+++ b/WebCore/rendering/RenderTextControlSingleLine.h
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2008 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
+ * 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 RenderTextControlSingleLine_h
+#define RenderTextControlSingleLine_h
+
+#include "PopupMenuClient.h"
+#include "RenderTextControl.h"
+#include "Timer.h"
+
+namespace WebCore {
+
+class InputElement;
+class SearchFieldCancelButtonElement;
+class SearchFieldResultsButtonElement;
+class SearchPopupMenu;
+class TextControlInnerElement;
+
+class RenderTextControlSingleLine : public RenderTextControl, private PopupMenuClient {
+public:
+ RenderTextControlSingleLine(Node*);
+ virtual ~RenderTextControlSingleLine();
+
+ virtual bool hasControlClip() const { return m_cancelButton; }
+ virtual bool isTextField() const { return true; }
+
+ bool placeholderIsVisible() const { return m_placeholderVisible; }
+ bool placeholderShouldBeVisible() const;
+ void updatePlaceholderVisibility();
+
+ void addSearchResult();
+ void stopSearchEventTimer();
+
+ bool popupIsVisible() const { return m_searchPopupIsVisible; }
+ void showPopup();
+ virtual void hidePopup(); // PopupMenuClient method
+
+ virtual void subtreeHasChanged();
+ virtual void paint(PaintInfo&, int tx, int ty);
+ virtual void layout();
+
+ virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, int x, int y, int tx, int ty, HitTestAction);
+ void forwardEvent(Event*);
+
+private:
+ virtual void capsLockStateMayHaveChanged();
+
+ int textBlockWidth() const;
+ virtual int preferredContentWidth(float charWidth) const;
+ virtual void adjustControlHeightBasedOnLineHeight(int lineHeight);
+
+ void createSubtreeIfNeeded();
+ virtual void updateFromElement();
+ virtual void cacheSelection(int start, int end);
+ virtual void styleDidChange(RenderStyle::Diff, 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;
+ const AtomicString& autosaveName() const;
+
+ void startSearchEventTimer();
+ void searchEventTimerFired(Timer<RenderTextControlSingleLine>*);
+
+private:
+ // PopupMenuClient methods
+ virtual void valueChanged(unsigned listIndex, bool fireEvents = true);
+ virtual String itemText(unsigned listIndex) const;
+ virtual bool itemIsEnabled(unsigned listIndex) const;
+ virtual PopupMenuStyle itemStyle(unsigned listIndex) const;
+ virtual PopupMenuStyle menuStyle() const;
+ virtual int clientInsetLeft() const;
+ virtual int clientInsetRight() const;
+ virtual int clientPaddingLeft() const;
+ virtual int clientPaddingRight() const;
+ virtual int listSize() const;
+ virtual int selectedIndex() const;
+ virtual bool itemIsSeparator(unsigned listIndex) const;
+ virtual bool itemIsLabel(unsigned listIndex) const;
+ virtual bool itemIsSelected(unsigned listIndex) const;
+ virtual bool shouldPopOver() const { return false; }
+ virtual bool valueShouldChangeOnHotTrack() const { return false; }
+ virtual void setTextFromItem(unsigned listIndex);
+ virtual FontSelector* fontSelector() const;
+ virtual HostWindow* hostWindow() const;
+ virtual PassRefPtr<Scrollbar> createScrollbar(ScrollbarClient*, ScrollbarOrientation, ScrollbarControlSize);
+
+ InputElement* inputElement() const;
+
+private:
+ bool m_placeholderVisible;
+ bool m_searchPopupIsVisible;
+ bool m_shouldDrawCapsLockIndicator;
+
+ RefPtr<TextControlInnerElement> m_innerBlock;
+ RefPtr<SearchFieldResultsButtonElement> m_resultsButton;
+ RefPtr<SearchFieldCancelButtonElement> m_cancelButton;
+
+ Timer<RenderTextControlSingleLine> m_searchEventTimer;
+ RefPtr<SearchPopupMenu> m_searchPopup;
+ Vector<String> m_recentSearches;
+};
+
+}
+
+#endif
diff --git a/WebCore/rendering/RenderTheme.cpp b/WebCore/rendering/RenderTheme.cpp
index 9eb3ac2..e7fa5de 100644
--- a/WebCore/rendering/RenderTheme.cpp
+++ b/WebCore/rendering/RenderTheme.cpp
@@ -202,12 +202,6 @@ void RenderTheme::adjustStyle(CSSStyleSelector* selector, RenderStyle* style, El
}
}
-#if !PLATFORM(QT)
-void RenderTheme::adjustDefaultStyleSheet(CSSStyleSheet*)
-{
-}
-#endif
-
bool RenderTheme::paint(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
{
// If painting is disabled, but we aren't updating control tints, then just bail.
@@ -278,6 +272,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:
@@ -372,18 +372,71 @@ bool RenderTheme::paintDecorations(RenderObject* o, const RenderObject::PaintInf
return false;
}
+#if ENABLE(VIDEO)
+bool RenderTheme::hitTestMediaControlPart(RenderObject* o, const IntPoint& absPoint)
+{
+ if (!o->isBox())
+ return false;
+
+ FloatPoint localPoint = o->absoluteToLocal(absPoint, false, true); // respect transforms
+ return toRenderBox(o)->borderBoxRect().contains(roundedIntPoint(localPoint));
+}
+#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
@@ -392,50 +445,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
}
@@ -602,7 +661,8 @@ bool RenderTheme::isDefault(const RenderObject* o) const
}
#if !USE(NEW_THEME)
-void RenderTheme::adjustCheckboxStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
+
+void RenderTheme::adjustCheckboxStyle(CSSStyleSelector*, RenderStyle* style, Element*) const
{
// A summary of the rules for checkbox designed to match WinIE:
// width/height - honored (WinIE actually scales its control for small widths, but lets it overflow for small heights.)
@@ -619,7 +679,7 @@ void RenderTheme::adjustCheckboxStyle(CSSStyleSelector* selector, RenderStyle* s
style->setBoxShadow(0);
}
-void RenderTheme::adjustRadioStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
+void RenderTheme::adjustRadioStyle(CSSStyleSelector*, RenderStyle* style, Element*) const
{
// A summary of the rules for checkbox designed to match WinIE:
// width/height - honored (WinIE actually scales its control for small widths, but lets it overflow for small heights.)
@@ -636,35 +696,40 @@ void RenderTheme::adjustRadioStyle(CSSStyleSelector* selector, RenderStyle* styl
style->setBoxShadow(0);
}
-void RenderTheme::adjustButtonStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
+void RenderTheme::adjustButtonStyle(CSSStyleSelector*, RenderStyle* style, Element*) const
{
// Most platforms will completely honor all CSS, and so we have no need to adjust the style
// at all by default. We will still allow the theme a crack at setting up a desired vertical size.
setButtonSize(style);
}
+
#endif
-void RenderTheme::adjustTextFieldStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
+void RenderTheme::adjustTextFieldStyle(CSSStyleSelector*, RenderStyle*, Element*) const
+{
+}
+
+void RenderTheme::adjustTextAreaStyle(CSSStyleSelector*, RenderStyle*, Element*) const
{
}
-void RenderTheme::adjustTextAreaStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
+void RenderTheme::adjustMenuListStyle(CSSStyleSelector*, RenderStyle*, Element*) const
{
}
-void RenderTheme::adjustMenuListStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
+void RenderTheme::adjustMenuListButtonStyle(CSSStyleSelector*, RenderStyle*, Element*) const
{
}
-void RenderTheme::adjustMenuListButtonStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
+void RenderTheme::adjustButtonInnerStyle(RenderStyle*) const
{
}
-void RenderTheme::adjustSliderTrackStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
+void RenderTheme::adjustSliderTrackStyle(CSSStyleSelector*, RenderStyle*, Element*) const
{
}
-void RenderTheme::adjustSliderThumbStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
+void RenderTheme::adjustSliderThumbStyle(CSSStyleSelector*, RenderStyle*, Element*) const
{
}
@@ -672,30 +737,37 @@ void RenderTheme::adjustSliderThumbSize(RenderObject*) const
{
}
-void RenderTheme::adjustSearchFieldStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
+void RenderTheme::adjustSearchFieldStyle(CSSStyleSelector*, RenderStyle*, Element*) const
{
}
-void RenderTheme::adjustSearchFieldCancelButtonStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
+void RenderTheme::adjustSearchFieldCancelButtonStyle(CSSStyleSelector*, RenderStyle*, Element*) const
{
}
-void RenderTheme::adjustSearchFieldDecorationStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
+void RenderTheme::adjustSearchFieldDecorationStyle(CSSStyleSelector*, RenderStyle*, Element*) const
{
}
-void RenderTheme::adjustSearchFieldResultsDecorationStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
+void RenderTheme::adjustSearchFieldResultsDecorationStyle(CSSStyleSelector*, RenderStyle*, Element*) const
{
}
-void RenderTheme::adjustSearchFieldResultsButtonStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
+void RenderTheme::adjustSearchFieldResultsButtonStyle(CSSStyleSelector*, RenderStyle*, Element*) const
{
}
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
diff --git a/WebCore/rendering/RenderTheme.h b/WebCore/rendering/RenderTheme.h
index 2935d42..828e789 100644
--- a/WebCore/rendering/RenderTheme.h
+++ b/WebCore/rendering/RenderTheme.h
@@ -50,10 +50,6 @@ public:
void adjustStyle(CSSStyleSelector*, RenderStyle*, Element*, bool UAHasAppearance,
const BorderData&, const FillLayer&, const Color& backgroundColor);
- // This method is called once, from CSSStyleSelector::loadDefaultStyle(), to let each platform adjust
- // the default CSS rules in html4.css.
- static void adjustDefaultStyleSheet(CSSStyleSheet*);
-
// This method is called to paint the widget as a background of the RenderObject. A widget's foreground, e.g., the
// text of a button, is always rendered by the engine itself. The boolean return value indicates
// whether the CSS border/background should also be painted.
@@ -64,6 +60,14 @@ public:
// The remaining methods should be implemented by the platform-specific portion of the theme, e.g.,
// RenderThemeMac.cpp for Mac OS X.
+ // These methods return the theme's extra style sheets rules, to let each platform
+ // adjust the default CSS rules in html4.css, quirks.css, or mediaControls.css
+ virtual String extraDefaultStyleSheet() { return String(); }
+ virtual String extraQuirksStyleSheet() { return String(); }
+#if ENABLE(VIDEO)
+ virtual String extraMediaControlsStyleSheet() { return String(); };
+#endif
+
// 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.
@@ -100,27 +104,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;
-
- // The platform selection color.
- virtual Color platformActiveSelectionBackgroundColor() const;
- virtual Color platformInactiveSelectionBackgroundColor() const;
- virtual Color platformActiveSelectionForegroundColor() const;
- virtual Color platformInactiveSelectionForegroundColor() const;
+ // List box selection colors
+ Color activeListBoxSelectionBackgroundColor() const;
+ Color activeListBoxSelectionForegroundColor() const;
+ Color inactiveListBoxSelectionBackgroundColor() const;
+ Color inactiveListBoxSelectionForegroundColor() const;
- // List Box selection color
- virtual Color activeListBoxSelectionBackgroundColor() const;
- virtual Color activeListBoxSelectionForegroundColor() const;
- virtual Color inactiveListBoxSelectionBackgroundColor() const;
- virtual Color inactiveListBoxSelectionForegroundColor() const;
+ virtual Color platformTextSearchHighlightColor() const;
virtual void platformColorsDidChange();
- virtual double caretBlinkFrequency() const { return 0.5; }
+ virtual double caretBlinkInterval() const { return 0.5; }
// System fonts and colors for CSS.
virtual void systemFont(int cssValueId, FontDescription&) const = 0;
@@ -128,6 +128,7 @@ 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; }
@@ -138,7 +139,26 @@ public:
// 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;
@@ -197,6 +217,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
@@ -212,8 +235,16 @@ 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
diff --git a/WebCore/rendering/RenderThemeChromiumGtk.cpp b/WebCore/rendering/RenderThemeChromiumGtk.cpp
new file mode 100644
index 0000000..220ce07
--- /dev/null
+++ b/WebCore/rendering/RenderThemeChromiumGtk.cpp
@@ -0,0 +1,532 @@
+/*
+ * 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 "RenderThemeChromiumGtk.h"
+
+#include "ChromiumBridge.h"
+#include "CSSValueKeywords.h"
+#include "GraphicsContext.h"
+#include "NotImplemented.h"
+#include "PlatformContextSkia.h"
+#include "RenderObject.h"
+#include "ScrollbarTheme.h"
+#include "gtkdrawing.h"
+#include "GdkSkia.h"
+#include "TransformationMatrix.h"
+#include "UserAgentStyleSheets.h"
+
+#include <gdk/gdk.h>
+
+namespace WebCore {
+
+enum PaddingType {
+ TopPadding,
+ RightPadding,
+ BottomPadding,
+ LeftPadding
+};
+
+static const int styledMenuListInternalPadding[4] = { 1, 4, 1, 4 };
+
+// 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 = 16.0;
+
+static Color makeColor(const GdkColor& c)
+{
+ return Color(makeRGB(c.red >> 8, c.green >> 8, c.blue >> 8));
+}
+
+// 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.
+static const char* defaultGUIFont(Document* document)
+{
+ return "Arial";
+}
+
+// Converts points to pixels. One point is 1/72 of an inch.
+static float pointsToPixels(float points)
+{
+ static float pixelsPerInch = 0.0f;
+ if (!pixelsPerInch) {
+ GdkScreen* screen = gdk_screen_get_default();
+ // FIXME: I'm getting floating point values of ~75 and ~100,
+ // and it's making my fonts look all wrong. Figure this out.
+#if 0
+ if (screen)
+ pixelsPerInch = gdk_screen_get_resolution(screen);
+ else
+#endif
+ pixelsPerInch = 96.0f; // Match the default we set on Windows.
+ }
+
+ static const float pointsPerInch = 72.0f;
+ return points / pointsPerInch * pixelsPerInch;
+}
+
+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));
+}
+
+static bool supportsFocus(ControlPart appearance)
+{
+ switch (appearance) {
+ case PushButtonPart:
+ case ButtonPart:
+ case TextFieldPart:
+ case TextAreaPart:
+ case SearchFieldPart:
+ case MenulistPart:
+ case RadioPart:
+ case CheckboxPart:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static GtkTextDirection gtkTextDirection(TextDirection direction)
+{
+ switch (direction) {
+ case RTL:
+ return GTK_TEXT_DIR_RTL;
+ case LTR:
+ return GTK_TEXT_DIR_LTR;
+ default:
+ return GTK_TEXT_DIR_NONE;
+ }
+}
+
+static void setMozState(RenderTheme* theme, GtkWidgetState* state, RenderObject* o)
+{
+ state->active = theme->isPressed(o);
+ state->focused = theme->isFocused(o);
+ state->inHover = theme->isHovered(o);
+ // FIXME: Disabled does not always give the correct appearance for ReadOnly
+ state->disabled = !theme->isEnabled(o) || theme->isReadOnlyControl(o);
+ state->isDefault = false;
+ state->canDefault = false;
+ state->depressed = false;
+}
+
+static bool paintMozWidget(RenderTheme* theme, GtkThemeWidgetType type, RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& rect)
+{
+ // Painting is disabled so just claim to have succeeded
+ if (i.context->paintingDisabled())
+ return false;
+
+ GtkWidgetState mozState;
+ setMozState(theme, &mozState, o);
+
+ int flags;
+
+ // We might want to make setting flags the caller's job at some point rather than doing it here.
+ switch (type) {
+ case MOZ_GTK_BUTTON:
+ flags = GTK_RELIEF_NORMAL;
+ break;
+ case MOZ_GTK_CHECKBUTTON:
+ case MOZ_GTK_RADIOBUTTON:
+ flags = theme->isChecked(o);
+ break;
+ default:
+ flags = 0;
+ break;
+ }
+
+ PlatformContextSkia* pcs = i.context->platformContext();
+ SkCanvas* canvas = pcs->canvas();
+ if (!canvas)
+ return false;
+
+ GdkRectangle gdkRect;
+ gdkRect.x = rect.x();
+ gdkRect.y = rect.y();
+ gdkRect.width = rect.width();
+ gdkRect.height = rect.height();
+
+ // getTotalClip returns the currently set clip region in device coordinates,
+ // so we have to apply the current transform (actually we only support translations)
+ // to get the page coordinates that our gtk widget rendering expects.
+ // We invert it because we want to map from device coordinates to page coordinates.
+ const SkIRect clipRegion = canvas->getTotalClip().getBounds();
+ TransformationMatrix ctm = i.context->getCTM().inverse();
+ IntPoint pos = ctm.mapPoint(IntPoint(SkScalarRound(clipRegion.fLeft), SkScalarRound(clipRegion.fTop)));
+ GdkRectangle gdkClipRect;
+ gdkClipRect.x = pos.x();
+ gdkClipRect.y = pos.y();
+ gdkClipRect.width = clipRegion.width();
+ gdkClipRect.height = clipRegion.height();
+
+ // moz_gtk_widget_paint will paint outside the bounds of gdkRect unless we further restrict |gdkClipRect|.
+ gdk_rectangle_intersect(&gdkRect, &gdkClipRect, &gdkClipRect);
+
+ GtkTextDirection direction = gtkTextDirection(o->style()->direction());
+
+ return moz_gtk_widget_paint(type, pcs->gdk_skia(), &gdkRect, &gdkClipRect, &mozState, flags, direction) != MOZ_GTK_SUCCESS;
+}
+
+static void gtkStyleSetCallback(GtkWidget* widget, GtkStyle* previous, RenderTheme* renderTheme)
+{
+ // FIXME: Make sure this function doesn't get called many times for a single GTK+ style change signal.
+ renderTheme->platformColorsDidChange();
+}
+
+static double querySystemBlinkInterval(double defaultInterval)
+{
+ GtkSettings* settings = gtk_settings_get_default();
+
+ gboolean shouldBlink;
+ gint time;
+
+ g_object_get(settings, "gtk-cursor-blink", &shouldBlink, "gtk-cursor-blink-time", &time, NULL);
+
+ if (!shouldBlink)
+ return 0;
+
+ return time / 1000.0;
+}
+
+// Implement WebCore::theme() for getting the global RenderTheme.
+RenderTheme* theme()
+{
+ static RenderThemeChromiumGtk gtkTheme;
+ return &gtkTheme;
+}
+
+RenderThemeChromiumGtk::RenderThemeChromiumGtk()
+ : m_gtkWindow(0)
+ , m_gtkContainer(0)
+ , m_gtkEntry(0)
+ , m_gtkTreeView(0)
+{
+}
+
+// Use the Windows style sheets to match their metrics.
+String RenderThemeChromiumGtk::extraDefaultStyleSheet()
+{
+ return String(themeWinUserAgentStyleSheet, sizeof(themeWinUserAgentStyleSheet));
+}
+
+String RenderThemeChromiumGtk::extraQuirksStyleSheet()
+{
+ return String(themeWinQuirksUserAgentStyleSheet, sizeof(themeWinQuirksUserAgentStyleSheet));
+}
+
+bool RenderThemeChromiumGtk::supportsFocusRing(const RenderStyle* style) const
+{
+ return supportsFocus(style->appearance());
+}
+
+Color RenderThemeChromiumGtk::platformActiveSelectionBackgroundColor() const
+{
+ GtkWidget* widget = gtkEntry();
+ return makeColor(widget->style->base[GTK_STATE_SELECTED]);
+}
+
+Color RenderThemeChromiumGtk::platformInactiveSelectionBackgroundColor() const
+{
+ GtkWidget* widget = gtkEntry();
+ return makeColor(widget->style->base[GTK_STATE_ACTIVE]);
+}
+
+Color RenderThemeChromiumGtk::platformActiveSelectionForegroundColor() const
+{
+ GtkWidget* widget = gtkEntry();
+ return makeColor(widget->style->text[GTK_STATE_SELECTED]);
+}
+
+Color RenderThemeChromiumGtk::platformInactiveSelectionForegroundColor() const
+{
+ GtkWidget* widget = gtkEntry();
+ return makeColor(widget->style->text[GTK_STATE_ACTIVE]);
+}
+
+Color RenderThemeChromiumGtk::platformTextSearchHighlightColor() const
+{
+ return Color(255, 255, 150);
+}
+
+double RenderThemeChromiumGtk::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;
+
+ // We cache the interval so we don't have to repeatedly request it from gtk.
+ static double blinkInterval = querySystemBlinkInterval(RenderTheme::caretBlinkInterval());
+ return blinkInterval;
+}
+
+void RenderThemeChromiumGtk::systemFont(int propId, Document* document, FontDescription& fontDescription) const
+{
+ const char* faceName = 0;
+ float fontSize = 0;
+ // FIXME: see also RenderThemeChromiumWin.cpp
+ switch (propId) {
+ case CSSValueMenu:
+ case CSSValueStatusBar:
+ case CSSValueSmallCaption:
+ // triggered by LayoutTests/fast/css/css2-system-fonts.html
+ notImplemented();
+ break;
+ case CSSValueWebkitMiniControl:
+ case CSSValueWebkitSmallControl:
+ case CSSValueWebkitControl:
+ faceName = defaultGUIFont(document);
+ // Why 2 points smaller? Because that's what Gecko does.
+ fontSize = DefaultFontSize - pointsToPixels(2);
+ break;
+ default:
+ faceName = defaultGUIFont(document);
+ fontSize = DefaultFontSize;
+ }
+
+ // Only update if the size makes sense.
+ if (fontSize > 0) {
+ fontDescription.firstFamily().setFamily(faceName);
+ fontDescription.setSpecifiedSize(fontSize);
+ fontDescription.setIsAbsoluteSize(true);
+ fontDescription.setGenericFamily(FontDescription::NoFamily);
+ fontDescription.setWeight(FontWeightNormal);
+ fontDescription.setItalic(false);
+ }
+}
+
+int RenderThemeChromiumGtk::minimumMenuListSize(RenderStyle* style) const
+{
+ return 0;
+}
+
+bool RenderThemeChromiumGtk::paintCheckbox(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& rect)
+{
+ return paintMozWidget(this, MOZ_GTK_CHECKBUTTON, o, i, rect);
+}
+
+void RenderThemeChromiumGtk::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 RenderThemeChromiumGtk::paintRadio(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& rect)
+{
+ return paintMozWidget(this, MOZ_GTK_RADIOBUTTON, o, i, rect);
+}
+
+void RenderThemeChromiumGtk::setRadioSize(RenderStyle* style) const
+{
+ // Use same sizing for radio box as checkbox.
+ setCheckboxSize(style);
+}
+
+bool RenderThemeChromiumGtk::paintButton(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& rect)
+{
+ return paintMozWidget(this, MOZ_GTK_BUTTON, o, i, rect);
+}
+
+bool RenderThemeChromiumGtk::paintTextField(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& rect)
+{
+ return paintMozWidget(this, MOZ_GTK_ENTRY, o, i, rect);
+}
+
+bool RenderThemeChromiumGtk::paintSearchField(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& rect)
+{
+ return paintTextField(o, i, rect);
+}
+
+bool RenderThemeChromiumGtk::paintSearchFieldResultsDecoration(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& rect)
+{
+ return paintMozWidget(this, MOZ_GTK_CHECKMENUITEM, o, i, rect);
+}
+
+bool RenderThemeChromiumGtk::paintSearchFieldResultsButton(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& rect)
+{
+ return paintMozWidget(this, MOZ_GTK_DROPDOWN_ARROW, o, i, rect);
+}
+
+bool RenderThemeChromiumGtk::paintSearchFieldCancelButton(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& rect)
+{
+ return paintMozWidget(this, MOZ_GTK_CHECKMENUITEM, o, i, rect);
+}
+
+void RenderThemeChromiumGtk::adjustMenuListStyle(CSSStyleSelector* selector, RenderStyle* style, WebCore::Element* e) const
+{
+ // Height is locked to auto on all browsers.
+ style->setLineHeight(RenderStyle::initialLineHeight());
+}
+
+bool RenderThemeChromiumGtk::paintMenuList(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& rect)
+{
+ return paintMozWidget(this, MOZ_GTK_DROPDOWN, o, i, rect);
+}
+
+void RenderThemeChromiumGtk::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 RenderThemeChromiumGtk::paintMenuListButton(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& r)
+{
+ return paintMenuList(o, i, r);
+}
+
+int RenderThemeChromiumGtk::popupInternalPaddingLeft(RenderStyle* style) const
+{
+ return menuListInternalPadding(style, LeftPadding);
+}
+
+int RenderThemeChromiumGtk::popupInternalPaddingRight(RenderStyle* style) const
+{
+ return menuListInternalPadding(style, RightPadding);
+}
+
+int RenderThemeChromiumGtk::popupInternalPaddingTop(RenderStyle* style) const
+{
+ return menuListInternalPadding(style, TopPadding);
+}
+
+int RenderThemeChromiumGtk::popupInternalPaddingBottom(RenderStyle* style) const
+{
+ return menuListInternalPadding(style, BottomPadding);
+}
+
+void RenderThemeChromiumGtk::adjustButtonInnerStyle(RenderStyle* style) 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));
+}
+
+bool RenderThemeChromiumGtk::controlSupportsTints(const RenderObject* o) const
+{
+ return isEnabled(o);
+}
+
+Color RenderThemeChromiumGtk::activeListBoxSelectionBackgroundColor() const
+{
+ GtkWidget* widget = gtkTreeView();
+ return makeColor(widget->style->base[GTK_STATE_SELECTED]);
+}
+
+Color RenderThemeChromiumGtk::activeListBoxSelectionForegroundColor() const
+{
+ GtkWidget* widget = gtkTreeView();
+ return makeColor(widget->style->text[GTK_STATE_SELECTED]);
+}
+
+Color RenderThemeChromiumGtk::inactiveListBoxSelectionBackgroundColor() const
+{
+ GtkWidget* widget = gtkTreeView();
+ return makeColor(widget->style->base[GTK_STATE_ACTIVE]);
+}
+
+Color RenderThemeChromiumGtk::inactiveListBoxSelectionForegroundColor() const
+{
+ GtkWidget* widget = gtkTreeView();
+ return makeColor(widget->style->text[GTK_STATE_ACTIVE]);
+}
+
+GtkWidget* RenderThemeChromiumGtk::gtkEntry() const
+{
+ if (m_gtkEntry)
+ return m_gtkEntry;
+
+ m_gtkEntry = gtk_entry_new();
+ g_signal_connect(m_gtkEntry, "style-set", G_CALLBACK(gtkStyleSetCallback), theme());
+ gtk_container_add(gtkContainer(), m_gtkEntry);
+ gtk_widget_realize(m_gtkEntry);
+
+ return m_gtkEntry;
+}
+
+GtkWidget* RenderThemeChromiumGtk::gtkTreeView() const
+{
+ if (m_gtkTreeView)
+ return m_gtkTreeView;
+
+ m_gtkTreeView = gtk_tree_view_new();
+ g_signal_connect(m_gtkTreeView, "style-set", G_CALLBACK(gtkStyleSetCallback), theme());
+ gtk_container_add(gtkContainer(), m_gtkTreeView);
+ gtk_widget_realize(m_gtkTreeView);
+
+ return m_gtkTreeView;
+}
+
+GtkContainer* RenderThemeChromiumGtk::gtkContainer() const
+{
+ if (m_gtkContainer)
+ return m_gtkContainer;
+
+ m_gtkWindow = gtk_window_new(GTK_WINDOW_POPUP);
+ m_gtkContainer = GTK_CONTAINER(gtk_fixed_new());
+ gtk_container_add(GTK_CONTAINER(m_gtkWindow), GTK_WIDGET(m_gtkContainer));
+ gtk_widget_realize(m_gtkWindow);
+
+ return m_gtkContainer;
+}
+
+int RenderThemeChromiumGtk::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 bar_type = style->direction() == LTR ? RightPadding : LeftPadding;
+ if (paddingType == bar_type && style->appearance() != NoControlPart)
+ padding += ScrollbarTheme::nativeTheme()->scrollbarThickness();
+
+ return padding;
+}
+
+} // namespace WebCore
diff --git a/WebCore/rendering/RenderThemeChromiumGtk.h b/WebCore/rendering/RenderThemeChromiumGtk.h
new file mode 100644
index 0000000..77d927f
--- /dev/null
+++ b/WebCore/rendering/RenderThemeChromiumGtk.h
@@ -0,0 +1,136 @@
+/*
+ * 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 RenderThemeChromiumGtk_h
+#define RenderThemeChromiumGtk_h
+
+#include "RenderTheme.h"
+
+#include <gtk/gtk.h>
+
+namespace WebCore {
+
+ class RenderThemeChromiumGtk : public RenderTheme {
+ public:
+ RenderThemeChromiumGtk();
+ ~RenderThemeChromiumGtk() { }
+
+ virtual String extraDefaultStyleSheet();
+ virtual String extraQuirksStyleSheet();
+
+ // A method asking if the theme's controls actually care about redrawing when hovered.
+ virtual bool supportsHover(const RenderStyle*) const { return true; }
+
+ // 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 platformTextSearchHighlightColor() const;
+
+ virtual double caretBlinkInterval() const;
+
+ // System fonts.
+ virtual void systemFont(int propId, Document*, 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* o, const RenderObject::PaintInfo& i, const IntRect& r) { return paintTextField(o, i, r); }
+
+ virtual bool paintSearchField(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+
+ virtual bool paintSearchFieldResultsDecoration(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+ virtual bool paintSearchFieldResultsButton(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+ virtual bool paintSearchFieldCancelButton(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 void adjustButtonInnerStyle(RenderStyle* style) 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; }
+
+ // List Box selection color
+ virtual Color activeListBoxSelectionBackgroundColor() const;
+ virtual Color activeListBoxSelectionForegroundColor() const;
+ virtual Color inactiveListBoxSelectionBackgroundColor() const;
+ virtual Color inactiveListBoxSelectionForegroundColor() const;
+
+ private:
+ // Hold the state
+ GtkWidget* gtkEntry() const;
+ GtkWidget* gtkTreeView() const;
+
+ // Unmapped GdkWindow having a container. This is holding all our fake widgets
+ GtkContainer* gtkContainer() const;
+
+ private:
+ int menuListInternalPadding(RenderStyle*, int paddingType) const;
+
+ mutable GtkWidget* m_gtkWindow;
+ mutable GtkContainer* m_gtkContainer;
+ mutable GtkWidget* m_gtkEntry;
+ mutable GtkWidget* m_gtkTreeView;
+ };
+
+} // namespace WebCore
+
+#endif
diff --git a/WebCore/rendering/RenderThemeChromiumMac.h b/WebCore/rendering/RenderThemeChromiumMac.h
new file mode 100644
index 0000000..b750213
--- /dev/null
+++ b/WebCore/rendering/RenderThemeChromiumMac.h
@@ -0,0 +1,210 @@
+/*
+ * 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.
+ *
+ * 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 <wtf/HashMap.h>
+#import <wtf/RetainPtr.h>
+
+#ifdef __OBJC__
+@class WebCoreRenderThemeNotificationObserver;
+#else
+class WebCoreRenderThemeNotificationObserver;
+#endif
+
+namespace WebCore {
+
+ class RenderStyle;
+
+ class RenderThemeChromiumMac : public RenderTheme {
+ public:
+ RenderThemeChromiumMac();
+ virtual ~RenderThemeChromiumMac();
+
+ // 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 void platformColorsDidChange();
+
+ // System fonts.
+ virtual void systemFont(int cssValueId, Document*, 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 bool paintCapsLockIndicator(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+
+ virtual Color systemColor(int cssValueId) const;
+
+ protected:
+ // 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:
+ 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/WebCore/rendering/RenderThemeChromiumMac.mm b/WebCore/rendering/RenderThemeChromiumMac.mm
new file mode 100644
index 0000000..6318fd9
--- /dev/null
+++ b/WebCore/rendering/RenderThemeChromiumMac.mm
@@ -0,0 +1,1973 @@
+/*
+ * Copyright (C) 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * 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.
+ */
+
+// 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 "CSSStyleSelector.h"
+#import "CSSValueKeywords.h"
+#import "Document.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);
+}
+
+RenderTheme* theme()
+{
+ static RenderThemeChromiumMac* macTheme = new RenderThemeChromiumMac;
+ return macTheme;
+}
+
+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]));
+}
+
+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, Document* document, 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 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->element() && o->element()->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->style()->appearance() == CheckboxPart || o->style()->appearance() == RadioPart)
+ return o->marginTop() + o->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)
+{
+ // 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)
+{
+ // 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)
+{
+ 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->isEnabled() ? 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)
+{
+ 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)
+{
+ 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)
+{
+ 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;
+}
+
+bool RenderThemeChromiumMac::paintMediaFullscreenButton(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
+{
+#if ENABLE(VIDEO)
+ Node* node = o->element();
+ if (!node)
+ return false;
+
+ LocalCurrentGraphicsContext localContext(paintInfo.context);
+ wkDrawMediaUIPart(MediaFullscreenButton, 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->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;
+
+ LocalCurrentGraphicsContext localContext(paintInfo.context);
+ wkDrawMediaUIPart(mediaElement->muted() ? MediaUnMuteButton : MediaMuteButton, 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->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;
+
+ LocalCurrentGraphicsContext localContext(paintInfo.context);
+ wkDrawMediaUIPart(mediaElement->canPlay() ? MediaPlayButton : MediaPauseButton, 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->element();
+ if (!node)
+ return false;
+
+ LocalCurrentGraphicsContext localContext(paintInfo.context);
+ wkDrawMediaUIPart(MediaSeekBackButton, 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->element();
+ if (!node)
+ return false;
+
+ LocalCurrentGraphicsContext localContext(paintInfo.context);
+ wkDrawMediaUIPart(MediaSeekForwardButton, 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->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 timeLoaded = 0;
+ float currentTime = 0;
+ float duration = 0;
+ if (MediaPlayer* player = mediaElement->player()) {
+ duration = player->duration();
+ timeLoaded = player->maxTimeBuffered();
+ currentTime = player->currentTime();
+ }
+
+ wkDrawMediaSliderTrack(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->element();
+ if (!node)
+ return false;
+
+ LocalCurrentGraphicsContext localContext(paintInfo.context);
+ wkDrawMediaUIPart(MediaSliderThumb, 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/WebCore/rendering/RenderThemeChromiumWin.cpp b/WebCore/rendering/RenderThemeChromiumWin.cpp
new file mode 100644
index 0000000..c304385
--- /dev/null
+++ b/WebCore/rendering/RenderThemeChromiumWin.cpp
@@ -0,0 +1,614 @@
+/*
+ * 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., 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 "CSSStyleSheet.h"
+#include "CSSValueKeywords.h"
+#include "Document.h"
+#include "FontSelector.h"
+#include "FontUtilsChromiumWin.h"
+#include "GraphicsContext.h"
+#include "ScrollbarTheme.h"
+#include "SkiaUtils.h"
+#include "ThemeHelperChromiumWin.h"
+#include "UserAgentStyleSheets.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 {
+
+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);
+}
+
+enum PaddingType {
+ TopPadding,
+ RightPadding,
+ BottomPadding,
+ LeftPadding
+};
+
+static const int styledMenuListInternalPadding[4] = { 1, 4, 1, 4 };
+
+// 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 = 16.0;
+
+static FontDescription smallSystemFont;
+static FontDescription menuFont;
+static FontDescription labelFont;
+
+bool RenderThemeChromiumWin::m_findInPageMode = false;
+
+// 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 TextFieldPart:
+ case TextAreaPart:
+ return true;
+ }
+ return false;
+}
+
+static void setFixedPadding(RenderStyle* style, const int padding[4])
+{
+ style->setPaddingLeft(Length(padding[LeftPadding], Fixed));
+ style->setPaddingRight(Length(padding[RightPadding], Fixed));
+ style->setPaddingTop(Length(padding[TopPadding], Fixed));
+ style->setPaddingBottom(Length(padding[BottomPadding], Fixed));
+}
+
+// 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;
+}
+
+// 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.
+static wchar_t* defaultGUIFont(Document* document)
+{
+ UScriptCode dominantScript = document->dominantScript();
+ const wchar_t* family = NULL;
+
+ // FIXME: Special-casing of Latin/Greeek/Cyrillic should go away once
+ // GetFontFamilyForScript is enhanced to support GenericFamilyType for
+ // real. For now, we make sure that we use Arial to match IE for those
+ // scripts.
+ if (dominantScript != USCRIPT_LATIN &&
+ dominantScript != USCRIPT_CYRILLIC &&
+ dominantScript != USCRIPT_GREEK &&
+ dominantScript != USCRIPT_INVALID_CODE) {
+ family = getFontFamilyForScript(dominantScript, FontDescription::NoFamily);
+ if (family)
+ return const_cast<wchar_t*>(family);
+ }
+ return L"Arial";
+}
+
+// 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 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));
+}
+
+static double querySystemBlinkInterval(double defaultInterval)
+{
+ UINT blinkTime = GetCaretBlinkTime();
+ if (blinkTime == 0)
+ return defaultInterval;
+ if (blinkTime == INFINITE)
+ return 0;
+ return blinkTime / 1000.0;
+}
+
+// Implement WebCore::theme() for getting the global RenderTheme.
+RenderTheme* theme()
+{
+ static RenderThemeChromiumWin winTheme;
+ return &winTheme;
+}
+
+String RenderThemeChromiumWin::extraDefaultStyleSheet()
+{
+ return String(themeWinUserAgentStyleSheet, sizeof(themeWinUserAgentStyleSheet));
+}
+
+String RenderThemeChromiumWin::extraQuirksStyleSheet()
+{
+ return String(themeWinQuirksUserAgentStyleSheet, sizeof(themeWinQuirksUserAgentStyleSheet));
+}
+
+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("#0000FF"); // Royal blue.
+ if (m_findInPageMode)
+ return Color(255, 150, 50, 200); // Orange.
+ COLORREF color = GetSysColor(COLOR_HIGHLIGHT);
+ return Color(GetRValue(color), GetGValue(color), GetBValue(color), 255);
+}
+
+Color RenderThemeChromiumWin::platformInactiveSelectionBackgroundColor() const
+{
+ if (ChromiumBridge::layoutTestMode())
+ return Color("#999999"); // Medium gray.
+ if (m_findInPageMode)
+ return Color(255, 150, 50, 200); // Orange.
+ COLORREF color = GetSysColor(COLOR_GRAYTEXT);
+ return Color(GetRValue(color), GetGValue(color), GetBValue(color), 255);
+}
+
+Color RenderThemeChromiumWin::platformActiveSelectionForegroundColor() const
+{
+ if (ChromiumBridge::layoutTestMode())
+ return Color("#FFFFCC"); // Pale yellow.
+ COLORREF color = GetSysColor(COLOR_HIGHLIGHTTEXT);
+ return Color(GetRValue(color), GetGValue(color), GetBValue(color), 255);
+}
+
+Color RenderThemeChromiumWin::platformInactiveSelectionForegroundColor() const
+{
+ return Color::white;
+}
+
+Color RenderThemeChromiumWin::platformTextSearchHighlightColor() const
+{
+ return Color(255, 255, 150);
+}
+
+double RenderThemeChromiumWin::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;
+
+ // This involves a system call, so we cache the result.
+ static double blinkInterval = querySystemBlinkInterval(RenderTheme::caretBlinkInterval());
+ return blinkInterval;
+}
+
+void RenderThemeChromiumWin::systemFont(int propId, Document* document, FontDescription& fontDescription) const
+{
+ // This logic owes much to RenderThemeSafari.cpp.
+ FontDescription* cachedDesc = NULL;
+ wchar_t* faceName = 0;
+ float fontSize = 0;
+ switch (propId) {
+ case CSSValueSmallCaption:
+ cachedDesc = &smallSystemFont;
+ if (!smallSystemFont.isAbsoluteSize()) {
+ NONCLIENTMETRICS metrics;
+ getNonClientMetrics(&metrics);
+ faceName = metrics.lfSmCaptionFont.lfFaceName;
+ fontSize = systemFontSize(metrics.lfSmCaptionFont);
+ }
+ break;
+ case CSSValueMenu:
+ cachedDesc = &menuFont;
+ if (!menuFont.isAbsoluteSize()) {
+ NONCLIENTMETRICS metrics;
+ getNonClientMetrics(&metrics);
+ faceName = 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(document);
+ // Why 2 points smaller? Because that's what Gecko does.
+ fontSize = defaultFontSize - pointsToPixels(2);
+ break;
+ default:
+ faceName = defaultGUIFont(document);
+ fontSize = defaultFontSize;
+ break;
+ }
+
+ if (!cachedDesc)
+ cachedDesc = &fontDescription;
+
+ if (fontSize) {
+ ASSERT(faceName);
+ cachedDesc->firstFamily().setFamily(AtomicString(faceName,
+ wcslen(faceName)));
+ cachedDesc->setIsAbsoluteSize(true);
+ cachedDesc->setGenericFamily(FontDescription::NoFamily);
+ cachedDesc->setSpecifiedSize(fontSize);
+ cachedDesc->setWeight(FontWeightNormal);
+ cachedDesc->setItalic(false);
+ }
+ fontDescription = *cachedDesc;
+}
+
+int RenderThemeChromiumWin::minimumMenuListSize(RenderStyle* style) const
+{
+ return 0;
+}
+
+void RenderThemeChromiumWin::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);
+}
+
+void RenderThemeChromiumWin::setRadioSize(RenderStyle* style) const
+{
+ // Use same sizing for radio box as checkbox.
+ setCheckboxSize(style);
+}
+
+bool RenderThemeChromiumWin::paintButton(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& r)
+{
+ const ThemeData& themeData = getThemeData(o);
+
+ WebCore::ThemeHelperWin helper(i.context, r);
+ ChromiumBridge::paintButton(helper.context(),
+ themeData.m_part,
+ themeData.m_state,
+ themeData.m_classicState,
+ helper.rect());
+ return false;
+}
+
+bool RenderThemeChromiumWin::paintTextField(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& r)
+{
+ return paintTextFieldInternal(o, i, r, true);
+}
+
+bool RenderThemeChromiumWin::paintSearchField(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& r)
+{
+ return paintTextField(o, i, r);
+}
+
+void RenderThemeChromiumWin::adjustMenuListStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
+{
+ // Height is locked to auto on all browsers.
+ style->setLineHeight(RenderStyle::initialLineHeight());
+}
+
+// Used to paint unstyled menulists (i.e. with the default border)
+bool RenderThemeChromiumWin::paintMenuList(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& r)
+{
+ int borderRight = o->borderRight();
+ int borderLeft = o->borderLeft();
+ int borderTop = o->borderTop();
+ int borderBottom = o->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 + o->paddingLeft();
+ int spacingRight = borderRight + o->paddingRight();
+ int spacingTop = borderTop + o->paddingTop();
+ int spacingBottom = borderBottom + o->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::ThemeHelperWin helper(i.context, rect);
+ ChromiumBridge::paintMenuList(helper.context(),
+ CP_DROPDOWNBUTTON,
+ determineState(o),
+ determineClassicState(o),
+ helper.rect());
+ return false;
+}
+
+void RenderThemeChromiumWin::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 RenderThemeChromiumWin::paintMenuListButton(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& r)
+{
+ return paintMenuList(o, i, r);
+}
+
+int RenderThemeChromiumWin::popupInternalPaddingLeft(RenderStyle* style) const
+{
+ return menuListInternalPadding(style, LeftPadding);
+}
+
+int RenderThemeChromiumWin::popupInternalPaddingRight(RenderStyle* style) const
+{
+ return menuListInternalPadding(style, RightPadding);
+}
+
+int RenderThemeChromiumWin::popupInternalPaddingTop(RenderStyle* style) const
+{
+ return menuListInternalPadding(style, TopPadding);
+}
+
+int RenderThemeChromiumWin::popupInternalPaddingBottom(RenderStyle* style) const
+{
+ return menuListInternalPadding(style, BottomPadding);
+}
+
+void RenderThemeChromiumWin::adjustButtonInnerStyle(RenderStyle* style) 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));
+}
+
+// static
+void RenderThemeChromiumWin::setDefaultFontSize(int fontSize) {
+ defaultFontSize = static_cast<float>(fontSize);
+
+ // Reset cached fonts.
+ smallSystemFont = menuFont = labelFont = FontDescription();
+}
+
+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))
+ 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::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 PushButtonPart:
+ case ButtonPart:
+ result.m_part = BP_PUSHBUTTON;
+ result.m_classicState = DFCS_BUTTONPUSH;
+ break;
+ case CheckboxPart:
+ result.m_part = BP_CHECKBOX;
+ result.m_classicState = DFCS_BUTTONCHECK;
+ break;
+ case RadioPart:
+ result.m_part = BP_RADIOBUTTON;
+ result.m_classicState = DFCS_BUTTONRADIO;
+ break;
+ case ListboxPart:
+ case MenulistPart:
+ case TextFieldPart:
+ case TextAreaPart:
+ result.m_part = ETS_NORMAL;
+ break;
+ }
+
+ result.m_state = determineState(o);
+ 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);
+
+ WebCore::ThemeHelperWin helper(i.context, r);
+ ChromiumBridge::paintTextField(helper.context(),
+ themeData.m_part,
+ themeData.m_state,
+ themeData.m_classicState,
+ helper.rect(),
+ o->style()->backgroundColor(),
+ true,
+ drawEdges);
+ return false;
+}
+
+int RenderThemeChromiumWin::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 PopupMenuChromium.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;
+}
+
+// static
+void RenderThemeChromiumWin::setFindInPageMode(bool enable) {
+ if (m_findInPageMode == enable)
+ return;
+
+ m_findInPageMode = enable;
+ theme()->platformColorsDidChange();
+}
+
+} // namespace WebCore
diff --git a/WebCore/rendering/RenderThemeChromiumWin.h b/WebCore/rendering/RenderThemeChromiumWin.h
new file mode 100644
index 0000000..2d335c2
--- /dev/null
+++ b/WebCore/rendering/RenderThemeChromiumWin.h
@@ -0,0 +1,136 @@
+/*
+ * 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 "RenderTheme.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 RenderTheme {
+ public:
+ RenderThemeChromiumWin() { }
+ ~RenderThemeChromiumWin() { }
+
+ virtual String extraDefaultStyleSheet();
+ virtual String extraQuirksStyleSheet();
+
+ // A method asking if the theme's controls actually care about redrawing when hovered.
+ virtual bool supportsHover(const RenderStyle*) const { return true; }
+
+ // 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 platformTextSearchHighlightColor() const;
+
+ virtual double caretBlinkInterval() const;
+
+ // System fonts.
+ virtual void systemFont(int propId, Document*, FontDescription&) const;
+
+ virtual int minimumMenuListSize(RenderStyle*) const;
+
+ virtual bool paintCheckbox(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& r) { return paintButton(o, i, r); }
+ virtual void setCheckboxSize(RenderStyle*) const;
+
+ virtual bool paintRadio(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& r) { return paintButton(o, i, r); }
+ 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* o, const RenderObject::PaintInfo& i, const IntRect& r) { return paintTextField(o, i, r); }
+
+ virtual bool paintSearchField(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 void adjustButtonInnerStyle(RenderStyle*) 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);
+
+ // Enables/Disables FindInPage mode, which (if enabled) overrides the
+ // selection rect color to be orange.
+ static void setFindInPageMode(bool);
+
+ private:
+ unsigned determineState(RenderObject*);
+ unsigned determineClassicState(RenderObject*);
+
+ ThemeData getThemeData(RenderObject*);
+
+ bool paintTextFieldInternal(RenderObject*, const RenderObject::PaintInfo&, const IntRect&, bool);
+
+ int menuListInternalPadding(RenderStyle*, int paddingType) const;
+
+ // A flag specifying whether we are in Find-in-page mode or not.
+ static bool m_findInPageMode;
+ };
+
+} // namespace WebCore
+
+#endif
diff --git a/WebCore/rendering/RenderThemeMac.h b/WebCore/rendering/RenderThemeMac.h
index 1a49898..0d31603 100644
--- a/WebCore/rendering/RenderThemeMac.h
+++ b/WebCore/rendering/RenderThemeMac.h
@@ -55,8 +55,11 @@ 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 void platformColorsDidChange();
// System fonts.
@@ -76,6 +79,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 +114,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,10 +122,20 @@ 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:
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;
+
// Get the control size based off the font. Used by some of the controls (like buttons).
NSControlSize controlSizeForFont(RenderStyle*) const;
NSControlSize controlSizeForSystemFont(RenderStyle*) const;
diff --git a/WebCore/rendering/RenderThemeMac.mm b/WebCore/rendering/RenderThemeMac.mm
index 699b74a..b2d320a 100644
--- a/WebCore/rendering/RenderThemeMac.mm
+++ b/WebCore/rendering/RenderThemeMac.mm
@@ -25,7 +25,6 @@
#import "CSSValueKeywords.h"
#import "Document.h"
#import "Element.h"
-#import "FoundationExtras.h"
#import "FrameView.h"
#import "GraphicsContext.h"
#import "HTMLInputElement.h"
@@ -33,13 +32,16 @@
#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 "UserAgentStyleSheets.h"
#import <Carbon/Carbon.h>
#import <Cocoa/Cocoa.h>
#import <wtf/RetainPtr.h>
+#import <wtf/StdLibExtras.h>
#import <math.h>
#ifdef BUILDING_ON_TIGER
@@ -73,9 +75,9 @@ using std::min;
return self;
}
-- (void)systemColorsDidChange:(NSNotification *)notification
+- (void)systemColorsDidChange:(NSNotification *)unusedNotification
{
- ASSERT([[notification name] isEqualToString:NSSystemColorsDidChangeNotification]);
+ ASSERT_UNUSED(unusedNotification, [[unusedNotification name] isEqualToString:NSSystemColorsDidChangeNotification]);
_theme->platformColorsDidChange();
}
@@ -133,12 +135,27 @@ Color RenderThemeMac::platformInactiveSelectionBackgroundColor() const
return Color(static_cast<int>(255.0 * [color redComponent]), static_cast<int>(255.0 * [color greenComponent]), static_cast<int>(255.0 * [color blueComponent]));
}
-Color RenderThemeMac::activeListBoxSelectionBackgroundColor() const
+Color RenderThemeMac::platformActiveListBoxSelectionBackgroundColor() 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 RenderThemeMac::platformActiveListBoxSelectionForegroundColor() const
+{
+ return Color::white;
+}
+
+Color RenderThemeMac::platformInactiveListBoxSelectionForegroundColor() const
+{
+ return Color::black;
+}
+
+Color RenderThemeMac::platformInactiveListBoxSelectionBackgroundColor() const
+{
+ return platformInactiveSelectionBackgroundColor();
+}
+
static FontWeight toFontWeight(NSInteger appKitFontWeight)
{
ASSERT(appKitFontWeight > 0 && appKitFontWeight < 15);
@@ -168,13 +185,13 @@ static FontWeight toFontWeight(NSInteger appKitFontWeight)
void RenderThemeMac::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;
+ DEFINE_STATIC_LOCAL(FontDescription, systemFont, ());
+ DEFINE_STATIC_LOCAL(FontDescription, smallSystemFont, ());
+ DEFINE_STATIC_LOCAL(FontDescription, menuFont, ());
+ DEFINE_STATIC_LOCAL(FontDescription, labelFont, ());
+ DEFINE_STATIC_LOCAL(FontDescription, miniControlFont, ());
+ DEFINE_STATIC_LOCAL(FontDescription, smallControlFont, ());
+ DEFINE_STATIC_LOCAL(FontDescription, controlFont, ());
FontDescription* cachedDesc;
NSFont* font = nil;
@@ -229,7 +246,7 @@ void RenderThemeMac::systemFont(int cssValueId, FontDescription& fontDescription
static RGBA32 convertNSColorToColor(NSColor *color)
{
- NSColor *colorInColorSpace = [color colorUsingColorSpaceName:NSCalibratedRGBColorSpace];
+ NSColor *colorInColorSpace = [color colorUsingColorSpaceName:NSDeviceRGBColorSpace];
if (colorInColorSpace) {
static const double scaleFactor = nextafter(256.0, 0.0);
return makeRGB(static_cast<int>(scaleFactor * [colorInColorSpace redComponent]),
@@ -249,7 +266,7 @@ static RGBA32 convertNSColorToColor(NSColor *color)
samplesPerPixel:4
hasAlpha:YES
isPlanar:NO
- colorSpaceName:NSCalibratedRGBColorSpace
+ colorSpaceName:NSDeviceRGBColorSpace
bytesPerRow:4
bitsPerPixel:32];
@@ -276,7 +293,7 @@ static RGBA32 menuBackgroundColor()
samplesPerPixel:4
hasAlpha:YES
isPlanar:NO
- colorSpaceName:NSCalibratedRGBColorSpace
+ colorSpaceName:NSDeviceRGBColorSpace
bytesPerRow:4
bitsPerPixel:32];
@@ -416,6 +433,14 @@ bool RenderThemeMac::isControlStyled(const RenderStyle* style, const BorderData&
{
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);
}
@@ -466,6 +491,28 @@ IntRect RenderThemeMac::inflateRect(const IntRect& r, const IntSize& size, const
return result;
}
+FloatRect RenderThemeMac::convertToPaintingRect(const RenderObject* inputRenderer, const RenderObject* partRenderer, const FloatRect& inputRect, const IntRect& r) const
+{
+ FloatRect partRect(inputRect);
+
+ // Compute an offset between the part renderer and the input renderer
+ FloatSize offsetFromInputRenderer;
+ const RenderObject* renderer = partRenderer;
+ while (renderer && renderer != inputRenderer) {
+ RenderObject* containingRenderer = renderer->container();
+ offsetFromInputRenderer -= renderer->offsetFromContainer(containingRenderer);
+ renderer = containingRenderer;
+ }
+ // If the input renderer was not a container, something went wrong
+ ASSERT(renderer == inputRenderer);
+ // Move the rect into partRenderer's coords
+ partRect.move(offsetFromInputRenderer);
+ // Account for the local drawing offset (tx, ty)
+ partRect.move(r.x(), r.y());
+
+ return partRect;
+}
+
void RenderThemeMac::updateCheckedState(NSCell* cell, const RenderObject* o)
{
bool oldIndeterminate = [cell state] == NSMixedState;
@@ -577,7 +624,7 @@ void RenderThemeMac::setSizeFromFont(RenderStyle* style, const IntSize* sizes) c
style->setHeight(Length(size.height(), Fixed));
}
-void RenderThemeMac::setFontFromControlSize(CSSStyleSelector* selector, RenderStyle* style, NSControlSize controlSize) const
+void RenderThemeMac::setFontFromControlSize(CSSStyleSelector*, RenderStyle* style, NSControlSize controlSize) const
{
FontDescription fontDescription;
fontDescription.setIsAbsoluteSize(true);
@@ -616,7 +663,7 @@ void RenderThemeMac::adjustTextFieldStyle(CSSStyleSelector*, RenderStyle*, Eleme
{
}
-bool RenderThemeMac::paintCapsLockIndicator(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
+bool RenderThemeMac::paintCapsLockIndicator(RenderObject*, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
{
if (paintInfo.context->paintingDisabled())
return true;
@@ -717,7 +764,7 @@ const int styledPopupPaddingLeft = 8;
const int styledPopupPaddingTop = 1;
const int styledPopupPaddingBottom = 2;
-static void TopGradientInterpolate(void* info, const CGFloat* inData, CGFloat* outData)
+static void TopGradientInterpolate(void*, 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 };
@@ -727,7 +774,7 @@ static void TopGradientInterpolate(void* info, const CGFloat* inData, CGFloat* o
outData[i] = (1.0f - a) * dark[i] + a * light[i];
}
-static void BottomGradientInterpolate(void* info, const CGFloat* inData, CGFloat* outData)
+static void BottomGradientInterpolate(void*, 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 };
@@ -737,7 +784,7 @@ static void BottomGradientInterpolate(void* info, const CGFloat* inData, CGFloat
outData[i] = (1.0f - a) * dark[i] + a * light[i];
}
-static void MainGradientInterpolate(void* info, const CGFloat* inData, CGFloat* outData)
+static void MainGradientInterpolate(void*, 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 };
@@ -747,7 +794,7 @@ static void MainGradientInterpolate(void* info, const CGFloat* inData, CGFloat*
outData[i] = (1.0f - a) * dark[i] + a * light[i];
}
-static void TrackGradientInterpolate(void* info, const CGFloat* inData, CGFloat* outData)
+static void TrackGradientInterpolate(void*, 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 };
@@ -956,7 +1003,7 @@ int RenderThemeMac::popupInternalPaddingBottom(RenderStyle* style) const
return 0;
}
-void RenderThemeMac::adjustMenuListButtonStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
+void RenderThemeMac::adjustMenuListButtonStyle(CSSStyleSelector*, RenderStyle* style, Element*) const
{
float fontScale = style->fontSize() / baseFontSize;
@@ -997,7 +1044,7 @@ int RenderThemeMac::minimumMenuListSize(RenderStyle* style) const
const int trackWidth = 5;
const int trackRadius = 2;
-void RenderThemeMac::adjustSliderTrackStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
+void RenderThemeMac::adjustSliderTrackStyle(CSSStyleSelector*, RenderStyle* style, Element*) const
{
style->setBoxShadow(0);
}
@@ -1041,7 +1088,7 @@ bool RenderThemeMac::paintSliderTrack(RenderObject* o, const RenderObject::Paint
return false;
}
-void RenderThemeMac::adjustSliderThumbStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
+void RenderThemeMac::adjustSliderThumbStyle(CSSStyleSelector*, RenderStyle* style, Element*) const
{
style->setBoxShadow(0);
}
@@ -1108,23 +1155,6 @@ bool RenderThemeMac::paintSliderThumb(RenderObject* o, const RenderObject::Paint
return false;
}
-const int sliderThumbWidth = 15;
-const int sliderThumbHeight = 15;
-const int mediaSliderThumbWidth = 13;
-const int mediaSliderThumbHeight = 14;
-
-void RenderThemeMac::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 RenderThemeMac::paintSearchField(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
{
NSSearchFieldCell* search = this->search();
@@ -1163,7 +1193,7 @@ bool RenderThemeMac::paintSearchField(RenderObject* o, const RenderObject::Paint
return false;
}
-void RenderThemeMac::setSearchCellState(RenderObject* o, const IntRect& r)
+void RenderThemeMac::setSearchCellState(RenderObject* o, const IntRect&)
{
NSSearchFieldCell* search = this->search();
@@ -1190,7 +1220,7 @@ void RenderThemeMac::setSearchFieldSize(RenderStyle* style) const
setSizeFromFont(style, searchFieldSizes());
}
-void RenderThemeMac::adjustSearchFieldStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
+void RenderThemeMac::adjustSearchFieldStyle(CSSStyleSelector* selector, RenderStyle* style, Element*) const
{
// Override border.
style->resetBorder();
@@ -1224,6 +1254,9 @@ void RenderThemeMac::adjustSearchFieldStyle(CSSStyleSelector* selector, RenderSt
bool RenderThemeMac::paintSearchFieldCancelButton(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
{
Node* input = o->node()->shadowAncestorNode();
+ if (!input->renderer()->isBox())
+ return false;
+
setSearchCellState(input->renderer(), r);
NSSearchFieldCell* search = this->search();
@@ -1234,9 +1267,10 @@ bool RenderThemeMac::paintSearchFieldCancelButton(RenderObject* o, const RenderO
float zoomLevel = o->style()->effectiveZoom();
- NSRect bounds = [search cancelButtonRectForBounds:NSRect(input->renderer()->absoluteBoundingBoxRect())];
-
- IntRect unzoomedRect(bounds);
+ FloatRect localBounds = [search cancelButtonRectForBounds:NSRect(input->renderBox()->borderBoxRect())];
+ localBounds = convertToPaintingRect(input->renderer(), o, localBounds, r);
+
+ FloatRect unzoomedRect(localBounds);
if (zoomLevel != 1.0f) {
unzoomedRect.setWidth(unzoomedRect.width() / zoomLevel);
unzoomedRect.setHeight(unzoomedRect.height() / zoomLevel);
@@ -1258,7 +1292,7 @@ const IntSize* RenderThemeMac::cancelButtonSizes() const
return sizes;
}
-void RenderThemeMac::adjustSearchFieldCancelButtonStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
+void RenderThemeMac::adjustSearchFieldCancelButtonStyle(CSSStyleSelector*, RenderStyle* style, Element*) const
{
IntSize size = sizeForSystemFont(style, cancelButtonSizes());
style->setWidth(Length(size.width(), Fixed));
@@ -1273,7 +1307,7 @@ const IntSize* RenderThemeMac::resultsButtonSizes() const
}
const int emptyResultsOffset = 9;
-void RenderThemeMac::adjustSearchFieldDecorationStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
+void RenderThemeMac::adjustSearchFieldDecorationStyle(CSSStyleSelector*, RenderStyle* style, Element*) const
{
IntSize size = sizeForSystemFont(style, resultsButtonSizes());
style->setWidth(Length(size.width() - emptyResultsOffset, Fixed));
@@ -1281,12 +1315,12 @@ void RenderThemeMac::adjustSearchFieldDecorationStyle(CSSStyleSelector* selector
style->setBoxShadow(0);
}
-bool RenderThemeMac::paintSearchFieldDecoration(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
+bool RenderThemeMac::paintSearchFieldDecoration(RenderObject*, const RenderObject::PaintInfo&, const IntRect&)
{
return false;
}
-void RenderThemeMac::adjustSearchFieldResultsDecorationStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
+void RenderThemeMac::adjustSearchFieldResultsDecorationStyle(CSSStyleSelector*, RenderStyle* style, Element*) const
{
IntSize size = sizeForSystemFont(style, resultsButtonSizes());
style->setWidth(Length(size.width(), Fixed));
@@ -1294,9 +1328,12 @@ void RenderThemeMac::adjustSearchFieldResultsDecorationStyle(CSSStyleSelector* s
style->setBoxShadow(0);
}
-bool RenderThemeMac::paintSearchFieldResultsDecoration(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
+bool RenderThemeMac::paintSearchFieldResultsDecoration(RenderObject* o, const RenderObject::PaintInfo&, const IntRect& r)
{
Node* input = o->node()->shadowAncestorNode();
+ if (!input->renderer()->isBox())
+ return false;
+
setSearchCellState(input->renderer(), r);
NSSearchFieldCell* search = this->search();
@@ -1304,14 +1341,16 @@ bool RenderThemeMac::paintSearchFieldResultsDecoration(RenderObject* o, const Re
if ([search searchMenuTemplate] != nil)
[search setSearchMenuTemplate:nil];
- NSRect bounds = [search searchButtonRectForBounds:NSRect(input->renderer()->absoluteBoundingBoxRect())];
- [[search searchButtonCell] drawWithFrame:bounds inView:o->view()->frameView()->documentView()];
+ FloatRect localBounds = [search searchButtonRectForBounds:NSRect(input->renderBox()->borderBoxRect())];
+ localBounds = convertToPaintingRect(input->renderer(), o, localBounds, r);
+
+ [[search searchButtonCell] drawWithFrame:localBounds inView:o->view()->frameView()->documentView()];
[[search searchButtonCell] setControlView:nil];
return false;
}
const int resultsArrowWidth = 5;
-void RenderThemeMac::adjustSearchFieldResultsButtonStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
+void RenderThemeMac::adjustSearchFieldResultsButtonStyle(CSSStyleSelector*, RenderStyle* style, Element*) const
{
IntSize size = sizeForSystemFont(style, resultsButtonSizes());
style->setWidth(Length(size.width() + resultsArrowWidth, Fixed));
@@ -1322,6 +1361,9 @@ void RenderThemeMac::adjustSearchFieldResultsButtonStyle(CSSStyleSelector* selec
bool RenderThemeMac::paintSearchFieldResultsButton(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
{
Node* input = o->node()->shadowAncestorNode();
+ if (!input->renderer()->isBox())
+ return false;
+
setSearchCellState(input->renderer(), r);
NSSearchFieldCell* search = this->search();
@@ -1333,9 +1375,10 @@ bool RenderThemeMac::paintSearchFieldResultsButton(RenderObject* o, const Render
float zoomLevel = o->style()->effectiveZoom();
- NSRect bounds = [search searchButtonRectForBounds:NSRect(input->renderer()->absoluteBoundingBoxRect())];
+ FloatRect localBounds = [search searchButtonRectForBounds:NSRect(input->renderBox()->borderBoxRect())];
+ localBounds = convertToPaintingRect(input->renderer(), o, localBounds, r);
- IntRect unzoomedRect(bounds);
+ IntRect unzoomedRect(localBounds);
if (zoomLevel != 1.0f) {
unzoomedRect.setWidth(unzoomedRect.width() / zoomLevel);
unzoomedRect.setHeight(unzoomedRect.height() / zoomLevel);
@@ -1352,6 +1395,71 @@ bool RenderThemeMac::paintSearchFieldResultsButton(RenderObject* o, const Render
return false;
}
+#if ENABLE(VIDEO)
+typedef enum {
+ MediaControllerThemeClassic = 1,
+ MediaControllerThemeQT = 2
+} MediaControllerThemeStyle;
+
+static int mediaControllerTheme()
+{
+ static const long minimumQuickTimeVersion = 0x07600000; // 7.6
+ static SInt32 quickTimeVersion = 0;
+
+ if (!quickTimeVersion) {
+ OSErr err;
+ err = Gestalt(gestaltQuickTime, &quickTimeVersion);
+ if (err != noErr)
+ return MediaControllerThemeClassic;
+ }
+ if (quickTimeVersion < minimumQuickTimeVersion)
+ return MediaControllerThemeClassic;
+
+ // keep the feature off for now without an explicit opt-in
+ Boolean validKey;
+ Boolean useQTMediaUI = CFPreferencesGetAppBooleanValue(CFSTR("UseQuickTimeMediaUI"), CFSTR("com.apple.WebCore"), &validKey);
+ if (!validKey || !useQTMediaUI)
+ return MediaControllerThemeClassic;
+
+ return MediaControllerThemeQT;
+}
+#endif
+
+const int sliderThumbWidth = 15;
+const int sliderThumbHeight = 15;
+const int mediaSliderThumbWidth = 13;
+const int mediaSliderThumbHeight = 14;
+
+void RenderThemeMac::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));
+ }
+
+#if ENABLE(VIDEO)
+ else if (o->style()->appearance() == MediaSliderThumbPart) {
+ int width = mediaSliderThumbWidth;
+ int height = mediaSliderThumbHeight;
+
+ if (mediaControllerTheme() == MediaControllerThemeQT) {
+ CGSize size;
+
+ wkMeasureMediaUIPart(MediaSliderThumb, MediaControllerThemeQT, NULL, &size);
+ width = size.width;
+ height = size.height;
+ }
+
+ o->style()->setWidth(Length(width, Fixed));
+ o->style()->setHeight(Length(height, Fixed));
+ }
+#endif
+}
+
+
+#if ENABLE(VIDEO)
+
bool RenderThemeMac::paintMediaFullscreenButton(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
{
Node* node = o->element();
@@ -1359,7 +1467,7 @@ bool RenderThemeMac::paintMediaFullscreenButton(RenderObject* o, const RenderObj
return false;
LocalCurrentGraphicsContext localContext(paintInfo.context);
- wkDrawMediaFullscreenButton(paintInfo.context->platformContext(), r, node->active());
+ wkDrawMediaUIPart(MediaFullscreenButton, mediaControllerTheme(), paintInfo.context->platformContext(), r, node->active());
return false;
}
@@ -1375,10 +1483,7 @@ bool RenderThemeMac::paintMediaMuteButton(RenderObject* o, const RenderObject::P
return false;
LocalCurrentGraphicsContext localContext(paintInfo.context);
- if (mediaElement->muted())
- wkDrawMediaUnMuteButton(paintInfo.context->platformContext(), r, node->active());
- else
- wkDrawMediaMuteButton(paintInfo.context->platformContext(), r, node->active());
+ wkDrawMediaUIPart(mediaElement->muted() ? MediaUnMuteButton : MediaMuteButton, mediaControllerTheme(), paintInfo.context->platformContext(), r, node->active());
return false;
}
@@ -1394,10 +1499,7 @@ bool RenderThemeMac::paintMediaPlayButton(RenderObject* o, const RenderObject::P
return false;
LocalCurrentGraphicsContext localContext(paintInfo.context);
- if (mediaElement->canPlay())
- wkDrawMediaPlayButton(paintInfo.context->platformContext(), r, node->active());
- else
- wkDrawMediaPauseButton(paintInfo.context->platformContext(), r, node->active());
+ wkDrawMediaUIPart(mediaElement->canPlay() ? MediaPlayButton : MediaPauseButton, mediaControllerTheme(), paintInfo.context->platformContext(), r, node->active());
return false;
}
@@ -1408,7 +1510,7 @@ bool RenderThemeMac::paintMediaSeekBackButton(RenderObject* o, const RenderObjec
return false;
LocalCurrentGraphicsContext localContext(paintInfo.context);
- wkDrawMediaSeekBackButton(paintInfo.context->platformContext(), r, node->active());
+ wkDrawMediaUIPart(MediaSeekBackButton, mediaControllerTheme(), paintInfo.context->platformContext(), r, node->active());
return false;
}
@@ -1419,7 +1521,7 @@ bool RenderThemeMac::paintMediaSeekForwardButton(RenderObject* o, const RenderOb
return false;
LocalCurrentGraphicsContext localContext(paintInfo.context);
- wkDrawMediaSeekForwardButton(paintInfo.context->platformContext(), r, node->active());
+ wkDrawMediaUIPart(MediaSeekForwardButton, mediaControllerTheme(), paintInfo.context->platformContext(), r, node->active());
return false;
}
@@ -1434,12 +1536,16 @@ bool RenderThemeMac::paintMediaSliderTrack(RenderObject* o, const RenderObject::
if (!mediaElement)
return false;
- float percentLoaded = 0;
- if (MediaPlayer* player = mediaElement->player())
- if (player->duration())
- percentLoaded = player->maxTimeBuffered() / player->duration();
-
- wkDrawMediaSliderTrack(paintInfo.context->platformContext(), r, percentLoaded);
+ float timeLoaded = 0;
+ float currentTime = 0;
+ float duration = 0;
+ if (MediaPlayer* player = mediaElement->player()) {
+ duration = player->duration();
+ timeLoaded = player->maxTimeBuffered();
+ currentTime = player->currentTime();
+ }
+
+ wkDrawMediaSliderTrack(mediaControllerTheme(), paintInfo.context->platformContext(), r, timeLoaded, currentTime, duration);
return false;
}
@@ -1450,10 +1556,66 @@ bool RenderThemeMac::paintMediaSliderThumb(RenderObject* o, const RenderObject::
return false;
LocalCurrentGraphicsContext localContext(paintInfo.context);
- wkDrawMediaSliderThumb(paintInfo.context->platformContext(), r, node->active());
+ wkDrawMediaUIPart(MediaSliderThumb, mediaControllerTheme(), paintInfo.context->platformContext(), r, node->active());
+ return false;
+}
+
+bool RenderThemeMac::paintMediaTimelineContainer(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
+{
+ Node* node = o->element();
+ if (!node)
+ return false;
+
+ LocalCurrentGraphicsContext localContext(paintInfo.context);
+ wkDrawMediaUIPart(MediaTimelineContainer, mediaControllerTheme(), paintInfo.context->platformContext(), r, node->active());
+ return false;
+}
+
+bool RenderThemeMac::paintMediaCurrentTime(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
+{
+ Node* node = o->element();
+ if (!node)
+ return false;
+
+ LocalCurrentGraphicsContext localContext(paintInfo.context);
+ wkDrawMediaUIPart(MediaCurrentTimeDisplay, mediaControllerTheme(), paintInfo.context->platformContext(), r, node->active());
return false;
}
+bool RenderThemeMac::paintMediaTimeRemaining(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
+{
+ Node* node = o->element();
+ if (!node)
+ return false;
+
+ LocalCurrentGraphicsContext localContext(paintInfo.context);
+ wkDrawMediaUIPart(MediaTimeRemainingDisplay, mediaControllerTheme(), paintInfo.context->platformContext(), r, node->active());
+ return false;
+}
+
+String RenderThemeMac::extraMediaControlsStyleSheet()
+{
+ if (mediaControllerTheme() == MediaControllerThemeQT)
+ return String(mediaControlsQTUserAgentStyleSheet, sizeof(mediaControlsQTUserAgentStyleSheet));
+ else
+ return String();
+}
+
+bool RenderThemeMac::hitTestMediaControlPart(RenderObject* o, const IntPoint& absPoint)
+{
+ if (!o->isBox())
+ return false;
+
+ if (mediaControllerTheme() == MediaControllerThemeQT) {
+ ControlPart part = o->style()->appearance();
+ FloatPoint localPoint = o->absoluteToLocal(absPoint, false, true); // respect transforms
+ return wkHitTestMediaUIPart(part - MediaFullscreenButtonPart, MediaControllerThemeQT, CGRect(toRenderBox(o)->borderBoxRect()), CGPoint(localPoint));
+ }
+ else
+ return RenderTheme::hitTestMediaControlPart(o, absPoint);
+}
+#endif
+
NSPopUpButtonCell* RenderThemeMac::popupButton() const
{
if (!m_popupButton) {
diff --git a/WebCore/rendering/RenderThemeSafari.cpp b/WebCore/rendering/RenderThemeSafari.cpp
index 31315bc..ef39a3e 100644
--- a/WebCore/rendering/RenderThemeSafari.cpp
+++ b/WebCore/rendering/RenderThemeSafari.cpp
@@ -272,8 +272,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);
}
diff --git a/WebCore/rendering/RenderThemeWin.cpp b/WebCore/rendering/RenderThemeWin.cpp
index 14dcbf1..e4717a1 100644
--- a/WebCore/rendering/RenderThemeWin.cpp
+++ b/WebCore/rendering/RenderThemeWin.cpp
@@ -21,6 +21,7 @@
#include "config.h"
#include "RenderThemeWin.h"
+#include "CSSStyleSheet.h"
#include "CSSValueKeywords.h"
#include "Document.h"
#include "GraphicsContext.h"
@@ -29,6 +30,7 @@
#include "Icon.h"
#include "RenderSlider.h"
#include "SoftLinking.h"
+#include "UserAgentStyleSheets.h"
#include <tchar.h>
@@ -81,11 +83,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;
-
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))
@@ -95,8 +92,26 @@ SOFT_LINK(uxtheme, IsThemeBackgroundPartiallyTransparent, BOOL, WINAPI, (HANDLE
static bool haveTheme;
+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;
void RenderThemeWin::setWebKitIsBeingUnloaded()
@@ -178,6 +193,16 @@ void RenderThemeWin::themeChanged()
close();
}
+String RenderThemeWin::extraDefaultStyleSheet()
+{
+ return String(themeWinUserAgentStyleSheet, sizeof(themeWinUserAgentStyleSheet));
+}
+
+String RenderThemeWin::extraQuirksStyleSheet()
+{
+ return String(themeWinQuirksUserAgentStyleSheet, sizeof(themeWinQuirksUserAgentStyleSheet));
+}
+
bool RenderThemeWin::supportsHover(const RenderStyle*) const
{
// The Classic/2k look has no hover effects.
@@ -187,39 +212,45 @@ 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)
+static void fillFontDescription(FontDescription& fontDescription, LOGFONT& logFont, float fontSize)
{
fontDescription.setIsAbsoluteSize(true);
fontDescription.setGenericFamily(FontDescription::NoFamily);
fontDescription.firstFamily().setFamily(String(logFont.lfFaceName));
- fontDescription.setSpecifiedSize(abs(logFont.lfHeight));
+ fontDescription.setSpecifiedSize(fontSize);
fontDescription.setWeight(logFont.lfWeight >= 700 ? FontWeightBold : FontWeightNormal); // FIXME: Use real weight.
fontDescription.setItalic(logFont.lfItalic);
}
+static void fillFontDescription(FontDescription& fontDescription, LOGFONT& logFont)
+{
+ fillFontDescription(fontDescription, logFont, abs(logFont.lfHeight));
+}
+
void RenderThemeWin::systemFont(int propId, FontDescription& fontDescription) const
{
static FontDescription captionFont;
+ static FontDescription controlFont;
static FontDescription smallCaptionFont;
static FontDescription menuFont;
static FontDescription iconFont;
@@ -267,13 +298,23 @@ void RenderThemeWin::systemFont(int propId, FontDescription& fontDescription) co
fontDescription = captionFont;
break;
case CSSValueSmallCaption:
- case CSSValueWebkitSmallControl: // Equivalent to small-caption.
- case CSSValueWebkitMiniControl: // Just map to small.
- case CSSValueWebkitControl: // Just map to small.
if (!smallCaptionFont.isAbsoluteSize())
fillFontDescription(smallCaptionFont, ncm.lfSmCaptionFont);
fontDescription = smallCaptionFont;
break;
+ case CSSValueWebkitSmallControl:
+ case CSSValueWebkitMiniControl: // Just map to small.
+ case CSSValueWebkitControl: // Just map to small.
+ if (!controlFont.isAbsoluteSize()) {
+ HGDIOBJ hGDI = ::GetStockObject(DEFAULT_GUI_FONT);
+ if (hGDI) {
+ LOGFONT logFont;
+ if (::GetObject(hGDI, sizeof(logFont), &logFont) > 0)
+ fillFontDescription(controlFont, logFont, defaultControlFontPixelSize);
+ }
+ }
+ fontDescription = controlFont;
+ break;
default: { // Everything else uses the stock GUI font.
if (!systemFont.isAbsoluteSize()) {
HGDIOBJ hGDI = ::GetStockObject(DEFAULT_GUI_FONT);
@@ -288,22 +329,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;
@@ -345,7 +387,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;
@@ -404,6 +446,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;
@@ -457,6 +500,7 @@ ThemeData RenderThemeWin::getThemeData(RenderObject* o)
result.m_part = BP_RADIO;
result.m_state = determineState(o);
break;
+ case SearchFieldPart:
case TextFieldPart:
case TextAreaPart:
result.m_part = TFP_TEXTFIELD;
@@ -666,7 +710,16 @@ void RenderThemeWin::adjustSliderThumbSize(RenderObject* o) const
o->style()->setWidth(Length(sliderThumbWidth, Fixed));
o->style()->setHeight(Length(sliderThumbHeight, Fixed));
}
- }
+}
+
+void RenderThemeWin::adjustButtonInnerStyle(RenderStyle* style) 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));
+}
bool RenderThemeWin::paintSearchField(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& r)
{
@@ -685,33 +738,36 @@ void RenderThemeWin::adjustSearchFieldStyle(CSSStyleSelector* selector, RenderSt
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
@@ -720,46 +776,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;
}
@@ -802,7 +885,9 @@ static int cssValueIdToSysColorIndex(int cssValueId)
Color RenderThemeWin::systemColor(int cssValueId) const
{
int sysColorIndex = cssValueIdToSysColorIndex(cssValueId);
- ASSERT(sysColorIndex != -1);
+ if (sysColorIndex == -1)
+ return RenderTheme::systemColor(cssValueId);
+
COLORREF color = GetSysColor(sysColorIndex);
return Color(GetRValue(color), GetGValue(color), GetBValue(color));
}
diff --git a/WebCore/rendering/RenderThemeWin.h b/WebCore/rendering/RenderThemeWin.h
index 513f6b5..5d5bd4b 100644
--- a/WebCore/rendering/RenderThemeWin.h
+++ b/WebCore/rendering/RenderThemeWin.h
@@ -50,7 +50,10 @@ class RenderThemeWin : public RenderTheme {
public:
RenderThemeWin();
~RenderThemeWin();
-
+
+ virtual String extraDefaultStyleSheet();
+ virtual String extraQuirksStyleSheet();
+
// A method asking if the theme's controls actually care about redrawing when hovered.
virtual bool supportsHover(const RenderStyle*) const;
@@ -89,6 +92,8 @@ public:
virtual bool paintSliderThumb(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& r);
virtual void adjustSliderThumbSize(RenderObject*) const;
+ virtual void adjustButtonInnerStyle(RenderStyle*) const;
+
virtual void adjustSearchFieldStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
virtual bool paintSearchField(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
@@ -112,6 +117,8 @@ public:
static void setWebKitIsBeingUnloaded();
+ virtual bool supportsFocusRing(const RenderStyle*) const;
+
private:
void addIntrinsicMargins(RenderStyle*) const;
void close();
@@ -121,7 +128,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/WebCore/rendering/RenderTreeAsText.cpp b/WebCore/rendering/RenderTreeAsText.cpp
index 346968b..cf7e027 100644
--- a/WebCore/rendering/RenderTreeAsText.cpp
+++ b/WebCore/rendering/RenderTreeAsText.cpp
@@ -34,6 +34,7 @@
#include "HTMLNames.h"
#include "InlineTextBox.h"
#include "RenderBR.h"
+#include "RenderInline.h"
#include "RenderListMarker.h"
#include "RenderTableCell.h"
#include "RenderView.h"
@@ -69,7 +70,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:
@@ -180,7 +181,37 @@ static TextStream &operator<<(TextStream& ts, const RenderObject& o)
}
}
- 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.isBox()) {
+ if (o.isRenderInline()) {
+ // FIXME: Would be better not to just dump 0, 0 as the x and y here.
+ const RenderInline& inlineFlow = static_cast<const RenderInline&>(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
+ 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 +237,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.isBox())
+ return ts;
+
+ const RenderBox& box = *toRenderBox(&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 +261,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 +274,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 +289,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 +339,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";
}
@@ -344,7 +383,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,7 +400,7 @@ 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();
@@ -416,7 +455,7 @@ static void writeLayers(TextStream& ts, const RenderLayer* rootLayer, RenderLaye
{
// Calculate the clip rects we should use.
IntRect layerBounds, damageRect, clipRectToApply, outlineRect;
- l->calculateRects(rootLayer, paintDirtyRect, layerBounds, damageRect, clipRectToApply, outlineRect);
+ l->calculateRects(rootLayer, paintDirtyRect, layerBounds, damageRect, clipRectToApply, outlineRect, true);
// Ensure our lists are up-to-date.
l->updateZOrderLists();
@@ -501,8 +540,8 @@ String externalRepresentation(RenderObject* o)
#endif
if (o->view()->frameView())
o->view()->frameView()->layout();
- RenderLayer* l = o->layer();
- if (l) {
+ if (o->hasLayer()) {
+ RenderLayer* l = toRenderBox(o)->layer();
writeLayers(ts, l, l, IntRect(l->xPos(), l->yPos(), l->width(), l->height()));
writeSelection(ts, o);
}
diff --git a/WebCore/rendering/RenderVideo.cpp b/WebCore/rendering/RenderVideo.cpp
index d677725..be75997 100644
--- a/WebCore/rendering/RenderVideo.cpp
+++ b/WebCore/rendering/RenderVideo.cpp
@@ -68,7 +68,7 @@ void RenderVideo::videoSizeChanged()
IntRect RenderVideo::videoBox() const
{
- IntRect contentRect = contentBox();
+ IntRect contentRect = contentBoxRect();
if (intrinsicSize().isEmpty() || contentRect.isEmpty())
return IntRect();
@@ -124,11 +124,11 @@ void RenderVideo::updatePlayer()
mediaPlayer->setVisible(false);
return;
}
- int x;
- int y;
- absolutePosition(x, y);
+
+ // FIXME: This doesn't work correctly with transforms.
+ FloatPoint absPos = localToAbsolute();
IntRect videoBounds = videoBox();
- videoBounds.move(x, y);
+ videoBounds.move(absPos.x(), absPos.y());
mediaPlayer->setFrameView(document()->view());
mediaPlayer->setRect(videoBounds);
mediaPlayer->setVisible(true);
@@ -174,7 +174,7 @@ int RenderVideo::calcReplacedWidth(bool includeMaxWidth) const
if (isWidthSpecified())
width = calcReplacedWidthUsing(style()->width());
else
- width = calcAspectRatioWidth();
+ width = calcAspectRatioWidth() * style()->effectiveZoom();
int minW = calcReplacedWidthUsing(style()->minWidth());
int maxW = !includeMaxWidth || style()->maxWidth().isUndefined() ? width : calcReplacedWidthUsing(style()->maxWidth());
@@ -188,7 +188,7 @@ int RenderVideo::calcReplacedHeight() const
if (isHeightSpecified())
height = calcReplacedHeightUsing(style()->height());
else
- height = calcAspectRatioHeight();
+ height = calcAspectRatioHeight() * style()->effectiveZoom();
int minH = calcReplacedHeightUsing(style()->minHeight());
int maxH = style()->maxHeight().isUndefined() ? height : calcReplacedHeightUsing(style()->maxHeight());
diff --git a/WebCore/rendering/RenderView.cpp b/WebCore/rendering/RenderView.cpp
index a447bc8..7ce4998 100644
--- a/WebCore/rendering/RenderView.cpp
+++ b/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,6 +23,7 @@
#include "Document.h"
#include "Element.h"
+#include "FloatQuad.h"
#include "Frame.h"
#include "FrameView.h"
#include "GraphicsContext.h"
@@ -54,10 +53,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;
@@ -77,20 +73,20 @@ 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());
#ifdef ANDROID_LAYOUT
const Settings * settings = document()->settings();
ASSERT(settings);
if (settings->layoutAlgorithm() == Settings::kLayoutFitColumnToScreen)
m_visibleWidth = m_frameView->screenWidth();
- if (settings->useWideViewport() && settings->viewportWidth() == -1 && m_width < minPrefWidth())
- m_width = m_minPrefWidth;
+ if (settings->useWideViewport() && settings->viewportWidth() == -1 && width() < minPrefWidth())
+ setWidth(m_minPrefWidth);
#endif
m_marginLeft = 0;
m_marginRight = 0;
@@ -108,10 +104,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()) {
@@ -130,8 +126,8 @@ void RenderView::layout()
RenderBlock::layout();
// Ensure that docWidth() >= width() and docHeight() >= height().
- setOverflowWidth(m_width);
- setOverflowHeight(m_height);
+ setOverflowWidth(width());
+ setOverflowHeight(height());
setOverflowWidth(docWidth());
setOverflowHeight(docHeight());
@@ -143,20 +139,39 @@ void RenderView::layout()
setNeedsLayout(false);
}
-bool RenderView::absolutePosition(int& xPos, int& yPos, bool fixed) const
+FloatPoint RenderView::localToAbsolute(FloatPoint localPoint, bool fixed, bool) const
+{
+ // This disables the css position:fixed to the Browser window. Instead
+ // the fixed element will be always fixed to the top page.
+#ifndef ANDROID_DISABLE_POSITION_FIXED
+ if (fixed && m_frameView)
+ localPoint += m_frameView->scrollOffset();
+#endif
+ return localPoint;
+}
+
+FloatPoint RenderView::absoluteToLocal(FloatPoint containerPoint, bool fixed, bool) const
{
- if (fixed && m_frameView) {
-#ifdef ANDROID_DISABLE_POSITION_FIXED
- // This disables the css position:fixed to the Browser window. Instead
- // the fixed element will be always fixed to the top page.
- xPos = yPos = 0;
-#else
- xPos = m_frameView->scrollX();
- yPos = m_frameView->scrollY();
+ // This disables the css position:fixed to the Browser window. Instead
+ // the fixed element will be always fixed to the top page.
+#ifndef ANDROID_DISABLE_POSITION_FIXED
+ if (fixed && m_frameView)
+ containerPoint -= m_frameView->scrollOffset();
#endif
- } else
- xPos = yPos = 0;
- return true;
+ return containerPoint;
+}
+
+FloatQuad RenderView::localToContainerQuad(const FloatQuad& localQuad, RenderBox* repaintContainer, bool fixed) const
+{
+ // 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);
+
+ FloatQuad quad = localQuad;
+ if (fixed && m_frameView)
+ quad += m_frameView->scrollOffset();
+
+ return quad;
}
void RenderView::paint(PaintInfo& paintInfo, int tx, int ty)
@@ -172,7 +187,12 @@ void RenderView::paint(PaintInfo& paintInfo, int tx, int ty)
paintObject(paintInfo, tx, ty);
}
-void RenderView::paintBoxDecorations(PaintInfo& paintInfo, int tx, int ty)
+static inline bool rendererObscuresBackground(RenderObject* object)
+{
+ return object && object->style()->visibility() == VISIBLE && object->style()->opacity() == 1 && !object->style()->hasTransform();
+}
+
+void RenderView::paintBoxDecorations(PaintInfo& paintInfo, int, int)
{
// Check to see if we are enclosed by a layer that requires complex painting rules. If so, we cannot blit
// when scrolling, and we need to use slow repaints. Examples of layers that require this are transparent layers,
@@ -188,10 +208,12 @@ void RenderView::paintBoxDecorations(PaintInfo& paintInfo, int tx, int ty)
}
}
- if (elt || (firstChild() && firstChild()->style()->visibility() == VISIBLE) || !view())
+ // If painting will entirely fill the view, no need to fill the background.
+ if (elt || rendererObscuresBackground(firstChild()) || !view())
return;
- // This code typically only executes if the root element's visibility has been set to hidden.
+ // This code typically only executes if the root element's visibility has been set to hidden,
+ // or there is a transform on the <html>.
// Only fill with the base background color (typically white) if we're the root document,
// since iframes/frames with no background in the child document should show the parent's background.
if (view()->isTransparent()) // FIXME: This needs to be dynamic. We should be able to go back to blitting if we ever stop being transparent.
@@ -221,7 +243,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);
@@ -236,8 +258,12 @@ void RenderView::repaintViewRectangle(const IntRect& ur, bool immediate)
}
}
-void RenderView::computeAbsoluteRepaintRect(IntRect& rect, bool fixed)
+void RenderView::computeRectForRepaint(IntRect& rect, RenderBox* repaintContainer, 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;
@@ -254,7 +280,12 @@ void RenderView::absoluteRects(Vector<IntRect>& rects, int tx, int ty, bool)
rects.append(IntRect(tx, ty, m_layer->width(), m_layer->height()));
}
-RenderObject* rendererAfterPosition(RenderObject* object, unsigned offset)
+void RenderView::absoluteQuads(Vector<FloatQuad>& quads, bool)
+{
+ quads.append(FloatRect(0, 0, m_layer->width(), m_layer->height()));
+}
+
+static RenderObject* rendererAfterPosition(RenderObject* object, unsigned offset)
{
if (!object)
return 0;
@@ -263,7 +294,17 @@ RenderObject* rendererAfterPosition(RenderObject* object, unsigned offset)
return child ? child : object->nextInPreOrderAfterChildren();
}
-IntRect RenderView::selectionRect(bool clipToVisibleContent) const
+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();
@@ -495,7 +536,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();
@@ -503,7 +544,7 @@ IntRect RenderView::viewRect() const
int RenderView::docHeight() const
{
- int h = m_height;
+ int h = height();
int lowestPos = lowestPosition();
if (lowestPos > h)
h = lowestPos;
@@ -512,7 +553,7 @@ int RenderView::docHeight() const
// 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)
@@ -523,12 +564,12 @@ int RenderView::docHeight() const
int RenderView::docWidth() const
{
- int w = m_width;
+ int w = width();
int rightmostPos = rightmostPosition();
if (rightmostPos > w)
w = rightmostPos;
-
- 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;
@@ -540,22 +581,26 @@ int RenderView::docWidth() const
int RenderView::viewHeight() const
{
int height = 0;
- if (!printing() && m_frameView)
- height = m_frameView->visibleHeight();
+ if (!printing() && m_frameView) {
+ height = m_frameView->layoutHeight();
+ height = m_frameView->useFixedLayout() ? ceilf(style()->effectiveZoom() * float(height)) : height;
+ }
return height;
}
int RenderView::viewWidth() const
{
int width = 0;
- if (!printing() && m_frameView)
- width = m_frameView->visibleWidth();
+ if (!printing() && m_frameView) {
+ width = m_frameView->layoutWidth();
+ width = m_frameView->useFixedLayout() ? ceilf(style()->effectiveZoom() * float(width)) : width;
+ }
return width;
}
// 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, RenderBox* forRenderer, bool forcedBreak)
{
// Nobody else can set a page break once we have a forced break.
if (m_forcedPageBreak)
@@ -569,16 +614,15 @@ void RenderView::setBestTruncatedAt(int y, RenderObject* forRenderer, bool force
}
// prefer the widest object who tries to move the pagination point
- int width = forRenderer->width();
- if (width > m_truncatorWidth) {
- m_truncatorWidth = width;
+ if (forRenderer->width() > m_truncatorWidth) {
+ m_truncatorWidth = forRenderer->width();
m_bestTruncatedAt = y;
}
}
void RenderView::pushLayoutState(RenderObject* root)
{
- ASSERT(!m_frameView->needsFullRepaint());
+ ASSERT(!doingFullRepaint());
ASSERT(m_layoutStateDisableCount == 0);
ASSERT(m_layoutState == 0);
diff --git a/WebCore/rendering/RenderView.h b/WebCore/rendering/RenderView.h
index b437cd1..8e7bf95 100644
--- a/WebCore/rendering/RenderView.h
+++ b/WebCore/rendering/RenderView.h
@@ -44,12 +44,13 @@ public:
virtual void calcWidth();
virtual void calcHeight();
virtual void calcPrefWidths();
- virtual bool absolutePosition(int& xPos, int& yPos, bool fixed = false) const;
+ 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;
int docHeight() const;
int docWidth() const;
- // The same as the FrameView's visibleHeight/visibleWidth but with null check guards.
+ // The same as the FrameView's layoutHeight/layoutWidth but with null check guards.
int viewHeight() const;
int viewWidth() const;
@@ -59,7 +60,7 @@ public:
virtual bool hasOverhangingFloats() { return false; }
- virtual void computeAbsoluteRepaintRect(IntRect&, bool fixed = false);
+ virtual void computeRectForRepaint(IntRect&, RenderBox* repaintContainer, bool fixed = false);
virtual void repaintViewRectangle(const IntRect&, bool immediate = false);
virtual void paint(PaintInfo&, int tx, int ty);
@@ -74,14 +75,15 @@ 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, RenderBox* 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);
- IntRect selectionRect(bool clipToVisibleContent = true) const;
+ IntRect selectionBounds(bool clipToVisibleContent = true) const;
void setMaximalOutlineSize(int o) { m_maximalOutlineSize = o; }
int maximalOutlineSize() const { return m_maximalOutlineSize; }
@@ -98,14 +100,25 @@ public:
void removeWidget(RenderObject*);
// 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);
}
@@ -113,22 +126,32 @@ 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--; }
protected:
+ virtual FloatQuad localToContainerQuad(const FloatQuad&, RenderBox* repaintContainer, bool fixed = false) const;
+
+private:
+ // selectionRect should never be called on a RenderView
+ virtual IntRect selectionRect(bool);
+
+protected:
FrameView* m_frameView;
RenderObject* m_selectionStart;
@@ -151,11 +174,67 @@ private:
int m_bestTruncatedAt;
int m_truncatorWidth;
bool m_forcedPageBreak;
- IntSize m_layoutDelta;
LayoutState* m_layoutState;
unsigned m_layoutStateDisableCount;
};
+// 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 disableState = false)
+ : m_view(view)
+ , m_disabled(disableState)
+ , m_didStart(false)
+ , m_didEnd(false)
+ {
+ push(root, offset);
+ }
+
+ // ctor to maybe push later
+ LayoutStateMaintainer(RenderView* view)
+ : m_view(view)
+ , m_disabled(false)
+ , m_didStart(false)
+ , m_didEnd(false)
+ {
+ }
+
+ ~LayoutStateMaintainer()
+ {
+ 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);
+ m_view->popLayoutState();
+ if (m_disabled)
+ m_view->enableLayoutState();
+ m_didEnd = true;
+ }
+ }
+
+ bool didPush() const { return m_didStart; }
+
+private:
+ RenderView* m_view;
+ 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
+};
+
} // namespace WebCore
#endif // RenderView_h
diff --git a/WebCore/rendering/RenderWidget.cpp b/WebCore/rendering/RenderWidget.cpp
index 57b8722..9bf8111 100644
--- a/WebCore/rendering/RenderWidget.cpp
+++ b/WebCore/rendering/RenderWidget.cpp
@@ -75,9 +75,10 @@ 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) {
@@ -94,7 +95,7 @@ void RenderWidget::destroy()
RenderArena* arena = renderArena();
if (layer)
- layer->clearClipRect();
+ layer->clearClipRects();
if (style() && (style()->height().isPercent() || style()->minHeight().isPercent() || style()->maxHeight().isPercent()))
RenderBlock::removePercentHeightDescendant(this);
@@ -172,8 +173,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);
@@ -188,7 +189,7 @@ void RenderWidget::paint(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
if (m_widget) {
@@ -218,16 +219,14 @@ void RenderWidget::updateWidgetPosition()
if (!m_widget)
return;
- int x;
- int y;
- absolutePosition(x, y);
- x += borderLeft() + paddingLeft();
- y += borderTop() + paddingTop();
+ // FIXME: This doesn't work correctly with transforms.
+ 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(x, 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.
@@ -273,7 +272,7 @@ bool RenderWidget::nodeAtPoint(const HitTestRequest& request, HitTestResult& res
// 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()));
+ result.setIsOverWidget(contentBoxRect().contains(result.localPoint()));
return inside;
}
diff --git a/WebCore/rendering/RootInlineBox.cpp b/WebCore/rendering/RootInlineBox.cpp
index e98d20e..6d42aa7 100644
--- a/WebCore/rendering/RootInlineBox.cpp
+++ b/WebCore/rendering/RootInlineBox.cpp
@@ -187,7 +187,7 @@ void RootInlineBox::paint(RenderObject::PaintInfo& paintInfo, int tx, int ty)
bool RootInlineBox::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, int x, int y, int tx, int ty)
{
- if (m_hasEllipsisBox && object()->style()->visibility() == VISIBLE) {
+ if (m_hasEllipsisBox && visibleToHitTesting()) {
if (ellipsisBox()->nodeAtPoint(request, result, x, y, tx, ty)) {
object()->updateHitTestResult(result, IntPoint(x - tx, y - ty));
return true;
@@ -240,18 +240,28 @@ GapRects RootInlineBox::fillLineSelectionGap(int selTop, int selHeight, RenderBl
lastBox->xPos() + 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();
+ 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));
+ if (isPreviousBoxSelected) // Selection may be non-contiguous, see comment above.
+ result.uniteCenter(block()->fillHorizontalSelectionGap(box->parent()->object(),
+ lastX + tx, selTop + ty,
+ box->xPos() - lastX, selHeight, paintInfo));
lastX = box->xPos() + box->width();
}
if (box == lastBox)
break;
+ isPreviousBoxSelected = box->selectionState() != RenderObject::SelectionNone;
}
}
@@ -332,7 +342,7 @@ RenderBlock* RootInlineBox::block() const
return static_cast<RenderBlock*>(m_object);
}
-bool isEditableLeaf(InlineBox* leaf)
+static bool isEditableLeaf(InlineBox* leaf)
{
return leaf && leaf->object() && leaf->object()->element() && leaf->object()->element()->isContentEditable();
}
diff --git a/WebCore/rendering/RootInlineBox.h b/WebCore/rendering/RootInlineBox.h
index 4724110..a16d1e5 100644
--- a/WebCore/rendering/RootInlineBox.h
+++ b/WebCore/rendering/RootInlineBox.h
@@ -119,7 +119,7 @@ public:
InlineBox* closestLeafChildForXPos(int x, bool onlyEditableLeaves = false);
- Vector<RenderObject*>& floats()
+ Vector<RenderBox*>& floats()
{
ASSERT(!isDirty());
if (!m_overflow)
@@ -127,7 +127,7 @@ public:
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; }
protected:
// Normally we are only as tall as the style on our block dictates, but we might have content
@@ -158,7 +158,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();
};
diff --git a/WebCore/rendering/SVGCharacterLayoutInfo.cpp b/WebCore/rendering/SVGCharacterLayoutInfo.cpp
index 287aeac..89bab2d 100644
--- a/WebCore/rendering/SVGCharacterLayoutInfo.cpp
+++ b/WebCore/rendering/SVGCharacterLayoutInfo.cpp
@@ -512,9 +512,9 @@ bool SVGChar::isHidden() const
return pathData && pathData->hidden;
}
-AffineTransform SVGChar::characterTransform() const
+TransformationMatrix SVGChar::characterTransform() const
{
- AffineTransform ctm;
+ TransformationMatrix ctm;
// Rotate character around angle, and possibly scale.
ctm.translate(x, y);
diff --git a/WebCore/rendering/SVGCharacterLayoutInfo.h b/WebCore/rendering/SVGCharacterLayoutInfo.h
index f3c5209..0188b9d 100644
--- a/WebCore/rendering/SVGCharacterLayoutInfo.h
+++ b/WebCore/rendering/SVGCharacterLayoutInfo.h
@@ -29,7 +29,7 @@
#include <wtf/HashSet.h>
#include <wtf/Vector.h>
-#include "AffineTransform.h"
+#include "TransformationMatrix.h"
#include <wtf/RefCounted.h>
#include "SVGRenderStyle.h"
#include "SVGTextContentElement.h"
@@ -235,7 +235,7 @@ struct SVGChar {
// Helper methods
bool isHidden() const;
- AffineTransform characterTransform() const;
+ TransformationMatrix characterTransform() const;
};
struct SVGInlineBoxCharacterRange {
@@ -276,7 +276,7 @@ struct SVGTextChunk {
// textLength & lengthAdjust support
float textLength;
ELengthAdjust lengthAdjust;
- AffineTransform ctm;
+ TransformationMatrix ctm;
// status flags
bool isVerticalText : 1;
@@ -292,7 +292,7 @@ struct SVGTextChunk {
struct SVGTextChunkWalkerBase {
virtual ~SVGTextChunkWalkerBase() { }
- virtual void operator()(SVGInlineTextBox* textBox, int startOffset, const AffineTransform& chunkCtm,
+ virtual void operator()(SVGInlineTextBox* textBox, int startOffset, const TransformationMatrix& chunkCtm,
const Vector<SVGChar>::iterator& start, const Vector<SVGChar>::iterator& end) = 0;
// Followings methods are only used for painting text chunks
@@ -308,7 +308,7 @@ struct SVGTextChunkWalker : public SVGTextChunkWalkerBase {
public:
typedef void (CallbackClass::*SVGTextChunkWalkerCallback)(SVGInlineTextBox* textBox,
int startOffset,
- const AffineTransform& chunkCtm,
+ const TransformationMatrix& chunkCtm,
const Vector<SVGChar>::iterator& start,
const Vector<SVGChar>::iterator& end);
@@ -336,7 +336,7 @@ public:
ASSERT(walker);
}
- virtual void operator()(SVGInlineTextBox* textBox, int startOffset, const AffineTransform& chunkCtm,
+ virtual void operator()(SVGInlineTextBox* textBox, int startOffset, const TransformationMatrix& chunkCtm,
const Vector<SVGChar>::iterator& start, const Vector<SVGChar>::iterator& end)
{
(*m_object.*m_walkerCallback)(textBox, startOffset, chunkCtm, start, end);
diff --git a/WebCore/rendering/SVGInlineFlowBox.cpp b/WebCore/rendering/SVGInlineFlowBox.cpp
index bbd8f4a..2649664 100644
--- a/WebCore/rendering/SVGInlineFlowBox.cpp
+++ b/WebCore/rendering/SVGInlineFlowBox.cpp
@@ -32,20 +32,21 @@ namespace WebCore {
using namespace SVGNames;
-void SVGInlineFlowBox::paint(RenderObject::PaintInfo& paintInfo, int tx, int ty)
+void SVGInlineFlowBox::paint(RenderObject::PaintInfo&, int, int)
{
ASSERT_NOT_REACHED();
}
-int SVGInlineFlowBox::placeBoxesHorizontally(int x, int& leftPosition, int& rightPosition, bool& needsWordSpacing)
+int SVGInlineFlowBox::placeBoxesHorizontally(int, int&, int&, bool&)
{
// no-op
return 0;
}
-void SVGInlineFlowBox::verticallyAlignBoxes(int& heightOfBlock)
+int SVGInlineFlowBox::verticallyAlignBoxes(int)
{
// no-op
+ return 0;
}
} // namespace WebCore
diff --git a/WebCore/rendering/SVGInlineFlowBox.h b/WebCore/rendering/SVGInlineFlowBox.h
index 96c5d4a..bb31807 100644
--- a/WebCore/rendering/SVGInlineFlowBox.h
+++ b/WebCore/rendering/SVGInlineFlowBox.h
@@ -38,7 +38,7 @@ public:
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);
};
} // namespace WebCore
diff --git a/WebCore/rendering/SVGInlineTextBox.cpp b/WebCore/rendering/SVGInlineTextBox.cpp
index ceb7b0e..620aea5 100644
--- a/WebCore/rendering/SVGInlineTextBox.cpp
+++ b/WebCore/rendering/SVGInlineTextBox.cpp
@@ -80,10 +80,8 @@ float SVGInlineTextBox::calculateGlyphWidth(RenderStyle* style, int offset, int
return style->font().floatWidth(svgTextRunForInlineTextBox(textObject()->text()->characters() + offset, 1, style, this, 0), extraCharsAvailable, charsConsumed, glyphName);
}
-float SVGInlineTextBox::calculateGlyphHeight(RenderStyle* style, int offset, int extraCharsAvailable) const
+float SVGInlineTextBox::calculateGlyphHeight(RenderStyle* style, int, int) const
{
- ASSERT(style);
-
// This is just a guess, and the only purpose of this function is to centralize this hack.
// In real-life top-top-bottom scripts this won't be enough, I fear.
return style->font().ascent() + style->font().descent();
@@ -113,7 +111,7 @@ FloatRect SVGInlineTextBox::calculateGlyphBoundaries(RenderStyle* style, int off
FloatRect glyphRect(x1, y1, x2 - x1, y2 - y1);
// Take per-character transformations into account
- AffineTransform ctm = svgChar.characterTransform();
+ TransformationMatrix ctm = svgChar.characterTransform();
if (!ctm.isIdentity())
glyphRect = ctm.mapRect(glyphRect);
@@ -131,7 +129,7 @@ struct SVGInlineTextBoxClosestCharacterToPositionWalker {
{
}
- void chunkPortionCallback(SVGInlineTextBox* textBox, int startOffset, const AffineTransform& chunkCtm,
+ void chunkPortionCallback(SVGInlineTextBox* textBox, int startOffset, const TransformationMatrix& chunkCtm,
const Vector<SVGChar>::iterator& start, const Vector<SVGChar>::iterator& end)
{
RenderStyle* style = textBox->textObject()->style();
@@ -198,7 +196,7 @@ struct SVGInlineTextBoxSelectionRectWalker {
{
}
- void chunkPortionCallback(SVGInlineTextBox* textBox, int startOffset, const AffineTransform& chunkCtm,
+ void chunkPortionCallback(SVGInlineTextBox* textBox, int startOffset, const TransformationMatrix& chunkCtm,
const Vector<SVGChar>::iterator& start, const Vector<SVGChar>::iterator& end)
{
RenderStyle* style = textBox->textObject()->style();
@@ -279,21 +277,21 @@ bool SVGInlineTextBox::svgCharacterHitsPosition(int x, int y, int& offset) const
return true;
}
-int SVGInlineTextBox::offsetForPosition(int x, bool includePartialGlyphs) const
+int SVGInlineTextBox::offsetForPosition(int, bool) const
{
// SVG doesn't use the offset <-> position selection system.
ASSERT_NOT_REACHED();
return 0;
}
-int SVGInlineTextBox::positionForOffset(int offset) const
+int SVGInlineTextBox::positionForOffset(int) const
{
// SVG doesn't use the offset <-> position selection system.
ASSERT_NOT_REACHED();
return 0;
}
-bool SVGInlineTextBox::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, int x, int y, int tx, int ty)
+bool SVGInlineTextBox::nodeAtPoint(const HitTestRequest&, HitTestResult& result, int x, int y, int tx, int ty)
{
ASSERT(!isLineBreak());
@@ -348,11 +346,9 @@ 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();
- AffineTransform ctm = svgChar.characterTransform();
+ TransformationMatrix ctm = svgChar.characterTransform();
if (!ctm.isIdentity())
paintInfo.context->concatCTM(ctm);
@@ -367,8 +363,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);
@@ -397,7 +393,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);
@@ -436,7 +432,7 @@ void SVGInlineTextBox::paintCharacters(RenderObject::PaintInfo& paintInfo, int t
paintInfo.context->concatCTM(ctm.inverse());
}
-void SVGInlineTextBox::paintSelection(int boxStartOffset, const SVGChar& svgChar, const UChar* chars, 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;
@@ -475,9 +471,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(textObject()->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();
}
@@ -520,7 +516,7 @@ void SVGInlineTextBox::paintDecoration(ETextDecoration decoration, GraphicsConte
context->save();
context->beginPath();
- AffineTransform ctm = svgChar.characterTransform();
+ TransformationMatrix ctm = svgChar.characterTransform();
if (!ctm.isIdentity())
context->concatCTM(ctm);
diff --git a/WebCore/rendering/SVGInlineTextBox.h b/WebCore/rendering/SVGInlineTextBox.h
index 1ddc23a..9882128 100644
--- a/WebCore/rendering/SVGInlineTextBox.h
+++ b/WebCore/rendering/SVGInlineTextBox.h
@@ -50,7 +50,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&);
diff --git a/WebCore/rendering/SVGRenderSupport.cpp b/WebCore/rendering/SVGRenderSupport.cpp
index f3223f1..9ffc533 100644
--- a/WebCore/rendering/SVGRenderSupport.cpp
+++ b/WebCore/rendering/SVGRenderSupport.cpp
@@ -25,7 +25,7 @@
#if ENABLE(SVG)
#include "SVGRenderSupport.h"
-#include "AffineTransform.h"
+#include "TransformationMatrix.h"
#include "ImageBuffer.h"
#include "RenderObject.h"
#include "RenderSVGContainer.h"
@@ -35,11 +35,17 @@
#include "SVGResourceMasker.h"
#include "SVGStyledElement.h"
#include "SVGURIReference.h"
+#include <wtf/UnusedParam.h>
namespace WebCore {
void prepareToRenderSVGContent(RenderObject* object, RenderObject::PaintInfo& paintInfo, const FloatRect& boundingBox, SVGResourceFilter*& filter, SVGResourceFilter* rootFilter)
-{
+{
+#if !ENABLE(SVG_FILTERS)
+ UNUSED_PARAM(filter);
+ UNUSED_PARAM(rootFilter);
+#endif
+
SVGElement* svgElement = static_cast<SVGElement*>(object->element());
ASSERT(svgElement && svgElement->document() && svgElement->isStyled());
ASSERT(object);
@@ -104,6 +110,12 @@ void prepareToRenderSVGContent(RenderObject* object, RenderObject::PaintInfo& pa
void finishRenderSVGContent(RenderObject* object, RenderObject::PaintInfo& paintInfo, const FloatRect& boundingBox, SVGResourceFilter*& filter, GraphicsContext* savedContext)
{
+#if !ENABLE(SVG_FILTERS)
+ UNUSED_PARAM(boundingBox);
+ UNUSED_PARAM(filter);
+ UNUSED_PARAM(savedContext);
+#endif
+
ASSERT(object);
const RenderStyle* style = object->style();
diff --git a/WebCore/rendering/SVGRenderTreeAsText.cpp b/WebCore/rendering/SVGRenderTreeAsText.cpp
index d3e029c..74a8af9 100644
--- a/WebCore/rendering/SVGRenderTreeAsText.cpp
+++ b/WebCore/rendering/SVGRenderTreeAsText.cpp
@@ -88,7 +88,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);
@@ -151,7 +151,7 @@ TextStream& operator<<(TextStream& ts, const FloatSize& s)
return ts;
}
-TextStream& operator<<(TextStream& ts, const AffineTransform& transform)
+TextStream& operator<<(TextStream& ts, const TransformationMatrix& transform)
{
if (transform.isIdentity())
ts << "identity";
@@ -233,8 +233,10 @@ static void writeStyle(TextStream& ts, const RenderObject& object)
if (!object.localTransform().isIdentity())
ts << " [transform=" << object.localTransform() << "]";
- if (svgStyle->imageRendering() != SVGRenderStyle::initialImageRendering())
- ts << " [image rendering=" << svgStyle->imageRendering() << "]";
+ if (svgStyle->imageRendering() != SVGRenderStyle::initialImageRendering()) {
+ unsigned imageRenderingAsInteger = svgStyle->imageRendering();
+ ts << " [image rendering=" << imageRenderingAsInteger << "]";
+ }
if (style->opacity() != RenderStyle::initialOpacity())
ts << " [opacity=" << style->opacity() << "]";
if (object.isRenderPath()) {
@@ -329,7 +331,7 @@ 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() << "]";
@@ -514,7 +516,9 @@ void write(TextStream& ts, const RenderSVGInlineText& text, int indent)
ts << " {" << tagName << "}";
}
- ts << " at (" << text.xPos() << "," << text.yPos() << ") size " << text.width() << "x" << text.height() << "\n";
+ IntRect linesBox = text.linesBoundingBox();
+
+ ts << " at (" << text.firstRunX() << "," << text.firstRunY() << ") size " << linesBox.width() << "x" << linesBox.height() << "\n";
writeSVGInlineText(ts, text, indent);
}
diff --git a/WebCore/rendering/SVGRenderTreeAsText.h b/WebCore/rendering/SVGRenderTreeAsText.h
index e23b82c..c4d832d 100644
--- a/WebCore/rendering/SVGRenderTreeAsText.h
+++ b/WebCore/rendering/SVGRenderTreeAsText.h
@@ -32,7 +32,7 @@
namespace WebCore {
- class AffineTransform;
+ class TransformationMatrix;
class Color;
class FloatPoint;
class FloatRect;
@@ -56,7 +56,7 @@ void write(TextStream&, const RenderSVGText&, int ident = 0);
void writeRenderResources(TextStream&, Node* parent);
// helper operators defined used in various classes to dump the render tree.
-TextStream& operator<<(TextStream&, const AffineTransform&);
+TextStream& operator<<(TextStream&, const TransformationMatrix&);
TextStream& operator<<(TextStream&, const IntRect&);
TextStream& operator<<(TextStream&, const Color&);
TextStream& operator<<(TextStream&, const IntPoint&);
diff --git a/WebCore/rendering/SVGRootInlineBox.cpp b/WebCore/rendering/SVGRootInlineBox.cpp
index e5f9fdf..62a8b04 100644
--- a/WebCore/rendering/SVGRootInlineBox.cpp
+++ b/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"
@@ -481,7 +482,7 @@ struct SVGRootInlineBoxPaintWalker {
return false;
}
- void chunkPortionCallback(SVGInlineTextBox* textBox, int startOffset, const AffineTransform& chunkCtm,
+ void chunkPortionCallback(SVGInlineTextBox* textBox, int startOffset, const TransformationMatrix& chunkCtm,
const Vector<SVGChar>::iterator& start, const Vector<SVGChar>::iterator& end)
{
RenderText* text = textBox->textObject();
@@ -611,10 +612,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)
@@ -842,7 +843,7 @@ static void applyTextLengthCorrectionToTextChunk(SVGTextChunk& chunk)
SVGChar& firstChar = *(chunk.start);
// Assure we apply the chunk scaling in the right origin
- AffineTransform newChunkCtm;
+ TransformationMatrix newChunkCtm;
newChunkCtm.translate(firstChar.x, firstChar.y);
newChunkCtm = chunk.ctm * newChunkCtm;
newChunkCtm.translate(-firstChar.x, -firstChar.y);
@@ -887,7 +888,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!
@@ -915,6 +916,9 @@ void SVGRootInlineBox::buildLayoutInformation(InlineFlowBox* start, SVGCharacter
ASSERT(curr->isInlineFlowBox());
InlineFlowBox* flowBox = static_cast<InlineFlowBox*>(curr);
+ if (!flowBox->object()->element())
+ continue; // Skip generated content.
+
bool isAnchor = flowBox->object()->element()->hasTagName(SVGNames::aTag);
bool isTextPath = flowBox->object()->element()->hasTagName(SVGNames::textPathTag);
@@ -952,7 +956,7 @@ void SVGRootInlineBox::buildLayoutInformation(InlineFlowBox* start, SVGCharacter
Vector<SVGTextChunk>::iterator it = tempChunks.begin();
Vector<SVGTextChunk>::iterator end = tempChunks.end();
- AffineTransform ctm;
+ TransformationMatrix ctm;
float computedLength = 0.0f;
for (; it != end; ++it) {
@@ -1035,10 +1039,10 @@ void SVGRootInlineBox::layoutInlineBoxes(InlineFlowBox* start, Vector<SVGChar>::
int minY = enclosedStringRect.y();
int maxY = minY + enclosedStringRect.height();
- curr->setXPos(minX - object()->xPos());
+ curr->setXPos(minX - block()->x());
curr->setWidth(enclosedStringRect.width());
- curr->setYPos(minY - object()->yPos());
+ curr->setYPos(minY - block()->y());
curr->setBaseline(font.ascent());
curr->setHeight(enclosedStringRect.height());
@@ -1062,12 +1066,16 @@ void SVGRootInlineBox::layoutInlineBoxes(InlineFlowBox* start, Vector<SVGChar>::
int maxY = INT_MIN;
InlineFlowBox* flowBox = static_cast<InlineFlowBox*>(curr);
+
+ if (!flowBox->object()->element())
+ continue; // Skip generated content.
+
layoutInlineBoxes(flowBox, it, minX, maxX, minY, maxY);
- curr->setXPos(minX - object()->xPos());
+ curr->setXPos(minX - block()->x());
curr->setWidth(maxX - minX);
- curr->setYPos(minY - object()->yPos());
+ curr->setYPos(minY - block()->y());
curr->setBaseline(font.ascent());
curr->setHeight(maxY - minY);
@@ -1086,10 +1094,10 @@ void SVGRootInlineBox::layoutInlineBoxes(InlineFlowBox* start, Vector<SVGChar>::
}
if (start->isRootInlineBox()) {
- int top = lowY - object()->yPos();
- int bottom = highY - object()->yPos();
+ int top = lowY - block()->y();
+ int bottom = highY - block()->y();
- start->setXPos(lowX - object()->xPos());
+ start->setXPos(lowX - block()->x());
start->setYPos(top);
start->setWidth(highX - lowX);
@@ -1517,6 +1525,9 @@ void SVGRootInlineBox::buildTextChunks(Vector<SVGChar>& svgChars, InlineFlowBox*
ASSERT(curr->isInlineFlowBox());
InlineFlowBox* flowBox = static_cast<InlineFlowBox*>(curr);
+ if (!flowBox->object()->element())
+ continue; // Skip generated content.
+
bool isTextPath = flowBox->object()->element()->hasTagName(SVGNames::textPathTag);
#if DEBUG_CHUNK_BUILDING > 1
diff --git a/WebCore/rendering/SVGRootInlineBox.h b/WebCore/rendering/SVGRootInlineBox.h
index 800664b..bfe9889 100644
--- a/WebCore/rendering/SVGRootInlineBox.h
+++ b/WebCore/rendering/SVGRootInlineBox.h
@@ -55,7 +55,7 @@ public:
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();
diff --git a/WebCore/rendering/TextControlInnerElements.cpp b/WebCore/rendering/TextControlInnerElements.cpp
index f14480f..452333c 100644
--- a/WebCore/rendering/TextControlInnerElements.cpp
+++ b/WebCore/rendering/TextControlInnerElements.cpp
@@ -32,9 +32,10 @@
#include "EventNames.h"
#include "Frame.h"
#include "HTMLInputElement.h"
+#include "HTMLNames.h"
#include "HTMLTextAreaElement.h"
#include "MouseEvent.h"
-#include "RenderTextControl.h"
+#include "RenderTextControlSingleLine.h"
namespace WebCore {
@@ -47,13 +48,18 @@ public:
bool RenderTextControlInnerBlock::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, int x, int y, int tx, int ty, HitTestAction hitTestAction)
{
- RenderTextControl* renderer = static_cast<RenderTextControl*>(node()->shadowAncestorNode()->renderer());
-
- return RenderBlock::nodeAtPoint(request, result, x, y, tx, ty, renderer->placeholderIsVisible() ? HitTestBlockBackground : hitTestAction);
+ RenderObject* renderer = node()->shadowAncestorNode()->renderer();
+
+ bool placeholderIsVisible = false;
+ if (renderer->isTextField())
+ placeholderIsVisible = static_cast<RenderTextControlSingleLine*>(renderer)->placeholderIsVisible();
+
+ return RenderBlock::nodeAtPoint(request, result, x, y, tx, ty, placeholderIsVisible ? HitTestBlockBackground : hitTestAction);
}
TextControlInnerElement::TextControlInnerElement(Document* doc, Node* shadowParent)
- : HTMLDivElement(doc), m_shadowParent(shadowParent)
+ : HTMLDivElement(HTMLNames::divTag, doc)
+ , m_shadowParent(shadowParent)
{
}
@@ -122,10 +128,11 @@ void SearchFieldResultsButtonElement::defaultEventHandler(Event* evt)
if (evt->type() == eventNames().mousedownEvent && evt->isMouseEvent() && static_cast<MouseEvent*>(evt)->button() == LeftButton) {
input->focus();
input->select();
- if (input && input->renderer() && static_cast<RenderTextControl*>(input->renderer())->popupIsVisible())
- static_cast<RenderTextControl*>(input->renderer())->hidePopup();
+ RenderTextControlSingleLine* renderer = static_cast<RenderTextControlSingleLine*>(input->renderer());
+ if (renderer->popupIsVisible())
+ renderer->hidePopup();
else if (input->maxResults() > 0)
- static_cast<RenderTextControl*>(input->renderer())->showPopup();
+ renderer->showPopup();
evt->setDefaultHandled();
}
if (!evt->defaultHandled())
@@ -146,13 +153,13 @@ void SearchFieldCancelButtonElement::defaultEventHandler(Event* evt)
input->focus();
input->select();
evt->setDefaultHandled();
- if (renderer() && renderer()->style()->visibility() == VISIBLE)
+ if (renderer() && renderer()->visibleToHitTesting())
if (Frame* frame = document()->frame()) {
frame->eventHandler()->setCapturingMouseEventsNode(this);
m_capturing = true;
}
} else if (evt->type() == eventNames().mouseupEvent && evt->isMouseEvent() && static_cast<MouseEvent*>(evt)->button() == LeftButton) {
- if (m_capturing && renderer() && renderer()->style()->visibility() == VISIBLE) {
+ if (m_capturing && renderer() && renderer()->visibleToHitTesting()) {
if (hovered()) {
input->setValue("");
input->onSearch();
diff --git a/WebCore/rendering/bidi.cpp b/WebCore/rendering/bidi.cpp
index 93f3b0f..2f05e7f 100644
--- a/WebCore/rendering/bidi.cpp
+++ b/WebCore/rendering/bidi.cpp
@@ -35,6 +35,7 @@
#include "break_lines.h"
#include <wtf/AlwaysInline.h>
#include <wtf/RefCountedLeakCounter.h>
+#include <wtf/StdLibExtras.h>
#include <wtf/Vector.h>
#ifdef ANDROID_LAYOUT
#include "Frame.h"
@@ -94,7 +95,7 @@ static bool betweenMidpoints;
static bool isLineEmpty = true;
static bool previousLineBrokeCleanly = true;
-static int getBorderPaddingMargin(RenderObject* child, bool endOfInline)
+static int getBorderPaddingMargin(RenderBox* child, bool endOfInline)
{
bool leftSide = (child->style()->direction() == LTR) ? !endOfInline : endOfInline;
if (leftSide)
@@ -107,11 +108,11 @@ static int inlineWidth(RenderObject* child, bool start = true, bool end = true)
unsigned lineDepth = 1;
int extraWidth = 0;
RenderObject* parent = child->parent();
- while (parent->isInline() && !parent->isInlineBlockOrInlineTable() && lineDepth++ < cMaxLineDepth) {
+ while (parent->isBox() && parent->isInline() && !parent->isInlineBlockOrInlineTable() && lineDepth++ < cMaxLineDepth) {
if (start && parent->firstChild() == child)
- extraWidth += getBorderPaddingMargin(parent, false);
+ extraWidth += getBorderPaddingMargin(toRenderBox(parent), false);
if (end && parent->lastChild() == child)
- extraWidth += getBorderPaddingMargin(parent, true);
+ extraWidth += getBorderPaddingMargin(toRenderBox(parent), true);
child = parent;
parent = child->parent();
}
@@ -180,7 +181,7 @@ static inline RenderObject* bidiNext(RenderBlock* block, RenderObject* current,
next = 0;
if (!oldEndOfInline && !current->isFloating() && !current->isReplaced() && !current->isPositioned()) {
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();
@@ -193,19 +194,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();
@@ -219,7 +220,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;
@@ -232,7 +233,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;
}
@@ -249,7 +250,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) {
@@ -284,7 +285,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;
@@ -312,7 +313,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;
@@ -364,12 +365,12 @@ static void checkMidpoints(InlineIterator& lBreak)
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;
}
@@ -392,7 +393,7 @@ static void addMidpoint(const InlineIterator& 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->hasStaticX() && !obj->hasStaticY() && !obj->container()->isRenderInline()))
return;
bool haveNextMidpoint = (sCurrMidpoint < sNumMidpoints);
@@ -470,7 +471,7 @@ InlineFlowBox* RenderBlock::createLineBoxes(RenderObject* obj)
InlineFlowBox* parentBox = 0;
InlineFlowBox* result = 0;
do {
- ASSERT(obj->isInlineFlow() || obj == this);
+ ASSERT(obj->isRenderInline() || obj == this);
RenderFlow* flow = static_cast<RenderFlow*>(obj);
// Get the last box we made for this render object.
@@ -572,7 +573,7 @@ RootInlineBox* RenderBlock::constructLine(unsigned runCount, BidiRun* firstRun,
void RenderBlock::computeHorizontalPositionsForLine(RootInlineBox* lineBox, BidiRun* firstRun, BidiRun* trailingSpaceRun, bool reachedEnd)
{
// First determine our total width.
- int availableWidth = lineWidth(m_height);
+ int availableWidth = lineWidth(height());
int totWidth = lineBox->getFlowSpacingWidth();
bool needsWordSpacing = false;
unsigned numSpaces = 0;
@@ -584,7 +585,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();
@@ -596,28 +597,26 @@ 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]))
+ if (!r->m_start && needsWordSpacing && isSpaceOrNewline(rt->characters()[r->m_start]))
totWidth += rt->style(m_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();
+ } 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());
switch(textAlign) {
case LEFT:
case WEBKIT_LEFT:
@@ -691,9 +690,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')
@@ -726,12 +725,12 @@ 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.
@@ -742,7 +741,7 @@ void RenderBlock::computeVerticalPositionsForLine(RootInlineBox* lineBox, BidiRu
// 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->setYPos(height());
// Position is used to properly position both replaced elements and
// to update the static normal flow x/y of positioned elements.
@@ -759,34 +758,6 @@ void RenderBlock::bidiReorderLine(InlineBidiResolver& resolver, const InlineIter
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)
@@ -806,7 +777,7 @@ void RenderBlock::layoutInlineChildren(bool relayoutChildren, int& repaintTop, i
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.
@@ -853,6 +824,8 @@ void RenderBlock::layoutInlineChildren(bool relayoutChildren, int& repaintTop, i
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);
@@ -861,7 +834,7 @@ void RenderBlock::layoutInlineChildren(bool relayoutChildren, int& repaintTop, i
o->setPrefWidthsDirty(true, false);
if (o->isPositioned())
- o->containingBlock()->insertPositionedObject(o);
+ o->containingBlock()->insertPositionedObject(box);
else {
#ifdef ANDROID_LAYOUT
// ignore text wrap for textField or menuList
@@ -869,18 +842,18 @@ void RenderBlock::layoutInlineChildren(bool relayoutChildren, int& repaintTop, i
doTextWrap = false;
#endif
if (o->isFloating())
- floats.append(FloatWithRect(o));
+ floats.append(FloatWithRect(box));
else if (fullLayout || o->needsLayout()) // Replaced elements
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())
+ if (o->isRenderInline())
static_cast<RenderFlow*>(o)->calcMargins(containerWidth);
o->setNeedsLayout(false);
#ifdef ANDROID_LAYOUT
@@ -928,7 +901,7 @@ void RenderBlock::layoutInlineChildren(bool relayoutChildren, int& repaintTop, i
if (!isConstrained) {
int maxWidth = view()->frameView()->screenWidth() - 2 * ANDROID_FCTS_MARGIN_PADDING;
if (maxWidth > 0) {
- m_width = min(m_width, maxWidth);
+ setWidth(min(width(), maxWidth));
m_minPrefWidth = min(m_minPrefWidth, maxWidth);
m_maxPrefWidth = min(m_maxPrefWidth, maxWidth);
m_overflowWidth = min(m_overflowWidth, maxWidth);
@@ -944,14 +917,13 @@ void RenderBlock::layoutInlineChildren(bool relayoutChildren, int& repaintTop, i
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() && m_layer) {
// 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());
+ v->repaintViewRectangle(m_layer->repaintRect());
}
}
@@ -973,8 +945,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) {
@@ -1007,7 +979,7 @@ void RenderBlock::layoutInlineChildren(bool relayoutChildren, int& repaintTop, i
bool endLineMatched = false;
bool checkForEndLineMatch = endLine;
bool checkForFloatsFromLastLine = false;
- int lastHeight = m_height;
+ int lastHeight = height();
while (!end.atEnd()) {
// FIXME: Is this check necessary before the first iteration or can it be moved to the end?
@@ -1016,10 +988,7 @@ void RenderBlock::layoutInlineChildren(bool relayoutChildren, int& repaintTop, i
betweenMidpoints = false;
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);
if (resolver.position().atEnd()) {
@@ -1038,7 +1007,7 @@ void RenderBlock::layoutInlineChildren(bool relayoutChildren, int& repaintTop, i
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()) {
@@ -1150,7 +1119,7 @@ void RenderBlock::layoutInlineChildren(bool relayoutChildren, int& repaintTop, i
lastFloat = m_floatingObjects->last();
}
- lastHeight = m_height;
+ lastHeight = height();
sNumMidpoints = 0;
sCurrMidpoint = 0;
resolver.setPosition(end);
@@ -1159,7 +1128,7 @@ void RenderBlock::layoutInlineChildren(bool relayoutChildren, int& repaintTop, i
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) {
@@ -1167,17 +1136,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;
@@ -1213,16 +1182,16 @@ void RenderBlock::layoutInlineChildren(bool relayoutChildren, int& repaintTop, i
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.
@@ -1239,10 +1208,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) {
@@ -1286,7 +1255,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;
@@ -1304,15 +1273,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++;
@@ -1320,7 +1289,7 @@ RootInlineBox* RenderBlock::determineStartPosition(bool& fullLayout, InlineBidiR
}
line = line->nextRootBox();
}
- m_height = savedHeight;
+ setHeight(savedHeight);
}
m_firstLine = !last;
@@ -1329,7 +1298,7 @@ RootInlineBox* RenderBlock::determineStartPosition(bool& fullLayout, InlineBidiR
RenderObject* startObj;
int pos = 0;
if (last) {
- m_height = last->blockHeight();
+ setHeight(last->blockHeight());
startObj = last->lineBreakObj();
pos = last->lineBreakPos();
resolver.setStatus(last->lineBreakBidiStatus());
@@ -1389,12 +1358,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())
@@ -1425,10 +1394,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())
@@ -1492,12 +1461,12 @@ static inline bool shouldPreserveNewline(RenderObject* object)
return object->style()->preserveNewline();
}
-static bool inlineFlowRequiresLineBox(RenderObject* flow)
+static bool inlineFlowRequiresLineBox(RenderBox* 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->isRenderInline() && !flow->firstChild() && flow->hasHorizontalBordersPaddingOrMargin();
}
static inline bool requiresLineBox(const InlineIterator& it)
@@ -1505,7 +1474,7 @@ static inline bool requiresLineBox(const InlineIterator& it)
if (it.obj->isFloatingOrPositioned())
return false;
- if (it.obj->isInlineFlow() && !inlineFlowRequiresLineBox(it.obj))
+ if (it.obj->isRenderInline() && !inlineFlowRequiresLineBox(toRenderBox(it.obj)))
return false;
if (!shouldCollapseWhiteSpace(it.obj->style()) || it.obj->isBR())
@@ -1537,28 +1506,28 @@ void RenderBlock::skipTrailingWhitespace(InlineIterator& iterator)
while (!iterator.atEnd() && !requiresLineBox(iterator)) {
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);
+ c->setStaticX(style()->direction() == LTR ? leftOffset(height()) : rightOffset(height()));
+ c->setStaticY(height());
}
if (object->hasStaticX()) {
if (object->style()->isOriginalDisplayInlineType())
- object->setStaticX(style()->direction() == LTR ? leftOffset(m_height) : width() - rightOffset(m_height));
+ object->setStaticX(style()->direction() == LTR ? leftOffset(height()) : width() - rightOffset(height()));
else
object->setStaticX(style()->direction() == LTR ? borderLeft() + paddingLeft() : borderRight() + paddingRight());
}
if (object->hasStaticY())
- object->setStaticY(m_height);
+ object->setStaticY(height());
}
iterator.increment();
}
@@ -1566,34 +1535,34 @@ void RenderBlock::skipTrailingWhitespace(InlineIterator& iterator)
int RenderBlock::skipLeadingWhitespace(InlineBidiResolver& resolver)
{
- int availableWidth = lineWidth(m_height);
+ int availableWidth = lineWidth(height());
while (!resolver.position().atEnd() && !requiresLineBox(resolver.position())) {
RenderObject* object = resolver.position().obj;
if (object->isFloating()) {
- insertFloatingObject(object);
+ insertFloatingObject(toRenderBox(object));
positionNewFloats();
- availableWidth = lineWidth(m_height);
+ availableWidth = lineWidth(height());
} 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);
+ c->setStaticX(style()->direction() == LTR ? leftOffset(height()) : rightOffset(height()));
+ c->setStaticY(height());
}
if (object->hasStaticX()) {
if (object->style()->isOriginalDisplayInlineType())
- object->setStaticX(style()->direction() == LTR ? leftOffset(m_height) : width() - rightOffset(m_height));
+ object->setStaticX(style()->direction() == LTR ? leftOffset(height()) : width() - rightOffset(height()));
else
object->setStaticX(style()->direction() == LTR ? borderLeft() + paddingLeft() : borderRight() + paddingRight());
}
if (object->hasStaticY())
- object->setStaticY(m_height);
+ object->setStaticY(height());
}
resolver.increment();
}
@@ -1606,8 +1575,8 @@ int RenderBlock::skipLeadingWhitespace(InlineBidiResolver& resolver)
static bool shouldSkipWhitespaceAfterStartObject(RenderBlock* block, RenderObject* o)
{
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));
@@ -1623,7 +1592,7 @@ void RenderBlock::fitBelowFloats(int widthToFit, int& availableWidth)
ASSERT(widthToFit > availableWidth);
int floatBottom;
- int lastFloatBottom = m_height;
+ int lastFloatBottom = height();
int newLineWidth = availableWidth;
while (true) {
floatBottom = nextFloatBottomBelow(lastFloatBottom);
@@ -1637,7 +1606,7 @@ void RenderBlock::fitBelowFloats(int widthToFit, int& availableWidth)
}
if (newLineWidth > availableWidth) {
- m_height = lastFloatBottom;
+ setHeight(lastFloatBottom);
availableWidth = newLineWidth;
}
}
@@ -1730,13 +1699,14 @@ 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());
} else
floatsFitOnLine = false;
} else if (o->isPositioned()) {
@@ -1755,13 +1725,13 @@ InlineIterator RenderBlock::findNextLineBreak(InlineBidiResolver& resolver, ECle
// and determine our static y position now.
bool needToSetStaticY = o->hasStaticY();
if (o->hasStaticY() && isInlineType) {
- o->setStaticY(m_height);
+ o->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
@@ -1777,15 +1747,17 @@ InlineIterator RenderBlock::findNextLineBreak(InlineBidiResolver& resolver, ECle
}
}
- } else if (o->isInlineFlow()) {
+ } else if (o->isRenderInline()) {
// Right now, we should only encounter empty inlines here.
ASSERT(!o->firstChild());
+ RenderBox* flowBox = toRenderBox(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;
@@ -1801,9 +1773,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;
@@ -1833,12 +1807,12 @@ 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;
@@ -1885,7 +1859,7 @@ 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--;
@@ -1975,7 +1949,7 @@ InlineIterator RenderBlock::findNextLineBreak(InlineBidiResolver& resolver, ECle
}
}
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
@@ -2096,7 +2070,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)))
@@ -2220,7 +2194,7 @@ InlineIterator RenderBlock::findNextLineBreak(InlineBidiResolver& resolver, ECle
// 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);
@@ -2240,7 +2214,7 @@ 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);
}
@@ -2250,7 +2224,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);
@@ -2270,7 +2244,7 @@ void RenderBlock::checkLinesForTextOverflow()
// Determine the width of the ellipsis using the current font.
// FIXME: CSS3 says this is configurable, also need to use 0x002E (FULL STOP) if horizontal ellipsis is "not renderable"
TextRun ellipsisRun(&horizontalEllipsis, 1);
- static AtomicString ellipsisStr(&horizontalEllipsis, 1);
+ DEFINE_STATIC_LOCAL(AtomicString, ellipsisStr, (&horizontalEllipsis, 1));
const Font& firstLineFont = firstLineStyle()->font();
const Font& font = style()->font();
int firstLineEllipsisWidth = firstLineFont.width(ellipsisRun);
diff --git a/WebCore/rendering/bidi.h b/WebCore/rendering/bidi.h
index fc6de5b..9058eeb 100644
--- a/WebCore/rendering/bidi.h
+++ b/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/WebCore/rendering/style/Animation.cpp b/WebCore/rendering/style/Animation.cpp
deleted file mode 100644
index ed3a7e7..0000000
--- a/WebCore/rendering/style/Animation.cpp
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * Copyright (C) 1999 Antti Koivisto (koivisto@kde.org)
- * Copyright (C) 2004, 2005, 2006, 2007, 2008 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 "Animation.h"
-
-#include "RenderStyle.h"
-
-namespace WebCore {
-
-Animation::Animation()
- : m_delay(RenderStyle::initialAnimationDelay())
- , m_direction(RenderStyle::initialAnimationDirection())
- , m_duration(RenderStyle::initialAnimationDuration())
- , m_iterationCount(RenderStyle::initialAnimationIterationCount())
- , m_name(RenderStyle::initialAnimationName())
- , m_property(RenderStyle::initialAnimationProperty())
- , m_timingFunction(RenderStyle::initialAnimationTimingFunction())
- , m_playState(RenderStyle::initialAnimationPlayState())
- , m_delaySet(false)
- , m_directionSet(false)
- , m_durationSet(false)
- , m_iterationCountSet(false)
- , m_nameSet(false)
- , m_playStateSet(false)
- , m_propertySet(false)
- , m_timingFunctionSet(false)
- , m_isNone(false)
-{
-}
-
-Animation::Animation(const Animation& o)
- : RefCounted<Animation>()
- , m_delay(o.m_delay)
- , m_direction(o.m_direction)
- , m_duration(o.m_duration)
- , m_iterationCount(o.m_iterationCount)
- , m_name(o.m_name)
- , m_property(o.m_property)
- , m_timingFunction(o.m_timingFunction)
- , m_playState(o.m_playState)
- , m_delaySet(o.m_delaySet)
- , m_directionSet(o.m_directionSet)
- , m_durationSet(o.m_durationSet)
- , m_iterationCountSet(o.m_iterationCountSet)
- , m_nameSet(o.m_nameSet)
- , m_playStateSet(o.m_playStateSet)
- , m_propertySet(o.m_propertySet)
- , m_timingFunctionSet(o.m_timingFunctionSet)
- , m_isNone(o.m_isNone)
-{
-}
-
-Animation& Animation::operator=(const Animation& o)
-{
- m_delay = o.m_delay;
- m_direction = o.m_direction;
- m_duration = o.m_duration;
- m_iterationCount = o.m_iterationCount;
- m_name = o.m_name;
- m_playState = o.m_playState;
- m_property = o.m_property;
- m_timingFunction = o.m_timingFunction;
-
- m_delaySet = o.m_delaySet;
- m_directionSet = o.m_directionSet;
- m_durationSet = o.m_durationSet;
- m_iterationCountSet = o.m_iterationCountSet;
- m_nameSet = o.m_nameSet;
- m_playStateSet = o.m_playStateSet;
- m_propertySet = o.m_propertySet;
- m_timingFunctionSet = o.m_timingFunctionSet;
-
- m_isNone = o.m_isNone;
-
- return *this;
-}
-
-Animation::~Animation()
-{
-}
-
-bool Animation::animationsMatch(const Animation* o, bool matchPlayStates) const
-{
- if (!o)
- return false;
-
- bool result = m_delay == o->m_delay &&
- m_direction == o->m_direction &&
- m_duration == o->m_duration &&
- m_iterationCount == o->m_iterationCount &&
- m_name == o->m_name &&
- m_property == o->m_property &&
- m_timingFunction == o->m_timingFunction &&
- m_delaySet == o->m_delaySet &&
- m_directionSet == o->m_directionSet &&
- m_durationSet == o->m_durationSet &&
- m_iterationCountSet == o->m_iterationCountSet &&
- m_nameSet == o->m_nameSet &&
- m_propertySet == o->m_propertySet &&
- m_timingFunctionSet == o->m_timingFunctionSet &&
- m_isNone == o->m_isNone;
-
- if (!result)
- return false;
-
- return !matchPlayStates || (m_playState == o->m_playState && m_playStateSet == o->m_playStateSet);
-}
-
-} // namespace WebCore
diff --git a/WebCore/rendering/style/Animation.h b/WebCore/rendering/style/Animation.h
deleted file mode 100644
index 8930e30..0000000
--- a/WebCore/rendering/style/Animation.h
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
- * Copyright (C) 2000 Lars Knoll (knoll@kde.org)
- * (C) 2000 Antti Koivisto (koivisto@kde.org)
- * (C) 2000 Dirk Mueller (mueller@kde.org)
- * Copyright (C) 2003, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
- * Copyright (C) 2006 Graham Dennis (graham.dennis@gmail.com)
- *
- * 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 Animation_h
-#define Animation_h
-
-#include "PlatformString.h"
-#include "TimingFunction.h"
-#include <wtf/PassRefPtr.h>
-#include <wtf/RefCounted.h>
-
-namespace WebCore {
-
-class Animation : public RefCounted<Animation> {
-public:
- ~Animation();
-
- static PassRefPtr<Animation> create() { return adoptRef(new Animation); };
-
- bool isDelaySet() const { return m_delaySet; }
- bool isDirectionSet() const { return m_directionSet; }
- bool isDurationSet() const { return m_durationSet; }
- bool isIterationCountSet() const { return m_iterationCountSet; }
- bool isNameSet() const { return m_nameSet; }
- bool isPlayStateSet() const { return m_playStateSet; }
- bool isPropertySet() const { return m_propertySet; }
- bool isTimingFunctionSet() const { return m_timingFunctionSet; }
-
- // Flags this to be the special "none" animation (animation-name: none)
- bool isNoneAnimation() const { return m_isNone; }
- // We can make placeholder Animation objects to keep the comma-separated lists
- // of properties in sync. isValidAnimation means this is not a placeholder.
- bool isValidAnimation() const { return !m_isNone && !m_name.isEmpty(); }
-
- bool isEmpty() const
- {
- return (!m_directionSet && !m_durationSet && !m_nameSet && !m_playStateSet &&
- !m_iterationCountSet && !m_delaySet && !m_timingFunctionSet && !m_propertySet);
- }
-
- bool isEmptyOrZeroDuration() const
- {
- return isEmpty() || (m_duration == 0 && m_delay <= 0);
- }
-
- void clearDelay() { m_delaySet = false; }
- void clearDirection() { m_directionSet = false; }
- void clearDuration() { m_durationSet = false; }
- void clearIterationCount() { m_iterationCountSet = false; }
- void clearName() { m_nameSet = false; }
- void clearPlayState() { m_playStateSet = AnimPlayStatePlaying; }
- void clearProperty() { m_propertySet = false; }
- void clearTimingFunction() { m_timingFunctionSet = false; }
-
- double delay() const { return m_delay; }
- bool direction() const { return m_direction; }
- double duration() const { return m_duration; }
- int iterationCount() const { return m_iterationCount; }
- const String& name() const { return m_name; }
- unsigned playState() const { return m_playState; }
- int property() const { return m_property; }
- const TimingFunction& timingFunction() const { return m_timingFunction; }
-
- void setDelay(double c) { m_delay = c; m_delaySet = true; }
- void setDirection(bool d) { m_direction = d; m_directionSet = true; }
- void setDuration(double d) { ASSERT(d >= 0); m_duration = d; m_durationSet = true; }
- void setIterationCount(int c) { m_iterationCount = c; m_iterationCountSet = true; }
- void setName(const String& n) { m_name = n; m_nameSet = true; }
- void setPlayState(unsigned d) { m_playState = d; m_playStateSet = true; }
- void setProperty(int t) { m_property = t; m_propertySet = true; }
- void setTimingFunction(const TimingFunction& f) { m_timingFunction = f; m_timingFunctionSet = true; }
-
- void setIsNoneAnimation(bool n) { m_isNone = n; }
-
- Animation& operator=(const Animation& o);
-
- // return true if all members of this class match (excluding m_next)
- bool animationsMatch(const Animation*, bool matchPlayStates = true) const;
-
- // return true every Animation in the chain (defined by m_next) match
- bool operator==(const Animation& o) const { return animationsMatch(&o); }
- bool operator!=(const Animation& o) const { return !(*this == o); }
-
-private:
- Animation();
- Animation(const Animation& o);
-
- double m_delay;
- bool m_direction;
- double m_duration;
- int m_iterationCount;
- String m_name;
- int m_property;
- TimingFunction m_timingFunction;
-
- unsigned m_playState : 2;
-
- bool m_delaySet : 1;
- bool m_directionSet : 1;
- bool m_durationSet : 1;
- bool m_iterationCountSet : 1;
- bool m_nameSet : 1;
- bool m_playStateSet : 1;
- bool m_propertySet : 1;
- bool m_timingFunctionSet : 1;
-
- bool m_isNone : 1;
-};
-
-} // namespace WebCore
-
-#endif // Animation_h
diff --git a/WebCore/rendering/style/AnimationList.cpp b/WebCore/rendering/style/AnimationList.cpp
deleted file mode 100644
index 804dede..0000000
--- a/WebCore/rendering/style/AnimationList.cpp
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (C) 1999 Antti Koivisto (koivisto@kde.org)
- * Copyright (C) 2004, 2005, 2006, 2007, 2008 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 "AnimationList.h"
-
-namespace WebCore {
-
-#define FILL_UNSET_PROPERTY(test, propGet, propSet) \
-for (i = 0; i < size() && animation(i)->test(); ++i) { } \
-if (i < size() && i != 0) { \
- for (size_t j = 0; i < size(); ++i, ++j) \
- animation(i)->propSet(animation(j)->propGet()); \
-}
-
-void AnimationList::fillUnsetProperties()
-{
- size_t i;
- FILL_UNSET_PROPERTY(isDelaySet, delay, setDelay);
- FILL_UNSET_PROPERTY(isDirectionSet, direction, setDirection);
- FILL_UNSET_PROPERTY(isDurationSet, duration, setDuration);
- FILL_UNSET_PROPERTY(isIterationCountSet, iterationCount, setIterationCount);
- FILL_UNSET_PROPERTY(isPlayStateSet, playState, setPlayState);
- FILL_UNSET_PROPERTY(isNameSet, name, setName);
- FILL_UNSET_PROPERTY(isTimingFunctionSet, timingFunction, setTimingFunction);
- FILL_UNSET_PROPERTY(isPropertySet, property, setProperty);
-}
-
-bool AnimationList::operator==(const AnimationList& o) const
-{
- if (size() != o.size())
- return false;
- for (size_t i = 0; i < size(); ++i)
- if (*animation(i) != *o.animation(i))
- return false;
- return true;
-}
-
-} // namespace WebCore
diff --git a/WebCore/rendering/style/AnimationList.h b/WebCore/rendering/style/AnimationList.h
deleted file mode 100644
index 9901424..0000000
--- a/WebCore/rendering/style/AnimationList.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright (C) 2000 Lars Knoll (knoll@kde.org)
- * (C) 2000 Antti Koivisto (koivisto@kde.org)
- * (C) 2000 Dirk Mueller (mueller@kde.org)
- * Copyright (C) 2003, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
- * Copyright (C) 2006 Graham Dennis (graham.dennis@gmail.com)
- *
- * 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 AnimationList_h
-#define AnimationList_h
-
-#include "Animation.h"
-#include <wtf/RefPtr.h>
-#include <wtf/Vector.h>
-
-namespace WebCore {
-
-class AnimationList {
-public:
- void fillUnsetProperties();
- bool operator==(const AnimationList& o) const;
- bool operator!=(const AnimationList& o) const
- {
- return !(*this == o);
- }
-
- size_t size() const { return m_animations.size(); }
- bool isEmpty() const { return m_animations.isEmpty(); }
-
- void resize(size_t n) { m_animations.resize(n); }
- void remove(size_t i) { m_animations.remove(i); }
- void append(PassRefPtr<Animation> anim) { m_animations.append(anim); }
-
- Animation* animation(size_t i) { return m_animations[i].get(); }
- const Animation* animation(size_t i) const { return m_animations[i].get(); }
-
-private:
- Vector<RefPtr<Animation> > m_animations;
-};
-
-
-} // namespace WebCore
-
-#endif // AnimationList_h
diff --git a/WebCore/rendering/style/FillLayer.h b/WebCore/rendering/style/FillLayer.h
index 8f0ad94..2dc5871 100644
--- a/WebCore/rendering/style/FillLayer.h
+++ b/WebCore/rendering/style/FillLayer.h
@@ -120,8 +120,8 @@ public:
static EFillRepeat initialFillRepeat(EFillLayerType) { return RepeatFill; }
static CompositeOperator initialFillComposite(EFillLayerType) { return CompositeSourceOver; }
static LengthSize initialFillSize(EFillLayerType) { return LengthSize(); }
- static Length initialFillXPosition(EFillLayerType type) { return Length(0.0, Percent); }
- static Length initialFillYPosition(EFillLayerType type) { return Length(0.0, Percent); }
+ static Length initialFillXPosition(EFillLayerType) { return Length(0.0, Percent); }
+ static Length initialFillYPosition(EFillLayerType) { return Length(0.0, Percent); }
static StyleImage* initialFillImage(EFillLayerType) { return 0; }
private:
diff --git a/WebCore/rendering/style/IdentityTransformOperation.h b/WebCore/rendering/style/IdentityTransformOperation.h
deleted file mode 100644
index 54c49a3..0000000
--- a/WebCore/rendering/style/IdentityTransformOperation.h
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright (C) 2000 Lars Knoll (knoll@kde.org)
- * (C) 2000 Antti Koivisto (koivisto@kde.org)
- * (C) 2000 Dirk Mueller (mueller@kde.org)
- * Copyright (C) 2003, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
- * Copyright (C) 2006 Graham Dennis (graham.dennis@gmail.com)
- *
- * 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 IdentityTransformOperation_h
-#define IdentityTransformOperation_h
-
-#include "TransformOperation.h"
-
-namespace WebCore {
-
-class IdentityTransformOperation : public TransformOperation {
-public:
- static PassRefPtr<IdentityTransformOperation> create()
- {
- return adoptRef(new IdentityTransformOperation());
- }
-
- virtual bool isIdentity() const { return true; }
- virtual OperationType getOperationType() const { return IDENTITY; }
- virtual bool isSameType(const TransformOperation& o) const { return o.getOperationType() == IDENTITY; }
-
- virtual bool operator==(const TransformOperation& o) const
- {
- return isSameType(o);
- }
-
- virtual bool apply(AffineTransform& transform, const IntSize& borderBoxSize) const
- {
- return false;
- }
-
- virtual PassRefPtr<TransformOperation> blend(const TransformOperation* from, double progress, bool blendToIdentity = false)
- {
- return this;
- }
-
-private:
- IdentityTransformOperation()
- {
- }
-
-};
-
-} // namespace WebCore
-
-#endif // IdentityTransformOperation_h
diff --git a/WebCore/rendering/style/MatrixTransformOperation.cpp b/WebCore/rendering/style/MatrixTransformOperation.cpp
deleted file mode 100644
index c41ae3e..0000000
--- a/WebCore/rendering/style/MatrixTransformOperation.cpp
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright (C) 1999 Antti Koivisto (koivisto@kde.org)
- * Copyright (C) 2004, 2005, 2006, 2007, 2008 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 "MatrixTransformOperation.h"
-
-#include <algorithm>
-
-namespace WebCore {
-
-PassRefPtr<TransformOperation> MatrixTransformOperation::blend(const TransformOperation* from, double progress, bool blendToIdentity)
-{
- if (from && !from->isSameType(*this))
- return this;
-
- // convert the TransformOperations into matrices
- IntSize size;
- AffineTransform fromT;
- AffineTransform toT(m_a, m_b, m_c, m_d, m_e, m_f);
- if (from) {
- const MatrixTransformOperation* m = static_cast<const MatrixTransformOperation*>(from);
- fromT.setMatrix(m->m_a, m->m_b, m->m_c, m->m_d, m->m_e, m->m_f);
- }
-
- if (blendToIdentity)
- std::swap(fromT, toT);
-
- toT.blend(fromT, progress);
- return MatrixTransformOperation::create(toT.a(), toT.b(), toT.c(), toT.d(), toT.e(), toT.f());
-}
-
-} // namespace WebCore
diff --git a/WebCore/rendering/style/MatrixTransformOperation.h b/WebCore/rendering/style/MatrixTransformOperation.h
deleted file mode 100644
index 574f2a8..0000000
--- a/WebCore/rendering/style/MatrixTransformOperation.h
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Copyright (C) 2000 Lars Knoll (knoll@kde.org)
- * (C) 2000 Antti Koivisto (koivisto@kde.org)
- * (C) 2000 Dirk Mueller (mueller@kde.org)
- * Copyright (C) 2003, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
- * Copyright (C) 2006 Graham Dennis (graham.dennis@gmail.com)
- *
- * 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 MatrixTransformOperation_h
-#define MatrixTransformOperation_h
-
-#include "TransformOperation.h"
-
-namespace WebCore {
-
-class MatrixTransformOperation : public TransformOperation {
-public:
- static PassRefPtr<MatrixTransformOperation> create(double a, double b, double c, double d, double e, double f)
- {
- return adoptRef(new MatrixTransformOperation(a, b, c, d, e, f));
- }
-
- virtual bool isIdentity() const { return m_a == 1 && m_b == 0 && m_c == 0 && m_d == 1 && m_e == 0 && m_f == 0; }
- virtual OperationType getOperationType() const { return MATRIX; }
- virtual bool isSameType(const TransformOperation& o) const { return o.getOperationType() == MATRIX; }
-
- virtual bool operator==(const TransformOperation& o) const
- {
- if (!isSameType(o))
- return false;
-
- const MatrixTransformOperation* m = static_cast<const MatrixTransformOperation*>(&o);
- return m_a == m->m_a && m_b == m->m_b && m_c == m->m_c && m_d == m->m_d && m_e == m->m_e && m_f == m->m_f;
- }
-
- virtual bool apply(AffineTransform& transform, const IntSize& borderBoxSize) const
- {
- AffineTransform matrix(m_a, m_b, m_c, m_d, m_e, m_f);
- transform = matrix * transform;
- return false;
- }
-
- virtual PassRefPtr<TransformOperation> blend(const TransformOperation* from, double progress, bool blendToIdentity = false);
-
-private:
- MatrixTransformOperation(double a, double b, double c, double d, double e, double f)
- : m_a(a)
- , m_b(b)
- , m_c(c)
- , m_d(d)
- , m_e(e)
- , m_f(f)
- {
- }
-
- double m_a;
- double m_b;
- double m_c;
- double m_d;
- double m_e;
- double m_f;
-};
-
-} // namespace WebCore
-
-#endif // MatrixTransformOperation_h
diff --git a/WebCore/rendering/style/RenderStyle.cpp b/WebCore/rendering/style/RenderStyle.cpp
index 5088c33..09445b9 100644
--- a/WebCore/rendering/style/RenderStyle.cpp
+++ b/WebCore/rendering/style/RenderStyle.cpp
@@ -29,6 +29,7 @@
#include "RenderArena.h"
#include "RenderObject.h"
#include "StyleImage.h"
+#include <wtf/StdLibExtras.h>
#include <algorithm>
namespace WebCore {
@@ -232,7 +233,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.
@@ -498,7 +499,8 @@ void RenderStyle::setCursorList(PassRefPtr<CursorList> other)
void RenderStyle::clearCursorList()
{
- inherited.access()->cursorData = CursorList::create();
+ if (inherited->cursorData)
+ inherited.access()->cursorData = 0;
}
bool RenderStyle::contentDataEquivalent(const RenderStyle* otherStyle) const
@@ -635,7 +637,7 @@ void RenderStyle::setContent(CounterContent* c, bool add)
newContentData->m_type = CONTENT_COUNTER;
}
-void RenderStyle::applyTransform(AffineTransform& transform, const IntSize& borderBoxSize, bool includeTransformOrigin) const
+void RenderStyle::applyTransform(TransformationMatrix& transform, const IntSize& borderBoxSize, bool includeTransformOrigin) 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
@@ -720,13 +722,13 @@ CounterDirectiveMap& RenderStyle::accessCounterDirectives()
#if ENABLE(DASHBOARD_SUPPORT)
const Vector<StyleDashboardRegion>& RenderStyle::initialDashboardRegions()
{
- static Vector<StyleDashboardRegion> emptyList;
+ DEFINE_STATIC_LOCAL(Vector<StyleDashboardRegion>, emptyList, ());
return emptyList;
}
const Vector<StyleDashboardRegion>& RenderStyle::noneDashboardRegions()
{
- static Vector<StyleDashboardRegion> noneList;
+ DEFINE_STATIC_LOCAL(Vector<StyleDashboardRegion>, noneList, ());
static bool noneListInitialized = false;
if (!noneListInitialized) {
@@ -750,7 +752,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);
@@ -773,7 +775,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);
diff --git a/WebCore/rendering/style/RenderStyle.h b/WebCore/rendering/style/RenderStyle.h
index 084bdc8..fed3057 100644
--- a/WebCore/rendering/style/RenderStyle.h
+++ b/WebCore/rendering/style/RenderStyle.h
@@ -25,7 +25,7 @@
#ifndef RenderStyle_h
#define RenderStyle_h
-#include "AffineTransform.h"
+#include "TransformationMatrix.h"
#include "AnimationList.h"
#include "BorderData.h"
#include "BorderValue.h"
@@ -72,6 +72,7 @@
#include "TransformOperations.h"
#include <wtf/OwnPtr.h>
#include <wtf/RefCounted.h>
+#include <wtf/StdLibExtras.h>
#include <wtf/Vector.h>
#if ENABLE(DASHBOARD_SUPPORT)
@@ -110,8 +111,9 @@ 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,
+ 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 };
static const int FIRST_INTERNAL_PSEUDOID = FILE_UPLOAD_BUTTON;
@@ -139,7 +141,8 @@ protected:
(_box_direction == other._box_direction) &&
(_visuallyOrdered == other._visuallyOrdered) &&
(_htmlHacks == other._htmlHacks) &&
- (_force_backgrounds_to_white == other._force_backgrounds_to_white);
+ (_force_backgrounds_to_white == other._force_backgrounds_to_white) &&
+ (_pointerEvents == other._pointerEvents);
}
bool operator!=(const InheritedFlags& other) const { return !(*this == other); }
@@ -162,6 +165,7 @@ protected:
bool _visuallyOrdered : 1;
bool _htmlHacks :1;
bool _force_backgrounds_to_white : 1;
+ unsigned _pointerEvents : 4; // EPointerEvents
} inherited_flags;
// don't inherit
@@ -268,6 +272,7 @@ protected:
inherited_flags._htmlHacks=false;
inherited_flags._box_direction = initialBoxDirection();
inherited_flags._force_backgrounds_to_white = false;
+ inherited_flags._pointerEvents = initialPointerEvents();
noninherited_flags._effectiveDisplay = noninherited_flags._originalDisplay = initialDisplay();
noninherited_flags._overflowX = initialOverflowX();
@@ -624,11 +629,12 @@ public:
Length transformOriginX() const { return rareNonInheritedData->m_transform->m_x; }
Length transformOriginY() const { return rareNonInheritedData->m_transform->m_y; }
bool hasTransform() const { return !rareNonInheritedData->m_transform->m_operations.operations().isEmpty(); }
- void applyTransform(AffineTransform&, const IntSize& borderBoxSize, bool includeTransformOrigin = true) const;
+ void applyTransform(TransformationMatrix&, const IntSize& borderBoxSize, bool includeTransformOrigin = true) const;
bool hasMask() const { return rareNonInheritedData->m_mask.hasImage() || rareNonInheritedData->m_maskBoxImage.hasImage(); }
// End CSS3 Getters
// Apple-specific property getter methods
+ EPointerEvents pointerEvents() const { return static_cast<EPointerEvents>(inherited_flags._pointerEvents); }
const AnimationList* animations() const { return rareNonInheritedData->m_animations.get(); }
const AnimationList* transitions() const { return rareNonInheritedData->m_transitions.get(); }
@@ -923,6 +929,8 @@ public:
// End CSS3 Setters
// Apple-specific property setters
+ void setPointerEvents(EPointerEvents p) { inherited_flags._pointerEvents = p; }
+
void clearAnimations()
{
rareNonInheritedData.access()->m_animations.clear();
@@ -1107,19 +1115,12 @@ public:
static bool initialVisuallyOrdered() { return false; }
static float initialTextStrokeWidth() { return 0; }
static unsigned short initialColumnCount() { return 1; }
- static const TransformOperations& initialTransform() { static TransformOperations ops; return ops; }
+ 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; }
// Keep these at the end.
- static float initialAnimationDelay() { return 0; }
- static bool initialAnimationDirection() { return false; }
- static double initialAnimationDuration() { return 0; }
- static int initialAnimationIterationCount() { return 1; }
- static String initialAnimationName() { return String(); }
- static unsigned initialAnimationPlayState() { return AnimPlayStatePlaying; }
- static int initialAnimationProperty() { return cAnimateAll; }
- static TimingFunction initialAnimationTimingFunction() { return TimingFunction(); }
static int initialLineClamp() { return -1; }
static bool initialTextSizeAdjust() { return true; }
static ETextSecurity initialTextSecurity() { return TSNONE; }
diff --git a/WebCore/rendering/style/RenderStyleConstants.h b/WebCore/rendering/style/RenderStyleConstants.h
index 37fbc1e..40ad3cc 100644
--- a/WebCore/rendering/style/RenderStyleConstants.h
+++ b/WebCore/rendering/style/RenderStyleConstants.h
@@ -258,6 +258,11 @@ enum EDisplay {
TABLE_CAPTION, BOX, INLINE_BOX, NONE
};
+enum EPointerEvents {
+ PE_NONE, PE_AUTO, PE_STROKE, PE_FILL, PE_PAINTED, PE_VISIBLE,
+ PE_VISIBLE_STROKE, PE_VISIBLE_FILL, PE_VISIBLE_PAINTED, PE_ALL
+};
+
} // namespace WebCore
#endif // RenderStyleConstants_h
diff --git a/WebCore/rendering/style/RotateTransformOperation.cpp b/WebCore/rendering/style/RotateTransformOperation.cpp
deleted file mode 100644
index 4887cee..0000000
--- a/WebCore/rendering/style/RotateTransformOperation.cpp
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (C) 1999 Antti Koivisto (koivisto@kde.org)
- * Copyright (C) 2004, 2005, 2006, 2007, 2008 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 "RotateTransformOperation.h"
-
-namespace WebCore {
-
-PassRefPtr<TransformOperation> RotateTransformOperation::blend(const TransformOperation* from, double progress, bool blendToIdentity)
-{
- if (from && !from->isSameType(*this))
- return this;
-
- if (blendToIdentity)
- return RotateTransformOperation::create(m_angle - m_angle * progress, m_type);
-
- const RotateTransformOperation* fromOp = static_cast<const RotateTransformOperation*>(from);
- double fromAngle = fromOp ? fromOp->m_angle : 0;
- return RotateTransformOperation::create(fromAngle + (m_angle - fromAngle) * progress, m_type);
-}
-
-} // namespace WebCore
diff --git a/WebCore/rendering/style/RotateTransformOperation.h b/WebCore/rendering/style/RotateTransformOperation.h
deleted file mode 100644
index 9cfc9c8..0000000
--- a/WebCore/rendering/style/RotateTransformOperation.h
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright (C) 2000 Lars Knoll (knoll@kde.org)
- * (C) 2000 Antti Koivisto (koivisto@kde.org)
- * (C) 2000 Dirk Mueller (mueller@kde.org)
- * Copyright (C) 2003, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
- * Copyright (C) 2006 Graham Dennis (graham.dennis@gmail.com)
- *
- * 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 RotateTransformOperation_h
-#define RotateTransformOperation_h
-
-#include "TransformOperation.h"
-
-namespace WebCore {
-
-class RotateTransformOperation : public TransformOperation {
-public:
- static PassRefPtr<RotateTransformOperation> create(double angle, OperationType type)
- {
- return adoptRef(new RotateTransformOperation(angle, type));
- }
-
- virtual bool isIdentity() const { return m_angle == 0; }
- virtual OperationType getOperationType() const { return m_type; }
- virtual bool isSameType(const TransformOperation& o) const { return o.getOperationType() == m_type; }
-
- virtual bool operator==(const TransformOperation& o) const
- {
- if (!isSameType(o))
- return false;
- const RotateTransformOperation* r = static_cast<const RotateTransformOperation*>(&o);
- return m_angle == r->m_angle;
- }
-
- virtual bool apply(AffineTransform& transform, const IntSize& borderBoxSize) const
- {
- transform.rotate(m_angle);
- return false;
- }
-
- virtual PassRefPtr<TransformOperation> blend(const TransformOperation* from, double progress, bool blendToIdentity = false);
-
- double angle() const { return m_angle; }
-
-private:
- RotateTransformOperation(double angle, OperationType type)
- : m_angle(angle)
- , m_type(type)
- {
- }
-
- double m_angle;
- OperationType m_type;
-};
-
-} // namespace WebCore
-
-#endif // RotateTransformOperation_h
diff --git a/WebCore/rendering/style/SVGRenderStyle.h b/WebCore/rendering/style/SVGRenderStyle.h
index 5724621..0e9dae4 100644
--- a/WebCore/rendering/style/SVGRenderStyle.h
+++ b/WebCore/rendering/style/SVGRenderStyle.h
@@ -63,7 +63,6 @@ namespace WebCore {
SVG_RS_DEFINE_ATTRIBUTE_INHERITED(WindRule, FillRule, fillRule, RULE_NONZERO)
SVG_RS_DEFINE_ATTRIBUTE_INHERITED(EImageRendering, ImageRendering, imageRendering, IR_AUTO)
SVG_RS_DEFINE_ATTRIBUTE_INHERITED(LineJoin, JoinStyle, joinStyle, MiterJoin)
- SVG_RS_DEFINE_ATTRIBUTE_INHERITED(EPointerEvents, PointerEvents, pointerEvents, PE_VISIBLE_PAINTED)
SVG_RS_DEFINE_ATTRIBUTE_INHERITED(EShapeRendering, ShapeRendering, shapeRendering, SR_AUTO)
SVG_RS_DEFINE_ATTRIBUTE_INHERITED(ETextAnchor, TextAnchor, textAnchor, TA_START)
SVG_RS_DEFINE_ATTRIBUTE_INHERITED(ETextRendering, TextRendering, textRendering, TR_AUTO)
@@ -122,7 +121,6 @@ namespace WebCore {
(_textAnchor == other._textAnchor) &&
(_colorInterpolation == other._colorInterpolation) &&
(_colorInterpolationFilters == other._colorInterpolationFilters) &&
- (_pointerEvents == other._pointerEvents) &&
(_writingMode == other._writingMode) &&
(_glyphOrientationHorizontal == other._glyphOrientationHorizontal) &&
(_glyphOrientationVertical == other._glyphOrientationVertical);
@@ -144,7 +142,6 @@ namespace WebCore {
unsigned _textAnchor : 2; // ETextAnchor
unsigned _colorInterpolation : 2; // EColorInterpolation
unsigned _colorInterpolationFilters : 2; // EColorInterpolation
- unsigned _pointerEvents : 4; // EPointerEvents
unsigned _writingMode : 3; // EWritingMode
unsigned _glyphOrientationHorizontal : 3; // EGlyphOrientation
unsigned _glyphOrientationVertical : 3; // EGlyphOrientation
@@ -199,7 +196,6 @@ namespace WebCore {
svg_inherited_flags._joinStyle = initialJoinStyle();
svg_inherited_flags._colorInterpolation = initialColorInterpolation();
svg_inherited_flags._colorInterpolationFilters = initialColorInterpolationFilters();
- svg_inherited_flags._pointerEvents = initialPointerEvents();
svg_inherited_flags._writingMode = initialWritingMode();
svg_inherited_flags._glyphOrientationHorizontal = initialGlyphOrientationHorizontal();
svg_inherited_flags._glyphOrientationVertical = initialGlyphOrientationVertical();
diff --git a/WebCore/rendering/style/SVGRenderStyleDefs.h b/WebCore/rendering/style/SVGRenderStyleDefs.h
index 12a70d3..cb504d2 100644
--- a/WebCore/rendering/style/SVGRenderStyleDefs.h
+++ b/WebCore/rendering/style/SVGRenderStyleDefs.h
@@ -119,11 +119,6 @@ namespace WebCore {
DB_CENTRAL, DB_MIDDLE, DB_TEXT_AFTER_EDGE, DB_TEXT_BEFORE_EDGE
};
- enum EPointerEvents {
- PE_NONE, PE_STROKE, PE_FILL, PE_PAINTED, PE_VISIBLE,
- PE_VISIBLE_STROKE, PE_VISIBLE_FILL, PE_VISIBLE_PAINTED, PE_ALL
- };
-
class CSSValue;
class CSSValueList;
class SVGPaint;
diff --git a/WebCore/rendering/style/ScaleTransformOperation.cpp b/WebCore/rendering/style/ScaleTransformOperation.cpp
deleted file mode 100644
index 49a8fd8..0000000
--- a/WebCore/rendering/style/ScaleTransformOperation.cpp
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (C) 1999 Antti Koivisto (koivisto@kde.org)
- * Copyright (C) 2004, 2005, 2006, 2007, 2008 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 "ScaleTransformOperation.h"
-
-namespace WebCore {
-
-PassRefPtr<TransformOperation> ScaleTransformOperation::blend(const TransformOperation* from, double progress, bool blendToIdentity)
-{
- if (from && !from->isSameType(*this))
- return this;
-
- if (blendToIdentity)
- return ScaleTransformOperation::create(m_x + (1. - m_x) * progress, m_y + (1. - m_y) * progress, m_type);
-
- const ScaleTransformOperation* fromOp = static_cast<const ScaleTransformOperation*>(from);
- double fromX = fromOp ? fromOp->m_x : 1.;
- double fromY = fromOp ? fromOp->m_y : 1.;
- return ScaleTransformOperation::create(fromX + (m_x - fromX) * progress, fromY + (m_y - fromY) * progress, m_type);
-}
-
-} // namespace WebCore
diff --git a/WebCore/rendering/style/ScaleTransformOperation.h b/WebCore/rendering/style/ScaleTransformOperation.h
deleted file mode 100644
index 787f067..0000000
--- a/WebCore/rendering/style/ScaleTransformOperation.h
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright (C) 2000 Lars Knoll (knoll@kde.org)
- * (C) 2000 Antti Koivisto (koivisto@kde.org)
- * (C) 2000 Dirk Mueller (mueller@kde.org)
- * Copyright (C) 2003, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
- * Copyright (C) 2006 Graham Dennis (graham.dennis@gmail.com)
- *
- * 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 ScaleTransformOperation_h
-#define ScaleTransformOperation_h
-
-#include "TransformOperation.h"
-
-namespace WebCore {
-
-class ScaleTransformOperation : public TransformOperation {
-public:
- static PassRefPtr<ScaleTransformOperation> create(double sx, double sy, OperationType type)
- {
- return adoptRef(new ScaleTransformOperation(sx, sy, type));
- }
-
- virtual bool isIdentity() const { return m_x == 1 && m_y == 1; }
- virtual OperationType getOperationType() const { return m_type; }
- virtual bool isSameType(const TransformOperation& o) const { return o.getOperationType() == m_type; }
-
- virtual bool operator==(const TransformOperation& o) const
- {
- if (!isSameType(o))
- return false;
- const ScaleTransformOperation* s = static_cast<const ScaleTransformOperation*>(&o);
- return m_x == s->m_x && m_y == s->m_y;
- }
-
- virtual bool apply(AffineTransform& transform, const IntSize& borderBoxSize) const
- {
- transform.scale(m_x, m_y);
- return false;
- }
-
- virtual PassRefPtr<TransformOperation> blend(const TransformOperation* from, double progress, bool blendToIdentity = false);
-
-private:
- ScaleTransformOperation(double sx, double sy, OperationType type)
- : m_x(sx)
- , m_y(sy)
- , m_type(type)
- {
- }
-
- double m_x;
- double m_y;
- OperationType m_type;
-};
-
-} // namespace WebCore
-
-#endif // ScaleTransformOperation_h
diff --git a/WebCore/rendering/style/SkewTransformOperation.cpp b/WebCore/rendering/style/SkewTransformOperation.cpp
deleted file mode 100644
index 2a430e9..0000000
--- a/WebCore/rendering/style/SkewTransformOperation.cpp
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (C) 1999 Antti Koivisto (koivisto@kde.org)
- * Copyright (C) 2004, 2005, 2006, 2007, 2008 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 "SkewTransformOperation.h"
-
-namespace WebCore {
-
-PassRefPtr<TransformOperation> SkewTransformOperation::blend(const TransformOperation* from, double progress, bool blendToIdentity)
-{
- if (from && !from->isSameType(*this))
- return this;
-
- if (blendToIdentity)
- return SkewTransformOperation::create(m_angleX - m_angleX * progress, m_angleY - m_angleY * progress, m_type);
-
- const SkewTransformOperation* fromOp = static_cast<const SkewTransformOperation*>(from);
- double fromAngleX = fromOp ? fromOp->m_angleX : 0;
- double fromAngleY = fromOp ? fromOp->m_angleY : 0;
- return SkewTransformOperation::create(fromAngleX + (m_angleX - fromAngleX) * progress, fromAngleY + (m_angleY - fromAngleY) * progress, m_type);
-}
-
-} // namespace WebCore
diff --git a/WebCore/rendering/style/SkewTransformOperation.h b/WebCore/rendering/style/SkewTransformOperation.h
deleted file mode 100644
index a7879e8..0000000
--- a/WebCore/rendering/style/SkewTransformOperation.h
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright (C) 2000 Lars Knoll (knoll@kde.org)
- * (C) 2000 Antti Koivisto (koivisto@kde.org)
- * (C) 2000 Dirk Mueller (mueller@kde.org)
- * Copyright (C) 2003, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
- * Copyright (C) 2006 Graham Dennis (graham.dennis@gmail.com)
- *
- * 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 SkewTransformOperation_h
-#define SkewTransformOperation_h
-
-#include "TransformOperation.h"
-
-namespace WebCore {
-
-class SkewTransformOperation : public TransformOperation {
-public:
- static PassRefPtr<SkewTransformOperation> create(double angleX, double angleY, OperationType type)
- {
- return adoptRef(new SkewTransformOperation(angleX, angleY, type));
- }
-
- virtual bool isIdentity() const { return m_angleX == 0 && m_angleY == 0; }
- virtual OperationType getOperationType() const { return m_type; }
- virtual bool isSameType(const TransformOperation& o) const { return o.getOperationType() == m_type; }
-
- virtual bool operator==(const TransformOperation& o) const
- {
- if (!isSameType(o))
- return false;
- const SkewTransformOperation* s = static_cast<const SkewTransformOperation*>(&o);
- return m_angleX == s->m_angleX && m_angleY == s->m_angleY;
- }
-
- virtual bool apply(AffineTransform& transform, const IntSize& borderBoxSize) const
- {
- transform.skew(m_angleX, m_angleY);
- return false;
- }
-
- virtual PassRefPtr<TransformOperation> blend(const TransformOperation* from, double progress, bool blendToIdentity = false);
-
-private:
- SkewTransformOperation(double angleX, double angleY, OperationType type)
- : m_angleX(angleX)
- , m_angleY(angleY)
- , m_type(type)
- {
- }
-
- double m_angleX;
- double m_angleY;
- OperationType m_type;
-};
-
-} // namespace WebCore
-
-#endif // SkewTransformOperation_h
diff --git a/WebCore/rendering/style/StyleCachedImage.cpp b/WebCore/rendering/style/StyleCachedImage.cpp
index 17ebce9..b55c5b9 100644
--- a/WebCore/rendering/style/StyleCachedImage.cpp
+++ b/WebCore/rendering/style/StyleCachedImage.cpp
@@ -84,7 +84,7 @@ void StyleCachedImage::removeClient(RenderObject* renderer)
return m_image->removeClient(renderer);
}
-Image* StyleCachedImage::image(RenderObject* renderer, const IntSize&) const
+Image* StyleCachedImage::image(RenderObject*, const IntSize&) const
{
return m_image->image();
}
diff --git a/WebCore/rendering/style/StyleImage.h b/WebCore/rendering/style/StyleImage.h
index 4bdba6e..cb90288 100644
--- a/WebCore/rendering/style/StyleImage.h
+++ b/WebCore/rendering/style/StyleImage.h
@@ -48,7 +48,7 @@ public:
virtual PassRefPtr<CSSValue> cssValue() = 0;
- virtual bool canRender(float multiplier) const { return true; }
+ virtual bool canRender(float /*multiplier*/) const { return true; }
virtual bool isLoaded() const { return true; }
virtual bool errorOccurred() const { return false; }
virtual IntSize imageSize(const RenderObject*, float multiplier) const = 0;
diff --git a/WebCore/rendering/style/TimingFunction.h b/WebCore/rendering/style/TimingFunction.h
deleted file mode 100644
index f114596..0000000
--- a/WebCore/rendering/style/TimingFunction.h
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright (C) 2000 Lars Knoll (knoll@kde.org)
- * (C) 2000 Antti Koivisto (koivisto@kde.org)
- * (C) 2000 Dirk Mueller (mueller@kde.org)
- * Copyright (C) 2003, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
- * Copyright (C) 2006 Graham Dennis (graham.dennis@gmail.com)
- *
- * 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 TimingFunction_h
-#define TimingFunction_h
-
-#include "RenderStyleConstants.h"
-
-namespace WebCore {
-
-struct TimingFunction {
- TimingFunction()
- : m_type(CubicBezierTimingFunction)
- , m_x1(0.25)
- , m_y1(0.1)
- , m_x2(0.25)
- , m_y2(1.0)
- {
- }
-
- TimingFunction(ETimingFunctionType timingFunction, double x1 = 0.0, double y1 = 0.0, double x2 = 1.0, double y2 = 1.0)
- : m_type(timingFunction)
- , m_x1(x1)
- , m_y1(y1)
- , m_x2(x2)
- , m_y2(y2)
- {
- }
-
- bool operator==(const TimingFunction& o) const
- {
- return m_type == o.m_type && m_x1 == o.m_x1 && m_y1 == o.m_y1 && m_x2 == o.m_x2 && m_y2 == o.m_y2;
- }
-
- double x1() const { return m_x1; }
- double y1() const { return m_y1; }
- double x2() const { return m_x2; }
- double y2() const { return m_y2; }
-
- ETimingFunctionType type() const { return m_type; }
-
-private:
- ETimingFunctionType m_type;
-
- double m_x1;
- double m_y1;
- double m_x2;
- double m_y2;
-};
-
-} // namespace WebCore
-
-#endif // TimingFunction_h
diff --git a/WebCore/rendering/style/TransformOperation.h b/WebCore/rendering/style/TransformOperation.h
deleted file mode 100644
index 1baa67d..0000000
--- a/WebCore/rendering/style/TransformOperation.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright (C) 2000 Lars Knoll (knoll@kde.org)
- * (C) 2000 Antti Koivisto (koivisto@kde.org)
- * (C) 2000 Dirk Mueller (mueller@kde.org)
- * Copyright (C) 2003, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
- * Copyright (C) 2006 Graham Dennis (graham.dennis@gmail.com)
- *
- * 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 TransformOperation_h
-#define TransformOperation_h
-
-#include "AffineTransform.h"
-#include "IntSize.h"
-#include <wtf/PassRefPtr.h>
-#include <wtf/RefCounted.h>
-
-namespace WebCore {
-
-// CSS Transforms (may become part of CSS3)
-
-class TransformOperation : public RefCounted<TransformOperation> {
-public:
- enum OperationType {
- SCALE_X, SCALE_Y, SCALE,
- TRANSLATE_X, TRANSLATE_Y, TRANSLATE,
- ROTATE,
- SKEW_X, SKEW_Y, SKEW,
- MATRIX, IDENTITY, NONE
- };
-
- virtual ~TransformOperation() { }
-
- virtual bool operator==(const TransformOperation&) const = 0;
- bool operator!=(const TransformOperation& o) const { return !(*this == o); }
-
- virtual bool isIdentity() const = 0;
-
- virtual bool apply(AffineTransform&, const IntSize& borderBoxSize) const = 0;
-
- virtual PassRefPtr<TransformOperation> blend(const TransformOperation* from, double progress, bool blendToIdentity = false) = 0;
-
- virtual OperationType getOperationType() const = 0;
- virtual bool isSameType(const TransformOperation& o) const { return false; }
-};
-
-} // namespace WebCore
-
-#endif // TransformOperation_h
diff --git a/WebCore/rendering/style/TransformOperations.cpp b/WebCore/rendering/style/TransformOperations.cpp
deleted file mode 100644
index 3d71480..0000000
--- a/WebCore/rendering/style/TransformOperations.cpp
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright (C) 1999 Antti Koivisto (koivisto@kde.org)
- * Copyright (C) 2004, 2005, 2006, 2007, 2008 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 "TransformOperations.h"
-
-#include "IdentityTransformOperation.h"
-
-namespace WebCore {
-
-TransformOperations::TransformOperations(bool makeIdentity)
-{
- if (makeIdentity)
- m_operations.append(IdentityTransformOperation::create());
-}
-
-bool TransformOperations::operator==(const TransformOperations& o) const
-{
- if (m_operations.size() != o.m_operations.size())
- return false;
-
- unsigned s = m_operations.size();
- for (unsigned i = 0; i < s; i++) {
- if (*m_operations[i] != *o.m_operations[i])
- return false;
- }
-
- return true;
-}
-
-} // namespace WebCore
diff --git a/WebCore/rendering/style/TransformOperations.h b/WebCore/rendering/style/TransformOperations.h
deleted file mode 100644
index d558a4e..0000000
--- a/WebCore/rendering/style/TransformOperations.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright (C) 2000 Lars Knoll (knoll@kde.org)
- * (C) 2000 Antti Koivisto (koivisto@kde.org)
- * (C) 2000 Dirk Mueller (mueller@kde.org)
- * Copyright (C) 2003, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
- * Copyright (C) 2006 Graham Dennis (graham.dennis@gmail.com)
- *
- * 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 TransformOperations_h
-#define TransformOperations_h
-
-#include "TransformOperation.h"
-#include <wtf/RefPtr.h>
-#include <wtf/Vector.h>
-
-namespace WebCore {
-
-class TransformOperations {
-public:
- TransformOperations(bool makeIdentity = false);
-
- bool operator==(const TransformOperations& o) const;
- bool operator!=(const TransformOperations& o) const
- {
- return !(*this == o);
- }
-
- void apply(const IntSize& sz, AffineTransform& t) const
- {
- for (unsigned i = 0; i < m_operations.size(); ++i)
- m_operations[i]->apply(t, sz);
- }
-
- Vector<RefPtr<TransformOperation> >& operations() { return m_operations; }
- const Vector<RefPtr<TransformOperation> >& operations() const { return m_operations; }
-
-private:
- Vector<RefPtr<TransformOperation> > m_operations;
-};
-
-} // namespace WebCore
-
-#endif // TransformOperations_h
diff --git a/WebCore/rendering/style/TranslateTransformOperation.cpp b/WebCore/rendering/style/TranslateTransformOperation.cpp
deleted file mode 100644
index 47471c4..0000000
--- a/WebCore/rendering/style/TranslateTransformOperation.cpp
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (C) 1999 Antti Koivisto (koivisto@kde.org)
- * Copyright (C) 2004, 2005, 2006, 2007, 2008 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 "TranslateTransformOperation.h"
-
-namespace WebCore {
-
-PassRefPtr<TransformOperation> TranslateTransformOperation::blend(const TransformOperation* from, double progress, bool blendToIdentity)
-{
- if (from && !from->isSameType(*this))
- return this;
-
- if (blendToIdentity)
- return TranslateTransformOperation::create(Length(m_x.type()).blend(m_x, progress), Length(m_y.type()).blend(m_y, progress), m_type);
-
- const TranslateTransformOperation* fromOp = static_cast<const TranslateTransformOperation*>(from);
- Length fromX = fromOp ? fromOp->m_x : Length(m_x.type());
- Length fromY = fromOp ? fromOp->m_y : Length(m_y.type());
- return TranslateTransformOperation::create(m_x.blend(fromX, progress), m_y.blend(fromY, progress), m_type);
-}
-
-} // namespace WebCore
diff --git a/WebCore/rendering/style/TranslateTransformOperation.h b/WebCore/rendering/style/TranslateTransformOperation.h
deleted file mode 100644
index c292ae7..0000000
--- a/WebCore/rendering/style/TranslateTransformOperation.h
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright (C) 2000 Lars Knoll (knoll@kde.org)
- * (C) 2000 Antti Koivisto (koivisto@kde.org)
- * (C) 2000 Dirk Mueller (mueller@kde.org)
- * Copyright (C) 2003, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
- * Copyright (C) 2006 Graham Dennis (graham.dennis@gmail.com)
- *
- * 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 TranslateTransformOperation_h
-#define TranslateTransformOperation_h
-
-#include "Length.h"
-#include "TransformOperation.h"
-
-namespace WebCore {
-
-class TranslateTransformOperation : public TransformOperation {
-public:
- static PassRefPtr<TranslateTransformOperation> create(const Length& tx, const Length& ty, OperationType type)
- {
- return adoptRef(new TranslateTransformOperation(tx, ty, type));
- }
-
- virtual bool isIdentity() const { return m_x.calcFloatValue(1) == 0 && m_y.calcFloatValue(1) == 0; }
- virtual OperationType getOperationType() const { return m_type; }
- virtual bool isSameType(const TransformOperation& o) const { return o.getOperationType() == m_type; }
-
- virtual bool operator==(const TransformOperation& o) const
- {
- if (!isSameType(o))
- return false;
- const TranslateTransformOperation* t = static_cast<const TranslateTransformOperation*>(&o);
- return m_x == t->m_x && m_y == t->m_y;
- }
-
- virtual bool apply(AffineTransform& transform, const IntSize& borderBoxSize) const
- {
- transform.translate(m_x.calcFloatValue(borderBoxSize.width()), m_y.calcFloatValue(borderBoxSize.height()));
- return m_x.type() == Percent || m_y.type() == Percent;
- }
-
- virtual PassRefPtr<TransformOperation> blend(const TransformOperation* from, double progress, bool blendToIdentity = false);
-
-private:
- TranslateTransformOperation(const Length& tx, const Length& ty, OperationType type)
- : m_x(tx)
- , m_y(ty)
- , m_type(type)
- {
- }
-
- Length m_x;
- Length m_y;
- OperationType m_type;
-};
-
-} // namespace WebCore
-
-#endif // TranslateTransformOperation_h