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