Image* HTMLCanvasElement::copiedImage() const { if (!m_copiedImage && buffer()) { if (m_context && m_context->is3d()) { toWebGLRenderingContext(m_context.get())->setSavingImage(true); m_context->paintRenderingResultsToCanvas(); toWebGLRenderingContext(m_context.get())->setSavingImage(false); } m_copiedImage = buffer()->copyImage(CopyBackingStore, Unscaled); updateExternallyAllocatedMemory(); } return m_copiedImage.get(); }
void HTMLCanvasElement::paint(GraphicsContext* context, const LayoutRect& r) { if (m_context) { if (!paintsIntoCanvasBuffer()) return; m_context->paintRenderingResultsToCanvas(); } if (hasImageBuffer()) { ImageBuffer* imageBuffer = buffer(); if (imageBuffer) { CompositeOperator compositeOperator = !m_context || m_context->hasAlpha() ? CompositeSourceOver : CompositeCopy; if (m_presentedImage) context->drawImage(m_presentedImage.get(), pixelSnappedIntRect(r), compositeOperator, DoNotRespectImageOrientation); else context->drawImageBuffer(imageBuffer, pixelSnappedIntRect(r), 0, compositeOperator); } } else { // When alpha is false, we should draw to opaque black. if (m_context && !m_context->hasAlpha()) context->fillRect(FloatRect(r), Color(0, 0, 0)); } if (is3D()) toWebGLRenderingContext(m_context.get())->markLayerComposited(); }
void HTMLCanvasElement::reset() { if (m_ignoreReset) return; resetDirtyRect(); bool ok; bool hadImageBuffer = hasImageBuffer(); int w = getAttribute(widthAttr).toInt(&ok); if (!ok || w < 0) w = DefaultWidth; int h = getAttribute(heightAttr).toInt(&ok); if (!ok || h < 0) h = DefaultHeight; if (m_contextStateSaver) { // Reset to the initial graphics context state. m_contextStateSaver->restore(); m_contextStateSaver->save(); } if (m_context && m_context->is2d()) toCanvasRenderingContext2D(m_context.get())->reset(); IntSize oldSize = size(); IntSize newSize(w, h); // If the size of an existing buffer matches, we can just clear it instead of reallocating. // This optimization is only done for 2D canvases for now. if (hadImageBuffer && oldSize == newSize && m_context && m_context->is2d()) { if (!m_didClearImageBuffer) clearImageBuffer(); return; } setSurfaceSize(newSize); if (m_context && m_context->is3d() && oldSize != size()) toWebGLRenderingContext(m_context.get())->reshape(width(), height()); if (RenderObject* renderer = this->renderer()) { if (renderer->isCanvas()) { if (oldSize != size()) { toRenderHTMLCanvas(renderer)->canvasSizeChanged(); if (renderBox() && renderBox()->hasAcceleratedCompositing()) renderBox()->contentChanged(CanvasChanged); } if (hadImageBuffer) renderer->setShouldDoFullPaintInvalidation(true); } } WillBeHeapHashSet<RawPtrWillBeWeakMember<CanvasObserver> >::iterator end = m_observers.end(); for (WillBeHeapHashSet<RawPtrWillBeWeakMember<CanvasObserver> >::iterator it = m_observers.begin(); it != end; ++it) (*it)->canvasResized(this); }
void V8HTMLCanvasElement::getContextMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) { v8::Handle<v8::Object> holder = info.Holder(); v8::Isolate* isolate = info.GetIsolate(); HTMLCanvasElement* impl = V8HTMLCanvasElement::toNative(holder); TOSTRING_VOID(V8StringResource<>, contextIdResource, info[0]); String contextId = contextIdResource; RefPtr<CanvasContextAttributes> attributes = nullptr; if (contextId == "webgl" || contextId == "experimental-webgl") { RefPtr<WebGLContextAttributes> webGLAttributes = WebGLContextAttributes::create(); if (info.Length() > 1 && info[1]->IsObject()) { v8::Handle<v8::Object> jsAttributes = info[1]->ToObject(); v8::Handle<v8::String> alpha = v8AtomicString(isolate, "alpha"); if (jsAttributes->Has(alpha) && !isUndefinedOrNull(jsAttributes->Get(alpha))) webGLAttributes->setAlpha(jsAttributes->Get(alpha)->BooleanValue()); v8::Handle<v8::String> depth = v8AtomicString(isolate, "depth"); if (jsAttributes->Has(depth) && !isUndefinedOrNull(jsAttributes->Get(depth))) webGLAttributes->setDepth(jsAttributes->Get(depth)->BooleanValue()); v8::Handle<v8::String> stencil = v8AtomicString(isolate, "stencil"); if (jsAttributes->Has(stencil) && !isUndefinedOrNull(jsAttributes->Get(stencil))) webGLAttributes->setStencil(jsAttributes->Get(stencil)->BooleanValue()); v8::Handle<v8::String> antialias = v8AtomicString(isolate, "antialias"); if (jsAttributes->Has(antialias) && !isUndefinedOrNull(jsAttributes->Get(antialias))) webGLAttributes->setAntialias(jsAttributes->Get(antialias)->BooleanValue()); v8::Handle<v8::String> premultipliedAlpha = v8AtomicString(isolate, "premultipliedAlpha"); if (jsAttributes->Has(premultipliedAlpha) && !isUndefinedOrNull(jsAttributes->Get(premultipliedAlpha))) webGLAttributes->setPremultipliedAlpha(jsAttributes->Get(premultipliedAlpha)->BooleanValue()); v8::Handle<v8::String> preserveDrawingBuffer = v8AtomicString(isolate, "preserveDrawingBuffer"); if (jsAttributes->Has(preserveDrawingBuffer) && !isUndefinedOrNull(jsAttributes->Get(preserveDrawingBuffer))) webGLAttributes->setPreserveDrawingBuffer(jsAttributes->Get(preserveDrawingBuffer)->BooleanValue()); v8::Handle<v8::String> failIfMajorPerformanceCaveat = v8AtomicString(isolate, "failIfMajorPerformanceCaveat"); if (jsAttributes->Has(failIfMajorPerformanceCaveat) && !isUndefinedOrNull(jsAttributes->Get(failIfMajorPerformanceCaveat))) webGLAttributes->setFailIfMajorPerformanceCaveat(jsAttributes->Get(failIfMajorPerformanceCaveat)->BooleanValue()); } attributes = webGLAttributes; } else { RefPtr<Canvas2DContextAttributes> canvas2DAttributes = Canvas2DContextAttributes::create(); attributes = canvas2DAttributes; } CanvasRenderingContext* result = impl->getContext(contextId, attributes.get()); if (!result) { v8SetReturnValueNull(info); return; } if (result->is2d()) { v8::Handle<v8::Value> v8Result = toV8(toCanvasRenderingContext2D(result), info.Holder(), info.GetIsolate()); v8SetReturnValue(info, v8Result); return; } if (result->is3d()) { v8::Handle<v8::Value> v8Result = toV8(toWebGLRenderingContext(result), info.Holder(), info.GetIsolate()); v8SetReturnValue(info, v8Result); return; } ASSERT_NOT_REACHED(); v8SetReturnValueNull(info); }
String HTMLCanvasElement::toDataURLInternal(const String& mimeType, const double* quality, bool isSaving) const { if (m_size.isEmpty() || !buffer()) return String("data:,"); String encodingMimeType = toEncodingMimeType(mimeType); // Try to get ImageData first, as that may avoid lossy conversions. RefPtr<ImageData> imageData = getImageData(); if (imageData) return ImageDataToDataURL(ImageDataBuffer(imageData->size(), imageData->data()), encodingMimeType, quality); if (m_context && m_context->is3d()) { toWebGLRenderingContext(m_context.get())->setSavingImage(isSaving); m_context->paintRenderingResultsToCanvas(); toWebGLRenderingContext(m_context.get())->setSavingImage(false); } return buffer()->toDataURL(encodingMimeType, quality); }
PassRefPtr<ImageData> HTMLCanvasElement::getImageData() const { if (!m_context || !m_context->is3d()) return nullptr; return toWebGLRenderingContext(m_context.get())->paintRenderingResultsToImageData(); }