/*
 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
 *           (C) 1999 Antti Koivisto (koivisto@kde.org)
 *           (C) 2000 Dirk Mueller (mueller@kde.org)
 *           (C) 2006 Allan Sandfeld Jensen (kde@carewolf.com)
 *           (C) 2006 Samuel Weinig (sam.weinig@gmail.com)
 * Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009, 2010, 2011 Apple Inc. All rights reserved.
 * Copyright (C) 2010 Google Inc. All rights reserved.
 * Copyright (C) Research In Motion Limited 2011-2012. All rights reserved.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public License
 * along with this library; see the file COPYING.LIB.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 *
 */

#include "config.h"
#include "RenderImage.h"

#include "AXObjectCache.h"
#include "BitmapImage.h"
#include "CachedImage.h"
#include "FocusController.h"
#include "FontCache.h"
#include "FontCascade.h"
#include "Frame.h"
#include "FrameSelection.h"
#include "GeometryUtilities.h"
#include "GraphicsContext.h"
#include "HTMLAreaElement.h"
#include "HTMLImageElement.h"
#include "HTMLInputElement.h"
#include "HTMLMapElement.h"
#include "HTMLNames.h"
#include "HitTestResult.h"
#include "InlineElementBox.h"
#include "Page.h"
#include "PaintInfo.h"
#include "RenderFragmentedFlow.h"
#include "RenderImageResourceStyleImage.h"
#include "RenderLayoutState.h"
#include "RenderTheme.h"
#include "RenderView.h"
#include "RuntimeEnabledFeatures.h"
#include "SVGImage.h"
#include "Settings.h"
#include <wtf/IsoMallocInlines.h>
#include <wtf/StackStats.h>

#if PLATFORM(IOS_FAMILY)
#include "LogicalSelectionOffsetCaches.h"
#include "SelectionRect.h"
#endif

#if USE(CG)
#include "PDFDocumentImage.h"
#include "Settings.h"
#endif

namespace WebCore {

WTF_MAKE_ISO_ALLOCATED_IMPL(RenderImage);

#if PLATFORM(IOS_FAMILY)
// FIXME: This doesn't behave correctly for floating or positioned images, but WebCore doesn't handle those well
// during selection creation yet anyway.
// FIXME: We can't tell whether or not we contain the start or end of the selected Range using only the offsets
// of the start and end, we need to know the whole Position.
void RenderImage::collectSelectionRects(Vector<SelectionRect>& rects, unsigned, unsigned)
{
    RenderBlock* containingBlock = this->containingBlock();

    IntRect imageRect;
    // FIXME: It doesn't make sense to package line bounds into SelectionRects. We should find
    // the right and left extent of the selection once for the entire selected Range, perhaps
    // using the Range's common ancestor.
    IntRect lineExtentRect;
    bool isFirstOnLine = false;
    bool isLastOnLine = false;

    InlineBox* inlineBox = inlineBoxWrapper();
    if (!inlineBox) {
        // This is a block image.
        imageRect = IntRect(0, 0, width(), height());
        isFirstOnLine = true;
        isLastOnLine = true;
        lineExtentRect = imageRect;
        if (containingBlock->isHorizontalWritingMode()) {
            lineExtentRect.setX(containingBlock->x());
            lineExtentRect.setWidth(containingBlock->width());
        } else {
            lineExtentRect.setY(containingBlock->y());
            lineExtentRect.setHeight(containingBlock->height());
        }
    } else {
        LayoutUnit selectionTop = !containingBlock->style().isFlippedBlocksWritingMode() ? inlineBox->root().selectionTop() - logicalTop() : logicalBottom() - inlineBox->root().selectionBottom();
        imageRect = IntRect(0,  selectionTop, logicalWidth(), inlineBox->root().selectionHeight());
        isFirstOnLine = !inlineBox->previousOnLineExists();
        isLastOnLine = !inlineBox->nextOnLineExists();
        LogicalSelectionOffsetCaches cache(*containingBlock);
        LayoutUnit leftOffset = containingBlock->logicalLeftSelectionOffset(*containingBlock, LayoutUnit(inlineBox->logicalTop()), cache);
        LayoutUnit rightOffset = containingBlock->logicalRightSelectionOffset(*containingBlock, LayoutUnit(inlineBox->logicalTop()), cache);
        lineExtentRect = IntRect(leftOffset - logicalLeft(), imageRect.y(), rightOffset - leftOffset, imageRect.height());
        if (!inlineBox->isHorizontal()) {
            imageRect = imageRect.transposedRect();
            lineExtentRect = lineExtentRect.transposedRect();
        }
    }

    bool isFixed = false;
    IntRect absoluteBounds = localToAbsoluteQuad(FloatRect(imageRect), UseTransforms, &isFixed).enclosingBoundingBox();
    IntRect lineExtentBounds = localToAbsoluteQuad(FloatRect(lineExtentRect)).enclosingBoundingBox();
    if (!containingBlock->isHorizontalWritingMode())
        lineExtentBounds = lineExtentBounds.transposedRect();

    // FIXME: We should consider either making SelectionRect a struct or better organize its optional fields into
    // an auxiliary struct to simplify its initialization.
    rects.append(SelectionRect(absoluteBounds, containingBlock->style().direction(), lineExtentBounds.x(), lineExtentBounds.maxX(), lineExtentBounds.maxY(), 0, false /* line break */, isFirstOnLine, isLastOnLine, false /* contains start */, false /* contains end */, containingBlock->style().isHorizontalWritingMode(), isFixed, false /* ruby text */, view().pageNumberForBlockProgressionOffset(absoluteBounds.x())));
}
#endif

using namespace HTMLNames;

RenderImage::RenderImage(Element& element, RenderStyle&& style, StyleImage* styleImage, const float imageDevicePixelRatio)
    : RenderReplaced(element, WTFMove(style), IntSize())
    , m_imageResource(styleImage ? makeUnique<RenderImageResourceStyleImage>(*styleImage) : makeUnique<RenderImageResource>())
    , m_imageDevicePixelRatio(imageDevicePixelRatio)
{
    updateAltText();
    if (is<HTMLImageElement>(element))
        m_hasShadowControls = downcast<HTMLImageElement>(element).hasShadowControls();
}

RenderImage::RenderImage(Document& document, RenderStyle&& style, StyleImage* styleImage)
    : RenderReplaced(document, WTFMove(style), IntSize())
    , m_imageResource(styleImage ? makeUnique<RenderImageResourceStyleImage>(*styleImage) : makeUnique<RenderImageResource>())
{
}

RenderImage::~RenderImage()
{
    // Do not add any code here. Add it to willBeDestroyed() instead.
}

void RenderImage::willBeDestroyed()
{
    imageResource().shutdown();
    RenderReplaced::willBeDestroyed();
}

// 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;
static const int maxAltTextHeight = 256;

IntSize RenderImage::imageSizeForError(CachedImage* newImage) const
{
    ASSERT_ARG(newImage, newImage);
    ASSERT_ARG(newImage, newImage->imageForRenderer(this));

    FloatSize imageSize;
    if (newImage->willPaintBrokenImage()) {
        std::pair<Image*, float> brokenImageAndImageScaleFactor = newImage->brokenImage(document().deviceScaleFactor());
        imageSize = brokenImageAndImageScaleFactor.first->size();
        imageSize.scale(1 / brokenImageAndImageScaleFactor.second);
    } else
        imageSize = newImage->imageForRenderer(this)->size();

    // imageSize() returns 0 for the error image. We need the true size of the
    // error image, so we have to get it by grabbing image() directly.
    return IntSize(paddingWidth + imageSize.width() * style().effectiveZoom(), paddingHeight + imageSize.height() * style().effectiveZoom());
}

// Sets the image height and width to fit the alt text.  Returns true if the
// image size changed.
ImageSizeChangeType RenderImage::setImageSizeForAltText(CachedImage* newImage /* = 0 */)
{
    IntSize imageSize;
    if (newImage && newImage->imageForRenderer(this))
        imageSize = imageSizeForError(newImage);
    else if (!m_altText.isEmpty() || newImage) {
        // If we'll be displaying either text or an image, add a little padding.
        imageSize = IntSize(paddingWidth, paddingHeight);
    }

    // we have an alt and the user meant it (its not a text we invented)
    if (!m_altText.isEmpty()) {
        const FontCascade& font = style().fontCascade();
        IntSize paddedTextSize(paddingWidth + std::min(ceilf(font.width(RenderBlock::constructTextRun(m_altText, style()))), maxAltTextWidth), paddingHeight + std::min(font.fontMetrics().height(), maxAltTextHeight));
        imageSize = imageSize.expandedTo(paddedTextSize);
    }

    if (imageSize == intrinsicSize())
        return ImageSizeChangeNone;

    setIntrinsicSize(imageSize);
    return ImageSizeChangeForAltText;
}

bool RenderImage::isEditableImage() const
{
    if (!element() || !is<HTMLImageElement>(element()))
        return false;
    return downcast<HTMLImageElement>(element())->hasEditableImageAttribute();
}
    
bool RenderImage::requiresLayer() const
{
    if (RenderReplaced::requiresLayer())
        return true;
    
    if (isEditableImage())
        return true;
    
    return false;
}

void RenderImage::styleWillChange(StyleDifference diff, const RenderStyle& newStyle)
{
    if (!hasInitializedStyle())
        imageResource().initialize(*this);
    RenderReplaced::styleWillChange(diff, newStyle);
}

void RenderImage::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
{
    RenderReplaced::styleDidChange(diff, oldStyle);
    if (m_needsToSetSizeForAltText) {
        if (!m_altText.isEmpty() && setImageSizeForAltText(cachedImage()))
            repaintOrMarkForLayout(ImageSizeChangeForAltText);
        m_needsToSetSizeForAltText = false;
    }
#if ENABLE(CSS_IMAGE_ORIENTATION)
    if (diff == StyleDifference::Layout && oldStyle->imageOrientation() != style().imageOrientation())
        return repaintOrMarkForLayout(ImageSizeChangeNone);
#endif

#if ENABLE(CSS_IMAGE_RESOLUTION)
    if (diff == StyleDifference::Layout
        && (oldStyle->imageResolution() != style().imageResolution()
            || oldStyle->imageResolutionSnap() != style().imageResolutionSnap()
            || oldStyle->imageResolutionSource() != style().imageResolutionSource()))
        repaintOrMarkForLayout(ImageSizeChangeNone);
#endif
}

void RenderImage::imageChanged(WrappedImagePtr newImage, const IntRect* rect)
{
    if (renderTreeBeingDestroyed())
        return;

    if (hasVisibleBoxDecorations() || hasMask() || hasShapeOutside())
        RenderReplaced::imageChanged(newImage, rect);

    if (newImage != imageResource().imagePtr() || !newImage)
        return;

    // At a zoom level of 1 the image is guaranteed to have an integer size.
    incrementVisuallyNonEmptyPixelCountIfNeeded(flooredIntSize(imageResource().imageSize(1.0f)));

    ImageSizeChangeType imageSizeChange = ImageSizeChangeNone;

    // Set image dimensions, taking into account the size of the alt text.
    if (imageResource().errorOccurred()) {
        if (!m_altText.isEmpty() && document().hasPendingStyleRecalc()) {
            ASSERT(element());
            if (element()) {
                m_needsToSetSizeForAltText = true;
                element()->invalidateStyle();
            }
            return;
        }
        imageSizeChange = setImageSizeForAltText(cachedImage());
    }
    repaintOrMarkForLayout(imageSizeChange, rect);
    if (AXObjectCache* cache = document().existingAXObjectCache())
        cache->deferRecomputeIsIgnoredIfNeeded(element());
}

void RenderImage::updateIntrinsicSizeIfNeeded(const LayoutSize& newSize)
{
    if (imageResource().errorOccurred() || !m_imageResource->cachedImage())
        return;
    setIntrinsicSize(newSize);
}

void RenderImage::updateInnerContentRect()
{
    // Propagate container size to image resource.
    IntSize containerSize(replacedContentRect().size());
    if (!containerSize.isEmpty()) {
        URL imageSourceURL;
        if (HTMLImageElement* imageElement = is<HTMLImageElement>(element()) ? downcast<HTMLImageElement>(element()) : nullptr)
            imageSourceURL = document().completeURL(imageElement->imageSourceURL());
        imageResource().setContainerContext(containerSize, imageSourceURL);
    }
}

void RenderImage::repaintOrMarkForLayout(ImageSizeChangeType imageSizeChange, const IntRect* rect)
{
#if ENABLE(CSS_IMAGE_RESOLUTION)
    double scale = style().imageResolution();
    if (style().imageResolutionSnap() == ImageResolutionSnap::Pixels)
        scale = roundForImpreciseConversion<int>(scale);
    if (scale <= 0)
        scale = 1;
    LayoutSize newIntrinsicSize = imageResource().intrinsicSize(style().effectiveZoom() / scale);
#else
    LayoutSize newIntrinsicSize = imageResource().intrinsicSize(style().effectiveZoom());
#endif
    LayoutSize oldIntrinsicSize = intrinsicSize();

    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.
    // layout() will be called after we are inserted in the tree which will take care of
    // what we are doing here.
    if (!containingBlock())
        return;

    bool imageSourceHasChangedSize = oldIntrinsicSize != newIntrinsicSize || imageSizeChange != ImageSizeChangeNone;

    if (imageSourceHasChangedSize && setNeedsLayoutIfNeededAfterIntrinsicSizeChange())
        return;

    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
        // may need values from the containing block, though, so make sure that we're not too
        // early. It may be that layout hasn't even taken place once yet.

        // FIXME: we should not have to trigger another call to setContainerContextForRenderer()
        // from here, since it's already being done during layout.
        updateInnerContentRect();
    }

    LayoutRect repaintRect = contentBoxRect();
    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.intersect(enclosingIntRect(mapRect(*rect, FloatRect(FloatPoint(), imageResource().imageSize(1.0f)), repaintRect)));
    }
        
    repaintRectangle(repaintRect);

    // Tell any potential compositing layers that the image needs updating.
    contentChanged(ImageChanged);
}

void RenderImage::notifyFinished(CachedResource& newImage)
{
    if (renderTreeBeingDestroyed())
        return;

    invalidateBackgroundObscurationStatus();

    if (&newImage == cachedImage()) {
        // tell any potential compositing layers
        // that the image is done and they can reference it directly.
        contentChanged(ImageChanged);
    }

    if (is<HTMLImageElement>(element()))
        page().didFinishLoadingImageForElement(downcast<HTMLImageElement>(*element()));
}

void RenderImage::setImageDevicePixelRatio(float factor)
{
    if (m_imageDevicePixelRatio == factor)
        return;

    m_imageDevicePixelRatio = factor;
    intrinsicSizeChanged();
}

bool RenderImage::isShowingMissingOrImageError() const
{
    return !imageResource().cachedImage() || imageResource().errorOccurred();
}

bool RenderImage::isShowingAltText() const
{
    return isShowingMissingOrImageError() && !m_altText.isEmpty();
}

bool RenderImage::shouldDisplayBrokenImageIcon() const
{
    return imageResource().errorOccurred();
}

bool RenderImage::hasNonBitmapImage() const
{
    if (!imageResource().cachedImage())
        return false;

    Image* image = cachedImage()->imageForRenderer(this);
    return image && !is<BitmapImage>(image);
}

void RenderImage::paintIncompleteImageOutline(PaintInfo& paintInfo, LayoutPoint paintOffset, LayoutUnit borderWidth) const
{
    auto contentSize = this->contentSize();
    if (contentSize.width() <= 2 || contentSize.height() <= 2)
        return;

    auto leftBorder = borderLeft();
    auto topBorder = borderTop();
    auto leftPadding = paddingLeft();
    auto topPadding = paddingTop();

    // Draw an outline rect where the image should be.
    GraphicsContext& context = paintInfo.context();
    context.setStrokeStyle(SolidStroke);
    context.setStrokeColor(Color::lightGray);
    context.setFillColor(Color::transparent);
    context.drawRect(snapRectToDevicePixels(LayoutRect({ paintOffset.x() + leftBorder + leftPadding, paintOffset.y() + topBorder + topPadding }, contentSize), document().deviceScaleFactor()), borderWidth);
}

void RenderImage::paintReplaced(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
{
    GraphicsContext& context = paintInfo.context();
    if (context.invalidatingImagesWithAsyncDecodes()) {
        if (cachedImage() && cachedImage()->isClientWaitingForAsyncDecoding(*this))
            cachedImage()->removeAllClientsWaitingForAsyncDecoding();
        return;
    }

    auto contentSize = this->contentSize();
    float deviceScaleFactor = document().deviceScaleFactor();
    LayoutUnit missingImageBorderWidth(1 / deviceScaleFactor);

    if (!imageResource().cachedImage() || shouldDisplayBrokenImageIcon()) {
        if (paintInfo.phase == PaintPhase::Selection)
            return;

        if (paintInfo.phase == PaintPhase::Foreground)
            page().addRelevantUnpaintedObject(this, visualOverflowRect());

        paintIncompleteImageOutline(paintInfo, paintOffset, missingImageBorderWidth);

        if (contentSize.width() > 2 && contentSize.height() > 2) {
            LayoutUnit leftBorder = borderLeft();
            LayoutUnit topBorder = borderTop();
            LayoutUnit leftPad = paddingLeft();
            LayoutUnit topPad = paddingTop();

            bool errorPictureDrawn = false;
            LayoutSize imageOffset;
            // When calculating the usable dimensions, exclude the pixels of
            // the outline rect so the error image/alt text doesn't draw on it.
            LayoutSize usableSize = contentSize - LayoutSize(2 * missingImageBorderWidth, 2 * missingImageBorderWidth);

            RefPtr<Image> image = imageResource().image();

            if (shouldDisplayBrokenImageIcon() && !image->isNull() && usableSize.width() >= image->width() && usableSize.height() >= image->height()) {
                // Call brokenImage() explicitly to ensure we get the broken image icon at the appropriate resolution.
                std::pair<Image*, float> brokenImageAndImageScaleFactor = cachedImage()->brokenImage(deviceScaleFactor);
                image = brokenImageAndImageScaleFactor.first;
                FloatSize imageSize = image->size();
                imageSize.scale(1 / brokenImageAndImageScaleFactor.second);

                // Center the error image, accounting for border and padding.
                LayoutUnit centerX { (usableSize.width() - imageSize.width()) / 2 };
                if (centerX < 0)
                    centerX = 0;
                LayoutUnit centerY { (usableSize.height() - imageSize.height()) / 2 };
                if (centerY < 0)
                    centerY = 0;
                imageOffset = LayoutSize(leftBorder + leftPad + centerX + missingImageBorderWidth, topBorder + topPad + centerY + missingImageBorderWidth);

                context.drawImage(*image, snapRectToDevicePixels(LayoutRect(paintOffset + imageOffset, imageSize), deviceScaleFactor), { imageOrientation() });
                errorPictureDrawn = true;
            }

            if (!m_altText.isEmpty()) {
                String text = document().displayStringModifiedByEncoding(m_altText);
                context.setFillColor(style().visitedDependentColorWithColorFilter(CSSPropertyColor));
                const FontCascade& font = style().fontCascade();
                const FontMetrics& fontMetrics = font.fontMetrics();
                LayoutUnit ascent = fontMetrics.ascent();
                LayoutPoint altTextOffset = paintOffset;
                altTextOffset.move(leftBorder + leftPad + (paddingWidth / 2) - missingImageBorderWidth, topBorder + topPad + ascent + (paddingHeight / 2) - missingImageBorderWidth);

                // Only draw the alt text if it'll fit within the content box,
                // and only if it fits above the error image.
                TextRun textRun = RenderBlock::constructTextRun(text, style());
                LayoutUnit textWidth { font.width(textRun) };
                if (errorPictureDrawn) {
                    if (usableSize.width() >= textWidth && fontMetrics.height() <= imageOffset.height())
                        context.drawText(font, textRun, altTextOffset);
                } else if (usableSize.width() >= textWidth && usableSize.height() >= fontMetrics.height())
                    context.drawText(font, textRun, altTextOffset);
            }
        }
        return;
    }
    
    if (contentSize.isEmpty())
        return;

    bool showBorderForIncompleteImage = settings().incompleteImageBorderEnabled();

    RefPtr<Image> img = imageResource().image(flooredIntSize(contentSize));
    if (!img || img->isNull()) {
        if (showBorderForIncompleteImage)
            paintIncompleteImageOutline(paintInfo, paintOffset, missingImageBorderWidth);

        if (paintInfo.phase == PaintPhase::Foreground)
            page().addRelevantUnpaintedObject(this, visualOverflowRect());
        return;
    }

    LayoutRect contentBoxRect = this->contentBoxRect();
    contentBoxRect.moveBy(paintOffset);
    LayoutRect replacedContentRect = this->replacedContentRect();
    replacedContentRect.moveBy(paintOffset);
    bool clip = !contentBoxRect.contains(replacedContentRect);
    GraphicsContextStateSaver stateSaver(context, clip);
    if (clip)
        context.clip(contentBoxRect);

    ImageDrawResult result = paintIntoRect(paintInfo, snapRectToDevicePixels(replacedContentRect, deviceScaleFactor));

    if (showBorderForIncompleteImage && (result != ImageDrawResult::DidDraw || (cachedImage() && cachedImage()->isLoading())))
        paintIncompleteImageOutline(paintInfo, paintOffset, missingImageBorderWidth);
    
    if (cachedImage() && paintInfo.phase == PaintPhase::Foreground) {
        // For now, count images as unpainted if they are still progressively loading. We may want 
        // to refine this in the future to account for the portion of the image that has painted.
        LayoutRect visibleRect = intersection(replacedContentRect, contentBoxRect);
        if (cachedImage()->isLoading() || result == ImageDrawResult::DidRequestDecoding)
            page().addRelevantUnpaintedObject(this, visibleRect);
        else
            page().addRelevantRepaintedObject(this, visibleRect);
    }
}

void RenderImage::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
{
    RenderReplaced::paint(paintInfo, paintOffset);
    
    if (paintInfo.phase == PaintPhase::Outline)
        paintAreaElementFocusRing(paintInfo, paintOffset);
}
    
void RenderImage::paintAreaElementFocusRing(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
{
#if !PLATFORM(IOS_FAMILY) || ENABLE(FULL_KEYBOARD_ACCESS)
    if (document().printing() || !frame().selection().isFocusedAndActive())
        return;
    
    if (paintInfo.context().paintingDisabled() && !paintInfo.context().performingPaintInvalidation())
        return;

    Element* focusedElement = document().focusedElement();
    if (!is<HTMLAreaElement>(focusedElement))
        return;

    HTMLAreaElement& areaElement = downcast<HTMLAreaElement>(*focusedElement);
    if (areaElement.imageElement() != element())
        return;

    auto* areaElementStyle = areaElement.computedStyle();
    if (!areaElementStyle)
        return;

    float outlineWidth = areaElementStyle->outlineWidth();
    if (!outlineWidth)
        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.
    auto path = areaElement.computePathForFocusRing(size());
    if (path.isEmpty())
        return;

    AffineTransform zoomTransform;
    zoomTransform.scale(style().effectiveZoom());
    path.transform(zoomTransform);

    auto adjustedOffset = paintOffset;
    adjustedOffset.moveBy(location());
    path.translate(toFloatSize(adjustedOffset));

#if PLATFORM(MAC)
    bool needsRepaint;
    paintInfo.context().drawFocusRing(path, page().focusController().timeSinceFocusWasSet().seconds(), needsRepaint, RenderTheme::singleton().focusRingColor(styleColorOptions()));
    if (needsRepaint)
        page().focusController().setFocusedElementNeedsRepaint();
#else
    paintInfo.context().drawFocusRing(path, outlineWidth, areaElementStyle->outlineOffset(), areaElementStyle->visitedDependentColorWithColorFilter(CSSPropertyOutlineColor));
#endif // PLATFORM(MAC)
#else
    UNUSED_PARAM(paintInfo);
    UNUSED_PARAM(paintOffset);
#endif // ENABLE(FULL_KEYBOARD_ACCESS)
}

void RenderImage::areaElementFocusChanged(HTMLAreaElement* element)
{
    ASSERT_UNUSED(element, element->imageElement() == this->element());

    // It would be more efficient to only repaint the focus ring rectangle
    // for the passed-in area element. That would require adding functions
    // to the area element class.
    repaint();
}

ImageDrawResult RenderImage::paintIntoRect(PaintInfo& paintInfo, const FloatRect& rect)
{
    if (!imageResource().cachedImage() || imageResource().errorOccurred() || rect.width() <= 0 || rect.height() <= 0)
        return ImageDrawResult::DidNothing;

    RefPtr<Image> img = imageResource().image(flooredIntSize(rect.size()));
    if (!img || img->isNull())
        return ImageDrawResult::DidNothing;

    HTMLImageElement* imageElement = is<HTMLImageElement>(element()) ? downcast<HTMLImageElement>(element()) : nullptr;

    // FIXME: Document when image != img.get().
    Image* image = imageResource().image().get();

#if USE(CG)
    if (is<PDFDocumentImage>(image))
        downcast<PDFDocumentImage>(*image).setPdfImageCachingPolicy(settings().pdfImageCachingPolicy());
#endif

    if (is<BitmapImage>(image))
        downcast<BitmapImage>(*image).updateFromSettings(settings());

    ImagePaintingOptions options = {
        imageElement ? imageElement->compositeOperator() : CompositeSourceOver,
        decodingModeForImageDraw(*image, paintInfo),
        imageOrientation(),
        image ? chooseInterpolationQuality(paintInfo.context(), *image, image, LayoutSize(rect.size())) : InterpolationDefault
    };

    auto drawResult = paintInfo.context().drawImage(*img, rect, options);
    if (drawResult == ImageDrawResult::DidRequestDecoding)
        imageResource().cachedImage()->addClientWaitingForAsyncDecoding(*this);

#if USE(SYSTEM_PREVIEW)
    if (imageElement && imageElement->isSystemPreviewImage() && drawResult == ImageDrawResult::DidDraw && RuntimeEnabledFeatures::sharedFeatures().systemPreviewEnabled())
        theme().paintSystemPreviewBadge(*img, paintInfo, rect);
#endif

    return drawResult;
}

bool RenderImage::boxShadowShouldBeAppliedToBackground(const LayoutPoint& paintOffset, BackgroundBleedAvoidance bleedAvoidance, InlineFlowBox*) const
{
    if (!RenderBoxModelObject::boxShadowShouldBeAppliedToBackground(paintOffset, bleedAvoidance))
        return false;

    return !const_cast<RenderImage*>(this)->backgroundIsKnownToBeObscured(paintOffset);
}

bool RenderImage::foregroundIsKnownToBeOpaqueInRect(const LayoutRect& localRect, unsigned maxDepthToTest) const
{
    UNUSED_PARAM(maxDepthToTest);
    if (!imageResource().cachedImage() || imageResource().errorOccurred())
        return false;
    if (cachedImage() && !cachedImage()->isLoaded())
        return false;
    if (!contentBoxRect().contains(localRect))
        return false;
    FillBox backgroundClip = style().backgroundClip();
    // Background paints under borders.
    if (backgroundClip == FillBox::Border && style().hasBorder() && !borderObscuresBackground())
        return false;
    // Background shows in padding area.
    if ((backgroundClip == FillBox::Border || backgroundClip == FillBox::Padding) && style().hasPadding())
        return false;
    // Object-fit may leave parts of the content box empty.
    ObjectFit objectFit = style().objectFit();
    if (objectFit != ObjectFit::Fill && objectFit != ObjectFit::Cover)
        return false;

    LengthPoint objectPosition = style().objectPosition();
    if (objectPosition != RenderStyle::initialObjectPosition())
        return false;

    // Check for image with alpha.
    return cachedImage() && cachedImage()->currentFrameKnownToBeOpaque(this);
}

bool RenderImage::computeBackgroundIsKnownToBeObscured(const LayoutPoint& paintOffset)
{
    if (!hasBackground())
        return false;
    
    LayoutRect paintedExtent;
    if (!getBackgroundPaintedExtent(paintOffset, paintedExtent))
        return false;
    return foregroundIsKnownToBeOpaqueInRect(paintedExtent, 0);
}

LayoutUnit RenderImage::minimumReplacedHeight() const
{
    return imageResource().errorOccurred() ? intrinsicSize().height() : 0_lu;
}

HTMLMapElement* RenderImage::imageMap() const
{
    auto* imageElement = element();
    if (!imageElement || !is<HTMLImageElement>(imageElement))
        return nullptr;
    return downcast<HTMLImageElement>(imageElement)->associatedMapElement();
}

bool RenderImage::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction hitTestAction)
{
    HitTestResult tempResult(result.hitTestLocation());
    bool inside = RenderReplaced::nodeAtPoint(request, tempResult, locationInContainer, accumulatedOffset, hitTestAction);

    if (tempResult.innerNode() && element()) {
        if (HTMLMapElement* map = imageMap()) {
            LayoutRect contentBox = contentBoxRect();
            float scaleFactor = 1 / style().effectiveZoom();
            LayoutPoint mapLocation = locationInContainer.point() - toLayoutSize(accumulatedOffset) - locationOffset() - toLayoutSize(contentBox.location());
            mapLocation.scale(scaleFactor);

            if (map->mapMouseEvent(mapLocation, contentBox.size(), tempResult))
                tempResult.setInnerNonSharedNode(element());
        }
    }

    if (!inside && request.resultIsElementList())
        result.append(tempResult, request);
    if (inside)
        result = tempResult;
    return inside;
}

void RenderImage::updateAltText()
{
    if (!element())
        return;

    if (is<HTMLInputElement>(*element()))
        m_altText = downcast<HTMLInputElement>(*element()).altText();
    else if (is<HTMLImageElement>(*element()))
        m_altText = downcast<HTMLImageElement>(*element()).altText();
}

bool RenderImage::canHaveChildren() const
{
#if !ENABLE(SERVICE_CONTROLS)
    return false;
#else
    return m_hasShadowControls;
#endif
}

void RenderImage::layout()
{
    // Recomputing overflow is required only when child content is present. 
    if (needsSimplifiedNormalFlowLayoutOnly() && !m_hasShadowControls) {
        clearNeedsLayout();
        return;
    }

    StackStats::LayoutCheckPoint layoutCheckPoint;

    LayoutSize oldSize = contentBoxRect().size();
    RenderReplaced::layout();

    updateInnerContentRect();

    if (m_hasShadowControls)
        layoutShadowControls(oldSize);
}

void RenderImage::layoutShadowControls(const LayoutSize& oldSize)
{
    // We expect a single containing box under the UA shadow root.
    ASSERT(firstChild() == lastChild());

    auto* controlsRenderer = downcast<RenderBox>(firstChild());
    if (!controlsRenderer)
        return;
    
    bool controlsNeedLayout = controlsRenderer->needsLayout();
    // If the region chain has changed we also need to relayout the controls to update the region box info.
    // FIXME: We can do better once we compute region box info for RenderReplaced, not only for RenderBlock.
    const RenderFragmentedFlow* fragmentedFlow = enclosingFragmentedFlow();
    if (fragmentedFlow && !controlsNeedLayout) {
        if (fragmentedFlow->pageLogicalSizeChanged())
            controlsNeedLayout = true;
    }

    LayoutSize newSize = contentBoxRect().size();
    if (newSize == oldSize && !controlsNeedLayout)
        return;

    // When calling layout() on a child node, a parent must either push a LayoutStateMaintainter, or 
    // instantiate LayoutStateDisabler. Since using a LayoutStateMaintainer is slightly more efficient,
    // and this method might be called many times per second during video playback, use a LayoutStateMaintainer:
    LayoutStateMaintainer statePusher(*this, locationOffset(), hasTransform() || hasReflection() || style().isFlippedBlocksWritingMode());

    if (shadowControlsNeedCustomLayoutMetrics()) {
        controlsRenderer->setLocation(LayoutPoint(borderLeft(), borderTop()) + LayoutSize(paddingLeft(), paddingTop()));
        controlsRenderer->mutableStyle().setHeight(Length(newSize.height(), Fixed));
        controlsRenderer->mutableStyle().setWidth(Length(newSize.width(), Fixed));
    }

    controlsRenderer->setNeedsLayout(MarkOnlyThis);
    controlsRenderer->layout();
    clearChildNeedsLayout();
}

void RenderImage::computeIntrinsicRatioInformation(FloatSize& intrinsicSize, double& intrinsicRatio) const
{
    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() && (imageResource().imageHasRelativeWidth() || imageResource().imageHasRelativeHeight())) {
        RenderObject* containingBlock = isOutOfFlowPositioned() ? container() : this->containingBlock();
        if (is<RenderBox>(*containingBlock)) {
            auto& box = downcast<RenderBox>(*containingBlock);
            intrinsicSize.setWidth(box.availableLogicalWidth());
            intrinsicSize.setHeight(box.availableLogicalHeight(IncludeMarginBorderPadding));
        }
    }

    // Don't compute an intrinsic ratio to preserve historical WebKit behavior if we're painting alt text and/or a broken image.
    if (shouldDisplayBrokenImageIcon()) {
        intrinsicRatio = 1;
        return;
    }
}

bool RenderImage::needsPreferredWidthsRecalculation() const
{
    if (RenderReplaced::needsPreferredWidthsRecalculation())
        return true;
    return embeddedContentBox();
}

RenderBox* RenderImage::embeddedContentBox() const
{
    CachedImage* cachedImage = this->cachedImage();
    if (cachedImage && is<SVGImage>(cachedImage->image()))
        return downcast<SVGImage>(*cachedImage->image()).embeddedContentBox();

    return nullptr;
}

void RenderImage::incrementVisuallyNonEmptyPixelCountIfNeeded(const IntSize& size)
{
    if (m_didIncrementVisuallyNonEmptyPixelCount)
        return;

    view().frameView().incrementVisuallyNonEmptyPixelCount(size);
    m_didIncrementVisuallyNonEmptyPixelCount = true;
}

} // namespace WebCore
