summaryrefslogtreecommitdiffstats
path: root/WebCore/rendering
diff options
context:
space:
mode:
Diffstat (limited to 'WebCore/rendering')
-rw-r--r--WebCore/rendering/AutoTableLayout.cpp14
-rw-r--r--WebCore/rendering/CounterNode.h2
-rw-r--r--WebCore/rendering/FixedTableLayout.cpp5
-rw-r--r--WebCore/rendering/HitTestResult.cpp44
-rw-r--r--WebCore/rendering/HitTestResult.h8
-rw-r--r--WebCore/rendering/InlineBox.cpp38
-rw-r--r--WebCore/rendering/InlineBox.h41
-rw-r--r--WebCore/rendering/InlineFlowBox.cpp131
-rw-r--r--WebCore/rendering/InlineFlowBox.h20
-rw-r--r--WebCore/rendering/InlineTextBox.cpp22
-rw-r--r--WebCore/rendering/LayoutState.h2
-rw-r--r--WebCore/rendering/MediaControlElements.cpp323
-rw-r--r--WebCore/rendering/MediaControlElements.h97
-rw-r--r--WebCore/rendering/RenderApplet.cpp1
-rw-r--r--WebCore/rendering/RenderApplet.h9
-rw-r--r--WebCore/rendering/RenderArena.cpp2
-rw-r--r--WebCore/rendering/RenderBlock.cpp185
-rw-r--r--WebCore/rendering/RenderBlock.h287
-rw-r--r--WebCore/rendering/RenderBlockLineLayout.cpp (renamed from WebCore/rendering/bidi.cpp)337
-rw-r--r--WebCore/rendering/RenderBox.cpp59
-rw-r--r--WebCore/rendering/RenderBox.h20
-rw-r--r--WebCore/rendering/RenderBoxModelObject.cpp255
-rw-r--r--WebCore/rendering/RenderBoxModelObject.h17
-rw-r--r--WebCore/rendering/RenderButton.cpp5
-rw-r--r--WebCore/rendering/RenderButton.h15
-rw-r--r--WebCore/rendering/RenderCounter.cpp4
-rw-r--r--WebCore/rendering/RenderCounter.h21
-rw-r--r--WebCore/rendering/RenderDataGrid.cpp250
-rw-r--r--WebCore/rendering/RenderDataGrid.h84
-rw-r--r--WebCore/rendering/RenderFieldset.cpp17
-rw-r--r--WebCore/rendering/RenderFieldset.h23
-rw-r--r--WebCore/rendering/RenderFileUploadControl.h28
-rw-r--r--WebCore/rendering/RenderFlexibleBox.cpp119
-rw-r--r--WebCore/rendering/RenderFrame.h9
-rw-r--r--WebCore/rendering/RenderFrameSet.cpp13
-rw-r--r--WebCore/rendering/RenderFrameSet.h40
-rw-r--r--WebCore/rendering/RenderHTMLCanvas.h20
-rw-r--r--WebCore/rendering/RenderImage.cpp25
-rw-r--r--WebCore/rendering/RenderImage.h60
-rw-r--r--WebCore/rendering/RenderInline.cpp20
-rw-r--r--WebCore/rendering/RenderInline.h89
-rw-r--r--WebCore/rendering/RenderLayer.cpp251
-rw-r--r--WebCore/rendering/RenderLayer.h46
-rw-r--r--WebCore/rendering/RenderLayerBacking.cpp279
-rw-r--r--WebCore/rendering/RenderLayerBacking.h37
-rw-r--r--WebCore/rendering/RenderLayerCompositor.cpp591
-rw-r--r--WebCore/rendering/RenderLayerCompositor.h64
-rw-r--r--WebCore/rendering/RenderListBox.cpp70
-rw-r--r--WebCore/rendering/RenderListBox.h44
-rw-r--r--WebCore/rendering/RenderListItem.cpp34
-rw-r--r--WebCore/rendering/RenderListItem.h32
-rw-r--r--WebCore/rendering/RenderListMarker.h32
-rw-r--r--WebCore/rendering/RenderMarquee.cpp3
-rw-r--r--WebCore/rendering/RenderMedia.cpp221
-rw-r--r--WebCore/rendering/RenderMedia.h58
-rw-r--r--WebCore/rendering/RenderMediaControls.cpp38
-rw-r--r--WebCore/rendering/RenderMenuList.cpp16
-rw-r--r--WebCore/rendering/RenderMenuList.h31
-rw-r--r--WebCore/rendering/RenderObject.cpp95
-rw-r--r--WebCore/rendering/RenderObject.h18
-rw-r--r--WebCore/rendering/RenderObjectChildList.cpp9
-rw-r--r--WebCore/rendering/RenderPart.cpp16
-rw-r--r--WebCore/rendering/RenderPart.h13
-rw-r--r--WebCore/rendering/RenderPartObject.cpp22
-rw-r--r--WebCore/rendering/RenderPartObject.h11
-rw-r--r--WebCore/rendering/RenderPath.h19
-rw-r--r--WebCore/rendering/RenderReplaced.cpp9
-rw-r--r--WebCore/rendering/RenderReplaced.h41
-rw-r--r--WebCore/rendering/RenderReplica.cpp5
-rw-r--r--WebCore/rendering/RenderSVGBlock.h2
-rw-r--r--WebCore/rendering/RenderSVGContainer.cpp4
-rw-r--r--WebCore/rendering/RenderSVGContainer.h32
-rw-r--r--WebCore/rendering/RenderSVGHiddenContainer.cpp4
-rw-r--r--WebCore/rendering/RenderSVGHiddenContainer.h3
-rw-r--r--WebCore/rendering/RenderSVGImage.cpp18
-rw-r--r--WebCore/rendering/RenderSVGImage.h9
-rw-r--r--WebCore/rendering/RenderSVGInline.cpp4
-rw-r--r--WebCore/rendering/RenderSVGInline.h2
-rw-r--r--WebCore/rendering/RenderSVGInlineText.cpp2
-rw-r--r--WebCore/rendering/RenderSVGInlineText.h3
-rw-r--r--WebCore/rendering/RenderSVGRoot.cpp4
-rw-r--r--WebCore/rendering/RenderSVGRoot.h24
-rw-r--r--WebCore/rendering/RenderSVGText.cpp4
-rw-r--r--WebCore/rendering/RenderSVGText.h4
-rw-r--r--WebCore/rendering/RenderSVGTextPath.h13
-rw-r--r--WebCore/rendering/RenderSVGViewportContainer.cpp25
-rw-r--r--WebCore/rendering/RenderSVGViewportContainer.h25
-rw-r--r--WebCore/rendering/RenderScrollbar.cpp10
-rw-r--r--WebCore/rendering/RenderScrollbar.h38
-rw-r--r--WebCore/rendering/RenderScrollbarTheme.cpp22
-rw-r--r--WebCore/rendering/RenderSlider.cpp135
-rw-r--r--WebCore/rendering/RenderSlider.h13
-rw-r--r--WebCore/rendering/RenderTable.cpp103
-rw-r--r--WebCore/rendering/RenderTable.h76
-rw-r--r--WebCore/rendering/RenderTableCell.cpp20
-rw-r--r--WebCore/rendering/RenderTableCell.h60
-rw-r--r--WebCore/rendering/RenderTableCol.cpp36
-rw-r--r--WebCore/rendering/RenderTableCol.h41
-rw-r--r--WebCore/rendering/RenderTableRow.cpp11
-rw-r--r--WebCore/rendering/RenderTableRow.h29
-rw-r--r--WebCore/rendering/RenderTableSection.cpp16
-rw-r--r--WebCore/rendering/RenderTableSection.h67
-rw-r--r--WebCore/rendering/RenderText.h12
-rw-r--r--WebCore/rendering/RenderTextControl.cpp41
-rw-r--r--WebCore/rendering/RenderTextControl.h43
-rw-r--r--WebCore/rendering/RenderTextControlMultiLine.cpp16
-rw-r--r--WebCore/rendering/RenderTextControlMultiLine.h15
-rw-r--r--WebCore/rendering/RenderTextControlSingleLine.cpp27
-rw-r--r--WebCore/rendering/RenderTextControlSingleLine.h28
-rw-r--r--WebCore/rendering/RenderTheme.cpp28
-rw-r--r--WebCore/rendering/RenderTheme.h36
-rw-r--r--WebCore/rendering/RenderThemeChromiumLinux.cpp564
-rw-r--r--WebCore/rendering/RenderThemeChromiumLinux.h97
-rw-r--r--WebCore/rendering/RenderThemeChromiumMac.h11
-rw-r--r--WebCore/rendering/RenderThemeChromiumMac.mm57
-rw-r--r--WebCore/rendering/RenderThemeChromiumSkia.cpp753
-rw-r--r--WebCore/rendering/RenderThemeChromiumSkia.h150
-rw-r--r--WebCore/rendering/RenderThemeChromiumWin.cpp434
-rw-r--r--WebCore/rendering/RenderThemeChromiumWin.h84
-rw-r--r--WebCore/rendering/RenderThemeMac.h12
-rw-r--r--WebCore/rendering/RenderThemeMac.mm172
-rw-r--r--WebCore/rendering/RenderThemeSafari.cpp53
-rw-r--r--WebCore/rendering/RenderThemeSafari.h9
-rw-r--r--WebCore/rendering/RenderThemeWin.cpp14
-rw-r--r--WebCore/rendering/RenderThemeWin.h7
-rw-r--r--WebCore/rendering/RenderThemeWince.cpp667
-rw-r--r--WebCore/rendering/RenderThemeWince.h147
-rw-r--r--WebCore/rendering/RenderTreeAsText.cpp24
-rw-r--r--WebCore/rendering/RenderVideo.cpp35
-rw-r--r--WebCore/rendering/RenderVideo.h43
-rw-r--r--WebCore/rendering/RenderView.cpp4
-rw-r--r--WebCore/rendering/RenderView.h14
-rw-r--r--WebCore/rendering/RenderWidget.cpp31
-rw-r--r--WebCore/rendering/RenderWidget.h22
-rw-r--r--WebCore/rendering/RootInlineBox.cpp4
-rw-r--r--WebCore/rendering/SVGCharacterLayoutInfo.cpp6
-rw-r--r--WebCore/rendering/SVGCharacterLayoutInfo.h3
-rw-r--r--WebCore/rendering/SVGInlineFlowBox.h2
-rw-r--r--WebCore/rendering/SVGInlineTextBox.h2
-rw-r--r--WebCore/rendering/SVGRenderSupport.cpp8
-rw-r--r--WebCore/rendering/SVGRenderTreeAsText.cpp48
-rw-r--r--WebCore/rendering/SVGRenderTreeAsText.h24
-rw-r--r--WebCore/rendering/SVGRootInlineBox.cpp7
-rw-r--r--WebCore/rendering/SVGRootInlineBox.h2
-rw-r--r--WebCore/rendering/TextControlInnerElements.cpp16
-rw-r--r--WebCore/rendering/TextControlInnerElements.h4
-rw-r--r--WebCore/rendering/TransformState.h2
-rw-r--r--WebCore/rendering/bidi.h65
-rw-r--r--WebCore/rendering/style/FillLayer.h10
-rw-r--r--WebCore/rendering/style/RenderStyle.cpp62
-rw-r--r--WebCore/rendering/style/RenderStyle.h24
-rw-r--r--WebCore/rendering/style/RenderStyleConstants.h14
-rw-r--r--WebCore/rendering/style/SVGRenderStyle.cpp3
-rw-r--r--WebCore/rendering/style/SVGRenderStyleDefs.h4
-rw-r--r--WebCore/rendering/style/ShadowData.cpp6
-rw-r--r--WebCore/rendering/style/ShadowData.h20
-rw-r--r--WebCore/rendering/style/StyleInheritedData.h2
-rw-r--r--WebCore/rendering/style/StyleRareInheritedData.cpp1
158 files changed, 6214 insertions, 3500 deletions
diff --git a/WebCore/rendering/AutoTableLayout.cpp b/WebCore/rendering/AutoTableLayout.cpp
index 43c66cd..c37fba4 100644
--- a/WebCore/rendering/AutoTableLayout.cpp
+++ b/WebCore/rendering/AutoTableLayout.cpp
@@ -59,8 +59,10 @@ void AutoTableLayout::recalcColumn(int effCol)
RenderTableCell* maxContributor = 0;
while (child) {
- if (child->isTableSection()) {
- RenderTableSection* section = static_cast<RenderTableSection*>(child);
+ if (child->isTableCol())
+ toRenderTableCol(child)->calcPrefWidths();
+ else if (child->isTableSection()) {
+ RenderTableSection* section = toRenderTableSection(child);
int numRows = section->numRows();
RenderTableCell* last = 0;
for (int i = 0; i < numRows; i++) {
@@ -92,7 +94,7 @@ void AutoTableLayout::recalcColumn(int effCol)
w.setRawValue(32760);
if (w.isNegative())
w.setValue(0);
- switch(w.type()) {
+ switch (w.type()) {
case Fixed:
// ignore width=0
if (w.value() > 0 && (int)l.width.type() != Percent) {
@@ -167,7 +169,7 @@ void AutoTableLayout::fullRecalc()
int cCol = 0;
while (child) {
if (child->isTableCol()) {
- RenderTableCol *col = static_cast<RenderTableCol*>(child);
+ RenderTableCol *col = toRenderTableCol(child);
int span = col->span();
if (col->firstChild()) {
grpWidth = col->style()->width();
@@ -225,7 +227,7 @@ static bool shouldScaleColumns(RenderTable* table)
if (tw.isPercent())
scale = false;
else {
- RenderTableCell* cell = static_cast<RenderTableCell*>(cb);
+ RenderTableCell* cell = toRenderTableCell(cb);
if (cell->colSpan() > 1 || cell->table()->style()->width().isAuto())
scale = false;
else
@@ -575,7 +577,7 @@ void AutoTableLayout::layout()
int reduction = min(w, excess);
// the lines below might look inconsistent, but that's the way it's handled in mozilla
excess -= reduction;
- int newWidth = max(int (m_layoutStruct[i].effMinWidth), w - reduction);
+ int newWidth = max(static_cast<int>(m_layoutStruct[i].effMinWidth), w - reduction);
available += w - newWidth;
m_layoutStruct[i].calcWidth = newWidth;
}
diff --git a/WebCore/rendering/CounterNode.h b/WebCore/rendering/CounterNode.h
index 57f9563..b432e1d 100644
--- a/WebCore/rendering/CounterNode.h
+++ b/WebCore/rendering/CounterNode.h
@@ -37,7 +37,7 @@ namespace WebCore {
class RenderObject;
-class CounterNode : Noncopyable {
+class CounterNode : public Noncopyable {
public:
CounterNode(RenderObject*, bool isReset, int value);
diff --git a/WebCore/rendering/FixedTableLayout.cpp b/WebCore/rendering/FixedTableLayout.cpp
index f995fbf..ee3e75a 100644
--- a/WebCore/rendering/FixedTableLayout.cpp
+++ b/WebCore/rendering/FixedTableLayout.cpp
@@ -93,7 +93,7 @@ int FixedTableLayout::calcWidthArray(int)
Length grpWidth;
while (child) {
if (child->isTableCol()) {
- RenderTableCol* col = static_cast<RenderTableCol*>(child);
+ RenderTableCol* col = toRenderTableCol(child);
if (col->firstChild())
grpWidth = col->style()->width();
else {
@@ -128,6 +128,7 @@ int FixedTableLayout::calcWidthArray(int)
currentEffectiveColumn++;
}
}
+ toRenderTableCol(child)->calcPrefWidths();
} else
break;
@@ -155,7 +156,7 @@ int FixedTableLayout::calcWidthArray(int)
child = firstRow->firstChild();
while (child) {
if (child->isTableCell()) {
- RenderTableCell* cell = static_cast<RenderTableCell*>(child);
+ RenderTableCell* cell = toRenderTableCell(child);
if (cell->prefWidthsDirty())
cell->calcPrefWidths();
diff --git a/WebCore/rendering/HitTestResult.cpp b/WebCore/rendering/HitTestResult.cpp
index f2ed7db..b7de46b 100644
--- a/WebCore/rendering/HitTestResult.cpp
+++ b/WebCore/rendering/HitTestResult.cpp
@@ -26,6 +26,7 @@
#include "HTMLAnchorElement.h"
#include "HTMLImageElement.h"
#include "HTMLInputElement.h"
+#include "HTMLMediaElement.h"
#include "HTMLNames.h"
#include "RenderImage.h"
#include "Scrollbar.h"
@@ -145,17 +146,20 @@ bool HitTestResult::isSelected() const
return frame->selection()->contains(m_point);
}
-String HitTestResult::spellingToolTip() const
+String HitTestResult::spellingToolTip(TextDirection& dir) const
{
+ dir = LTR;
// Return the tool tip string associated with this point, if any. Only markers associated with bad grammar
// currently supply strings, but maybe someday markers associated with misspelled words will also.
if (!m_innerNonSharedNode)
return String();
- DocumentMarker* marker = m_innerNonSharedNode->document()->markerContainingPoint(m_point, DocumentMarker::Grammar);
+ DocumentMarker* marker = m_innerNonSharedNode->document()->markerContainingPoint(m_point, DocumentMarker::Grammar);
if (!marker)
return String();
+ if (RenderObject* renderer = m_innerNonSharedNode->renderer())
+ dir = renderer->style()->direction();
return marker->description;
}
@@ -173,15 +177,19 @@ String HitTestResult::replacedString() const
return marker->description;
}
-String HitTestResult::title() const
+String HitTestResult::title(TextDirection& dir) const
{
+ dir = LTR;
// Find the title in the nearest enclosing DOM node.
// For <area> tags in image maps, walk the tree for the <area>, not the <img> using it.
for (Node* titleNode = m_innerNode.get(); titleNode; titleNode = titleNode->parentNode()) {
if (titleNode->isElementNode()) {
String title = static_cast<Element*>(titleNode)->title();
- if (!title.isEmpty())
+ if (!title.isEmpty()) {
+ if (RenderObject* renderer = titleNode->renderer())
+ dir = renderer->style()->direction();
return title;
+ }
}
}
return String();
@@ -208,7 +216,7 @@ String HitTestResult::altDisplayString() const
HTMLInputElement* input = static_cast<HTMLInputElement*>(m_innerNonSharedNode.get());
return displayString(input->alt(), m_innerNonSharedNode.get());
}
-
+
#if ENABLE(WML)
if (m_innerNonSharedNode->hasTagName(WMLNames::imgTag)) {
WMLImageElement* image = static_cast<WMLImageElement*>(m_innerNonSharedNode.get());
@@ -266,7 +274,29 @@ KURL HitTestResult::absoluteImageURL() const
} else
return KURL();
- return m_innerNonSharedNode->document()->completeURL(parseURL(urlString));
+ return m_innerNonSharedNode->document()->completeURL(deprecatedParseURL(urlString));
+}
+
+KURL HitTestResult::absoluteMediaURL() const
+{
+#if ENABLE(VIDEO)
+ if (!(m_innerNonSharedNode && m_innerNonSharedNode->document()))
+ return KURL();
+
+ if (!(m_innerNonSharedNode->renderer() && m_innerNonSharedNode->renderer()->isMedia()))
+ return KURL();
+
+ AtomicString urlString;
+ if (m_innerNonSharedNode->hasTagName(HTMLNames::videoTag) || m_innerNonSharedNode->hasTagName(HTMLNames::audioTag)) {
+ HTMLMediaElement* mediaElement = static_cast<HTMLMediaElement*>(m_innerNonSharedNode.get());
+ urlString = mediaElement->currentSrc();
+ } else
+ return KURL();
+
+ return m_innerNonSharedNode->document()->completeURL(deprecatedParseURL(urlString));
+#else
+ return KURL();
+#endif
}
KURL HitTestResult::absoluteLinkURL() const
@@ -288,7 +318,7 @@ KURL HitTestResult::absoluteLinkURL() const
else
return KURL();
- return m_innerURLElement->document()->completeURL(parseURL(urlString));
+ return m_innerURLElement->document()->completeURL(deprecatedParseURL(urlString));
}
bool HitTestResult::isLiveLink() const
diff --git a/WebCore/rendering/HitTestResult.h b/WebCore/rendering/HitTestResult.h
index 4f0383f..f29ca41 100644
--- a/WebCore/rendering/HitTestResult.h
+++ b/WebCore/rendering/HitTestResult.h
@@ -23,6 +23,7 @@
#define HitTestResult_h
#include "IntPoint.h"
+#include "TextDirection.h"
#include <wtf/RefPtr.h>
namespace WebCore {
@@ -30,8 +31,8 @@ namespace WebCore {
class Element;
class Frame;
class Image;
-class KURL;
class IntRect;
+class KURL;
class Node;
class Scrollbar;
class String;
@@ -64,14 +65,15 @@ public:
Frame* targetFrame() const;
IntRect boundingBox() const;
bool isSelected() const;
- String spellingToolTip() const;
+ String spellingToolTip(TextDirection&) const;
String replacedString() const;
- String title() const;
+ String title(TextDirection&) const;
String altDisplayString() const;
String titleDisplayString() const;
Image* image() const;
IntRect imageRect() const;
KURL absoluteImageURL() const;
+ KURL absoluteMediaURL() const;
KURL absoluteLinkURL() const;
String textContent() const;
bool isLiveLink() const;
diff --git a/WebCore/rendering/InlineBox.cpp b/WebCore/rendering/InlineBox.cpp
index 2d956a8..bbf11b3 100644
--- a/WebCore/rendering/InlineBox.cpp
+++ b/WebCore/rendering/InlineBox.cpp
@@ -88,10 +88,10 @@ void InlineBox::showTreeForThis() const
int InlineBox::height() const
{
#if ENABLE(SVG)
- if (isSVG())
- return svgBoxHeight();
+ if (hasVirtualHeight())
+ return virtualHeight();
#endif
-
+
if (renderer()->isText())
return m_isText ? renderer()->style(m_firstLine)->font().height() : 0;
if (renderer()->isBox() && parent())
@@ -244,26 +244,26 @@ bool InlineBox::prevOnLineExists() const
return m_prevOnLineExists;
}
-InlineBox* InlineBox::firstLeafChild()
-{
- return this;
-}
-
-InlineBox* InlineBox::lastLeafChild()
-{
- return this;
-}
-
-InlineBox* InlineBox::nextLeafChild()
+InlineBox* InlineBox::nextLeafChild() const
{
- return parent() ? parent()->firstLeafChildAfterBox(this) : 0;
+ InlineBox* leaf = 0;
+ for (InlineBox* box = nextOnLine(); box && !leaf; box = box->nextOnLine())
+ leaf = box->isLeaf() ? box : static_cast<InlineFlowBox*>(box)->firstLeafChild();
+ if (!leaf && parent())
+ leaf = parent()->nextLeafChild();
+ return leaf;
}
-
-InlineBox* InlineBox::prevLeafChild()
+
+InlineBox* InlineBox::prevLeafChild() const
{
- return parent() ? parent()->lastLeafChildBeforeBox(this) : 0;
+ InlineBox* leaf = 0;
+ for (InlineBox* box = prevOnLine(); box && !leaf; box = box->prevOnLine())
+ leaf = box->isLeaf() ? box : static_cast<InlineFlowBox*>(box)->lastLeafChild();
+ if (!leaf && parent())
+ leaf = parent()->prevLeafChild();
+ return leaf;
}
-
+
RenderObject::SelectionState InlineBox::selectionState()
{
return renderer()->selectionState();
diff --git a/WebCore/rendering/InlineBox.h b/WebCore/rendering/InlineBox.h
index 9585278..c03758d 100644
--- a/WebCore/rendering/InlineBox.h
+++ b/WebCore/rendering/InlineBox.h
@@ -49,7 +49,7 @@ public:
, m_dirty(false)
, m_extracted(false)
#if ENABLE(SVG)
- , m_isSVG(false)
+ , m_hasVirtualHeight(false)
#endif
, m_endsWithBreak(false)
, m_hasSelectedChildren(false)
@@ -82,7 +82,7 @@ public:
, m_dirty(dirty)
, m_extracted(extracted)
#if ENABLE(SVG)
- , m_isSVG(false)
+ , m_hasVirtualHeight(false)
#endif
, m_endsWithBreak(false)
, m_hasSelectedChildren(false)
@@ -129,18 +129,22 @@ public:
#ifndef NDEBUG
void showTreeForThis() const;
#endif
+
+ bool isText() const { return m_isText; }
+ void setIsText(bool b) { m_isText = b; }
+
virtual bool isInlineBox() { return false; }
virtual bool isInlineFlowBox() const { return false; }
virtual bool isInlineTextBox() { return false; }
virtual bool isRootInlineBox() const { return false; }
#if ENABLE(SVG)
virtual bool isSVGRootInlineBox() { return false; }
- bool isSVG() const { return m_isSVG; }
- void setIsSVG(bool b) { m_isSVG = b; }
-#endif
- bool isText() const { return m_isText; }
- void setIsText(bool b) { m_isText = b; }
+ bool hasVirtualHeight() const { return m_hasVirtualHeight; }
+ void setHasVirtualHeight() { m_hasVirtualHeight = true; }
+ virtual int virtualHeight() const { ASSERT_NOT_REACHED(); return 0; }
+#endif
+
bool isConstructed() { return m_constructed; }
virtual void setConstructed()
{
@@ -171,10 +175,10 @@ public:
bool nextOnLineExists() const;
bool prevOnLineExists() const;
- virtual InlineBox* firstLeafChild();
- virtual InlineBox* lastLeafChild();
- InlineBox* nextLeafChild();
- InlineBox* prevLeafChild();
+ virtual bool isLeaf() const { return true; }
+
+ InlineBox* nextLeafChild() const;
+ InlineBox* prevLeafChild() const;
RenderObject* renderer() const { return m_renderer; }
@@ -201,6 +205,9 @@ public:
int height() const;
+ inline int baselinePosition(bool isRootLineBox) const { return renderer()->baselinePosition(m_firstLine, isRootLineBox); }
+ inline int lineHeight(bool isRootLineBox) const { return renderer()->lineHeight(m_firstLine, isRootLineBox); }
+
virtual int topOverflow() const { return y(); }
virtual int bottomOverflow() const { return y() + height(); }
virtual int leftOverflow() const { return x(); }
@@ -239,15 +246,10 @@ public:
RenderBoxModelObject* boxModelObject() const
{
if (!m_renderer->isText())
- return static_cast<RenderBoxModelObject*>(m_renderer);
+ return toRenderBoxModelObject(m_renderer);
return 0;
}
-protected:
-#if ENABLE(SVG)
- virtual int svgBoxHeight() const { return 0; }
-#endif
-
private:
InlineBox* m_next; // The next element on the same line as us.
InlineBox* m_prev; // The previous element on the same line as us.
@@ -272,10 +274,7 @@ private:
protected:
bool m_dirty : 1;
bool m_extracted : 1;
-
-#if ENABLE(SVG)
- bool m_isSVG : 1;
-#endif
+ bool m_hasVirtualHeight : 1;
// for RootInlineBox
bool m_endsWithBreak : 1; // Whether the line ends with a <br>.
diff --git a/WebCore/rendering/InlineFlowBox.cpp b/WebCore/rendering/InlineFlowBox.cpp
index 0432a4c..543c190 100644
--- a/WebCore/rendering/InlineFlowBox.cpp
+++ b/WebCore/rendering/InlineFlowBox.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003, 2004, 2005, 2006, 2007 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
@@ -253,12 +253,10 @@ int InlineFlowBox::placeBoxesHorizontally(int xPos, int& leftPosition, int& righ
// Set our x position.
setX(xPos);
- int boxShadowLeft = 0;
- int boxShadowRight = 0;
- for (ShadowData* boxShadow = renderer()->style(m_firstLine)->boxShadow(); boxShadow; boxShadow = boxShadow->next) {
- boxShadowLeft = min(boxShadow->x - boxShadow->blur, boxShadowLeft);
- boxShadowRight = max(boxShadow->x + boxShadow->blur, boxShadowRight);
- }
+ int boxShadowLeft;
+ int boxShadowRight;
+ renderer()->style(m_firstLine)->getBoxShadowHorizontalExtent(boxShadowLeft, boxShadowRight);
+
leftPosition = min(xPos + boxShadowLeft, leftPosition);
int startX = xPos;
@@ -311,7 +309,7 @@ int InlineFlowBox::placeBoxesHorizontally(int xPos, int& leftPosition, int& righ
xPos += flow->marginLeft();
xPos = flow->placeBoxesHorizontally(xPos, leftPosition, rightPosition, needsWordSpacing);
xPos += flow->marginRight();
- } else if (!curr->renderer()->isListMarker() || static_cast<RenderListMarker*>(curr->renderer())->isInside()) {
+ } else if (!curr->renderer()->isListMarker() || toRenderListMarker(curr->renderer())->isInside()) {
xPos += curr->boxModelObject()->marginLeft();
curr->setX(xPos);
leftPosition = min(xPos + toRenderBox(curr->renderer())->overflowLeft(false), leftPosition);
@@ -371,7 +369,7 @@ void InlineFlowBox::adjustMaxAscentAndDescent(int& maxAscent, int& maxDescent,
if (curr->renderer()->isPositioned())
continue; // Positioned placeholders don't affect calculations.
if (curr->y() == PositionTop || curr->y() == PositionBottom) {
- int lineHeight = curr->renderer()->lineHeight(m_firstLine);
+ int lineHeight = curr->lineHeight(false);
if (curr->y() == PositionTop) {
if (maxAscent + maxDescent < lineHeight)
maxDescent = lineHeight - maxAscent;
@@ -404,11 +402,11 @@ void InlineFlowBox::computeLogicalBoxHeights(int& maxPositionTop, int& maxPositi
{
if (isRootInlineBox()) {
// Examine our root box.
- int lineHeight = renderer()->lineHeight(m_firstLine, true);
- int baseline = renderer()->baselinePosition(m_firstLine, true);
+ int height = lineHeight(true);
+ int baseline = baselinePosition(true);
if (hasTextChildren() || strictMode) {
int ascent = baseline;
- int descent = lineHeight - ascent;
+ int descent = height - ascent;
if (maxAscent < ascent)
maxAscent = ascent;
if (maxDescent < descent)
@@ -456,8 +454,8 @@ void InlineFlowBox::computeLogicalBoxHeights(int& maxPositionTop, int& maxPositi
}
}
} else {
- lineHeight = curr->renderer()->lineHeight(m_firstLine);
- baseline = curr->renderer()->baselinePosition(m_firstLine);
+ lineHeight = curr->lineHeight(false);
+ baseline = curr->baselinePosition(false);
}
curr->setY(verticalPositionForBox(curr, m_firstLine));
@@ -485,8 +483,8 @@ void InlineFlowBox::placeBoxesVertically(int yPos, int maxHeight, int maxAscent,
int& topPosition, int& bottomPosition, int& selectionTop, int& selectionBottom)
{
if (isRootInlineBox())
- setY(yPos + max(0, maxAscent - renderer()->baselinePosition(m_firstLine, true))); // Place our root box.
-
+ setY(yPos + max(0, maxAscent - baselinePosition(true))); // Place our root box.
+
for (InlineBox* curr = firstChild(); curr; curr = curr->nextOnLine()) {
if (curr->renderer()->isPositioned())
continue; // Positioned placeholders don't affect calculations.
@@ -501,11 +499,11 @@ void InlineFlowBox::placeBoxesVertically(int yPos, int maxHeight, int maxAscent,
if (curr->y() == PositionTop)
curr->setY(yPos);
else if (curr->y() == PositionBottom)
- curr->setY(yPos + maxHeight - curr->renderer()->lineHeight(m_firstLine));
+ curr->setY(yPos + maxHeight - curr->lineHeight(false));
else {
if ((isInlineFlow && !static_cast<InlineFlowBox*>(curr)->hasTextChildren()) && !curr->boxModelObject()->hasHorizontalBordersOrPadding() && !strictMode)
childAffectsTopBottomPos = false;
- int posAdjust = maxAscent - curr->renderer()->baselinePosition(m_firstLine);
+ int posAdjust = maxAscent - curr->baselinePosition(false);
if (!childAffectsTopBottomPos)
posAdjust = max(0, posAdjust);
curr->setY(curr->y() + yPos + posAdjust);
@@ -521,16 +519,9 @@ void InlineFlowBox::placeBoxesVertically(int yPos, int maxHeight, int maxAscent,
int overflowBottom = 0;
if (curr->isText() || curr->isInlineFlowBox()) {
const Font& font = curr->renderer()->style(m_firstLine)->font();
- newY += curr->renderer()->baselinePosition(m_firstLine) - font.ascent();
- for (ShadowData* shadow = curr->renderer()->style()->textShadow(); shadow; shadow = shadow->next) {
- overflowTop = min(overflowTop, shadow->y - shadow->blur);
- overflowBottom = max(overflowBottom, shadow->y + shadow->blur);
- }
+ newY += curr->baselinePosition(false) - font.ascent();
- for (ShadowData* boxShadow = curr->renderer()->style(m_firstLine)->boxShadow(); boxShadow; boxShadow = boxShadow->next) {
- overflowTop = min(overflowTop, boxShadow->y - boxShadow->blur);
- overflowBottom = max(overflowBottom, boxShadow->y + boxShadow->blur);
- }
+ curr->renderer()->style(m_firstLine)->getBoxShadowVerticalExtent(overflowTop, overflowBottom);
for (ShadowData* textShadow = curr->renderer()->style(m_firstLine)->textShadow(); textShadow; textShadow = textShadow->next) {
overflowTop = min(overflowTop, textShadow->y - textShadow->blur);
@@ -565,7 +556,7 @@ void InlineFlowBox::placeBoxesVertically(int yPos, int maxHeight, int maxAscent,
if (isRootInlineBox()) {
const Font& font = renderer()->style(m_firstLine)->font();
- setY(y() + renderer()->baselinePosition(m_firstLine, true) - font.ascent());
+ setY(y() + baselinePosition(true) - font.ascent());
if (hasTextChildren() || strictMode) {
selectionTop = min(selectionTop, y());
selectionBottom = max(selectionBottom, y() + height());
@@ -597,16 +588,16 @@ void InlineFlowBox::paint(RenderObject::PaintInfo& paintInfo, int tx, int ty)
{
int xPos = tx + m_x - renderer()->maximalOutlineSize(paintInfo.phase);
int w = width() + 2 * renderer()->maximalOutlineSize(paintInfo.phase);
- int shadowLeft = 0;
- int shadowRight = 0;
- for (ShadowData* boxShadow = renderer()->style(m_firstLine)->boxShadow(); boxShadow; boxShadow = boxShadow->next) {
- shadowLeft = min(boxShadow->x - boxShadow->blur, shadowLeft);
- shadowRight = max(boxShadow->x + boxShadow->blur, shadowRight);
- }
+ int shadowLeft;
+ int shadowRight;
+
+ renderer()->style(m_firstLine)->getBoxShadowHorizontalExtent(shadowLeft, shadowRight);
+
for (ShadowData* textShadow = renderer()->style(m_firstLine)->textShadow(); textShadow; textShadow = textShadow->next) {
shadowLeft = min(textShadow->x - textShadow->blur, shadowLeft);
shadowRight = max(textShadow->x + textShadow->blur, shadowRight);
}
+
xPos += shadowLeft;
w += -shadowLeft + shadowRight;
bool intersectsDamageRect = xPos < paintInfo.rect.right() && xPos + w > paintInfo.rect.x();
@@ -658,22 +649,20 @@ void InlineFlowBox::paint(RenderObject::PaintInfo& paintInfo, int tx, int ty)
paintTextDecorations(paintInfo, tx, ty, true);
}
-void InlineFlowBox::paintFillLayers(const RenderObject::PaintInfo& paintInfo, const Color& c, const FillLayer* fillLayer,
- int my, int mh, int _tx, int _ty, int w, int h, CompositeOperator op)
+void InlineFlowBox::paintFillLayers(const RenderObject::PaintInfo& paintInfo, const Color& c, const FillLayer* fillLayer, int _tx, int _ty, int w, int h, CompositeOperator op)
{
if (!fillLayer)
return;
- paintFillLayers(paintInfo, c, fillLayer->next(), my, mh, _tx, _ty, w, h, op);
- paintFillLayer(paintInfo, c, fillLayer, my, mh, _tx, _ty, w, h, op);
+ paintFillLayers(paintInfo, c, fillLayer->next(), _tx, _ty, w, h, op);
+ paintFillLayer(paintInfo, c, fillLayer, _tx, _ty, w, h, op);
}
-void InlineFlowBox::paintFillLayer(const RenderObject::PaintInfo& paintInfo, const Color& c, const FillLayer* fillLayer,
- int my, int mh, int tx, int ty, int w, int h, CompositeOperator op)
+void InlineFlowBox::paintFillLayer(const RenderObject::PaintInfo& paintInfo, const Color& c, const FillLayer* fillLayer, int tx, int ty, int w, int h, CompositeOperator op)
{
StyleImage* img = fillLayer->image();
bool hasFillImage = img && img->canRender(renderer()->style()->effectiveZoom());
if ((!hasFillImage && !renderer()->style()->hasBorderRadius()) || (!prevLineBox() && !nextLineBox()) || !parent())
- boxModelObject()->paintFillLayerExtended(paintInfo, c, fillLayer, my, mh, tx, ty, w, h, this, op);
+ boxModelObject()->paintFillLayerExtended(paintInfo, c, fillLayer, tx, ty, w, h, this, op);
else {
// We have a fill image that spans multiple lines.
// We need to adjust _tx and _ty by the width of all previous lines.
@@ -692,19 +681,19 @@ void InlineFlowBox::paintFillLayer(const RenderObject::PaintInfo& paintInfo, con
totalWidth += curr->width();
paintInfo.context->save();
paintInfo.context->clip(IntRect(tx, ty, width(), height()));
- boxModelObject()->paintFillLayerExtended(paintInfo, c, fillLayer, my, mh, startX, ty, totalWidth, h, this, op);
+ boxModelObject()->paintFillLayerExtended(paintInfo, c, fillLayer, startX, ty, totalWidth, h, this, op);
paintInfo.context->restore();
}
}
-void InlineFlowBox::paintBoxShadow(GraphicsContext* context, RenderStyle* s, int tx, int ty, int w, int h)
+void InlineFlowBox::paintBoxShadow(GraphicsContext* context, RenderStyle* s, ShadowStyle shadowStyle, int tx, int ty, int w, int h)
{
if ((!prevLineBox() && !nextLineBox()) || !parent())
- boxModelObject()->paintBoxShadow(context, tx, ty, w, h, s);
+ boxModelObject()->paintBoxShadow(context, tx, ty, w, h, s, shadowStyle);
else {
// FIXME: We can do better here in the multi-line case. We want to push a clip so that the shadow doesn't
// protrude incorrectly at the edges, and we want to possibly include shadows cast from the previous/following lines
- boxModelObject()->paintBoxShadow(context, tx, ty, w, h, s, includeLeftEdge(), includeRightEdge());
+ boxModelObject()->paintBoxShadow(context, tx, ty, w, h, s, shadowStyle, includeLeftEdge(), includeRightEdge());
}
}
@@ -720,13 +709,6 @@ void InlineFlowBox::paintBoxDecorations(RenderObject::PaintInfo& paintInfo, int
int w = width();
int h = height();
- int my = max(ty, paintInfo.rect.y());
- int mh;
- if (ty < paintInfo.rect.y())
- mh = max(0, h - (paintInfo.rect.y() - ty));
- else
- mh = min(paintInfo.rect.height(), h);
-
GraphicsContext* context = paintInfo.context;
// You can use p::first-line to specify a background. If so, the root line boxes for
@@ -735,10 +717,13 @@ void InlineFlowBox::paintBoxDecorations(RenderObject::PaintInfo& paintInfo, int
if ((!parent() && m_firstLine && styleToUse != renderer()->style()) || (parent() && renderer()->hasBoxDecorations())) {
// Shadow comes first and is behind the background and border.
if (styleToUse->boxShadow())
- paintBoxShadow(context, styleToUse, tx, ty, w, h);
+ paintBoxShadow(context, styleToUse, Normal, tx, ty, w, h);
Color c = styleToUse->backgroundColor();
- paintFillLayers(paintInfo, c, styleToUse->backgroundLayers(), my, mh, tx, ty, w, h);
+ paintFillLayers(paintInfo, c, styleToUse->backgroundLayers(), tx, ty, w, h);
+
+ if (styleToUse->boxShadow())
+ paintBoxShadow(context, styleToUse, Inset, tx, ty, w, h);
// :first-line cannot be used to put borders on a line. Always paint borders with our
// non-first-line style.
@@ -789,14 +774,6 @@ void InlineFlowBox::paintMask(RenderObject::PaintInfo& paintInfo, int tx, int ty
int w = width();
int h = height();
- int my = max(ty, paintInfo.rect.y());
- int mh;
- if (ty < paintInfo.rect.y())
- mh = max(0, h - (paintInfo.rect.y() - ty));
- else
- mh = min(paintInfo.rect.height(), h);
-
-
// Figure out if we need to push a transparency layer to render our mask.
bool pushTransparencyLayer = false;
const NinePieceImage& maskNinePieceImage = renderer()->style()->maskBoxImage();
@@ -811,7 +788,7 @@ void InlineFlowBox::paintMask(RenderObject::PaintInfo& paintInfo, int tx, int ty
compositeOp = CompositeSourceOver;
}
- paintFillLayers(paintInfo, Color(), renderer()->style()->maskLayers(), my, mh, tx, ty, w, h, compositeOp);
+ paintFillLayers(paintInfo, Color(), renderer()->style()->maskLayers(), tx, ty, w, h, compositeOp);
bool hasBoxImage = maskBoxImage && maskBoxImage->canRender(renderer()->style()->effectiveZoom());
if (!hasBoxImage || !maskBoxImage->isLoaded())
@@ -997,33 +974,19 @@ void InlineFlowBox::paintTextDecorations(RenderObject::PaintInfo& paintInfo, int
}
}
-InlineBox* InlineFlowBox::firstLeafChild()
-{
- return firstLeafChildAfterBox();
-}
-
-InlineBox* InlineFlowBox::lastLeafChild()
-{
- return lastLeafChildBeforeBox();
-}
-
-InlineBox* InlineFlowBox::firstLeafChildAfterBox(InlineBox* start)
+InlineBox* InlineFlowBox::firstLeafChild() const
{
InlineBox* leaf = 0;
- for (InlineBox* box = start ? start->nextOnLine() : firstChild(); box && !leaf; box = box->nextOnLine())
- leaf = box->firstLeafChild();
- if (start && !leaf && parent())
- return parent()->firstLeafChildAfterBox(this);
+ for (InlineBox* child = firstChild(); child && !leaf; child = child->nextOnLine())
+ leaf = child->isLeaf() ? child : static_cast<InlineFlowBox*>(child)->firstLeafChild();
return leaf;
}
-InlineBox* InlineFlowBox::lastLeafChildBeforeBox(InlineBox* start)
+InlineBox* InlineFlowBox::lastLeafChild() const
{
InlineBox* leaf = 0;
- for (InlineBox* box = start ? start->prevOnLine() : lastChild(); box && !leaf; box = box->prevOnLine())
- leaf = box->lastLeafChild();
- if (start && !leaf && parent())
- return parent()->lastLeafChildBeforeBox(this);
+ for (InlineBox* child = lastChild(); child && !leaf; child = child->prevOnLine())
+ leaf = child->isLeaf() ? child : static_cast<InlineFlowBox*>(child)->lastLeafChild();
return leaf;
}
@@ -1054,7 +1017,7 @@ int InlineFlowBox::placeEllipsisBox(bool ltr, int blockLeftEdge, int blockRightE
int visibleLeftEdge = blockLeftEdge;
int visibleRightEdge = blockRightEdge;
- while(box) {
+ while (box) {
int currResult = box->placeEllipsisBox(ltr, visibleLeftEdge, visibleRightEdge, ellipsisWidth, foundBox);
if (currResult != -1 && result == -1)
result = currResult;
diff --git a/WebCore/rendering/InlineFlowBox.h b/WebCore/rendering/InlineFlowBox.h
index 2462eba..809fd54 100644
--- a/WebCore/rendering/InlineFlowBox.h
+++ b/WebCore/rendering/InlineFlowBox.h
@@ -58,13 +58,13 @@ public:
InlineFlowBox* prevFlowBox() const { return static_cast<InlineFlowBox*>(m_prevLine); }
InlineFlowBox* nextFlowBox() const { return static_cast<InlineFlowBox*>(m_nextLine); }
- InlineBox* firstChild() { checkConsistency(); return m_firstChild; }
- InlineBox* lastChild() { checkConsistency(); return m_lastChild; }
+ InlineBox* firstChild() const { checkConsistency(); return m_firstChild; }
+ InlineBox* lastChild() const { checkConsistency(); return m_lastChild; }
- virtual InlineBox* firstLeafChild();
- virtual InlineBox* lastLeafChild();
- InlineBox* firstLeafChildAfterBox(InlineBox* start = 0);
- InlineBox* lastLeafChildBeforeBox(InlineBox* start = 0);
+ virtual bool isLeaf() const { return false; }
+
+ InlineBox* firstLeafChild() const;
+ InlineBox* lastLeafChild() const;
virtual void setConstructed()
{
@@ -87,11 +87,9 @@ public:
virtual void paintBoxDecorations(RenderObject::PaintInfo&, int tx, int ty);
virtual void paintMask(RenderObject::PaintInfo&, int tx, int ty);
- void paintFillLayers(const RenderObject::PaintInfo&, const Color&, const FillLayer*,
- int my, int mh, int tx, int ty, int w, int h, CompositeOperator = CompositeSourceOver);
- void paintFillLayer(const RenderObject::PaintInfo&, const Color&, const FillLayer*,
- int my, int mh, int tx, int ty, int w, int h, CompositeOperator = CompositeSourceOver);
- void paintBoxShadow(GraphicsContext*, RenderStyle*, int tx, int ty, int w, int h);
+ void paintFillLayers(const RenderObject::PaintInfo&, const Color&, const FillLayer*, int tx, int ty, int w, int h, CompositeOperator = CompositeSourceOver);
+ void paintFillLayer(const RenderObject::PaintInfo&, const Color&, const FillLayer*, int tx, int ty, int w, int h, CompositeOperator = CompositeSourceOver);
+ void paintBoxShadow(GraphicsContext*, RenderStyle*, ShadowStyle, int tx, int ty, int w, int h);
virtual void paintTextDecorations(RenderObject::PaintInfo&, int tx, int ty, bool paintedChildren = false);
virtual void paint(RenderObject::PaintInfo&, int tx, int ty);
virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, int x, int y, int tx, int ty);
diff --git a/WebCore/rendering/InlineTextBox.cpp b/WebCore/rendering/InlineTextBox.cpp
index 418be15..619fb95 100644
--- a/WebCore/rendering/InlineTextBox.cpp
+++ b/WebCore/rendering/InlineTextBox.cpp
@@ -256,6 +256,11 @@ bool InlineTextBox::nodeAtPoint(const HitTestRequest&, HitTestResult& result, in
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)
{
+ Color fillColor = context->fillColor();
+ bool opaque = fillColor.alpha() == 255;
+ if (!opaque)
+ context->setFillColor(Color::black);
+
do {
IntSize extraOffset;
@@ -264,7 +269,7 @@ static void paintTextWithShadows(GraphicsContext* context, const Font& font, con
int shadowBlur = shadow->blur;
const Color& shadowColor = shadow->color;
- if (shadow->next || stroked) {
+ if (shadow->next || stroked || !opaque) {
IntRect shadowRect(x, y, w, h);
shadowRect.inflate(shadowBlur);
shadowRect.move(shadowOffset);
@@ -275,7 +280,8 @@ static void paintTextWithShadows(GraphicsContext* context, const Font& font, con
shadowOffset -= extraOffset;
}
context->setShadow(shadowOffset, shadowBlur, shadowColor);
- }
+ } else if (!opaque)
+ context->setFillColor(fillColor);
if (startOffset <= endOffset)
context->drawText(font, textRun, textOrigin + extraOffset, startOffset, endOffset);
@@ -289,13 +295,13 @@ static void paintTextWithShadows(GraphicsContext* context, const Font& font, con
if (!shadow)
break;
- if (shadow->next || stroked)
+ if (shadow->next || stroked || !opaque)
context->restore();
else
context->clearShadow();
shadow = shadow->next;
- } while (shadow || stroked);
+ } while (shadow || stroked || !opaque);
}
void InlineTextBox::paint(RenderObject::PaintInfo& paintInfo, int tx, int ty)
@@ -753,8 +759,8 @@ void InlineTextBox::paintSpellingOrGrammarMarker(GraphicsContext* pt, int tx, in
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.
+ // 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.
int y = selectionTop();
int h = selectionHeight();
@@ -770,8 +776,8 @@ void InlineTextBox::paintTextMatchMarker(GraphicsContext* pt, int tx, int ty, Do
// Optionally highlight the text
if (renderer()->document()->frame()->markedTextMatchesAreHighlighted()) {
Color color = marker.activeMatch ?
- theme()->platformActiveTextSearchHighlightColor() :
- theme()->platformInactiveTextSearchHighlightColor();
+ renderer()->theme()->platformActiveTextSearchHighlightColor() :
+ renderer()->theme()->platformInactiveTextSearchHighlightColor();
pt->save();
updateGraphicsContext(pt, color, color, 0); // Don't draw text at all!
pt->clip(IntRect(tx + m_x, ty + y, m_width, h));
diff --git a/WebCore/rendering/LayoutState.h b/WebCore/rendering/LayoutState.h
index afa2952..2f040c8 100644
--- a/WebCore/rendering/LayoutState.h
+++ b/WebCore/rendering/LayoutState.h
@@ -36,7 +36,7 @@ class RenderArena;
class RenderBox;
class RenderObject;
-class LayoutState : Noncopyable {
+class LayoutState : public Noncopyable {
public:
LayoutState()
: m_clipped(false)
diff --git a/WebCore/rendering/MediaControlElements.cpp b/WebCore/rendering/MediaControlElements.cpp
index 5cd9363..352f270 100644
--- a/WebCore/rendering/MediaControlElements.cpp
+++ b/WebCore/rendering/MediaControlElements.cpp
@@ -32,6 +32,7 @@
#include "MediaControlElements.h"
+#include "LocalizedStrings.h"
#include "EventNames.h"
#include "FloatConversion.h"
#include "Frame.h"
@@ -40,6 +41,7 @@
#include "RenderMedia.h"
#include "RenderSlider.h"
#include "RenderTheme.h"
+#include "CString.h"
namespace WebCore {
@@ -74,50 +76,165 @@ void MediaControlShadowRootElement::updateStyle()
}
// ----------------------------
+
-MediaTextDisplayElement::MediaTextDisplayElement(Document* doc, PseudoId pseudo, HTMLMediaElement* mediaElement)
+MediaControlElement::MediaControlElement(Document* doc, PseudoId pseudo, HTMLMediaElement* mediaElement)
: HTMLDivElement(divTag, doc)
, m_mediaElement(mediaElement)
, m_pseudoStyleId(pseudo)
{
- RenderStyle* style = m_mediaElement->renderer()->getCachedPseudoStyle(m_pseudoStyleId);
- RenderObject* renderer = createRenderer(m_mediaElement->renderer()->renderArena(), style);
- if (renderer) {
- setRenderer(renderer);
- renderer->setStyle(style);
- }
- setAttached();
setInDocument(true);
}
-void MediaTextDisplayElement::attachToParent(Element* parent)
+void MediaControlElement::attachToParent(Element* parent)
{
parent->addChild(this);
- if (renderer())
- parent->renderer()->addChild(renderer());
}
-void MediaTextDisplayElement::update()
+void MediaControlElement::update()
{
if (renderer())
renderer()->updateFromElement();
+ updateStyle();
+}
+
+PassRefPtr<RenderStyle> MediaControlElement::styleForElement()
+{
+ RenderStyle* style = m_mediaElement->renderer()->getCachedPseudoStyle(m_pseudoStyleId);
+ if (!style)
+ return 0;
+
+ // text-decoration can't be overrided from CSS. So we do it here.
+ // See https://bugs.webkit.org/show_bug.cgi?id=27015
+ style->setTextDecoration(TDNONE);
+ style->setTextDecorationsInEffect(TDNONE);
+
+ return style;
}
-void MediaTextDisplayElement::updateStyle()
+bool MediaControlElement::rendererIsNeeded(RenderStyle* style)
{
- if (renderer() && m_mediaElement->renderer()) {
- RenderStyle* style = m_mediaElement->renderer()->getCachedPseudoStyle(m_pseudoStyleId);
- renderer()->setStyle(style);
+ return HTMLDivElement::rendererIsNeeded(style) && parent() && parent()->renderer();
+}
+
+void MediaControlElement::attach()
+{
+ RefPtr<RenderStyle> style = styleForElement();
+ if (!style)
+ return;
+ bool needsRenderer = rendererIsNeeded(style.get());
+ if (!needsRenderer)
+ return;
+ RenderObject* renderer = createRenderer(m_mediaElement->renderer()->renderArena(), style.get());
+ if (!renderer)
+ return;
+ renderer->setStyle(style.get());
+ setRenderer(renderer);
+ if (parent() && parent()->renderer()) {
+ // Find next sibling with a renderer to determine where to insert.
+ Node* sibling = nextSibling();
+ while (sibling && !sibling->renderer())
+ sibling = sibling->nextSibling();
+ parent()->renderer()->addChild(renderer, sibling ? sibling->renderer() : 0);
}
+ ContainerNode::attach();
}
-MediaTimeDisplayElement::MediaTimeDisplayElement(Document* doc, HTMLMediaElement* element, bool currentTime)
- : MediaTextDisplayElement(doc, currentTime ? MEDIA_CONTROLS_CURRENT_TIME_DISPLAY : MEDIA_CONTROLS_TIME_REMAINING_DISPLAY, element)
+void MediaControlElement::updateStyle()
{
+ if (!m_mediaElement || !m_mediaElement->renderer())
+ return;
+
+ RefPtr<RenderStyle> style = styleForElement();
+ if (!style)
+ return;
+
+ bool needsRenderer = rendererIsNeeded(style.get()) && parent() && parent()->renderer();
+ if (renderer() && !needsRenderer)
+ detach();
+ else if (!renderer() && needsRenderer)
+ attach();
+ else if (renderer()) {
+ renderer()->setStyle(style.get());
+
+ // Make sure that if there is any innerText renderer, it is updated as well.
+ if (firstChild() && firstChild()->renderer())
+ firstChild()->renderer()->setStyle(style.get());
+ }
}
// ----------------------------
+MediaControlTimelineContainerElement::MediaControlTimelineContainerElement(Document* doc, HTMLMediaElement* element)
+: MediaControlElement(doc, MEDIA_CONTROLS_TIMELINE_CONTAINER, element)
+{
+}
+
+bool MediaControlTimelineContainerElement::rendererIsNeeded(RenderStyle* style)
+{
+ if (!MediaControlElement::rendererIsNeeded(style))
+ return false;
+
+ // This is for MediaControllerThemeClassic:
+ // If there is no style for MediaControlStatusDisplayElement style, don't hide
+ // the timeline.
+ if (!m_mediaElement->renderer()->getCachedPseudoStyle(MEDIA_CONTROLS_STATUS_DISPLAY))
+ return true;
+
+ float duration = m_mediaElement->duration();
+ return !isnan(duration) && !isinf(duration);
+}
+
+
+// ----------------------------
+
+MediaControlStatusDisplayElement::MediaControlStatusDisplayElement(Document* doc, HTMLMediaElement* element)
+: MediaControlElement(doc, MEDIA_CONTROLS_STATUS_DISPLAY, element)
+, m_stateBeingDisplayed(Nothing)
+{
+}
+
+void MediaControlStatusDisplayElement::update()
+{
+ MediaControlElement::update();
+
+ // Get the new state that we'll have to display.
+ StateBeingDisplayed newStateToDisplay = Nothing;
+
+ if (m_mediaElement->readyState() != HTMLMediaElement::HAVE_ENOUGH_DATA && !m_mediaElement->currentSrc().isEmpty())
+ newStateToDisplay = Loading;
+ else if (m_mediaElement->movieLoadType() == MediaPlayer::LiveStream)
+ newStateToDisplay = LiveBroadcast;
+
+ // Propagate only if needed.
+ if (newStateToDisplay == m_stateBeingDisplayed)
+ return;
+ m_stateBeingDisplayed = newStateToDisplay;
+
+ ExceptionCode e;
+ switch (m_stateBeingDisplayed) {
+ case Nothing:
+ setInnerText("", e);
+ break;
+ case Loading:
+ setInnerText(mediaElementLoadingStateText(), e);
+ break;
+ case LiveBroadcast:
+ setInnerText(mediaElementLiveBroadcastStateText(), e);
+ break;
+ }
+}
+
+bool MediaControlStatusDisplayElement::rendererIsNeeded(RenderStyle* style)
+{
+ if (!MediaControlElement::rendererIsNeeded(style))
+ return false;
+ float duration = m_mediaElement->duration();
+ return (isnan(duration) || isinf(duration));
+}
+
+// ----------------------------
+
MediaControlInputElement::MediaControlInputElement(Document* doc, PseudoId pseudo, const String& type, HTMLMediaElement* mediaElement, MediaControlElementType displayType)
: HTMLInputElement(inputTag, doc)
, m_mediaElement(mediaElement)
@@ -125,20 +242,12 @@ MediaControlInputElement::MediaControlInputElement(Document* doc, PseudoId pseud
, m_displayType(displayType)
{
setInputType(type);
- RenderStyle* style = m_mediaElement->renderer()->getCachedPseudoStyle(m_pseudoStyleId);
- RenderObject* renderer = createRenderer(m_mediaElement->renderer()->renderArena(), style);
- if (renderer) {
- setRenderer(renderer);
- renderer->setStyle(style);
- }
- setAttached();
setInDocument(true);
}
void MediaControlInputElement::attachToParent(Element* parent)
{
parent->addChild(this);
- parent->renderer()->addChild(renderer());
}
void MediaControlInputElement::update()
@@ -146,20 +255,65 @@ void MediaControlInputElement::update()
updateDisplayType();
if (renderer())
renderer()->updateFromElement();
+ updateStyle();
}
-void MediaControlInputElement::updateStyle()
+PassRefPtr<RenderStyle> MediaControlInputElement::styleForElement()
{
- if (renderer() && m_mediaElement->renderer()) {
- RenderStyle* style = m_mediaElement->renderer()->getCachedPseudoStyle(m_pseudoStyleId);
- renderer()->setStyle(style);
- }
+ return m_mediaElement->renderer()->getCachedPseudoStyle(m_pseudoStyleId);
+}
+
+bool MediaControlInputElement::rendererIsNeeded(RenderStyle* style)
+{
+ return HTMLInputElement::rendererIsNeeded(style) && parent() && parent()->renderer();
}
+void MediaControlInputElement::attach()
+{
+ RefPtr<RenderStyle> style = styleForElement();
+ if (!style)
+ return;
+
+ bool needsRenderer = rendererIsNeeded(style.get());
+ if (!needsRenderer)
+ return;
+ RenderObject* renderer = createRenderer(m_mediaElement->renderer()->renderArena(), style.get());
+ if (!renderer)
+ return;
+ renderer->setStyle(style.get());
+ setRenderer(renderer);
+ if (parent() && parent()->renderer()) {
+ // Find next sibling with a renderer to determine where to insert.
+ Node* sibling = nextSibling();
+ while (sibling && !sibling->renderer())
+ sibling = sibling->nextSibling();
+ parent()->renderer()->addChild(renderer, sibling ? sibling->renderer() : 0);
+ }
+ ContainerNode::attach();
+}
+
+void MediaControlInputElement::updateStyle()
+{
+ if (!m_mediaElement || !m_mediaElement->renderer())
+ return;
+
+ RefPtr<RenderStyle> style = styleForElement();
+ if (!style)
+ return;
+
+ bool needsRenderer = rendererIsNeeded(style.get()) && parent() && parent()->renderer();
+ if (renderer() && !needsRenderer)
+ detach();
+ else if (!renderer() && needsRenderer)
+ attach();
+ else if (renderer())
+ renderer()->setStyle(style.get());
+}
+
bool MediaControlInputElement::hitTest(const IntPoint& absPoint)
{
if (renderer() && renderer()->style()->hasAppearance())
- return theme()->hitTestMediaControlPart(renderer(), absPoint);
+ return renderer()->theme()->hitTestMediaControlPart(renderer(), absPoint);
return false;
}
@@ -266,6 +420,59 @@ void MediaControlSeekButtonElement::seekTimerFired(Timer<MediaControlSeekButtonE
m_mediaElement->setCurrentTime(m_mediaElement->currentTime() + seekTime, ec);
}
+void MediaControlSeekButtonElement::detach()
+{
+ if (m_capturing) {
+ if (Frame* frame = document()->frame())
+ frame->eventHandler()->setCapturingMouseEventsNode(0);
+ }
+ MediaControlInputElement::detach();
+}
+
+
+// ----------------------------
+
+MediaControlRewindButtonElement::MediaControlRewindButtonElement(Document* doc, HTMLMediaElement* element)
+: MediaControlInputElement(doc, MEDIA_CONTROLS_REWIND_BUTTON, "button", element, MediaRewindButton)
+{
+}
+
+void MediaControlRewindButtonElement::defaultEventHandler(Event* event)
+{
+ if (event->type() == eventNames().clickEvent) {
+ m_mediaElement->rewind(30);
+ event->setDefaultHandled();
+ }
+ HTMLInputElement::defaultEventHandler(event);
+}
+
+bool MediaControlRewindButtonElement::rendererIsNeeded(RenderStyle* style)
+{
+ return MediaControlInputElement::rendererIsNeeded(style) && m_mediaElement->movieLoadType() != MediaPlayer::LiveStream;
+}
+
+
+// ----------------------------
+
+MediaControlReturnToRealtimeButtonElement::MediaControlReturnToRealtimeButtonElement(Document* doc, HTMLMediaElement* element)
+: MediaControlInputElement(doc, MEDIA_CONTROLS_RETURN_TO_REALTIME_BUTTON, "button", element, MediaReturnToRealtimeButton)
+{
+}
+
+void MediaControlReturnToRealtimeButtonElement::defaultEventHandler(Event* event)
+{
+ if (event->type() == eventNames().clickEvent) {
+ m_mediaElement->returnToRealtime();
+ event->setDefaultHandled();
+ }
+ HTMLInputElement::defaultEventHandler(event);
+}
+
+bool MediaControlReturnToRealtimeButtonElement::rendererIsNeeded(RenderStyle* style)
+{
+ return MediaControlInputElement::rendererIsNeeded(style) && m_mediaElement->movieLoadType() == MediaPlayer::LiveStream;
+}
+
// ----------------------------
MediaControlTimelineElement::MediaControlTimelineElement(Document* document, HTMLMediaElement* element)
@@ -275,14 +482,17 @@ MediaControlTimelineElement::MediaControlTimelineElement(Document* document, HTM
void MediaControlTimelineElement::defaultEventHandler(Event* event)
{
+ // Left button is 0. Accepts only if mouse event is from left button.
+ if (!event->isMouseEvent() || static_cast<MouseEvent*>(event)->button())
+ return;
+
if (event->type() == eventNames().mousedownEvent)
m_mediaElement->beginScrubbing();
- HTMLInputElement::defaultEventHandler(event);
+ MediaControlInputElement::defaultEventHandler(event);
- if (event->type() == eventNames().mouseoverEvent || event->type() == eventNames().mouseoutEvent || event->type() == eventNames().mousemoveEvent ) {
+ if (event->type() == eventNames().mouseoverEvent || event->type() == eventNames().mouseoutEvent || event->type() == eventNames().mousemoveEvent)
return;
- }
float time = narrowPrecisionToFloat(value().toDouble());
if (time != m_mediaElement->currentTime()) {
@@ -290,9 +500,9 @@ void MediaControlTimelineElement::defaultEventHandler(Event* event)
m_mediaElement->setCurrentTime(time, ec);
}
- RenderSlider* slider = static_cast<RenderSlider*>(renderer());
+ RenderSlider* slider = toRenderSlider(renderer());
if (slider && slider->inDragMode())
- static_cast<RenderMedia*>(m_mediaElement->renderer())->updateTimeDisplay();
+ toRenderMedia(m_mediaElement->renderer())->updateTimeDisplay();
if (event->type() == eventNames().mouseupEvent)
m_mediaElement->endScrubbing();
@@ -305,6 +515,7 @@ void MediaControlTimelineElement::update(bool updateDuration)
setAttribute(maxAttr, String::number(isfinite(dur) ? dur : 0));
}
setValue(String::number(m_mediaElement->currentTime()));
+ MediaControlInputElement::update();
}
// ----------------------------
@@ -322,7 +533,45 @@ void MediaControlFullscreenButtonElement::defaultEventHandler(Event* event)
HTMLInputElement::defaultEventHandler(event);
}
+bool MediaControlFullscreenButtonElement::rendererIsNeeded(RenderStyle* style)
+{
+ return MediaControlInputElement::rendererIsNeeded(style) && m_mediaElement->supportsFullscreen();
+}
+
+
// ----------------------------
+MediaControlTimeDisplayElement::MediaControlTimeDisplayElement(Document* doc, PseudoId pseudo, HTMLMediaElement* element)
+ : MediaControlElement(doc, pseudo, element)
+ , m_isVisible(true)
+{
+}
+
+PassRefPtr<RenderStyle> MediaControlTimeDisplayElement::styleForElement()
+{
+ RefPtr<RenderStyle> style = MediaControlElement::styleForElement();
+ if (!m_isVisible) {
+ style = RenderStyle::clone(style.get());
+ style->setWidth(Length(0, Fixed));
+ }
+ return style;
+}
+
+void MediaControlTimeDisplayElement::setVisible(bool visible)
+{
+ if (visible == m_isVisible)
+ return;
+ m_isVisible = visible;
+
+ // This function is used during the RenderMedia::layout()
+ // call, where we cannot change the renderer at this time.
+ if (!renderer() || !renderer()->style())
+ return;
+
+ RefPtr<RenderStyle> style = styleForElement();
+ renderer()->setStyle(style.get());
+}
+
+
} //namespace WebCore
#endif // enable(video)
diff --git a/WebCore/rendering/MediaControlElements.h b/WebCore/rendering/MediaControlElements.h
index d52d4bc..d5fa5d2 100644
--- a/WebCore/rendering/MediaControlElements.h
+++ b/WebCore/rendering/MediaControlElements.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2008, 2009 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -43,11 +43,24 @@ namespace WebCore {
class Event;
class Frame;
+// Must match WebKitSystemInterface.h
enum MediaControlElementType {
- MediaFullscreenButton, MediaMuteButton, MediaPlayButton,
- MediaSeekBackButton, MediaSeekForwardButton, MediaSlider, MediaSliderThumb,
- MediaUnMuteButton, MediaPauseButton, MediaTimelineContainer, MediaCurrentTimeDisplay,
- MediaTimeRemainingDisplay, MediaControlsPanel
+ MediaFullscreenButton = 0,
+ MediaMuteButton,
+ MediaPlayButton,
+ MediaSeekBackButton,
+ MediaSeekForwardButton,
+ MediaSlider,
+ MediaSliderThumb,
+ MediaRewindButton,
+ MediaReturnToRealtimeButton,
+ MediaUnMuteButton,
+ MediaPauseButton,
+ MediaTimelineContainer,
+ MediaCurrentTimeDisplay,
+ MediaTimeRemainingDisplay,
+ MediaStatusDisplay,
+ MediaControlsPanel
};
class MediaControlShadowRootElement : public HTMLDivElement {
@@ -63,15 +76,19 @@ private:
HTMLMediaElement* m_mediaElement;
};
- // ----------------------------
-
-class MediaTextDisplayElement : public HTMLDivElement
-{
+// ----------------------------
+
+class MediaControlElement : public HTMLDivElement {
public:
- MediaTextDisplayElement(Document*, PseudoId, HTMLMediaElement*);
+ MediaControlElement(Document*, PseudoId, HTMLMediaElement*);
+ virtual void attach();
+ virtual bool rendererIsNeeded(RenderStyle*);
+
+ virtual PassRefPtr<RenderStyle> styleForElement();
void attachToParent(Element*);
void update();
- void updateStyle();
+ virtual void updateStyle();
+
protected:
HTMLMediaElement* m_mediaElement;
PseudoId m_pseudoStyleId;
@@ -79,9 +96,22 @@ protected:
// ----------------------------
-class MediaTimeDisplayElement : public MediaTextDisplayElement {
+class MediaControlTimelineContainerElement : public MediaControlElement {
public:
- MediaTimeDisplayElement(Document*, HTMLMediaElement*, bool currentTime);
+ MediaControlTimelineContainerElement(Document*, HTMLMediaElement*);
+ virtual bool rendererIsNeeded(RenderStyle*);
+};
+
+// ----------------------------
+
+class MediaControlStatusDisplayElement : public MediaControlElement {
+public:
+ MediaControlStatusDisplayElement(Document*, HTMLMediaElement*);
+ virtual void update();
+ virtual bool rendererIsNeeded(RenderStyle*);
+private:
+ enum StateBeingDisplayed { Nothing, Loading, LiveBroadcast };
+ StateBeingDisplayed m_stateBeingDisplayed;
};
// ----------------------------
@@ -89,10 +119,16 @@ public:
class MediaControlInputElement : public HTMLInputElement {
public:
MediaControlInputElement(Document*, PseudoId, const String& type, HTMLMediaElement*, MediaControlElementType);
+ virtual void attach();
+ virtual bool rendererIsNeeded(RenderStyle*);
+
+ virtual PassRefPtr<RenderStyle> styleForElement();
void attachToParent(Element*);
void update();
void updateStyle();
+
bool hitTest(const IntPoint& absPoint);
+ MediaControlElementType displayType() const { return m_displayType; }
protected:
virtual void updateDisplayType() { }
@@ -127,6 +163,7 @@ class MediaControlSeekButtonElement : public MediaControlInputElement {
public:
MediaControlSeekButtonElement(Document*, HTMLMediaElement*, bool forward);
virtual void defaultEventHandler(Event*);
+ virtual void detach();
void seekTimerFired(Timer<MediaControlSeekButtonElement>*);
private:
@@ -135,6 +172,24 @@ private:
bool m_capturing;
Timer<MediaControlSeekButtonElement> m_seekTimer;
};
+
+// ----------------------------
+
+class MediaControlRewindButtonElement : public MediaControlInputElement {
+public:
+ MediaControlRewindButtonElement(Document*, HTMLMediaElement*);
+ virtual void defaultEventHandler(Event*);
+ virtual bool rendererIsNeeded(RenderStyle*);
+};
+
+// ----------------------------
+
+class MediaControlReturnToRealtimeButtonElement : public MediaControlInputElement {
+public:
+ MediaControlReturnToRealtimeButtonElement(Document*, HTMLMediaElement*);
+ virtual void defaultEventHandler(Event*);
+ virtual bool rendererIsNeeded(RenderStyle*);
+};
// ----------------------------
@@ -151,6 +206,19 @@ class MediaControlFullscreenButtonElement : public MediaControlInputElement {
public:
MediaControlFullscreenButtonElement(Document*, HTMLMediaElement*);
virtual void defaultEventHandler(Event*);
+ virtual bool rendererIsNeeded(RenderStyle*);
+};
+
+// ----------------------------
+
+class MediaControlTimeDisplayElement : public MediaControlElement {
+public:
+ MediaControlTimeDisplayElement(Document*, PseudoId, HTMLMediaElement*);
+ void setVisible(bool);
+ virtual PassRefPtr<RenderStyle> styleForElement();
+
+private:
+ bool m_isVisible;
};
// ----------------------------
@@ -160,9 +228,10 @@ public:
RenderMediaControlShadowRoot(Element* e) : RenderBlock(e) { }
void setParent(RenderObject* p) { RenderObject::setParent(p); }
};
-
+
// ----------------------------
+
} //namespace WebCore
#endif // enable(video)
#endif // MediaControlElements_h
diff --git a/WebCore/rendering/RenderApplet.cpp b/WebCore/rendering/RenderApplet.cpp
index a989d6f..062641e 100644
--- a/WebCore/rendering/RenderApplet.cpp
+++ b/WebCore/rendering/RenderApplet.cpp
@@ -26,6 +26,7 @@
#include "HTMLAppletElement.h"
#include "HTMLNames.h"
#include "HTMLParamElement.h"
+#include "Widget.h"
namespace WebCore {
diff --git a/WebCore/rendering/RenderApplet.h b/WebCore/rendering/RenderApplet.h
index b481d87..343421e 100644
--- a/WebCore/rendering/RenderApplet.h
+++ b/WebCore/rendering/RenderApplet.h
@@ -46,6 +46,15 @@ namespace WebCore {
HashMap<String, String> m_args;
};
+ inline RenderApplet* toRenderApplet(RenderObject* object)
+ {
+ ASSERT(!object || object->isApplet());
+ return static_cast<RenderApplet*>(object);
+ }
+
+ // This will catch anyone doing an unnecessary cast.
+ void toRenderApplet(const RenderApplet*);
+
} // namespace WebCore
#endif // RenderApplet_h
diff --git a/WebCore/rendering/RenderArena.cpp b/WebCore/rendering/RenderArena.cpp
index c490d2b..3ab4dff 100644
--- a/WebCore/rendering/RenderArena.cpp
+++ b/WebCore/rendering/RenderArena.cpp
@@ -39,7 +39,7 @@
#include <string.h>
#include <wtf/Assertions.h>
-#define ROUNDUP(x,y) ((((x)+((y)-1))/(y))*(y))
+#define ROUNDUP(x, y) ((((x)+((y)-1))/(y))*(y))
namespace WebCore {
diff --git a/WebCore/rendering/RenderBlock.cpp b/WebCore/rendering/RenderBlock.cpp
index ded093f..e10c331 100644
--- a/WebCore/rendering/RenderBlock.cpp
+++ b/WebCore/rendering/RenderBlock.cpp
@@ -88,6 +88,10 @@ static PercentHeightContainerMap* gPercentHeightContainerMap = 0;
typedef WTF::HashMap<RenderBlock*, ListHashSet<RenderInline*>*> ContinuationOutlineTableMap;
+typedef WTF::HashSet<RenderBlock*> DelayedUpdateScrollInfoSet;
+static int gDelayUpdateScrollInfo = 0;
+static DelayedUpdateScrollInfoSet* gDelayedUpdateScrollInfoSet = 0;
+
// Our MarginInfo state used when laying out block children.
RenderBlock::MarginInfo::MarginInfo(RenderBlock* block, int top, int bottom)
{
@@ -393,14 +397,14 @@ void RenderBlock::deleteLineBoxTree()
m_lineBoxes.deleteLineBoxTree(renderArena());
}
-RootInlineBox* RenderBlock::createRootBox()
+RootInlineBox* RenderBlock::createRootInlineBox()
{
return new (renderArena()) RootInlineBox(this);
}
-RootInlineBox* RenderBlock::createRootInlineBox()
+RootInlineBox* RenderBlock::createAndAppendRootInlineBox()
{
- RootInlineBox* rootBox = createRootBox();
+ RootInlineBox* rootBox = createRootInlineBox();
m_lineBoxes.appendLineBox(rootBox);
return rootBox;
}
@@ -553,10 +557,11 @@ void RenderBlock::removeChild(RenderObject* oldChild)
int RenderBlock::overflowHeight(bool includeInterior) const
{
if (!includeInterior && hasOverflowClip()) {
- int shadowHeight = 0;
- for (ShadowData* boxShadow = style()->boxShadow(); boxShadow; boxShadow = boxShadow->next)
- shadowHeight = max(boxShadow->y + boxShadow->blur, shadowHeight);
- int inflatedHeight = height() + shadowHeight;
+ int shadowTop;
+ int shadowBottom;
+ style()->getBoxShadowVerticalExtent(shadowTop, shadowBottom);
+
+ int inflatedHeight = height() + shadowBottom;
if (hasReflection())
inflatedHeight = max(inflatedHeight, reflectionBox().bottom());
return inflatedHeight;
@@ -567,10 +572,11 @@ int RenderBlock::overflowHeight(bool includeInterior) const
int RenderBlock::overflowWidth(bool includeInterior) const
{
if (!includeInterior && hasOverflowClip()) {
- int shadowWidth = 0;
- for (ShadowData* boxShadow = style()->boxShadow(); boxShadow; boxShadow = boxShadow->next)
- shadowWidth = max(boxShadow->x + boxShadow->blur, shadowWidth);
- int inflatedWidth = width() + shadowWidth;
+ int shadowLeft;
+ int shadowRight;
+ style()->getBoxShadowHorizontalExtent(shadowLeft, shadowRight);
+
+ int inflatedWidth = width() + shadowRight;
if (hasReflection())
inflatedWidth = max(inflatedWidth, reflectionBox().right());
return inflatedWidth;
@@ -581,9 +587,10 @@ int RenderBlock::overflowWidth(bool includeInterior) const
int RenderBlock::overflowLeft(bool includeInterior) const
{
if (!includeInterior && hasOverflowClip()) {
- int shadowLeft = 0;
- for (ShadowData* boxShadow = style()->boxShadow(); boxShadow; boxShadow = boxShadow->next)
- shadowLeft = min(boxShadow->x - boxShadow->blur, shadowLeft);
+ int shadowLeft;
+ int shadowRight;
+ style()->getBoxShadowHorizontalExtent(shadowLeft, shadowRight);
+
int left = shadowLeft;
if (hasReflection())
left = min(left, reflectionBox().x());
@@ -595,9 +602,10 @@ int RenderBlock::overflowLeft(bool includeInterior) const
int RenderBlock::overflowTop(bool includeInterior) const
{
if (!includeInterior && hasOverflowClip()) {
- int shadowTop = 0;
- for (ShadowData* boxShadow = style()->boxShadow(); boxShadow; boxShadow = boxShadow->next)
- shadowTop = min(boxShadow->y - boxShadow->blur, shadowTop);
+ int shadowTop;
+ int shadowBottom;
+ style()->getBoxShadowVerticalExtent(shadowTop, shadowBottom);
+
int top = shadowTop;
if (hasReflection())
top = min(top, reflectionBox().y());
@@ -610,17 +618,12 @@ IntRect RenderBlock::overflowRect(bool includeInterior) const
{
if (!includeInterior && hasOverflowClip()) {
IntRect box = borderBoxRect();
- int shadowLeft = 0;
- int shadowRight = 0;
- int shadowTop = 0;
- int shadowBottom = 0;
-
- for (ShadowData* boxShadow = style()->boxShadow(); boxShadow; boxShadow = boxShadow->next) {
- shadowLeft = min(boxShadow->x - boxShadow->blur, shadowLeft);
- shadowRight = max(boxShadow->x + boxShadow->blur, shadowRight);
- shadowTop = min(boxShadow->y - boxShadow->blur, shadowTop);
- shadowBottom = max(boxShadow->y + boxShadow->blur, shadowBottom);
- }
+
+ int shadowLeft;
+ int shadowRight;
+ int shadowTop;
+ int shadowBottom;
+ style()->getBoxShadowExtent(shadowTop, shadowRight, shadowBottom, shadowLeft);
box.move(shadowLeft, shadowTop);
box.setWidth(box.width() - shadowLeft + shadowRight);
@@ -692,6 +695,45 @@ bool RenderBlock::isSelfCollapsingBlock() const
return false;
}
+void RenderBlock::startDelayUpdateScrollInfo()
+{
+ if (gDelayUpdateScrollInfo == 0) {
+ ASSERT(!gDelayedUpdateScrollInfoSet);
+ gDelayedUpdateScrollInfoSet = new DelayedUpdateScrollInfoSet;
+ }
+ ASSERT(gDelayedUpdateScrollInfoSet);
+ ++gDelayUpdateScrollInfo;
+}
+
+void RenderBlock::finishDelayUpdateScrollInfo()
+{
+ --gDelayUpdateScrollInfo;
+ ASSERT(gDelayUpdateScrollInfo >= 0);
+ if (gDelayUpdateScrollInfo == 0) {
+ ASSERT(gDelayedUpdateScrollInfoSet);
+
+ for (DelayedUpdateScrollInfoSet::iterator it = gDelayedUpdateScrollInfoSet->begin(); it != gDelayedUpdateScrollInfoSet->end(); ++it) {
+ RenderBlock* block = *it;
+ if (block->hasOverflowClip()) {
+ block->layer()->updateScrollInfoAfterLayout();
+ }
+ }
+
+ delete gDelayedUpdateScrollInfoSet;
+ gDelayedUpdateScrollInfoSet = 0;
+ }
+}
+
+void RenderBlock::updateScrollInfoAfterLayout()
+{
+ if (hasOverflowClip()) {
+ if (gDelayUpdateScrollInfo)
+ gDelayedUpdateScrollInfoSet->add(this);
+ else
+ layer()->updateScrollInfoAfterLayout();
+ }
+}
+
void RenderBlock::layout()
{
// Update our first letter info now.
@@ -843,16 +885,23 @@ void RenderBlock::layoutBlock(bool relayoutChildren)
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, width() + boxShadow->x + boxShadow->blur);
- m_overflowTop = min(m_overflowTop, boxShadow->y - boxShadow->blur);
- m_overflowHeight = max(m_overflowHeight, height() + boxShadow->y + boxShadow->blur);
- }
-
+ int shadowLeft;
+ int shadowRight;
+ int shadowTop;
+ int shadowBottom;
+ style()->getBoxShadowExtent(shadowTop, shadowRight, shadowBottom, shadowLeft);
+
+ m_overflowLeft = min(m_overflowLeft, shadowLeft);
+ m_overflowWidth = max(m_overflowWidth, width() + shadowRight);
+ m_overflowTop = min(m_overflowTop, shadowTop);
+ m_overflowHeight = max(m_overflowHeight, height() + shadowBottom);
+
if (hasReflection()) {
- m_overflowTop = min(m_overflowTop, reflectionBox().y());
- m_overflowHeight = max(m_overflowHeight, reflectionBox().bottom());
+ IntRect reflection(reflectionBox());
+ m_overflowLeft = min(m_overflowLeft, reflection.x());
+ m_overflowWidth = max(m_overflowWidth, reflection.right());
+ m_overflowTop = min(m_overflowTop, reflection.y());
+ m_overflowHeight = max(m_overflowHeight, reflection.bottom());
}
}
@@ -860,8 +909,7 @@ void RenderBlock::layoutBlock(bool relayoutChildren)
// Update our scroll information if we're overflow:auto/scroll/hidden now that we know if
// we overflow or not.
- if (hasOverflowClip())
- layer()->updateScrollInfoAfterLayout();
+ updateScrollInfoAfterLayout();
// Repaint with our new bounds if they are different from our old bounds.
bool didFullRepaint = repainter.repaintAfterLayout();
@@ -987,13 +1035,13 @@ bool RenderBlock::handleRunInChild(RenderBox* child)
if (!child->isRunIn() || !child->childrenInline() && !child->isReplaced())
return false;
- RenderBlock* blockRunIn = toRenderBlock(child);
// Get the next non-positioned/non-floating RenderBlock.
+ RenderBlock* blockRunIn = toRenderBlock(child);
RenderObject* curr = blockRunIn->nextSibling();
while (curr && curr->isFloatingOrPositioned())
curr = curr->nextSibling();
- if (!curr || !curr->isRenderBlock() || !curr->childrenInline() || curr->isRunIn())
+ if (!curr || !curr->isRenderBlock() || !curr->childrenInline() || curr->isRunIn() || curr->isAnonymous())
return false;
RenderBlock* currBlock = toRenderBlock(curr);
@@ -1452,8 +1500,10 @@ void RenderBlock::layoutBlockChildren(bool relayoutChildren, int& maxFloatBottom
child->repaintDuringLayoutIfMoved(oldRect);
}
- if (!childHadLayout && child->checkForRepaintDuringLayout())
+ if (!childHadLayout && child->checkForRepaintDuringLayout()) {
child->repaint();
+ child->repaintOverhangingFloats(true);
+ }
ASSERT(oldLayoutDelta == view()->layoutDelta());
}
@@ -1481,8 +1531,7 @@ bool RenderBlock::layoutOnlyPositionedObjects()
statePusher.pop();
- if (hasOverflowClip())
- layer()->updateScrollInfoAfterLayout();
+ updateScrollInfoAfterLayout();
#ifdef ANDROID_FIX
// iframe flatten will call FrameView::layout() which calls performPostLayoutTasks,
@@ -2444,10 +2493,10 @@ bool RenderBlock::positionNewFloats()
if (o->style()->floating() == FLEFT) {
int heightRemainingLeft = 1;
int heightRemainingRight = 1;
- int fx = leftRelOffset(y,lo, false, &heightRemainingLeft);
- while (rightRelOffset(y,ro, false, &heightRemainingRight)-fx < fwidth) {
+ int fx = leftRelOffset(y, lo, false, &heightRemainingLeft);
+ while (rightRelOffset(y, ro, false, &heightRemainingRight)-fx < fwidth) {
y += min(heightRemainingLeft, heightRemainingRight);
- fx = leftRelOffset(y,lo, false, &heightRemainingLeft);
+ fx = leftRelOffset(y, lo, false, &heightRemainingLeft);
}
fx = max(0, fx);
f->m_left = fx;
@@ -2455,8 +2504,8 @@ bool RenderBlock::positionNewFloats()
} else {
int heightRemainingLeft = 1;
int heightRemainingRight = 1;
- int fx = rightRelOffset(y,ro, false, &heightRemainingRight);
- while (fx - leftRelOffset(y,lo, false, &heightRemainingLeft) < fwidth) {
+ int fx = rightRelOffset(y, ro, false, &heightRemainingRight);
+ while (fx - leftRelOffset(y, lo, false, &heightRemainingLeft) < fwidth) {
y += min(heightRemainingLeft, heightRemainingRight);
fx = rightRelOffset(y, ro, false, &heightRemainingRight);
}
@@ -2481,7 +2530,7 @@ void RenderBlock::newLine(EClear clear)
positionNewFloats();
// set y position
int newY = 0;
- switch(clear)
+ switch (clear)
{
case CLEFT:
newY = leftBottom();
@@ -2652,12 +2701,12 @@ int
RenderBlock::floatBottom() const
{
if (!m_floatingObjects) return 0;
- int bottom=0;
+ int bottom = 0;
FloatingObject* r;
DeprecatedPtrListIterator<FloatingObject> it(*m_floatingObjects);
for ( ; (r = it.current()); ++it )
if (r->m_bottom>bottom)
- bottom=r->m_bottom;
+ bottom = r->m_bottom;
return bottom;
}
@@ -2942,12 +2991,12 @@ int
RenderBlock::leftBottom()
{
if (!m_floatingObjects) return 0;
- int bottom=0;
+ int bottom = 0;
FloatingObject* r;
DeprecatedPtrListIterator<FloatingObject> it(*m_floatingObjects);
for ( ; (r = it.current()); ++it )
if (r->m_bottom > bottom && r->type() == FloatingObject::FloatLeft)
- bottom=r->m_bottom;
+ bottom = r->m_bottom;
return bottom;
}
@@ -2956,12 +3005,12 @@ int
RenderBlock::rightBottom()
{
if (!m_floatingObjects) return 0;
- int bottom=0;
+ int bottom = 0;
FloatingObject* r;
DeprecatedPtrListIterator<FloatingObject> it(*m_floatingObjects);
for ( ; (r = it.current()); ++it )
if (r->m_bottom>bottom && r->type() == FloatingObject::FloatRight)
- bottom=r->m_bottom;
+ bottom = r->m_bottom;
return bottom;
}
@@ -3269,12 +3318,12 @@ void RenderBlock::addVisualOverflow(const IntRect& r)
m_overflowHeight = max(m_overflowHeight, r.bottom());
}
-bool RenderBlock::isPointInOverflowControl(HitTestResult& result, int, int, int, int)
+bool RenderBlock::isPointInOverflowControl(HitTestResult& result, int _x, int _y, int _tx, int _ty)
{
if (!scrollsOverflow())
return false;
- return layer()->hitTestOverflowControls(result);
+ return layer()->hitTestOverflowControls(result, IntPoint(_x - _tx, _y - _ty));
}
bool RenderBlock::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, int _x, int _y, int _tx, int _ty, HitTestAction hitTestAction)
@@ -3898,7 +3947,7 @@ void RenderBlock::calcPrefWidths()
}
if (isTableCell()) {
- Length w = static_cast<const RenderTableCell*>(this)->styleOrColWidth();
+ Length w = toRenderTableCell(this)->styleOrColWidth();
if (w.isFixed() && w.value() > 0)
m_maxPrefWidth = max(m_minPrefWidth, calcContentBoxWidth(w.value()));
}
@@ -3917,14 +3966,16 @@ void RenderBlock::calcPrefWidths()
int toAdd = 0;
toAdd = borderLeft() + borderRight() + paddingLeft() + paddingRight();
+ if (hasOverflowClip() && style()->overflowY() == OSCROLL)
+ toAdd += verticalScrollbarWidth();
+
m_minPrefWidth += toAdd;
m_maxPrefWidth += toAdd;
setPrefWidthsDirty(false);
}
-struct InlineMinMaxIterator
-{
+struct InlineMinMaxIterator {
/* InlineMinMaxIterator is a class that will iterate over all render objects that contribute to
inline min/max width calculations. Note the following about the way it walks:
(1) Positioned content is skipped (since it does not contribute to min/max width of a block)
@@ -4393,8 +4444,16 @@ void RenderBlock::calcBlockPrefWidths()
bool RenderBlock::hasLineIfEmpty() const
{
- return node() && ((node()->isContentEditable() && node()->rootEditableElement() == node()) ||
- (node()->isShadowNode() && node()->shadowParentNode()->hasTagName(inputTag)));
+ if (!node())
+ return false;
+
+ if (node()->isContentEditable() && node()->rootEditableElement() == node())
+ return true;
+
+ if (node()->isShadowNode() && (node()->shadowParentNode()->hasTagName(inputTag) || node()->shadowParentNode()->hasTagName(textareaTag)))
+ return true;
+
+ return false;
}
int RenderBlock::lineHeight(bool firstLine, bool isRootLineBox) const
diff --git a/WebCore/rendering/RenderBlock.h b/WebCore/rendering/RenderBlock.h
index f313b3d..839be16 100644
--- a/WebCore/rendering/RenderBlock.h
+++ b/WebCore/rendering/RenderBlock.h
@@ -1,10 +1,8 @@
/*
- * This file is part of the render object implementation for KHTML.
- *
* Copyright (C) 1999 Lars Knoll (knoll@kde.org)
* (C) 1999 Antti Koivisto (koivisto@kde.org)
* (C) 2007 David Smith (catfish.man@gmail.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
@@ -35,14 +33,15 @@
namespace WebCore {
class InlineIterator;
-class Position;
class RenderInline;
class RootInlineBox;
struct BidiRun;
template <class Iterator, class Run> class BidiResolver;
+template <class Iterator> class MidpointState;
typedef BidiResolver<InlineIterator, BidiRun> InlineBidiResolver;
+typedef MidpointState<InlineIterator> LineMidpointState;
enum CaretType { CursorCaret, DragCaret };
@@ -51,26 +50,15 @@ public:
RenderBlock(Node*);
virtual ~RenderBlock();
- virtual RenderObjectChildList* virtualChildren() { return children(); }
- virtual const RenderObjectChildList* virtualChildren() const { return children(); }
const RenderObjectChildList* children() const { return &m_children; }
RenderObjectChildList* children() { return &m_children; }
virtual void destroy();
- virtual const char* renderName() const;
-
// These two functions are overridden for inline-block.
virtual int lineHeight(bool firstLine, bool isRootLineBox = false) const;
virtual int baselinePosition(bool firstLine, bool isRootLineBox = false) const;
- virtual bool isRenderBlock() const { return true; }
- virtual bool isBlockFlow() const { return (!isInline() || isReplaced()) && !isTable(); }
- virtual bool isInlineBlockOrInlineTable() const { return isInline() && isReplaced(); }
-
- void makeChildrenNonInline(RenderObject* insertionPoint = 0);
- virtual void removeLeftoverAnonymousBlock(RenderBlock* child);
-
RenderLineBoxList* lineBoxes() { return &m_lineBoxes; }
const RenderLineBoxList* lineBoxes() const { return &m_lineBoxes; }
@@ -78,7 +66,6 @@ public:
InlineFlowBox* lastLineBox() const { return m_lineBoxes.lastLineBox(); }
void deleteLineBoxTree();
- virtual void dirtyLinesFromChangedChild(RenderObject* child) { m_lineBoxes.dirtyLinesFromChangedChild(this, child); }
// The height (and width) of a block when you include overflow spillage out of the bottom
// of the block (e.g., a <div style="height:25px"> that has a 100px tall image inside
@@ -88,15 +75,86 @@ public:
virtual int overflowLeft(bool includeInterior = true) const;
virtual int overflowTop(bool includeInterior = true) const;
virtual IntRect overflowRect(bool includeInterior = true) const;
- virtual void setOverflowHeight(int h) { m_overflowHeight = h; }
- virtual void setOverflowWidth(int w) { m_overflowWidth = w; }
void addVisualOverflow(const IntRect&);
- virtual bool isSelfCollapsingBlock() const;
+ virtual void addChild(RenderObject* newChild, RenderObject* beforeChild = 0);
+ virtual void removeChild(RenderObject*);
- virtual int maxTopMargin(bool positive) const { return positive ? maxTopPosMargin() : maxTopNegMargin(); }
- virtual int maxBottomMargin(bool positive) const { return positive ? maxBottomPosMargin() : maxBottomNegMargin(); }
+ virtual void layoutBlock(bool relayoutChildren);
+
+ void insertPositionedObject(RenderBox*);
+ void removePositionedObject(RenderBox*);
+ void removePositionedObjects(RenderBlock*);
+
+ void addPercentHeightDescendant(RenderBox*);
+ static void removePercentHeightDescendant(RenderBox*);
+ HashSet<RenderBox*>* percentHeightDescendants() const;
+
+ RootInlineBox* createAndAppendRootInlineBox();
+
+ bool generatesLineBoxesForInlineChild(RenderObject*, bool isLineEmpty = true, bool previousLineBrokeCleanly = true);
+
+ void markAllDescendantsWithFloatsForLayout(RenderBox* floatToRemove = 0, bool inLayout = true);
+ void markPositionedObjectsForLayout();
+
+ bool containsFloats() { return m_floatingObjects && !m_floatingObjects->isEmpty(); }
+ bool containsFloat(RenderObject*);
+
+ IntRect floatRect() const;
+
+ int lineWidth(int y, bool firstLine) const;
+ virtual int lowestPosition(bool includeOverflowInterior = true, bool includeSelf = true) const;
+ virtual int rightmostPosition(bool includeOverflowInterior = true, bool includeSelf = true) const;
+ virtual int leftmostPosition(bool includeOverflowInterior = true, bool includeSelf = true) const;
+
+ int rightOffset(int y, bool firstLine) const { return rightRelOffset(y, rightOffset(), firstLine); }
+ int leftOffset(int y, bool firstLine) const { return leftRelOffset(y, leftOffset(), firstLine); }
+
+ virtual VisiblePosition positionForPoint(const IntPoint&);
+
+ // Block flows subclass availableWidth to handle multi column layout (shrinking the width available to children when laying out.)
+ virtual int availableWidth() const;
+
+ RootInlineBox* firstRootBox() const { return static_cast<RootInlineBox*>(firstLineBox()); }
+ RootInlineBox* lastRootBox() const { return static_cast<RootInlineBox*>(lastLineBox()); }
+
+ bool containsNonZeroBidiLevel() const;
+
+ virtual void setSelectionState(SelectionState s);
+
+ GapRects selectionGapRectsForRepaint(RenderBoxModelObject* repaintContainer);
+ IntRect fillLeftSelectionGap(RenderObject* selObj, int xPos, int yPos, int height, RenderBlock* rootBlock,
+ int blockX, int blockY, int tx, int ty, const PaintInfo*);
+ IntRect fillRightSelectionGap(RenderObject* selObj, int xPos, int yPos, int height, RenderBlock* rootBlock,
+ int blockX, int blockY, int tx, int ty, const PaintInfo*);
+ IntRect fillHorizontalSelectionGap(RenderObject* selObj, int xPos, int yPos, int width, int height, const PaintInfo*);
+
+ void getHorizontalSelectionGapInfo(SelectionState, bool& leftGap, bool& rightGap);
+
+ // Helper methods for computing line counts and heights for line counts.
+ RootInlineBox* lineAtIndex(int);
+ int lineCount();
+ int heightForLineCount(int);
+ void clearTruncation();
+
+ void adjustRectForColumns(IntRect&) const;
+
+ void addContinuationWithOutline(RenderInline*);
+
+ RenderInline* inlineContinuation() const { return m_inlineContinuation; }
+ void setInlineContinuation(RenderInline* c) { m_inlineContinuation = c; }
+
+ // This function is a convenience helper for creating an anonymous block that inherits its
+ // style from this RenderBlock.
+ RenderBlock* createAnonymousBlock() const;
+
+ Vector<IntRect>* columnRects() const;
+ int columnGap() const;
+
+protected:
+ virtual void setOverflowHeight(int h) { m_overflowHeight = h; }
+ virtual void setOverflowWidth(int w) { m_overflowWidth = w; }
int maxTopPosMargin() const { return m_maxMargin ? m_maxMargin->m_topPos : MaxMargin::topPosDefault(this); }
int maxTopNegMargin() const { return m_maxMargin ? m_maxMargin->m_topNeg : MaxMargin::topNegDefault(this); }
@@ -115,60 +173,104 @@ public:
}
}
- virtual void addChild(RenderObject* newChild, RenderObject* beforeChild = 0);
- virtual void removeChild(RenderObject*);
+ virtual void layout();
+
+ void layoutPositionedObjects(bool relayoutChildren);
+
+ virtual void paint(PaintInfo&, int tx, int ty);
+ virtual void paintObject(PaintInfo&, int tx, int ty);
+
+ int rightRelOffset(int y, int fixedOffset, bool applyTextIndent = true, int* heightRemaining = 0) const;
+ int leftRelOffset(int y, int fixedOffset, bool applyTextIndent = true, int* heightRemaining = 0) const;
+
+ virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, int x, int y, int tx, int ty, HitTestAction);
+
+ virtual void calcPrefWidths();
+
+ virtual int firstLineBoxBaseline() const;
+ virtual int lastLineBoxBaseline() const;
+
+ virtual void updateFirstLetter();
+
+ virtual void updateHitTestResult(HitTestResult&, const IntPoint&);
+
+ // Delay update scrollbar until finishDelayRepaint() will be
+ // called. This function is used when a flexbox is laying out its
+ // descendant. If multiple calls are made to startDelayRepaint(),
+ // finishDelayRepaint() will do nothing until finishDelayRepaint()
+ // is called the same number of times.
+ static void startDelayUpdateScrollInfo();
+ static void finishDelayUpdateScrollInfo();
+
+ virtual void styleWillChange(StyleDifference, const RenderStyle* newStyle);
+ virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
+
+ virtual bool hasLineIfEmpty() const;
+ bool layoutOnlyPositionedObjects();
+
+private:
+ virtual RenderObjectChildList* virtualChildren() { return children(); }
+ virtual const RenderObjectChildList* virtualChildren() const { return children(); }
+
+ virtual const char* renderName() const;
+
+ virtual bool isRenderBlock() const { return true; }
+ virtual bool isBlockFlow() const { return (!isInline() || isReplaced()) && !isTable(); }
+ virtual bool isInlineBlockOrInlineTable() const { return isInline() && isReplaced(); }
+
+ void makeChildrenNonInline(RenderObject* insertionPoint = 0);
+ virtual void removeLeftoverAnonymousBlock(RenderBlock* child);
+
+ virtual void dirtyLinesFromChangedChild(RenderObject* child) { m_lineBoxes.dirtyLinesFromChangedChild(this, child); }
+
+ virtual bool isSelfCollapsingBlock() const;
+
+ virtual int maxTopMargin(bool positive) const { return positive ? maxTopPosMargin() : maxTopNegMargin(); }
+ virtual int maxBottomMargin(bool positive) const { return positive ? maxBottomPosMargin() : maxBottomNegMargin(); }
virtual void repaintOverhangingFloats(bool paintAllDescendants);
- virtual void layout();
- virtual void layoutBlock(bool relayoutChildren);
void layoutBlockChildren(bool relayoutChildren, int& maxFloatBottom);
void layoutInlineChildren(bool relayoutChildren, int& repaintTop, int& repaintBottom);
- void layoutPositionedObjects(bool relayoutChildren);
- void insertPositionedObject(RenderBox*);
- void removePositionedObject(RenderBox*);
- void removePositionedObjects(RenderBlock*);
-
- void addPercentHeightDescendant(RenderBox*);
- static void removePercentHeightDescendant(RenderBox*);
- HashSet<RenderBox*>* percentHeightDescendants() const;
-
virtual void positionListMarker() { }
virtual void borderFitAdjust(int& x, int& w) const; // Shrink the box in which the border paints if border-fit is set.
virtual void updateBeforeAfterContent(PseudoId);
- RootInlineBox* createRootInlineBox();
+ virtual RootInlineBox* createRootInlineBox(); // Subclassed by SVG and Ruby.
// Called to lay out the legend for a fieldset.
virtual RenderObject* layoutLegend(bool /*relayoutChildren*/) { return 0; }
- // the implementation of the following functions is in bidi.cpp
struct FloatWithRect {
FloatWithRect(RenderBox* f)
: object(f)
, rect(IntRect(f->x() - f->marginLeft(), f->y() - f->marginTop(), f->width() + f->marginLeft() + f->marginRight(), f->height() + f->marginTop() + f->marginBottom()))
+ , everHadLayout(f->m_everHadLayout)
{
}
RenderBox* object;
IntRect rect;
+ bool everHadLayout;
};
- void bidiReorderLine(InlineBidiResolver&, const InlineIterator& end);
- RootInlineBox* determineStartPosition(bool& firstLine, bool& fullLayout, InlineBidiResolver&, Vector<FloatWithRect>& floats, unsigned& numCleanFloats);
+ // The following functions' implementations are in RenderBlockLineLayout.cpp.
+ void bidiReorderLine(InlineBidiResolver&, const InlineIterator& end, bool previousLineBrokeCleanly);
+ RootInlineBox* determineStartPosition(bool& firstLine, bool& fullLayout, bool& previousLineBrokeCleanly,
+ InlineBidiResolver&, Vector<FloatWithRect>& floats, unsigned& numCleanFloats);
RootInlineBox* determineEndPosition(RootInlineBox* startBox, InlineIterator& cleanLineStart,
BidiStatus& cleanLineBidiStatus,
int& yPos);
bool matchedEndLine(const InlineBidiResolver&, const InlineIterator& endLineStart, const BidiStatus& endLineStatus,
RootInlineBox*& endLine, int& endYPos, int& repaintBottom, int& repaintTop);
- bool generatesLineBoxesForInlineChild(RenderObject*);
- void skipTrailingWhitespace(InlineIterator&);
- int skipLeadingWhitespace(InlineBidiResolver&, bool firstLine);
+
+ void skipTrailingWhitespace(InlineIterator&, bool isLineEmpty, bool previousLineBrokeCleanly);
+ int skipLeadingWhitespace(InlineBidiResolver&, bool firstLine, bool isLineEmpty, bool previousLineBrokeCleanly);
void fitBelowFloats(int widthToFit, bool firstLine, int& availableWidth);
- InlineIterator findNextLineBreak(InlineBidiResolver&, bool firstLine, EClear* clear = 0);
+ InlineIterator findNextLineBreak(InlineBidiResolver&, bool firstLine, bool& isLineEmpty, bool& previousLineBrokeCleanly, EClear* clear = 0);
RootInlineBox* constructLine(unsigned runCount, BidiRun* firstRun, BidiRun* lastRun, bool firstLine, bool lastLine, RenderObject* endObject);
InlineFlowBox* createLineBoxes(RenderObject*, bool firstLine);
void computeHorizontalPositionsForLine(RootInlineBox*, bool firstLine, BidiRun* firstRun, BidiRun* trailingSpaceRun, bool reachedEnd);
@@ -176,10 +278,8 @@ public:
void checkLinesForOverflow();
void deleteEllipsisLineBoxes();
void checkLinesForTextOverflow();
- // end bidi.cpp functions
+ // End of functions defined in RenderBlockLineLayout.cpp.
- virtual void paint(PaintInfo&, int tx, int ty);
- virtual void paintObject(PaintInfo&, int tx, int ty);
void paintFloats(PaintInfo&, int tx, int ty, bool preservePhase = false);
void paintContents(PaintInfo&, int tx, int ty);
void paintColumnContents(PaintInfo&, int tx, int ty, bool paintFloats = false);
@@ -197,11 +297,6 @@ public:
bool positionNewFloats();
void clearFloats();
int getClearDelta(RenderBox* child, int yPos);
- void markAllDescendantsWithFloatsForLayout(RenderBox* floatToRemove = 0, bool inLayout = true);
- void markPositionedObjectsForLayout();
-
- bool containsFloats() { return m_floatingObjects && !m_floatingObjects->isEmpty(); }
- bool containsFloat(RenderObject*);
virtual bool avoidsFloats() const;
@@ -213,49 +308,20 @@ public:
int floatBottom() const;
inline int leftBottom();
inline int rightBottom();
- IntRect floatRect() const;
-
- int lineWidth(int y, bool firstLine) const;
- virtual int lowestPosition(bool includeOverflowInterior = true, bool includeSelf = true) const;
- virtual int rightmostPosition(bool includeOverflowInterior = true, bool includeSelf = true) const;
- virtual int leftmostPosition(bool includeOverflowInterior = true, bool includeSelf = true) const;
int rightOffset() const;
- int rightRelOffset(int y, int fixedOffset, bool applyTextIndent = true, int* heightRemaining = 0) const;
- int rightOffset(int y, bool firstLine) const { return rightRelOffset(y, rightOffset(), firstLine); }
-
int leftOffset() const;
- int leftRelOffset(int y, int fixedOffset, bool applyTextIndent = true, int* heightRemaining = 0) const;
- int leftOffset(int y, bool firstLine) const { return leftRelOffset(y, leftOffset(), firstLine); }
-
- virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, int x, int y, int tx, int ty, HitTestAction);
virtual bool hitTestColumns(const HitTestRequest&, HitTestResult&, int x, int y, int tx, int ty, HitTestAction);
virtual bool hitTestContents(const HitTestRequest&, HitTestResult&, int x, int y, int tx, int ty, HitTestAction);
virtual bool isPointInOverflowControl(HitTestResult&, int x, int y, int tx, int ty);
- virtual VisiblePosition positionForPoint(const IntPoint&);
-
- // Block flows subclass availableWidth to handle multi column layout (shrinking the width available to children when laying out.)
- virtual int availableWidth() const;
-
- virtual void calcPrefWidths();
void calcInlinePrefWidths();
void calcBlockPrefWidths();
- virtual int firstLineBoxBaseline() const;
- virtual int lastLineBoxBaseline() const;
-
- 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;
- virtual void updateFirstLetter();
-
bool inRootBlockContext() const;
virtual IntRect rectWithOutlineForRepaint(RenderBoxModelObject* repaintContainer, int outlineWidth);
@@ -263,17 +329,12 @@ public:
virtual RenderObject* hoverAncestor() const;
virtual void updateDragState(bool dragOn);
- virtual void updateHitTestResult(HitTestResult&, const IntPoint&);
-
virtual void childBecameNonInline(RenderObject* child);
- virtual void setSelectionState(SelectionState s);
-
virtual IntRect selectionRectForRepaint(RenderBoxModelObject* repaintContainer, bool /*clipToVisibleContent*/)
{
return selectionGapRectsForRepaint(repaintContainer);
}
- GapRects selectionGapRectsForRepaint(RenderBoxModelObject* repaintContainer);
virtual bool shouldPaintSelectionGaps() const;
bool isSelectionRoot() const;
GapRects fillSelectionGaps(RenderBlock* rootBlock, int blockX, int blockY, int tx, int ty,
@@ -284,64 +345,29 @@ public:
int& lastTop, int& lastLeft, int& lastRight, const PaintInfo*);
IntRect fillVerticalSelectionGap(int lastTop, int lastLeft, int lastRight, int bottomY, RenderBlock* rootBlock,
int blockX, int blockY, const PaintInfo*);
- IntRect fillLeftSelectionGap(RenderObject* selObj, int xPos, int yPos, int height, RenderBlock* rootBlock,
- int blockX, int blockY, int tx, int ty, const PaintInfo*);
- IntRect fillRightSelectionGap(RenderObject* selObj, int xPos, int yPos, int height, RenderBlock* rootBlock,
- int blockX, int blockY, int tx, int ty, const PaintInfo*);
- IntRect fillHorizontalSelectionGap(RenderObject* selObj, int xPos, int yPos, int width, int height, const PaintInfo*);
-
- void getHorizontalSelectionGapInfo(SelectionState, bool& leftGap, bool& rightGap);
int leftSelectionOffset(RenderBlock* rootBlock, int y);
int rightSelectionOffset(RenderBlock* rootBlock, int y);
virtual void absoluteRects(Vector<IntRect>&, int tx, int ty);
virtual void absoluteQuads(Vector<FloatQuad>&);
- // Helper methods for computing line counts and heights for line counts.
- RootInlineBox* lineAtIndex(int);
- int lineCount();
- int heightForLineCount(int);
- void clearTruncation();
-
int desiredColumnWidth() const;
unsigned desiredColumnCount() const;
- Vector<IntRect>* columnRects() const;
void setDesiredColumnCountAndWidth(int count, int width);
- int columnGap() const;
- void adjustRectForColumns(IntRect&) const;
-
- void addContinuationWithOutline(RenderInline*);
void paintContinuationOutlines(PaintInfo&, int tx, int ty);
- RenderInline* inlineContinuation() const { return m_inlineContinuation; }
- void setInlineContinuation(RenderInline* c) { m_inlineContinuation = c; }
-
virtual IntRect localCaretRect(InlineBox*, int caretOffset, int* extraWidthToEndOfLine = 0);
virtual void addFocusRingRects(GraphicsContext*, int tx, int ty);
- // This function is a convenience helper for creating an anonymous block that inherits its
- // style from this RenderBlock.
- RenderBlock* createAnonymousBlock() const;
-
-private:
void adjustPointToColumnContents(IntPoint&) const;
void adjustForBorderFit(int x, int& left, int& right) const; // Helper function for borderFitAdjust
void markLinesDirtyInVerticalRange(int top, int bottom);
-protected:
- virtual void styleWillChange(StyleDifference, const RenderStyle* newStyle);
- virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
-
void newLine(EClear);
- virtual bool hasLineIfEmpty() const;
- bool layoutOnlyPositionedObjects();
- virtual RootInlineBox* createRootBox(); // Subclassed by SVG.
-
-private:
Position positionForBox(InlineBox*, bool start = true) const;
Position positionForRenderer(RenderObject*, bool start = true) const;
VisiblePosition positionForPointWithInlineChildren(const IntPoint&);
@@ -354,7 +380,8 @@ private:
bool expandsToEncloseOverhangingFloats() const;
-protected:
+ void updateScrollInfoAfterLayout();
+
struct FloatingObject {
enum Type {
FloatLeft,
@@ -465,7 +492,6 @@ protected:
void setCollapsedBottomMargin(const MarginInfo&);
// End helper functions and structs used by layoutBlockChildren.
-private:
typedef ListHashSet<RenderBox*>::const_iterator Iterator;
DeprecatedPtrList<FloatingObject>* m_floatingObjects;
ListHashSet<RenderBox*>* m_positionedObjects;
@@ -499,33 +525,34 @@ private:
MaxMargin* m_maxMargin;
-protected:
RenderObjectChildList m_children;
RenderLineBoxList m_lineBoxes; // All of the root line boxes created for this block flow. For example, <div>Hello<br>world.</div> will have two total lines for the <div>.
+protected:
// How much content overflows out of our block vertically or horizontally.
int m_overflowHeight;
int m_overflowWidth;
int m_overflowLeft;
int m_overflowTop;
-
+
+private:
mutable int m_lineHeight;
};
-inline RenderBlock* toRenderBlock(RenderObject* o)
+inline RenderBlock* toRenderBlock(RenderObject* object)
{
- ASSERT(!o || o->isRenderBlock());
- return static_cast<RenderBlock*>(o);
+ ASSERT(!object || object->isRenderBlock());
+ return static_cast<RenderBlock*>(object);
}
-inline const RenderBlock* toRenderBlock(const RenderObject* o)
+inline const RenderBlock* toRenderBlock(const RenderObject* object)
{
- ASSERT(!o || o->isRenderBlock());
- return static_cast<const RenderBlock*>(o);
+ ASSERT(!object || object->isRenderBlock());
+ return static_cast<const RenderBlock*>(object);
}
// This will catch anyone doing an unnecessary cast.
-void toRenderBlock(const RenderBlock* o);
+void toRenderBlock(const RenderBlock*);
} // namespace WebCore
diff --git a/WebCore/rendering/bidi.cpp b/WebCore/rendering/RenderBlockLineLayout.cpp
index dc5176e..2a70d6a 100644
--- a/WebCore/rendering/bidi.cpp
+++ b/WebCore/rendering/RenderBlockLineLayout.cpp
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2000 Lars Knoll (knoll@kde.org)
- * Copyright (C) 2004, 2006, 2007, 2008 Apple Inc. All right reserved.
+ * Copyright (C) 2003, 2004, 2006, 2007, 2008, 2009 Apple Inc. All right reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -20,17 +20,13 @@
*/
#include "config.h"
-#include "bidi.h"
+#include "BidiResolver.h"
#include "CharacterNames.h"
-#include "Document.h"
-#include "Element.h"
-#include "FrameView.h"
#include "InlineTextBox.h"
#include "Logging.h"
#include "RenderArena.h"
#include "RenderInline.h"
-#include "RenderLayer.h"
#include "RenderListMarker.h"
#include "RenderView.h"
#include "break_lines.h"
@@ -38,13 +34,6 @@
#include <wtf/RefCountedLeakCounter.h>
#include <wtf/StdLibExtras.h>
#include <wtf/Vector.h>
-#ifdef ANDROID_LAYOUT
-#include "Frame.h"
-#include "FrameTree.h"
-#include "Settings.h"
-#include "Text.h"
-#include "HTMLNames.h"
-#endif // ANDROID_LAYOUT
using namespace std;
using namespace WTF;
@@ -77,7 +66,7 @@ public:
bool atEnd() const;
UChar current() const;
- WTF::Unicode::Direction direction() const;
+ Direction direction() const;
RenderBlock* block;
RenderObject* obj;
@@ -85,17 +74,6 @@ public:
int nextBreakablePosition;
};
-// Midpoint globals. The goal is not to do any allocation when dealing with
-// these midpoints, so we just keep an array around and never clear it. We track
-// the number of items and position using the two other variables.
-static Vector<InlineIterator>* smidpoints;
-static unsigned sNumMidpoints;
-static unsigned sCurrMidpoint;
-static bool betweenMidpoints;
-
-static bool isLineEmpty = true;
-static bool previousLineBrokeCleanly = true;
-
static int getBorderPaddingMargin(RenderBoxModelObject* child, bool endOfInline)
{
bool leftSide = (child->style()->direction() == LTR) ? !endOfInline : endOfInline;
@@ -120,8 +98,35 @@ static int inlineWidth(RenderObject* child, bool start = true, bool end = true)
return extraWidth;
}
+struct BidiRun : BidiCharacterRun {
+ BidiRun(int start, int stop, RenderObject* object, BidiContext* context, Direction dir)
+ : BidiCharacterRun(start, stop, context, dir)
+ , m_object(object)
+ , m_box(0)
+ {
+ }
+
+ void destroy();
+
+ // Overloaded new operator.
+ void* operator new(size_t, RenderArena*) throw();
+
+ // Overridden to prevent the normal delete from being called.
+ void operator delete(void*, size_t);
+
+ BidiRun* next() { return static_cast<BidiRun*>(m_next); }
+
+private:
+ // The normal operator new is disallowed.
+ void* operator new(size_t) throw();
+
+public:
+ RenderObject* m_object;
+ InlineBox* m_box;
+};
+
#ifndef NDEBUG
-static WTF::RefCountedLeakCounter bidiRunCounter("BidiRun");
+static RefCountedLeakCounter bidiRunCounter("BidiRun");
static bool inBidiRunDestroy;
#endif
@@ -334,35 +339,35 @@ ALWAYS_INLINE Direction InlineIterator::direction() const
// -------------------------------------------------------------------------------------------------
-static void chopMidpointsAt(RenderObject* obj, unsigned pos)
+static void chopMidpointsAt(LineMidpointState& lineMidpointState, RenderObject* obj, unsigned pos)
{
- if (!sNumMidpoints)
+ if (!lineMidpointState.numMidpoints)
return;
- InlineIterator* midpoints = smidpoints->data();
- for (int i = sNumMidpoints - 1; i >= 0; i--) {
+ InlineIterator* midpoints = lineMidpointState.midpoints.data();
+ for (int i = lineMidpointState.numMidpoints - 1; i >= 0; i--) {
const InlineIterator& point = midpoints[i];
if (point.obj == obj && point.pos == pos) {
- sNumMidpoints = i;
+ lineMidpointState.numMidpoints = i;
break;
}
}
}
-static void checkMidpoints(InlineIterator& lBreak)
+static void checkMidpoints(LineMidpointState& lineMidpointState, InlineIterator& lBreak)
{
// Check to see if our last midpoint is a start point beyond the line break. If so,
// shave it off the list, and shave off a trailing space if the previous end point doesn't
// preserve whitespace.
- if (lBreak.obj && sNumMidpoints && sNumMidpoints % 2 == 0) {
- InlineIterator* midpoints = smidpoints->data();
- InlineIterator& endpoint = midpoints[sNumMidpoints-2];
- const InlineIterator& startpoint = midpoints[sNumMidpoints-1];
+ if (lBreak.obj && lineMidpointState.numMidpoints && !(lineMidpointState.numMidpoints % 2)) {
+ InlineIterator* midpoints = lineMidpointState.midpoints.data();
+ InlineIterator& endpoint = midpoints[lineMidpointState.numMidpoints - 2];
+ const InlineIterator& startpoint = midpoints[lineMidpointState.numMidpoints - 1];
InlineIterator currpoint = endpoint;
while (!currpoint.atEnd() && currpoint != startpoint && currpoint != lBreak)
currpoint.increment();
if (currpoint == lBreak) {
// We hit the line break before the start point. Shave off the start point.
- sNumMidpoints--;
+ lineMidpointState.numMidpoints--;
if (endpoint.obj->style()->collapseWhiteSpace()) {
if (endpoint.obj->isText()) {
// Don't shave a character off the endpoint if it was from a soft hyphen.
@@ -382,13 +387,13 @@ static void checkMidpoints(InlineIterator& lBreak)
}
}
-static void addMidpoint(const InlineIterator& midpoint)
+static void addMidpoint(LineMidpointState& lineMidpointState, const InlineIterator& midpoint)
{
- if (smidpoints->size() <= sNumMidpoints)
- smidpoints->grow(sNumMidpoints + 10);
+ if (lineMidpointState.midpoints.size() <= lineMidpointState.numMidpoints)
+ lineMidpointState.midpoints.grow(lineMidpointState.numMidpoints + 10);
- InlineIterator* midpoints = smidpoints->data();
- midpoints[sNumMidpoints++] = midpoint;
+ InlineIterator* midpoints = lineMidpointState.midpoints.data();
+ midpoints[lineMidpointState.numMidpoints++] = midpoint;
}
static void appendRunsForObject(int start, int end, RenderObject* obj, InlineBidiResolver& resolver)
@@ -397,18 +402,19 @@ static void appendRunsForObject(int start, int end, RenderObject* obj, InlineBid
(obj->isPositioned() && !obj->style()->hasStaticX() && !obj->style()->hasStaticY() && !obj->container()->isRenderInline()))
return;
- bool haveNextMidpoint = (sCurrMidpoint < sNumMidpoints);
+ LineMidpointState& lineMidpointState = resolver.midpointState();
+ bool haveNextMidpoint = (lineMidpointState.currentMidpoint < lineMidpointState.numMidpoints);
InlineIterator nextMidpoint;
if (haveNextMidpoint)
- nextMidpoint = smidpoints->at(sCurrMidpoint);
- if (betweenMidpoints) {
+ nextMidpoint = lineMidpointState.midpoints[lineMidpointState.currentMidpoint];
+ if (lineMidpointState.betweenMidpoints) {
if (!(haveNextMidpoint && nextMidpoint.obj == obj))
return;
// This is a new start point. Stop ignoring objects and
// adjust our start.
- betweenMidpoints = false;
+ lineMidpointState.betweenMidpoints = false;
start = nextMidpoint.pos;
- sCurrMidpoint++;
+ lineMidpointState.currentMidpoint++;
if (start < end)
return appendRunsForObject(start, end, obj, resolver);
} else {
@@ -420,8 +426,8 @@ static void appendRunsForObject(int start, int end, RenderObject* obj, InlineBid
// An end midpoint has been encountered within our object. We
// need to go ahead and append a run with our endpoint.
if (static_cast<int>(nextMidpoint.pos + 1) <= end) {
- betweenMidpoints = true;
- sCurrMidpoint++;
+ lineMidpointState.betweenMidpoints = true;
+ lineMidpointState.currentMidpoint++;
if (nextMidpoint.pos != UINT_MAX) { // UINT_MAX means stop at the object and don't include any of it.
if (static_cast<int>(nextMidpoint.pos + 1) > start)
resolver.addRun(new (obj->renderArena())
@@ -466,7 +472,7 @@ void InlineBidiResolver::appendRun()
static inline InlineBox* createInlineBoxForRenderer(RenderObject* obj, bool isRootLineBox, bool isOnlyRun = false)
{
if (isRootLineBox)
- return toRenderBlock(obj)->createRootInlineBox();
+ return toRenderBlock(obj)->createAndAppendRootInlineBox();
if (obj->isText()) {
InlineTextBox* textBox = toRenderText(obj)->createInlineTextBox();
@@ -480,7 +486,7 @@ static inline InlineBox* createInlineBoxForRenderer(RenderObject* obj, bool isRo
if (obj->isBox())
return toRenderBox(obj)->createInlineBox();
- return toRenderInline(obj)->createInlineFlowBox();
+ return toRenderInline(obj)->createAndAppendInlineFlowBox();
}
static inline void dirtyLineBoxesForRenderer(RenderObject* o, bool fullLayout)
@@ -658,7 +664,7 @@ void RenderBlock::computeHorizontalPositionsForLine(RootInlineBox* lineBox, bool
// objects horizontally. The total width of the line can be increased if we end up
// justifying text.
int x = leftOffset(height(), firstLine);
- switch(textAlign) {
+ switch (textAlign) {
case LEFT:
case WEBKIT_LEFT:
// The direction of the block should determine what happens with wide lines. In
@@ -798,7 +804,7 @@ void RenderBlock::computeVerticalPositionsForLine(RootInlineBox* lineBox, BidiRu
}
// collects one line of the paragraph and transforms it to visual order
-void RenderBlock::bidiReorderLine(InlineBidiResolver& resolver, const InlineIterator& end)
+void RenderBlock::bidiReorderLine(InlineBidiResolver& resolver, const InlineIterator& end, bool previousLineBrokeCleanly)
{
resolver.createBidiRunsForLine(end, style()->visuallyOrdered(), previousLineBrokeCleanly);
}
@@ -825,7 +831,6 @@ void RenderBlock::layoutInlineChildren(bool relayoutChildren, int& repaintTop, i
// Figure out if we should clear out our line boxes.
// FIXME: Handle resize eventually!
- // FIXME: Do something better when floats are present.
bool fullLayout = !firstLineBox() || !firstChild() || selfNeedsLayout() || relayoutChildren;
if (fullLayout)
lineBoxes()->deleteLineBoxes(renderArena());
@@ -842,32 +847,6 @@ void RenderBlock::layoutInlineChildren(bool relayoutChildren, int& repaintTop, i
deleteEllipsisLineBoxes();
if (firstChild()) {
-#ifdef ANDROID_LAYOUT
- // if we are in fitColumnToScreen mode and viewport width is not device-width,
- // and the current object is not float:right in LTR or not float:left in RTL,
- // and text align is auto, or justify or left in LTR, or right in RTL, we
- // will wrap text around screen width so that it doesn't need to scroll
- // horizontally when reading a paragraph.
- const Settings* settings = document()->settings();
- bool doTextWrap = settings && settings->viewportWidth() != 0 &&
- settings->layoutAlgorithm() == Settings::kLayoutFitColumnToScreen;
- if (doTextWrap) {
- int ta = style()->textAlign();
- int dir = style()->direction();
- bool autowrap = style()->autoWrap();
- // if the RenderBlock is positioned, don't wrap text around screen
- // width as it may cause text to overlap.
- bool positioned = isPositioned();
- EFloat cssfloat = style()->floating();
- doTextWrap = autowrap && !positioned &&
- (((dir == LTR && cssfloat != FRIGHT) ||
- (dir == RTL && cssfloat != FLEFT)) &&
- ((ta == TAAUTO) || (ta == JUSTIFY) ||
- ((ta == LEFT || ta == WEBKIT_LEFT) && (dir == LTR)) ||
- ((ta == RIGHT || ta == WEBKIT_RIGHT) && (dir == RTL))));
- }
- bool hasTextToWrap = false;
-#endif
// layout replaced elements
bool endOfInline = false;
RenderObject* o = bidiFirst(this, 0, false);
@@ -886,11 +865,6 @@ void RenderBlock::layoutInlineChildren(bool relayoutChildren, int& repaintTop, i
if (o->isPositioned())
o->containingBlock()->insertPositionedObject(box);
else {
-#ifdef ANDROID_LAYOUT
- // ignore text wrap for textField or menuList
- if (doTextWrap && (o->isTextField() || o->isMenuList()))
- doTextWrap = false;
-#endif
if (o->isFloating())
floats.append(FloatWithRect(box));
else if (fullLayout || o->needsLayout()) // Replaced elements
@@ -902,80 +876,18 @@ void RenderBlock::layoutInlineChildren(bool relayoutChildren, int& repaintTop, i
if (fullLayout || o->selfNeedsLayout())
dirtyLineBoxesForRenderer(o, fullLayout);
o->setNeedsLayout(false);
-#ifdef ANDROID_LAYOUT
- if (doTextWrap && !hasTextToWrap && o->isText()) {
- Node* node = o->node();
- // as it is very common for sites to use a serial of <a> or
- // <li> as tabs, we don't force text to wrap if all the text
- // are short and within an <a> or <li> tag, and only separated
- // by short word like "|" or ";".
- if (node && node->isTextNode() &&
- !static_cast<Text*>(node)->containsOnlyWhitespace()) {
- int length = static_cast<Text*>(node)->length();
- // FIXME, need a magic number to decide it is too long to
- // be a tab. Pick 25 for now as it covers around 160px
- // (half of 320px) with the default font.
- if (length > 25 || (length > 3 &&
- (!node->parent()->hasTagName(HTMLNames::aTag) &&
- !node->parent()->hasTagName(HTMLNames::liTag))))
- hasTextToWrap = true;
- }
- }
-#endif
if (!o->isText())
toRenderInline(o)->invalidateVerticalPosition(); // FIXME: Should do better here and not always invalidate everything.
}
o = bidiNext(this, o, 0, false, &endOfInline);
}
-#ifdef ANDROID_LAYOUT
- // try to make sure that inline text will not span wider than the
- // screen size unless the container has a fixed height,
- if (doTextWrap && hasTextToWrap) {
- // check all the nested containing blocks, unless it is table or
- // table-cell, to make sure there is no fixed height as it implies
- // fixed layout. If we constrain the text to fit screen, we may
- // cause text overlap with the block after.
- bool isConstrained = false;
- RenderObject* obj = this;
- while (obj) {
- if (obj->style()->height().isFixed() && (!obj->isTable() && !obj->isTableCell())) {
- isConstrained = true;
- break;
- }
- if (obj->isFloating() || obj->isPositioned()) {
- // floating and absolute or fixed positioning are done out
- // of normal flow. Don't need to worry about height any more.
- break;
- }
- obj = obj->container();
- }
- if (!isConstrained) {
- int screenWidth = view()->frameView()->screenWidth();
- if (screenWidth > 0 && width() > screenWidth) {
- // if the current padding is smaller, add an extra to make
- // it 2 * ANDROID_FCTS_MARGIN_PADDING so that the text won't
- // overlap with the screen edge. If the current padding is
- // negative, leave it alone.
- int padding = paddingLeft() + paddingRight();
- if (padding < 0 || padding >= 2 * ANDROID_FCTS_MARGIN_PADDING)
- padding = 0;
- else
- padding = 2 * ANDROID_FCTS_MARGIN_PADDING - padding;
- int maxWidth = screenWidth - padding;
- setWidth(min(width(), maxWidth));
- m_minPrefWidth = min(m_minPrefWidth, maxWidth);
- m_maxPrefWidth = min(m_maxPrefWidth, maxWidth);
- m_overflowWidth = min(m_overflowWidth, maxWidth);
- }
- }
- }
-#endif
// We want to skip ahead to the first dirty line
InlineBidiResolver resolver;
unsigned floatIndex;
bool firstLine = true;
- RootInlineBox* startLine = determineStartPosition(firstLine, fullLayout, resolver, floats, floatIndex);
+ bool previousLineBrokeCleanly = true;
+ RootInlineBox* startLine = determineStartPosition(firstLine, fullLayout, previousLineBrokeCleanly, resolver, floats, floatIndex);
if (fullLayout && !selfNeedsLayout()) {
setNeedsLayout(true, false); // Mark ourselves as needing a full layout. This way we'll repaint like
@@ -992,11 +904,7 @@ void RenderBlock::layoutInlineChildren(bool relayoutChildren, int& repaintTop, i
FloatingObject* lastFloat = m_floatingObjects ? m_floatingObjects->last() : 0;
- if (!smidpoints)
- smidpoints = new Vector<InlineIterator>();
-
- sNumMidpoints = 0;
- sCurrMidpoint = 0;
+ LineMidpointState& lineMidpointState = resolver.midpointState();
// We also find the first clean line and extract these lines. We will add them back
// if we determine that we're able to synchronize after handling all our dirty lines.
@@ -1044,16 +952,19 @@ void RenderBlock::layoutInlineChildren(bool relayoutChildren, int& repaintTop, i
bool checkForFloatsFromLastLine = false;
int lastHeight = height();
+ bool isLineEmpty = true;
+
while (!end.atEnd()) {
// FIXME: Is this check necessary before the first iteration or can it be moved to the end?
if (checkForEndLineMatch && (endLineMatched = matchedEndLine(resolver, cleanLineStart, cleanLineBidiStatus, endLine, endLineYPos, repaintBottom, repaintTop)))
break;
- betweenMidpoints = false;
+ lineMidpointState.reset();
+
isLineEmpty = true;
EClear clear = CNONE;
- end = findNextLineBreak(resolver, firstLine, &clear);
+ end = findNextLineBreak(resolver, firstLine, isLineEmpty, previousLineBrokeCleanly, &clear);
if (resolver.position().atEnd()) {
resolver.deleteRuns();
checkForFloatsFromLastLine = true;
@@ -1062,7 +973,7 @@ void RenderBlock::layoutInlineChildren(bool relayoutChildren, int& repaintTop, i
ASSERT(end != resolver.position());
if (!isLineEmpty) {
- bidiReorderLine(resolver, end);
+ bidiReorderLine(resolver, end, previousLineBrokeCleanly);
ASSERT(resolver.position() == end);
BidiRun* trailingSpaceRun = 0;
@@ -1176,8 +1087,7 @@ void RenderBlock::layoutInlineChildren(bool relayoutChildren, int& repaintTop, i
}
lastHeight = height();
- sNumMidpoints = 0;
- sCurrMidpoint = 0;
+ lineMidpointState.reset();
resolver.setPosition(end);
}
@@ -1232,11 +1142,19 @@ void RenderBlock::layoutInlineChildren(bool relayoutChildren, int& repaintTop, i
}
lastFloat = m_floatingObjects->last();
}
+ size_t floatCount = floats.size();
+ // Floats that did not have layout did not repaint when we laid them out. They would have
+ // painted by now if they had moved, but if they stayed at (0, 0), they still need to be
+ // painted.
+ for (size_t i = 0; i < floatCount; ++i) {
+ if (!floats[i].everHadLayout) {
+ RenderBox* f = floats[i].object;
+ if (!f->x() && !f->y() && f->checkForRepaintDuringLayout())
+ f->repaint();
+ }
+ }
}
- sNumMidpoints = 0;
- sCurrMidpoint = 0;
-
// Now add in the bottom border/padding.
setHeight(height() + toAdd);
@@ -1255,7 +1173,8 @@ void RenderBlock::layoutInlineChildren(bool relayoutChildren, int& repaintTop, i
checkLinesForTextOverflow();
}
-RootInlineBox* RenderBlock::determineStartPosition(bool& firstLine, bool& fullLayout, InlineBidiResolver& resolver, Vector<FloatWithRect>& floats, unsigned& numCleanFloats)
+RootInlineBox* RenderBlock::determineStartPosition(bool& firstLine, bool& fullLayout, bool& previousLineBrokeCleanly,
+ InlineBidiResolver& resolver, Vector<FloatWithRect>& floats, unsigned& numCleanFloats)
{
RootInlineBox* curr = 0;
RootInlineBox* last = 0;
@@ -1486,7 +1405,7 @@ bool RenderBlock::matchedEndLine(const InlineBidiResolver& resolver, const Inlin
return false;
}
-static inline bool skipNonBreakingSpace(const InlineIterator& it)
+static inline bool skipNonBreakingSpace(const InlineIterator& it, bool isLineEmpty, bool previousLineBrokeCleanly)
{
if (it.obj->style()->nbspMode() != SPACE || it.current() != noBreakSpace)
return false;
@@ -1502,7 +1421,7 @@ static inline bool skipNonBreakingSpace(const InlineIterator& it)
return true;
}
-static inline bool shouldCollapseWhiteSpace(const RenderStyle* style)
+static inline bool shouldCollapseWhiteSpace(const RenderStyle* style, bool isLineEmpty, bool previousLineBrokeCleanly)
{
return style->collapseWhiteSpace() || (style->whiteSpace() == PRE_WRAP && (!isLineEmpty || !previousLineBrokeCleanly));
}
@@ -1525,7 +1444,7 @@ static bool inlineFlowRequiresLineBox(RenderInline* flow)
return !flow->firstChild() && flow->hasHorizontalBordersPaddingOrMargin();
}
-static inline bool requiresLineBox(const InlineIterator& it)
+static inline bool requiresLineBox(const InlineIterator& it, bool isLineEmpty, bool previousLineBrokeCleanly)
{
if (it.obj->isFloatingOrPositioned())
return false;
@@ -1533,19 +1452,20 @@ static inline bool requiresLineBox(const InlineIterator& it)
if (it.obj->isRenderInline() && !inlineFlowRequiresLineBox(toRenderInline(it.obj)))
return false;
- if (!shouldCollapseWhiteSpace(it.obj->style()) || it.obj->isBR())
+ if (!shouldCollapseWhiteSpace(it.obj->style(), isLineEmpty, previousLineBrokeCleanly) || it.obj->isBR())
return true;
UChar current = it.current();
- return current != ' ' && current != '\t' && current != softHyphen && (current != '\n' || shouldPreserveNewline(it.obj)) && !skipNonBreakingSpace(it);
+ return current != ' ' && current != '\t' && current != softHyphen && (current != '\n' || shouldPreserveNewline(it.obj))
+ && !skipNonBreakingSpace(it, isLineEmpty, previousLineBrokeCleanly);
}
-bool RenderBlock::generatesLineBoxesForInlineChild(RenderObject* inlineObj)
+bool RenderBlock::generatesLineBoxesForInlineChild(RenderObject* inlineObj, bool isLineEmpty, bool previousLineBrokeCleanly)
{
ASSERT(inlineObj->parent() == this);
InlineIterator it(this, inlineObj, 0);
- while (!it.atEnd() && !requiresLineBox(it))
+ while (!it.atEnd() && !requiresLineBox(it, isLineEmpty, previousLineBrokeCleanly))
it.increment();
return !it.atEnd();
@@ -1557,9 +1477,9 @@ bool RenderBlock::generatesLineBoxesForInlineChild(RenderObject* inlineObj)
// object iteration process.
// NB. this function will insert any floating elements that would otherwise
// be skipped but it will not position them.
-void RenderBlock::skipTrailingWhitespace(InlineIterator& iterator)
+void RenderBlock::skipTrailingWhitespace(InlineIterator& iterator, bool isLineEmpty, bool previousLineBrokeCleanly)
{
- while (!iterator.atEnd() && !requiresLineBox(iterator)) {
+ while (!iterator.atEnd() && !requiresLineBox(iterator, isLineEmpty, previousLineBrokeCleanly)) {
RenderObject* object = iterator.obj;
if (object->isFloating()) {
insertFloatingObject(toRenderBox(object));
@@ -1590,10 +1510,10 @@ void RenderBlock::skipTrailingWhitespace(InlineIterator& iterator)
}
}
-int RenderBlock::skipLeadingWhitespace(InlineBidiResolver& resolver, bool firstLine)
+int RenderBlock::skipLeadingWhitespace(InlineBidiResolver& resolver, bool firstLine, bool isLineEmpty, bool previousLineBrokeCleanly)
{
int availableWidth = lineWidth(height(), firstLine);
- while (!resolver.position().atEnd() && !requiresLineBox(resolver.position())) {
+ while (!resolver.position().atEnd() && !requiresLineBox(resolver.position(), isLineEmpty, previousLineBrokeCleanly)) {
RenderObject* object = resolver.position().obj;
if (object->isFloating()) {
insertFloatingObject(toRenderBox(object));
@@ -1630,14 +1550,14 @@ int RenderBlock::skipLeadingWhitespace(InlineBidiResolver& resolver, bool firstL
// This is currently just used for list markers and inline flows that have line boxes. Neither should
// have an effect on whitespace at the start of the line.
-static bool shouldSkipWhitespaceAfterStartObject(RenderBlock* block, RenderObject* o)
+static bool shouldSkipWhitespaceAfterStartObject(RenderBlock* block, RenderObject* o, LineMidpointState& lineMidpointState)
{
RenderObject* next = bidiNext(block, o);
if (next && !next->isBR() && next->isText() && toRenderText(next)->textLength() > 0) {
RenderText* nextText = toRenderText(next);
UChar nextChar = nextText->characters()[0];
if (nextText->style()->isCollapsibleWhiteSpace(nextChar)) {
- addMidpoint(InlineIterator(0, o, 0));
+ addMidpoint(lineMidpointState, InlineIterator(0, o, 0));
return true;
}
}
@@ -1676,13 +1596,15 @@ static inline unsigned textWidth(RenderText* text, unsigned from, unsigned len,
return font.width(TextRun(text->characters() + from, len, !collapseWhiteSpace, xPos));
}
-InlineIterator RenderBlock::findNextLineBreak(InlineBidiResolver& resolver, bool firstLine, EClear* clear)
+InlineIterator RenderBlock::findNextLineBreak(InlineBidiResolver& resolver, bool firstLine, bool& isLineEmpty, bool& previousLineBrokeCleanly,
+ EClear* clear)
{
ASSERT(resolver.position().block == this);
bool appliedStartWidth = resolver.position().pos > 0;
-
- int width = skipLeadingWhitespace(resolver, firstLine);
+ LineMidpointState& lineMidpointState = resolver.midpointState();
+
+ int width = skipLeadingWhitespace(resolver, firstLine, isLineEmpty, previousLineBrokeCleanly);
int w = 0;
int tmpW = 0;
@@ -1807,8 +1729,8 @@ InlineIterator RenderBlock::findNextLineBreak(InlineBidiResolver& resolver, bool
ignoreStart.obj = o;
ignoreStart.pos = 0;
if (ignoringSpaces) {
- addMidpoint(ignoreStart); // Stop ignoring spaces.
- addMidpoint(ignoreStart); // Start ignoring again.
+ addMidpoint(lineMidpointState, ignoreStart); // Stop ignoring spaces.
+ addMidpoint(lineMidpointState, ignoreStart); // Start ignoring again.
}
}
@@ -1827,10 +1749,10 @@ InlineIterator RenderBlock::findNextLineBreak(InlineBidiResolver& resolver, bool
isLineEmpty = false;
if (ignoringSpaces) {
trailingSpaceObject = 0;
- addMidpoint(InlineIterator(0, o, 0)); // Stop ignoring spaces.
- addMidpoint(InlineIterator(0, o, 0)); // Start ignoring again.
+ addMidpoint(lineMidpointState, InlineIterator(0, o, 0)); // Stop ignoring spaces.
+ addMidpoint(lineMidpointState, InlineIterator(0, o, 0)); // Start ignoring again.
} else if (style()->collapseWhiteSpace() && resolver.position().obj == o
- && shouldSkipWhitespaceAfterStartObject(this, o)) {
+ && shouldSkipWhitespaceAfterStartObject(this, o, lineMidpointState)) {
// Like with list markers, we start ignoring spaces to make sure that any
// additional spaces we see will be discarded.
currentCharacterIsSpace = true;
@@ -1854,7 +1776,7 @@ InlineIterator RenderBlock::findNextLineBreak(InlineBidiResolver& resolver, bool
}
if (ignoringSpaces)
- addMidpoint(InlineIterator(0, o, 0));
+ addMidpoint(lineMidpointState, InlineIterator(0, o, 0));
isLineEmpty = false;
ignoringSpaces = false;
@@ -1864,8 +1786,8 @@ InlineIterator RenderBlock::findNextLineBreak(InlineBidiResolver& resolver, bool
// Optimize for a common case. If we can't find whitespace after the list
// item, then this is all moot. -dwh
- if (o->isListMarker() && !static_cast<RenderListMarker*>(o)->isInside()) {
- if (style()->collapseWhiteSpace() && shouldSkipWhitespaceAfterStartObject(this, o)) {
+ if (o->isListMarker() && !toRenderListMarker(o)->isInside()) {
+ if (style()->collapseWhiteSpace() && shouldSkipWhitespaceAfterStartObject(this, o, lineMidpointState)) {
// Like with inline flows, we start ignoring spaces to make sure that any
// additional spaces we see will be discarded.
currentCharacterIsSpace = true;
@@ -1928,10 +1850,11 @@ InlineIterator RenderBlock::findNextLineBreak(InlineBidiResolver& resolver, bool
else
beforeSoftHyphen = InlineIterator(0, last, last->isText() ? toRenderText(last)->textLength() - 1 : 0);
// Two consecutive soft hyphens. Avoid overlapping midpoints.
- if (sNumMidpoints && smidpoints->at(sNumMidpoints - 1).obj == o && smidpoints->at(sNumMidpoints - 1).pos == pos)
- sNumMidpoints--;
+ if (lineMidpointState.numMidpoints && lineMidpointState.midpoints[lineMidpointState.numMidpoints - 1].obj == o &&
+ lineMidpointState.midpoints[lineMidpointState.numMidpoints - 1].pos == pos)
+ lineMidpointState.numMidpoints--;
else
- addMidpoint(beforeSoftHyphen);
+ addMidpoint(lineMidpointState, beforeSoftHyphen);
// Add the width up to but not including the hyphen.
tmpW += textWidth(t, lastSpace, pos - lastSpace, f, w + tmpW, isFixedPitch, collapseWhiteSpace) + lastSpaceWordSpacing;
@@ -1943,7 +1866,7 @@ InlineIterator RenderBlock::findNextLineBreak(InlineBidiResolver& resolver, bool
InlineIterator afterSoftHyphen(0, o, pos);
afterSoftHyphen.increment();
- addMidpoint(afterSoftHyphen);
+ addMidpoint(lineMidpointState, afterSoftHyphen);
}
pos++;
@@ -1974,7 +1897,7 @@ InlineIterator RenderBlock::findNextLineBreak(InlineBidiResolver& resolver, bool
ignoringSpaces = false;
lastSpaceWordSpacing = 0;
lastSpace = pos; // e.g., "Foo goo", don't add in any of the ignored spaces.
- addMidpoint(InlineIterator(0, o, pos));
+ addMidpoint(lineMidpointState, InlineIterator(0, o, pos));
stoppedIgnoringSpaces = true;
} else {
// Just keep ignoring these spaces.
@@ -2012,15 +1935,15 @@ InlineIterator RenderBlock::findNextLineBreak(InlineBidiResolver& resolver, bool
lBreak.obj = o;
lBreak.pos = pos;
lBreak.nextBreakablePosition = nextBreakable;
- skipTrailingWhitespace(lBreak);
+ skipTrailingWhitespace(lBreak, isLineEmpty, previousLineBrokeCleanly);
}
}
if (lineWasTooWide || w + tmpW > width) {
if (lBreak.obj && shouldPreserveNewline(lBreak.obj) && lBreak.obj->isText() && !toRenderText(lBreak.obj)->isWordBreak() && toRenderText(lBreak.obj)->characters()[lBreak.pos] == '\n') {
if (!stoppedIgnoringSpaces && pos > 0) {
// We need to stop right before the newline and then start up again.
- addMidpoint(InlineIterator(0, o, pos - 1)); // Stop
- addMidpoint(InlineIterator(0, o, pos)); // Start
+ addMidpoint(lineMidpointState, InlineIterator(0, o, pos - 1)); // Stop
+ addMidpoint(lineMidpointState, InlineIterator(0, o, pos)); // Start
}
lBreak.increment();
previousLineBrokeCleanly = true;
@@ -2038,8 +1961,8 @@ InlineIterator RenderBlock::findNextLineBreak(InlineBidiResolver& resolver, bool
if (c == '\n' && preserveNewline) {
if (!stoppedIgnoringSpaces && pos > 0) {
// We need to stop right before the newline and then start up again.
- addMidpoint(InlineIterator(0, o, pos - 1)); // Stop
- addMidpoint(InlineIterator(0, o, pos)); // Start
+ addMidpoint(lineMidpointState, InlineIterator(0, o, pos - 1)); // Stop
+ addMidpoint(lineMidpointState, InlineIterator(0, o, pos)); // Start
}
lBreak.obj = o;
lBreak.pos = pos;
@@ -2085,7 +2008,7 @@ InlineIterator RenderBlock::findNextLineBreak(InlineBidiResolver& resolver, bool
// We just entered a mode where we are ignoring
// spaces. Create a midpoint to terminate the run
// before the second space.
- addMidpoint(ignoreStart);
+ addMidpoint(lineMidpointState, ignoreStart);
}
}
} else if (ignoringSpaces) {
@@ -2094,7 +2017,7 @@ InlineIterator RenderBlock::findNextLineBreak(InlineBidiResolver& resolver, bool
ignoringSpaces = false;
lastSpaceWordSpacing = applyWordSpacing ? wordSpacing : 0;
lastSpace = pos; // e.g., "Foo goo", don't add in any of the ignored spaces.
- addMidpoint(InlineIterator(0, o, pos));
+ addMidpoint(lineMidpointState, InlineIterator(0, o, pos));
}
if (currentCharacterIsSpace && !previousCharacterIsSpace) {
@@ -2183,7 +2106,7 @@ InlineIterator RenderBlock::findNextLineBreak(InlineBidiResolver& resolver, bool
if (!o->isFloatingOrPositioned()) {
last = o;
- if (last->isReplaced() && autoWrap && (!last->isImage() || allowImagesToBreak) && (!last->isListMarker() || static_cast<RenderListMarker*>(last)->isInside())) {
+ if (last->isReplaced() && autoWrap && (!last->isImage() || allowImagesToBreak) && (!last->isListMarker() || toRenderListMarker(last)->isInside())) {
w += tmpW;
tmpW = 0;
lBreak.obj = next;
@@ -2246,15 +2169,15 @@ InlineIterator RenderBlock::findNextLineBreak(InlineBidiResolver& resolver, bool
lBreak.increment();
// Sanity check our midpoints.
- checkMidpoints(lBreak);
+ checkMidpoints(lineMidpointState, lBreak);
if (trailingSpaceObject) {
// This object is either going to be part of the last midpoint, or it is going
// to be the actual endpoint. In both cases we just decrease our pos by 1 level to
// exclude the space, allowing it to - in effect - collapse into the newline.
- if (sNumMidpoints%2==1) {
- InlineIterator* midpoints = smidpoints->data();
- midpoints[sNumMidpoints-1].pos--;
+ if (lineMidpointState.numMidpoints % 2) {
+ InlineIterator* midpoints = lineMidpointState.midpoints.data();
+ midpoints[lineMidpointState.numMidpoints - 1].pos--;
}
//else if (lBreak.pos > 0)
// lBreak.pos--;
@@ -2264,7 +2187,7 @@ InlineIterator RenderBlock::findNextLineBreak(InlineBidiResolver& resolver, bool
unsigned length = text->textLength();
unsigned pos = length >= 2 ? length - 2 : UINT_MAX;
InlineIterator endMid(0, trailingSpaceObject, pos);
- addMidpoint(endMid);
+ addMidpoint(lineMidpointState, endMid);
}
}
@@ -2280,9 +2203,9 @@ InlineIterator RenderBlock::findNextLineBreak(InlineBidiResolver& resolver, bool
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 = toRenderText(lBreak.obj)->characters()[lBreak.pos-1];
+ UChar c = toRenderText(lBreak.obj)->characters()[lBreak.pos - 1];
if (c == softHyphen)
- chopMidpointsAt(lBreak.obj, lBreak.pos-2);
+ chopMidpointsAt(lineMidpointState, lBreak.obj, lBreak.pos - 2);
}
return lBreak;
diff --git a/WebCore/rendering/RenderBox.cpp b/WebCore/rendering/RenderBox.cpp
index 9eb5898..4c2bff0 100644
--- a/WebCore/rendering/RenderBox.cpp
+++ b/WebCore/rendering/RenderBox.cpp
@@ -3,7 +3,7 @@
* (C) 1999 Antti Koivisto (koivisto@kde.org)
* (C) 2005 Allan Sandfeld Jensen (kde@carewolf.com)
* (C) 2005, 2006 Samuel Weinig (sam.weinig@gmail.com)
- * Copyright (C) 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -254,22 +254,22 @@ 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 layer()->scrollWidth();
- return overflowWidth();
+ // For objects with visible overflow, this matches IE.
+ if (style()->direction() == LTR)
+ return max(clientWidth(), rightmostPosition(true, false) - borderLeft());
+ return clientWidth() - min(0, leftmostPosition(true, false) - borderLeft());
}
int RenderBox::scrollHeight() const
{
if (hasOverflowClip())
return layer()->scrollHeight();
- return overflowHeight();
+ // For objects with visible overflow, this matches IE.
+ return max(clientHeight(), lowestPosition(true, false) - borderTop());
}
int RenderBox::scrollLeft() const
@@ -588,9 +588,7 @@ void RenderBox::paintRootBoxDecorations(PaintInfo& paintInfo, int tx, int ty)
int bw = max(w + marginLeft() + marginRight() + borderLeft() + borderRight(), rw);
int bh = max(h + marginTop() + marginBottom() + borderTop() + borderBottom(), rh);
- int my = max(by, paintInfo.rect.y());
-
- paintFillLayers(paintInfo, bgColor, bgLayer, my, paintInfo.rect.height(), bx, by, bw, bh);
+ paintFillLayers(paintInfo, bgColor, bgLayer, bx, by, bw, bh);
if (style()->hasBorder() && style()->display() != INLINE)
paintBorder(paintInfo.context, tx, ty, w, h, style());
@@ -613,16 +611,9 @@ void RenderBox::paintBoxDecorations(PaintInfo& paintInfo, int tx, int ty)
// balloon layout is an example of this).
borderFitAdjust(tx, w);
- int my = max(ty, paintInfo.rect.y());
- int mh;
- if (ty < paintInfo.rect.y())
- mh = max(0, h - (paintInfo.rect.y() - ty));
- else
- mh = min(paintInfo.rect.height(), h);
-
// FIXME: Should eventually give the theme control over whether the box shadow should paint, since controls could have
// custom shadows of their own.
- paintBoxShadow(paintInfo.context, tx, ty, w, h, style());
+ paintBoxShadow(paintInfo.context, tx, ty, w, h, style(), Normal);
// If we have a native theme appearance, paint that before painting our background.
// The theme will tell us whether or not we should also paint the CSS background.
@@ -632,10 +623,11 @@ void RenderBox::paintBoxDecorations(PaintInfo& paintInfo, int tx, int ty)
// independent of the body. Go through the DOM to get to the root element's render object,
// since the root could be inline and wrapped in an anonymous block.
if (!isBody() || document()->documentElement()->renderer()->style()->hasBackground())
- paintFillLayers(paintInfo, style()->backgroundColor(), style()->backgroundLayers(), my, mh, tx, ty, w, h);
+ paintFillLayers(paintInfo, style()->backgroundColor(), style()->backgroundLayers(), tx, ty, w, h);
if (style()->hasAppearance())
theme()->paintDecorations(this, paintInfo, IntRect(tx, ty, w, h));
}
+ paintBoxShadow(paintInfo.context, tx, ty, w, h, style(), Inset);
// The theme will tell us whether or not we should also paint the CSS border.
if ((!style()->hasAppearance() || (!themePainted && theme()->paintBorderOnly(this, paintInfo, IntRect(tx, ty, w, h)))) && style()->hasBorder())
@@ -654,17 +646,10 @@ void RenderBox::paintMask(PaintInfo& paintInfo, int tx, int ty)
// balloon layout is an example of this).
borderFitAdjust(tx, w);
- int my = max(ty, paintInfo.rect.y());
- int mh;
- if (ty < paintInfo.rect.y())
- mh = max(0, h - (paintInfo.rect.y() - ty));
- else
- mh = min(paintInfo.rect.height(), h);
-
- paintMaskImages(paintInfo, my, mh, tx, ty, w, h);
+ paintMaskImages(paintInfo, tx, ty, w, h);
}
-void RenderBox::paintMaskImages(const PaintInfo& paintInfo, int my, int mh, int tx, int ty, int w, int h)
+void RenderBox::paintMaskImages(const PaintInfo& paintInfo, int tx, int ty, int w, int h)
{
// Figure out if we need to push a transparency layer to render our mask.
bool pushTransparencyLayer = false;
@@ -695,7 +680,7 @@ void RenderBox::paintMaskImages(const PaintInfo& paintInfo, int my, int mh, int
compositeOp = CompositeSourceOver;
}
- paintFillLayers(paintInfo, Color(), style()->maskLayers(), my, mh, tx, ty, w, h, compositeOp);
+ paintFillLayers(paintInfo, Color(), style()->maskLayers(), tx, ty, w, h, compositeOp);
paintNinePieceImage(paintInfo.context, tx, ty, w, h, style(), style()->maskBoxImage(), compositeOp);
if (pushTransparencyLayer)
@@ -721,20 +706,18 @@ IntRect RenderBox::maskClipRect()
return result;
}
-void RenderBox::paintFillLayers(const PaintInfo& paintInfo, const Color& c, const FillLayer* fillLayer,
- int clipY, int clipH, int tx, int ty, int width, int height, CompositeOperator op)
+void RenderBox::paintFillLayers(const PaintInfo& paintInfo, const Color& c, const FillLayer* fillLayer, int tx, int ty, int width, int height, CompositeOperator op)
{
if (!fillLayer)
return;
- paintFillLayers(paintInfo, c, fillLayer->next(), clipY, clipH, tx, ty, width, height, op);
- paintFillLayer(paintInfo, c, fillLayer, clipY, clipH, tx, ty, width, height, op);
+ paintFillLayers(paintInfo, c, fillLayer->next(), tx, ty, width, height, op);
+ paintFillLayer(paintInfo, c, fillLayer, tx, ty, width, height, op);
}
-void RenderBox::paintFillLayer(const PaintInfo& paintInfo, const Color& c, const FillLayer* fillLayer,
- int clipY, int clipH, int tx, int ty, int width, int height, CompositeOperator op)
+void RenderBox::paintFillLayer(const PaintInfo& paintInfo, const Color& c, const FillLayer* fillLayer, int tx, int ty, int width, int height, CompositeOperator op)
{
- paintFillLayerExtended(paintInfo, c, fillLayer, clipY, clipH, tx, ty, width, height, 0, op);
+ paintFillLayerExtended(paintInfo, c, fillLayer, tx, ty, width, height, 0, op);
}
void RenderBox::imageChanged(WrappedImagePtr image, const IntRect*)
@@ -1567,7 +1550,7 @@ int RenderBox::calcPercentageHeight(const Length& height)
// no size and allow the flexing of the table or the cell to its specified height to cause us
// to grow to fill the space. This could end up being wrong in some cases, but it is
// preferable to the alternative (sizing intrinsically and making the row end up too big).
- RenderTableCell* cell = static_cast<RenderTableCell*>(cb);
+ RenderTableCell* cell = toRenderTableCell(cb);
if (scrollsOverflowY() && (!cell->style()->height().isAuto() || !cell->table()->style()->height().isAuto()))
return 0;
return -1;
@@ -1631,7 +1614,7 @@ int RenderBox::calcReplacedWidthUsing(Length width) const
default:
return intrinsicSize().width();
}
- }
+}
int RenderBox::calcReplacedHeight() const
{
diff --git a/WebCore/rendering/RenderBox.h b/WebCore/rendering/RenderBox.h
index ba96f01..cb2297b 100644
--- a/WebCore/rendering/RenderBox.h
+++ b/WebCore/rendering/RenderBox.h
@@ -251,7 +251,7 @@ public:
virtual void paintObject(PaintInfo&, int /*tx*/, int /*ty*/) { ASSERT_NOT_REACHED(); }
virtual void paintBoxDecorations(PaintInfo&, int tx, int ty);
- virtual void paintMask(PaintInfo& paintInfo, int tx, int ty);
+ virtual void paintMask(PaintInfo&, int tx, int ty);
virtual void imageChanged(WrappedImagePtr, const IntRect* = 0);
// Called when a positioned object moves but doesn't change size. A simplified layout is done
@@ -288,10 +288,10 @@ protected:
virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
virtual void updateBoxModelInfoFromStyle();
- void paintFillLayer(const PaintInfo&, const Color&, const FillLayer*, int clipY, int clipHeight, int tx, int ty, int width, int height, CompositeOperator = CompositeSourceOver);
- void paintFillLayers(const PaintInfo&, const Color&, const FillLayer*, int clipY, int clipHeight, int tx, int ty, int width, int height, CompositeOperator = CompositeSourceOver);
+ void paintFillLayer(const PaintInfo&, const Color&, const FillLayer*, int tx, int ty, int width, int height, CompositeOperator = CompositeSourceOver);
+ void paintFillLayers(const PaintInfo&, const Color&, const FillLayer*, int tx, int ty, int width, int height, CompositeOperator = CompositeSourceOver);
- void paintMaskImages(const PaintInfo&, int clipY, int clipHeight, int tx, int ty, int width, int height);
+ void paintMaskImages(const PaintInfo&, int tx, int ty, int width, int height);
#if PLATFORM(MAC)
void paintCustomHighlight(int tx, int ty, const AtomicString& type, bool behindText);
@@ -365,16 +365,16 @@ private:
static bool s_hadOverflowClip;
};
-inline RenderBox* toRenderBox(RenderObject* o)
+inline RenderBox* toRenderBox(RenderObject* object)
{
- ASSERT(!o || o->isBox());
- return static_cast<RenderBox*>(o);
+ ASSERT(!object || object->isBox());
+ return static_cast<RenderBox*>(object);
}
-inline const RenderBox* toRenderBox(const RenderObject* o)
+inline const RenderBox* toRenderBox(const RenderObject* object)
{
- ASSERT(!o || o->isBox());
- return static_cast<const RenderBox*>(o);
+ ASSERT(!object || object->isBox());
+ return static_cast<const RenderBox*>(object);
}
// This will catch anyone doing an unnecessary cast.
diff --git a/WebCore/rendering/RenderBoxModelObject.cpp b/WebCore/rendering/RenderBoxModelObject.cpp
index 7ad1a5e..3a7ff71 100644
--- a/WebCore/rendering/RenderBoxModelObject.cpp
+++ b/WebCore/rendering/RenderBoxModelObject.cpp
@@ -173,13 +173,20 @@ void RenderBoxModelObject::updateBoxModelInfoFromStyle()
int RenderBoxModelObject::relativePositionOffsetX() const
{
+ // Objects that shrink to avoid floats normally use available line width when computing containing block width. However
+ // in the case of relative positioning using percentages, we can't do this. The offset should always be resolved using the
+ // available width of the containing block. Therefore we don't use containingBlockWidthForContent() here, but instead explicitly
+ // call availableWidth on our containing block.
if (!style()->left().isAuto()) {
+ RenderBlock* cb = containingBlock();
if (!style()->right().isAuto() && containingBlock()->style()->direction() == RTL)
- return -style()->right().calcValue(containingBlockWidthForContent());
- return style()->left().calcValue(containingBlockWidthForContent());
+ return -style()->right().calcValue(cb->availableWidth());
+ return style()->left().calcValue(cb->availableWidth());
+ }
+ if (!style()->right().isAuto()) {
+ RenderBlock* cb = containingBlock();
+ return -style()->right().calcValue(cb->availableWidth());
}
- if (!style()->right().isAuto())
- return -style()->right().calcValue(containingBlockWidthForContent());
return 0;
}
@@ -297,8 +304,7 @@ int RenderBoxModelObject::paddingRight(bool) const
}
-void RenderBoxModelObject::paintFillLayerExtended(const PaintInfo& paintInfo, const Color& c, const FillLayer* bgLayer, int clipY, int clipH,
- int tx, int ty, int w, int h, InlineFlowBox* box, CompositeOperator op)
+void RenderBoxModelObject::paintFillLayerExtended(const PaintInfo& paintInfo, const Color& c, const FillLayer* bgLayer, int tx, int ty, int w, int h, InlineFlowBox* box, CompositeOperator op)
{
GraphicsContext* context = paintInfo.context;
bool includeLeftEdge = box ? box->includeLeftEdge() : true;
@@ -323,6 +329,18 @@ void RenderBoxModelObject::paintFillLayerExtended(const PaintInfo& paintInfo, co
clippedToBorderRadius = true;
}
+ bool clippedWithLocalScrolling = hasOverflowClip() && bgLayer->attachment() == LocalBackgroundAttachment;
+ if (clippedWithLocalScrolling) {
+ // Clip to the overflow area.
+ context->save();
+ context->clip(toRenderBox(this)->overflowClipRect(tx, ty));
+
+ // Now adjust our tx, ty, w, h to reflect a scrolled content box with borders at the ends.
+ layer()->subtractScrolledContentOffset(tx, ty);
+ w = bLeft + layer()->scrollWidth() + bRight;
+ h = borderTop() + layer()->scrollHeight() + borderBottom();
+ }
+
if (bgLayer->clip() == PaddingFillBox || bgLayer->clip() == ContentFillBox) {
// Clip to the padding or content boxes as necessary.
bool includePadding = bgLayer->clip() == ContentFillBox;
@@ -340,7 +358,7 @@ void RenderBoxModelObject::paintFillLayerExtended(const PaintInfo& paintInfo, co
maskRect.intersect(paintInfo.rect);
// Now create the mask.
- OwnPtr<ImageBuffer> maskImage = ImageBuffer::create(maskRect.size(), false);
+ OwnPtr<ImageBuffer> maskImage = ImageBuffer::create(maskRect.size());
if (!maskImage)
return;
@@ -411,7 +429,8 @@ void RenderBoxModelObject::paintFillLayerExtended(const PaintInfo& paintInfo, co
// Paint the color first underneath all images.
if (!bgLayer->next()) {
- IntRect rect(tx, clipY, w, clipH);
+ IntRect rect(tx, ty, w, h);
+ rect.intersect(paintInfo.rect);
// If we have an alpha and we are painting the root element, go ahead and blend with the base background color.
if (isOpaqueRoot) {
Color baseColor = view()->frameView()->baseBackgroundColor();
@@ -469,6 +488,9 @@ void RenderBoxModelObject::paintFillLayerExtended(const PaintInfo& paintInfo, co
if (clippedToBorderRadius)
// Undo the border radius clip
context->restore();
+
+ if (clippedWithLocalScrolling) // Undo the clip for local background attachments.
+ context->restore();
}
IntSize RenderBoxModelObject::calculateBackgroundSize(const FillLayer* bgLayer, int scaledWidth, int scaledHeight) const
@@ -525,9 +547,9 @@ void RenderBoxModelObject::calculateBackgroundImageGeometry(const FillLayer* bgL
int rh = 0;
// CSS2 chapter 14.2.1
-
- if (bgLayer->attachment()) {
- // Scroll
+ bool fixedAttachment = bgLayer->attachment() == FixedBackgroundAttachment;
+ if (!fixedAttachment) {
+ // Scroll and Local
if (bgLayer->origin() != BorderFillBox) {
left = borderLeft();
right = borderRight();
@@ -557,7 +579,7 @@ void RenderBoxModelObject::calculateBackgroundImageGeometry(const FillLayer* bgL
pw = w - left - right;
ph = h - top - bottom;
} else {
- // Fixed
+ // Fixed background attachment.
IntRect vr = viewRect();
cx = vr.x();
cy = vr.y();
@@ -571,7 +593,7 @@ void RenderBoxModelObject::calculateBackgroundImageGeometry(const FillLayer* bgL
int ch;
IntSize scaledImageSize;
- if (isRoot() && bgLayer->attachment())
+ if (isRoot() && !fixedAttachment)
scaledImageSize = calculateBackgroundSize(bgLayer, rw, rh);
else
scaledImageSize = calculateBackgroundSize(bgLayer, pw, ph);
@@ -582,7 +604,7 @@ void RenderBoxModelObject::calculateBackgroundImageGeometry(const FillLayer* bgL
EFillRepeat backgroundRepeat = bgLayer->repeat();
int xPosition;
- if (isRoot() && bgLayer->attachment())
+ if (isRoot() && !fixedAttachment)
xPosition = bgLayer->xPosition().calcMinValue(rw - scaledImageWidth, true);
else
xPosition = bgLayer->xPosition().calcMinValue(pw - scaledImageWidth, true);
@@ -596,7 +618,7 @@ void RenderBoxModelObject::calculateBackgroundImageGeometry(const FillLayer* bgL
}
int yPosition;
- if (isRoot() && bgLayer->attachment())
+ if (isRoot() && !fixedAttachment)
yPosition = bgLayer->yPosition().calcMinValue(rh - scaledImageHeight, true);
else
yPosition = bgLayer->yPosition().calcMinValue(ph - scaledImageHeight, true);
@@ -609,7 +631,7 @@ void RenderBoxModelObject::calculateBackgroundImageGeometry(const FillLayer* bgL
ch = scaledImageHeight + min(yPosition + top, 0);
}
- if (!bgLayer->attachment()) {
+ if (fixedAttachment) {
sx += max(tx - cx, 0);
sy += max(ty - cy, 0);
}
@@ -1124,52 +1146,209 @@ void RenderBoxModelObject::paintBorder(GraphicsContext* graphicsContext, int tx,
graphicsContext->restore();
}
-void RenderBoxModelObject::paintBoxShadow(GraphicsContext* context, int tx, int ty, int w, int h, const RenderStyle* s, bool begin, bool end)
+void RenderBoxModelObject::paintBoxShadow(GraphicsContext* context, int tx, int ty, int w, int h, const RenderStyle* s, ShadowStyle shadowStyle, bool begin, bool end)
{
// FIXME: Deal with border-image. Would be great to use border-image as a mask.
+ if (context->paintingDisabled())
+ return;
+
IntRect rect(tx, ty, w, h);
+ IntSize topLeft;
+ IntSize topRight;
+ IntSize bottomLeft;
+ IntSize bottomRight;
+
bool hasBorderRadius = s->hasBorderRadius();
+ if (hasBorderRadius && (begin || end)) {
+ IntSize topLeftRadius, topRightRadius, bottomLeftRadius, bottomRightRadius;
+ s->getBorderRadiiForRect(rect, topLeftRadius, topRightRadius, bottomLeftRadius, bottomRightRadius);
+
+ if (begin) {
+ if (shadowStyle == Inset) {
+ topLeftRadius.expand(-borderLeft(), -borderTop());
+ topLeftRadius.clampNegativeToZero();
+ bottomLeftRadius.expand(-borderLeft(), -borderBottom());
+ bottomLeftRadius.clampNegativeToZero();
+ }
+ topLeft = topLeftRadius;
+ bottomLeft = bottomLeftRadius;
+ }
+ if (end) {
+ if (shadowStyle == Inset) {
+ topRightRadius.expand(-borderRight(), -borderTop());
+ topRightRadius.clampNegativeToZero();
+ bottomRightRadius.expand(-borderRight(), -borderBottom());
+ bottomRightRadius.clampNegativeToZero();
+ }
+ topRight = topRightRadius;
+ bottomRight = bottomRightRadius;
+ }
+ }
+
+ if (shadowStyle == Inset) {
+ rect.move(begin ? borderLeft() : 0, borderTop());
+ rect.setWidth(rect.width() - (begin ? borderLeft() : 0) - (end ? borderRight() : 0));
+ rect.setHeight(rect.height() - borderTop() - borderBottom());
+ }
+
bool hasOpaqueBackground = s->backgroundColor().isValid() && s->backgroundColor().alpha() == 255;
for (ShadowData* shadow = s->boxShadow(); shadow; shadow = shadow->next) {
- context->save();
+ if (shadow->style != shadowStyle)
+ continue;
IntSize shadowOffset(shadow->x, shadow->y);
int shadowBlur = shadow->blur;
- IntRect fillRect(rect);
+ int shadowSpread = shadow->spread;
+ Color& shadowColor = shadow->color;
+
+ if (shadow->style == Normal) {
+ IntRect fillRect(rect);
+ fillRect.inflate(shadowSpread);
+ if (fillRect.isEmpty())
+ continue;
- if (hasBorderRadius) {
IntRect shadowRect(rect);
- shadowRect.inflate(shadowBlur);
+ shadowRect.inflate(shadowBlur + shadowSpread);
shadowRect.move(shadowOffset);
+
+ context->save();
context->clip(shadowRect);
// Move the fill just outside the clip, adding 1 pixel separation so that the fill does not
// bleed in (due to antialiasing) if the context is transformed.
- IntSize extraOffset(w + max(0, shadowOffset.width()) + shadowBlur + 1, 0);
+ IntSize extraOffset(w + max(0, shadowOffset.width()) + shadowBlur + 2 * shadowSpread + 1, 0);
shadowOffset -= extraOffset;
fillRect.move(extraOffset);
- }
- context->setShadow(shadowOffset, shadowBlur, shadow->color);
- if (hasBorderRadius) {
- IntSize topLeftRadius, topRightRadius, bottomLeftRadius, bottomRightRadius;
- s->getBorderRadiiForRect(rect, topLeftRadius, topRightRadius, bottomLeftRadius, bottomRightRadius);
+ context->setShadow(shadowOffset, shadowBlur, shadowColor);
+ if (hasBorderRadius) {
+ IntRect rectToClipOut = rect;
+ IntSize topLeftToClipOut = topLeft;
+ IntSize topRightToClipOut = topRight;
+ IntSize bottomLeftToClipOut = bottomLeft;
+ IntSize bottomRightToClipOut = bottomRight;
+
+ if (shadowSpread < 0) {
+ topLeft.expand(shadowSpread, shadowSpread);
+ topLeft.clampNegativeToZero();
- IntSize topLeft = begin ? topLeftRadius : IntSize();
- IntSize topRight = end ? topRightRadius : IntSize();
- IntSize bottomLeft = begin ? bottomLeftRadius : IntSize();
- IntSize bottomRight = end ? bottomRightRadius : IntSize();
+ topRight.expand(shadowSpread, shadowSpread);
+ topRight.clampNegativeToZero();
- if (!hasOpaqueBackground)
- context->clipOutRoundedRect(rect, topLeft, topRight, bottomLeft, bottomRight);
- context->fillRoundedRect(fillRect, topLeft, topRight, bottomLeft, bottomRight, Color::black);
+ bottomLeft.expand(shadowSpread, shadowSpread);
+ bottomLeft.clampNegativeToZero();
+
+ bottomRight.expand(shadowSpread, shadowSpread);
+ bottomRight.clampNegativeToZero();
+ }
+
+ // If the box is opaque, it is unnecessary to clip it out. However, doing so saves time
+ // when painting the shadow. On the other hand, it introduces subpixel gaps along the
+ // corners. Those are avoided by insetting the clipping path by one pixel.
+ if (hasOpaqueBackground) {
+ rectToClipOut.inflate(-1);
+
+ topLeftToClipOut.expand(-1, -1);
+ topLeftToClipOut.clampNegativeToZero();
+
+ topRightToClipOut.expand(-1, -1);
+ topRightToClipOut.clampNegativeToZero();
+
+ bottomLeftToClipOut.expand(-1, -1);
+ bottomLeftToClipOut.clampNegativeToZero();
+
+ bottomRightToClipOut.expand(-1, -1);
+ bottomRightToClipOut.clampNegativeToZero();
+ }
+
+ if (!rectToClipOut.isEmpty())
+ context->clipOutRoundedRect(rectToClipOut, topLeftToClipOut, topRightToClipOut, bottomLeftToClipOut, bottomRightToClipOut);
+ context->fillRoundedRect(fillRect, topLeft, topRight, bottomLeft, bottomRight, Color::black);
+ } else {
+ IntRect rectToClipOut = rect;
+
+ // If the box is opaque, it is unnecessary to clip it out. However, doing so saves time
+ // when painting the shadow. On the other hand, it introduces subpixel gaps along the
+ // edges if they are not pixel-aligned. Those are avoided by insetting the clipping path
+ // by one pixel.
+ if (hasOpaqueBackground) {
+ TransformationMatrix currentTransformation = context->getCTM();
+ if (currentTransformation.a() != 1 || (currentTransformation.d() != 1 && currentTransformation.d() != -1)
+ || currentTransformation.b() || currentTransformation.c())
+ rectToClipOut.inflate(-1);
+ }
+
+ if (!rectToClipOut.isEmpty())
+ context->clipOut(rectToClipOut);
+ context->fillRect(fillRect, Color::black);
+ }
+
+ context->restore();
} else {
- if (!hasOpaqueBackground)
- context->clipOut(rect);
- context->fillRect(fillRect, Color::black);
+ // Inset shadow.
+ IntRect holeRect(rect);
+ holeRect.inflate(-shadowSpread);
+
+ if (holeRect.isEmpty()) {
+ if (hasBorderRadius)
+ context->fillRoundedRect(rect, topLeft, topRight, bottomLeft, bottomRight, shadowColor);
+ else
+ context->fillRect(rect, shadowColor);
+ continue;
+ }
+ if (!begin) {
+ holeRect.move(-max(shadowOffset.width(), 0) - shadowBlur, 0);
+ holeRect.setWidth(holeRect.width() + max(shadowOffset.width(), 0) + shadowBlur);
+ }
+ if (!end)
+ holeRect.setWidth(holeRect.width() - min(shadowOffset.width(), 0) + shadowBlur);
+
+ Color fillColor(shadowColor.red(), shadowColor.green(), shadowColor.blue(), 255);
+
+ IntRect outerRect(rect);
+ outerRect.inflateX(w - 2 * shadowSpread);
+ outerRect.inflateY(h - 2 * shadowSpread);
+
+ context->save();
+
+ if (hasBorderRadius)
+ context->clip(Path::createRoundedRectangle(rect, topLeft, topRight, bottomLeft, bottomRight));
+ else
+ context->clip(rect);
+
+ IntSize extraOffset(2 * w + max(0, shadowOffset.width()) + shadowBlur - 2 * shadowSpread + 1, 0);
+ context->translate(extraOffset.width(), extraOffset.height());
+ shadowOffset -= extraOffset;
+
+ context->beginPath();
+ context->addPath(Path::createRectangle(outerRect));
+
+ if (hasBorderRadius) {
+ if (shadowSpread > 0) {
+ topLeft.expand(-shadowSpread, -shadowSpread);
+ topLeft.clampNegativeToZero();
+
+ topRight.expand(-shadowSpread, -shadowSpread);
+ topRight.clampNegativeToZero();
+
+ bottomLeft.expand(-shadowSpread, -shadowSpread);
+ bottomLeft.clampNegativeToZero();
+
+ bottomRight.expand(-shadowSpread, -shadowSpread);
+ bottomRight.clampNegativeToZero();
+ }
+ context->addPath(Path::createRoundedRectangle(holeRect, topLeft, topRight, bottomLeft, bottomRight));
+ } else
+ context->addPath(Path::createRectangle(holeRect));
+
+ context->setFillRule(RULE_EVENODD);
+ context->setFillColor(fillColor);
+ context->setShadow(shadowOffset, shadowBlur, shadowColor);
+ context->fillPath();
+
+ context->restore();
}
- context->restore();
}
}
diff --git a/WebCore/rendering/RenderBoxModelObject.h b/WebCore/rendering/RenderBoxModelObject.h
index f2c6326..baa5ecb 100644
--- a/WebCore/rendering/RenderBoxModelObject.h
+++ b/WebCore/rendering/RenderBoxModelObject.h
@@ -89,9 +89,8 @@ public:
void paintBorder(GraphicsContext*, int tx, int ty, int w, int h, const RenderStyle*, bool begin = true, bool end = true);
bool paintNinePieceImage(GraphicsContext*, int tx, int ty, int w, int h, const RenderStyle*, const NinePieceImage&, CompositeOperator = CompositeSourceOver);
- void paintBoxShadow(GraphicsContext*, int tx, int ty, int w, int h, const RenderStyle*, bool begin = true, bool end = true);
- 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);
+ void paintBoxShadow(GraphicsContext*, int tx, int ty, int w, int h, const RenderStyle*, ShadowStyle, bool begin = true, bool end = true);
+ void paintFillLayerExtended(const PaintInfo&, const Color&, const FillLayer*, int tx, int ty, int width, int height, InlineFlowBox* = 0, CompositeOperator = CompositeSourceOver);
// The difference between this inline's baseline position and the line's baseline position.
int verticalPosition(bool firstLine) const;
@@ -115,16 +114,16 @@ private:
static bool s_layerWasSelfPainting;
};
-inline RenderBoxModelObject* toRenderBoxModelObject(RenderObject* o)
+inline RenderBoxModelObject* toRenderBoxModelObject(RenderObject* object)
{
- ASSERT(!o || o->isBoxModelObject());
- return static_cast<RenderBoxModelObject*>(o);
+ ASSERT(!object || object->isBoxModelObject());
+ return static_cast<RenderBoxModelObject*>(object);
}
-inline const RenderBoxModelObject* toRenderBoxModelObject(const RenderObject* o)
+inline const RenderBoxModelObject* toRenderBoxModelObject(const RenderObject* object)
{
- ASSERT(!o || o->isBoxModelObject());
- return static_cast<const RenderBoxModelObject*>(o);
+ ASSERT(!object || object->isBoxModelObject());
+ return static_cast<const RenderBoxModelObject*>(object);
}
// This will catch anyone doing an unnecessary cast.
diff --git a/WebCore/rendering/RenderButton.cpp b/WebCore/rendering/RenderButton.cpp
index b266f42..6d36a0f 100644
--- a/WebCore/rendering/RenderButton.cpp
+++ b/WebCore/rendering/RenderButton.cpp
@@ -164,6 +164,11 @@ void RenderButton::setText(const String& str)
}
}
+String RenderButton::text() const
+{
+ return m_buttonText ? m_buttonText->text() : 0;
+}
+
void RenderButton::updateBeforeAfterContent(PseudoId type)
{
if (m_inner)
diff --git a/WebCore/rendering/RenderButton.h b/WebCore/rendering/RenderButton.h
index 89f7cf8..3a74589 100644
--- a/WebCore/rendering/RenderButton.h
+++ b/WebCore/rendering/RenderButton.h
@@ -55,7 +55,8 @@ public:
virtual IntRect controlClipRect(int /*tx*/, int /*ty*/) const;
void setText(const String&);
-
+ String text() const;
+
virtual bool canHaveChildren() const;
protected:
@@ -73,16 +74,16 @@ protected:
bool m_default;
};
-inline RenderButton* toRenderButton(RenderObject* o)
+inline RenderButton* toRenderButton(RenderObject* object)
{
- ASSERT(!o || o->isRenderButton());
- return static_cast<RenderButton*>(o);
+ ASSERT(!object || object->isRenderButton());
+ return static_cast<RenderButton*>(object);
}
-inline const RenderButton* toRenderButton(const RenderObject* o)
+inline const RenderButton* toRenderButton(const RenderObject* object)
{
- ASSERT(!o || o->isRenderButton());
- return static_cast<const RenderButton*>(o);
+ ASSERT(!object || object->isRenderButton());
+ return static_cast<const RenderButton*>(object);
}
// This will catch anyone doing an unnecessary cast.
diff --git a/WebCore/rendering/RenderCounter.cpp b/WebCore/rendering/RenderCounter.cpp
index fd6d80d..67e5cba 100644
--- a/WebCore/rendering/RenderCounter.cpp
+++ b/WebCore/rendering/RenderCounter.cpp
@@ -107,8 +107,8 @@ static bool planCounter(RenderObject* object, const AtomicString& counterName, b
if (counterName == "list-item") {
if (object->isListItem()) {
- if (static_cast<RenderListItem*>(object)->hasExplicitValue()) {
- value = static_cast<RenderListItem*>(object)->explicitValue();
+ if (toRenderListItem(object)->hasExplicitValue()) {
+ value = toRenderListItem(object)->explicitValue();
isReset = true;
return true;
}
diff --git a/WebCore/rendering/RenderCounter.h b/WebCore/rendering/RenderCounter.h
index 55aab73..961968e 100644
--- a/WebCore/rendering/RenderCounter.h
+++ b/WebCore/rendering/RenderCounter.h
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2004 Allan Sandfeld Jensen (kde@carewolf.com)
- * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -33,21 +33,30 @@ class RenderCounter : public RenderText {
public:
RenderCounter(Document*, const CounterContent&);
+ void invalidate();
+
+ static void destroyCounterNodes(RenderObject*);
+
+private:
virtual const char* renderName() const;
virtual bool isCounter() const;
virtual PassRefPtr<StringImpl> originalText() const;
virtual void calcPrefWidths(int leadWidth);
- void invalidate();
-
- static void destroyCounterNodes(RenderObject*);
-
-private:
CounterContent m_counter;
mutable CounterNode* m_counterNode;
};
+inline RenderCounter* toRenderCounter(RenderObject* object)
+{
+ ASSERT(!object || object->isCounter());
+ return static_cast<RenderCounter*>(object);
+}
+
+// This will catch anyone doing an unnecessary cast.
+void toRenderCounter(const RenderCounter*);
+
} // namespace WebCore
#endif // RenderCounter_h
diff --git a/WebCore/rendering/RenderDataGrid.cpp b/WebCore/rendering/RenderDataGrid.cpp
new file mode 100644
index 0000000..bdf723f
--- /dev/null
+++ b/WebCore/rendering/RenderDataGrid.cpp
@@ -0,0 +1,250 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if ENABLE(DATAGRID)
+
+#include "RenderDataGrid.h"
+
+#include "CSSStyleSelector.h"
+#include "FocusController.h"
+#include "Frame.h"
+#include "GraphicsContext.h"
+#include "Page.h"
+#include "RenderView.h"
+#include "Scrollbar.h"
+
+using std::min;
+
+namespace WebCore {
+
+static const int cDefaultWidth = 300;
+
+RenderDataGrid::RenderDataGrid(Element* elt)
+ : RenderBlock(elt)
+{
+}
+
+RenderDataGrid::~RenderDataGrid()
+{
+}
+
+void RenderDataGrid::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
+{
+ RenderBlock::styleDidChange(diff, oldStyle);
+ recalcStyleForColumns();
+}
+
+void RenderDataGrid::recalcStyleForColumns()
+{
+ DataGridColumnList* columns = gridElement()->columns();
+ unsigned length = columns->length();
+ for (unsigned i = 0; i < length; ++i)
+ recalcStyleForColumn(columns->item(i));
+}
+
+void RenderDataGrid::recalcStyleForColumn(DataGridColumn* column)
+{
+ if (!column->columnStyle())
+ column->setColumnStyle(document()->styleSelector()->pseudoStyleForDataGridColumn(column, style()));
+ if (!column->headerStyle())
+ column->setHeaderStyle(document()->styleSelector()->pseudoStyleForDataGridColumnHeader(column, style()));
+}
+
+RenderStyle* RenderDataGrid::columnStyle(DataGridColumn* column)
+{
+ if (!column->columnStyle())
+ recalcStyleForColumn(column);
+ return column->columnStyle();
+}
+
+RenderStyle* RenderDataGrid::headerStyle(DataGridColumn* column)
+{
+ if (!column->headerStyle())
+ recalcStyleForColumn(column);
+ return column->headerStyle();
+}
+
+void RenderDataGrid::calcPrefWidths()
+{
+ m_minPrefWidth = 0;
+ m_maxPrefWidth = 0;
+
+ if (style()->width().isFixed() && style()->width().value() > 0)
+ m_minPrefWidth = m_maxPrefWidth = calcContentBoxWidth(style()->width().value());
+ else
+ m_maxPrefWidth = calcContentBoxWidth(cDefaultWidth);
+
+ if (style()->minWidth().isFixed() && style()->minWidth().value() > 0) {
+ m_maxPrefWidth = max(m_maxPrefWidth, calcContentBoxWidth(style()->minWidth().value()));
+ m_minPrefWidth = max(m_minPrefWidth, calcContentBoxWidth(style()->minWidth().value()));
+ } else if (style()->width().isPercent() || (style()->width().isAuto() && style()->height().isPercent()))
+ m_minPrefWidth = 0;
+ else
+ m_minPrefWidth = m_maxPrefWidth;
+
+ if (style()->maxWidth().isFixed() && style()->maxWidth().value() != undefinedLength) {
+ m_maxPrefWidth = min(m_maxPrefWidth, calcContentBoxWidth(style()->maxWidth().value()));
+ m_minPrefWidth = min(m_minPrefWidth, calcContentBoxWidth(style()->maxWidth().value()));
+ }
+
+ int toAdd = paddingLeft() + paddingRight() + borderLeft() + borderRight();
+ m_minPrefWidth += toAdd;
+ m_maxPrefWidth += toAdd;
+
+ setPrefWidthsDirty(false);
+}
+
+void RenderDataGrid::layout()
+{
+ RenderBlock::layout();
+ layoutColumns();
+}
+
+void RenderDataGrid::layoutColumns()
+{
+ // FIXME: Implement.
+}
+
+void RenderDataGrid::paintObject(PaintInfo& paintInfo, int tx, int ty)
+{
+ if (style()->visibility() != VISIBLE)
+ return;
+
+ // Paint our background and border.
+ RenderBlock::paintObject(paintInfo, tx, ty);
+
+ if (paintInfo.phase != PaintPhaseForeground)
+ return;
+
+ // Paint our column headers first.
+ paintColumnHeaders(paintInfo, tx, ty);
+}
+
+void RenderDataGrid::paintColumnHeaders(PaintInfo& paintInfo, int tx, int ty)
+{
+ DataGridColumnList* columns = gridElement()->columns();
+ unsigned length = columns->length();
+ for (unsigned i = 0; i < length; ++i) {
+ DataGridColumn* column = columns->item(i);
+ RenderStyle* columnStyle = headerStyle(column);
+
+ // Don't render invisible columns.
+ if (!columnStyle || columnStyle->display() == NONE || columnStyle->visibility() != VISIBLE)
+ continue;
+
+ // Paint the column header if it intersects the dirty rect.
+ IntRect columnRect(column->rect());
+ columnRect.move(tx, ty);
+ if (columnRect.intersects(paintInfo.rect))
+ paintColumnHeader(column, paintInfo, tx, ty);
+ }
+}
+
+void RenderDataGrid::paintColumnHeader(DataGridColumn*, PaintInfo&, int, int)
+{
+ // FIXME: Implement.
+}
+
+// Scrolling implementation functions
+void RenderDataGrid::valueChanged(Scrollbar*)
+{
+ // FIXME: Implement.
+}
+
+void RenderDataGrid::invalidateScrollbarRect(Scrollbar*, const IntRect&)
+{
+ // FIXME: Implement.
+}
+
+bool RenderDataGrid::isActive() const
+{
+ Page* page = document()->frame()->page();
+ return page && page->focusController()->isActive();
+}
+
+
+IntRect RenderDataGrid::convertFromScrollbarToContainingView(const Scrollbar* scrollbar, const IntRect& scrollbarRect) const
+{
+ RenderView* view = this->view();
+ if (!view)
+ return scrollbarRect;
+
+ IntRect rect = scrollbarRect;
+
+ int scrollbarLeft = width() - borderRight() - scrollbar->width();
+ int scrollbarTop = borderTop();
+ rect.move(scrollbarLeft, scrollbarTop);
+
+ return view->frameView()->convertFromRenderer(this, rect);
+}
+
+IntRect RenderDataGrid::convertFromContainingViewToScrollbar(const Scrollbar* scrollbar, const IntRect& parentRect) const
+{
+ RenderView* view = this->view();
+ if (!view)
+ return parentRect;
+
+ IntRect rect = view->frameView()->convertToRenderer(this, parentRect);
+
+ int scrollbarLeft = width() - borderRight() - scrollbar->width();
+ int scrollbarTop = borderTop();
+ rect.move(-scrollbarLeft, -scrollbarTop);
+ return rect;
+}
+
+IntPoint RenderDataGrid::convertFromScrollbarToContainingView(const Scrollbar* scrollbar, const IntPoint& scrollbarPoint) const
+{
+ RenderView* view = this->view();
+ if (!view)
+ return scrollbarPoint;
+
+ IntPoint point = scrollbarPoint;
+
+ int scrollbarLeft = width() - borderRight() - scrollbar->width();
+ int scrollbarTop = borderTop();
+ point.move(scrollbarLeft, scrollbarTop);
+
+ return view->frameView()->convertFromRenderer(this, point);
+}
+
+IntPoint RenderDataGrid::convertFromContainingViewToScrollbar(const Scrollbar* scrollbar, const IntPoint& parentPoint) const
+{
+ RenderView* view = this->view();
+ if (!view)
+ return parentPoint;
+
+ IntPoint point = view->frameView()->convertToRenderer(this, parentPoint);
+
+ int scrollbarLeft = width() - borderRight() - scrollbar->width();
+ int scrollbarTop = borderTop();
+ point.move(-scrollbarLeft, -scrollbarTop);
+ return point;
+}
+
+}
+
+#endif
diff --git a/WebCore/rendering/RenderDataGrid.h b/WebCore/rendering/RenderDataGrid.h
new file mode 100644
index 0000000..467edcc
--- /dev/null
+++ b/WebCore/rendering/RenderDataGrid.h
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef RenderDataGrid_h
+#define RenderDataGrid_h
+
+#if ENABLE(DATAGRID)
+
+#include "HTMLDataGridElement.h"
+#include "RenderBlock.h"
+#include "ScrollbarClient.h"
+#include "StyleImage.h"
+#include <wtf/RefPtr.h>
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+class RenderDataGrid : public RenderBlock, private ScrollbarClient {
+public:
+ RenderDataGrid(Element*);
+ ~RenderDataGrid();
+
+ virtual const char* renderName() const { return "RenderDataGrid"; }
+ virtual bool canHaveChildren() const { return false; }
+ virtual void calcPrefWidths();
+ virtual void layout();
+ virtual void paintObject(PaintInfo&, int tx, int ty);
+
+ void columnsChanged();
+
+private:
+ virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
+
+ RenderStyle* columnStyle(DataGridColumn*);
+ RenderStyle* headerStyle(DataGridColumn*);
+ void recalcStyleForColumns();
+ void recalcStyleForColumn(DataGridColumn*);
+
+ void layoutColumns();
+ void paintColumnHeaders(PaintInfo&, int tx, int ty);
+ void paintColumnHeader(DataGridColumn*, PaintInfo&, int tx, int ty);
+
+ HTMLDataGridElement* gridElement() const { return static_cast<HTMLDataGridElement*>(node()); }
+
+ // ScrollbarClient interface.
+ virtual void valueChanged(Scrollbar*);
+ virtual void invalidateScrollbarRect(Scrollbar*, const IntRect&);
+ virtual bool isActive() const;
+ virtual bool scrollbarCornerPresent() const { return false; } // We don't support resize on data grids yet. If we did this would have to change.
+ virtual IntRect convertFromScrollbarToContainingView(const Scrollbar*, const IntRect&) const;
+ virtual IntRect convertFromContainingViewToScrollbar(const Scrollbar*, const IntRect&) const;
+ virtual IntPoint convertFromScrollbarToContainingView(const Scrollbar*, const IntPoint&) const;
+ virtual IntPoint convertFromContainingViewToScrollbar(const Scrollbar*, const IntPoint&) const;
+
+ RefPtr<Scrollbar> m_vBar;
+};
+
+}
+
+#endif
+
+#endif // RenderDataGrid_h
diff --git a/WebCore/rendering/RenderFieldset.cpp b/WebCore/rendering/RenderFieldset.cpp
index 310dbe4..437991a 100644
--- a/WebCore/rendering/RenderFieldset.cpp
+++ b/WebCore/rendering/RenderFieldset.cpp
@@ -99,7 +99,7 @@ RenderObject* RenderFieldset::layoutLegend(bool relayoutChildren)
int b = borderTop();
int h = legend->height();
legend->setLocation(xPos, max((b-h)/2, 0));
- setHeight(max(b,h) + paddingTop());
+ setHeight(max(b, h) + paddingTop());
}
return legend;
}
@@ -131,13 +131,10 @@ void RenderFieldset::paintBoxDecorations(PaintInfo& paintInfo, int tx, int ty)
h -= yOff;
ty += yOff;
- int my = max(ty, paintInfo.rect.y());
- int end = min(paintInfo.rect.bottom(), ty + h);
- int mh = end - my;
+ paintBoxShadow(paintInfo.context, tx, ty, w, h, style(), Normal);
- paintBoxShadow(paintInfo.context, tx, ty, w, h, style());
-
- paintFillLayers(paintInfo, style()->backgroundColor(), style()->backgroundLayers(), my, mh, tx, ty, w, h);
+ paintFillLayers(paintInfo, style()->backgroundColor(), style()->backgroundLayers(), tx, ty, w, h);
+ paintBoxShadow(paintInfo.context, tx, ty, w, h, style(), Inset);
if (!style()->hasBorder())
return;
@@ -176,11 +173,7 @@ void RenderFieldset::paintMask(PaintInfo& paintInfo, int tx, int ty)
h -= yOff;
ty += yOff;
- int my = max(ty, paintInfo.rect.y());
- int end = min(paintInfo.rect.bottom(), ty + h);
- int mh = end - my;
-
- paintMaskImages(paintInfo, my, mh, tx, ty, w, h);
+ paintMaskImages(paintInfo, tx, ty, w, h);
}
void RenderFieldset::paintBorderMinusLegend(GraphicsContext* graphicsContext, int tx, int ty, int w, int h,
diff --git a/WebCore/rendering/RenderFieldset.h b/WebCore/rendering/RenderFieldset.h
index ed57d3a..df6a1da 100644
--- a/WebCore/rendering/RenderFieldset.h
+++ b/WebCore/rendering/RenderFieldset.h
@@ -1,10 +1,8 @@
/*
- * This file is part of the DOM implementation for KDE.
- *
* Copyright (C) 1999 Lars Knoll (knoll@kde.org)
* (C) 1999 Antti Koivisto (koivisto@kde.org)
* (C) 2000 Dirk Mueller (mueller@kde.org)
- * Copyright (C) 2004, 2006 Apple Computer, Inc.
+ * Copyright (C) 2004, 2006, 2009 Apple Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -34,6 +32,9 @@ class RenderFieldset : public RenderBlock {
public:
RenderFieldset(Node*);
+ RenderBox* findLegend() const;
+
+private:
virtual const char* renderName() const { return "RenderFieldSet"; }
virtual bool isFieldset() const { return true; }
@@ -43,17 +44,23 @@ public:
virtual bool avoidsFloats() const { return true; }
virtual bool stretchesToMinIntrinsicWidth() const { return true; }
- RenderBox* findLegend() const;
-
-protected:
virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
-private:
virtual void paintBoxDecorations(PaintInfo&, int tx, int ty);
- virtual void paintMask(PaintInfo& paintInfo, int tx, int ty);
+ virtual void paintMask(PaintInfo&, int tx, int ty);
+
void paintBorderMinusLegend(GraphicsContext*, int tx, int ty, int w, int h, const RenderStyle*, int lx, int lw, int lb);
};
+inline RenderFieldset* toRenderFieldset(RenderObject* object)
+{
+ ASSERT(!object || object->isFieldset());
+ return static_cast<RenderFieldset*>(object);
+}
+
+// This will catch anyone doing an unnecessary cast.
+void toRenderFieldset(const RenderFieldset*);
+
} // namespace WebCore
#endif // RenderFieldset_h
diff --git a/WebCore/rendering/RenderFileUploadControl.h b/WebCore/rendering/RenderFileUploadControl.h
index 85bc09f..bd7d62a 100644
--- a/WebCore/rendering/RenderFileUploadControl.h
+++ b/WebCore/rendering/RenderFileUploadControl.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006, 2007 Apple Inc.
+ * Copyright (C) 2006, 2007, 2009 Apple Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -35,13 +35,7 @@ class HTMLInputElement;
class RenderFileUploadControl : public RenderBlock, private FileChooserClient {
public:
RenderFileUploadControl(HTMLInputElement*);
- ~RenderFileUploadControl();
-
- virtual const char* renderName() const { return "RenderFileUploadControl"; }
-
- virtual void updateFromElement();
- virtual void calcPrefWidths();
- virtual void paintObject(PaintInfo&, int tx, int ty);
+ virtual ~RenderFileUploadControl();
void click();
@@ -54,10 +48,15 @@ public:
bool allowsMultipleFiles();
-protected:
+private:
+ virtual const char* renderName() const { return "RenderFileUploadControl"; }
+
+ virtual void updateFromElement();
+ virtual void calcPrefWidths();
+ virtual void paintObject(PaintInfo&, int tx, int ty);
+
virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
-private:
int maxFilenameWidth() const;
PassRefPtr<RenderStyle> createButtonStyle(const RenderStyle* parentStyle) const;
@@ -65,6 +64,15 @@ private:
RefPtr<FileChooser> m_fileChooser;
};
+inline RenderFileUploadControl* toRenderFileUploadControl(RenderObject* object)
+{
+ ASSERT(!object || !strcmp(object->renderName(), "RenderFileUploadControl"));
+ return static_cast<RenderFileUploadControl*>(object);
+}
+
+// This will catch anyone doing an unnecessary cast.
+void toRenderFileUploadControl(const RenderFileUploadControl*);
+
} // namespace WebCore
#endif // RenderFileUploadControl_h
diff --git a/WebCore/rendering/RenderFlexibleBox.cpp b/WebCore/rendering/RenderFlexibleBox.cpp
index d4eaaf4..6bbcc43 100644
--- a/WebCore/rendering/RenderFlexibleBox.cpp
+++ b/WebCore/rendering/RenderFlexibleBox.cpp
@@ -41,7 +41,8 @@ namespace WebCore {
class FlexBoxIterator {
public:
- FlexBoxIterator(RenderFlexibleBox* parent) {
+ FlexBoxIterator(RenderFlexibleBox* parent)
+ {
box = parent;
if (box->style()->boxOrient() == HORIZONTAL && box->style()->direction() == RTL)
forward = box->style()->boxDirection() != BNORMAL;
@@ -61,17 +62,20 @@ public:
reset();
}
- void reset() {
+ void reset()
+ {
current = 0;
currentOrdinal = forward ? 0 : lastOrdinal+1;
}
- RenderBox* first() {
+ RenderBox* first()
+ {
reset();
return next();
}
- RenderBox* next() {
+ RenderBox* next()
+ {
do {
if (!current) {
if (forward) {
@@ -192,6 +196,10 @@ void RenderFlexibleBox::calcPrefWidths()
}
int toAdd = borderLeft() + borderRight() + paddingLeft() + paddingRight();
+
+ if (hasOverflowClip() && style()->overflowY() == OSCROLL)
+ toAdd += verticalScrollbarWidth();
+
m_minPrefWidth += toAdd;
m_maxPrefWidth += toAdd;
@@ -288,13 +296,17 @@ void RenderFlexibleBox::layoutBlock(bool relayoutChildren)
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, width() + boxShadow->x + boxShadow->blur);
- m_overflowTop = min(m_overflowTop, boxShadow->y - boxShadow->blur);
- m_overflowHeight = max(m_overflowHeight, height() + boxShadow->y + boxShadow->blur);
- }
-
+ int shadowLeft;
+ int shadowRight;
+ int shadowTop;
+ int shadowBottom;
+ style()->getBoxShadowExtent(shadowTop, shadowRight, shadowBottom, shadowLeft);
+
+ m_overflowLeft = min(m_overflowLeft, shadowLeft);
+ m_overflowWidth = max(m_overflowWidth, width() + shadowRight);
+ m_overflowTop = min(m_overflowTop, shadowTop);
+ m_overflowHeight = max(m_overflowHeight, height() + shadowBottom);
+
if (hasReflection()) {
IntRect reflection(reflectionBox());
m_overflowTop = min(m_overflowTop, reflection.y());
@@ -317,23 +329,10 @@ void RenderFlexibleBox::layoutBlock(bool relayoutChildren)
setNeedsLayout(false);
}
-void RenderFlexibleBox::layoutHorizontalBox(bool relayoutChildren)
+// The first walk over our kids is to find out if we have any flexible children.
+static void gatherFlexChildrenInfo(FlexBoxIterator& iterator, bool relayoutChildren, unsigned int& highestFlexGroup, unsigned int& lowestFlexGroup, bool& haveFlex)
{
- int toAdd = borderBottom() + paddingBottom() + horizontalScrollbarHeight();
- int yPos = borderTop() + paddingTop();
- int xPos = borderLeft() + paddingLeft();
- bool heightSpecified = false;
- int oldHeight = 0;
-
- unsigned int highestFlexGroup = 0;
- unsigned int lowestFlexGroup = 0;
- bool haveFlex = false;
- int remainingSpace = 0;
- m_overflowHeight = height();
-
- // The first walk over our kids is to find out if we have any flexible children.
- FlexBoxIterator iterator(this);
- RenderBox* child = iterator.next();
+ RenderBox* child = iterator.first();
while (child) {
// Check to see if this child flexes.
if (!child->isPositioned() && child->style()->boxFlex() > 0.0f) {
@@ -353,7 +352,29 @@ void RenderFlexibleBox::layoutHorizontalBox(bool relayoutChildren)
}
child = iterator.next();
}
-
+}
+
+void RenderFlexibleBox::layoutHorizontalBox(bool relayoutChildren)
+{
+ int toAdd = borderBottom() + paddingBottom() + horizontalScrollbarHeight();
+ int yPos = borderTop() + paddingTop();
+ int xPos = borderLeft() + paddingLeft();
+ bool heightSpecified = false;
+ int oldHeight = 0;
+
+ int remainingSpace = 0;
+ m_overflowHeight = height();
+
+ FlexBoxIterator iterator(this);
+ unsigned int highestFlexGroup = 0;
+ unsigned int lowestFlexGroup = 0;
+ bool haveFlex = false;
+ gatherFlexChildrenInfo(iterator, relayoutChildren, highestFlexGroup, lowestFlexGroup, haveFlex);
+
+ RenderBox* child;
+
+ RenderBlock::startDelayUpdateScrollInfo();
+
// We do 2 passes. The first pass is simply to lay everyone out at
// their preferred widths. The second pass handles flexing the children.
do {
@@ -578,7 +599,9 @@ void RenderFlexibleBox::layoutHorizontalBox(bool relayoutChildren)
} while (haveFlex);
m_flexingChildren = false;
-
+
+ RenderBlock::finishDelayUpdateScrollInfo();
+
if (remainingSpace > 0 && ((style()->direction() == LTR && style()->boxPack() != BSTART) ||
(style()->direction() == RTL && style()->boxPack() != BEND))) {
// Children must be repositioned.
@@ -665,39 +688,21 @@ void RenderFlexibleBox::layoutVerticalBox(bool relayoutChildren)
{
int xPos = borderLeft() + paddingLeft();
int yPos = borderTop() + paddingTop();
- if( style()->direction() == RTL )
+ if (style()->direction() == RTL)
xPos = width() - paddingRight() - borderRight();
int toAdd = borderBottom() + paddingBottom() + horizontalScrollbarHeight();
bool heightSpecified = false;
int oldHeight = 0;
-
+
+ int remainingSpace = 0;
+
+ FlexBoxIterator iterator(this);
unsigned int highestFlexGroup = 0;
unsigned int lowestFlexGroup = 0;
bool haveFlex = false;
- int remainingSpace = 0;
-
- // The first walk over our kids is to find out if we have any flexible children.
- FlexBoxIterator iterator(this);
- RenderBox* child = iterator.next();
- while (child) {
- // Check to see if this child flexes.
- if (!child->isPositioned() && child->style()->boxFlex() > 0.0f) {
- // We always have to lay out flexible objects again, since the flex distribution
- // may have changed, and we need to reallocate space.
- child->setOverrideSize(-1);
- if (!relayoutChildren)
- child->setChildNeedsLayout(true, false);
- haveFlex = true;
- unsigned int flexGroup = child->style()->boxFlexGroup();
- if (lowestFlexGroup == 0)
- lowestFlexGroup = flexGroup;
- if (flexGroup < lowestFlexGroup)
- lowestFlexGroup = flexGroup;
- if (flexGroup > highestFlexGroup)
- highestFlexGroup = flexGroup;
- }
- child = iterator.next();
- }
+ gatherFlexChildrenInfo(iterator, relayoutChildren, highestFlexGroup, lowestFlexGroup, haveFlex);
+
+ RenderBox* child;
// We confine the line clamp ugliness to vertical flexible boxes (thus keeping it out of
// mainstream block layout); this is not really part of the XUL box model.
@@ -806,6 +811,8 @@ void RenderFlexibleBox::layoutVerticalBox(bool relayoutChildren)
}
}
+ RenderBlock::startDelayUpdateScrollInfo();
+
// We do 2 passes. The first pass is simply to lay everyone out at
// their preferred widths. The second pass handles flexing the children.
// Our first pass is done without flexing. We simply lay the children
@@ -994,6 +1001,8 @@ void RenderFlexibleBox::layoutVerticalBox(bool relayoutChildren)
}
} while (haveFlex);
+ RenderBlock::finishDelayUpdateScrollInfo();
+
if (style()->boxPack() != BSTART && remainingSpace > 0) {
// Children must be repositioned.
int offset = 0;
diff --git a/WebCore/rendering/RenderFrame.h b/WebCore/rendering/RenderFrame.h
index 47dad32..5b3b533 100644
--- a/WebCore/rendering/RenderFrame.h
+++ b/WebCore/rendering/RenderFrame.h
@@ -46,6 +46,15 @@ private:
virtual void viewCleared();
};
+inline RenderFrame* toRenderFrame(RenderObject* object)
+{
+ ASSERT(!object || object->isFrame());
+ return static_cast<RenderFrame*>(object);
+}
+
+// This will catch anyone doing an unnecessary cast.
+void toRenderFrame(const RenderFrame*);
+
} // namespace WebCore
#endif // RenderFrame_h
diff --git a/WebCore/rendering/RenderFrameSet.cpp b/WebCore/rendering/RenderFrameSet.cpp
index 0353bb1..0838798 100644
--- a/WebCore/rendering/RenderFrameSet.cpp
+++ b/WebCore/rendering/RenderFrameSet.cpp
@@ -68,7 +68,7 @@ inline HTMLFrameSetElement* RenderFrameSet::frameSet() const
static Color borderStartEdgeColor()
{
- return Color(170,170,170);
+ return Color(170, 170, 170);
}
static Color borderEndEdgeColor()
@@ -419,9 +419,9 @@ void RenderFrameSet::computeEdgeInfo()
for (int c = 0; c < cols; ++c) {
FrameEdgeInfo edgeInfo;
if (child->isFrameSet())
- edgeInfo = static_cast<RenderFrameSet*>(child)->edgeInfo();
+ edgeInfo = toRenderFrameSet(child)->edgeInfo();
else
- edgeInfo = static_cast<RenderFrame*>(child)->edgeInfo();
+ edgeInfo = toRenderFrame(child)->edgeInfo();
fillFromEdgeInfo(edgeInfo, r, c);
child = child->nextSibling();
if (!child)
@@ -693,9 +693,10 @@ bool RenderFrameSet::userResize(MouseEvent* evt)
void RenderFrameSet::setIsResizing(bool isResizing)
{
m_isResizing = isResizing;
- for (RenderObject* p = parent(); p; p = p->parent())
- if (p->isFrameSet())
- static_cast<RenderFrameSet*>(p)->m_isChildResizing = isResizing;
+ for (RenderObject* ancestor = parent(); ancestor; ancestor = ancestor->parent()) {
+ if (ancestor->isFrameSet())
+ toRenderFrameSet(ancestor)->m_isChildResizing = isResizing;
+ }
if (Frame* frame = document()->frame())
frame->eventHandler()->setResizingFrameSet(isResizing ? frameSet() : 0);
}
diff --git a/WebCore/rendering/RenderFrameSet.h b/WebCore/rendering/RenderFrameSet.h
index 0c80ad9..aa3ac64 100644
--- a/WebCore/rendering/RenderFrameSet.h
+++ b/WebCore/rendering/RenderFrameSet.h
@@ -32,8 +32,7 @@ class MouseEvent;
enum FrameEdge { LeftFrameEdge, RightFrameEdge, TopFrameEdge, BottomFrameEdge };
-struct FrameEdgeInfo
-{
+struct FrameEdgeInfo {
FrameEdgeInfo(bool preventResize = false, bool allowBorder = true)
: m_preventResize(4)
, m_allowBorder(4)
@@ -58,19 +57,9 @@ public:
RenderFrameSet(HTMLFrameSetElement*);
virtual ~RenderFrameSet();
- virtual RenderObjectChildList* virtualChildren() { return children(); }
- virtual const RenderObjectChildList* virtualChildren() const { return children(); }
const RenderObjectChildList* children() const { return &m_children; }
RenderObjectChildList* children() { return &m_children; }
- virtual const char* renderName() const { return "RenderFrameSet"; }
- virtual bool isFrameSet() const { return true; }
-
- virtual void layout();
- virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, int x, int y, int tx, int ty, HitTestAction);
- virtual void paint(PaintInfo& paintInfo, int tx, int ty);
- virtual bool isChildAllowed(RenderObject*, RenderStyle*) const;
-
FrameEdgeInfo edgeInfo() const;
bool userResize(MouseEvent*);
@@ -88,7 +77,7 @@ public:
private:
static const int noSplit = -1;
- class GridAxis : Noncopyable {
+ class GridAxis : public Noncopyable {
public:
GridAxis();
void resize(int);
@@ -100,6 +89,17 @@ private:
int m_splitResizeOffset;
};
+ virtual RenderObjectChildList* virtualChildren() { return children(); }
+ virtual const RenderObjectChildList* virtualChildren() const { return children(); }
+
+ virtual const char* renderName() const { return "RenderFrameSet"; }
+ virtual bool isFrameSet() const { return true; }
+
+ virtual void layout();
+ virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, int x, int y, int tx, int ty, HitTestAction);
+ virtual void paint(PaintInfo&, int tx, int ty);
+ virtual bool isChildAllowed(RenderObject*, RenderStyle*) const;
+
inline HTMLFrameSetElement* frameSet() const;
void setIsResizing(bool);
@@ -115,8 +115,8 @@ private:
void startResizing(GridAxis&, int position);
void continueResizing(GridAxis&, int position);
- void paintRowBorder(const PaintInfo& paintInfo, const IntRect& rect);
- void paintColumnBorder(const PaintInfo& paintInfo, const IntRect& rect);
+ void paintRowBorder(const PaintInfo&, const IntRect&);
+ void paintColumnBorder(const PaintInfo&, const IntRect&);
RenderObjectChildList m_children;
@@ -130,6 +130,16 @@ private:
#endif
};
+
+inline RenderFrameSet* toRenderFrameSet(RenderObject* object)
+{
+ ASSERT(!object || object->isFrameSet());
+ return static_cast<RenderFrameSet*>(object);
+}
+
+// This will catch anyone doing an unnecessary cast.
+void toRenderFrameSet(const RenderFrameSet*);
+
} // namespace WebCore
#endif // RenderFrameSet_h
diff --git a/WebCore/rendering/RenderHTMLCanvas.h b/WebCore/rendering/RenderHTMLCanvas.h
index ad6c505..e82cf9a 100644
--- a/WebCore/rendering/RenderHTMLCanvas.h
+++ b/WebCore/rendering/RenderHTMLCanvas.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004, 2006, 2007 Apple Inc. All rights reserved.
+ * Copyright (C) 2004, 2006, 2007, 2009 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -36,17 +36,23 @@ class RenderHTMLCanvas : public RenderReplaced {
public:
RenderHTMLCanvas(HTMLCanvasElement*);
- virtual const char* renderName() const { return "RenderHTMLCanvas"; }
-
- virtual void paintReplaced(PaintInfo& paintInfo, int tx, int ty);
-
void canvasSizeChanged();
-protected:
+private:
+ virtual const char* renderName() const { return "RenderHTMLCanvas"; }
+ virtual void paintReplaced(PaintInfo&, int tx, int ty);
virtual void intrinsicSizeChanged() { canvasSizeChanged(); }
-
};
+inline RenderHTMLCanvas* toRenderHTMLCanvas(RenderObject* object)
+{
+ ASSERT(!object || !strcmp(object->renderName(), "RenderHTMLCanvas"));
+ return static_cast<RenderHTMLCanvas*>(object);
+}
+
+// This will catch anyone doing an unnecessary cast.
+void toRenderHTMLCanvas(const RenderHTMLCanvas*);
+
} // namespace WebCore
#endif // RenderHTMLCanvas_h
diff --git a/WebCore/rendering/RenderImage.cpp b/WebCore/rendering/RenderImage.cpp
index f48a219..5c11e41 100644
--- a/WebCore/rendering/RenderImage.cpp
+++ b/WebCore/rendering/RenderImage.cpp
@@ -26,9 +26,6 @@
#include "config.h"
#include "RenderImage.h"
-#include "BitmapImage.h"
-#include "Document.h"
-#include "FrameView.h"
#include "GraphicsContext.h"
#include "HTMLImageElement.h"
#include "HTMLInputElement.h"
@@ -93,8 +90,7 @@ private:
Timer<RenderImage> m_highQualityRepaintTimer;
};
-class RenderImageScaleObserver
-{
+class RenderImageScaleObserver {
public:
static bool shouldImagePaintAtLowQuality(RenderImage*, const IntSize&);
@@ -447,20 +443,19 @@ HTMLMapElement* RenderImage::imageMap()
return i ? i->document()->getImageMap(i->useMap()) : 0;
}
-bool RenderImage::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, int _x, int _y, int _tx, int _ty, HitTestAction hitTestAction)
+bool RenderImage::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, int x, int y, int tx, int ty, HitTestAction hitTestAction)
{
HitTestResult tempResult(result.point());
- bool inside = RenderReplaced::nodeAtPoint(request, tempResult, _x, _y, _tx, _ty, hitTestAction);
+ bool inside = RenderReplaced::nodeAtPoint(request, tempResult, x, y, tx, ty, hitTestAction);
if (inside && node()) {
- int tx = _tx + x();
- int ty = _ty + y();
-
- HTMLMapElement* map = imageMap();
- if (map) {
- // we're a client side image map
- inside = map->mapMouseEvent(_x - tx, _y - ty, IntSize(contentWidth(), contentHeight()), tempResult);
- tempResult.setInnerNonSharedNode(node());
+ if (HTMLMapElement* map = imageMap()) {
+ IntRect contentBox = contentBoxRect();
+ float zoom = style()->effectiveZoom();
+ int mapX = lroundf((x - tx - this->x() - contentBox.x()) / zoom);
+ int mapY = lroundf((y - ty - this->y() - contentBox.y()) / zoom);
+ if (map->mapMouseEvent(mapX, mapY, contentBox.size(), tempResult))
+ tempResult.setInnerNonSharedNode(node());
}
}
diff --git a/WebCore/rendering/RenderImage.h b/WebCore/rendering/RenderImage.h
index 042452f..2224412 100644
--- a/WebCore/rendering/RenderImage.h
+++ b/WebCore/rendering/RenderImage.h
@@ -3,7 +3,7 @@
* (C) 1999 Antti Koivisto (koivisto@kde.org)
* (C) 2006 Allan Sandfeld Jensen (kde@carewolf.com)
* (C) 2006 Samuel Weinig (sam.weinig@gmail.com)
- * Copyright (C) 2004, 2005, 2006, 2007 Apple Inc. All rights reserved.
+ * Copyright (C) 2004, 2005, 2006, 2007, 2009 Apple Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -25,8 +25,6 @@
#ifndef RenderImage_h
#define RenderImage_h
-#include "CachedImage.h"
-#include "CachedResourceHandle.h"
#include "RenderReplaced.h"
namespace WebCore {
@@ -38,18 +36,6 @@ public:
RenderImage(Node*);
virtual ~RenderImage();
- virtual const char* renderName() const { return "RenderImage"; }
-
- virtual bool isImage() const { return true; }
- virtual bool isRenderImage() const { return true; }
-
- virtual void paintReplaced(PaintInfo& paintInfo, int tx, int ty);
-
- virtual int minimumReplacedHeight() const;
-
- virtual void imageChanged(WrappedImagePtr, const IntRect* = 0);
- virtual void notifyFinished(CachedResource*);
-
bool setImageSizeForAltText(CachedImage* newImage = 0);
void updateAltText();
@@ -57,13 +43,6 @@ public:
void setCachedImage(CachedImage*);
CachedImage* cachedImage() const { return m_cachedImage.get(); }
- virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, int x, int y, int tx, int ty, HitTestAction);
-
- virtual int calcReplacedWidth(bool includeMaxWidth = true) const;
- virtual int calcReplacedHeight() const;
-
- virtual void calcPrefWidths();
-
HTMLMapElement* imageMap();
void resetAnimation();
@@ -73,8 +52,29 @@ 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 /* width */ = 0, int /* height */ = 0) { return m_cachedImage ? m_cachedImage->image() : nullImage(); }
virtual bool errorOccurred() const { return m_cachedImage && m_cachedImage->errorOccurred(); }
+
+ virtual void imageChanged(WrappedImagePtr, const IntRect* = 0);
+
+private:
+ virtual const char* renderName() const { return "RenderImage"; }
+
+ virtual bool isImage() const { return true; }
+ virtual bool isRenderImage() const { return true; }
+
+ virtual void paintReplaced(PaintInfo&, int tx, int ty);
+
+ virtual int minimumReplacedHeight() const;
+
+ virtual void notifyFinished(CachedResource*);
+ virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, int x, int y, int tx, int ty, HitTestAction);
+
+ virtual int calcReplacedWidth(bool includeMaxWidth = true) const;
+ virtual int calcReplacedHeight() const;
+
+ virtual void calcPrefWidths();
+
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); }
virtual bool imageHasRelativeWidth() const { return m_cachedImage ? m_cachedImage->imageHasRelativeWidth() : false; }
@@ -84,7 +84,6 @@ protected:
virtual void intrinsicSizeChanged() { imageChanged(imagePtr()); }
-private:
int calcAspectRatioWidth() const;
int calcAspectRatioHeight() const;
@@ -95,6 +94,7 @@ protected:
// The image we are rendering.
CachedResourceHandle<CachedImage> m_cachedImage;
+private:
// Text to display as long as the image isn't available.
String m_altText;
@@ -103,16 +103,16 @@ protected:
friend class RenderImageScaleObserver;
};
-inline RenderImage* toRenderImage(RenderObject* o)
+inline RenderImage* toRenderImage(RenderObject* object)
{
- ASSERT(!o || o->isRenderImage());
- return static_cast<RenderImage*>(o);
+ ASSERT(!object || object->isRenderImage());
+ return static_cast<RenderImage*>(object);
}
-inline const RenderImage* toRenderImage(const RenderObject* o)
+inline const RenderImage* toRenderImage(const RenderObject* object)
{
- ASSERT(!o || o->isRenderImage());
- return static_cast<const RenderImage*>(o);
+ ASSERT(!object || object->isRenderImage());
+ return static_cast<const RenderImage*>(object);
}
// This will catch anyone doing an unnecessary cast.
diff --git a/WebCore/rendering/RenderInline.cpp b/WebCore/rendering/RenderInline.cpp
index 3965d94..53962d2 100644
--- a/WebCore/rendering/RenderInline.cpp
+++ b/WebCore/rendering/RenderInline.cpp
@@ -1,9 +1,7 @@
/*
- * This file is part of the render object implementation for KHTML.
- *
* Copyright (C) 1999 Lars Knoll (knoll@kde.org)
* (C) 1999 Antti Koivisto (koivisto@kde.org)
- * Copyright (C) 2003, 2004, 2005, 2006 Apple Computer, Inc.
+ * Copyright (C) 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
@@ -51,10 +49,6 @@ RenderInline::RenderInline(Node* node)
setChildrenInline(true);
}
-RenderInline::~RenderInline()
-{
-}
-
void RenderInline::destroy()
{
// Detach our continuation first.
@@ -258,7 +252,7 @@ void RenderInline::splitInlines(RenderBlock* fromBlock, RenderBlock* toBlock,
// We have been reparented and are now under the fromBlock. We need
// to walk up our inline parent chain until we hit the containing block.
// Once we hit the containing block we're done.
- RenderBoxModelObject* curr = static_cast<RenderBoxModelObject*>(parent());
+ RenderBoxModelObject* curr = toRenderBoxModelObject(parent());
RenderBoxModelObject* currChild = this;
// FIXME: Because splitting is O(n^2) as tags nest pathologically, we cap the depth at which we're willing to clone.
@@ -302,7 +296,7 @@ void RenderInline::splitInlines(RenderBlock* fromBlock, RenderBlock* toBlock,
// Keep walking up the chain.
currChild = curr;
- curr = static_cast<RenderBoxModelObject*>(curr->parent());
+ curr = toRenderBoxModelObject(curr->parent());
splitDepth++;
}
@@ -384,7 +378,7 @@ void RenderInline::addChildToContinuation(RenderObject* newChild, RenderObject*
ASSERT(!beforeChild || beforeChild->parent()->isRenderBlock() || beforeChild->parent()->isRenderInline());
RenderBoxModelObject* beforeChildParent = 0;
if (beforeChild)
- beforeChildParent = static_cast<RenderBoxModelObject*>(beforeChild->parent());
+ beforeChildParent = toRenderBoxModelObject(beforeChild->parent());
else {
RenderBoxModelObject* cont = nextContinuation(flow);
if (cont)
@@ -749,14 +743,14 @@ void RenderInline::dirtyLineBoxes(bool fullLayout)
m_lineBoxes.dirtyLineBoxes();
}
-InlineFlowBox* RenderInline::createFlowBox()
+InlineFlowBox* RenderInline::createInlineFlowBox()
{
return new (renderArena()) InlineFlowBox(this);
}
-InlineFlowBox* RenderInline::createInlineFlowBox()
+InlineFlowBox* RenderInline::createAndAppendInlineFlowBox()
{
- InlineFlowBox* flowBox = createFlowBox();
+ InlineFlowBox* flowBox = createInlineFlowBox();
m_lineBoxes.appendLineBox(flowBox);
return flowBox;
}
diff --git a/WebCore/rendering/RenderInline.h b/WebCore/rendering/RenderInline.h
index cf6b84b..14d76ca 100644
--- a/WebCore/rendering/RenderInline.h
+++ b/WebCore/rendering/RenderInline.h
@@ -1,9 +1,7 @@
/*
- * This file is part of the render object implementation for KHTML.
- *
* Copyright (C) 1999 Lars Knoll (knoll@kde.org)
* (C) 1999 Antti Koivisto (koivisto@kde.org)
- * Copyright (C) 2003 Apple Computer, Inc.
+ * 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
@@ -35,20 +33,51 @@ class Position;
class RenderInline : public RenderBoxModelObject {
public:
RenderInline(Node*);
- virtual ~RenderInline();
+ virtual void destroy();
+
+ virtual void addChild(RenderObject* newChild, RenderObject* beforeChild = 0);
+
+ virtual int marginLeft() const;
+ virtual int marginRight() const;
+
+ virtual void absoluteRects(Vector<IntRect>&, int tx, int ty);
+ virtual void absoluteQuads(Vector<FloatQuad>&);
+
+ IntRect linesBoundingBox() const;
+
+ InlineFlowBox* createAndAppendInlineFlowBox();
+
+ void dirtyLineBoxes(bool fullLayout);
+
+ RenderLineBoxList* lineBoxes() { return &m_lineBoxes; }
+ const RenderLineBoxList* lineBoxes() const { return &m_lineBoxes; }
+
+ InlineFlowBox* firstLineBox() const { return m_lineBoxes.firstLineBox(); }
+ InlineFlowBox* lastLineBox() const { return m_lineBoxes.lastLineBox(); }
+
+ RenderBoxModelObject* continuation() const { return m_continuation; }
+
+ virtual void updateDragState(bool dragOn);
+
+ IntSize relativePositionedInlineOffset(const RenderBox* child) const;
+
+ virtual void addFocusRingRects(GraphicsContext*, int tx, int ty);
+ void paintOutline(GraphicsContext*, int tx, int ty);
+
+ int verticalPositionFromCache(bool firstLine) const;
+ void invalidateVerticalPosition() { m_verticalPosition = PositionUndefined; }
+
+private:
virtual RenderObjectChildList* virtualChildren() { return children(); }
virtual const RenderObjectChildList* virtualChildren() const { return children(); }
const RenderObjectChildList* children() const { return &m_children; }
RenderObjectChildList* children() { return &m_children; }
- virtual void destroy();
-
virtual const char* renderName() const;
virtual bool isRenderInline() const { return true; }
- virtual void addChild(RenderObject* newChild, RenderObject* beforeChild = 0);
void addChildToContinuation(RenderObject* newChild, RenderObject* beforeChild);
virtual void addChildIgnoringContinuation(RenderObject* newChild, RenderObject* beforeChild = 0);
@@ -73,94 +102,64 @@ public:
// Just ignore top/bottom margins on RenderInlines.
virtual int marginTop() const { return 0; }
virtual int marginBottom() const { return 0; }
- virtual int marginLeft() const;
- virtual int marginRight() const;
-
- virtual void absoluteRects(Vector<IntRect>&, int tx, int ty);
- virtual void absoluteQuads(Vector<FloatQuad>&);
-
virtual IntRect clippedOverflowRectForRepaint(RenderBoxModelObject* repaintContainer);
virtual IntRect rectWithOutlineForRepaint(RenderBoxModelObject* repaintContainer, int outlineWidth);
virtual void computeRectForRepaint(RenderBoxModelObject* repaintContainer, IntRect& rect, bool fixed);
virtual VisiblePosition positionForPoint(const IntPoint&);
- IntRect linesBoundingBox() const;
-
virtual IntRect borderBoundingBox() const
{
IntRect boundingBox = linesBoundingBox();
return IntRect(0, 0, boundingBox.width(), boundingBox.height());
}
- InlineFlowBox* createInlineFlowBox();
- void dirtyLineBoxes(bool fullLayout);
- virtual void dirtyLinesFromChangedChild(RenderObject* child) { m_lineBoxes.dirtyLinesFromChangedChild(this, child); }
-
- RenderLineBoxList* lineBoxes() { return &m_lineBoxes; }
- const RenderLineBoxList* lineBoxes() const { return &m_lineBoxes; }
+ virtual InlineFlowBox* createInlineFlowBox(); // Subclassed by SVG and Ruby
- InlineFlowBox* firstLineBox() const { return m_lineBoxes.firstLineBox(); }
- InlineFlowBox* lastLineBox() const { return m_lineBoxes.lastLineBox(); }
+ virtual void dirtyLinesFromChangedChild(RenderObject* child) { m_lineBoxes.dirtyLinesFromChangedChild(this, child); }
virtual int lineHeight(bool firstLine, bool isRootLineBox = false) const;
- RenderBoxModelObject* continuation() const { return m_continuation; }
RenderInline* inlineContinuation() const;
void setContinuation(RenderBoxModelObject* c) { m_continuation = c; }
- virtual void updateDragState(bool dragOn);
-
virtual void childBecameNonInline(RenderObject* child);
virtual void updateHitTestResult(HitTestResult&, const IntPoint&);
- IntSize relativePositionedInlineOffset(const RenderBox* child) const;
-
- virtual void addFocusRingRects(GraphicsContext*, int tx, int ty);
- void paintOutline(GraphicsContext*, int tx, int ty);
-
virtual void imageChanged(WrappedImagePtr, const IntRect* = 0);
- int verticalPositionFromCache(bool firstLine) const;
- void invalidateVerticalPosition() { m_verticalPosition = PositionUndefined; }
-
#if ENABLE(DASHBOARD_SUPPORT)
virtual void addDashboardRegions(Vector<DashboardRegionValue>&);
#endif
-protected:
virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
virtual void updateBoxModelInfoFromStyle();
- virtual InlineFlowBox* createFlowBox(); // Subclassed by SVG
static RenderInline* cloneInline(RenderInline* src);
-private:
void paintOutlineForLine(GraphicsContext*, int tx, int ty, const IntRect& prevLine, const IntRect& thisLine, const IntRect& nextLine);
RenderBoxModelObject* continuationBefore(RenderObject* beforeChild);
-protected:
RenderObjectChildList m_children;
RenderLineBoxList m_lineBoxes; // All of the line boxes created for this inline flow. For example, <i>Hello<br>world.</i> will have two <i> line boxes.
-private:
RenderBoxModelObject* m_continuation; // Can be either a block or an inline. <b><i><p>Hello</p></i></b>. In this example the <i> will have a block as its continuation but the
// <b> will just have an inline as its continuation.
mutable int m_lineHeight;
mutable int m_verticalPosition;
};
-inline RenderInline* toRenderInline(RenderObject* o)
+inline RenderInline* toRenderInline(RenderObject* object)
{
- ASSERT(!o || o->isRenderInline());
- return static_cast<RenderInline*>(o);
+ ASSERT(!object || object->isRenderInline());
+ return static_cast<RenderInline*>(object);
}
-inline const RenderInline* toRenderInline(const RenderObject* o)
+inline const RenderInline* toRenderInline(const RenderObject* object)
{
- ASSERT(!o || o->isRenderInline());
- return static_cast<const RenderInline*>(o);
+ ASSERT(!object || object->isRenderInline());
+ return static_cast<const RenderInline*>(object);
}
// This will catch anyone doing an unnecessary cast.
diff --git a/WebCore/rendering/RenderLayer.cpp b/WebCore/rendering/RenderLayer.cpp
index 80c7155..ab78f40 100644
--- a/WebCore/rendering/RenderLayer.cpp
+++ b/WebCore/rendering/RenderLayer.cpp
@@ -167,7 +167,7 @@ RenderLayer::RenderLayer(RenderBoxModelObject* renderer)
, m_has3DTransformedDescendant(false)
#if USE(ACCELERATED_COMPOSITING)
, m_hasCompositingDescendant(false)
- , m_mustOverlayCompositedLayers(false)
+ , m_mustOverlapCompositedLayers(false)
#endif
, m_marquee(0)
, m_staticX(0)
@@ -229,11 +229,24 @@ RenderLayerCompositor* RenderLayer::compositor() const
void RenderLayer::rendererContentChanged()
{
+ // This can get called when video becomes accelerated, so the layers may change.
+ if (compositor()->updateLayerCompositingState(this))
+ compositor()->setCompositingLayersNeedRebuild();
+
if (m_backing)
m_backing->rendererContentChanged();
}
#endif // USE(ACCELERATED_COMPOSITING)
+bool RenderLayer::hasAcceleratedCompositing() const
+{
+#if USE(ACCELERATED_COMPOSITING)
+ return compositor()->hasAcceleratedCompositing();
+#else
+ return false;
+#endif
+}
+
void RenderLayer::setStaticY(int staticY)
{
if (m_staticY == staticY)
@@ -242,17 +255,17 @@ void RenderLayer::setStaticY(int staticY)
renderer()->setChildNeedsLayout(true, false);
}
-void RenderLayer::updateLayerPositions(bool doFullRepaint, bool checkForRepaint)
+void RenderLayer::updateLayerPositions(UpdateLayerPositionsFlags flags)
{
- if (doFullRepaint) {
+ if (flags & DoFullRepaint) {
renderer()->repaint();
#if USE(ACCELERATED_COMPOSITING)
- checkForRepaint = false;
+ flags &= ~CheckForRepaint;
// We need the full repaint to propagate to child layers if we are hardware compositing.
if (!compositor()->inCompositingMode())
- doFullRepaint = false;
+ flags &= ~DoFullRepaint;
#else
- checkForRepaint = doFullRepaint = false;
+ flags &= ~(CheckForRepaint | DoFullRepaint);
#endif
}
@@ -279,7 +292,7 @@ void RenderLayer::updateLayerPositions(bool doFullRepaint, bool checkForRepaint)
RenderBoxModelObject* repaintContainer = renderer()->containerForRepaint();
IntRect newRect = renderer()->clippedOverflowRectForRepaint(repaintContainer);
IntRect newOutlineBox = renderer()->outlineBoundsForRepaint(repaintContainer);
- if (checkForRepaint) {
+ if (flags & CheckForRepaint) {
if (view && !view->printing()) {
if (m_needsFullRepaint) {
renderer()->repaintUsingContainer(repaintContainer, m_repaintRect);
@@ -303,14 +316,11 @@ void RenderLayer::updateLayerPositions(bool doFullRepaint, bool checkForRepaint)
m_reflection->layout();
for (RenderLayer* child = firstChild(); child; child = child->nextSibling())
- child->updateLayerPositions(doFullRepaint, checkForRepaint);
+ child->updateLayerPositions(flags);
#if USE(ACCELERATED_COMPOSITING)
- if (!parent())
- compositor()->updateRootLayerPosition();
-
- if (isComposited())
- backing()->updateAfterLayout();
+ if ((flags & UpdateCompositingLayers) && isComposited())
+ backing()->updateAfterLayout(RenderLayerBacking::CompositingChildren);
#endif
// With all our children positioned, now update our marquee if we need to.
@@ -318,6 +328,13 @@ void RenderLayer::updateLayerPositions(bool doFullRepaint, bool checkForRepaint)
m_marquee->updateMarqueePosition();
}
+void RenderLayer::computeRepaintRects()
+{
+ RenderBoxModelObject* repaintContainer = renderer()->containerForRepaint();
+ m_repaintRect = renderer()->clippedOverflowRectForRepaint(repaintContainer);
+ m_outlineBox = renderer()->outlineBoundsForRepaint(repaintContainer);
+}
+
void RenderLayer::updateTransform()
{
// hasTransform() on the renderer is also true when there is transform-style: preserve-3d or perspective set,
@@ -338,7 +355,7 @@ void RenderLayer::updateTransform()
ASSERT(box);
m_transform->makeIdentity();
box->style()->applyTransform(*m_transform, box->borderBoxRect().size(), RenderStyle::IncludeTransformOrigin);
- makeMatrixRenderable(*m_transform);
+ makeMatrixRenderable(*m_transform, hasAcceleratedCompositing());
}
if (had3DTransform != has3DTransform())
@@ -355,7 +372,7 @@ TransformationMatrix RenderLayer::currentTransform() const
TransformationMatrix currTransform;
RefPtr<RenderStyle> style = renderer()->animation()->getAnimatedStyleForRenderer(renderer());
style->applyTransform(currTransform, renderBox()->borderBoxRect().size(), RenderStyle::IncludeTransformOrigin);
- makeMatrixRenderable(currTransform);
+ makeMatrixRenderable(currTransform, hasAcceleratedCompositing());
return currTransform;
}
#endif
@@ -443,7 +460,7 @@ void RenderLayer::updateVisibilityStatus()
else {
do {
r = r->parent();
- if (r==renderer())
+ if (r == renderer())
r = 0;
} while (r && !r->nextSibling());
if (r)
@@ -948,7 +965,6 @@ void RenderLayer::panScrollFromPoint(const IntPoint& sourcePoint)
const int shortDistanceLimit = 100; // We delimit a 200 pixels long square enclosing the original point
const int speedReducer = 2; // Within this square we divide the scrolling speed by 2
- const int iconRadius = 10;
Frame* frame = renderer()->document()->frame();
if (!frame)
return;
@@ -965,9 +981,9 @@ void RenderLayer::panScrollFromPoint(const IntPoint& sourcePoint)
int xDelta = currentMousePosition.x() - sourcePoint.x();
int yDelta = currentMousePosition.y() - sourcePoint.y();
- if (abs(xDelta) < iconRadius) // at the center we let the space for the icon
+ if (abs(xDelta) < ScrollView::noPanScrollRadius) // at the center we let the space for the icon
xDelta = 0;
- if (abs(yDelta) < iconRadius)
+ if (abs(yDelta) < ScrollView::noPanScrollRadius)
yDelta = 0;
// Let's attenuate the speed for the short distances
@@ -1048,13 +1064,16 @@ void RenderLayer::scrollToOffset(int x, int y, bool updateScrollbars, bool repai
m_scrollX = newScrollX;
m_scrollY = y;
- // Update the positions of our child layers.
+ // Update the positions of our child layers. Don't have updateLayerPositions() update
+ // compositing layers, because we need to do a deep update from the compositing ancestor.
for (RenderLayer* child = firstChild(); child; child = child->nextSibling())
- child->updateLayerPositions(false, false);
+ child->updateLayerPositions(0);
#if USE(ACCELERATED_COMPOSITING)
- if (isComposited())
- m_backing->updateGraphicsLayerGeometry();
+ if (compositor()->inCompositingMode()) {
+ if (RenderLayer* compositingAncestor = ancestorCompositingLayer())
+ compositingAncestor->backing()->updateAfterLayout(RenderLayerBacking::AllDescendants);
+ }
#endif
RenderView* view = renderer()->view();
@@ -1300,7 +1319,7 @@ void RenderLayer::resize(const PlatformMouseEvent& evt, const IntSize& oldOffset
ExceptionCode ec;
- if (difference.width()) {
+ if (resize != RESIZE_VERTICAL && difference.width()) {
if (element->isFormControlElement()) {
// Make implicit margins from the theme explicit (see <http://bugs.webkit.org/show_bug.cgi?id=9547>).
style->setProperty(CSSPropertyMarginLeft, String::number(renderer->marginLeft() / zoomFactor) + "px", false, ec);
@@ -1312,7 +1331,7 @@ void RenderLayer::resize(const PlatformMouseEvent& evt, const IntSize& oldOffset
style->setProperty(CSSPropertyWidth, String::number(baseWidth + difference.width()) + "px", false, ec);
}
- if (difference.height()) {
+ if (resize != RESIZE_HORIZONTAL && difference.height()) {
if (element->isFormControlElement()) {
// Make implicit margins from the theme explicit (see <http://bugs.webkit.org/show_bug.cgi?id=9547>).
style->setProperty(CSSPropertyMarginTop, String::number(renderer->marginTop() / zoomFactor) + "px", false, ec);
@@ -1412,6 +1431,66 @@ bool RenderLayer::scrollbarCornerPresent() const
return !scrollCornerRect(this, renderBox()->borderBoxRect()).isEmpty();
}
+IntRect RenderLayer::convertFromScrollbarToContainingView(const Scrollbar* scrollbar, const IntRect& scrollbarRect) const
+{
+ RenderView* view = renderer()->view();
+ if (!view)
+ return scrollbarRect;
+
+ IntRect rect = scrollbarRect;
+ rect.move(scrollbarOffset(scrollbar));
+
+ return view->frameView()->convertFromRenderer(renderer(), rect);
+}
+
+IntRect RenderLayer::convertFromContainingViewToScrollbar(const Scrollbar* scrollbar, const IntRect& parentRect) const
+{
+ RenderView* view = renderer()->view();
+ if (!view)
+ return parentRect;
+
+ IntRect rect = view->frameView()->convertToRenderer(renderer(), parentRect);
+ rect.move(-scrollbarOffset(scrollbar));
+ return rect;
+}
+
+IntPoint RenderLayer::convertFromScrollbarToContainingView(const Scrollbar* scrollbar, const IntPoint& scrollbarPoint) const
+{
+ RenderView* view = renderer()->view();
+ if (!view)
+ return scrollbarPoint;
+
+ IntPoint point = scrollbarPoint;
+ point.move(scrollbarOffset(scrollbar));
+ return view->frameView()->convertFromRenderer(renderer(), point);
+}
+
+IntPoint RenderLayer::convertFromContainingViewToScrollbar(const Scrollbar* scrollbar, const IntPoint& parentPoint) const
+{
+ RenderView* view = renderer()->view();
+ if (!view)
+ return parentPoint;
+
+ IntPoint point = view->frameView()->convertToRenderer(renderer(), parentPoint);
+
+ point.move(-scrollbarOffset(scrollbar));
+ return point;
+}
+
+IntSize RenderLayer::scrollbarOffset(const Scrollbar* scrollbar) const
+{
+ RenderBox* box = renderBox();
+
+ if (scrollbar == m_vBar.get())
+ return IntSize(box->width() - box->borderRight() - scrollbar->width(), box->borderTop());
+
+ if (scrollbar == m_hBar.get())
+ return IntSize(box->borderLeft(), box->height() - box->borderBottom() - scrollbar->height());
+
+ ASSERT_NOT_REACHED();
+ return IntSize();
+}
+
void RenderLayer::invalidateScrollbarRect(Scrollbar* scrollbar, const IntRect& rect)
{
IntRect scrollRect = rect;
@@ -1823,34 +1902,29 @@ bool RenderLayer::isPointInResizeControl(const IntPoint& absolutePoint) const
return resizerCornerRect(this, localBounds).contains(localPoint);
}
-bool RenderLayer::hitTestOverflowControls(HitTestResult& result)
+bool RenderLayer::hitTestOverflowControls(HitTestResult& result, const IntPoint& localPoint)
{
if (!m_hBar && !m_vBar && (!renderer()->hasOverflowClip() || renderer()->style()->resize() == RESIZE_NONE))
return false;
RenderBox* box = renderBox();
ASSERT(box);
-
- int x = 0;
- int y = 0;
- convertToLayerCoords(root(), x, y);
- IntRect absBounds(x, y, box->width(), box->height());
IntRect resizeControlRect;
if (renderer()->style()->resize() != RESIZE_NONE) {
- resizeControlRect = resizerCornerRect(this, absBounds);
- if (resizeControlRect.contains(result.point()))
+ resizeControlRect = resizerCornerRect(this, box->borderBoxRect());
+ if (resizeControlRect.contains(localPoint))
return true;
}
int resizeControlSize = max(resizeControlRect.height(), 0);
if (m_vBar) {
- IntRect vBarRect(absBounds.right() - box->borderRight() - m_vBar->width(),
- absBounds.y() + box->borderTop(),
+ IntRect vBarRect(box->width() - box->borderRight() - m_vBar->width(),
+ box->borderTop(),
m_vBar->width(),
- absBounds.height() - (box->borderTop() + box->borderBottom()) - (m_hBar ? m_hBar->height() : resizeControlSize));
- if (vBarRect.contains(result.point())) {
+ box->height() - (box->borderTop() + box->borderBottom()) - (m_hBar ? m_hBar->height() : resizeControlSize));
+ if (vBarRect.contains(localPoint)) {
result.setScrollbar(m_vBar.get());
return true;
}
@@ -1858,11 +1932,11 @@ bool RenderLayer::hitTestOverflowControls(HitTestResult& result)
resizeControlSize = max(resizeControlRect.width(), 0);
if (m_hBar) {
- IntRect hBarRect(absBounds.x() + box->borderLeft(),
- absBounds.bottom() - box->borderBottom() - m_hBar->height(),
- absBounds.width() - (box->borderLeft() + box->borderRight()) - (m_vBar ? m_vBar->width() : resizeControlSize),
+ IntRect hBarRect(box->borderLeft(),
+ box->height() - box->borderBottom() - m_hBar->height(),
+ box->width() - (box->borderLeft() + box->borderRight()) - (m_vBar ? m_vBar->width() : resizeControlSize),
m_hBar->height());
- if (hBarRect.contains(result.point())) {
+ if (hBarRect.contains(localPoint)) {
result.setScrollbar(m_hBar.get());
return true;
}
@@ -1894,7 +1968,7 @@ bool RenderLayer::scroll(ScrollDirection direction, ScrollGranularity granularit
void RenderLayer::paint(GraphicsContext* p, const IntRect& damageRect, PaintRestriction paintRestriction, RenderObject *paintingRoot)
{
RenderObject::OverlapTestRequestMap overlapTestRequests;
- paintLayer(this, p, damageRect, false, paintRestriction, paintingRoot, &overlapTestRequests);
+ paintLayer(this, p, damageRect, paintRestriction, paintingRoot, &overlapTestRequests);
RenderObject::OverlapTestRequestMap::iterator end = overlapTestRequests.end();
for (RenderObject::OverlapTestRequestMap::iterator it = overlapTestRequests.begin(); it != end; ++it)
it->first->setOverlapTestResult(false);
@@ -1930,15 +2004,29 @@ static void performOverlapTests(RenderObject::OverlapTestRequestMap& overlapTest
overlapTestRequests.remove(overlappedRequestClients[i]);
}
+#if USE(ACCELERATED_COMPOSITING)
+static bool shouldDoSoftwarePaint(const RenderLayer* layer, bool paintingReflection)
+{
+ return paintingReflection && !layer->has3DTransform();
+}
+#endif
+
void RenderLayer::paintLayer(RenderLayer* rootLayer, GraphicsContext* p,
- const IntRect& paintDirtyRect, bool haveTransparency, PaintRestriction paintRestriction,
+ const IntRect& paintDirtyRect, PaintRestriction paintRestriction,
RenderObject* paintingRoot, RenderObject::OverlapTestRequestMap* overlapTestRequests,
- bool appliedTransform, bool temporaryClipRects)
+ PaintLayerFlags paintFlags)
{
#if USE(ACCELERATED_COMPOSITING)
- // Composited RenderLayers are painted via the backing's paintIntoLayer().
- if (isComposited() && !backing()->paintingGoesToWindow())
- return;
+ if (isComposited()) {
+ // The updatingControlTints() painting pass goes through compositing layers,
+ // but we need to ensure that we don't cache clip rects computed with the wrong root in this case.
+ if (p->updatingControlTints())
+ paintFlags |= PaintLayerTemporaryClipRects;
+ else if (!backing()->paintingGoesToWindow() && !shouldDoSoftwarePaint(this, paintFlags & PaintLayerPaintingReflection)) {
+ // If this RenderLayer should paint into its backing, that will be done via RenderLayerBacking::paintIntoLayer().
+ return;
+ }
+ }
#endif
// Avoid painting layers when stylesheets haven't loaded. This eliminates FOUC.
@@ -1952,24 +2040,24 @@ void RenderLayer::paintLayer(RenderLayer* rootLayer, GraphicsContext* p,
return;
if (paintsWithTransparency())
- haveTransparency = true;
+ paintFlags |= PaintLayerHaveTransparency;
// Apply a transform if we have one. A reflection is considered to be a transform, since it is a flip and a translate.
- if (paintsWithTransform() && !appliedTransform) {
+ if (paintsWithTransform() && !(paintFlags & PaintLayerAppliedTransform)) {
// If the transform can't be inverted, then don't paint anything.
if (!m_transform->isInvertible())
return;
// If we have a transparency layer enclosing us and we are the root of a transform, then we need to establish the transparency
// layer from the parent now.
- if (haveTransparency)
+ if (paintFlags & PaintLayerHaveTransparency)
parent()->beginTransparencyLayers(p, rootLayer);
// Make sure the parent's clip rects have been calculated.
IntRect clipRect = paintDirtyRect;
if (parent()) {
ClipRects parentRects;
- parentClipRects(rootLayer, parentRects, temporaryClipRects);
+ parentClipRects(rootLayer, parentRects, paintFlags & PaintLayerTemporaryClipRects);
clipRect = parentRects.overflowClipRect();
clipRect.intersect(paintDirtyRect);
}
@@ -1996,7 +2084,7 @@ void 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, overlapTestRequests, true, temporaryClipRects);
+ paintLayer(this, p, transform.inverse().mapRect(paintDirtyRect), paintRestriction, paintingRoot, overlapTestRequests, paintFlags | PaintLayerAppliedTransform);
p->restore();
@@ -2006,24 +2094,27 @@ void RenderLayer::paintLayer(RenderLayer* rootLayer, GraphicsContext* p,
return;
}
+ PaintLayerFlags localPaintFlags = paintFlags & ~PaintLayerAppliedTransform;
+ bool haveTransparency = localPaintFlags & PaintLayerHaveTransparency;
+
// Paint the reflection first if we have one.
- if (m_reflection && !m_paintingInsideReflection && (!m_transform || appliedTransform)) {
+ if (m_reflection && !m_paintingInsideReflection) {
// Mark that we are now inside replica painting.
m_paintingInsideReflection = true;
- reflectionLayer()->paintLayer(rootLayer, p, paintDirtyRect, haveTransparency, paintRestriction, paintingRoot, overlapTestRequests, false, temporaryClipRects);
+ reflectionLayer()->paintLayer(rootLayer, p, paintDirtyRect, paintRestriction, paintingRoot, overlapTestRequests, localPaintFlags | PaintLayerPaintingReflection);
m_paintingInsideReflection = false;
}
// Calculate the clip rects we should use.
IntRect layerBounds, damageRect, clipRectToApply, outlineRect;
- calculateRects(rootLayer, paintDirtyRect, layerBounds, damageRect, clipRectToApply, outlineRect, temporaryClipRects);
+ calculateRects(rootLayer, paintDirtyRect, layerBounds, damageRect, clipRectToApply, outlineRect, localPaintFlags & PaintLayerTemporaryClipRects);
int x = layerBounds.x();
int y = layerBounds.y();
int tx = x - renderBoxX();
int ty = y - renderBoxY();
// Ensure our lists are up-to-date.
- updateLayerListsIfNeeded();
+ updateCompositingAndLayerListsIfNeeded();
bool selectionOnly = paintRestriction == PaintRestrictionSelectionOnly || paintRestriction == PaintRestrictionSelectionOnlyBlackText;
bool forceBlackText = paintRestriction == PaintRestrictionSelectionOnlyBlackText;
@@ -2061,7 +2152,7 @@ void 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, overlapTestRequests, false, temporaryClipRects);
+ it[0]->paintLayer(rootLayer, p, paintDirtyRect, paintRestriction, paintingRoot, overlapTestRequests, localPaintFlags);
// Now establish the appropriate clip and paint our child RenderObjects.
if (shouldPaint && !clipRectToApply.isEmpty()) {
@@ -2100,12 +2191,12 @@ void RenderLayer::paintLayer(RenderLayer* rootLayer, GraphicsContext* p,
// Paint any child layers that have overflow.
if (m_normalFlowList)
for (Vector<RenderLayer*>::iterator it = m_normalFlowList->begin(); it != m_normalFlowList->end(); ++it)
- it[0]->paintLayer(rootLayer, p, paintDirtyRect, haveTransparency, paintRestriction, paintingRoot, overlapTestRequests, false, temporaryClipRects);
+ it[0]->paintLayer(rootLayer, p, paintDirtyRect, paintRestriction, paintingRoot, overlapTestRequests, localPaintFlags);
// Now walk the sorted list of children with positive z-indices.
if (m_posZOrderList)
for (Vector<RenderLayer*>::iterator it = m_posZOrderList->begin(); it != m_posZOrderList->end(); ++it)
- it[0]->paintLayer(rootLayer, p, paintDirtyRect, haveTransparency, paintRestriction, paintingRoot, overlapTestRequests, false, temporaryClipRects);
+ it[0]->paintLayer(rootLayer, p, paintDirtyRect, paintRestriction, paintingRoot, overlapTestRequests, localPaintFlags);
if (renderer()->hasMask() && shouldPaint && !selectionOnly && !damageRect.isEmpty()) {
setClip(p, paintDirtyRect, damageRect);
@@ -2303,7 +2394,7 @@ RenderLayer* RenderLayer::hitTestLayer(RenderLayer* rootLayer, RenderLayer* cont
#if USE(ACCELERATED_COMPOSITING)
if (isComposited()) {
// It doesn't make sense to project hitTestRect into the plane of this layer, so use the same bounds we use for painting.
- localHitTestRect = compositor()->calculateCompositedBounds(this, this);
+ localHitTestRect = backing()->compositedBounds();
} else
#endif
localHitTestRect = newTransformState->mappedQuad().enclosingBoundingBox();
@@ -2313,7 +2404,7 @@ RenderLayer* RenderLayer::hitTestLayer(RenderLayer* rootLayer, RenderLayer* cont
}
// Ensure our lists and 3d status are up-to-date.
- updateLayerListsIfNeeded();
+ updateCompositingAndLayerListsIfNeeded();
update3DTransformedDescendantStatus();
RefPtr<HitTestingTransformState> localTransformState;
@@ -2551,13 +2642,13 @@ void RenderLayer::calculateClipRects(const RenderLayer* rootLayer, ClipRects& cl
}
if (renderer()->hasOverflowClip()) {
- IntRect newOverflowClip = toRenderBox(renderer())->overflowClipRect(x,y);
+ IntRect newOverflowClip = toRenderBox(renderer())->overflowClipRect(x, y);
clipRects.setOverflowClipRect(intersection(newOverflowClip, clipRects.overflowClipRect()));
if (renderer()->isPositioned() || renderer()->isRelPositioned())
clipRects.setPosClipRect(intersection(newOverflowClip, clipRects.posClipRect()));
}
if (renderer()->hasClip()) {
- IntRect newPosClip = toRenderBox(renderer())->clipRect(x,y);
+ IntRect newPosClip = toRenderBox(renderer())->clipRect(x, y);
clipRects.setPosClipRect(intersection(newPosClip, clipRects.posClipRect()));
clipRects.setOverflowClipRect(intersection(newPosClip, clipRects.overflowClipRect()));
clipRects.setFixedClipRect(intersection(newPosClip, clipRects.fixedClipRect()));
@@ -2607,10 +2698,10 @@ void RenderLayer::calculateRects(const RenderLayer* rootLayer, const IntRect& pa
if (renderer()->hasOverflowClip() || renderer()->hasClip()) {
// This layer establishes a clip of some kind.
if (renderer()->hasOverflowClip())
- foregroundRect.intersect(toRenderBox(renderer())->overflowClipRect(x,y));
+ foregroundRect.intersect(toRenderBox(renderer())->overflowClipRect(x, y));
if (renderer()->hasClip()) {
// Clip applies to *us* as well, so go ahead and update the damageRect.
- IntRect newPosClip = toRenderBox(renderer())->clipRect(x,y);
+ IntRect newPosClip = toRenderBox(renderer())->clipRect(x, y);
backgroundRect.intersect(newPosClip);
foregroundRect.intersect(newPosClip);
outlineRect.intersect(newPosClip);
@@ -2621,10 +2712,13 @@ void RenderLayer::calculateRects(const RenderLayer* rootLayer, const IntRect& pa
if (ShadowData* boxShadow = renderer()->style()->boxShadow()) {
IntRect overflow = layerBounds;
do {
- IntRect shadowRect = layerBounds;
- shadowRect.move(boxShadow->x, boxShadow->y);
- shadowRect.inflate(boxShadow->blur);
- overflow.unite(shadowRect);
+ if (boxShadow->style == Normal) {
+ IntRect shadowRect = layerBounds;
+ shadowRect.move(boxShadow->x, boxShadow->y);
+ shadowRect.inflate(boxShadow->blur + boxShadow->spread);
+ overflow.unite(shadowRect);
+ }
+
boxShadow = boxShadow->next;
} while (boxShadow);
backgroundRect.intersect(overflow);
@@ -2897,7 +2991,7 @@ void RenderLayer::dirtyZOrderLists()
#if USE(ACCELERATED_COMPOSITING)
if (!renderer()->documentBeingDestroyed())
- compositor()->setCompositingLayersNeedUpdate();
+ compositor()->setCompositingLayersNeedRebuild();
#endif
}
@@ -2916,7 +3010,7 @@ void RenderLayer::dirtyNormalFlowList()
#if USE(ACCELERATED_COMPOSITING)
if (!renderer()->documentBeingDestroyed())
- compositor()->setCompositingLayersNeedUpdate();
+ compositor()->setCompositingLayersNeedRebuild();
#endif
}
@@ -2986,6 +3080,12 @@ void RenderLayer::collectLayers(Vector<RenderLayer*>*& posBuffer, Vector<RenderL
void RenderLayer::updateLayerListsIfNeeded()
{
+ updateZOrderLists();
+ updateNormalFlowList();
+}
+
+void RenderLayer::updateCompositingAndLayerListsIfNeeded()
+{
#if USE(ACCELERATED_COMPOSITING)
if (compositor()->inCompositingMode()) {
if ((isStackingContext() && m_zOrderListsDirty) || m_normalFlowListDirty)
@@ -2993,8 +3093,7 @@ void RenderLayer::updateLayerListsIfNeeded()
return;
}
#endif
- updateZOrderLists();
- updateNormalFlowList();
+ updateLayerListsIfNeeded();
}
void RenderLayer::repaintIncludingDescendants()
@@ -3051,7 +3150,7 @@ void RenderLayer::repaintIncludingNonCompositingDescendants(RenderBoxModelObject
bool RenderLayer::shouldBeNormalFlowOnly() const
{
- return (renderer()->hasOverflowClip() || renderer()->hasReflection() || renderer()->hasMask()) &&
+ return (renderer()->hasOverflowClip() || renderer()->hasReflection() || renderer()->hasMask() || renderer()->isVideo()) &&
!renderer()->isPositioned() &&
!renderer()->isRelPositioned() &&
!renderer()->hasTransform() &&
@@ -3060,7 +3159,7 @@ bool RenderLayer::shouldBeNormalFlowOnly() const
bool RenderLayer::isSelfPaintingLayer() const
{
- return !isNormalFlowOnly() || renderer()->hasReflection() || renderer()->hasMask() || renderer()->isTableRow();
+ return !isNormalFlowOnly() || renderer()->hasReflection() || renderer()->hasMask() || renderer()->isTableRow() || renderer()->isVideo();
}
void RenderLayer::styleChanged(StyleDifference diff, const RenderStyle*)
@@ -3106,7 +3205,7 @@ void RenderLayer::styleChanged(StyleDifference diff, const RenderStyle*)
updateTransform();
if (compositor()->updateLayerCompositingState(this))
- compositor()->setCompositingLayersNeedUpdate();
+ compositor()->setCompositingLayersNeedRebuild();
else if (m_backing)
m_backing->updateGraphicsLayerGeometry();
diff --git a/WebCore/rendering/RenderLayer.h b/WebCore/rendering/RenderLayer.h
index 9c8de5e..1772c66 100644
--- a/WebCore/rendering/RenderLayer.h
+++ b/WebCore/rendering/RenderLayer.h
@@ -264,7 +264,7 @@ public:
void positionOverflowControls(int tx, int ty);
bool isPointInResizeControl(const IntPoint& absolutePoint) const;
- bool hitTestOverflowControls(HitTestResult&);
+ bool hitTestOverflowControls(HitTestResult&, const IntPoint& localPoint);
IntSize offsetFromResizeCorner(const IntPoint& absolutePoint) const;
void paintOverflowControls(GraphicsContext*, int tx, int ty, const IntRect& damageRect);
@@ -289,9 +289,19 @@ public:
// Allows updates of layer content without repainting.
void rendererContentChanged();
#endif
+
+ // Returns true if the accelerated compositing is enabled
+ bool hasAcceleratedCompositing() const;
void updateLayerPosition();
- void updateLayerPositions(bool doFullRepaint = false, bool checkForRepaint = true);
+
+ enum UpdateLayerPositionsFlag {
+ DoFullRepaint = 1,
+ CheckForRepaint = 1 << 1,
+ UpdateCompositingLayers = 1 << 2,
+ };
+ typedef unsigned UpdateLayerPositionsFlags;
+ void updateLayerPositions(UpdateLayerPositionsFlags = DoFullRepaint | UpdateCompositingLayers);
void updateTransform();
@@ -372,6 +382,7 @@ public:
// Return a cached repaint rect, computed relative to the layer renderer's containerForRepaint.
IntRect repaintRect() const { return m_repaintRect; }
+ void computeRepaintRects();
void setNeedsFullRepaint(bool f = true) { m_needsFullRepaint = f; }
int staticX() const { return m_staticX; }
@@ -438,11 +449,20 @@ private:
void collectLayers(Vector<RenderLayer*>*&, Vector<RenderLayer*>*&);
void updateLayerListsIfNeeded();
+ void updateCompositingAndLayerListsIfNeeded();
+ enum PaintLayerFlag {
+ PaintLayerHaveTransparency = 1,
+ PaintLayerAppliedTransform = 1 << 1,
+ PaintLayerTemporaryClipRects = 1 << 2,
+ PaintLayerPaintingReflection = 1 << 3
+ };
+
+ typedef unsigned PaintLayerFlags;
+
void paintLayer(RenderLayer* rootLayer, GraphicsContext*, const IntRect& paintDirtyRect,
- bool haveTransparency, PaintRestriction, RenderObject* paintingRoot,
- RenderObject::OverlapTestRequestMap* = 0,
- bool appliedTransform = false, bool temporaryClipRects = false);
+ PaintRestriction, RenderObject* paintingRoot, RenderObject::OverlapTestRequestMap* = 0,
+ PaintLayerFlags paintFlags = 0);
RenderLayer* hitTestLayer(RenderLayer* rootLayer, RenderLayer* containerLayer, const HitTestRequest& request, HitTestResult& result,
const IntRect& hitTestRect, const IntPoint& hitTestPoint, bool appliedTransform,
@@ -458,11 +478,18 @@ private:
bool shouldBeNormalFlowOnly() const;
+ // ScrollBarClient interface
virtual void valueChanged(Scrollbar*);
virtual void invalidateScrollbarRect(Scrollbar*, const IntRect&);
virtual bool isActive() const;
virtual bool scrollbarCornerPresent() const;
-
+ virtual IntRect convertFromScrollbarToContainingView(const Scrollbar*, const IntRect&) const;
+ virtual IntRect convertFromContainingViewToScrollbar(const Scrollbar*, const IntRect&) const;
+ virtual IntPoint convertFromScrollbarToContainingView(const Scrollbar*, const IntPoint&) const;
+ virtual IntPoint convertFromContainingViewToScrollbar(const Scrollbar*, const IntPoint&) const;
+
+ IntSize scrollbarOffset(const Scrollbar*) const;
+
void updateOverflowStatus(bool horizontalOverflow, bool verticalOverflow);
void childVisibilityChanged(bool newVisibility);
@@ -482,6 +509,7 @@ private:
void createReflection();
void updateReflectionStyle();
bool paintingInsideReflection() const { return m_paintingInsideReflection; }
+ void setPaintingInsideReflection(bool b) { m_paintingInsideReflection = b; }
void parentClipRects(const RenderLayer* rootLayer, ClipRects&, bool temporaryClipRects = false) const;
@@ -497,8 +525,8 @@ private:
bool hasCompositingDescendant() const { return m_hasCompositingDescendant; }
void setHasCompositingDescendant(bool b) { m_hasCompositingDescendant = b; }
- bool mustOverlayCompositedLayers() const { return m_mustOverlayCompositedLayers; }
- void setMustOverlayCompositedLayers(bool b) { m_mustOverlayCompositedLayers = b; }
+ bool mustOverlapCompositedLayers() const { return m_mustOverlapCompositedLayers; }
+ void setMustOverlapCompositedLayers(bool b) { m_mustOverlapCompositedLayers = b; }
#endif
private:
@@ -591,7 +619,7 @@ protected:
// in a preserves3D hierarchy. Hint to do 3D-aware hit testing.
#if USE(ACCELERATED_COMPOSITING)
bool m_hasCompositingDescendant : 1;
- bool m_mustOverlayCompositedLayers : 1;
+ bool m_mustOverlapCompositedLayers : 1;
#endif
RenderMarquee* m_marquee; // Used by layers with overflow:marquee
diff --git a/WebCore/rendering/RenderLayerBacking.cpp b/WebCore/rendering/RenderLayerBacking.cpp
index e16ecf7..e98c458 100644
--- a/WebCore/rendering/RenderLayerBacking.cpp
+++ b/WebCore/rendering/RenderLayerBacking.cpp
@@ -55,10 +55,9 @@ RenderLayerBacking::RenderLayerBacking(RenderLayer* layer)
: m_owningLayer(layer)
, m_ancestorClippingLayer(0)
, m_graphicsLayer(0)
- , m_contentsLayer(0)
+ , m_foregroundLayer(0)
, m_clippingLayer(0)
, m_hasDirectlyCompositedContent(false)
- , m_compositingContentOffsetDirty(true)
{
createGraphicsLayer();
}
@@ -66,7 +65,7 @@ RenderLayerBacking::RenderLayerBacking(RenderLayer* layer)
RenderLayerBacking::~RenderLayerBacking()
{
updateClippingLayers(false, false);
- updateContentsLayer(false);
+ updateForegroundLayer(false);
destroyGraphicsLayer();
}
@@ -75,14 +74,17 @@ void RenderLayerBacking::createGraphicsLayer()
m_graphicsLayer = GraphicsLayer::createGraphicsLayer(this);
#ifndef NDEBUG
- if (renderer()->node()->isDocumentNode())
- m_graphicsLayer->setName("Document Node");
- else {
- if (renderer()->node()->isHTMLElement() && renderer()->node()->hasID())
- m_graphicsLayer->setName(renderer()->renderName() + String(" ") + static_cast<HTMLElement*>(renderer()->node())->id());
- else
- m_graphicsLayer->setName(renderer()->renderName());
- }
+ if (renderer()->node()) {
+ if (renderer()->node()->isDocumentNode())
+ m_graphicsLayer->setName("Document Node");
+ else {
+ if (renderer()->node()->isHTMLElement() && renderer()->node()->hasID())
+ m_graphicsLayer->setName(renderer()->renderName() + String(" ") + static_cast<HTMLElement*>(renderer()->node())->id());
+ else
+ m_graphicsLayer->setName(renderer()->renderName());
+ }
+ } else
+ m_graphicsLayer->setName("Anonymous Node");
#endif // NDEBUG
updateLayerOpacity();
@@ -97,8 +99,8 @@ void RenderLayerBacking::destroyGraphicsLayer()
delete m_graphicsLayer;
m_graphicsLayer = 0;
- delete m_contentsLayer;
- m_contentsLayer = 0;
+ delete m_foregroundLayer;
+ m_foregroundLayer = 0;
delete m_clippingLayer;
m_clippingLayer = 0;
@@ -106,7 +108,7 @@ void RenderLayerBacking::destroyGraphicsLayer()
void RenderLayerBacking::updateLayerOpacity()
{
- m_graphicsLayer->setOpacity(compositingOpacity(renderer()->opacity()), 0, 0);
+ m_graphicsLayer->setOpacity(compositingOpacity(renderer()->opacity()));
}
void RenderLayerBacking::updateLayerTransform()
@@ -118,17 +120,31 @@ void RenderLayerBacking::updateLayerTransform()
TransformationMatrix t;
if (m_owningLayer->hasTransform()) {
style->applyTransform(t, toRenderBox(renderer())->borderBoxRect().size(), RenderStyle::ExcludeTransformOrigin);
- makeMatrixRenderable(t);
+ makeMatrixRenderable(t, compositor()->hasAcceleratedCompositing());
}
m_graphicsLayer->setTransform(t);
}
-void RenderLayerBacking::updateAfterLayout()
+void RenderLayerBacking::updateAfterLayout(UpdateDepth updateDepth)
{
- // Only need to update geometry if there isn't a layer update pending.
- if (!compositor()->compositingLayersNeedUpdate())
- updateGraphicsLayerGeometry();
+ RenderLayerCompositor* layerCompositor = compositor();
+ if (!layerCompositor->compositingLayersNeedRebuild()) {
+ // Calling updateGraphicsLayerGeometry() here gives incorrect results, because the
+ // position of this layer's GraphicsLayer depends on the position of our compositing
+ // ancestor's GraphicsLayer. That cannot be determined until all the descendant
+ // RenderLayers of that ancestor have been processed via updateLayerPositions().
+ //
+ // The solution is to update compositing children of this layer here,
+ // via updateCompositingChildrenGeometry().
+ setCompositedBounds(layerCompositor->calculateCompositedBounds(m_owningLayer, m_owningLayer));
+ layerCompositor->updateCompositingDescendantGeometry(m_owningLayer, m_owningLayer, updateDepth);
+
+ if (!m_owningLayer->parent()) {
+ updateGraphicsLayerGeometry();
+ layerCompositor->updateRootLayerPosition();
+ }
+ }
}
bool RenderLayerBacking::updateGraphicsLayerConfiguration()
@@ -136,7 +152,7 @@ bool RenderLayerBacking::updateGraphicsLayerConfiguration()
RenderLayerCompositor* compositor = this->compositor();
bool layerConfigChanged = false;
- if (updateContentsLayer(compositor->needsContentsCompositingLayer(m_owningLayer)))
+ if (updateForegroundLayer(compositor->needsContentsCompositingLayer(m_owningLayer)))
layerConfigChanged = true;
if (updateClippingLayers(compositor->clippedByAncestor(m_owningLayer), compositor->clipsCompositingDescendants(m_owningLayer)))
@@ -178,16 +194,16 @@ void RenderLayerBacking::updateGraphicsLayerGeometry()
m_graphicsLayer->setPreserves3D(style->transformStyle3D() == TransformStyle3DPreserve3D);
m_graphicsLayer->setBackfaceVisibility(style->backfaceVisibility() == BackfaceVisibilityVisible);
- m_compositingContentOffsetDirty = true;
-
RenderLayer* compAncestor = m_owningLayer->ancestorCompositingLayer();
// We compute everything relative to the enclosing compositing layer.
IntRect ancestorCompositingBounds;
- if (compAncestor)
- ancestorCompositingBounds = compositor()->calculateCompositedBounds(compAncestor, compAncestor);
-
- IntRect localCompositingBounds = compositor()->calculateCompositedBounds(m_owningLayer, m_owningLayer);
+ if (compAncestor) {
+ ASSERT(compAncestor->backing());
+ ancestorCompositingBounds = compAncestor->backing()->compositedBounds();
+ }
+
+ IntRect localCompositingBounds = compositedBounds();
IntRect relativeCompositingBounds(localCompositingBounds);
int deltaX = 0, deltaY = 0;
@@ -276,21 +292,21 @@ void RenderLayerBacking::updateGraphicsLayerGeometry()
m_graphicsLayer->setAnchorPoint(FloatPoint3D(0.5f, 0.5f, 0));
}
- if (m_contentsLayer) {
+ if (m_foregroundLayer) {
// The contents layer is always coincidental with the graphicsLayer for now.
- m_contentsLayer->setPosition(IntPoint(0, 0));
- m_contentsLayer->setSize(newSize);
- m_contentsLayer->setOffsetFromRenderer(m_graphicsLayer->offsetFromRenderer());
+ m_foregroundLayer->setPosition(IntPoint(0, 0));
+ m_foregroundLayer->setSize(newSize);
+ m_foregroundLayer->setOffsetFromRenderer(m_graphicsLayer->offsetFromRenderer());
}
- m_graphicsLayer->updateContentsRect();
+ m_graphicsLayer->setContentsRect(contentsBox());
if (!m_hasDirectlyCompositedContent)
m_graphicsLayer->setDrawsContent(!isSimpleContainerCompositingLayer() && !paintingGoesToWindow());
}
void RenderLayerBacking::updateInternalHierarchy()
{
- // m_contentsLayer has to be inserted in the correct order with child layers,
+ // m_foregroundLayer has to be inserted in the correct order with child layers,
// so it's not inserted here.
if (m_ancestorClippingLayer) {
m_ancestorClippingLayer->removeAllChildren();
@@ -347,24 +363,24 @@ bool RenderLayerBacking::updateClippingLayers(bool needsAncestorClip, bool needs
return layersChanged;
}
-bool RenderLayerBacking::updateContentsLayer(bool needsContentsLayer)
+bool RenderLayerBacking::updateForegroundLayer(bool needsForegroundLayer)
{
bool layerChanged = false;
- if (needsContentsLayer) {
- if (!m_contentsLayer) {
- m_contentsLayer = GraphicsLayer::createGraphicsLayer(this);
+ if (needsForegroundLayer) {
+ if (!m_foregroundLayer) {
+ m_foregroundLayer = GraphicsLayer::createGraphicsLayer(this);
#ifndef NDEBUG
- m_contentsLayer->setName("Contents");
+ m_foregroundLayer->setName("Contents");
#endif
- m_contentsLayer->setDrawsContent(true);
- m_contentsLayer->setDrawingPhase(GraphicsLayerPaintForegroundMask);
+ m_foregroundLayer->setDrawsContent(true);
+ m_foregroundLayer->setDrawingPhase(GraphicsLayerPaintForegroundMask);
m_graphicsLayer->setDrawingPhase(GraphicsLayerPaintBackgroundMask);
layerChanged = true;
}
- } else if (m_contentsLayer) {
- m_contentsLayer->removeFromParent();
- delete m_contentsLayer;
- m_contentsLayer = 0;
+ } else if (m_foregroundLayer) {
+ m_foregroundLayer->removeFromParent();
+ delete m_foregroundLayer;
+ m_foregroundLayer = 0;
m_graphicsLayer->setDrawingPhase(GraphicsLayerPaintAllMask);
layerChanged = true;
}
@@ -410,7 +426,7 @@ static bool hasBoxDecorationsWithBackgroundImage(const RenderStyle* style)
bool RenderLayerBacking::rendererHasBackground() const
{
// FIXME: share more code here
- if (renderer()->node()->isDocumentNode()) {
+ if (renderer()->node() && renderer()->node()->isDocumentNode()) {
RenderObject* htmlObject = renderer()->firstChild();
if (!htmlObject)
return false;
@@ -433,7 +449,7 @@ bool RenderLayerBacking::rendererHasBackground() const
const Color& RenderLayerBacking::rendererBackgroundColor() const
{
// FIXME: share more code here
- if (renderer()->node()->isDocumentNode()) {
+ if (renderer()->node() && renderer()->node()->isDocumentNode()) {
RenderObject* htmlObject = renderer()->firstChild();
RenderStyle* style = htmlObject->style();
if (style->hasBackground())
@@ -469,7 +485,7 @@ bool RenderLayerBacking::isSimpleContainerCompositingLayer() const
if (!renderObject->firstChild())
return true;
- if (renderObject->node()->isDocumentNode()) {
+ if (renderObject->node() && renderObject->node()->isDocumentNode()) {
// Look to see if the root object has a non-simple backgound
RenderObject* rootObject = renderObject->document()->documentElement()->renderer();
if (!rootObject)
@@ -529,29 +545,29 @@ bool RenderLayerBacking::hasNonCompositingContent() const
// FIXME: test for overflow controls.
if (m_owningLayer->isStackingContext()) {
// Use the m_hasCompositingDescendant bit to optimize?
- Vector<RenderLayer*>* negZOrderList = m_owningLayer->negZOrderList();
- if (negZOrderList && negZOrderList->size() > 0) {
- for (Vector<RenderLayer*>::const_iterator it = negZOrderList->begin(); it != negZOrderList->end(); ++it) {
- RenderLayer* curLayer = (*it);
+ if (Vector<RenderLayer*>* negZOrderList = m_owningLayer->negZOrderList()) {
+ size_t listSize = negZOrderList->size();
+ for (size_t i = 0; i < listSize; ++i) {
+ RenderLayer* curLayer = negZOrderList->at(i);
if (!curLayer->isComposited())
return true;
}
}
- Vector<RenderLayer*>* posZOrderList = m_owningLayer->posZOrderList();
- if (posZOrderList && posZOrderList->size() > 0) {
- for (Vector<RenderLayer*>::const_iterator it = posZOrderList->begin(); it != posZOrderList->end(); ++it) {
- RenderLayer* curLayer = (*it);
+ if (Vector<RenderLayer*>* posZOrderList = m_owningLayer->posZOrderList()) {
+ size_t listSize = posZOrderList->size();
+ for (size_t i = 0; i < listSize; ++i) {
+ RenderLayer* curLayer = posZOrderList->at(i);
if (!curLayer->isComposited())
return true;
}
}
}
- Vector<RenderLayer*>* normalFlowList = m_owningLayer->normalFlowList();
- if (normalFlowList && normalFlowList->size() > 0) {
- for (Vector<RenderLayer*>::const_iterator it = normalFlowList->begin(); it != normalFlowList->end(); ++it) {
- RenderLayer* curLayer = (*it);
+ if (Vector<RenderLayer*>* normalFlowList = m_owningLayer->normalFlowList()) {
+ size_t listSize = normalFlowList->size();
+ for (size_t i = 0; i < listSize; ++i) {
+ RenderLayer* curLayer = normalFlowList->at(i);
if (!curLayer->isComposited())
return true;
}
@@ -567,11 +583,15 @@ bool RenderLayerBacking::canUseDirectCompositing() const
RenderObject* renderObject = renderer();
// Reject anything that isn't an image
- if (!renderObject->isImage())
+ if (!renderObject->isImage() && !renderObject->isVideo())
return false;
if (renderObject->hasMask() || renderObject->hasReflection())
return false;
+
+ // Video can use an inner layer even if it has box decorations; we draw those into another layer.
+ if (renderObject->isVideo())
+ return true;
// Reject anything that would require the image to be drawn via the GraphicsContext,
// like border, shadows etc. Solid background color is OK.
@@ -587,7 +607,7 @@ void RenderLayerBacking::rendererContentChanged()
void RenderLayerBacking::updateImageContents()
{
ASSERT(renderer()->isImage());
- RenderImage* imageRenderer = static_cast<RenderImage*>(renderer());
+ RenderImage* imageRenderer = toRenderImage(renderer());
CachedImage* cachedImage = imageRenderer->cachedImage();
if (!cachedImage)
@@ -637,24 +657,25 @@ FloatPoint RenderLayerBacking::computePerspectiveOrigin(const IntRect& borderBox
}
// Return the offset from the top-left of this compositing layer at which the renderer's contents are painted.
-IntSize RenderLayerBacking::contentOffsetInCompostingLayer()
+IntSize RenderLayerBacking::contentOffsetInCompostingLayer() const
{
- if (!m_compositingContentOffsetDirty)
- return m_compositingContentOffset;
-
- IntRect relativeCompositingBounds = compositor()->calculateCompositedBounds(m_owningLayer, m_owningLayer);
- m_compositingContentOffset = IntSize(-relativeCompositingBounds.x(), -relativeCompositingBounds.y());
- m_compositingContentOffsetDirty = false;
-
- return m_compositingContentOffset;
+ return IntSize(-m_compositedBounds.x(), -m_compositedBounds.y());
}
-IntRect RenderLayerBacking::contentsBox(const GraphicsLayer*)
+IntRect RenderLayerBacking::contentsBox() const
{
if (!renderer()->isBox())
return IntRect();
- IntRect contentsRect = toRenderBox(renderer())->contentBoxRect();
+ IntRect contentsRect;
+#if ENABLE(VIDEO)
+ if (renderer()->isVideo()) {
+ RenderVideo* videoRenderer = toRenderVideo(renderer());
+ contentsRect = videoRenderer->videoBox();
+ } else
+#endif
+ contentsRect = toRenderBox(renderer())->contentBoxRect();
+
IntSize contentOffset = contentOffsetInCompostingLayer();
contentsRect.move(contentOffset);
return contentsRect;
@@ -679,16 +700,17 @@ bool RenderLayerBacking::paintingGoesToWindow() const
void RenderLayerBacking::setContentsNeedDisplay()
{
- if (m_graphicsLayer)
+ if (m_graphicsLayer && m_graphicsLayer->drawsContent())
m_graphicsLayer->setNeedsDisplay();
- if (m_contentsLayer)
- m_contentsLayer->setNeedsDisplay();
+
+ if (m_foregroundLayer && m_foregroundLayer->drawsContent())
+ m_foregroundLayer->setNeedsDisplay();
}
// r is in the coordinate space of the layer's render object
void RenderLayerBacking::setContentsNeedDisplayInRect(const IntRect& r)
{
- if (m_graphicsLayer) {
+ if (m_graphicsLayer && m_graphicsLayer->drawsContent()) {
FloatPoint dirtyOrigin = contentsToGraphicsLayerCoordinates(m_graphicsLayer, FloatPoint(r.x(), r.y()));
FloatRect dirtyRect(dirtyOrigin, r.size());
FloatRect bounds(FloatPoint(), m_graphicsLayer->size());
@@ -696,9 +718,9 @@ void RenderLayerBacking::setContentsNeedDisplayInRect(const IntRect& r)
m_graphicsLayer->setNeedsDisplayInRect(dirtyRect);
}
- if (m_contentsLayer) {
+ if (m_foregroundLayer && m_foregroundLayer->drawsContent()) {
// FIXME: do incremental repaint
- m_contentsLayer->setNeedsDisplay();
+ m_foregroundLayer->setNeedsDisplay();
}
}
@@ -720,7 +742,7 @@ static void restoreClip(GraphicsContext* p, const IntRect& paintDirtyRect, const
// Share this with RenderLayer::paintLayer, which would have to be educated about GraphicsLayerPaintingPhase?
void RenderLayerBacking::paintIntoLayer(RenderLayer* rootLayer, GraphicsContext* context,
const IntRect& paintDirtyRect, // in the coords of rootLayer
- bool haveTransparency, PaintRestriction paintRestriction, GraphicsLayerPaintingPhase paintingPhase,
+ PaintRestriction paintRestriction, GraphicsLayerPaintingPhase paintingPhase,
RenderObject* paintingRoot)
{
if (paintingGoesToWindow()) {
@@ -730,6 +752,14 @@ void RenderLayerBacking::paintIntoLayer(RenderLayer* rootLayer, GraphicsContext*
m_owningLayer->updateLayerListsIfNeeded();
+ // Paint the reflection first if we have one.
+ if (m_owningLayer->hasReflection()) {
+ // Mark that we are now inside replica painting.
+ m_owningLayer->setPaintingInsideReflection(true);
+ m_owningLayer->reflectionLayer()->paintLayer(rootLayer, context, paintDirtyRect, paintRestriction, paintingRoot, 0, RenderLayer::PaintLayerPaintingReflection);
+ m_owningLayer->setPaintingInsideReflection(false);
+ }
+
// Calculate the clip rects we should use.
IntRect layerBounds, damageRect, clipRectToApply, outlineRect;
m_owningLayer->calculateRects(rootLayer, paintDirtyRect, layerBounds, damageRect, clipRectToApply, outlineRect);
@@ -747,13 +777,15 @@ void RenderLayerBacking::paintIntoLayer(RenderLayer* rootLayer, GraphicsContext*
if (paintingRoot && !renderer()->isDescendantOf(paintingRoot))
paintingRootForRenderer = paintingRoot;
- if (paintingPhase & GraphicsLayerPaintBackgroundMask) {
+ bool shouldPaint = m_owningLayer->hasVisibleContent() && m_owningLayer->isSelfPaintingLayer();
+
+ if (shouldPaint && (paintingPhase & GraphicsLayerPaintBackgroundMask)) {
// If this is the root then we need to send in a bigger bounding box
// because we'll be painting the background as well (see RenderBox::paintRootBoxDecorations()).
IntRect paintBox = clipRectToApply;
// FIXME: do we need this code?
- if (renderer()->node()->isDocumentNode() && renderer()->document()->isHTMLDocument()) {
+ if (renderer()->node() && renderer()->node()->isDocumentNode() && renderer()->document()->isHTMLDocument()) {
RenderBox* box = toRenderBox(renderer());
int w = box->width();
int h = box->height();
@@ -791,13 +823,13 @@ void RenderLayerBacking::paintIntoLayer(RenderLayer* rootLayer, GraphicsContext*
restoreClip(context, paintDirtyRect, damageRect);
}
- if (paintingPhase & GraphicsLayerPaintForegroundMask) {
+ if (shouldPaint && (paintingPhase & GraphicsLayerPaintForegroundMask)) {
// Now walk the sorted list of children with negative z-indices. Only RenderLayers without compositing layers will paint.
// FIXME: should these be painted as background?
Vector<RenderLayer*>* negZOrderList = m_owningLayer->negZOrderList();
if (negZOrderList) {
for (Vector<RenderLayer*>::iterator it = negZOrderList->begin(); it != negZOrderList->end(); ++it)
- it[0]->paintLayer(rootLayer, context, paintDirtyRect, haveTransparency, paintRestriction, paintingRoot);
+ it[0]->paintLayer(rootLayer, context, paintDirtyRect, paintRestriction, paintingRoot);
}
bool forceBlackText = paintRestriction == PaintRestrictionSelectionOnlyBlackText;
@@ -836,14 +868,14 @@ void RenderLayerBacking::paintIntoLayer(RenderLayer* rootLayer, GraphicsContext*
Vector<RenderLayer*>* normalFlowList = m_owningLayer->normalFlowList();
if (normalFlowList) {
for (Vector<RenderLayer*>::iterator it = normalFlowList->begin(); it != normalFlowList->end(); ++it)
- it[0]->paintLayer(rootLayer, context, paintDirtyRect, haveTransparency, paintRestriction, paintingRoot);
+ it[0]->paintLayer(rootLayer, context, paintDirtyRect, paintRestriction, paintingRoot);
}
// Now walk the sorted list of children with positive z-indices.
Vector<RenderLayer*>* posZOrderList = m_owningLayer->posZOrderList();
if (posZOrderList) {
for (Vector<RenderLayer*>::iterator it = posZOrderList->begin(); it != posZOrderList->end(); ++it)
- it[0]->paintLayer(rootLayer, context, paintDirtyRect, haveTransparency, paintRestriction, paintingRoot);
+ it[0]->paintLayer(rootLayer, context, paintDirtyRect, paintRestriction, paintingRoot);
}
if (renderer()->hasMask() && !selectionOnly && !damageRect.isEmpty()) {
@@ -866,7 +898,7 @@ void RenderLayerBacking::paintContents(const GraphicsLayer*, GraphicsContext& co
{
// We have to use the same root as for hit testing, because both methods
// can compute and cache clipRects.
- IntRect enclosingBBox = compositor()->calculateCompositedBounds(m_owningLayer, m_owningLayer);
+ IntRect enclosingBBox = compositedBounds();
IntRect clipRect(clip);
@@ -880,7 +912,7 @@ void RenderLayerBacking::paintContents(const GraphicsLayer*, GraphicsContext& co
IntRect dirtyRect = enclosingBBox;
dirtyRect.intersect(clipRect);
- paintIntoLayer(m_owningLayer, &context, dirtyRect, false, PaintRestrictionNone, drawingPhase, renderer());
+ paintIntoLayer(m_owningLayer, &context, dirtyRect, PaintRestrictionNone, drawingPhase, renderer());
}
bool RenderLayerBacking::startAnimation(double beginTime, const Animation* anim, const KeyframeList& keyframes)
@@ -891,8 +923,8 @@ bool RenderLayerBacking::startAnimation(double beginTime, const Animation* anim,
if (!hasOpacity && !hasTransform)
return false;
- GraphicsLayer::TransformValueList transformVector;
- GraphicsLayer::FloatValueList opacityVector;
+ KeyframeValueList transformVector(AnimatedPropertyWebkitTransform);
+ KeyframeValueList opacityVector(AnimatedPropertyOpacity);
for (Vector<KeyframeValue>::const_iterator it = keyframes.beginKeyframes(); it != keyframes.endKeyframes(); ++it) {
const RenderStyle* keyframeStyle = it->style();
@@ -905,22 +937,26 @@ bool RenderLayerBacking::startAnimation(double beginTime, const Animation* anim,
const TimingFunction* tf = keyframeStyle->hasAnimations() ? &((*keyframeStyle->animations()).animation(0)->timingFunction()) : 0;
if (hasTransform)
- transformVector.insert(key, &(keyframeStyle->transform()), tf);
-
+ transformVector.insert(new TransformAnimationValue(key, &(keyframeStyle->transform()), tf));
+
if (hasOpacity)
- opacityVector.insert(key, keyframeStyle->opacity(), tf);
+ opacityVector.insert(new FloatAnimationValue(key, keyframeStyle->opacity(), tf));
}
bool didAnimateTransform = !hasTransform;
bool didAnimateOpacity = !hasOpacity;
- if (hasTransform && m_graphicsLayer->animateTransform(transformVector, toRenderBox(renderer())->borderBoxRect().size(), anim, beginTime, false))
+ if (hasTransform && m_graphicsLayer->addAnimation(transformVector, toRenderBox(renderer())->borderBoxRect().size(), anim, keyframes.animationName(), beginTime))
didAnimateTransform = true;
- if (hasOpacity && m_graphicsLayer->animateFloat(AnimatedPropertyOpacity, opacityVector, anim, beginTime))
+ if (hasOpacity && m_graphicsLayer->addAnimation(opacityVector, IntSize(), anim, keyframes.animationName(), beginTime))
didAnimateOpacity = true;
- return didAnimateTransform && didAnimateOpacity;
+ bool runningAcceleratedAnimation = didAnimateTransform && didAnimateOpacity;
+ if (runningAcceleratedAnimation)
+ compositor()->didStartAcceleratedAnimation();
+
+ return runningAcceleratedAnimation;
}
bool RenderLayerBacking::startTransition(double beginTime, int property, const RenderStyle* fromStyle, const RenderStyle* toStyle)
@@ -931,29 +967,27 @@ bool RenderLayerBacking::startTransition(double beginTime, int property, const R
if (property == (int)CSSPropertyOpacity) {
const Animation* opacityAnim = toStyle->transitionForProperty(CSSPropertyOpacity);
if (opacityAnim && !opacityAnim->isEmptyOrZeroDuration()) {
- // If beginTime is not 0, we are restarting this transition, so first set the from value
- // in case it was smashed by a previous animation.
- if (beginTime > 0)
- m_graphicsLayer->setOpacity(compositingOpacity(fromStyle->opacity()), 0, 0);
-
- if (m_graphicsLayer->setOpacity(compositingOpacity(toStyle->opacity()), opacityAnim, beginTime))
+ KeyframeValueList opacityVector(AnimatedPropertyOpacity);
+ opacityVector.insert(new FloatAnimationValue(0, compositingOpacity(fromStyle->opacity())));
+ opacityVector.insert(new FloatAnimationValue(1, compositingOpacity(toStyle->opacity())));
+ if (m_graphicsLayer->addAnimation(opacityVector, toRenderBox(renderer())->borderBoxRect().size(), opacityAnim, String(), beginTime))
didAnimate = true;
}
}
if (property == (int)CSSPropertyWebkitTransform && m_owningLayer->hasTransform()) {
- // We get a TransformOperation, which is a linked list of primitive operations and their arguments.
- // Arguments can be floats or Length values, which need to be converted to numbers using
- // val.calcFloatValue(renderer()->width()) (or height()).
const Animation* transformAnim = toStyle->transitionForProperty(CSSPropertyWebkitTransform);
if (transformAnim && !transformAnim->isEmptyOrZeroDuration()) {
- GraphicsLayer::TransformValueList transformVector;
- transformVector.insert(0, &fromStyle->transform(), 0);
- transformVector.insert(1, &toStyle->transform(), 0);
- if (m_graphicsLayer->animateTransform(transformVector, toRenderBox(renderer())->borderBoxRect().size(), transformAnim, beginTime, true))
+ KeyframeValueList transformVector(AnimatedPropertyWebkitTransform);
+ transformVector.insert(new TransformAnimationValue(0, &fromStyle->transform()));
+ transformVector.insert(new TransformAnimationValue(1, &toStyle->transform()));
+ if (m_graphicsLayer->addAnimation(transformVector, toRenderBox(renderer())->borderBoxRect().size(), transformAnim, String(), beginTime))
didAnimate = true;
}
}
+
+ if (didAnimate)
+ compositor()->didStartAcceleratedAnimation();
return didAnimate;
}
@@ -963,21 +997,32 @@ void RenderLayerBacking::notifyAnimationStarted(const GraphicsLayer*, double tim
renderer()->animation()->notifyAnimationStarted(renderer(), time);
}
-void RenderLayerBacking::animationFinished(const String& name, int index, bool reset)
+void RenderLayerBacking::notifySyncRequired(const GraphicsLayer*)
{
- m_graphicsLayer->removeFinishedAnimations(name, index, reset);
+ if (!renderer()->documentBeingDestroyed())
+ compositor()->scheduleSync();
+}
+
+void RenderLayerBacking::animationFinished(const String& animationName)
+{
+ m_graphicsLayer->removeAnimationsForKeyframes(animationName);
+}
+
+void RenderLayerBacking::animationPaused(const String& animationName)
+{
+ m_graphicsLayer->pauseAnimation(animationName);
}
void RenderLayerBacking::transitionFinished(int property)
{
AnimatedPropertyID animatedProperty = cssToGraphicsLayerProperty(property);
if (animatedProperty != AnimatedPropertyInvalid)
- m_graphicsLayer->removeFinishedTransitions(animatedProperty);
+ m_graphicsLayer->removeAnimationsForProperty(animatedProperty);
}
-void RenderLayerBacking::suspendAnimations()
+void RenderLayerBacking::suspendAnimations(double time)
{
- m_graphicsLayer->suspendAnimations();
+ m_graphicsLayer->suspendAnimations(time);
}
void RenderLayerBacking::resumeAnimations()
@@ -985,6 +1030,16 @@ void RenderLayerBacking::resumeAnimations()
m_graphicsLayer->resumeAnimations();
}
+IntRect RenderLayerBacking::compositedBounds() const
+{
+ return m_compositedBounds;
+}
+
+void RenderLayerBacking::setCompositedBounds(const IntRect& bounds)
+{
+ m_compositedBounds = bounds;
+
+}
int RenderLayerBacking::graphicsLayerToCSSProperty(AnimatedPropertyID property)
{
int cssProperty = CSSPropertyInvalid;
diff --git a/WebCore/rendering/RenderLayerBacking.h b/WebCore/rendering/RenderLayerBacking.h
index a6a6c1f..b027685 100644
--- a/WebCore/rendering/RenderLayerBacking.h
+++ b/WebCore/rendering/RenderLayerBacking.h
@@ -53,12 +53,15 @@ public:
RenderLayer* owningLayer() const { return m_owningLayer; }
- void updateAfterLayout();
+ enum UpdateDepth { CompositingChildren, AllDescendants };
+ void updateAfterLayout(UpdateDepth);
// Returns true if layer configuration changed.
bool updateGraphicsLayerConfiguration();
- void updateGraphicsLayerGeometry();
- void updateInternalHierarchy();
+ // Update graphics layer position and bounds.
+ void updateGraphicsLayerGeometry(); // make private
+ // Update contents and clipping structure.
+ void updateInternalHierarchy(); // make private
GraphicsLayer* graphicsLayer() const { return m_graphicsLayer; }
@@ -70,8 +73,8 @@ public:
bool hasAncestorClippingLayer() const { return m_ancestorClippingLayer != 0; }
GraphicsLayer* ancestorClippingLayer() const { return m_ancestorClippingLayer; }
- bool hasContentsLayer() const { return m_contentsLayer != 0; }
- GraphicsLayer* contentsLayer() const { return m_contentsLayer; }
+ bool hasContentsLayer() const { return m_foregroundLayer != 0; }
+ GraphicsLayer* foregroundLayer() const { return m_foregroundLayer; }
GraphicsLayer* parentForSublayers() const { return m_clippingLayer ? m_clippingLayer : m_graphicsLayer; }
GraphicsLayer* childForSuperlayers() const { return m_ancestorClippingLayer ? m_ancestorClippingLayer : m_graphicsLayer; }
@@ -94,21 +97,26 @@ public:
// Interface to start, finish, suspend and resume animations and transitions
bool startAnimation(double beginTime, const Animation* anim, const KeyframeList& keyframes);
bool startTransition(double beginTime, int property, const RenderStyle* fromStyle, const RenderStyle* toStyle);
- void animationFinished(const String& name, int index, bool reset);
+ void animationFinished(const String& name);
+ void animationPaused(const String& name);
void transitionFinished(int property);
- void suspendAnimations();
+ void suspendAnimations(double time = 0);
void resumeAnimations();
+ IntRect compositedBounds() const;
+ void setCompositedBounds(const IntRect&);
+
FloatPoint graphicsLayerToContentsCoordinates(const GraphicsLayer*, const FloatPoint&);
FloatPoint contentsToGraphicsLayerCoordinates(const GraphicsLayer*, const FloatPoint&);
// GraphicsLayerClient interface
virtual void notifyAnimationStarted(const GraphicsLayer*, double startTime);
+ virtual void notifySyncRequired(const GraphicsLayer*);
virtual void paintContents(const GraphicsLayer*, GraphicsContext&, GraphicsLayerPaintingPhase, const IntRect& clip);
- virtual IntRect contentsBox(const GraphicsLayer*);
+ IntRect contentsBox() const;
private:
void createGraphicsLayer();
@@ -118,9 +126,9 @@ private:
RenderLayerCompositor* compositor() const { return m_owningLayer->compositor(); }
bool updateClippingLayers(bool needsAncestorClip, bool needsDescendantClip);
- bool updateContentsLayer(bool needsContentsLayer);
+ bool updateForegroundLayer(bool needsForegroundLayer);
- IntSize contentOffsetInCompostingLayer();
+ IntSize contentOffsetInCompostingLayer() const;
// Result is transform origin in pixels.
FloatPoint3D computeTransformOrigin(const IntRect& borderBox) const;
// Result is perspective origin in pixels.
@@ -146,7 +154,7 @@ private:
bool hasNonCompositingContent() const;
void paintIntoLayer(RenderLayer* rootLayer, GraphicsContext*, const IntRect& paintDirtyRect,
- bool haveTransparency, PaintRestriction paintRestriction, GraphicsLayerPaintingPhase, RenderObject* paintingRoot);
+ PaintRestriction paintRestriction, GraphicsLayerPaintingPhase, RenderObject* paintingRoot);
static int graphicsLayerToCSSProperty(AnimatedPropertyID);
static AnimatedPropertyID cssToGraphicsLayerProperty(int);
@@ -156,13 +164,12 @@ private:
GraphicsLayer* m_ancestorClippingLayer; // only used if we are clipped by an ancestor which is not a stacking context
GraphicsLayer* m_graphicsLayer;
- GraphicsLayer* m_contentsLayer; // only used in cases where we need to draw the foreground separately
+ GraphicsLayer* m_foregroundLayer; // only used in cases where we need to draw the foreground separately
GraphicsLayer* m_clippingLayer; // only used if we have clipping on a stacking context, with compositing children
- IntSize m_compositingContentOffset;
+ IntRect m_compositedBounds;
- bool m_hasDirectlyCompositedContent: 1;
- bool m_compositingContentOffsetDirty: 1;
+ bool m_hasDirectlyCompositedContent;
};
} // namespace WebCore
diff --git a/WebCore/rendering/RenderLayerCompositor.cpp b/WebCore/rendering/RenderLayerCompositor.cpp
index fec3b1d..fb15800 100644
--- a/WebCore/rendering/RenderLayerCompositor.cpp
+++ b/WebCore/rendering/RenderLayerCompositor.cpp
@@ -38,7 +38,9 @@
#include "HitTestResult.h"
#include "Page.h"
#include "RenderLayerBacking.h"
+#include "RenderVideo.h"
#include "RenderView.h"
+#include "Settings.h"
#if PROFILE_LAYER_REBUILD
#include <wtf/CurrentTime.h>
@@ -58,34 +60,29 @@ namespace WebCore {
struct CompositingState {
CompositingState(RenderLayer* compAncestor)
- : m_subtreeIsCompositing(false)
- , m_compositingAncestor(compAncestor)
+ : m_compositingAncestor(compAncestor)
+ , m_subtreeIsCompositing(false)
#ifndef NDEBUG
, m_depth(0)
#endif
{
}
- bool m_subtreeIsCompositing;
RenderLayer* m_compositingAncestor;
+ bool m_subtreeIsCompositing;
#ifndef NDEBUG
int m_depth;
#endif
};
-static TransformationMatrix flipTransform()
-{
- TransformationMatrix flipper;
- flipper.flipY();
- return flipper;
-}
-
RenderLayerCompositor::RenderLayerCompositor(RenderView* renderView)
: m_renderView(renderView)
, m_rootPlatformLayer(0)
+ , m_hasAcceleratedCompositing(true)
+ , m_compositingConsultsOverlap(true)
, m_compositing(false)
, m_rootLayerAttached(false)
- , m_compositingLayersNeedUpdate(false)
+ , m_compositingLayersNeedRebuild(false)
#if PROFILE_LAYER_REBUILD
, m_rootLayerUpdateCount(0)
#endif // PROFILE_LAYER_REBUILD
@@ -108,39 +105,52 @@ void RenderLayerCompositor::enableCompositingMode(bool enable /* = true */)
// the empty root layer, which has minimal overhead.
if (m_compositing)
ensureRootPlatformLayer();
+ else
+ destroyRootPlatformLayer();
}
}
-void RenderLayerCompositor::setCompositingLayersNeedUpdate(bool needUpdate)
+void RenderLayerCompositor::cacheAcceleratedCompositingEnabledFlag()
{
- if (inCompositingMode()) {
- if (!m_compositingLayersNeedUpdate && needUpdate)
- scheduleViewUpdate();
+ bool hasAcceleratedCompositing = false;
+ if (Settings* settings = m_renderView->document()->settings())
+ hasAcceleratedCompositing = settings->acceleratedCompositingEnabled();
- m_compositingLayersNeedUpdate = needUpdate;
- }
+ if (hasAcceleratedCompositing != m_hasAcceleratedCompositing)
+ setCompositingLayersNeedRebuild();
+
+ m_hasAcceleratedCompositing = hasAcceleratedCompositing;
+}
+
+void RenderLayerCompositor::setCompositingLayersNeedRebuild(bool needRebuild)
+{
+ if (inCompositingMode())
+ m_compositingLayersNeedRebuild = needRebuild;
}
-void RenderLayerCompositor::scheduleViewUpdate()
+void RenderLayerCompositor::scheduleSync()
{
Frame* frame = m_renderView->frameView()->frame();
Page* page = frame ? frame->page() : 0;
if (!page)
return;
- page->chrome()->client()->scheduleViewUpdate();
+ page->chrome()->client()->scheduleCompositingLayerSync();
}
void RenderLayerCompositor::updateCompositingLayers(RenderLayer* updateRoot)
{
- if (!m_compositingLayersNeedUpdate)
+ // When m_compositingConsultsOverlap is true, then layer positions affect compositing,
+ // so we can only bail here when we're not looking at overlap.
+ if (!m_compositingLayersNeedRebuild && !m_compositingConsultsOverlap)
return;
ASSERT(inCompositingMode());
+ bool needLayerRebuild = m_compositingLayersNeedRebuild;
if (!updateRoot) {
- // Only clear the flag if we're updating the entire hierarchy
- m_compositingLayersNeedUpdate = false;
+ // Only clear the flag if we're updating the entire hierarchy.
+ m_compositingLayersNeedRebuild = false;
updateRoot = rootRenderLayer();
}
@@ -156,13 +166,20 @@ void RenderLayerCompositor::updateCompositingLayers(RenderLayer* updateRoot)
// complex.
{
CompositingState compState(updateRoot);
- computeCompositingRequirements(updateRoot, compState);
+ bool layersChanged;
+ if (m_compositingConsultsOverlap) {
+ OverlapMap overlapTestRequestMap;
+ computeCompositingRequirements(updateRoot, &overlapTestRequestMap, compState, layersChanged);
+ } else
+ computeCompositingRequirements(updateRoot, 0, compState, layersChanged);
+
+ needLayerRebuild |= layersChanged;
}
// Now create and parent the compositing layers.
{
CompositingState compState(updateRoot);
- rebuildCompositingLayerTree(updateRoot, compState);
+ rebuildCompositingLayerTree(updateRoot, compState, needLayerRebuild);
}
#if PROFILE_LAYER_REBUILD
@@ -171,16 +188,23 @@ void RenderLayerCompositor::updateCompositingLayers(RenderLayer* updateRoot)
fprintf(stderr, "Update %d: computeCompositingRequirements for the world took %fms\n",
m_rootLayerUpdateCount, 1000.0 * (endTime - startTime));
#endif
- ASSERT(updateRoot || !m_compositingLayersNeedUpdate);
+ ASSERT(updateRoot || !m_compositingLayersNeedRebuild);
+
+ if (!hasAcceleratedCompositing())
+ enableCompositingMode(false);
}
-bool RenderLayerCompositor::updateLayerCompositingState(RenderLayer* layer, CompositingChangeRepaint shouldRepaint)
+bool RenderLayerCompositor::updateBacking(RenderLayer* layer, CompositingChangeRepaint shouldRepaint)
{
- bool needsLayer = needsToBeComposited(layer);
bool layerChanged = false;
- if (needsLayer) {
+ if (needsToBeComposited(layer)) {
enableCompositingMode();
+
+ // 3D transforms turn off the testing of overlap.
+ if (requiresCompositingForTransform(layer->renderer()))
+ setCompositingConsultsOverlap(false);
+
if (!layer->backing()) {
// If we need to repaint, do so before making backing
@@ -195,12 +219,30 @@ bool RenderLayerCompositor::updateLayerCompositingState(RenderLayer* layer, Comp
layer->clearBacking();
layerChanged = true;
+ // The layer's cached repaints rects are relative to the repaint container, so change when
+ // compositing changes; we need to update them here.
+ layer->computeRepaintRects();
+
// If we need to repaint, do so now that we've removed the backing
if (shouldRepaint == CompositingChangeRepaintNow)
repaintOnCompositingChange(layer);
}
}
+#if ENABLE(VIDEO)
+ if (layerChanged && layer->renderer()->isVideo()) {
+ // If it's a video, give the media player a chance to hook up to the layer.
+ RenderVideo* video = toRenderVideo(layer->renderer());
+ video->acceleratedRenderingStateChanged();
+ }
+#endif
+ return layerChanged;
+}
+
+bool RenderLayerCompositor::updateLayerCompositingState(RenderLayer* layer, CompositingChangeRepaint shouldRepaint)
+{
+ bool layerChanged = updateBacking(layer, shouldRepaint);
+
// See if we need content or clipping layers. Methods called here should assume
// that the compositing state of descendant layers has not been updated yet.
if (layer->backing() && layer->backing()->updateGraphicsLayerConfiguration())
@@ -211,6 +253,10 @@ bool RenderLayerCompositor::updateLayerCompositingState(RenderLayer* layer, Comp
void RenderLayerCompositor::repaintOnCompositingChange(RenderLayer* layer)
{
+ // If the renderer is not attached yet, no need to repaint.
+ if (!layer->renderer()->parent())
+ return;
+
RenderBoxModelObject* repaintContainer = layer->renderer()->containerForRepaint();
if (!repaintContainer)
repaintContainer = m_renderView;
@@ -226,17 +272,27 @@ void RenderLayerCompositor::repaintOnCompositingChange(RenderLayer* layer)
// The bounds of the GraphicsLayer created for a compositing layer is the union of the bounds of all the descendant
// RenderLayers that are rendered by the composited RenderLayer.
-IntRect RenderLayerCompositor::calculateCompositedBounds(const RenderLayer* layer, const RenderLayer* ancestorLayer, IntRect* layerBoundingBox)
+IntRect RenderLayerCompositor::calculateCompositedBounds(const RenderLayer* layer, const RenderLayer* ancestorLayer)
{
+ if (!layer->isSelfPaintingLayer())
+ return IntRect();
+
IntRect boundingBoxRect, unionBounds;
boundingBoxRect = unionBounds = layer->localBoundingBox();
+ if (layer->renderer()->hasOverflowClip() || layer->renderer()->hasMask()) {
+ int ancestorRelX = 0, ancestorRelY = 0;
+ layer->convertToLayerCoords(ancestorLayer, ancestorRelX, ancestorRelY);
+ boundingBoxRect.move(ancestorRelX, ancestorRelY);
+ return boundingBoxRect;
+ }
+
ASSERT(layer->isStackingContext() || (!layer->m_posZOrderList || layer->m_posZOrderList->size() == 0));
- Vector<RenderLayer*>* negZOrderList = layer->negZOrderList();
- if (negZOrderList) {
- for (Vector<RenderLayer*>::iterator it = negZOrderList->begin(); it != negZOrderList->end(); ++it) {
- RenderLayer* curLayer = (*it);
+ if (Vector<RenderLayer*>* negZOrderList = layer->negZOrderList()) {
+ size_t listSize = negZOrderList->size();
+ for (size_t i = 0; i < listSize; ++i) {
+ RenderLayer* curLayer = negZOrderList->at(i);
if (!curLayer->isComposited()) {
IntRect childUnionBounds = calculateCompositedBounds(curLayer, layer);
unionBounds.unite(childUnionBounds);
@@ -244,10 +300,10 @@ IntRect RenderLayerCompositor::calculateCompositedBounds(const RenderLayer* laye
}
}
- Vector<RenderLayer*>* posZOrderList = layer->posZOrderList();
- if (posZOrderList) {
- for (Vector<RenderLayer*>::iterator it = posZOrderList->begin(); it != posZOrderList->end(); ++it) {
- RenderLayer* curLayer = (*it);
+ if (Vector<RenderLayer*>* posZOrderList = layer->posZOrderList()) {
+ size_t listSize = posZOrderList->size();
+ for (size_t i = 0; i < listSize; ++i) {
+ RenderLayer* curLayer = posZOrderList->at(i);
if (!curLayer->isComposited()) {
IntRect childUnionBounds = calculateCompositedBounds(curLayer, layer);
unionBounds.unite(childUnionBounds);
@@ -255,10 +311,10 @@ IntRect RenderLayerCompositor::calculateCompositedBounds(const RenderLayer* laye
}
}
- Vector<RenderLayer*>* normalFlowList = layer->normalFlowList();
- if (normalFlowList) {
- for (Vector<RenderLayer*>::iterator it = normalFlowList->begin(); it != normalFlowList->end(); ++it) {
- RenderLayer* curLayer = (*it);
+ if (Vector<RenderLayer*>* normalFlowList = layer->normalFlowList()) {
+ size_t listSize = normalFlowList->size();
+ for (size_t i = 0; i < listSize; ++i) {
+ RenderLayer* curLayer = normalFlowList->at(i);
if (!curLayer->isComposited()) {
IntRect curAbsBounds = calculateCompositedBounds(curLayer, layer);
unionBounds.unite(curAbsBounds);
@@ -276,39 +332,38 @@ IntRect RenderLayerCompositor::calculateCompositedBounds(const RenderLayer* laye
layer->convertToLayerCoords(ancestorLayer, ancestorRelX, ancestorRelY);
unionBounds.move(ancestorRelX, ancestorRelY);
- if (layerBoundingBox) {
- boundingBoxRect.move(ancestorRelX, ancestorRelY);
- *layerBoundingBox = boundingBoxRect;
- }
-
return unionBounds;
}
void RenderLayerCompositor::layerWasAdded(RenderLayer* /*parent*/, RenderLayer* /*child*/)
{
- setCompositingLayersNeedUpdate();
+ setCompositingLayersNeedRebuild();
}
void RenderLayerCompositor::layerWillBeRemoved(RenderLayer* parent, RenderLayer* child)
{
- if (child->isComposited())
- setCompositingParent(child, 0);
-
- // If the document is being torn down (document's renderer() is null), then there's
- // no need to do any layer updating.
- if (parent->renderer()->documentBeingDestroyed())
+ if (!child->isComposited() || parent->renderer()->documentBeingDestroyed())
return;
+ setCompositingParent(child, 0);
+
RenderLayer* compLayer = parent->enclosingCompositingLayer();
if (compLayer) {
- IntRect ancestorRect = calculateCompositedBounds(child, compLayer);
- compLayer->setBackingNeedsRepaintInRect(ancestorRect);
+ ASSERT(compLayer->backing());
+ IntRect compBounds = child->backing()->compositedBounds();
+
+ int offsetX = 0, offsetY = 0;
+ child->convertToLayerCoords(compLayer, offsetX, offsetY);
+ compBounds.move(offsetX, offsetY);
+
+ compLayer->setBackingNeedsRepaintInRect(compBounds);
+
// The contents of this layer may be moving from a GraphicsLayer to the window,
// so we need to make sure the window system synchronizes those changes on the screen.
m_renderView->frameView()->setNeedsOneShotDrawingSynchronization();
}
- setCompositingLayersNeedUpdate();
+ setCompositingLayersNeedRebuild();
}
RenderLayer* RenderLayerCompositor::enclosingNonStackingClippingLayer(const RenderLayer* layer) const
@@ -323,6 +378,31 @@ RenderLayer* RenderLayerCompositor::enclosingNonStackingClippingLayer(const Rend
return 0;
}
+void RenderLayerCompositor::addToOverlapMap(OverlapMap& overlapMap, RenderLayer* layer, IntRect& layerBounds, bool& boundsComputed)
+{
+ if (layer->isRootLayer())
+ return;
+
+ if (!boundsComputed) {
+ layerBounds = layer->renderer()->localToAbsoluteQuad(FloatRect(layer->localBoundingBox())).enclosingBoundingBox();
+ boundsComputed = true;
+ }
+
+ overlapMap.add(layer, layerBounds);
+}
+
+bool RenderLayerCompositor::overlapsCompositedLayers(OverlapMap& overlapMap, const IntRect& layerBounds)
+{
+ RenderLayerCompositor::OverlapMap::const_iterator end = overlapMap.end();
+ for (RenderLayerCompositor::OverlapMap::const_iterator it = overlapMap.begin(); it != end; ++it) {
+ const IntRect& bounds = it->second;
+ if (layerBounds.intersects(bounds))
+ return true;
+ }
+
+ return false;
+}
+
// Recurse through the layers in z-index and overflow order (which is equivalent to painting order)
// For the z-order children of a compositing layer:
// If a child layers has a compositing layer, then all subsequent layers must
@@ -332,7 +412,7 @@ RenderLayer* RenderLayerCompositor::enclosingNonStackingClippingLayer(const Rend
// must be compositing so that its contents render over that child.
// This implies that its positive z-index children must also be compositing.
//
-void RenderLayerCompositor::computeCompositingRequirements(RenderLayer* layer, struct CompositingState& ioCompState)
+void RenderLayerCompositor::computeCompositingRequirements(RenderLayer* layer, OverlapMap* overlapMap, struct CompositingState& compositingState, bool& layersChanged)
{
layer->updateLayerPosition();
layer->updateZOrderLists();
@@ -340,61 +420,82 @@ void RenderLayerCompositor::computeCompositingRequirements(RenderLayer* layer, s
// Clear the flag
layer->setHasCompositingDescendant(false);
- layer->setMustOverlayCompositedLayers(ioCompState.m_subtreeIsCompositing);
- const bool willBeComposited = needsToBeComposited(layer);
- // If we are going to become composited, repaint the old rendering destination
- if (!layer->isComposited() && willBeComposited)
- repaintOnCompositingChange(layer);
+ bool mustOverlapCompositedLayers = compositingState.m_subtreeIsCompositing;
- ioCompState.m_subtreeIsCompositing = willBeComposited;
+ bool haveComputedBounds = false;
+ IntRect absBounds;
+ if (overlapMap && mustOverlapCompositedLayers) {
+ // If we're testing for overlap, we only need to composite if we overlap something that is already composited.
+ absBounds = layer->renderer()->localToAbsoluteQuad(FloatRect(layer->localBoundingBox())).enclosingBoundingBox();
+ haveComputedBounds = true;
+ mustOverlapCompositedLayers &= overlapsCompositedLayers(*overlapMap, absBounds);
+ }
+
+ layer->setMustOverlapCompositedLayers(mustOverlapCompositedLayers);
+
+ // The children of this layer don't need to composite, unless there is
+ // a compositing layer among them, so start by inheriting the compositing
+ // ancestor with m_subtreeIsCompositing set to false.
+ CompositingState childState(compositingState.m_compositingAncestor);
+#ifndef NDEBUG
+ ++childState.m_depth;
+#endif
- CompositingState childState = ioCompState;
- if (willBeComposited)
+ const bool willBeComposited = needsToBeComposited(layer);
+ if (willBeComposited) {
+ // Tell the parent it has compositing descendants.
+ compositingState.m_subtreeIsCompositing = true;
+ // This layer now acts as the ancestor for kids.
childState.m_compositingAncestor = layer;
+ if (overlapMap)
+ addToOverlapMap(*overlapMap, layer, absBounds, haveComputedBounds);
+ }
- // The children of this stacking context don't need to composite, unless there is
- // a compositing layer among them, so start by assuming false.
- childState.m_subtreeIsCompositing = false;
-
-#ifndef NDEBUG
- ++childState.m_depth;
+#if ENABLE(VIDEO)
+ // Video is special. It's a replaced element with a content layer, but has shadow content
+ // for the controller that must render in front. Without this, the controls fail to show
+ // when the video element is a stacking context (e.g. due to opacity or transform).
+ if (willBeComposited && layer->renderer()->isVideo())
+ childState.m_subtreeIsCompositing = true;
#endif
if (layer->isStackingContext()) {
ASSERT(!layer->m_zOrderListsDirty);
- Vector<RenderLayer*>* negZOrderList = layer->negZOrderList();
- if (negZOrderList && negZOrderList->size() > 0) {
- for (Vector<RenderLayer*>::const_iterator it = negZOrderList->begin(); it != negZOrderList->end(); ++it) {
- RenderLayer* curLayer = (*it);
- computeCompositingRequirements(curLayer, childState);
-
- // if we have to make a layer for this child, make one now so we can have a contents layer
- // (since we need to ensure that the -ve z-order child renders underneath our contents)
+ if (Vector<RenderLayer*>* negZOrderList = layer->negZOrderList()) {
+ size_t listSize = negZOrderList->size();
+ for (size_t i = 0; i < listSize; ++i) {
+ RenderLayer* curLayer = negZOrderList->at(i);
+ computeCompositingRequirements(curLayer, overlapMap, childState, layersChanged);
+
+ // If we have to make a layer for this child, make one now so we can have a contents layer
+ // (since we need to ensure that the -ve z-order child renders underneath our contents).
if (childState.m_subtreeIsCompositing) {
- // make |this| compositing
- layer->setMustOverlayCompositedLayers(true);
+ // make layer compositing
+ layer->setMustOverlapCompositedLayers(true);
childState.m_compositingAncestor = layer;
+ if (overlapMap)
+ addToOverlapMap(*overlapMap, layer, absBounds, haveComputedBounds);
}
}
}
}
ASSERT(!layer->m_normalFlowListDirty);
- Vector<RenderLayer*>* normalFlowList = layer->normalFlowList();
- if (normalFlowList && normalFlowList->size() > 0) {
- for (Vector<RenderLayer*>::const_iterator it = normalFlowList->begin(); it != normalFlowList->end(); ++it) {
- RenderLayer* curLayer = (*it);
- computeCompositingRequirements(curLayer, childState);
+ if (Vector<RenderLayer*>* normalFlowList = layer->normalFlowList()) {
+ size_t listSize = normalFlowList->size();
+ for (size_t i = 0; i < listSize; ++i) {
+ RenderLayer* curLayer = normalFlowList->at(i);
+ computeCompositingRequirements(curLayer, overlapMap, childState, layersChanged);
}
}
if (layer->isStackingContext()) {
- Vector<RenderLayer*>* posZOrderList = layer->posZOrderList();
- if (posZOrderList && posZOrderList->size() > 0) {
- for (Vector<RenderLayer*>::const_iterator it = posZOrderList->begin(); it != posZOrderList->end(); ++it) {
- RenderLayer* curLayer = (*it);
- computeCompositingRequirements(curLayer, childState);
+ if (Vector<RenderLayer*>* posZOrderList = layer->posZOrderList()) {
+ size_t listSize = posZOrderList->size();
+ for (size_t i = 0; i < listSize; ++i) {
+ RenderLayer* curLayer = posZOrderList->at(i);
+ computeCompositingRequirements(curLayer, overlapMap, childState, layersChanged);
}
}
}
@@ -403,24 +504,40 @@ void RenderLayerCompositor::computeCompositingRequirements(RenderLayer* layer, s
// be composited. Also, if we have opacity < 1, then we need to be a layer so that
// the child layers are opaque, then rendered with opacity on this layer.
if (childState.m_subtreeIsCompositing &&
- (layer->renderer()->hasTransform() || layer->renderer()->style()->opacity() < 1))
- layer->setMustOverlayCompositedLayers(true);
+ (layer->renderer()->hasTransform() || layer->renderer()->style()->opacity() < 1)) {
+ layer->setMustOverlapCompositedLayers(true);
+ if (overlapMap)
+ addToOverlapMap(*overlapMap, layer, absBounds, haveComputedBounds);
+ }
// Subsequent layers in the parent stacking context also need to composite.
if (childState.m_subtreeIsCompositing)
- ioCompState.m_subtreeIsCompositing = true;
+ compositingState.m_subtreeIsCompositing = true;
+
+ // If the layer is going into compositing mode, repaint its old location.
+ if (!layer->isComposited() && needsToBeComposited(layer))
+ repaintOnCompositingChange(layer);
// Set the flag to say that this SC has compositing children.
// this can affect the answer to needsToBeComposited() when clipping,
// but that's ok here.
layer->setHasCompositingDescendant(childState.m_subtreeIsCompositing);
+
+ // Update backing now, so that we can use isComposited() reliably during tree traversal in rebuildCompositingLayerTree().
+ if (updateBacking(layer, CompositingChangeRepaintNow))
+ layersChanged = true;
}
void RenderLayerCompositor::setCompositingParent(RenderLayer* childLayer, RenderLayer* parentLayer)
{
ASSERT(childLayer->isComposited());
- ASSERT(!parentLayer || parentLayer->isComposited());
-
+
+ // It's possible to be called with a parent that isn't yet composited when we're doing
+ // partial updates as required by painting or hit testing. Just bail in that case;
+ // we'll do a full layer update soon.
+ if (!parentLayer || !parentLayer->isComposited())
+ return;
+
if (parentLayer) {
GraphicsLayer* hostingLayer = parentLayer->backing()->parentForSublayers();
GraphicsLayer* hostedLayer = childLayer->backing()->childForSuperlayers();
@@ -451,20 +568,45 @@ void RenderLayerCompositor::parentInRootLayer(RenderLayer* layer)
}
}
-void RenderLayerCompositor::rebuildCompositingLayerTree(RenderLayer* layer, struct CompositingState& ioCompState)
+#if ENABLE(VIDEO)
+bool RenderLayerCompositor::canAccelerateVideoRendering(RenderVideo* o) const
{
- bool wasComposited = layer->isComposited();
+ // FIXME: ideally we need to look at all ancestors for mask or video. But for now,
+ // just bail on the obvious cases.
+ if (o->hasMask() || o->hasReflection() || !m_hasAcceleratedCompositing)
+ return false;
+
+ return o->supportsAcceleratedRendering();
+}
+#endif
+void RenderLayerCompositor::rebuildCompositingLayerTree(RenderLayer* layer, struct CompositingState& compositingState, bool updateHierarchy)
+{
// Make the layer compositing if necessary, and set up clipping and content layers.
// Note that we can only do work here that is independent of whether the descendant layers
// have been processed. computeCompositingRequirements() will already have done the repaint if necessary.
- updateLayerCompositingState(layer, CompositingChangeWillRepaintLater);
+ RenderLayerBacking* layerBacking = layer->backing();
+ if (layerBacking) {
+ // The compositing state of all our children has been updated already, so now
+ // we can compute and cache the composited bounds for this layer.
+ layerBacking->setCompositedBounds(calculateCompositedBounds(layer, layer));
+
+ layerBacking->updateGraphicsLayerConfiguration();
+ layerBacking->updateGraphicsLayerGeometry();
+
+ if (!layer->parent())
+ updateRootLayerPosition();
+
+ // FIXME: make this more incremental
+ if (updateHierarchy)
+ layerBacking->parentForSublayers()->removeAllChildren();
+ }
// host the document layer in the RenderView's root layer
- if (layer->isRootLayer())
+ if (updateHierarchy && layer->isRootLayer() && layer->isComposited())
parentInRootLayer(layer);
- CompositingState childState = ioCompState;
+ CompositingState childState = compositingState;
if (layer->isComposited())
childState.m_compositingAncestor = layer;
@@ -472,14 +614,6 @@ void RenderLayerCompositor::rebuildCompositingLayerTree(RenderLayer* layer, stru
++childState.m_depth;
#endif
- RenderLayerBacking* layerBacking = layer->backing();
-
- // FIXME: make this more incremental
- if (layerBacking) {
- layerBacking->parentForSublayers()->removeAllChildren();
- layerBacking->updateInternalHierarchy();
- }
-
// The children of this stacking context don't need to composite, unless there is
// a compositing layer among them, so start by assuming false.
childState.m_subtreeIsCompositing = false;
@@ -487,58 +621,89 @@ void RenderLayerCompositor::rebuildCompositingLayerTree(RenderLayer* layer, stru
if (layer->isStackingContext()) {
ASSERT(!layer->m_zOrderListsDirty);
- Vector<RenderLayer*>* negZOrderList = layer->negZOrderList();
- if (negZOrderList && negZOrderList->size() > 0) {
- for (Vector<RenderLayer*>::const_iterator it = negZOrderList->begin(); it != negZOrderList->end(); ++it) {
- RenderLayer* curLayer = (*it);
- rebuildCompositingLayerTree(curLayer, childState);
- if (curLayer->isComposited())
+ if (Vector<RenderLayer*>* negZOrderList = layer->negZOrderList()) {
+ size_t listSize = negZOrderList->size();
+ for (size_t i = 0; i < listSize; ++i) {
+ RenderLayer* curLayer = negZOrderList->at(i);
+ rebuildCompositingLayerTree(curLayer, childState, updateHierarchy);
+ if (updateHierarchy && curLayer->isComposited())
setCompositingParent(curLayer, childState.m_compositingAncestor);
}
}
- if (layerBacking && layerBacking->contentsLayer()) {
+ if (updateHierarchy && layerBacking && layerBacking->foregroundLayer()) {
// we only have a contents layer if we have an m_layer
- layerBacking->contentsLayer()->removeFromParent();
+ layerBacking->foregroundLayer()->removeFromParent();
GraphicsLayer* hostingLayer = layerBacking->clippingLayer() ? layerBacking->clippingLayer() : layerBacking->graphicsLayer();
- hostingLayer->addChild(layerBacking->contentsLayer());
+ hostingLayer->addChild(layerBacking->foregroundLayer());
}
}
ASSERT(!layer->m_normalFlowListDirty);
- Vector<RenderLayer*>* normalFlowList = layer->normalFlowList();
- if (normalFlowList && normalFlowList->size() > 0) {
- for (Vector<RenderLayer*>::iterator it = normalFlowList->begin(); it != normalFlowList->end(); ++it) {
- RenderLayer* curLayer = (*it);
- rebuildCompositingLayerTree(curLayer, childState);
- if (curLayer->isComposited())
+ if (Vector<RenderLayer*>* normalFlowList = layer->normalFlowList()) {
+ size_t listSize = normalFlowList->size();
+ for (size_t i = 0; i < listSize; ++i) {
+ RenderLayer* curLayer = normalFlowList->at(i);
+ rebuildCompositingLayerTree(curLayer, childState, updateHierarchy);
+ if (updateHierarchy && curLayer->isComposited())
setCompositingParent(curLayer, childState.m_compositingAncestor);
}
}
if (layer->isStackingContext()) {
- Vector<RenderLayer*>* posZOrderList = layer->posZOrderList();
- if (posZOrderList && posZOrderList->size() > 0) {
- for (Vector<RenderLayer*>::const_iterator it = posZOrderList->begin(); it != posZOrderList->end(); ++it) {
- RenderLayer* curLayer = (*it);
- rebuildCompositingLayerTree(curLayer, childState);
- if (curLayer->isComposited())
+ if (Vector<RenderLayer*>* posZOrderList = layer->posZOrderList()) {
+ size_t listSize = posZOrderList->size();
+ for (size_t i = 0; i < listSize; ++i) {
+ RenderLayer* curLayer = posZOrderList->at(i);
+ rebuildCompositingLayerTree(curLayer, childState, updateHierarchy);
+ if (updateHierarchy && curLayer->isComposited())
setCompositingParent(curLayer, childState.m_compositingAncestor);
}
}
}
+}
+
+
+// Recurs down the RenderLayer tree until its finds the compositing descendants of compositingAncestor and updates their geometry.
+void RenderLayerCompositor::updateCompositingDescendantGeometry(RenderLayer* compositingAncestor, RenderLayer* layer, RenderLayerBacking::UpdateDepth updateDepth)
+{
+ if (layer != compositingAncestor) {
+ if (RenderLayerBacking* layerBacking = layer->backing()) {
+ layerBacking->setCompositedBounds(calculateCompositedBounds(layer, layer));
+ layerBacking->updateGraphicsLayerGeometry();
+ if (updateDepth == RenderLayerBacking::CompositingChildren)
+ return;
+ }
+ }
+
+ if (!layer->hasCompositingDescendant())
+ return;
- if (layerBacking) {
- // Do work here that requires that we've processed all of the descendant layers
- layerBacking->updateGraphicsLayerGeometry();
- } else if (wasComposited) {
- // We stopped being a compositing layer. Now that our descendants have been udated, we can
- // repaint our new rendering destination.
- repaintOnCompositingChange(layer);
+ if (layer->isStackingContext()) {
+ if (Vector<RenderLayer*>* negZOrderList = layer->negZOrderList()) {
+ size_t listSize = negZOrderList->size();
+ for (size_t i = 0; i < listSize; ++i)
+ updateCompositingDescendantGeometry(compositingAncestor, negZOrderList->at(i), updateDepth);
+ }
+ }
+
+ if (Vector<RenderLayer*>* normalFlowList = layer->normalFlowList()) {
+ size_t listSize = normalFlowList->size();
+ for (size_t i = 0; i < listSize; ++i)
+ updateCompositingDescendantGeometry(compositingAncestor, normalFlowList->at(i), updateDepth);
+ }
+
+ if (layer->isStackingContext()) {
+ if (Vector<RenderLayer*>* posZOrderList = layer->posZOrderList()) {
+ size_t listSize = posZOrderList->size();
+ for (size_t i = 0; i < listSize; ++i)
+ updateCompositingDescendantGeometry(compositingAncestor, posZOrderList->at(i), updateDepth);
+ }
}
}
+
void RenderLayerCompositor::repaintCompositedLayersAbsoluteRect(const IntRect& absRect)
{
recursiveRepaintLayerRect(rootRenderLayer(), absRect);
@@ -550,10 +715,10 @@ void RenderLayerCompositor::recursiveRepaintLayerRect(RenderLayer* layer, const
layer->setBackingNeedsRepaintInRect(rect);
if (layer->hasCompositingDescendant()) {
- Vector<RenderLayer*>* negZOrderList = layer->negZOrderList();
- if (negZOrderList) {
- for (Vector<RenderLayer*>::iterator it = negZOrderList->begin(); it != negZOrderList->end(); ++it) {
- RenderLayer* curLayer = (*it);
+ if (Vector<RenderLayer*>* negZOrderList = layer->negZOrderList()) {
+ size_t listSize = negZOrderList->size();
+ for (size_t i = 0; i < listSize; ++i) {
+ RenderLayer* curLayer = negZOrderList->at(i);
int x = 0, y = 0;
curLayer->convertToLayerCoords(layer, x, y);
IntRect childRect(rect);
@@ -562,10 +727,10 @@ void RenderLayerCompositor::recursiveRepaintLayerRect(RenderLayer* layer, const
}
}
- Vector<RenderLayer*>* posZOrderList = layer->posZOrderList();
- if (posZOrderList) {
- for (Vector<RenderLayer*>::iterator it = posZOrderList->begin(); it != posZOrderList->end(); ++it) {
- RenderLayer* curLayer = (*it);
+ if (Vector<RenderLayer*>* posZOrderList = layer->posZOrderList()) {
+ size_t listSize = posZOrderList->size();
+ for (size_t i = 0; i < listSize; ++i) {
+ RenderLayer* curLayer = posZOrderList->at(i);
int x = 0, y = 0;
curLayer->convertToLayerCoords(layer, x, y);
IntRect childRect(rect);
@@ -573,17 +738,16 @@ void RenderLayerCompositor::recursiveRepaintLayerRect(RenderLayer* layer, const
recursiveRepaintLayerRect(curLayer, childRect);
}
}
-
- Vector<RenderLayer*>* normalFlowList = layer->normalFlowList();
- if (normalFlowList) {
- for (Vector<RenderLayer*>::iterator it = normalFlowList->begin(); it != normalFlowList->end(); ++it) {
- RenderLayer* curLayer = (*it);
- int x = 0, y = 0;
- curLayer->convertToLayerCoords(layer, x, y);
- IntRect childRect(rect);
- childRect.move(-x, -y);
- recursiveRepaintLayerRect(curLayer, childRect);
- }
+ }
+ if (Vector<RenderLayer*>* normalFlowList = layer->normalFlowList()) {
+ size_t listSize = normalFlowList->size();
+ for (size_t i = 0; i < listSize; ++i) {
+ RenderLayer* curLayer = normalFlowList->at(i);
+ int x = 0, y = 0;
+ curLayer->convertToLayerCoords(layer, x, y);
+ IntRect childRect(rect);
+ childRect.move(-x, -y);
+ recursiveRepaintLayerRect(curLayer, childRect);
}
}
}
@@ -629,7 +793,15 @@ void RenderLayerCompositor::willMoveOffscreen()
void RenderLayerCompositor::updateRootLayerPosition()
{
if (m_rootPlatformLayer)
- m_rootPlatformLayer->setSize(FloatSize(m_renderView->docWidth(), m_renderView->docHeight()));
+ m_rootPlatformLayer->setSize(FloatSize(m_renderView->overflowWidth(), m_renderView->overflowHeight()));
+}
+
+void RenderLayerCompositor::didStartAcceleratedAnimation()
+{
+ // If an accelerated animation or transition runs, we have to turn off overlap checking because
+ // we don't do layout for every frame, but we have to ensure that the layering is
+ // correct between the animating object and other objects on the page.
+ setCompositingConsultsOverlap(false);
}
bool RenderLayerCompositor::has3DContent() const
@@ -639,52 +811,21 @@ bool RenderLayerCompositor::has3DContent() const
bool RenderLayerCompositor::needsToBeComposited(const RenderLayer* layer) const
{
- return requiresCompositingLayer(layer) || layer->mustOverlayCompositedLayers();
-}
+ if (!m_hasAcceleratedCompositing || !layer->isSelfPaintingLayer())
+ return false;
-#define VERBOSE_COMPOSITINGLAYER 0
+ return requiresCompositingLayer(layer) || layer->mustOverlapCompositedLayers();
+}
// Note: this specifies whether the RL needs a compositing layer for intrinsic reasons.
// Use needsToBeComposited() to determine if a RL actually needs a compositing layer.
// static
bool RenderLayerCompositor::requiresCompositingLayer(const RenderLayer* layer) const
{
- // FIXME: cache the result of these tests?
-#if VERBOSE_COMPOSITINGLAYER
- bool gotReason = false;
-
- if (!gotReason && inCompositingMode() && layer->isRootLayer()) {
- fprintf(stderr, "RenderLayer %p requires compositing layer because: it's the document root\n", layer);
- gotReason = true;
- }
-
- if (!gotReason && requiresCompositingForTransform(layer->renderer())) {
- fprintf(stderr, "RenderLayer %p requires compositing layer because: it has 3d transform, perspective, backface, or animating transform\n", layer);
- gotReason = true;
- }
-
- if (!gotReason && layer->renderer()->style()->backfaceVisibility() == BackfaceVisibilityHidden) {
- fprintf(stderr, "RenderLayer %p requires compositing layer because: it has backface-visibility: hidden\n", layer);
- gotReason = true;
- }
-
- if (!gotReason && clipsCompositingDescendants(layer)) {
- fprintf(stderr, "RenderLayer %p requires compositing layer because: it has overflow clip\n", layer);
- gotReason = true;
- }
-
- if (!gotReason && requiresCompositingForAnimation(layer->renderer())) {
- fprintf(stderr, "RenderLayer %p requires compositing layer because: it has a running transition for opacity or transform\n", layer);
- gotReason = true;
- }
-
- if (!gotReason)
- fprintf(stderr, "RenderLayer %p does not require compositing layer\n", layer);
-#endif
-
// The root layer always has a compositing layer, but it may not have backing.
return (inCompositingMode() && layer->isRootLayer()) ||
requiresCompositingForTransform(layer->renderer()) ||
+ requiresCompositingForVideo(layer->renderer()) ||
layer->renderer()->style()->backfaceVisibility() == BackfaceVisibilityHidden ||
clipsCompositingDescendants(layer) ||
requiresCompositingForAnimation(layer->renderer());
@@ -737,7 +878,7 @@ bool RenderLayerCompositor::clipsCompositingDescendants(const RenderLayer* layer
layer->renderer()->hasOverflowClip();
}
-bool RenderLayerCompositor::requiresCompositingForTransform(RenderObject* renderer)
+bool RenderLayerCompositor::requiresCompositingForTransform(RenderObject* renderer) const
{
RenderStyle* style = renderer->style();
// Note that we ask the renderer if it has a transform, because the style may have transforms,
@@ -745,12 +886,23 @@ bool RenderLayerCompositor::requiresCompositingForTransform(RenderObject* render
return renderer->hasTransform() && (style->transform().has3DOperation() || style->transformStyle3D() == TransformStyle3DPreserve3D || style->hasPerspective());
}
-bool RenderLayerCompositor::requiresCompositingForAnimation(RenderObject* renderer)
+bool RenderLayerCompositor::requiresCompositingForVideo(RenderObject* renderer) const
{
- AnimationController* animController = renderer->animation();
- if (animController)
- return animController->isAnimatingPropertyOnRenderer(renderer, CSSPropertyOpacity) ||
- animController->isAnimatingPropertyOnRenderer(renderer, CSSPropertyWebkitTransform);
+#if ENABLE(VIDEO)
+ if (renderer->isVideo()) {
+ RenderVideo* video = toRenderVideo(renderer);
+ return canAccelerateVideoRendering(video);
+ }
+#endif
+ return false;
+}
+
+bool RenderLayerCompositor::requiresCompositingForAnimation(RenderObject* renderer) const
+{
+ if (AnimationController* animController = renderer->animation()) {
+ return (animController->isAnimatingPropertyOnRenderer(renderer, CSSPropertyOpacity) && inCompositingMode())
+ || animController->isAnimatingPropertyOnRenderer(renderer, CSSPropertyWebkitTransform);
+ }
return false;
}
@@ -768,11 +920,10 @@ void RenderLayerCompositor::ensureRootPlatformLayer()
return;
m_rootPlatformLayer = GraphicsLayer::createGraphicsLayer(0);
- m_rootPlatformLayer->setSize(FloatSize(m_renderView->docWidth(), m_renderView->docHeight()));
+ m_rootPlatformLayer->setSize(FloatSize(m_renderView->overflowWidth(), m_renderView->overflowHeight()));
m_rootPlatformLayer->setPosition(FloatPoint(0, 0));
-
- if (GraphicsLayer::compositingCoordinatesOrientation() == GraphicsLayer::CompositingCoordinatesBottomUp)
- m_rootPlatformLayer->setChildrenTransform(flipTransform());
+ // The root layer does flipping if we need it on this platform.
+ m_rootPlatformLayer->setGeometryOrientation(GraphicsLayer::compositingCoordinatesOrientation());
// Need to clip to prevent transformed content showing outside this frame
m_rootPlatformLayer->setMasksToBounds(true);
@@ -780,6 +931,16 @@ void RenderLayerCompositor::ensureRootPlatformLayer()
didMoveOnscreen();
}
+void RenderLayerCompositor::destroyRootPlatformLayer()
+{
+ if (!m_rootPlatformLayer)
+ return;
+
+ willMoveOffscreen();
+ delete m_rootPlatformLayer;
+ m_rootPlatformLayer = 0;
+}
+
bool RenderLayerCompositor::layerHas3DContent(const RenderLayer* layer) const
{
const RenderStyle* style = layer->renderer()->style();
@@ -791,29 +952,29 @@ bool RenderLayerCompositor::layerHas3DContent(const RenderLayer* layer) const
return true;
if (layer->isStackingContext()) {
- Vector<RenderLayer*>* negZOrderList = layer->negZOrderList();
- if (negZOrderList) {
- for (Vector<RenderLayer*>::iterator it = negZOrderList->begin(); it != negZOrderList->end(); ++it) {
- RenderLayer* curLayer = (*it);
+ if (Vector<RenderLayer*>* negZOrderList = layer->negZOrderList()) {
+ size_t listSize = negZOrderList->size();
+ for (size_t i = 0; i < listSize; ++i) {
+ RenderLayer* curLayer = negZOrderList->at(i);
if (layerHas3DContent(curLayer))
return true;
}
}
- Vector<RenderLayer*>* posZOrderList = layer->posZOrderList();
- if (posZOrderList) {
- for (Vector<RenderLayer*>::iterator it = posZOrderList->begin(); it != posZOrderList->end(); ++it) {
- RenderLayer* curLayer = (*it);
+ if (Vector<RenderLayer*>* posZOrderList = layer->posZOrderList()) {
+ size_t listSize = posZOrderList->size();
+ for (size_t i = 0; i < listSize; ++i) {
+ RenderLayer* curLayer = posZOrderList->at(i);
if (layerHas3DContent(curLayer))
return true;
}
}
}
- Vector<RenderLayer*>* normalFlowList = layer->normalFlowList();
- if (normalFlowList) {
- for (Vector<RenderLayer*>::iterator it = normalFlowList->begin(); it != normalFlowList->end(); ++it) {
- RenderLayer* curLayer = (*it);
+ if (Vector<RenderLayer*>* normalFlowList = layer->normalFlowList()) {
+ size_t listSize = normalFlowList->size();
+ for (size_t i = 0; i < listSize; ++i) {
+ RenderLayer* curLayer = normalFlowList->at(i);
if (layerHas3DContent(curLayer))
return true;
}
diff --git a/WebCore/rendering/RenderLayerCompositor.h b/WebCore/rendering/RenderLayerCompositor.h
index 76cb35f..02929dc 100644
--- a/WebCore/rendering/RenderLayerCompositor.h
+++ b/WebCore/rendering/RenderLayerCompositor.h
@@ -27,12 +27,16 @@
#define RenderLayerCompositor_h
#include "RenderLayer.h"
+#include "RenderLayerBacking.h"
namespace WebCore {
#define PROFILE_LAYER_REBUILD 0
class GraphicsLayer;
+#if ENABLE(VIDEO)
+class RenderVideo;
+#endif
// RenderLayerCompositor manages the hierarchy of
// composited RenderLayers. It determines which RenderLayers
@@ -53,11 +57,24 @@ public:
// This will make a compositing layer at the root automatically, and hook up to
// the native view/window system.
void enableCompositingMode(bool enable = true);
-
- void setCompositingLayersNeedUpdate(bool needUpdate = true);
- bool compositingLayersNeedUpdate() const { return m_compositingLayersNeedUpdate; }
-
- void scheduleViewUpdate();
+
+ // Returns true if the accelerated compositing is enabled
+ bool hasAcceleratedCompositing() const { return m_hasAcceleratedCompositing; }
+
+ // Copy the acceleratedCompositingEnabledFlag from Settings
+ void cacheAcceleratedCompositingEnabledFlag();
+
+ // Called when the layer hierarchy needs to be updated (compositing layers have been
+ // created, destroyed or re-parented).
+ void setCompositingLayersNeedRebuild(bool needRebuild = true);
+ bool compositingLayersNeedRebuild() const { return m_compositingLayersNeedRebuild; }
+
+ // Controls whether or not to consult geometry when deciding which layers need
+ // to be composited. Defaults to true.
+ void setCompositingConsultsOverlap(bool b) { m_compositingConsultsOverlap = b; }
+ bool compositingConsultsOverlap() const { return m_compositingConsultsOverlap; }
+
+ void scheduleSync();
// Rebuild the tree of compositing layers
void updateCompositingLayers(RenderLayer* updateRoot = 0);
@@ -66,6 +83,9 @@ public:
enum CompositingChangeRepaint { CompositingChangeRepaintNow, CompositingChangeWillRepaintLater };
bool updateLayerCompositingState(RenderLayer*, CompositingChangeRepaint = CompositingChangeRepaintNow);
+ // Update the geometry for compositing children of compositingAncestor.
+ void updateCompositingDescendantGeometry(RenderLayer* compositingAncestor, RenderLayer* layer, RenderLayerBacking::UpdateDepth);
+
// Whether layer's backing needs a graphics layer to do clipping by an ancestor (non-stacking-context parent with overflow).
bool clippedByAncestor(RenderLayer*) const;
// Whether layer's backing needs a graphics layer to clip z-order children of the given layer.
@@ -75,7 +95,7 @@ public:
bool needsContentsCompositingLayer(const RenderLayer*) const;
// Return the bounding box required for compositing layer and its childern, relative to ancestorLayer.
// If layerBoundingBox is not 0, on return it contains the bounding box of this layer only.
- IntRect calculateCompositedBounds(const RenderLayer* layer, const RenderLayer* ancestorLayer, IntRect* layerBoundingBox = 0);
+ IntRect calculateCompositedBounds(const RenderLayer* layer, const RenderLayer* ancestorLayer);
// Repaint the appropriate layers when the given RenderLayer starts or stops being composited.
void repaintOnCompositingChange(RenderLayer*);
@@ -97,6 +117,13 @@ public:
void willMoveOffscreen();
void updateRootLayerPosition();
+
+ void didStartAcceleratedAnimation();
+
+#if ENABLE(VIDEO)
+ // Use by RenderVideo to ask if it should try to use accelerated compositing.
+ bool canAccelerateVideoRendering(RenderVideo*) const;
+#endif
// Walk the tree looking for layers with 3d transforms. Useful in case you need
// to know if there is non-affine content, e.g. for drawing into an image.
@@ -108,11 +135,19 @@ private:
// Whether the layer has an intrinsic need for compositing layer.
bool requiresCompositingLayer(const RenderLayer*) const;
+ // Make or destroy the backing for this layer; returns true if backing changed.
+ bool updateBacking(RenderLayer*, CompositingChangeRepaint shouldRepaint);
+
// Repaint the given rect (which is layer's coords), and regions of child layers that intersect that rect.
void recursiveRepaintLayerRect(RenderLayer* layer, const IntRect& rect);
- void computeCompositingRequirements(RenderLayer*, struct CompositingState&);
- void rebuildCompositingLayerTree(RenderLayer* layer, struct CompositingState&);
+ typedef HashMap<RenderLayer*, IntRect> OverlapMap;
+ static void addToOverlapMap(OverlapMap&, RenderLayer*, IntRect& layerBounds, bool& boundsComputed);
+ static bool overlapsCompositedLayers(OverlapMap&, const IntRect& layerBounds);
+
+ // Returns true if any layer's compositing changed
+ void computeCompositingRequirements(RenderLayer*, OverlapMap*, struct CompositingState&, bool& layersChanged);
+ void rebuildCompositingLayerTree(RenderLayer* layer, struct CompositingState&, bool updateHierarchy);
// Hook compositing layers together
void setCompositingParent(RenderLayer* childLayer, RenderLayer* parentLayer);
@@ -123,17 +158,22 @@ private:
bool layerHas3DContent(const RenderLayer*) const;
void ensureRootPlatformLayer();
-
+ void destroyRootPlatformLayer();
+
// Whether a running transition or animation enforces the need for a compositing layer.
- static bool requiresCompositingForAnimation(RenderObject*);
- static bool requiresCompositingForTransform(RenderObject*);
+ bool requiresCompositingForAnimation(RenderObject*) const;
+ bool requiresCompositingForTransform(RenderObject*) const;
+ bool requiresCompositingForVideo(RenderObject*) const;
private:
RenderView* m_renderView;
GraphicsLayer* m_rootPlatformLayer;
+ bool m_hasAcceleratedCompositing;
+ bool m_compositingConsultsOverlap;
bool m_compositing;
bool m_rootLayerAttached;
- bool m_compositingLayersNeedUpdate;
+ bool m_compositingLayersNeedRebuild;
+
#if PROFILE_LAYER_REBUILD
int m_rootLayerUpdateCount;
#endif
diff --git a/WebCore/rendering/RenderListBox.cpp b/WebCore/rendering/RenderListBox.cpp
index 83c569e..e6c28f7 100644
--- a/WebCore/rendering/RenderListBox.cpp
+++ b/WebCore/rendering/RenderListBox.cpp
@@ -370,7 +370,7 @@ bool RenderListBox::isPointInOverflowControl(HitTestResult& result, int _x, int
return false;
IntRect vertRect(_tx + width() - borderRight() - m_vBar->width(),
- _ty,
+ _ty + borderTop(),
m_vBar->width(),
height() - borderTop() - borderBottom());
@@ -416,22 +416,22 @@ void RenderListBox::panScroll(const IntPoint& panStartMousePosition)
int yDelta = currentMousePosition.y() - panStartMousePosition.y();
- // If the point is too far from the center we limit the speed
+ // If the point is too far from the center we limit the speed
yDelta = max(min(yDelta, maxSpeed), -maxSpeed);
- if(abs(yDelta) < iconRadius) // at the center we let the space for the icon
+ if (abs(yDelta) < iconRadius) // at the center we let the space for the icon
return;
if (yDelta > 0)
//offsetY = view()->viewHeight();
absOffset.move(0, listHeight());
- else if (yDelta < 0)
- yDelta--;
+ else if (yDelta < 0)
+ yDelta--;
// Let's attenuate the speed
yDelta /= speedReducer;
- IntPoint scrollPoint(0,0);
+ IntPoint scrollPoint(0, 0);
scrollPoint.setY(absOffset.y() + yDelta);
int newOffset = scrollToward(scrollPoint);
if (newOffset < 0)
@@ -623,6 +623,64 @@ void RenderListBox::invalidateScrollbarRect(Scrollbar* scrollbar, const IntRect&
repaintRectangle(scrollRect);
}
+IntRect RenderListBox::convertFromScrollbarToContainingView(const Scrollbar* scrollbar, const IntRect& scrollbarRect) const
+{
+ RenderView* view = this->view();
+ if (!view)
+ return scrollbarRect;
+
+ IntRect rect = scrollbarRect;
+
+ int scrollbarLeft = width() - borderRight() - scrollbar->width();
+ int scrollbarTop = borderTop();
+ rect.move(scrollbarLeft, scrollbarTop);
+
+ return view->frameView()->convertFromRenderer(this, rect);
+}
+
+IntRect RenderListBox::convertFromContainingViewToScrollbar(const Scrollbar* scrollbar, const IntRect& parentRect) const
+{
+ RenderView* view = this->view();
+ if (!view)
+ return parentRect;
+
+ IntRect rect = view->frameView()->convertToRenderer(this, parentRect);
+
+ int scrollbarLeft = width() - borderRight() - scrollbar->width();
+ int scrollbarTop = borderTop();
+ rect.move(-scrollbarLeft, -scrollbarTop);
+ return rect;
+}
+
+IntPoint RenderListBox::convertFromScrollbarToContainingView(const Scrollbar* scrollbar, const IntPoint& scrollbarPoint) const
+{
+ RenderView* view = this->view();
+ if (!view)
+ return scrollbarPoint;
+
+ IntPoint point = scrollbarPoint;
+
+ int scrollbarLeft = width() - borderRight() - scrollbar->width();
+ int scrollbarTop = borderTop();
+ point.move(scrollbarLeft, scrollbarTop);
+
+ return view->frameView()->convertFromRenderer(this, point);
+}
+
+IntPoint RenderListBox::convertFromContainingViewToScrollbar(const Scrollbar* scrollbar, const IntPoint& parentPoint) const
+{
+ RenderView* view = this->view();
+ if (!view)
+ return parentPoint;
+
+ IntPoint point = view->frameView()->convertToRenderer(this, parentPoint);
+
+ int scrollbarLeft = width() - borderRight() - scrollbar->width();
+ int scrollbarTop = borderTop();
+ point.move(-scrollbarLeft, -scrollbarTop);
+ return point;
+}
+
PassRefPtr<Scrollbar> RenderListBox::createScrollbar()
{
RefPtr<Scrollbar> widget;
diff --git a/WebCore/rendering/RenderListBox.h b/WebCore/rendering/RenderListBox.h
index b8c0540..e5454e5 100644
--- a/WebCore/rendering/RenderListBox.h
+++ b/WebCore/rendering/RenderListBox.h
@@ -1,7 +1,7 @@
/*
* This file is part of the select element renderer in WebCore.
*
- * Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
+ * Copyright (C) 2006, 2007, 2009 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -39,8 +39,21 @@ namespace WebCore {
class RenderListBox : public RenderBlock, private ScrollbarClient {
public:
RenderListBox(Element*);
- ~RenderListBox();
+ virtual ~RenderListBox();
+ void selectionChanged();
+
+ void setOptionsChanged(bool changed) { m_optionsChanged = changed; }
+
+ int listIndexAtOffset(int x, int y);
+ IntRect itemBoundingBoxRect(int tx, int ty, int index);
+
+ bool scrollToRevealElementAtListIndex(int index);
+ bool listIndexIsVisible(int index);
+
+ int scrollToward(const IntPoint&); // Returns the new index or -1 if no scroll occurred
+
+private:
virtual const char* renderName() const { return "RenderListBox"; }
virtual bool isListBox() const { return true; }
@@ -63,16 +76,6 @@ public:
virtual void layout();
- void selectionChanged();
-
- void setOptionsChanged(bool changed) { m_optionsChanged = changed; }
-
- int listIndexAtOffset(int x, int y);
- IntRect itemBoundingBoxRect(int tx, int ty, int index);
-
- bool scrollToRevealElementAtListIndex(int index);
- bool listIndexIsVisible(int index);
-
virtual bool canBeProgramaticallyScrolled(bool) const { return true; }
virtual void autoscroll();
virtual void stopAutoscroll();
@@ -80,8 +83,6 @@ public:
virtual bool shouldPanScroll() const { return true; }
virtual void panScroll(const IntPoint&);
- int scrollToward(const IntPoint&); // Returns the new index or -1 if no scroll occurred
-
virtual int verticalScrollbarWidth() const;
virtual int scrollLeft() const;
virtual int scrollTop() const;
@@ -92,15 +93,17 @@ public:
virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, int x, int y, int tx, int ty, HitTestAction);
-protected:
virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
-private:
// ScrollbarClient interface.
virtual void valueChanged(Scrollbar*);
virtual void invalidateScrollbarRect(Scrollbar*, const IntRect&);
virtual bool isActive() const;
virtual bool scrollbarCornerPresent() const { return false; } // We don't support resize on list boxes yet. If we did this would have to change.
+ virtual IntRect convertFromScrollbarToContainingView(const Scrollbar*, const IntRect&) const;
+ virtual IntRect convertFromContainingViewToScrollbar(const Scrollbar*, const IntRect&) const;
+ virtual IntPoint convertFromScrollbarToContainingView(const Scrollbar*, const IntPoint&) const;
+ virtual IntPoint convertFromContainingViewToScrollbar(const Scrollbar*, const IntPoint&) const;
void setHasVerticalScrollbar(bool hasScrollbar);
PassRefPtr<Scrollbar> createScrollbar();
@@ -126,6 +129,15 @@ private:
RefPtr<Scrollbar> m_vBar;
};
+inline RenderListBox* toRenderListBox(RenderObject* object)
+{
+ ASSERT(!object || object->isListBox());
+ return static_cast<RenderListBox*>(object);
+}
+
+// This will catch anyone doing an unnecessary cast.
+void toRenderListBox(const RenderListBox*);
+
} // namepace WebCore
#endif // RenderListBox_h
diff --git a/WebCore/rendering/RenderListItem.cpp b/WebCore/rendering/RenderListItem.cpp
index fb965d2..374ef66 100644
--- a/WebCore/rendering/RenderListItem.cpp
+++ b/WebCore/rendering/RenderListItem.cpp
@@ -91,20 +91,20 @@ static Node* enclosingList(Node* node)
static RenderListItem* previousListItem(Node* list, const RenderListItem* item)
{
- for (Node* n = item->node()->traversePreviousNode(); n != list; n = n->traversePreviousNode()) {
- RenderObject* o = n->renderer();
- if (o && o->isListItem()) {
- Node* otherList = enclosingList(n);
- // This item is part of our current list, so it's what we're looking for.
- if (list == otherList)
- return static_cast<RenderListItem*>(o);
- // We found ourself inside another list; lets skip the rest of it.
- // Use traverseNextNode() here because the other list itself may actually
- // be a list item itself. We need to examine it, so we do this to counteract
- // the traversePreviousNode() that will be done by the loop.
- if (otherList)
- n = otherList->traverseNextNode();
- }
+ for (Node* node = item->node()->traversePreviousNode(); node != list; node = node->traversePreviousNode()) {
+ RenderObject* renderer = node->renderer();
+ if (!renderer || !renderer->isListItem())
+ continue;
+ Node* otherList = enclosingList(node);
+ // This item is part of our current list, so it's what we're looking for.
+ if (list == otherList)
+ return toRenderListItem(renderer);
+ // We found ourself inside another list; lets skip the rest of it.
+ // Use traverseNextNode() here because the other list itself may actually
+ // be a list item itself. We need to examine it, so we do this to counteract
+ // the traversePreviousNode() that will be done by the loop.
+ if (otherList)
+ node = otherList->traverseNextNode();
}
return 0;
}
@@ -302,9 +302,9 @@ void RenderListItem::explicitValueChanged()
RenderObject* listRenderer = 0;
if (listNode)
listRenderer = listNode->renderer();
- for (RenderObject* r = this; r; r = r->nextInPreOrder(listRenderer))
- if (r->isListItem()) {
- RenderListItem* item = static_cast<RenderListItem*>(r);
+ for (RenderObject* renderer = this; renderer; renderer = renderer->nextInPreOrder(listRenderer))
+ if (renderer->isListItem()) {
+ RenderListItem* item = toRenderListItem(renderer);
if (!item->m_hasExplicitValue) {
item->m_isValueUpToDate = false;
if (RenderListMarker* marker = item->m_marker)
diff --git a/WebCore/rendering/RenderListItem.h b/WebCore/rendering/RenderListItem.h
index 91844f7..21544f9 100644
--- a/WebCore/rendering/RenderListItem.h
+++ b/WebCore/rendering/RenderListItem.h
@@ -1,7 +1,7 @@
/*
* Copyright (C) 1999 Lars Knoll (knoll@kde.org)
* (C) 1999 Antti Koivisto (koivisto@kde.org)
- * Copyright (C) 2003, 2004, 2005, 2006, 2007 Apple Inc. All rights reserved.
+ * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2009 Apple Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -33,12 +33,6 @@ class RenderListItem : public RenderBlock {
public:
RenderListItem(Node*);
- virtual const char* renderName() const { return "RenderListItem"; }
-
- virtual bool isListItem() const { return true; }
-
- virtual void destroy();
-
int value() const { if (!m_isValueUpToDate) updateValueNow(); return m_value; }
void updateValue();
@@ -47,6 +41,16 @@ public:
void setExplicitValue(int value);
void clearExplicitValue();
+ void setNotInList(bool notInList) { m_notInList = notInList; }
+ bool notInList() const { return m_notInList; }
+
+private:
+ virtual const char* renderName() const { return "RenderListItem"; }
+
+ virtual bool isListItem() const { return true; }
+
+ virtual void destroy();
+
virtual bool isEmpty() const;
virtual void paint(PaintInfo&, int tx, int ty);
@@ -55,15 +59,10 @@ public:
virtual void positionListMarker();
- void setNotInList(bool notInList) { m_notInList = notInList; }
- bool notInList() const { return m_notInList; }
-
const String& markerText() const;
-protected:
virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
-private:
void updateMarkerLocation();
inline int calcValue() const;
void updateValueNow() const;
@@ -78,6 +77,15 @@ private:
bool m_notInList : 1;
};
+inline RenderListItem* toRenderListItem(RenderObject* object)
+{
+ ASSERT(!object || object->isListItem());
+ return static_cast<RenderListItem*>(object);
+}
+
+// This will catch anyone doing an unnecessary cast.
+void toRenderListItem(const RenderListItem*);
+
} // namespace WebCore
#endif // RenderListItem_h
diff --git a/WebCore/rendering/RenderListMarker.h b/WebCore/rendering/RenderListMarker.h
index 57580a8..5b46278 100644
--- a/WebCore/rendering/RenderListMarker.h
+++ b/WebCore/rendering/RenderListMarker.h
@@ -1,7 +1,7 @@
/*
* Copyright (C) 1999 Lars Knoll (knoll@kde.org)
* (C) 1999 Antti Koivisto (koivisto@kde.org)
- * Copyright (C) 2003, 2004, 2005, 2006, 2007 Apple Inc. All rights reserved.
+ * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2009 Apple Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -36,8 +36,15 @@ String listMarkerText(EListStyleType, int value);
class RenderListMarker : public RenderBox {
public:
RenderListMarker(RenderListItem*);
- ~RenderListMarker();
+ virtual ~RenderListMarker();
+ virtual void calcPrefWidths();
+
+ const String& text() const { return m_text; }
+
+ bool isInside() const;
+
+private:
virtual const char* renderName() const { return "RenderListMarker"; }
virtual bool isListMarker() const { return true; }
@@ -45,7 +52,6 @@ public:
virtual void paint(PaintInfo&, int tx, int ty);
virtual void layout();
- virtual void calcPrefWidths();
virtual void imageChanged(WrappedImagePtr, const IntRect* = 0);
@@ -56,9 +62,6 @@ public:
bool isImage() const;
bool isText() const { return !isImage(); }
- const String& text() const { return m_text; }
-
- bool isInside() const;
virtual void setSelectionState(SelectionState);
virtual IntRect selectionRectForRepaint(RenderBoxModelObject* repaintContainer, bool clipToVisibleContent = true);
@@ -66,11 +69,9 @@ public:
void updateMargins();
-protected:
virtual void styleWillChange(StyleDifference, const RenderStyle* newStyle);
virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
-private:
IntRect getRelativeMarkerRect();
String m_text;
@@ -78,6 +79,21 @@ private:
RenderListItem* m_listItem;
};
+inline RenderListMarker* toRenderListMarker(RenderObject* object)
+{
+ ASSERT(!object || object->isListMarker());
+ return static_cast<RenderListMarker*>(object);
+}
+
+inline const RenderListMarker* toRenderListMarker(const RenderObject* object)
+{
+ ASSERT(!object || object->isListMarker());
+ return static_cast<const RenderListMarker*>(object);
+}
+
+// This will catch anyone doing an unnecessary cast.
+void toRenderListMarker(const RenderListMarker*);
+
} // namespace WebCore
#endif // RenderListMarker_h
diff --git a/WebCore/rendering/RenderMarquee.cpp b/WebCore/rendering/RenderMarquee.cpp
index 48659f7..31a8305 100644
--- a/WebCore/rendering/RenderMarquee.cpp
+++ b/WebCore/rendering/RenderMarquee.cpp
@@ -235,7 +235,7 @@ void RenderMarquee::updateMarqueeStyle()
// to a marquee of 200px.
if (isHorizontal()) {
if (s->height().isFixed() && s->height().value() < s->fontSize())
- s->setHeight(Length(s->fontSize(),Fixed));
+ s->setHeight(Length(s->fontSize(), Fixed));
} else if (s->height().isAuto()) //vertical marquee with no specified height
s->setHeight(Length(200, Fixed));
@@ -309,4 +309,3 @@ void RenderMarquee::timerFired(Timer<RenderMarquee>*)
}
} // namespace WebCore
-
diff --git a/WebCore/rendering/RenderMedia.cpp b/WebCore/rendering/RenderMedia.cpp
index 2ffa2f6..b87e99d 100644
--- a/WebCore/rendering/RenderMedia.cpp
+++ b/WebCore/rendering/RenderMedia.cpp
@@ -45,7 +45,8 @@ using namespace HTMLNames;
static const double cTimeUpdateRepeatDelay = 0.2;
static const double cOpacityAnimationRepeatDelay = 0.05;
// FIXME get this from style
-static const double cOpacityAnimationDuration = 0.1;
+static const double cOpacityAnimationDurationFadeIn = 0.1;
+static const double cOpacityAnimationDurationFadeOut = 0.3;
RenderMedia::RenderMedia(HTMLMediaElement* video)
: RenderReplaced(video)
@@ -53,9 +54,9 @@ RenderMedia::RenderMedia(HTMLMediaElement* video)
, m_opacityAnimationTimer(this, &RenderMedia::opacityAnimationTimerFired)
, m_mouseOver(false)
, m_opacityAnimationStartTime(0)
+ , m_opacityAnimationDuration(cOpacityAnimationDurationFadeIn)
, m_opacityAnimationFrom(0)
, m_opacityAnimationTo(1.0f)
- , m_previousVisible(VISIBLE)
{
}
@@ -65,6 +66,7 @@ RenderMedia::RenderMedia(HTMLMediaElement* video, const IntSize& intrinsicSize)
, m_opacityAnimationTimer(this, &RenderMedia::opacityAnimationTimerFired)
, m_mouseOver(false)
, m_opacityAnimationStartTime(0)
+ , m_opacityAnimationDuration(cOpacityAnimationDurationFadeIn)
, m_opacityAnimationFrom(0)
, m_opacityAnimationTo(1.0f)
{
@@ -104,20 +106,32 @@ void RenderMedia::styleDidChange(StyleDifference diff, const RenderStyle* oldSty
RenderReplaced::styleDidChange(diff, oldStyle);
if (m_controlsShadowRoot) {
- if (m_panel->renderer())
- m_panel->renderer()->setStyle(getCachedPseudoStyle(MEDIA_CONTROLS_PANEL));
-
- if (m_timelineContainer->renderer())
- m_timelineContainer->renderer()->setStyle(getCachedPseudoStyle(MEDIA_CONTROLS_TIMELINE_CONTAINER));
-
- m_muteButton->updateStyle();
- m_playButton->updateStyle();
- m_seekBackButton->updateStyle();
- m_seekForwardButton->updateStyle();
- m_timeline->updateStyle();
- m_fullscreenButton->updateStyle();
- m_currentTimeDisplay->updateStyle();
- m_timeRemainingDisplay->updateStyle();
+ if (m_panel)
+ m_panel->updateStyle();
+ if (m_muteButton)
+ m_muteButton->updateStyle();
+ if (m_playButton)
+ m_playButton->updateStyle();
+ if (m_seekBackButton)
+ m_seekBackButton->updateStyle();
+ if (m_seekForwardButton)
+ m_seekForwardButton->updateStyle();
+ if (m_rewindButton)
+ m_rewindButton->updateStyle();
+ if (m_returnToRealtimeButton)
+ m_returnToRealtimeButton->updateStyle();
+ if (m_statusDisplay)
+ m_statusDisplay->updateStyle();
+ if (m_timelineContainer)
+ m_timelineContainer->updateStyle();
+ if (m_timeline)
+ m_timeline->updateStyle();
+ if (m_fullscreenButton)
+ m_fullscreenButton->updateStyle();
+ if (m_currentTimeDisplay)
+ m_currentTimeDisplay->updateStyle();
+ if (m_timeRemainingDisplay)
+ m_timeRemainingDisplay->updateStyle();
}
}
@@ -132,6 +146,13 @@ void RenderMedia::layout()
return;
IntSize newSize = contentBoxRect().size();
if (newSize != oldSize || controlsRenderer->needsLayout()) {
+
+ if (m_currentTimeDisplay && m_timeRemainingDisplay) {
+ bool shouldShowTimeDisplays = shouldShowTimeDisplayControls();
+ m_currentTimeDisplay->setVisible(shouldShowTimeDisplays);
+ m_timeRemainingDisplay->setVisible(shouldShowTimeDisplays);
+ }
+
controlsRenderer->setLocation(borderLeft() + paddingLeft(), borderTop() + paddingTop());
controlsRenderer->style()->setHeight(Length(newSize.height(), Fixed));
controlsRenderer->style()->setWidth(Length(newSize.width(), Fixed));
@@ -151,17 +172,8 @@ void RenderMedia::createControlsShadowRoot()
void RenderMedia::createPanel()
{
ASSERT(!m_panel);
- RenderStyle* style = getCachedPseudoStyle(MEDIA_CONTROLS_PANEL);
- m_panel = new HTMLDivElement(HTMLNames::divTag, document());
- RenderObject* renderer = m_panel->createRenderer(renderArena(), style);
- if (renderer) {
- m_panel->setRenderer(renderer);
- renderer->setStyle(style);
- m_panel->setAttached();
- m_panel->setInDocument(true);
- m_controlsShadowRoot->addChild(m_panel);
- m_controlsShadowRoot->renderer()->addChild(renderer);
- }
+ m_panel = new MediaControlElement(document(), MEDIA_CONTROLS_PANEL, mediaElement());
+ m_panel->attachToParent(m_controlsShadowRoot.get());
}
void RenderMedia::createMuteButton()
@@ -192,20 +204,32 @@ void RenderMedia::createSeekForwardButton()
m_seekForwardButton->attachToParent(m_panel.get());
}
+void RenderMedia::createRewindButton()
+{
+ ASSERT(!m_rewindButton);
+ m_rewindButton = new MediaControlRewindButtonElement(document(), mediaElement());
+ m_rewindButton->attachToParent(m_panel.get());
+}
+
+void RenderMedia::createReturnToRealtimeButton()
+{
+ ASSERT(!m_returnToRealtimeButton);
+ m_returnToRealtimeButton = new MediaControlReturnToRealtimeButtonElement(document(), mediaElement());
+ m_returnToRealtimeButton->attachToParent(m_panel.get());
+}
+
+void RenderMedia::createStatusDisplay()
+{
+ ASSERT(!m_statusDisplay);
+ m_statusDisplay = new MediaControlStatusDisplayElement(document(), mediaElement());
+ m_statusDisplay->attachToParent(m_panel.get());
+}
+
void RenderMedia::createTimelineContainer()
{
ASSERT(!m_timelineContainer);
- RenderStyle* style = getCachedPseudoStyle(MEDIA_CONTROLS_TIMELINE_CONTAINER);
- m_timelineContainer = new HTMLDivElement(HTMLNames::divTag, document());
- RenderObject* renderer = m_timelineContainer->createRenderer(renderArena(), style);
- if (renderer) {
- m_timelineContainer->setRenderer(renderer);
- renderer->setStyle(style);
- m_timelineContainer->setAttached();
- m_timelineContainer->setInDocument(true);
- m_panel->addChild(m_timelineContainer);
- m_panel->renderer()->addChild(renderer);
- }
+ m_timelineContainer = new MediaControlTimelineContainerElement(document(), mediaElement());
+ m_timelineContainer->attachToParent(m_panel.get());
}
void RenderMedia::createTimeline()
@@ -215,18 +239,18 @@ void RenderMedia::createTimeline()
m_timeline->setAttribute(precisionAttr, "float");
m_timeline->attachToParent(m_timelineContainer.get());
}
-
+
void RenderMedia::createCurrentTimeDisplay()
{
ASSERT(!m_currentTimeDisplay);
- m_currentTimeDisplay = new MediaTimeDisplayElement(document(), mediaElement(), true);
+ m_currentTimeDisplay = new MediaControlTimeDisplayElement(document(), MEDIA_CONTROLS_CURRENT_TIME_DISPLAY, mediaElement());
m_currentTimeDisplay->attachToParent(m_timelineContainer.get());
}
void RenderMedia::createTimeRemainingDisplay()
{
ASSERT(!m_timeRemainingDisplay);
- m_timeRemainingDisplay = new MediaTimeDisplayElement(document(), mediaElement(), false);
+ m_timeRemainingDisplay = new MediaControlTimeDisplayElement(document(), MEDIA_CONTROLS_TIME_REMAINING_DISPLAY, mediaElement());
m_timeRemainingDisplay->attachToParent(m_timelineContainer.get());
}
@@ -251,10 +275,13 @@ void RenderMedia::updateControls()
m_panel = 0;
m_muteButton = 0;
m_playButton = 0;
+ m_statusDisplay = 0;
m_timelineContainer = 0;
m_timeline = 0;
m_seekBackButton = 0;
m_seekForwardButton = 0;
+ m_rewindButton = 0;
+ m_returnToRealtimeButton = 0;
m_currentTimeDisplay = 0;
m_timeRemainingDisplay = 0;
m_fullscreenButton = 0;
@@ -269,38 +296,65 @@ void RenderMedia::updateControls()
if (!m_controlsShadowRoot) {
createControlsShadowRoot();
createPanel();
- createMuteButton();
- createPlayButton();
- createTimelineContainer();
- createTimeline();
- createSeekBackButton();
- createSeekForwardButton();
- createCurrentTimeDisplay();
- createTimeRemainingDisplay();
- createFullscreenButton();
+ if (m_panel) {
+ createRewindButton();
+ createMuteButton();
+ createPlayButton();
+ createReturnToRealtimeButton();
+ createStatusDisplay();
+ createTimelineContainer();
+ createSeekBackButton();
+ createSeekForwardButton();
+ createFullscreenButton();
+ if (m_timelineContainer) {
+ createCurrentTimeDisplay();
+ createTimeline();
+ createTimeRemainingDisplay();
+ }
+ m_panel->attach();
+ }
}
if (media->canPlay()) {
if (m_timeUpdateTimer.isActive())
m_timeUpdateTimer.stop();
- } else if (style()->visibility() == VISIBLE && m_timeline && m_timeline->renderer() && m_timeline->renderer()->style()->display() != NONE ) {
+ } 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_panel) {
+ // update() might alter the opacity of the element, especially if we are in the middle
+ // of an animation. This is the only element concerned as we animate only this element.
+ float opacityBeforeChangingStyle = m_panel->renderer() ? m_panel->renderer()->style()->opacity() : 0;
+ m_panel->update();
+ changeOpacity(m_panel.get(), opacityBeforeChangingStyle);
+ }
if (m_muteButton)
m_muteButton->update();
if (m_playButton)
m_playButton->update();
+ if (m_timelineContainer)
+ m_timelineContainer->update();
if (m_timeline)
m_timeline->update();
+ if (m_currentTimeDisplay)
+ m_currentTimeDisplay->update();
+ if (m_timeRemainingDisplay)
+ m_timeRemainingDisplay->update();
if (m_seekBackButton)
m_seekBackButton->update();
if (m_seekForwardButton)
m_seekForwardButton->update();
+ if (m_rewindButton)
+ m_rewindButton->update();
+ if (m_returnToRealtimeButton)
+ m_returnToRealtimeButton->update();
+ if (m_statusDisplay)
+ m_statusDisplay->update();
if (m_fullscreenButton)
m_fullscreenButton->update();
+
updateTimeDisplay();
updateControlVisibility();
}
@@ -355,26 +409,34 @@ void RenderMedia::updateControlVisibility()
if (!media->hasVideo())
return;
- // do fading manually, css animations don't work well with shadow trees
- bool visible = style()->visibility() == VISIBLE && (m_mouseOver || media->canPlay());
- if (visible == (m_opacityAnimationTo > 0))
+ // Don't fade if the media element is not visible
+ if (style()->visibility() != VISIBLE)
return;
+
+ bool shouldHideController = !m_mouseOver && !media->canPlay();
+
+ // Do fading manually, css animations don't work with shadow trees
- if (style()->visibility() != m_previousVisible) {
- // 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(), m_opacityAnimationTo);
+ float animateFrom = m_panel->renderer()->style()->opacity();
+ float animateTo = shouldHideController ? 0.0f : 1.0f;
+
+ if (animateFrom == animateTo)
return;
- }
- if (visible) {
- m_opacityAnimationFrom = m_panel->renderer()->style()->opacity();
- m_opacityAnimationTo = 1.0f;
- } else {
- m_opacityAnimationFrom = m_panel->renderer()->style()->opacity();
- m_opacityAnimationTo = 0;
+ if (m_opacityAnimationTimer.isActive()) {
+ if (m_opacityAnimationTo == animateTo)
+ return;
+ m_opacityAnimationTimer.stop();
}
+
+ if (animateFrom < animateTo)
+ m_opacityAnimationDuration = cOpacityAnimationDurationFadeIn;
+ else
+ m_opacityAnimationDuration = cOpacityAnimationDurationFadeOut;
+
+ m_opacityAnimationFrom = animateFrom;
+ m_opacityAnimationTo = animateTo;
+
m_opacityAnimationStartTime = currentTime();
m_opacityAnimationTimer.startRepeating(cOpacityAnimationRepeatDelay);
}
@@ -393,11 +455,11 @@ void RenderMedia::changeOpacity(HTMLElement* e, float opacity)
void RenderMedia::opacityAnimationTimerFired(Timer<RenderMedia>*)
{
double time = currentTime() - m_opacityAnimationStartTime;
- if (time >= cOpacityAnimationDuration) {
- time = cOpacityAnimationDuration;
+ if (time >= m_opacityAnimationDuration) {
+ time = m_opacityAnimationDuration;
m_opacityAnimationTimer.stop();
}
- float opacity = narrowPrecisionToFloat(m_opacityAnimationFrom + (m_opacityAnimationTo - m_opacityAnimationFrom) * time / cOpacityAnimationDuration);
+ float opacity = narrowPrecisionToFloat(m_opacityAnimationFrom + (m_opacityAnimationTo - m_opacityAnimationFrom) * time / m_opacityAnimationDuration);
changeOpacity(m_panel.get(), opacity);
}
@@ -418,6 +480,12 @@ void RenderMedia::forwardEvent(Event* event)
if (m_seekForwardButton && m_seekForwardButton->hitTest(point))
m_seekForwardButton->defaultEventHandler(event);
+ if (m_rewindButton && m_rewindButton->hitTest(point))
+ m_rewindButton->defaultEventHandler(event);
+
+ if (m_returnToRealtimeButton && m_returnToRealtimeButton->hitTest(point))
+ m_returnToRealtimeButton->defaultEventHandler(event);
+
if (m_timeline && m_timeline->hitTest(point))
m_timeline->defaultEventHandler(event);
@@ -465,6 +533,19 @@ int RenderMedia::leftmostPosition(bool includeOverflowInterior, bool includeSelf
return min(left, m_controlsShadowRoot->renderBox()->x() + m_controlsShadowRoot->renderBox()->leftmostPosition(includeOverflowInterior, includeSelf));
}
+
+// We want the timeline slider to be at least 100 pixels wide.
+static const int minWidthToDisplayTimeDisplays = 16 + 16 + 45 + 100 + 45 + 16 + 1;
+
+bool RenderMedia::shouldShowTimeDisplayControls() const
+{
+ if (!m_currentTimeDisplay && !m_timeRemainingDisplay)
+ return false;
+
+ int width = mediaElement()->renderBox()->width();
+ return width >= minWidthToDisplayTimeDisplays * style()->effectiveZoom();
+}
+
} // namespace WebCore
#endif
diff --git a/WebCore/rendering/RenderMedia.h b/WebCore/rendering/RenderMedia.h
index 6013d7b..5697bda 100644
--- a/WebCore/rendering/RenderMedia.h
+++ b/WebCore/rendering/RenderMedia.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2007, 2008, 2009 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -38,9 +38,14 @@ class HTMLMediaElement;
class MediaControlMuteButtonElement;
class MediaControlPlayButtonElement;
class MediaControlSeekButtonElement;
+class MediaControlRewindButtonElement;
+class MediaControlReturnToRealtimeButtonElement;
class MediaControlTimelineElement;
class MediaControlFullscreenButtonElement;
-class MediaTimeDisplayElement;
+class MediaControlTimeDisplayElement;
+class MediaControlStatusDisplayElement;
+class MediaControlTimelineContainerElement;
+class MediaControlElement;
class MediaPlayer;
class RenderMedia : public RenderReplaced {
@@ -49,23 +54,16 @@ public:
RenderMedia(HTMLMediaElement*, const IntSize& intrinsicSize);
virtual ~RenderMedia();
- virtual RenderObjectChildList* virtualChildren() { return children(); }
- virtual const RenderObjectChildList* virtualChildren() const { return children(); }
const RenderObjectChildList* children() const { return &m_children; }
RenderObjectChildList* children() { return &m_children; }
- virtual void destroy();
-
- virtual void layout();
-
- virtual const char* renderName() const { return "RenderMedia"; }
- virtual bool isMedia() const { return true; }
-
HTMLMediaElement* mediaElement() const;
MediaPlayer* player() const;
static String formatTime(float time);
+ bool shouldShowTimeDisplayControls() const;
+
void updateFromElement();
void updatePlayer();
void updateControls();
@@ -73,11 +71,22 @@ public:
void forwardEvent(Event*);
+protected:
+ virtual void layout();
+
+private:
+ virtual RenderObjectChildList* virtualChildren() { return children(); }
+ virtual const RenderObjectChildList* virtualChildren() const { return children(); }
+
+ virtual void destroy();
+
+ virtual const char* renderName() const { return "RenderMedia"; }
+ virtual bool isMedia() const { return true; }
+
virtual 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;
-private:
void createControlsShadowRoot();
void destroyControlsShadowRoot();
void createPanel();
@@ -85,6 +94,9 @@ private:
void createPlayButton();
void createSeekBackButton();
void createSeekForwardButton();
+ void createRewindButton();
+ void createReturnToRealtimeButton();
+ void createStatusDisplay();
void createTimelineContainer();
void createTimeline();
void createCurrentTimeDisplay();
@@ -100,16 +112,19 @@ private:
virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
RefPtr<HTMLElement> m_controlsShadowRoot;
- RefPtr<HTMLElement> m_panel;
+ RefPtr<MediaControlElement> m_panel;
RefPtr<MediaControlMuteButtonElement> m_muteButton;
RefPtr<MediaControlPlayButtonElement> m_playButton;
RefPtr<MediaControlSeekButtonElement> m_seekBackButton;
RefPtr<MediaControlSeekButtonElement> m_seekForwardButton;
+ RefPtr<MediaControlRewindButtonElement> m_rewindButton;
+ RefPtr<MediaControlReturnToRealtimeButtonElement> m_returnToRealtimeButton;
RefPtr<MediaControlTimelineElement> m_timeline;
RefPtr<MediaControlFullscreenButtonElement> m_fullscreenButton;
- RefPtr<HTMLElement> m_timelineContainer;
- RefPtr<MediaTimeDisplayElement> m_currentTimeDisplay;
- RefPtr<MediaTimeDisplayElement> m_timeRemainingDisplay;
+ RefPtr<MediaControlTimelineContainerElement> m_timelineContainer;
+ RefPtr<MediaControlTimeDisplayElement> m_currentTimeDisplay;
+ RefPtr<MediaControlTimeDisplayElement> m_timeRemainingDisplay;
+ RefPtr<MediaControlStatusDisplayElement> m_statusDisplay;
RenderObjectChildList m_children;
Node* m_lastUnderNode;
Node* m_nodeUnderMouse;
@@ -118,11 +133,20 @@ private:
Timer<RenderMedia> m_opacityAnimationTimer;
bool m_mouseOver;
double m_opacityAnimationStartTime;
+ double m_opacityAnimationDuration;
float m_opacityAnimationFrom;
float m_opacityAnimationTo;
- EVisibility m_previousVisible;
};
+inline RenderMedia* toRenderMedia(RenderObject* object)
+{
+ ASSERT(!object || object->isMedia());
+ return static_cast<RenderMedia*>(object);
+}
+
+// This will catch anyone doing an unnecessary cast.
+void toRenderMedia(const RenderMedia*);
+
} // namespace WebCore
#endif
diff --git a/WebCore/rendering/RenderMediaControls.cpp b/WebCore/rendering/RenderMediaControls.cpp
index f1ff55f..06d901a 100644
--- a/WebCore/rendering/RenderMediaControls.cpp
+++ b/WebCore/rendering/RenderMediaControls.cpp
@@ -51,19 +51,20 @@ SOFT_LINK(SafariTheme, STPaintProgressIndicator, void, APIENTRY, (ProgressIndica
static ThemeControlState determineState(RenderObject* o)
{
ThemeControlState result = 0;
- if (theme()->isActive(o))
+ RenderTheme* theme = o->theme();
+ if (theme->isActive(o))
result |= SafariTheme::ActiveState;
- if (theme()->isEnabled(o) && !theme()->isReadOnlyControl(o))
+ if (theme->isEnabled(o) && !theme->isReadOnlyControl(o))
result |= SafariTheme::EnabledState;
- if (theme()->isPressed(o))
+ if (theme->isPressed(o))
result |= SafariTheme::PressedState;
- if (theme()->isChecked(o))
+ if (theme->isChecked(o))
result |= SafariTheme::CheckedState;
- if (theme()->isIndeterminate(o))
+ if (theme->isIndeterminate(o))
result |= SafariTheme::IndeterminateCheckedState;
- if (theme()->isFocused(o))
+ if (theme->isFocused(o))
result |= SafariTheme::FocusedState;
- if (theme()->isDefault(o))
+ if (theme->isDefault(o))
result |= SafariTheme::DefaultState;
return result;
}
@@ -101,13 +102,17 @@ bool RenderMediaControls::paintMediaControlsPart(MediaControlElementType part, R
break;
case MediaMuteButton:
case MediaUnMuteButton:
- if (HTMLMediaElement* mediaElement = parentMediaElement(o))
- paintThemePart(mediaElement->muted() ? SafariTheme::MediaUnMuteButtonPart : SafariTheme::MediaMuteButtonPart, paintInfo.context->platformContext(), r, NSRegularControlSize, determineState(o));
+ if (MediaControlMuteButtonElement* btn = static_cast<MediaControlMuteButtonElement*>(o->node())) {
+ bool audioEnabled = btn->displayType() == MediaMuteButton;
+ paintThemePart(audioEnabled ? SafariTheme::MediaMuteButtonPart : SafariTheme::MediaUnMuteButtonPart, paintInfo.context->platformContext(), r, NSRegularControlSize, determineState(o));
+ }
break;
case MediaPauseButton:
case MediaPlayButton:
- if (HTMLMediaElement* mediaElement = parentMediaElement(o))
- paintThemePart(mediaElement->canPlay() ? SafariTheme::MediaPlayButtonPart : SafariTheme::MediaPauseButtonPart, paintInfo.context->platformContext(), r, NSRegularControlSize, determineState(o));
+ if (MediaControlPlayButtonElement* btn = static_cast<MediaControlPlayButtonElement*>(o->node())) {
+ bool currentlyPlaying = btn->displayType() == MediaPlayButton;
+ paintThemePart(currentlyPlaying ? SafariTheme::MediaPauseButtonPart : SafariTheme::MediaPlayButtonPart, paintInfo.context->platformContext(), r, NSRegularControlSize, determineState(o));
+ }
break;
case MediaSeekBackButton:
paintThemePart(SafariTheme::MediaSeekBackButtonPart, paintInfo.context->platformContext(), r, NSRegularControlSize, determineState(o));
@@ -116,15 +121,8 @@ bool RenderMediaControls::paintMediaControlsPart(MediaControlElementType part, R
paintThemePart(SafariTheme::MediaSeekForwardButtonPart, paintInfo.context->platformContext(), r, NSRegularControlSize, determineState(o));
break;
case MediaSlider: {
- HTMLMediaElement* mediaElement = parentMediaElement(o);
- if (!mediaElement)
- break;
-
- MediaPlayer* player = mediaElement->player();
- float duration = player ? player->duration() : 0;
- float percentLoaded = duration ? player->maxTimeBuffered() /duration : 0;
-
- STPaintProgressIndicator(SafariTheme::MediaType, paintInfo.context->platformContext(), r, NSRegularControlSize, 0, percentLoaded);
+ if (HTMLMediaElement* mediaElement = parentMediaElement(o))
+ STPaintProgressIndicator(SafariTheme::MediaType, paintInfo.context->platformContext(), r, NSRegularControlSize, 0, mediaElement->percentLoaded());
break;
}
case MediaSliderThumb:
diff --git a/WebCore/rendering/RenderMenuList.cpp b/WebCore/rendering/RenderMenuList.cpp
index 95de7a2..9d2e7e0 100644
--- a/WebCore/rendering/RenderMenuList.cpp
+++ b/WebCore/rendering/RenderMenuList.cpp
@@ -25,6 +25,7 @@
#include "RenderMenuList.h"
#include "CSSStyleSelector.h"
+#include "Frame.h"
#include "FrameView.h"
#include "HTMLNames.h"
#include "NodeRenderStyle.h"
@@ -296,8 +297,14 @@ void RenderMenuList::hidePopup()
void RenderMenuList::valueChanged(unsigned listIndex, bool fireOnChange)
{
+ // Check to ensure a page navigation has not occurred while
+ // the popup was up.
+ Document* doc = static_cast<Element*>(node())->document();
+ if (!doc || doc != doc->frame()->document())
+ return;
+
SelectElement* select = toSelectElement(static_cast<Element*>(node()));
- select->setSelectedIndex(select->listToOptionIndex(listIndex), true, fireOnChange);
+ select->setSelectedIndexByUser(select->listToOptionIndex(listIndex), true, fireOnChange);
}
String RenderMenuList::itemText(unsigned listIndex) const
@@ -311,6 +318,13 @@ String RenderMenuList::itemText(unsigned listIndex) const
return String();
}
+String RenderMenuList::itemToolTip(unsigned listIndex) const
+{
+ SelectElement* select = toSelectElement(static_cast<Element*>(node()));
+ Element* element = select->listItems()[listIndex];
+ return element->title();
+}
+
bool RenderMenuList::itemIsEnabled(unsigned listIndex) const
{
SelectElement* select = toSelectElement(static_cast<Element*>(node()));
diff --git a/WebCore/rendering/RenderMenuList.h b/WebCore/rendering/RenderMenuList.h
index 7966eff..5c18e9e 100644
--- a/WebCore/rendering/RenderMenuList.h
+++ b/WebCore/rendering/RenderMenuList.h
@@ -40,7 +40,16 @@ class RenderText;
class RenderMenuList : public RenderFlexibleBox, private PopupMenuClient {
public:
RenderMenuList(Element*);
- ~RenderMenuList();
+ virtual ~RenderMenuList();
+
+public:
+ bool popupIsVisible() const { return m_popupIsVisible; }
+ void showPopup();
+ void hidePopup();
+
+ void setOptionsChanged(bool changed) { m_optionsChanged = changed; }
+
+ String text() const;
private:
virtual bool isMenuList() const { return true; }
@@ -59,20 +68,11 @@ private:
virtual void calcPrefWidths();
-public:
- bool popupIsVisible() const { return m_popupIsVisible; }
- void showPopup();
- void hidePopup();
-
- void setOptionsChanged(bool changed) { m_optionsChanged = changed; }
-
- String text() const;
-
-private:
virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
// PopupMenuClient methods
virtual String itemText(unsigned listIndex) const;
+ virtual String itemToolTip(unsigned listIndex) const;
virtual bool itemIsEnabled(unsigned listIndex) const;
virtual PopupMenuStyle itemStyle(unsigned listIndex) const;
virtual PopupMenuStyle menuStyle() const;
@@ -113,6 +113,15 @@ private:
bool m_popupIsVisible;
};
+inline RenderMenuList* toRenderMenuList(RenderObject* object)
+{
+ ASSERT(!object || object->isMenuList());
+ return static_cast<RenderMenuList*>(object);
+}
+
+// This will catch anyone doing an unnecessary cast.
+void toRenderMenuList(const RenderMenuList*);
+
}
#endif
diff --git a/WebCore/rendering/RenderObject.cpp b/WebCore/rendering/RenderObject.cpp
index 2aba22a..5137338 100644
--- a/WebCore/rendering/RenderObject.cpp
+++ b/WebCore/rendering/RenderObject.cpp
@@ -217,6 +217,13 @@ RenderObject::~RenderObject()
#endif
}
+RenderTheme* RenderObject::theme() const
+{
+ ASSERT(document()->page());
+
+ return document()->page()->theme();
+}
+
bool RenderObject::isDescendantOf(const RenderObject* obj) const
{
for (const RenderObject* r = this; r; r = r->m_parent) {
@@ -243,9 +250,10 @@ bool RenderObject::isHTMLMarquee() const
static void updateListMarkerNumbers(RenderObject* child)
{
- for (RenderObject* r = child; r; r = r->nextSibling())
- if (r->isListItem())
- static_cast<RenderListItem*>(r)->updateValue();
+ for (RenderObject* sibling = child; sibling; sibling = sibling->nextSibling()) {
+ if (sibling->isListItem())
+ toRenderListItem(sibling)->updateValue();
+ }
}
void RenderObject::addChild(RenderObject* newChild, RenderObject* beforeChild)
@@ -281,7 +289,7 @@ void RenderObject::addChild(RenderObject* newChild, RenderObject* beforeChild)
RenderTable* table;
RenderObject* afterChild = beforeChild ? beforeChild->previousSibling() : children->lastChild();
if (afterChild && afterChild->isAnonymous() && afterChild->isTable())
- table = static_cast<RenderTable*>(afterChild);
+ table = toRenderTable(afterChild);
else {
table = new (renderArena()) RenderTable(document() /* is anonymous */);
RefPtr<RenderStyle> newStyle = RenderStyle::create();
@@ -591,7 +599,7 @@ void RenderObject::setLayerNeedsFullRepaint()
RenderBlock* RenderObject::containingBlock() const
{
if (isTableCell()) {
- const RenderTableCell* cell = static_cast<const RenderTableCell*>(this);
+ const RenderTableCell* cell = toRenderTableCell(this);
if (parent() && cell->section())
return cell->table();
return 0;
@@ -639,13 +647,16 @@ static bool mustRepaintFillLayers(const RenderObject* renderer, const FillLayer*
// Make sure we have a valid image.
StyleImage* img = layer->image();
- bool shouldPaintBackgroundImage = img && img->canRender(renderer->style()->effectiveZoom());
+ if (!img || !img->canRender(renderer->style()->effectiveZoom()))
+ return false;
- // These are always percents or auto.
- if (shouldPaintBackgroundImage &&
- (!layer->xPosition().isZero() || !layer->yPosition().isZero() ||
- layer->size().width().isPercent() || layer->size().height().isPercent()))
- // The image will shift unpredictably if the size changes.
+ if (!layer->xPosition().isZero() || !layer->yPosition().isZero())
+ return true;
+
+ if (layer->isSizeSet()) {
+ if (layer->size().width().isPercent() || layer->size().height().isPercent())
+ return true;
+ } else if (img->usesImageContainerSize())
return true;
return false;
@@ -767,7 +778,7 @@ void RenderObject::drawLineForBoxSide(GraphicsContext* graphicsContext, int x1,
break;
case BSRight:
drawLineForBoxSide(graphicsContext, x1, y1 + max((adjbw1 * 2 + 1) / 3, 0),
- x1 + third, y2 - max(( adjbw2 * 2 + 1) / 3, 0),
+ x1 + third, y2 - max((adjbw2 * 2 + 1) / 3, 0),
s, c, textcolor, SOLID, adjbw1bigthird, adjbw2bigthird);
drawLineForBoxSide(graphicsContext, x2 - third, y1 + max((-adjbw1 * 2 + 1) / 3, 0),
x2, y2 - max((-adjbw2 * 2 + 1) / 3, 0),
@@ -1206,12 +1217,11 @@ bool RenderObject::repaintAfterLayoutIfNeeded(RenderBoxModelObject* repaintConta
// two rectangles (but typically only one).
RenderStyle* outlineStyle = outlineStyleForRepaint();
int ow = outlineStyle->outlineSize();
- ShadowData* boxShadow = style()->boxShadow();
int width = abs(newOutlineBox.width() - oldOutlineBox.width());
if (width) {
- int shadowRight = 0;
- for (ShadowData* shadow = boxShadow; shadow; shadow = shadow->next)
- shadowRight = max(shadow->x + shadow->blur, shadowRight);
+ int shadowLeft;
+ int shadowRight;
+ style()->getBoxShadowHorizontalExtent(shadowLeft, 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);
@@ -1227,9 +1237,9 @@ bool RenderObject::repaintAfterLayoutIfNeeded(RenderBoxModelObject* repaintConta
}
int height = abs(newOutlineBox.height() - oldOutlineBox.height());
if (height) {
- int shadowBottom = 0;
- for (ShadowData* shadow = boxShadow; shadow; shadow = shadow->next)
- shadowBottom = max(shadow->y + shadow->blur, shadowBottom);
+ int shadowTop;
+ int shadowBottom;
+ style()->getBoxShadowVerticalExtent(shadowTop, 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);
@@ -1692,7 +1702,7 @@ void RenderObject::getTransformFromContainer(const RenderObject* containerObject
transform.multLeft(layer->currentTransform());
#if ENABLE(3D_RENDERING)
- if (containerObject && containerObject->style()->hasPerspective()) {
+ if (containerObject && containerObject->hasLayer() && containerObject->style()->hasPerspective()) {
// Perpsective on the container affects us, so we have to factor it in here.
ASSERT(containerObject->hasLayer());
FloatPoint perspectiveOrigin = toRenderBox(containerObject)->layer()->perspectiveOrigin();
@@ -1731,8 +1741,8 @@ IntSize RenderObject::offsetFromContainer(RenderObject* o) const
IntRect RenderObject::localCaretRect(InlineBox*, int, int* extraWidthToEndOfLine)
{
- if (extraWidthToEndOfLine)
- *extraWidthToEndOfLine = 0;
+ if (extraWidthToEndOfLine)
+ *extraWidthToEndOfLine = 0;
return IntRect();
}
@@ -1815,7 +1825,7 @@ void RenderObject::destroy()
children->destroyLeftoverChildren();
// If this renderer is being autoscrolled, stop the autoscroll timer
- if (document()->frame() && document()->frame()->eventHandler()->autoscrollRenderer() == this)
+ if (document()->frame()->eventHandler()->autoscrollRenderer() == this)
document()->frame()->eventHandler()->stopAutoscrollTimer(true);
if (m_hasCounterNodeMap)
@@ -1973,6 +1983,27 @@ void RenderObject::layout()
setNeedsLayout(false);
}
+PassRefPtr<RenderStyle> RenderObject::uncachedFirstLineStyle(RenderStyle* style) const
+{
+ if (!document()->usesFirstLineRules())
+ return 0;
+
+ ASSERT(!isText());
+
+ RefPtr<RenderStyle> result;
+
+ if (isBlockFlow()) {
+ if (RenderBlock* firstLineBlock = this->firstLineBlock())
+ result = firstLineBlock->getUncachedPseudoStyle(FIRST_LINE, style, firstLineBlock == this ? style : 0);
+ } else if (!isAnonymous() && isRenderInline()) {
+ RenderStyle* parentStyle = parent()->firstLineStyle();
+ if (parentStyle != parent()->style())
+ result = getUncachedPseudoStyle(FIRST_LINE_INHERITED, parentStyle, style);
+ }
+
+ return result.release();
+}
+
RenderStyle* RenderObject::firstLineStyleSlowCase() const
{
ASSERT(document()->usesFirstLineRules());
@@ -2009,13 +2040,15 @@ RenderStyle* RenderObject::getCachedPseudoStyle(PseudoId pseudo, RenderStyle* pa
return 0;
}
-PassRefPtr<RenderStyle> RenderObject::getUncachedPseudoStyle(PseudoId pseudo, RenderStyle* parentStyle) const
+PassRefPtr<RenderStyle> RenderObject::getUncachedPseudoStyle(PseudoId pseudo, RenderStyle* parentStyle, RenderStyle* ownStyle) const
{
- if (pseudo < FIRST_INTERNAL_PSEUDOID && !style()->hasPseudoStyle(pseudo))
+ if (pseudo < FIRST_INTERNAL_PSEUDOID && !ownStyle && !style()->hasPseudoStyle(pseudo))
return 0;
- if (!parentStyle)
+ if (!parentStyle) {
+ ASSERT(!ownStyle);
parentStyle = style();
+ }
Node* n = node();
while (n && !n->isElementNode())
@@ -2210,10 +2243,12 @@ void RenderObject::adjustRectForOutlineAndShadow(IntRect& rect) const
int shadowBottom = 0;
do {
- shadowLeft = min(boxShadow->x - boxShadow->blur - outlineSize, shadowLeft);
- shadowRight = max(boxShadow->x + boxShadow->blur + outlineSize, shadowRight);
- shadowTop = min(boxShadow->y - boxShadow->blur - outlineSize, shadowTop);
- shadowBottom = max(boxShadow->y + boxShadow->blur + outlineSize, shadowBottom);
+ if (boxShadow->style == Normal) {
+ shadowLeft = min(boxShadow->x - boxShadow->blur - boxShadow->spread - outlineSize, shadowLeft);
+ shadowRight = max(boxShadow->x + boxShadow->blur + boxShadow->spread + outlineSize, shadowRight);
+ shadowTop = min(boxShadow->y - boxShadow->blur - boxShadow->spread - outlineSize, shadowTop);
+ shadowBottom = max(boxShadow->y + boxShadow->blur + boxShadow->spread + outlineSize, shadowBottom);
+ }
boxShadow = boxShadow->next;
} while (boxShadow);
diff --git a/WebCore/rendering/RenderObject.h b/WebCore/rendering/RenderObject.h
index 0901bff..911169d 100644
--- a/WebCore/rendering/RenderObject.h
+++ b/WebCore/rendering/RenderObject.h
@@ -48,6 +48,7 @@ class RenderInline;
class RenderBlock;
class RenderFlow;
class RenderLayer;
+class RenderTheme;
class TransformState;
class VisiblePosition;
@@ -137,6 +138,8 @@ public:
RenderObject(Node*);
virtual ~RenderObject();
+ RenderTheme* theme() const;
+
virtual const char* renderName() const = 0;
RenderObject* parent() const { return m_parent; }
@@ -273,6 +276,7 @@ public:
virtual bool isTextControl() const { return false; }
virtual bool isTextArea() const { return false; }
virtual bool isTextField() const { return false; }
+ virtual bool isVideo() const { return false; }
virtual bool isWidget() const { return false; }
bool isRoot() const { return document()->documentElement() == m_node; }
@@ -378,7 +382,7 @@ public:
// The pseudo element style can be cached or uncached. Use the cached method if the pseudo element doesn't respect
// any pseudo classes (and therefore has no concept of changing state).
RenderStyle* getCachedPseudoStyle(PseudoId, RenderStyle* parentStyle = 0) const;
- PassRefPtr<RenderStyle> getUncachedPseudoStyle(PseudoId, RenderStyle* parentStyle = 0) const;
+ PassRefPtr<RenderStyle> getUncachedPseudoStyle(PseudoId, RenderStyle* parentStyle = 0, RenderStyle* ownStyle = 0) const;
virtual void updateDragState(bool dragOn);
@@ -549,7 +553,11 @@ public:
RenderStyle* style() const { return m_style.get(); }
RenderStyle* firstLineStyle() const { return document()->usesFirstLineRules() ? firstLineStyleSlowCase() : style(); }
RenderStyle* style(bool firstLine) const { return firstLine ? firstLineStyle() : style(); }
-
+
+ // Used only by Element::pseudoStyleCacheIsInvalid to get a first line style based off of a
+ // given new style, without accessing the cache.
+ PassRefPtr<RenderStyle> uncachedFirstLineStyle(RenderStyle*) const;
+
// Anonymous blocks that are part of of a continuation chain will return their inline continuation's outline style instead.
// This is typically only relevant when repainting.
virtual RenderStyle* outlineStyleForRepaint() const { return style(); }
@@ -955,12 +963,14 @@ inline void RenderObject::markContainingBlocksForLayout(bool scheduleRelayout, R
last->scheduleRelayout();
}
-inline void makeMatrixRenderable(TransformationMatrix& matrix)
+inline void makeMatrixRenderable(TransformationMatrix& matrix, bool has3DRendering)
{
#if !ENABLE(3D_RENDERING)
+ UNUSED_PARAM(has3DRendering);
matrix.makeAffine();
#else
- UNUSED_PARAM(matrix);
+ if (!has3DRendering)
+ matrix.makeAffine();
#endif
}
diff --git a/WebCore/rendering/RenderObjectChildList.cpp b/WebCore/rendering/RenderObjectChildList.cpp
index 32e856f..23ab98f 100644
--- a/WebCore/rendering/RenderObjectChildList.cpp
+++ b/WebCore/rendering/RenderObjectChildList.cpp
@@ -41,13 +41,12 @@ namespace WebCore {
static void updateListMarkerNumbers(RenderObject* child)
{
- for (RenderObject* r = child; r; r = r->nextSibling()) {
- if (r->isListItem())
- static_cast<RenderListItem*>(r)->updateValue();
+ for (RenderObject* sibling = child; sibling; sibling = sibling->nextSibling()) {
+ if (sibling->isListItem())
+ toRenderListItem(sibling)->updateValue();
}
}
-
void RenderObjectChildList::destroyLeftoverChildren()
{
while (firstChild()) {
@@ -281,7 +280,7 @@ static void invalidateCountersInContainer(RenderObject* container)
return;
for (RenderObject* content = container->firstChild(); content; content = content->nextSibling()) {
if (content->isCounter())
- static_cast<RenderCounter*>(content)->invalidate();
+ toRenderCounter(content)->invalidate();
}
}
diff --git a/WebCore/rendering/RenderPart.cpp b/WebCore/rendering/RenderPart.cpp
index bcf9ef9..cb56c0c 100644
--- a/WebCore/rendering/RenderPart.cpp
+++ b/WebCore/rendering/RenderPart.cpp
@@ -41,13 +41,11 @@ RenderPart::~RenderPart()
clearWidget();
}
-void RenderPart::setWidget(Widget* widget)
+void RenderPart::setWidget(PassRefPtr<Widget> widget)
{
if (widget == this->widget())
return;
- if (widget && widget->isFrameView())
- static_cast<FrameView*>(widget)->ref();
RenderWidget::setWidget(widget);
// make sure the scrollbars are set correctly for restore
@@ -59,16 +57,4 @@ void RenderPart::viewCleared()
{
}
-void RenderPart::deleteWidget(Widget* widget)
-{
- // Since deref ends up calling setWidget back on us, need to make sure
- // that widget is already 0 so it won't do any work.
- ASSERT(!this->widget());
-
- if (widget && widget->isFrameView())
- static_cast<FrameView*>(widget)->deref();
- else
- delete widget;
-}
-
}
diff --git a/WebCore/rendering/RenderPart.h b/WebCore/rendering/RenderPart.h
index e47ead0..08abf99 100644
--- a/WebCore/rendering/RenderPart.h
+++ b/WebCore/rendering/RenderPart.h
@@ -34,7 +34,7 @@ public:
bool hasFallbackContent() const { return m_hasFallbackContent; }
- virtual void setWidget(Widget*);
+ virtual void setWidget(PassRefPtr<Widget>);
virtual void viewCleared();
protected:
@@ -43,10 +43,17 @@ protected:
private:
virtual bool isRenderPart() const { return true; }
virtual const char* renderName() const { return "RenderPart"; }
-
- virtual void deleteWidget(Widget*);
};
+inline RenderPart* toRenderPart(RenderObject* object)
+{
+ ASSERT(!object || object->isRenderPart());
+ return static_cast<RenderPart*>(object);
+}
+
+// This will catch anyone doing an unnecessary cast.
+void toRenderPart(const RenderPart*);
+
}
#endif
diff --git a/WebCore/rendering/RenderPartObject.cpp b/WebCore/rendering/RenderPartObject.cpp
index 0e7655b..5f6d903 100644
--- a/WebCore/rendering/RenderPartObject.cpp
+++ b/WebCore/rendering/RenderPartObject.cpp
@@ -72,7 +72,7 @@ static bool isURLAllowed(Document* doc, const String& url)
KURL completeURL = doc->completeURL(url);
bool foundSelfReference = false;
for (Frame* frame = doc->frame(); frame; frame = frame->tree()->parent()) {
- if (equalIgnoringRef(frame->loader()->url(), completeURL)) {
+ if (equalIgnoringFragmentIdentifier(frame->loader()->url(), completeURL)) {
if (foundSelfReference)
return false;
foundSelfReference = true;
@@ -142,6 +142,24 @@ static inline bool shouldUseEmbedDescendant(HTMLObjectElement* objectElement, co
#endif
}
+static void mapDataParamToSrc(Vector<String>* paramNames, Vector<String>* paramValues)
+{
+ // Some plugins don't understand the "data" attribute of the OBJECT tag (i.e. Real and WMP
+ // require "src" attribute).
+ int srcIndex = -1, dataIndex = -1;
+ for (unsigned int i = 0; i < paramNames->size(); ++i) {
+ if (equalIgnoringCase((*paramNames)[i], "src"))
+ srcIndex = i;
+ else if (equalIgnoringCase((*paramNames)[i], "data"))
+ dataIndex = i;
+ }
+
+ if (srcIndex == -1 && dataIndex != -1) {
+ paramNames->append("src");
+ paramValues->append((*paramValues)[dataIndex]);
+ }
+}
+
void RenderPartObject::updateWidget(bool onlyCreateNonNetscapePlugins)
{
String url;
@@ -238,6 +256,8 @@ void RenderPartObject::updateWidget(bool onlyCreateNonNetscapePlugins)
}
}
+ mapDataParamToSrc(&paramNames, &paramValues);
+
// If we still don't have a type, try to map from a specific CLASSID to a type.
if (serviceType.isEmpty())
serviceType = serviceTypeForClassId(o->classId(), pluginData);
diff --git a/WebCore/rendering/RenderPartObject.h b/WebCore/rendering/RenderPartObject.h
index 0370c9f..092395d 100644
--- a/WebCore/rendering/RenderPartObject.h
+++ b/WebCore/rendering/RenderPartObject.h
@@ -1,7 +1,7 @@
/*
* Copyright (C) 1999 Lars Knoll (knoll@kde.org)
* (C) 2000 Simon Hausmann <hausmann@kde.org>
- * Copyright (C) 2006, 2009 Apple Inc.
+ * Copyright (C) 2006, 2009 Apple Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -46,6 +46,15 @@ private:
virtual void viewCleared();
};
+inline RenderPartObject* toRenderPartObject(RenderObject* object)
+{
+ ASSERT(!object || !strcmp(object->renderName(), "RenderPartObject"));
+ return static_cast<RenderPartObject*>(object);
+}
+
+// This will catch anyone doing an unnecessary cast.
+void toRenderPartObject(const RenderPartObject*);
+
} // namespace WebCore
#endif // RenderPartObject_h
diff --git a/WebCore/rendering/RenderPath.h b/WebCore/rendering/RenderPath.h
index a4aefed..2ff179e 100644
--- a/WebCore/rendering/RenderPath.h
+++ b/WebCore/rendering/RenderPath.h
@@ -40,6 +40,9 @@ class RenderPath : public RenderSVGModelObject {
public:
RenderPath(SVGStyledTransformableElement*);
+ const Path& path() const;
+
+private:
// Hit-detection seperated for the fill and the stroke
bool fillContains(const FloatPoint&, bool requiresFill = true) const;
bool strokeContains(const FloatPoint&, bool requiresStroke = true) const;
@@ -49,7 +52,6 @@ public:
virtual TransformationMatrix localToParentTransform() const;
- const Path& path() const;
void setPath(const Path&);
virtual bool isRenderPath() const { return true; }
@@ -73,6 +75,21 @@ private:
TransformationMatrix m_localTransform;
};
+inline RenderPath* toRenderPath(RenderObject* object)
+{
+ ASSERT(!object || object->isRenderPath());
+ return static_cast<RenderPath*>(object);
+}
+
+inline const RenderPath* toRenderPath(const RenderObject* object)
+{
+ ASSERT(!object || object->isRenderPath());
+ return static_cast<const RenderPath*>(object);
+}
+
+// This will catch anyone doing an unnecessary cast.
+void toRenderPath(const RenderPath*);
+
}
#endif // ENABLE(SVG)
diff --git a/WebCore/rendering/RenderReplaced.cpp b/WebCore/rendering/RenderReplaced.cpp
index e61ac8e..692a66e 100644
--- a/WebCore/rendering/RenderReplaced.cpp
+++ b/WebCore/rendering/RenderReplaced.cpp
@@ -127,8 +127,7 @@ void RenderReplaced::paint(PaintInfo& paintInfo, int tx, int ty)
drawSelectionTint = false;
}
- bool clipToBorderRadius = style()->overflowX() != OVISIBLE && style()->hasBorderRadius();
- if (clipToBorderRadius) {
+ if (style()->hasBorderRadius()) {
// Push a clip if we have a border radius, since we want to round the foreground content that gets painted.
paintInfo.context->save();
@@ -141,7 +140,7 @@ void RenderReplaced::paint(PaintInfo& paintInfo, int tx, int ty)
paintReplaced(paintInfo, tx, ty);
- if (clipToBorderRadius)
+ if (style()->hasBorderRadius())
paintInfo.context->restore();
// The selection tint never gets clipped by border-radius rounding, since we want it to run right up to the edges of
@@ -332,9 +331,11 @@ void RenderReplaced::adjustOverflowForBoxShadowAndReflect()
{
IntRect overflow;
for (ShadowData* boxShadow = style()->boxShadow(); boxShadow; boxShadow = boxShadow->next) {
+ if (boxShadow->style == Inset)
+ continue;
IntRect shadow = borderBoxRect();
shadow.move(boxShadow->x, boxShadow->y);
- shadow.inflate(boxShadow->blur);
+ shadow.inflate(boxShadow->blur + boxShadow->spread);
overflow.unite(shadow);
}
diff --git a/WebCore/rendering/RenderReplaced.h b/WebCore/rendering/RenderReplaced.h
index 4937446..70ad4f2 100644
--- a/WebCore/rendering/RenderReplaced.h
+++ b/WebCore/rendering/RenderReplaced.h
@@ -1,6 +1,6 @@
/*
* Copyright (C) 1999 Lars Knoll (knoll@kde.org)
- * Copyright (C) 2004, 2005, 2006, 2007 Apple Inc.
+ * Copyright (C) 2004, 2005, 2006, 2007, 2009 Apple Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -32,6 +32,25 @@ public:
RenderReplaced(Node*, const IntSize& intrinsicSize);
virtual ~RenderReplaced();
+protected:
+ virtual void layout();
+
+ virtual IntSize intrinsicSize() const;
+
+ virtual void setSelectionState(SelectionState);
+
+ bool isSelected() const;
+
+ virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
+
+ void setIntrinsicSize(const IntSize&);
+ virtual void intrinsicSizeChanged();
+
+ bool shouldPaint(PaintInfo&, int& tx, int& ty);
+ void adjustOverflowForBoxShadowAndReflect();
+ IntRect localSelectionRect(bool checkWhetherSelected = true) const;
+
+private:
virtual const char* renderName() const { return "RenderReplaced"; }
virtual bool canHaveChildren() const { return false; }
@@ -40,15 +59,12 @@ public:
virtual int baselinePosition(bool firstLine, bool isRootLineBox = false) const;
virtual void calcPrefWidths();
-
- virtual void layout();
+
virtual int minimumReplacedHeight() const { return 0; }
virtual void paint(PaintInfo&, int tx, int ty);
virtual void paintReplaced(PaintInfo&, int /*tx*/, int /*ty*/) { }
- virtual IntSize intrinsicSize() const;
-
virtual int overflowHeight(bool includeInterior = true) const;
virtual int overflowWidth(bool includeInterior = true) const;
virtual int overflowLeft(bool includeInterior = true) const;
@@ -61,22 +77,9 @@ public:
virtual VisiblePosition positionForPoint(const IntPoint&);
virtual bool canBeSelectionLeaf() const { return true; }
- virtual void setSelectionState(SelectionState);
- virtual IntRect selectionRectForRepaint(RenderBoxModelObject* repaintContainer, bool clipToVisibleContent = true);
-
- bool isSelected() const;
-protected:
- virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
-
- void setIntrinsicSize(const IntSize&);
- virtual void intrinsicSizeChanged();
-
- bool shouldPaint(PaintInfo&, int& tx, int& ty);
- void adjustOverflowForBoxShadowAndReflect();
- IntRect localSelectionRect(bool checkWhetherSelected = true) const;
+ virtual IntRect selectionRectForRepaint(RenderBoxModelObject* repaintContainer, bool clipToVisibleContent = true);
-private:
IntSize m_intrinsicSize;
};
diff --git a/WebCore/rendering/RenderReplica.cpp b/WebCore/rendering/RenderReplica.cpp
index e805298..5fa3c62 100644
--- a/WebCore/rendering/RenderReplica.cpp
+++ b/WebCore/rendering/RenderReplica.cpp
@@ -72,9 +72,8 @@ void RenderReplica::paint(PaintInfo& paintInfo, int tx, int ty)
// computing using the wrong rootLayer
layer()->parent()->paintLayer(layer()->transform() ? layer()->parent() : layer()->enclosingTransformedAncestor(),
paintInfo.context, paintInfo.rect,
- true, PaintRestrictionNone, 0, 0,
- true, // appliedTransform
- true); // temporaryClipRects
+ PaintRestrictionNone, 0, 0,
+ RenderLayer::PaintLayerHaveTransparency | RenderLayer::PaintLayerAppliedTransform | RenderLayer::PaintLayerTemporaryClipRects | RenderLayer::PaintLayerPaintingReflection);
else if (paintInfo.phase == PaintPhaseMask)
paintMask(paintInfo, tx, ty);
}
diff --git a/WebCore/rendering/RenderSVGBlock.h b/WebCore/rendering/RenderSVGBlock.h
index f8afd0f..a4ececb 100644
--- a/WebCore/rendering/RenderSVGBlock.h
+++ b/WebCore/rendering/RenderSVGBlock.h
@@ -34,6 +34,8 @@ class SVGElement;
class RenderSVGBlock : public RenderBlock, protected SVGRenderBase {
public:
RenderSVGBlock(SVGElement*);
+
+private:
virtual void setStyle(PassRefPtr<RenderStyle>);
};
diff --git a/WebCore/rendering/RenderSVGContainer.cpp b/WebCore/rendering/RenderSVGContainer.cpp
index 8a77d2e..d7aec99 100644
--- a/WebCore/rendering/RenderSVGContainer.cpp
+++ b/WebCore/rendering/RenderSVGContainer.cpp
@@ -42,10 +42,6 @@ RenderSVGContainer::RenderSVGContainer(SVGStyledElement* node)
{
}
-RenderSVGContainer::~RenderSVGContainer()
-{
-}
-
bool RenderSVGContainer::drawsContents() const
{
return m_drawsContents;
diff --git a/WebCore/rendering/RenderSVGContainer.h b/WebCore/rendering/RenderSVGContainer.h
index 4bb7e44..f2195e3 100644
--- a/WebCore/rendering/RenderSVGContainer.h
+++ b/WebCore/rendering/RenderSVGContainer.h
@@ -2,6 +2,7 @@
Copyright (C) 2004, 2005, 2007 Nikolas Zimmermann <zimmermann@kde.org>
2004, 2005, 2007 Rob Buis <buis@kde.org>
Copyright (C) 2009 Google, Inc. All rights reserved.
+ Copyright (C) 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
@@ -33,10 +34,7 @@ class SVGElement;
class RenderSVGContainer : public RenderSVGModelObject {
public:
RenderSVGContainer(SVGStyledElement*);
- ~RenderSVGContainer();
- virtual RenderObjectChildList* virtualChildren() { return children(); }
- virtual const RenderObjectChildList* virtualChildren() const { return children(); }
const RenderObjectChildList* children() const { return &m_children; }
RenderObjectChildList* children() { return &m_children; }
@@ -44,11 +42,18 @@ public:
void setDrawsContents(bool);
bool drawsContents() const;
+protected:
+ virtual void paint(PaintInfo&, int parentX, int parentY);
+
+private:
+ virtual RenderObjectChildList* virtualChildren() { return children(); }
+ virtual const RenderObjectChildList* virtualChildren() const { return children(); }
+
virtual bool isSVGContainer() const { return true; }
virtual const char* renderName() const { return "RenderSVGContainer"; }
virtual void layout();
- virtual void paint(PaintInfo&, int parentX, int parentY);
+
virtual void addFocusRingRects(GraphicsContext*, int tx, int ty);
virtual FloatRect objectBoundingBox() const;
@@ -56,7 +61,6 @@ public:
virtual bool nodeAtFloatPoint(const HitTestRequest&, HitTestResult&, const FloatPoint& pointInParent, HitTestAction);
-protected:
// Allow RenderSVGTransformableContainer to hook in at the right time in layout()
virtual void calculateLocalTransform() { }
@@ -65,13 +69,29 @@ protected:
virtual void applyViewportClip(PaintInfo&) { }
virtual bool pointIsInsideViewportClip(const FloatPoint& /*pointInParent*/) { return true; }
-private:
bool selfWillPaint() const;
RenderObjectChildList m_children;
bool m_drawsContents : 1;
};
+inline RenderSVGContainer* toRenderSVGContainer(RenderObject* object)
+{
+ // Note: isSVGContainer is also true for RenderSVGViewportContainer, which is not derived from this.
+ ASSERT(!object || object->isSVGContainer() && strcmp(object->renderName(), "RenderSVGViewportContainer"));
+ return static_cast<RenderSVGContainer*>(object);
+}
+
+inline const RenderSVGContainer* toRenderSVGContainer(const RenderObject* object)
+{
+ // Note: isSVGContainer is also true for RenderSVGViewportContainer, which is not derived from this.
+ ASSERT(!object || object->isSVGContainer() && strcmp(object->renderName(), "RenderSVGViewportContainer"));
+ return static_cast<const RenderSVGContainer*>(object);
+}
+
+// This will catch anyone doing an unnecessary cast.
+void toRenderSVGContainer(const RenderSVGContainer*);
+
} // namespace WebCore
#endif // ENABLE(SVG)
diff --git a/WebCore/rendering/RenderSVGHiddenContainer.cpp b/WebCore/rendering/RenderSVGHiddenContainer.cpp
index f08c008..d4b39d3 100644
--- a/WebCore/rendering/RenderSVGHiddenContainer.cpp
+++ b/WebCore/rendering/RenderSVGHiddenContainer.cpp
@@ -35,10 +35,6 @@ RenderSVGHiddenContainer::RenderSVGHiddenContainer(SVGStyledElement* element)
{
}
-RenderSVGHiddenContainer::~RenderSVGHiddenContainer()
-{
-}
-
void RenderSVGHiddenContainer::layout()
{
ASSERT(needsLayout());
diff --git a/WebCore/rendering/RenderSVGHiddenContainer.h b/WebCore/rendering/RenderSVGHiddenContainer.h
index 5a208d0..0ef0a43 100644
--- a/WebCore/rendering/RenderSVGHiddenContainer.h
+++ b/WebCore/rendering/RenderSVGHiddenContainer.h
@@ -36,9 +36,8 @@ namespace WebCore {
class RenderSVGHiddenContainer : public RenderSVGContainer {
public:
RenderSVGHiddenContainer(SVGStyledElement*);
- virtual ~RenderSVGHiddenContainer();
- virtual bool isSVGContainer() const { return true; }
+ private:
virtual bool isSVGHiddenContainer() const { return true; }
virtual const char* renderName() const { return "RenderSVGHiddenContainer"; }
diff --git a/WebCore/rendering/RenderSVGImage.cpp b/WebCore/rendering/RenderSVGImage.cpp
index b38352e..7e0b40d 100644
--- a/WebCore/rendering/RenderSVGImage.cpp
+++ b/WebCore/rendering/RenderSVGImage.cpp
@@ -2,7 +2,7 @@
Copyright (C) 2006 Alexander Kellett <lypanov@kde.org>
Copyright (C) 2006 Apple Computer, Inc.
Copyright (C) 2007 Nikolas Zimmermann <zimmermann@kde.org>
- Copyright (C) 2007, 2008 Rob Buis <buis@kde.org>
+ Copyright (C) 2007, 2008, 2009 Rob Buis <buis@kde.org>
Copyright (C) 2009, Google, Inc.
This library is free software; you can redistribute it and/or
@@ -47,10 +47,6 @@ RenderSVGImage::RenderSVGImage(SVGImageElement* impl)
{
}
-RenderSVGImage::~RenderSVGImage()
-{
-}
-
void RenderSVGImage::adjustRectsForAspectRatio(FloatRect& destRect, FloatRect& srcRect, SVGPreserveAspectRatio* aspectRatio)
{
float origDestWidth = destRect.width();
@@ -59,7 +55,7 @@ void RenderSVGImage::adjustRectsForAspectRatio(FloatRect& destRect, FloatRect& s
float widthToHeightMultiplier = srcRect.height() / srcRect.width();
if (origDestHeight > (origDestWidth * widthToHeightMultiplier)) {
destRect.setHeight(origDestWidth * widthToHeightMultiplier);
- switch(aspectRatio->align()) {
+ switch (aspectRatio->align()) {
case SVGPreserveAspectRatio::SVG_PRESERVEASPECTRATIO_XMINYMID:
case SVGPreserveAspectRatio::SVG_PRESERVEASPECTRATIO_XMIDYMID:
case SVGPreserveAspectRatio::SVG_PRESERVEASPECTRATIO_XMAXYMID:
@@ -74,7 +70,7 @@ void RenderSVGImage::adjustRectsForAspectRatio(FloatRect& destRect, FloatRect& s
}
if (origDestWidth > (origDestHeight / widthToHeightMultiplier)) {
destRect.setWidth(origDestHeight / widthToHeightMultiplier);
- switch(aspectRatio->align()) {
+ switch (aspectRatio->align()) {
case SVGPreserveAspectRatio::SVG_PRESERVEASPECTRATIO_XMIDYMIN:
case SVGPreserveAspectRatio::SVG_PRESERVEASPECTRATIO_XMIDYMID:
case SVGPreserveAspectRatio::SVG_PRESERVEASPECTRATIO_XMIDYMAX:
@@ -93,7 +89,7 @@ void RenderSVGImage::adjustRectsForAspectRatio(FloatRect& destRect, FloatRect& s
if (origDestHeight < (origDestWidth * widthToHeightMultiplier)) {
float destToSrcMultiplier = srcRect.width() / destRect.width();
srcRect.setHeight(destRect.height() * destToSrcMultiplier);
- switch(aspectRatio->align()) {
+ switch (aspectRatio->align()) {
case SVGPreserveAspectRatio::SVG_PRESERVEASPECTRATIO_XMINYMID:
case SVGPreserveAspectRatio::SVG_PRESERVEASPECTRATIO_XMIDYMID:
case SVGPreserveAspectRatio::SVG_PRESERVEASPECTRATIO_XMAXYMID:
@@ -110,7 +106,7 @@ void RenderSVGImage::adjustRectsForAspectRatio(FloatRect& destRect, FloatRect& s
if (origDestWidth < (origDestHeight / widthToHeightMultiplier)) {
float destToSrcMultiplier = srcRect.height() / destRect.height();
srcRect.setWidth(destRect.width() * destToSrcMultiplier);
- switch(aspectRatio->align()) {
+ switch (aspectRatio->align()) {
case SVGPreserveAspectRatio::SVG_PRESERVEASPECTRATIO_XMIDYMIN:
case SVGPreserveAspectRatio::SVG_PRESERVEASPECTRATIO_XMIDYMID:
case SVGPreserveAspectRatio::SVG_PRESERVEASPECTRATIO_XMIDYMAX:
@@ -227,9 +223,7 @@ FloatRect RenderSVGImage::repaintRectInLocalCoordinates() const
void RenderSVGImage::imageChanged(WrappedImagePtr image, const IntRect* rect)
{
RenderImage::imageChanged(image, rect);
-
- // We override to invalidate a larger rect, since SVG images can draw outside their "bounds"
- repaintRectangle(absoluteClippedOverflowRect()); // FIXME: Isn't this just repaint()?
+ repaint();
}
IntRect RenderSVGImage::clippedOverflowRectForRepaint(RenderBoxModelObject* repaintContainer)
diff --git a/WebCore/rendering/RenderSVGImage.h b/WebCore/rendering/RenderSVGImage.h
index 01b8b65..ef11719 100644
--- a/WebCore/rendering/RenderSVGImage.h
+++ b/WebCore/rendering/RenderSVGImage.h
@@ -1,6 +1,6 @@
/*
Copyright (C) 2006 Alexander Kellett <lypanov@kde.org>
- Copyright (C) 2006 Apple Computer, Inc.
+ Copyright (C) 2006, 2009 Apple Inc. All rights reserved.
Copyright (C) 2007 Rob Buis <buis@kde.org>
Copyright (C) 2009 Google, Inc.
@@ -38,8 +38,8 @@ namespace WebCore {
class RenderSVGImage : public RenderImage, SVGRenderBase {
public:
RenderSVGImage(SVGImageElement*);
- virtual ~RenderSVGImage();
+ private:
virtual const char* renderName() const { return "RenderSVGImage"; }
virtual bool isSVGImage() const { return true; }
@@ -63,12 +63,11 @@ namespace WebCore {
virtual void layout();
virtual void paint(PaintInfo&, int parentX, int parentY);
- bool requiresLayer() const { return false; }
+ virtual bool requiresLayer() const { return false; }
virtual bool nodeAtFloatPoint(const HitTestRequest&, HitTestResult&, const FloatPoint& pointInParent, HitTestAction);
- virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, int _x, int _y, int _tx, int _ty, HitTestAction);
+ virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, int x, int y, int tx, int ty, HitTestAction);
- private:
virtual TransformationMatrix localTransform() const { return m_localTransform; }
TransformationMatrix m_localTransform;
diff --git a/WebCore/rendering/RenderSVGInline.cpp b/WebCore/rendering/RenderSVGInline.cpp
index 3c44dd8..cf97b52 100644
--- a/WebCore/rendering/RenderSVGInline.cpp
+++ b/WebCore/rendering/RenderSVGInline.cpp
@@ -39,10 +39,10 @@ RenderSVGInline::RenderSVGInline(Node* n)
{
}
-InlineFlowBox* RenderSVGInline::createFlowBox()
+InlineFlowBox* RenderSVGInline::createInlineFlowBox()
{
InlineFlowBox* box = new (renderArena()) SVGInlineFlowBox(this);
- box->setIsSVG(true);
+ box->setHasVirtualHeight();
return box;
}
diff --git a/WebCore/rendering/RenderSVGInline.h b/WebCore/rendering/RenderSVGInline.h
index 1ff8d02..9f9f3f5 100644
--- a/WebCore/rendering/RenderSVGInline.h
+++ b/WebCore/rendering/RenderSVGInline.h
@@ -40,7 +40,7 @@ public:
virtual void absoluteQuads(Vector<FloatQuad>&);
private:
- virtual InlineFlowBox* createFlowBox();
+ virtual InlineFlowBox* createInlineFlowBox();
};
}
diff --git a/WebCore/rendering/RenderSVGInlineText.cpp b/WebCore/rendering/RenderSVGInlineText.cpp
index b1a21d7..48d01ae 100644
--- a/WebCore/rendering/RenderSVGInlineText.cpp
+++ b/WebCore/rendering/RenderSVGInlineText.cpp
@@ -134,7 +134,7 @@ FloatQuad RenderSVGInlineText::computeRepaintQuadForRange(RenderBoxModelObject*
InlineTextBox* RenderSVGInlineText::createTextBox()
{
InlineTextBox* box = new (renderArena()) SVGInlineTextBox(this);
- box->setIsSVG(true);
+ box->setHasVirtualHeight();
return box;
}
diff --git a/WebCore/rendering/RenderSVGInlineText.h b/WebCore/rendering/RenderSVGInlineText.h
index c4a096d..e9c5d6e 100644
--- a/WebCore/rendering/RenderSVGInlineText.h
+++ b/WebCore/rendering/RenderSVGInlineText.h
@@ -33,6 +33,8 @@ namespace WebCore {
class RenderSVGInlineText : public RenderText {
public:
RenderSVGInlineText(Node*, PassRefPtr<StringImpl>);
+
+private:
virtual const char* renderName() const { return "RenderSVGInlineText"; }
virtual void styleDidChange(StyleDifference, const RenderStyle*);
@@ -49,7 +51,6 @@ public:
virtual void destroy();
-private:
virtual InlineTextBox* createTextBox();
IntRect computeRepaintRectForRange(RenderBoxModelObject* repaintContainer, int startPos, int endPos);
FloatQuad computeRepaintQuadForRange(RenderBoxModelObject* repaintContainer, int startPos, int endPos);
diff --git a/WebCore/rendering/RenderSVGRoot.cpp b/WebCore/rendering/RenderSVGRoot.cpp
index 80c29dd..0a39bf4 100644
--- a/WebCore/rendering/RenderSVGRoot.cpp
+++ b/WebCore/rendering/RenderSVGRoot.cpp
@@ -48,10 +48,6 @@ RenderSVGRoot::RenderSVGRoot(SVGStyledElement* node)
setReplaced(true);
}
-RenderSVGRoot::~RenderSVGRoot()
-{
-}
-
int RenderSVGRoot::lineHeight(bool, bool) const
{
return height() + marginTop() + marginBottom();
diff --git a/WebCore/rendering/RenderSVGRoot.h b/WebCore/rendering/RenderSVGRoot.h
index 50866d2..08c3058 100644
--- a/WebCore/rendering/RenderSVGRoot.h
+++ b/WebCore/rendering/RenderSVGRoot.h
@@ -2,6 +2,7 @@
Copyright (C) 2004, 2005, 2007 Nikolas Zimmermann <zimmermann@kde.org>
2004, 2005, 2007 Rob Buis <buis@kde.org>
Copyright (C) 2009 Google, Inc. All rights reserved.
+ Copyright (C) 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
@@ -35,13 +36,14 @@ class TransformationMatrix;
class RenderSVGRoot : public RenderBox, SVGRenderBase {
public:
RenderSVGRoot(SVGStyledElement*);
- ~RenderSVGRoot();
- virtual RenderObjectChildList* virtualChildren() { return children(); }
- virtual const RenderObjectChildList* virtualChildren() const { return children(); }
const RenderObjectChildList* children() const { return &m_children; }
RenderObjectChildList* children() { return &m_children; }
+private:
+ virtual RenderObjectChildList* virtualChildren() { return children(); }
+ virtual const RenderObjectChildList* virtualChildren() const { return children(); }
+
virtual bool isSVGRoot() const { return true; }
virtual const char* renderName() const { return "RenderSVGRoot"; }
@@ -70,7 +72,6 @@ public:
virtual void mapLocalToContainer(RenderBoxModelObject* repaintContainer, bool useTransforms, bool fixed, TransformState&) const;
-private:
void calcViewport();
const FloatSize& viewportSize() const;
@@ -85,6 +86,21 @@ private:
FloatSize m_viewportSize;
};
+inline RenderSVGRoot* toRenderSVGRoot(RenderObject* object)
+{
+ ASSERT(!object || object->isSVGRoot());
+ return static_cast<RenderSVGRoot*>(object);
+}
+
+inline const RenderSVGRoot* toRenderSVGRoot(const RenderObject* object)
+{
+ ASSERT(!object || object->isSVGRoot());
+ return static_cast<const RenderSVGRoot*>(object);
+}
+
+// This will catch anyone doing an unnecessary cast.
+void toRenderSVGRoot(const RenderSVGRoot*);
+
} // namespace WebCore
#endif // ENABLE(SVG)
diff --git a/WebCore/rendering/RenderSVGText.cpp b/WebCore/rendering/RenderSVGText.cpp
index 9e9809d..3919d7f 100644
--- a/WebCore/rendering/RenderSVGText.cpp
+++ b/WebCore/rendering/RenderSVGText.cpp
@@ -89,10 +89,10 @@ void RenderSVGText::layout()
setNeedsLayout(false);
}
-RootInlineBox* RenderSVGText::createRootBox()
+RootInlineBox* RenderSVGText::createRootInlineBox()
{
RootInlineBox* box = new (renderArena()) SVGRootInlineBox(this);
- box->setIsSVG(true);
+ box->setHasVirtualHeight();
return box;
}
diff --git a/WebCore/rendering/RenderSVGText.h b/WebCore/rendering/RenderSVGText.h
index c1f1430..9a2770b 100644
--- a/WebCore/rendering/RenderSVGText.h
+++ b/WebCore/rendering/RenderSVGText.h
@@ -37,6 +37,7 @@ class RenderSVGText : public RenderSVGBlock {
public:
RenderSVGText(SVGTextElement* node);
+private:
virtual const char* renderName() const { return "RenderSVGText"; }
virtual bool isSVGText() const { return true; }
@@ -61,11 +62,10 @@ public:
virtual FloatRect objectBoundingBox() const;
virtual FloatRect repaintRectInLocalCoordinates() const;
-private:
// FIXME: This can be removed when localTransform() is removed from RenderObject
virtual TransformationMatrix localTransform() const { return m_localTransform; }
- virtual RootInlineBox* createRootBox();
+ virtual RootInlineBox* createRootInlineBox();
TransformationMatrix m_localTransform;
};
diff --git a/WebCore/rendering/RenderSVGTextPath.h b/WebCore/rendering/RenderSVGTextPath.h
index efab659..8e6ff42 100644
--- a/WebCore/rendering/RenderSVGTextPath.h
+++ b/WebCore/rendering/RenderSVGTextPath.h
@@ -2,6 +2,7 @@
* This file is part of the WebKit project.
*
* Copyright (C) 2007 Nikolas Zimmermann <zimmermann@kde.org>
+ * Copyright (C) 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
@@ -37,9 +38,9 @@ namespace WebCore {
bool exactAlignment() const;
bool stretchMethod() const;
+ private:
virtual const char* renderName() const { return "RenderSVGTextPath"; }
- private:
float m_startOffset;
bool m_exactAlignment : 1;
@@ -47,6 +48,16 @@ namespace WebCore {
Path m_layoutPath;
};
+
+ inline RenderSVGTextPath* toRenderSVGTextPath(RenderObject* object)
+ {
+ ASSERT(!object || !strcmp(object->renderName(), "RenderSVGTextPath"));
+ return static_cast<RenderSVGTextPath*>(object);
+ }
+
+ // This will catch anyone doing an unnecessary cast.
+ void toRenderSVGTextPath(const RenderSVGTextPath*);
+
}
#endif // ENABLE(SVG)
diff --git a/WebCore/rendering/RenderSVGViewportContainer.cpp b/WebCore/rendering/RenderSVGViewportContainer.cpp
index d208621..a432ef3 100644
--- a/WebCore/rendering/RenderSVGViewportContainer.cpp
+++ b/WebCore/rendering/RenderSVGViewportContainer.cpp
@@ -38,14 +38,14 @@ RenderSVGViewportContainer::RenderSVGViewportContainer(SVGStyledElement* node)
{
}
-RenderSVGViewportContainer::~RenderSVGViewportContainer()
-{
-}
-
void RenderSVGViewportContainer::paint(PaintInfo& paintInfo, int parentX, int parentY)
{
+ // FIXME: The if statement here evaluates to false. isEmpty() is exactly the same
+ // as what is on the right side, so it's basically !isEmpty && isEmpty. So this
+ // function does nothing.
+
// A value of zero disables rendering of the element.
- if (!viewport().isEmpty() && (viewport().width() <= 0. || viewport().height() <= 0.))
+ if (!m_viewport.isEmpty() && (m_viewport.width() <= 0. || m_viewport.height() <= 0.))
return;
RenderSVGContainer::paint(paintInfo, parentX, parentY);
@@ -54,12 +54,7 @@ void RenderSVGViewportContainer::paint(PaintInfo& paintInfo, int parentX, int pa
void RenderSVGViewportContainer::applyViewportClip(PaintInfo& paintInfo)
{
if (style()->overflowX() != OVISIBLE)
- paintInfo.context->clip(enclosingIntRect(viewport())); // FIXME: Eventually we'll want float-precision clipping
-}
-
-FloatRect RenderSVGViewportContainer::viewport() const
-{
- return m_viewport;
+ paintInfo.context->clip(enclosingIntRect(m_viewport)); // FIXME: Eventually we'll want float-precision clipping
}
void RenderSVGViewportContainer::calcViewport()
@@ -91,10 +86,10 @@ TransformationMatrix RenderSVGViewportContainer::viewportTransform() const
{
if (node()->hasTagName(SVGNames::svgTag)) {
SVGSVGElement* svg = static_cast<SVGSVGElement*>(node());
- return svg->viewBoxToViewTransform(viewport().width(), viewport().height());
+ return svg->viewBoxToViewTransform(m_viewport.width(), m_viewport.height());
} else if (node()->hasTagName(SVGNames::markerTag)) {
SVGMarkerElement* marker = static_cast<SVGMarkerElement*>(node());
- return marker->viewBoxToViewTransform(viewport().width(), viewport().height());
+ return marker->viewBoxToViewTransform(m_viewport.width(), m_viewport.height());
}
return TransformationMatrix();
@@ -103,7 +98,7 @@ TransformationMatrix RenderSVGViewportContainer::viewportTransform() const
TransformationMatrix RenderSVGViewportContainer::localToParentTransform() const
{
TransformationMatrix viewportTranslation;
- viewportTranslation.translate(viewport().x(), viewport().y());
+ viewportTranslation.translate(m_viewport.x(), m_viewport.y());
return viewportTransform() * viewportTranslation;
// If this class were ever given a localTransform(), then the above would read:
// return viewportTransform() * localTransform() * viewportTranslation;
@@ -121,7 +116,7 @@ bool RenderSVGViewportContainer::pointIsInsideViewportClip(const FloatPoint& poi
// Respect the viewport clip (which is in parent coords). SVG does not support separate x/y overflow rules.
if (style()->overflowX() == OHIDDEN) {
ASSERT(style()->overflowY() == OHIDDEN);
- if (!viewport().contains(pointInParent))
+ if (!m_viewport.contains(pointInParent))
return false;
}
return true;
diff --git a/WebCore/rendering/RenderSVGViewportContainer.h b/WebCore/rendering/RenderSVGViewportContainer.h
index 8657af4..b8b30b5 100644
--- a/WebCore/rendering/RenderSVGViewportContainer.h
+++ b/WebCore/rendering/RenderSVGViewportContainer.h
@@ -2,6 +2,7 @@
Copyright (C) 2004, 2005, 2007 Nikolas Zimmermann <zimmermann@kde.org>
2004, 2005, 2007 Rob Buis <buis@kde.org>
2009 Google, Inc.
+ Copyright (C) 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
@@ -33,24 +34,21 @@ namespace WebCore {
class RenderSVGViewportContainer : public RenderSVGContainer {
public:
RenderSVGViewportContainer(SVGStyledElement*);
- ~RenderSVGViewportContainer();
- virtual bool isSVGContainer() const { return true; }
- virtual const char* renderName() const { return "RenderSVGViewportContainer"; }
+ // FIXME: This is only public for SVGResourceMarker::draw, likely the callsite should be changed.
+ TransformationMatrix viewportTransform() const;
virtual void paint(PaintInfo&, int parentX, int parentY);
+private:
+ virtual bool isSVGContainer() const { return true; }
+ virtual const char* renderName() const { return "RenderSVGViewportContainer"; }
+
virtual TransformationMatrix localToParentTransform() const;
// FIXME: This override should be removed once callers of RenderBox::absoluteTransform() can be removed.
virtual TransformationMatrix absoluteTransform() const;
- FloatRect viewport() const;
-
- // FIXME: This is only public for SVGResourceMarker::draw, likely the callsite should be changed.
- TransformationMatrix viewportTransform() const;
-
-private:
virtual void calcViewport();
virtual void applyViewportClip(PaintInfo&);
@@ -59,6 +57,15 @@ private:
FloatRect m_viewport;
};
+inline RenderSVGViewportContainer* toRenderSVGViewportContainer(RenderObject* object)
+{
+ ASSERT(!object || !strcmp(object->renderName(), "RenderSVGViewportContainer"));
+ return static_cast<RenderSVGViewportContainer*>(object);
+}
+
+// This will catch anyone doing an unnecessary cast.
+void toRenderSVGViewportContainer(const RenderSVGViewportContainer*);
+
} // namespace WebCore
#endif // ENABLE(SVG)
diff --git a/WebCore/rendering/RenderScrollbar.cpp b/WebCore/rendering/RenderScrollbar.cpp
index db24a06..b3c5369 100644
--- a/WebCore/rendering/RenderScrollbar.cpp
+++ b/WebCore/rendering/RenderScrollbar.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ * Copyright (C) 2008, 2009 Apple Inc. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -25,6 +25,7 @@
#include "config.h"
#include "RenderScrollbar.h"
+
#include "RenderScrollbarPart.h"
#include "RenderScrollbarTheme.h"
@@ -173,9 +174,14 @@ static PseudoId pseudoForScrollbarPart(ScrollbarPart part)
return SCROLLBAR_THUMB;
case TrackBGPart:
return SCROLLBAR_TRACK;
- default:
+ case ScrollbarBGPart:
return SCROLLBAR;
+ case NoPart:
+ case AllParts:
+ break;
}
+ ASSERT_NOT_REACHED();
+ return SCROLLBAR;
}
void RenderScrollbar::updateScrollbarPart(ScrollbarPart partType, bool destroy)
diff --git a/WebCore/rendering/RenderScrollbar.h b/WebCore/rendering/RenderScrollbar.h
index 524c4e8..b3c00ef 100644
--- a/WebCore/rendering/RenderScrollbar.h
+++ b/WebCore/rendering/RenderScrollbar.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ * Copyright (C) 2008, 2009 Apple Inc. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -33,7 +33,6 @@
namespace WebCore {
class RenderBox;
-class RenderStyle;
class RenderScrollbarPart;
class RenderStyle;
@@ -46,21 +45,9 @@ public:
static PassRefPtr<Scrollbar> createCustomScrollbar(ScrollbarClient*, ScrollbarOrientation, RenderBox*);
virtual ~RenderScrollbar();
- virtual void setParent(ScrollView*);
- virtual void setEnabled(bool);
-
- virtual void paint(GraphicsContext*, const IntRect& damageRect);
-
- virtual void setHoveredPart(ScrollbarPart);
- virtual void setPressedPart(ScrollbarPart);
-
- void updateScrollbarParts(bool destroy = false);
-
static ScrollbarPart partForStyleResolve();
static RenderScrollbar* scrollbarForStyleResolve();
- virtual void styleChanged();
-
RenderBox* owningRenderer() const { return m_owner; }
void paintPart(GraphicsContext*, ScrollbarPart, const IntRect&);
@@ -72,6 +59,20 @@ public:
int minimumThumbLength();
private:
+ virtual void setParent(ScrollView*);
+ virtual void setEnabled(bool);
+
+ virtual void paint(GraphicsContext*, const IntRect& damageRect);
+
+ virtual void setHoveredPart(ScrollbarPart);
+ virtual void setPressedPart(ScrollbarPart);
+
+ virtual void styleChanged();
+
+ virtual bool isCustomScrollbar() const { return true; }
+
+ void updateScrollbarParts(bool destroy = false);
+
PassRefPtr<RenderStyle> getScrollbarPseudoStyle(ScrollbarPart, PseudoId);
void updateScrollbarPart(ScrollbarPart, bool destroy = false);
@@ -79,6 +80,15 @@ private:
HashMap<unsigned, RenderScrollbarPart*> m_parts;
};
+inline RenderScrollbar* toRenderScrollbar(Scrollbar* scrollbar)
+{
+ ASSERT(!scrollbar || scrollbar->isCustomScrollbar());
+ return static_cast<RenderScrollbar*>(scrollbar);
+}
+
+// This will catch anyone doing an unnecessary cast.
+void toRenderScrollbar(const RenderScrollbar*);
+
} // namespace WebCore
#endif // RenderScrollbar_h
diff --git a/WebCore/rendering/RenderScrollbarTheme.cpp b/WebCore/rendering/RenderScrollbarTheme.cpp
index d7cfb2b..06ca32a 100644
--- a/WebCore/rendering/RenderScrollbarTheme.cpp
+++ b/WebCore/rendering/RenderScrollbarTheme.cpp
@@ -66,17 +66,17 @@ bool RenderScrollbarTheme::hasThumb(Scrollbar* scrollbar)
int RenderScrollbarTheme::minimumThumbLength(Scrollbar* scrollbar)
{
- return static_cast<RenderScrollbar*>(scrollbar)->minimumThumbLength();
+ return toRenderScrollbar(scrollbar)->minimumThumbLength();
}
IntRect RenderScrollbarTheme::backButtonRect(Scrollbar* scrollbar, ScrollbarPart partType, bool)
{
- return static_cast<RenderScrollbar*>(scrollbar)->buttonRect(partType);
+ return toRenderScrollbar(scrollbar)->buttonRect(partType);
}
IntRect RenderScrollbarTheme::forwardButtonRect(Scrollbar* scrollbar, ScrollbarPart partType, bool)
{
- return static_cast<RenderScrollbar*>(scrollbar)->buttonRect(partType);
+ return toRenderScrollbar(scrollbar)->buttonRect(partType);
}
IntRect RenderScrollbarTheme::trackRect(Scrollbar* scrollbar, bool)
@@ -88,13 +88,13 @@ IntRect RenderScrollbarTheme::trackRect(Scrollbar* scrollbar, bool)
int endLength;
buttonSizesAlongTrackAxis(scrollbar, startLength, endLength);
- return static_cast<RenderScrollbar*>(scrollbar)->trackRect(startLength, endLength);
+ return toRenderScrollbar(scrollbar)->trackRect(startLength, endLength);
}
IntRect RenderScrollbarTheme::constrainTrackRectToTrackPieces(Scrollbar* scrollbar, const IntRect& rect)
{
- IntRect backRect = static_cast<RenderScrollbar*>(scrollbar)->trackPieceRectWithMargins(BackTrackPart, rect);
- IntRect forwardRect = static_cast<RenderScrollbar*>(scrollbar)->trackPieceRectWithMargins(ForwardTrackPart, rect);
+ IntRect backRect = toRenderScrollbar(scrollbar)->trackPieceRectWithMargins(BackTrackPart, rect);
+ IntRect forwardRect = toRenderScrollbar(scrollbar)->trackPieceRectWithMargins(ForwardTrackPart, rect);
IntRect result = rect;
if (scrollbar->orientation() == HorizontalScrollbar) {
result.setX(backRect.x());
@@ -114,27 +114,27 @@ void RenderScrollbarTheme::paintScrollCorner(ScrollView*, GraphicsContext* conte
void RenderScrollbarTheme::paintScrollbarBackground(GraphicsContext* context, Scrollbar* scrollbar)
{
- static_cast<RenderScrollbar*>(scrollbar)->paintPart(context, ScrollbarBGPart, scrollbar->frameRect());
+ toRenderScrollbar(scrollbar)->paintPart(context, ScrollbarBGPart, scrollbar->frameRect());
}
void RenderScrollbarTheme::paintTrackBackground(GraphicsContext* context, Scrollbar* scrollbar, const IntRect& rect)
{
- static_cast<RenderScrollbar*>(scrollbar)->paintPart(context, TrackBGPart, rect);
+ toRenderScrollbar(scrollbar)->paintPart(context, TrackBGPart, rect);
}
void RenderScrollbarTheme::paintTrackPiece(GraphicsContext* context, Scrollbar* scrollbar, const IntRect& rect, ScrollbarPart part)
{
- static_cast<RenderScrollbar*>(scrollbar)->paintPart(context, part, rect);
+ toRenderScrollbar(scrollbar)->paintPart(context, part, rect);
}
void RenderScrollbarTheme::paintButton(GraphicsContext* context, Scrollbar* scrollbar, const IntRect& rect, ScrollbarPart part)
{
- static_cast<RenderScrollbar*>(scrollbar)->paintPart(context, part, rect);
+ toRenderScrollbar(scrollbar)->paintPart(context, part, rect);
}
void RenderScrollbarTheme::paintThumb(GraphicsContext* context, Scrollbar* scrollbar, const IntRect& rect)
{
- static_cast<RenderScrollbar*>(scrollbar)->paintPart(context, ThumbPart, rect);
+ toRenderScrollbar(scrollbar)->paintPart(context, ThumbPart, rect);
}
}
diff --git a/WebCore/rendering/RenderSlider.cpp b/WebCore/rendering/RenderSlider.cpp
index f1e35e5..8a19d97 100644
--- a/WebCore/rendering/RenderSlider.cpp
+++ b/WebCore/rendering/RenderSlider.cpp
@@ -125,47 +125,57 @@ public:
bool inDragMode() const { return m_inDragMode; }
virtual void defaultEventHandler(Event*);
+ virtual void detach();
private:
virtual bool isShadowNode() const { return true; }
virtual Node* shadowParentNode() { return m_shadowParent; }
+ FloatPoint m_offsetToThumb;
Node* m_shadowParent;
- FloatPoint m_initialClickPoint; // initial click point in RenderSlider-local coordinates
- int m_initialPosition;
bool m_inDragMode;
};
SliderThumbElement::SliderThumbElement(Document* document, Node* shadowParent)
: HTMLDivElement(divTag, document)
, m_shadowParent(shadowParent)
- , m_initialPosition(0)
, m_inDragMode(false)
{
}
void SliderThumbElement::defaultEventHandler(Event* event)
{
+ if (!event->isMouseEvent()) {
+ HTMLDivElement::defaultEventHandler(event);
+ return;
+ }
+
+ MouseEvent* mouseEvent = static_cast<MouseEvent*>(event);
+ bool isLeftButton = mouseEvent->button() == LeftButton;
const AtomicString& eventType = event->type();
- if (eventType == eventNames().mousedownEvent && event->isMouseEvent() && static_cast<MouseEvent*>(event)->button() == LeftButton) {
- MouseEvent* mouseEvent = static_cast<MouseEvent*>(event);
- RenderSlider* slider;
- if (document()->frame() && renderer() &&
- (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(mouseEvent->absoluteLocation(), false, true);
- // Cache the initial position of the thumb.
- m_initialPosition = slider->currentPosition();
- m_inDragMode = true;
-
- document()->frame()->eventHandler()->setCapturingMouseEventsNode(m_shadowParent);
-
- event->setDefaultHandled();
- return;
+
+ if (eventType == eventNames().mousedownEvent && isLeftButton) {
+ if (document()->frame() && renderer()) {
+ RenderSlider* slider = toRenderSlider(renderer()->parent());
+ if (slider) {
+ if (slider->mouseEventIsInThumb(mouseEvent)) {
+ // We selected the thumb, we want the cursor to always stay at
+ // the same position relative to the thumb.
+ m_offsetToThumb = slider->mouseEventOffsetToThumb(mouseEvent);
+ } else {
+ // We are outside the thumb, move the thumb to the point were
+ // we clicked. We'll be exactly at the center of the thumb.
+ m_offsetToThumb.setX(0);
+ m_offsetToThumb.setY(0);
+ }
+
+ m_inDragMode = true;
+ document()->frame()->eventHandler()->setCapturingMouseEventsNode(m_shadowParent);
+ event->setDefaultHandled();
+ return;
+ }
}
- } else if (eventType == eventNames().mouseupEvent && event->isMouseEvent() && static_cast<MouseEvent*>(event)->button() == LeftButton) {
+ } else if (eventType == eventNames().mouseupEvent && isLeftButton) {
if (m_inDragMode) {
if (Frame* frame = document()->frame())
frame->eventHandler()->setCapturingMouseEventsNode(0);
@@ -173,24 +183,31 @@ void SliderThumbElement::defaultEventHandler(Event* event)
event->setDefaultHandled();
return;
}
- } else if (eventType == eventNames().mousemoveEvent && event->isMouseEvent()) {
+ } else if (eventType == eventNames().mousemoveEvent) {
if (m_inDragMode && renderer() && renderer()->parent()) {
- // Move the slider
- MouseEvent* mouseEvent = static_cast<MouseEvent*>(event);
- RenderSlider* slider = static_cast<RenderSlider*>(renderer()->parent());
-
- FloatPoint curPoint = slider->absoluteToLocal(mouseEvent->absoluteLocation(), false, true);
- IntPoint eventOffset(m_initialPosition + curPoint.x() - m_initialClickPoint.x() + renderBox()->width() / 2,
- m_initialPosition + curPoint.y() - m_initialClickPoint.y() + renderBox()->height() / 2);
- slider->setValueForPosition(slider->positionForOffset(eventOffset));
- event->setDefaultHandled();
- return;
+ RenderSlider* slider = toRenderSlider(renderer()->parent());
+ if (slider) {
+ FloatPoint curPoint = slider->absoluteToLocal(mouseEvent->absoluteLocation(), false, true);
+ IntPoint eventOffset(curPoint.x() + m_offsetToThumb.x(), curPoint.y() + m_offsetToThumb.y());
+ slider->setValueForPosition(slider->positionForOffset(eventOffset));
+ event->setDefaultHandled();
+ return;
+ }
}
}
HTMLDivElement::defaultEventHandler(event);
}
+void SliderThumbElement::detach()
+{
+ if (m_inDragMode) {
+ if (Frame* frame = document()->frame())
+ frame->eventHandler()->setCapturingMouseEventsNode(0);
+ }
+ HTMLDivElement::detach();
+}
+
RenderSlider::RenderSlider(HTMLInputElement* element)
: RenderBlock(element)
{
@@ -272,6 +289,30 @@ PassRefPtr<RenderStyle> RenderSlider::createThumbStyle(const RenderStyle* parent
return style.release();
}
+IntRect RenderSlider::thumbRect()
+{
+ if (!m_thumb)
+ return IntRect();
+
+ IntRect thumbRect;
+ RenderBox* thumb = toRenderBox(m_thumb->renderer());
+
+ thumbRect.setWidth(thumb->style()->width().calcMinValue(contentWidth()));
+ thumbRect.setHeight(thumb->style()->height().calcMinValue(contentHeight()));
+
+ double fraction = sliderPosition(static_cast<HTMLInputElement*>(node()));
+ IntRect contentRect = contentBoxRect();
+ if (style()->appearance() == SliderVerticalPart) {
+ thumbRect.setX(contentRect.x() + (contentRect.width() - thumbRect.width()) / 2);
+ thumbRect.setY(contentRect.y() + static_cast<int>(nextafter((contentRect.height() - thumbRect.height()) + 1, 0) * (1 - fraction)));
+ } else {
+ thumbRect.setX(contentRect.x() + static_cast<int>(nextafter((contentRect.width() - thumbRect.width()) + 1, 0) * fraction));
+ thumbRect.setY(contentRect.y() + (contentRect.height() - thumbRect.height()) / 2);
+ }
+
+ return thumbRect;
+}
+
void RenderSlider::layout()
{
ASSERT(needsLayout());
@@ -311,23 +352,8 @@ void RenderSlider::layout()
thumb->layoutIfNeeded();
- IntRect thumbRect;
-
- thumbRect.setWidth(thumb->style()->width().calcMinValue(contentWidth()));
- thumbRect.setHeight(thumb->style()->height().calcMinValue(contentHeight()));
-
- double fraction = sliderPosition(static_cast<HTMLInputElement*>(node()));
- IntRect contentRect = contentBoxRect();
- if (style()->appearance() == SliderVerticalPart) {
- thumbRect.setX(contentRect.x() + (contentRect.width() - thumbRect.width()) / 2);
- thumbRect.setY(contentRect.y() + static_cast<int>(nextafter((contentRect.height() - thumbRect.height()) + 1, 0) * (1 - fraction)));
- } else {
- thumbRect.setX(contentRect.x() + static_cast<int>(nextafter((contentRect.width() - thumbRect.width()) + 1, 0) * fraction));
- thumbRect.setY(contentRect.y() + (contentRect.height() - thumbRect.height()) / 2);
- }
-
- thumb->setFrameRect(thumbRect);
-
+ IntRect rect = thumbRect();
+ thumb->setFrameRect(rect);
if (thumb->checkForRepaintDuringLayout())
thumb->repaintDuringLayoutIfMoved(oldThumbRect);
@@ -391,6 +417,17 @@ bool RenderSlider::mouseEventIsInThumb(MouseEvent* evt)
return thumbBounds.contains(roundedIntPoint(localPoint));
}
+FloatPoint RenderSlider::mouseEventOffsetToThumb(MouseEvent* evt)
+{
+ ASSERT(m_thumb && m_thumb->renderer());
+ FloatPoint localPoint = m_thumb->renderBox()->absoluteToLocal(evt->absoluteLocation(), false, true);
+ IntRect thumbBounds = m_thumb->renderBox()->borderBoxRect();
+ FloatPoint offset;
+ offset.setX(thumbBounds.x() + thumbBounds.width() / 2 - localPoint.x());
+ offset.setY(thumbBounds.y() + thumbBounds.height() / 2 - localPoint.y());
+ return offset;
+}
+
void RenderSlider::setValueForPosition(int position)
{
if (!m_thumb || !m_thumb->renderer())
diff --git a/WebCore/rendering/RenderSlider.h b/WebCore/rendering/RenderSlider.h
index f1eab9c..92ad73b 100644
--- a/WebCore/rendering/RenderSlider.h
+++ b/WebCore/rendering/RenderSlider.h
@@ -36,17 +36,19 @@ namespace WebCore {
void forwardEvent(Event*);
bool inDragMode() const;
+ IntRect thumbRect();
private:
virtual const char* renderName() const { return "RenderSlider"; }
virtual bool isSlider() const { return true; }
- virtual int baselinePosition( bool, bool ) const;
+ virtual int baselinePosition(bool, bool) const;
virtual void calcPrefWidths();
virtual void layout();
virtual void updateFromElement();
bool mouseEventIsInThumb(MouseEvent*);
+ FloatPoint mouseEventOffsetToThumb(MouseEvent*);
void setValueForPosition(int position);
void setPositionFromValue();
@@ -65,6 +67,15 @@ namespace WebCore {
friend class SliderThumbElement;
};
+ inline RenderSlider* toRenderSlider(RenderObject* object)
+ {
+ ASSERT(!object || object->isSlider());
+ return static_cast<RenderSlider*>(object);
+ }
+
+ // This will catch anyone doing an unnecessary cast.
+ void toRenderSlider(const RenderSlider*);
+
} // namespace WebCore
#endif // RenderSlider_h
diff --git a/WebCore/rendering/RenderTable.cpp b/WebCore/rendering/RenderTable.cpp
index ed1be3e..7599999 100644
--- a/WebCore/rendering/RenderTable.cpp
+++ b/WebCore/rendering/RenderTable.cpp
@@ -4,7 +4,7 @@
* (C) 1998 Waldo Bastian (bastian@kde.org)
* (C) 1999 Lars Knoll (knoll@kde.org)
* (C) 1999 Antti Koivisto (koivisto@kde.org)
- * 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.
* Copyright (C) 2006 Alexey Proskuryakov (ap@nypop.com)
*
* This library is free software; you can redistribute it and/or
@@ -53,7 +53,6 @@ RenderTable::RenderTable(Node* node)
, m_head(0)
, m_foot(0)
, m_firstBody(0)
- , m_tableLayout(0)
, m_currentBorder(0)
, m_hasColElements(false)
, m_needsSectionRecalc(0)
@@ -69,11 +68,6 @@ RenderTable::RenderTable(Node* node)
m_columns.fill(ColumnStruct(), 1);
}
-RenderTable::~RenderTable()
-{
- delete m_tableLayout;
-}
-
void RenderTable::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
{
RenderBlock::styleDidChange(diff, oldStyle);
@@ -86,14 +80,12 @@ void RenderTable::styleDidChange(StyleDifference diff, const RenderStyle* oldSty
m_columnPos[0] = m_hSpacing;
if (!m_tableLayout || style()->tableLayout() != oldTableLayout) {
- delete m_tableLayout;
-
// According to the CSS2 spec, you only use fixed table layout if an
// explicit width is specified on the table. Auto width implies auto table layout.
if (style()->tableLayout() == TFIXED && !style()->width().isAuto())
- m_tableLayout = new FixedTableLayout(this);
+ m_tableLayout.set(new FixedTableLayout(this));
else
- m_tableLayout = new AutoTableLayout(this);
+ m_tableLayout.set(new AutoTableLayout(this));
}
}
@@ -136,18 +128,18 @@ void RenderTable::addChild(RenderObject* child, RenderObject* beforeChild)
case TABLE_HEADER_GROUP:
resetSectionPointerIfNotBefore(m_head, beforeChild);
if (!m_head) {
- m_head = static_cast<RenderTableSection*>(child);
+ m_head = toRenderTableSection(child);
} else {
resetSectionPointerIfNotBefore(m_firstBody, beforeChild);
if (!m_firstBody)
- m_firstBody = static_cast<RenderTableSection*>(child);
+ m_firstBody = toRenderTableSection(child);
}
wrapInAnonymousSection = false;
break;
case TABLE_FOOTER_GROUP:
resetSectionPointerIfNotBefore(m_foot, beforeChild);
if (!m_foot) {
- m_foot = static_cast<RenderTableSection*>(child);
+ m_foot = toRenderTableSection(child);
wrapInAnonymousSection = false;
break;
}
@@ -155,7 +147,7 @@ void RenderTable::addChild(RenderObject* child, RenderObject* beforeChild)
case TABLE_ROW_GROUP:
resetSectionPointerIfNotBefore(m_firstBody, beforeChild);
if (!m_firstBody)
- m_firstBody = static_cast<RenderTableSection*>(child);
+ m_firstBody = toRenderTableSection(child);
wrapInAnonymousSection = false;
break;
default:
@@ -347,11 +339,14 @@ void RenderTable::layout()
#endif
if (child->isTableSection()) {
child->layoutIfNeeded();
- RenderTableSection* section = static_cast<RenderTableSection*>(child);
+ RenderTableSection* section = toRenderTableSection(child);
calculatedHeight += section->calcRowHeight();
if (collapsing)
section->recalcOuterBorder();
ASSERT(!section->needsLayout());
+ } else if (child->isTableCol()) {
+ child->layoutIfNeeded();
+ ASSERT(!child->needsLayout());
}
}
@@ -408,7 +403,7 @@ void RenderTable::layout()
for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
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);
+ toRenderTableSection(child)->layoutRows(child == m_firstBody ? max(0, th - calculatedHeight) : 0);
}
if (!m_firstBody && th > calculatedHeight && !style()->htmlHacks()) {
@@ -462,13 +457,17 @@ void RenderTable::layout()
layoutPositionedObjects(true);
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, width() + boxShadow->x + boxShadow->blur);
- m_overflowTop = min(m_overflowTop, boxShadow->y - boxShadow->blur);
- m_overflowHeight = max(m_overflowHeight, height() + boxShadow->y + boxShadow->blur);
- }
-
+ int shadowLeft;
+ int shadowRight;
+ int shadowTop;
+ int shadowBottom;
+ style()->getBoxShadowExtent(shadowTop, shadowRight, shadowBottom, shadowLeft);
+
+ m_overflowLeft = min(m_overflowLeft, shadowLeft);
+ m_overflowWidth = max(m_overflowWidth, width() + shadowRight);
+ m_overflowTop = min(m_overflowTop, shadowTop);
+ m_overflowHeight = max(m_overflowHeight, height() + shadowBottom);
+
if (hasReflection()) {
IntRect reflection(reflectionBox());
m_overflowTop = min(m_overflowTop, reflection.y());
@@ -492,7 +491,7 @@ void RenderTable::setCellWidths()
{
for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
if (child->isTableSection())
- static_cast<RenderTableSection*>(child)->setCellWidths();
+ toRenderTableSection(child)->setCellWidths();
}
}
@@ -552,7 +551,7 @@ void RenderTable::paintObject(PaintInfo& paintInfo, int tx, int ty)
RenderObject* stop = nextInPreOrderAfterChildren();
for (RenderObject* o = firstChild(); o && o != stop; o = o->nextInPreOrder())
if (o->isTableCell())
- static_cast<RenderTableCell*>(o)->collectBorderStyles(borderStyles);
+ toRenderTableCell(o)->collectBorderStyles(borderStyles);
RenderTableCell::sortBorderStyles(borderStyles);
size_t count = borderStyles.size();
for (size_t i = 0; i < count; ++i) {
@@ -578,16 +577,10 @@ void RenderTable::paintBoxDecorations(PaintInfo& paintInfo, int tx, int ty)
ty += captionHeight;
}
- int my = max(ty, paintInfo.rect.y());
- int mh;
- if (ty < paintInfo.rect.y())
- mh = max(0, h - (paintInfo.rect.y() - ty));
- else
- mh = min(paintInfo.rect.height(), h);
-
- paintBoxShadow(paintInfo.context, tx, ty, w, h, style());
+ paintBoxShadow(paintInfo.context, tx, ty, w, h, style(), Normal);
- paintFillLayers(paintInfo, style()->backgroundColor(), style()->backgroundLayers(), my, mh, tx, ty, w, h);
+ paintFillLayers(paintInfo, style()->backgroundColor(), style()->backgroundLayers(), tx, ty, w, h);
+ paintBoxShadow(paintInfo.context, tx, ty, w, h, style(), Inset);
if (style()->hasBorder() && !collapseBorders())
paintBorder(paintInfo.context, tx, ty, w, h, style());
@@ -609,14 +602,7 @@ void RenderTable::paintMask(PaintInfo& paintInfo, int tx, int ty)
ty += captionHeight;
}
- int my = max(ty, paintInfo.rect.y());
- int mh;
- if (ty < paintInfo.rect.y())
- mh = max(0, h - (paintInfo.rect.y() - ty));
- else
- mh = min(paintInfo.rect.height(), h);
-
- paintMaskImages(paintInfo, my, mh, tx, ty, w, h);
+ paintMaskImages(paintInfo, tx, ty, w, h);
}
void RenderTable::calcPrefWidths()
@@ -648,7 +634,7 @@ void RenderTable::splitColumn(int pos, int firstSpan)
// change width of all rows.
for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
if (child->isTableSection())
- static_cast<RenderTableSection*>(child)->splitColumn(pos, oldSize + 1);
+ toRenderTableSection(child)->splitColumn(pos, oldSize + 1);
}
m_columnPos.grow(numEffCols() + 1);
@@ -666,7 +652,7 @@ void RenderTable::appendColumn(int span)
// change width of all rows.
for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
if (child->isTableSection())
- static_cast<RenderTableSection*>(child)->appendColumn(pos);
+ toRenderTableSection(child)->appendColumn(pos);
}
m_columnPos.grow(numEffCols() + 1);
@@ -682,7 +668,7 @@ RenderTableCol* RenderTable::colElement(int col, bool* startEdge, bool* endEdge)
while (child) {
if (child->isTableCol()) {
- RenderTableCol* colElem = static_cast<RenderTableCol*>(child);
+ RenderTableCol* colElem = toRenderTableCol(child);
int span = colElem->span();
if (!colElem->firstChild()) {
int startCol = cCol;
@@ -735,7 +721,7 @@ void RenderTable::recalcSections() const
break;
case TABLE_HEADER_GROUP:
if (child->isTableSection()) {
- RenderTableSection* section = static_cast<RenderTableSection*>(child);
+ RenderTableSection* section = toRenderTableSection(child);
if (!m_head)
m_head = section;
else if (!m_firstBody)
@@ -745,7 +731,7 @@ void RenderTable::recalcSections() const
break;
case TABLE_FOOTER_GROUP:
if (child->isTableSection()) {
- RenderTableSection* section = static_cast<RenderTableSection*>(child);
+ RenderTableSection* section = toRenderTableSection(child);
if (!m_foot)
m_foot = section;
else if (!m_firstBody)
@@ -755,7 +741,7 @@ void RenderTable::recalcSections() const
break;
case TABLE_ROW_GROUP:
if (child->isTableSection()) {
- RenderTableSection* section = static_cast<RenderTableSection*>(child);
+ RenderTableSection* section = toRenderTableSection(child);
if (!m_firstBody)
m_firstBody = section;
section->recalcCellsIfNeeded();
@@ -770,7 +756,7 @@ void RenderTable::recalcSections() const
int maxCols = 0;
for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
if (child->isTableSection()) {
- RenderTableSection* section = static_cast<RenderTableSection*>(child);
+ RenderTableSection* section = toRenderTableSection(child);
int sectionCols = section->numColumns();
if (sectionCols > maxCols)
maxCols = sectionCols;
@@ -960,9 +946,8 @@ int RenderTable::outerBorderBottom() const
bottomSection = m_foot;
else {
RenderObject* child;
- for (child = lastChild(); child && !child->isTableSection(); child = child->previousSibling())
- ;
- bottomSection = child ? static_cast<RenderTableSection*>(child) : 0;
+ for (child = lastChild(); child && !child->isTableSection(); child = child->previousSibling()) { }
+ bottomSection = child ? toRenderTableSection(child) : 0;
}
if (bottomSection) {
borderWidth = bottomSection->outerBorderBottom();
@@ -994,7 +979,7 @@ int RenderTable::outerBorderLeft() const
for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
if (!child->isTableSection())
continue;
- int sw = static_cast<RenderTableSection*>(child)->outerBorderLeft();
+ int sw = toRenderTableSection(child)->outerBorderLeft();
if (sw == -1)
continue;
else
@@ -1024,7 +1009,7 @@ int RenderTable::outerBorderRight() const
for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
if (!child->isTableSection())
continue;
- int sw = static_cast<RenderTableSection*>(child)->outerBorderRight();
+ int sw = toRenderTableSection(child)->outerBorderRight();
if (sw == -1)
continue;
else
@@ -1046,13 +1031,13 @@ RenderTableSection* RenderTable::sectionAbove(const RenderTableSection* section,
RenderObject* prevSection = section == m_foot ? lastChild() : section->previousSibling();
while (prevSection) {
- if (prevSection->isTableSection() && prevSection != m_head && prevSection != m_foot && (!skipEmptySections || static_cast<RenderTableSection*>(prevSection)->numRows()))
+ if (prevSection->isTableSection() && prevSection != m_head && prevSection != m_foot && (!skipEmptySections || toRenderTableSection(prevSection)->numRows()))
break;
prevSection = prevSection->previousSibling();
}
if (!prevSection && m_head && (!skipEmptySections || m_head->numRows()))
prevSection = m_head;
- return static_cast<RenderTableSection*>(prevSection);
+ return toRenderTableSection(prevSection);
}
RenderTableSection* RenderTable::sectionBelow(const RenderTableSection* section, bool skipEmptySections) const
@@ -1064,13 +1049,13 @@ RenderTableSection* RenderTable::sectionBelow(const RenderTableSection* section,
RenderObject* nextSection = section == m_head ? firstChild() : section->nextSibling();
while (nextSection) {
- if (nextSection->isTableSection() && nextSection != m_head && nextSection != m_foot && (!skipEmptySections || static_cast<RenderTableSection*>(nextSection)->numRows()))
+ if (nextSection->isTableSection() && nextSection != m_head && nextSection != m_foot && (!skipEmptySections || toRenderTableSection(nextSection)->numRows()))
break;
nextSection = nextSection->nextSibling();
}
if (!nextSection && m_foot && (!skipEmptySections || m_foot->numRows()))
nextSection = m_foot;
- return static_cast<RenderTableSection*>(nextSection);
+ return toRenderTableSection(nextSection);
}
RenderTableCell* RenderTable::cellAbove(const RenderTableCell* cell) const
diff --git a/WebCore/rendering/RenderTable.h b/WebCore/rendering/RenderTable.h
index 2fb7a14..d07a727 100644
--- a/WebCore/rendering/RenderTable.h
+++ b/WebCore/rendering/RenderTable.h
@@ -1,12 +1,10 @@
/*
- * This file is part of the DOM implementation for KDE.
- *
* Copyright (C) 1997 Martin Jones (mjones@kde.org)
* (C) 1997 Torben Weis (weis@kde.org)
* (C) 1998 Waldo Bastian (bastian@kde.org)
* (C) 1999 Lars Knoll (knoll@kde.org)
* (C) 1999 Antti Koivisto (koivisto@kde.org)
- * Copyright (C) 2003, 2004, 2005, 2006 Apple Computer, Inc.
+ * Copyright (C) 2003, 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
@@ -40,13 +38,6 @@ class TableLayout;
class RenderTable : public RenderBlock {
public:
RenderTable(Node*);
- ~RenderTable();
-
- virtual const char* renderName() const { return "RenderTable"; }
-
- virtual bool isTable() const { return true; }
-
- virtual bool avoidsFloats() const { return true; }
int getColumnPos(int col) const { return m_columnPos[col]; }
@@ -70,26 +61,7 @@ public:
int calcBorderRight() const;
void recalcHorizontalBorders();
- // overrides
virtual void addChild(RenderObject* child, RenderObject* beforeChild = 0);
- virtual void removeChild(RenderObject* oldChild);
-
- virtual void paint(PaintInfo&, int tx, int ty);
- virtual void paintObject(PaintInfo&, int tx, int ty);
- virtual void paintBoxDecorations(PaintInfo&, int tx, int ty);
- virtual void paintMask(PaintInfo& paintInfo, int tx, int ty);
- virtual void layout();
- virtual void calcPrefWidths();
- virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, int xPos, int yPos, int tx, int ty, HitTestAction);
-
- virtual int firstLineBoxBaseline() const;
-
- virtual RenderBlock* firstLineBlock() const;
- virtual void updateFirstLetter();
-
- virtual void setCellWidths();
-
- virtual void calcWidth();
struct ColumnStruct {
enum {
@@ -163,8 +135,6 @@ public:
bool hasSections() const { return m_head || m_foot || m_firstBody; }
- virtual IntRect overflowClipRect(int tx, int ty);
-
void recalcSectionsIfNeeded() const
{
if (m_needsSectionRecalc)
@@ -180,6 +150,33 @@ protected:
virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
private:
+ virtual const char* renderName() const { return "RenderTable"; }
+
+ virtual bool isTable() const { return true; }
+
+ virtual bool avoidsFloats() const { return true; }
+
+ virtual void removeChild(RenderObject* oldChild);
+
+ virtual void paint(PaintInfo&, int tx, int ty);
+ virtual void paintObject(PaintInfo&, int tx, int ty);
+ virtual void paintBoxDecorations(PaintInfo&, int tx, int ty);
+ virtual void paintMask(PaintInfo&, int tx, int ty);
+ virtual void layout();
+ virtual void calcPrefWidths();
+ virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, int xPos, int yPos, int tx, int ty, HitTestAction);
+
+ virtual int firstLineBoxBaseline() const;
+
+ virtual RenderBlock* firstLineBlock() const;
+ virtual void updateFirstLetter();
+
+ virtual void setCellWidths();
+
+ virtual void calcWidth();
+
+ virtual IntRect overflowClipRect(int tx, int ty);
+
void recalcSections() const;
mutable Vector<int> m_columnPos;
@@ -190,7 +187,7 @@ private:
mutable RenderTableSection* m_foot;
mutable RenderTableSection* m_firstBody;
- TableLayout* m_tableLayout;
+ OwnPtr<TableLayout> m_tableLayout;
const CollapsedBorderValue* m_currentBorder;
@@ -206,6 +203,21 @@ private:
int m_borderRight;
};
+inline RenderTable* toRenderTable(RenderObject* object)
+{
+ ASSERT(!object || object->isTable());
+ return static_cast<RenderTable*>(object);
+}
+
+inline const RenderTable* toRenderTable(const RenderObject* object)
+{
+ ASSERT(!object || object->isTable());
+ return static_cast<const RenderTable*>(object);
+}
+
+// This will catch anyone doing an unnecessary cast.
+void toRenderTable(const RenderTable*);
+
} // namespace WebCore
#endif // RenderTable_h
diff --git a/WebCore/rendering/RenderTableCell.cpp b/WebCore/rendering/RenderTableCell.cpp
index f5e6ae2..8b7a068 100644
--- a/WebCore/rendering/RenderTableCell.cpp
+++ b/WebCore/rendering/RenderTableCell.cpp
@@ -4,7 +4,7 @@
* (C) 1998 Waldo Bastian (bastian@kde.org)
* (C) 1999 Lars Knoll (knoll@kde.org)
* (C) 1999 Antti Koivisto (koivisto@kde.org)
- * Copyright (C) 2003, 2004, 2005, 2006, 2007 Apple Inc. All rights reserved.
+ * 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
@@ -564,7 +564,7 @@ CollapsedBorderValue RenderTableCell::collapsedBottomBorder() const
// Now check row groups.
RenderTableSection* currSection = section();
- if (row() + rowSpan() >= static_cast<RenderTableSection*>(currSection)->numRows()) {
+ if (row() + rowSpan() >= currSection->numRows()) {
// (5) Our row group's bottom border.
result = compareBorders(result, CollapsedBorderValue(&currSection->style()->borderBottom(), BROWGROUP));
if (!result.exists())
@@ -845,10 +845,6 @@ void RenderTableCell::paintBackgroundsBehindCell(PaintInfo& paintInfo, int tx, i
int w = width();
int h = height();
- int my = max(ty, paintInfo.rect.y());
- int end = min(paintInfo.rect.bottom(), ty + h);
- int mh = end - my;
-
Color c = backgroundObject->style()->backgroundColor();
const FillLayer* bgLayer = backgroundObject->style()->backgroundLayers();
@@ -862,7 +858,7 @@ void RenderTableCell::paintBackgroundsBehindCell(PaintInfo& paintInfo, int tx, i
paintInfo.context->save();
paintInfo.context->clip(clipRect);
}
- paintFillLayers(paintInfo, c, bgLayer, my, mh, tx, ty, w, h);
+ paintFillLayers(paintInfo, c, bgLayer, tx, ty, w, h);
if (shouldClip)
paintInfo.context->restore();
}
@@ -878,10 +874,12 @@ void RenderTableCell::paintBoxDecorations(PaintInfo& paintInfo, int tx, int ty)
int h = height();
if (style()->boxShadow())
- paintBoxShadow(paintInfo.context, tx, ty, w, h, style());
+ paintBoxShadow(paintInfo.context, tx, ty, w, h, style(), Normal);
// Paint our cell background.
paintBackgroundsBehindCell(paintInfo, tx, ty, this);
+ if (style()->boxShadow())
+ paintBoxShadow(paintInfo.context, tx, ty, w, h, style(), Inset);
if (!style()->hasBorder() || tableElt->collapseBorders())
return;
@@ -901,11 +899,7 @@ void RenderTableCell::paintMask(PaintInfo& paintInfo, int tx, int ty)
int w = width();
int h = height();
- int my = max(ty, paintInfo.rect.y());
- int end = min(paintInfo.rect.bottom(), ty + h);
- int mh = end - my;
-
- paintMaskImages(paintInfo, my, mh, tx, ty, w, h);
+ paintMaskImages(paintInfo, tx, ty, w, h);
}
} // namespace WebCore
diff --git a/WebCore/rendering/RenderTableCell.h b/WebCore/rendering/RenderTableCell.h
index 4b09032..9532bb6 100644
--- a/WebCore/rendering/RenderTableCell.h
+++ b/WebCore/rendering/RenderTableCell.h
@@ -4,7 +4,7 @@
* (C) 1998 Waldo Bastian (bastian@kde.org)
* (C) 1999 Lars Knoll (knoll@kde.org)
* (C) 1999 Antti Koivisto (koivisto@kde.org)
- * Copyright (C) 2003, 2004, 2005, 2006, 2007 Apple Inc. All rights reserved.
+ * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2009 Apple Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -33,12 +33,6 @@ class RenderTableCell : public RenderBlock {
public:
RenderTableCell(Node*);
- virtual const char* renderName() const { return isAnonymous() ? "RenderTableCell (anonymous)" : "RenderTableCell"; }
-
- virtual bool isTableCell() const { return true; }
-
- virtual void destroy();
-
// FIXME: need to implement cellIndex
int cellIndex() const { return 0; }
void setCellIndex(int) { }
@@ -54,19 +48,19 @@ public:
int row() const { return m_row; }
void setRow(int row) { m_row = row; }
- RenderTableSection* section() const { return static_cast<RenderTableSection*>(parent()->parent()); }
- RenderTable* table() const { return static_cast<RenderTable*>(parent()->parent()->parent()); }
+ RenderTableSection* section() const { return toRenderTableSection(parent()->parent()); }
+ RenderTable* table() const { return toRenderTable(parent()->parent()->parent()); }
Length styleOrColWidth() const;
- virtual bool requiresLayer() const { return isPositioned() || isTransparent() || hasOverflowClip() || hasTransform() || hasMask() || hasReflection(); }
-
virtual void calcPrefWidths();
- virtual void calcWidth();
+
+#if PLATFORM(ANDROID)
#ifdef ANDROID_LAYOUT
// RenderTableSection needs to access this in setCellWidths()
int getVisibleWidth() { return m_visibleWidth; }
-#endif
+#endif
+#endif
void updateWidth(int);
@@ -94,13 +88,8 @@ public:
virtual void layout();
virtual void paint(PaintInfo&, int tx, int ty);
- virtual void paintBoxDecorations(PaintInfo&, int tx, int ty);
- virtual void paintMask(PaintInfo& paintInfo, int tx, int ty);
- void paintCollapsedBorder(GraphicsContext*, int x, int y, int w, int h);
- void paintBackgroundsBehindCell(PaintInfo&, int tx, int ty, RenderObject* backgroundObject);
- virtual IntRect clippedOverflowRectForRepaint(RenderBoxModelObject* repaintContainer);
- virtual void computeRectForRepaint(RenderBoxModelObject* repaintContainer, IntRect&, bool fixed = false);
+ void paintBackgroundsBehindCell(PaintInfo&, int tx, int ty, RenderObject* backgroundObject);
virtual int baselinePosition(bool firstLine = false, bool isRootLineBox = false) const;
@@ -125,6 +114,24 @@ protected:
virtual void mapAbsoluteToLocalPoint(bool fixed, bool useTransforms, TransformState&) const;
private:
+ virtual const char* renderName() const { return isAnonymous() ? "RenderTableCell (anonymous)" : "RenderTableCell"; }
+
+ virtual bool isTableCell() const { return true; }
+
+ virtual void destroy();
+
+ virtual bool requiresLayer() const { return isPositioned() || isTransparent() || hasOverflowClip() || hasTransform() || hasMask() || hasReflection(); }
+
+ virtual void calcWidth();
+
+ virtual void paintBoxDecorations(PaintInfo&, int tx, int ty);
+ virtual void paintMask(PaintInfo&, int tx, int ty);
+
+ virtual IntRect clippedOverflowRectForRepaint(RenderBoxModelObject* repaintContainer);
+ virtual void computeRectForRepaint(RenderBoxModelObject* repaintContainer, IntRect&, bool fixed = false);
+
+ void paintCollapsedBorder(GraphicsContext*, int x, int y, int w, int h);
+
int m_row;
int m_column;
int m_rowSpan;
@@ -134,6 +141,21 @@ private:
int m_percentageHeight;
};
+inline RenderTableCell* toRenderTableCell(RenderObject* object)
+{
+ ASSERT(!object || object->isTableCell());
+ return static_cast<RenderTableCell*>(object);
+}
+
+inline const RenderTableCell* toRenderTableCell(const RenderObject* object)
+{
+ ASSERT(!object || object->isTableCell());
+ return static_cast<const RenderTableCell*>(object);
+}
+
+// This will catch anyone doing an unnecessary cast.
+void toRenderTableCell(const RenderTableCell*);
+
} // namespace WebCore
#endif // RenderTableCell_h
diff --git a/WebCore/rendering/RenderTableCol.cpp b/WebCore/rendering/RenderTableCol.cpp
index f17963c..80e74e1 100644
--- a/WebCore/rendering/RenderTableCol.cpp
+++ b/WebCore/rendering/RenderTableCol.cpp
@@ -1,12 +1,10 @@
-/**
- * This file is part of the DOM implementation for KDE.
- *
+/*
* Copyright (C) 1997 Martin Jones (mjones@kde.org)
* (C) 1997 Torben Weis (weis@kde.org)
* (C) 1998 Waldo Bastian (bastian@kde.org)
* (C) 1999 Lars Knoll (knoll@kde.org)
* (C) 1999 Antti Koivisto (koivisto@kde.org)
- * Copyright (C) 2003, 2004, 2005, 2006 Apple Computer, Inc.
+ * Copyright (C) 2003, 2004, 2005, 2006, 2009 Apple Inc. All rights reserved.
* Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
*
* This library is free software; you can redistribute it and/or
@@ -31,13 +29,15 @@
#include "CachedImage.h"
#include "HTMLNames.h"
#include "HTMLTableColElement.h"
+#include "RenderTable.h"
namespace WebCore {
using namespace HTMLNames;
RenderTableCol::RenderTableCol(Node* node)
- : RenderBox(node), m_span(1)
+ : RenderBox(node)
+ , m_span(1)
{
// init RenderObject attributes
setInline(true); // our object is not Inline
@@ -75,13 +75,11 @@ IntRect RenderTableCol::clippedOverflowRectForRepaint(RenderBoxModelObject* repa
// 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();
- if (table && table->isTable())
- return table->clippedOverflowRectForRepaint(repaintContainer);
- return IntRect();
+ RenderTable* parentTable = table();
+ if (!parentTable)
+ return IntRect();
+ return parentTable->clippedOverflowRectForRepaint(repaintContainer);
}
void RenderTableCol::imageChanged(WrappedImagePtr, const IntRect*)
@@ -90,4 +88,20 @@ void RenderTableCol::imageChanged(WrappedImagePtr, const IntRect*)
repaint();
}
+void RenderTableCol::calcPrefWidths()
+{
+ setPrefWidthsDirty(false);
+
+ for (RenderObject* child = firstChild(); child; child = child->nextSibling())
+ child->setPrefWidthsDirty(false);
+}
+
+RenderTable* RenderTableCol::table() const
+{
+ RenderObject* table = parent();
+ if (table && !table->isTable())
+ table = table->parent();
+ return table && table->isTable() ? toRenderTable(table) : 0;
+}
+
}
diff --git a/WebCore/rendering/RenderTableCol.h b/WebCore/rendering/RenderTableCol.h
index 8c494b2..87209a1 100644
--- a/WebCore/rendering/RenderTableCol.h
+++ b/WebCore/rendering/RenderTableCol.h
@@ -1,12 +1,10 @@
/*
- * This file is part of the DOM implementation for KDE.
- *
* Copyright (C) 1997 Martin Jones (mjones@kde.org)
* (C) 1997 Torben Weis (weis@kde.org)
* (C) 1998 Waldo Bastian (bastian@kde.org)
* (C) 1999 Lars Knoll (knoll@kde.org)
* (C) 1999 Antti Koivisto (koivisto@kde.org)
- * Copyright (C) 2003, 2004, 2005, 2006 Apple Computer, Inc.
+ * Copyright (C) 2003, 2004, 2005, 2006, 2009 Apple Inc. All rights reserved.
* Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
*
* This library is free software; you can redistribute it and/or
@@ -32,16 +30,24 @@
namespace WebCore {
-class RenderTableCol : public RenderBox
-{
+class RenderTable;
+
+class RenderTableCol : public RenderBox {
public:
RenderTableCol(Node*);
- virtual RenderObjectChildList* virtualChildren() { return children(); }
- virtual const RenderObjectChildList* virtualChildren() const { return children(); }
const RenderObjectChildList* children() const { return &m_children; }
RenderObjectChildList* children() { return &m_children; }
+ virtual void calcPrefWidths();
+
+ int span() const { return m_span; }
+ void setSpan(int span) { m_span = span; }
+
+private:
+ virtual RenderObjectChildList* virtualChildren() { return children(); }
+ virtual const RenderObjectChildList* virtualChildren() const { return children(); }
+
virtual const char* renderName() const { return "RenderTableCol"; }
virtual bool isTableCol() const { return true; }
virtual int lineHeight(bool) const { return 0; }
@@ -54,14 +60,27 @@ public:
virtual IntRect clippedOverflowRectForRepaint(RenderBoxModelObject* repaintContainer);
virtual void imageChanged(WrappedImagePtr, const IntRect* = 0);
- int span() const { return m_span; }
- void setSpan(int s) { m_span = s; }
-
-private:
+ RenderTable* table() const;
+
RenderObjectChildList m_children;
int m_span;
};
+inline RenderTableCol* toRenderTableCol(RenderObject* object)
+{
+ ASSERT(!object || object->isTableCol());
+ return static_cast<RenderTableCol*>(object);
+}
+
+inline const RenderTableCol* toRenderTableCol(const RenderObject* object)
+{
+ ASSERT(!object || object->isTableCol());
+ return static_cast<const RenderTableCol*>(object);
+}
+
+// This will catch anyone doing an unnecessary cast.
+void toRenderTableCol(const RenderTableCol*);
+
}
#endif
diff --git a/WebCore/rendering/RenderTableRow.cpp b/WebCore/rendering/RenderTableRow.cpp
index 33b2c39..bafadfc 100644
--- a/WebCore/rendering/RenderTableRow.cpp
+++ b/WebCore/rendering/RenderTableRow.cpp
@@ -99,7 +99,7 @@ void RenderTableRow::addChild(RenderObject* child, RenderObject* beforeChild)
while (beforeChild && beforeChild->parent() != this)
beforeChild = beforeChild->parent();
- RenderTableCell* cell = static_cast<RenderTableCell*>(child);
+ RenderTableCell* cell = toRenderTableCell(child);
// Generated content can result in us having a null section so make sure to null check our parent.
if (parent())
@@ -121,7 +121,7 @@ void RenderTableRow::layout()
for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
if (child->isTableCell()) {
- RenderTableCell* cell = static_cast<RenderTableCell*>(child);
+ RenderTableCell* cell = toRenderTableCell(child);
if (child->needsLayout()) {
cell->calcVerticalMargins();
cell->layout();
@@ -147,6 +147,11 @@ void RenderTableRow::layout()
IntRect RenderTableRow::clippedOverflowRectForRepaint(RenderBoxModelObject* repaintContainer)
{
+ ASSERT(parent());
+
+ if (repaintContainer == this)
+ return RenderBox::clippedOverflowRectForRepaint(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.
@@ -185,7 +190,7 @@ void RenderTableRow::paint(PaintInfo& paintInfo, int tx, int ty)
if (child->isTableCell()) {
// Paint the row background behind the cell.
if (paintInfo.phase == PaintPhaseBlockBackground || paintInfo.phase == PaintPhaseChildBlockBackground) {
- RenderTableCell* cell = static_cast<RenderTableCell*>(child);
+ RenderTableCell* cell = toRenderTableCell(child);
cell->paintBackgroundsBehindCell(paintInfo, tx, ty, this);
}
if (!toRenderBox(child)->hasSelfPaintingLayer())
diff --git a/WebCore/rendering/RenderTableRow.h b/WebCore/rendering/RenderTableRow.h
index 9622480..588252b 100644
--- a/WebCore/rendering/RenderTableRow.h
+++ b/WebCore/rendering/RenderTableRow.h
@@ -1,12 +1,10 @@
/*
- * This file is part of the DOM implementation for KDE.
- *
* Copyright (C) 1997 Martin Jones (mjones@kde.org)
* (C) 1997 Torben Weis (weis@kde.org)
* (C) 1998 Waldo Bastian (bastian@kde.org)
* (C) 1999 Lars Knoll (knoll@kde.org)
* (C) 1999 Antti Koivisto (koivisto@kde.org)
- * Copyright (C) 2003, 2004, 2005, 2006 Apple Computer, Inc.
+ * Copyright (C) 2003, 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
@@ -35,15 +33,16 @@ class RenderTableRow : public RenderBox {
public:
RenderTableRow(Node*);
- virtual RenderObjectChildList* virtualChildren() { return children(); }
- virtual const RenderObjectChildList* virtualChildren() const { return children(); }
const RenderObjectChildList* children() const { return &m_children; }
RenderObjectChildList* children() { return &m_children; }
- RenderTableSection* section() const { return static_cast<RenderTableSection*>(parent()); }
- RenderTable* table() const { return static_cast<RenderTable*>(parent()->parent()); }
+ RenderTableSection* section() const { return toRenderTableSection(parent()); }
+ RenderTable* table() const { return toRenderTable(parent()->parent()); }
private:
+ virtual RenderObjectChildList* virtualChildren() { return children(); }
+ virtual const RenderObjectChildList* virtualChildren() const { return children(); }
+
virtual const char* renderName() const { return isAnonymous() ? "RenderTableRow (anonymous)" : "RenderTableRow"; }
virtual bool isTableRow() const { return true; }
@@ -65,10 +64,24 @@ private:
virtual void styleWillChange(StyleDifference, const RenderStyle* newStyle);
-private:
RenderObjectChildList m_children;
};
+inline RenderTableRow* toRenderTableRow(RenderObject* object)
+{
+ ASSERT(!object || object->isTableRow());
+ return static_cast<RenderTableRow*>(object);
+}
+
+inline const RenderTableRow* toRenderTableRow(const RenderObject* object)
+{
+ ASSERT(!object || object->isTableRow());
+ return static_cast<const RenderTableRow*>(object);
+}
+
+// This will catch anyone doing an unnecessary cast.
+void toRenderTableRow(const RenderTableRow*);
+
} // namespace WebCore
#endif // RenderTableRow_h
diff --git a/WebCore/rendering/RenderTableSection.cpp b/WebCore/rendering/RenderTableSection.cpp
index efa8850..5d47357 100644
--- a/WebCore/rendering/RenderTableSection.cpp
+++ b/WebCore/rendering/RenderTableSection.cpp
@@ -128,7 +128,7 @@ void RenderTableSection::addChild(RenderObject* child, RenderObject* beforeChild
if (!ensureRows(m_cRow + 1))
return;
- m_grid[m_cRow].rowRenderer = static_cast<RenderTableRow*>(child);
+ m_grid[m_cRow].rowRenderer = toRenderTableRow(child);
if (!beforeChild) {
m_grid[m_cRow].height = child->style()->height();
@@ -612,7 +612,7 @@ int RenderTableSection::layoutRows(int toAdd)
for (RenderObject* o = cell->firstChild(); o; o = o->nextSibling()) {
if (!o->isText() && o->style()->height().isPercent() && (flexAllChildren || o->isReplaced() || (o->isBox() && toRenderBox(o)->scrollsOverflow()))) {
// Tables with no sections do not flex.
- if (!o->isTable() || static_cast<RenderTable*>(o)->hasSections()) {
+ if (!o->isTable() || toRenderTable(o)->hasSections()) {
o->setNeedsLayout(true, false);
cellChildrenFlex = true;
}
@@ -741,7 +741,7 @@ int RenderTableSection::lowestPosition(bool includeOverflowInterior, bool includ
for (RenderObject* row = firstChild(); row; row = row->nextSibling()) {
for (RenderObject* curr = row->firstChild(); curr; curr = curr->nextSibling()) {
if (curr->isTableCell()) {
- RenderTableCell* cell = static_cast<RenderTableCell*>(curr);
+ RenderTableCell* cell = toRenderTableCell(curr);
bottom = max(bottom, cell->y() + cell->lowestPosition(false));
}
}
@@ -759,7 +759,7 @@ int RenderTableSection::rightmostPosition(bool includeOverflowInterior, bool inc
for (RenderObject* row = firstChild(); row; row = row->nextSibling()) {
for (RenderObject* curr = row->firstChild(); curr; curr = curr->nextSibling()) {
if (curr->isTableCell()) {
- RenderTableCell* cell = static_cast<RenderTableCell*>(curr);
+ RenderTableCell* cell = toRenderTableCell(curr);
right = max(right, cell->x() + cell->rightmostPosition(false));
}
}
@@ -777,7 +777,7 @@ int RenderTableSection::leftmostPosition(bool includeOverflowInterior, bool incl
for (RenderObject* row = firstChild(); row; row = row->nextSibling()) {
for (RenderObject* curr = row->firstChild(); curr; curr = curr->nextSibling()) {
if (curr->isTableCell()) {
- RenderTableCell* cell = static_cast<RenderTableCell*>(curr);
+ RenderTableCell* cell = toRenderTableCell(curr);
left = min(left, cell->x() + cell->leftmostPosition(false));
}
}
@@ -1129,7 +1129,7 @@ void RenderTableSection::paintObject(PaintInfo& paintInfo, int tx, int ty)
if (!cell || (r > startrow && (cellAt(r - 1, c).cell == cell)))
continue;
- RenderTableRow* row = static_cast<RenderTableRow*>(cell->parent());
+ RenderTableRow* row = toRenderTableRow(cell->parent());
if (paintPhase == PaintPhaseBlockBackground || paintPhase == PaintPhaseChildBlockBackground) {
// We need to handle painting a stack of backgrounds. This stack (from bottom to top) consists of
@@ -1182,12 +1182,12 @@ void RenderTableSection::recalcCells()
if (!ensureRows(m_cRow + 1))
break;
- RenderTableRow* tableRow = static_cast<RenderTableRow*>(row);
+ RenderTableRow* tableRow = toRenderTableRow(row);
m_grid[m_cRow].rowRenderer = tableRow;
for (RenderObject* cell = row->firstChild(); cell; cell = cell->nextSibling()) {
if (cell->isTableCell())
- addCell(static_cast<RenderTableCell*>(cell), tableRow);
+ addCell(toRenderTableCell(cell), tableRow);
}
}
}
diff --git a/WebCore/rendering/RenderTableSection.h b/WebCore/rendering/RenderTableSection.h
index 30614f0..c0098bc 100644
--- a/WebCore/rendering/RenderTableSection.h
+++ b/WebCore/rendering/RenderTableSection.h
@@ -1,12 +1,10 @@
/*
- * This file is part of the DOM implementation for KDE.
- *
* Copyright (C) 1997 Martin Jones (mjones@kde.org)
* (C) 1997 Torben Weis (weis@kde.org)
* (C) 1998 Waldo Bastian (bastian@kde.org)
* (C) 1999 Lars Knoll (knoll@kde.org)
* (C) 1999 Antti Koivisto (koivisto@kde.org)
- * Copyright (C) 2003, 2004, 2005, 2006 Apple Computer, Inc.
+ * Copyright (C) 2003, 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
@@ -38,23 +36,12 @@ class RenderTableRow;
class RenderTableSection : public RenderBox {
public:
RenderTableSection(Node*);
- ~RenderTableSection();
+ virtual ~RenderTableSection();
- virtual RenderObjectChildList* virtualChildren() { return children(); }
- virtual const RenderObjectChildList* virtualChildren() const { return children(); }
const RenderObjectChildList* children() const { return &m_children; }
RenderObjectChildList* children() { return &m_children; }
- virtual const char* renderName() const { return isAnonymous() ? "RenderTableSection (anonymous)" : "RenderTableSection"; }
-
- virtual bool isTableSection() const { return true; }
-
- virtual void destroy();
-
- virtual void layout();
-
virtual void addChild(RenderObject* child, RenderObject* beforeChild = 0);
- virtual void removeChild(RenderObject* oldChild);
virtual int firstLineBoxBaseline() const;
@@ -64,7 +51,7 @@ public:
int calcRowHeight();
int layoutRows(int height);
- RenderTable* table() const { return static_cast<RenderTable*>(parent()); }
+ RenderTable* table() const { return toRenderTable(parent()); }
struct CellStruct {
RenderTableCell* cell;
@@ -91,10 +78,6 @@ public:
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;
- virtual int rightmostPosition(bool includeOverflowInterior, bool includeSelf) const;
- virtual int leftmostPosition(bool includeOverflowInterior, bool includeSelf) const;
-
int calcOuterBorderTop() const;
int calcOuterBorderBottom() const;
int calcOuterBorderLeft(bool rtl) const;
@@ -106,11 +89,6 @@ public:
int outerBorderLeft() const { return m_outerBorderLeft; }
int outerBorderRight() const { return m_outerBorderRight; }
- virtual void paint(PaintInfo&, int tx, int ty);
- virtual void paintObject(PaintInfo&, int tx, int ty);
-
- virtual void imageChanged(WrappedImagePtr, const IntRect* = 0);
-
int numRows() const { return m_gridRows; }
int numColumns() const;
void recalcCells();
@@ -129,9 +107,31 @@ public:
int getBaseline(int row) { return m_grid[row].baseline; }
+private:
+ virtual RenderObjectChildList* virtualChildren() { return children(); }
+ virtual const RenderObjectChildList* virtualChildren() const { return children(); }
+
+ virtual const char* renderName() const { return isAnonymous() ? "RenderTableSection (anonymous)" : "RenderTableSection"; }
+
+ virtual bool isTableSection() const { return true; }
+
+ virtual void destroy();
+
+ virtual void layout();
+
+ virtual void removeChild(RenderObject* oldChild);
+
+ virtual int lowestPosition(bool includeOverflowInterior, bool includeSelf) const;
+ virtual int rightmostPosition(bool includeOverflowInterior, bool includeSelf) const;
+ virtual int leftmostPosition(bool includeOverflowInterior, bool includeSelf) const;
+
+ virtual void paint(PaintInfo&, int tx, int ty);
+ virtual void paintObject(PaintInfo&, int tx, int ty);
+
+ virtual void imageChanged(WrappedImagePtr, const IntRect* = 0);
+
virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, int x, int y, int tx, int ty, HitTestAction);
-private:
virtual int lineHeight(bool, bool) const { return 0; }
bool ensureRows(int);
@@ -161,6 +161,21 @@ private:
bool m_hasOverflowingCell;
};
+inline RenderTableSection* toRenderTableSection(RenderObject* object)
+{
+ ASSERT(!object || object->isTableSection());
+ return static_cast<RenderTableSection*>(object);
+}
+
+inline const RenderTableSection* toRenderTableSection(const RenderObject* object)
+{
+ ASSERT(!object || object->isTableSection());
+ return static_cast<const RenderTableSection*>(object);
+}
+
+// This will catch anyone doing an unnecessary cast.
+void toRenderTableSection(const RenderTableSection*);
+
} // namespace WebCore
#endif // RenderTableSection_h
diff --git a/WebCore/rendering/RenderText.h b/WebCore/rendering/RenderText.h
index 2e04a9e..915ff40 100644
--- a/WebCore/rendering/RenderText.h
+++ b/WebCore/rendering/RenderText.h
@@ -173,16 +173,16 @@ private:
mutable bool m_knownNotToUseFallbackFonts : 1;
};
-inline RenderText* toRenderText(RenderObject* o)
+inline RenderText* toRenderText(RenderObject* object)
{
- ASSERT(!o || o->isText());
- return static_cast<RenderText*>(o);
+ ASSERT(!object || object->isText());
+ return static_cast<RenderText*>(object);
}
-inline const RenderText* toRenderText(const RenderObject* o)
+inline const RenderText* toRenderText(const RenderObject* object)
{
- ASSERT(!o || o->isText());
- return static_cast<const RenderText*>(o);
+ ASSERT(!object || object->isText());
+ return static_cast<const RenderText*>(object);
}
// This will catch anyone doing an unnecessary cast.
diff --git a/WebCore/rendering/RenderTextControl.cpp b/WebCore/rendering/RenderTextControl.cpp
index 752ad7b..70b6518 100644
--- a/WebCore/rendering/RenderTextControl.cpp
+++ b/WebCore/rendering/RenderTextControl.cpp
@@ -235,7 +235,7 @@ void RenderTextControl::setSelectionRange(int start, int end)
end = max(end, 0);
start = min(max(start, 0), end);
- document()->updateLayout();
+ ASSERT(!document()->childNeedsAndNotInStyleRecalc());
if (style()->visibility() == HIDDEN || !m_innerText || !m_innerText->renderer() || !m_innerText->renderBox()->height()) {
cacheSelection(start, end);
@@ -248,9 +248,11 @@ void RenderTextControl::setSelectionRange(int start, int end)
else
endPosition = visiblePositionForIndex(end);
- ASSERT(startPosition.isNotNull() && endPosition.isNotNull());
- ASSERT(startPosition.deepEquivalent().node()->shadowAncestorNode() == node() && endPosition.deepEquivalent().node()->shadowAncestorNode() == node());
-
+ // startPosition and endPosition can be null position for example when
+ // "-webkit-user-select: none" style attribute is specified.
+ if (startPosition.isNotNull() && endPosition.isNotNull()) {
+ ASSERT(startPosition.deepEquivalent().node()->shadowAncestorNode() == node() && endPosition.deepEquivalent().node()->shadowAncestorNode() == node());
+ }
VisibleSelection newSelection = VisibleSelection(startPosition, endPosition);
if (Frame* frame = document()->frame())
@@ -326,26 +328,14 @@ String RenderTextControl::text()
if (!m_innerText)
return "";
- Frame* frame = document()->frame();
- Text* compositionNode = frame ? frame->editor()->compositionNode() : 0;
-
Vector<UChar> result;
for (Node* n = m_innerText.get(); n; n = n->traverseNextNode(m_innerText.get())) {
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();
- if (text != compositionNode)
- result.append(data.characters(), length);
- else {
- unsigned compositionStart = min(frame->editor()->compositionStart(), length);
- unsigned compositionEnd = min(max(compositionStart, frame->editor()->compositionEnd()), length);
- result.append(data.characters(), compositionStart);
- result.append(data.characters() + compositionEnd, length - compositionEnd);
- }
+ String data = static_cast<Text*>(n)->data();
+ result.append(data.characters(), data.length());
}
}
@@ -387,9 +377,6 @@ String RenderTextControl::textWithHardLineBreaks()
if (!box)
return "";
- Frame* frame = document()->frame();
- Text* compositionNode = frame ? frame->editor()->compositionNode() : 0;
-
Node* breakNode;
unsigned breakOffset;
RootInlineBox* line = box->root();
@@ -404,19 +391,7 @@ String RenderTextControl::textWithHardLineBreaks()
Text* text = static_cast<Text*>(n);
String data = text->data();
unsigned length = data.length();
- unsigned compositionStart = (text == compositionNode)
- ? min(frame->editor()->compositionStart(), length) : 0;
- unsigned compositionEnd = (text == compositionNode)
- ? min(max(compositionStart, frame->editor()->compositionEnd()), length) : 0;
unsigned position = 0;
- while (breakNode == n && breakOffset < compositionStart) {
- result.append(data.characters() + position, breakOffset - position);
- position = breakOffset;
- result.append(&newlineCharacter, 1);
- getNextSoftBreak(line, breakNode, breakOffset);
- }
- result.append(data.characters() + position, compositionStart - position);
- position = compositionEnd;
while (breakNode == n && breakOffset <= length) {
if (breakOffset > position) {
result.append(data.characters() + position, breakOffset - position);
diff --git a/WebCore/rendering/RenderTextControl.h b/WebCore/rendering/RenderTextControl.h
index bce9619..c0fc343 100644
--- a/WebCore/rendering/RenderTextControl.h
+++ b/WebCore/rendering/RenderTextControl.h
@@ -34,17 +34,6 @@ class RenderTextControl : public RenderBlock {
public:
virtual ~RenderTextControl();
- virtual const char* renderName() const { return "RenderTextControl"; }
- virtual bool isTextControl() const { return true; }
- virtual bool hasControlClip() const { return false; }
- virtual IntRect controlClipRect(int tx, int ty) const;
- virtual void calcHeight();
- virtual void calcPrefWidths();
- virtual void removeLeftoverAnonymousBlock(RenderBlock*) { }
- virtual void updateFromElement();
- virtual bool canHaveChildren() const { return false; }
- virtual bool avoidsFloats() const { return true; }
-
bool isEdited() const { return m_edited; }
void setEdited(bool isEdited) { m_edited = isEdited; }
@@ -64,10 +53,6 @@ public:
String textWithHardLineBreaks();
void selectionChanged(bool userTriggered);
- virtual void addFocusRingRects(GraphicsContext*, int tx, int ty);
-
- virtual bool canBeProgramaticallyScrolled(bool) const { return true; }
-
VisiblePosition visiblePositionForIndex(int index);
int indexForVisiblePosition(const VisiblePosition&);
@@ -92,10 +77,26 @@ protected:
virtual void cacheSelection(int start, int end) = 0;
virtual PassRefPtr<RenderStyle> createInnerTextStyle(const RenderStyle* startStyle) const = 0;
+ virtual void updateFromElement();
+ virtual void calcHeight();
+
friend class TextIterator;
HTMLElement* innerTextElement() const;
private:
+ virtual const char* renderName() const { return "RenderTextControl"; }
+ virtual bool isTextControl() const { return true; }
+ virtual bool hasControlClip() const { return false; }
+ virtual IntRect controlClipRect(int tx, int ty) const;
+ virtual void calcPrefWidths();
+ virtual void removeLeftoverAnonymousBlock(RenderBlock*) { }
+ virtual bool canHaveChildren() const { return false; }
+ virtual bool avoidsFloats() const { return true; }
+
+ virtual void addFocusRingRects(GraphicsContext*, int tx, int ty);
+
+ virtual bool canBeProgramaticallyScrolled(bool) const { return true; }
+
String finishText(Vector<UChar>&) const;
bool m_edited;
@@ -103,16 +104,16 @@ private:
RefPtr<TextControlInnerTextElement> m_innerText;
};
-inline RenderTextControl* toRenderTextControl(RenderObject* o)
+inline RenderTextControl* toRenderTextControl(RenderObject* object)
{
- ASSERT(!o || o->isTextControl());
- return static_cast<RenderTextControl*>(o);
+ ASSERT(!object || object->isTextControl());
+ return static_cast<RenderTextControl*>(object);
}
-inline const RenderTextControl* toRenderTextControl(const RenderObject* o)
+inline const RenderTextControl* toRenderTextControl(const RenderObject* object)
{
- ASSERT(!o || o->isTextControl());
- return static_cast<const RenderTextControl*>(o);
+ ASSERT(!object || object->isTextControl());
+ return static_cast<const RenderTextControl*>(object);
}
// This will catch anyone doing an unnecessary cast.
diff --git a/WebCore/rendering/RenderTextControlMultiLine.cpp b/WebCore/rendering/RenderTextControlMultiLine.cpp
index 516d812..ac790e2 100644
--- a/WebCore/rendering/RenderTextControlMultiLine.cpp
+++ b/WebCore/rendering/RenderTextControlMultiLine.cpp
@@ -51,6 +51,9 @@ void RenderTextControlMultiLine::subtreeHasChanged()
if (!node()->focused())
return;
+ // Fire the "input" DOM event
+ node()->dispatchEvent(eventNames().inputEvent, true, false);
+
if (Frame* frame = document()->frame())
frame->textDidChangeInTextArea(static_cast<Element*>(node()));
}
@@ -106,19 +109,6 @@ PassRefPtr<RenderStyle> RenderTextControlMultiLine::createInnerTextStyle(const R
textBlockStyle->inheritFrom(startStyle);
adjustInnerTextStyle(startStyle, textBlockStyle.get());
-
- // FIXME: This code should just map wrap into CSS in the DOM code.
- // Then here we should set the textBlockStyle appropriately based off this
- // object's style()->whiteSpace() and style->wordWrap().
- // Set word wrap property based on wrap attribute.
- if (static_cast<HTMLTextAreaElement*>(node())->shouldWrapText()) {
- textBlockStyle->setWhiteSpace(PRE_WRAP);
- textBlockStyle->setWordWrap(BreakWordWrap);
- } else {
- textBlockStyle->setWhiteSpace(PRE);
- textBlockStyle->setWordWrap(NormalWordWrap);
- }
-
textBlockStyle->setDisplay(BLOCK);
return textBlockStyle.release();
diff --git a/WebCore/rendering/RenderTextControlMultiLine.h b/WebCore/rendering/RenderTextControlMultiLine.h
index 579047d..7296653 100644
--- a/WebCore/rendering/RenderTextControlMultiLine.h
+++ b/WebCore/rendering/RenderTextControlMultiLine.h
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2008 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
+ * Copyright (C) 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
@@ -30,14 +31,15 @@ public:
RenderTextControlMultiLine(Node*);
virtual ~RenderTextControlMultiLine();
+ void forwardEvent(Event*);
+
+private:
virtual bool isTextArea() const { return true; }
virtual void subtreeHasChanged();
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;
@@ -48,6 +50,15 @@ private:
virtual PassRefPtr<RenderStyle> createInnerTextStyle(const RenderStyle* startStyle) const;
};
+inline RenderTextControlMultiLine* toRenderTextControlMultiLine(RenderObject* object)
+{
+ ASSERT(!object || object->isTextArea());
+ return static_cast<RenderTextControlMultiLine*>(object);
+}
+
+// This will catch anyone doing an unnecessary cast.
+void toRenderTextControlMultiLine(const RenderTextControlMultiLine*);
+
}
#endif
diff --git a/WebCore/rendering/RenderTextControlSingleLine.cpp b/WebCore/rendering/RenderTextControlSingleLine.cpp
index 0d0a5fe..b448eb7 100644
--- a/WebCore/rendering/RenderTextControlSingleLine.cpp
+++ b/WebCore/rendering/RenderTextControlSingleLine.cpp
@@ -234,17 +234,12 @@ void RenderTextControlSingleLine::layout()
int desiredHeight = textBlockHeight();
int currentHeight = innerTextRenderer->height();
- if (m_innerBlock || currentHeight > height()) {
+ if (currentHeight > height()) {
if (desiredHeight != currentHeight)
relayoutChildren = true;
innerTextRenderer->style()->setHeight(Length(desiredHeight, Fixed));
- }
-
- if (m_innerBlock) {
- ASSERT(innerBlockRenderer);
- if (desiredHeight != innerBlockRenderer->height())
- relayoutChildren = true;
- innerBlockRenderer->style()->setHeight(Length(desiredHeight, Fixed));
+ if (m_innerBlock)
+ innerBlockRenderer->style()->setHeight(Length(desiredHeight, Fixed));
}
// Set the text block width
@@ -262,13 +257,11 @@ void RenderTextControlSingleLine::layout()
RenderBlock::layoutBlock(relayoutChildren);
- // For text fields, center the inner text vertically
- // Don't do this for search fields, since we don't honor height for them
- if (!m_innerBlock) {
- currentHeight = innerTextRenderer->height();
- if (currentHeight < height())
- innerTextRenderer->setLocation(innerTextRenderer->x(), (height() - currentHeight) / 2);
- }
+ // Center the child block vertically
+ RenderBox* childBlock = innerBlockRenderer ? innerBlockRenderer : innerTextRenderer;
+ currentHeight = childBlock->height();
+ if (currentHeight < height())
+ childBlock->setLocation(childBlock->x(), (height() - currentHeight) / 2);
}
bool RenderTextControlSingleLine::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, int xPos, int yPos, int tx, int ty, HitTestAction hitTestAction)
@@ -762,8 +755,8 @@ int RenderTextControlSingleLine::selectedIndex() const
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);
+ // 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
diff --git a/WebCore/rendering/RenderTextControlSingleLine.h b/WebCore/rendering/RenderTextControlSingleLine.h
index 23352b4..da9838f 100644
--- a/WebCore/rendering/RenderTextControlSingleLine.h
+++ b/WebCore/rendering/RenderTextControlSingleLine.h
@@ -1,4 +1,5 @@
/*
+ * Copyright (C) 2006, 2007, 2009 Apple Inc. All rights reserved.
* Copyright (C) 2008 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
*
* This library is free software; you can redistribute it and/or
@@ -38,9 +39,6 @@ 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();
@@ -52,14 +50,19 @@ public:
void showPopup();
virtual void hidePopup(); // PopupMenuClient method
+ void forwardEvent(Event*);
+
+ void capsLockStateMayHaveChanged();
+
+private:
+ virtual bool hasControlClip() const { return m_cancelButton; }
+ virtual bool isTextField() const { return true; }
+
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*);
-
- void capsLockStateMayHaveChanged();
virtual void autoscroll();
@@ -72,7 +75,6 @@ public:
virtual void setScrollTop(int);
virtual bool scroll(ScrollDirection, ScrollGranularity, float multiplier = 1.0f);
-private:
int textBlockWidth() const;
virtual int preferredContentWidth(float charWidth) const;
virtual void adjustControlHeightBasedOnLineHeight(int lineHeight);
@@ -94,10 +96,10 @@ private:
void startSearchEventTimer();
void searchEventTimerFired(Timer<RenderTextControlSingleLine>*);
-private:
// PopupMenuClient methods
virtual void valueChanged(unsigned listIndex, bool fireEvents = true);
virtual String itemText(unsigned listIndex) const;
+ virtual String itemToolTip(unsigned) const { return String(); }
virtual bool itemIsEnabled(unsigned listIndex) const;
virtual PopupMenuStyle itemStyle(unsigned listIndex) const;
virtual PopupMenuStyle menuStyle() const;
@@ -119,7 +121,6 @@ private:
InputElement* inputElement() const;
-private:
bool m_placeholderVisible;
bool m_searchPopupIsVisible;
bool m_shouldDrawCapsLockIndicator;
@@ -133,6 +134,15 @@ private:
Vector<String> m_recentSearches;
};
+inline RenderTextControlSingleLine* toRenderTextControlSingleLine(RenderObject* object)
+{
+ ASSERT(!object || object->isTextField());
+ return static_cast<RenderTextControlSingleLine*>(object);
+}
+
+// This will catch anyone doing an unnecessary cast.
+void toRenderTextControlSingleLine(const RenderTextControlSingleLine*);
+
}
#endif
diff --git a/WebCore/rendering/RenderTheme.cpp b/WebCore/rendering/RenderTheme.cpp
index 4aaf9be..63e7d45 100644
--- a/WebCore/rendering/RenderTheme.cpp
+++ b/WebCore/rendering/RenderTheme.cpp
@@ -42,6 +42,12 @@ namespace WebCore {
using namespace HTMLNames;
+static Color& customFocusRingColor()
+{
+ DEFINE_STATIC_LOCAL(Color, color, ());
+ return color;
+}
+
RenderTheme::RenderTheme()
#if USE(NEW_THEME)
: m_theme(platformTheme())
@@ -62,7 +68,7 @@ void RenderTheme::adjustStyle(CSSStyleSelector* selector, RenderStyle* style, El
else if (style->display() == COMPACT || style->display() == RUN_IN || style->display() == LIST_ITEM || style->display() == TABLE)
style->setDisplay(BLOCK);
- if (UAHasAppearance && theme()->isControlStyled(style, border, background, backgroundColor)) {
+ if (UAHasAppearance && isControlStyled(style, border, background, backgroundColor)) {
if (part == MenulistPart) {
style->setAppearance(MenulistButtonPart);
part = MenulistButtonPart;
@@ -266,6 +272,10 @@ bool RenderTheme::paint(RenderObject* o, const RenderObject::PaintInfo& paintInf
return paintMediaSeekBackButton(o, paintInfo, r);
case MediaSeekForwardButtonPart:
return paintMediaSeekForwardButton(o, paintInfo, r);
+ case MediaRewindButtonPart:
+ return paintMediaRewindButton(o, paintInfo, r);
+ case MediaReturnToRealtimeButtonPart:
+ return paintMediaReturnToRealtimeButton(o, paintInfo, r);
case MediaSliderPart:
return paintMediaSliderTrack(o, paintInfo, r);
case MediaSliderThumbPart:
@@ -276,8 +286,8 @@ bool RenderTheme::paint(RenderObject* o, const RenderObject::PaintInfo& paintInf
return paintMediaTimeRemaining(o, paintInfo, r);
case MediaCurrentTimePart:
return paintMediaCurrentTime(o, paintInfo, r);
- case MediaTimelineContainerPart:
- return paintMediaTimelineContainer(o, paintInfo, r);
+ case MediaControlsBackgroundPart:
+ return paintMediaControlsBackground(o, paintInfo, r);
case MenulistButtonPart:
case TextFieldPart:
case TextAreaPart:
@@ -313,6 +323,7 @@ bool RenderTheme::paintBorderOnly(RenderObject* o, const RenderObject::PaintInfo
case TextAreaPart:
return paintTextArea(o, paintInfo, r);
case MenulistButtonPart:
+ case SearchFieldPart:
return true;
case CheckboxPart:
case RadioPart:
@@ -325,7 +336,6 @@ bool RenderTheme::paintBorderOnly(RenderObject* o, const RenderObject::PaintInfo
case SliderVerticalPart:
case SliderThumbHorizontalPart:
case SliderThumbVerticalPart:
- case SearchFieldPart:
case SearchFieldCancelButtonPart:
case SearchFieldDecorationPart:
case SearchFieldResultsDecorationPart:
@@ -853,4 +863,14 @@ Color RenderTheme::platformInactiveTextSearchHighlightColor() const
return Color(255, 255, 0); // Yellow.
}
+void RenderTheme::setCustomFocusRingColor(const Color& c)
+{
+ customFocusRingColor() = c;
+}
+
+Color RenderTheme::focusRingColor()
+{
+ return customFocusRingColor().isValid() ? customFocusRingColor() : defaultTheme()->platformFocusRingColor();
+}
+
} // namespace WebCore
diff --git a/WebCore/rendering/RenderTheme.h b/WebCore/rendering/RenderTheme.h
index 450e2f6..4f37015 100644
--- a/WebCore/rendering/RenderTheme.h
+++ b/WebCore/rendering/RenderTheme.h
@@ -23,13 +23,16 @@
#ifndef RenderTheme_h
#define RenderTheme_h
-#include "RenderObject.h"
#if USE(NEW_THEME)
#include "Theme.h"
#else
#include "ThemeTypes.h"
#endif
+#include "RenderObject.h"
+#include "RenderTheme.h"
#include "ScrollTypes.h"
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefCounted.h>
namespace WebCore {
@@ -38,11 +41,24 @@ class PopupMenu;
class RenderMenuList;
class CSSStyleSheet;
-class RenderTheme {
-public:
+class RenderTheme : public RefCounted<RenderTheme> {
+protected:
RenderTheme();
+
+public:
virtual ~RenderTheme() { }
+ // This function is to be implemented in your platform-specific theme implementation to hand back the
+ // appropriate platform theme. When the theme is needed in non-page dependent code, a default theme is
+ // used as fallback, which is returned for a nulled page, so the platform code needs to account for this.
+ static PassRefPtr<RenderTheme> themeForPage(Page* page);
+
+ // When the theme is needed in non-page dependent code, the defaultTheme() is used as fallback.
+ static inline PassRefPtr<RenderTheme> defaultTheme()
+ {
+ return themeForPage(0);
+ };
+
// This method is called whenever style has been computed for an element and the appearance
// property has been set to a value other than "none". The theme should map in all of the appropriate
// metrics and defaults given the contents of the style. This includes sophisticated operations like
@@ -62,7 +78,7 @@ public:
// 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
+ // adjust the default CSS rules in html.css, quirks.css, or mediaControls.css
virtual String extraDefaultStyleSheet() { return String(); }
virtual String extraQuirksStyleSheet() { return String(); }
#if ENABLE(VIDEO)
@@ -121,6 +137,10 @@ public:
virtual Color platformActiveTextSearchHighlightColor() const;
virtual Color platformInactiveTextSearchHighlightColor() const;
+ static Color focusRingColor();
+ virtual Color platformFocusRingColor() const { return Color(0, 0, 0); }
+ static void setCustomFocusRingColor(const Color&);
+
virtual void platformColorsDidChange();
virtual double caretBlinkInterval() const { return 0.5; }
@@ -227,7 +247,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 paintMediaRewindButton(RenderObject*, const RenderObject::PaintInfo&, const IntRect&) { return true; }
+ virtual bool paintMediaReturnToRealtimeButton(RenderObject*, const RenderObject::PaintInfo&, const IntRect&) { return true; }
+ virtual bool paintMediaControlsBackground(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; }
@@ -260,10 +282,6 @@ private:
#endif
};
-// Function to obtain the theme. This is implemented in your platform-specific theme implementation to hand
-// back the appropriate platform theme.
-RenderTheme* theme();
-
} // namespace WebCore
#endif // RenderTheme_h
diff --git a/WebCore/rendering/RenderThemeChromiumLinux.cpp b/WebCore/rendering/RenderThemeChromiumLinux.cpp
index 8049403..c4020d3 100644
--- a/WebCore/rendering/RenderThemeChromiumLinux.cpp
+++ b/WebCore/rendering/RenderThemeChromiumLinux.cpp
@@ -3,6 +3,7 @@
* Copyright (C) 2007 Alp Toker <alp@atoker.com>
* Copyright (C) 2008 Collabora Ltd.
* Copyright (C) 2008, 2009 Google Inc.
+ * Copyright (C) 2009 Kenneth Rohde Christiansen
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -24,102 +25,29 @@
#include "config.h"
#include "RenderThemeChromiumLinux.h"
-#include "ChromiumBridge.h"
+#include "Color.h"
#include "CSSValueKeywords.h"
-#include "GraphicsContext.h"
-#include "HTMLMediaElement.h"
-#include "HTMLNames.h"
-#include "Image.h"
-#include "MediaControlElements.h"
-#include "PlatformContextSkia.h"
-#include "RenderBox.h"
#include "RenderObject.h"
-#include "ScrollbarTheme.h"
-#include "TransformationMatrix.h"
#include "UserAgentStyleSheets.h"
-#include "SkShader.h"
-#include "SkGradientShader.h"
-
namespace WebCore {
-enum PaddingType {
- TopPadding,
- RightPadding,
- BottomPadding,
- LeftPadding
-};
-
-static const int styledMenuListInternalPadding[4] = { 1, 4, 1, 4 };
-
-// The 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 const float defaultFontSize = 16.0;
-
-// The background for the media player controls should be a 60% opaque black rectangle. This
-// matches the UI mockups for the default UI theme.
-static const float defaultMediaControlOpacity = 0.6f;
-
-// These values all match Safari/Win.
-static const float defaultControlFontPixelSize = 13;
-static const float defaultCancelButtonSize = 9;
-static const float minCancelButtonSize = 5;
-static const float maxCancelButtonSize = 21;
-static const float defaultSearchFieldResultsDecorationSize = 13;
-static const float minSearchFieldResultsDecorationSize = 9;
-static const float maxSearchFieldResultsDecorationSize = 30;
-static const float defaultSearchFieldResultsButtonWidth = 18;
-
-static bool supportsFocus(ControlPart appearance)
+PassRefPtr<RenderTheme> RenderThemeChromiumLinux::create()
{
- // This causes WebKit to draw the focus rings for us.
- return false;
+ return adoptRef(new RenderThemeChromiumLinux());
}
-static void setSizeIfAuto(RenderStyle* style, const IntSize& size)
+PassRefPtr<RenderTheme> RenderTheme::themeForPage(Page* page)
{
- if (style->width().isIntrinsicOrAuto())
- style->setWidth(Length(size.width(), Fixed));
- if (style->height().isAuto())
- style->setHeight(Length(size.height(), Fixed));
+ static RenderTheme* rt = RenderThemeChromiumLinux::create().releaseRef();
+ return rt;
}
-// 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()
-{
- return "Arial";
-}
-
-#if ENABLE(VIDEO)
-// Attempt to retrieve a HTMLMediaElement from a Node. Returns NULL if one cannot be found.
-static HTMLMediaElement* mediaElementParent(Node* node)
-{
- if (!node)
- return 0;
- Node* mediaNode = node->shadowAncestorNode();
- if (!mediaNode || (!mediaNode->hasTagName(HTMLNames::videoTag) && !mediaNode->hasTagName(HTMLNames::audioTag)))
- return 0;
-
- return static_cast<HTMLMediaElement*>(mediaNode);
-}
-#endif
-
-RenderTheme* theme()
+RenderThemeChromiumLinux::RenderThemeChromiumLinux()
{
- static RenderThemeChromiumLinux theme;
- return &theme;
}
-RenderThemeChromiumLinux::RenderThemeChromiumLinux()
+RenderThemeChromiumLinux::~RenderThemeChromiumLinux()
{
}
@@ -132,465 +60,12 @@ Color RenderThemeChromiumLinux::systemColor(int cssValueId) const
return RenderTheme::systemColor(cssValueId);
}
-// Use the Windows style sheets to match their metrics.
String RenderThemeChromiumLinux::extraDefaultStyleSheet()
{
- return String(themeWinUserAgentStyleSheet, sizeof(themeWinUserAgentStyleSheet)) +
+ return RenderThemeChromiumSkia::extraDefaultStyleSheet() +
String(themeChromiumLinuxUserAgentStyleSheet, sizeof(themeChromiumLinuxUserAgentStyleSheet));
}
-String RenderThemeChromiumLinux::extraQuirksStyleSheet()
-{
- return String(themeWinQuirksUserAgentStyleSheet, sizeof(themeWinQuirksUserAgentStyleSheet));
-}
-
-#if ENABLE(VIDEO)
-String RenderThemeChromiumLinux::extraMediaControlsStyleSheet()
-{
- return String(mediaControlsChromiumUserAgentStyleSheet, sizeof(mediaControlsChromiumUserAgentStyleSheet));
-}
-#endif
-
-bool RenderThemeChromiumLinux::supportsFocusRing(const RenderStyle* style) const
-{
- return supportsFocus(style->appearance());
-}
-
-Color RenderThemeChromiumLinux::platformActiveSelectionBackgroundColor() const
-{
- return Color(0x1e, 0x90, 0xff);
-}
-
-Color RenderThemeChromiumLinux::platformInactiveSelectionBackgroundColor() const
-{
- return Color(0xc8, 0xc8, 0xc8);
-}
-
-Color RenderThemeChromiumLinux::platformActiveSelectionForegroundColor() const
-{
- return Color::black;
-}
-
-Color RenderThemeChromiumLinux::platformInactiveSelectionForegroundColor() const
-{
- return Color(0x32, 0x32, 0x32);
-}
-
-Color RenderThemeChromiumLinux::platformTextSearchHighlightColor() const
-{
- return Color(0xff, 0xff, 0x96);
-}
-
-double RenderThemeChromiumLinux::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.
- return 0.5;
-}
-
-void RenderThemeChromiumLinux::systemFont(int propId, FontDescription& fontDescription) const
-{
- float fontSize = defaultFontSize;
-
- switch (propId) {
- case CSSValueWebkitMiniControl:
- case CSSValueWebkitSmallControl:
- case CSSValueWebkitControl:
- // Why 2 points smaller? Because that's what Gecko does. Note that we
- // are assuming a 96dpi screen, which is the default that we use on
- // Windows.
- static const float pointsPerInch = 72.0f;
- static const float pixelsPerInch = 96.0f;
- fontSize -= (2.0f / pointsPerInch) * pixelsPerInch;
- break;
- }
-
- fontDescription.firstFamily().setFamily(defaultGUIFont());
- fontDescription.setSpecifiedSize(fontSize);
- fontDescription.setIsAbsoluteSize(true);
- fontDescription.setGenericFamily(FontDescription::NoFamily);
- fontDescription.setWeight(FontWeightNormal);
- fontDescription.setItalic(false);
-}
-
-int RenderThemeChromiumLinux::minimumMenuListSize(RenderStyle* style) const
-{
- return 0;
-}
-
-bool RenderThemeChromiumLinux::paintCheckbox(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& rect)
-{
- static Image* const checkedImage = Image::loadPlatformResource("linuxCheckboxOn").releaseRef();
- static Image* const uncheckedImage = Image::loadPlatformResource("linuxCheckboxOff").releaseRef();
-
- Image* image = this->isChecked(o) ? checkedImage : uncheckedImage;
- i.context->drawImage(image, rect);
- return false;
-}
-
-void RenderThemeChromiumLinux::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 RenderThemeChromiumLinux::paintRadio(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& rect)
-{
- static Image* const checkedImage = Image::loadPlatformResource("linuxRadioOn").releaseRef();
- static Image* const uncheckedImage = Image::loadPlatformResource("linuxRadioOff").releaseRef();
-
- Image* image = this->isChecked(o) ? checkedImage : uncheckedImage;
- i.context->drawImage(image, rect);
- return false;
-}
-
-void RenderThemeChromiumLinux::setRadioSize(RenderStyle* style) const
-{
- // Use same sizing for radio box as checkbox.
- setCheckboxSize(style);
-}
-
-static SkColor brightenColor(double h, double s, double l, float brightenAmount)
-{
- l += brightenAmount;
- if (l > 1.0)
- l = 1.0;
- if (l < 0.0)
- l = 0.0;
-
- return makeRGBAFromHSLA(h, s, l, 1.0);
-}
-
-static void paintButtonLike(RenderTheme* theme, RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& rect)
-{
- SkCanvas* const canvas = i.context->platformContext()->canvas();
- SkPaint paint;
- SkRect skrect;
- const int right = rect.x() + rect.width();
- const int bottom = rect.y() + rect.height();
- SkColor baseColor = SkColorSetARGB(0xff, 0xdd, 0xdd, 0xdd);
- if (o->style()->hasBackground())
- baseColor = o->style()->backgroundColor().rgb();
- double h, s, l;
- Color(baseColor).getHSL(h, s, l);
- // Our standard gradient is from 0xdd to 0xf8. This is the amount of
- // increased luminance between those values.
- SkColor lightColor(brightenColor(h, s, l, 0.105));
-
- // If the button is too small, fallback to drawing a single, solid color
- if (rect.width() < 5 || rect.height() < 5) {
- paint.setColor(baseColor);
- skrect.set(rect.x(), rect.y(), right, bottom);
- canvas->drawRect(skrect, paint);
- return;
- }
-
- const int borderAlpha = theme->isHovered(o) ? 0x80 : 0x55;
- paint.setARGB(borderAlpha, 0, 0, 0);
- canvas->drawLine(rect.x() + 1, rect.y(), right - 1, rect.y(), paint);
- canvas->drawLine(right - 1, rect.y() + 1, right - 1, bottom - 1, paint);
- canvas->drawLine(rect.x() + 1, bottom - 1, right - 1, bottom - 1, paint);
- canvas->drawLine(rect.x(), rect.y() + 1, rect.x(), bottom - 1, paint);
-
- paint.setARGB(0xff, 0, 0, 0);
- SkPoint p[2];
- const int lightEnd = theme->isPressed(o) ? 1 : 0;
- const int darkEnd = !lightEnd;
- p[lightEnd].set(SkIntToScalar(rect.x()), SkIntToScalar(rect.y()));
- p[darkEnd].set(SkIntToScalar(rect.x()), SkIntToScalar(bottom - 1));
- SkColor colors[2];
- colors[0] = lightColor;
- colors[1] = baseColor;
-
- SkShader* shader = SkGradientShader::CreateLinear(
- p, colors, NULL, 2, SkShader::kClamp_TileMode, NULL);
- paint.setStyle(SkPaint::kFill_Style);
- paint.setShader(shader);
- shader->unref();
-
- skrect.set(rect.x() + 1, rect.y() + 1, right - 1, bottom - 1);
- canvas->drawRect(skrect, paint);
-
- paint.setShader(NULL);
- paint.setColor(brightenColor(h, s, l, -0.0588));
- canvas->drawPoint(rect.x() + 1, rect.y() + 1, paint);
- canvas->drawPoint(right - 2, rect.y() + 1, paint);
- canvas->drawPoint(rect.x() + 1, bottom - 2, paint);
- canvas->drawPoint(right - 2, bottom - 2, paint);
-}
-
-bool RenderThemeChromiumLinux::paintButton(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& rect)
-{
- paintButtonLike(this, o, i, rect);
- return false;
-}
-
-bool RenderThemeChromiumLinux::paintTextField(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& rect)
-{
- return true;
-}
-
-void RenderThemeChromiumLinux::adjustSearchFieldCancelButtonStyle(CSSStyleSelector*, RenderStyle* style, Element*) const
-{
- // Scale the button size based on the font size
- float fontScale = style->fontSize() / defaultControlFontPixelSize;
- int cancelButtonSize = lroundf(std::min(std::max(minCancelButtonSize, defaultCancelButtonSize * fontScale), maxCancelButtonSize));
- style->setWidth(Length(cancelButtonSize, Fixed));
- style->setHeight(Length(cancelButtonSize, Fixed));
-}
-
-bool RenderThemeChromiumLinux::paintSearchFieldCancelButton(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& r)
-{
- IntRect bounds = r;
- ASSERT(o->parent());
- if (!o->parent() || !o->parent()->isBox())
- return false;
-
- RenderBox* parentRenderBox = toRenderBox(o->parent());
-
- IntRect parentBox = parentRenderBox->absoluteContentBox();
-
- // Make sure the scaled button stays square and will fit in its parent's box
- bounds.setHeight(std::min(parentBox.width(), std::min(parentBox.height(), bounds.height())));
- bounds.setWidth(bounds.height());
-
- // Center the button vertically. Round up though, so if it has to be one pixel off-center, it will
- // be one pixel closer to the bottom of the field. This tends to look better with the text.
- bounds.setY(parentBox.y() + (parentBox.height() - bounds.height() + 1) / 2);
-
- static Image* cancelImage = Image::loadPlatformResource("searchCancel").releaseRef();
- static Image* cancelPressedImage = Image::loadPlatformResource("searchCancelPressed").releaseRef();
- i.context->drawImage(isPressed(o) ? cancelPressedImage : cancelImage, bounds);
- return false;
-}
-
-void RenderThemeChromiumLinux::adjustSearchFieldDecorationStyle(CSSStyleSelector*, RenderStyle* style, Element*) const
-{
- IntSize emptySize(1, 11);
- style->setWidth(Length(emptySize.width(), Fixed));
- style->setHeight(Length(emptySize.height(), Fixed));
-}
-
-void RenderThemeChromiumLinux::adjustSearchFieldResultsDecorationStyle(CSSStyleSelector*, RenderStyle* style, Element*) const
-{
- // Scale the decoration size based on the font size
- float fontScale = style->fontSize() / defaultControlFontPixelSize;
- int magnifierSize = lroundf(std::min(std::max(minSearchFieldResultsDecorationSize, defaultSearchFieldResultsDecorationSize * fontScale),
- maxSearchFieldResultsDecorationSize));
- style->setWidth(Length(magnifierSize, Fixed));
- style->setHeight(Length(magnifierSize, Fixed));
-}
-
-bool RenderThemeChromiumLinux::paintSearchFieldResultsDecoration(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& r)
-{
- IntRect bounds = r;
- ASSERT(o->parent());
- if (!o->parent() || !o->parent()->isBox())
- return false;
-
- RenderBox* parentRenderBox = toRenderBox(o->parent());
- IntRect parentBox = parentRenderBox->absoluteContentBox();
-
- // Make sure the scaled decoration stays square and will fit in its parent's box
- bounds.setHeight(std::min(parentBox.width(), std::min(parentBox.height(), bounds.height())));
- bounds.setWidth(bounds.height());
-
- // Center the decoration vertically. Round up though, so if it has to be one pixel off-center, it will
- // be one pixel closer to the bottom of the field. This tends to look better with the text.
- bounds.setY(parentBox.y() + (parentBox.height() - bounds.height() + 1) / 2);
-
- static Image* magnifierImage = Image::loadPlatformResource("searchMagnifier").releaseRef();
- i.context->drawImage(magnifierImage, bounds);
- return false;
-}
-
-void RenderThemeChromiumLinux::adjustSearchFieldResultsButtonStyle(CSSStyleSelector*, RenderStyle* style, Element*) const
-{
- // Scale the button size based on the font size
- float fontScale = style->fontSize() / defaultControlFontPixelSize;
- int magnifierHeight = lroundf(std::min(std::max(minSearchFieldResultsDecorationSize, defaultSearchFieldResultsDecorationSize * fontScale),
- maxSearchFieldResultsDecorationSize));
- int magnifierWidth = lroundf(magnifierHeight * defaultSearchFieldResultsButtonWidth / defaultSearchFieldResultsDecorationSize);
- style->setWidth(Length(magnifierWidth, Fixed));
- style->setHeight(Length(magnifierHeight, Fixed));
-}
-
-bool RenderThemeChromiumLinux::paintSearchFieldResultsButton(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& r)
-{
- IntRect bounds = r;
- ASSERT(o->parent());
- if (!o->parent())
- return false;
- if (!o->parent() || !o->parent()->isBox())
- return false;
-
- RenderBox* parentRenderBox = toRenderBox(o->parent());
- IntRect parentBox = parentRenderBox->absoluteContentBox();
-
- // Make sure the scaled decoration will fit in its parent's box
- bounds.setHeight(std::min(parentBox.height(), bounds.height()));
- bounds.setWidth(std::min(parentBox.width(), static_cast<int>(bounds.height() * defaultSearchFieldResultsButtonWidth / defaultSearchFieldResultsDecorationSize)));
-
- // Center the button vertically. Round up though, so if it has to be one pixel off-center, it will
- // be one pixel closer to the bottom of the field. This tends to look better with the text.
- bounds.setY(parentBox.y() + (parentBox.height() - bounds.height() + 1) / 2);
-
- static Image* magnifierImage = Image::loadPlatformResource("searchMagnifierResults").releaseRef();
- i.context->drawImage(magnifierImage, bounds);
- return false;
-}
-
-bool RenderThemeChromiumLinux::paintMediaButtonInternal(GraphicsContext* context, const IntRect& rect, Image* image)
-{
- context->beginTransparencyLayer(defaultMediaControlOpacity);
-
- // Draw background.
- Color oldFill = context->fillColor();
- Color oldStroke = context->strokeColor();
-
- context->setFillColor(Color::black);
- context->setStrokeColor(Color::black);
- context->drawRect(rect);
-
- context->setFillColor(oldFill);
- context->setStrokeColor(oldStroke);
-
- // Create a destination rectangle for the image that is centered in the drawing rectangle, rounded left, and down.
- IntRect imageRect = image->rect();
- imageRect.setY(rect.y() + (rect.height() - image->height() + 1) / 2);
- imageRect.setX(rect.x() + (rect.width() - image->width() + 1) / 2);
-
- context->drawImage(image, imageRect, CompositeSourceAtop);
- context->endTransparencyLayer();
-
- return false;
-}
-
-bool RenderThemeChromiumLinux::paintMediaPlayButton(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& rect)
-{
-#if ENABLE(VIDEO)
- HTMLMediaElement* mediaElement = mediaElementParent(o->node());
- if (!mediaElement)
- return false;
-
- static Image* mediaPlay = Image::loadPlatformResource("mediaPlay").releaseRef();
- static Image* mediaPause = Image::loadPlatformResource("mediaPause").releaseRef();
-
- return paintMediaButtonInternal(paintInfo.context, rect, mediaElement->paused() ? mediaPlay : mediaPause);
-#else
- return false;
-#endif
-}
-
-bool RenderThemeChromiumLinux::paintMediaMuteButton(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& rect)
-{
-#if ENABLE(VIDEO)
- HTMLMediaElement* mediaElement = mediaElementParent(o->node());
- if (!mediaElement)
- return false;
-
- static Image* soundFull = Image::loadPlatformResource("mediaSoundFull").releaseRef();
- static Image* soundNone = Image::loadPlatformResource("mediaSoundNone").releaseRef();
-
- return paintMediaButtonInternal(paintInfo.context, rect, mediaElement->muted() ? soundNone: soundFull);
-#else
- return false;
-#endif
-}
-
-void RenderThemeChromiumLinux::adjustMenuListStyle(CSSStyleSelector* selector, RenderStyle* style, WebCore::Element* e) const
-{
- // Height is locked to auto on all browsers.
- style->setLineHeight(RenderStyle::initialLineHeight());
-}
-
-bool RenderThemeChromiumLinux::paintMenuList(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& rect)
-{
- SkCanvas* const canvas = i.context->platformContext()->canvas();
- const int right = rect.x() + rect.width();
- const int middle = rect.y() + rect.height() / 2;
-
- paintButtonLike(this, o, i, rect);
-
- SkPaint paint;
- paint.setARGB(0xff, 0, 0, 0);
- paint.setAntiAlias(true);
- paint.setStyle(SkPaint::kFill_Style);
-
- SkPath path;
- path.moveTo(right - 13, middle - 3);
- path.rLineTo(6, 0);
- path.rLineTo(-3, 6);
- path.close();
- canvas->drawPath(path, paint);
-
- return false;
-}
-
-void RenderThemeChromiumLinux::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 RenderThemeChromiumLinux::paintMenuListButton(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& rect)
-{
- return paintMenuList(o, i, rect);
-}
-
-int RenderThemeChromiumLinux::popupInternalPaddingLeft(RenderStyle* style) const
-{
- return menuListInternalPadding(style, LeftPadding);
-}
-
-int RenderThemeChromiumLinux::popupInternalPaddingRight(RenderStyle* style) const
-{
- return menuListInternalPadding(style, RightPadding);
-}
-
-int RenderThemeChromiumLinux::popupInternalPaddingTop(RenderStyle* style) const
-{
- return menuListInternalPadding(style, TopPadding);
-}
-
-int RenderThemeChromiumLinux::popupInternalPaddingBottom(RenderStyle* style) const
-{
- return menuListInternalPadding(style, BottomPadding);
-}
-
-int RenderThemeChromiumLinux::buttonInternalPaddingLeft() const
-{
- return 3;
-}
-
-int RenderThemeChromiumLinux::buttonInternalPaddingRight() const
-{
- return 3;
-}
-
-int RenderThemeChromiumLinux::buttonInternalPaddingTop() const
-{
- return 1;
-}
-
-int RenderThemeChromiumLinux::buttonInternalPaddingBottom() const
-{
- return 1;
-}
-
bool RenderThemeChromiumLinux::controlSupportsTints(const RenderObject* o) const
{
return isEnabled(o);
@@ -616,22 +91,9 @@ Color RenderThemeChromiumLinux::inactiveListBoxSelectionForegroundColor() const
return Color(0x32, 0x32, 0x32);
}
-int RenderThemeChromiumLinux::menuListInternalPadding(RenderStyle* style, int paddingType) const
+bool RenderThemeChromiumLinux::supportsControlTints() 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;
+ return true;
}
-} // namespace WebCore
+} // namespace WebCore
diff --git a/WebCore/rendering/RenderThemeChromiumLinux.h b/WebCore/rendering/RenderThemeChromiumLinux.h
index 11239d9..e75ddd5 100644
--- a/WebCore/rendering/RenderThemeChromiumLinux.h
+++ b/WebCore/rendering/RenderThemeChromiumLinux.h
@@ -7,6 +7,7 @@
* Copyright (C) 2007 Alp Toker <alp@atoker.com>
* Copyright (C) 2008, 2009 Google, Inc.
* All rights reserved.
+ * Copyright (C) 2009 Kenneth Rohde Christiansen
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -28,101 +29,20 @@
#ifndef RenderThemeChromiumLinux_h
#define RenderThemeChromiumLinux_h
-#include "RenderTheme.h"
+#include "RenderThemeChromiumSkia.h"
namespace WebCore {
- class RenderThemeChromiumLinux : public RenderTheme {
+ class RenderThemeChromiumLinux : public RenderThemeChromiumSkia {
public:
- RenderThemeChromiumLinux();
- ~RenderThemeChromiumLinux() { }
-
+ static PassRefPtr<RenderTheme> create();
virtual String extraDefaultStyleSheet();
- virtual String extraQuirksStyleSheet();
-#if ENABLE(VIDEO)
- virtual String extraMediaControlsStyleSheet();
-#endif
-
- // A method asking if the theme's controls actually care about redrawing when hovered.
- virtual bool supportsHover(const RenderStyle*) const { 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, FontDescription&) const;
virtual Color systemColor(int cssValidId) 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* o, const RenderObject::PaintInfo& i, const IntRect& r) { return paintTextField(o, i, r); }
-
- virtual void adjustSearchFieldCancelButtonStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
- virtual bool paintSearchFieldCancelButton(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
-
- virtual void adjustSearchFieldDecorationStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
-
- virtual void adjustSearchFieldResultsDecorationStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
- virtual bool paintSearchFieldResultsDecoration(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
-
- virtual void adjustSearchFieldResultsButtonStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
- virtual bool paintSearchFieldResultsButton(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
-
- virtual bool paintMediaPlayButton(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
- virtual bool paintMediaMuteButton(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
-
- // MenuList refers to an unstyled menulist (meaning a menulist without
- // background-color or border set) and MenuListButton refers to a styled
- // menulist (a menulist with background-color or border set). They have
- // this distinction to support showing aqua style themes whenever they
- // possibly can, which is something we don't want to replicate.
- //
- // In short, we either go down the MenuList code path or the MenuListButton
- // codepath. We never go down both. And in both cases, they render the
- // entire menulist.
- virtual void adjustMenuListStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
- virtual bool paintMenuList(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
- virtual void adjustMenuListButtonStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
- virtual bool paintMenuListButton(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
-
- // These methods define the padding for the MenuList's inner block.
- virtual int popupInternalPaddingLeft(RenderStyle*) const;
- virtual int popupInternalPaddingRight(RenderStyle*) const;
- virtual int popupInternalPaddingTop(RenderStyle*) const;
- virtual int popupInternalPaddingBottom(RenderStyle*) const;
-
- virtual int buttonInternalPaddingLeft() const;
- virtual int buttonInternalPaddingRight() const;
- virtual int buttonInternalPaddingTop() const;
- virtual int buttonInternalPaddingBottom() const;
-
// 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;
@@ -130,10 +50,13 @@ namespace WebCore {
virtual Color inactiveListBoxSelectionForegroundColor() const;
private:
- int menuListInternalPadding(RenderStyle*, int paddingType) const;
- bool paintMediaButtonInternal(GraphicsContext*, const IntRect&, Image*);
+ RenderThemeChromiumLinux();
+ virtual ~RenderThemeChromiumLinux();
+
+ // A general method asking if any control tinting is supported at all.
+ virtual bool supportsControlTints() const;
};
} // namespace WebCore
-#endif
+#endif // RenderThemeChromiumLinux_h
diff --git a/WebCore/rendering/RenderThemeChromiumMac.h b/WebCore/rendering/RenderThemeChromiumMac.h
index f072000..ffb2548 100644
--- a/WebCore/rendering/RenderThemeChromiumMac.h
+++ b/WebCore/rendering/RenderThemeChromiumMac.h
@@ -3,6 +3,7 @@
*
* Copyright (C) 2005 Apple Computer, Inc.
* Copyright (C) 2008, 2009 Google, Inc.
+ * Copyright (C) 2009 Kenneth Rohde Christiansen
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -41,8 +42,7 @@ namespace WebCore {
class RenderThemeChromiumMac : public RenderTheme {
public:
- RenderThemeChromiumMac();
- virtual ~RenderThemeChromiumMac();
+ static PassRefPtr<RenderTheme> create();
// A method to obtain the baseline position for a "leaf" control. This will only be used if a baseline
// position cannot be determined by examining child content. Checkboxes and radio buttons are examples of
@@ -62,7 +62,9 @@ namespace WebCore {
virtual Color platformActiveSelectionBackgroundColor() const;
virtual Color platformInactiveSelectionBackgroundColor() const;
- virtual Color activeListBoxSelectionBackgroundColor() const;
+ virtual Color platformActiveListBoxSelectionBackgroundColor() const;
+
+ virtual Color platformFocusRingColor() const;
virtual void platformColorsDidChange();
@@ -140,6 +142,9 @@ namespace WebCore {
virtual bool paintMediaSliderThumb(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
private:
+ RenderThemeChromiumMac();
+ virtual ~RenderThemeChromiumMac();
+
IntRect inflateRect(const IntRect&, const IntSize&, const int* margins, float zoomLevel = 1.0f) const;
// Get the control size based off the font. Used by some of the controls (like buttons).
diff --git a/WebCore/rendering/RenderThemeChromiumMac.mm b/WebCore/rendering/RenderThemeChromiumMac.mm
index f6081a5..23201c9 100644
--- a/WebCore/rendering/RenderThemeChromiumMac.mm
+++ b/WebCore/rendering/RenderThemeChromiumMac.mm
@@ -1,6 +1,7 @@
/*
* Copyright (C) 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
* Copyright (C) 2008, 2009 Google, Inc.
+ * Copyright (C) 2009 Kenneth Rohde Christiansen
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -31,6 +32,8 @@
#import <math.h>
#import "BitmapImage.h"
+#import "ChromiumBridge.h"
+#import "ColorMac.h"
#import "CSSStyleSelector.h"
#import "CSSValueKeywords.h"
#import "Element.h"
@@ -43,6 +46,7 @@
#import "Image.h"
#import "LocalCurrentGraphicsContext.h"
#import "MediaControlElements.h"
+#import "RenderMedia.h"
#import "RenderSlider.h"
#import "RenderView.h"
#import "SharedBuffer.h"
@@ -124,10 +128,15 @@ IntRect NSRectToIntRect(const NSRect & rect)
return IntRect(rect.origin.x, rect.origin.y, rect.size.width, rect.size.height);
}
-RenderTheme* theme()
+PassRefPtr<RenderTheme> RenderThemeChromiumMac::create()
{
- static RenderThemeChromiumMac* macTheme = new RenderThemeChromiumMac;
- return macTheme;
+ return adoptRef(new RenderThemeChromiumMac);
+}
+
+PassRefPtr<RenderTheme> RenderTheme::themeForPage(Page* page)
+{
+ static RenderTheme* rt = RenderThemeChromiumMac::create().releaseRef();
+ return rt;
}
RenderThemeChromiumMac::RenderThemeChromiumMac()
@@ -158,12 +167,20 @@ Color RenderThemeChromiumMac::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 RenderThemeChromiumMac::activeListBoxSelectionBackgroundColor() const
+Color RenderThemeChromiumMac::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 RenderThemeChromiumMac::platformFocusRingColor() const
+{
+ if (ChromiumBridge::layoutTestMode())
+ return oldAquaFocusRingColor();
+
+ return systemColor(CSSValueWebkitFocusRingColor);
+}
+
static FontWeight toFontWeight(NSInteger appKitFontWeight)
{
ASSERT(appKitFontWeight > 0 && appKitFontWeight < 15);
@@ -416,6 +433,9 @@ Color RenderThemeChromiumMac::systemColor(int cssValueId) const
case CSSValueThreedlightshadow:
color = convertNSColorToColor([NSColor controlLightHighlightColor]);
break;
+ case CSSValueWebkitFocusRingColor:
+ color = convertNSColorToColor([NSColor keyboardFocusIndicatorColor]);
+ break;
case CSSValueWindow:
color = convertNSColorToColor([NSColor windowBackgroundColor]);
break;
@@ -1486,7 +1506,7 @@ bool RenderThemeChromiumMac::paintSliderThumb(RenderObject* o, const RenderObjec
else
oldPressed = m_isSliderThumbHorizontalPressed;
- bool pressed = static_cast<RenderSlider*>(o->parent())->inDragMode();
+ bool pressed = toRenderSlider(o->parent())->inDragMode();
if (o->style()->appearance() == SliderThumbVerticalPart)
m_isSliderThumbVerticalPressed = pressed;
@@ -1781,6 +1801,12 @@ typedef enum {
MediaControllerThemeClassic = 1,
MediaControllerThemeQT = 2
} MediaControllerThemeStyle;
+
+enum WKMediaControllerThemeState {
+ MediaUIPartDisabledFlag = 1 << 0,
+ MediaUIPartPressedFlag = 1 << 1,
+ MediaUIPartDrawEndCapsFlag = 1 << 3,
+};
#endif
bool RenderThemeChromiumMac::paintMediaFullscreenButton(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
@@ -1791,7 +1817,8 @@ bool RenderThemeChromiumMac::paintMediaFullscreenButton(RenderObject* o, const R
return false;
LocalCurrentGraphicsContext localContext(paintInfo.context);
- wkDrawMediaUIPart(MediaFullscreenButton, MediaControllerThemeClassic, paintInfo.context->platformContext(), r, node->active());
+ wkDrawMediaUIPart(MediaFullscreenButton, MediaControllerThemeClassic, paintInfo.context->platformContext(), r,
+ node->active() ? MediaUIPartPressedFlag : 0);
#endif
return false;
}
@@ -1809,7 +1836,8 @@ bool RenderThemeChromiumMac::paintMediaMuteButton(RenderObject* o, const RenderO
return false;
LocalCurrentGraphicsContext localContext(paintInfo.context);
- wkDrawMediaUIPart(mediaElement->muted() ? MediaUnMuteButton : MediaMuteButton, MediaControllerThemeClassic, paintInfo.context->platformContext(), r, node->active());
+ wkDrawMediaUIPart(mediaElement->muted() ? MediaUnMuteButton : MediaMuteButton, MediaControllerThemeClassic, paintInfo.context->platformContext(), r,
+ node->active() ? MediaUIPartPressedFlag : 0);
#endif
return false;
}
@@ -1827,7 +1855,8 @@ bool RenderThemeChromiumMac::paintMediaPlayButton(RenderObject* o, const RenderO
return false;
LocalCurrentGraphicsContext localContext(paintInfo.context);
- wkDrawMediaUIPart(mediaElement->canPlay() ? MediaPlayButton : MediaPauseButton, MediaControllerThemeClassic, paintInfo.context->platformContext(), r, node->active());
+ wkDrawMediaUIPart(mediaElement->canPlay() ? MediaPlayButton : MediaPauseButton, MediaControllerThemeClassic, paintInfo.context->platformContext(), r,
+ node->active() ? MediaUIPartPressedFlag : 0);
#endif
return false;
}
@@ -1840,7 +1869,8 @@ bool RenderThemeChromiumMac::paintMediaSeekBackButton(RenderObject* o, const Ren
return false;
LocalCurrentGraphicsContext localContext(paintInfo.context);
- wkDrawMediaUIPart(MediaSeekBackButton, MediaControllerThemeClassic, paintInfo.context->platformContext(), r, node->active());
+ wkDrawMediaUIPart(MediaSeekBackButton, MediaControllerThemeClassic, paintInfo.context->platformContext(), r,
+ node->active() ? MediaUIPartPressedFlag : 0);
#endif
return false;
}
@@ -1853,7 +1883,8 @@ bool RenderThemeChromiumMac::paintMediaSeekForwardButton(RenderObject* o, const
return false;
LocalCurrentGraphicsContext localContext(paintInfo.context);
- wkDrawMediaUIPart(MediaSeekForwardButton, MediaControllerThemeClassic, paintInfo.context->platformContext(), r, node->active());
+ wkDrawMediaUIPart(MediaSeekForwardButton, MediaControllerThemeClassic, paintInfo.context->platformContext(), r,
+ node->active() ? MediaUIPartPressedFlag : 0);
#endif
return false;
}
@@ -1879,7 +1910,8 @@ bool RenderThemeChromiumMac::paintMediaSliderTrack(RenderObject* o, const Render
currentTime = player->currentTime();
}
- wkDrawMediaSliderTrack(MediaControllerThemeClassic, paintInfo.context->platformContext(), r, timeLoaded, currentTime, duration);
+ bool shouldDrawEndCaps = !toRenderMedia(mediaElement->renderer())->shouldShowTimeDisplayControls();
+ wkDrawMediaSliderTrack(MediaControllerThemeClassic, paintInfo.context->platformContext(), r, timeLoaded, currentTime, duration, shouldDrawEndCaps ? MediaUIPartDrawEndCapsFlag : 0);
#endif
return false;
}
@@ -1892,7 +1924,8 @@ bool RenderThemeChromiumMac::paintMediaSliderThumb(RenderObject* o, const Render
return false;
LocalCurrentGraphicsContext localContext(paintInfo.context);
- wkDrawMediaUIPart(MediaSliderThumb, MediaControllerThemeClassic, paintInfo.context->platformContext(), r, node->active());
+ wkDrawMediaUIPart(MediaSliderThumb, MediaControllerThemeClassic, paintInfo.context->platformContext(), r,
+ node->active() ? MediaUIPartPressedFlag : 0);
#endif
return false;
}
diff --git a/WebCore/rendering/RenderThemeChromiumSkia.cpp b/WebCore/rendering/RenderThemeChromiumSkia.cpp
index bf217c8..79804ac 100644
--- a/WebCore/rendering/RenderThemeChromiumSkia.cpp
+++ b/WebCore/rendering/RenderThemeChromiumSkia.cpp
@@ -1,2 +1,751 @@
-// FIXME: This is a placeholder to avoid some issues with webkit.gyp in the chromium tree. Having this placeholder until we can factor out
-// RenderThemeChromiumSkia from RenderThemeChromiumLinux will keep the HEAD of both trees compatible.
+/*
+ * Copyright (C) 2007 Apple Inc.
+ * Copyright (C) 2007 Alp Toker <alp@atoker.com>
+ * Copyright (C) 2008 Collabora Ltd.
+ * Copyright (C) 2008, 2009 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "RenderThemeChromiumSkia.h"
+
+#include "ChromiumBridge.h"
+#include "CSSValueKeywords.h"
+#include "GraphicsContext.h"
+#include "HTMLMediaElement.h"
+#include "HTMLNames.h"
+#include "Image.h"
+#include "MediaControlElements.h"
+#include "PlatformContextSkia.h"
+#include "RenderBox.h"
+#include "RenderObject.h"
+#include "ScrollbarTheme.h"
+#include "TransformationMatrix.h"
+#include "UserAgentStyleSheets.h"
+
+#include "SkShader.h"
+#include "SkGradientShader.h"
+
+namespace WebCore {
+
+enum PaddingType {
+ TopPadding,
+ RightPadding,
+ BottomPadding,
+ LeftPadding
+};
+
+static const int styledMenuListInternalPadding[4] = { 1, 4, 1, 4 };
+
+// These values all match Safari/Win.
+static const float defaultControlFontPixelSize = 13;
+static const float defaultCancelButtonSize = 9;
+static const float minCancelButtonSize = 5;
+static const float maxCancelButtonSize = 21;
+static const float defaultSearchFieldResultsDecorationSize = 13;
+static const float minSearchFieldResultsDecorationSize = 9;
+static const float maxSearchFieldResultsDecorationSize = 30;
+static const float defaultSearchFieldResultsButtonWidth = 18;
+
+static void setSizeIfAuto(RenderStyle* style, const IntSize& size)
+{
+ if (style->width().isIntrinsicOrAuto())
+ style->setWidth(Length(size.width(), Fixed));
+ if (style->height().isAuto())
+ style->setHeight(Length(size.height(), Fixed));
+}
+
+#if ENABLE(VIDEO)
+// Attempt to retrieve a HTMLMediaElement from a Node. Returns NULL if one cannot be found.
+static HTMLMediaElement* mediaElementParent(Node* node)
+{
+ if (!node)
+ return 0;
+ Node* mediaNode = node->shadowAncestorNode();
+ if (!mediaNode || (!mediaNode->hasTagName(HTMLNames::videoTag) && !mediaNode->hasTagName(HTMLNames::audioTag)))
+ return 0;
+
+ return static_cast<HTMLMediaElement*>(mediaNode);
+}
+#endif
+
+// We aim to match IE here.
+// -IE uses a font based on the encoding as the default font for form controls.
+// -Gecko uses MS Shell Dlg (actually calls GetStockObject(DEFAULT_GUI_FONT),
+// which returns MS Shell Dlg)
+// -Safari uses Lucida Grande.
+//
+// FIXME: The only case where we know we don't match IE is for ANSI encodings.
+// IE uses MS Shell Dlg there, which we render incorrectly at certain pixel
+// sizes (e.g. 15px). So, for now we just use Arial.
+const String& RenderThemeChromiumSkia::defaultGUIFont()
+{
+ DEFINE_STATIC_LOCAL(String, fontFace, ("Arial"));
+ return fontFace;
+}
+
+float RenderThemeChromiumSkia::defaultFontSize = 16.0;
+
+RenderThemeChromiumSkia::RenderThemeChromiumSkia()
+{
+}
+
+RenderThemeChromiumSkia::~RenderThemeChromiumSkia()
+{
+}
+
+// Use the Windows style sheets to match their metrics.
+String RenderThemeChromiumSkia::extraDefaultStyleSheet()
+{
+ return String(themeWinUserAgentStyleSheet, sizeof(themeWinUserAgentStyleSheet));
+}
+
+String RenderThemeChromiumSkia::extraQuirksStyleSheet()
+{
+ return String(themeWinQuirksUserAgentStyleSheet, sizeof(themeWinQuirksUserAgentStyleSheet));
+}
+
+#if ENABLE(VIDEO)
+String RenderThemeChromiumSkia::extraMediaControlsStyleSheet()
+{
+ return String(mediaControlsChromiumUserAgentStyleSheet, sizeof(mediaControlsChromiumUserAgentStyleSheet));
+}
+#endif
+
+bool RenderThemeChromiumSkia::supportsHover(const RenderStyle* style) const
+{
+ return true;
+}
+
+bool RenderThemeChromiumSkia::supportsFocusRing(const RenderStyle* style) const
+{
+ // This causes WebKit to draw the focus rings for us.
+ return false;
+}
+
+Color RenderThemeChromiumSkia::platformActiveSelectionBackgroundColor() const
+{
+ return Color(0x1e, 0x90, 0xff);
+}
+
+Color RenderThemeChromiumSkia::platformInactiveSelectionBackgroundColor() const
+{
+ return Color(0xc8, 0xc8, 0xc8);
+}
+
+Color RenderThemeChromiumSkia::platformActiveSelectionForegroundColor() const
+{
+ return Color::black;
+}
+
+Color RenderThemeChromiumSkia::platformInactiveSelectionForegroundColor() const
+{
+ return Color(0x32, 0x32, 0x32);
+}
+
+Color RenderThemeChromiumSkia::platformFocusRingColor() const
+{
+ static Color focusRingColor(229, 151, 0, 255);
+ return focusRingColor;
+}
+
+double RenderThemeChromiumSkia::caretBlinkInterval() const
+{
+ // Disable the blinking caret in layout test mode, as it introduces
+ // a race condition for the pixel tests. http://b/1198440
+ if (ChromiumBridge::layoutTestMode())
+ return 0;
+
+ return caretBlinkIntervalInternal();
+}
+
+void RenderThemeChromiumSkia::systemFont(int propId, FontDescription& fontDescription) const
+{
+ float fontSize = defaultFontSize;
+
+ switch (propId) {
+ case CSSValueWebkitMiniControl:
+ case CSSValueWebkitSmallControl:
+ case CSSValueWebkitControl:
+ // Why 2 points smaller? Because that's what Gecko does. Note that we
+ // are assuming a 96dpi screen, which is the default that we use on
+ // Windows.
+ static const float pointsPerInch = 72.0f;
+ static const float pixelsPerInch = 96.0f;
+ fontSize -= (2.0f / pointsPerInch) * pixelsPerInch;
+ break;
+ }
+
+ fontDescription.firstFamily().setFamily(defaultGUIFont());
+ fontDescription.setSpecifiedSize(fontSize);
+ fontDescription.setIsAbsoluteSize(true);
+ fontDescription.setGenericFamily(FontDescription::NoFamily);
+ fontDescription.setWeight(FontWeightNormal);
+ fontDescription.setItalic(false);
+}
+
+int RenderThemeChromiumSkia::minimumMenuListSize(RenderStyle* style) const
+{
+ return 0;
+}
+
+bool RenderThemeChromiumSkia::paintCheckbox(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& rect)
+{
+ static Image* const checkedImage = Image::loadPlatformResource("linuxCheckboxOn").releaseRef();
+ static Image* const uncheckedImage = Image::loadPlatformResource("linuxCheckboxOff").releaseRef();
+ static Image* const disabledCheckedImage = Image::loadPlatformResource("linuxCheckboxDisabledOn").releaseRef();
+ static Image* const disabledUncheckedImage = Image::loadPlatformResource("linuxCheckboxDisabledOff").releaseRef();
+
+ Image* image;
+
+ if (this->isEnabled(o))
+ image = this->isChecked(o) ? checkedImage : uncheckedImage;
+ else
+ image = this->isChecked(o) ? disabledCheckedImage : disabledUncheckedImage;
+
+ i.context->drawImage(image, rect);
+ return false;
+}
+
+void RenderThemeChromiumSkia::setCheckboxSize(RenderStyle* style) const
+{
+ // If the width and height are both specified, then we have nothing to do.
+ if (!style->width().isIntrinsicOrAuto() && !style->height().isAuto())
+ return;
+
+ // FIXME: A hard-coded size of 13 is used. This is wrong but necessary
+ // for now. It matches Firefox. At different DPI settings on Windows,
+ // querying the theme gives you a larger size that accounts for the higher
+ // DPI. Until our entire engine honors a DPI setting other than 96, we
+ // can't rely on the theme's metrics.
+ const IntSize size(13, 13);
+ setSizeIfAuto(style, size);
+}
+
+bool RenderThemeChromiumSkia::paintRadio(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& rect)
+{
+ static Image* const checkedImage = Image::loadPlatformResource("linuxRadioOn").releaseRef();
+ static Image* const uncheckedImage = Image::loadPlatformResource("linuxRadioOff").releaseRef();
+ static Image* const disabledCheckedImage = Image::loadPlatformResource("linuxRadioDisabledOn").releaseRef();
+ static Image* const disabledUncheckedImage = Image::loadPlatformResource("linuxRadioDisabledOff").releaseRef();
+
+ Image* image;
+ if (this->isEnabled(o))
+ image = this->isChecked(o) ? checkedImage : uncheckedImage;
+ else
+ image = this->isChecked(o) ? disabledCheckedImage : disabledUncheckedImage;
+
+ i.context->drawImage(image, rect);
+ return false;
+}
+
+void RenderThemeChromiumSkia::setRadioSize(RenderStyle* style) const
+{
+ // Use same sizing for radio box as checkbox.
+ setCheckboxSize(style);
+}
+
+static SkColor brightenColor(double h, double s, double l, float brightenAmount)
+{
+ l += brightenAmount;
+ if (l > 1.0)
+ l = 1.0;
+ if (l < 0.0)
+ l = 0.0;
+
+ return makeRGBAFromHSLA(h, s, l, 1.0);
+}
+
+static void paintButtonLike(RenderTheme* theme, RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& rect)
+{
+ SkCanvas* const canvas = i.context->platformContext()->canvas();
+ SkPaint paint;
+ SkRect skrect;
+ const int right = rect.x() + rect.width();
+ const int bottom = rect.y() + rect.height();
+ SkColor baseColor = SkColorSetARGB(0xff, 0xdd, 0xdd, 0xdd);
+ if (o->style()->hasBackground())
+ baseColor = o->style()->backgroundColor().rgb();
+ double h, s, l;
+ Color(baseColor).getHSL(h, s, l);
+ // Our standard gradient is from 0xdd to 0xf8. This is the amount of
+ // increased luminance between those values.
+ SkColor lightColor(brightenColor(h, s, l, 0.105));
+
+ // If the button is too small, fallback to drawing a single, solid color
+ if (rect.width() < 5 || rect.height() < 5) {
+ paint.setColor(baseColor);
+ skrect.set(rect.x(), rect.y(), right, bottom);
+ canvas->drawRect(skrect, paint);
+ return;
+ }
+
+ const int borderAlpha = theme->isHovered(o) ? 0x80 : 0x55;
+ paint.setARGB(borderAlpha, 0, 0, 0);
+ canvas->drawLine(rect.x() + 1, rect.y(), right - 1, rect.y(), paint);
+ canvas->drawLine(right - 1, rect.y() + 1, right - 1, bottom - 1, paint);
+ canvas->drawLine(rect.x() + 1, bottom - 1, right - 1, bottom - 1, paint);
+ canvas->drawLine(rect.x(), rect.y() + 1, rect.x(), bottom - 1, paint);
+
+ paint.setARGB(0xff, 0, 0, 0);
+ SkPoint p[2];
+ const int lightEnd = theme->isPressed(o) ? 1 : 0;
+ const int darkEnd = !lightEnd;
+ p[lightEnd].set(SkIntToScalar(rect.x()), SkIntToScalar(rect.y()));
+ p[darkEnd].set(SkIntToScalar(rect.x()), SkIntToScalar(bottom - 1));
+ SkColor colors[2];
+ colors[0] = lightColor;
+ colors[1] = baseColor;
+
+ SkShader* shader = SkGradientShader::CreateLinear(
+ p, colors, NULL, 2, SkShader::kClamp_TileMode, NULL);
+ paint.setStyle(SkPaint::kFill_Style);
+ paint.setShader(shader);
+ shader->unref();
+
+ skrect.set(rect.x() + 1, rect.y() + 1, right - 1, bottom - 1);
+ canvas->drawRect(skrect, paint);
+
+ paint.setShader(NULL);
+ paint.setColor(brightenColor(h, s, l, -0.0588));
+ canvas->drawPoint(rect.x() + 1, rect.y() + 1, paint);
+ canvas->drawPoint(right - 2, rect.y() + 1, paint);
+ canvas->drawPoint(rect.x() + 1, bottom - 2, paint);
+ canvas->drawPoint(right - 2, bottom - 2, paint);
+}
+
+bool RenderThemeChromiumSkia::paintButton(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& rect)
+{
+ paintButtonLike(this, o, i, rect);
+ return false;
+}
+
+bool RenderThemeChromiumSkia::paintTextField(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& rect)
+{
+ return true;
+}
+
+bool RenderThemeChromiumSkia::paintTextArea(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& r)
+{
+ return paintTextField(o, i, r);
+}
+
+bool RenderThemeChromiumSkia::paintSearchField(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& r)
+{
+ return paintTextField(o, i, r);
+}
+
+void RenderThemeChromiumSkia::adjustSearchFieldCancelButtonStyle(CSSStyleSelector*, RenderStyle* style, Element*) const
+{
+ // Scale the button size based on the font size
+ float fontScale = style->fontSize() / defaultControlFontPixelSize;
+ int cancelButtonSize = lroundf(std::min(std::max(minCancelButtonSize, defaultCancelButtonSize * fontScale), maxCancelButtonSize));
+ style->setWidth(Length(cancelButtonSize, Fixed));
+ style->setHeight(Length(cancelButtonSize, Fixed));
+}
+
+bool RenderThemeChromiumSkia::paintSearchFieldCancelButton(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& r)
+{
+ IntRect bounds = r;
+ ASSERT(o->parent());
+ if (!o->parent() || !o->parent()->isBox())
+ return false;
+
+ RenderBox* parentRenderBox = toRenderBox(o->parent());
+
+ IntRect parentBox = parentRenderBox->absoluteContentBox();
+
+ // Make sure the scaled button stays square and will fit in its parent's box
+ bounds.setHeight(std::min(parentBox.width(), std::min(parentBox.height(), bounds.height())));
+ bounds.setWidth(bounds.height());
+
+ // Center the button vertically. Round up though, so if it has to be one pixel off-center, it will
+ // be one pixel closer to the bottom of the field. This tends to look better with the text.
+ bounds.setY(parentBox.y() + (parentBox.height() - bounds.height() + 1) / 2);
+
+ static Image* cancelImage = Image::loadPlatformResource("searchCancel").releaseRef();
+ static Image* cancelPressedImage = Image::loadPlatformResource("searchCancelPressed").releaseRef();
+ i.context->drawImage(isPressed(o) ? cancelPressedImage : cancelImage, bounds);
+ return false;
+}
+
+void RenderThemeChromiumSkia::adjustSearchFieldDecorationStyle(CSSStyleSelector*, RenderStyle* style, Element*) const
+{
+ IntSize emptySize(1, 11);
+ style->setWidth(Length(emptySize.width(), Fixed));
+ style->setHeight(Length(emptySize.height(), Fixed));
+}
+
+void RenderThemeChromiumSkia::adjustSearchFieldResultsDecorationStyle(CSSStyleSelector*, RenderStyle* style, Element*) const
+{
+ // Scale the decoration size based on the font size
+ float fontScale = style->fontSize() / defaultControlFontPixelSize;
+ int magnifierSize = lroundf(std::min(std::max(minSearchFieldResultsDecorationSize, defaultSearchFieldResultsDecorationSize * fontScale),
+ maxSearchFieldResultsDecorationSize));
+ style->setWidth(Length(magnifierSize, Fixed));
+ style->setHeight(Length(magnifierSize, Fixed));
+}
+
+bool RenderThemeChromiumSkia::paintSearchFieldResultsDecoration(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& r)
+{
+ IntRect bounds = r;
+ ASSERT(o->parent());
+ if (!o->parent() || !o->parent()->isBox())
+ return false;
+
+ RenderBox* parentRenderBox = toRenderBox(o->parent());
+ IntRect parentBox = parentRenderBox->absoluteContentBox();
+
+ // Make sure the scaled decoration stays square and will fit in its parent's box
+ bounds.setHeight(std::min(parentBox.width(), std::min(parentBox.height(), bounds.height())));
+ bounds.setWidth(bounds.height());
+
+ // Center the decoration vertically. Round up though, so if it has to be one pixel off-center, it will
+ // be one pixel closer to the bottom of the field. This tends to look better with the text.
+ bounds.setY(parentBox.y() + (parentBox.height() - bounds.height() + 1) / 2);
+
+ static Image* magnifierImage = Image::loadPlatformResource("searchMagnifier").releaseRef();
+ i.context->drawImage(magnifierImage, bounds);
+ return false;
+}
+
+void RenderThemeChromiumSkia::adjustSearchFieldResultsButtonStyle(CSSStyleSelector*, RenderStyle* style, Element*) const
+{
+ // Scale the button size based on the font size
+ float fontScale = style->fontSize() / defaultControlFontPixelSize;
+ int magnifierHeight = lroundf(std::min(std::max(minSearchFieldResultsDecorationSize, defaultSearchFieldResultsDecorationSize * fontScale),
+ maxSearchFieldResultsDecorationSize));
+ int magnifierWidth = lroundf(magnifierHeight * defaultSearchFieldResultsButtonWidth / defaultSearchFieldResultsDecorationSize);
+ style->setWidth(Length(magnifierWidth, Fixed));
+ style->setHeight(Length(magnifierHeight, Fixed));
+}
+
+bool RenderThemeChromiumSkia::paintSearchFieldResultsButton(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& r)
+{
+ IntRect bounds = r;
+ ASSERT(o->parent());
+ if (!o->parent())
+ return false;
+ if (!o->parent() || !o->parent()->isBox())
+ return false;
+
+ RenderBox* parentRenderBox = toRenderBox(o->parent());
+ IntRect parentBox = parentRenderBox->absoluteContentBox();
+
+ // Make sure the scaled decoration will fit in its parent's box
+ bounds.setHeight(std::min(parentBox.height(), bounds.height()));
+ bounds.setWidth(std::min(parentBox.width(), static_cast<int>(bounds.height() * defaultSearchFieldResultsButtonWidth / defaultSearchFieldResultsDecorationSize)));
+
+ // Center the button vertically. Round up though, so if it has to be one pixel off-center, it will
+ // be one pixel closer to the bottom of the field. This tends to look better with the text.
+ bounds.setY(parentBox.y() + (parentBox.height() - bounds.height() + 1) / 2);
+
+ static Image* magnifierImage = Image::loadPlatformResource("searchMagnifierResults").releaseRef();
+ i.context->drawImage(magnifierImage, bounds);
+ return false;
+}
+
+bool RenderThemeChromiumSkia::paintMediaButtonInternal(GraphicsContext* context, const IntRect& rect, Image* image)
+{
+ // Create a destination rectangle for the image that is centered in the drawing rectangle, rounded left, and down.
+ IntRect imageRect = image->rect();
+ imageRect.setY(rect.y() + (rect.height() - image->height() + 1) / 2);
+ imageRect.setX(rect.x() + (rect.width() - image->width() + 1) / 2);
+
+ context->drawImage(image, imageRect);
+ return true;
+}
+
+bool RenderThemeChromiumSkia::paintMediaControlsBackground(RenderObject* object, const RenderObject::PaintInfo& paintInfo, const IntRect& rect)
+{
+#if ENABLE(VIDEO)
+ HTMLMediaElement* mediaElement = mediaElementParent(object->node());
+ if (!mediaElement)
+ return false;
+
+ if (!rect.isEmpty())
+ {
+ SkCanvas* canvas = paintInfo.context->platformContext()->canvas();
+ SkPaint paint;
+
+ // Draws the left border, it is always 1px wide.
+ paint.setColor(object->style()->borderLeftColor().rgb());
+ canvas->drawLine(rect.x() + 1, rect.y(),
+ rect.x() + 1, rect.y() + rect.height(),
+ paint);
+
+ // Draws the right border, it is always 1px wide.
+ paint.setColor(object->style()->borderRightColor().rgb());
+ canvas->drawLine(rect.x() + rect.width() - 1, rect.y(),
+ rect.x() + rect.width() - 1, rect.y() + rect.height(),
+ paint);
+ }
+ return true;
+#else
+ UNUSED_PARAM(object);
+ UNUSED_PARAM(paintInfo);
+ UNUSED_PARAM(rect);
+ return false;
+#endif
+}
+
+bool RenderThemeChromiumSkia::paintMediaSliderTrack(RenderObject* object, const RenderObject::PaintInfo& paintInfo, const IntRect& rect)
+{
+#if ENABLE(VIDEO)
+ HTMLMediaElement* mediaElement = mediaElementParent(object->node());
+ if (!mediaElement)
+ return false;
+
+ SkCanvas* canvas = paintInfo.context->platformContext()->canvas();
+ SkRect backgroundRect;
+ backgroundRect.set(rect.x(), rect.y(), rect.x() + rect.width(), rect.y() + rect.height());
+
+ SkPaint paint;
+ paint.setAntiAlias(true);
+
+ // Draw the border of the time bar. The border only has one single color,
+ // width and radius. So use the property of the left border.
+ SkColor borderColor = object->style()->borderLeftColor().rgb();
+ int borderWidth = object->style()->borderLeftWidth();
+ IntSize borderRadius = object->style()->borderTopLeftRadius();
+ paint.setStyle(SkPaint::kStroke_Style);
+ paint.setStrokeWidth(borderWidth);
+ paint.setColor(borderColor);
+ canvas->drawRoundRect(backgroundRect, borderRadius.width(), borderRadius.height(), paint);
+
+ // Draw the background of the time bar.
+ SkColor backgroundColor = object->style()->backgroundColor().rgb();
+ paint.setStyle(SkPaint::kFill_Style);
+ paint.setColor(backgroundColor);
+ canvas->drawRoundRect(backgroundRect, borderRadius.width(), borderRadius.height(), paint);
+
+ if (backgroundRect.width() >= 3 && backgroundRect.height() >= 3)
+ {
+ // Draw the buffered ranges.
+ // FIXME: Draw multiple ranges if there are multiple buffered ranges.
+ SkRect bufferedRect;
+ bufferedRect.set(backgroundRect.fLeft + 2, backgroundRect.fTop + 2,
+ backgroundRect.fRight - 1, backgroundRect.fBottom - 1);
+ int width = static_cast<int>(bufferedRect.width() * mediaElement->percentLoaded());
+ bufferedRect.fRight = bufferedRect.fLeft + width;
+
+ SkPoint points[2] = { { 0, bufferedRect.fTop }, { 0, bufferedRect.fBottom } };
+ SkColor startColor = object->style()->color().rgb();
+ SkColor endColor = SkColorSetRGB(SkColorGetR(startColor) / 2,
+ SkColorGetG(startColor) / 2,
+ SkColorGetB(startColor) / 2);
+ SkColor colors[2] = { startColor, endColor };
+ SkShader* gradient = SkGradientShader::CreateLinear(points, colors, 0,
+ sizeof(points) / sizeof(points[0]),
+ SkShader::kMirror_TileMode, 0);
+
+ paint.reset();
+ paint.setShader(gradient);
+ paint.setAntiAlias(true);
+ // Check for round rect with zero width or height, otherwise Skia will assert
+ if (bufferedRect.width() > 0 && bufferedRect.height() > 0)
+ canvas->drawRoundRect(bufferedRect, borderRadius.width(), borderRadius.height(), paint);
+ gradient->unref();
+ }
+ return true;
+#else
+ UNUSED_PARAM(object);
+ UNUSED_PARAM(paintInfo);
+ UNUSED_PARAM(rect);
+ return false;
+#endif
+}
+
+void RenderThemeChromiumSkia::adjustSliderThumbSize(RenderObject* object) const {
+#if ENABLE(VIDEO)
+ if (object->style()->appearance() == MediaSliderThumbPart) {
+ static Image* mediaSliderThumb = Image::loadPlatformResource("mediaSliderThumb").releaseRef();
+
+ object->style()->setWidth(Length(mediaSliderThumb->width(), Fixed));
+ object->style()->setHeight(Length(mediaSliderThumb->height(), Fixed));
+ }
+#else
+ UNUSED_PARAM(object);
+#endif
+}
+
+bool RenderThemeChromiumSkia::paintMediaSliderThumb(RenderObject* object, const RenderObject::PaintInfo& paintInfo, const IntRect& rect)
+{
+#if ENABLE(VIDEO)
+ if (!object->parent()->isSlider())
+ return false;
+
+ static Image* mediaSliderThumb = Image::loadPlatformResource("mediaSliderThumb").releaseRef();
+
+ return paintMediaButtonInternal(paintInfo.context, rect, mediaSliderThumb);
+#else
+ UNUSED_PARAM(object);
+ UNUSED_PARAM(paintInfo);
+ UNUSED_PARAM(rect);
+ return false;
+#endif
+}
+
+bool RenderThemeChromiumSkia::paintMediaPlayButton(RenderObject* object, const RenderObject::PaintInfo& paintInfo, const IntRect& rect)
+{
+#if ENABLE(VIDEO)
+ HTMLMediaElement* mediaElement = mediaElementParent(object->node());
+ if (!mediaElement)
+ return false;
+
+ static Image* mediaPlay = Image::loadPlatformResource("mediaPlay").releaseRef();
+ static Image* mediaPause = Image::loadPlatformResource("mediaPause").releaseRef();
+
+ return paintMediaButtonInternal(paintInfo.context, rect, mediaElement->paused() ? mediaPlay : mediaPause);
+#else
+ UNUSED_PARAM(object);
+ UNUSED_PARAM(paintInfo);
+ UNUSED_PARAM(rect);
+ return false;
+#endif
+}
+
+bool RenderThemeChromiumSkia::paintMediaMuteButton(RenderObject* object, const RenderObject::PaintInfo& paintInfo, const IntRect& rect)
+{
+#if ENABLE(VIDEO)
+ HTMLMediaElement* mediaElement = mediaElementParent(object->node());
+ if (!mediaElement)
+ return false;
+
+ static Image* soundFull = Image::loadPlatformResource("mediaSoundFull").releaseRef();
+ static Image* soundNone = Image::loadPlatformResource("mediaSoundNone").releaseRef();
+
+ return paintMediaButtonInternal(paintInfo.context, rect, mediaElement->muted() ? soundNone: soundFull);
+#else
+ UNUSED_PARAM(object);
+ UNUSED_PARAM(paintInfo);
+ UNUSED_PARAM(rect);
+ return false;
+#endif
+}
+
+void RenderThemeChromiumSkia::adjustMenuListStyle(CSSStyleSelector* selector, RenderStyle* style, WebCore::Element* e) const
+{
+ // Height is locked to auto on all browsers.
+ style->setLineHeight(RenderStyle::initialLineHeight());
+}
+
+bool RenderThemeChromiumSkia::paintMenuList(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& rect)
+{
+ SkCanvas* const canvas = i.context->platformContext()->canvas();
+ const int right = rect.x() + rect.width();
+ const int middle = rect.y() + rect.height() / 2;
+
+ paintButtonLike(this, o, i, rect);
+
+ SkPaint paint;
+ paint.setARGB(0xff, 0, 0, 0);
+ paint.setAntiAlias(true);
+ paint.setStyle(SkPaint::kFill_Style);
+
+ SkPath path;
+ path.moveTo(right - 13, middle - 3);
+ path.rLineTo(6, 0);
+ path.rLineTo(-3, 6);
+ path.close();
+ canvas->drawPath(path, paint);
+
+ return false;
+}
+
+void RenderThemeChromiumSkia::adjustMenuListButtonStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
+{
+ adjustMenuListStyle(selector, style, e);
+}
+
+// Used to paint styled menulists (i.e. with a non-default border)
+bool RenderThemeChromiumSkia::paintMenuListButton(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& rect)
+{
+ return paintMenuList(o, i, rect);
+}
+
+int RenderThemeChromiumSkia::popupInternalPaddingLeft(RenderStyle* style) const
+{
+ return menuListInternalPadding(style, LeftPadding);
+}
+
+int RenderThemeChromiumSkia::popupInternalPaddingRight(RenderStyle* style) const
+{
+ return menuListInternalPadding(style, RightPadding);
+}
+
+int RenderThemeChromiumSkia::popupInternalPaddingTop(RenderStyle* style) const
+{
+ return menuListInternalPadding(style, TopPadding);
+}
+
+int RenderThemeChromiumSkia::popupInternalPaddingBottom(RenderStyle* style) const
+{
+ return menuListInternalPadding(style, BottomPadding);
+}
+
+int RenderThemeChromiumSkia::buttonInternalPaddingLeft() const
+{
+ return 3;
+}
+
+int RenderThemeChromiumSkia::buttonInternalPaddingRight() const
+{
+ return 3;
+}
+
+int RenderThemeChromiumSkia::buttonInternalPaddingTop() const
+{
+ return 1;
+}
+
+int RenderThemeChromiumSkia::buttonInternalPaddingBottom() const
+{
+ return 1;
+}
+
+// static
+void RenderThemeChromiumSkia::setDefaultFontSize(int fontSize)
+{
+ defaultFontSize = static_cast<float>(fontSize);
+}
+
+double RenderThemeChromiumSkia::caretBlinkIntervalInternal() const
+{
+ return RenderTheme::caretBlinkInterval();
+}
+
+int RenderThemeChromiumSkia::menuListInternalPadding(RenderStyle* style, int paddingType) const
+{
+ // This internal padding is in addition to the user-supplied padding.
+ // Matches the FF behavior.
+ int padding = styledMenuListInternalPadding[paddingType];
+
+ // Reserve the space for right arrow here. The rest of the padding is
+ // set by adjustMenuListStyle, since PopMenuWin.cpp uses the padding from
+ // RenderMenuList to lay out the individual items in the popup.
+ // If the MenuList actually has appearance "NoAppearance", then that means
+ // we don't draw a button, so don't reserve space for it.
+ const int barType = style->direction() == LTR ? RightPadding : LeftPadding;
+ if (paddingType == barType && style->appearance() != NoControlPart)
+ padding += ScrollbarTheme::nativeTheme()->scrollbarThickness();
+
+ return padding;
+}
+
+} // namespace WebCore
diff --git a/WebCore/rendering/RenderThemeChromiumSkia.h b/WebCore/rendering/RenderThemeChromiumSkia.h
index bf217c8..7544c22 100644
--- a/WebCore/rendering/RenderThemeChromiumSkia.h
+++ b/WebCore/rendering/RenderThemeChromiumSkia.h
@@ -1,2 +1,148 @@
-// FIXME: This is a placeholder to avoid some issues with webkit.gyp in the chromium tree. Having this placeholder until we can factor out
-// RenderThemeChromiumSkia from RenderThemeChromiumLinux will keep the HEAD of both trees compatible.
+/*
+ * This file is part of the WebKit project.
+ *
+ * Copyright (C) 2006 Apple Computer, Inc.
+ * Copyright (C) 2006 Michael Emmel mike.emmel@gmail.com
+ * Copyright (C) 2007 Holger Hans Peter Freyther
+ * Copyright (C) 2007 Alp Toker <alp@atoker.com>
+ * Copyright (C) 2008, 2009 Google, Inc.
+ * All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef RenderThemeChromiumSkia_h
+#define RenderThemeChromiumSkia_h
+
+#include "RenderTheme.h"
+
+namespace WebCore {
+
+ class RenderThemeChromiumSkia : public RenderTheme {
+ public:
+ RenderThemeChromiumSkia();
+ virtual ~RenderThemeChromiumSkia();
+
+ virtual String extraDefaultStyleSheet();
+ virtual String extraQuirksStyleSheet();
+#if ENABLE(VIDEO)
+ virtual String extraMediaControlsStyleSheet();
+#endif
+
+ // A method asking if the theme's controls actually care about redrawing when hovered.
+ virtual bool supportsHover(const RenderStyle*) const;
+
+ // A method asking if the theme is able to draw the focus ring.
+ virtual bool supportsFocusRing(const RenderStyle*) const;
+
+ // The platform selection color.
+ virtual Color platformActiveSelectionBackgroundColor() const;
+ virtual Color platformInactiveSelectionBackgroundColor() const;
+ virtual Color platformActiveSelectionForegroundColor() const;
+ virtual Color platformInactiveSelectionForegroundColor() const;
+ virtual Color platformFocusRingColor() const;
+
+ // To change the blink interval, override caretBlinkIntervalInternal instead of this one so that we may share layout test code an intercepts.
+ virtual double caretBlinkInterval() const;
+
+ // System fonts.
+ virtual void systemFont(int propId, FontDescription&) const;
+
+ virtual int minimumMenuListSize(RenderStyle*) const;
+
+ virtual bool paintCheckbox(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+ virtual void setCheckboxSize(RenderStyle*) const;
+
+ virtual bool paintRadio(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+ virtual void setRadioSize(RenderStyle*) const;
+
+ virtual bool paintButton(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+
+ virtual bool paintTextField(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+
+ virtual bool paintTextArea(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+
+ virtual bool paintSearchField(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+
+ virtual void adjustSearchFieldCancelButtonStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+ virtual bool paintSearchFieldCancelButton(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+
+ virtual void adjustSearchFieldDecorationStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+
+ virtual void adjustSearchFieldResultsDecorationStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+ virtual bool paintSearchFieldResultsDecoration(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+
+ virtual void adjustSearchFieldResultsButtonStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+ virtual bool paintSearchFieldResultsButton(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+
+ virtual bool paintMediaControlsBackground(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+ virtual bool paintMediaSliderTrack(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+ virtual void adjustSliderThumbSize(RenderObject*) const;
+ virtual bool paintMediaSliderThumb(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+ virtual bool paintMediaPlayButton(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+ virtual bool paintMediaMuteButton(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+
+ // MenuList refers to an unstyled menulist (meaning a menulist without
+ // background-color or border set) and MenuListButton refers to a styled
+ // menulist (a menulist with background-color or border set). They have
+ // this distinction to support showing aqua style themes whenever they
+ // possibly can, which is something we don't want to replicate.
+ //
+ // In short, we either go down the MenuList code path or the MenuListButton
+ // codepath. We never go down both. And in both cases, they render the
+ // entire menulist.
+ virtual void adjustMenuListStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+ virtual bool paintMenuList(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+ virtual void adjustMenuListButtonStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+ virtual bool paintMenuListButton(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+
+ // These methods define the padding for the MenuList's inner block.
+ virtual int popupInternalPaddingLeft(RenderStyle*) const;
+ virtual int popupInternalPaddingRight(RenderStyle*) const;
+ virtual int popupInternalPaddingTop(RenderStyle*) const;
+ virtual int popupInternalPaddingBottom(RenderStyle*) const;
+
+ virtual int buttonInternalPaddingLeft() const;
+ virtual int buttonInternalPaddingRight() const;
+ virtual int buttonInternalPaddingTop() const;
+ virtual int buttonInternalPaddingBottom() const;
+
+ // Provide a way to pass the default font size from the Settings object
+ // to the render theme. FIXME: http://b/1129186 A cleaner way would be
+ // to remove the default font size from this object and have callers
+ // that need the value to get it directly from the appropriate Settings
+ // object.
+ static void setDefaultFontSize(int);
+
+ protected:
+ static const String& defaultGUIFont();
+
+ // The default variable-width font size. We use this as the default font
+ // size for the "system font", and as a base size (which we then shrink) for
+ // form control fonts.
+ static float defaultFontSize;
+
+ virtual double caretBlinkIntervalInternal() const;
+
+ private:
+ int menuListInternalPadding(RenderStyle*, int paddingType) const;
+ bool paintMediaButtonInternal(GraphicsContext*, const IntRect&, Image*);
+ };
+
+} // namespace WebCore
+
+#endif // RenderThemeChromiumSkia_h
diff --git a/WebCore/rendering/RenderThemeChromiumWin.cpp b/WebCore/rendering/RenderThemeChromiumWin.cpp
index 5288191..35d1580 100644
--- a/WebCore/rendering/RenderThemeChromiumWin.cpp
+++ b/WebCore/rendering/RenderThemeChromiumWin.cpp
@@ -3,6 +3,7 @@
*
* Copyright (C) 2006 Apple Computer, Inc.
* Copyright (C) 2008, 2009 Google, Inc.
+ * Copyright (C) 2009 Kenneth Rohde Christiansen
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -29,7 +30,6 @@
#include <vssym32.h>
#include "ChromiumBridge.h"
-#include "CSSStyleSheet.h"
#include "CSSValueKeywords.h"
#include "FontSelector.h"
#include "FontUtilsChromiumWin.h"
@@ -40,9 +40,7 @@
#include "RenderBox.h"
#include "RenderSlider.h"
#include "ScrollbarTheme.h"
-#include "SkiaUtils.h"
#include "TransparencyWin.h"
-#include "UserAgentStyleSheets.h"
#include "WindowsVersion.h"
// FIXME: This dependency should eventually be removed.
@@ -57,28 +55,6 @@
namespace WebCore {
namespace {
-
-// The background for the media player controls should be a 60% opaque black rectangle. This
-// matches the UI mockups for the default UI theme.
-static const float defaultMediaControlOpacity = 0.6f;
-
-// These values all match Safari/Win.
-static const float defaultControlFontPixelSize = 13;
-static const float defaultCancelButtonSize = 9;
-static const float minCancelButtonSize = 5;
-static const float maxCancelButtonSize = 21;
-static const float defaultSearchFieldResultsDecorationSize = 13;
-static const float minSearchFieldResultsDecorationSize = 9;
-static const float maxSearchFieldResultsDecorationSize = 30;
-static const float defaultSearchFieldResultsButtonWidth = 18;
-
-bool canvasHasMultipleLayers(const SkCanvas* canvas)
-{
- SkCanvas::LayerIter iter(const_cast<SkCanvas*>(canvas), false);
- iter.next(); // There is always at least one layer.
- return !iter.done(); // There is > 1 layer if the the iterator can stil advance.
-}
-
class ThemePainter : public TransparencyWin {
public:
ThemePainter(GraphicsContext* context, const IntRect& r)
@@ -93,6 +69,13 @@ public:
}
private:
+ static bool canvasHasMultipleLayers(const SkCanvas* canvas)
+ {
+ SkCanvas::LayerIter iter(const_cast<SkCanvas*>(canvas), false);
+ iter.next(); // There is always at least one layer.
+ return !iter.done(); // There is > 1 layer if the the iterator can stil advance.
+ }
+
static LayerMode getLayerMode(GraphicsContext* context, TransformMode transformMode)
{
if (context->platformContext()->isDrawingToImageBuffer()) // Might have transparent background.
@@ -116,7 +99,8 @@ private:
} // namespace
-static void getNonClientMetrics(NONCLIENTMETRICS* metrics) {
+static void getNonClientMetrics(NONCLIENTMETRICS* metrics)
+{
static UINT size = WebCore::isVistaOrNewer() ?
sizeof(NONCLIENTMETRICS) : NONCLIENTMETRICS_SIZE_PRE_VISTA;
metrics->cbSize = size;
@@ -124,20 +108,6 @@ static void getNonClientMetrics(NONCLIENTMETRICS* metrics) {
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;
@@ -159,14 +129,6 @@ static bool supportsFocus(ControlPart appearance)
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)
@@ -201,20 +163,6 @@ static float systemFontSize(const LOGFONT& font)
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()
-{
- return L"Arial";
-}
-
// Converts |points| to pixels. One point is 1/72 of an inch.
static float pointsToPixels(float points)
{
@@ -233,14 +181,6 @@ static float pointsToPixels(float points)
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();
@@ -251,51 +191,24 @@ static double querySystemBlinkInterval(double defaultInterval)
return blinkTime / 1000.0;
}
-#if ENABLE(VIDEO)
-// Attempt to retrieve a HTMLMediaElement from a Node. Returns NULL if one cannot be found.
-static HTMLMediaElement* mediaElementParent(Node* node)
-{
- if (!node)
- return 0;
- Node* mediaNode = node->shadowAncestorNode();
- if (!mediaNode || (!mediaNode->hasTagName(HTMLNames::videoTag) && !mediaNode->hasTagName(HTMLNames::audioTag)))
- return 0;
-
- return static_cast<HTMLMediaElement*>(mediaNode);
-}
-#endif
-
-// Implement WebCore::theme() for getting the global RenderTheme.
-RenderTheme* theme()
+PassRefPtr<RenderTheme> RenderThemeChromiumWin::create()
{
- static RenderThemeChromiumWin winTheme;
- return &winTheme;
+ return adoptRef(new RenderThemeChromiumWin);
}
-String RenderThemeChromiumWin::extraDefaultStyleSheet()
+PassRefPtr<RenderTheme> RenderTheme::themeForPage(Page* page)
{
- return String(themeWinUserAgentStyleSheet, sizeof(themeWinUserAgentStyleSheet));
+ static RenderTheme* rt = RenderThemeChromiumWin::create().releaseRef();
+ return rt;
}
-String RenderThemeChromiumWin::extraQuirksStyleSheet()
-{
- return String(themeWinQuirksUserAgentStyleSheet, sizeof(themeWinQuirksUserAgentStyleSheet));
-}
-
-#if ENABLE(VIDEO)
-String RenderThemeChromiumWin::extraMediaControlsStyleSheet()
-{
- return String(mediaControlsChromiumUserAgentStyleSheet, sizeof(mediaControlsChromiumUserAgentStyleSheet));
-}
-#endif
-
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;
+ // 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
@@ -337,23 +250,11 @@ Color RenderThemeChromiumWin::platformInactiveTextSearchHighlightColor() const
return Color(0xff, 0xff, 0x96); // Yellow.
}
-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, FontDescription& fontDescription) const
{
// This logic owes much to RenderThemeSafari.cpp.
- FontDescription* cachedDesc = NULL;
- wchar_t* faceName = 0;
+ FontDescription* cachedDesc = 0;
+ AtomicString faceName;
float fontSize = 0;
switch (propId) {
case CSSValueSmallCaption:
@@ -361,7 +262,7 @@ void RenderThemeChromiumWin::systemFont(int propId, FontDescription& fontDescrip
if (!smallSystemFont.isAbsoluteSize()) {
NONCLIENTMETRICS metrics;
getNonClientMetrics(&metrics);
- faceName = metrics.lfSmCaptionFont.lfFaceName;
+ faceName = AtomicString(metrics.lfSmCaptionFont.lfFaceName, wcslen(metrics.lfSmCaptionFont.lfFaceName));
fontSize = systemFontSize(metrics.lfSmCaptionFont);
}
break;
@@ -370,7 +271,7 @@ void RenderThemeChromiumWin::systemFont(int propId, FontDescription& fontDescrip
if (!menuFont.isAbsoluteSize()) {
NONCLIENTMETRICS metrics;
getNonClientMetrics(&metrics);
- faceName = metrics.lfMenuFont.lfFaceName;
+ faceName = AtomicString(metrics.lfMenuFont.lfFaceName, wcslen(metrics.lfMenuFont.lfFaceName));
fontSize = systemFontSize(metrics.lfMenuFont);
}
break;
@@ -400,9 +301,7 @@ void RenderThemeChromiumWin::systemFont(int propId, FontDescription& fontDescrip
cachedDesc = &fontDescription;
if (fontSize) {
- ASSERT(faceName);
- cachedDesc->firstFamily().setFamily(AtomicString(faceName,
- wcslen(faceName)));
+ cachedDesc->firstFamily().setFamily(faceName);
cachedDesc->setIsAbsoluteSize(true);
cachedDesc->setGenericFamily(FontDescription::NoFamily);
cachedDesc->setSpecifiedSize(fontSize);
@@ -412,44 +311,28 @@ void RenderThemeChromiumWin::systemFont(int propId, FontDescription& fontDescrip
fontDescription = *cachedDesc;
}
-int RenderThemeChromiumWin::minimumMenuListSize(RenderStyle* style) const
-{
- return 0;
-}
-
void RenderThemeChromiumWin::adjustSliderThumbSize(RenderObject* o) const
{
// These sizes match what WinXP draws for various menus.
const int sliderThumbAlongAxis = 11;
const int sliderThumbAcrossAxis = 21;
- if (o->style()->appearance() == SliderThumbHorizontalPart || o->style()->appearance() == MediaSliderThumbPart) {
+ if (o->style()->appearance() == SliderThumbHorizontalPart) {
o->style()->setWidth(Length(sliderThumbAlongAxis, Fixed));
o->style()->setHeight(Length(sliderThumbAcrossAxis, Fixed));
} else if (o->style()->appearance() == SliderThumbVerticalPart) {
o->style()->setWidth(Length(sliderThumbAcrossAxis, Fixed));
o->style()->setHeight(Length(sliderThumbAlongAxis, Fixed));
- }
+ } else
+ RenderThemeChromiumSkia::adjustSliderThumbSize(o);
}
-void RenderThemeChromiumWin::setCheckboxSize(RenderStyle* style) const
+bool RenderThemeChromiumWin::paintCheckbox(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& r)
{
- // 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);
+ return paintButton(o, i, r);
}
-
-void RenderThemeChromiumWin::setRadioSize(RenderStyle* style) const
+bool RenderThemeChromiumWin::paintRadio(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& r)
{
- // Use same sizing for radio box as checkbox.
- setCheckboxSize(style);
+ return paintButton(o, i, r);
}
bool RenderThemeChromiumWin::paintButton(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& r)
@@ -483,178 +366,9 @@ bool RenderThemeChromiumWin::paintSliderTrack(RenderObject* o, const RenderObjec
return false;
}
-void RenderThemeChromiumWin::adjustSearchFieldCancelButtonStyle(CSSStyleSelector*, RenderStyle* style, Element*) const
-{
- // Scale the button size based on the font size
- float fontScale = style->fontSize() / defaultControlFontPixelSize;
- int cancelButtonSize = lroundf(std::min(std::max(minCancelButtonSize, defaultCancelButtonSize * fontScale), maxCancelButtonSize));
- style->setWidth(Length(cancelButtonSize, Fixed));
- style->setHeight(Length(cancelButtonSize, Fixed));
-}
-
-bool RenderThemeChromiumWin::paintSearchFieldCancelButton(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& r)
-{
- IntRect bounds = r;
- ASSERT(o->parent());
- if (!o->parent() || !o->parent()->isBox())
- return false;
-
- RenderBox* parentRenderBox = toRenderBox(o->parent());
-
- IntRect parentBox = parentRenderBox->absoluteContentBox();
-
- // Make sure the scaled button stays square and will fit in its parent's box
- bounds.setHeight(std::min(parentBox.width(), std::min(parentBox.height(), bounds.height())));
- bounds.setWidth(bounds.height());
-
- // Center the button vertically. Round up though, so if it has to be one pixel off-center, it will
- // be one pixel closer to the bottom of the field. This tends to look better with the text.
- bounds.setY(parentBox.y() + (parentBox.height() - bounds.height() + 1) / 2);
-
- static Image* cancelImage = Image::loadPlatformResource("searchCancel").releaseRef();
- static Image* cancelPressedImage = Image::loadPlatformResource("searchCancelPressed").releaseRef();
- i.context->drawImage(isPressed(o) ? cancelPressedImage : cancelImage, bounds);
- return false;
-}
-
-void RenderThemeChromiumWin::adjustSearchFieldDecorationStyle(CSSStyleSelector*, RenderStyle* style, Element*) const
-{
- IntSize emptySize(1, 11);
- style->setWidth(Length(emptySize.width(), Fixed));
- style->setHeight(Length(emptySize.height(), Fixed));
-}
-
-void RenderThemeChromiumWin::adjustSearchFieldResultsDecorationStyle(CSSStyleSelector*, RenderStyle* style, Element*) const
-{
- // Scale the decoration size based on the font size
- float fontScale = style->fontSize() / defaultControlFontPixelSize;
- int magnifierSize = lroundf(std::min(std::max(minSearchFieldResultsDecorationSize, defaultSearchFieldResultsDecorationSize * fontScale),
- maxSearchFieldResultsDecorationSize));
- style->setWidth(Length(magnifierSize, Fixed));
- style->setHeight(Length(magnifierSize, Fixed));
-}
-
-bool RenderThemeChromiumWin::paintSearchFieldResultsDecoration(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& r)
-{
- IntRect bounds = r;
- ASSERT(o->parent());
- if (!o->parent() || !o->parent()->isBox())
- return false;
-
- RenderBox* parentRenderBox = toRenderBox(o->parent());
- IntRect parentBox = parentRenderBox->absoluteContentBox();
-
- // Make sure the scaled decoration stays square and will fit in its parent's box
- bounds.setHeight(std::min(parentBox.width(), std::min(parentBox.height(), bounds.height())));
- bounds.setWidth(bounds.height());
-
- // Center the decoration vertically. Round up though, so if it has to be one pixel off-center, it will
- // be one pixel closer to the bottom of the field. This tends to look better with the text.
- bounds.setY(parentBox.y() + (parentBox.height() - bounds.height() + 1) / 2);
-
- static Image* magnifierImage = Image::loadPlatformResource("searchMagnifier").releaseRef();
- i.context->drawImage(magnifierImage, bounds);
- return false;
-}
-
-void RenderThemeChromiumWin::adjustSearchFieldResultsButtonStyle(CSSStyleSelector*, RenderStyle* style, Element*) const
-{
- // Scale the button size based on the font size
- float fontScale = style->fontSize() / defaultControlFontPixelSize;
- int magnifierHeight = lroundf(std::min(std::max(minSearchFieldResultsDecorationSize, defaultSearchFieldResultsDecorationSize * fontScale),
- maxSearchFieldResultsDecorationSize));
- int magnifierWidth = lroundf(magnifierHeight * defaultSearchFieldResultsButtonWidth / defaultSearchFieldResultsDecorationSize);
- style->setWidth(Length(magnifierWidth, Fixed));
- style->setHeight(Length(magnifierHeight, Fixed));
-}
-
-bool RenderThemeChromiumWin::paintSearchFieldResultsButton(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& r)
-{
- IntRect bounds = r;
- ASSERT(o->parent());
- if (!o->parent())
- return false;
- if (!o->parent() || !o->parent()->isBox())
- return false;
-
- RenderBox* parentRenderBox = toRenderBox(o->parent());
- IntRect parentBox = parentRenderBox->absoluteContentBox();
-
- // Make sure the scaled decoration will fit in its parent's box
- bounds.setHeight(std::min(parentBox.height(), bounds.height()));
- bounds.setWidth(std::min(parentBox.width(), static_cast<int>(bounds.height() * defaultSearchFieldResultsButtonWidth / defaultSearchFieldResultsDecorationSize)));
-
- // Center the button vertically. Round up though, so if it has to be one pixel off-center, it will
- // be one pixel closer to the bottom of the field. This tends to look better with the text.
- bounds.setY(parentBox.y() + (parentBox.height() - bounds.height() + 1) / 2);
-
- static Image* magnifierImage = Image::loadPlatformResource("searchMagnifierResults").releaseRef();
- i.context->drawImage(magnifierImage, bounds);
- return false;
-}
-
-bool RenderThemeChromiumWin::paintMediaButtonInternal(GraphicsContext* context, const IntRect& rect, Image* image)
+bool RenderThemeChromiumWin::paintSliderThumb(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& r)
{
- context->beginTransparencyLayer(defaultMediaControlOpacity);
-
- // Draw background.
- Color oldFill = context->fillColor();
- Color oldStroke = context->strokeColor();
-
- context->setFillColor(Color::black);
- context->setStrokeColor(Color::black);
- context->drawRect(rect);
-
- context->setFillColor(oldFill);
- context->setStrokeColor(oldStroke);
-
- // Create a destination rectangle for the image that is centered in the drawing rectangle, rounded left, and down.
- IntRect imageRect = image->rect();
- imageRect.setY(rect.y() + (rect.height() - image->height() + 1) / 2);
- imageRect.setX(rect.x() + (rect.width() - image->width() + 1) / 2);
-
- context->drawImage(image, imageRect, CompositeSourceAtop);
- context->endTransparencyLayer();
-
- return false;
-}
-
-bool RenderThemeChromiumWin::paintMediaPlayButton(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& rect)
-{
-#if ENABLE(VIDEO)
- HTMLMediaElement* mediaElement = mediaElementParent(o->node());
- if (!mediaElement)
- return false;
-
- static Image* mediaPlay = Image::loadPlatformResource("mediaPlay").releaseRef();
- static Image* mediaPause = Image::loadPlatformResource("mediaPause").releaseRef();
-
- return paintMediaButtonInternal(paintInfo.context, rect, mediaElement->paused() ? mediaPlay : mediaPause);
-#else
- return false;
-#endif
-}
-
-bool RenderThemeChromiumWin::paintMediaMuteButton(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& rect)
-{
-#if ENABLE(VIDEO)
- HTMLMediaElement* mediaElement = mediaElementParent(o->node());
- if (!mediaElement)
- return false;
-
- static Image* soundFull = Image::loadPlatformResource("mediaSoundFull").releaseRef();
- static Image* soundNone = Image::loadPlatformResource("mediaSoundNone").releaseRef();
-
- return paintMediaButtonInternal(paintInfo.context, rect, mediaElement->muted() ? soundNone: soundFull);
-#else
- return false;
-#endif
-}
-
-void RenderThemeChromiumWin::adjustMenuListStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
-{
- // Height is locked to auto on all browsers.
- style->setLineHeight(RenderStyle::initialLineHeight());
+ return paintSliderTrack(o, i, r);
}
// Used to paint unstyled menulists (i.e. with the default border)
@@ -709,66 +423,22 @@ bool RenderThemeChromiumWin::paintMenuList(RenderObject* o, const RenderObject::
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);
-}
-
-int RenderThemeChromiumWin::buttonInternalPaddingLeft() const
-{
- return 3;
-}
-
-int RenderThemeChromiumWin::buttonInternalPaddingRight() const
-{
- return 3;
-}
-
-int RenderThemeChromiumWin::buttonInternalPaddingTop() const
-{
- return 1;
-}
-
-int RenderThemeChromiumWin::buttonInternalPaddingBottom() const
-{
- return 1;
-}
-
// static
void RenderThemeChromiumWin::setDefaultFontSize(int fontSize)
{
- defaultFontSize = static_cast<float>(fontSize);
+ RenderThemeChromiumSkia::setDefaultFontSize(fontSize);
// Reset cached fonts.
smallSystemFont = menuFont = labelFont = FontDescription();
}
+double RenderThemeChromiumWin::caretBlinkIntervalInternal() const
+{
+ // This involves a system call, so we cache the result.
+ static double blinkInterval = querySystemBlinkInterval(RenderTheme::caretBlinkInterval());
+ return blinkInterval;
+}
+
unsigned RenderThemeChromiumWin::determineState(RenderObject* o)
{
unsigned result = TS_NORMAL;
@@ -795,7 +465,7 @@ unsigned RenderThemeChromiumWin::determineSliderThumbState(RenderObject* o)
result = TUS_DISABLED;
else if (supportsFocus(o->style()->appearance()) && isFocused(o->parent()))
result = TUS_FOCUSED;
- else if (static_cast<RenderSlider*>(o->parent())->inDragMode())
+ else if (toRenderSlider(o->parent())->inDragMode())
result = TUS_PRESSED;
else if (isHovered(o))
result = TUS_HOT;
@@ -909,22 +579,4 @@ bool RenderThemeChromiumWin::paintTextFieldInternal(RenderObject* o,
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;
-}
-
} // namespace WebCore
diff --git a/WebCore/rendering/RenderThemeChromiumWin.h b/WebCore/rendering/RenderThemeChromiumWin.h
index 6ba6595..5e98c9b 100644
--- a/WebCore/rendering/RenderThemeChromiumWin.h
+++ b/WebCore/rendering/RenderThemeChromiumWin.h
@@ -24,7 +24,7 @@
#ifndef RenderThemeChromiumWin_h
#define RenderThemeChromiumWin_h
-#include "RenderTheme.h"
+#include "RenderThemeChromiumSkia.h"
#if WIN32
typedef void* HANDLE;
@@ -42,19 +42,9 @@ namespace WebCore {
unsigned m_classicState;
};
- class RenderThemeChromiumWin : public RenderTheme {
+ class RenderThemeChromiumWin : public RenderThemeChromiumSkia {
public:
- RenderThemeChromiumWin() { }
- ~RenderThemeChromiumWin() { }
-
- virtual String extraDefaultStyleSheet();
- virtual String extraQuirksStyleSheet();
-#if ENABLE(VIDEO)
- virtual String extraMediaControlsStyleSheet();
-#endif
-
- // A method asking if the theme's controls actually care about redrawing when hovered.
- virtual bool supportsHover(const RenderStyle*) const { return true; }
+ static PassRefPtr<RenderTheme> create();
// A method asking if the theme is able to draw the focus ring.
virtual bool supportsFocusRing(const RenderStyle*) const;
@@ -67,46 +57,18 @@ namespace WebCore {
virtual Color platformActiveTextSearchHighlightColor() const;
virtual Color platformInactiveTextSearchHighlightColor() const;
- virtual double caretBlinkInterval() const;
-
// System fonts.
virtual void systemFont(int propId, FontDescription&) const;
- virtual int minimumMenuListSize(RenderStyle*) const;
-
virtual void adjustSliderThumbSize(RenderObject*) 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;
-
+ // Various paint functions.
+ virtual bool paintCheckbox(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+ virtual bool paintRadio(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
virtual bool paintButton(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
-
virtual bool paintTextField(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
-
- virtual bool paintTextArea(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& r) { return paintTextField(o, i, r); }
-
virtual bool paintSliderTrack(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
-
- virtual bool paintSliderThumb(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& r) { return paintSliderTrack(o, i, r); }
-
- virtual bool paintSearchField(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& r) { return paintTextField(o, i, r); }
-
- virtual void adjustSearchFieldCancelButtonStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
- virtual bool paintSearchFieldCancelButton(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
-
- virtual void adjustSearchFieldDecorationStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
-
- virtual void adjustSearchFieldResultsDecorationStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
- virtual bool paintSearchFieldResultsDecoration(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
-
- virtual void adjustSearchFieldResultsButtonStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
- virtual bool paintSearchFieldResultsButton(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
-
- virtual bool paintMediaPlayButton(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
- virtual bool paintMediaMuteButton(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+ virtual bool paintSliderThumb(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
// MenuList refers to an unstyled menulist (meaning a menulist without
// background-color or border set) and MenuListButton refers to a styled
@@ -117,30 +79,19 @@ namespace WebCore {
// In short, we either go down the MenuList code path or the MenuListButton
// codepath. We never go down both. And in both cases, they render the
// entire menulist.
- virtual void adjustMenuListStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
virtual bool paintMenuList(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
- virtual void adjustMenuListButtonStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
- virtual bool paintMenuListButton(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
-
- // These methods define the padding for the MenuList's inner block.
- virtual int popupInternalPaddingLeft(RenderStyle*) const;
- virtual int popupInternalPaddingRight(RenderStyle*) const;
- virtual int popupInternalPaddingTop(RenderStyle*) const;
- virtual int popupInternalPaddingBottom(RenderStyle*) const;
-
- virtual int buttonInternalPaddingLeft() const;
- virtual int buttonInternalPaddingRight() const;
- virtual int buttonInternalPaddingTop() const;
- virtual int buttonInternalPaddingBottom() const;
-
- // Provide a way to pass the default font size from the Settings object
- // to the render theme. FIXME: http://b/1129186 A cleaner way would be
- // to remove the default font size from this object and have callers
- // that need the value to get it directly from the appropriate Settings
- // object.
+
+ // Override RenderThemeChromiumSkia's setDefaultFontSize method to also reset the local font property caches.
+ // See comment in RenderThemeChromiumSkia::setDefaultFontSize() regarding ugliness of this hack.
static void setDefaultFontSize(int);
+ protected:
+ virtual double caretBlinkIntervalInternal() const;
+
private:
+ RenderThemeChromiumWin() { }
+ virtual ~RenderThemeChromiumWin() { }
+
unsigned determineState(RenderObject*);
unsigned determineSliderThumbState(RenderObject*);
unsigned determineClassicState(RenderObject*);
@@ -148,9 +99,6 @@ namespace WebCore {
ThemeData getThemeData(RenderObject*);
bool paintTextFieldInternal(RenderObject*, const RenderObject::PaintInfo&, const IntRect&, bool);
- bool paintMediaButtonInternal(GraphicsContext*, const IntRect&, Image*);
-
- int menuListInternalPadding(RenderStyle*, int paddingType) const;
};
} // namespace WebCore
diff --git a/WebCore/rendering/RenderThemeMac.h b/WebCore/rendering/RenderThemeMac.h
index 63f1d97..85f141f 100644
--- a/WebCore/rendering/RenderThemeMac.h
+++ b/WebCore/rendering/RenderThemeMac.h
@@ -39,8 +39,7 @@ class RenderStyle;
class RenderThemeMac : public RenderTheme {
public:
- RenderThemeMac();
- virtual ~RenderThemeMac();
+ static PassRefPtr<RenderTheme> create();
// A method asking if the control changes its tint when the window has focus or not.
virtual bool controlSupportsTints(const RenderObject*) const;
@@ -59,6 +58,7 @@ public:
virtual Color platformActiveListBoxSelectionForegroundColor() const;
virtual Color platformInactiveListBoxSelectionBackgroundColor() const;
virtual Color platformInactiveListBoxSelectionForegroundColor() const;
+ virtual Color platformFocusRingColor() const;
virtual ScrollbarControlSize scrollbarControlSizeForPart(ControlPart) { return SmallScrollbar; }
@@ -124,16 +124,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 paintMediaRewindButton(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+ virtual bool paintMediaReturnToRealtimeButton(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+ virtual bool paintMediaControlsBackground(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
virtual bool paintMediaCurrentTime(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
virtual bool paintMediaTimeRemaining(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
// Media controls
- virtual bool hitTestMediaControlPart(RenderObject*, const IntPoint& absPoint);
virtual String extraMediaControlsStyleSheet();
#endif
private:
+ RenderThemeMac();
+ virtual ~RenderThemeMac();
+
IntRect inflateRect(const IntRect&, const IntSize&, const int* margins, float zoomLevel = 1.0f) const;
FloatRect convertToPaintingRect(const RenderObject* inputRenderer, const RenderObject* partRenderer, const FloatRect& inputRect, const IntRect& r) const;
diff --git a/WebCore/rendering/RenderThemeMac.mm b/WebCore/rendering/RenderThemeMac.mm
index c3ec91a..6315f9f 100644
--- a/WebCore/rendering/RenderThemeMac.mm
+++ b/WebCore/rendering/RenderThemeMac.mm
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -21,6 +21,7 @@
#import "RenderThemeMac.h"
#import "BitmapImage.h"
+#import "ColorMac.h"
#import "CSSStyleSelector.h"
#import "CSSValueKeywords.h"
#import "Document.h"
@@ -33,6 +34,7 @@
#import "Image.h"
#import "LocalCurrentGraphicsContext.h"
#import "MediaControlElements.h"
+#import "RenderMedia.h"
#import "RenderSlider.h"
#import "RenderView.h"
#import "SharedBuffer.h"
@@ -101,10 +103,15 @@ enum {
leftPadding
};
-RenderTheme* theme()
+PassRefPtr<RenderTheme> RenderTheme::themeForPage(Page*)
{
- static RenderThemeMac* macTheme = new RenderThemeMac;
- return macTheme;
+ static RenderTheme* rt = RenderThemeMac::create().releaseRef();
+ return rt;
+}
+
+PassRefPtr<RenderTheme> RenderThemeMac::create()
+{
+ return adoptRef(new RenderThemeMac);
}
RenderThemeMac::RenderThemeMac()
@@ -151,6 +158,14 @@ Color RenderThemeMac::platformInactiveListBoxSelectionForegroundColor() const
return Color::black;
}
+Color RenderThemeMac::platformFocusRingColor() const
+{
+ if (usesTestModeFocusRingColor())
+ return oldAquaFocusRingColor();
+
+ return systemColor(CSSValueWebkitFocusRingColor);
+}
+
Color RenderThemeMac::platformInactiveListBoxSelectionBackgroundColor() const
{
return platformInactiveSelectionBackgroundColor();
@@ -408,6 +423,9 @@ Color RenderThemeMac::systemColor(int cssValueId) const
case CSSValueThreedlightshadow:
color = convertNSColorToColor([NSColor controlLightHighlightColor]);
break;
+ case CSSValueWebkitFocusRingColor:
+ color = convertNSColorToColor([NSColor keyboardFocusIndicatorColor]);
+ break;
case CSSValueWindow:
color = convertNSColorToColor([NSColor windowBackgroundColor]);
break;
@@ -1116,7 +1134,7 @@ bool RenderThemeMac::paintSliderThumb(RenderObject* o, const RenderObject::Paint
else
oldPressed = m_isSliderThumbHorizontalPressed;
- bool pressed = static_cast<RenderSlider*>(o->parent())->inDragMode();
+ bool pressed = toRenderSlider(o->parent())->inDragMode();
if (o->style()->appearance() == SliderThumbVerticalPart)
m_isSliderThumbVerticalPressed = pressed;
@@ -1403,25 +1421,37 @@ typedef enum {
static int mediaControllerTheme()
{
- static const long minimumQuickTimeVersion = 0x07600000; // 7.6
+ static const long minimumQuickTimeVersion = 0x07630000; // 7.6.3
static SInt32 quickTimeVersion = 0;
+ static int controllerTheme = -1;
+
+ if (controllerTheme != -1)
+ return controllerTheme;
+
+ controllerTheme = MediaControllerThemeClassic;
if (!quickTimeVersion) {
OSErr err;
err = Gestalt(gestaltQuickTime, &quickTimeVersion);
if (err != noErr)
- return MediaControllerThemeClassic;
+ return controllerTheme;
}
if (quickTimeVersion < minimumQuickTimeVersion)
- return MediaControllerThemeClassic;
+ return controllerTheme;
- // keep the feature off for now without an explicit opt-in
Boolean validKey;
Boolean useQTMediaUI = CFPreferencesGetAppBooleanValue(CFSTR("UseQuickTimeMediaUI"), CFSTR("com.apple.WebCore"), &validKey);
+
+#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
+ if (validKey && !useQTMediaUI)
+ return controllerTheme;
+#else
if (!validKey || !useQTMediaUI)
- return MediaControllerThemeClassic;
+ return controllerTheme;
+#endif
- return MediaControllerThemeQT;
+ controllerTheme = MediaControllerThemeQT;
+ return controllerTheme;
}
#endif
@@ -1460,6 +1490,37 @@ void RenderThemeMac::adjustSliderThumbSize(RenderObject* o) const
#if ENABLE(VIDEO)
+enum WKMediaControllerThemeState {
+ MediaUIPartDisabledFlag = 1 << 0,
+ MediaUIPartPressedFlag = 1 << 1,
+ MediaUIPartDrawEndCapsFlag = 1 << 3,
+};
+
+static unsigned getMediaUIPartStateFlags(Node* node)
+{
+ unsigned flags = 0;
+
+ if (node->active())
+ flags |= MediaUIPartPressedFlag;
+ return flags;
+}
+
+// Utility to scale when the UI part are not scaled by wkDrawMediaUIPart
+static FloatRect getUnzoomedRectAndAdjustCurrentContext(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect &originalRect)
+{
+ float zoomLevel = o->style()->effectiveZoom();
+ FloatRect unzoomedRect(originalRect);
+ if (zoomLevel != 1.0f && mediaControllerTheme() == MediaControllerThemeQT) {
+ 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());
+ }
+ return unzoomedRect;
+}
+
+
bool RenderThemeMac::paintMediaFullscreenButton(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
{
Node* node = o->node();
@@ -1467,7 +1528,7 @@ bool RenderThemeMac::paintMediaFullscreenButton(RenderObject* o, const RenderObj
return false;
LocalCurrentGraphicsContext localContext(paintInfo.context);
- wkDrawMediaUIPart(MediaFullscreenButton, mediaControllerTheme(), paintInfo.context->platformContext(), r, node->active());
+ wkDrawMediaUIPart(MediaFullscreenButton, mediaControllerTheme(), paintInfo.context->platformContext(), r, getMediaUIPartStateFlags(node));
return false;
}
@@ -1478,12 +1539,11 @@ bool RenderThemeMac::paintMediaMuteButton(RenderObject* o, const RenderObject::P
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, mediaControllerTheme(), paintInfo.context->platformContext(), r, node->active());
+ if (MediaControlPlayButtonElement* btn = static_cast<MediaControlPlayButtonElement*>(node)) {
+ LocalCurrentGraphicsContext localContext(paintInfo.context);
+ wkDrawMediaUIPart(btn->displayType(), mediaControllerTheme(), paintInfo.context->platformContext(), r, getMediaUIPartStateFlags(node));
+
+ }
return false;
}
@@ -1494,12 +1554,10 @@ bool RenderThemeMac::paintMediaPlayButton(RenderObject* o, const RenderObject::P
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, mediaControllerTheme(), paintInfo.context->platformContext(), r, node->active());
+ if (MediaControlPlayButtonElement* btn = static_cast<MediaControlPlayButtonElement*>(node)) {
+ LocalCurrentGraphicsContext localContext(paintInfo.context);
+ wkDrawMediaUIPart(btn->displayType(), mediaControllerTheme(), paintInfo.context->platformContext(), r, getMediaUIPartStateFlags(node));
+ }
return false;
}
@@ -1510,7 +1568,7 @@ bool RenderThemeMac::paintMediaSeekBackButton(RenderObject* o, const RenderObjec
return false;
LocalCurrentGraphicsContext localContext(paintInfo.context);
- wkDrawMediaUIPart(MediaSeekBackButton, mediaControllerTheme(), paintInfo.context->platformContext(), r, node->active());
+ wkDrawMediaUIPart(MediaSeekBackButton, mediaControllerTheme(), paintInfo.context->platformContext(), r, getMediaUIPartStateFlags(node));
return false;
}
@@ -1521,7 +1579,7 @@ bool RenderThemeMac::paintMediaSeekForwardButton(RenderObject* o, const RenderOb
return false;
LocalCurrentGraphicsContext localContext(paintInfo.context);
- wkDrawMediaUIPart(MediaSeekForwardButton, mediaControllerTheme(), paintInfo.context->platformContext(), r, node->active());
+ wkDrawMediaUIPart(MediaSeekForwardButton, mediaControllerTheme(), paintInfo.context->platformContext(), r, getMediaUIPartStateFlags(node));
return false;
}
@@ -1545,7 +1603,12 @@ bool RenderThemeMac::paintMediaSliderTrack(RenderObject* o, const RenderObject::
currentTime = player->currentTime();
}
- wkDrawMediaSliderTrack(mediaControllerTheme(), paintInfo.context->platformContext(), r, timeLoaded, currentTime, duration);
+ paintInfo.context->save();
+ FloatRect unzoomedRect = getUnzoomedRectAndAdjustCurrentContext(o, paintInfo, r);
+ wkDrawMediaSliderTrack(mediaControllerTheme(), paintInfo.context->platformContext(), unzoomedRect,
+ timeLoaded, currentTime, duration, getMediaUIPartStateFlags(node));
+
+ paintInfo.context->restore();
return false;
}
@@ -1556,18 +1619,41 @@ bool RenderThemeMac::paintMediaSliderThumb(RenderObject* o, const RenderObject::
return false;
LocalCurrentGraphicsContext localContext(paintInfo.context);
- wkDrawMediaUIPart(MediaSliderThumb, mediaControllerTheme(), paintInfo.context->platformContext(), r, node->active());
+ wkDrawMediaUIPart(MediaSliderThumb, mediaControllerTheme(), paintInfo.context->platformContext(), r, getMediaUIPartStateFlags(node));
+ return false;
+}
+
+bool RenderThemeMac::paintMediaRewindButton(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
+{
+ Node* node = o->node();
+ if (!node)
+ return false;
+
+ LocalCurrentGraphicsContext localContext(paintInfo.context);
+ wkDrawMediaUIPart(MediaRewindButton, mediaControllerTheme(), paintInfo.context->platformContext(), r, getMediaUIPartStateFlags(node));
return false;
}
-bool RenderThemeMac::paintMediaTimelineContainer(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
+bool RenderThemeMac::paintMediaReturnToRealtimeButton(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
+{
+ Node* node = o->node();
+ if (!node)
+ return false;
+
+ LocalCurrentGraphicsContext localContext(paintInfo.context);
+ wkDrawMediaUIPart(MediaReturnToRealtimeButton, mediaControllerTheme(), paintInfo.context->platformContext(), r, getMediaUIPartStateFlags(node));
+ return false;
+}
+
+
+bool RenderThemeMac::paintMediaControlsBackground(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
{
Node* node = o->node();
if (!node)
return false;
LocalCurrentGraphicsContext localContext(paintInfo.context);
- wkDrawMediaUIPart(MediaTimelineContainer, mediaControllerTheme(), paintInfo.context->platformContext(), r, node->active());
+ wkDrawMediaUIPart(MediaTimelineContainer, mediaControllerTheme(), paintInfo.context->platformContext(), r, getMediaUIPartStateFlags(node));
return false;
}
@@ -1577,8 +1663,10 @@ bool RenderThemeMac::paintMediaCurrentTime(RenderObject* o, const RenderObject::
if (!node)
return false;
- LocalCurrentGraphicsContext localContext(paintInfo.context);
- wkDrawMediaUIPart(MediaCurrentTimeDisplay, mediaControllerTheme(), paintInfo.context->platformContext(), r, node->active());
+ paintInfo.context->save();
+ FloatRect unzoomedRect = getUnzoomedRectAndAdjustCurrentContext(o, paintInfo, r);
+ wkDrawMediaUIPart(MediaCurrentTimeDisplay, mediaControllerTheme(), paintInfo.context->platformContext(), unzoomedRect, getMediaUIPartStateFlags(node));
+ paintInfo.context->restore();
return false;
}
@@ -1588,8 +1676,10 @@ bool RenderThemeMac::paintMediaTimeRemaining(RenderObject* o, const RenderObject
if (!node)
return false;
- LocalCurrentGraphicsContext localContext(paintInfo.context);
- wkDrawMediaUIPart(MediaTimeRemainingDisplay, mediaControllerTheme(), paintInfo.context->platformContext(), r, node->active());
+ paintInfo.context->save();
+ FloatRect unzoomedRect = getUnzoomedRectAndAdjustCurrentContext(o, paintInfo, r);
+ wkDrawMediaUIPart(MediaTimeRemainingDisplay, mediaControllerTheme(), paintInfo.context->platformContext(), unzoomedRect, getMediaUIPartStateFlags(node));
+ paintInfo.context->restore();
return false;
}
@@ -1600,20 +1690,6 @@ String RenderThemeMac::extraMediaControlsStyleSheet()
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
diff --git a/WebCore/rendering/RenderThemeSafari.cpp b/WebCore/rendering/RenderThemeSafari.cpp
index 3affd1f..23998d4 100644
--- a/WebCore/rendering/RenderThemeSafari.cpp
+++ b/WebCore/rendering/RenderThemeSafari.cpp
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2007, 2008 Apple Inc.
+ * Copyright (C) 2009 Kenneth Rohde Christiansen
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -65,13 +66,24 @@ enum {
leftPadding
};
-RenderTheme* theme()
+PassRefPtr<RenderTheme> RenderThemeSafari::create()
{
- static RenderThemeSafari safariTheme;
- static RenderThemeWin windowsTheme;
- if (Settings::shouldPaintNativeControls())
- return &windowsTheme;
- return &safariTheme;
+ return adoptRef(new RenderThemeSafari);
+}
+
+PassRefPtr<RenderTheme> RenderTheme::themeForPage(Page* page)
+{
+ static RenderTheme* safariTheme = RenderThemeSafari::create().releaseRef();
+ static RenderTheme* windowsTheme = RenderThemeWin::create().releaseRef();
+
+ // FIXME: This is called before Settings has been initialized by WebKit, so will return a
+ // potentially wrong answer the very first time it's called (see
+ // <https://bugs.webkit.org/show_bug.cgi?id=26493>).
+ if (Settings::shouldPaintNativeControls()) {
+ RenderTheme::setCustomFocusRingColor(safariTheme->platformFocusRingColor());
+ return windowsTheme; // keep the reference of one.
+ }
+ return safariTheme; // keep the reference of one.
}
#if !defined(NDEBUG) && defined(USE_DEBUG_SAFARI_THEME)
@@ -84,6 +96,17 @@ SOFT_LINK(SafariTheme, paintThemePart, void, __stdcall, (ThemePart part, CGConte
#if defined(SAFARI_THEME_VERSION) && SAFARI_THEME_VERSION >= 2
SOFT_LINK(SafariTheme, STPaintProgressIndicator, void, APIENTRY, (ProgressIndicatorType type, CGContextRef context, const CGRect& rect, NSControlSize size, ThemeControlState state, float value), (type, context, rect, size, state, value))
#endif
+SOFT_LINK_OPTIONAL(SafariTheme, STCopyThemeColor, CGColorRef, APIENTRY, (unsigned color, SafariTheme::ThemeControlState));
+
+static const unsigned stFocusRingColorID = 4;
+
+static const unsigned aquaFocusRingColor = 0xFF7DADD9;
+
+static RGBA32 makeRGBAFromCGColor(CGColorRef color)
+{
+ const CGFloat* components = CGColorGetComponents(color);
+ return makeRGBA(255 * components[0], 255 * components[1], 255 * components[2], 255 * components[3]);
+}
ThemeControlState RenderThemeSafari::determineState(RenderObject* o) const
{
@@ -139,6 +162,22 @@ Color RenderThemeSafari::activeListBoxSelectionBackgroundColor() const
return Color(56, 117, 215);
}
+Color RenderThemeSafari::platformFocusRingColor() const
+{
+ static Color focusRingColor;
+
+ if (!focusRingColor.isValid()) {
+ if (STCopyThemeColorPtr()) {
+ RetainPtr<CGColorRef> color(AdoptCF, STCopyThemeColorPtr()(stFocusRingColorID, SafariTheme::ActiveState));
+ focusRingColor = makeRGBAFromCGColor(color.get());
+ }
+ if (!focusRingColor.isValid())
+ focusRingColor = aquaFocusRingColor;
+ }
+
+ return focusRingColor;
+}
+
static float systemFontSizeForControlSize(NSControlSize controlSize)
{
static float sizes[] = { 13.0f, 11.0f, 9.0f };
@@ -961,7 +1000,7 @@ bool RenderThemeSafari::paintSliderThumb(RenderObject* o, const RenderObject::Pa
ASSERT(o->parent()->isSlider());
- bool pressed = static_cast<RenderSlider*>(o->parent())->inDragMode();
+ bool pressed = toRenderSlider(o->parent())->inDragMode();
ThemeControlState state = determineState(o->parent());
state &= ~SafariTheme::PressedState;
if (pressed)
diff --git a/WebCore/rendering/RenderThemeSafari.h b/WebCore/rendering/RenderThemeSafari.h
index 8ac5acf..fb8ffb0 100644
--- a/WebCore/rendering/RenderThemeSafari.h
+++ b/WebCore/rendering/RenderThemeSafari.h
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2007, 2008 Apple Inc.
+ * Copyright (C) 2009 Kenneth Rohde Christiansen
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -46,8 +47,7 @@ class RenderStyle;
class RenderThemeSafari : public RenderTheme {
public:
- RenderThemeSafari();
- virtual ~RenderThemeSafari();
+ static PassRefPtr<RenderTheme> create();
// A method to obtain the baseline position for a "leaf" control. This will only be used if a baseline
// position cannot be determined by examining child content. Checkboxes and radio buttons are examples of
@@ -69,6 +69,8 @@ public:
virtual Color platformInactiveSelectionBackgroundColor() const;
virtual Color activeListBoxSelectionBackgroundColor() const;
+ virtual Color platformFocusRingColor() const;
+
// System fonts.
virtual void systemFont(int propId, FontDescription&) const;
@@ -137,6 +139,9 @@ protected:
#endif
private:
+ RenderThemeSafari();
+ virtual ~RenderThemeSafari();
+
IntRect inflateRect(const IntRect&, const IntSize&, const int* margins) const;
// Get the control size based off the font. Used by some of the controls (like buttons).
diff --git a/WebCore/rendering/RenderThemeWin.cpp b/WebCore/rendering/RenderThemeWin.cpp
index 1fa5162..92bfd03 100644
--- a/WebCore/rendering/RenderThemeWin.cpp
+++ b/WebCore/rendering/RenderThemeWin.cpp
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2006, 2007 Apple Inc.
+ * Copyright (C) 2009 Kenneth Rohde Christiansen
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -134,11 +135,16 @@ void RenderThemeWin::setWebKitIsBeingUnloaded()
gWebKitIsBeingUnloaded = true;
}
+PassRefPtr<RenderTheme> RenderThemeWin::create()
+{
+ return adoptRef(new RenderThemeWin);
+}
+
#if !USE(SAFARI_THEME)
-RenderTheme* theme()
+PassRefPtr<RenderTheme> RenderTheme::themeForPage(Page* page)
{
- static RenderThemeWin winTheme;
- return &winTheme;
+ static RenderTheme* winTheme = RenderThemeWin::create().releaseRef();
+ return winTheme;
}
#endif
@@ -422,7 +428,7 @@ unsigned RenderThemeWin::determineSliderThumbState(RenderObject* o)
result = TUS_DISABLED;
else if (supportsFocus(o->style()->appearance()) && isFocused(o->parent()))
result = TUS_FOCUSED;
- else if (static_cast<RenderSlider*>(o->parent())->inDragMode())
+ else if (toRenderSlider(o->parent())->inDragMode())
result = TUS_PRESSED;
else if (isHovered(o))
result = TUS_HOT;
diff --git a/WebCore/rendering/RenderThemeWin.h b/WebCore/rendering/RenderThemeWin.h
index 25473a1..99c2004 100644
--- a/WebCore/rendering/RenderThemeWin.h
+++ b/WebCore/rendering/RenderThemeWin.h
@@ -2,6 +2,7 @@
* This file is part of the WebKit project.
*
* Copyright (C) 2006, 2008 Apple Computer, Inc.
+ * Copyright (C) 2009 Kenneth Rohde Christiansen
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -48,8 +49,7 @@ struct ThemeData {
class RenderThemeWin : public RenderTheme {
public:
- RenderThemeWin();
- ~RenderThemeWin();
+ static PassRefPtr<RenderTheme> create();
virtual String extraDefaultStyleSheet();
virtual String extraQuirksStyleSheet();
@@ -135,6 +135,9 @@ public:
#endif
private:
+ RenderThemeWin();
+ ~RenderThemeWin();
+
void addIntrinsicMargins(RenderStyle*) const;
void close();
diff --git a/WebCore/rendering/RenderThemeWince.cpp b/WebCore/rendering/RenderThemeWince.cpp
new file mode 100644
index 0000000..fb89678
--- /dev/null
+++ b/WebCore/rendering/RenderThemeWince.cpp
@@ -0,0 +1,667 @@
+/*
+ * This file is part of the WebKit project.
+ *
+ * Copyright (C) 2006, 2007 Apple Computer, Inc.
+ * Copyright (C) 2007-2009 Torch Mobile, 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 "RenderThemeWince.h"
+
+#include "CSSStyleSheet.h"
+#include "CSSValueKeywords.h"
+#include "Document.h"
+#include "GraphicsContext.h"
+#if ENABLE(VIDEO)
+#include "HTMLMediaElement.h"
+#endif
+
+#include <windows.h>
+
+/*
+ * The following constants are used to determine how a widget is drawn using
+ * Windows' Theme API. For more information on theme parts and states see
+ * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/shellcc/platform/commctls/userex/topics/partsandstates.asp
+ */
+#define THEME_COLOR 204
+#define THEME_FONT 210
+
+// Generic state constants
+#define TS_NORMAL 1
+#define TS_HOVER 2
+#define TS_ACTIVE 3
+#define TS_DISABLED 4
+#define TS_FOCUSED 5
+
+// Button constants
+#define BP_BUTTON 1
+#define BP_RADIO 2
+#define BP_CHECKBOX 3
+
+// Textfield constants
+#define TFP_TEXTFIELD 1
+#define TFS_READONLY 6
+
+typedef HANDLE (WINAPI*openThemeDataPtr)(HWND hwnd, LPCWSTR pszClassList);
+typedef HRESULT (WINAPI*closeThemeDataPtr)(HANDLE hTheme);
+typedef HRESULT (WINAPI*drawThemeBackgroundPtr)(HANDLE hTheme, HDC hdc, int iPartId,
+ int iStateId, const RECT *pRect,
+ const RECT* pClipRect);
+typedef HRESULT (WINAPI*drawThemeEdgePtr)(HANDLE hTheme, HDC hdc, int iPartId,
+ int iStateId, const RECT *pRect,
+ unsigned uEdge, unsigned uFlags,
+ const RECT* pClipRect);
+typedef HRESULT (WINAPI*getThemeContentRectPtr)(HANDLE hTheme, HDC hdc, int iPartId,
+ int iStateId, const RECT* pRect,
+ RECT* pContentRect);
+typedef HRESULT (WINAPI*getThemePartSizePtr)(HANDLE hTheme, HDC hdc, int iPartId,
+ int iStateId, RECT* prc, int ts,
+ SIZE* psz);
+typedef HRESULT (WINAPI*getThemeSysFontPtr)(HANDLE hTheme, int iFontId, OUT LOGFONT* pFont);
+typedef HRESULT (WINAPI*getThemeColorPtr)(HANDLE hTheme, HDC hdc, int iPartId,
+ int iStateId, int iPropId, OUT COLORREF* pFont);
+
+namespace WebCore {
+
+static const int dropDownButtonWidth = 17;
+static const int trackWidth = 4;
+
+PassRefPtr<RenderTheme> RenderThemeWince::create()
+{
+ return adoptRef(new RenderThemeWince);
+}
+
+PassRefPtr<RenderTheme> RenderTheme::themeForPage(Page* page)
+{
+ static RenderTheme* winceTheme = RenderThemeWince::create().releaseRef();
+ return winceTheme;
+}
+
+RenderThemeWince::RenderThemeWince()
+{
+}
+
+RenderThemeWince::~RenderThemeWince()
+{
+}
+
+Color RenderThemeWince::platformActiveSelectionBackgroundColor() const
+{
+ COLORREF color = GetSysColor(COLOR_HIGHLIGHT);
+ return Color(GetRValue(color), GetGValue(color), GetBValue(color), 255);
+}
+
+Color RenderThemeWince::platformInactiveSelectionBackgroundColor() const
+{
+ COLORREF color = GetSysColor(COLOR_GRAYTEXT);
+ return Color(GetRValue(color), GetGValue(color), GetBValue(color), 255);
+}
+
+Color RenderThemeWince::platformActiveSelectionForegroundColor() const
+{
+ COLORREF color = GetSysColor(COLOR_HIGHLIGHTTEXT);
+ return Color(GetRValue(color), GetGValue(color), GetBValue(color), 255);
+}
+
+Color RenderThemeWince::platformInactiveSelectionForegroundColor() const
+{
+ return Color::white;
+}
+
+bool RenderThemeWince::supportsFocus(ControlPart appearance) const
+{
+ switch (appearance) {
+ case PushButtonPart:
+ case ButtonPart:
+ case TextFieldPart:
+ case TextAreaPart:
+ return true;
+ default:
+ return false;
+ }
+
+ return false;
+}
+
+bool RenderThemeWince::supportsFocusRing(const RenderStyle *style) const
+{
+ return supportsFocus(style->appearance());
+}
+
+unsigned RenderThemeWince::determineClassicState(RenderObject* o)
+{
+ unsigned result = 0;
+ if (!isEnabled(o) || isReadOnlyControl(o))
+ result = DFCS_INACTIVE;
+ else if (isPressed(o)) // Active supersedes hover
+ result = DFCS_PUSHED;
+
+ if (isChecked(o))
+ result |= DFCS_CHECKED;
+ return result;
+}
+
+ThemeData RenderThemeWince::getThemeData(RenderObject* o)
+{
+ ThemeData result;
+ switch (o->style()->appearance()) {
+ case PushButtonPart:
+ case ButtonPart:
+ result.m_part = BP_BUTTON;
+ 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_RADIO;
+ result.m_classicState = DFCS_BUTTONRADIO;
+ break;
+ case ListboxPart:
+ case MenulistPart:
+ case TextFieldPart:
+ case TextAreaPart:
+ result.m_part = TFP_TEXTFIELD;
+ break;
+ }
+
+ result.m_classicState |= determineClassicState(o);
+
+ return result;
+}
+
+bool RenderThemeWince::paintButton(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& r)
+{
+ // Get the correct theme data for a button
+ ThemeData themeData = getThemeData(o);
+
+ // Now paint the button.
+ i.context->drawFrameControl(r, DFC_BUTTON, themeData.m_classicState);
+ if (isFocused(o)) {
+ if (themeData.m_part == BP_BUTTON) {
+ IntRect focusRect(r);
+ focusRect.inflate(-2);
+ i.context->drawFocusRect(focusRect);
+ } else
+ i.context->drawFocusRect(r);
+ }
+
+ return false;
+}
+
+void RenderThemeWince::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.
+ if (style->width().isIntrinsicOrAuto())
+ style->setWidth(Length(13, Fixed));
+ if (style->height().isAuto())
+ style->setHeight(Length(13, Fixed));
+}
+
+bool RenderThemeWince::paintTextField(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& r)
+{
+ // Get the correct theme data for a textfield
+ ThemeData themeData = getThemeData(o);
+
+ // Now paint the text field.
+ i.context->paintTextField(r, themeData.m_classicState);
+
+ return false;
+}
+
+void RenderThemeWince::adjustMenuListStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
+{
+ style->resetBorder();
+ adjustMenuListButtonStyle(selector, style, e);
+}
+
+bool RenderThemeWince::paintMenuList(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& r)
+{
+ paintTextField(o, i, r);
+ paintMenuListButton(o, i, r);
+ return true;
+}
+
+bool RenderThemeWince::paintMenuListButton(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& r)
+{
+ IntRect buttonRect(r.right() - dropDownButtonWidth - 1, r.y(), dropDownButtonWidth, r.height());
+ buttonRect.inflateY(-1);
+ i.context->drawFrameControl(buttonRect, DFC_SCROLL, DFCS_SCROLLCOMBOBOX | determineClassicState(o));
+ return true;
+}
+
+void RenderThemeWince::systemFont(int propId, FontDescription& fontDescription) const
+{
+ notImplemented();
+}
+
+void RenderThemeWince::themeChanged()
+{
+}
+
+String RenderThemeWince::extraDefaultStyleSheet()
+{
+ notImplemented();
+ return String();
+}
+
+String RenderThemeWince::extraQuirksStyleSheet()
+{
+ notImplemented();
+ return String();
+}
+
+bool RenderThemeWince::supportsHover(const RenderStyle*) const
+{
+ return false;
+}
+
+// Map a CSSValue* system color to an index understood by GetSysColor
+static int cssValueIdToSysColorIndex(int cssValueId)
+{
+ switch (cssValueId) {
+ case CSSValueActiveborder: return COLOR_ACTIVEBORDER;
+ case CSSValueActivecaption: return COLOR_ACTIVECAPTION;
+ case CSSValueAppworkspace: return COLOR_APPWORKSPACE;
+ case CSSValueBackground: return COLOR_BACKGROUND;
+ case CSSValueButtonface: return COLOR_BTNFACE;
+ case CSSValueButtonhighlight: return COLOR_BTNHIGHLIGHT;
+ case CSSValueButtonshadow: return COLOR_BTNSHADOW;
+ case CSSValueButtontext: return COLOR_BTNTEXT;
+ case CSSValueCaptiontext: return COLOR_CAPTIONTEXT;
+ case CSSValueGraytext: return COLOR_GRAYTEXT;
+ case CSSValueHighlight: return COLOR_HIGHLIGHT;
+ case CSSValueHighlighttext: return COLOR_HIGHLIGHTTEXT;
+ case CSSValueInactiveborder: return COLOR_INACTIVEBORDER;
+ case CSSValueInactivecaption: return COLOR_INACTIVECAPTION;
+ case CSSValueInactivecaptiontext: return COLOR_INACTIVECAPTIONTEXT;
+ case CSSValueInfobackground: return COLOR_INFOBK;
+ case CSSValueInfotext: return COLOR_INFOTEXT;
+ case CSSValueMenu: return COLOR_MENU;
+ case CSSValueMenutext: return COLOR_MENUTEXT;
+ case CSSValueScrollbar: return COLOR_SCROLLBAR;
+ case CSSValueThreeddarkshadow: return COLOR_3DDKSHADOW;
+ case CSSValueThreedface: return COLOR_3DFACE;
+ case CSSValueThreedhighlight: return COLOR_3DHIGHLIGHT;
+ case CSSValueThreedlightshadow: return COLOR_3DLIGHT;
+ case CSSValueThreedshadow: return COLOR_3DSHADOW;
+ case CSSValueWindow: return COLOR_WINDOW;
+ case CSSValueWindowframe: return COLOR_WINDOWFRAME;
+ case CSSValueWindowtext: return COLOR_WINDOWTEXT;
+ default: return -1; // Unsupported CSSValue
+ }
+}
+
+Color RenderThemeWince::systemColor(int cssValueId) const
+{
+ int sysColorIndex = cssValueIdToSysColorIndex(cssValueId);
+ if (sysColorIndex == -1)
+ return RenderTheme::systemColor(cssValueId);
+
+ COLORREF color = GetSysColor(sysColorIndex);
+ return Color(GetRValue(color), GetGValue(color), GetBValue(color));
+}
+
+const int sliderThumbWidth = 7;
+const int sliderThumbHeight = 15;
+
+void RenderThemeWince::adjustSliderThumbSize(RenderObject* o) const
+{
+ if (o->style()->appearance() == SliderThumbVerticalPart) {
+ o->style()->setWidth(Length(sliderThumbHeight, Fixed));
+ o->style()->setHeight(Length(sliderThumbWidth, Fixed));
+ } else if (o->style()->appearance() == SliderThumbHorizontalPart) {
+ o->style()->setWidth(Length(sliderThumbWidth, Fixed));
+ o->style()->setHeight(Length(sliderThumbHeight, Fixed));
+ }
+}
+
+#if 0
+void RenderThemeWince::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));
+}
+
+void RenderThemeWince::adjustSearchFieldStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
+{
+ // Override padding size to match AppKit text positioning.
+ const int padding = 1;
+ style->setPaddingLeft(Length(padding, Fixed));
+ style->setPaddingRight(Length(padding, Fixed));
+ style->setPaddingTop(Length(padding, Fixed));
+ style->setPaddingBottom(Length(padding, Fixed));
+}
+#endif
+
+bool RenderThemeWince::paintSearchField(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& r)
+{
+ return paintTextField(o, i, r);
+}
+
+bool RenderThemeWince::paintSearchFieldCancelButton(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
+{
+ Color buttonColor = (o->node() && o->node()->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();
+ return false;
+}
+
+void RenderThemeWince::adjustSearchFieldCancelButtonStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
+{
+ IntSize cancelSize(13, 11);
+ style->setWidth(Length(cancelSize.width(), Fixed));
+ style->setHeight(Length(cancelSize.height(), Fixed));
+}
+
+void RenderThemeWince::adjustSearchFieldDecorationStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
+{
+ IntSize emptySize(1, 11);
+ style->setWidth(Length(emptySize.width(), Fixed));
+ style->setHeight(Length(emptySize.height(), Fixed));
+}
+
+void RenderThemeWince::adjustSearchFieldResultsDecorationStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
+{
+ IntSize magnifierSize(15, 11);
+ style->setWidth(Length(magnifierSize.width(), Fixed));
+ style->setHeight(Length(magnifierSize.height(), Fixed));
+}
+
+bool RenderThemeWince::paintSearchFieldResultsDecoration(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
+{
+ notImplemented();
+ return false;
+}
+
+void RenderThemeWince::adjustSearchFieldResultsButtonStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
+{
+ IntSize magnifierSize(15, 11);
+ style->setWidth(Length(magnifierSize.width(), Fixed));
+ style->setHeight(Length(magnifierSize.height(), Fixed));
+}
+
+bool RenderThemeWince::paintSearchFieldResultsButton(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
+{
+ paintSearchFieldResultsDecoration(o, paintInfo, r);
+ return false;
+}
+
+void RenderThemeWince::adjustMenuListButtonStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
+{
+ // These are the paddings needed to place the text correctly in the <select> box
+ const int dropDownBoxPaddingTop = 2;
+ const int dropDownBoxPaddingRight = style->direction() == LTR ? 4 + dropDownButtonWidth : 4;
+ const int dropDownBoxPaddingBottom = 2;
+ const int dropDownBoxPaddingLeft = style->direction() == LTR ? 4 : 4 + dropDownButtonWidth;
+ // The <select> box must be at least 12px high for the button to render nicely on Windows
+ const int dropDownBoxMinHeight = 12;
+
+ // Position the text correctly within the select box and make the box wide enough to fit the dropdown button
+ style->setPaddingTop(Length(dropDownBoxPaddingTop, Fixed));
+ style->setPaddingRight(Length(dropDownBoxPaddingRight, Fixed));
+ style->setPaddingBottom(Length(dropDownBoxPaddingBottom, Fixed));
+ style->setPaddingLeft(Length(dropDownBoxPaddingLeft, Fixed));
+
+ // Height is locked to auto
+ style->setHeight(Length(Auto));
+
+ // Calculate our min-height
+ int minHeight = style->font().height();
+ minHeight = max(minHeight, dropDownBoxMinHeight);
+
+ style->setMinHeight(Length(minHeight, Fixed));
+
+ // White-space is locked to pre
+ style->setWhiteSpace(PRE);
+
+ DWORD colorMenu = GetSysColor(COLOR_MENU);
+ DWORD colorMenuText = GetSysColor(COLOR_MENUTEXT);
+ Color bgColor(GetRValue(colorMenu), GetGValue(colorMenu), GetBValue(colorMenu), 255);
+ Color textColor(GetRValue(colorMenuText), GetGValue(colorMenuText), GetBValue(colorMenuText), 255);
+ if (bgColor == textColor)
+ textColor.setRGB((~bgColor.rgb()) | 0xFF000000);
+ style->clearBackgroundLayers();
+ style->accessBackgroundLayers()->setClip(ContentFillBox);
+ style->setBackgroundColor(bgColor);
+ style->setColor(textColor);
+}
+
+#if ENABLE(VIDEO)
+// Attempt to retrieve a HTMLMediaElement from a Node. Returns 0 if one cannot be found.
+static HTMLMediaElement* mediaElementParent(Node* node)
+{
+ if (!node)
+ return 0;
+ Node* mediaNode = node->shadowAncestorNode();
+ if (!mediaNode || (!mediaNode->hasTagName(HTMLNames::videoTag) && !mediaNode->hasTagName(HTMLNames::audioTag)))
+ return 0;
+
+ return static_cast<HTMLMediaElement*>(mediaNode);
+}
+#endif
+
+bool RenderThemeWince::paintSliderTrack(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& r)
+{
+ bool rc = RenderTheme::paintSliderTrack(o, i, r);
+ IntPoint left = IntPoint(r.x() + 2, (r.y() + r.bottom()) / 2);
+ i.context->save();
+ i.context->setStrokeColor(Color::gray);
+ i.context->setFillColor(Color::gray);
+ i.context->fillRect(r);
+#if ENABLE(VIDEO)
+ HTMLMediaElement *mediaElement = mediaElementParent(o->node());
+ if (mediaElement) {
+ i.context->setStrokeColor(Color(0, 0xff, 0));
+ IntPoint right = IntPoint(left.x() + mediaElement->percentLoaded() * (r.right() - r.x() - 4), (r.y() + r.bottom()) / 2);
+ i.context->drawLine(left, right);
+ left = right;
+ }
+#endif
+ i.context->setStrokeColor(Color::black);
+ i.context->drawLine(left, IntPoint(r.right() - 2, left.y()));
+ i.context->restore();
+ return rc;
+}
+
+bool RenderThemeWince::paintSliderThumb(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& r)
+{
+ bool rc = RenderTheme::paintSliderThumb(o, i, r);
+ i.context->save();
+ i.context->setStrokeColor(Color::black);
+ i.context->setFillColor(Color::black);
+#if ENABLE(VIDEO)
+ HTMLMediaElement *mediaElement = mediaElementParent(o->node());
+ if (mediaElement) {
+ float pt = (mediaElement->currentTime() - mediaElement->startTime()) / mediaElement->duration();
+ FloatRect intRect = r;
+ intRect.setX(intRect.x() + intRect.width() * pt - 2);
+ intRect.setWidth(5);
+ i.context->fillRect(intRect);
+ }
+#endif
+ i.context->restore();
+ return rc;
+}
+
+int RenderThemeWince::buttonInternalPaddingLeft() const
+{
+ return 3;
+}
+
+int RenderThemeWince::buttonInternalPaddingRight() const
+{
+ return 3;
+}
+
+int RenderThemeWince::buttonInternalPaddingTop() const
+{
+ return 1;
+}
+
+int RenderThemeWince::buttonInternalPaddingBottom() const
+{
+ return 1;
+}
+
+void RenderThemeWince::adjustSearchFieldStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
+{
+ const int padding = 1;
+ style->setPaddingLeft(Length(padding, Fixed));
+ style->setPaddingRight(Length(padding, Fixed));
+ style->setPaddingTop(Length(padding, Fixed));
+ style->setPaddingBottom(Length(padding, Fixed));
+}
+
+#if ENABLE(VIDEO)
+
+bool RenderThemeWince::paintMediaFullscreenButton(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
+{
+ bool rc = paintButton(o, paintInfo, r);
+ FloatRect imRect = r;
+ imRect.inflate(-2);
+ paintInfo.context->save();
+ paintInfo.context->setStrokeColor(Color::black);
+ paintInfo.context->setFillColor(Color::gray);
+ paintInfo.context->fillRect(imRect);
+ paintInfo.context->restore();
+ return rc;
+}
+
+bool RenderThemeWince::paintMediaMuteButton(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
+{
+ bool rc = paintButton(o, paintInfo, r);
+ HTMLMediaElement *mediaElement = mediaElementParent(o->node());
+ bool muted = !mediaElement || mediaElement->muted();
+ FloatRect imRect = r;
+ imRect.inflate(-2);
+ paintInfo.context->save();
+ paintInfo.context->setStrokeColor(Color::black);
+ paintInfo.context->setFillColor(Color::black);
+ FloatPoint pts[6] = {
+ FloatPoint(imRect.x() + 1, imRect.y() + imRect.height() / 3.0),
+ FloatPoint(imRect.x() + 1 + imRect.width() / 2.0, imRect.y() + imRect.height() / 3.0),
+ FloatPoint(imRect.right() - 1, imRect.y()),
+ FloatPoint(imRect.right() - 1, imRect.bottom()),
+ FloatPoint(imRect.x() + 1 + imRect.width() / 2.0, imRect.y() + 2.0 * imRect.height() / 3.0),
+ FloatPoint(imRect.x() + 1, imRect.y() + 2.0 * imRect.height() / 3.0)
+ };
+ paintInfo.context->drawConvexPolygon(6, pts);
+ if (muted)
+ paintInfo.context->drawLine(IntPoint(imRect.right(), imRect.y()), IntPoint(imRect.x(), imRect.bottom()));
+ paintInfo.context->restore();
+ return rc;
+}
+
+bool RenderThemeWince::paintMediaPlayButton(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
+{
+ bool rc = paintButton(o, paintInfo, r);
+ FloatRect imRect = r;
+ imRect.inflate(-3);
+ paintInfo.context->save();
+ paintInfo.context->setStrokeColor(Color::black);
+ paintInfo.context->setFillColor(Color::black);
+ HTMLMediaElement *mediaElement = mediaElementParent(o->node());
+ bool paused = !mediaElement || mediaElement->paused();
+ if (paused) {
+ float width = imRect.width();
+ imRect.setWidth(width / 3.0);
+ paintInfo.context->fillRect(imRect);
+ imRect.move(2.0 * width / 3.0, 0);
+ paintInfo.context->fillRect(imRect);
+ } else {
+ FloatPoint pts[3] = { FloatPoint(imRect.x(), imRect.y()), FloatPoint(imRect.right(), (imRect.y() + imRect.bottom()) / 2.0), FloatPoint(imRect.x(), imRect.bottom()) };
+ paintInfo.context->drawConvexPolygon(3, pts);
+ }
+ paintInfo.context->restore();
+ return rc;
+}
+
+bool RenderThemeWince::paintMediaSeekBackButton(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
+{
+ bool rc = paintButton(o, paintInfo, r);
+ FloatRect imRect = r;
+ imRect.inflate(-3);
+ FloatPoint pts[3] = { FloatPoint((imRect.x() + imRect.right()) / 2.0, imRect.y()), FloatPoint(imRect.x(), (imRect.y() + imRect.bottom()) / 2.0), FloatPoint((imRect.x() + imRect.right()) / 2.0, imRect.bottom()) };
+ FloatPoint pts2[3] = { FloatPoint(imRect.right(), imRect.y()), FloatPoint((imRect.x() + imRect.right()) / 2.0, (imRect.y() + imRect.bottom()) / 2.0), FloatPoint(imRect.right(), imRect.bottom()) };
+ paintInfo.context->save();
+ paintInfo.context->setStrokeColor(Color::black);
+ paintInfo.context->setFillColor(Color::black);
+ paintInfo.context->drawConvexPolygon(3, pts);
+ paintInfo.context->drawConvexPolygon(3, pts2);
+ paintInfo.context->restore();
+ return rc;
+}
+
+bool RenderThemeWince::paintMediaSeekForwardButton(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
+{
+ bool rc = paintButton(o, paintInfo, r);
+ FloatRect imRect = r;
+ imRect.inflate(-3);
+ FloatPoint pts[3] = { FloatPoint(imRect.x(), imRect.y()), FloatPoint((imRect.x() + imRect.right()) / 2.0, (imRect.y() + imRect.bottom()) / 2.0), FloatPoint(imRect.x(), imRect.bottom()) };
+ FloatPoint pts2[3] = { FloatPoint((imRect.x() + imRect.right()) / 2.0, imRect.y()), FloatPoint(imRect.right(), (imRect.y() + imRect.bottom()) / 2.0), FloatPoint((imRect.x() + imRect.right()) / 2.0, imRect.bottom()) };
+ paintInfo.context->save();
+ paintInfo.context->setStrokeColor(Color::black);
+ paintInfo.context->setFillColor(Color::black);
+ paintInfo.context->drawConvexPolygon(3, pts);
+ paintInfo.context->drawConvexPolygon(3, pts2);
+ paintInfo.context->restore();
+ return rc;
+}
+
+bool RenderThemeWince::paintMediaSliderTrack(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
+{
+ return paintSliderTrack(o, paintInfo, r);
+}
+
+bool RenderThemeWince::paintMediaSliderThumb(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
+{
+ return paintSliderThumb(o, paintInfo, r);
+}
+#endif
+
+}
+
diff --git a/WebCore/rendering/RenderThemeWince.h b/WebCore/rendering/RenderThemeWince.h
new file mode 100644
index 0000000..a2d04e1
--- /dev/null
+++ b/WebCore/rendering/RenderThemeWince.h
@@ -0,0 +1,147 @@
+/*
+ * This file is part of the WebKit project.
+ *
+ * Copyright (C) 2006, 2008 Apple Computer, Inc.
+ * Copyright (C) 2009 Torch Mobile, 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 RenderThemeWince_h
+#define RenderThemeWince_h
+
+#include "RenderTheme.h"
+
+typedef void* HANDLE;
+typedef struct HINSTANCE__* HINSTANCE;
+typedef HINSTANCE HMODULE;
+
+namespace WebCore {
+
+ struct ThemeData {
+ ThemeData() :m_part(0), m_state(0), m_classicState(0) {}
+ ThemeData(int part, int state)
+ : m_part(part)
+ , m_state(state)
+ , m_classicState(0)
+ { }
+
+ unsigned m_part;
+ unsigned m_state;
+ unsigned m_classicState;
+ };
+
+ class RenderThemeWince : public RenderTheme {
+ public:
+ static PassRefPtr<RenderTheme> create();
+ ~RenderThemeWince();
+
+ 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;
+
+ virtual Color platformActiveSelectionBackgroundColor() const;
+ virtual Color platformInactiveSelectionBackgroundColor() const;
+ virtual Color platformActiveSelectionForegroundColor() const;
+ virtual Color platformInactiveSelectionForegroundColor() const;
+
+ // System fonts.
+ virtual void systemFont(int propId, FontDescription&) const;
+ virtual Color systemColor(int cssValueId) 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* style) const
+ { return setCheckboxSize(style); }
+
+ 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 void adjustMenuListStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const;
+ virtual bool paintMenuList(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+ virtual void adjustMenuListButtonStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const;
+
+ virtual bool paintMenuListButton(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+
+ virtual bool paintSliderTrack(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& r);
+ virtual bool paintSliderThumb(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& r);
+ virtual void adjustSliderThumbSize(RenderObject*) const;
+
+ virtual bool popupOptionSupportsTextIndent() const { return true; }
+
+ virtual int buttonInternalPaddingLeft() const;
+ virtual int buttonInternalPaddingRight() const;
+ virtual int buttonInternalPaddingTop() const;
+ virtual int buttonInternalPaddingBottom() const;
+
+ virtual void adjustSearchFieldStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+ virtual bool paintSearchField(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+
+ 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&) { return false; }
+
+ 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 void themeChanged();
+
+ virtual void adjustButtonStyle(CSSStyleSelector*, RenderStyle* style, Element*) const {}
+ virtual void adjustTextFieldStyle(CSSStyleSelector*, RenderStyle* style, Element*) const {}
+ virtual void adjustTextAreaStyle(CSSStyleSelector*, RenderStyle* style, Element*) const {}
+
+ static void setWebKitIsBeingUnloaded();
+
+ virtual bool supportsFocusRing(const RenderStyle*) const;
+
+ #if ENABLE(VIDEO)
+ virtual bool paintMediaFullscreenButton(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+ virtual bool paintMediaPlayButton(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+ virtual bool paintMediaMuteButton(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+ virtual bool paintMediaSeekBackButton(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+ virtual bool paintMediaSeekForwardButton(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+ virtual bool paintMediaSliderTrack(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+ virtual bool paintMediaSliderThumb(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+ #endif
+
+ private:
+ RenderThemeWince();
+
+ unsigned determineClassicState(RenderObject*);
+ bool supportsFocus(ControlPart) const;
+
+ ThemeData getThemeData(RenderObject*);
+ };
+
+};
+
+#endif
diff --git a/WebCore/rendering/RenderTreeAsText.cpp b/WebCore/rendering/RenderTreeAsText.cpp
index 79d1724..5c6e738 100644
--- a/WebCore/rendering/RenderTreeAsText.cpp
+++ b/WebCore/rendering/RenderTreeAsText.cpp
@@ -204,14 +204,14 @@ static TextStream &operator<<(TextStream& ts, const RenderObject& o)
// 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);
+ const RenderTableCell& cell = *toRenderTableCell(&o);
r = IntRect(cell.x(), cell.y() + cell.intrinsicPaddingTop(), cell.width(), cell.height() - cell.intrinsicPaddingTop() - cell.intrinsicPaddingBottom());
} else if (o.isBox())
r = toRenderBox(&o)->frameRect();
// FIXME: Temporary in order to ensure compatibility with existing layout test results.
if (adjustForTableCells)
- r.move(0, -static_cast<RenderTableCell*>(o.containingBlock())->intrinsicPaddingTop());
+ r.move(0, -toRenderTableCell(o.containingBlock())->intrinsicPaddingTop());
ts << " " << r;
@@ -307,12 +307,12 @@ static TextStream &operator<<(TextStream& ts, const RenderObject& o)
}
if (o.isTableCell()) {
- const RenderTableCell& c = static_cast<const RenderTableCell&>(o);
+ const RenderTableCell& c = *toRenderTableCell(&o);
ts << " [r=" << c.row() << " c=" << c.col() << " rs=" << c.rowSpan() << " cs=" << c.colSpan() << "]";
}
if (o.isListMarker()) {
- String text = static_cast<const RenderListMarker&>(o).text();
+ String text = toRenderListMarker(&o)->text();
if (!text.isEmpty()) {
if (text.length() != 1)
text = quoteAndEscapeNonPrintables(text);
@@ -343,7 +343,7 @@ static void writeTextRun(TextStream& ts, const RenderText& o, const InlineTextBo
// 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();
+ y -= toRenderTableCell(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");
@@ -359,26 +359,26 @@ void write(TextStream& ts, const RenderObject& o, int indent)
{
#if ENABLE(SVG)
if (o.isRenderPath()) {
- write(ts, static_cast<const RenderPath&>(o), indent);
+ write(ts, *toRenderPath(&o), indent);
return;
}
if (o.isSVGContainer()) {
- write(ts, static_cast<const RenderSVGContainer&>(o), indent);
+ writeSVGContainer(ts, o, indent);
return;
}
if (o.isSVGRoot()) {
- write(ts, static_cast<const RenderSVGRoot&>(o), indent);
+ write(ts, *toRenderSVGRoot(&o), indent);
return;
}
if (o.isSVGText()) {
if (!o.isText())
- write(ts, static_cast<const RenderSVGText&>(o), indent);
+ writeSVGText(ts, *toRenderBlock(&o), indent);
else
- write(ts, static_cast<const RenderSVGInlineText&>(o), indent);
+ writeSVGInlineText(ts, *toRenderText(&o), indent);
return;
}
if (o.isSVGImage()) {
- write(ts, static_cast<const RenderSVGImage&>(o), indent);
+ writeSVGImage(ts, *toRenderImage(&o), indent);
return;
}
#endif
@@ -402,7 +402,7 @@ void write(TextStream& ts, const RenderObject& o, int indent)
}
if (o.isWidget()) {
- Widget* widget = static_cast<const RenderWidget&>(o).widget();
+ Widget* widget = toRenderWidget(&o)->widget();
if (widget && widget->isFrameView()) {
FrameView* view = static_cast<FrameView*>(widget);
RenderView* root = view->frame()->contentRenderer();
diff --git a/WebCore/rendering/RenderVideo.cpp b/WebCore/rendering/RenderVideo.cpp
index d47e2f3..246d0c0 100644
--- a/WebCore/rendering/RenderVideo.cpp
+++ b/WebCore/rendering/RenderVideo.cpp
@@ -35,6 +35,11 @@
#include "HTMLVideoElement.h"
#include "MediaPlayer.h"
+#if USE(ACCELERATED_COMPOSITING)
+#include "RenderLayer.h"
+#include "RenderLayerBacking.h"
+#endif
+
using namespace std;
namespace WebCore {
@@ -139,6 +144,10 @@ void RenderVideo::updatePlayer()
mediaPlayer->setVisible(false);
return;
}
+
+#if USE(ACCELERATED_COMPOSITING)
+ layer()->rendererContentChanged();
+#endif
IntRect videoBounds = videoBox();
mediaPlayer->setFrameView(document()->view());
@@ -246,6 +255,32 @@ void RenderVideo::calcPrefWidths()
setPrefWidthsDirty(false);
}
+#if USE(ACCELERATED_COMPOSITING)
+bool RenderVideo::supportsAcceleratedRendering() const
+{
+ MediaPlayer* p = player();
+ if (p)
+ return p->supportsAcceleratedRendering();
+
+ return false;
+}
+
+void RenderVideo::acceleratedRenderingStateChanged()
+{
+ MediaPlayer* p = player();
+ if (p)
+ p->acceleratedRenderingStateChanged();
+}
+
+GraphicsLayer* RenderVideo::videoGraphicsLayer() const
+{
+ if (hasLayer() && layer()->isComposited())
+ return layer()->backing()->graphicsLayer();
+
+ return 0;
+}
+#endif // USE(ACCELERATED_COMPOSITING)
+
} // namespace WebCore
#endif
diff --git a/WebCore/rendering/RenderVideo.h b/WebCore/rendering/RenderVideo.h
index 43c1e7b..79e5b4e 100644
--- a/WebCore/rendering/RenderVideo.h
+++ b/WebCore/rendering/RenderVideo.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2007 Apple Inc. All rights reserved.
+ * Copyright (C) 2007, 2009 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -33,15 +33,35 @@
namespace WebCore {
class HTMLMediaElement;
+#if USE(ACCELERATED_COMPOSITING)
+class GraphicsLayer;
+#endif
class RenderVideo : public RenderMedia {
public:
RenderVideo(HTMLMediaElement*);
virtual ~RenderVideo();
+ void videoSizeChanged();
+ IntRect videoBox() const;
+
+#if USE(ACCELERATED_COMPOSITING)
+ bool supportsAcceleratedRendering() const;
+ void acceleratedRenderingStateChanged();
+ GraphicsLayer* videoGraphicsLayer() const;
+#endif
+
+private:
+ virtual void updateFromElement();
+
+ virtual void intrinsicSizeChanged() { videoSizeChanged(); }
+
virtual const char* renderName() const { return "RenderVideo"; }
- virtual void paintReplaced(PaintInfo& paintInfo, int tx, int ty);
+ virtual bool requiresLayer() const { return true; }
+ virtual bool isVideo() const { return true; }
+
+ virtual void paintReplaced(PaintInfo&, int tx, int ty);
virtual void layout();
@@ -50,25 +70,24 @@ public:
virtual void calcPrefWidths();
- void videoSizeChanged();
-
- void updateFromElement();
-
-protected:
- virtual void intrinsicSizeChanged() { videoSizeChanged(); }
-
-private:
int calcAspectRatioWidth() const;
int calcAspectRatioHeight() const;
bool isWidthSpecified() const;
bool isHeightSpecified() const;
- IntRect videoBox() const;
-
void updatePlayer();
};
+inline RenderVideo* toRenderVideo(RenderObject* object)
+{
+ ASSERT(!object || object->isVideo());
+ return static_cast<RenderVideo*>(object);
+}
+
+// This will catch anyone doing an unnecessary cast.
+void toRenderVideo(const RenderVideo*);
+
} // namespace WebCore
#endif
diff --git a/WebCore/rendering/RenderView.cpp b/WebCore/rendering/RenderView.cpp
index e110d80..584e38a 100644
--- a/WebCore/rendering/RenderView.cpp
+++ b/WebCore/rendering/RenderView.cpp
@@ -355,8 +355,8 @@ void RenderView::setMaximalOutlineSize(int o)
if (o != m_maximalOutlineSize) {
m_maximalOutlineSize = o;
- if (m_frameView)
- m_frameView->updateCompositingLayers(FrameView::ForcedCompositingUpdate);
+ // maximalOutlineSize affects compositing layer dimensions.
+ compositor()->setCompositingLayersNeedRebuild(); // FIXME: this really just needs to be a geometry update.
}
}
#endif
diff --git a/WebCore/rendering/RenderView.h b/WebCore/rendering/RenderView.h
index bcade1a..089fe85 100644
--- a/WebCore/rendering/RenderView.h
+++ b/WebCore/rendering/RenderView.h
@@ -208,16 +208,16 @@ private:
#endif
};
-inline RenderView* toRenderView(RenderObject* o)
+inline RenderView* toRenderView(RenderObject* object)
{
- ASSERT(!o || o->isRenderView());
- return static_cast<RenderView*>(o);
+ ASSERT(!object || object->isRenderView());
+ return static_cast<RenderView*>(object);
}
-inline const RenderView* toRenderView(const RenderObject* o)
+inline const RenderView* toRenderView(const RenderObject* object)
{
- ASSERT(!o || o->isRenderView());
- return static_cast<const RenderView*>(o);
+ ASSERT(!object || object->isRenderView());
+ return static_cast<const RenderView*>(object);
}
// This will catch anyone doing an unnecessary cast.
@@ -225,7 +225,7 @@ void toRenderView(const RenderView*);
// Stack-based class to assist with LayoutState push/pop
-class LayoutStateMaintainer : Noncopyable {
+class LayoutStateMaintainer : public Noncopyable {
public:
// ctor to push now
LayoutStateMaintainer(RenderView* view, RenderBox* root, IntSize offset, bool disableState = false)
diff --git a/WebCore/rendering/RenderWidget.cpp b/WebCore/rendering/RenderWidget.cpp
index ec2ee6a..16526ca 100644
--- a/WebCore/rendering/RenderWidget.cpp
+++ b/WebCore/rendering/RenderWidget.cpp
@@ -73,8 +73,8 @@ void RenderWidget::destroy()
if (m_widget) {
if (m_frameView)
- m_frameView->removeChild(m_widget);
- widgetRendererMap().remove(m_widget);
+ m_frameView->removeChild(m_widget.get());
+ widgetRendererMap().remove(m_widget.get());
}
// removes from override size map
@@ -113,17 +113,17 @@ void RenderWidget::setWidgetGeometry(const IntRect& frame)
}
}
-void RenderWidget::setWidget(Widget* widget)
+void RenderWidget::setWidget(PassRefPtr<Widget> widget)
{
if (widget != m_widget) {
if (m_widget) {
m_widget->removeFromParent();
- widgetRendererMap().remove(m_widget);
+ widgetRendererMap().remove(m_widget.get());
clearWidget();
}
m_widget = widget;
if (m_widget) {
- widgetRendererMap().add(m_widget, this);
+ widgetRendererMap().add(m_widget.get(), this);
// if we've already received a layout, apply the calculated space to the
// widget immediately, but we have to have really been full constructed (with a non-null
// style pointer).
@@ -135,7 +135,7 @@ void RenderWidget::setWidget(Widget* widget)
else
m_widget->show();
}
- m_frameView->addChild(m_widget);
+ m_frameView->addChild(m_widget.get());
}
}
}
@@ -182,8 +182,7 @@ void RenderWidget::paint(PaintInfo& paintInfo, int tx, int ty)
paintCustomHighlight(tx - x(), ty - y(), style()->highlight(), true);
#endif
- bool clipToBorderRadius = style()->overflowX() != OVISIBLE && style()->hasBorderRadius();
- if (clipToBorderRadius) {
+ if (style()->hasBorderRadius()) {
// Push a clip if we have a border radius, since we want to round the foreground content that gets painted.
paintInfo.context->save();
@@ -204,13 +203,13 @@ void RenderWidget::paint(PaintInfo& paintInfo, int tx, int ty)
// to paint itself. That way it will composite properly with z-indexed layers.
m_widget->paint(paintInfo.context, paintInfo.rect);
- if (m_widget->isFrameView() && paintInfo.overlapTestRequests && !static_cast<FrameView*>(m_widget)->useSlowRepaints()) {
+ if (m_widget->isFrameView() && paintInfo.overlapTestRequests && !static_cast<FrameView*>(m_widget.get())->useSlowRepaints()) {
ASSERT(!paintInfo.overlapTestRequests->contains(this));
paintInfo.overlapTestRequests->set(this, m_widget->frameRect());
}
}
- if (clipToBorderRadius)
+ if (style()->hasBorderRadius())
paintInfo.context->restore();
// Paint a partially transparent wash over selected widgets.
@@ -224,7 +223,7 @@ void RenderWidget::setOverlapTestResult(bool isOverlapped)
{
ASSERT(m_widget);
ASSERT(m_widget->isFrameView());
- static_cast<FrameView*>(m_widget)->setIsOverlapped(isOverlapped);
+ static_cast<FrameView*>(m_widget.get())->setIsOverlapped(isOverlapped);
}
void RenderWidget::deref(RenderArena *arena)
@@ -259,7 +258,7 @@ void RenderWidget::updateWidgetPosition()
// if the frame bounds got changed, or if view needs layout (possibly indicating
// content size is wrong) we have to do a layout to set the right widget size
if (m_widget->isFrameView()) {
- FrameView* frameView = static_cast<FrameView*>(m_widget);
+ FrameView* frameView = static_cast<FrameView*>(m_widget.get());
if (boundsChanged || frameView->needsLayout())
frameView->layout();
}
@@ -276,15 +275,7 @@ void RenderWidget::setSelectionState(SelectionState state)
void RenderWidget::clearWidget()
{
- Widget* widget = m_widget;
m_widget = 0;
- if (widget)
- deleteWidget(widget);
-}
-
-void RenderWidget::deleteWidget(Widget* widget)
-{
- delete widget;
}
RenderWidget* RenderWidget::find(const Widget* widget)
diff --git a/WebCore/rendering/RenderWidget.h b/WebCore/rendering/RenderWidget.h
index d23dbb3..bb68143 100644
--- a/WebCore/rendering/RenderWidget.h
+++ b/WebCore/rendering/RenderWidget.h
@@ -33,8 +33,8 @@ class RenderWidget : public RenderReplaced, private OverlapTestRequestClient {
public:
virtual ~RenderWidget();
- Widget* widget() const { return m_widget; }
- virtual void setWidget(Widget*);
+ Widget* widget() const { return m_widget.get(); }
+ virtual void setWidget(PassRefPtr<Widget>);
static RenderWidget* find(const Widget*);
@@ -57,7 +57,6 @@ private:
virtual void destroy();
virtual void setSelectionState(SelectionState);
virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, int x, int y, int tx, int ty, HitTestAction);
- virtual void deleteWidget(Widget*);
virtual void setOverlapTestResult(bool);
void setWidgetGeometry(const IntRect&);
@@ -65,11 +64,26 @@ private:
RenderArena* ref() { ++m_refCount; return renderArena(); }
void deref(RenderArena*);
- Widget* m_widget;
+ RefPtr<Widget> m_widget;
FrameView* m_frameView;
int m_refCount;
};
+inline RenderWidget* toRenderWidget(RenderObject* object)
+{
+ ASSERT(!object || object->isWidget());
+ return static_cast<RenderWidget*>(object);
+}
+
+inline const RenderWidget* toRenderWidget(const RenderObject* object)
+{
+ ASSERT(!object || object->isWidget());
+ return static_cast<const RenderWidget*>(object);
+}
+
+// This will catch anyone doing an unnecessary cast.
+void toRenderWidget(const RenderWidget*);
+
} // namespace WebCore
#endif // RenderWidget_h
diff --git a/WebCore/rendering/RootInlineBox.cpp b/WebCore/rendering/RootInlineBox.cpp
index ed125ee..e8f04da 100644
--- a/WebCore/rendering/RootInlineBox.cpp
+++ b/WebCore/rendering/RootInlineBox.cpp
@@ -355,8 +355,8 @@ static bool isEditableLeaf(InlineBox* leaf)
InlineBox* RootInlineBox::closestLeafChildForXPos(int x, bool onlyEditableLeaves)
{
- InlineBox* firstLeaf = firstLeafChildAfterBox();
- InlineBox* lastLeaf = lastLeafChildBeforeBox();
+ InlineBox* firstLeaf = firstLeafChild();
+ InlineBox* lastLeaf = lastLeafChild();
if (firstLeaf == lastLeaf && (!onlyEditableLeaves || isEditableLeaf(firstLeaf)))
return firstLeaf;
diff --git a/WebCore/rendering/SVGCharacterLayoutInfo.cpp b/WebCore/rendering/SVGCharacterLayoutInfo.cpp
index 8871a75..900e0ba 100644
--- a/WebCore/rendering/SVGCharacterLayoutInfo.cpp
+++ b/WebCore/rendering/SVGCharacterLayoutInfo.cpp
@@ -274,7 +274,7 @@ void SVGCharacterLayoutInfo::addLayoutInformation(InlineFlowBox* flowBox, float
angleStack.isEmpty() && baselineShiftStack.isEmpty() &&
curx == 0.0f && cury == 0.0f;
- RenderSVGTextPath* textPath = static_cast<RenderSVGTextPath*>(flowBox->renderer());
+ RenderSVGTextPath* textPath = toRenderSVGTextPath(flowBox->renderer());
Path path = textPath->layoutPath();
float baselineShift = calculateBaselineShift(textPath);
@@ -390,11 +390,11 @@ void SVGCharacterLayoutInfo::addStackContent(StackType type, const PositionedFlo
dyStackChanged = true;
dyStack.append(list);
break;
- case AngleStack:
+ case AngleStack:
angleStackChanged = true;
angleStack.append(list);
break;
- default:
+ default:
ASSERT_NOT_REACHED();
}
}
diff --git a/WebCore/rendering/SVGCharacterLayoutInfo.h b/WebCore/rendering/SVGCharacterLayoutInfo.h
index 0188b9d..b5b4f3e 100644
--- a/WebCore/rendering/SVGCharacterLayoutInfo.h
+++ b/WebCore/rendering/SVGCharacterLayoutInfo.h
@@ -44,8 +44,7 @@ class SVGNumberList;
class SVGTextPositioningElement;
template<class Type>
-class PositionedVector : public Vector<Type>
-{
+class PositionedVector : public Vector<Type> {
public:
PositionedVector<Type>()
: m_position(0)
diff --git a/WebCore/rendering/SVGInlineFlowBox.h b/WebCore/rendering/SVGInlineFlowBox.h
index 1aa2637..f6eb87a 100644
--- a/WebCore/rendering/SVGInlineFlowBox.h
+++ b/WebCore/rendering/SVGInlineFlowBox.h
@@ -37,7 +37,7 @@ public:
{
}
- virtual int svgBoxHeight() const { return m_height; }
+ virtual int virtualHeight() const { return m_height; }
void setHeight(int h) { m_height = h; }
virtual void paint(RenderObject::PaintInfo&, int tx, int ty);
diff --git a/WebCore/rendering/SVGInlineTextBox.h b/WebCore/rendering/SVGInlineTextBox.h
index 410218d..76837cc 100644
--- a/WebCore/rendering/SVGInlineTextBox.h
+++ b/WebCore/rendering/SVGInlineTextBox.h
@@ -38,7 +38,7 @@ namespace WebCore {
public:
SVGInlineTextBox(RenderObject* obj);
- virtual int svgBoxHeight() const { return m_height; }
+ virtual int virtualHeight() const { return m_height; }
void setHeight(int h) { m_height = h; }
virtual int selectionTop();
diff --git a/WebCore/rendering/SVGRenderSupport.cpp b/WebCore/rendering/SVGRenderSupport.cpp
index c2c8e0b..fb6866f 100644
--- a/WebCore/rendering/SVGRenderSupport.cpp
+++ b/WebCore/rendering/SVGRenderSupport.cpp
@@ -120,7 +120,7 @@ void SVGRenderBase::prepareToRenderSVGContent(RenderObject* object, RenderObject
#if ENABLE(FILTERS)
if (filter) {
filter->addClient(styledElement);
- filter->prepareFilter(paintInfo.context, object->objectBoundingBox());
+ filter->prepareFilter(paintInfo.context, object);
} else if (!filterId.isEmpty())
svgElement->document()->accessSVGExtensions()->addPendingResource(filterId, styledElement);
#endif
@@ -152,7 +152,7 @@ void SVGRenderBase::finishRenderSVGContent(RenderObject* object, RenderObject::P
#if ENABLE(FILTERS)
if (filter) {
- filter->applyFilter(paintInfo.context, object->objectBoundingBox());
+ filter->applyFilter(paintInfo.context, object);
paintInfo.context = savedContext;
}
#endif
@@ -169,9 +169,11 @@ void renderSubtreeToImage(ImageBuffer* image, RenderObject* item)
ASSERT(image->context());
RenderObject::PaintInfo info(image->context(), IntRect(), PaintPhaseForeground, 0, 0, 0);
+ // FIXME: isSVGContainer returns true for RenderSVGViewportContainer, so if this is ever
+ // called with one of those, we will read from the wrong offset in an object due to a bad cast.
RenderSVGContainer* svgContainer = 0;
if (item && item->isSVGContainer())
- svgContainer = static_cast<RenderSVGContainer*>(item);
+ svgContainer = toRenderSVGContainer(item);
bool drawsContents = svgContainer ? svgContainer->drawsContents() : false;
if (svgContainer && !drawsContents)
diff --git a/WebCore/rendering/SVGRenderTreeAsText.cpp b/WebCore/rendering/SVGRenderTreeAsText.cpp
index 33baeba..28e506a 100644
--- a/WebCore/rendering/SVGRenderTreeAsText.cpp
+++ b/WebCore/rendering/SVGRenderTreeAsText.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004, 2005, 2007 Apple Inc. All rights reserved.
+ * Copyright (C) 2004, 2005, 2007, 2009 Apple Inc. All rights reserved.
* (C) 2005 Rob Buis <buis@kde.org>
* (C) 2006 Alexander Kellett <lypanov@kde.org>
*
@@ -31,14 +31,15 @@
#include "SVGRenderTreeAsText.h"
#include "GraphicsTypes.h"
-#include "InlineTextBox.h"
#include "HTMLNames.h"
+#include "InlineTextBox.h"
+#include "NodeRenderStyle.h"
+#include "RenderImage.h"
#include "RenderPath.h"
#include "RenderSVGContainer.h"
-#include "RenderSVGImage.h"
#include "RenderSVGInlineText.h"
-#include "RenderSVGText.h"
#include "RenderSVGRoot.h"
+#include "RenderSVGText.h"
#include "RenderTreeAsText.h"
#include "SVGCharacterLayoutInfo.h"
#include "SVGInlineTextBox.h"
@@ -272,7 +273,7 @@ static void writeStyle(TextStream& ts, const RenderObject& object)
ts << s << *strokePaintServer;
double dashOffset = SVGRenderStyle::cssPrimitiveToLength(&path, svgStyle->strokeDashOffset(), 0.0f);
- const DashArray& dashArray = dashArrayFromRenderingStyle(style);
+ const DashArray& dashArray = dashArrayFromRenderingStyle(style, object.document()->documentElement()->renderStyle());
double strokeWidth = SVGRenderStyle::cssPrimitiveToLength(&path, svgStyle->strokeWidth(), 1.0f);
writeIfNotDefault(ts, "opacity", svgStyle->strokeOpacity(), 1.0f);
@@ -321,35 +322,23 @@ static TextStream& operator<<(TextStream& ts, const RenderPath& path)
return ts;
}
-static TextStream& operator<<(TextStream& ts, const RenderSVGContainer& container)
-{
- return writePositionAndStyle(ts, container);
-}
-
static TextStream& operator<<(TextStream& ts, const RenderSVGRoot& root)
{
return writePositionAndStyle(ts, root);
}
-static TextStream& operator<<(TextStream& ts, const RenderSVGImage& root)
-{
- return writePositionAndStyle(ts, root);
-}
-
-static TextStream& operator<<(TextStream& ts, const RenderSVGText& text)
+static void writeRenderSVGTextBox(TextStream& ts, const RenderBlock& text)
{
SVGRootInlineBox* box = static_cast<SVGRootInlineBox*>(text.firstRootBox());
if (!box)
- return ts;
+ return;
Vector<SVGTextChunk>& chunks = const_cast<Vector<SVGTextChunk>& >(box->svgTextChunks());
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()))
writeNameValuePair(ts, "color", text.style()->color().name());
-
- return ts;
}
static inline bool containsInlineTextBox(SVGTextChunk& chunk, SVGInlineTextBox* box)
@@ -454,7 +443,7 @@ static inline void writeSVGInlineTextBox(TextStream& ts, SVGInlineTextBox* textB
}
}
-static inline void writeSVGInlineText(TextStream& ts, const RenderSVGInlineText& text, int indent)
+static inline void writeSVGInlineTextBoxes(TextStream& ts, const RenderText& text, int indent)
{
for (InlineTextBox* box = text.firstTextBox(); box; box = box->nextTextBox())
writeSVGInlineTextBox(ts, static_cast<SVGInlineTextBox*>(box), indent);
@@ -475,10 +464,11 @@ static void writeChildren(TextStream& ts, const RenderObject& object, int indent
write(ts, *child, indent + 1);
}
-void write(TextStream& ts, const RenderSVGContainer& container, int indent)
+void writeSVGContainer(TextStream& ts, const RenderObject& container, int indent)
{
writeStandardPrefix(ts, container, indent);
- ts << container << "\n";
+ writePositionAndStyle(ts, container);
+ ts << "\n";
writeChildren(ts, container, indent);
}
@@ -489,20 +479,21 @@ void write(TextStream& ts, const RenderSVGRoot& root, int indent)
writeChildren(ts, root, indent);
}
-void write(TextStream& ts, const RenderSVGText& text, int indent)
+void writeSVGText(TextStream& ts, const RenderBlock& text, int indent)
{
writeStandardPrefix(ts, text, indent);
- ts << text << "\n";
+ writeRenderSVGTextBox(ts, text);
+ ts << "\n";
writeChildren(ts, text, indent);
}
-void write(TextStream& ts, const RenderSVGInlineText& text, int indent)
+void writeSVGInlineText(TextStream& ts, const RenderText& text, int indent)
{
writeStandardPrefix(ts, text, indent);
// Why not just linesBoundingBox()?
ts << " " << FloatRect(text.firstRunOrigin(), text.linesBoundingBox().size()) << "\n";
- writeSVGInlineText(ts, text, indent);
+ writeSVGInlineTextBoxes(ts, text, indent);
}
void write(TextStream& ts, const RenderPath& path, int indent)
@@ -511,10 +502,11 @@ void write(TextStream& ts, const RenderPath& path, int indent)
ts << path << "\n";
}
-void write(TextStream& ts, const RenderSVGImage& image, int indent)
+void writeSVGImage(TextStream& ts, const RenderImage& image, int indent)
{
writeStandardPrefix(ts, image, indent);
- ts << image << "\n";
+ writePositionAndStyle(ts, image);
+ ts << "\n";
}
void writeRenderResources(TextStream& ts, Node* parent)
diff --git a/WebCore/rendering/SVGRenderTreeAsText.h b/WebCore/rendering/SVGRenderTreeAsText.h
index 35c3d5c..bee4f36 100644
--- a/WebCore/rendering/SVGRenderTreeAsText.h
+++ b/WebCore/rendering/SVGRenderTreeAsText.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004, 2005 Apple Computer, Inc. All rights reserved.
+ * Copyright (C) 2004, 2005, 2009 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -32,7 +32,6 @@
namespace WebCore {
- class TransformationMatrix;
class Color;
class FloatPoint;
class FloatRect;
@@ -40,20 +39,21 @@ namespace WebCore {
class IntPoint;
class IntRect;
class Node;
+ class RenderBlock;
+ class RenderImage;
+ class RenderObject;
class RenderPath;
- class RenderSVGContainer;
- class RenderSVGInlineText;
class RenderSVGRoot;
- class RenderSVGText;
- class RenderSVGImage;
+ class RenderText;
+ class TransformationMatrix;
// functions used by the main RenderTreeAsText code
-void write(TextStream&, const RenderPath&, int indent = 0);
-void write(TextStream&, const RenderSVGContainer&, int indent = 0);
-void write(TextStream&, const RenderSVGInlineText&, int indent = 0);
-void write(TextStream&, const RenderSVGRoot&, int indent = 0);
-void write(TextStream&, const RenderSVGText&, int indent = 0);
-void write(TextStream&, const RenderSVGImage&, int indent = 0);
+void write(TextStream&, const RenderPath&, int indent);
+void write(TextStream&, const RenderSVGRoot&, int indent);
+void writeSVGContainer(TextStream&, const RenderObject&, int indent);
+void writeSVGImage(TextStream&, const RenderImage&, int indent);
+void writeSVGInlineText(TextStream&, const RenderText&, int indent);
+void writeSVGText(TextStream&, const RenderBlock&, int indent);
void writeRenderResources(TextStream&, Node* parent);
diff --git a/WebCore/rendering/SVGRootInlineBox.cpp b/WebCore/rendering/SVGRootInlineBox.cpp
index d92f54c..8319e7c 100644
--- a/WebCore/rendering/SVGRootInlineBox.cpp
+++ b/WebCore/rendering/SVGRootInlineBox.cpp
@@ -285,14 +285,11 @@ static inline void closeTextChunk(SVGTextChunkLayoutInfo& info)
RenderSVGRoot* findSVGRootObject(RenderObject* start)
{
- // Find associated root inline box
+ // Find associated root inline box.
while (start && !start->isSVGRoot())
start = start->parent();
-
ASSERT(start);
- ASSERT(start->isSVGRoot());
-
- return static_cast<RenderSVGRoot*>(start);
+ return toRenderSVGRoot(start);
}
static inline FloatPoint topLeftPositionOfCharacterRange(Vector<SVGChar>& chars)
diff --git a/WebCore/rendering/SVGRootInlineBox.h b/WebCore/rendering/SVGRootInlineBox.h
index 735f755..65bade0 100644
--- a/WebCore/rendering/SVGRootInlineBox.h
+++ b/WebCore/rendering/SVGRootInlineBox.h
@@ -53,7 +53,7 @@ public:
virtual bool isSVGRootInlineBox() { return true; }
- virtual int svgBoxHeight() const { return m_height; }
+ virtual int virtualHeight() const { return m_height; }
void setHeight(int h) { m_height = h; }
virtual void paint(RenderObject::PaintInfo&, int tx, int ty);
diff --git a/WebCore/rendering/TextControlInnerElements.cpp b/WebCore/rendering/TextControlInnerElements.cpp
index cd067de..fc7f7f0 100644
--- a/WebCore/rendering/TextControlInnerElements.cpp
+++ b/WebCore/rendering/TextControlInnerElements.cpp
@@ -56,7 +56,7 @@ bool RenderTextControlInnerBlock::nodeAtPoint(const HitTestRequest& request, Hit
bool placeholderIsVisible = false;
if (renderer->isTextField())
- placeholderIsVisible = static_cast<RenderTextControlSingleLine*>(renderer)->placeholderIsVisible();
+ placeholderIsVisible = toRenderTextControlSingleLine(renderer)->placeholderIsVisible();
return RenderBlock::nodeAtPoint(request, result, x, y, tx, ty, placeholderIsVisible ? HitTestBlockBackground : hitTestAction);
}
@@ -69,7 +69,7 @@ VisiblePosition RenderTextControlInnerBlock::positionForPoint(const IntPoint& po
// Multiline text controls have the scroll on shadowAncestorNode, so we need to take that
// into account here.
if (m_multiLine) {
- RenderTextControl* renderer = static_cast<RenderTextControl*>(node()->shadowAncestorNode()->renderer());
+ RenderTextControl* renderer = toRenderTextControl(node()->shadowAncestorNode()->renderer());
if (renderer->hasOverflowClip())
renderer->layer()->addScrolledContentOffset(contentsX, contentsY);
}
@@ -155,7 +155,7 @@ void SearchFieldResultsButtonElement::defaultEventHandler(Event* evt)
if (evt->type() == eventNames().mousedownEvent && evt->isMouseEvent() && static_cast<MouseEvent*>(evt)->button() == LeftButton) {
input->focus();
input->select();
- RenderTextControlSingleLine* renderer = static_cast<RenderTextControlSingleLine*>(input->renderer());
+ RenderTextControlSingleLine* renderer = toRenderTextControlSingleLine(input->renderer());
if (renderer->popupIsVisible())
renderer->hidePopup();
else if (input->maxResults() > 0)
@@ -172,6 +172,16 @@ SearchFieldCancelButtonElement::SearchFieldCancelButtonElement(Document* doc)
{
}
+void SearchFieldCancelButtonElement::detach()
+{
+ if (m_capturing) {
+ if (Frame* frame = document()->frame())
+ frame->eventHandler()->setCapturingMouseEventsNode(0);
+ }
+ TextControlInnerElement::detach();
+}
+
+
void SearchFieldCancelButtonElement::defaultEventHandler(Event* evt)
{
// If the element is visible, on mouseup, clear the value, and set selection
diff --git a/WebCore/rendering/TextControlInnerElements.h b/WebCore/rendering/TextControlInnerElements.h
index 9e81ada..f72ddf2 100644
--- a/WebCore/rendering/TextControlInnerElements.h
+++ b/WebCore/rendering/TextControlInnerElements.h
@@ -32,8 +32,7 @@ namespace WebCore {
class String;
-class TextControlInnerElement : public HTMLDivElement
-{
+class TextControlInnerElement : public HTMLDivElement {
public:
TextControlInnerElement(Document*, Node* shadowParent = 0);
@@ -64,6 +63,7 @@ class SearchFieldCancelButtonElement : public TextControlInnerElement {
public:
SearchFieldCancelButtonElement(Document*);
virtual void defaultEventHandler(Event*);
+ virtual void detach();
private:
bool m_capturing;
};
diff --git a/WebCore/rendering/TransformState.h b/WebCore/rendering/TransformState.h
index 92275f9..d2c962a 100644
--- a/WebCore/rendering/TransformState.h
+++ b/WebCore/rendering/TransformState.h
@@ -37,7 +37,7 @@
namespace WebCore {
-class TransformState : Noncopyable {
+class TransformState : public Noncopyable {
public:
enum TransformDirection { ApplyTransformDirection, UnapplyInverseTransformDirection };
enum TransformAccumulation { FlattenTransform, AccumulateTransform };
diff --git a/WebCore/rendering/bidi.h b/WebCore/rendering/bidi.h
deleted file mode 100644
index 9058eeb..0000000
--- a/WebCore/rendering/bidi.h
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * This file is part of the html renderer for KDE.
- *
- * Copyright (C) 2000 Lars Knoll (knoll@kde.org)
- * Copyright (C) 2003 Apple Computer, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-
-#ifndef bidi_h
-#define bidi_h
-
-#include "BidiResolver.h"
-
-namespace WebCore {
-
-class RenderArena;
-class RenderBlock;
-class RenderObject;
-class InlineBox;
-
-struct BidiRun : BidiCharacterRun {
- BidiRun(int start, int stop, RenderObject* object, BidiContext* context, WTF::Unicode::Direction dir)
- : BidiCharacterRun(start, stop, context, dir)
- , m_object(object)
- , m_box(0)
- {
- }
-
- void destroy();
-
- // Overloaded new operator.
- void* operator new(size_t, RenderArena*) throw();
-
- // Overridden to prevent the normal delete from being called.
- void operator delete(void*, size_t);
-
- BidiRun* next() { return static_cast<BidiRun*>(m_next); }
-
-private:
- // The normal operator new is disallowed.
- void* operator new(size_t) throw();
-
-public:
- RenderObject* m_object;
- InlineBox* m_box;
-};
-
-} // namespace WebCore
-
-#endif // bidi_h
diff --git a/WebCore/rendering/style/FillLayer.h b/WebCore/rendering/style/FillLayer.h
index 2dc5871..c3944ad 100644
--- a/WebCore/rendering/style/FillLayer.h
+++ b/WebCore/rendering/style/FillLayer.h
@@ -42,7 +42,7 @@ public:
StyleImage* image() const { return m_image.get(); }
Length xPosition() const { return m_xPosition; }
Length yPosition() const { return m_yPosition; }
- bool attachment() const { return m_attachment; }
+ EFillAttachment attachment() const { return static_cast<EFillAttachment>(m_attachment); }
EFillBox clip() const { return static_cast<EFillBox>(m_clip); }
EFillBox origin() const { return static_cast<EFillBox>(m_origin); }
EFillRepeat repeat() const { return static_cast<EFillRepeat>(m_repeat); }
@@ -65,7 +65,7 @@ public:
void setImage(StyleImage* i) { m_image = i; m_imageSet = true; }
void setXPosition(const Length& l) { m_xPosition = l; m_xPosSet = true; }
void setYPosition(const Length& l) { m_yPosition = l; m_yPosSet = true; }
- void setAttachment(bool b) { m_attachment = b; m_attachmentSet = true; }
+ void setAttachment(EFillAttachment attachment) { m_attachment = attachment; m_attachmentSet = true; }
void setClip(EFillBox b) { m_clip = b; m_clipSet = true; }
void setOrigin(EFillBox b) { m_origin = b; m_originSet = true; }
void setRepeat(EFillRepeat r) { m_repeat = r; m_repeatSet = true; }
@@ -104,7 +104,7 @@ public:
bool hasFixedImage() const
{
- if (m_image && !m_attachment)
+ if (m_image && m_attachment == FixedBackgroundAttachment)
return true;
return m_next ? m_next->hasFixedImage() : false;
}
@@ -114,7 +114,7 @@ public:
void fillUnsetProperties();
void cullEmptyLayers();
- static bool initialFillAttachment(EFillLayerType) { return true; }
+ static EFillAttachment initialFillAttachment(EFillLayerType) { return ScrollBackgroundAttachment; }
static EFillBox initialFillClip(EFillLayerType) { return BorderFillBox; }
static EFillBox initialFillOrigin(EFillLayerType type) { return type == BackgroundFillLayer ? PaddingFillBox : BorderFillBox; }
static EFillRepeat initialFillRepeat(EFillLayerType) { return RepeatFill; }
@@ -133,7 +133,7 @@ public:
Length m_xPosition;
Length m_yPosition;
- bool m_attachment : 1;
+ unsigned m_attachment : 2; // EFillAttachment
unsigned m_clip : 2; // EFillBox
unsigned m_origin : 2; // EFillBox
unsigned m_repeat : 2; // EFillRepeat
diff --git a/WebCore/rendering/style/RenderStyle.cpp b/WebCore/rendering/style/RenderStyle.cpp
index f3a2cd9..0e258c8 100644
--- a/WebCore/rendering/style/RenderStyle.cpp
+++ b/WebCore/rendering/style/RenderStyle.cpp
@@ -206,7 +206,7 @@ void RenderStyle::setHasPseudoStyle(PseudoId pseudo)
noninherited_flags._pseudoBits |= pseudoBit(pseudo);
}
-RenderStyle* RenderStyle::getCachedPseudoStyle(PseudoId pid)
+RenderStyle* RenderStyle::getCachedPseudoStyle(PseudoId pid) const
{
if (!m_cachedPseudoStyle || styleType() != NOPSEUDO)
return 0;
@@ -225,7 +225,14 @@ RenderStyle* RenderStyle::addCachedPseudoStyle(PassRefPtr<RenderStyle> pseudo)
return m_cachedPseudoStyle.get();
}
-bool RenderStyle::inheritedNotEqual(RenderStyle* other) const
+void RenderStyle::getPseudoStyleCache(PseudoStyleCache& cache) const
+{
+ ASSERT(cache.isEmpty());
+ for (RenderStyle* pseudoStyle = m_cachedPseudoStyle.get(); pseudoStyle; pseudoStyle = pseudoStyle->m_cachedPseudoStyle.get())
+ cache.append(pseudoStyle);
+}
+
+bool RenderStyle::inheritedNotEqual(const RenderStyle* other) const
{
return inherited_flags != other->inherited_flags ||
inherited != other->inherited ||
@@ -688,6 +695,8 @@ void RenderStyle::addBindingURI(StringImpl* uri)
void RenderStyle::setTextShadow(ShadowData* val, bool add)
{
+ ASSERT(!val || !val->spread && val->style == Normal);
+
StyleRareInheritedData* rareData = rareInheritedData.access();
if (!add) {
delete rareData->textShadow;
@@ -897,4 +906,53 @@ void RenderStyle::setBlendedFontSize(int size)
font().update(font().fontSelector());
}
+void RenderStyle::getBoxShadowExtent(int &top, int &right, int &bottom, int &left) const
+{
+ top = 0;
+ right = 0;
+ bottom = 0;
+ left = 0;
+
+ for (ShadowData* boxShadow = this->boxShadow(); boxShadow; boxShadow = boxShadow->next) {
+ if (boxShadow->style == Inset)
+ continue;
+ int blurAndSpread = boxShadow->blur + boxShadow->spread;
+
+ top = min(top, boxShadow->y - blurAndSpread);
+ right = max(right, boxShadow->x + blurAndSpread);
+ bottom = max(bottom, boxShadow->y + blurAndSpread);
+ left = min(left, boxShadow->x - blurAndSpread);
+ }
+}
+
+void RenderStyle::getBoxShadowHorizontalExtent(int &left, int &right) const
+{
+ left = 0;
+ right = 0;
+
+ for (ShadowData* boxShadow = this->boxShadow(); boxShadow; boxShadow = boxShadow->next) {
+ if (boxShadow->style == Inset)
+ continue;
+ int blurAndSpread = boxShadow->blur + boxShadow->spread;
+
+ left = min(left, boxShadow->x - blurAndSpread);
+ right = max(right, boxShadow->x + blurAndSpread);
+ }
+}
+
+void RenderStyle::getBoxShadowVerticalExtent(int &top, int &bottom) const
+{
+ top = 0;
+ bottom = 0;
+
+ for (ShadowData* boxShadow = this->boxShadow(); boxShadow; boxShadow = boxShadow->next) {
+ if (boxShadow->style == Inset)
+ continue;
+ int blurAndSpread = boxShadow->blur + boxShadow->spread;
+
+ top = min(top, boxShadow->y - blurAndSpread);
+ bottom = max(bottom, boxShadow->y + blurAndSpread);
+ }
+}
+
} // namespace WebCore
diff --git a/WebCore/rendering/style/RenderStyle.h b/WebCore/rendering/style/RenderStyle.h
index 5062596..720bc8d 100644
--- a/WebCore/rendering/style/RenderStyle.h
+++ b/WebCore/rendering/style/RenderStyle.h
@@ -301,12 +301,15 @@ public:
void inheritFrom(const RenderStyle* inheritParent);
- PseudoId styleType() { return static_cast<PseudoId>(noninherited_flags._styleType); }
+ PseudoId styleType() const { return static_cast<PseudoId>(noninherited_flags._styleType); }
void setStyleType(PseudoId styleType) { noninherited_flags._styleType = styleType; }
- RenderStyle* getCachedPseudoStyle(PseudoId);
+ RenderStyle* getCachedPseudoStyle(PseudoId) const;
RenderStyle* addCachedPseudoStyle(PassRefPtr<RenderStyle>);
+ typedef Vector<RenderStyle*, 10> PseudoStyleCache;
+ void getPseudoStyleCache(PseudoStyleCache&) const;
+
bool affectedByHoverRules() const { return noninherited_flags._affectedByHover; }
bool affectedByActiveRules() const { return noninherited_flags._affectedByActive; }
bool affectedByDragRules() const { return noninherited_flags._affectedByDrag; }
@@ -520,7 +523,7 @@ public:
StyleImage* backgroundImage() const { return background->m_background.m_image.get(); }
EFillRepeat backgroundRepeat() const { return static_cast<EFillRepeat>(background->m_background.m_repeat); }
CompositeOperator backgroundComposite() const { return static_cast<CompositeOperator>(background->m_background.m_composite); }
- bool backgroundAttachment() const { return background->m_background.m_attachment; }
+ EFillAttachment backgroundAttachment() const { return static_cast<EFillAttachment>(background->m_background.m_attachment); }
EFillBox backgroundClip() const { return static_cast<EFillBox>(background->m_background.m_clip); }
EFillBox backgroundOrigin() const { return static_cast<EFillBox>(background->m_background.m_origin); }
Length backgroundXPosition() const { return background->m_background.m_xPosition; }
@@ -532,7 +535,7 @@ public:
StyleImage* maskImage() const { return rareNonInheritedData->m_mask.m_image.get(); }
EFillRepeat maskRepeat() const { return static_cast<EFillRepeat>(rareNonInheritedData->m_mask.m_repeat); }
CompositeOperator maskComposite() const { return static_cast<CompositeOperator>(rareNonInheritedData->m_mask.m_composite); }
- bool maskAttachment() const { return rareNonInheritedData->m_mask.m_attachment; }
+ EFillAttachment maskAttachment() const { return static_cast<EFillAttachment>(rareNonInheritedData->m_mask.m_attachment); }
EFillBox maskClip() const { return static_cast<EFillBox>(rareNonInheritedData->m_mask.m_clip); }
EFillBox maskOrigin() const { return static_cast<EFillBox>(rareNonInheritedData->m_mask.m_origin); }
Length maskXPosition() const { return rareNonInheritedData->m_mask.m_xPosition; }
@@ -603,7 +606,12 @@ public:
unsigned int boxOrdinalGroup() const { return rareNonInheritedData->flexibleBox->ordinal_group; }
EBoxOrient boxOrient() const { return static_cast<EBoxOrient>(rareNonInheritedData->flexibleBox->orient); }
EBoxAlignment boxPack() const { return static_cast<EBoxAlignment>(rareNonInheritedData->flexibleBox->pack); }
+
ShadowData* boxShadow() const { return rareNonInheritedData->m_boxShadow.get(); }
+ void getBoxShadowExtent(int &top, int &right, int &bottom, int &left) const;
+ void getBoxShadowHorizontalExtent(int &left, int &right) const;
+ void getBoxShadowVerticalExtent(int &top, int &bottom) const;
+
StyleReflection* boxReflect() const { return rareNonInheritedData->m_boxReflect.get(); }
EBoxSizing boxSizing() const { return static_cast<EBoxSizing>(box->boxSizing); }
Length marqueeIncrement() const { return rareNonInheritedData->marquee->increment; }
@@ -792,7 +800,7 @@ public:
void setOverflowY(EOverflow v) { noninherited_flags._overflowY = v; }
void setVisibility(EVisibility v) { inherited_flags._visibility = v; }
void setVerticalAlign(EVerticalAlign v) { noninherited_flags._vertical_align = v; }
- void setVerticalAlignLength(Length l) { SET_VAR(box, vertical_align, l ) }
+ void setVerticalAlignLength(Length l) { SET_VAR(box, vertical_align, l) }
void setHasClip(bool b = true) { SET_VAR(visual, hasClip, b) }
void setClipLeft(Length v) { SET_VAR(visual, clip.m_left, v) }
@@ -801,7 +809,7 @@ public:
void setClipBottom(Length v) { SET_VAR(visual, clip.m_bottom, v) }
void setClip(Length top, Length right, Length bottom, Length left);
- void setUnicodeBidi( EUnicodeBidi b ) { noninherited_flags._unicodeBidi = b; }
+ void setUnicodeBidi(EUnicodeBidi b) { noninherited_flags._unicodeBidi = b; }
void setClear(EClear v) { noninherited_flags._clear = v; }
void setTableLayout(ETableLayout v) { noninherited_flags._table_layout = v; }
@@ -888,7 +896,7 @@ public:
void setPaddingLeft(Length v) { SET_VAR(surround, padding.m_left, v) }
void setPaddingRight(Length v) { SET_VAR(surround, padding.m_right, v) }
- void setCursor( ECursor c ) { inherited_flags._cursor_style = c; }
+ void setCursor(ECursor c) { inherited_flags._cursor_style = c; }
void addCursor(CachedImage*, const IntPoint& = IntPoint());
void setCursorList(PassRefPtr<CursorList>);
void clearCursorList();
@@ -1033,7 +1041,7 @@ public:
const CounterDirectiveMap* counterDirectives() const;
CounterDirectiveMap& accessCounterDirectives();
- bool inheritedNotEqual(RenderStyle*) const;
+ bool inheritedNotEqual(const RenderStyle*) const;
StyleDifference diff(const RenderStyle*, unsigned& changedContextSensitiveProperties) const;
diff --git a/WebCore/rendering/style/RenderStyleConstants.h b/WebCore/rendering/style/RenderStyleConstants.h
index 405cf7c..c491816 100644
--- a/WebCore/rendering/style/RenderStyleConstants.h
+++ b/WebCore/rendering/style/RenderStyleConstants.h
@@ -69,7 +69,8 @@ enum PseudoId {
SLIDER_THUMB, SEARCH_CANCEL_BUTTON, SEARCH_DECORATION, SEARCH_RESULTS_DECORATION, SEARCH_RESULTS_BUTTON, MEDIA_CONTROLS_PANEL,
MEDIA_CONTROLS_PLAY_BUTTON, MEDIA_CONTROLS_MUTE_BUTTON, MEDIA_CONTROLS_TIMELINE, MEDIA_CONTROLS_TIMELINE_CONTAINER,
MEDIA_CONTROLS_CURRENT_TIME_DISPLAY, MEDIA_CONTROLS_TIME_REMAINING_DISPLAY, MEDIA_CONTROLS_SEEK_BACK_BUTTON,
- MEDIA_CONTROLS_SEEK_FORWARD_BUTTON, MEDIA_CONTROLS_FULLSCREEN_BUTTON,
+ MEDIA_CONTROLS_SEEK_FORWARD_BUTTON, MEDIA_CONTROLS_FULLSCREEN_BUTTON, MEDIA_CONTROLS_REWIND_BUTTON,
+ MEDIA_CONTROLS_RETURN_TO_REALTIME_BUTTON, MEDIA_CONTROLS_STATUS_DISPLAY,
SCROLLBAR_THUMB, SCROLLBAR_BUTTON, SCROLLBAR_TRACK, SCROLLBAR_TRACK_PIECE, SCROLLBAR_CORNER, RESIZER,
FIRST_INTERNAL_PSEUDOID = FILE_UPLOAD_BUTTON
@@ -109,7 +110,7 @@ enum EVerticalAlign {
TEXT_BOTTOM, TOP, BOTTOM, BASELINE_MIDDLE, LENGTH
};
-enum EClear{
+enum EClear {
CNONE = 0, CLEFT = 1, CRIGHT = 2, CBOTH = 3
};
@@ -121,6 +122,10 @@ enum EUnicodeBidi {
UBNormal, Embed, Override
};
+enum EFillAttachment {
+ ScrollBackgroundAttachment, LocalBackgroundAttachment, FixedBackgroundAttachment
+};
+
enum EFillBox {
BorderFillBox, PaddingFillBox, ContentFillBox, TextFillBox
};
@@ -207,6 +212,11 @@ enum StyleContentType {
enum EBorderFit { BorderFitBorder, BorderFitLines };
+enum EAnimPlayState {
+ AnimPlayStatePlaying = 0x0,
+ AnimPlayStatePaused = 0x1
+};
+
enum ETimingFunctionType { LinearTimingFunction, CubicBezierTimingFunction };
enum EWhiteSpace {
diff --git a/WebCore/rendering/style/SVGRenderStyle.cpp b/WebCore/rendering/style/SVGRenderStyle.cpp
index c5f0648..1289b06 100644
--- a/WebCore/rendering/style/SVGRenderStyle.cpp
+++ b/WebCore/rendering/style/SVGRenderStyle.cpp
@@ -32,6 +32,7 @@
#include "CSSPrimitiveValue.h"
#include "CSSValueList.h"
+#include "NodeRenderStyle.h"
#include "RenderObject.h"
#include "RenderStyle.h"
#include "SVGStyledElement.h"
@@ -136,7 +137,7 @@ float SVGRenderStyle::cssPrimitiveToLength(const RenderObject* item, CSSValue* v
}
}
- return primitive->computeLengthFloat(const_cast<RenderStyle*>(item->style()));
+ return primitive->computeLengthFloat(const_cast<RenderStyle*>(item->style()), item->document()->documentElement()->renderStyle());
}
}
diff --git a/WebCore/rendering/style/SVGRenderStyleDefs.h b/WebCore/rendering/style/SVGRenderStyleDefs.h
index cb504d2..b7bf026 100644
--- a/WebCore/rendering/style/SVGRenderStyleDefs.h
+++ b/WebCore/rendering/style/SVGRenderStyleDefs.h
@@ -60,13 +60,13 @@
#define SVG_RS_DEFINE_ATTRIBUTE_DATAREF_WITH_INITIAL_REFCOUNTED(Data, Group, Variable, Type, Name, Initial) \
Data* Name() const { return Group->Variable.get(); } \
void set##Type(PassRefPtr<Data> obj) { \
- if(!(Group->Variable == obj)) \
+ if (!(Group->Variable == obj)) \
Group.access()->Variable = obj; \
} \
static Data* initial##Type() { return Initial; }
#define SVG_RS_SET_VARIABLE(Group, Variable, Value) \
- if(!(Group->Variable == Value)) \
+ if (!(Group->Variable == Value)) \
Group.access()->Variable = Value;
namespace WebCore {
diff --git a/WebCore/rendering/style/ShadowData.cpp b/WebCore/rendering/style/ShadowData.cpp
index 75fb9dc..1954224 100644
--- a/WebCore/rendering/style/ShadowData.cpp
+++ b/WebCore/rendering/style/ShadowData.cpp
@@ -1,6 +1,6 @@
/*
* Copyright (C) 1999 Antti Koivisto (koivisto@kde.org)
- * Copyright (C) 2004, 2005, 2006, 2007, 2008 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
@@ -28,6 +28,8 @@ ShadowData::ShadowData(const ShadowData& o)
: x(o.x)
, y(o.y)
, blur(o.blur)
+ , spread(o.spread)
+ , style(o.style)
, color(o.color)
{
next = o.next ? new ShadowData(*o.next) : 0;
@@ -39,7 +41,7 @@ bool ShadowData::operator==(const ShadowData& o) const
(next && o.next && *next != *o.next))
return false;
- return x == o.x && y == o.y && blur == o.blur && color == o.color;
+ return x == o.x && y == o.y && blur == o.blur && spread == o.spread && style == o.style && color == o.color;
}
} // namespace WebCore
diff --git a/WebCore/rendering/style/ShadowData.h b/WebCore/rendering/style/ShadowData.h
index dac2b18..f4061f2 100644
--- a/WebCore/rendering/style/ShadowData.h
+++ b/WebCore/rendering/style/ShadowData.h
@@ -2,7 +2,7 @@
* 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) 2003, 2005, 2006, 2007, 2008, 2009 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
@@ -29,6 +29,8 @@
namespace WebCore {
+enum ShadowStyle { Normal, Inset };
+
// This struct holds information about shadows for the text-shadow and box-shadow properties.
struct ShadowData {
@@ -36,15 +38,19 @@ struct ShadowData {
: x(0)
, y(0)
, blur(0)
+ , spread(0)
+ , style(Normal)
, next(0)
{
}
- ShadowData(int _x, int _y, int _blur, const Color& _color)
- : x(_x)
- , y(_y)
- , blur(_blur)
- , color(_color)
+ ShadowData(int x, int y, int blur, int spread, ShadowStyle style, const Color& color)
+ : x(x)
+ , y(y)
+ , blur(blur)
+ , spread(spread)
+ , style(style)
+ , color(color)
, next(0)
{
}
@@ -62,6 +68,8 @@ struct ShadowData {
int x;
int y;
int blur;
+ int spread;
+ ShadowStyle style;
Color color;
ShadowData* next;
};
diff --git a/WebCore/rendering/style/StyleInheritedData.h b/WebCore/rendering/style/StyleInheritedData.h
index 5f1077e..548ca72 100644
--- a/WebCore/rendering/style/StyleInheritedData.h
+++ b/WebCore/rendering/style/StyleInheritedData.h
@@ -44,7 +44,7 @@ public:
~StyleInheritedData();
bool operator==(const StyleInheritedData& o) const;
- bool operator!=( const StyleInheritedData& o) const
+ bool operator!=(const StyleInheritedData& o) const
{
return !(*this == o);
}
diff --git a/WebCore/rendering/style/StyleRareInheritedData.cpp b/WebCore/rendering/style/StyleRareInheritedData.cpp
index 680fd57..0f3b7e7 100644
--- a/WebCore/rendering/style/StyleRareInheritedData.cpp
+++ b/WebCore/rendering/style/StyleRareInheritedData.cpp
@@ -89,6 +89,7 @@ bool StyleRareInheritedData::operator==(const StyleRareInheritedData& o) const
#ifdef ANDROID_CSS_TAP_HIGHLIGHT_COLOR
&& tapHighlightColor == o.tapHighlightColor
#endif
+ && resize == o.resize
&& userSelect == o.userSelect;
}