Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(333)

Side by Side Diff: Source/core/rendering/RenderImage.cpp

Issue 22482004: Add support for the object-fit CSS property. (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Code review Created 7 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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);
pdr. 2013/08/09 23:39:22 In general, we try to avoid clipping because it's
mstensho (USE GERRIT) 2013/08/12 13:39:11 Done. Please take a look at what I did. I was con
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698