summaryrefslogtreecommitdiffstats
path: root/WebCore/rendering
diff options
context:
space:
mode:
Diffstat (limited to 'WebCore/rendering')
-rw-r--r--WebCore/rendering/RenderBlock.cpp5
-rw-r--r--WebCore/rendering/RenderBox.cpp6
-rw-r--r--WebCore/rendering/RenderEmbeddedObject.cpp8
-rw-r--r--WebCore/rendering/RenderFileUploadControl.cpp13
-rw-r--r--WebCore/rendering/RenderFileUploadControl.h3
-rw-r--r--WebCore/rendering/RenderForeignObject.cpp7
-rw-r--r--WebCore/rendering/RenderLayer.cpp4
-rw-r--r--WebCore/rendering/RenderLayerBacking.cpp106
-rw-r--r--WebCore/rendering/RenderLayerBacking.h10
-rw-r--r--WebCore/rendering/RenderLayerCompositor.cpp12
-rw-r--r--WebCore/rendering/RenderMenuList.cpp8
-rw-r--r--WebCore/rendering/RenderMenuList.h1
-rw-r--r--WebCore/rendering/RenderObject.cpp14
-rw-r--r--WebCore/rendering/RenderObjectChildList.cpp16
-rw-r--r--WebCore/rendering/RenderPath.cpp6
-rw-r--r--WebCore/rendering/RenderSVGContainer.cpp7
-rw-r--r--WebCore/rendering/RenderSVGImage.cpp8
-rw-r--r--WebCore/rendering/RenderSVGModelObject.cpp8
-rw-r--r--WebCore/rendering/RenderSVGModelObject.h1
-rw-r--r--WebCore/rendering/RenderSVGResource.cpp30
-rw-r--r--WebCore/rendering/RenderSVGResource.h3
-rw-r--r--WebCore/rendering/RenderSVGResourceClipper.cpp48
-rw-r--r--WebCore/rendering/RenderSVGResourceClipper.h3
-rw-r--r--WebCore/rendering/RenderSVGResourceContainer.h53
-rw-r--r--WebCore/rendering/RenderSVGResourceFilter.cpp13
-rw-r--r--WebCore/rendering/RenderSVGResourceGradient.cpp13
-rw-r--r--WebCore/rendering/RenderSVGResourceMarker.cpp12
-rw-r--r--WebCore/rendering/RenderSVGResourceMasker.cpp32
-rw-r--r--WebCore/rendering/RenderSVGResourceMasker.h2
-rw-r--r--WebCore/rendering/RenderSVGResourcePattern.cpp29
-rw-r--r--WebCore/rendering/RenderSVGResourcePattern.h2
-rw-r--r--WebCore/rendering/RenderSVGRoot.cpp2
-rw-r--r--WebCore/rendering/RenderSVGShadowTreeRootContainer.cpp5
-rw-r--r--WebCore/rendering/RenderSVGShadowTreeRootContainer.h2
-rw-r--r--WebCore/rendering/RenderSVGText.cpp6
-rw-r--r--WebCore/rendering/RenderTextControlSingleLine.cpp42
-rw-r--r--WebCore/rendering/RenderTextControlSingleLine.h3
-rw-r--r--WebCore/rendering/RenderTheme.cpp15
-rw-r--r--WebCore/rendering/RenderThemeChromiumLinux.cpp32
-rw-r--r--WebCore/rendering/RenderThemeChromiumLinux.h14
-rw-r--r--WebCore/rendering/RenderThemeChromiumWin.cpp150
-rw-r--r--WebCore/rendering/RenderThemeChromiumWin.h14
-rw-r--r--WebCore/rendering/RenderThemeMac.mm9
-rw-r--r--WebCore/rendering/RenderTreeAsText.cpp32
-rw-r--r--WebCore/rendering/RenderTreeAsText.h3
-rw-r--r--WebCore/rendering/RenderView.cpp19
-rw-r--r--WebCore/rendering/TextControlInnerElements.cpp97
-rw-r--r--WebCore/rendering/TextControlInnerElements.h33
-rw-r--r--WebCore/rendering/style/FillLayer.cpp35
-rw-r--r--WebCore/rendering/style/RenderStyle.h4
50 files changed, 727 insertions, 273 deletions
diff --git a/WebCore/rendering/RenderBlock.cpp b/WebCore/rendering/RenderBlock.cpp
index c97d965..1b855d4 100644
--- a/WebCore/rendering/RenderBlock.cpp
+++ b/WebCore/rendering/RenderBlock.cpp
@@ -3,6 +3,7 @@
* (C) 1999 Antti Koivisto (koivisto@kde.org)
* (C) 2007 David Smith (catfish.man@gmail.com)
* Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved.
+ * Copyright (C) Research In Motion Limited 2010. 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
@@ -940,6 +941,10 @@ static bool canMergeContiguousAnonymousBlocks(RenderObject* oldChild, RenderObje
|| (next && (!next->isAnonymousBlock() || toRenderBlock(next)->continuation())))
return false;
+ // FIXME: This check isn't required when inline run-ins can't be split into continuations.
+ if (prev && prev->firstChild() && prev->firstChild()->isInline() && prev->firstChild()->isRunIn())
+ return false;
+
#if ENABLE(RUBY)
if ((prev && (prev->isRubyRun() || prev->isRubyBase()))
|| (next && (next->isRubyRun() || next->isRubyBase())))
diff --git a/WebCore/rendering/RenderBox.cpp b/WebCore/rendering/RenderBox.cpp
index d4c691f..8d18440 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, 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010 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
@@ -155,7 +155,9 @@ void RenderBox::styleWillChange(StyleDifference diff, const RenderStyle* newStyl
if (isFloating() && !isPositioned() && (newStyle->position() == AbsolutePosition || newStyle->position() == FixedPosition))
removeFloatingOrPositionedChildFromBlockLists();
}
- }
+ } else if (newStyle && isBody())
+ view()->repaint();
+
if (FrameView *frameView = view()->frameView()) {
bool newStyleIsFixed = newStyle && newStyle->position() == FixedPosition;
bool oldStyleIsFixed = style() && style()->position() == FixedPosition;
diff --git a/WebCore/rendering/RenderEmbeddedObject.cpp b/WebCore/rendering/RenderEmbeddedObject.cpp
index de9ca17..e72825e 100644
--- a/WebCore/rendering/RenderEmbeddedObject.cpp
+++ b/WebCore/rendering/RenderEmbeddedObject.cpp
@@ -42,7 +42,7 @@
#include "MouseEvent.h"
#include "Page.h"
#include "Path.h"
-#include "PluginWidget.h"
+#include "PluginViewBase.h"
#include "RenderTheme.h"
#include "RenderView.h"
#include "RenderWidgetProtector.h"
@@ -53,10 +53,6 @@
#include "HTMLVideoElement.h"
#endif
-#if USE(ACCELERATED_COMPOSITING)
-#include "PluginWidget.h"
-#endif
-
namespace WebCore {
using namespace HTMLNames;
@@ -102,7 +98,7 @@ bool RenderEmbeddedObject::requiresLayer() const
bool RenderEmbeddedObject::allowsAcceleratedCompositing() const
{
- return widget() && widget()->isPluginWidget() && static_cast<PluginWidget*>(widget())->platformLayer();
+ return widget() && widget()->isPluginViewBase() && static_cast<PluginViewBase*>(widget())->platformLayer();
}
#endif
diff --git a/WebCore/rendering/RenderFileUploadControl.cpp b/WebCore/rendering/RenderFileUploadControl.cpp
index c652276..f31ca20 100644
--- a/WebCore/rendering/RenderFileUploadControl.cpp
+++ b/WebCore/rendering/RenderFileUploadControl.cpp
@@ -94,10 +94,23 @@ void RenderFileUploadControl::valueChanged()
bool RenderFileUploadControl::allowsMultipleFiles()
{
+#if ENABLE(DIRECTORY_UPLOAD)
+ if (allowsDirectoryUpload())
+ return true;
+#endif
+
HTMLInputElement* input = static_cast<HTMLInputElement*>(node());
return !input->getAttribute(multipleAttr).isNull();
}
+#if ENABLE(DIRECTORY_UPLOAD)
+bool RenderFileUploadControl::allowsDirectoryUpload()
+{
+ HTMLInputElement* input = static_cast<HTMLInputElement*>(node());
+ return !input->getAttribute(webkitdirectoryAttr).isNull();
+}
+#endif
+
String RenderFileUploadControl::acceptTypes()
{
return static_cast<HTMLInputElement*>(node())->accept();
diff --git a/WebCore/rendering/RenderFileUploadControl.h b/WebCore/rendering/RenderFileUploadControl.h
index 25d2639..205ba47 100644
--- a/WebCore/rendering/RenderFileUploadControl.h
+++ b/WebCore/rendering/RenderFileUploadControl.h
@@ -62,6 +62,9 @@ private:
void valueChanged();
void repaint() { RenderBlock::repaint(); }
bool allowsMultipleFiles();
+#if ENABLE(DIRECTORY_UPLOAD)
+ bool allowsDirectoryUpload();
+#endif
String acceptTypes();
void chooseIconForFiles(FileChooser*, const Vector<String>&);
diff --git a/WebCore/rendering/RenderForeignObject.cpp b/WebCore/rendering/RenderForeignObject.cpp
index 4b94bab..8b84f97 100644
--- a/WebCore/rendering/RenderForeignObject.cpp
+++ b/WebCore/rendering/RenderForeignObject.cpp
@@ -26,6 +26,7 @@
#include "RenderForeignObject.h"
#include "GraphicsContext.h"
+#include "RenderSVGResource.h"
#include "RenderView.h"
#include "SVGForeignObjectElement.h"
#include "SVGRenderSupport.h"
@@ -98,7 +99,7 @@ void RenderForeignObject::layout()
ASSERT(needsLayout());
ASSERT(!view()->layoutStateEnabled()); // RenderSVGRoot disables layoutState for the SVG rendering tree.
- LayoutRepainter repainter(*this, checkForRepaintDuringLayout());
+ LayoutRepainter repainter(*this, m_everHadLayout && checkForRepaintDuringLayout());
SVGForeignObjectElement* foreign = static_cast<SVGForeignObjectElement*>(node());
if (m_needsTransformUpdate) {
@@ -118,6 +119,10 @@ void RenderForeignObject::layout()
setLocation(roundedIntPoint(viewportLocation));
RenderBlock::layout();
+ // Invalidate all resources of this client, if we changed something.
+ if (m_everHadLayout && selfNeedsLayout())
+ RenderSVGResource::invalidateAllResourcesOfRenderer(this);
+
repainter.repaintAfterLayout();
setNeedsLayout(false);
}
diff --git a/WebCore/rendering/RenderLayer.cpp b/WebCore/rendering/RenderLayer.cpp
index 78fddfd..f0c6333 100644
--- a/WebCore/rendering/RenderLayer.cpp
+++ b/WebCore/rendering/RenderLayer.cpp
@@ -3761,7 +3761,7 @@ bool RenderLayer::shouldBeNormalFlowOnly() const
static bool hasOverflowScroll(const RenderLayer* layer)
{
RenderBox* box = layer->renderBox();
- if (!box || !box->node()->hasTagName(HTMLNames::divTag))
+ if (!box || !box->node() || !box->node()->hasTagName(HTMLNames::divTag))
return false;
EOverflow x = box->style()->overflowX();
EOverflow y = box->style()->overflowY();
@@ -3933,7 +3933,7 @@ void showLayerTree(const WebCore::RenderLayer* layer)
return;
if (WebCore::Frame* frame = layer->renderer()->frame()) {
- WebCore::String output = externalRepresentation(frame, WebCore::RenderAsTextShowAllLayers | WebCore::RenderAsTextShowLayerNesting | WebCore::RenderAsTextShowCompositedLayers | WebCore::RenderAsTextShowAddresses);
+ WebCore::String output = externalRepresentation(frame, WebCore::RenderAsTextShowAllLayers | WebCore::RenderAsTextShowLayerNesting | WebCore::RenderAsTextShowCompositedLayers | WebCore::RenderAsTextShowAddresses | WebCore::RenderAsTextShowIDAndClass);
fprintf(stderr, "%s\n", output.utf8().data());
}
}
diff --git a/WebCore/rendering/RenderLayerBacking.cpp b/WebCore/rendering/RenderLayerBacking.cpp
index 1153727..2bc6a88 100644
--- a/WebCore/rendering/RenderLayerBacking.cpp
+++ b/WebCore/rendering/RenderLayerBacking.cpp
@@ -43,7 +43,7 @@
#include "HTMLNames.h"
#include "InspectorTimelineAgent.h"
#include "KeyframeList.h"
-#include "PluginWidget.h"
+#include "PluginViewBase.h"
#include "RenderBox.h"
#include "RenderIFrame.h"
#include "RenderImage.h"
@@ -68,6 +68,7 @@ using namespace HTMLNames;
static bool hasBorderOutlineOrShadow(const RenderStyle*);
static bool hasBoxDecorationsOrBackground(const RenderObject*);
static bool hasBoxDecorationsOrBackgroundImage(const RenderStyle*);
+static IntRect clipBox(RenderBox* renderer);
static inline bool is3DCanvas(RenderObject* renderer)
{
@@ -143,10 +144,60 @@ static bool hasNonZeroTransformOrigin(const RenderObject* renderer)
|| (style->transformOriginY().type() == Fixed && style->transformOriginY().value());
}
+static RenderLayer* enclosingOverflowClipAncestor(RenderLayer* layer, bool& crossesTransform)
+{
+ crossesTransform = false;
+
+ for (RenderLayer* curr = layer->parent(); curr; curr = curr->parent()) {
+ if (curr->renderer()->hasOverflowClip())
+ return curr;
+
+ if (curr->hasTransform())
+ crossesTransform = true;
+ }
+
+ return 0;
+}
+
void RenderLayerBacking::updateCompositedBounds()
{
IntRect layerBounds = compositor()->calculateCompositedBounds(m_owningLayer, m_owningLayer);
+ // Clip to the size of the document or enclosing overflow-scroll layer.
+ if (compositor()->compositingConsultsOverlap() && !m_owningLayer->hasTransform()) {
+ bool crossesTransform;
+ RenderLayer* overflowAncestor = enclosingOverflowClipAncestor(m_owningLayer, crossesTransform);
+ // If an ancestor is transformed, we can't currently compute the correct rect to intersect with.
+ // We'd need RenderObject::convertContainerToLocalQuad(), which doesn't yet exist.
+ if (!crossesTransform) {
+ IntRect clippingBounds;
+ RenderLayer* boundsRelativeLayer;
+
+ if (overflowAncestor) {
+ RenderBox* overflowBox = toRenderBox(overflowAncestor->renderer());
+ // If scrollbars are visible, then constrain the layer to the scrollable area, so we can avoid redraws
+ // on scrolling. Otherwise just clip to the visible area (it can still be scrolled via JS, but we'll come
+ // back through this code when the scroll offset changes).
+ if (overflowBox->scrollsOverflow())
+ clippingBounds = IntRect(-overflowAncestor->scrollXOffset(), -overflowAncestor->scrollYOffset(), overflowBox->scrollWidth(), overflowBox->scrollHeight());
+ else
+ clippingBounds = clipBox(overflowBox);
+
+ boundsRelativeLayer = overflowAncestor;
+ } else {
+ RenderView* view = m_owningLayer->renderer()->view();
+ clippingBounds = view->layoutOverflowRect();
+ boundsRelativeLayer = view->layer();
+ }
+
+ int deltaX = 0;
+ int deltaY = 0;
+ m_owningLayer->convertToLayerCoords(boundsRelativeLayer, deltaX, deltaY);
+ clippingBounds.move(-deltaX, -deltaY);
+ layerBounds.intersect(clippingBounds);
+ }
+ }
+
// If the element has a transform-origin that has fixed lengths, and the renderer has zero size,
// then we need to ensure that the compositing layer has non-zero size so that we can apply
// the transform-origin via the GraphicsLayer anchorPoint (which is expressed as a fractional value).
@@ -215,8 +266,8 @@ bool RenderLayerBacking::updateGraphicsLayerConfiguration()
updateImageContents();
if (renderer()->isEmbeddedObject() && toRenderEmbeddedObject(renderer())->allowsAcceleratedCompositing()) {
- PluginWidget* pluginWidget = static_cast<PluginWidget*>(toRenderEmbeddedObject(renderer())->widget());
- m_graphicsLayer->setContentsToMedia(pluginWidget->platformLayer());
+ PluginViewBase* pluginViewBase = static_cast<PluginViewBase*>(toRenderEmbeddedObject(renderer())->widget());
+ m_graphicsLayer->setContentsToMedia(pluginViewBase->platformLayer());
}
#if ENABLE(VIDEO)
else if (renderer()->isVideo()) {
@@ -259,11 +310,11 @@ void RenderLayerBacking::updateGraphicsLayerGeometry()
// Set transform property, if it is not animating. We have to do this here because the transform
// is affected by the layer dimensions.
- if (!renderer()->animation()->isAnimatingPropertyOnRenderer(renderer(), CSSPropertyWebkitTransform))
+ if (!renderer()->animation()->isRunningAcceleratedAnimationOnRenderer(renderer(), CSSPropertyWebkitTransform))
updateLayerTransform(renderer()->style());
// Set opacity, if it is not animating.
- if (!renderer()->animation()->isAnimatingPropertyOnRenderer(renderer(), CSSPropertyOpacity))
+ if (!renderer()->animation()->isRunningAcceleratedAnimationOnRenderer(renderer(), CSSPropertyOpacity))
updateLayerOpacity(renderer()->style());
RenderStyle* style = renderer()->style();
@@ -312,7 +363,12 @@ void RenderLayerBacking::updateGraphicsLayerGeometry()
}
m_graphicsLayer->setPosition(FloatPoint() + (relativeCompositingBounds.location() - graphicsLayerParentLocation));
+
+ IntSize oldOffsetFromRenderer = m_graphicsLayer->offsetFromRenderer();
m_graphicsLayer->setOffsetFromRenderer(localCompositingBounds.location() - IntPoint());
+ // If the compositing layer offset changes, we need to repaint.
+ if (oldOffsetFromRenderer != m_graphicsLayer->offsetFromRenderer())
+ m_graphicsLayer->setNeedsDisplay();
FloatSize oldSize = m_graphicsLayer->size();
FloatSize newSize = relativeCompositingBounds.size();
@@ -961,38 +1017,11 @@ void RenderLayerBacking::paintIntoLayer(RenderLayer* rootLayer, GraphicsContext*
bool shouldPaint = (m_owningLayer->hasVisibleContent() || m_owningLayer->hasVisibleDescendant()) && m_owningLayer->isSelfPaintingLayer();
if (shouldPaint && (paintingPhase & GraphicsLayerPaintBackground)) {
- // If this is the root then we need to send in a bigger bounding box
- // because we'll be painting the background as well (see RenderBox::paintRootBoxDecorations()).
- IntRect paintBox = clipRectToApply;
-
- // FIXME: do we need this code?
- if (renderer()->node() && renderer()->node()->isDocumentNode() && renderer()->document()->isHTMLDocument()) {
- RenderBox* box = toRenderBox(renderer());
- int w = box->width();
- int h = box->height();
-
- int rw;
- int rh;
- if (FrameView* frameView = box->view()->frameView()) {
- rw = frameView->contentsWidth();
- rh = frameView->contentsHeight();
- } else {
- rw = box->view()->width();
- rh = box->view()->height();
- }
-
- int bx = tx - box->marginLeft();
- int by = ty - box->marginTop();
- int bw = max(w + box->marginLeft() + box->marginRight() + box->borderLeft() + box->borderRight(), rw);
- int bh = max(h + box->marginTop() + box->marginBottom() + box->borderTop() + box->borderBottom(), rh);
- paintBox = IntRect(bx, by, bw, bh);
- }
-
// Paint our background first, before painting any child layers.
// Establish the clip used to paint our background.
setClip(context, paintDirtyRect, damageRect);
- PaintInfo info(context, paintBox, PaintPhaseBlockBackground, false, paintingRootForRenderer, 0);
+ PaintInfo info(context, damageRect, PaintPhaseBlockBackground, false, paintingRootForRenderer, 0);
renderer()->paint(info, tx, ty);
// Our scrollbar widgets paint exactly when we tell them to, so that they work properly with
@@ -1307,6 +1336,17 @@ String RenderLayerBacking::nameForLayer() const
}
#endif
+CompositingLayerType RenderLayerBacking::compositingLayerType() const
+{
+ if (m_graphicsLayer->hasContentsLayer())
+ return MediaCompositingLayer;
+
+ if (m_graphicsLayer->drawsContent())
+ return m_graphicsLayer->usingTiledLayer() ? TiledCompositingLayer : NormalCompositingLayer;
+
+ return ContainerCompositingLayer;
+}
+
} // namespace WebCore
#endif // USE(ACCELERATED_COMPOSITING)
diff --git a/WebCore/rendering/RenderLayerBacking.h b/WebCore/rendering/RenderLayerBacking.h
index 16c39da..852fc04 100644
--- a/WebCore/rendering/RenderLayerBacking.h
+++ b/WebCore/rendering/RenderLayerBacking.h
@@ -40,6 +40,13 @@ namespace WebCore {
class KeyframeList;
class RenderLayerCompositor;
+enum CompositingLayerType {
+ NormalCompositingLayer, // non-tiled layer with backing store
+ TiledCompositingLayer, // tiled layer (always has backing store)
+ MediaCompositingLayer, // layer that contains an image, video, webGL or plugin
+ ContainerCompositingLayer // layer with no backing store
+};
+
// RenderLayerBacking controls the compositing behavior for a single RenderLayer.
// It holds the various GraphicsLayers, and makes decisions about intra-layer rendering
// optimizations.
@@ -127,6 +134,9 @@ public:
IntRect contentsBox() const;
+ // For informative purposes only.
+ CompositingLayerType compositingLayerType() const;
+
private:
void createGraphicsLayer();
void destroyGraphicsLayer();
diff --git a/WebCore/rendering/RenderLayerCompositor.cpp b/WebCore/rendering/RenderLayerCompositor.cpp
index fe0d4e8..46278a2 100644
--- a/WebCore/rendering/RenderLayerCompositor.cpp
+++ b/WebCore/rendering/RenderLayerCompositor.cpp
@@ -643,9 +643,11 @@ void RenderLayerCompositor::computeCompositingRequirements(RenderLayer* layer, O
}
}
- // If we just entered compositing mode, the root will have become composited.
- if (layer->isRootLayer() && inCompositingMode())
- willBeComposited = true;
+ // If we just entered compositing mode, the root will have become composited (as long as accelerated compositing is enabled).
+ if (layer->isRootLayer()) {
+ if (inCompositingMode() && m_hasAcceleratedCompositing)
+ willBeComposited = true;
+ }
ASSERT(willBeComposited == needsToBeComposited(layer));
@@ -1337,8 +1339,8 @@ bool RenderLayerCompositor::requiresCompositingForIFrame(RenderObject* renderer)
bool RenderLayerCompositor::requiresCompositingForAnimation(RenderObject* renderer) const
{
if (AnimationController* animController = renderer->animation()) {
- return (animController->isAnimatingPropertyOnRenderer(renderer, CSSPropertyOpacity) && inCompositingMode())
- || animController->isAnimatingPropertyOnRenderer(renderer, CSSPropertyWebkitTransform);
+ return (animController->isRunningAnimationOnRenderer(renderer, CSSPropertyOpacity) && inCompositingMode())
+ || animController->isRunningAnimationOnRenderer(renderer, CSSPropertyWebkitTransform);
}
return false;
}
diff --git a/WebCore/rendering/RenderMenuList.cpp b/WebCore/rendering/RenderMenuList.cpp
index 77fe3c2..177921c 100644
--- a/WebCore/rendering/RenderMenuList.cpp
+++ b/WebCore/rendering/RenderMenuList.cpp
@@ -26,7 +26,6 @@
#include "RenderMenuList.h"
#include "AXObjectCache.h"
-#include "AccessibilityObject.h"
#include "CSSStyleSelector.h"
#include "Frame.h"
#include "FrameView.h"
@@ -350,6 +349,11 @@ String RenderMenuList::itemText(unsigned listIndex) const
return String();
}
+String RenderMenuList::itemLabel(unsigned) const
+{
+ return String();
+}
+
String RenderMenuList::itemAccessibilityText(unsigned listIndex) const
{
// Allow the accessible name be changed if necessary.
@@ -358,7 +362,7 @@ String RenderMenuList::itemAccessibilityText(unsigned listIndex) const
if (listIndex >= listItems.size())
return String();
- return AccessibilityObject::getAttribute(listItems[listIndex], aria_labelAttr);
+ return listItems[listIndex]->getAttribute(aria_labelAttr);
}
String RenderMenuList::itemToolTip(unsigned listIndex) const
diff --git a/WebCore/rendering/RenderMenuList.h b/WebCore/rendering/RenderMenuList.h
index 9e51996..d72e1a9 100644
--- a/WebCore/rendering/RenderMenuList.h
+++ b/WebCore/rendering/RenderMenuList.h
@@ -82,6 +82,7 @@ private:
// PopupMenuClient methods
virtual String itemText(unsigned listIndex) const;
+ virtual String itemLabel(unsigned listIndex) const;
virtual String itemToolTip(unsigned listIndex) const;
virtual String itemAccessibilityText(unsigned listIndex) const;
virtual bool itemIsEnabled(unsigned listIndex) const;
diff --git a/WebCore/rendering/RenderObject.cpp b/WebCore/rendering/RenderObject.cpp
index 4ff35eb..783ed63 100644
--- a/WebCore/rendering/RenderObject.cpp
+++ b/WebCore/rendering/RenderObject.cpp
@@ -944,10 +944,10 @@ void RenderObject::drawBoxSideFromPath(GraphicsContext* graphicsContext, IntRect
whiteSpaceWidth += (patWidth / numberOfWhitespaceDashes);
}
- DashArray* lineDash = new DashArray();
- lineDash->append(patWidth);
- lineDash->append(whiteSpaceWidth);
- graphicsContext->setLineDash(*lineDash, patWidth);
+ DashArray lineDash;
+ lineDash.append(patWidth);
+ lineDash.append(whiteSpaceWidth);
+ graphicsContext->setLineDash(lineDash, patWidth);
graphicsContext->addPath(borderPath);
graphicsContext->strokePath();
return;
@@ -1357,7 +1357,8 @@ bool RenderObject::repaintAfterLayoutIfNeeded(RenderBoxModelObject* repaintConta
if (v->printing())
return false; // Don't repaint if we're printing.
- ASSERT(!newBoundsPtr || *newBoundsPtr == clippedOverflowRectForRepaint(repaintContainer));
+ // This ASSERT fails due to animations. See https://bugs.webkit.org/show_bug.cgi?id=37048
+ // ASSERT(!newBoundsPtr || *newBoundsPtr == clippedOverflowRectForRepaint(repaintContainer));
IntRect newBounds = newBoundsPtr ? *newBoundsPtr : clippedOverflowRectForRepaint(repaintContainer);
IntRect newOutlineBox;
@@ -1366,7 +1367,8 @@ bool RenderObject::repaintAfterLayoutIfNeeded(RenderBoxModelObject* repaintConta
if (!fullRepaint && style()->borderFit() == BorderFitLines)
fullRepaint = true;
if (!fullRepaint) {
- ASSERT(!newOutlineBoxRectPtr || *newOutlineBoxRectPtr == outlineBoundsForRepaint(repaintContainer));
+ // This ASSERT fails due to animations. See https://bugs.webkit.org/show_bug.cgi?id=37048
+ // ASSERT(!newOutlineBoxRectPtr || *newOutlineBoxRectPtr == outlineBoundsForRepaint(repaintContainer));
newOutlineBox = newOutlineBoxRectPtr ? *newOutlineBoxRectPtr : outlineBoundsForRepaint(repaintContainer);
if (newOutlineBox.location() != oldOutlineBox.location() || (mustRepaintBackgroundOrBorder() && (newBounds != oldBounds || newOutlineBox != oldOutlineBox)))
fullRepaint = true;
diff --git a/WebCore/rendering/RenderObjectChildList.cpp b/WebCore/rendering/RenderObjectChildList.cpp
index 6775537..68e392c 100644
--- a/WebCore/rendering/RenderObjectChildList.cpp
+++ b/WebCore/rendering/RenderObjectChildList.cpp
@@ -1,5 +1,6 @@
/*
- * Copyright (C) 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2009, 2010 Apple Inc. All rights reserved.
+ * Copyright (C) Research In Motion Limited 2010. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -44,7 +45,11 @@ void RenderObjectChildList::destroyLeftoverChildren()
while (firstChild()) {
if (firstChild()->isListMarker() || (firstChild()->style()->styleType() == FIRST_LETTER && !firstChild()->isText()))
firstChild()->remove(); // List markers are owned by their enclosing list and so don't get destroyed by this container. Similarly, first letters are destroyed by their remaining text fragment.
- else {
+ else if (firstChild()->isRunIn() && firstChild()->node()) {
+ firstChild()->node()->setRenderer(0);
+ firstChild()->node()->setNeedsStyleRecalc();
+ firstChild()->destroy();
+ } else {
// Destroy any anonymous children remaining in the render tree, as well as implicit (shadow) DOM elements like those used in the engine-based text fields.
if (firstChild()->node())
firstChild()->node()->setRenderer(0);
@@ -62,9 +67,12 @@ RenderObject* RenderObjectChildList::removeChildNode(RenderObject* owner, Render
// disappears gets repainted properly.
if (!owner->documentBeingDestroyed() && fullRemove && oldChild->m_everHadLayout) {
oldChild->setNeedsLayoutAndPrefWidthsRecalc();
- oldChild->repaint();
+ if (oldChild->isBody())
+ owner->view()->repaint();
+ else
+ oldChild->repaint();
}
-
+
// If we have a line box wrapper, delete it.
if (oldChild->isBox())
toRenderBox(oldChild)->deleteLineBoxWrapper();
diff --git a/WebCore/rendering/RenderPath.cpp b/WebCore/rendering/RenderPath.cpp
index 27d480d..dd79397 100644
--- a/WebCore/rendering/RenderPath.cpp
+++ b/WebCore/rendering/RenderPath.cpp
@@ -97,7 +97,7 @@ bool RenderPath::strokeContains(const FloatPoint& point, bool requiresStroke) co
void RenderPath::layout()
{
- LayoutRepainter repainter(*this, checkForRepaintDuringLayout() && selfNeedsLayout());
+ LayoutRepainter repainter(*this, m_everHadLayout && checkForRepaintDuringLayout());
SVGStyledTransformableElement* element = static_cast<SVGStyledTransformableElement*>(node());
bool needsPathUpdate = m_needsPathUpdate;
@@ -111,6 +111,10 @@ void RenderPath::layout()
m_needsTransformUpdate = false;
}
+ // Invalidate all resources of this client, if we changed something.
+ if (m_everHadLayout && selfNeedsLayout())
+ RenderSVGResource::invalidateAllResourcesOfRenderer(this);
+
// At this point LayoutRepainter already grabbed the old bounds,
// recalculate them now so repaintAfterLayout() uses the new bounds
if (needsPathUpdate || m_needsBoundariesUpdate) {
diff --git a/WebCore/rendering/RenderSVGContainer.cpp b/WebCore/rendering/RenderSVGContainer.cpp
index d4ca69f..ad63771 100644
--- a/WebCore/rendering/RenderSVGContainer.cpp
+++ b/WebCore/rendering/RenderSVGContainer.cpp
@@ -27,6 +27,7 @@
#include "RenderSVGContainer.h"
#include "GraphicsContext.h"
+#include "RenderSVGResource.h"
#include "RenderSVGResourceFilter.h"
#include "RenderView.h"
#include "SVGRenderSupport.h"
@@ -50,13 +51,17 @@ void RenderSVGContainer::layout()
// Allow RenderSVGViewportContainer to update its viewport.
calcViewport();
- LayoutRepainter repainter(*this, checkForRepaintDuringLayout() || selfWillPaint());
+ LayoutRepainter repainter(*this, m_everHadLayout && checkForRepaintDuringLayout());
// Allow RenderSVGTransformableContainer to update its transform.
calculateLocalTransform();
SVGRenderSupport::layoutChildren(this, selfNeedsLayout());
+ // Invalidate all resources of this client, if we changed something.
+ if (m_everHadLayout && selfNeedsLayout())
+ RenderSVGResource::invalidateAllResourcesOfRenderer(this);
+
repainter.repaintAfterLayout();
setNeedsLayout(false);
}
diff --git a/WebCore/rendering/RenderSVGImage.cpp b/WebCore/rendering/RenderSVGImage.cpp
index a4572e6..44b68b1 100644
--- a/WebCore/rendering/RenderSVGImage.cpp
+++ b/WebCore/rendering/RenderSVGImage.cpp
@@ -52,7 +52,7 @@ void RenderSVGImage::layout()
{
ASSERT(needsLayout());
- LayoutRepainter repainter(*this, checkForRepaintDuringLayout());
+ LayoutRepainter repainter(*this, m_everHadLayout && checkForRepaintDuringLayout());
SVGImageElement* image = static_cast<SVGImageElement*>(node());
if (m_needsTransformUpdate) {
@@ -66,11 +66,15 @@ void RenderSVGImage::layout()
calcWidth();
calcHeight();
+ // FIXME: Optimize caching the repaint rects.
m_localBounds = FloatRect(image->x().value(image), image->y().value(image), image->width().value(image), image->height().value(image));
m_cachedLocalRepaintRect = FloatRect();
+ // Invalidate all resources of this client, if we changed something.
+ if (m_everHadLayout && selfNeedsLayout())
+ RenderSVGResource::invalidateAllResourcesOfRenderer(this);
+
repainter.repaintAfterLayout();
-
setNeedsLayout(false);
}
diff --git a/WebCore/rendering/RenderSVGModelObject.cpp b/WebCore/rendering/RenderSVGModelObject.cpp
index 3d22e7a..49404cb 100644
--- a/WebCore/rendering/RenderSVGModelObject.cpp
+++ b/WebCore/rendering/RenderSVGModelObject.cpp
@@ -87,6 +87,14 @@ void RenderSVGModelObject::destroy()
RenderObject::destroy();
}
+void RenderSVGModelObject::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
+{
+ RenderObject::styleDidChange(diff, oldStyle);
+
+ if (style() && (diff == StyleDifferenceLayout || diff == StyleDifferenceRepaint))
+ RenderSVGResource::markForLayoutAndParentResourceInvalidation(this, false);
+}
+
bool RenderSVGModelObject::nodeAtPoint(const HitTestRequest&, HitTestResult&, int, int, int, int, HitTestAction)
{
ASSERT_NOT_REACHED();
diff --git a/WebCore/rendering/RenderSVGModelObject.h b/WebCore/rendering/RenderSVGModelObject.h
index 82c08c0..741cd61 100644
--- a/WebCore/rendering/RenderSVGModelObject.h
+++ b/WebCore/rendering/RenderSVGModelObject.h
@@ -61,6 +61,7 @@ public:
virtual void destroy();
virtual void mapLocalToContainer(RenderBoxModelObject* repaintContainer, bool useTransforms, bool fixed, TransformState&) const;
+ virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
private:
// This method should never be called, SVG uses a different nodeAtPoint method
diff --git a/WebCore/rendering/RenderSVGResource.cpp b/WebCore/rendering/RenderSVGResource.cpp
index 0aa7182..b4f499e 100644
--- a/WebCore/rendering/RenderSVGResource.cpp
+++ b/WebCore/rendering/RenderSVGResource.cpp
@@ -184,21 +184,17 @@ RenderSVGResourceSolidColor* RenderSVGResource::sharedSolidPaintingResource()
return s_sharedSolidPaintingResource;
}
-void RenderSVGResource::markForLayoutAndResourceInvalidation(RenderObject* object)
+void RenderSVGResource::markForLayoutAndResourceInvalidation(RenderObject* object, bool needsBoundariesUpdate)
{
ASSERT(object);
ASSERT(object->node());
ASSERT(object->node()->isSVGElement());
- // Mark the renderer for layout
- object->setNeedsLayout(true);
+ // Eventually mark the renderer needing a boundaries update
+ if (needsBoundariesUpdate)
+ object->setNeedsBoundariesUpdate();
- // Notify any resources in the ancestor chain, that we've been invalidated
- SVGElement* element = static_cast<SVGElement*>(object->node());
- if (!element->isStyled())
- return;
-
- static_cast<SVGStyledElement*>(element)->invalidateResourcesInAncestorChain();
+ markForLayoutAndParentResourceInvalidation(object);
}
static inline void invalidatePaintingResource(SVGPaint* paint, RenderObject* object)
@@ -254,6 +250,22 @@ void RenderSVGResource::invalidateAllResourcesOfRenderer(RenderObject* object)
invalidatePaintingResource(svgStyle->strokePaint(), object);
}
+void RenderSVGResource::markForLayoutAndParentResourceInvalidation(RenderObject* object, bool needsLayout)
+{
+ ASSERT(object);
+ if (needsLayout)
+ object->setNeedsLayout(true);
+
+ // Invalidate resources in ancestor chain, if needed.
+ RenderObject* current = object->parent();
+ while (current) {
+ if (current->isSVGResourceContainer())
+ current->toRenderSVGResourceContainer()->invalidateClients();
+
+ current = current->parent();
+ }
+}
+
}
#endif
diff --git a/WebCore/rendering/RenderSVGResource.h b/WebCore/rendering/RenderSVGResource.h
index 34ff14e..b3ea6fb 100644
--- a/WebCore/rendering/RenderSVGResource.h
+++ b/WebCore/rendering/RenderSVGResource.h
@@ -80,12 +80,13 @@ public:
static RenderSVGResourceSolidColor* sharedSolidPaintingResource();
static void invalidateAllResourcesOfRenderer(RenderObject*);
+ static void markForLayoutAndParentResourceInvalidation(RenderObject*, bool needsLayout = true);
private:
static void adjustColorForPseudoRules(const RenderStyle*, bool useFillPaint, Color&);
protected:
- void markForLayoutAndResourceInvalidation(RenderObject*);
+ void markForLayoutAndResourceInvalidation(RenderObject*, bool needsBoundariesUpdate = true);
};
}
diff --git a/WebCore/rendering/RenderSVGResourceClipper.cpp b/WebCore/rendering/RenderSVGResourceClipper.cpp
index cc499bf..e923f7e 100644
--- a/WebCore/rendering/RenderSVGResourceClipper.cpp
+++ b/WebCore/rendering/RenderSVGResourceClipper.cpp
@@ -49,6 +49,7 @@ RenderSVGResourceType RenderSVGResourceClipper::s_resourceType = ClipperResource
RenderSVGResourceClipper::RenderSVGResourceClipper(SVGClipPathElement* node)
: RenderSVGResourceContainer(node)
+ , m_invalidationBlocked(false)
{
}
@@ -60,12 +61,13 @@ RenderSVGResourceClipper::~RenderSVGResourceClipper()
void RenderSVGResourceClipper::invalidateClients()
{
+ if (m_invalidationBlocked)
+ return;
+
HashMap<RenderObject*, ClipperData*>::const_iterator end = m_clipper.end();
- for (HashMap<RenderObject*, ClipperData*>::const_iterator it = m_clipper.begin(); it != end; ++it) {
- RenderObject* renderer = it->first;
- renderer->setNeedsBoundariesUpdate();
- renderer->setNeedsLayout(true);
- }
+ for (HashMap<RenderObject*, ClipperData*>::const_iterator it = m_clipper.begin(); it != end; ++it)
+ markForLayoutAndResourceInvalidation(it->first);
+
deleteAllValues(m_clipper);
m_clipper.clear();
m_clipBoundaries = FloatRect();
@@ -73,12 +75,10 @@ void RenderSVGResourceClipper::invalidateClients()
void RenderSVGResourceClipper::invalidateClient(RenderObject* object)
{
- ASSERT(object);
+ if (m_invalidationBlocked)
+ return;
- // FIXME: The HashSet should always contain the object on calling invalidateClient. A race condition
- // during the parsing can causes a call of invalidateClient right before the call of applyResource.
- // We return earlier for the moment. This bug should be fixed in:
- // https://bugs.webkit.org/show_bug.cgi?id=35181
+ ASSERT(object);
if (!m_clipper.contains(object))
return;
@@ -95,6 +95,11 @@ bool RenderSVGResourceClipper::applyResource(RenderObject* object, RenderStyle*,
#else
UNUSED_PARAM(resourceMode);
#endif
+
+ // Early exit, if this resource contains a child which references ourselves.
+ if (containsCyclicReference(node()))
+ return false;
+
applyClippingToContext(object, object->objectBoundingBox(), object->repaintRectInLocalCoordinates(), context);
return true;
}
@@ -237,6 +242,10 @@ bool RenderSVGResourceClipper::createClipData(ClipperData* clipperData, const Fl
svgStyle->setStrokeOpacity(1.0f);
svgStyle->setFilterResource(String());
svgStyle->setMaskerResource(String());
+
+ // The setStyle() call results in a styleDidChange() call, which in turn invalidations the resources.
+ // As we're mutating the resource on purpose, block updates until we've resetted the style again.
+ m_invalidationBlocked = true;
renderer->setStyle(newRenderStyle.release());
// In the case of a <use> element, we obtained its renderere above, to retrieve its clipRule.
@@ -245,6 +254,7 @@ bool RenderSVGResourceClipper::createClipData(ClipperData* clipperData, const Fl
SVGRenderSupport::renderSubtreeToImage(clipperData->clipMaskImage.get(), isUseElement ? childNode->renderer() : renderer);
renderer->setStyle(oldRenderStyle.release());
+ m_invalidationBlocked = false;
}
maskContext->restore();
@@ -270,6 +280,12 @@ void RenderSVGResourceClipper::calculateClipContentRepaintRect()
bool RenderSVGResourceClipper::hitTestClipContent(const FloatRect& objectBoundingBox, const FloatPoint& nodeAtPoint)
{
+ // FIXME: We should be able to check whether m_clipper.contains(object) - this doesn't work at the moment
+ // as resourceBoundingBox() has already created ClipperData, even if applyResource() returned false.
+ // Early exit, if this resource contains a child which references ourselves.
+ if (containsCyclicReference(node()))
+ return false;
+
FloatPoint point = nodeAtPoint;
if (!SVGRenderSupport::pointInClippingArea(this, point))
return false;
@@ -296,12 +312,16 @@ bool RenderSVGResourceClipper::hitTestClipContent(const FloatRect& objectBoundin
return false;
}
-FloatRect RenderSVGResourceClipper::resourceBoundingBox(RenderObject* object)
+bool RenderSVGResourceClipper::childElementReferencesResource(const SVGRenderStyle* style, const String& referenceId) const
{
- // Save the reference to the calling object for relayouting it on changing resource properties.
- if (!m_clipper.contains(object))
- m_clipper.set(object, new ClipperData);
+ if (!style->hasClipper())
+ return false;
+
+ return style->clipperResource() == referenceId;
+}
+FloatRect RenderSVGResourceClipper::resourceBoundingBox(RenderObject* object)
+{
// Resource was not layouted yet. Give back the boundingBox of the object.
if (selfNeedsLayout())
return object->objectBoundingBox();
diff --git a/WebCore/rendering/RenderSVGResourceClipper.h b/WebCore/rendering/RenderSVGResourceClipper.h
index 78ec75b..7128aa1 100644
--- a/WebCore/rendering/RenderSVGResourceClipper.h
+++ b/WebCore/rendering/RenderSVGResourceClipper.h
@@ -68,6 +68,9 @@ private:
bool createClipData(ClipperData*, const FloatRect&, const FloatRect&);
void calculateClipContentRepaintRect();
+ virtual bool childElementReferencesResource(const SVGRenderStyle*, const String&) const;
+
+ bool m_invalidationBlocked;
FloatRect m_clipBoundaries;
HashMap<RenderObject*, ClipperData*> m_clipper;
};
diff --git a/WebCore/rendering/RenderSVGResourceContainer.h b/WebCore/rendering/RenderSVGResourceContainer.h
index 54617bb..5f1c828 100644
--- a/WebCore/rendering/RenderSVGResourceContainer.h
+++ b/WebCore/rendering/RenderSVGResourceContainer.h
@@ -26,6 +26,7 @@
#include "SVGStyledTransformableElement.h"
#include "RenderSVGResource.h"
+#include "RenderSVGShadowTreeRootContainer.h"
namespace WebCore {
@@ -35,8 +36,7 @@ public:
RenderSVGResourceContainer(SVGStyledElement* node)
: RenderSVGHiddenContainer(node)
, RenderSVGResource()
- // FIXME: Should probably be using getIdAttribute rather than idForStyleResolution.
- , m_id(node->hasID() ? node->idForStyleResolution() : nullAtom)
+ , m_id(node->hasID() ? node->getIdAttribute() : nullAtom)
{
ASSERT(node->document());
node->document()->accessSVGExtensions()->addResource(m_id, this);
@@ -57,9 +57,7 @@ public:
// Remove old id, that is guaranteed to be present in cache
extensions->removeResource(m_id);
-
- // FIXME: Should probably be using getIdAttribute rather than idForStyleResolution.
- m_id = node()->hasID() ? static_cast<Element*>(node())->idForStyleResolution() : nullAtom;
+ m_id = static_cast<Element*>(node())->getIdAttribute();
// It's possible that an element is referencing us with the new id, and has to be notified that we're existing now
if (extensions->isPendingResource(m_id)) {
@@ -84,7 +82,8 @@ public:
virtual bool drawsContents() { return false; }
virtual RenderSVGResourceContainer* toRenderSVGResourceContainer() { return this; }
-
+ virtual bool childElementReferencesResource(const SVGRenderStyle*, const String&) const { return false; }
+
static AffineTransform transformOnNonScalingStroke(RenderObject* object, const AffineTransform resourceTransform)
{
if (!object->isRenderPath())
@@ -96,6 +95,48 @@ public:
return transform;
}
+ bool containsCyclicReference(const Node* startNode) const
+ {
+ ASSERT(startNode->document());
+
+ for (Node* node = startNode->firstChild(); node; node = node->nextSibling()) {
+ if (!node->isSVGElement())
+ continue;
+
+ RenderObject* renderer = node->renderer();
+ if (!renderer)
+ continue;
+
+ RenderStyle* style = renderer->style();
+ if (!style)
+ continue;
+
+ const SVGRenderStyle* svgStyle = style->svgStyle();
+ ASSERT(svgStyle);
+
+ // Let the class inheriting from us decide whether the child element references ourselves.
+ if (childElementReferencesResource(svgStyle, m_id))
+ return true;
+
+ // Dive into shadow tree to check for cycles there.
+ if (node->hasTagName(SVGNames::useTag)) {
+ ASSERT(renderer->isSVGShadowTreeRootContainer());
+ if (Node* shadowRoot = static_cast<RenderSVGShadowTreeRootContainer*>(renderer)->rootElement()) {
+ if (containsCyclicReference(shadowRoot))
+ return true;
+ }
+
+ }
+
+ if (node->hasChildNodes()) {
+ if (containsCyclicReference(node))
+ return true;
+ }
+ }
+
+ return false;
+ }
+
private:
AtomicString m_id;
};
diff --git a/WebCore/rendering/RenderSVGResourceFilter.cpp b/WebCore/rendering/RenderSVGResourceFilter.cpp
index 19a6ccb..a6358f0 100644
--- a/WebCore/rendering/RenderSVGResourceFilter.cpp
+++ b/WebCore/rendering/RenderSVGResourceFilter.cpp
@@ -67,11 +67,9 @@ RenderSVGResourceFilter::~RenderSVGResourceFilter()
void RenderSVGResourceFilter::invalidateClients()
{
HashMap<RenderObject*, FilterData*>::const_iterator end = m_filter.end();
- for (HashMap<RenderObject*, FilterData*>::const_iterator it = m_filter.begin(); it != end; ++it) {
- RenderObject* renderer = it->first;
- renderer->setNeedsBoundariesUpdate();
- renderer->setNeedsLayout(true);
- }
+ for (HashMap<RenderObject*, FilterData*>::const_iterator it = m_filter.begin(); it != end; ++it)
+ markForLayoutAndResourceInvalidation(it->first);
+
deleteAllValues(m_filter);
m_filter.clear();
}
@@ -79,11 +77,6 @@ void RenderSVGResourceFilter::invalidateClients()
void RenderSVGResourceFilter::invalidateClient(RenderObject* object)
{
ASSERT(object);
-
- // FIXME: The HashMap should always contain the object on calling invalidateClient. A race condition
- // during the parsing can causes a call of invalidateClient right before the call of applyResource.
- // We return earlier for the moment. This bug should be fixed in:
- // https://bugs.webkit.org/show_bug.cgi?id=35181
if (!m_filter.contains(object))
return;
diff --git a/WebCore/rendering/RenderSVGResourceGradient.cpp b/WebCore/rendering/RenderSVGResourceGradient.cpp
index 74f5b13..ce51369 100644
--- a/WebCore/rendering/RenderSVGResourceGradient.cpp
+++ b/WebCore/rendering/RenderSVGResourceGradient.cpp
@@ -51,7 +51,7 @@ void RenderSVGResourceGradient::invalidateClients()
{
const HashMap<RenderObject*, GradientData*>::const_iterator end = m_gradient.end();
for (HashMap<RenderObject*, GradientData*>::const_iterator it = m_gradient.begin(); it != end; ++it)
- markForLayoutAndResourceInvalidation(it->first);
+ markForLayoutAndResourceInvalidation(it->first, false);
deleteAllValues(m_gradient);
m_gradient.clear();
@@ -60,16 +60,11 @@ void RenderSVGResourceGradient::invalidateClients()
void RenderSVGResourceGradient::invalidateClient(RenderObject* object)
{
ASSERT(object);
-
- // FIXME: The HashMap should always contain the object on calling invalidateClient. A race condition
- // during the parsing can causes a call of invalidateClient right before the call of applyResource.
- // We return earlier for the moment. This bug should be fixed in:
- // https://bugs.webkit.org/show_bug.cgi?id=35181
if (!m_gradient.contains(object))
return;
delete m_gradient.take(object);
- markForLayoutAndResourceInvalidation(object);
+ markForLayoutAndResourceInvalidation(object, false);
}
#if PLATFORM(CG)
@@ -133,7 +128,7 @@ static inline AffineTransform clipToTextMask(GraphicsContext* context,
matrix.translate(maskBoundingBox.x(), maskBoundingBox.y());
matrix.scaleNonUniform(maskBoundingBox.width(), maskBoundingBox.height());
}
- matrix.multiply(gradientData->transform);
+ matrix.multLeft(gradientData->transform);
return matrix;
}
#endif
@@ -179,7 +174,7 @@ bool RenderSVGResourceGradient::applyResource(RenderObject* object, RenderStyle*
gradientData->userspaceTransform.scaleNonUniform(objectBoundingBox.width(), objectBoundingBox.height());
}
- gradientData->userspaceTransform.multiply(gradientData->transform);
+ gradientData->userspaceTransform.multLeft(gradientData->transform);
gradientData->gradient->setGradientSpaceTransform(gradientData->userspaceTransform);
}
diff --git a/WebCore/rendering/RenderSVGResourceMarker.cpp b/WebCore/rendering/RenderSVGResourceMarker.cpp
index ce331a7..4f0cace 100644
--- a/WebCore/rendering/RenderSVGResourceMarker.cpp
+++ b/WebCore/rendering/RenderSVGResourceMarker.cpp
@@ -62,11 +62,8 @@ void RenderSVGResourceMarker::addClient(const RenderObject* object)
void RenderSVGResourceMarker::invalidateClients()
{
const HashSet<const RenderObject*>::const_iterator end = m_marker.end();
- for (HashSet<const RenderObject*>::const_iterator it = m_marker.begin(); it != end; ++it) {
- RenderObject* renderer = const_cast<RenderObject*>(*it);
- renderer->setNeedsBoundariesUpdate();
- renderer->setNeedsLayout(true);
- }
+ for (HashSet<const RenderObject*>::const_iterator it = m_marker.begin(); it != end; ++it)
+ markForLayoutAndResourceInvalidation(const_cast<RenderObject*>(*it));
m_marker.clear();
}
@@ -74,11 +71,6 @@ void RenderSVGResourceMarker::invalidateClients()
void RenderSVGResourceMarker::invalidateClient(RenderObject* object)
{
ASSERT(object);
-
- // FIXME: The HashSet should always contain the object on calling invalidateClient. A race condition
- // during the parsing can causes a call of invalidateClient right before the call of applyResource.
- // We return earlier for the moment. This bug should be fixed in:
- // https://bugs.webkit.org/show_bug.cgi?id=35181
if (!m_marker.contains(object))
return;
diff --git a/WebCore/rendering/RenderSVGResourceMasker.cpp b/WebCore/rendering/RenderSVGResourceMasker.cpp
index 74d3fe6..83a64b5 100644
--- a/WebCore/rendering/RenderSVGResourceMasker.cpp
+++ b/WebCore/rendering/RenderSVGResourceMasker.cpp
@@ -58,11 +58,8 @@ RenderSVGResourceMasker::~RenderSVGResourceMasker()
void RenderSVGResourceMasker::invalidateClients()
{
HashMap<RenderObject*, MaskerData*>::const_iterator end = m_masker.end();
- for (HashMap<RenderObject*, MaskerData*>::const_iterator it = m_masker.begin(); it != end; ++it) {
- RenderObject* renderer = it->first;
- renderer->setNeedsBoundariesUpdate();
- renderer->setNeedsLayout(true);
- }
+ for (HashMap<RenderObject*, MaskerData*>::const_iterator it = m_masker.begin(); it != end; ++it)
+ markForLayoutAndResourceInvalidation(it->first);
deleteAllValues(m_masker);
m_masker.clear();
@@ -72,11 +69,6 @@ void RenderSVGResourceMasker::invalidateClients()
void RenderSVGResourceMasker::invalidateClient(RenderObject* object)
{
ASSERT(object);
-
- // FIXME: The HashMap should always contain the object on calling invalidateClient. A race condition
- // during the parsing can causes a call of invalidateClient right before the call of applyResource.
- // We return earlier for the moment. This bug should be fixed in:
- // https://bugs.webkit.org/show_bug.cgi?id=35181
if (!m_masker.contains(object))
return;
@@ -84,6 +76,14 @@ void RenderSVGResourceMasker::invalidateClient(RenderObject* object)
markForLayoutAndResourceInvalidation(object);
}
+bool RenderSVGResourceMasker::childElementReferencesResource(const SVGRenderStyle* style, const String& referenceId) const
+{
+ if (!style->hasMasker())
+ return false;
+
+ return style->maskerResource() == referenceId;
+}
+
bool RenderSVGResourceMasker::applyResource(RenderObject* object, RenderStyle*, GraphicsContext*& context, unsigned short resourceMode)
{
ASSERT(object);
@@ -103,6 +103,10 @@ bool RenderSVGResourceMasker::applyResource(RenderObject* object, RenderStyle*,
if (!maskElement)
return false;
+ // Early exit, if this resource contains a child which references ourselves.
+ if (containsCyclicReference(node()))
+ return false;
+
createMaskImage(maskerData, maskElement, object);
}
@@ -178,6 +182,10 @@ void RenderSVGResourceMasker::createMaskImage(MaskerData* maskerData, const SVGM
maskImageContext->restore();
+#if !PLATFORM(CG)
+ maskerData->maskImage->transformColorSpace(DeviceRGB, LinearRGB);
+#endif
+
// create the luminance mask
RefPtr<ImageData> imageData(maskerData->maskImage->getUnmultipliedImageData(maskImageRect));
CanvasPixelArray* srcPixelArray(imageData->data());
@@ -212,10 +220,6 @@ void RenderSVGResourceMasker::calculateMaskContentRepaintRect()
FloatRect RenderSVGResourceMasker::resourceBoundingBox(RenderObject* object)
{
- // Save the reference to the calling object for relayouting it on changing resource properties.
- if (!m_masker.contains(object))
- m_masker.set(object, new MaskerData);
-
// Resource was not layouted yet. Give back clipping rect of the mask.
SVGMaskElement* maskElement = static_cast<SVGMaskElement*>(node());
FloatRect objectBoundingBox = object->objectBoundingBox();
diff --git a/WebCore/rendering/RenderSVGResourceMasker.h b/WebCore/rendering/RenderSVGResourceMasker.h
index f6301cb..56f657b 100644
--- a/WebCore/rendering/RenderSVGResourceMasker.h
+++ b/WebCore/rendering/RenderSVGResourceMasker.h
@@ -69,6 +69,8 @@ private:
void createMaskImage(MaskerData*, const SVGMaskElement*, RenderObject*);
void calculateMaskContentRepaintRect();
+ virtual bool childElementReferencesResource(const SVGRenderStyle*, const String&) const;
+
FloatRect m_maskBoundaries;
HashMap<RenderObject*, MaskerData*> m_masker;
};
diff --git a/WebCore/rendering/RenderSVGResourcePattern.cpp b/WebCore/rendering/RenderSVGResourcePattern.cpp
index ba24fcf..a2234c8 100644
--- a/WebCore/rendering/RenderSVGResourcePattern.cpp
+++ b/WebCore/rendering/RenderSVGResourcePattern.cpp
@@ -48,7 +48,7 @@ void RenderSVGResourcePattern::invalidateClients()
{
const HashMap<RenderObject*, PatternData*>::const_iterator end = m_pattern.end();
for (HashMap<RenderObject*, PatternData*>::const_iterator it = m_pattern.begin(); it != end; ++it)
- markForLayoutAndResourceInvalidation(it->first);
+ markForLayoutAndResourceInvalidation(it->first, false);
deleteAllValues(m_pattern);
m_pattern.clear();
@@ -57,16 +57,26 @@ void RenderSVGResourcePattern::invalidateClients()
void RenderSVGResourcePattern::invalidateClient(RenderObject* object)
{
ASSERT(object);
-
- // FIXME: The HashMap should always contain the object on calling invalidateClient. A race condition
- // during the parsing can causes a call of invalidateClient right before the call of applyResource.
- // We return earlier for the moment. This bug should be fixed in:
- // https://bugs.webkit.org/show_bug.cgi?id=35181
if (!m_pattern.contains(object))
return;
delete m_pattern.take(object);
- markForLayoutAndResourceInvalidation(object);
+ markForLayoutAndResourceInvalidation(object, false);
+}
+
+bool RenderSVGResourcePattern::childElementReferencesResource(const SVGRenderStyle* style, const String& referenceId) const
+{
+ if (style->hasFill()) {
+ if (style->fillPaint()->matchesTargetURI(referenceId))
+ return true;
+ }
+
+ if (style->hasStroke()) {
+ if (style->strokePaint()->matchesTargetURI(referenceId))
+ return true;
+ }
+
+ return false;
}
bool RenderSVGResourcePattern::applyResource(RenderObject* object, RenderStyle* style, GraphicsContext*& context, unsigned short resourceMode)
@@ -91,7 +101,6 @@ bool RenderSVGResourcePattern::applyResource(RenderObject* object, RenderStyle*
PatternData* patternData = m_pattern.get(object);
if (!patternData->pattern) {
-
// Create tile image
OwnPtr<ImageBuffer> tileImage = createTileImage(patternData, patternElement, object);
if (!tileImage)
@@ -235,6 +244,10 @@ PassOwnPtr<ImageBuffer> RenderSVGResourcePattern::createTileImage(PatternData* p
if (!attributes.patternContentElement())
return 0;
+ // Early exit, if this resource contains a child which references ourselves.
+ if (containsCyclicReference(attributes.patternContentElement()))
+ return 0;
+
FloatRect objectBoundingBox = object->objectBoundingBox();
FloatRect patternBoundaries = calculatePatternBoundaries(attributes, objectBoundingBox, patternElement);
AffineTransform patternTransform = attributes.patternTransform();
diff --git a/WebCore/rendering/RenderSVGResourcePattern.h b/WebCore/rendering/RenderSVGResourcePattern.h
index 690b0de..ec89777 100644
--- a/WebCore/rendering/RenderSVGResourcePattern.h
+++ b/WebCore/rendering/RenderSVGResourcePattern.h
@@ -67,6 +67,8 @@ private:
FloatRect calculatePatternBoundariesIncludingOverflow(PatternAttributes&, const FloatRect& objectBoundingBox,
const AffineTransform& viewBoxCTM, const FloatRect& patternBoundaries) const;
+ virtual bool childElementReferencesResource(const SVGRenderStyle*, const String&) const;
+
HashMap<RenderObject*, PatternData*> m_pattern;
};
diff --git a/WebCore/rendering/RenderSVGRoot.cpp b/WebCore/rendering/RenderSVGRoot.cpp
index 396df19..1659e40 100644
--- a/WebCore/rendering/RenderSVGRoot.cpp
+++ b/WebCore/rendering/RenderSVGRoot.cpp
@@ -112,7 +112,7 @@ void RenderSVGRoot::layout()
view()->disableLayoutState();
bool needsLayout = selfNeedsLayout();
- LayoutRepainter repainter(*this, checkForRepaintDuringLayout() && needsLayout);
+ LayoutRepainter repainter(*this, needsLayout && m_everHadLayout && checkForRepaintDuringLayout());
IntSize oldSize(width(), height());
calcWidth();
diff --git a/WebCore/rendering/RenderSVGShadowTreeRootContainer.cpp b/WebCore/rendering/RenderSVGShadowTreeRootContainer.cpp
index 9d3d26f..888dd57 100644
--- a/WebCore/rendering/RenderSVGShadowTreeRootContainer.cpp
+++ b/WebCore/rendering/RenderSVGShadowTreeRootContainer.cpp
@@ -96,6 +96,11 @@ void RenderSVGShadowTreeRootContainer::styleDidChange(StyleDifference diff, cons
shadowRootRenderer->setStyle(style());
}
+Node* RenderSVGShadowTreeRootContainer::rootElement() const
+{
+ return m_shadowRoot.get();
+}
+
}
#endif
diff --git a/WebCore/rendering/RenderSVGShadowTreeRootContainer.h b/WebCore/rendering/RenderSVGShadowTreeRootContainer.h
index 81ae44b..bff2a87 100644
--- a/WebCore/rendering/RenderSVGShadowTreeRootContainer.h
+++ b/WebCore/rendering/RenderSVGShadowTreeRootContainer.h
@@ -39,6 +39,8 @@ public:
void updateStyle(Node::StyleChange);
virtual void updateFromElement();
+ Node* rootElement() const;
+
private:
virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
diff --git a/WebCore/rendering/RenderSVGText.cpp b/WebCore/rendering/RenderSVGText.cpp
index 12f3cb5..58348db 100644
--- a/WebCore/rendering/RenderSVGText.cpp
+++ b/WebCore/rendering/RenderSVGText.cpp
@@ -73,7 +73,7 @@ void RenderSVGText::mapLocalToContainer(RenderBoxModelObject* repaintContainer,
void RenderSVGText::layout()
{
ASSERT(needsLayout());
- LayoutRepainter repainter(*this, checkForRepaintDuringLayout());
+ LayoutRepainter repainter(*this, m_everHadLayout && checkForRepaintDuringLayout());
if (m_needsTransformUpdate) {
SVGTextElement* text = static_cast<SVGTextElement*>(node());
@@ -98,6 +98,10 @@ void RenderSVGText::layout()
ASSERT(childrenInline());
forceLayoutInlineChildren();
+ // Invalidate all resources of this client, if we changed something.
+ if (m_everHadLayout && selfNeedsLayout())
+ RenderSVGResource::invalidateAllResourcesOfRenderer(this);
+
repainter.repaintAfterLayout();
setNeedsLayout(false);
}
diff --git a/WebCore/rendering/RenderTextControlSingleLine.cpp b/WebCore/rendering/RenderTextControlSingleLine.cpp
index b6c2916..71d5a86 100644
--- a/WebCore/rendering/RenderTextControlSingleLine.cpp
+++ b/WebCore/rendering/RenderTextControlSingleLine.cpp
@@ -69,6 +69,8 @@ RenderTextControlSingleLine::~RenderTextControlSingleLine()
if (m_innerBlock)
m_innerBlock->detach();
+ if (m_innerSpinButton)
+ m_innerSpinButton->detach();
if (m_outerSpinButton)
m_outerSpinButton->detach();
}
@@ -261,6 +263,12 @@ void RenderTextControlSingleLine::layout()
if (currentHeight < height())
childBlock->setY((height() - currentHeight) / 2);
+ // Ignores the paddings for the inner spin button.
+ if (RenderBox* spinBox = m_innerSpinButton ? m_innerSpinButton->renderBox() : 0) {
+ spinBox->setLocation(spinBox->x() + paddingRight(), borderTop());
+ spinBox->setHeight(height() - borderTop() - borderBottom());
+ }
+
// Center the spin button vertically, and move it to the right by
// padding + border of the text fields.
if (RenderBox* spinBox = m_outerSpinButton ? m_outerSpinButton->renderBox() : 0) {
@@ -292,6 +300,8 @@ bool RenderTextControlSingleLine::nodeAtPoint(const HitTestRequest& request, Hit
hitInnerTextElement(result, xPos, yPos, tx, ty);
// If we found a spin button, we're done.
+ if (m_innerSpinButton && result.innerNode() == m_innerSpinButton)
+ return true;
if (m_outerSpinButton && result.innerNode() == m_outerSpinButton)
return true;
// If we're not a search field, or we already found the speech, results or cancel buttons, we're done.
@@ -376,6 +386,8 @@ void RenderTextControlSingleLine::forwardEvent(Event* event)
m_resultsButton->defaultEventHandler(event);
else if (m_cancelButton && localPoint.x() > textRight)
m_cancelButton->defaultEventHandler(event);
+ else if (m_innerSpinButton && localPoint.x() > textRight && localPoint.x() < textRight + m_innerSpinButton->renderBox()->width())
+ m_innerSpinButton->defaultEventHandler(event);
else if (m_outerSpinButton && localPoint.x() > textRight)
m_outerSpinButton->defaultEventHandler(event);
else
@@ -469,6 +481,11 @@ int RenderTextControlSingleLine::textBlockWidth() const
width -= cancelRenderer->width() + cancelRenderer->marginLeft() + cancelRenderer->marginRight();
}
+ if (RenderBox* spinRenderer = m_innerSpinButton ? m_innerSpinButton->renderBox() : 0) {
+ spinRenderer->calcWidth();
+ width -= spinRenderer->width() + spinRenderer->marginLeft() + spinRenderer->marginRight();
+ }
+
#if ENABLE(INPUT_SPEECH)
if (RenderBox* speechRenderer = m_speechButton ? m_speechButton->renderBox() : 0) {
speechRenderer->calcWidth();
@@ -534,6 +551,9 @@ int RenderTextControlSingleLine::preferredContentWidth(float charWidth) const
result += cancelRenderer->borderLeft() + cancelRenderer->borderRight() +
cancelRenderer->paddingLeft() + cancelRenderer->paddingRight();
+ if (RenderBox* spinRenderer = m_innerSpinButton ? m_innerSpinButton->renderBox() : 0)
+ result += spinRenderer->minPrefWidth();
+
#if ENABLE(INPUT_SPEECH)
if (RenderBox* speechRenderer = m_speechButton ? m_speechButton->renderBox() : 0) {
result += speechRenderer->borderLeft() + speechRenderer->borderRight() +
@@ -598,7 +618,12 @@ void RenderTextControlSingleLine::createSubtreeIfNeeded()
#endif
if (!createSubtree) {
RenderTextControl::createSubtreeIfNeeded(m_innerBlock.get());
- if (inputElement()->hasSpinButton() && !m_outerSpinButton) {
+ bool hasSpinButton = inputElement()->hasSpinButton();
+ if (hasSpinButton && !m_innerSpinButton) {
+ m_innerSpinButton = SpinButtonElement::create(node());
+ m_innerSpinButton->attachInnerElement(node(), createInnerSpinButtonStyle(), renderArena());
+ }
+ if (hasSpinButton && !m_outerSpinButton) {
m_outerSpinButton = SpinButtonElement::create(node());
m_outerSpinButton->attachInnerElement(node(), createOuterSpinButtonStyle(), renderArena());
}
@@ -767,6 +792,16 @@ PassRefPtr<RenderStyle> RenderTextControlSingleLine::createCancelButtonStyle(con
return cancelBlockStyle.release();
}
+PassRefPtr<RenderStyle> RenderTextControlSingleLine::createInnerSpinButtonStyle() const
+{
+ ASSERT(node()->isHTMLElement());
+ RefPtr<RenderStyle> buttonStyle = getCachedPseudoStyle(INNER_SPIN_BUTTON);
+ if (!buttonStyle)
+ buttonStyle = RenderStyle::create();
+ buttonStyle->inheritFrom(style());
+ return buttonStyle.release();
+}
+
PassRefPtr<RenderStyle> RenderTextControlSingleLine::createOuterSpinButtonStyle() const
{
ASSERT(node()->isHTMLElement());
@@ -880,6 +915,11 @@ String RenderTextControlSingleLine::itemText(unsigned listIndex) const
return m_recentSearches[listIndex - 1];
}
+String RenderTextControlSingleLine::itemLabel(unsigned) const
+{
+ return String();
+}
+
bool RenderTextControlSingleLine::itemIsEnabled(unsigned listIndex) const
{
if (!listIndex || itemIsSeparator(listIndex))
diff --git a/WebCore/rendering/RenderTextControlSingleLine.h b/WebCore/rendering/RenderTextControlSingleLine.h
index ab9f711..92ecadd 100644
--- a/WebCore/rendering/RenderTextControlSingleLine.h
+++ b/WebCore/rendering/RenderTextControlSingleLine.h
@@ -98,6 +98,7 @@ private:
PassRefPtr<RenderStyle> createInnerBlockStyle(const RenderStyle* startStyle) const;
PassRefPtr<RenderStyle> createResultsButtonStyle(const RenderStyle* startStyle) const;
PassRefPtr<RenderStyle> createCancelButtonStyle(const RenderStyle* startStyle) const;
+ PassRefPtr<RenderStyle> createInnerSpinButtonStyle() const;
PassRefPtr<RenderStyle> createOuterSpinButtonStyle() const;
#if ENABLE(INPUT_SPEECH)
PassRefPtr<RenderStyle> createSpeechButtonStyle(const RenderStyle* startStyle) const;
@@ -115,6 +116,7 @@ private:
virtual void selectionChanged(unsigned, bool) {}
virtual void selectionCleared() {}
virtual String itemText(unsigned listIndex) const;
+ virtual String itemLabel(unsigned listIndex) const;
virtual String itemToolTip(unsigned) const { return String(); }
virtual String itemAccessibilityText(unsigned) const { return String(); }
virtual bool itemIsEnabled(unsigned listIndex) const;
@@ -145,6 +147,7 @@ private:
RefPtr<TextControlInnerElement> m_innerBlock;
RefPtr<SearchFieldResultsButtonElement> m_resultsButton;
RefPtr<SearchFieldCancelButtonElement> m_cancelButton;
+ RefPtr<TextControlInnerElement> m_innerSpinButton;
RefPtr<TextControlInnerElement> m_outerSpinButton;
#if ENABLE(INPUT_SPEECH)
RefPtr<InputFieldSpeechButtonElement> m_speechButton;
diff --git a/WebCore/rendering/RenderTheme.cpp b/WebCore/rendering/RenderTheme.cpp
index 2147b36..3fcb2c9 100644
--- a/WebCore/rendering/RenderTheme.cpp
+++ b/WebCore/rendering/RenderTheme.cpp
@@ -832,7 +832,7 @@ bool RenderTheme::isSpinUpButtonPartPressed(const RenderObject* o) const
|| !static_cast<Element*>(node)->isSpinButtonElement())
return false;
SpinButtonElement* element = static_cast<SpinButtonElement*>(node);
- return element->onUpButton();
+ return element->upDownState() == SpinButtonElement::Up;
}
bool RenderTheme::isReadOnlyControl(const RenderObject* o) const
@@ -845,19 +845,22 @@ bool RenderTheme::isReadOnlyControl(const RenderObject* o) const
bool RenderTheme::isHovered(const RenderObject* o) const
{
- if (!o->node())
+ Node* node = o->node();
+ if (!node)
return false;
- return o->node()->hovered();
+ if (!node->isElementNode() || !static_cast<Element*>(node)->isSpinButtonElement())
+ return node->hovered();
+ SpinButtonElement* element = static_cast<SpinButtonElement*>(node);
+ return element->hovered() && element->upDownState() != SpinButtonElement::Indeterminate;
}
bool RenderTheme::isSpinUpButtonPartHovered(const RenderObject* o) const
{
Node* node = o->node();
- if (!node || !node->active() || !node->isElementNode()
- || !static_cast<Element*>(node)->isSpinButtonElement())
+ if (!node || !node->isElementNode() || !static_cast<Element*>(node)->isSpinButtonElement())
return false;
SpinButtonElement* element = static_cast<SpinButtonElement*>(node);
- return element->onUpButton();
+ return element->upDownState() == SpinButtonElement::Up;
}
bool RenderTheme::isDefault(const RenderObject* o) const
diff --git a/WebCore/rendering/RenderThemeChromiumLinux.cpp b/WebCore/rendering/RenderThemeChromiumLinux.cpp
index c29353d..de83ae9 100644
--- a/WebCore/rendering/RenderThemeChromiumLinux.cpp
+++ b/WebCore/rendering/RenderThemeChromiumLinux.cpp
@@ -27,14 +27,13 @@
#include "CSSValueKeywords.h"
#include "Color.h"
+#include "PlatformThemeChromiumGtk.h"
#include "RenderObject.h"
+#include "ScrollbarTheme.h"
#include "UserAgentStyleSheets.h"
namespace WebCore {
-unsigned RenderThemeChromiumLinux::m_thumbInactiveColor = 0xeaeaea;
-unsigned RenderThemeChromiumLinux::m_thumbActiveColor = 0xf4f4f4;
-unsigned RenderThemeChromiumLinux::m_trackColor = 0xd3d3d3;
unsigned RenderThemeChromiumLinux::m_activeSelectionBackgroundColor =
0xff1e90ff;
unsigned RenderThemeChromiumLinux::m_activeSelectionForegroundColor =
@@ -168,12 +167,29 @@ void RenderThemeChromiumLinux::setSelectionColors(
m_inactiveSelectionForegroundColor = inactiveForegroundColor;
}
-void RenderThemeChromiumLinux::setScrollbarColors(
- SkColor inactiveColor, SkColor activeColor, SkColor trackColor)
+void RenderThemeChromiumLinux::adjustInnerSpinButtonStyle(CSSStyleSelector*, RenderStyle* style, Element*) const
{
- m_thumbInactiveColor = inactiveColor;
- m_thumbActiveColor = activeColor;
- m_trackColor = trackColor;
+ int width = ScrollbarTheme::nativeTheme()->scrollbarThickness();
+ style->setWidth(Length(width, Fixed));
+ style->setMinWidth(Length(width, Fixed));
+}
+
+bool RenderThemeChromiumLinux::paintInnerSpinButton(RenderObject* object, const PaintInfo& info, const IntRect& rect)
+{
+ ControlStates northStates = controlStatesForRenderer(object);
+ ControlStates southStates = northStates;
+ if (northStates & SpinUpState)
+ southStates &= ~(HoverState | PressedState);
+ else
+ northStates &= ~(HoverState | PressedState);
+
+ IntRect half = rect;
+ half.setHeight(rect.height() / 2);
+ PlatformThemeChromiumGtk::paintArrowButton(info.context, half, PlatformThemeChromiumGtk::North, northStates);
+
+ half.setY(rect.y() + rect.height() / 2);
+ PlatformThemeChromiumGtk::paintArrowButton(info.context, half, PlatformThemeChromiumGtk::South, southStates);
+ return false;
}
} // namespace WebCore
diff --git a/WebCore/rendering/RenderThemeChromiumLinux.h b/WebCore/rendering/RenderThemeChromiumLinux.h
index c60dec3..9eeca97 100644
--- a/WebCore/rendering/RenderThemeChromiumLinux.h
+++ b/WebCore/rendering/RenderThemeChromiumLinux.h
@@ -59,18 +59,14 @@ namespace WebCore {
static void setCaretBlinkInterval(double interval);
virtual double caretBlinkIntervalInternal() const;
+ virtual void adjustInnerSpinButtonStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+ virtual bool paintInnerSpinButton(RenderObject*, const PaintInfo&, const IntRect&);
+
static void setSelectionColors(unsigned activeBackgroundColor,
unsigned activeForegroundColor,
unsigned inactiveBackgroundColor,
unsigned inactiveForegroundColor);
- static void setScrollbarColors(unsigned inactive_color,
- unsigned active_color,
- unsigned track_color);
- static unsigned thumbInactiveColor() { return m_thumbInactiveColor; }
- static unsigned thumbActiveColor() { return m_thumbActiveColor; }
- static unsigned trackColor() { return m_trackColor; }
-
private:
RenderThemeChromiumLinux();
virtual ~RenderThemeChromiumLinux();
@@ -84,10 +80,6 @@ namespace WebCore {
static unsigned m_activeSelectionForegroundColor;
static unsigned m_inactiveSelectionBackgroundColor;
static unsigned m_inactiveSelectionForegroundColor;
-
- static unsigned m_thumbInactiveColor;
- static unsigned m_thumbActiveColor;
- static unsigned m_trackColor;
};
} // namespace WebCore
diff --git a/WebCore/rendering/RenderThemeChromiumWin.cpp b/WebCore/rendering/RenderThemeChromiumWin.cpp
index 1172f96..3023798 100644
--- a/WebCore/rendering/RenderThemeChromiumWin.cpp
+++ b/WebCore/rendering/RenderThemeChromiumWin.cpp
@@ -29,8 +29,8 @@
#include <uxtheme.h>
#include <vssym32.h>
-#include "ChromiumBridge.h"
#include "CSSValueKeywords.h"
+#include "ChromiumBridge.h"
#include "CurrentTime.h"
#include "FontSelector.h"
#include "FontUtilsChromiumWin.h"
@@ -57,53 +57,71 @@
namespace WebCore {
namespace {
-class ThemePainter : public TransparencyWin {
+class ThemePainter {
public:
ThemePainter(GraphicsContext* context, const IntRect& r)
{
- TransformMode transformMode = getTransformMode(context->getCTM());
- init(context, getLayerMode(context, transformMode), transformMode, r);
+ TransparencyWin::TransformMode transformMode = getTransformMode(context->getCTM());
+ m_helper.init(context, getLayerMode(context, transformMode), transformMode, r);
+
+ if (!m_helper.context()) {
+ // TransparencyWin doesn't have well-defined copy-ctor nor op=()
+ // so we re-initialize it instead of assigning a fresh istance.
+ // On the reinitialization, we fallback to use NoLayer mode.
+ // Note that the original initialization failure can be caused by
+ // a failure of an internal buffer allocation and NoLayer mode
+ // does not have such buffer allocations.
+ m_helper.~TransparencyWin();
+ new (&m_helper) TransparencyWin();
+ m_helper.init(context, TransparencyWin::NoLayer, transformMode, r);
+ }
}
~ThemePainter()
{
- composite();
+ m_helper.composite();
}
+ GraphicsContext* context() { return m_helper.context(); }
+ const IntRect& drawRect() { return m_helper.drawRect(); }
+
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.
+ 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)
+ static TransparencyWin::LayerMode getLayerMode(GraphicsContext* context, TransparencyWin::TransformMode transformMode)
{
- if (context->platformContext()->isDrawingToImageBuffer()) // Might have transparent background.
- return WhiteLayer;
- else if (canvasHasMultipleLayers(context->platformContext()->canvas())) // Needs antialiasing help.
- return OpaqueCompositeLayer;
- else // Nothing interesting.
- return transformMode == KeepTransform ? NoLayer : OpaqueCompositeLayer;
+ if (context->platformContext()->isDrawingToImageBuffer()) // Might have transparent background.
+ return TransparencyWin::WhiteLayer;
+ if (canvasHasMultipleLayers(context->platformContext()->canvas())) // Needs antialiasing help.
+ return TransparencyWin::OpaqueCompositeLayer;
+ // Nothing interesting.
+ return transformMode == TransparencyWin::KeepTransform ? TransparencyWin::NoLayer : TransparencyWin::OpaqueCompositeLayer;
}
- static TransformMode getTransformMode(const AffineTransform& matrix)
+ static TransparencyWin::TransformMode getTransformMode(const AffineTransform& matrix)
{
- if (matrix.b() != 0 || matrix.c() != 0) // Skew.
- return Untransform;
- else if (matrix.a() != 1.0 || matrix.d() != 1.0) // Scale.
- return ScaleTransform;
- else // Nothing interesting.
- return KeepTransform;
+ if (matrix.b() || matrix.c()) // Skew.
+ return TransparencyWin::Untransform;
+ if (matrix.a() != 1.0 || matrix.d() != 1.0) // Scale.
+ return TransparencyWin::ScaleTransform;
+ // Nothing interesting.
+ return TransparencyWin::KeepTransform;
}
+
+ TransparencyWin m_helper;
};
-} // namespace
+} // namespace
static void getNonClientMetrics(NONCLIENTMETRICS* metrics)
{
- static UINT size = WebCore::isVistaOrNewer() ?
+ static UINT size = isVistaOrNewer() ?
sizeof(NONCLIENTMETRICS) : NONCLIENTMETRICS_SIZE_PRE_VISTA;
metrics->cbSize = size;
bool success = !!SystemParametersInfo(SPI_GETNONCLIENTMETRICS, size, metrics, 0);
@@ -139,7 +157,7 @@ static float systemFontSize(const LOGFONT& font)
if (size < 0) {
HFONT hFont = CreateFontIndirect(&font);
if (hFont) {
- HDC hdc = GetDC(0); // What about printing? Is this the right DC?
+ HDC hdc = GetDC(0); // What about printing? Is this the right DC?
if (hdc) {
HGDIOBJ hObject = SelectObject(hdc, hFont);
TEXTMETRIC tm;
@@ -170,8 +188,8 @@ static float pointsToPixels(float points)
{
static float pixelsPerInch = 0.0f;
if (!pixelsPerInch) {
- HDC hdc = GetDC(0); // What about printing? Is this the right DC?
- if (hdc) { // Can this ever actually be NULL?
+ HDC hdc = GetDC(0); // What about printing? Is this the right DC?
+ if (hdc) { // Can this ever actually be NULL?
pixelsPerInch = GetDeviceCaps(hdc, LOGPIXELSY);
ReleaseDC(0, hdc);
} else {
@@ -186,7 +204,7 @@ static float pointsToPixels(float points)
static double querySystemBlinkInterval(double defaultInterval)
{
UINT blinkTime = GetCaretBlinkTime();
- if (blinkTime == 0)
+ if (!blinkTime)
return defaultInterval;
if (blinkTime == INFINITE)
return 0;
@@ -216,7 +234,7 @@ bool RenderThemeChromiumWin::supportsFocusRing(const RenderStyle* style) const
Color RenderThemeChromiumWin::platformActiveSelectionBackgroundColor() const
{
if (ChromiumBridge::layoutTestMode())
- return Color(0x00, 0x00, 0xff); // Royal blue.
+ return Color(0x00, 0x00, 0xff); // Royal blue.
COLORREF color = GetSysColor(COLOR_HIGHLIGHT);
return Color(GetRValue(color), GetGValue(color), GetBValue(color), 0xff);
}
@@ -224,7 +242,7 @@ Color RenderThemeChromiumWin::platformActiveSelectionBackgroundColor() const
Color RenderThemeChromiumWin::platformInactiveSelectionBackgroundColor() const
{
if (ChromiumBridge::layoutTestMode())
- return Color(0x99, 0x99, 0x99); // Medium gray.
+ return Color(0x99, 0x99, 0x99); // Medium gray.
COLORREF color = GetSysColor(COLOR_GRAYTEXT);
return Color(GetRValue(color), GetGValue(color), GetBValue(color), 0xff);
}
@@ -232,7 +250,7 @@ Color RenderThemeChromiumWin::platformInactiveSelectionBackgroundColor() const
Color RenderThemeChromiumWin::platformActiveSelectionForegroundColor() const
{
if (ChromiumBridge::layoutTestMode())
- return Color(0xff, 0xff, 0xcc); // Pale yellow.
+ return Color(0xff, 0xff, 0xcc); // Pale yellow.
COLORREF color = GetSysColor(COLOR_HIGHLIGHTTEXT);
return Color(GetRValue(color), GetGValue(color), GetBValue(color), 0xff);
}
@@ -244,7 +262,7 @@ Color RenderThemeChromiumWin::platformInactiveSelectionForegroundColor() const
Color RenderThemeChromiumWin::platformActiveTextSearchHighlightColor() const
{
- return Color(0xff, 0x96, 0x32); // Orange.
+ return Color(0xff, 0x96, 0x32); // Orange.
}
Color RenderThemeChromiumWin::platformInactiveTextSearchHighlightColor() const
@@ -387,7 +405,7 @@ bool RenderThemeChromiumWin::paintButton(RenderObject* o, const PaintInfo& i, co
{
const ThemeData& themeData = getThemeData(o);
- WebCore::ThemePainter painter(i.context, r);
+ ThemePainter painter(i.context, r);
ChromiumBridge::paintButton(painter.context(),
themeData.m_part,
themeData.m_state,
@@ -405,7 +423,7 @@ bool RenderThemeChromiumWin::paintSliderTrack(RenderObject* o, const PaintInfo&
{
const ThemeData& themeData = getThemeData(o);
- WebCore::ThemePainter painter(i.context, r);
+ ThemePainter painter(i.context, r);
ChromiumBridge::paintTrackbar(painter.context(),
themeData.m_part,
themeData.m_state,
@@ -436,7 +454,7 @@ bool RenderThemeChromiumWin::paintMenuList(RenderObject* o, const PaintInfo& i,
// draw individual borders and then pass that to skia so we can avoid
// drawing any borders that are set to 0. For non-zero borders, we draw the
// border, but webkit just draws over it.
- bool drawEdges = !(borderRight == 0 && borderLeft == 0 && borderTop == 0 && borderBottom == 0);
+ bool drawEdges = !(!borderRight && !borderLeft && !borderTop && !borderBottom);
paintTextFieldInternal(o, i, r, drawEdges);
@@ -462,7 +480,7 @@ bool RenderThemeChromiumWin::paintMenuList(RenderObject* o, const PaintInfo& i,
r.height() - (spacingTop + spacingBottom));
// Get the correct theme data for a textfield and paint the menu.
- WebCore::ThemePainter painter(i.context, rect);
+ ThemePainter painter(i.context, rect);
ChromiumBridge::paintMenuList(painter.context(),
CP_DROPDOWNBUTTON,
determineState(o),
@@ -487,19 +505,20 @@ double RenderThemeChromiumWin::caretBlinkIntervalInternal() const
return blinkInterval;
}
-unsigned RenderThemeChromiumWin::determineState(RenderObject* o)
+unsigned RenderThemeChromiumWin::determineState(RenderObject* o, ControlSubPart subPart)
{
unsigned result = TS_NORMAL;
ControlPart appearance = o->style()->appearance();
if (!isEnabled(o))
result = TS_DISABLED;
- else if (isReadOnlyControl(o) && (TextFieldPart == appearance || TextAreaPart == appearance || SearchFieldPart == appearance))
- result = ETS_READONLY; // Readonly is supported on textfields.
- else if (isPressed(o)) // Active overrides hover and focused.
+ else if (isReadOnlyControl(o))
+ result = (appearance == TextFieldPart || appearance == TextAreaPart || appearance == SearchFieldPart) ? ETS_READONLY : TS_DISABLED;
+ // Active overrides hover and focused.
+ else if (isPressed(o) && (subPart == SpinButtonUp) == isSpinUpButtonPartPressed(o))
result = TS_PRESSED;
else if (supportsFocus(appearance) && isFocused(o))
result = ETS_FOCUSED;
- else if (isHovered(o))
+ else if (isHovered(o) && (subPart == SpinButtonUp) == isSpinUpButtonPartHovered(o))
result = TS_HOT;
// CBS_UNCHECKED*: 1-4
@@ -526,7 +545,7 @@ unsigned RenderThemeChromiumWin::determineSliderThumbState(RenderObject* o)
return result;
}
-unsigned RenderThemeChromiumWin::determineClassicState(RenderObject* o)
+unsigned RenderThemeChromiumWin::determineClassicState(RenderObject* o, ControlSubPart subPart)
{
unsigned result = 0;
@@ -548,13 +567,14 @@ unsigned RenderThemeChromiumWin::determineClassicState(RenderObject* o)
else if (isHovered(o))
result = DFCS_HOT;
} else {
- if (!isEnabled(o))
+ if (!isEnabled(o) || isReadOnlyControl(o))
result = DFCS_INACTIVE;
- else if (isPressed(o)) // Active supersedes hover
+ // Active supersedes hover
+ else if (isPressed(o) && (subPart == SpinButtonUp) == isSpinUpButtonPartPressed(o))
result = DFCS_PUSHED;
else if (supportsFocus(part) && isFocused(o)) // So does focused
result = 0;
- else if (isHovered(o))
+ else if (isHovered(o) && (subPart == SpinButtonUp) == isSpinUpButtonPartHovered(o))
result = DFCS_HOT;
// Classic theme can't represent indeterminate states. Use unchecked appearance.
if (isChecked(o) && !isIndeterminate(o))
@@ -563,7 +583,7 @@ unsigned RenderThemeChromiumWin::determineClassicState(RenderObject* o)
return result;
}
-ThemeData RenderThemeChromiumWin::getThemeData(RenderObject* o)
+ThemeData RenderThemeChromiumWin::getThemeData(RenderObject* o, ControlSubPart subPart)
{
ThemeData result;
switch (o->style()->appearance()) {
@@ -608,9 +628,14 @@ ThemeData RenderThemeChromiumWin::getThemeData(RenderObject* o)
result.m_part = EP_EDITTEXT;
result.m_state = determineState(o);
break;
+ case InnerSpinButtonPart:
+ result.m_part = subPart == SpinButtonUp ? SPNP_UP : SPNP_DOWN;
+ result.m_state = determineState(o, subPart);
+ result.m_classicState = subPart == SpinButtonUp ? DFCS_SCROLLUP : DFCS_SCROLLDOWN;
+ break;
}
- result.m_classicState |= determineClassicState(o);
+ result.m_classicState |= determineClassicState(o, subPart);
return result;
}
@@ -646,7 +671,7 @@ bool RenderThemeChromiumWin::paintTextFieldInternal(RenderObject* o,
}
{
const ThemeData& themeData = getThemeData(o);
- WebCore::ThemePainter painter(i.context, r);
+ ThemePainter painter(i.context, r);
ChromiumBridge::paintTextField(painter.context(),
themeData.m_part,
themeData.m_state,
@@ -662,6 +687,37 @@ bool RenderThemeChromiumWin::paintTextFieldInternal(RenderObject* o,
return false;
}
+void RenderThemeChromiumWin::adjustInnerSpinButtonStyle(CSSStyleSelector*, RenderStyle* style, Element*) const
+{
+ int width = ScrollbarTheme::nativeTheme()->scrollbarThickness();
+ style->setWidth(Length(width, Fixed));
+ style->setMinWidth(Length(width, Fixed));
+}
+
+bool RenderThemeChromiumWin::paintInnerSpinButton(RenderObject* object, const PaintInfo& info, const IntRect& rect)
+{
+ IntRect half = rect;
+
+ half.setHeight(rect.height() / 2);
+ const ThemeData& upThemeData = getThemeData(object, SpinButtonUp);
+ ThemePainter upPainter(info.context, half);
+ ChromiumBridge::paintSpinButton(upPainter.context(),
+ upThemeData.m_part,
+ upThemeData.m_state,
+ upThemeData.m_classicState,
+ upPainter.drawRect());
+
+ half.setY(rect.y() + rect.height() / 2);
+ const ThemeData& downThemeData = getThemeData(object, SpinButtonDown);
+ ThemePainter downPainter(info.context, half);
+ ChromiumBridge::paintSpinButton(downPainter.context(),
+ downThemeData.m_part,
+ downThemeData.m_state,
+ downThemeData.m_classicState,
+ downPainter.drawRect());
+ return false;
+}
+
#if ENABLE(PROGRESS_TAG)
// MSDN says that update intervals for the bar is 30ms.
diff --git a/WebCore/rendering/RenderThemeChromiumWin.h b/WebCore/rendering/RenderThemeChromiumWin.h
index c6c95e6..661b623 100644
--- a/WebCore/rendering/RenderThemeChromiumWin.h
+++ b/WebCore/rendering/RenderThemeChromiumWin.h
@@ -86,6 +86,8 @@ namespace WebCore {
// See comment in RenderThemeChromiumSkia::setDefaultFontSize() regarding ugliness of this hack.
static void setDefaultFontSize(int);
+ virtual void adjustInnerSpinButtonStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+ virtual bool paintInnerSpinButton(RenderObject*, const PaintInfo&, const IntRect&);
#if ENABLE(PROGRESS_TAG)
virtual double animationRepeatIntervalForProgressBar(RenderProgress*) const;
@@ -98,14 +100,20 @@ namespace WebCore {
virtual double caretBlinkIntervalInternal() const;
private:
+ enum ControlSubPart {
+ None,
+ SpinButtonDown,
+ SpinButtonUp,
+ };
+
RenderThemeChromiumWin() { }
virtual ~RenderThemeChromiumWin() { }
- unsigned determineState(RenderObject*);
+ unsigned determineState(RenderObject*, ControlSubPart = None);
unsigned determineSliderThumbState(RenderObject*);
- unsigned determineClassicState(RenderObject*);
+ unsigned determineClassicState(RenderObject*, ControlSubPart = None);
- ThemeData getThemeData(RenderObject*);
+ ThemeData getThemeData(RenderObject*, ControlSubPart = None);
bool paintTextFieldInternal(RenderObject*, const PaintInfo&, const IntRect&, bool);
};
diff --git a/WebCore/rendering/RenderThemeMac.mm b/WebCore/rendering/RenderThemeMac.mm
index bbf6906..cc2ff1f 100644
--- a/WebCore/rendering/RenderThemeMac.mm
+++ b/WebCore/rendering/RenderThemeMac.mm
@@ -826,6 +826,8 @@ bool RenderThemeMac::paintMeter(RenderObject* renderObject, const PaintInfo& pai
if (!renderObject->isMeter())
return true;
+ LocalCurrentGraphicsContext localContext(paintInfo.context);
+
// Becaue NSLevelIndicatorCell doesn't support vertical gauge, we use a portable version
if (rect.width() < rect.height())
return RenderTheme::paintMeter(renderObject, paintInfo, rect);
@@ -1379,8 +1381,8 @@ bool RenderThemeMac::paintSliderThumb(RenderObject* o, const PaintInfo& paintInf
bool RenderThemeMac::paintSearchField(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
{
- NSSearchFieldCell* search = this->search();
LocalCurrentGraphicsContext localContext(paintInfo.context);
+ NSSearchFieldCell* search = this->search();
setSearchCellState(o, r);
@@ -1480,6 +1482,7 @@ bool RenderThemeMac::paintSearchFieldCancelButton(RenderObject* o, const PaintIn
if (!input->renderer()->isBox())
return false;
+ LocalCurrentGraphicsContext localContext(paintInfo.context);
setSearchCellState(input->renderer(), r);
NSSearchFieldCell* search = this->search();
@@ -1562,12 +1565,13 @@ void RenderThemeMac::adjustSearchFieldResultsDecorationStyle(CSSStyleSelector*,
style->setBoxShadow(0);
}
-bool RenderThemeMac::paintSearchFieldResultsDecoration(RenderObject* o, const PaintInfo&, const IntRect& r)
+bool RenderThemeMac::paintSearchFieldResultsDecoration(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
{
Node* input = o->node()->shadowAncestorNode();
if (!input->renderer()->isBox())
return false;
+ LocalCurrentGraphicsContext localContext(paintInfo.context);
setSearchCellState(input->renderer(), r);
NSSearchFieldCell* search = this->search();
@@ -1600,6 +1604,7 @@ bool RenderThemeMac::paintSearchFieldResultsButton(RenderObject* o, const PaintI
if (!input->renderer()->isBox())
return false;
+ LocalCurrentGraphicsContext localContext(paintInfo.context);
setSearchCellState(input->renderer(), r);
NSSearchFieldCell* search = this->search();
diff --git a/WebCore/rendering/RenderTreeAsText.cpp b/WebCore/rendering/RenderTreeAsText.cpp
index 26f40ab..408015c 100644
--- a/WebCore/rendering/RenderTreeAsText.cpp
+++ b/WebCore/rendering/RenderTreeAsText.cpp
@@ -234,9 +234,9 @@ void RenderTreeAsText::writeRenderObject(TextStream& ts, const RenderObject& o,
ts << " " << r;
if (!(o.isText() && !o.isBR())) {
- if (o.isFileUploadControl()) {
+ if (o.isFileUploadControl())
ts << " " << quoteAndEscapeNonPrintables(toRenderFileUploadControl(&o)->fileTextValue());
- }
+
if (o.parent() && (o.parent()->style()->color() != o.style()->color()))
ts << " [color=" << o.style()->color().name() << "]";
@@ -355,6 +355,24 @@ void RenderTreeAsText::writeRenderObject(TextStream& ts, const RenderObject& o,
ts << ": " << text;
}
}
+
+ if (behavior & RenderAsTextShowIDAndClass) {
+ if (Node* node = o.node()) {
+ if (node->hasID())
+ ts << " id=\"" + static_cast<Element*>(node)->getIdAttribute() + "\"";
+
+ if (node->hasClass()) {
+ StyledElement* styledElement = static_cast<StyledElement*>(node);
+ String classes;
+ for (size_t i = 0; i < styledElement->classNames().size(); ++i) {
+ if (i > 0)
+ classes += " ";
+ classes += styledElement->classNames()[i];
+ }
+ ts << " class=\"" + classes + "\"";
+ }
+ }
+ }
#if PLATFORM(QT)
// Print attributes of embedded QWidgets. E.g. when the WebCore::Widget
@@ -580,6 +598,7 @@ static String nodePosition(Node* node)
{
String result;
+ Element* body = node->document()->body();
Node* parent;
for (Node* n = node; n; n = parent) {
parent = n->parentNode();
@@ -587,9 +606,14 @@ static String nodePosition(Node* node)
parent = n->shadowParentNode();
if (n != node)
result += " of ";
- if (parent)
+ if (parent) {
+ if (body && n == body) {
+ // We don't care what offset body may be in the document.
+ result += "body";
+ break;
+ }
result += "child " + String::number(n->nodeIndex()) + " {" + getTagName(n) + "}";
- else
+ } else
result += "document";
}
diff --git a/WebCore/rendering/RenderTreeAsText.h b/WebCore/rendering/RenderTreeAsText.h
index 1635e79..645ccc0 100644
--- a/WebCore/rendering/RenderTreeAsText.h
+++ b/WebCore/rendering/RenderTreeAsText.h
@@ -40,7 +40,8 @@ enum RenderAsTextBehaviorFlags {
RenderAsTextShowLayerNesting = 1 << 1, // Annotate the layer lists.
RenderAsTextShowCompositedLayers = 1 << 2, // Show which layers are composited.
RenderAsTextShowAddresses = 1 << 3, // Show layer and renderer addresses.
- RenderAsTextPrintingMode = 1 << 4 // Dump the tree in printing mode.
+ RenderAsTextShowIDAndClass = 1 << 4, // Show id and class attributes
+ RenderAsTextPrintingMode = 1 << 5 // Dump the tree in printing mode.
};
typedef unsigned RenderAsTextBehavior;
diff --git a/WebCore/rendering/RenderView.cpp b/WebCore/rendering/RenderView.cpp
index 232dd5d..449c15c 100644
--- a/WebCore/rendering/RenderView.cpp
+++ b/WebCore/rendering/RenderView.cpp
@@ -456,13 +456,15 @@ void RenderView::setSelection(RenderObject* start, int startPos, RenderObject* e
if ((os->canBeSelectionLeaf() || os == m_selectionStart || os == m_selectionEnd) && os->selectionState() != SelectionNone) {
// Blocks are responsible for painting line gaps and margin gaps. They must be examined as well.
oldSelectedObjects.set(os, new RenderSelectionInfo(os, true));
- RenderBlock* cb = os->containingBlock();
- while (cb && !cb->isRenderView()) {
- RenderBlockSelectionInfo* blockInfo = oldSelectedBlocks.get(cb);
- if (blockInfo)
- break;
- oldSelectedBlocks.set(cb, new RenderBlockSelectionInfo(cb));
- cb = cb->containingBlock();
+ if (blockRepaintMode == RepaintNewXOROld) {
+ RenderBlock* cb = os->containingBlock();
+ while (cb && !cb->isRenderView()) {
+ RenderBlockSelectionInfo* blockInfo = oldSelectedBlocks.get(cb);
+ if (blockInfo)
+ break;
+ oldSelectedBlocks.set(cb, new RenderBlockSelectionInfo(cb));
+ cb = cb->containingBlock();
+ }
}
}
@@ -565,8 +567,7 @@ void RenderView::setSelection(RenderObject* start, int startPos, RenderObject* e
RenderBlockSelectionInfo* newInfo = newSelectedBlocks.get(block);
RenderBlockSelectionInfo* oldInfo = i->second;
if (!newInfo || oldInfo->rects() != newInfo->rects() || oldInfo->state() != newInfo->state()) {
- if (blockRepaintMode == RepaintNewXOROld)
- oldInfo->repaint();
+ oldInfo->repaint();
if (newInfo) {
newInfo->repaint();
newSelectedBlocks.remove(block);
diff --git a/WebCore/rendering/TextControlInnerElements.cpp b/WebCore/rendering/TextControlInnerElements.cpp
index 36e30af..24e1d74 100644
--- a/WebCore/rendering/TextControlInnerElements.cpp
+++ b/WebCore/rendering/TextControlInnerElements.cpp
@@ -36,8 +36,10 @@
#include "HTMLNames.h"
#include "HTMLTextAreaElement.h"
#include "MouseEvent.h"
+#include "Page.h"
#include "RenderLayer.h"
#include "RenderTextControlSingleLine.h"
+#include "SpeechInput.h"
namespace WebCore {
@@ -246,7 +248,7 @@ void SearchFieldCancelButtonElement::defaultEventHandler(Event* event)
inline SpinButtonElement::SpinButtonElement(Node* shadowParent)
: TextControlInnerElement(shadowParent->document(), shadowParent)
, m_capturing(false)
- , m_onUpButton(false)
+ , m_upDownState(Indeterminate)
{
}
@@ -278,12 +280,19 @@ void SpinButtonElement::defaultEventHandler(Event* event)
}
HTMLInputElement* input = static_cast<HTMLInputElement*>(shadowAncestorNode());
+ if (input->disabled() || input->isReadOnlyFormControl()) {
+ if (!event->defaultHandled())
+ HTMLDivElement::defaultEventHandler(event);
+ return;
+ }
+
IntPoint local = roundedIntPoint(box->absoluteToLocal(mouseEvent->absoluteLocation(), false, true));
if (event->type() == eventNames().clickEvent) {
if (box->borderBoxRect().contains(local)) {
+ RefPtr<Node> protector(input);
input->focus();
input->select();
- if (local.y() < box->y() + box->height() / 2)
+ if (local.y() < box->height() / 2)
input->stepUpFromRenderer(1);
else
input->stepUpFromRenderer(-1);
@@ -297,9 +306,9 @@ void SpinButtonElement::defaultEventHandler(Event* event)
m_capturing = true;
}
}
- bool oldOnUpButton = m_onUpButton;
- m_onUpButton = local.y() < box->y() + box->height() / 2;
- if (m_onUpButton != oldOnUpButton)
+ UpDownState oldUpDownState = m_upDownState;
+ m_upDownState = local.y() < box->height() / 2 ? Up : Down;
+ if (m_upDownState != oldUpDownState)
renderer()->repaint();
} else {
if (m_capturing) {
@@ -315,12 +324,21 @@ void SpinButtonElement::defaultEventHandler(Event* event)
HTMLDivElement::defaultEventHandler(event);
}
+void SpinButtonElement::setHovered(bool flag)
+{
+ if (!hovered() && flag)
+ m_upDownState = Indeterminate;
+ TextControlInnerElement::setHovered(flag);
+}
+
+
// ----------------------------
#if ENABLE(INPUT_SPEECH)
inline InputFieldSpeechButtonElement::InputFieldSpeechButtonElement(Document* document)
: TextControlInnerElement(document)
+ , m_capturing(false)
{
}
@@ -331,8 +349,73 @@ PassRefPtr<InputFieldSpeechButtonElement> InputFieldSpeechButtonElement::create(
void InputFieldSpeechButtonElement::defaultEventHandler(Event* event)
{
- // FIXME: Start speech recognition here.
- HTMLDivElement::defaultEventHandler(event);
+ // On mouse down, select the text and set focus.
+ HTMLInputElement* input = static_cast<HTMLInputElement*>(shadowAncestorNode());
+ if (event->type() == eventNames().mousedownEvent && event->isMouseEvent() && static_cast<MouseEvent*>(event)->button() == LeftButton) {
+ if (renderer() && renderer()->visibleToHitTesting()) {
+ if (Frame* frame = document()->frame()) {
+ frame->eventHandler()->setCapturingMouseEventsNode(this);
+ m_capturing = true;
+ }
+ }
+ // The call to focus() below dispatches a focus event, and an event handler in the page might
+ // remove the input element from DOM. To make sure it remains valid until we finish our work
+ // here, we take a temporary reference.
+ RefPtr<HTMLInputElement> holdRef(input);
+ input->focus();
+ input->select();
+ event->setDefaultHandled();
+ }
+ // On mouse up, start speech recognition.
+ if (event->type() == eventNames().mouseupEvent && event->isMouseEvent() && static_cast<MouseEvent*>(event)->button() == LeftButton) {
+ if (m_capturing && renderer() && renderer()->visibleToHitTesting()) {
+ if (Frame* frame = document()->frame()) {
+ frame->eventHandler()->setCapturingMouseEventsNode(0);
+ m_capturing = false;
+ }
+ if (hovered()) {
+ speechInput()->startRecognition();
+ event->setDefaultHandled();
+ }
+ }
+ }
+
+ if (!event->defaultHandled())
+ HTMLDivElement::defaultEventHandler(event);
+}
+
+SpeechInput* InputFieldSpeechButtonElement::speechInput()
+{
+ if (!m_speechInput)
+ m_speechInput.set(new SpeechInput(document()->page()->speechInputClient(), this));
+ return m_speechInput.get();
+}
+
+void InputFieldSpeechButtonElement::recordingComplete()
+{
+ // FIXME: Add UI feedback here to indicate that audio recording stopped and recognition is
+ // in progress.
+}
+
+void InputFieldSpeechButtonElement::setRecognitionResult(const String& result)
+{
+ HTMLInputElement* input = static_cast<HTMLInputElement*>(shadowAncestorNode());
+ // The call to setValue() below dispatches an event, and an event handler in the page might
+ // remove the input element from DOM. To make sure it remains valid until we finish our work
+ // here, we take a temporary reference.
+ RefPtr<HTMLInputElement> holdRef(input);
+ input->setValue(result);
+ input->dispatchFormControlChangeEvent();
+ renderer()->repaint();
+}
+
+void InputFieldSpeechButtonElement::detach()
+{
+ if (m_capturing) {
+ if (Frame* frame = document()->frame())
+ frame->eventHandler()->setCapturingMouseEventsNode(0);
+ }
+ TextControlInnerElement::detach();
}
#endif // ENABLE(INPUT_SPEECH)
diff --git a/WebCore/rendering/TextControlInnerElements.h b/WebCore/rendering/TextControlInnerElements.h
index 1884a34..68d6ff4 100644
--- a/WebCore/rendering/TextControlInnerElements.h
+++ b/WebCore/rendering/TextControlInnerElements.h
@@ -28,9 +28,11 @@
#define TextControlInnerElements_h
#include "HTMLDivElement.h"
+#include "SpeechInputListener.h"
namespace WebCore {
+class SpeechInput;
class String;
class TextControlInnerElement : public HTMLDivElement {
@@ -88,33 +90,50 @@ private:
class SpinButtonElement : public TextControlInnerElement {
public:
- static PassRefPtr<SpinButtonElement> create(Node*);
+ enum UpDownState {
+ Indeterminate, // Hovered, but the event is not handled.
+ Down,
+ Up,
+ };
- // FIXME: "Spin button on up button" is not a phrase with a single clear meaning.
- // Need a name for this that makes it clearer.
- bool onUpButton() const { return m_onUpButton; }
+ static PassRefPtr<SpinButtonElement> create(Node*);
+ UpDownState upDownState() const { return m_upDownState; }
private:
SpinButtonElement(Node*);
virtual bool isSpinButtonElement() const { return true; }
- virtual bool isEnabledFormControl() { return static_cast<Element*>(shadowAncestorNode())->isEnabledFormControl(); }
+ // FIXME: shadowAncestorNode() should be const.
+ virtual bool isEnabledFormControl() const { return static_cast<Element*>(const_cast<SpinButtonElement*>(this)->shadowAncestorNode())->isEnabledFormControl(); }
+ virtual bool isReadOnlyFormControl() const { return static_cast<Element*>(const_cast<SpinButtonElement*>(this)->shadowAncestorNode())->isReadOnlyFormControl(); }
virtual void defaultEventHandler(Event*);
+ virtual void setHovered(bool = true);
bool m_capturing;
- bool m_onUpButton;
+ UpDownState m_upDownState;
};
#if ENABLE(INPUT_SPEECH)
-class InputFieldSpeechButtonElement : public TextControlInnerElement {
+class InputFieldSpeechButtonElement
+ : public TextControlInnerElement,
+ public SpeechInputListener {
public:
static PassRefPtr<InputFieldSpeechButtonElement> create(Document*);
virtual void defaultEventHandler(Event*);
+ // SpeechInputListener methods.
+ void recordingComplete();
+ void setRecognitionResult(const String& result);
+
private:
InputFieldSpeechButtonElement(Document*);
+ virtual void detach();
+ SpeechInput* speechInput();
+
+ bool m_capturing;
+ OwnPtr<SpeechInput> m_speechInput;
};
#endif // ENABLE(INPUT_SPEECH)
diff --git a/WebCore/rendering/style/FillLayer.cpp b/WebCore/rendering/style/FillLayer.cpp
index 59f3bb2..3469e97 100644
--- a/WebCore/rendering/style/FillLayer.cpp
+++ b/WebCore/rendering/style/FillLayer.cpp
@@ -129,17 +129,6 @@ bool FillLayer::operator==(const FillLayer& o) const
void FillLayer::fillUnsetProperties()
{
FillLayer* curr;
- for (curr = this; curr && curr->isImageSet(); curr = curr->next()) { }
- if (curr && curr != this) {
- // We need to fill in the remaining values with the pattern specified.
- for (FillLayer* pattern = this; curr; curr = curr->next()) {
- curr->m_image = pattern->m_image;
- pattern = pattern->next();
- if (pattern == curr || !pattern)
- pattern = this;
- }
- }
-
for (curr = this; curr && curr->isXPositionSet(); curr = curr->next()) { }
if (curr && curr != this) {
// We need to fill in the remaining values with the pattern specified.
@@ -243,15 +232,27 @@ void FillLayer::fillUnsetProperties()
void FillLayer::cullEmptyLayers()
{
+ // CSS3 background layering: the number of background layers is determined
+ // by the number of values in the 'background-image' property.
+ // http://www.w3.org/TR/css3-background/#layering
+
FillLayer* next;
for (FillLayer* p = this; p; p = next) {
next = p->m_next;
- if (next && !next->isImageSet() &&
- !next->isXPositionSet() && !next->isYPositionSet() &&
- !next->isAttachmentSet() && !next->isClipSet() &&
- !next->isCompositeSet() && !next->isOriginSet() &&
- !next->isRepeatXSet() && !next->isRepeatYSet()
- && !next->isSizeSet()) {
+ if (!next)
+ break;
+
+ bool anyAttributeSet = next->isXPositionSet()
+ || next->isYPositionSet()
+ || next->isAttachmentSet()
+ || next->isClipSet()
+ || next->isCompositeSet()
+ || next->isOriginSet()
+ || next->isRepeatXSet()
+ || next->isRepeatYSet()
+ || next->isSizeSet();
+
+ if (!next->isImageSet() || !anyAttributeSet) {
delete next;
p->m_next = 0;
break;
diff --git a/WebCore/rendering/style/RenderStyle.h b/WebCore/rendering/style/RenderStyle.h
index 782508e..58af7cf 100644
--- a/WebCore/rendering/style/RenderStyle.h
+++ b/WebCore/rendering/style/RenderStyle.h
@@ -876,8 +876,8 @@ public:
void adjustBackgroundLayers()
{
if (backgroundLayers()->next()) {
- accessBackgroundLayers()->cullEmptyLayers();
accessBackgroundLayers()->fillUnsetProperties();
+ accessBackgroundLayers()->cullEmptyLayers();
}
}
@@ -887,8 +887,8 @@ public:
void adjustMaskLayers()
{
if (maskLayers()->next()) {
- accessMaskLayers()->cullEmptyLayers();
accessMaskLayers()->fillUnsetProperties();
+ accessMaskLayers()->cullEmptyLayers();
}
}