void HTMLCanvasElement::createImageBuffer() const { ASSERT(!m_imageBuffer); m_hasCreatedImageBuffer = true; m_didClearImageBuffer = true; FloatSize logicalSize = size(); FloatSize deviceSize = convertLogicalToDevice(logicalSize); if (!deviceSize.isExpressibleAsIntSize()) return; if (deviceSize.width() * deviceSize.height() > MaxCanvasArea) { StringBuilder stringBuilder; stringBuilder.appendLiteral("Canvas area exceeds the maximum limit (width * height > "); stringBuilder.appendNumber(MaxCanvasArea); stringBuilder.appendLiteral(")."); document().addConsoleMessage(MessageSource::JS, MessageLevel::Warning, stringBuilder.toString()); return; } // Make sure we don't use more pixel memory than the system can support. size_t requestedPixelMemory = 4 * width() * height(); if (activePixelMemory + requestedPixelMemory > maxActivePixelMemory()) { StringBuilder stringBuilder; stringBuilder.appendLiteral("Total canvas memory use exceeds the maximum limit ("); stringBuilder.appendNumber(maxActivePixelMemory() / 1024 / 1024); stringBuilder.appendLiteral(" MB)."); document().addConsoleMessage(MessageSource::JS, MessageLevel::Warning, stringBuilder.toString()); return; } IntSize bufferSize(deviceSize.width(), deviceSize.height()); if (!bufferSize.width() || !bufferSize.height()) return; RenderingMode renderingMode = shouldAccelerate(bufferSize) ? Accelerated : Unaccelerated; setImageBuffer(ImageBuffer::create(size(), renderingMode)); if (!m_imageBuffer) return; m_imageBuffer->context().setShadowsIgnoreTransforms(true); m_imageBuffer->context().setImageInterpolationQuality(DefaultInterpolationQuality); if (document().settings() && !document().settings()->antialiased2dCanvasEnabled()) m_imageBuffer->context().setShouldAntialias(false); m_imageBuffer->context().setStrokeThickness(1); m_contextStateSaver = std::make_unique<GraphicsContextStateSaver>(m_imageBuffer->context()); JSC::JSLockHolder lock(scriptExecutionContext()->vm()); scriptExecutionContext()->vm().heap.reportExtraMemoryAllocated(memoryCost()); #if USE(IOSURFACE_CANVAS_BACKING_STORE) || ENABLE(ACCELERATED_2D_CANVAS) if (m_context && m_context->is2d()) // Recalculate compositing requirements if acceleration state changed. const_cast<HTMLCanvasElement*>(this)->setNeedsStyleRecalc(SyntheticStyleChange); #endif }
void HTMLCanvasElement::createImageBuffer() const { ASSERT(!m_imageBuffer); m_hasCreatedImageBuffer = true; m_didClearImageBuffer = true; FloatSize logicalSize(width(), height()); FloatSize deviceSize = convertLogicalToDevice(logicalSize); if (!deviceSize.isExpressibleAsIntSize()) return; if (deviceSize.width() * deviceSize.height() > MaxCanvasArea) return; #if USE(SKIA) if (deviceSize.width() > MaxSkiaDim || deviceSize.height() > MaxSkiaDim) return; #endif IntSize bufferSize(deviceSize.width(), deviceSize.height()); if (!bufferSize.width() || !bufferSize.height()) return; RenderingMode renderingMode = shouldAccelerate(bufferSize) ? Accelerated : #if USE(SKIA) UnacceleratedNonPlatformBuffer; #else Unaccelerated; #endif m_imageBuffer = ImageBuffer::create(bufferSize, ColorSpaceDeviceRGB, renderingMode); if (!m_imageBuffer) return; m_imageBuffer->context()->scale(FloatSize(bufferSize.width() / logicalSize.width(), bufferSize.height() / logicalSize.height())); m_imageBuffer->context()->setShadowsIgnoreTransforms(true); m_imageBuffer->context()->setImageInterpolationQuality(DefaultInterpolationQuality); m_imageBuffer->context()->setStrokeThickness(1); m_contextStateSaver = adoptPtr(new GraphicsContextStateSaver(*m_imageBuffer->context())); #if USE(JSC) JSC::JSLock lock(JSC::SilenceAssertionsOnly); scriptExecutionContext()->globalData()->heap.reportExtraMemoryCost(m_imageBuffer->dataSize()); #endif #if USE(IOSURFACE_CANVAS_BACKING_STORE) || (ENABLE(ACCELERATED_2D_CANVAS) && USE(ACCELERATED_COMPOSITING)) if (m_context && m_context->is2d()) // Recalculate compositing requirements if acceleration state changed. const_cast<HTMLCanvasElement*>(this)->setNeedsStyleRecalc(SyntheticStyleChange); #endif }
void HTMLCanvasElement::createImageBuffer() const { ASSERT(!m_imageBuffer); m_hasCreatedImageBuffer = true; m_didClearImageBuffer = true; FloatSize logicalSize = size(); FloatSize deviceSize = convertLogicalToDevice(logicalSize); if (!deviceSize.isExpressibleAsIntSize()) return; #if PLATFORM(IOS) if (deviceSize.width() * deviceSize.height() * 4 > m_maximumDecodedImageSize) return; #else if (deviceSize.width() * deviceSize.height() > MaxCanvasArea) return; #endif IntSize bufferSize(deviceSize.width(), deviceSize.height()); if (!bufferSize.width() || !bufferSize.height()) return; RenderingMode renderingMode = shouldAccelerate(bufferSize) ? Accelerated : Unaccelerated; m_imageBuffer = ImageBuffer::create(size(), m_deviceScaleFactor, ColorSpaceDeviceRGB, renderingMode); if (!m_imageBuffer) return; m_imageBuffer->context()->setShadowsIgnoreTransforms(true); m_imageBuffer->context()->setImageInterpolationQuality(DefaultInterpolationQuality); if (document().settings() && !document().settings()->antialiased2dCanvasEnabled()) m_imageBuffer->context()->setShouldAntialias(false); m_imageBuffer->context()->setStrokeThickness(1); m_contextStateSaver = adoptPtr(new GraphicsContextStateSaver(*m_imageBuffer->context())); JSC::JSLockHolder lock(scriptExecutionContext()->vm()); size_t numBytes = 4 * m_imageBuffer->internalSize().width() * m_imageBuffer->internalSize().height(); scriptExecutionContext()->vm()->heap.reportExtraMemoryCost(numBytes); #if USE(IOSURFACE_CANVAS_BACKING_STORE) || ENABLE(ACCELERATED_2D_CANVAS) if (m_context && m_context->is2d()) // Recalculate compositing requirements if acceleration state changed. const_cast<HTMLCanvasElement*>(this)->setNeedsStyleRecalc(SyntheticStyleChange); #endif }