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