OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) | 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) |
3 * (C) 1999 Antti Koivisto (koivisto@kde.org) | 3 * (C) 1999 Antti Koivisto (koivisto@kde.org) |
4 * (C) 2000 Dirk Mueller (mueller@kde.org) | 4 * (C) 2000 Dirk Mueller (mueller@kde.org) |
5 * (C) 2006 Allan Sandfeld Jensen (kde@carewolf.com) | 5 * (C) 2006 Allan Sandfeld Jensen (kde@carewolf.com) |
6 * (C) 2006 Samuel Weinig (sam.weinig@gmail.com) | 6 * (C) 2006 Samuel Weinig (sam.weinig@gmail.com) |
7 * Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009, 2010, 2011 Apple Inc. All r
ights reserved. | 7 * Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009, 2010, 2011 Apple Inc. All r
ights reserved. |
8 * Copyright (C) 2010 Google Inc. All rights reserved. | 8 * Copyright (C) 2010 Google Inc. All rights reserved. |
9 * Copyright (C) Research In Motion Limited 2011-2012. All rights reserved. | 9 * Copyright (C) Research In Motion Limited 2011-2012. All rights reserved. |
10 * | 10 * |
(...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
189 bool RenderImage::updateIntrinsicSizeIfNeeded(const LayoutSize& newSize, bool im
ageSizeChanged) | 189 bool RenderImage::updateIntrinsicSizeIfNeeded(const LayoutSize& newSize, bool im
ageSizeChanged) |
190 { | 190 { |
191 if (newSize == intrinsicSize() && !imageSizeChanged) | 191 if (newSize == intrinsicSize() && !imageSizeChanged) |
192 return false; | 192 return false; |
193 if (m_imageResource->errorOccurred() || !m_imageResource->hasImage()) | 193 if (m_imageResource->errorOccurred() || !m_imageResource->hasImage()) |
194 return imageSizeChanged; | 194 return imageSizeChanged; |
195 setIntrinsicSize(newSize); | 195 setIntrinsicSize(newSize); |
196 return true; | 196 return true; |
197 } | 197 } |
198 | 198 |
| 199 void RenderImage::updateInnerContentRect() |
| 200 { |
| 201 // Propagate container size to image resource. |
| 202 LayoutRect paintRect = replacedContentRect(); |
| 203 IntSize containerSize(paintRect.width(), paintRect.height()); |
| 204 if (!containerSize.isEmpty()) |
| 205 m_imageResource->setContainerSizeForRenderer(containerSize); |
| 206 } |
| 207 |
199 void RenderImage::imageDimensionsChanged(bool imageSizeChanged, const IntRect* r
ect) | 208 void RenderImage::imageDimensionsChanged(bool imageSizeChanged, const IntRect* r
ect) |
200 { | 209 { |
201 bool intrinsicSizeChanged = updateIntrinsicSizeIfNeeded(m_imageResource->ima
geSize(style()->effectiveZoom()), imageSizeChanged); | 210 bool intrinsicSizeChanged = updateIntrinsicSizeIfNeeded(m_imageResource->int
rinsicSize(style()->effectiveZoom()), imageSizeChanged); |
202 | 211 |
203 // In the case of generated image content using :before/:after/content, we m
ight not be | 212 // In the case of generated image content using :before/:after/content, we m
ight not be |
204 // in the render tree yet. In that case, we just need to update our intrinsi
c size. | 213 // in the render tree yet. In that case, we just need to update our intrinsi
c size. |
205 // layout() will be called after we are inserted in the tree which will take
care of | 214 // layout() will be called after we are inserted in the tree which will take
care of |
206 // what we are doing here. | 215 // what we are doing here. |
207 if (!containingBlock()) | 216 if (!containingBlock()) |
208 return; | 217 return; |
209 | 218 |
210 bool shouldRepaint = true; | 219 bool shouldRepaint = true; |
211 if (intrinsicSizeChanged) { | 220 if (intrinsicSizeChanged) { |
(...skipping 17 matching lines...) Expand all Loading... |
229 bool containingBlockNeedsToRecomputePreferredSize = | 238 bool containingBlockNeedsToRecomputePreferredSize = |
230 style()->logicalWidth().isPercent() | 239 style()->logicalWidth().isPercent() |
231 || style()->logicalMaxWidth().isPercent() | 240 || style()->logicalMaxWidth().isPercent() |
232 || style()->logicalMinWidth().isPercent(); | 241 || style()->logicalMinWidth().isPercent(); |
233 | 242 |
234 if (imageSizeChanged || hasOverrideSize || containingBlockNeedsToRecompu
tePreferredSize) { | 243 if (imageSizeChanged || hasOverrideSize || containingBlockNeedsToRecompu
tePreferredSize) { |
235 shouldRepaint = false; | 244 shouldRepaint = false; |
236 if (!selfNeedsLayout()) | 245 if (!selfNeedsLayout()) |
237 setNeedsLayout(true); | 246 setNeedsLayout(true); |
238 } | 247 } |
| 248 |
| 249 if (everHadLayout() && !selfNeedsLayout()) { |
| 250 // The inner content rectangle is calculated during layout, but may
need an update now |
| 251 // (unless the box has already been scheduled for layout). In order
to calculate it, we |
| 252 // may need values from the containing block, though, so make sure t
hat we're not too |
| 253 // early. It may be that layout hasn't even taken place once yet. |
| 254 updateInnerContentRect(); |
| 255 } |
239 } | 256 } |
240 | 257 |
241 if (shouldRepaint) { | 258 if (shouldRepaint) { |
242 LayoutRect repaintRect; | 259 LayoutRect repaintRect; |
243 if (rect) { | 260 if (rect) { |
244 // The image changed rect is in source image coordinates (pre-zoomin
g), | 261 // The image changed rect is in source image coordinates (pre-zoomin
g), |
245 // so map from the bounds of the image to the contentsBox. | 262 // so map from the bounds of the image to the contentsBox. |
246 repaintRect = enclosingIntRect(mapRect(*rect, FloatRect(FloatPoint()
, m_imageResource->imageSize(1.0f)), contentBoxRect())); | 263 repaintRect = enclosingIntRect(mapRect(*rect, FloatRect(FloatPoint()
, m_imageResource->imageSize(1.0f)), contentBoxRect())); |
247 // Guard against too-large changed rects. | 264 // Guard against too-large changed rects. |
248 repaintRect.intersect(contentBoxRect()); | 265 repaintRect.intersect(contentBoxRect()); |
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
356 } | 373 } |
357 } | 374 } |
358 } else if (m_imageResource->hasImage() && cWidth > 0 && cHeight > 0) { | 375 } else if (m_imageResource->hasImage() && cWidth > 0 && cHeight > 0) { |
359 RefPtr<Image> img = m_imageResource->image(cWidth, cHeight); | 376 RefPtr<Image> img = m_imageResource->image(cWidth, cHeight); |
360 if (!img || img->isNull()) { | 377 if (!img || img->isNull()) { |
361 if (page && paintInfo.phase == PaintPhaseForeground) | 378 if (page && paintInfo.phase == PaintPhaseForeground) |
362 page->addRelevantUnpaintedObject(this, visualOverflowRect()); | 379 page->addRelevantUnpaintedObject(this, visualOverflowRect()); |
363 return; | 380 return; |
364 } | 381 } |
365 | 382 |
366 LayoutSize contentSize(cWidth, cHeight); | 383 LayoutRect contentRect = contentBoxRect(); |
367 LayoutPoint contentLocation = paintOffset; | 384 contentRect.moveBy(paintOffset); |
368 contentLocation.move(leftBorder + leftPad, topBorder + topPad); | 385 LayoutRect paintRect = replacedContentRect(); |
369 paintIntoRect(context, LayoutRect(contentLocation, contentSize)); | 386 paintRect.moveBy(paintOffset); |
| 387 bool clip = !contentRect.contains(paintRect); |
| 388 if (clip) { |
| 389 context->save(); |
| 390 context->clip(contentRect); |
| 391 } |
| 392 |
| 393 paintIntoRect(context, paintRect); |
370 | 394 |
371 if (cachedImage() && page && paintInfo.phase == PaintPhaseForeground) { | 395 if (cachedImage() && page && paintInfo.phase == PaintPhaseForeground) { |
372 // For now, count images as unpainted if they are still progressivel
y loading. We may want | 396 // For now, count images as unpainted if they are still progressivel
y loading. We may want |
373 // to refine this in the future to account for the portion of the im
age that has painted. | 397 // to refine this in the future to account for the portion of the im
age that has painted. |
| 398 LayoutRect visibleRect = intersection(paintRect, contentRect); |
374 if (cachedImage()->isLoading()) | 399 if (cachedImage()->isLoading()) |
375 page->addRelevantUnpaintedObject(this, LayoutRect(contentLocatio
n, contentSize)); | 400 page->addRelevantUnpaintedObject(this, visibleRect); |
376 else | 401 else |
377 page->addRelevantRepaintedObject(this, LayoutRect(contentLocatio
n, contentSize)); | 402 page->addRelevantRepaintedObject(this, visibleRect); |
378 } | 403 } |
| 404 |
| 405 if (clip) |
| 406 context->restore(); |
379 } | 407 } |
380 } | 408 } |
381 | 409 |
382 void RenderImage::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset) | 410 void RenderImage::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset) |
383 { | 411 { |
384 RenderReplaced::paint(paintInfo, paintOffset); | 412 RenderReplaced::paint(paintInfo, paintOffset); |
385 | 413 |
386 if (paintInfo.phase == PaintPhaseOutline) | 414 if (paintInfo.phase == PaintPhaseOutline) |
387 paintAreaElementFocusRing(paintInfo); | 415 paintAreaElementFocusRing(paintInfo); |
388 } | 416 } |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
478 return false; | 506 return false; |
479 if (!contentBoxRect().contains(localRect)) | 507 if (!contentBoxRect().contains(localRect)) |
480 return false; | 508 return false; |
481 EFillBox backgroundClip = style()->backgroundClip(); | 509 EFillBox backgroundClip = style()->backgroundClip(); |
482 // Background paints under borders. | 510 // Background paints under borders. |
483 if (backgroundClip == BorderFillBox && style()->hasBorder() && !borderObscur
esBackground()) | 511 if (backgroundClip == BorderFillBox && style()->hasBorder() && !borderObscur
esBackground()) |
484 return false; | 512 return false; |
485 // Background shows in padding area. | 513 // Background shows in padding area. |
486 if ((backgroundClip == BorderFillBox || backgroundClip == PaddingFillBox) &&
style()->hasPadding()) | 514 if ((backgroundClip == BorderFillBox || backgroundClip == PaddingFillBox) &&
style()->hasPadding()) |
487 return false; | 515 return false; |
| 516 // Object-fit may leave parts of the content box empty. |
| 517 EObjectFit objectFit = style()->objectFit(); |
| 518 if (objectFit != ObjectFitFill && objectFit != ObjectFitCover) |
| 519 return false; |
488 // Check for image with alpha. | 520 // Check for image with alpha. |
489 return m_imageResource->cachedImage() && m_imageResource->cachedImage()->cur
rentFrameKnownToBeOpaque(this); | 521 return m_imageResource->cachedImage() && m_imageResource->cachedImage()->cur
rentFrameKnownToBeOpaque(this); |
490 } | 522 } |
491 | 523 |
492 bool RenderImage::computeBackgroundIsKnownToBeObscured() | 524 bool RenderImage::computeBackgroundIsKnownToBeObscured() |
493 { | 525 { |
494 if (!hasBackground()) | 526 if (!hasBackground()) |
495 return false; | 527 return false; |
496 return foregroundIsKnownToBeOpaqueInRect(backgroundPaintedExtent(), 0); | 528 return foregroundIsKnownToBeOpaqueInRect(backgroundPaintedExtent(), 0); |
497 } | 529 } |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
539 if (node()->hasTagName(inputTag)) | 571 if (node()->hasTagName(inputTag)) |
540 m_altText = toHTMLInputElement(node())->altText(); | 572 m_altText = toHTMLInputElement(node())->altText(); |
541 else if (node()->hasTagName(imgTag)) | 573 else if (node()->hasTagName(imgTag)) |
542 m_altText = toHTMLImageElement(node())->altText(); | 574 m_altText = toHTMLImageElement(node())->altText(); |
543 } | 575 } |
544 | 576 |
545 void RenderImage::layout() | 577 void RenderImage::layout() |
546 { | 578 { |
547 StackStats::LayoutCheckPoint layoutCheckPoint; | 579 StackStats::LayoutCheckPoint layoutCheckPoint; |
548 RenderReplaced::layout(); | 580 RenderReplaced::layout(); |
549 | 581 updateInnerContentRect(); |
550 // Propagate container size to image resource. | |
551 IntSize containerSize(contentWidth(), contentHeight()); | |
552 if (!containerSize.isEmpty()) | |
553 m_imageResource->setContainerSizeForRenderer(containerSize); | |
554 } | 582 } |
555 | 583 |
556 void RenderImage::computeIntrinsicRatioInformation(FloatSize& intrinsicSize, dou
ble& intrinsicRatio, bool& isPercentageIntrinsicSize) const | 584 void RenderImage::computeIntrinsicRatioInformation(FloatSize& intrinsicSize, dou
ble& intrinsicRatio, bool& isPercentageIntrinsicSize) const |
557 { | 585 { |
558 RenderReplaced::computeIntrinsicRatioInformation(intrinsicSize, intrinsicRat
io, isPercentageIntrinsicSize); | 586 RenderReplaced::computeIntrinsicRatioInformation(intrinsicSize, intrinsicRat
io, isPercentageIntrinsicSize); |
559 | 587 |
560 // Our intrinsicSize is empty if we're rendering generated images with relat
ive width/height. Figure out the right intrinsic size to use. | 588 // Our intrinsicSize is empty if we're rendering generated images with relat
ive width/height. Figure out the right intrinsic size to use. |
561 if (intrinsicSize.isEmpty() && (m_imageResource->imageHasRelativeWidth() ||
m_imageResource->imageHasRelativeHeight())) { | 589 if (intrinsicSize.isEmpty() && (m_imageResource->imageHasRelativeWidth() ||
m_imageResource->imageHasRelativeHeight())) { |
562 RenderObject* containingBlock = isOutOfFlowPositioned() ? container() :
this->containingBlock(); | 590 RenderObject* containingBlock = isOutOfFlowPositioned() ? container() :
this->containingBlock(); |
563 if (containingBlock->isBox()) { | 591 if (containingBlock->isBox()) { |
(...skipping 22 matching lines...) Expand all Loading... |
586 return 0; | 614 return 0; |
587 | 615 |
588 CachedImage* cachedImage = m_imageResource->cachedImage(); | 616 CachedImage* cachedImage = m_imageResource->cachedImage(); |
589 if (cachedImage && cachedImage->image() && cachedImage->image()->isSVGImage(
)) | 617 if (cachedImage && cachedImage->image() && cachedImage->image()->isSVGImage(
)) |
590 return static_cast<SVGImage*>(cachedImage->image())->embeddedContentBox(
); | 618 return static_cast<SVGImage*>(cachedImage->image())->embeddedContentBox(
); |
591 | 619 |
592 return 0; | 620 return 0; |
593 } | 621 } |
594 | 622 |
595 } // namespace WebCore | 623 } // namespace WebCore |
OLD | NEW |