18e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project/* 28e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Copyright (C) 2004, 2006, 2007 Apple Inc. All rights reserved. 38e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Copyright (C) 2007 Alp Toker <alp@atoker.com> 48e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 58e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Redistribution and use in source and binary forms, with or without 68e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * modification, are permitted provided that the following conditions 78e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * are met: 88e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 1. Redistributions of source code must retain the above copyright 98e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * notice, this list of conditions and the following disclaimer. 108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 2. Redistributions in binary form must reproduce the above copyright 118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * notice, this list of conditions and the following disclaimer in the 128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * documentation and/or other materials provided with the distribution. 138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY 158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR 188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project */ 268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "config.h" 288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "HTMLCanvasElement.h" 298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 30d0825bca7fe65beaee391d30da42e937db621564Steve Block#include "CanvasContextAttributes.h" 318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "CanvasGradient.h" 328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "CanvasPattern.h" 338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "CanvasRenderingContext2D.h" 34231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block#if ENABLE(3D_CANVAS) 35d0825bca7fe65beaee391d30da42e937db621564Steve Block#include "WebGLContextAttributes.h" 36643ca7872b450ea4efacab6188849e5aac2ba161Steve Block#include "WebGLRenderingContext.h" 37231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block#endif 388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "CanvasStyle.h" 398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "Chrome.h" 408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "Document.h" 418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "ExceptionCode.h" 428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "Frame.h" 438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "GraphicsContext.h" 448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "HTMLNames.h" 458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "ImageBuffer.h" 468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "MIMETypeRegistry.h" 475f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian#include "MappedAttribute.h" 488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "Page.h" 498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "RenderHTMLCanvas.h" 508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "Settings.h" 518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include <math.h> 528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include <stdio.h> 538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectnamespace WebCore { 558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectusing namespace HTMLNames; 578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// These values come from the WhatWG spec. 598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic const int defaultWidth = 300; 608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic const int defaultHeight = 150; 618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// Firefox limits width/height to 32767 pixels, but slows down dramatically before it 638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// reaches that limit. We limit by area instead, giving us larger maximum dimensions, 648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// in exchange for a smaller maximum canvas size. 658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectconst float HTMLCanvasElement::MaxCanvasArea = 32768 * 8192; // Maximum canvas area in CSS pixels 668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 67635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source ProjectHTMLCanvasElement::HTMLCanvasElement(const QualifiedName& tagName, Document* doc) 68635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project : HTMLElement(tagName, doc) 698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project , m_size(defaultWidth, defaultHeight) 708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project , m_observer(0) 718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project , m_originClean(true) 728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project , m_ignoreReset(false) 738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project , m_createdImageBuffer(false) 748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 75635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project ASSERT(hasTagName(canvasTag)); 768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectHTMLCanvasElement::~HTMLCanvasElement() 798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 805f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian if (m_observer) 815f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian m_observer->canvasDestroyed(this); 828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#if ENABLE(DASHBOARD_SUPPORT) 858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectHTMLTagStatus HTMLCanvasElement::endTagRequirement() const 878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project Settings* settings = document()->settings(); 898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (settings && settings->usesDashboardBackwardCompatibilityMode()) 908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return TagStatusForbidden; 918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return HTMLElement::endTagRequirement(); 938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectint HTMLCanvasElement::tagPriority() const 968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project Settings* settings = document()->settings(); 988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (settings && settings->usesDashboardBackwardCompatibilityMode()) 998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return 0; 1008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return HTMLElement::tagPriority(); 1028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 1038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#endif 1058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid HTMLCanvasElement::parseMappedAttribute(MappedAttribute* attr) 1078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 1088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project const QualifiedName& attrName = attr->name(); 1098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (attrName == widthAttr || attrName == heightAttr) 1108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project reset(); 1118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project HTMLElement::parseMappedAttribute(attr); 1128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 1138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectRenderObject* HTMLCanvasElement::createRenderer(RenderArena* arena, RenderStyle* style) 1158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 1168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project Settings* settings = document()->settings(); 1178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (settings && settings->isJavaScriptEnabled()) { 1188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_rendererIsCanvas = true; 1198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return new (arena) RenderHTMLCanvas(this); 1208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 1218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_rendererIsCanvas = false; 1238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return HTMLElement::createRenderer(arena, style); 1248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 1258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid HTMLCanvasElement::setHeight(int value) 1278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 1288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project setAttribute(heightAttr, String::number(value)); 1298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 1308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid HTMLCanvasElement::setWidth(int value) 1328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 1338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project setAttribute(widthAttr, String::number(value)); 1348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 1358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectString HTMLCanvasElement::toDataURL(const String& mimeType, ExceptionCode& ec) 1378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 1388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!m_originClean) { 1398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project ec = SECURITY_ERR; 1408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return String(); 1418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 1428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 143cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block if (m_size.isEmpty() || !buffer()) 1448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return String("data:,"); 1458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (mimeType.isNull() || !MIMETypeRegistry::isSupportedImageMIMETypeForEncoding(mimeType)) 1478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return buffer()->toDataURL("image/png"); 1488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return buffer()->toDataURL(mimeType); 1508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 1518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 152d0825bca7fe65beaee391d30da42e937db621564Steve BlockCanvasRenderingContext* HTMLCanvasElement::getContext(const String& type, CanvasContextAttributes* attrs) 1538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 154643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // A Canvas can either be "2D" or "webgl" but never both. If you request a 2D canvas and the existing 155643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // context is already 2D, just return that. If the existing context is WebGL, then destroy it 156643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // before creating a new 2D context. Vice versa when requesting a WebGL canvas. Requesting a 157231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block // context with any other type string will destroy any existing context. 158231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block 159231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block // FIXME - The code depends on the context not going away once created, to prevent JS from 160231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block // seeing a dangling pointer. So for now we will disallow the context from being changed 161231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block // once it is created. 1628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (type == "2d") { 163231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block if (m_context && !m_context->is2d()) 164231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block return 0; 165231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block if (!m_context) 166231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block m_context = new CanvasRenderingContext2D(this); 167231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block return m_context.get(); 168231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block } 169231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block#if ENABLE(3D_CANVAS) 170231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block Settings* settings = document()->settings(); 171231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block if (settings && settings->webGLEnabled()) { 172643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // Accept the legacy "webkit-3d" name as well as the provisional "experimental-webgl" name. 173643ca7872b450ea4efacab6188849e5aac2ba161Steve Block // Once ratified, we will also accept "webgl" as the context name. 174231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block if ((type == "webkit-3d") || 175643ca7872b450ea4efacab6188849e5aac2ba161Steve Block (type == "experimental-webgl")) { 176231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block if (m_context && !m_context->is3d()) 177231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block return 0; 178231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block if (!m_context) { 179d0825bca7fe65beaee391d30da42e937db621564Steve Block m_context = WebGLRenderingContext::create(this, static_cast<WebGLContextAttributes*>(attrs)); 180cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block if (m_context) { 181cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block // Need to make sure a RenderLayer and compositing layer get created for the Canvas 182cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block setNeedsStyleRecalc(SyntheticStyleChange); 183cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block } 184231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block } 185231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block return m_context.get(); 186231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block } 1878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 188d0825bca7fe65beaee391d30da42e937db621564Steve Block#else 189d0825bca7fe65beaee391d30da42e937db621564Steve Block UNUSED_PARAM(attrs); 190231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block#endif 1918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return 0; 1928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 1938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid HTMLCanvasElement::willDraw(const FloatRect& rect) 1958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 196231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block if (m_imageBuffer) 197231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block m_imageBuffer->clearImage(); 1988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 199635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (RenderBox* ro = renderBox()) { 200635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project FloatRect destRect = ro->contentBoxRect(); 201635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project FloatRect r = mapRect(rect, FloatRect(0, 0, m_size.width(), m_size.height()), destRect); 202635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project r.intersect(destRect); 203635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (m_dirtyRect.contains(r)) 204635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project return; 205635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 206635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project m_dirtyRect.unite(r); 207635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project ro->repaintRectangle(enclosingIntRect(m_dirtyRect)); 2088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 2098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (m_observer) 2118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_observer->canvasChanged(this, rect); 2128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 2138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid HTMLCanvasElement::reset() 2158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 2168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (m_ignoreReset) 2178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 2188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project bool ok; 2208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int w = getAttribute(widthAttr).toInt(&ok); 2218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!ok) 2228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project w = defaultWidth; 2238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project int h = getAttribute(heightAttr).toInt(&ok); 2248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!ok) 2258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project h = defaultHeight; 2268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project IntSize oldSize = m_size; 2288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_size = IntSize(w, h); 2298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 230d0825bca7fe65beaee391d30da42e937db621564Steve Block#if ENABLE(3D_CANVAS) 231d0825bca7fe65beaee391d30da42e937db621564Steve Block if (m_context && m_context->is3d()) 232d0825bca7fe65beaee391d30da42e937db621564Steve Block static_cast<WebGLRenderingContext*>(m_context.get())->reshape(width(), height()); 233d0825bca7fe65beaee391d30da42e937db621564Steve Block#endif 234d0825bca7fe65beaee391d30da42e937db621564Steve Block 2358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project bool hadImageBuffer = m_createdImageBuffer; 2368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_createdImageBuffer = false; 2378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_imageBuffer.clear(); 238231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block if (m_context && m_context->is2d()) 239231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block static_cast<CanvasRenderingContext2D*>(m_context.get())->reset(); 2408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2410bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if (RenderObject* renderer = this->renderer()) { 2428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (m_rendererIsCanvas) { 2438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (oldSize != m_size) 2440bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch toRenderHTMLCanvas(renderer)->canvasSizeChanged(); 2458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (hadImageBuffer) 2460bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch renderer->repaint(); 2478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 2480bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch } 2490bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 2508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (m_observer) 2518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_observer->canvasResized(this); 2528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 2538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid HTMLCanvasElement::paint(GraphicsContext* context, const IntRect& r) 2558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 256635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project // Clear the dirty rect 257635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project m_dirtyRect = FloatRect(); 258635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 2598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (context->paintingDisabled()) 2608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 2618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 262231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block#if ENABLE(3D_CANVAS) 263d0825bca7fe65beaee391d30da42e937db621564Steve Block WebGLRenderingContext* context3D = 0; 264231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block if (m_context && m_context->is3d()) { 265643ca7872b450ea4efacab6188849e5aac2ba161Steve Block context3D = static_cast<WebGLRenderingContext*>(m_context.get()); 266231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block context3D->beginPaint(); 267231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block } 268231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block#endif 269231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block 2708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (m_imageBuffer) { 2718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project Image* image = m_imageBuffer->image(); 2728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (image) 273643ca7872b450ea4efacab6188849e5aac2ba161Steve Block context->drawImage(image, DeviceColorSpace, r); 2748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 275231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block 276231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block#if ENABLE(3D_CANVAS) 277d0825bca7fe65beaee391d30da42e937db621564Steve Block if (context3D) 278231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block context3D->endPaint(); 279231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block#endif 2808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 2818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectIntRect HTMLCanvasElement::convertLogicalToDevice(const FloatRect& logicalRect) const 2838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 2848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return IntRect(convertLogicalToDevice(logicalRect.location()), convertLogicalToDevice(logicalRect.size())); 2858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 2868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectIntSize HTMLCanvasElement::convertLogicalToDevice(const FloatSize& logicalSize) const 2888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 2899652d6b88e01f27d69c804ac6bc56b527b33c219Grace Kloba#if PLATFORM(ANDROID) 2909652d6b88e01f27d69c804ac6bc56b527b33c219Grace Kloba /* In Android we capture the drawing into a displayList, and then 2919652d6b88e01f27d69c804ac6bc56b527b33c219Grace Kloba replay that list at various scale factors (sometimes zoomed out, other 2929652d6b88e01f27d69c804ac6bc56b527b33c219Grace Kloba times zoomed in for "normal" reading, yet other times at arbitrary 2939652d6b88e01f27d69c804ac6bc56b527b33c219Grace Kloba zoom values based on the user's choice). In all of these cases, we do 2949652d6b88e01f27d69c804ac6bc56b527b33c219Grace Kloba not re-record the displayList, hence it is usually harmful to perform 2959652d6b88e01f27d69c804ac6bc56b527b33c219Grace Kloba any pre-rounding, since we just don't know the actual drawing resolution 2969652d6b88e01f27d69c804ac6bc56b527b33c219Grace Kloba at record time. 2979652d6b88e01f27d69c804ac6bc56b527b33c219Grace Kloba */ 2989652d6b88e01f27d69c804ac6bc56b527b33c219Grace Kloba float pageScaleFactor = 1.0f; 2999652d6b88e01f27d69c804ac6bc56b527b33c219Grace Kloba#else 3008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project float pageScaleFactor = document()->frame() ? document()->frame()->page()->chrome()->scaleFactor() : 1.0f; 3019652d6b88e01f27d69c804ac6bc56b527b33c219Grace Kloba#endif 3028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project float wf = ceilf(logicalSize.width() * pageScaleFactor); 3038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project float hf = ceilf(logicalSize.height() * pageScaleFactor); 3048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!(wf >= 1 && hf >= 1 && wf * hf <= MaxCanvasArea)) 3068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return IntSize(); 3078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return IntSize(static_cast<unsigned>(wf), static_cast<unsigned>(hf)); 3098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 3108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectIntPoint HTMLCanvasElement::convertLogicalToDevice(const FloatPoint& logicalPos) const 3128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 3139652d6b88e01f27d69c804ac6bc56b527b33c219Grace Kloba#if PLATFORM(ANDROID) 3149652d6b88e01f27d69c804ac6bc56b527b33c219Grace Kloba /* In Android we capture the drawing into a displayList, and then 3159652d6b88e01f27d69c804ac6bc56b527b33c219Grace Kloba replay that list at various scale factors (sometimes zoomed out, other 3169652d6b88e01f27d69c804ac6bc56b527b33c219Grace Kloba times zoomed in for "normal" reading, yet other times at arbitrary 3179652d6b88e01f27d69c804ac6bc56b527b33c219Grace Kloba zoom values based on the user's choice). In all of these cases, we do 3189652d6b88e01f27d69c804ac6bc56b527b33c219Grace Kloba not re-record the displayList, hence it is usually harmful to perform 3199652d6b88e01f27d69c804ac6bc56b527b33c219Grace Kloba any pre-rounding, since we just don't know the actual drawing resolution 3209652d6b88e01f27d69c804ac6bc56b527b33c219Grace Kloba at record time. 3219652d6b88e01f27d69c804ac6bc56b527b33c219Grace Kloba */ 3229652d6b88e01f27d69c804ac6bc56b527b33c219Grace Kloba float pageScaleFactor = 1.0f; 3239652d6b88e01f27d69c804ac6bc56b527b33c219Grace Kloba#else 3248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project float pageScaleFactor = document()->frame() ? document()->frame()->page()->chrome()->scaleFactor() : 1.0f; 3259652d6b88e01f27d69c804ac6bc56b527b33c219Grace Kloba#endif 3268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project float xf = logicalPos.x() * pageScaleFactor; 3278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project float yf = logicalPos.y() * pageScaleFactor; 3288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return IntPoint(static_cast<unsigned>(xf), static_cast<unsigned>(yf)); 3308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 3318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid HTMLCanvasElement::createImageBuffer() const 3338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 3348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project ASSERT(!m_imageBuffer); 3358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_createdImageBuffer = true; 3378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project FloatSize unscaledSize(width(), height()); 3398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project IntSize size = convertLogicalToDevice(unscaledSize); 3408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!size.width() || !size.height()) 3418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 342635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 3430bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch m_imageBuffer = ImageBuffer::create(size); 3445f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian // The convertLogicalToDevice MaxCanvasArea check should prevent common cases 3455f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian // where ImageBuffer::create() returns NULL, however we could still be low on memory. 3465f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian if (!m_imageBuffer) 3475f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian return; 348635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project m_imageBuffer->context()->scale(FloatSize(size.width() / unscaledSize.width(), size.height() / unscaledSize.height())); 349635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project m_imageBuffer->context()->setShadowsIgnoreTransforms(true); 3508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 3518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectGraphicsContext* HTMLCanvasElement::drawingContext() const 3538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 3548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return buffer() ? m_imageBuffer->context() : 0; 3558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 3568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectImageBuffer* HTMLCanvasElement::buffer() const 3588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 3598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!m_createdImageBuffer) 3608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project createImageBuffer(); 3618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return m_imageBuffer.get(); 3628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 363635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 3648a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve BlockAffineTransform HTMLCanvasElement::baseTransform() const 365635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{ 366635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project ASSERT(m_createdImageBuffer); 367635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project FloatSize unscaledSize(width(), height()); 368635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project IntSize size = convertLogicalToDevice(unscaledSize); 3698a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block AffineTransform transform; 370635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project if (size.width() && size.height()) 3718f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian transform.scaleNonUniform(size.width() / unscaledSize.width(), size.height() / unscaledSize.height()); 372635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project transform.multiply(m_imageBuffer->baseTransform()); 373635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project return transform; 374635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project} 3758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 376231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block#if ENABLE(3D_CANVAS) 377231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Blockbool HTMLCanvasElement::is3D() const 378231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block{ 379231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block return m_context && m_context->is3d(); 380231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block} 381231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block#endif 382231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block 3838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 384