summaryrefslogtreecommitdiffstats
path: root/chromium/third_party/WebKit/Source/core/rendering/RenderImage.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/third_party/WebKit/Source/core/rendering/RenderImage.cpp')
-rw-r--r--chromium/third_party/WebKit/Source/core/rendering/RenderImage.cpp201
1 files changed, 91 insertions, 110 deletions
diff --git a/chromium/third_party/WebKit/Source/core/rendering/RenderImage.cpp b/chromium/third_party/WebKit/Source/core/rendering/RenderImage.cpp
index f2db1e3a3a6..610c7906446 100644
--- a/chromium/third_party/WebKit/Source/core/rendering/RenderImage.cpp
+++ b/chromium/third_party/WebKit/Source/core/rendering/RenderImage.cpp
@@ -28,19 +28,19 @@
#include "config.h"
#include "core/rendering/RenderImage.h"
-#include "HTMLNames.h"
+#include "core/HTMLNames.h"
#include "core/editing/FrameSelection.h"
#include "core/fetch/ImageResource.h"
#include "core/fetch/ResourceLoadPriorityOptimizer.h"
#include "core/fetch/ResourceLoader.h"
+#include "core/frame/LocalFrame.h"
#include "core/html/HTMLAreaElement.h"
#include "core/html/HTMLImageElement.h"
#include "core/html/HTMLInputElement.h"
#include "core/html/HTMLMapElement.h"
#include "core/inspector/InspectorInstrumentation.h"
-#include "core/frame/Frame.h"
+#include "core/inspector/InspectorTraceEvents.h"
#include "core/rendering/HitTestResult.h"
-#include "core/rendering/LayoutRectRecorder.h"
#include "core/rendering/PaintInfo.h"
#include "core/rendering/RenderView.h"
#include "core/svg/graphics/SVGImage.h"
@@ -57,12 +57,12 @@ using namespace HTMLNames;
RenderImage::RenderImage(Element* element)
: RenderReplaced(element, IntSize())
- , m_needsToSetSizeForAltText(false)
, m_didIncrementVisuallyNonEmptyPixelCount(false)
, m_isGeneratedContent(false)
, m_imageDevicePixelRatio(1.0f)
{
updateAltText();
+ ResourceLoadPriorityOptimizer::resourceLoadPriorityOptimizer()->addRenderObject(this);
}
RenderImage* RenderImage::createAnonymous(Document* document)
@@ -141,22 +141,12 @@ bool RenderImage::setImageSizeForAltText(ImageResource* newImage /* = 0 */)
return true;
}
-void RenderImage::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
-{
- RenderReplaced::styleDidChange(diff, oldStyle);
- if (m_needsToSetSizeForAltText) {
- if (!m_altText.isEmpty() && setImageSizeForAltText(m_imageResource->cachedImage()))
- imageDimensionsChanged(true /* imageSizeChanged */);
- m_needsToSetSizeForAltText = false;
- }
-}
-
void RenderImage::imageChanged(WrappedImagePtr newImage, const IntRect* rect)
{
if (documentBeingDestroyed())
return;
- if (hasBoxDecorations() || hasMask())
+ if (hasBoxDecorations() || hasMask() || hasShapeOutside())
RenderReplaced::imageChanged(newImage, rect);
if (!m_imageResource)
@@ -179,29 +169,17 @@ void RenderImage::imageChanged(WrappedImagePtr newImage, const IntRect* rect)
bool imageSizeChanged = false;
// Set image dimensions, taking into account the size of the alt text.
- if (m_imageResource->errorOccurred() || !newImage) {
- if (!m_altText.isEmpty() && document().hasPendingStyleRecalc()) {
- ASSERT(node());
- if (node()) {
- m_needsToSetSizeForAltText = true;
- node()->setNeedsStyleRecalc(LocalStyleChange, StyleChangeFromRenderer);
- }
- return;
- }
+ if (m_imageResource->errorOccurred() || !newImage)
imageSizeChanged = setImageSizeForAltText(m_imageResource->cachedImage());
- }
- imageDimensionsChanged(imageSizeChanged, rect);
+ repaintOrMarkForLayout(imageSizeChanged, rect);
}
-bool RenderImage::updateIntrinsicSizeIfNeeded(const LayoutSize& newSize, bool imageSizeChanged)
+void RenderImage::updateIntrinsicSizeIfNeeded(const LayoutSize& newSize)
{
- if (newSize == intrinsicSize() && !imageSizeChanged)
- return false;
if (m_imageResource->errorOccurred() || !m_imageResource->hasImage())
- return imageSizeChanged;
+ return;
setIntrinsicSize(newSize);
- return true;
}
void RenderImage::updateInnerContentRect()
@@ -213,9 +191,11 @@ void RenderImage::updateInnerContentRect()
m_imageResource->setContainerSizeForRenderer(containerSize);
}
-void RenderImage::imageDimensionsChanged(bool imageSizeChanged, const IntRect* rect)
+void RenderImage::repaintOrMarkForLayout(bool imageSizeChangedToAccomodateAltText, const IntRect* rect)
{
- bool intrinsicSizeChanged = updateIntrinsicSizeIfNeeded(m_imageResource->intrinsicSize(style()->effectiveZoom()), imageSizeChanged);
+ LayoutSize oldIntrinsicSize = intrinsicSize();
+ LayoutSize newIntrinsicSize = m_imageResource->intrinsicSize(style()->effectiveZoom());
+ updateIntrinsicSizeIfNeeded(newIntrinsicSize);
// In the case of generated image content using :before/:after/content, we might not be
// in the render tree yet. In that case, we just need to update our intrinsic size.
@@ -224,37 +204,25 @@ void RenderImage::imageDimensionsChanged(bool imageSizeChanged, const IntRect* r
if (!containingBlock())
return;
- bool shouldRepaint = true;
- if (intrinsicSizeChanged) {
- if (!preferredLogicalWidthsDirty())
- setPreferredLogicalWidthsDirty();
+ bool imageSourceHasChangedSize = oldIntrinsicSize != newIntrinsicSize || imageSizeChangedToAccomodateAltText;
+ if (imageSourceHasChangedSize)
+ setPreferredLogicalWidthsDirty();
- bool hasOverrideSize = hasOverrideHeight() || hasOverrideWidth();
- if (!hasOverrideSize && !imageSizeChanged) {
- LogicalExtentComputedValues computedValues;
- computeLogicalWidthInRegion(computedValues);
- LayoutUnit newWidth = computedValues.m_extent;
- computeLogicalHeight(height(), 0, computedValues);
- LayoutUnit newHeight = computedValues.m_extent;
+ // If the actual area occupied by the image has changed and it is not constrained by style then a layout is required.
+ bool imageSizeIsConstrained = style()->logicalWidth().isSpecified() && style()->logicalHeight().isSpecified();
+ bool needsLayout = !imageSizeIsConstrained && imageSourceHasChangedSize;
- imageSizeChanged = width() != newWidth || height() != newHeight;
- }
+ // FIXME: We only need to recompute the containing block's preferred size if the containing block's size
+ // depends on the image's size (i.e., the container uses shrink-to-fit sizing).
+ // There's no easy way to detect that shrink-to-fit is needed, always force a layout.
+ bool containingBlockNeedsToRecomputePreferredSize = style()->logicalWidth().isPercent() || style()->logicalMaxWidth().isPercent() || style()->logicalMinWidth().isPercent();
- // FIXME: We only need to recompute the containing block's preferred size
- // if the containing block's size depends on the image's size (i.e., the container uses shrink-to-fit sizing).
- // There's no easy way to detect that shrink-to-fit is needed, always force a layout.
- bool containingBlockNeedsToRecomputePreferredSize =
- style()->logicalWidth().isPercent()
- || style()->logicalMaxWidth().isPercent()
- || style()->logicalMinWidth().isPercent();
-
- if (imageSizeChanged || hasOverrideSize || containingBlockNeedsToRecomputePreferredSize) {
- shouldRepaint = false;
- if (!selfNeedsLayout())
- setNeedsLayout();
- }
+ if (needsLayout || containingBlockNeedsToRecomputePreferredSize) {
+ setNeedsLayoutAndFullPaintInvalidation();
+ return;
}
+ // The image hasn't changed in size or its style constrains its size, so a repaint will suffice.
if (everHadLayout() && !selfNeedsLayout()) {
// The inner content rectangle is calculated during layout, but may need an update now
// (unless the box has already been scheduled for layout). In order to calculate it, we
@@ -263,22 +231,26 @@ void RenderImage::imageDimensionsChanged(bool imageSizeChanged, const IntRect* r
updateInnerContentRect();
}
- if (shouldRepaint) {
- LayoutRect repaintRect;
- if (rect) {
- // The image changed rect is in source image coordinates (pre-zooming),
- // so map from the bounds of the image to the contentsBox.
- repaintRect = enclosingIntRect(mapRect(*rect, FloatRect(FloatPoint(), m_imageResource->imageSize(1.0f)), contentBoxRect()));
- // Guard against too-large changed rects.
- repaintRect.intersect(contentBoxRect());
- } else
- repaintRect = contentBoxRect();
-
- repaintRectangle(repaintRect);
+ LayoutRect repaintRect;
+ if (rect) {
+ // The image changed rect is in source image coordinates (without zoom),
+ // so map from the bounds of the image to the contentsBox.
+ const LayoutSize imageSizeWithoutZoom = m_imageResource->imageSize(1 / style()->effectiveZoom());
+ repaintRect = enclosingIntRect(mapRect(*rect, FloatRect(FloatPoint(), imageSizeWithoutZoom), contentBoxRect()));
+ // Guard against too-large changed rects.
+ repaintRect.intersect(contentBoxRect());
+ } else {
+ repaintRect = contentBoxRect();
+ }
- // Tell any potential compositing layers that the image needs updating.
- contentChanged(ImageChanged);
+ {
+ // FIXME: We should not be allowing repaint during layout. crbug.com/339584
+ AllowPaintInvalidationScope scoper(frameView());
+ invalidatePaintRectangle(repaintRect);
}
+
+ // Tell any potential compositing layers that the image needs updating.
+ contentChanged(ImageChanged);
}
void RenderImage::notifyFinished(Resource* newImage)
@@ -361,15 +333,20 @@ void RenderImage::paintReplaced(PaintInfo& paintInfo, const LayoutPoint& paintOf
// Only draw the alt text if it'll fit within the content box,
// and only if it fits above the error image.
TextRun textRun = RenderBlockFlow::constructTextRun(this, font, m_altText, style(), TextRun::AllowTrailingExpansion | TextRun::ForbidLeadingExpansion, DefaultTextRunFlags | RespectDirection);
- LayoutUnit textWidth = font.width(textRun);
+ float textWidth = font.width(textRun);
TextRunPaintInfo textRunPaintInfo(textRun);
textRunPaintInfo.bounds = FloatRect(textRectOrigin, FloatSize(textWidth, fontMetrics.height()));
context->setFillColor(resolveColor(CSSPropertyColor));
+ if (textRun.direction() == RTL) {
+ int availableWidth = cWidth - static_cast<int>(paddingWidth);
+ textOrigin.move(availableWidth - ceilf(textWidth), 0);
+ }
if (errorPictureDrawn) {
if (usableWidth >= textWidth && fontMetrics.height() <= imageOffset.height())
- context->drawText(font, textRunPaintInfo, textOrigin);
- } else if (usableWidth >= textWidth && usableHeight >= fontMetrics.height())
- context->drawText(font, textRunPaintInfo, textOrigin);
+ context->drawBidiText(font, textRunPaintInfo, textOrigin);
+ } else if (usableWidth >= textWidth && usableHeight >= fontMetrics.height()) {
+ context->drawBidiText(font, textRunPaintInfo, textOrigin);
+ }
}
}
} else if (m_imageResource->hasImage() && cWidth > 0 && cHeight > 0) {
@@ -413,21 +390,21 @@ void RenderImage::paintAreaElementFocusRing(PaintInfo& paintInfo)
return;
Element* focusedElement = document.focusedElement();
- if (!focusedElement || !isHTMLAreaElement(focusedElement))
+ if (!isHTMLAreaElement(focusedElement))
return;
- HTMLAreaElement* areaElement = toHTMLAreaElement(focusedElement);
- if (areaElement->imageElement() != node())
+ HTMLAreaElement& areaElement = toHTMLAreaElement(*focusedElement);
+ if (areaElement.imageElement() != node())
return;
// Even if the theme handles focus ring drawing for entire elements, it won't do it for
// an area within an image, so we don't call RenderTheme::supportsFocusRing here.
- Path path = areaElement->computePath(this);
+ Path path = areaElement.computePath(this);
if (path.isEmpty())
return;
- RenderStyle* areaElementStyle = areaElement->computedStyle();
+ RenderStyle* areaElementStyle = areaElement.computedStyle();
unsigned short outlineWidth = areaElementStyle->outlineWidth();
if (!outlineWidth)
return;
@@ -456,7 +433,7 @@ void RenderImage::areaElementFocusChanged(HTMLAreaElement* areaElement)
repaintRect.moveBy(-absoluteContentBox().location());
repaintRect.inflate(outlineWidth);
- repaintRectangle(repaintRect);
+ invalidatePaintRectangle(repaintRect);
}
void RenderImage::paintIntoRect(GraphicsContext* context, const LayoutRect& rect)
@@ -469,13 +446,18 @@ void RenderImage::paintIntoRect(GraphicsContext* context, const LayoutRect& rect
if (!img || img->isNull())
return;
- HTMLImageElement* imageElt = (node() && node()->hasTagName(imgTag)) ? toHTMLImageElement(node()) : 0;
+ HTMLImageElement* imageElt = isHTMLImageElement(node()) ? toHTMLImageElement(node()) : 0;
CompositeOperator compositeOperator = imageElt ? imageElt->compositeOperator() : CompositeSourceOver;
Image* image = m_imageResource->image().get();
- bool useLowQualityScaling = shouldPaintAtLowQuality(context, image, image, alignedRect.size());
+ InterpolationQuality interpolationQuality = chooseInterpolationQuality(context, image, image, alignedRect.size());
+ TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "PaintImage", "data", InspectorPaintImageEvent::data(*this));
+ // FIXME(361045): remove InspectorInstrumentation calls once DevTools Timeline migrates to tracing.
InspectorInstrumentation::willPaintImage(this);
- context->drawImage(m_imageResource->image(alignedRect.width(), alignedRect.height()).get(), alignedRect, compositeOperator, shouldRespectImageOrientation(), useLowQualityScaling);
+ InterpolationQuality previousInterpolationQuality = context->imageInterpolationQuality();
+ context->setImageInterpolationQuality(interpolationQuality);
+ context->drawImage(m_imageResource->image(alignedRect.width(), alignedRect.height()).get(), alignedRect, compositeOperator, shouldRespectImageOrientation());
+ context->setImageInterpolationQuality(previousInterpolationQuality);
InspectorInstrumentation::didPaintImage(this);
}
@@ -517,7 +499,11 @@ bool RenderImage::computeBackgroundIsKnownToBeObscured()
{
if (!hasBackground())
return false;
- return foregroundIsKnownToBeOpaqueInRect(backgroundPaintedExtent(), 0);
+
+ LayoutRect paintedExtent;
+ if (!getBackgroundPaintedExtent(paintedExtent))
+ return false;
+ return foregroundIsKnownToBeOpaqueInRect(paintedExtent, 0);
}
LayoutUnit RenderImage::minimumReplacedHeight() const
@@ -527,7 +513,7 @@ LayoutUnit RenderImage::minimumReplacedHeight() const
HTMLMapElement* RenderImage::imageMap() const
{
- HTMLImageElement* i = node() && node()->hasTagName(imgTag) ? toHTMLImageElement(node()) : 0;
+ HTMLImageElement* i = isHTMLImageElement(node()) ? toHTMLImageElement(node()) : 0;
return i ? i->treeScope().getImageMap(i->fastGetAttribute(usemapAttr)) : 0;
}
@@ -560,35 +546,22 @@ void RenderImage::updateAltText()
if (!node())
return;
- if (node()->hasTagName(inputTag))
+ if (isHTMLInputElement(*node()))
m_altText = toHTMLInputElement(node())->altText();
- else if (node()->hasTagName(imgTag))
+ else if (isHTMLImageElement(*node()))
m_altText = toHTMLImageElement(node())->altText();
}
void RenderImage::layout()
{
- LayoutRectRecorder recorder(*this);
RenderReplaced::layout();
updateInnerContentRect();
}
-void RenderImage::didLayout(ResourceLoadPriorityOptimizer& optimizer)
-{
- RenderReplaced::didLayout(optimizer);
- updateImageLoadingPriority(optimizer);
-}
-
-void RenderImage::didScroll(ResourceLoadPriorityOptimizer& optimizer)
-{
- RenderReplaced::didScroll(optimizer);
- updateImageLoadingPriority(optimizer);
-}
-
-void RenderImage::updateImageLoadingPriority(ResourceLoadPriorityOptimizer& optimizer)
+bool RenderImage::updateImageLoadingPriorities()
{
if (!m_imageResource || !m_imageResource->cachedImage() || m_imageResource->cachedImage()->isLoaded())
- return;
+ return false;
LayoutRect viewBounds = viewRect();
LayoutRect objectBounds = absoluteContentBox();
@@ -604,20 +577,28 @@ void RenderImage::updateImageLoadingPriority(ResourceLoadPriorityOptimizer& opti
ResourceLoadPriorityOptimizer::VisibilityStatus status = isVisible ?
ResourceLoadPriorityOptimizer::Visible : ResourceLoadPriorityOptimizer::NotVisible;
- optimizer.notifyImageResourceVisibility(m_imageResource->cachedImage(), status);
+ LayoutRect screenArea;
+ if (!objectBounds.isEmpty()) {
+ screenArea = viewBounds;
+ screenArea.intersect(objectBounds);
+ }
+
+ ResourceLoadPriorityOptimizer::resourceLoadPriorityOptimizer()->notifyImageResourceVisibility(m_imageResource->cachedImage(), status, screenArea);
+
+ return true;
}
-void RenderImage::computeIntrinsicRatioInformation(FloatSize& intrinsicSize, double& intrinsicRatio, bool& isPercentageIntrinsicSize) const
+void RenderImage::computeIntrinsicRatioInformation(FloatSize& intrinsicSize, double& intrinsicRatio) const
{
- RenderReplaced::computeIntrinsicRatioInformation(intrinsicSize, intrinsicRatio, isPercentageIntrinsicSize);
+ RenderReplaced::computeIntrinsicRatioInformation(intrinsicSize, intrinsicRatio);
// Our intrinsicSize is empty if we're rendering generated images with relative width/height. Figure out the right intrinsic size to use.
if (intrinsicSize.isEmpty() && (m_imageResource->imageHasRelativeWidth() || m_imageResource->imageHasRelativeHeight())) {
RenderObject* containingBlock = isOutOfFlowPositioned() ? container() : this->containingBlock();
if (containingBlock->isBox()) {
RenderBox* box = toRenderBox(containingBlock);
- intrinsicSize.setWidth(box->availableLogicalWidth());
- intrinsicSize.setHeight(box->availableLogicalHeight(IncludeMarginBorderPadding));
+ intrinsicSize.setWidth(box->availableLogicalWidth().toFloat());
+ intrinsicSize.setHeight(box->availableLogicalHeight(IncludeMarginBorderPadding).toFloat());
}
}
// Don't compute an intrinsic ratio to preserve historical WebKit behavior if we're painting alt text and/or a broken image.