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 #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 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 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 113 FillLayer::~FillLayer() 114 { 115 delete m_next; 116 } 117 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 160 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 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 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 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 320 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 329 bool FillLayer::clipOccludesNextLayers(bool firstLayer) const 330 { 331 if (firstLayer) 332 computeClipMax(); 333 return m_clip == m_clipMax; 334 } 335 336 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 347 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 358 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 375 bool FillLayer::hasRepeatXY() const 376 { 377 return m_repeatX == RepeatFill && m_repeatY == RepeatFill; 378 } 379 380 } // namespace blink 381