Upstream version 5.34.92.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / core / html / canvas / CanvasRenderingContext2D.cpp
1 /*
2  * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 Apple Inc. All rights reserved.
3  * Copyright (C) 2008, 2010 Nokia Corporation and/or its subsidiary(-ies)
4  * Copyright (C) 2007 Alp Toker <alp@atoker.com>
5  * Copyright (C) 2008 Eric Seidel <eric@webkit.org>
6  * Copyright (C) 2008 Dirk Schulze <krit@webkit.org>
7  * Copyright (C) 2010 Torch Mobile (Beijing) Co. Ltd. All rights reserved.
8  * Copyright (C) 2012, 2013 Intel Corporation. All rights reserved.
9  * Copyright (C) 2013 Adobe Systems Incorporated. All rights reserved.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions and the following disclaimer.
16  * 2. Redistributions in binary form must reproduce the above copyright
17  *    notice, this list of conditions and the following disclaimer in the
18  *    documentation and/or other materials provided with the distribution.
19  *
20  * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
21  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
24  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
28  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32
33 #include "config.h"
34 #include "core/html/canvas/CanvasRenderingContext2D.h"
35
36 #include "CSSPropertyNames.h"
37 #include "bindings/v8/ExceptionMessages.h"
38 #include "bindings/v8/ExceptionState.h"
39 #include "bindings/v8/ExceptionStatePlaceholder.h"
40 #include "core/accessibility/AXObjectCache.h"
41 #include "core/css/CSSFontSelector.h"
42 #include "core/css/parser/BisonCSSParser.h"
43 #include "core/css/StylePropertySet.h"
44 #include "core/css/resolver/StyleResolver.h"
45 #include "core/dom/ExceptionCode.h"
46 #include "core/fetch/ImageResource.h"
47 #include "core/html/HTMLCanvasElement.h"
48 #include "core/html/HTMLImageElement.h"
49 #include "core/html/HTMLMediaElement.h"
50 #include "core/html/HTMLVideoElement.h"
51 #include "core/html/ImageData.h"
52 #include "core/html/TextMetrics.h"
53 #include "core/html/canvas/CanvasGradient.h"
54 #include "core/html/canvas/CanvasPattern.h"
55 #include "core/html/canvas/CanvasStyle.h"
56 #include "core/html/canvas/DOMPath.h"
57 #include "core/frame/ImageBitmap.h"
58 #include "core/rendering/RenderImage.h"
59 #include "core/rendering/RenderLayer.h"
60 #include "core/rendering/RenderTheme.h"
61 #include "platform/fonts/FontCache.h"
62 #include "platform/geometry/FloatQuad.h"
63 #include "platform/graphics/GraphicsContextStateSaver.h"
64 #include "platform/graphics/DrawLooper.h"
65 #include "platform/text/TextRun.h"
66 #include "platform/weborigin/SecurityOrigin.h"
67 #include "wtf/CheckedArithmetic.h"
68 #include "wtf/MathExtras.h"
69 #include "wtf/OwnPtr.h"
70 #include "wtf/Uint8ClampedArray.h"
71 #include "wtf/text/StringBuilder.h"
72
73 using namespace std;
74
75 namespace WebCore {
76
77 static const int defaultFontSize = 10;
78 static const char defaultFontFamily[] = "sans-serif";
79 static const char defaultFont[] = "10px sans-serif";
80
81 CanvasRenderingContext2D::CanvasRenderingContext2D(HTMLCanvasElement* canvas, const Canvas2DContextAttributes* attrs, bool usesCSSCompatibilityParseMode)
82     : CanvasRenderingContext(canvas)
83     , m_stateStack(1)
84     , m_unrealizedSaveCount(0)
85     , m_usesCSSCompatibilityParseMode(usesCSSCompatibilityParseMode)
86     , m_hasAlpha(!attrs || attrs->alpha())
87 {
88     ScriptWrappable::init(this);
89 }
90
91 void CanvasRenderingContext2D::unwindStateStack()
92 {
93     // Ensure that the state stack in the ImageBuffer's context
94     // is cleared before destruction, to avoid assertions in the
95     // GraphicsContext dtor.
96     if (size_t stackSize = m_stateStack.size()) {
97         if (GraphicsContext* context = canvas()->existingDrawingContext()) {
98             while (--stackSize)
99                 context->restore();
100         }
101     }
102 }
103
104 CanvasRenderingContext2D::~CanvasRenderingContext2D()
105 {
106 #if !ASSERT_DISABLED
107     unwindStateStack();
108 #endif
109 }
110
111 bool CanvasRenderingContext2D::isAccelerated() const
112 {
113     if (!canvas()->hasImageBuffer())
114         return false;
115     GraphicsContext* context = drawingContext();
116     return context && context->isAccelerated();
117 }
118
119 void CanvasRenderingContext2D::reset()
120 {
121     unwindStateStack();
122     m_stateStack.resize(1);
123     m_stateStack.first() = State();
124     m_path.clear();
125     m_unrealizedSaveCount = 0;
126 }
127
128 // Important: Several of these properties are also stored in GraphicsContext's
129 // StrokeData. The default values that StrokeData uses may not the same values
130 // that the canvas 2d spec specifies. Make sure to sync the initial state of the
131 // GraphicsContext in HTMLCanvasElement::createImageBuffer()!
132 CanvasRenderingContext2D::State::State()
133     : m_strokeStyle(CanvasStyle::createFromRGBA(Color::black))
134     , m_fillStyle(CanvasStyle::createFromRGBA(Color::black))
135     , m_lineWidth(1)
136     , m_lineCap(ButtCap)
137     , m_lineJoin(MiterJoin)
138     , m_miterLimit(10)
139     , m_shadowBlur(0)
140     , m_shadowColor(Color::transparent)
141     , m_globalAlpha(1)
142     , m_globalComposite(CompositeSourceOver)
143     , m_globalBlend(blink::WebBlendModeNormal)
144     , m_invertibleCTM(true)
145     , m_lineDashOffset(0)
146     , m_imageSmoothingEnabled(true)
147     , m_textAlign(StartTextAlign)
148     , m_textBaseline(AlphabeticTextBaseline)
149     , m_unparsedFont(defaultFont)
150     , m_realizedFont(false)
151 {
152 }
153
154 CanvasRenderingContext2D::State::State(const State& other)
155     : CSSFontSelectorClient()
156     , m_unparsedStrokeColor(other.m_unparsedStrokeColor)
157     , m_unparsedFillColor(other.m_unparsedFillColor)
158     , m_strokeStyle(other.m_strokeStyle)
159     , m_fillStyle(other.m_fillStyle)
160     , m_lineWidth(other.m_lineWidth)
161     , m_lineCap(other.m_lineCap)
162     , m_lineJoin(other.m_lineJoin)
163     , m_miterLimit(other.m_miterLimit)
164     , m_shadowOffset(other.m_shadowOffset)
165     , m_shadowBlur(other.m_shadowBlur)
166     , m_shadowColor(other.m_shadowColor)
167     , m_globalAlpha(other.m_globalAlpha)
168     , m_globalComposite(other.m_globalComposite)
169     , m_globalBlend(other.m_globalBlend)
170     , m_transform(other.m_transform)
171     , m_invertibleCTM(other.m_invertibleCTM)
172     , m_lineDashOffset(other.m_lineDashOffset)
173     , m_imageSmoothingEnabled(other.m_imageSmoothingEnabled)
174     , m_textAlign(other.m_textAlign)
175     , m_textBaseline(other.m_textBaseline)
176     , m_unparsedFont(other.m_unparsedFont)
177     , m_font(other.m_font)
178     , m_realizedFont(other.m_realizedFont)
179 {
180     if (m_realizedFont)
181         static_cast<CSSFontSelector*>(m_font.fontSelector())->registerForInvalidationCallbacks(this);
182 }
183
184 CanvasRenderingContext2D::State& CanvasRenderingContext2D::State::operator=(const State& other)
185 {
186     if (this == &other)
187         return *this;
188
189     if (m_realizedFont)
190         static_cast<CSSFontSelector*>(m_font.fontSelector())->unregisterForInvalidationCallbacks(this);
191
192     m_unparsedStrokeColor = other.m_unparsedStrokeColor;
193     m_unparsedFillColor = other.m_unparsedFillColor;
194     m_strokeStyle = other.m_strokeStyle;
195     m_fillStyle = other.m_fillStyle;
196     m_lineWidth = other.m_lineWidth;
197     m_lineCap = other.m_lineCap;
198     m_lineJoin = other.m_lineJoin;
199     m_miterLimit = other.m_miterLimit;
200     m_shadowOffset = other.m_shadowOffset;
201     m_shadowBlur = other.m_shadowBlur;
202     m_shadowColor = other.m_shadowColor;
203     m_globalAlpha = other.m_globalAlpha;
204     m_globalComposite = other.m_globalComposite;
205     m_globalBlend = other.m_globalBlend;
206     m_transform = other.m_transform;
207     m_invertibleCTM = other.m_invertibleCTM;
208     m_imageSmoothingEnabled = other.m_imageSmoothingEnabled;
209     m_textAlign = other.m_textAlign;
210     m_textBaseline = other.m_textBaseline;
211     m_unparsedFont = other.m_unparsedFont;
212     m_font = other.m_font;
213     m_realizedFont = other.m_realizedFont;
214
215     if (m_realizedFont)
216         static_cast<CSSFontSelector*>(m_font.fontSelector())->registerForInvalidationCallbacks(this);
217
218     return *this;
219 }
220
221 CanvasRenderingContext2D::State::~State()
222 {
223     if (m_realizedFont)
224         static_cast<CSSFontSelector*>(m_font.fontSelector())->unregisterForInvalidationCallbacks(this);
225 }
226
227 void CanvasRenderingContext2D::State::fontsNeedUpdate(CSSFontSelector* fontSelector)
228 {
229     ASSERT_ARG(fontSelector, fontSelector == m_font.fontSelector());
230     ASSERT(m_realizedFont);
231
232     m_font.update(fontSelector);
233 }
234
235 void CanvasRenderingContext2D::realizeSavesLoop()
236 {
237     ASSERT(m_unrealizedSaveCount);
238     ASSERT(m_stateStack.size() >= 1);
239     GraphicsContext* context = drawingContext();
240     do {
241         m_stateStack.append(state());
242         if (context)
243             context->save();
244     } while (--m_unrealizedSaveCount);
245 }
246
247 void CanvasRenderingContext2D::restore()
248 {
249     if (m_unrealizedSaveCount) {
250         --m_unrealizedSaveCount;
251         return;
252     }
253     ASSERT(m_stateStack.size() >= 1);
254     if (m_stateStack.size() <= 1)
255         return;
256     m_path.transform(state().m_transform);
257     m_stateStack.removeLast();
258     m_path.transform(state().m_transform.inverse());
259     GraphicsContext* c = drawingContext();
260     if (!c)
261         return;
262     c->restore();
263 }
264
265 CanvasStyle* CanvasRenderingContext2D::strokeStyle() const
266 {
267     return state().m_strokeStyle.get();
268 }
269
270 void CanvasRenderingContext2D::setStrokeStyle(PassRefPtr<CanvasStyle> prpStyle)
271 {
272     RefPtr<CanvasStyle> style = prpStyle;
273
274     if (!style)
275         return;
276
277     if (state().m_strokeStyle && state().m_strokeStyle->isEquivalentColor(*style))
278         return;
279
280     if (style->isCurrentColor()) {
281         if (style->hasOverrideAlpha())
282             style = CanvasStyle::createFromRGBA(colorWithOverrideAlpha(currentColor(canvas()), style->overrideAlpha()));
283         else
284             style = CanvasStyle::createFromRGBA(currentColor(canvas()));
285     } else
286         checkOrigin(style->canvasPattern());
287
288     realizeSaves();
289     modifiableState().m_strokeStyle = style.release();
290     GraphicsContext* c = drawingContext();
291     if (!c)
292         return;
293     state().m_strokeStyle->applyStrokeColor(c);
294     modifiableState().m_unparsedStrokeColor = String();
295 }
296
297 CanvasStyle* CanvasRenderingContext2D::fillStyle() const
298 {
299     return state().m_fillStyle.get();
300 }
301
302 void CanvasRenderingContext2D::setFillStyle(PassRefPtr<CanvasStyle> prpStyle)
303 {
304     RefPtr<CanvasStyle> style = prpStyle;
305
306     if (!style)
307         return;
308
309     if (state().m_fillStyle && state().m_fillStyle->isEquivalentColor(*style))
310         return;
311
312     if (style->isCurrentColor()) {
313         if (style->hasOverrideAlpha())
314             style = CanvasStyle::createFromRGBA(colorWithOverrideAlpha(currentColor(canvas()), style->overrideAlpha()));
315         else
316             style = CanvasStyle::createFromRGBA(currentColor(canvas()));
317     } else
318         checkOrigin(style->canvasPattern());
319
320     realizeSaves();
321     modifiableState().m_fillStyle = style.release();
322     GraphicsContext* c = drawingContext();
323     if (!c)
324         return;
325     state().m_fillStyle->applyFillColor(c);
326     modifiableState().m_unparsedFillColor = String();
327 }
328
329 float CanvasRenderingContext2D::lineWidth() const
330 {
331     return state().m_lineWidth;
332 }
333
334 void CanvasRenderingContext2D::setLineWidth(float width)
335 {
336     if (!(std::isfinite(width) && width > 0))
337         return;
338     if (state().m_lineWidth == width)
339         return;
340     realizeSaves();
341     modifiableState().m_lineWidth = width;
342     GraphicsContext* c = drawingContext();
343     if (!c)
344         return;
345     c->setStrokeThickness(width);
346 }
347
348 String CanvasRenderingContext2D::lineCap() const
349 {
350     return lineCapName(state().m_lineCap);
351 }
352
353 void CanvasRenderingContext2D::setLineCap(const String& s)
354 {
355     LineCap cap;
356     if (!parseLineCap(s, cap))
357         return;
358     if (state().m_lineCap == cap)
359         return;
360     realizeSaves();
361     modifiableState().m_lineCap = cap;
362     GraphicsContext* c = drawingContext();
363     if (!c)
364         return;
365     c->setLineCap(cap);
366 }
367
368 String CanvasRenderingContext2D::lineJoin() const
369 {
370     return lineJoinName(state().m_lineJoin);
371 }
372
373 void CanvasRenderingContext2D::setLineJoin(const String& s)
374 {
375     LineJoin join;
376     if (!parseLineJoin(s, join))
377         return;
378     if (state().m_lineJoin == join)
379         return;
380     realizeSaves();
381     modifiableState().m_lineJoin = join;
382     GraphicsContext* c = drawingContext();
383     if (!c)
384         return;
385     c->setLineJoin(join);
386 }
387
388 float CanvasRenderingContext2D::miterLimit() const
389 {
390     return state().m_miterLimit;
391 }
392
393 void CanvasRenderingContext2D::setMiterLimit(float limit)
394 {
395     if (!(std::isfinite(limit) && limit > 0))
396         return;
397     if (state().m_miterLimit == limit)
398         return;
399     realizeSaves();
400     modifiableState().m_miterLimit = limit;
401     GraphicsContext* c = drawingContext();
402     if (!c)
403         return;
404     c->setMiterLimit(limit);
405 }
406
407 float CanvasRenderingContext2D::shadowOffsetX() const
408 {
409     return state().m_shadowOffset.width();
410 }
411
412 void CanvasRenderingContext2D::setShadowOffsetX(float x)
413 {
414     if (!std::isfinite(x))
415         return;
416     if (state().m_shadowOffset.width() == x)
417         return;
418     realizeSaves();
419     modifiableState().m_shadowOffset.setWidth(x);
420     applyShadow();
421 }
422
423 float CanvasRenderingContext2D::shadowOffsetY() const
424 {
425     return state().m_shadowOffset.height();
426 }
427
428 void CanvasRenderingContext2D::setShadowOffsetY(float y)
429 {
430     if (!std::isfinite(y))
431         return;
432     if (state().m_shadowOffset.height() == y)
433         return;
434     realizeSaves();
435     modifiableState().m_shadowOffset.setHeight(y);
436     applyShadow();
437 }
438
439 float CanvasRenderingContext2D::shadowBlur() const
440 {
441     return state().m_shadowBlur;
442 }
443
444 void CanvasRenderingContext2D::setShadowBlur(float blur)
445 {
446     if (!(std::isfinite(blur) && blur >= 0))
447         return;
448     if (state().m_shadowBlur == blur)
449         return;
450     realizeSaves();
451     modifiableState().m_shadowBlur = blur;
452     applyShadow();
453 }
454
455 String CanvasRenderingContext2D::shadowColor() const
456 {
457     return Color(state().m_shadowColor).serialized();
458 }
459
460 void CanvasRenderingContext2D::setShadowColor(const String& color)
461 {
462     RGBA32 rgba;
463     if (!parseColorOrCurrentColor(rgba, color, canvas()))
464         return;
465     if (state().m_shadowColor == rgba)
466         return;
467     realizeSaves();
468     modifiableState().m_shadowColor = rgba;
469     applyShadow();
470 }
471
472 const Vector<float>& CanvasRenderingContext2D::getLineDash() const
473 {
474     return state().m_lineDash;
475 }
476
477 static bool lineDashSequenceIsValid(const Vector<float>& dash)
478 {
479     for (size_t i = 0; i < dash.size(); i++) {
480         if (!std::isfinite(dash[i]) || dash[i] < 0)
481             return false;
482     }
483     return true;
484 }
485
486 void CanvasRenderingContext2D::setLineDash(const Vector<float>& dash)
487 {
488     if (!lineDashSequenceIsValid(dash))
489         return;
490
491     realizeSaves();
492     modifiableState().m_lineDash = dash;
493     // Spec requires the concatenation of two copies the dash list when the
494     // number of elements is odd
495     if (dash.size() % 2)
496         modifiableState().m_lineDash.append(dash);
497
498     applyLineDash();
499 }
500
501 void CanvasRenderingContext2D::setWebkitLineDash(const Vector<float>& dash)
502 {
503     if (!lineDashSequenceIsValid(dash))
504         return;
505
506     realizeSaves();
507     modifiableState().m_lineDash = dash;
508
509     applyLineDash();
510 }
511
512 float CanvasRenderingContext2D::lineDashOffset() const
513 {
514     return state().m_lineDashOffset;
515 }
516
517 void CanvasRenderingContext2D::setLineDashOffset(float offset)
518 {
519     if (!std::isfinite(offset) || state().m_lineDashOffset == offset)
520         return;
521
522     realizeSaves();
523     modifiableState().m_lineDashOffset = offset;
524     applyLineDash();
525 }
526
527 float CanvasRenderingContext2D::webkitLineDashOffset() const
528 {
529     return lineDashOffset();
530 }
531
532 void CanvasRenderingContext2D::setWebkitLineDashOffset(float offset)
533 {
534     setLineDashOffset(offset);
535 }
536
537 void CanvasRenderingContext2D::applyLineDash() const
538 {
539     GraphicsContext* c = drawingContext();
540     if (!c)
541         return;
542     DashArray convertedLineDash(state().m_lineDash.size());
543     for (size_t i = 0; i < state().m_lineDash.size(); ++i)
544         convertedLineDash[i] = static_cast<DashArrayElement>(state().m_lineDash[i]);
545     c->setLineDash(convertedLineDash, state().m_lineDashOffset);
546 }
547
548 float CanvasRenderingContext2D::globalAlpha() const
549 {
550     return state().m_globalAlpha;
551 }
552
553 void CanvasRenderingContext2D::setGlobalAlpha(float alpha)
554 {
555     if (!(alpha >= 0 && alpha <= 1))
556         return;
557     if (state().m_globalAlpha == alpha)
558         return;
559     realizeSaves();
560     modifiableState().m_globalAlpha = alpha;
561     GraphicsContext* c = drawingContext();
562     if (!c)
563         return;
564     c->setAlpha(alpha);
565 }
566
567 String CanvasRenderingContext2D::globalCompositeOperation() const
568 {
569     return compositeOperatorName(state().m_globalComposite, state().m_globalBlend);
570 }
571
572 void CanvasRenderingContext2D::setGlobalCompositeOperation(const String& operation)
573 {
574     CompositeOperator op = CompositeSourceOver;
575     blink::WebBlendMode blendMode = blink::WebBlendModeNormal;
576     if (!parseCompositeAndBlendOperator(operation, op, blendMode))
577         return;
578     if ((state().m_globalComposite == op) && (state().m_globalBlend == blendMode))
579         return;
580     realizeSaves();
581     modifiableState().m_globalComposite = op;
582     modifiableState().m_globalBlend = blendMode;
583     GraphicsContext* c = drawingContext();
584     if (!c)
585         return;
586     c->setCompositeOperation(op, blendMode);
587 }
588
589 void CanvasRenderingContext2D::setCurrentTransform(const SVGMatrix& matrix)
590 {
591     setTransform(matrix.a(), matrix.b(), matrix.c(), matrix.d(), matrix.e(), matrix.f());
592 }
593
594 void CanvasRenderingContext2D::scale(float sx, float sy)
595 {
596     GraphicsContext* c = drawingContext();
597     if (!c)
598         return;
599     if (!state().m_invertibleCTM)
600         return;
601
602     if (!std::isfinite(sx) | !std::isfinite(sy))
603         return;
604
605     AffineTransform newTransform = state().m_transform;
606     newTransform.scaleNonUniform(sx, sy);
607     if (state().m_transform == newTransform)
608         return;
609
610     realizeSaves();
611
612     if (!newTransform.isInvertible()) {
613         modifiableState().m_invertibleCTM = false;
614         return;
615     }
616
617     modifiableState().m_transform = newTransform;
618     c->scale(FloatSize(sx, sy));
619     m_path.transform(AffineTransform().scaleNonUniform(1.0 / sx, 1.0 / sy));
620 }
621
622 void CanvasRenderingContext2D::rotate(float angleInRadians)
623 {
624     GraphicsContext* c = drawingContext();
625     if (!c)
626         return;
627     if (!state().m_invertibleCTM)
628         return;
629
630     if (!std::isfinite(angleInRadians))
631         return;
632
633     AffineTransform newTransform = state().m_transform;
634     newTransform.rotate(angleInRadians / piDouble * 180.0);
635     if (state().m_transform == newTransform)
636         return;
637
638     realizeSaves();
639
640     if (!newTransform.isInvertible()) {
641         modifiableState().m_invertibleCTM = false;
642         return;
643     }
644
645     modifiableState().m_transform = newTransform;
646     c->rotate(angleInRadians);
647     m_path.transform(AffineTransform().rotate(-angleInRadians / piDouble * 180.0));
648 }
649
650 void CanvasRenderingContext2D::translate(float tx, float ty)
651 {
652     GraphicsContext* c = drawingContext();
653     if (!c)
654         return;
655     if (!state().m_invertibleCTM)
656         return;
657
658     if (!std::isfinite(tx) | !std::isfinite(ty))
659         return;
660
661     AffineTransform newTransform = state().m_transform;
662     newTransform.translate(tx, ty);
663     if (state().m_transform == newTransform)
664         return;
665
666     realizeSaves();
667
668     if (!newTransform.isInvertible()) {
669         modifiableState().m_invertibleCTM = false;
670         return;
671     }
672
673     modifiableState().m_transform = newTransform;
674     c->translate(tx, ty);
675     m_path.transform(AffineTransform().translate(-tx, -ty));
676 }
677
678 void CanvasRenderingContext2D::transform(float m11, float m12, float m21, float m22, float dx, float dy)
679 {
680     GraphicsContext* c = drawingContext();
681     if (!c)
682         return;
683     if (!state().m_invertibleCTM)
684         return;
685
686     if (!std::isfinite(m11) | !std::isfinite(m21) | !std::isfinite(dx) | !std::isfinite(m12) | !std::isfinite(m22) | !std::isfinite(dy))
687         return;
688
689     AffineTransform transform(m11, m12, m21, m22, dx, dy);
690     AffineTransform newTransform = state().m_transform * transform;
691     if (state().m_transform == newTransform)
692         return;
693
694     realizeSaves();
695
696     modifiableState().m_transform = newTransform;
697     if (!newTransform.isInvertible()) {
698         modifiableState().m_invertibleCTM = false;
699         return;
700     }
701
702     c->concatCTM(transform);
703     m_path.transform(transform.inverse());
704 }
705
706 void CanvasRenderingContext2D::resetTransform()
707 {
708     GraphicsContext* c = drawingContext();
709     if (!c)
710         return;
711
712     AffineTransform ctm = state().m_transform;
713     bool invertibleCTM = state().m_invertibleCTM;
714     // It is possible that CTM is identity while CTM is not invertible.
715     // When CTM becomes non-invertible, realizeSaves() can make CTM identity.
716     if (ctm.isIdentity() && invertibleCTM)
717         return;
718
719     realizeSaves();
720     // resetTransform() resolves the non-invertible CTM state.
721     modifiableState().m_transform.makeIdentity();
722     modifiableState().m_invertibleCTM = true;
723     c->setCTM(canvas()->baseTransform());
724
725     if (invertibleCTM)
726         m_path.transform(ctm);
727     // When else, do nothing because all transform methods didn't update m_path when CTM became non-invertible.
728     // It means that resetTransform() restores m_path just before CTM became non-invertible.
729 }
730
731 void CanvasRenderingContext2D::setTransform(float m11, float m12, float m21, float m22, float dx, float dy)
732 {
733     GraphicsContext* c = drawingContext();
734     if (!c)
735         return;
736
737     if (!std::isfinite(m11) | !std::isfinite(m21) | !std::isfinite(dx) | !std::isfinite(m12) | !std::isfinite(m22) | !std::isfinite(dy))
738         return;
739
740     resetTransform();
741     transform(m11, m12, m21, m22, dx, dy);
742 }
743
744 void CanvasRenderingContext2D::setStrokeColor(const String& color)
745 {
746     if (color == state().m_unparsedStrokeColor)
747         return;
748     realizeSaves();
749     setStrokeStyle(CanvasStyle::createFromString(color, &canvas()->document()));
750     modifiableState().m_unparsedStrokeColor = color;
751 }
752
753 void CanvasRenderingContext2D::setStrokeColor(float grayLevel)
754 {
755     if (state().m_strokeStyle && state().m_strokeStyle->isEquivalentRGBA(grayLevel, grayLevel, grayLevel, 1.0f))
756         return;
757     setStrokeStyle(CanvasStyle::createFromGrayLevelWithAlpha(grayLevel, 1.0f));
758 }
759
760 void CanvasRenderingContext2D::setStrokeColor(const String& color, float alpha)
761 {
762     setStrokeStyle(CanvasStyle::createFromStringWithOverrideAlpha(color, alpha));
763 }
764
765 void CanvasRenderingContext2D::setStrokeColor(float grayLevel, float alpha)
766 {
767     if (state().m_strokeStyle && state().m_strokeStyle->isEquivalentRGBA(grayLevel, grayLevel, grayLevel, alpha))
768         return;
769     setStrokeStyle(CanvasStyle::createFromGrayLevelWithAlpha(grayLevel, alpha));
770 }
771
772 void CanvasRenderingContext2D::setStrokeColor(float r, float g, float b, float a)
773 {
774     if (state().m_strokeStyle && state().m_strokeStyle->isEquivalentRGBA(r, g, b, a))
775         return;
776     setStrokeStyle(CanvasStyle::createFromRGBAChannels(r, g, b, a));
777 }
778
779 void CanvasRenderingContext2D::setStrokeColor(float c, float m, float y, float k, float a)
780 {
781     if (state().m_strokeStyle && state().m_strokeStyle->isEquivalentCMYKA(c, m, y, k, a))
782         return;
783     setStrokeStyle(CanvasStyle::createFromCMYKAChannels(c, m, y, k, a));
784 }
785
786 void CanvasRenderingContext2D::setFillColor(const String& color)
787 {
788     if (color == state().m_unparsedFillColor)
789         return;
790     realizeSaves();
791     setFillStyle(CanvasStyle::createFromString(color, &canvas()->document()));
792     modifiableState().m_unparsedFillColor = color;
793 }
794
795 void CanvasRenderingContext2D::setFillColor(float grayLevel)
796 {
797     if (state().m_fillStyle && state().m_fillStyle->isEquivalentRGBA(grayLevel, grayLevel, grayLevel, 1.0f))
798         return;
799     setFillStyle(CanvasStyle::createFromGrayLevelWithAlpha(grayLevel, 1.0f));
800 }
801
802 void CanvasRenderingContext2D::setFillColor(const String& color, float alpha)
803 {
804     setFillStyle(CanvasStyle::createFromStringWithOverrideAlpha(color, alpha));
805 }
806
807 void CanvasRenderingContext2D::setFillColor(float grayLevel, float alpha)
808 {
809     if (state().m_fillStyle && state().m_fillStyle->isEquivalentRGBA(grayLevel, grayLevel, grayLevel, alpha))
810         return;
811     setFillStyle(CanvasStyle::createFromGrayLevelWithAlpha(grayLevel, alpha));
812 }
813
814 void CanvasRenderingContext2D::setFillColor(float r, float g, float b, float a)
815 {
816     if (state().m_fillStyle && state().m_fillStyle->isEquivalentRGBA(r, g, b, a))
817         return;
818     setFillStyle(CanvasStyle::createFromRGBAChannels(r, g, b, a));
819 }
820
821 void CanvasRenderingContext2D::setFillColor(float c, float m, float y, float k, float a)
822 {
823     if (state().m_fillStyle && state().m_fillStyle->isEquivalentCMYKA(c, m, y, k, a))
824         return;
825     setFillStyle(CanvasStyle::createFromCMYKAChannels(c, m, y, k, a));
826 }
827
828 void CanvasRenderingContext2D::beginPath()
829 {
830     m_path.clear();
831 }
832
833 PassRefPtr<DOMPath> CanvasRenderingContext2D::currentPath()
834 {
835     return DOMPath::create(m_path);
836 }
837
838 void CanvasRenderingContext2D::setCurrentPath(DOMPath* path)
839 {
840     if (!path)
841         return;
842     m_path = path->path();
843 }
844
845 static bool validateRectForCanvas(float& x, float& y, float& width, float& height)
846 {
847     if (!std::isfinite(x) | !std::isfinite(y) | !std::isfinite(width) | !std::isfinite(height))
848         return false;
849
850     if (!width && !height)
851         return false;
852
853     if (width < 0) {
854         width = -width;
855         x -= width;
856     }
857
858     if (height < 0) {
859         height = -height;
860         y -= height;
861     }
862
863     return true;
864 }
865
866 static bool isFullCanvasCompositeMode(CompositeOperator op)
867 {
868     // See 4.8.11.1.3 Compositing
869     // CompositeSourceAtop and CompositeDestinationOut are not listed here as the platforms already
870     // implement the specification's behavior.
871     return op == CompositeSourceIn || op == CompositeSourceOut || op == CompositeDestinationIn || op == CompositeDestinationAtop;
872 }
873
874 static bool parseWinding(const String& windingRuleString, WindRule& windRule)
875 {
876     if (windingRuleString == "nonzero")
877         windRule = RULE_NONZERO;
878     else if (windingRuleString == "evenodd")
879         windRule = RULE_EVENODD;
880     else
881         return false;
882
883     return true;
884 }
885
886 void CanvasRenderingContext2D::fill(const String& windingRuleString)
887 {
888     GraphicsContext* c = drawingContext();
889     if (!c)
890         return;
891     if (!state().m_invertibleCTM)
892         return;
893     FloatRect clipBounds;
894     if (!drawingContext()->getTransformedClipBounds(&clipBounds))
895         return;
896
897     // If gradient size is zero, then paint nothing.
898     Gradient* gradient = c->fillGradient();
899     if (gradient && gradient->isZeroSize())
900         return;
901
902     if (!m_path.isEmpty()) {
903         WindRule windRule = c->fillRule();
904         WindRule newWindRule = RULE_NONZERO;
905         if (!parseWinding(windingRuleString, newWindRule))
906             return;
907         c->setFillRule(newWindRule);
908
909         if (isFullCanvasCompositeMode(state().m_globalComposite)) {
910             fullCanvasCompositedFill(m_path);
911             didDraw(clipBounds);
912         } else if (state().m_globalComposite == CompositeCopy) {
913             clearCanvas();
914             c->fillPath(m_path);
915             didDraw(clipBounds);
916         } else {
917             FloatRect dirtyRect;
918             if (computeDirtyRect(m_path.boundingRect(), clipBounds, &dirtyRect)) {
919                 c->fillPath(m_path);
920                 didDraw(dirtyRect);
921             }
922         }
923
924         c->setFillRule(windRule);
925     }
926 }
927
928 void CanvasRenderingContext2D::stroke()
929 {
930     GraphicsContext* c = drawingContext();
931     if (!c)
932         return;
933     if (!state().m_invertibleCTM)
934         return;
935
936     // If gradient size is zero, then paint nothing.
937     Gradient* gradient = c->strokeGradient();
938     if (gradient && gradient->isZeroSize())
939         return;
940
941     if (!m_path.isEmpty()) {
942         FloatRect bounds = m_path.boundingRect();
943         inflateStrokeRect(bounds);
944         FloatRect dirtyRect;
945         if (computeDirtyRect(bounds, &dirtyRect)) {
946             c->strokePath(m_path);
947             didDraw(dirtyRect);
948         }
949     }
950 }
951
952 void CanvasRenderingContext2D::clip(const String& windingRuleString)
953 {
954     GraphicsContext* c = drawingContext();
955     if (!c)
956         return;
957     if (!state().m_invertibleCTM)
958         return;
959
960     WindRule newWindRule = RULE_NONZERO;
961     if (!parseWinding(windingRuleString, newWindRule))
962         return;
963
964     realizeSaves();
965     c->canvasClip(m_path, newWindRule);
966 }
967
968 bool CanvasRenderingContext2D::isPointInPath(const float x, const float y, const String& windingRuleString)
969 {
970     GraphicsContext* c = drawingContext();
971     if (!c)
972         return false;
973     if (!state().m_invertibleCTM)
974         return false;
975
976     FloatPoint point(x, y);
977     AffineTransform ctm = state().m_transform;
978     FloatPoint transformedPoint = ctm.inverse().mapPoint(point);
979     if (!std::isfinite(transformedPoint.x()) || !std::isfinite(transformedPoint.y()))
980         return false;
981
982     WindRule windRule = RULE_NONZERO;
983     if (!parseWinding(windingRuleString, windRule))
984         return false;
985
986     return m_path.contains(transformedPoint, windRule);
987 }
988
989
990 bool CanvasRenderingContext2D::isPointInStroke(const float x, const float y)
991 {
992     GraphicsContext* c = drawingContext();
993     if (!c)
994         return false;
995     if (!state().m_invertibleCTM)
996         return false;
997
998     FloatPoint point(x, y);
999     AffineTransform ctm = state().m_transform;
1000     FloatPoint transformedPoint = ctm.inverse().mapPoint(point);
1001     if (!std::isfinite(transformedPoint.x()) || !std::isfinite(transformedPoint.y()))
1002         return false;
1003
1004     StrokeData strokeData;
1005     strokeData.setThickness(lineWidth());
1006     strokeData.setLineCap(getLineCap());
1007     strokeData.setLineJoin(getLineJoin());
1008     strokeData.setMiterLimit(miterLimit());
1009     strokeData.setLineDash(getLineDash(), lineDashOffset());
1010     return m_path.strokeContains(transformedPoint, strokeData);
1011 }
1012
1013 void CanvasRenderingContext2D::clearRect(float x, float y, float width, float height)
1014 {
1015     if (!validateRectForCanvas(x, y, width, height))
1016         return;
1017     GraphicsContext* context = drawingContext();
1018     if (!context)
1019         return;
1020     if (!state().m_invertibleCTM)
1021         return;
1022     FloatRect rect(x, y, width, height);
1023
1024     FloatRect dirtyRect;
1025     if (!computeDirtyRect(rect, &dirtyRect))
1026         return;
1027
1028     bool saved = false;
1029     if (shouldDrawShadows()) {
1030         context->save();
1031         saved = true;
1032         context->clearShadow();
1033     }
1034     if (state().m_globalAlpha != 1) {
1035         if (!saved) {
1036             context->save();
1037             saved = true;
1038         }
1039         context->setAlpha(1);
1040     }
1041     if (state().m_globalComposite != CompositeSourceOver) {
1042         if (!saved) {
1043             context->save();
1044             saved = true;
1045         }
1046         context->setCompositeOperation(CompositeSourceOver);
1047     }
1048     context->clearRect(rect);
1049     if (saved)
1050         context->restore();
1051
1052     didDraw(dirtyRect);
1053 }
1054
1055 void CanvasRenderingContext2D::fillRect(float x, float y, float width, float height)
1056 {
1057     if (!validateRectForCanvas(x, y, width, height))
1058         return;
1059
1060     GraphicsContext* c = drawingContext();
1061     if (!c)
1062         return;
1063     if (!state().m_invertibleCTM)
1064         return;
1065     FloatRect clipBounds;
1066     if (!drawingContext()->getTransformedClipBounds(&clipBounds))
1067         return;
1068
1069     // from the HTML5 Canvas spec:
1070     // If x0 = x1 and y0 = y1, then the linear gradient must paint nothing
1071     // If x0 = x1 and y0 = y1 and r0 = r1, then the radial gradient must paint nothing
1072     Gradient* gradient = c->fillGradient();
1073     if (gradient && gradient->isZeroSize())
1074         return;
1075
1076     FloatRect rect(x, y, width, height);
1077     if (rectContainsTransformedRect(rect, clipBounds)) {
1078         c->fillRect(rect);
1079         didDraw(clipBounds);
1080     } else if (isFullCanvasCompositeMode(state().m_globalComposite)) {
1081         fullCanvasCompositedFill(rect);
1082         didDraw(clipBounds);
1083     } else if (state().m_globalComposite == CompositeCopy) {
1084         clearCanvas();
1085         c->fillRect(rect);
1086         didDraw(clipBounds);
1087     } else {
1088         FloatRect dirtyRect;
1089         if (computeDirtyRect(rect, clipBounds, &dirtyRect)) {
1090             c->fillRect(rect);
1091             didDraw(dirtyRect);
1092         }
1093     }
1094 }
1095
1096 void CanvasRenderingContext2D::strokeRect(float x, float y, float width, float height)
1097 {
1098     if (!validateRectForCanvas(x, y, width, height))
1099         return;
1100
1101     if (!(state().m_lineWidth >= 0))
1102         return;
1103
1104     GraphicsContext* c = drawingContext();
1105     if (!c)
1106         return;
1107     if (!state().m_invertibleCTM)
1108         return;
1109
1110     // If gradient size is zero, then paint nothing.
1111     Gradient* gradient = c->strokeGradient();
1112     if (gradient && gradient->isZeroSize())
1113         return;
1114
1115     FloatRect rect(x, y, width, height);
1116
1117     FloatRect boundingRect = rect;
1118     boundingRect.inflate(state().m_lineWidth / 2);
1119     FloatRect dirtyRect;
1120     if (computeDirtyRect(boundingRect, &dirtyRect)) {
1121         c->strokeRect(rect, state().m_lineWidth);
1122         didDraw(dirtyRect);
1123     }
1124 }
1125
1126 void CanvasRenderingContext2D::setShadow(float width, float height, float blur)
1127 {
1128     setShadow(FloatSize(width, height), blur, Color::transparent);
1129 }
1130
1131 void CanvasRenderingContext2D::setShadow(float width, float height, float blur, const String& color)
1132 {
1133     RGBA32 rgba;
1134     if (!parseColorOrCurrentColor(rgba, color, canvas()))
1135         return;
1136     setShadow(FloatSize(width, height), blur, rgba);
1137 }
1138
1139 void CanvasRenderingContext2D::setShadow(float width, float height, float blur, float grayLevel)
1140 {
1141     setShadow(FloatSize(width, height), blur, makeRGBA32FromFloats(grayLevel, grayLevel, grayLevel, 1));
1142 }
1143
1144 void CanvasRenderingContext2D::setShadow(float width, float height, float blur, const String& color, float alpha)
1145 {
1146     RGBA32 rgba;
1147     if (!parseColorOrCurrentColor(rgba, color, canvas()))
1148         return;
1149     setShadow(FloatSize(width, height), blur, colorWithOverrideAlpha(rgba, alpha));
1150 }
1151
1152 void CanvasRenderingContext2D::setShadow(float width, float height, float blur, float grayLevel, float alpha)
1153 {
1154     setShadow(FloatSize(width, height), blur, makeRGBA32FromFloats(grayLevel, grayLevel, grayLevel, alpha));
1155 }
1156
1157 void CanvasRenderingContext2D::setShadow(float width, float height, float blur, float r, float g, float b, float a)
1158 {
1159     setShadow(FloatSize(width, height), blur, makeRGBA32FromFloats(r, g, b, a));
1160 }
1161
1162 void CanvasRenderingContext2D::setShadow(float width, float height, float blur, float c, float m, float y, float k, float a)
1163 {
1164     setShadow(FloatSize(width, height), blur, makeRGBAFromCMYKA(c, m, y, k, a));
1165 }
1166
1167 void CanvasRenderingContext2D::clearShadow()
1168 {
1169     setShadow(FloatSize(), 0, Color::transparent);
1170 }
1171
1172 void CanvasRenderingContext2D::setShadow(const FloatSize& offset, float blur, RGBA32 color)
1173 {
1174     if (state().m_shadowOffset == offset && state().m_shadowBlur == blur && state().m_shadowColor == color)
1175         return;
1176     bool wasDrawingShadows = shouldDrawShadows();
1177     realizeSaves();
1178     modifiableState().m_shadowOffset = offset;
1179     modifiableState().m_shadowBlur = blur;
1180     modifiableState().m_shadowColor = color;
1181     if (!wasDrawingShadows && !shouldDrawShadows())
1182         return;
1183     applyShadow();
1184 }
1185
1186 void CanvasRenderingContext2D::applyShadow()
1187 {
1188     GraphicsContext* c = drawingContext();
1189     if (!c)
1190         return;
1191
1192     if (shouldDrawShadows()) {
1193         c->setShadow(state().m_shadowOffset, state().m_shadowBlur, state().m_shadowColor,
1194             DrawLooper::ShadowIgnoresTransforms);
1195     } else {
1196         c->clearShadow();
1197     }
1198 }
1199
1200 bool CanvasRenderingContext2D::shouldDrawShadows() const
1201 {
1202     return alphaChannel(state().m_shadowColor) && (state().m_shadowBlur || !state().m_shadowOffset.isZero());
1203 }
1204
1205 enum ImageSizeType {
1206     ImageSizeAfterDevicePixelRatio,
1207     ImageSizeBeforeDevicePixelRatio
1208 };
1209
1210 static LayoutSize sizeFor(HTMLImageElement* image, ImageSizeType sizeType)
1211 {
1212     LayoutSize size;
1213     ImageResource* cachedImage = image->cachedImage();
1214     if (cachedImage) {
1215         size = cachedImage->imageSizeForRenderer(image->renderer(), 1.0f); // FIXME: Not sure about this.
1216
1217         if (sizeType == ImageSizeAfterDevicePixelRatio && image->renderer() && image->renderer()->isRenderImage() && cachedImage->image() && !cachedImage->image()->hasRelativeWidth())
1218             size.scale(toRenderImage(image->renderer())->imageDevicePixelRatio());
1219     }
1220     return size;
1221 }
1222
1223 static IntSize sizeFor(HTMLVideoElement* video)
1224 {
1225     if (MediaPlayer* player = video->player())
1226         return player->naturalSize();
1227     return IntSize();
1228 }
1229
1230 static inline FloatRect normalizeRect(const FloatRect& rect)
1231 {
1232     return FloatRect(min(rect.x(), rect.maxX()),
1233         min(rect.y(), rect.maxY()),
1234         max(rect.width(), -rect.width()),
1235         max(rect.height(), -rect.height()));
1236 }
1237
1238 static inline void clipRectsToImageRect(const FloatRect& imageRect, FloatRect* srcRect, FloatRect* dstRect)
1239 {
1240     if (imageRect.contains(*srcRect))
1241         return;
1242
1243     // Compute the src to dst transform
1244     FloatSize scale(dstRect->size().width() / srcRect->size().width(), dstRect->size().height() / srcRect->size().height());
1245     FloatPoint scaledSrcLocation = srcRect->location();
1246     scaledSrcLocation.scale(scale.width(), scale.height());
1247     FloatSize offset = dstRect->location() - scaledSrcLocation;
1248
1249     srcRect->intersect(imageRect);
1250
1251     // To clip the destination rectangle in the same proportion, transform the clipped src rect
1252     *dstRect = *srcRect;
1253     dstRect->scale(scale.width(), scale.height());
1254     dstRect->move(offset);
1255 }
1256
1257 void CanvasRenderingContext2D::drawImageInternal(Image* image, const FloatRect& srcRect, const FloatRect& dstRect, const CompositeOperator& op, const blink::WebBlendMode& blendMode)
1258 {
1259     if (!image)
1260         return;
1261
1262     GraphicsContext* c = drawingContext();
1263     if (!c)
1264         return;
1265     if (!state().m_invertibleCTM)
1266         return;
1267     FloatRect clipBounds;
1268     if (!drawingContext()->getTransformedClipBounds(&clipBounds))
1269         return;
1270
1271     if (rectContainsTransformedRect(dstRect, clipBounds)) {
1272         c->drawImage(image, dstRect, srcRect, op, blendMode);
1273         didDraw(clipBounds);
1274     } else if (isFullCanvasCompositeMode(op)) {
1275         fullCanvasCompositedDrawImage(image, dstRect, srcRect, op);
1276         didDraw(clipBounds);
1277     } else if (op == CompositeCopy) {
1278         clearCanvas();
1279         c->drawImage(image, dstRect, srcRect, op, blendMode);
1280         didDraw(clipBounds);
1281     } else {
1282         FloatRect dirtyRect;
1283         if (computeDirtyRect(dstRect, &dirtyRect)) {
1284             c->drawImage(image, dstRect, srcRect, op, blendMode);
1285             didDraw(dirtyRect);
1286         }
1287     }
1288 }
1289
1290 void CanvasRenderingContext2D::drawImage(ImageBitmap* bitmap, float x, float y, ExceptionState& exceptionState)
1291 {
1292     if (!bitmap) {
1293         exceptionState.throwDOMException(TypeMismatchError, "The element provided is invalid.");
1294         return;
1295     }
1296     drawImage(bitmap, x, y, bitmap->width(), bitmap->height(), exceptionState);
1297 }
1298
1299 void CanvasRenderingContext2D::drawImage(ImageBitmap* bitmap,
1300     float x, float y, float width, float height, ExceptionState& exceptionState)
1301 {
1302     if (!bitmap) {
1303         exceptionState.throwDOMException(TypeMismatchError, "The element provided is invalid.");
1304         return;
1305     }
1306     if (!bitmap->bitmapRect().width() || !bitmap->bitmapRect().height())
1307         return;
1308
1309     drawImage(bitmap, 0, 0, bitmap->width(), bitmap->height(), x, y, width, height, exceptionState);
1310 }
1311
1312 void CanvasRenderingContext2D::drawImage(ImageBitmap* bitmap,
1313     float sx, float sy, float sw, float sh,
1314     float dx, float dy, float dw, float dh, ExceptionState& exceptionState)
1315 {
1316     if (!bitmap) {
1317         exceptionState.throwDOMException(TypeMismatchError, "The element provided is invalid.");
1318         return;
1319     }
1320
1321     FloatRect srcRect(sx, sy, sw, sh);
1322     FloatRect dstRect(dx, dy, dw, dh);
1323     FloatRect bitmapRect = bitmap->bitmapRect();
1324
1325     if (!std::isfinite(dstRect.x()) || !std::isfinite(dstRect.y()) || !std::isfinite(dstRect.width()) || !std::isfinite(dstRect.height())
1326         || !std::isfinite(srcRect.x()) || !std::isfinite(srcRect.y()) || !std::isfinite(srcRect.width()) || !std::isfinite(srcRect.height()))
1327         return;
1328
1329     if (!dstRect.width() || !dstRect.height())
1330         return;
1331     if (!srcRect.width() || !srcRect.height()) {
1332         exceptionState.throwDOMException(IndexSizeError, String::format("The source %s is 0.", srcRect.width() ? "height" : "width"));
1333         return;
1334     }
1335
1336     ASSERT(bitmap->height() && bitmap->width());
1337     FloatRect normalizedSrcRect = normalizeRect(srcRect);
1338     FloatRect normalizedDstRect = normalizeRect(dstRect);
1339
1340     // Clip the rects to where the user thinks that the image is situated.
1341     clipRectsToImageRect(IntRect(IntPoint(), bitmap->size()), &normalizedSrcRect, &normalizedDstRect);
1342
1343     FloatRect intersectRect = intersection(bitmapRect, normalizedSrcRect);
1344     FloatRect actualSrcRect(intersectRect);
1345
1346     IntPoint bitmapOffset = bitmap->bitmapOffset();
1347     actualSrcRect.move(bitmapOffset - bitmapRect.location());
1348     FloatRect imageRect = FloatRect(bitmapOffset, bitmapRect.size());
1349
1350     FloatRect actualDstRect(FloatPoint(intersectRect.location() - normalizedSrcRect.location()), bitmapRect.size());
1351     actualDstRect.scale(normalizedDstRect.width() / normalizedSrcRect.width() * intersectRect.width() / bitmapRect.width(),
1352         normalizedDstRect.height() / normalizedSrcRect.height() * intersectRect.height() / bitmapRect.height());
1353     actualDstRect.moveBy(normalizedDstRect.location());
1354
1355     if (!imageRect.intersects(actualSrcRect))
1356         return;
1357
1358     RefPtr<Image> imageForRendering = bitmap->bitmapImage();
1359     if (!imageForRendering)
1360         return;
1361
1362     drawImageInternal(imageForRendering.get(), actualSrcRect, actualDstRect, state().m_globalComposite, state().m_globalBlend);
1363 }
1364
1365 void CanvasRenderingContext2D::drawImage(HTMLImageElement* image, float x, float y, ExceptionState& exceptionState)
1366 {
1367     if (!image) {
1368         exceptionState.throwDOMException(TypeMismatchError, "The image element provided is invalid.");
1369         return;
1370     }
1371     LayoutSize destRectSize = sizeFor(image, ImageSizeAfterDevicePixelRatio);
1372     drawImage(image, x, y, destRectSize.width(), destRectSize.height(), exceptionState);
1373 }
1374
1375 void CanvasRenderingContext2D::drawImage(HTMLImageElement* image,
1376     float x, float y, float width, float height, ExceptionState& exceptionState)
1377 {
1378     if (!image) {
1379         exceptionState.throwDOMException(TypeMismatchError, "The image element provided is invalid.");
1380         return;
1381     }
1382     LayoutSize sourceRectSize = sizeFor(image, ImageSizeBeforeDevicePixelRatio);
1383     drawImage(image, FloatRect(0, 0, sourceRectSize.width(), sourceRectSize.height()), FloatRect(x, y, width, height), exceptionState);
1384 }
1385
1386 void CanvasRenderingContext2D::drawImage(HTMLImageElement* image,
1387     float sx, float sy, float sw, float sh,
1388     float dx, float dy, float dw, float dh, ExceptionState& exceptionState)
1389 {
1390     drawImage(image, FloatRect(sx, sy, sw, sh), FloatRect(dx, dy, dw, dh), exceptionState);
1391 }
1392
1393 void CanvasRenderingContext2D::drawImage(HTMLImageElement* image, const FloatRect& srcRect, const FloatRect& dstRect, ExceptionState& exceptionState)
1394 {
1395     drawImage(image, srcRect, dstRect, state().m_globalComposite, state().m_globalBlend, exceptionState);
1396 }
1397
1398 void CanvasRenderingContext2D::drawImage(HTMLImageElement* image, const FloatRect& srcRect, const FloatRect& dstRect, const CompositeOperator& op, const blink::WebBlendMode& blendMode, ExceptionState& exceptionState)
1399 {
1400     if (!image) {
1401         exceptionState.throwDOMException(TypeMismatchError, "The image element provided is invalid.");
1402         return;
1403     }
1404
1405     if (!std::isfinite(dstRect.x()) || !std::isfinite(dstRect.y()) || !std::isfinite(dstRect.width()) || !std::isfinite(dstRect.height())
1406         || !std::isfinite(srcRect.x()) || !std::isfinite(srcRect.y()) || !std::isfinite(srcRect.width()) || !std::isfinite(srcRect.height()))
1407         return;
1408
1409     ImageResource* cachedImage = image->cachedImage();
1410     if (!cachedImage || !image->complete())
1411         return;
1412
1413     LayoutSize size = sizeFor(image, ImageSizeBeforeDevicePixelRatio);
1414     if (!size.width() || !size.height()) {
1415         exceptionState.throwDOMException(InvalidStateError, String::format("The source %s is 0.", size.width() ? "height" : "width"));
1416         return;
1417     }
1418
1419     if (!dstRect.width() || !dstRect.height())
1420         return;
1421
1422     FloatRect normalizedSrcRect = normalizeRect(srcRect);
1423     FloatRect normalizedDstRect = normalizeRect(dstRect);
1424
1425     FloatRect imageRect = FloatRect(FloatPoint(), size);
1426     if (!srcRect.width() || !srcRect.height()) {
1427         exceptionState.throwDOMException(IndexSizeError, String::format("The source %s is 0.", srcRect.width() ? "height" : "width"));
1428         return;
1429     }
1430     if (!imageRect.intersects(normalizedSrcRect))
1431         return;
1432
1433     clipRectsToImageRect(imageRect, &normalizedSrcRect, &normalizedDstRect);
1434
1435     checkOrigin(image);
1436
1437     Image* imageForRendering = cachedImage->imageForRenderer(image->renderer());
1438
1439     // For images that depend on an unavailable container size, we need to fall back to the intrinsic
1440     // object size. http://www.w3.org/TR/2dcontext2/#dom-context-2d-drawimage
1441     // FIXME: Without a specified image size this should resolve against the canvas element's size, see: crbug.com/230163.
1442     if (!image->renderer() && imageForRendering->usesContainerSize())
1443         imageForRendering->setContainerSize(imageForRendering->size());
1444
1445     drawImageInternal(imageForRendering, normalizedSrcRect, normalizedDstRect, op, blendMode);
1446 }
1447
1448 void CanvasRenderingContext2D::drawImage(HTMLCanvasElement* sourceCanvas, float x, float y, ExceptionState& exceptionState)
1449 {
1450     drawImage(sourceCanvas, 0, 0, sourceCanvas->width(), sourceCanvas->height(), x, y, sourceCanvas->width(), sourceCanvas->height(), exceptionState);
1451 }
1452
1453 void CanvasRenderingContext2D::drawImage(HTMLCanvasElement* sourceCanvas,
1454     float x, float y, float width, float height, ExceptionState& exceptionState)
1455 {
1456     drawImage(sourceCanvas, FloatRect(0, 0, sourceCanvas->width(), sourceCanvas->height()), FloatRect(x, y, width, height), exceptionState);
1457 }
1458
1459 void CanvasRenderingContext2D::drawImage(HTMLCanvasElement* sourceCanvas,
1460     float sx, float sy, float sw, float sh,
1461     float dx, float dy, float dw, float dh, ExceptionState& exceptionState)
1462 {
1463     drawImage(sourceCanvas, FloatRect(sx, sy, sw, sh), FloatRect(dx, dy, dw, dh), exceptionState);
1464 }
1465
1466 void CanvasRenderingContext2D::drawImage(HTMLCanvasElement* sourceCanvas, const FloatRect& srcRect,
1467     const FloatRect& dstRect, ExceptionState& exceptionState)
1468 {
1469     if (!sourceCanvas) {
1470         exceptionState.throwDOMException(TypeMismatchError, "The canvas element provided is invalid.");
1471         return;
1472     }
1473
1474     FloatRect srcCanvasRect = FloatRect(FloatPoint(), sourceCanvas->size());
1475
1476     if (!srcCanvasRect.width() || !srcCanvasRect.height()) {
1477         exceptionState.throwDOMException(InvalidStateError, String::format("The source canvas %s is 0.", srcCanvasRect.width() ? "height" : "width"));
1478         return;
1479     }
1480
1481     if (!srcRect.width() || !srcRect.height()) {
1482         exceptionState.throwDOMException(IndexSizeError, String::format("The source %s is 0.", srcRect.width() ? "height" : "width"));
1483         return;
1484     }
1485
1486     FloatRect normalizedSrcRect = normalizeRect(srcRect);
1487     FloatRect normalizedDstRect = normalizeRect(dstRect);
1488
1489     if (!srcCanvasRect.intersects(normalizedSrcRect) || !normalizedDstRect.width() || !normalizedDstRect.height())
1490         return;
1491
1492     clipRectsToImageRect(srcCanvasRect, &normalizedSrcRect, &normalizedDstRect);
1493
1494     GraphicsContext* c = drawingContext();
1495     if (!c)
1496         return;
1497     if (!state().m_invertibleCTM)
1498         return;
1499
1500     // FIXME: Do this through platform-independent GraphicsContext API.
1501     ImageBuffer* buffer = sourceCanvas->buffer();
1502     if (!buffer)
1503         return;
1504
1505     FloatRect clipBounds;
1506     if (!drawingContext()->getTransformedClipBounds(&clipBounds))
1507         return;
1508
1509     checkOrigin(sourceCanvas);
1510
1511     // If we're drawing from one accelerated canvas 2d to another, avoid calling sourceCanvas->makeRenderingResultsAvailable()
1512     // as that will do a readback to software.
1513     CanvasRenderingContext* sourceContext = sourceCanvas->renderingContext();
1514     // FIXME: Implement an accelerated path for drawing from a WebGL canvas to a 2d canvas when possible.
1515     if (sourceContext && sourceContext->is3d())
1516         sourceContext->paintRenderingResultsToCanvas();
1517
1518     if (rectContainsTransformedRect(normalizedDstRect, clipBounds)) {
1519         c->drawImageBuffer(buffer, normalizedDstRect, normalizedSrcRect, state().m_globalComposite, state().m_globalBlend);
1520         didDraw(clipBounds);
1521     } else if (isFullCanvasCompositeMode(state().m_globalComposite)) {
1522         fullCanvasCompositedDrawImage(buffer, normalizedDstRect, normalizedSrcRect, state().m_globalComposite);
1523         didDraw(clipBounds);
1524     } else if (state().m_globalComposite == CompositeCopy) {
1525         clearCanvas();
1526         c->drawImageBuffer(buffer, normalizedDstRect, normalizedSrcRect, state().m_globalComposite, state().m_globalBlend);
1527         didDraw(clipBounds);
1528     } else {
1529         FloatRect dirtyRect;
1530         if (computeDirtyRect(normalizedDstRect, clipBounds, &dirtyRect)) {
1531             c->drawImageBuffer(buffer, normalizedDstRect, normalizedSrcRect, state().m_globalComposite, state().m_globalBlend);
1532             didDraw(dirtyRect);
1533         }
1534     }
1535
1536     // Flush canvas's ImageBuffer when drawImage from WebGL to HW accelerated 2d canvas
1537     if (sourceContext && sourceContext->is3d() && is2d() && isAccelerated() && canvas()->buffer())
1538         canvas()->buffer()->flush();
1539 }
1540
1541 void CanvasRenderingContext2D::drawImage(HTMLVideoElement* video, float x, float y, ExceptionState& exceptionState)
1542 {
1543     if (!video) {
1544         exceptionState.throwDOMException(TypeMismatchError, "The video element provided is invalid.");
1545         return;
1546     }
1547     IntSize size = sizeFor(video);
1548     drawImage(video, x, y, size.width(), size.height(), exceptionState);
1549 }
1550
1551 void CanvasRenderingContext2D::drawImage(HTMLVideoElement* video,
1552     float x, float y, float width, float height, ExceptionState& exceptionState)
1553 {
1554     if (!video) {
1555         exceptionState.throwDOMException(TypeMismatchError, "The video element provided is invalid.");
1556         return;
1557     }
1558     IntSize size = sizeFor(video);
1559     drawImage(video, FloatRect(0, 0, size.width(), size.height()), FloatRect(x, y, width, height), exceptionState);
1560 }
1561
1562 void CanvasRenderingContext2D::drawImage(HTMLVideoElement* video,
1563     float sx, float sy, float sw, float sh,
1564     float dx, float dy, float dw, float dh, ExceptionState& exceptionState)
1565 {
1566     drawImage(video, FloatRect(sx, sy, sw, sh), FloatRect(dx, dy, dw, dh), exceptionState);
1567 }
1568
1569 void CanvasRenderingContext2D::drawImage(HTMLVideoElement* video, const FloatRect& srcRect, const FloatRect& dstRect, ExceptionState& exceptionState)
1570 {
1571     if (!video) {
1572         exceptionState.throwDOMException(TypeMismatchError, "The video element provided is invalid.");
1573         return;
1574     }
1575
1576     if (video->readyState() == HTMLMediaElement::HAVE_NOTHING || video->readyState() == HTMLMediaElement::HAVE_METADATA)
1577         return;
1578
1579     FloatRect videoRect = FloatRect(FloatPoint(), sizeFor(video));
1580     if (!srcRect.width() || !srcRect.height()) {
1581         exceptionState.throwDOMException(IndexSizeError, String::format("The source %s is 0.", srcRect.width() ? "height" : "width"));
1582         return;
1583     }
1584
1585     FloatRect normalizedSrcRect = normalizeRect(srcRect);
1586     FloatRect normalizedDstRect = normalizeRect(dstRect);
1587
1588     if (!videoRect.intersects(normalizedSrcRect) || !normalizedDstRect.width() || !normalizedDstRect.height())
1589         return;
1590
1591     clipRectsToImageRect(videoRect, &normalizedSrcRect, &normalizedDstRect);
1592
1593     GraphicsContext* c = drawingContext();
1594     if (!c)
1595         return;
1596     if (!state().m_invertibleCTM)
1597         return;
1598
1599     checkOrigin(video);
1600
1601     FloatRect dirtyRect;
1602     if (!computeDirtyRect(normalizedDstRect, &dirtyRect))
1603         return;
1604
1605     GraphicsContextStateSaver stateSaver(*c);
1606     c->clip(normalizedDstRect);
1607     c->translate(normalizedDstRect.x(), normalizedDstRect.y());
1608     c->scale(FloatSize(normalizedDstRect.width() / normalizedSrcRect.width(), normalizedDstRect.height() / normalizedSrcRect.height()));
1609     c->translate(-normalizedSrcRect.x(), -normalizedSrcRect.y());
1610     video->paintCurrentFrameInContext(c, IntRect(IntPoint(), sizeFor(video)));
1611     stateSaver.restore();
1612
1613     didDraw(dirtyRect);
1614 }
1615
1616 void CanvasRenderingContext2D::drawImageFromRect(HTMLImageElement* image,
1617     float sx, float sy, float sw, float sh,
1618     float dx, float dy, float dw, float dh,
1619     const String& compositeOperation)
1620 {
1621     CompositeOperator op;
1622     blink::WebBlendMode blendOp = blink::WebBlendModeNormal;
1623     if (!parseCompositeAndBlendOperator(compositeOperation, op, blendOp) || blendOp != blink::WebBlendModeNormal)
1624         op = CompositeSourceOver;
1625
1626     drawImage(image, FloatRect(sx, sy, sw, sh), FloatRect(dx, dy, dw, dh), op, blink::WebBlendModeNormal, IGNORE_EXCEPTION);
1627 }
1628
1629 void CanvasRenderingContext2D::setAlpha(float alpha)
1630 {
1631     setGlobalAlpha(alpha);
1632 }
1633
1634 void CanvasRenderingContext2D::setCompositeOperation(const String& operation)
1635 {
1636     setGlobalCompositeOperation(operation);
1637 }
1638
1639 void CanvasRenderingContext2D::clearCanvas()
1640 {
1641     FloatRect canvasRect(0, 0, canvas()->width(), canvas()->height());
1642     GraphicsContext* c = drawingContext();
1643     if (!c)
1644         return;
1645
1646     c->save();
1647     c->setCTM(canvas()->baseTransform());
1648     c->clearRect(canvasRect);
1649     c->restore();
1650 }
1651
1652 bool CanvasRenderingContext2D::rectContainsTransformedRect(const FloatRect& rect, const FloatRect& transformedRect) const
1653 {
1654     FloatQuad quad(rect);
1655     FloatQuad transformedQuad(transformedRect);
1656     return state().m_transform.mapQuad(quad).containsQuad(transformedQuad);
1657 }
1658
1659 static void drawImageToContext(Image* image, GraphicsContext* context, const FloatRect& dest, const FloatRect& src, CompositeOperator op)
1660 {
1661     context->drawImage(image, dest, src, op);
1662 }
1663
1664 static void drawImageToContext(ImageBuffer* imageBuffer, GraphicsContext* context, const FloatRect& dest, const FloatRect& src, CompositeOperator op)
1665 {
1666     context->drawImageBuffer(imageBuffer, dest, src, op);
1667 }
1668
1669 template<class T> void  CanvasRenderingContext2D::fullCanvasCompositedDrawImage(T* image, const FloatRect& dest, const FloatRect& src, CompositeOperator op)
1670 {
1671     ASSERT(isFullCanvasCompositeMode(op));
1672
1673     drawingContext()->beginLayer(1, op);
1674     drawImageToContext(image, drawingContext(), dest, src, CompositeSourceOver);
1675     drawingContext()->endLayer();
1676 }
1677
1678 static void fillPrimitive(const FloatRect& rect, GraphicsContext* context)
1679 {
1680     context->fillRect(rect);
1681 }
1682
1683 static void fillPrimitive(const Path& path, GraphicsContext* context)
1684 {
1685     context->fillPath(path);
1686 }
1687
1688 template<class T> void CanvasRenderingContext2D::fullCanvasCompositedFill(const T& area)
1689 {
1690     ASSERT(isFullCanvasCompositeMode(state().m_globalComposite));
1691
1692     GraphicsContext* c = drawingContext();
1693     ASSERT(c);
1694     c->beginLayer(1, state().m_globalComposite);
1695     CompositeOperator previousOperator = c->compositeOperation();
1696     c->setCompositeOperation(CompositeSourceOver);
1697     fillPrimitive(area, c);
1698     c->setCompositeOperation(previousOperator);
1699     c->endLayer();
1700 }
1701
1702 PassRefPtr<CanvasGradient> CanvasRenderingContext2D::createLinearGradient(float x0, float y0, float x1, float y1, ExceptionState& exceptionState)
1703 {
1704     if (!std::isfinite(x0))
1705         exceptionState.throwDOMException(NotSupportedError, ExceptionMessages::notAFiniteNumber(x0, "x0"));
1706     else if (!std::isfinite(y0))
1707         exceptionState.throwDOMException(NotSupportedError, ExceptionMessages::notAFiniteNumber(y0, "y0"));
1708     else if (!std::isfinite(x1))
1709         exceptionState.throwDOMException(NotSupportedError, ExceptionMessages::notAFiniteNumber(x1, "x1"));
1710     else if (!std::isfinite(y1))
1711         exceptionState.throwDOMException(NotSupportedError, ExceptionMessages::notAFiniteNumber(y1, "y1"));
1712
1713     if (exceptionState.hadException())
1714         return 0;
1715
1716     RefPtr<CanvasGradient> gradient = CanvasGradient::create(FloatPoint(x0, y0), FloatPoint(x1, y1));
1717     return gradient.release();
1718 }
1719
1720 PassRefPtr<CanvasGradient> CanvasRenderingContext2D::createRadialGradient(float x0, float y0, float r0, float x1, float y1, float r1, ExceptionState& exceptionState)
1721 {
1722     if (!std::isfinite(x0))
1723         exceptionState.throwDOMException(NotSupportedError, ExceptionMessages::notAFiniteNumber(x0, "x0"));
1724     else if (!std::isfinite(y0))
1725         exceptionState.throwDOMException(NotSupportedError, ExceptionMessages::notAFiniteNumber(y0, "y0"));
1726     else if (!std::isfinite(r0))
1727         exceptionState.throwDOMException(NotSupportedError, ExceptionMessages::notAFiniteNumber(r0, "r0"));
1728     else if (!std::isfinite(x1))
1729         exceptionState.throwDOMException(NotSupportedError, ExceptionMessages::notAFiniteNumber(x1, "x1"));
1730     else if (!std::isfinite(y1))
1731         exceptionState.throwDOMException(NotSupportedError, ExceptionMessages::notAFiniteNumber(y1, "y1"));
1732     else if (!std::isfinite(r1))
1733         exceptionState.throwDOMException(NotSupportedError, ExceptionMessages::notAFiniteNumber(r1, "r1"));
1734     else if (r0 < 0 || r1 < 0)
1735         exceptionState.throwDOMException(IndexSizeError, String::format("The %s provided is less than 0.", r0 < 0 ? "r0" : "r1"));
1736
1737     if (exceptionState.hadException())
1738         return 0;
1739
1740     RefPtr<CanvasGradient> gradient = CanvasGradient::create(FloatPoint(x0, y0), r0, FloatPoint(x1, y1), r1);
1741     return gradient.release();
1742 }
1743
1744 PassRefPtr<CanvasPattern> CanvasRenderingContext2D::createPattern(HTMLImageElement* image,
1745     const String& repetitionType, ExceptionState& exceptionState)
1746 {
1747     if (!image) {
1748         exceptionState.throwDOMException(TypeMismatchError, "The image element provided is invalid.");
1749         return 0;
1750     }
1751     bool repeatX, repeatY;
1752     CanvasPattern::parseRepetitionType(repetitionType, repeatX, repeatY, exceptionState);
1753     if (exceptionState.hadException())
1754         return 0;
1755
1756     if (!image->complete())
1757         return 0;
1758
1759     ImageResource* cachedImage = image->cachedImage();
1760     Image* imageForRendering = cachedImage ? cachedImage->imageForRenderer(image->renderer()) : 0;
1761     if (!imageForRendering)
1762         return CanvasPattern::create(Image::nullImage(), repeatX, repeatY, true);
1763
1764     // We need to synthesize a container size if a renderer is not available to provide one.
1765     if (!image->renderer() && imageForRendering->usesContainerSize())
1766         imageForRendering->setContainerSize(imageForRendering->size());
1767
1768     bool originClean = cachedImage->isAccessAllowed(canvas()->securityOrigin());
1769     return CanvasPattern::create(imageForRendering, repeatX, repeatY, originClean);
1770 }
1771
1772 PassRefPtr<CanvasPattern> CanvasRenderingContext2D::createPattern(HTMLCanvasElement* canvas,
1773     const String& repetitionType, ExceptionState& exceptionState)
1774 {
1775     if (!canvas)
1776         exceptionState.throwDOMException(TypeMismatchError, "The canvas element provided is invalid.");
1777     else if (!canvas->width() || !canvas->height())
1778         exceptionState.throwDOMException(InvalidStateError, String::format("The canvas %s is 0.", canvas->width() ? "height" : "width"));
1779
1780     if (exceptionState.hadException())
1781         return 0;
1782
1783     bool repeatX, repeatY;
1784     CanvasPattern::parseRepetitionType(repetitionType, repeatX, repeatY, exceptionState);
1785     if (exceptionState.hadException())
1786         return 0;
1787     return CanvasPattern::create(canvas->copiedImage(), repeatX, repeatY, canvas->originClean());
1788 }
1789
1790 bool CanvasRenderingContext2D::computeDirtyRect(const FloatRect& localRect, FloatRect* dirtyRect)
1791 {
1792     FloatRect clipBounds;
1793     if (!drawingContext()->getTransformedClipBounds(&clipBounds))
1794         return false;
1795     return computeDirtyRect(localRect, clipBounds, dirtyRect);
1796 }
1797
1798 bool CanvasRenderingContext2D::computeDirtyRect(const FloatRect& localRect, const FloatRect& transformedClipBounds, FloatRect* dirtyRect)
1799 {
1800     FloatRect canvasRect = state().m_transform.mapRect(localRect);
1801
1802     if (alphaChannel(state().m_shadowColor)) {
1803         FloatRect shadowRect(canvasRect);
1804         shadowRect.move(state().m_shadowOffset);
1805         shadowRect.inflate(state().m_shadowBlur);
1806         canvasRect.unite(shadowRect);
1807     }
1808
1809     canvasRect.intersect(transformedClipBounds);
1810     if (canvasRect.isEmpty())
1811         return false;
1812
1813     if (dirtyRect)
1814         *dirtyRect = canvasRect;
1815
1816     return true;
1817 }
1818
1819 void CanvasRenderingContext2D::didDraw(const FloatRect& dirtyRect)
1820 {
1821     if (dirtyRect.isEmpty())
1822         return;
1823
1824     // If we are drawing to hardware and we have a composited layer, just call contentChanged().
1825     if (isAccelerated()) {
1826         RenderBox* renderBox = canvas()->renderBox();
1827         if (renderBox && renderBox->hasAcceleratedCompositing()) {
1828             renderBox->contentChanged(CanvasPixelsChanged);
1829             canvas()->clearCopiedImage();
1830             canvas()->notifyObserversCanvasChanged(dirtyRect);
1831             return;
1832         }
1833     }
1834
1835     canvas()->didDraw(dirtyRect);
1836 }
1837
1838 GraphicsContext* CanvasRenderingContext2D::drawingContext() const
1839 {
1840     return canvas()->drawingContext();
1841 }
1842
1843 static PassRefPtr<ImageData> createEmptyImageData(const IntSize& size)
1844 {
1845     Checked<int, RecordOverflow> dataSize = 4;
1846     dataSize *= size.width();
1847     dataSize *= size.height();
1848     if (dataSize.hasOverflowed())
1849         return 0;
1850
1851     RefPtr<ImageData> data = ImageData::create(size);
1852     data->data()->zeroFill();
1853     return data.release();
1854 }
1855
1856 PassRefPtr<ImageData> CanvasRenderingContext2D::createImageData(PassRefPtr<ImageData> imageData, ExceptionState& exceptionState) const
1857 {
1858     if (!imageData) {
1859         exceptionState.throwDOMException(NotSupportedError, "The ImageData provided is invalid.");
1860         return 0;
1861     }
1862
1863     return createEmptyImageData(imageData->size());
1864 }
1865
1866 PassRefPtr<ImageData> CanvasRenderingContext2D::createImageData(float sw, float sh, ExceptionState& exceptionState) const
1867 {
1868     if (!sw || !sh)
1869         exceptionState.throwDOMException(IndexSizeError, String::format("The source %s is 0.", sw ? "height" : "width"));
1870     else if (!std::isfinite(sw))
1871         exceptionState.throwDOMException(NotSupportedError, ExceptionMessages::notAFiniteNumber(sw, "source width"));
1872     else if (!std::isfinite(sh))
1873         exceptionState.throwDOMException(NotSupportedError, ExceptionMessages::notAFiniteNumber(sh, "source height"));
1874
1875     if (exceptionState.hadException())
1876         return 0;
1877
1878     FloatSize logicalSize(fabs(sw), fabs(sh));
1879     if (!logicalSize.isExpressibleAsIntSize())
1880         return 0;
1881
1882     IntSize size = expandedIntSize(logicalSize);
1883     if (size.width() < 1)
1884         size.setWidth(1);
1885     if (size.height() < 1)
1886         size.setHeight(1);
1887
1888     return createEmptyImageData(size);
1889 }
1890
1891 PassRefPtr<ImageData> CanvasRenderingContext2D::webkitGetImageDataHD(float sx, float sy, float sw, float sh, ExceptionState& exceptionState) const
1892 {
1893     return getImageData(sx, sy, sw, sh, exceptionState);
1894 }
1895
1896 PassRefPtr<ImageData> CanvasRenderingContext2D::getImageData(float sx, float sy, float sw, float sh, ExceptionState& exceptionState) const
1897 {
1898     if (!canvas()->originClean())
1899         exceptionState.throwSecurityError("The canvas has been tainted by cross-origin data.");
1900     else if (!sw || !sh)
1901         exceptionState.throwDOMException(IndexSizeError, String::format("The source %s is 0.", sw ? "height" : "width"));
1902     else if (!std::isfinite(sx))
1903         exceptionState.throwDOMException(NotSupportedError, ExceptionMessages::notAFiniteNumber(sx, "source X"));
1904     else if (!std::isfinite(sy))
1905         exceptionState.throwDOMException(NotSupportedError, ExceptionMessages::notAFiniteNumber(sy, "source Y"));
1906     else if (!std::isfinite(sw))
1907         exceptionState.throwDOMException(NotSupportedError, ExceptionMessages::notAFiniteNumber(sw, "source width"));
1908     else if (!std::isfinite(sh))
1909         exceptionState.throwDOMException(NotSupportedError, ExceptionMessages::notAFiniteNumber(sh, "source height"));
1910
1911     if (exceptionState.hadException())
1912         return 0;
1913
1914     if (sw < 0) {
1915         sx += sw;
1916         sw = -sw;
1917     }
1918     if (sh < 0) {
1919         sy += sh;
1920         sh = -sh;
1921     }
1922
1923     FloatRect logicalRect(sx, sy, sw, sh);
1924     if (logicalRect.width() < 1)
1925         logicalRect.setWidth(1);
1926     if (logicalRect.height() < 1)
1927         logicalRect.setHeight(1);
1928     if (!logicalRect.isExpressibleAsIntRect())
1929         return 0;
1930
1931     IntRect imageDataRect = enclosingIntRect(logicalRect);
1932     ImageBuffer* buffer = canvas()->buffer();
1933     if (!buffer)
1934         return createEmptyImageData(imageDataRect.size());
1935
1936     RefPtr<Uint8ClampedArray> byteArray = buffer->getUnmultipliedImageData(imageDataRect);
1937     if (!byteArray)
1938         return 0;
1939
1940     return ImageData::create(imageDataRect.size(), byteArray.release());
1941 }
1942
1943 void CanvasRenderingContext2D::putImageData(ImageData* data, float dx, float dy, ExceptionState& exceptionState)
1944 {
1945     if (!data) {
1946         exceptionState.throwDOMException(TypeMismatchError, "The ImageData provided is invalid.");
1947         return;
1948     }
1949     putImageData(data, dx, dy, 0, 0, data->width(), data->height(), exceptionState);
1950 }
1951
1952 void CanvasRenderingContext2D::putImageData(ImageData* data, float dx, float dy, float dirtyX, float dirtyY,
1953     float dirtyWidth, float dirtyHeight, ExceptionState& exceptionState)
1954 {
1955     if (!data)
1956         exceptionState.throwDOMException(TypeMismatchError, "The ImageData provided is invalid.");
1957     else if (!std::isfinite(dx))
1958         exceptionState.throwDOMException(NotSupportedError, ExceptionMessages::notAFiniteNumber(dx, "dx"));
1959     else if (!std::isfinite(dy))
1960         exceptionState.throwDOMException(NotSupportedError, ExceptionMessages::notAFiniteNumber(dy, "dy"));
1961     else if (!std::isfinite(dirtyX))
1962         exceptionState.throwDOMException(NotSupportedError, ExceptionMessages::notAFiniteNumber(dirtyX, "dirtyX"));
1963     else if (!std::isfinite(dirtyY))
1964         exceptionState.throwDOMException(NotSupportedError, ExceptionMessages::notAFiniteNumber(dirtyY, "dirtyY"));
1965     else if (!std::isfinite(dirtyWidth))
1966         exceptionState.throwDOMException(NotSupportedError, ExceptionMessages::notAFiniteNumber(dirtyWidth, "dirtyWidth"));
1967     else if (!std::isfinite(dirtyHeight))
1968         exceptionState.throwDOMException(NotSupportedError, ExceptionMessages::notAFiniteNumber(dirtyHeight, "dirtyHeight"));
1969
1970     if (exceptionState.hadException())
1971         return;
1972
1973     ImageBuffer* buffer = canvas()->buffer();
1974     if (!buffer)
1975         return;
1976
1977     if (dirtyWidth < 0) {
1978         dirtyX += dirtyWidth;
1979         dirtyWidth = -dirtyWidth;
1980     }
1981
1982     if (dirtyHeight < 0) {
1983         dirtyY += dirtyHeight;
1984         dirtyHeight = -dirtyHeight;
1985     }
1986
1987     FloatRect clipRect(dirtyX, dirtyY, dirtyWidth, dirtyHeight);
1988     clipRect.intersect(IntRect(0, 0, data->width(), data->height()));
1989     IntSize destOffset(static_cast<int>(dx), static_cast<int>(dy));
1990     IntRect destRect = enclosingIntRect(clipRect);
1991     destRect.move(destOffset);
1992     destRect.intersect(IntRect(IntPoint(), buffer->size()));
1993     if (destRect.isEmpty())
1994         return;
1995     IntRect sourceRect(destRect);
1996     sourceRect.move(-destOffset);
1997
1998     buffer->putByteArray(Unmultiplied, data->data(), IntSize(data->width(), data->height()), sourceRect, IntPoint(destOffset));
1999
2000     didDraw(destRect);
2001 }
2002
2003 String CanvasRenderingContext2D::font() const
2004 {
2005     if (!state().m_realizedFont)
2006         return defaultFont;
2007
2008     StringBuilder serializedFont;
2009     const FontDescription& fontDescription = state().m_font.fontDescription();
2010
2011     if (fontDescription.italic())
2012         serializedFont.appendLiteral("italic ");
2013     if (fontDescription.weight() == FontWeightBold)
2014         serializedFont.appendLiteral("bold ");
2015     if (fontDescription.smallCaps() == FontSmallCapsOn)
2016         serializedFont.appendLiteral("small-caps ");
2017
2018     serializedFont.appendNumber(fontDescription.computedPixelSize());
2019     serializedFont.appendLiteral("px");
2020
2021     const FontFamily& firstFontFamily = fontDescription.family();
2022     for (const FontFamily* fontFamily = &firstFontFamily; fontFamily; fontFamily = fontFamily->next()) {
2023         if (fontFamily != &firstFontFamily)
2024             serializedFont.append(',');
2025
2026         // FIXME: We should append family directly to serializedFont rather than building a temporary string.
2027         String family = fontFamily->family();
2028         if (family.startsWith("-webkit-"))
2029             family = family.substring(8);
2030         if (family.contains(' '))
2031             family = "\"" + family + "\"";
2032
2033         serializedFont.append(' ');
2034         serializedFont.append(family);
2035     }
2036
2037     return serializedFont.toString();
2038 }
2039
2040 void CanvasRenderingContext2D::setFont(const String& newFont)
2041 {
2042     MutableStylePropertyMap::iterator i = m_fetchedFonts.find(newFont);
2043     RefPtr<MutableStylePropertySet> parsedStyle = i != m_fetchedFonts.end() ? i->value : 0;
2044
2045     if (!parsedStyle) {
2046         parsedStyle = MutableStylePropertySet::create();
2047         CSSParserMode mode = m_usesCSSCompatibilityParseMode ? HTMLQuirksMode : HTMLStandardMode;
2048         BisonCSSParser::parseValue(parsedStyle.get(), CSSPropertyFont, newFont, true, mode, 0);
2049         m_fetchedFonts.add(newFont, parsedStyle);
2050     }
2051     if (parsedStyle->isEmpty())
2052         return;
2053
2054     String fontValue = parsedStyle->getPropertyValue(CSSPropertyFont);
2055
2056     // According to http://lists.w3.org/Archives/Public/public-html/2009Jul/0947.html,
2057     // the "inherit" and "initial" values must be ignored.
2058     if (fontValue == "inherit" || fontValue == "initial")
2059         return;
2060
2061     // The parse succeeded.
2062     String newFontSafeCopy(newFont); // Create a string copy since newFont can be deleted inside realizeSaves.
2063     realizeSaves();
2064     modifiableState().m_unparsedFont = newFontSafeCopy;
2065
2066     // Map the <canvas> font into the text style. If the font uses keywords like larger/smaller, these will work
2067     // relative to the canvas.
2068     RefPtr<RenderStyle> newStyle = RenderStyle::create();
2069     if (RenderStyle* computedStyle = canvas()->computedStyle())
2070         newStyle->setFontDescription(computedStyle->fontDescription());
2071     else {
2072         FontFamily fontFamily;
2073         fontFamily.setFamily(defaultFontFamily);
2074
2075         FontDescription defaultFontDescription;
2076         defaultFontDescription.setFamily(fontFamily);
2077         defaultFontDescription.setSpecifiedSize(defaultFontSize);
2078         defaultFontDescription.setComputedSize(defaultFontSize);
2079
2080         newStyle->setFontDescription(defaultFontDescription);
2081     }
2082
2083     newStyle->font().update(newStyle->font().fontSelector());
2084
2085     // Now map the font property longhands into the style.
2086     CSSPropertyValue properties[] = {
2087         CSSPropertyValue(CSSPropertyFontFamily, *parsedStyle),
2088         CSSPropertyValue(CSSPropertyFontStyle, *parsedStyle),
2089         CSSPropertyValue(CSSPropertyFontVariant, *parsedStyle),
2090         CSSPropertyValue(CSSPropertyFontWeight, *parsedStyle),
2091         CSSPropertyValue(CSSPropertyFontSize, *parsedStyle),
2092         CSSPropertyValue(CSSPropertyLineHeight, *parsedStyle),
2093     };
2094
2095     StyleResolver& styleResolver = canvas()->document().ensureStyleResolver();
2096     styleResolver.applyPropertiesToStyle(properties, WTF_ARRAY_LENGTH(properties), newStyle.get());
2097
2098     if (state().m_realizedFont)
2099         static_cast<CSSFontSelector*>(state().m_font.fontSelector())->unregisterForInvalidationCallbacks(&modifiableState());
2100     modifiableState().m_font = newStyle->font();
2101     modifiableState().m_font.update(canvas()->document().styleEngine()->fontSelector());
2102     modifiableState().m_realizedFont = true;
2103     canvas()->document().styleEngine()->fontSelector()->registerForInvalidationCallbacks(&modifiableState());
2104 }
2105
2106 String CanvasRenderingContext2D::textAlign() const
2107 {
2108     return textAlignName(state().m_textAlign);
2109 }
2110
2111 void CanvasRenderingContext2D::setTextAlign(const String& s)
2112 {
2113     TextAlign align;
2114     if (!parseTextAlign(s, align))
2115         return;
2116     if (state().m_textAlign == align)
2117         return;
2118     realizeSaves();
2119     modifiableState().m_textAlign = align;
2120 }
2121
2122 String CanvasRenderingContext2D::textBaseline() const
2123 {
2124     return textBaselineName(state().m_textBaseline);
2125 }
2126
2127 void CanvasRenderingContext2D::setTextBaseline(const String& s)
2128 {
2129     TextBaseline baseline;
2130     if (!parseTextBaseline(s, baseline))
2131         return;
2132     if (state().m_textBaseline == baseline)
2133         return;
2134     realizeSaves();
2135     modifiableState().m_textBaseline = baseline;
2136 }
2137
2138 void CanvasRenderingContext2D::fillText(const String& text, float x, float y)
2139 {
2140     drawTextInternal(text, x, y, true);
2141 }
2142
2143 void CanvasRenderingContext2D::fillText(const String& text, float x, float y, float maxWidth)
2144 {
2145     drawTextInternal(text, x, y, true, maxWidth, true);
2146 }
2147
2148 void CanvasRenderingContext2D::strokeText(const String& text, float x, float y)
2149 {
2150     drawTextInternal(text, x, y, false);
2151 }
2152
2153 void CanvasRenderingContext2D::strokeText(const String& text, float x, float y, float maxWidth)
2154 {
2155     drawTextInternal(text, x, y, false, maxWidth, true);
2156 }
2157
2158 PassRefPtr<TextMetrics> CanvasRenderingContext2D::measureText(const String& text)
2159 {
2160     FontCachePurgePreventer fontCachePurgePreventer;
2161     RefPtr<TextMetrics> metrics = TextMetrics::create();
2162     canvas()->document().updateStyleIfNeeded();
2163     metrics->setWidth(accessFont().width(TextRun(text)));
2164     return metrics.release();
2165 }
2166
2167 static void replaceCharacterInString(String& text, WTF::CharacterMatchFunctionPtr matchFunction, const String& replacement)
2168 {
2169     const size_t replacementLength = replacement.length();
2170     size_t index = 0;
2171     while ((index = text.find(matchFunction, index)) != kNotFound) {
2172         text.replace(index, 1, replacement);
2173         index += replacementLength;
2174     }
2175 }
2176
2177 void CanvasRenderingContext2D::drawTextInternal(const String& text, float x, float y, bool fill, float maxWidth, bool useMaxWidth)
2178 {
2179     // accessFont needs the style to be up to date, but updating style can cause script to run,
2180     // (e.g. due to autofocus) which can free the GraphicsContext, so update style before grabbing
2181     // the GraphicsContext.
2182     canvas()->document().updateStyleIfNeeded();
2183
2184     GraphicsContext* c = drawingContext();
2185     if (!c)
2186         return;
2187     if (!state().m_invertibleCTM)
2188         return;
2189     if (!std::isfinite(x) | !std::isfinite(y))
2190         return;
2191     if (useMaxWidth && (!std::isfinite(maxWidth) || maxWidth <= 0))
2192         return;
2193
2194     // If gradient size is zero, then paint nothing.
2195     Gradient* gradient = c->strokeGradient();
2196     if (!fill && gradient && gradient->isZeroSize())
2197         return;
2198
2199     gradient = c->fillGradient();
2200     if (fill && gradient && gradient->isZeroSize())
2201         return;
2202
2203     FontCachePurgePreventer fontCachePurgePreventer;
2204
2205     const Font& font = accessFont();
2206     const FontMetrics& fontMetrics = font.fontMetrics();
2207     // According to spec, all the space characters must be replaced with U+0020 SPACE characters.
2208     String normalizedText = text;
2209     replaceCharacterInString(normalizedText, isSpaceOrNewline, " ");
2210
2211     // FIXME: Need to turn off font smoothing.
2212
2213     RenderStyle* computedStyle = canvas()->computedStyle();
2214     TextDirection direction = computedStyle ? computedStyle->direction() : LTR;
2215     bool isRTL = direction == RTL;
2216     bool override = computedStyle ? isOverride(computedStyle->unicodeBidi()) : false;
2217
2218     TextRun textRun(normalizedText, 0, 0, TextRun::AllowTrailingExpansion, direction, override, true, TextRun::NoRounding);
2219     // Draw the item text at the correct point.
2220     FloatPoint location(x, y);
2221     switch (state().m_textBaseline) {
2222     case TopTextBaseline:
2223     case HangingTextBaseline:
2224         location.setY(y + fontMetrics.ascent());
2225         break;
2226     case BottomTextBaseline:
2227     case IdeographicTextBaseline:
2228         location.setY(y - fontMetrics.descent());
2229         break;
2230     case MiddleTextBaseline:
2231         location.setY(y - fontMetrics.descent() + fontMetrics.height() / 2);
2232         break;
2233     case AlphabeticTextBaseline:
2234     default:
2235          // Do nothing.
2236         break;
2237     }
2238
2239     float fontWidth = font.width(TextRun(normalizedText, 0, 0, TextRun::AllowTrailingExpansion, direction, override));
2240
2241     useMaxWidth = (useMaxWidth && maxWidth < fontWidth);
2242     float width = useMaxWidth ? maxWidth : fontWidth;
2243
2244     TextAlign align = state().m_textAlign;
2245     if (align == StartTextAlign)
2246         align = isRTL ? RightTextAlign : LeftTextAlign;
2247     else if (align == EndTextAlign)
2248         align = isRTL ? LeftTextAlign : RightTextAlign;
2249
2250     switch (align) {
2251     case CenterTextAlign:
2252         location.setX(location.x() - width / 2);
2253         break;
2254     case RightTextAlign:
2255         location.setX(location.x() - width);
2256         break;
2257     default:
2258         break;
2259     }
2260
2261     // The slop built in to this mask rect matches the heuristic used in FontCGWin.cpp for GDI text.
2262     TextRunPaintInfo textRunPaintInfo(textRun);
2263     textRunPaintInfo.bounds = FloatRect(location.x() - fontMetrics.height() / 2,
2264                                         location.y() - fontMetrics.ascent() - fontMetrics.lineGap(),
2265                                         width + fontMetrics.height(),
2266                                         fontMetrics.lineSpacing());
2267     if (!fill)
2268         inflateStrokeRect(textRunPaintInfo.bounds);
2269
2270     FloatRect dirtyRect;
2271     if (!computeDirtyRect(textRunPaintInfo.bounds, &dirtyRect))
2272         return;
2273
2274     c->setTextDrawingMode(fill ? TextModeFill : TextModeStroke);
2275     if (useMaxWidth) {
2276         GraphicsContextStateSaver stateSaver(*c);
2277         c->translate(location.x(), location.y());
2278         // We draw when fontWidth is 0 so compositing operations (eg, a "copy" op) still work.
2279         c->scale(FloatSize((fontWidth > 0 ? (width / fontWidth) : 0), 1));
2280         c->drawBidiText(font, textRunPaintInfo, FloatPoint(0, 0), Font::UseFallbackIfFontNotReady);
2281     } else
2282         c->drawBidiText(font, textRunPaintInfo, location, Font::UseFallbackIfFontNotReady);
2283
2284     didDraw(dirtyRect);
2285 }
2286
2287 void CanvasRenderingContext2D::inflateStrokeRect(FloatRect& rect) const
2288 {
2289     // Fast approximation of the stroke's bounding rect.
2290     // This yields a slightly oversized rect but is very fast
2291     // compared to Path::strokeBoundingRect().
2292     static const float root2 = sqrtf(2);
2293     float delta = state().m_lineWidth / 2;
2294     if (state().m_lineJoin == MiterJoin)
2295         delta *= state().m_miterLimit;
2296     else if (state().m_lineCap == SquareCap)
2297         delta *= root2;
2298
2299     rect.inflate(delta);
2300 }
2301
2302 const Font& CanvasRenderingContext2D::accessFont()
2303 {
2304     // This needs style to be up to date, but can't assert so because drawTextInternal
2305     // can invalidate style before this is called (e.g. drawingContext invalidates style).
2306     if (!state().m_realizedFont)
2307         setFont(state().m_unparsedFont);
2308     return state().m_font;
2309 }
2310
2311 blink::WebLayer* CanvasRenderingContext2D::platformLayer() const
2312 {
2313     return canvas()->buffer() ? canvas()->buffer()->platformLayer() : 0;
2314 }
2315
2316 bool CanvasRenderingContext2D::imageSmoothingEnabled() const
2317 {
2318     return state().m_imageSmoothingEnabled;
2319 }
2320
2321 void CanvasRenderingContext2D::setImageSmoothingEnabled(bool enabled)
2322 {
2323     if (enabled == state().m_imageSmoothingEnabled)
2324         return;
2325
2326     realizeSaves();
2327     modifiableState().m_imageSmoothingEnabled = enabled;
2328     GraphicsContext* c = drawingContext();
2329     if (c)
2330         c->setImageInterpolationQuality(enabled ? DefaultInterpolationQuality : InterpolationNone);
2331 }
2332
2333 PassRefPtr<Canvas2DContextAttributes> CanvasRenderingContext2D::getContextAttributes() const
2334 {
2335     RefPtr<Canvas2DContextAttributes> attributes = Canvas2DContextAttributes::create();
2336     attributes->setAlpha(m_hasAlpha);
2337     return attributes.release();
2338 }
2339
2340 void CanvasRenderingContext2D::drawSystemFocusRing(Element* element)
2341 {
2342     if (!focusRingCallIsValid(m_path, element))
2343         return;
2344
2345     updateFocusRingAccessibility(m_path, element);
2346     // Note: we need to check document->focusedElement() rather than just calling
2347     // element->focused(), because element->focused() isn't updated until after
2348     // focus events fire.
2349     if (element->document().focusedElement() == element)
2350         drawFocusRing(m_path);
2351 }
2352
2353 bool CanvasRenderingContext2D::drawCustomFocusRing(Element* element)
2354 {
2355     if (!focusRingCallIsValid(m_path, element))
2356         return false;
2357
2358     updateFocusRingAccessibility(m_path, element);
2359
2360     // Return true if the application should draw the focus ring. The spec allows us to
2361     // override this for accessibility, but currently Blink doesn't take advantage of this.
2362     return element->focused();
2363 }
2364
2365 bool CanvasRenderingContext2D::focusRingCallIsValid(const Path& path, Element* element)
2366 {
2367     if (!state().m_invertibleCTM)
2368         return false;
2369     if (path.isEmpty())
2370         return false;
2371     if (!element->isDescendantOf(canvas()))
2372         return false;
2373
2374     return true;
2375 }
2376
2377 void CanvasRenderingContext2D::updateFocusRingAccessibility(const Path& path, Element* element)
2378 {
2379     if (!canvas()->renderer())
2380         return;
2381
2382     // If accessibility is already enabled in this frame, associate this path's
2383     // bounding box with the accessible object. Do this even if the element
2384     // isn't focused because assistive technology might try to explore the object's
2385     // location before it gets focus.
2386     if (AXObjectCache* axObjectCache = element->document().existingAXObjectCache()) {
2387         if (AXObject* obj = axObjectCache->getOrCreate(element)) {
2388             // Get the bounding rect and apply transformations.
2389             FloatRect bounds = m_path.boundingRect();
2390             AffineTransform ctm = state().m_transform;
2391             FloatRect transformedBounds = ctm.mapRect(bounds);
2392             LayoutRect elementRect = LayoutRect(transformedBounds);
2393
2394             // Offset by the canvas rect and set the bounds of the accessible element.
2395             IntRect canvasRect = canvas()->renderer()->absoluteBoundingBoxRect();
2396             elementRect.moveBy(canvasRect.location());
2397             obj->setElementRect(elementRect);
2398
2399             // Set the bounds of any ancestor accessible elements, up to the canvas element,
2400             // otherwise this element will appear to not be within its parent element.
2401             obj = obj->parentObject();
2402             while (obj && obj->node() != canvas()) {
2403                 obj->setElementRect(elementRect);
2404                 obj = obj->parentObject();
2405             }
2406         }
2407     }
2408 }
2409
2410 void CanvasRenderingContext2D::drawFocusRing(const Path& path)
2411 {
2412     GraphicsContext* c = drawingContext();
2413     if (!c)
2414         return;
2415
2416     FloatRect dirtyRect;
2417     if (!computeDirtyRect(path.boundingRect(), &dirtyRect))
2418         return;
2419
2420     c->save();
2421     c->setAlpha(1.0);
2422     c->clearShadow();
2423     c->setCompositeOperation(CompositeSourceOver, blink::WebBlendModeNormal);
2424
2425     // These should match the style defined in html.css.
2426     Color focusRingColor = RenderTheme::theme().focusRingColor();
2427     const int focusRingWidth = 5;
2428     const int focusRingOutline = 0;
2429     c->drawFocusRing(path, focusRingWidth, focusRingOutline, focusRingColor);
2430
2431     c->restore();
2432
2433     didDraw(dirtyRect);
2434 }
2435
2436 } // namespace WebCore