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