void RenderHTMLCanvas::paintReplaced(PaintInfo& paintInfo, const LayoutPoint& paintOffset) { GraphicsContext* context = paintInfo.context; LayoutRect contentRect = contentBoxRect(); contentRect.moveBy(paintOffset); LayoutRect paintRect = replacedContentRect(); paintRect.moveBy(paintOffset); bool clip = !contentRect.contains(paintRect); if (clip) { // Not allowed to overflow the content box. paintInfo.context->save(); paintInfo.context->clip(pixelSnappedIntRect(contentRect)); } // FIXME: InterpolationNone should be used if ImageRenderingOptimizeContrast is set. // See bug for more details: crbug.com/353716. InterpolationQuality interpolationQuality = style()->imageRendering() == ImageRenderingOptimizeContrast ? InterpolationLow : CanvasDefaultInterpolationQuality; HTMLCanvasElement* canvas = toHTMLCanvasElement(node()); LayoutSize layoutSize = contentRect.size(); if (style()->imageRendering() == ImageRenderingPixelated && (layoutSize.width() > canvas->width() || layoutSize.height() > canvas->height() || layoutSize == canvas->size())) { interpolationQuality = InterpolationNone; } InterpolationQuality previousInterpolationQuality = context->imageInterpolationQuality(); context->setImageInterpolationQuality(interpolationQuality); canvas->paint(context, paintRect); context->setImageInterpolationQuality(previousInterpolationQuality); if (clip) context->restore(); }
void GraphicsContext3D::paintRenderingResultsToCanvas(CanvasRenderingContext* context, DrawingBuffer*) { HTMLCanvasElement* canvas = context->canvas(); ImageBuffer* imageBuffer = canvas->buffer(); int rowBytes = m_currentWidth * 4; int totalBytes = rowBytes * m_currentHeight; OwnArrayPtr<unsigned char> pixels = adoptArrayPtr(new unsigned char[totalBytes]); if (!pixels) return; readRenderingResults(pixels.get(), totalBytes); if (!m_attrs.premultipliedAlpha) { for (int i = 0; i < totalBytes; i += 4) { // Premultiply alpha. pixels[i + 0] = std::min(255, pixels[i + 0] * pixels[i + 3] / 255); pixels[i + 1] = std::min(255, pixels[i + 1] * pixels[i + 3] / 255); pixels[i + 2] = std::min(255, pixels[i + 2] * pixels[i + 3] / 255); } } paintToCanvas(pixels.get(), m_currentWidth, m_currentHeight, canvas->width(), canvas->height(), imageBuffer->context()->platformContext()); }
JSValue* JSHTMLCanvasElement::getValueProperty(ExecState* exec, int token) const { switch (token) { case WidthAttrNum: { HTMLCanvasElement* imp = static_cast<HTMLCanvasElement*>(impl()); return jsNumber(exec, imp->width()); } case HeightAttrNum: { HTMLCanvasElement* imp = static_cast<HTMLCanvasElement*>(impl()); return jsNumber(exec, imp->height()); } case ConstructorAttrNum: return getConstructor(exec); } return 0; }
void GraphicsContext3D::paintRenderingResultsToCanvas(CanvasRenderingContext* context) { HTMLCanvasElement* canvas = context->canvas(); ImageBuffer* imageBuffer = canvas->buffer(); int rowBytes = m_currentWidth * 4; int totalBytes = rowBytes * m_currentHeight; OwnArrayPtr<unsigned char> pixels = adoptArrayPtr(new unsigned char[totalBytes]); if (!pixels) return; makeContextCurrent(); bool mustRestoreFBO = false; if (m_attrs.antialias) { ::glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, m_multisampleFBO); ::glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, m_fbo); ::glBlitFramebufferEXT(0, 0, m_currentWidth, m_currentHeight, 0, 0, m_currentWidth, m_currentHeight, GL_COLOR_BUFFER_BIT, GL_LINEAR); ::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_fbo); mustRestoreFBO = true; } else { if (m_boundFBO != m_fbo) { mustRestoreFBO = true; ::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_fbo); } } GLint packAlignment = 4; bool mustRestorePackAlignment = false; ::glGetIntegerv(GL_PACK_ALIGNMENT, &packAlignment); if (packAlignment > 4) { ::glPixelStorei(GL_PACK_ALIGNMENT, 4); mustRestorePackAlignment = true; } ::glReadPixels(0, 0, m_currentWidth, m_currentHeight, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, pixels.get()); if (mustRestorePackAlignment) ::glPixelStorei(GL_PACK_ALIGNMENT, packAlignment); if (mustRestoreFBO) ::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_boundFBO); paintToCanvas(pixels.get(), m_currentWidth, m_currentHeight, canvas->width(), canvas->height(), imageBuffer->context()->platformContext()); }
void GraphicsContext3DInternal::paintRenderingResultsToCanvas(CanvasRenderingContext* context) { HTMLCanvasElement* canvas = context->canvas(); ImageBuffer* imageBuffer = canvas->buffer(); unsigned char* pixels = 0; #if USE(SKIA) const SkBitmap* canvasBitmap = imageBuffer->context()->platformContext()->bitmap(); const SkBitmap* readbackBitmap = 0; ASSERT(canvasBitmap->config() == SkBitmap::kARGB_8888_Config); if (canvasBitmap->width() == m_impl->width() && canvasBitmap->height() == m_impl->height()) { // This is the fastest and most common case. We read back // directly into the canvas's backing store. readbackBitmap = canvasBitmap; m_resizingBitmap.reset(); } else { // We need to allocate a temporary bitmap for reading back the // pixel data. We will then use Skia to rescale this bitmap to // the size of the canvas's backing store. if (m_resizingBitmap.width() != m_impl->width() || m_resizingBitmap.height() != m_impl->height()) { m_resizingBitmap.setConfig(SkBitmap::kARGB_8888_Config, m_impl->width(), m_impl->height()); if (!m_resizingBitmap.allocPixels()) return; } readbackBitmap = &m_resizingBitmap; } // Read back the frame buffer. SkAutoLockPixels bitmapLock(*readbackBitmap); pixels = static_cast<unsigned char*>(readbackBitmap->getPixels()); #elif USE(CG) if (m_renderOutput) pixels = m_renderOutput; #else #error Must port to your platform #endif m_impl->readBackFramebuffer(pixels, 4 * m_impl->width() * m_impl->height()); if (!m_impl->getContextAttributes().premultipliedAlpha) { size_t bufferSize = 4 * m_impl->width() * m_impl->height(); for (size_t i = 0; i < bufferSize; i += 4) { pixels[i + 0] = std::min(255, pixels[i + 0] * pixels[i + 3] / 255); pixels[i + 1] = std::min(255, pixels[i + 1] * pixels[i + 3] / 255); pixels[i + 2] = std::min(255, pixels[i + 2] * pixels[i + 3] / 255); } } #if USE(SKIA) readbackBitmap->notifyPixelsChanged(); if (m_resizingBitmap.readyToDraw()) { // We need to draw the resizing bitmap into the canvas's backing store. SkCanvas canvas(*canvasBitmap); SkRect dst; dst.set(SkIntToScalar(0), SkIntToScalar(0), SkIntToScalar(canvasBitmap->width()), SkIntToScalar(canvasBitmap->height())); canvas.drawBitmapRect(m_resizingBitmap, 0, dst); } #elif USE(CG) if (m_renderOutput && context->is3d()) { WebGLRenderingContext* webGLContext = static_cast<WebGLRenderingContext*>(context); webGLContext->graphicsContext3D()->paintToCanvas(m_renderOutput, m_impl->width(), m_impl->height(), canvas->width(), canvas->height(), imageBuffer->context()->platformContext()); } #else #error Must port to your platform #endif }
static v8::Handle<v8::Value> widthAttrGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) { HTMLCanvasElement* imp = V8HTMLCanvasElement::toNative(info.Holder()); return v8Integer(imp->width(), info.GetIsolate()); }