예제 #1
0
void PDFDocumentImage::updateCachedImageIfNeeded(GraphicsContext* context, const FloatRect& dstRect, const FloatRect& srcRect)
{
    // If we have an existing image, reuse it if we're doing a low-quality paint, even if cache parameters don't match;
    // we'll rerender when we do the subsequent high-quality paint.
    InterpolationQuality interpolationQuality = context->imageInterpolationQuality();
    bool useLowQualityInterpolation = interpolationQuality == InterpolationNone || interpolationQuality == InterpolationLow;

    if (!m_cachedImageBuffer || (!cacheParametersMatch(context, dstRect, srcRect) && !useLowQualityInterpolation)) {
        m_cachedImageBuffer = context->createCompatibleBuffer(enclosingIntRect(dstRect).size());
        if (!m_cachedImageBuffer)
            return;
        GraphicsContext* bufferContext = m_cachedImageBuffer->context();
        if (!bufferContext) {
            m_cachedImageBuffer = nullptr;
            return;
        }

        transformContextForPainting(bufferContext, dstRect, srcRect);
        drawPDFPage(bufferContext);

        m_cachedTransform = context->getCTM(GraphicsContext::DefinitelyIncludeDeviceScale);
        m_cachedDestinationSize = dstRect.size();
        m_cachedSourceRect = srcRect;

        IntSize internalSize = m_cachedImageBuffer->internalSize();
        size_t oldCachedBytes = m_cachedBytes;
        m_cachedBytes = internalSize.width() * internalSize.height() * 4;

        if (imageObserver())
            imageObserver()->decodedSizeChanged(this, safeCast<int>(m_cachedBytes) - safeCast<int>(oldCachedBytes));
    }
}
예제 #2
0
void PDFDocumentImage::updateCachedImageIfNeeded(GraphicsContext& context, const FloatRect& dstRect, const FloatRect& srcRect)
{
#if PLATFORM(IOS)
    // On iOS, if the physical memory is less than 1GB, do not allocate more than 16MB for the PDF cachedImage.
    const size_t memoryThreshold = WTF::GB;
    const size_t maxArea = 16 * WTF::MB / 4; // 16 MB maximum size, divided by a rough cost of 4 bytes per pixel of area.

    if (ramSize() <= memoryThreshold && ImageBuffer::compatibleBufferSize(dstRect.size(), context).area() >= maxArea) {
        m_cachedImageBuffer = nullptr;
        return;
    }

    // On iOS, some clients use low-quality image interpolation always, which throws off this optimization,
    // as we never get the subsequent high-quality paint. Since live resize is rare on iOS, disable the optimization.
    // FIXME (136593): It's also possible to do the wrong thing here if CSS specifies low-quality interpolation via the "image-rendering"
    // property, on all platforms. We should only do this optimization if we're actually in a ImageQualityController live resize,
    // and are guaranteed to do a high-quality paint later.
    bool repaintIfNecessary = true;
#else
    // If we have an existing image, reuse it if we're doing a low-quality paint, even if cache parameters don't match;
    // we'll rerender when we do the subsequent high-quality paint.
    InterpolationQuality interpolationQuality = context.imageInterpolationQuality();
    bool repaintIfNecessary = interpolationQuality != InterpolationNone && interpolationQuality != InterpolationLow;
#endif

    if (m_cachedImageBuffer && (!repaintIfNecessary || cacheParametersMatch(context, dstRect, srcRect)))
        return;

    m_cachedImageBuffer = ImageBuffer::createCompatibleBuffer(FloatRect(enclosingIntRect(dstRect)).size(), context);
    if (!m_cachedImageBuffer)
        return;
    auto& bufferContext = m_cachedImageBuffer->context();

    transformContextForPainting(bufferContext, dstRect, srcRect);
    drawPDFPage(bufferContext);

    m_cachedTransform = context.getCTM(GraphicsContext::DefinitelyIncludeDeviceScale);
    m_cachedDestinationSize = dstRect.size();
    m_cachedSourceRect = srcRect;

    IntSize internalSize = m_cachedImageBuffer->internalSize();
    size_t oldCachedBytes = m_cachedBytes;
    m_cachedBytes = safeCast<size_t>(internalSize.width()) * internalSize.height() * 4;

    if (imageObserver())
        imageObserver()->decodedSizeChanged(this, safeCast<int>(m_cachedBytes) - safeCast<int>(oldCachedBytes));
}
예제 #3
0
void PDFDocumentImage::draw(GraphicsContext& context, const FloatRect& dstRect, const FloatRect& srcRect, CompositeOperator op, BlendMode, ImageOrientationDescription)
{
    if (!m_document || !m_hasPage)
        return;

    updateCachedImageIfNeeded(context, dstRect, srcRect);

    {
        GraphicsContextStateSaver stateSaver(context);
        context.setCompositeOperation(op);

        if (m_cachedImageBuffer)
            context.drawImageBuffer(*m_cachedImageBuffer, dstRect);
        else {
            transformContextForPainting(context, dstRect, srcRect);
            drawPDFPage(context);
        }
    }

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