• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
27 namespace blink {
28 
29 struct 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 
43 COMPILE_ASSERT(sizeof(FillLayer) == sizeof(SameSizeAsFillLayer), FillLayer_should_stay_small);
44 
FillLayer(EFillLayerType type,bool useInitialValues)45 FillLayer::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 
FillLayer(const FillLayer & o)79 FillLayer::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 
~FillLayer()113 FillLayer::~FillLayer()
114 {
115     delete m_next;
116 }
117 
operator =(const FillLayer & o)118 FillLayer& 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 
operator ==(const FillLayer & o) const160 bool 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 
fillUnsetProperties()173 void 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 
cullEmptyLayers()296 void 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 
clipMax(EFillBox clipA,EFillBox clipB)309 static 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 
computeClipMax() const320 void 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 
clipOccludesNextLayers(bool firstLayer) const329 bool FillLayer::clipOccludesNextLayers(bool firstLayer) const
330 {
331     if (firstLayer)
332         computeClipMax();
333     return m_clip == m_clipMax;
334 }
335 
containsImage(StyleImage * s) const336 bool 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 
imagesAreLoaded() const347 bool 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 
hasOpaqueImage(const RenderObject * renderer) const358 bool 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 
hasRepeatXY() const375 bool FillLayer::hasRepeatXY() const
376 {
377     return m_repeatX == RepeatFill && m_repeatY == RepeatFill;
378 }
379 
380 } // namespace blink
381