Index: Source/core/rendering/RenderImage.cpp |
diff --git a/Source/core/rendering/RenderImage.cpp b/Source/core/rendering/RenderImage.cpp |
index db06454872848db0d9052df89e64b92e1ed2ae71..63e5caac555034a01874e4d1f9467ba2f3365f8f 100644 |
--- a/Source/core/rendering/RenderImage.cpp |
+++ b/Source/core/rendering/RenderImage.cpp |
@@ -38,8 +38,7 @@ |
#include "core/html/HTMLImageElement.h" |
#include "core/html/HTMLInputElement.h" |
#include "core/html/HTMLMapElement.h" |
-#include "core/inspector/InspectorInstrumentation.h" |
-#include "core/paint/BoxPainter.h" |
+#include "core/paint/ImagePainter.h" |
#include "core/rendering/HitTestResult.h" |
#include "core/rendering/PaintInfo.h" |
#include "core/rendering/RenderLayer.h" |
@@ -48,8 +47,6 @@ |
#include "core/svg/graphics/SVGImage.h" |
#include "platform/fonts/Font.h" |
#include "platform/fonts/FontCache.h" |
-#include "platform/graphics/GraphicsContext.h" |
-#include "platform/graphics/GraphicsContextStateSaver.h" |
namespace blink { |
@@ -92,10 +89,6 @@ void RenderImage::setImageResource(PassOwnPtr<RenderImageResource> imageResource |
m_imageResource->initialize(this); |
} |
-// If we'll be displaying either alt text or an image, add some padding. |
-static const unsigned short paddingWidth = 4; |
-static const unsigned short paddingHeight = 4; |
- |
// Alt text is restricted to this maximum size, in pixels. These are |
// signed integers because they are compared with other signed values. |
static const float maxAltTextWidth = 1024; |
@@ -279,144 +272,12 @@ void RenderImage::notifyFinished(Resource* newImage) |
void RenderImage::paintReplaced(PaintInfo& paintInfo, const LayoutPoint& paintOffset) |
{ |
- LayoutUnit cWidth = contentWidth(); |
- LayoutUnit cHeight = contentHeight(); |
- |
- GraphicsContext* context = paintInfo.context; |
- |
- if (!m_imageResource->hasImage() || m_imageResource->errorOccurred()) { |
- if (paintInfo.phase == PaintPhaseSelection) |
- return; |
- |
- if (cWidth > 2 && cHeight > 2) { |
- const int borderWidth = 1; |
- |
- LayoutUnit leftBorder = borderLeft(); |
- LayoutUnit topBorder = borderTop(); |
- LayoutUnit leftPad = paddingLeft(); |
- LayoutUnit topPad = paddingTop(); |
- |
- // Draw an outline rect where the image should be. |
- context->setStrokeStyle(SolidStroke); |
- context->setStrokeColor(Color::lightGray); |
- context->setFillColor(Color::transparent); |
- context->drawRect(pixelSnappedIntRect(LayoutRect(paintOffset.x() + leftBorder + leftPad, paintOffset.y() + topBorder + topPad, cWidth, cHeight))); |
- |
- bool errorPictureDrawn = false; |
- LayoutSize imageOffset; |
- // When calculating the usable dimensions, exclude the pixels of |
- // the ouline rect so the error image/alt text doesn't draw on it. |
- LayoutUnit usableWidth = cWidth - 2 * borderWidth; |
- LayoutUnit usableHeight = cHeight - 2 * borderWidth; |
- |
- RefPtr<Image> image = m_imageResource->image(); |
- |
- if (m_imageResource->errorOccurred() && !image->isNull() && usableWidth >= image->width() && usableHeight >= image->height()) { |
- float deviceScaleFactor = blink::deviceScaleFactor(frame()); |
- // Call brokenImage() explicitly to ensure we get the broken image icon at the appropriate resolution. |
- pair<Image*, float> brokenImageAndImageScaleFactor = ImageResource::brokenImage(deviceScaleFactor); |
- image = brokenImageAndImageScaleFactor.first; |
- IntSize imageSize = image->size(); |
- imageSize.scale(1 / brokenImageAndImageScaleFactor.second); |
- // Center the error image, accounting for border and padding. |
- LayoutUnit centerX = (usableWidth - imageSize.width()) / 2; |
- if (centerX < 0) |
- centerX = 0; |
- LayoutUnit centerY = (usableHeight - imageSize.height()) / 2; |
- if (centerY < 0) |
- centerY = 0; |
- imageOffset = LayoutSize(leftBorder + leftPad + centerX + borderWidth, topBorder + topPad + centerY + borderWidth); |
- context->drawImage(image.get(), pixelSnappedIntRect(LayoutRect(paintOffset + imageOffset, imageSize)), CompositeSourceOver, shouldRespectImageOrientation()); |
- errorPictureDrawn = true; |
- } |
- |
- if (!m_altText.isEmpty()) { |
- const Font& font = style()->font(); |
- const FontMetrics& fontMetrics = font.fontMetrics(); |
- LayoutUnit ascent = fontMetrics.ascent(); |
- LayoutPoint textRectOrigin = paintOffset; |
- textRectOrigin.move(leftBorder + leftPad + (paddingWidth / 2) - borderWidth, topBorder + topPad + (paddingHeight / 2) - borderWidth); |
- LayoutPoint textOrigin(textRectOrigin.x(), textRectOrigin.y() + ascent); |
- |
- // Only draw the alt text if it'll fit within the content box, |
- // and only if it fits above the error image. |
- TextRun textRun = constructTextRun(this, font, m_altText, style(), TextRun::AllowTrailingExpansion | TextRun::ForbidLeadingExpansion, DefaultTextRunFlags | RespectDirection); |
- 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->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) { |
- LayoutRect contentRect = contentBoxRect(); |
- contentRect.moveBy(paintOffset); |
- LayoutRect paintRect = replacedContentRect(); |
- paintRect.moveBy(paintOffset); |
- bool clip = !contentRect.contains(paintRect); |
- if (clip) { |
- context->save(); |
- context->clip(contentRect); |
- } |
- |
- paintIntoRect(context, paintRect); |
- |
- if (clip) |
- context->restore(); |
- } |
+ ImagePainter(*this).paintReplaced(paintInfo, paintOffset); |
} |
void RenderImage::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset) |
{ |
- RenderReplaced::paint(paintInfo, paintOffset); |
- |
- if (paintInfo.phase == PaintPhaseOutline) |
- paintAreaElementFocusRing(paintInfo); |
-} |
- |
-void RenderImage::paintAreaElementFocusRing(PaintInfo& paintInfo) |
-{ |
- Document& document = this->document(); |
- |
- if (document.printing() || !document.frame()->selection().isFocusedAndActive()) |
- return; |
- |
- Element* focusedElement = document.focusedElement(); |
- if (!isHTMLAreaElement(focusedElement)) |
- return; |
- |
- 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); |
- if (path.isEmpty()) |
- return; |
- |
- RenderStyle* areaElementStyle = areaElement.computedStyle(); |
- unsigned short outlineWidth = areaElementStyle->outlineWidth(); |
- if (!outlineWidth) |
- return; |
- |
- // FIXME: Clip path instead of context when Skia pathops is ready. |
- // https://crbug.com/251206 |
- GraphicsContextStateSaver savedContext(*paintInfo.context); |
- paintInfo.context->clip(absoluteContentBox()); |
- paintInfo.context->drawFocusRing(path, outlineWidth, |
- areaElementStyle->outlineOffset(), |
- resolveColor(areaElementStyle, CSSPropertyOutlineColor)); |
+ ImagePainter(*this).paint(paintInfo, paintOffset); |
} |
void RenderImage::areaElementFocusChanged(HTMLAreaElement* areaElement) |
@@ -437,31 +298,6 @@ void RenderImage::areaElementFocusChanged(HTMLAreaElement* areaElement) |
paintInvalidationOrMarkForLayout(false, &paintInvalidationRect); |
} |
-void RenderImage::paintIntoRect(GraphicsContext* context, const LayoutRect& rect) |
-{ |
- IntRect alignedRect = pixelSnappedIntRect(rect); |
- if (!m_imageResource->hasImage() || m_imageResource->errorOccurred() || alignedRect.width() <= 0 || alignedRect.height() <= 0) |
- return; |
- |
- RefPtr<Image> img = m_imageResource->image(alignedRect.width(), alignedRect.height()); |
- if (!img || img->isNull()) |
- return; |
- |
- HTMLImageElement* imageElt = isHTMLImageElement(node()) ? toHTMLImageElement(node()) : 0; |
- CompositeOperator compositeOperator = imageElt ? imageElt->compositeOperator() : CompositeSourceOver; |
- Image* image = img.get(); |
- InterpolationQuality interpolationQuality = BoxPainter::chooseInterpolationQuality(*this, 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); |
- InterpolationQuality previousInterpolationQuality = context->imageInterpolationQuality(); |
- context->setImageInterpolationQuality(interpolationQuality); |
- context->drawImage(image, alignedRect, compositeOperator, shouldRespectImageOrientation()); |
- context->setImageInterpolationQuality(previousInterpolationQuality); |
- InspectorInstrumentation::didPaintImage(this); |
-} |
- |
bool RenderImage::boxShadowShouldBeAppliedToBackground(BackgroundBleedAvoidance bleedAvoidance, InlineFlowBox*) const |
{ |
if (!RenderBoxModelObject::boxShadowShouldBeAppliedToBackground(bleedAvoidance)) |