summaryrefslogtreecommitdiff
path: root/Source/WebCore/rendering/style/FillLayer.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Source/WebCore/rendering/style/FillLayer.cpp')
-rw-r--r--Source/WebCore/rendering/style/FillLayer.cpp190
1 files changed, 124 insertions, 66 deletions
diff --git a/Source/WebCore/rendering/style/FillLayer.cpp b/Source/WebCore/rendering/style/FillLayer.cpp
index 3c563b278..a4ed82641 100644
--- a/Source/WebCore/rendering/style/FillLayer.cpp
+++ b/Source/WebCore/rendering/style/FillLayer.cpp
@@ -1,6 +1,6 @@
/*
* Copyright (C) 1999 Antti Koivisto (koivisto@kde.org)
- * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2014 Apple Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -22,39 +22,40 @@
#include "config.h"
#include "FillLayer.h"
+#include "TextStream.h"
+#include <wtf/PointerComparison.h>
+
namespace WebCore {
struct SameSizeAsFillLayer {
- FillLayer* m_next;
+ FillLayer* next;
- RefPtr<StyleImage> m_image;
+ RefPtr<StyleImage> image;
- Length m_xPosition;
- Length m_yPosition;
+ Length x;
+ Length y;
- LengthSize m_sizeLength;
+ LengthSize sizeLength;
- unsigned m_bitfields: 32;
- unsigned m_bitfields2: 1;
+ unsigned bitfields : 32;
+ unsigned bitfields2 : 11;
};
COMPILE_ASSERT(sizeof(FillLayer) == sizeof(SameSizeAsFillLayer), FillLayer_should_stay_small);
FillLayer::FillLayer(EFillLayerType type)
- : m_next(0)
- , m_image(FillLayer::initialFillImage(type))
+ : m_image(FillLayer::initialFillImage(type))
, m_xPosition(FillLayer::initialFillXPosition(type))
, m_yPosition(FillLayer::initialFillYPosition(type))
- , m_sizeLength(FillLayer::initialFillSizeLength(type))
, m_attachment(FillLayer::initialFillAttachment(type))
, m_clip(FillLayer::initialFillClip(type))
, m_origin(FillLayer::initialFillOrigin(type))
, m_repeatX(FillLayer::initialFillRepeatX(type))
, m_repeatY(FillLayer::initialFillRepeatY(type))
, m_composite(FillLayer::initialFillComposite(type))
- , m_sizeType(FillLayer::initialFillSizeType(type))
+ , m_sizeType(SizeNone)
, m_blendMode(FillLayer::initialFillBlendMode(type))
- , m_maskSourceType(FillLayer::initialMaskSourceType(type))
+ , m_maskSourceType(FillLayer::initialFillMaskSourceType(type))
, m_imageSet(false)
, m_attachmentSet(false)
, m_clipSet(false)
@@ -63,9 +64,10 @@ FillLayer::FillLayer(EFillLayerType type)
, m_repeatYSet(false)
, m_xPosSet(false)
, m_yPosSet(false)
- , m_backgroundOriginSet(false)
- , m_backgroundXOrigin(LeftEdge)
- , m_backgroundYOrigin(TopEdge)
+ , m_backgroundXOriginSet(false)
+ , m_backgroundYOriginSet(false)
+ , m_backgroundXOrigin(static_cast<unsigned>(Edge::Left))
+ , m_backgroundYOrigin(static_cast<unsigned>(Edge::Top))
, m_compositeSet(type == MaskFillLayer)
, m_blendModeSet(false)
, m_maskSourceTypeSet(false)
@@ -74,7 +76,7 @@ FillLayer::FillLayer(EFillLayerType type)
}
FillLayer::FillLayer(const FillLayer& o)
- : m_next(o.m_next ? new FillLayer(*o.m_next) : 0)
+ : m_next(o.m_next ? std::make_unique<FillLayer>(*o.m_next) : nullptr)
, m_image(o.m_image)
, m_xPosition(o.m_xPosition)
, m_yPosition(o.m_yPosition)
@@ -96,7 +98,8 @@ FillLayer::FillLayer(const FillLayer& o)
, m_repeatYSet(o.m_repeatYSet)
, m_xPosSet(o.m_xPosSet)
, m_yPosSet(o.m_yPosSet)
- , m_backgroundOriginSet(o.m_backgroundOriginSet)
+ , m_backgroundXOriginSet(o.m_backgroundXOriginSet)
+ , m_backgroundYOriginSet(o.m_backgroundYOriginSet)
, m_backgroundXOrigin(o.m_backgroundXOrigin)
, m_backgroundYOrigin(o.m_backgroundYOrigin)
, m_compositeSet(o.m_compositeSet)
@@ -108,22 +111,21 @@ FillLayer::FillLayer(const FillLayer& o)
FillLayer::~FillLayer()
{
- delete m_next;
+ // Delete the layers in a loop rather than allowing recursive calls to the destructors.
+ for (std::unique_ptr<FillLayer> next = WTFMove(m_next); next; next = WTFMove(next->m_next)) { }
}
FillLayer& FillLayer::operator=(const FillLayer& o)
{
- if (m_next != o.m_next) {
- delete m_next;
- m_next = o.m_next ? new FillLayer(*o.m_next) : 0;
- }
+ m_next = o.m_next ? std::make_unique<FillLayer>(*o.m_next) : nullptr;
m_image = o.m_image;
m_xPosition = o.m_xPosition;
m_yPosition = o.m_yPosition;
m_backgroundXOrigin = o.m_backgroundXOrigin;
m_backgroundYOrigin = o.m_backgroundYOrigin;
- m_backgroundOriginSet = o.m_backgroundOriginSet;
+ m_backgroundXOriginSet = o.m_backgroundXOriginSet;
+ m_backgroundYOriginSet = o.m_backgroundYOriginSet;
m_sizeLength = o.m_sizeLength;
m_attachment = o.m_attachment;
m_clip = o.m_clip;
@@ -155,14 +157,14 @@ FillLayer& FillLayer::operator=(const FillLayer& o)
bool FillLayer::operator==(const FillLayer& o) const
{
// We do not check the "isSet" booleans for each property, since those are only used during initial construction
- // to propagate patterns into layers. All layer comparisons happen after values have all been filled in anyway.
- return StyleImage::imagesEquivalent(m_image.get(), o.m_image.get()) && m_xPosition == o.m_xPosition && m_yPosition == o.m_yPosition
- && m_backgroundXOrigin == o.m_backgroundXOrigin && m_backgroundYOrigin == o.m_backgroundYOrigin
- && m_attachment == o.m_attachment && m_clip == o.m_clip && m_composite == o.m_composite
- && m_blendMode == o.m_blendMode && m_origin == o.m_origin && m_repeatX == o.m_repeatX
- && m_repeatY == o.m_repeatY && m_sizeType == o.m_sizeType && m_maskSourceType == o.m_maskSourceType
- && m_sizeLength == o.m_sizeLength && m_type == o.m_type
- && ((m_next && o.m_next) ? *m_next == *o.m_next : m_next == o.m_next);
+ // to propagate patterns into layers. All layer comparisons happen after values have all been filled in anyway.
+ return arePointingToEqualData(m_image.get(), o.m_image.get()) && m_xPosition == o.m_xPosition && m_yPosition == o.m_yPosition
+ && m_backgroundXOrigin == o.m_backgroundXOrigin && m_backgroundYOrigin == o.m_backgroundYOrigin
+ && m_attachment == o.m_attachment && m_clip == o.m_clip && m_composite == o.m_composite
+ && m_blendMode == o.m_blendMode && m_origin == o.m_origin && m_repeatX == o.m_repeatX
+ && m_repeatY == o.m_repeatY && m_sizeType == o.m_sizeType && m_maskSourceType == o.m_maskSourceType
+ && m_sizeLength == o.m_sizeLength && m_type == o.m_type
+ && ((m_next && o.m_next) ? *m_next == *o.m_next : m_next == o.m_next);
}
void FillLayer::fillUnsetProperties()
@@ -173,10 +175,10 @@ void FillLayer::fillUnsetProperties()
// We need to fill in the remaining values with the pattern specified.
for (FillLayer* pattern = this; curr; curr = curr->next()) {
curr->m_xPosition = pattern->m_xPosition;
- if (pattern->isBackgroundOriginSet()) {
+ if (pattern->isBackgroundXOriginSet())
curr->m_backgroundXOrigin = pattern->m_backgroundXOrigin;
+ if (pattern->isBackgroundYOriginSet())
curr->m_backgroundYOrigin = pattern->m_backgroundYOrigin;
- }
pattern = pattern->next();
if (pattern == curr || !pattern)
pattern = this;
@@ -188,10 +190,10 @@ void FillLayer::fillUnsetProperties()
// We need to fill in the remaining values with the pattern specified.
for (FillLayer* pattern = this; curr; curr = curr->next()) {
curr->m_yPosition = pattern->m_yPosition;
- if (pattern->isBackgroundOriginSet()) {
+ if (pattern->isBackgroundXOriginSet())
curr->m_backgroundXOrigin = pattern->m_backgroundXOrigin;
+ if (pattern->isBackgroundYOriginSet())
curr->m_backgroundYOrigin = pattern->m_backgroundYOrigin;
- }
pattern = pattern->next();
if (pattern == curr || !pattern)
pattern = this;
@@ -290,18 +292,15 @@ void FillLayer::fillUnsetProperties()
void FillLayer::cullEmptyLayers()
{
- FillLayer* next;
- for (FillLayer* p = this; p; p = next) {
- next = p->m_next;
- if (next && !next->isImageSet()) {
- delete next;
- p->m_next = 0;
+ for (FillLayer* layer = this; layer; layer = layer->m_next.get()) {
+ if (layer->m_next && !layer->m_next->isImageSet()) {
+ layer->m_next = nullptr;
break;
}
}
}
-static EFillBox clipMax(EFillBox clipA, EFillBox clipB)
+static inline EFillBox clipMax(EFillBox clipA, EFillBox clipB)
{
if (clipA == BorderFillBox || clipB == BorderFillBox)
return BorderFillBox;
@@ -314,11 +313,15 @@ static EFillBox clipMax(EFillBox clipA, EFillBox clipB)
void FillLayer::computeClipMax() const
{
- if (m_next) {
- m_next->computeClipMax();
- m_clipMax = clipMax(clip(), m_next->clip());
- } else
- m_clipMax = m_clip;
+ Vector<const FillLayer*, 4> layers;
+ for (auto* layer = this; layer; layer = layer->m_next.get())
+ layers.append(layer);
+ EFillBox computedClipMax = TextFillBox;
+ for (unsigned i = layers.size(); i; --i) {
+ auto& layer = *layers[i - 1];
+ computedClipMax = clipMax(computedClipMax, layer.clip());
+ layer.m_clipMax = computedClipMax;
+ }
}
bool FillLayer::clipOccludesNextLayers(bool firstLayer) const
@@ -328,29 +331,25 @@ bool FillLayer::clipOccludesNextLayers(bool firstLayer) const
return m_clip == m_clipMax;
}
-bool FillLayer::containsImage(StyleImage* s) const
+bool FillLayer::containsImage(StyleImage& image) const
{
- if (!s)
- return false;
- if (m_image && *s == *m_image)
- return true;
- if (m_next)
- return m_next->containsImage(s);
+ for (auto* layer = this; layer; layer = layer->m_next.get()) {
+ if (layer->m_image && image == *layer->m_image)
+ return true;
+ }
return false;
}
bool FillLayer::imagesAreLoaded() const
{
- const FillLayer* curr;
- for (curr = this; curr; curr = curr->next()) {
- if (curr->m_image && !curr->m_image->isLoaded())
+ for (auto* layer = this; layer; layer = layer->m_next.get()) {
+ if (layer->m_image && !layer->m_image->isLoaded())
return false;
}
-
return true;
}
-bool FillLayer::hasOpaqueImage(const RenderElement* renderer) const
+bool FillLayer::hasOpaqueImage(const RenderElement& renderer) const
{
if (!m_image)
return false;
@@ -358,18 +357,77 @@ bool FillLayer::hasOpaqueImage(const RenderElement* renderer) const
if (m_composite == CompositeClear || m_composite == CompositeCopy)
return true;
- if (m_blendMode != BlendModeNormal)
- return false;
+ return m_blendMode == BlendModeNormal && m_composite == CompositeSourceOver && m_image->knownToBeOpaque(&renderer);
+}
- if (m_composite == CompositeSourceOver)
- return m_image->knownToBeOpaque(renderer);
+bool FillLayer::hasRepeatXY() const
+{
+ return m_repeatX == RepeatFill && m_repeatY == RepeatFill;
+}
+bool FillLayer::hasImage() const
+{
+ for (auto* layer = this; layer; layer = layer->m_next.get()) {
+ if (layer->image())
+ return true;
+ }
return false;
}
-bool FillLayer::hasRepeatXY() const
+bool FillLayer::hasFixedImage() const
{
- return m_repeatX == RepeatFill && m_repeatY == RepeatFill;
+ for (auto* layer = this; layer; layer = layer->m_next.get()) {
+ if (layer->m_image && layer->m_attachment == FixedBackgroundAttachment)
+ return true;
+ }
+ return false;
+}
+
+bool FillLayer::imagesIdentical(const FillLayer* layer1, const FillLayer* layer2)
+{
+ for (; layer1 && layer2; layer1 = layer1->next(), layer2 = layer2->next()) {
+ if (!arePointingToEqualData(layer1->image(), layer2->image()))
+ return false;
+ }
+
+ return !layer1 && !layer2;
+}
+
+TextStream& operator<<(TextStream& ts, FillSize fillSize)
+{
+ return ts << fillSize.type << " " << fillSize.size;
+}
+
+TextStream& operator<<(TextStream& ts, const FillLayer& layer)
+{
+ TextStream::GroupScope scope(ts);
+ ts << "fill-layer";
+
+ ts.startGroup();
+ ts << "position " << layer.xPosition() << " " << layer.yPosition();
+ ts.endGroup();
+
+ ts.dumpProperty("size", layer.size());
+
+ ts.startGroup();
+ ts << "background-origin " << layer.backgroundXOrigin() << " " << layer.backgroundYOrigin();
+ ts.endGroup();
+
+ ts.startGroup();
+ ts << "repeat " << layer.repeatX() << " " << layer.repeatY();
+ ts.endGroup();
+
+ ts.dumpProperty("clip", layer.clip());
+ ts.dumpProperty("origin", layer.origin());
+
+ ts.dumpProperty("composite", layer.composite());
+ ts.dumpProperty("blend-mode", layer.blendMode());
+ ts.dumpProperty("mask-type", layer.maskSourceType());
+
+ if (layer.next())
+ ts << *layer.next();
+
+ return ts;
}
} // namespace WebCore