HTMLCanvasElement.cpp revision cac0f67c402d107cdb10971b95719e2ff9c7c76b
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
308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "CanvasGradient.h"
318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "CanvasPattern.h"
328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "CanvasRenderingContext2D.h"
33231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block#if ENABLE(3D_CANVAS)
34231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block#include "CanvasRenderingContext3D.h"
35231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block#endif
368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "CanvasStyle.h"
378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "Chrome.h"
388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "Document.h"
398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "ExceptionCode.h"
408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "Frame.h"
418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "GraphicsContext.h"
428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "HTMLNames.h"
438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "ImageBuffer.h"
448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "MIMETypeRegistry.h"
455f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian#include "MappedAttribute.h"
468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "Page.h"
478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "RenderHTMLCanvas.h"
488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "Settings.h"
498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include <math.h>
508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include <stdio.h>
518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectnamespace WebCore {
538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectusing namespace HTMLNames;
558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// These values come from the WhatWG spec.
578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic const int defaultWidth = 300;
588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic const int defaultHeight = 150;
598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// Firefox limits width/height to 32767 pixels, but slows down dramatically before it
618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// reaches that limit. We limit by area instead, giving us larger maximum dimensions,
628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// in exchange for a smaller maximum canvas size.
638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectconst float HTMLCanvasElement::MaxCanvasArea = 32768 * 8192; // Maximum canvas area in CSS pixels
648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
65635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source ProjectHTMLCanvasElement::HTMLCanvasElement(const QualifiedName& tagName, Document* doc)
66635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    : HTMLElement(tagName, doc)
678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    , m_size(defaultWidth, defaultHeight)
688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    , m_observer(0)
698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    , m_originClean(true)
708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    , m_ignoreReset(false)
718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    , m_createdImageBuffer(false)
728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
73635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    ASSERT(hasTagName(canvasTag));
748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectHTMLCanvasElement::~HTMLCanvasElement()
778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
785f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    if (m_observer)
795f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        m_observer->canvasDestroyed(this);
808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#if ENABLE(DASHBOARD_SUPPORT)
838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectHTMLTagStatus HTMLCanvasElement::endTagRequirement() const
858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Settings* settings = document()->settings();
878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (settings && settings->usesDashboardBackwardCompatibilityMode())
888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return TagStatusForbidden;
898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return HTMLElement::endTagRequirement();
918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectint HTMLCanvasElement::tagPriority() const
948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Settings* settings = document()->settings();
968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (settings && settings->usesDashboardBackwardCompatibilityMode())
978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return 0;
988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return HTMLElement::tagPriority();
1008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#endif
1038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid HTMLCanvasElement::parseMappedAttribute(MappedAttribute* attr)
1058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
1068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    const QualifiedName& attrName = attr->name();
1078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (attrName == widthAttr || attrName == heightAttr)
1088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        reset();
1098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    HTMLElement::parseMappedAttribute(attr);
1108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectRenderObject* HTMLCanvasElement::createRenderer(RenderArena* arena, RenderStyle* style)
1138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
1148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Settings* settings = document()->settings();
1158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (settings && settings->isJavaScriptEnabled()) {
1168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        m_rendererIsCanvas = true;
1178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return new (arena) RenderHTMLCanvas(this);
1188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
1198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    m_rendererIsCanvas = false;
1218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return HTMLElement::createRenderer(arena, style);
1228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid HTMLCanvasElement::setHeight(int value)
1258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
1268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    setAttribute(heightAttr, String::number(value));
1278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid HTMLCanvasElement::setWidth(int value)
1308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
1318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    setAttribute(widthAttr, String::number(value));
1328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectString HTMLCanvasElement::toDataURL(const String& mimeType, ExceptionCode& ec)
1358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
1368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!m_originClean) {
1378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        ec = SECURITY_ERR;
1388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return String();
1398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
1408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
141cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    if (m_size.isEmpty() || !buffer())
1428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return String("data:,");
1438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (mimeType.isNull() || !MIMETypeRegistry::isSupportedImageMIMETypeForEncoding(mimeType))
1458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return buffer()->toDataURL("image/png");
1468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return buffer()->toDataURL(mimeType);
1488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectCanvasRenderingContext* HTMLCanvasElement::getContext(const String& type)
1518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
152231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    // A Canvas can either be "2D" or "3D" never both. If you request a 2D canvas and the existing
153231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    // context is already 2D, just return that. If the existing context is 3D, then destroy it
154231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    // before creating a new 2D context. Vice versa when requesting a 3D canvas. Requesting a
155231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    // context with any other type string will destroy any existing context.
156231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
157231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    // FIXME - The code depends on the context not going away once created, to prevent JS from
158231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    // seeing a dangling pointer. So for now we will disallow the context from being changed
159231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    // once it is created.
1608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (type == "2d") {
161231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        if (m_context && !m_context->is2d())
162231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block            return 0;
163231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        if (!m_context)
164231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block            m_context = new CanvasRenderingContext2D(this);
165231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        return m_context.get();
166231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    }
167231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block#if ENABLE(3D_CANVAS)
168231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    Settings* settings = document()->settings();
169231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    if (settings && settings->webGLEnabled()) {
170231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        if ((type == "webkit-3d") ||
171231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block            (type == "GL")) {
172231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block            if (m_context && !m_context->is3d())
173231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block                return 0;
174231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block            if (!m_context) {
175cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block                m_context = CanvasRenderingContext3D::create(this);
176cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block                if (m_context) {
177cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block                    // Need to make sure a RenderLayer and compositing layer get created for the Canvas
178cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block                    setNeedsStyleRecalc(SyntheticStyleChange);
179cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block                }
180231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block            }
181231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block            return m_context.get();
182231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        }
1838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
184231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block#endif
1858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return 0;
1868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid HTMLCanvasElement::willDraw(const FloatRect& rect)
1898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
190231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    if (m_imageBuffer)
191231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        m_imageBuffer->clearImage();
1928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
193635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    if (RenderBox* ro = renderBox()) {
194635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        FloatRect destRect = ro->contentBoxRect();
195635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        FloatRect r = mapRect(rect, FloatRect(0, 0, m_size.width(), m_size.height()), destRect);
196635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        r.intersect(destRect);
197635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        if (m_dirtyRect.contains(r))
198635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project            return;
199635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
200635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        m_dirtyRect.unite(r);
201635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        ro->repaintRectangle(enclosingIntRect(m_dirtyRect));
2028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
2038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (m_observer)
2058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        m_observer->canvasChanged(this, rect);
2068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
2078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid HTMLCanvasElement::reset()
2098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
2108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (m_ignoreReset)
2118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return;
2128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    bool ok;
2148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    int w = getAttribute(widthAttr).toInt(&ok);
2158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!ok)
2168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        w = defaultWidth;
2178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    int h = getAttribute(heightAttr).toInt(&ok);
2188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!ok)
2198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        h = defaultHeight;
2208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    IntSize oldSize = m_size;
2228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    m_size = IntSize(w, h);
2238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    bool hadImageBuffer = m_createdImageBuffer;
2258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    m_createdImageBuffer = false;
2268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    m_imageBuffer.clear();
227231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    if (m_context && m_context->is2d())
228231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        static_cast<CanvasRenderingContext2D*>(m_context.get())->reset();
2298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2300bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    if (RenderObject* renderer = this->renderer()) {
2318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (m_rendererIsCanvas) {
2328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            if (oldSize != m_size)
2330bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch                toRenderHTMLCanvas(renderer)->canvasSizeChanged();
2348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            if (hadImageBuffer)
2350bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch                renderer->repaint();
2368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
2370bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    }
2380bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
2398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (m_observer)
2408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        m_observer->canvasResized(this);
2418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
2428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid HTMLCanvasElement::paint(GraphicsContext* context, const IntRect& r)
2448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
245635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    // Clear the dirty rect
246635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    m_dirtyRect = FloatRect();
247635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
2488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (context->paintingDisabled())
2498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return;
2508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
251231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block#if ENABLE(3D_CANVAS)
252231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    CanvasRenderingContext3D* context3D = NULL;
253231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    if (m_context && m_context->is3d()) {
254231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        context3D = static_cast<CanvasRenderingContext3D*>(m_context.get());
255231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        context3D->beginPaint();
256231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    }
257231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block#endif
258231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
2598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (m_imageBuffer) {
2608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        Image* image = m_imageBuffer->image();
2618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (image)
2628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            context->drawImage(image, r);
2638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
264231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
265231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block#if ENABLE(3D_CANVAS)
266231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    if (context3D != NULL) {
267231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        context3D->reshape(r.width(), r.height());
268231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        context3D->endPaint();
269231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    }
270231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block#endif
2718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
2728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectIntRect HTMLCanvasElement::convertLogicalToDevice(const FloatRect& logicalRect) const
2748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
2758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return IntRect(convertLogicalToDevice(logicalRect.location()), convertLogicalToDevice(logicalRect.size()));
2768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
2778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectIntSize HTMLCanvasElement::convertLogicalToDevice(const FloatSize& logicalSize) const
2798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
2808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    float pageScaleFactor = document()->frame() ? document()->frame()->page()->chrome()->scaleFactor() : 1.0f;
2818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    float wf = ceilf(logicalSize.width() * pageScaleFactor);
2828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    float hf = ceilf(logicalSize.height() * pageScaleFactor);
2838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!(wf >= 1 && hf >= 1 && wf * hf <= MaxCanvasArea))
2858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return IntSize();
2868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return IntSize(static_cast<unsigned>(wf), static_cast<unsigned>(hf));
2888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
2898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectIntPoint HTMLCanvasElement::convertLogicalToDevice(const FloatPoint& logicalPos) const
2918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
2928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    float pageScaleFactor = document()->frame() ? document()->frame()->page()->chrome()->scaleFactor() : 1.0f;
2938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    float xf = logicalPos.x() * pageScaleFactor;
2948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    float yf = logicalPos.y() * pageScaleFactor;
2958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return IntPoint(static_cast<unsigned>(xf), static_cast<unsigned>(yf));
2978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
2988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid HTMLCanvasElement::createImageBuffer() const
3008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
3018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ASSERT(!m_imageBuffer);
3028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    m_createdImageBuffer = true;
3048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    FloatSize unscaledSize(width(), height());
3068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    IntSize size = convertLogicalToDevice(unscaledSize);
3078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!size.width() || !size.height())
3088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return;
309635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
3100bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    m_imageBuffer = ImageBuffer::create(size);
3115f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    // The convertLogicalToDevice MaxCanvasArea check should prevent common cases
3125f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    // where ImageBuffer::create() returns NULL, however we could still be low on memory.
3135f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    if (!m_imageBuffer)
3145f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        return;
315635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    m_imageBuffer->context()->scale(FloatSize(size.width() / unscaledSize.width(), size.height() / unscaledSize.height()));
316635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    m_imageBuffer->context()->setShadowsIgnoreTransforms(true);
3178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
3188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectGraphicsContext* HTMLCanvasElement::drawingContext() const
3208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
3218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return buffer() ? m_imageBuffer->context() : 0;
3228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
3238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectImageBuffer* HTMLCanvasElement::buffer() const
3258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
3268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!m_createdImageBuffer)
3278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        createImageBuffer();
3288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return m_imageBuffer.get();
3298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
330635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
331635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source ProjectTransformationMatrix HTMLCanvasElement::baseTransform() const
332635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{
333635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    ASSERT(m_createdImageBuffer);
334635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    FloatSize unscaledSize(width(), height());
335635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    IntSize size = convertLogicalToDevice(unscaledSize);
336635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    TransformationMatrix transform;
337635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    if (size.width() && size.height())
3388f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        transform.scaleNonUniform(size.width() / unscaledSize.width(), size.height() / unscaledSize.height());
339635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    transform.multiply(m_imageBuffer->baseTransform());
340635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    return transform;
341635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project}
3428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
343231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block#if ENABLE(3D_CANVAS)
344231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Blockbool HTMLCanvasElement::is3D() const
345231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block{
346231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    return m_context && m_context->is3d();
347231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block}
348231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block#endif
349231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
3508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
351