Implement CSS `display: flow-root` (modern clearfix)
[WebKit-https.git] / Source / WebCore / rendering / style / FillLayer.cpp
1 /*
2  * Copyright (C) 1999 Antti Koivisto (koivisto@kde.org)
3  * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2014 Apple Inc. All rights reserved.
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Library General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Library General Public License for more details.
14  *
15  * You should have received a copy of the GNU Library General Public License
16  * along with this library; see the file COPYING.LIB.  If not, write to
17  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18  * Boston, MA 02110-1301, USA.
19  *
20  */
21
22 #include "config.h"
23 #include "FillLayer.h"
24
25 #include <wtf/PointerComparison.h>
26 #include <wtf/text/TextStream.h>
27
28 namespace WebCore {
29
30 struct SameSizeAsFillLayer {
31     FillLayer* next;
32
33     RefPtr<StyleImage> image;
34
35     Length x;
36     Length y;
37
38     LengthSize sizeLength;
39
40     unsigned bitfields : 32;
41     unsigned bitfields2 : 11;
42 };
43
44 COMPILE_ASSERT(sizeof(FillLayer) == sizeof(SameSizeAsFillLayer), FillLayer_should_stay_small);
45
46 FillLayer::FillLayer(FillLayerType type)
47     : m_image(FillLayer::initialFillImage(type))
48     , m_xPosition(FillLayer::initialFillXPosition(type))
49     , m_yPosition(FillLayer::initialFillYPosition(type))
50     , m_attachment(static_cast<unsigned>(FillLayer::initialFillAttachment(type)))
51     , m_clip(static_cast<unsigned>(FillLayer::initialFillClip(type)))
52     , m_origin(static_cast<unsigned>(FillLayer::initialFillOrigin(type)))
53     , m_repeatX(static_cast<unsigned>(FillLayer::initialFillRepeatX(type)))
54     , m_repeatY(static_cast<unsigned>(FillLayer::initialFillRepeatY(type)))
55     , m_composite(FillLayer::initialFillComposite(type))
56     , m_sizeType(static_cast<unsigned>(FillSizeType::None))
57     , m_blendMode(static_cast<unsigned>(FillLayer::initialFillBlendMode(type)))
58     , m_maskSourceType(static_cast<unsigned>(FillLayer::initialFillMaskSourceType(type)))
59     , m_imageSet(false)
60     , m_attachmentSet(false)
61     , m_clipSet(false)
62     , m_originSet(false)
63     , m_repeatXSet(false)
64     , m_repeatYSet(false)
65     , m_xPosSet(false)
66     , m_yPosSet(false)
67     , m_backgroundXOriginSet(false)
68     , m_backgroundYOriginSet(false)
69     , m_backgroundXOrigin(static_cast<unsigned>(Edge::Left))
70     , m_backgroundYOrigin(static_cast<unsigned>(Edge::Top))
71     , m_compositeSet(type == FillLayerType::Mask)
72     , m_blendModeSet(false)
73     , m_maskSourceTypeSet(false)
74     , m_type(static_cast<unsigned>(type))
75 {
76 }
77
78 FillLayer::FillLayer(const FillLayer& o)
79     : m_next(o.m_next ? std::make_unique<FillLayer>(*o.m_next) : nullptr)
80     , m_image(o.m_image)
81     , m_xPosition(o.m_xPosition)
82     , m_yPosition(o.m_yPosition)
83     , m_sizeLength(o.m_sizeLength)
84     , m_attachment(o.m_attachment)
85     , m_clip(o.m_clip)
86     , m_origin(o.m_origin)
87     , m_repeatX(o.m_repeatX)
88     , m_repeatY(o.m_repeatY)
89     , m_composite(o.m_composite)
90     , m_sizeType(o.m_sizeType)
91     , m_blendMode(o.m_blendMode)
92     , m_maskSourceType(o.m_maskSourceType)
93     , m_imageSet(o.m_imageSet)
94     , m_attachmentSet(o.m_attachmentSet)
95     , m_clipSet(o.m_clipSet)
96     , m_originSet(o.m_originSet)
97     , m_repeatXSet(o.m_repeatXSet)
98     , m_repeatYSet(o.m_repeatYSet)
99     , m_xPosSet(o.m_xPosSet)
100     , m_yPosSet(o.m_yPosSet)
101     , m_backgroundXOriginSet(o.m_backgroundXOriginSet)
102     , m_backgroundYOriginSet(o.m_backgroundYOriginSet)
103     , m_backgroundXOrigin(o.m_backgroundXOrigin)
104     , m_backgroundYOrigin(o.m_backgroundYOrigin)
105     , m_compositeSet(o.m_compositeSet)
106     , m_blendModeSet(o.m_blendModeSet)
107     , m_maskSourceTypeSet(o.m_maskSourceTypeSet)
108     , m_type(o.m_type)
109 {
110 }
111
112 FillLayer::~FillLayer()
113 {
114     // Delete the layers in a loop rather than allowing recursive calls to the destructors.
115     for (std::unique_ptr<FillLayer> next = WTFMove(m_next); next; next = WTFMove(next->m_next)) { }
116 }
117
118 FillLayer& FillLayer::operator=(const FillLayer& o)
119 {
120     m_next = o.m_next ? std::make_unique<FillLayer>(*o.m_next) : nullptr;
121
122     m_image = o.m_image;
123     m_xPosition = o.m_xPosition;
124     m_yPosition = o.m_yPosition;
125     m_backgroundXOrigin = o.m_backgroundXOrigin;
126     m_backgroundYOrigin = o.m_backgroundYOrigin;
127     m_backgroundXOriginSet = o.m_backgroundXOriginSet;
128     m_backgroundYOriginSet = o.m_backgroundYOriginSet;
129     m_sizeLength = o.m_sizeLength;
130     m_attachment = o.m_attachment;
131     m_clip = o.m_clip;
132     m_composite = o.m_composite;
133     m_blendMode = o.m_blendMode;
134     m_origin = o.m_origin;
135     m_repeatX = o.m_repeatX;
136     m_repeatY = o.m_repeatY;
137     m_sizeType = o.m_sizeType;
138     m_maskSourceType = o.m_maskSourceType;
139
140     m_imageSet = o.m_imageSet;
141     m_attachmentSet = o.m_attachmentSet;
142     m_clipSet = o.m_clipSet;
143     m_compositeSet = o.m_compositeSet;
144     m_blendModeSet = o.m_blendModeSet;
145     m_originSet = o.m_originSet;
146     m_repeatXSet = o.m_repeatXSet;
147     m_repeatYSet = o.m_repeatYSet;
148     m_xPosSet = o.m_xPosSet;
149     m_yPosSet = o.m_yPosSet;
150     m_maskSourceTypeSet = o.m_maskSourceTypeSet;
151
152     m_type = o.m_type;
153
154     return *this;
155 }
156
157 bool FillLayer::operator==(const FillLayer& o) const
158 {
159     // We do not check the "isSet" booleans for each property, since those are only used during initial construction
160     // to propagate patterns into layers. All layer comparisons happen after values have all been filled in anyway.
161     return arePointingToEqualData(m_image.get(), o.m_image.get()) && m_xPosition == o.m_xPosition && m_yPosition == o.m_yPosition
162         && m_backgroundXOrigin == o.m_backgroundXOrigin && m_backgroundYOrigin == o.m_backgroundYOrigin
163         && m_attachment == o.m_attachment && m_clip == o.m_clip && m_composite == o.m_composite
164         && m_blendMode == o.m_blendMode && m_origin == o.m_origin && m_repeatX == o.m_repeatX
165         && m_repeatY == o.m_repeatY && m_sizeType == o.m_sizeType && m_maskSourceType == o.m_maskSourceType
166         && m_sizeLength == o.m_sizeLength && m_type == o.m_type
167         && ((m_next && o.m_next) ? *m_next == *o.m_next : m_next == o.m_next);
168 }
169
170 void FillLayer::fillUnsetProperties()
171 {
172     FillLayer* curr;
173     for (curr = this; curr && curr->isXPositionSet(); curr = curr->next()) { }
174     if (curr && curr != this) {
175         // We need to fill in the remaining values with the pattern specified.
176         for (FillLayer* pattern = this; curr; curr = curr->next()) {
177             curr->m_xPosition = pattern->m_xPosition;
178             if (pattern->isBackgroundXOriginSet())
179                 curr->m_backgroundXOrigin = pattern->m_backgroundXOrigin;
180             if (pattern->isBackgroundYOriginSet())
181                 curr->m_backgroundYOrigin = pattern->m_backgroundYOrigin;
182             pattern = pattern->next();
183             if (pattern == curr || !pattern)
184                 pattern = this;
185         }
186     }
187     
188     for (curr = this; curr && curr->isYPositionSet(); curr = curr->next()) { }
189     if (curr && curr != this) {
190         // We need to fill in the remaining values with the pattern specified.
191         for (FillLayer* pattern = this; curr; curr = curr->next()) {
192             curr->m_yPosition = pattern->m_yPosition;
193             if (pattern->isBackgroundXOriginSet())
194                 curr->m_backgroundXOrigin = pattern->m_backgroundXOrigin;
195             if (pattern->isBackgroundYOriginSet())
196                 curr->m_backgroundYOrigin = pattern->m_backgroundYOrigin;
197             pattern = pattern->next();
198             if (pattern == curr || !pattern)
199                 pattern = this;
200         }
201     }
202
203     for (curr = this; curr && curr->isAttachmentSet(); curr = curr->next()) { }
204     if (curr && curr != this) {
205         // We need to fill in the remaining values with the pattern specified.
206         for (FillLayer* pattern = this; curr; curr = curr->next()) {
207             curr->m_attachment = pattern->m_attachment;
208             pattern = pattern->next();
209             if (pattern == curr || !pattern)
210                 pattern = this;
211         }
212     }
213     
214     for (curr = this; curr && curr->isClipSet(); curr = curr->next()) { }
215     if (curr && curr != this) {
216         // We need to fill in the remaining values with the pattern specified.
217         for (FillLayer* pattern = this; curr; curr = curr->next()) {
218             curr->m_clip = pattern->m_clip;
219             pattern = pattern->next();
220             if (pattern == curr || !pattern)
221                 pattern = this;
222         }
223     }
224
225     for (curr = this; curr && curr->isCompositeSet(); curr = curr->next()) { }
226     if (curr && curr != this) {
227         // We need to fill in the remaining values with the pattern specified.
228         for (FillLayer* pattern = this; curr; curr = curr->next()) {
229             curr->m_composite = pattern->m_composite;
230             pattern = pattern->next();
231             if (pattern == curr || !pattern)
232                 pattern = this;
233         }
234     }
235
236     for (curr = this; curr && curr->isBlendModeSet(); curr = curr->next()) { }
237     if (curr && curr != this) {
238         // We need to fill in the remaining values with the pattern specified.
239         for (FillLayer* pattern = this; curr; curr = curr->next()) {
240             curr->m_blendMode = pattern->m_blendMode;
241             pattern = pattern->next();
242             if (pattern == curr || !pattern)
243                 pattern = this;
244         }
245     }
246
247     for (curr = this; curr && curr->isOriginSet(); curr = curr->next()) { }
248     if (curr && curr != this) {
249         // We need to fill in the remaining values with the pattern specified.
250         for (FillLayer* pattern = this; curr; curr = curr->next()) {
251             curr->m_origin = pattern->m_origin;
252             pattern = pattern->next();
253             if (pattern == curr || !pattern)
254                 pattern = this;
255         }
256     }
257
258     for (curr = this; curr && curr->isRepeatXSet(); curr = curr->next()) { }
259     if (curr && curr != this) {
260         // We need to fill in the remaining values with the pattern specified.
261         for (FillLayer* pattern = this; curr; curr = curr->next()) {
262             curr->m_repeatX = pattern->m_repeatX;
263             pattern = pattern->next();
264             if (pattern == curr || !pattern)
265                 pattern = this;
266         }
267     }
268
269     for (curr = this; curr && curr->isRepeatYSet(); curr = curr->next()) { }
270     if (curr && curr != this) {
271         // We need to fill in the remaining values with the pattern specified.
272         for (FillLayer* pattern = this; curr; curr = curr->next()) {
273             curr->m_repeatY = pattern->m_repeatY;
274             pattern = pattern->next();
275             if (pattern == curr || !pattern)
276                 pattern = this;
277         }
278     }
279     
280     for (curr = this; curr && curr->isSizeSet(); curr = curr->next()) { }
281     if (curr && curr != this) {
282         // We need to fill in the remaining values with the pattern specified.
283         for (FillLayer* pattern = this; curr; curr = curr->next()) {
284             curr->m_sizeType = pattern->m_sizeType;
285             curr->m_sizeLength = pattern->m_sizeLength;
286             pattern = pattern->next();
287             if (pattern == curr || !pattern)
288                 pattern = this;
289         }
290     }
291 }
292
293 void FillLayer::cullEmptyLayers()
294 {
295     for (FillLayer* layer = this; layer; layer = layer->m_next.get()) {
296         if (layer->m_next && !layer->m_next->isImageSet()) {
297             layer->m_next = nullptr;
298             break;
299         }
300     }
301 }
302
303 static inline FillBox clipMax(FillBox clipA, FillBox clipB)
304 {
305     if (clipA == FillBox::Border || clipB == FillBox::Border)
306         return FillBox::Border;
307     if (clipA == FillBox::Padding || clipB == FillBox::Padding)
308         return FillBox::Padding;
309     if (clipA == FillBox::Content || clipB == FillBox::Content)
310         return FillBox::Content;
311     return FillBox::Text;
312 }
313
314 void FillLayer::computeClipMax() const
315 {
316     Vector<const FillLayer*, 4> layers;
317     for (auto* layer = this; layer; layer = layer->m_next.get())
318         layers.append(layer);
319     FillBox computedClipMax = FillBox::Text;
320     for (unsigned i = layers.size(); i; --i) {
321         auto& layer = *layers[i - 1];
322         computedClipMax = clipMax(computedClipMax, layer.clip());
323         layer.m_clipMax = static_cast<unsigned>(computedClipMax);
324     }
325 }
326
327 bool FillLayer::clipOccludesNextLayers(bool firstLayer) const
328 {
329     if (firstLayer)
330         computeClipMax();
331     return m_clip == m_clipMax;
332 }
333
334 bool FillLayer::containsImage(StyleImage& image) const
335 {
336     for (auto* layer = this; layer; layer = layer->m_next.get()) {
337         if (layer->m_image && image == *layer->m_image)
338             return true;
339     }
340     return false;
341 }
342
343 bool FillLayer::imagesAreLoaded() const
344 {
345     for (auto* layer = this; layer; layer = layer->m_next.get()) {
346         if (layer->m_image && !layer->m_image->isLoaded())
347             return false;
348     }
349     return true;
350 }
351
352 bool FillLayer::hasOpaqueImage(const RenderElement& renderer) const
353 {
354     if (!m_image)
355         return false;
356
357     if (m_composite == CompositeClear || m_composite == CompositeCopy)
358         return true;
359
360     return static_cast<BlendMode>(m_blendMode) == BlendMode::Normal && m_composite == CompositeSourceOver && m_image->knownToBeOpaque(&renderer);
361 }
362
363 bool FillLayer::hasRepeatXY() const
364 {
365     return repeatX() == FillRepeat::Repeat && repeatY() == FillRepeat::Repeat;
366 }
367
368 bool FillLayer::hasImage() const
369 {
370     for (auto* layer = this; layer; layer = layer->m_next.get()) {
371         if (layer->image())
372             return true;
373     }
374     return false;
375 }
376
377 bool FillLayer::hasFixedImage() const
378 {
379     for (auto* layer = this; layer; layer = layer->m_next.get()) {
380         if (layer->m_image && layer->attachment() == FillAttachment::FixedBackground)
381             return true;
382     }
383     return false;
384 }
385
386 bool FillLayer::imagesIdentical(const FillLayer* layer1, const FillLayer* layer2)
387 {
388     for (; layer1 && layer2; layer1 = layer1->next(), layer2 = layer2->next()) {
389         if (!arePointingToEqualData(layer1->image(), layer2->image()))
390             return false;
391     }
392
393     return !layer1 && !layer2;
394 }
395
396 TextStream& operator<<(TextStream& ts, FillSize fillSize)
397 {
398     return ts << fillSize.type << " " << fillSize.size;
399 }
400
401 TextStream& operator<<(TextStream& ts, const FillLayer& layer)
402 {
403     TextStream::GroupScope scope(ts);
404     ts << "fill-layer";
405
406     ts.startGroup();
407     ts << "position " << layer.xPosition() << " " << layer.yPosition();
408     ts.endGroup();
409
410     ts.dumpProperty("size", layer.size());
411
412     ts.startGroup();
413     ts << "background-origin " << layer.backgroundXOrigin() << " " << layer.backgroundYOrigin();
414     ts.endGroup();
415
416     ts.startGroup();
417     ts << "repeat " << layer.repeatX() << " " << layer.repeatY();
418     ts.endGroup();
419
420     ts.dumpProperty("clip", layer.clip());
421     ts.dumpProperty("origin", layer.origin());
422
423     ts.dumpProperty("composite", layer.composite());
424     ts.dumpProperty("blend-mode", layer.blendMode());
425     ts.dumpProperty("mask-type", layer.maskSourceType());
426
427     if (layer.next())
428         ts << *layer.next();
429
430     return ts;
431 }
432
433 } // namespace WebCore