1/*
2 * Copyright (C) 1999 Antti Koivisto (koivisto@kde.org)
3 * Copyright (C) 2004, 2005, 2006, 2007, 2008 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 "core/rendering/style/FillLayer.h"
24
25#include "core/rendering/style/DataEquivalency.h"
26
27namespace blink {
28
29struct SameSizeAsFillLayer {
30    FillLayer* m_next;
31
32    RefPtr<StyleImage> m_image;
33
34    Length m_xPosition;
35    Length m_yPosition;
36
37    LengthSize m_sizeLength;
38
39    unsigned m_bitfields1;
40    unsigned m_bitfields2;
41};
42
43COMPILE_ASSERT(sizeof(FillLayer) == sizeof(SameSizeAsFillLayer), FillLayer_should_stay_small);
44
45FillLayer::FillLayer(EFillLayerType type, bool useInitialValues)
46    : m_next(0)
47    , m_image(FillLayer::initialFillImage(type))
48    , m_xPosition(FillLayer::initialFillXPosition(type))
49    , m_yPosition(FillLayer::initialFillYPosition(type))
50    , m_sizeLength(FillLayer::initialFillSizeLength(type))
51    , m_attachment(FillLayer::initialFillAttachment(type))
52    , m_clip(FillLayer::initialFillClip(type))
53    , m_origin(FillLayer::initialFillOrigin(type))
54    , m_repeatX(FillLayer::initialFillRepeatX(type))
55    , m_repeatY(FillLayer::initialFillRepeatY(type))
56    , m_composite(FillLayer::initialFillComposite(type))
57    , m_sizeType(useInitialValues ? FillLayer::initialFillSizeType(type) : SizeNone)
58    , m_blendMode(FillLayer::initialFillBlendMode(type))
59    , m_maskSourceType(FillLayer::initialFillMaskSourceType(type))
60    , m_backgroundXOrigin(LeftEdge)
61    , m_backgroundYOrigin(TopEdge)
62    , m_imageSet(useInitialValues)
63    , m_attachmentSet(useInitialValues)
64    , m_clipSet(useInitialValues)
65    , m_originSet(useInitialValues)
66    , m_repeatXSet(useInitialValues)
67    , m_repeatYSet(useInitialValues)
68    , m_xPosSet(useInitialValues)
69    , m_yPosSet(useInitialValues)
70    , m_backgroundXOriginSet(false)
71    , m_backgroundYOriginSet(false)
72    , m_compositeSet(useInitialValues || type == MaskFillLayer)
73    , m_blendModeSet(useInitialValues)
74    , m_maskSourceTypeSet(useInitialValues)
75    , m_type(type)
76{
77}
78
79FillLayer::FillLayer(const FillLayer& o)
80    : m_next(o.m_next ? new FillLayer(*o.m_next) : 0)
81    , m_image(o.m_image)
82    , m_xPosition(o.m_xPosition)
83    , m_yPosition(o.m_yPosition)
84    , m_sizeLength(o.m_sizeLength)
85    , m_attachment(o.m_attachment)
86    , m_clip(o.m_clip)
87    , m_origin(o.m_origin)
88    , m_repeatX(o.m_repeatX)
89    , m_repeatY(o.m_repeatY)
90    , m_composite(o.m_composite)
91    , m_sizeType(o.m_sizeType)
92    , m_blendMode(o.m_blendMode)
93    , m_maskSourceType(o.m_maskSourceType)
94    , m_backgroundXOrigin(o.m_backgroundXOrigin)
95    , m_backgroundYOrigin(o.m_backgroundYOrigin)
96    , m_imageSet(o.m_imageSet)
97    , m_attachmentSet(o.m_attachmentSet)
98    , m_clipSet(o.m_clipSet)
99    , m_originSet(o.m_originSet)
100    , m_repeatXSet(o.m_repeatXSet)
101    , m_repeatYSet(o.m_repeatYSet)
102    , m_xPosSet(o.m_xPosSet)
103    , m_yPosSet(o.m_yPosSet)
104    , m_backgroundXOriginSet(o.m_backgroundXOriginSet)
105    , m_backgroundYOriginSet(o.m_backgroundYOriginSet)
106    , m_compositeSet(o.m_compositeSet)
107    , m_blendModeSet(o.m_blendModeSet)
108    , m_maskSourceTypeSet(o.m_maskSourceTypeSet)
109    , m_type(o.m_type)
110{
111}
112
113FillLayer::~FillLayer()
114{
115    delete m_next;
116}
117
118FillLayer& FillLayer::operator=(const FillLayer& o)
119{
120    if (m_next != o.m_next) {
121        delete m_next;
122        m_next = o.m_next ? new FillLayer(*o.m_next) : 0;
123    }
124
125    m_image = o.m_image;
126    m_xPosition = o.m_xPosition;
127    m_yPosition = o.m_yPosition;
128    m_backgroundXOrigin = o.m_backgroundXOrigin;
129    m_backgroundYOrigin = o.m_backgroundYOrigin;
130    m_backgroundXOriginSet = o.m_backgroundXOriginSet;
131    m_backgroundYOriginSet = o.m_backgroundYOriginSet;
132    m_sizeLength = o.m_sizeLength;
133    m_attachment = o.m_attachment;
134    m_clip = o.m_clip;
135    m_composite = o.m_composite;
136    m_blendMode = o.m_blendMode;
137    m_origin = o.m_origin;
138    m_repeatX = o.m_repeatX;
139    m_repeatY = o.m_repeatY;
140    m_sizeType = o.m_sizeType;
141    m_maskSourceType = o.m_maskSourceType;
142
143    m_imageSet = o.m_imageSet;
144    m_attachmentSet = o.m_attachmentSet;
145    m_clipSet = o.m_clipSet;
146    m_compositeSet = o.m_compositeSet;
147    m_blendModeSet = o.m_blendModeSet;
148    m_originSet = o.m_originSet;
149    m_repeatXSet = o.m_repeatXSet;
150    m_repeatYSet = o.m_repeatYSet;
151    m_xPosSet = o.m_xPosSet;
152    m_yPosSet = o.m_yPosSet;
153    m_maskSourceTypeSet = o.m_maskSourceTypeSet;
154
155    m_type = o.m_type;
156
157    return *this;
158}
159
160bool FillLayer::operator==(const FillLayer& o) const
161{
162    // We do not check the "isSet" booleans for each property, since those are only used during initial construction
163    // to propagate patterns into layers.  All layer comparisons happen after values have all been filled in anyway.
164    return dataEquivalent(m_image, o.m_image) && m_xPosition == o.m_xPosition && m_yPosition == o.m_yPosition
165            && m_backgroundXOrigin == o.m_backgroundXOrigin && m_backgroundYOrigin == o.m_backgroundYOrigin
166            && m_attachment == o.m_attachment && m_clip == o.m_clip && m_composite == o.m_composite
167            && m_blendMode == o.m_blendMode && m_origin == o.m_origin && m_repeatX == o.m_repeatX
168            && m_repeatY == o.m_repeatY && m_sizeType == o.m_sizeType && m_maskSourceType == o.m_maskSourceType
169            && m_sizeLength == o.m_sizeLength && m_type == o.m_type
170            && ((m_next && o.m_next) ? *m_next == *o.m_next : m_next == o.m_next);
171}
172
173void FillLayer::fillUnsetProperties()
174{
175    FillLayer* curr;
176    for (curr = this; curr && curr->isXPositionSet(); curr = curr->next()) { }
177    if (curr && curr != this) {
178        // We need to fill in the remaining values with the pattern specified.
179        for (FillLayer* pattern = this; curr; curr = curr->next()) {
180            curr->m_xPosition = pattern->m_xPosition;
181            if (pattern->isBackgroundXOriginSet())
182                curr->m_backgroundXOrigin = pattern->m_backgroundXOrigin;
183            if (pattern->isBackgroundYOriginSet())
184                curr->m_backgroundYOrigin = pattern->m_backgroundYOrigin;
185            pattern = pattern->next();
186            if (pattern == curr || !pattern)
187                pattern = this;
188        }
189    }
190
191    for (curr = this; curr && curr->isYPositionSet(); curr = curr->next()) { }
192    if (curr && curr != this) {
193        // We need to fill in the remaining values with the pattern specified.
194        for (FillLayer* pattern = this; curr; curr = curr->next()) {
195            curr->m_yPosition = pattern->m_yPosition;
196            if (pattern->isBackgroundXOriginSet())
197                curr->m_backgroundXOrigin = pattern->m_backgroundXOrigin;
198            if (pattern->isBackgroundYOriginSet())
199                curr->m_backgroundYOrigin = pattern->m_backgroundYOrigin;
200            pattern = pattern->next();
201            if (pattern == curr || !pattern)
202                pattern = this;
203        }
204    }
205
206    for (curr = this; curr && curr->isAttachmentSet(); curr = curr->next()) { }
207    if (curr && curr != this) {
208        // We need to fill in the remaining values with the pattern specified.
209        for (FillLayer* pattern = this; curr; curr = curr->next()) {
210            curr->m_attachment = pattern->m_attachment;
211            pattern = pattern->next();
212            if (pattern == curr || !pattern)
213                pattern = this;
214        }
215    }
216
217    for (curr = this; curr && curr->isClipSet(); curr = curr->next()) { }
218    if (curr && curr != this) {
219        // We need to fill in the remaining values with the pattern specified.
220        for (FillLayer* pattern = this; curr; curr = curr->next()) {
221            curr->m_clip = pattern->m_clip;
222            pattern = pattern->next();
223            if (pattern == curr || !pattern)
224                pattern = this;
225        }
226    }
227
228    for (curr = this; curr && curr->isCompositeSet(); curr = curr->next()) { }
229    if (curr && curr != this) {
230        // We need to fill in the remaining values with the pattern specified.
231        for (FillLayer* pattern = this; curr; curr = curr->next()) {
232            curr->m_composite = pattern->m_composite;
233            pattern = pattern->next();
234            if (pattern == curr || !pattern)
235                pattern = this;
236        }
237    }
238
239    for (curr = this; curr && curr->isBlendModeSet(); curr = curr->next()) { }
240    if (curr && curr != this) {
241        // We need to fill in the remaining values with the pattern specified.
242        for (FillLayer* pattern = this; curr; curr = curr->next()) {
243            curr->m_blendMode = pattern->m_blendMode;
244            pattern = pattern->next();
245            if (pattern == curr || !pattern)
246                pattern = this;
247        }
248    }
249
250    for (curr = this; curr && curr->isOriginSet(); curr = curr->next()) { }
251    if (curr && curr != this) {
252        // We need to fill in the remaining values with the pattern specified.
253        for (FillLayer* pattern = this; curr; curr = curr->next()) {
254            curr->m_origin = pattern->m_origin;
255            pattern = pattern->next();
256            if (pattern == curr || !pattern)
257                pattern = this;
258        }
259    }
260
261    for (curr = this; curr && curr->isRepeatXSet(); curr = curr->next()) { }
262    if (curr && curr != this) {
263        // We need to fill in the remaining values with the pattern specified.
264        for (FillLayer* pattern = this; curr; curr = curr->next()) {
265            curr->m_repeatX = pattern->m_repeatX;
266            pattern = pattern->next();
267            if (pattern == curr || !pattern)
268                pattern = this;
269        }
270    }
271
272    for (curr = this; curr && curr->isRepeatYSet(); curr = curr->next()) { }
273    if (curr && curr != this) {
274        // We need to fill in the remaining values with the pattern specified.
275        for (FillLayer* pattern = this; curr; curr = curr->next()) {
276            curr->m_repeatY = pattern->m_repeatY;
277            pattern = pattern->next();
278            if (pattern == curr || !pattern)
279                pattern = this;
280        }
281    }
282
283    for (curr = this; curr && curr->isSizeSet(); curr = curr->next()) { }
284    if (curr && curr != this) {
285        // We need to fill in the remaining values with the pattern specified.
286        for (FillLayer* pattern = this; curr; curr = curr->next()) {
287            curr->m_sizeType = pattern->m_sizeType;
288            curr->m_sizeLength = pattern->m_sizeLength;
289            pattern = pattern->next();
290            if (pattern == curr || !pattern)
291                pattern = this;
292        }
293    }
294}
295
296void FillLayer::cullEmptyLayers()
297{
298    FillLayer* next;
299    for (FillLayer* p = this; p; p = next) {
300        next = p->m_next;
301        if (next && !next->isImageSet()) {
302            delete next;
303            p->m_next = 0;
304            break;
305        }
306    }
307}
308
309static EFillBox clipMax(EFillBox clipA, EFillBox clipB)
310{
311    if (clipA == BorderFillBox || clipB == BorderFillBox)
312        return BorderFillBox;
313    if (clipA == PaddingFillBox || clipB == PaddingFillBox)
314        return PaddingFillBox;
315    if (clipA == ContentFillBox || clipB == ContentFillBox)
316        return ContentFillBox;
317    return TextFillBox;
318}
319
320void FillLayer::computeClipMax() const
321{
322    if (m_next) {
323        m_next->computeClipMax();
324        m_clipMax = clipMax(clip(), m_next->clip());
325    } else
326        m_clipMax = m_clip;
327}
328
329bool FillLayer::clipOccludesNextLayers(bool firstLayer) const
330{
331    if (firstLayer)
332        computeClipMax();
333    return m_clip == m_clipMax;
334}
335
336bool FillLayer::containsImage(StyleImage* s) const
337{
338    if (!s)
339        return false;
340    if (m_image && *s == *m_image)
341        return true;
342    if (m_next)
343        return m_next->containsImage(s);
344    return false;
345}
346
347bool FillLayer::imagesAreLoaded() const
348{
349    const FillLayer* curr;
350    for (curr = this; curr; curr = curr->next()) {
351        if (curr->m_image && !curr->m_image->isLoaded())
352            return false;
353    }
354
355    return true;
356}
357
358bool FillLayer::hasOpaqueImage(const RenderObject* renderer) const
359{
360    if (!m_image)
361        return false;
362
363    if (m_composite == CompositeClear || m_composite == CompositeCopy)
364        return true;
365
366    if (m_blendMode != WebBlendModeNormal)
367        return false;
368
369    if (m_composite == CompositeSourceOver)
370        return m_image->knownToBeOpaque(renderer);
371
372    return false;
373}
374
375bool FillLayer::hasRepeatXY() const
376{
377    return m_repeatX == RepeatFill && m_repeatY == RepeatFill;
378}
379
380} // namespace blink
381