|
Lines 28-49
a/WebCore/html/HTMLCanvasElement.cpp_sec1
|
| 28 |
#include "HTMLCanvasElement.h" |
28 |
#include "HTMLCanvasElement.h" |
| 29 |
|
29 |
|
| 30 |
#include "CanvasContextAttributes.h" |
30 |
#include "CanvasContextAttributes.h" |
| 31 |
#include "CanvasGradient.h" |
|
|
| 32 |
#include "CanvasPattern.h" |
| 33 |
#include "CanvasRenderingContext2D.h" |
31 |
#include "CanvasRenderingContext2D.h" |
| 34 |
#if ENABLE(3D_CANVAS) |
32 |
#if ENABLE(3D_CANVAS) |
| 35 |
#include "WebGLContextAttributes.h" |
33 |
#include "WebGLContextAttributes.h" |
| 36 |
#include "WebGLRenderingContext.h" |
34 |
#include "WebGLRenderingContext.h" |
| 37 |
#endif |
35 |
#endif |
|
|
36 |
#include "CanvasGradient.h" |
| 37 |
#include "CanvasPattern.h" |
| 38 |
#include "CanvasStyle.h" |
38 |
#include "CanvasStyle.h" |
| 39 |
#include "Chrome.h" |
39 |
#include "Chrome.h" |
| 40 |
#include "Document.h" |
40 |
#include "Document.h" |
| 41 |
#include "ExceptionCode.h" |
|
|
| 42 |
#include "Frame.h" |
41 |
#include "Frame.h" |
| 43 |
#include "GraphicsContext.h" |
42 |
#include "GraphicsContext.h" |
| 44 |
#include "HTMLNames.h" |
43 |
#include "HTMLNames.h" |
| 45 |
#include "ImageBuffer.h" |
44 |
#include "ImageBuffer.h" |
| 46 |
#include "MIMETypeRegistry.h" |
|
|
| 47 |
#include "MappedAttribute.h" |
45 |
#include "MappedAttribute.h" |
| 48 |
#include "Page.h" |
46 |
#include "Page.h" |
| 49 |
#include "RenderHTMLCanvas.h" |
47 |
#include "RenderHTMLCanvas.h" |
|
Lines 55-76
namespace WebCore {
a/WebCore/html/HTMLCanvasElement.cpp_sec2
|
| 55 |
|
53 |
|
| 56 |
using namespace HTMLNames; |
54 |
using namespace HTMLNames; |
| 57 |
|
55 |
|
| 58 |
// These values come from the WhatWG spec. |
|
|
| 59 |
static const int defaultWidth = 300; |
| 60 |
static const int defaultHeight = 150; |
| 61 |
|
| 62 |
// Firefox limits width/height to 32767 pixels, but slows down dramatically before it |
| 63 |
// reaches that limit. We limit by area instead, giving us larger maximum dimensions, |
| 64 |
// in exchange for a smaller maximum canvas size. |
| 65 |
const float HTMLCanvasElement::MaxCanvasArea = 32768 * 8192; // Maximum canvas area in CSS pixels |
| 66 |
|
| 67 |
HTMLCanvasElement::HTMLCanvasElement(const QualifiedName& tagName, Document* doc) |
56 |
HTMLCanvasElement::HTMLCanvasElement(const QualifiedName& tagName, Document* doc) |
| 68 |
: HTMLElement(tagName, doc) |
57 |
: HTMLElement(tagName, doc) |
| 69 |
, m_size(defaultWidth, defaultHeight) |
58 |
, CanvasSurface(doc->frame() ? doc->frame()->page()->chrome()->scaleFactor() : 1) |
| 70 |
, m_observer(0) |
59 |
, m_observer(0) |
| 71 |
, m_originClean(true) |
|
|
| 72 |
, m_ignoreReset(false) |
60 |
, m_ignoreReset(false) |
| 73 |
, m_createdImageBuffer(false) |
|
|
| 74 |
{ |
61 |
{ |
| 75 |
ASSERT(hasTagName(canvasTag)); |
62 |
ASSERT(hasTagName(canvasTag)); |
| 76 |
} |
63 |
} |
|
Lines 133-154
void HTMLCanvasElement::setWidth(int value)
a/WebCore/html/HTMLCanvasElement.cpp_sec3
|
| 133 |
setAttribute(widthAttr, String::number(value)); |
120 |
setAttribute(widthAttr, String::number(value)); |
| 134 |
} |
121 |
} |
| 135 |
|
122 |
|
| 136 |
String HTMLCanvasElement::toDataURL(const String& mimeType, ExceptionCode& ec) |
|
|
| 137 |
{ |
| 138 |
if (!m_originClean) { |
| 139 |
ec = SECURITY_ERR; |
| 140 |
return String(); |
| 141 |
} |
| 142 |
|
| 143 |
if (m_size.isEmpty() || !buffer()) |
| 144 |
return String("data:,"); |
| 145 |
|
| 146 |
if (mimeType.isNull() || !MIMETypeRegistry::isSupportedImageMIMETypeForEncoding(mimeType)) |
| 147 |
return buffer()->toDataURL("image/png"); |
| 148 |
|
| 149 |
return buffer()->toDataURL(mimeType); |
| 150 |
} |
| 151 |
|
| 152 |
CanvasRenderingContext* HTMLCanvasElement::getContext(const String& type, CanvasContextAttributes* attrs) |
123 |
CanvasRenderingContext* HTMLCanvasElement::getContext(const String& type, CanvasContextAttributes* attrs) |
| 153 |
{ |
124 |
{ |
| 154 |
// A Canvas can either be "2D" or "webgl" but never both. If you request a 2D canvas and the existing |
125 |
// A Canvas can either be "2D" or "webgl" but never both. If you request a 2D canvas and the existing |
|
Lines 193-204
CanvasRenderingContext* HTMLCanvasElement::getContext(const String& type, Canvas
a/WebCore/html/HTMLCanvasElement.cpp_sec4
|
| 193 |
|
164 |
|
| 194 |
void HTMLCanvasElement::willDraw(const FloatRect& rect) |
165 |
void HTMLCanvasElement::willDraw(const FloatRect& rect) |
| 195 |
{ |
166 |
{ |
| 196 |
if (m_imageBuffer) |
167 |
CanvasSurface::willDraw(rect); |
| 197 |
m_imageBuffer->clearImage(); |
168 |
|
| 198 |
|
|
|
| 199 |
if (RenderBox* ro = renderBox()) { |
169 |
if (RenderBox* ro = renderBox()) { |
| 200 |
FloatRect destRect = ro->contentBoxRect(); |
170 |
FloatRect destRect = ro->contentBoxRect(); |
| 201 |
FloatRect r = mapRect(rect, FloatRect(0, 0, m_size.width(), m_size.height()), destRect); |
171 |
FloatRect r = mapRect(rect, FloatRect(0, 0, size().width(), size().height()), destRect); |
| 202 |
r.intersect(destRect); |
172 |
r.intersect(destRect); |
| 203 |
if (m_dirtyRect.contains(r)) |
173 |
if (m_dirtyRect.contains(r)) |
| 204 |
return; |
174 |
return; |
|
Lines 219-246
void HTMLCanvasElement::reset()
a/WebCore/html/HTMLCanvasElement.cpp_sec5
|
| 219 |
bool ok; |
189 |
bool ok; |
| 220 |
int w = getAttribute(widthAttr).toInt(&ok); |
190 |
int w = getAttribute(widthAttr).toInt(&ok); |
| 221 |
if (!ok) |
191 |
if (!ok) |
| 222 |
w = defaultWidth; |
192 |
w = DefaultWidth; |
| 223 |
int h = getAttribute(heightAttr).toInt(&ok); |
193 |
int h = getAttribute(heightAttr).toInt(&ok); |
| 224 |
if (!ok) |
194 |
if (!ok) |
| 225 |
h = defaultHeight; |
195 |
h = DefaultHeight; |
| 226 |
|
196 |
|
| 227 |
IntSize oldSize = m_size; |
197 |
IntSize oldSize = size(); |
| 228 |
m_size = IntSize(w, h); |
198 |
setSurfaceSize(IntSize(w, h)); |
| 229 |
|
199 |
|
| 230 |
#if ENABLE(3D_CANVAS) |
200 |
#if ENABLE(3D_CANVAS) |
| 231 |
if (m_context && m_context->is3d()) |
201 |
if (m_context && m_context->is3d()) |
| 232 |
static_cast<WebGLRenderingContext*>(m_context.get())->reshape(width(), height()); |
202 |
static_cast<WebGLRenderingContext*>(m_context.get())->reshape(width(), height()); |
| 233 |
#endif |
203 |
#endif |
| 234 |
|
204 |
|
| 235 |
bool hadImageBuffer = m_createdImageBuffer; |
205 |
bool hadImageBuffer = hasCreatedImageBuffer(); |
| 236 |
m_createdImageBuffer = false; |
|
|
| 237 |
m_imageBuffer.clear(); |
| 238 |
if (m_context && m_context->is2d()) |
206 |
if (m_context && m_context->is2d()) |
| 239 |
static_cast<CanvasRenderingContext2D*>(m_context.get())->reset(); |
207 |
static_cast<CanvasRenderingContext2D*>(m_context.get())->reset(); |
| 240 |
|
208 |
|
| 241 |
if (RenderObject* renderer = this->renderer()) { |
209 |
if (RenderObject* renderer = this->renderer()) { |
| 242 |
if (m_rendererIsCanvas) { |
210 |
if (m_rendererIsCanvas) { |
| 243 |
if (oldSize != m_size) |
211 |
if (oldSize != size()) |
| 244 |
toRenderHTMLCanvas(renderer)->canvasSizeChanged(); |
212 |
toRenderHTMLCanvas(renderer)->canvasSizeChanged(); |
| 245 |
if (hadImageBuffer) |
213 |
if (hadImageBuffer) |
| 246 |
renderer->repaint(); |
214 |
renderer->repaint(); |
|
Lines 267-276
void HTMLCanvasElement::paint(GraphicsContext* context, const IntRect& r)
a/WebCore/html/HTMLCanvasElement.cpp_sec6
|
| 267 |
} |
235 |
} |
| 268 |
#endif |
236 |
#endif |
| 269 |
|
237 |
|
| 270 |
if (m_imageBuffer) { |
238 |
if (hasCreatedImageBuffer()) { |
| 271 |
Image* image = m_imageBuffer->image(); |
239 |
ImageBuffer* imageBuffer = buffer(); |
| 272 |
if (image) |
240 |
if (imageBuffer) { |
| 273 |
context->drawImage(image, DeviceColorSpace, r); |
241 |
Image* image = imageBuffer->image(); |
|
|
242 |
if (image) |
| 243 |
context->drawImage(image, DeviceColorSpace, r); |
| 244 |
} |
| 274 |
} |
245 |
} |
| 275 |
|
246 |
|
| 276 |
#if ENABLE(3D_CANVAS) |
247 |
#if ENABLE(3D_CANVAS) |
|
Lines 279-354
void HTMLCanvasElement::paint(GraphicsContext* context, const IntRect& r)
a/WebCore/html/HTMLCanvasElement.cpp_sec7
|
| 279 |
#endif |
250 |
#endif |
| 280 |
} |
251 |
} |
| 281 |
|
252 |
|
| 282 |
IntRect HTMLCanvasElement::convertLogicalToDevice(const FloatRect& logicalRect) const |
|
|
| 283 |
{ |
| 284 |
return IntRect(convertLogicalToDevice(logicalRect.location()), convertLogicalToDevice(logicalRect.size())); |
| 285 |
} |
| 286 |
|
| 287 |
IntSize HTMLCanvasElement::convertLogicalToDevice(const FloatSize& logicalSize) const |
| 288 |
{ |
| 289 |
float pageScaleFactor = document()->frame() ? document()->frame()->page()->chrome()->scaleFactor() : 1.0f; |
| 290 |
float wf = ceilf(logicalSize.width() * pageScaleFactor); |
| 291 |
float hf = ceilf(logicalSize.height() * pageScaleFactor); |
| 292 |
|
| 293 |
if (!(wf >= 1 && hf >= 1 && wf * hf <= MaxCanvasArea)) |
| 294 |
return IntSize(); |
| 295 |
|
| 296 |
return IntSize(static_cast<unsigned>(wf), static_cast<unsigned>(hf)); |
| 297 |
} |
| 298 |
|
| 299 |
IntPoint HTMLCanvasElement::convertLogicalToDevice(const FloatPoint& logicalPos) const |
| 300 |
{ |
| 301 |
float pageScaleFactor = document()->frame() ? document()->frame()->page()->chrome()->scaleFactor() : 1.0f; |
| 302 |
float xf = logicalPos.x() * pageScaleFactor; |
| 303 |
float yf = logicalPos.y() * pageScaleFactor; |
| 304 |
|
| 305 |
return IntPoint(static_cast<unsigned>(xf), static_cast<unsigned>(yf)); |
| 306 |
} |
| 307 |
|
| 308 |
void HTMLCanvasElement::createImageBuffer() const |
| 309 |
{ |
| 310 |
ASSERT(!m_imageBuffer); |
| 311 |
|
| 312 |
m_createdImageBuffer = true; |
| 313 |
|
| 314 |
FloatSize unscaledSize(width(), height()); |
| 315 |
IntSize size = convertLogicalToDevice(unscaledSize); |
| 316 |
if (!size.width() || !size.height()) |
| 317 |
return; |
| 318 |
|
| 319 |
m_imageBuffer = ImageBuffer::create(size); |
| 320 |
// The convertLogicalToDevice MaxCanvasArea check should prevent common cases |
| 321 |
// where ImageBuffer::create() returns NULL, however we could still be low on memory. |
| 322 |
if (!m_imageBuffer) |
| 323 |
return; |
| 324 |
m_imageBuffer->context()->scale(FloatSize(size.width() / unscaledSize.width(), size.height() / unscaledSize.height())); |
| 325 |
m_imageBuffer->context()->setShadowsIgnoreTransforms(true); |
| 326 |
} |
| 327 |
|
| 328 |
GraphicsContext* HTMLCanvasElement::drawingContext() const |
| 329 |
{ |
| 330 |
return buffer() ? m_imageBuffer->context() : 0; |
| 331 |
} |
| 332 |
|
| 333 |
ImageBuffer* HTMLCanvasElement::buffer() const |
| 334 |
{ |
| 335 |
if (!m_createdImageBuffer) |
| 336 |
createImageBuffer(); |
| 337 |
return m_imageBuffer.get(); |
| 338 |
} |
| 339 |
|
| 340 |
AffineTransform HTMLCanvasElement::baseTransform() const |
| 341 |
{ |
| 342 |
ASSERT(m_createdImageBuffer); |
| 343 |
FloatSize unscaledSize(width(), height()); |
| 344 |
IntSize size = convertLogicalToDevice(unscaledSize); |
| 345 |
AffineTransform transform; |
| 346 |
if (size.width() && size.height()) |
| 347 |
transform.scaleNonUniform(size.width() / unscaledSize.width(), size.height() / unscaledSize.height()); |
| 348 |
transform.multiply(m_imageBuffer->baseTransform()); |
| 349 |
return transform; |
| 350 |
} |
| 351 |
|
| 352 |
#if ENABLE(3D_CANVAS) |
253 |
#if ENABLE(3D_CANVAS) |
| 353 |
bool HTMLCanvasElement::is3D() const |
254 |
bool HTMLCanvasElement::is3D() const |
| 354 |
{ |
255 |
{ |