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