/*
 * Copyright (C) 2004, 2005, 2006, 2013 Apple Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
 */

#include "config.h"
#include "PDFDocumentImage.h"

#if USE(CG)

#if PLATFORM(IOS_FAMILY)
#include <CoreGraphics/CoreGraphics.h>
#include <ImageIO/ImageIO.h>
#endif

#include "GraphicsContext.h"
#include "ImageBuffer.h"
#include "ImageObserver.h"
#include "IntRect.h"
#include "Length.h"
#include "NotImplemented.h"
#include "SharedBuffer.h"
#include <CoreGraphics/CGContext.h>
#include <CoreGraphics/CGPDFDocument.h>
#include <wtf/MathExtras.h>
#include <wtf/RAMSize.h>
#include <wtf/RetainPtr.h>
#include <wtf/StdLibExtras.h>
#include <wtf/text/TextStream.h>

#if !PLATFORM(COCOA)
#include "ImageSourceCG.h"
#endif

namespace WebCore {

PDFDocumentImage::PDFDocumentImage(ImageObserver* observer)
    : Image(observer)
{
}

PDFDocumentImage::~PDFDocumentImage() = default;

String PDFDocumentImage::filenameExtension() const
{
    return "pdf";
}

FloatSize PDFDocumentImage::size(ImageOrientation) const
{
    FloatSize expandedCropBoxSize = FloatSize(expandedIntSize(m_cropBox.size()));

    if (m_rotationDegrees == 90 || m_rotationDegrees == 270)
        return expandedCropBoxSize.transposedSize();
    return expandedCropBoxSize;
}

void PDFDocumentImage::computeIntrinsicDimensions(Length& intrinsicWidth, Length& intrinsicHeight, FloatSize& intrinsicRatio)
{
    // FIXME: If we want size negotiation with PDF documents as-image, this is the place to implement it (https://bugs.webkit.org/show_bug.cgi?id=12095).
    Image::computeIntrinsicDimensions(intrinsicWidth, intrinsicHeight, intrinsicRatio);
    intrinsicRatio = FloatSize();
}

EncodedDataStatus PDFDocumentImage::dataChanged(bool allDataReceived)
{
    ASSERT(!m_document);
    if (allDataReceived && !m_document) {
        createPDFDocument();

        if (pageCount()) {
            m_hasPage = true;
            computeBoundsForCurrentPage();
        }
    }
    return m_document ? EncodedDataStatus::Complete : EncodedDataStatus::Unknown;
}

void PDFDocumentImage::setPdfImageCachingPolicy(PDFImageCachingPolicy pdfImageCachingPolicy)
{
    if (m_pdfImageCachingPolicy == pdfImageCachingPolicy)
        return;

    m_pdfImageCachingPolicy = pdfImageCachingPolicy;
    destroyDecodedData();
}

bool PDFDocumentImage::cacheParametersMatch(GraphicsContext& context, const FloatRect& dstRect, const FloatRect& srcRect) const
{
    // Old and new source rectangles have to match.
    if (srcRect != m_cachedSourceRect)
        return false;

    // Old and new scaling factors "dest / src" have to match.
    if (dstRect.size() != m_cachedDestinationRect.size())
        return false;

    // m_cachedImageRect can be moved if srcRect and dstRect.size() did not change.
    FloatRect movedCachedImageRect = m_cachedImageRect;
    movedCachedImageRect.move(FloatSize(dstRect.location() - m_cachedDestinationRect.location()));

    // movedCachedImageRect has to contain the whole dirty rectangle.
    FloatRect dirtyRect = intersection(context.clipBounds(), dstRect);
    if (!movedCachedImageRect.contains(dirtyRect))
        return false;

    // Old and new context scaling factors have to match as well.
    AffineTransform::DecomposedType decomposedTransform;
    context.getCTM(GraphicsContext::DefinitelyIncludeDeviceScale).decompose(decomposedTransform);

    AffineTransform::DecomposedType cachedDecomposedTransform;
    m_cachedTransform.decompose(cachedDecomposedTransform);
    if (decomposedTransform.scaleX != cachedDecomposedTransform.scaleX || decomposedTransform.scaleY != cachedDecomposedTransform.scaleY)
        return false;

    return true;
}

static void transformContextForPainting(GraphicsContext& context, const FloatRect& dstRect, const FloatRect& srcRect)
{
    float hScale = dstRect.width() / srcRect.width();
    float vScale = dstRect.height() / srcRect.height();

    if (hScale != vScale) {
        float minimumScale = std::max((dstRect.width() - 0.5) / srcRect.width(), (dstRect.height() - 0.5) / srcRect.height());
        float maximumScale = std::min((dstRect.width() + 0.5) / srcRect.width(), (dstRect.height() + 0.5) / srcRect.height());

        // If the difference between the two scales is due to integer rounding of image sizes,
        // use the smaller of the two original scales to ensure that the image fits inside the
        // space originally allocated for it.
        if (minimumScale <= maximumScale) {
            hScale = std::min(hScale, vScale);
            vScale = hScale;
        }
    }

    // drawPDFPage() relies on drawing the whole PDF into a context starting at (0, 0). We need
    // to transform the destination context such that srcRect of the source context will be drawn
    // in dstRect of destination context.
    context.translate(dstRect.location() - srcRect.location());
    context.scale(FloatSize(hScale, -vScale));
    context.translate(0, -srcRect.height());
}

// To avoid the jetsam on iOS, we are going to limit the size of all the PDF cachedImages to be 64MB.
static const size_t s_maxCachedImageSide = 4 * 1024;
static const size_t s_maxCachedImageArea = s_maxCachedImageSide * s_maxCachedImageSide;

static const size_t s_maxDecodedDataSize = s_maxCachedImageArea * 4;
static size_t s_allDecodedDataSize = 0;

static FloatRect cachedImageRect(GraphicsContext& context, const FloatRect& dstRect)
{
    FloatRect dirtyRect = context.clipBounds();

    // Calculate the maximum rectangle we can cache around the center of the clipping bounds.
    FloatSize maxSize = s_maxCachedImageSide / context.scaleFactor();
    FloatPoint minLocation = FloatPoint(dirtyRect.center() - maxSize / 2);

    // Ensure the clipping bounds are all included but within the bounds of the dstRect
    return intersection(unionRect(dirtyRect, FloatRect(minLocation, maxSize)), dstRect);
}

void PDFDocumentImage::decodedSizeChanged(size_t newCachedBytes)
{
    if (!m_cachedBytes && !newCachedBytes)
        return;

    if (imageObserver())
        imageObserver()->decodedSizeChanged(*this, -static_cast<long long>(m_cachedBytes) + newCachedBytes);

    ASSERT(s_allDecodedDataSize >= m_cachedBytes);
    // Update with the difference in two steps to avoid unsigned underflow subtraction.
    s_allDecodedDataSize -= m_cachedBytes;
    s_allDecodedDataSize += newCachedBytes;

    m_cachedBytes = newCachedBytes;
}

void PDFDocumentImage::updateCachedImageIfNeeded(GraphicsContext& context, const FloatRect& dstRect, const FloatRect& srcRect)
{
    // Clipped option is for testing only. Force re-caching the PDF with each draw.
    bool forceUpdateCachedImage = m_pdfImageCachingPolicy == PDFImageCachingClipBoundsOnly || !m_cachedImageBuffer;
    if (!forceUpdateCachedImage && cacheParametersMatch(context, dstRect, srcRect)) {
        // Adjust the view-port rectangles if no re-caching will happen.
        m_cachedImageRect.move(FloatSize(dstRect.location() - m_cachedDestinationRect.location()));
        m_cachedDestinationRect = dstRect;
        return;
    }

    switch (m_pdfImageCachingPolicy) {
    case PDFImageCachingDisabled:
        return;
    case PDFImageCachingBelowMemoryLimit:
        // Keep the memory used by the cached image below some threshold, otherwise WebKit process
        // will jetsam if it exceeds its memory limit. Only a rectangle from the PDF may be cached.
        m_cachedImageRect = cachedImageRect(context, dstRect);
        break;
    case PDFImageCachingClipBoundsOnly:
        m_cachedImageRect = intersection(context.clipBounds(), dstRect);
        break;
    case PDFImageCachingEnabled:
        m_cachedImageRect = dstRect;
        break;
    }

    FloatSize cachedImageSize = FloatRect(enclosingIntRect(m_cachedImageRect)).size();

    // Cache the PDF image only if the size of the new image won't exceed the cache threshold.
    if (m_pdfImageCachingPolicy == PDFImageCachingBelowMemoryLimit) {
        IntSize scaledSize = ImageBuffer::compatibleBufferSize(cachedImageSize, context);
        if (s_allDecodedDataSize + scaledSize.unclampedArea() * 4 - m_cachedBytes > s_maxDecodedDataSize) {
            destroyDecodedData();
            return;
        }
    }

    m_cachedImageBuffer = ImageBuffer::createCompatibleBuffer(cachedImageSize, context);
    if (!m_cachedImageBuffer) {
        destroyDecodedData();
        return;
    }

    auto& bufferContext = m_cachedImageBuffer->context();
    // We need to transform the coordinate system such that top-left of m_cachedImageRect will be mapped to the
    // top-left of dstRect. Although only m_cachedImageRect.size() of the image copied, the sizes of srcRect
    // and dstRect should be passed to this function because they are used to calculate the image scaling.
    transformContextForPainting(bufferContext, dstRect, FloatRect(m_cachedImageRect.location(), srcRect.size()));
    drawPDFPage(bufferContext);

    m_cachedTransform = context.getCTM(GraphicsContext::DefinitelyIncludeDeviceScale);
    m_cachedDestinationRect = dstRect;
    m_cachedSourceRect = srcRect;
    ++m_cachingCountForTesting;

    IntSize internalSize = m_cachedImageBuffer->internalSize();
    decodedSizeChanged(internalSize.unclampedArea() * 4);
}

ImageDrawResult PDFDocumentImage::draw(GraphicsContext& context, const FloatRect& dstRect, const FloatRect& srcRect, const ImagePaintingOptions& options)
{
    if (!m_document || !m_hasPage)
        return ImageDrawResult::DidNothing;

    updateCachedImageIfNeeded(context, dstRect, srcRect);

    {
        GraphicsContextStateSaver stateSaver(context);
        context.setCompositeOperation(options.compositeOperator());

        if (m_cachedImageBuffer) {
            // Draw the ImageBuffer 'm_cachedImageBuffer' to the rectangle 'm_cachedImageRect'
            // on the destination context. Since the pixels of the rectangle 'm_cachedImageRect'
            // of the source PDF was copied to 'm_cachedImageBuffer', the sizes of the source
            // and the destination rectangles will be equal and no scaling will be needed here.
            context.drawImageBuffer(*m_cachedImageBuffer, m_cachedImageRect);
        }
        else {
            transformContextForPainting(context, dstRect, srcRect);
            drawPDFPage(context);
        }
    }

    if (imageObserver())
        imageObserver()->didDraw(*this);

    return ImageDrawResult::DidDraw;
}

void PDFDocumentImage::destroyDecodedData(bool)
{
    m_cachedImageBuffer = nullptr;
    m_cachedImageRect = FloatRect();
    decodedSizeChanged(0);
}

#if !USE(PDFKIT_FOR_PDFDOCUMENTIMAGE)

void PDFDocumentImage::createPDFDocument()
{
    RetainPtr<CGDataProviderRef> dataProvider = adoptCF(CGDataProviderCreateWithCFData(data()->createCFData().get()));
    m_document = adoptCF(CGPDFDocumentCreateWithProvider(dataProvider.get()));
}

void PDFDocumentImage::computeBoundsForCurrentPage()
{
    ASSERT(pageCount() > 0);
    CGPDFPageRef cgPage = CGPDFDocumentGetPage(m_document.get(), 1);
    CGRect mediaBox = CGPDFPageGetBoxRect(cgPage, kCGPDFMediaBox);

    // Get crop box (not always there). If not, use media box.
    CGRect r = CGPDFPageGetBoxRect(cgPage, kCGPDFCropBox);
    if (!CGRectIsEmpty(r))
        m_cropBox = r;
    else
        m_cropBox = mediaBox;

    m_rotationDegrees = CGPDFPageGetRotationAngle(cgPage);
}

unsigned PDFDocumentImage::pageCount() const
{
    return CGPDFDocumentGetNumberOfPages(m_document.get());
}

static void applyRotationForPainting(GraphicsContext& context, FloatSize size, int rotationDegrees)
{
    if (rotationDegrees == 90)
        context.translate(0, size.height());
    else if (rotationDegrees == 180)
        context.translate(size);
    else if (rotationDegrees == 270)
        context.translate(size.width(), 0);

    context.rotate(-deg2rad(static_cast<float>(rotationDegrees)));
}

void PDFDocumentImage::drawPDFPage(GraphicsContext& context)
{
    applyRotationForPainting(context, size(), m_rotationDegrees);

    context.translate(-m_cropBox.location());

#if USE(DIRECT2D)
    notImplemented();
#else
    // CGPDF pages are indexed from 1.
#if PLATFORM(COCOA)
    CGContextDrawPDFPageWithAnnotations(context.platformContext(), CGPDFDocumentGetPage(m_document.get(), 1), nullptr);
#else
    CGContextDrawPDFPage(context.platformContext(), CGPDFDocumentGetPage(m_document.get(), 1));
#endif
#endif
}

#endif // !USE(PDFKIT_FOR_PDFDOCUMENTIMAGE)

#if PLATFORM(MAC)

RetainPtr<CFMutableDataRef> PDFDocumentImage::convertPostScriptDataToPDF(RetainPtr<CFDataRef>&& postScriptData)
{
    // Convert PostScript to PDF using the Quartz 2D API.
    // http://developer.apple.com/documentation/GraphicsImaging/Conceptual/drawingwithquartz2d/dq_ps_convert/chapter_16_section_1.html

    CGPSConverterCallbacks callbacks = { };
    auto converter = adoptCF(CGPSConverterCreate(0, &callbacks, 0));
    auto provider = adoptCF(CGDataProviderCreateWithCFData(postScriptData.get()));
    auto pdfData = adoptCF(CFDataCreateMutable(kCFAllocatorDefault, 0));
    auto consumer = adoptCF(CGDataConsumerCreateWithCFData(pdfData.get()));

    CGPSConverterConvert(converter.get(), provider.get(), consumer.get(), 0);
    return pdfData;
}

#endif

void PDFDocumentImage::dump(TextStream& ts) const
{
    Image::dump(ts);
    ts.dumpProperty("page-count", pageCount());
    ts.dumpProperty("crop-box", m_cropBox);
    if (m_rotationDegrees)
        ts.dumpProperty("rotation", m_rotationDegrees);
}

}

#endif // USE(CG)
