Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(60)

Side by Side Diff: Source/core/html/canvas/CanvasRenderingContext2D.cpp

Issue 1093673002: Removing the dependency on GraphicsContext for drawing images in 2D canvas (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: rebase Created 5 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 Apple Inc. All rights reserved. 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) 3 * Copyright (C) 2008, 2010 Nokia Corporation and/or its subsidiary(-ies)
4 * Copyright (C) 2007 Alp Toker <alp@atoker.com> 4 * Copyright (C) 2007 Alp Toker <alp@atoker.com>
5 * Copyright (C) 2008 Eric Seidel <eric@webkit.org> 5 * Copyright (C) 2008 Eric Seidel <eric@webkit.org>
6 * Copyright (C) 2008 Dirk Schulze <krit@webkit.org> 6 * Copyright (C) 2008 Dirk Schulze <krit@webkit.org>
7 * Copyright (C) 2010 Torch Mobile (Beijing) Co. Ltd. All rights reserved. 7 * Copyright (C) 2010 Torch Mobile (Beijing) Co. Ltd. All rights reserved.
8 * Copyright (C) 2012, 2013 Intel Corporation. All rights reserved. 8 * Copyright (C) 2012, 2013 Intel Corporation. All rights reserved.
9 * Copyright (C) 2013 Adobe Systems Incorporated. All rights reserved. 9 * Copyright (C) 2013 Adobe Systems Incorporated. All rights reserved.
10 * 10 *
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
54 #include "core/html/canvas/CanvasRenderingContext2DState.h" 54 #include "core/html/canvas/CanvasRenderingContext2DState.h"
55 #include "core/html/canvas/CanvasStyle.h" 55 #include "core/html/canvas/CanvasStyle.h"
56 #include "core/html/canvas/HitRegion.h" 56 #include "core/html/canvas/HitRegion.h"
57 #include "core/html/canvas/Path2D.h" 57 #include "core/html/canvas/Path2D.h"
58 #include "core/layout/LayoutBox.h" 58 #include "core/layout/LayoutBox.h"
59 #include "core/layout/LayoutTheme.h" 59 #include "core/layout/LayoutTheme.h"
60 #include "platform/fonts/FontCache.h" 60 #include "platform/fonts/FontCache.h"
61 #include "platform/geometry/FloatQuad.h" 61 #include "platform/geometry/FloatQuad.h"
62 #include "platform/graphics/DrawLooperBuilder.h" 62 #include "platform/graphics/DrawLooperBuilder.h"
63 #include "platform/graphics/ExpensiveCanvasHeuristicParameters.h" 63 #include "platform/graphics/ExpensiveCanvasHeuristicParameters.h"
64 #include "platform/graphics/GraphicsContext.h"
65 #include "platform/graphics/ImageBuffer.h" 64 #include "platform/graphics/ImageBuffer.h"
65 #include "platform/graphics/StrokeData.h"
66 #include "platform/graphics/skia/SkiaUtils.h"
66 #include "platform/text/BidiTextRun.h" 67 #include "platform/text/BidiTextRun.h"
67 #include "third_party/skia/include/core/SkCanvas.h" 68 #include "third_party/skia/include/core/SkCanvas.h"
69 #include "third_party/skia/include/core/SkImageFilter.h"
68 #include "wtf/ArrayBufferContents.h" 70 #include "wtf/ArrayBufferContents.h"
69 #include "wtf/CheckedArithmetic.h" 71 #include "wtf/CheckedArithmetic.h"
70 #include "wtf/MathExtras.h" 72 #include "wtf/MathExtras.h"
71 #include "wtf/OwnPtr.h" 73 #include "wtf/OwnPtr.h"
72 #include "wtf/text/StringBuilder.h" 74 #include "wtf/text/StringBuilder.h"
73 75
74 namespace blink { 76 namespace blink {
75 77
76 static const int defaultFontSize = 10; 78 static const int defaultFontSize = 10;
77 static const char defaultFontFamily[] = "sans-serif"; 79 static const char defaultFontFamily[] = "sans-serif";
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
123 , m_contextLostMode(NotLostContext) 125 , m_contextLostMode(NotLostContext)
124 , m_contextRestorable(true) 126 , m_contextRestorable(true)
125 , m_tryRestoreContextAttemptCount(0) 127 , m_tryRestoreContextAttemptCount(0)
126 , m_dispatchContextLostEventTimer(this, &CanvasRenderingContext2D::dispatchC ontextLostEvent) 128 , m_dispatchContextLostEventTimer(this, &CanvasRenderingContext2D::dispatchC ontextLostEvent)
127 , m_dispatchContextRestoredEventTimer(this, &CanvasRenderingContext2D::dispa tchContextRestoredEvent) 129 , m_dispatchContextRestoredEventTimer(this, &CanvasRenderingContext2D::dispa tchContextRestoredEvent)
128 , m_tryRestoreContextEventTimer(this, &CanvasRenderingContext2D::tryRestoreC ontextEvent) 130 , m_tryRestoreContextEventTimer(this, &CanvasRenderingContext2D::tryRestoreC ontextEvent)
129 { 131 {
130 if (document.settings() && document.settings()->antialiasedClips2dCanvasEnab led()) 132 if (document.settings() && document.settings()->antialiasedClips2dCanvasEnab led())
131 m_clipAntialiasing = AntiAliased; 133 m_clipAntialiasing = AntiAliased;
132 m_stateStack.append(adoptPtrWillBeNoop(new CanvasRenderingContext2DState())) ; 134 m_stateStack.append(adoptPtrWillBeNoop(new CanvasRenderingContext2DState())) ;
135 setShouldAntialias(true);
133 } 136 }
134 137
135 void CanvasRenderingContext2D::unwindStateStack() 138 void CanvasRenderingContext2D::unwindStateStack()
136 { 139 {
137 if (size_t stackSize = m_stateStack.size()) { 140 if (size_t stackSize = m_stateStack.size()) {
138 if (SkCanvas* skCanvas = canvas()->existingDrawingCanvas()) { 141 if (SkCanvas* skCanvas = canvas()->existingDrawingCanvas()) {
139 while (--stackSize) 142 while (--stackSize)
140 skCanvas->restore(); 143 skCanvas->restore();
141 } 144 }
142 } 145 }
143 } 146 }
144 147
145 CanvasRenderingContext2D::~CanvasRenderingContext2D() 148 CanvasRenderingContext2D::~CanvasRenderingContext2D()
146 { 149 {
147 } 150 }
148 151
149 void CanvasRenderingContext2D::validateStateStack() 152 void CanvasRenderingContext2D::validateStateStack()
150 { 153 {
151 #if ENABLE(ASSERT) 154 #if ENABLE(ASSERT)
152 SkCanvas* skCanvas = canvas()->existingDrawingCanvas(); 155 SkCanvas* skCanvas = canvas()->existingDrawingCanvas();
153 if (skCanvas && m_contextLostMode == NotLostContext) { 156 if (skCanvas && m_contextLostMode == NotLostContext) {
154 ASSERT(static_cast<size_t>(skCanvas->getSaveCount() - 1) == m_stateStack .size()); 157 ASSERT(static_cast<size_t>(skCanvas->getSaveCount()) == m_stateStack.siz e());
155 } 158 }
156 #endif 159 #endif
157 } 160 }
158 161
159 CanvasRenderingContext2DState& CanvasRenderingContext2D::modifiableState() 162 CanvasRenderingContext2DState& CanvasRenderingContext2D::modifiableState()
160 { 163 {
161 ASSERT(!state().hasUnrealizedSaves()); 164 realizeSaves();
162 return *m_stateStack.last(); 165 return *m_stateStack.last();
163 } 166 }
164 167
165 bool CanvasRenderingContext2D::isAccelerated() const 168 bool CanvasRenderingContext2D::isAccelerated() const
166 { 169 {
167 if (!canvas()->hasImageBuffer()) 170 if (!canvas()->hasImageBuffer())
168 return false; 171 return false;
169 return canvas()->buffer()->isAccelerated(); 172 return canvas()->buffer()->isAccelerated();
170 } 173 }
171 174
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after
275 } 278 }
276 } 279 }
277 280
278 void CanvasRenderingContext2D::reset() 281 void CanvasRenderingContext2D::reset()
279 { 282 {
280 validateStateStack(); 283 validateStateStack();
281 unwindStateStack(); 284 unwindStateStack();
282 m_stateStack.resize(1); 285 m_stateStack.resize(1);
283 m_stateStack.first() = adoptPtrWillBeNoop(new CanvasRenderingContext2DState( )); 286 m_stateStack.first() = adoptPtrWillBeNoop(new CanvasRenderingContext2DState( ));
284 m_path.clear(); 287 m_path.clear();
288 SkCanvas* c = canvas()->existingDrawingCanvas();
289 if (c) {
290 c->resetMatrix();
291 c->clipRect(SkRect::MakeWH(canvas()->width(), canvas()->height()), SkReg ion::kReplace_Op);
292 }
285 validateStateStack(); 293 validateStateStack();
286 } 294 }
287 295
288 void CanvasRenderingContext2D::restoreCanvasMatrixClipStack() 296 void CanvasRenderingContext2D::restoreCanvasMatrixClipStack()
289 { 297 {
290 SkCanvas* c = drawingCanvas(); 298 SkCanvas* c = drawingCanvas();
291 if (!c) 299 if (!c)
292 return; 300 return;
293 WillBeHeapVector<OwnPtrWillBeMember<CanvasRenderingContext2DState>>::iterato r currState; 301 WillBeHeapVector<OwnPtrWillBeMember<CanvasRenderingContext2DState>>::iterato r currState;
302 ASSERT(m_stateStack.begin() < m_stateStack.end());
294 for (currState = m_stateStack.begin(); currState < m_stateStack.end(); currS tate++) { 303 for (currState = m_stateStack.begin(); currState < m_stateStack.end(); currS tate++) {
295 // The initial save accounts for the save installed by canvasElementElem ent::m_contextStateSaver
296 c->save();
297 c->setMatrix(SkMatrix::I()); 304 c->setMatrix(SkMatrix::I());
298 currState->get()->playbackClips(c); 305 currState->get()->playbackClips(c);
299 c->setMatrix(affineTransformToSkMatrix(currState->get()->transform())); 306 c->setMatrix(affineTransformToSkMatrix(currState->get()->transform()));
307 c->save();
300 } 308 }
309 c->restore();
301 } 310 }
302 311
303 void CanvasRenderingContext2D::realizeSaves(SkCanvas* canvas) 312 void CanvasRenderingContext2D::realizeSaves()
304 { 313 {
305 validateStateStack(); 314 validateStateStack();
306 if (state().hasUnrealizedSaves()) { 315 if (state().hasUnrealizedSaves()) {
307 ASSERT(m_stateStack.size() >= 1); 316 ASSERT(m_stateStack.size() >= 1);
308 // Reduce the current state's unrealized count by one now, 317 // Reduce the current state's unrealized count by one now,
309 // to reflect the fact we are saving one state. 318 // to reflect the fact we are saving one state.
310 m_stateStack.last()->restore(); 319 m_stateStack.last()->restore();
311 m_stateStack.append(adoptPtrWillBeNoop(new CanvasRenderingContext2DState (state(), CanvasRenderingContext2DState::DontCopyClipList))); 320 m_stateStack.append(adoptPtrWillBeNoop(new CanvasRenderingContext2DState (state(), CanvasRenderingContext2DState::DontCopyClipList)));
312 // Set the new state's unrealized count to 0, because it has no outstand ing saves. 321 // Set the new state's unrealized count to 0, because it has no outstand ing saves.
313 // We need to do this explicitly because the copy constructor and operat or= used 322 // We need to do this explicitly because the copy constructor and operat or= used
314 // by the Vector operations copy the unrealized count from the previous state (in 323 // by the Vector operations copy the unrealized count from the previous state (in
315 // turn necessary to support correct resizing and unwinding of the stack ). 324 // turn necessary to support correct resizing and unwinding of the stack ).
316 m_stateStack.last()->resetUnrealizedSaveCount(); 325 m_stateStack.last()->resetUnrealizedSaveCount();
317 if (!canvas) 326 SkCanvas* canvas = drawingCanvas();
318 canvas = drawingCanvas();
319 if (canvas) 327 if (canvas)
320 canvas->save(); 328 canvas->save();
321 validateStateStack(); 329 validateStateStack();
322 } 330 }
323 } 331 }
324 332
325 void CanvasRenderingContext2D::save() 333 void CanvasRenderingContext2D::save()
326 { 334 {
327 m_stateStack.last()->save(); 335 m_stateStack.last()->save();
328 } 336 }
329 337
330 void CanvasRenderingContext2D::restore() 338 void CanvasRenderingContext2D::restore()
331 { 339 {
332 validateStateStack(); 340 validateStateStack();
333 if (state().hasUnrealizedSaves()) { 341 if (state().hasUnrealizedSaves()) {
334 // We never realized the save, so just record that it was unnecessary. 342 // We never realized the save, so just record that it was unnecessary.
335 m_stateStack.last()->restore(); 343 m_stateStack.last()->restore();
336 return; 344 return;
337 } 345 }
338 ASSERT(m_stateStack.size() >= 1); 346 ASSERT(m_stateStack.size() >= 1);
339 if (m_stateStack.size() <= 1) 347 if (m_stateStack.size() <= 1)
340 return; 348 return;
341 m_path.transform(state().transform()); 349 m_path.transform(state().transform());
342 m_stateStack.removeLast(); 350 m_stateStack.removeLast();
343 m_path.transform(state().transform().inverse()); 351 m_path.transform(state().transform().inverse());
344 SkCanvas* c = drawingCanvas(); 352 SkCanvas* c = drawingCanvas();
345 if (c) 353 if (c)
346 c->restore(); 354 c->restore();
347 355
348 // Temporary code while crbug.com/453113 is a WIP: GraphicsContext state sta ck
349 // is no longer exercised so state stored still stored in GC must be re-inst alled
350 // after a restore.
351 GraphicsContext* gc = drawingContext();
352 if (gc) {
353 gc->setAlphaAsFloat(state().globalAlpha());
354 gc->setCompositeOperation(state().globalComposite());
355 gc->setImageInterpolationQuality(state().imageSmoothingEnabled() ? Canva sDefaultInterpolationQuality : InterpolationNone);
356 }
357
358 validateStateStack(); 356 validateStateStack();
359 } 357 }
360 358
361 static inline void convertCanvasStyleToUnionType(CanvasStyle* style, StringOrCan vasGradientOrCanvasPattern& returnValue) 359 static inline void convertCanvasStyleToUnionType(CanvasStyle* style, StringOrCan vasGradientOrCanvasPattern& returnValue)
362 { 360 {
363 if (CanvasGradient* gradient = style->canvasGradient()) { 361 if (CanvasGradient* gradient = style->canvasGradient()) {
364 returnValue.setCanvasGradient(gradient); 362 returnValue.setCanvasGradient(gradient);
365 return; 363 return;
366 } 364 }
367 if (CanvasPattern* pattern = style->canvasPattern()) { 365 if (CanvasPattern* pattern = style->canvasPattern()) {
(...skipping 15 matching lines...) Expand all
383 String colorString; 381 String colorString;
384 RefPtrWillBeRawPtr<CanvasStyle> canvasStyle = nullptr; 382 RefPtrWillBeRawPtr<CanvasStyle> canvasStyle = nullptr;
385 if (style.isString()) { 383 if (style.isString()) {
386 colorString = style.getAsString(); 384 colorString = style.getAsString();
387 if (colorString == state().unparsedStrokeColor()) 385 if (colorString == state().unparsedStrokeColor())
388 return; 386 return;
389 RGBA32 parsedColor = 0; 387 RGBA32 parsedColor = 0;
390 if (!parseColorOrCurrentColor(parsedColor, colorString, canvas())) 388 if (!parseColorOrCurrentColor(parsedColor, colorString, canvas()))
391 return; 389 return;
392 if (state().strokeStyle()->isEquivalentRGBA(parsedColor)) { 390 if (state().strokeStyle()->isEquivalentRGBA(parsedColor)) {
393 realizeSaves(nullptr);
394 modifiableState().setUnparsedStrokeColor(colorString); 391 modifiableState().setUnparsedStrokeColor(colorString);
395 return; 392 return;
396 } 393 }
397 canvasStyle = CanvasStyle::createFromRGBA(parsedColor); 394 canvasStyle = CanvasStyle::createFromRGBA(parsedColor);
398 } else if (style.isCanvasGradient()) { 395 } else if (style.isCanvasGradient()) {
399 canvasStyle = CanvasStyle::createFromGradient(style.getAsCanvasGradient( )); 396 canvasStyle = CanvasStyle::createFromGradient(style.getAsCanvasGradient( ));
400 } else if (style.isCanvasPattern()) { 397 } else if (style.isCanvasPattern()) {
401 RefPtrWillBeRawPtr<CanvasPattern> canvasPattern = style.getAsCanvasPatte rn(); 398 RefPtrWillBeRawPtr<CanvasPattern> canvasPattern = style.getAsCanvasPatte rn();
402 399
403 if (canvas()->originClean() && !canvasPattern->originClean()) 400 if (canvas()->originClean() && !canvasPattern->originClean())
404 canvas()->setOriginTainted(); 401 canvas()->setOriginTainted();
405 402
406 canvasStyle = CanvasStyle::createFromPattern(canvasPattern); 403 canvasStyle = CanvasStyle::createFromPattern(canvasPattern);
407 } 404 }
408 405
409 ASSERT(canvasStyle); 406 ASSERT(canvasStyle);
410 407
411 SkCanvas* c = drawingCanvas();
412 realizeSaves(c);
413 modifiableState().setStrokeStyle(canvasStyle.release()); 408 modifiableState().setStrokeStyle(canvasStyle.release());
414 if (!c)
415 return;
416 modifiableState().setUnparsedStrokeColor(colorString); 409 modifiableState().setUnparsedStrokeColor(colorString);
417 } 410 }
418 411
419 void CanvasRenderingContext2D::fillStyle(StringOrCanvasGradientOrCanvasPattern& returnValue) const 412 void CanvasRenderingContext2D::fillStyle(StringOrCanvasGradientOrCanvasPattern& returnValue) const
420 { 413 {
421 convertCanvasStyleToUnionType(state().fillStyle(), returnValue); 414 convertCanvasStyleToUnionType(state().fillStyle(), returnValue);
422 } 415 }
423 416
424 void CanvasRenderingContext2D::setFillStyle(const StringOrCanvasGradientOrCanvas Pattern& style) 417 void CanvasRenderingContext2D::setFillStyle(const StringOrCanvasGradientOrCanvas Pattern& style)
425 { 418 {
426 ASSERT(!style.isNull()); 419 ASSERT(!style.isNull());
427 validateStateStack(); 420 validateStateStack();
428 String colorString; 421 String colorString;
429 RefPtrWillBeRawPtr<CanvasStyle> canvasStyle = nullptr; 422 RefPtrWillBeRawPtr<CanvasStyle> canvasStyle = nullptr;
430 if (style.isString()) { 423 if (style.isString()) {
431 colorString = style.getAsString(); 424 colorString = style.getAsString();
432 if (colorString == state().unparsedFillColor()) 425 if (colorString == state().unparsedFillColor())
433 return; 426 return;
434 RGBA32 parsedColor = 0; 427 RGBA32 parsedColor = 0;
435 if (!parseColorOrCurrentColor(parsedColor, colorString, canvas())) 428 if (!parseColorOrCurrentColor(parsedColor, colorString, canvas()))
436 return; 429 return;
437 if (state().fillStyle()->isEquivalentRGBA(parsedColor)) { 430 if (state().fillStyle()->isEquivalentRGBA(parsedColor)) {
438 realizeSaves(nullptr);
439 modifiableState().setUnparsedFillColor(colorString); 431 modifiableState().setUnparsedFillColor(colorString);
440 return; 432 return;
441 } 433 }
442 canvasStyle = CanvasStyle::createFromRGBA(parsedColor); 434 canvasStyle = CanvasStyle::createFromRGBA(parsedColor);
443 } else if (style.isCanvasGradient()) { 435 } else if (style.isCanvasGradient()) {
444 canvasStyle = CanvasStyle::createFromGradient(style.getAsCanvasGradient( )); 436 canvasStyle = CanvasStyle::createFromGradient(style.getAsCanvasGradient( ));
445 } else if (style.isCanvasPattern()) { 437 } else if (style.isCanvasPattern()) {
446 RefPtrWillBeRawPtr<CanvasPattern> canvasPattern = style.getAsCanvasPatte rn(); 438 RefPtrWillBeRawPtr<CanvasPattern> canvasPattern = style.getAsCanvasPatte rn();
447 439
448 if (canvas()->originClean() && !canvasPattern->originClean()) 440 if (canvas()->originClean() && !canvasPattern->originClean())
449 canvas()->setOriginTainted(); 441 canvas()->setOriginTainted();
450 442
451 canvasStyle = CanvasStyle::createFromPattern(canvasPattern); 443 canvasStyle = CanvasStyle::createFromPattern(canvasPattern);
452 } 444 }
453 445
454 ASSERT(canvasStyle); 446 ASSERT(canvasStyle);
455 SkCanvas* c = drawingCanvas();
456 if (!c)
457 return;
458 realizeSaves(c);
459
460 modifiableState().setFillStyle(canvasStyle.release()); 447 modifiableState().setFillStyle(canvasStyle.release());
461 modifiableState().setUnparsedFillColor(colorString); 448 modifiableState().setUnparsedFillColor(colorString);
462 } 449 }
463 450
464 float CanvasRenderingContext2D::lineWidth() const 451 float CanvasRenderingContext2D::lineWidth() const
465 { 452 {
466 return state().lineWidth(); 453 return state().lineWidth();
467 } 454 }
468 455
469 void CanvasRenderingContext2D::setLineWidth(float width) 456 void CanvasRenderingContext2D::setLineWidth(float width)
470 { 457 {
471 if (!std::isfinite(width) || width <= 0) 458 if (!std::isfinite(width) || width <= 0)
472 return; 459 return;
473 if (state().lineWidth() == width) 460 if (state().lineWidth() == width)
474 return; 461 return;
475 SkCanvas* c = drawingCanvas();
476 realizeSaves(c);
477 modifiableState().setLineWidth(width); 462 modifiableState().setLineWidth(width);
478 if (!c)
479 return;
480 } 463 }
481 464
482 String CanvasRenderingContext2D::lineCap() const 465 String CanvasRenderingContext2D::lineCap() const
483 { 466 {
484 return lineCapName(state().lineCap()); 467 return lineCapName(state().lineCap());
485 } 468 }
486 469
487 void CanvasRenderingContext2D::setLineCap(const String& s) 470 void CanvasRenderingContext2D::setLineCap(const String& s)
488 { 471 {
489 LineCap cap; 472 LineCap cap;
490 if (!parseLineCap(s, cap)) 473 if (!parseLineCap(s, cap))
491 return; 474 return;
492 if (state().lineCap() == cap) 475 if (state().lineCap() == cap)
493 return; 476 return;
494 SkCanvas* c = drawingCanvas();
495 realizeSaves(c);
496 modifiableState().setLineCap(cap); 477 modifiableState().setLineCap(cap);
497 if (!c)
498 return;
499 } 478 }
500 479
501 String CanvasRenderingContext2D::lineJoin() const 480 String CanvasRenderingContext2D::lineJoin() const
502 { 481 {
503 return lineJoinName(state().lineJoin()); 482 return lineJoinName(state().lineJoin());
504 } 483 }
505 484
506 void CanvasRenderingContext2D::setLineJoin(const String& s) 485 void CanvasRenderingContext2D::setLineJoin(const String& s)
507 { 486 {
508 LineJoin join; 487 LineJoin join;
509 if (!parseLineJoin(s, join)) 488 if (!parseLineJoin(s, join))
510 return; 489 return;
511 if (state().lineJoin() == join) 490 if (state().lineJoin() == join)
512 return; 491 return;
513 SkCanvas* c = drawingCanvas();
514 realizeSaves(c);
515 modifiableState().setLineJoin(join); 492 modifiableState().setLineJoin(join);
516 if (!c)
517 return;
518 } 493 }
519 494
520 float CanvasRenderingContext2D::miterLimit() const 495 float CanvasRenderingContext2D::miterLimit() const
521 { 496 {
522 return state().miterLimit(); 497 return state().miterLimit();
523 } 498 }
524 499
525 void CanvasRenderingContext2D::setMiterLimit(float limit) 500 void CanvasRenderingContext2D::setMiterLimit(float limit)
526 { 501 {
527 if (!std::isfinite(limit) || limit <= 0) 502 if (!std::isfinite(limit) || limit <= 0)
528 return; 503 return;
529 if (state().miterLimit() == limit) 504 if (state().miterLimit() == limit)
530 return; 505 return;
531 SkCanvas* c = drawingCanvas();
532 realizeSaves(c);
533 modifiableState().setMiterLimit(limit); 506 modifiableState().setMiterLimit(limit);
534 if (!c)
535 return;
536 } 507 }
537 508
538 float CanvasRenderingContext2D::shadowOffsetX() const 509 float CanvasRenderingContext2D::shadowOffsetX() const
539 { 510 {
540 return state().shadowOffset().width(); 511 return state().shadowOffset().width();
541 } 512 }
542 513
543 void CanvasRenderingContext2D::setShadowOffsetX(float x) 514 void CanvasRenderingContext2D::setShadowOffsetX(float x)
544 { 515 {
545 if (!std::isfinite(x)) 516 if (!std::isfinite(x))
546 return; 517 return;
547 if (state().shadowOffset().width() == x) 518 if (state().shadowOffset().width() == x)
548 return; 519 return;
549 realizeSaves(nullptr);
550 modifiableState().setShadowOffsetX(x); 520 modifiableState().setShadowOffsetX(x);
551 } 521 }
552 522
553 float CanvasRenderingContext2D::shadowOffsetY() const 523 float CanvasRenderingContext2D::shadowOffsetY() const
554 { 524 {
555 return state().shadowOffset().height(); 525 return state().shadowOffset().height();
556 } 526 }
557 527
558 void CanvasRenderingContext2D::setShadowOffsetY(float y) 528 void CanvasRenderingContext2D::setShadowOffsetY(float y)
559 { 529 {
560 if (!std::isfinite(y)) 530 if (!std::isfinite(y))
561 return; 531 return;
562 if (state().shadowOffset().height() == y) 532 if (state().shadowOffset().height() == y)
563 return; 533 return;
564 realizeSaves(nullptr);
565 modifiableState().setShadowOffsetY(y); 534 modifiableState().setShadowOffsetY(y);
566 } 535 }
567 536
568 float CanvasRenderingContext2D::shadowBlur() const 537 float CanvasRenderingContext2D::shadowBlur() const
569 { 538 {
570 return state().shadowBlur(); 539 return state().shadowBlur();
571 } 540 }
572 541
573 void CanvasRenderingContext2D::setShadowBlur(float blur) 542 void CanvasRenderingContext2D::setShadowBlur(float blur)
574 { 543 {
575 if (!std::isfinite(blur) || blur < 0) 544 if (!std::isfinite(blur) || blur < 0)
576 return; 545 return;
577 if (state().shadowBlur() == blur) 546 if (state().shadowBlur() == blur)
578 return; 547 return;
579 realizeSaves(nullptr);
580 modifiableState().setShadowBlur(blur); 548 modifiableState().setShadowBlur(blur);
581 } 549 }
582 550
583 String CanvasRenderingContext2D::shadowColor() const 551 String CanvasRenderingContext2D::shadowColor() const
584 { 552 {
585 return Color(state().shadowColor()).serialized(); 553 return Color(state().shadowColor()).serialized();
586 } 554 }
587 555
588 void CanvasRenderingContext2D::setShadowColor(const String& color) 556 void CanvasRenderingContext2D::setShadowColor(const String& color)
589 { 557 {
590 RGBA32 rgba; 558 RGBA32 rgba;
591 if (!parseColorOrCurrentColor(rgba, color, canvas())) 559 if (!parseColorOrCurrentColor(rgba, color, canvas()))
592 return; 560 return;
593 if (state().shadowColor() == rgba) 561 if (state().shadowColor() == rgba)
594 return; 562 return;
595 realizeSaves(nullptr);
596 modifiableState().setShadowColor(rgba); 563 modifiableState().setShadowColor(rgba);
597 } 564 }
598 565
599 const Vector<float>& CanvasRenderingContext2D::getLineDash() const 566 const Vector<float>& CanvasRenderingContext2D::getLineDash() const
600 { 567 {
601 return state().lineDash(); 568 return state().lineDash();
602 } 569 }
603 570
604 static bool lineDashSequenceIsValid(const Vector<float>& dash) 571 static bool lineDashSequenceIsValid(const Vector<float>& dash)
605 { 572 {
606 for (size_t i = 0; i < dash.size(); i++) { 573 for (size_t i = 0; i < dash.size(); i++) {
607 if (!std::isfinite(dash[i]) || dash[i] < 0) 574 if (!std::isfinite(dash[i]) || dash[i] < 0)
608 return false; 575 return false;
609 } 576 }
610 return true; 577 return true;
611 } 578 }
612 579
613 void CanvasRenderingContext2D::setLineDash(const Vector<float>& dash) 580 void CanvasRenderingContext2D::setLineDash(const Vector<float>& dash)
614 { 581 {
615 if (!lineDashSequenceIsValid(dash)) 582 if (!lineDashSequenceIsValid(dash))
616 return; 583 return;
617
618 realizeSaves(nullptr);
619 modifiableState().setLineDash(dash); 584 modifiableState().setLineDash(dash);
620 } 585 }
621 586
622 float CanvasRenderingContext2D::lineDashOffset() const 587 float CanvasRenderingContext2D::lineDashOffset() const
623 { 588 {
624 return state().lineDashOffset(); 589 return state().lineDashOffset();
625 } 590 }
626 591
627 void CanvasRenderingContext2D::setLineDashOffset(float offset) 592 void CanvasRenderingContext2D::setLineDashOffset(float offset)
628 { 593 {
629 if (!std::isfinite(offset) || state().lineDashOffset() == offset) 594 if (!std::isfinite(offset) || state().lineDashOffset() == offset)
630 return; 595 return;
631
632 realizeSaves(nullptr);
633 modifiableState().setLineDashOffset(offset); 596 modifiableState().setLineDashOffset(offset);
634 } 597 }
635 598
636 float CanvasRenderingContext2D::globalAlpha() const 599 float CanvasRenderingContext2D::globalAlpha() const
637 { 600 {
638 return state().globalAlpha(); 601 return state().globalAlpha();
639 } 602 }
640 603
641 void CanvasRenderingContext2D::setGlobalAlpha(float alpha) 604 void CanvasRenderingContext2D::setGlobalAlpha(float alpha)
642 { 605 {
643 if (!(alpha >= 0 && alpha <= 1)) 606 if (!(alpha >= 0 && alpha <= 1))
644 return; 607 return;
645 if (state().globalAlpha() == alpha) 608 if (state().globalAlpha() == alpha)
646 return; 609 return;
647 SkCanvas* c = drawingCanvas();
648 realizeSaves(c);
649 modifiableState().setGlobalAlpha(alpha); 610 modifiableState().setGlobalAlpha(alpha);
650 if (!c) 611 }
651 return; 612
652 drawingContext()->setAlphaAsFloat(alpha); 613 bool CanvasRenderingContext2D::shouldAntialias() const
614 {
615 return state().shouldAntialias();
616 }
617
618 void CanvasRenderingContext2D::setShouldAntialias(bool doAA)
619 {
620 modifiableState().setShouldAntialias(doAA);
653 } 621 }
654 622
655 String CanvasRenderingContext2D::globalCompositeOperation() const 623 String CanvasRenderingContext2D::globalCompositeOperation() const
656 { 624 {
657 return compositeOperatorName(compositeOperatorFromSkia(state().globalComposi te()), blendModeFromSkia(state().globalComposite())); 625 return compositeOperatorName(compositeOperatorFromSkia(state().globalComposi te()), blendModeFromSkia(state().globalComposite()));
658 } 626 }
659 627
660 void CanvasRenderingContext2D::setGlobalCompositeOperation(const String& operati on) 628 void CanvasRenderingContext2D::setGlobalCompositeOperation(const String& operati on)
661 { 629 {
662 CompositeOperator op = CompositeSourceOver; 630 CompositeOperator op = CompositeSourceOver;
663 WebBlendMode blendMode = WebBlendModeNormal; 631 WebBlendMode blendMode = WebBlendModeNormal;
664 // TODO(dshwang): Support nonstandard "darker" until M43. crbug.com/425628 632 // TODO(dshwang): Support nonstandard "darker" until M43. crbug.com/425628
665 String operationName = operation; 633 String operationName = operation;
666 if (operation == "darker") { 634 if (operation == "darker") {
667 operationName = "darken"; 635 operationName = "darken";
668 if (canvas()) 636 if (canvas())
669 UseCounter::countDeprecation(canvas()->document(), UseCounter::Canva sRenderingContext2DCompositeOperationDarker); 637 UseCounter::countDeprecation(canvas()->document(), UseCounter::Canva sRenderingContext2DCompositeOperationDarker);
670 } 638 }
671 if (!parseCompositeAndBlendOperator(operationName, op, blendMode)) 639 if (!parseCompositeAndBlendOperator(operationName, op, blendMode))
672 return; 640 return;
673 SkXfermode::Mode xfermode = WebCoreCompositeToSkiaComposite(op, blendMode); 641 SkXfermode::Mode xfermode = WebCoreCompositeToSkiaComposite(op, blendMode);
674 if (state().globalComposite() == xfermode) 642 if (state().globalComposite() == xfermode)
675 return; 643 return;
676 SkCanvas* c = drawingCanvas();
677 realizeSaves(c);
678 modifiableState().setGlobalComposite(xfermode); 644 modifiableState().setGlobalComposite(xfermode);
679 if (!c)
680 return;
681 drawingContext()->setCompositeOperation(xfermode);
682 } 645 }
683 646
684 PassRefPtrWillBeRawPtr<SVGMatrixTearOff> CanvasRenderingContext2D::currentTransf orm() const 647 PassRefPtrWillBeRawPtr<SVGMatrixTearOff> CanvasRenderingContext2D::currentTransf orm() const
685 { 648 {
686 return SVGMatrixTearOff::create(state().transform()); 649 return SVGMatrixTearOff::create(state().transform());
687 } 650 }
688 651
689 void CanvasRenderingContext2D::setCurrentTransform(PassRefPtrWillBeRawPtr<SVGMat rixTearOff> passMatrixTearOff) 652 void CanvasRenderingContext2D::setCurrentTransform(PassRefPtrWillBeRawPtr<SVGMat rixTearOff> passMatrixTearOff)
690 { 653 {
691 RefPtrWillBeRawPtr<SVGMatrixTearOff> matrixTearOff = passMatrixTearOff; 654 RefPtrWillBeRawPtr<SVGMatrixTearOff> matrixTearOff = passMatrixTearOff;
692 const AffineTransform& transform = matrixTearOff->value(); 655 const AffineTransform& transform = matrixTearOff->value();
693 setTransform(transform.a(), transform.b(), transform.c(), transform.d(), tra nsform.e(), transform.f()); 656 setTransform(transform.a(), transform.b(), transform.c(), transform.d(), tra nsform.e(), transform.f());
694 } 657 }
695 658
696 void CanvasRenderingContext2D::scale(float sx, float sy) 659 void CanvasRenderingContext2D::scale(float sx, float sy)
697 { 660 {
698 SkCanvas* c = drawingCanvas(); 661 SkCanvas* c = drawingCanvas();
699 if (!c) 662 if (!c)
700 return; 663 return;
701 664
702 if (!std::isfinite(sx) || !std::isfinite(sy)) 665 if (!std::isfinite(sx) || !std::isfinite(sy))
703 return; 666 return;
704 667
705 AffineTransform newTransform = state().transform(); 668 AffineTransform newTransform = state().transform();
706 newTransform.scaleNonUniform(sx, sy); 669 newTransform.scaleNonUniform(sx, sy);
707 if (state().transform() == newTransform) 670 if (state().transform() == newTransform)
708 return; 671 return;
709 672
710 realizeSaves(c);
711
712 modifiableState().setTransform(newTransform); 673 modifiableState().setTransform(newTransform);
713 if (!state().isTransformInvertible()) 674 if (!state().isTransformInvertible())
714 return; 675 return;
715 676
716 c->scale(sx, sy); 677 c->scale(sx, sy);
717 m_path.transform(AffineTransform().scaleNonUniform(1.0 / sx, 1.0 / sy)); 678 m_path.transform(AffineTransform().scaleNonUniform(1.0 / sx, 1.0 / sy));
718 } 679 }
719 680
720 void CanvasRenderingContext2D::rotate(float angleInRadians) 681 void CanvasRenderingContext2D::rotate(float angleInRadians)
721 { 682 {
722 SkCanvas* c = drawingCanvas(); 683 SkCanvas* c = drawingCanvas();
723 if (!c) 684 if (!c)
724 return; 685 return;
725 686
726 if (!std::isfinite(angleInRadians)) 687 if (!std::isfinite(angleInRadians))
727 return; 688 return;
728 689
729 AffineTransform newTransform = state().transform(); 690 AffineTransform newTransform = state().transform();
730 newTransform.rotateRadians(angleInRadians); 691 newTransform.rotateRadians(angleInRadians);
731 if (state().transform() == newTransform) 692 if (state().transform() == newTransform)
732 return; 693 return;
733 694
734 realizeSaves(c);
735
736 modifiableState().setTransform(newTransform); 695 modifiableState().setTransform(newTransform);
737 if (!state().isTransformInvertible()) 696 if (!state().isTransformInvertible())
738 return; 697 return;
739 c->rotate(angleInRadians * (180.0f / piFloat)); 698 c->rotate(angleInRadians * (180.0f / piFloat));
740 m_path.transform(AffineTransform().rotateRadians(-angleInRadians)); 699 m_path.transform(AffineTransform().rotateRadians(-angleInRadians));
741 } 700 }
742 701
743 void CanvasRenderingContext2D::translate(float tx, float ty) 702 void CanvasRenderingContext2D::translate(float tx, float ty)
744 { 703 {
745 SkCanvas* c = drawingCanvas(); 704 SkCanvas* c = drawingCanvas();
746 if (!c) 705 if (!c)
747 return; 706 return;
748 if (!state().isTransformInvertible()) 707 if (!state().isTransformInvertible())
749 return; 708 return;
750 709
751 if (!std::isfinite(tx) || !std::isfinite(ty)) 710 if (!std::isfinite(tx) || !std::isfinite(ty))
752 return; 711 return;
753 712
754 AffineTransform newTransform = state().transform(); 713 AffineTransform newTransform = state().transform();
755 newTransform.translate(tx, ty); 714 newTransform.translate(tx, ty);
756 if (state().transform() == newTransform) 715 if (state().transform() == newTransform)
757 return; 716 return;
758 717
759 realizeSaves(c);
760
761 modifiableState().setTransform(newTransform); 718 modifiableState().setTransform(newTransform);
762 if (!state().isTransformInvertible()) 719 if (!state().isTransformInvertible())
763 return; 720 return;
764 c->translate(tx, ty); 721 c->translate(tx, ty);
765 m_path.transform(AffineTransform().translate(-tx, -ty)); 722 m_path.transform(AffineTransform().translate(-tx, -ty));
766 } 723 }
767 724
768 void CanvasRenderingContext2D::transform(float m11, float m12, float m21, float m22, float dx, float dy) 725 void CanvasRenderingContext2D::transform(float m11, float m12, float m21, float m22, float dx, float dy)
769 { 726 {
770 SkCanvas* c = drawingCanvas(); 727 SkCanvas* c = drawingCanvas();
771 if (!c) 728 if (!c)
772 return; 729 return;
773 730
774 if (!std::isfinite(m11) || !std::isfinite(m21) || !std::isfinite(dx) || !std ::isfinite(m12) || !std::isfinite(m22) || !std::isfinite(dy)) 731 if (!std::isfinite(m11) || !std::isfinite(m21) || !std::isfinite(dx) || !std ::isfinite(m12) || !std::isfinite(m22) || !std::isfinite(dy))
775 return; 732 return;
776 733
777 AffineTransform transform(m11, m12, m21, m22, dx, dy); 734 AffineTransform transform(m11, m12, m21, m22, dx, dy);
778 AffineTransform newTransform = state().transform() * transform; 735 AffineTransform newTransform = state().transform() * transform;
779 if (state().transform() == newTransform) 736 if (state().transform() == newTransform)
780 return; 737 return;
781 738
782 realizeSaves(c);
783
784 modifiableState().setTransform(newTransform); 739 modifiableState().setTransform(newTransform);
785 if (!state().isTransformInvertible()) 740 if (!state().isTransformInvertible())
786 return; 741 return;
787 742
788 c->concat(affineTransformToSkMatrix(transform)); 743 c->concat(affineTransformToSkMatrix(transform));
789 m_path.transform(transform.inverse()); 744 m_path.transform(transform.inverse());
790 } 745 }
791 746
792 void CanvasRenderingContext2D::resetTransform() 747 void CanvasRenderingContext2D::resetTransform()
793 { 748 {
794 SkCanvas* c = drawingCanvas(); 749 SkCanvas* c = drawingCanvas();
795 if (!c) 750 if (!c)
796 return; 751 return;
797 752
798 AffineTransform ctm = state().transform(); 753 AffineTransform ctm = state().transform();
799 bool invertibleCTM = state().isTransformInvertible(); 754 bool invertibleCTM = state().isTransformInvertible();
800 // It is possible that CTM is identity while CTM is not invertible. 755 // It is possible that CTM is identity while CTM is not invertible.
801 // When CTM becomes non-invertible, realizeSaves() can make CTM identity. 756 // When CTM becomes non-invertible, realizeSaves() can make CTM identity.
802 if (ctm.isIdentity() && invertibleCTM) 757 if (ctm.isIdentity() && invertibleCTM)
803 return; 758 return;
804 759
805 realizeSaves(c);
806 // resetTransform() resolves the non-invertible CTM state. 760 // resetTransform() resolves the non-invertible CTM state.
807 modifiableState().resetTransform(); 761 modifiableState().resetTransform();
808 c->setMatrix(affineTransformToSkMatrix(canvas()->baseTransform())); 762 c->setMatrix(affineTransformToSkMatrix(canvas()->baseTransform()));
809 763
810 if (invertibleCTM) 764 if (invertibleCTM)
811 m_path.transform(ctm); 765 m_path.transform(ctm);
812 // When else, do nothing because all transform methods didn't update m_path when CTM became non-invertible. 766 // When else, do nothing because all transform methods didn't update m_path when CTM became non-invertible.
813 // It means that resetTransform() restores m_path just before CTM became non -invertible. 767 // It means that resetTransform() restores m_path just before CTM became non -invertible.
814 } 768 }
815 769
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
892 bool CanvasRenderingContext2D::draw(const DrawFunc& drawFunc, const ContainsFunc & drawCoversClipBounds, const SkRect& bounds, CanvasRenderingContext2DState::Pai ntType paintType, CanvasRenderingContext2DState::ImageType imageType) 846 bool CanvasRenderingContext2D::draw(const DrawFunc& drawFunc, const ContainsFunc & drawCoversClipBounds, const SkRect& bounds, CanvasRenderingContext2DState::Pai ntType paintType, CanvasRenderingContext2DState::ImageType imageType)
893 { 847 {
894 if (!state().isTransformInvertible()) 848 if (!state().isTransformInvertible())
895 return false; 849 return false;
896 850
897 SkIRect clipBounds; 851 SkIRect clipBounds;
898 if (!drawingCanvas() || !drawingCanvas()->getClipDeviceBounds(&clipBounds)) 852 if (!drawingCanvas() || !drawingCanvas()->getClipDeviceBounds(&clipBounds))
899 return false; 853 return false;
900 854
901 // If gradient size is zero, then paint nothing. 855 // If gradient size is zero, then paint nothing.
902 CanvasGradient* gradient = state().style(paintType)->canvasGradient(); 856 CanvasStyle* style = state().style(paintType);
903 if (gradient && gradient->gradient()->isZeroSize()) 857 if (style) {
904 return false; 858 CanvasGradient* gradient = style->canvasGradient();
859 if (gradient && gradient->gradient()->isZeroSize())
860 return false;
861 }
905 862
906 if (isFullCanvasCompositeMode(state().globalComposite())) { 863 if (isFullCanvasCompositeMode(state().globalComposite())) {
907 fullCanvasCompositedDraw(drawFunc, paintType, imageType); 864 fullCanvasCompositedDraw(drawFunc, paintType, imageType);
908 didDraw(clipBounds); 865 didDraw(clipBounds);
909 } else if (state().globalComposite() == SkXfermode::kSrc_Mode) { 866 } else if (state().globalComposite() == SkXfermode::kSrc_Mode) {
910 clearCanvas(); // takes care of checkOvewrdraw() 867 clearCanvas(); // takes care of checkOvewrdraw()
911 const SkPaint* paint = state().getPaint(paintType, DrawForegroundOnly, i mageType); 868 const SkPaint* paint = state().getPaint(paintType, DrawForegroundOnly, i mageType);
912 drawFunc(paint); 869 drawFunc(paint);
913 didDraw(clipBounds); 870 didDraw(clipBounds);
914 } else { 871 } else {
915 SkIRect dirtyRect; 872 SkIRect dirtyRect;
916 if (computeDirtyRect(bounds, clipBounds, &dirtyRect)) { 873 if (computeDirtyRect(bounds, clipBounds, &dirtyRect)) {
917 const SkPaint* paint = state().getPaint(paintType, DrawShadowAndFore ground, imageType); 874 const SkPaint* paint = state().getPaint(paintType, DrawShadowAndFore ground, imageType);
918 if (paintType == CanvasRenderingContext2DState::FillPaintType && dra wCoversClipBounds(clipBounds)) 875 if (paintType != CanvasRenderingContext2DState::StrokePaintType && d rawCoversClipBounds(clipBounds))
919 checkOverdraw(bounds, paint, imageType, ClipFill); 876 checkOverdraw(bounds, paint, imageType, ClipFill);
920 drawFunc(paint); 877 drawFunc(paint);
921 didDraw(dirtyRect); 878 didDraw(dirtyRect);
922 } 879 }
923 } 880 }
924 return true; 881 return true;
925 } 882 }
926 883
927 static bool isPathExpensive(const Path& path) 884 static bool isPathExpensive(const Path& path)
928 { 885 {
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after
1057 void CanvasRenderingContext2D::clipInternal(const Path& path, const String& wind ingRuleString) 1014 void CanvasRenderingContext2D::clipInternal(const Path& path, const String& wind ingRuleString)
1058 { 1015 {
1059 SkCanvas* c = drawingCanvas(); 1016 SkCanvas* c = drawingCanvas();
1060 if (!c) { 1017 if (!c) {
1061 return; 1018 return;
1062 } 1019 }
1063 if (!state().isTransformInvertible()) { 1020 if (!state().isTransformInvertible()) {
1064 return; 1021 return;
1065 } 1022 }
1066 1023
1067 realizeSaves(c);
1068
1069 SkPath skPath = path.skPath(); 1024 SkPath skPath = path.skPath();
1070 skPath.setFillType(parseWinding(windingRuleString)); 1025 skPath.setFillType(parseWinding(windingRuleString));
1071 modifiableState().clipPath(skPath, m_clipAntialiasing); 1026 modifiableState().clipPath(skPath, m_clipAntialiasing);
1072 c->clipPath(skPath, SkRegion::kIntersect_Op, m_clipAntialiasing == AntiAlias ed); 1027 c->clipPath(skPath, SkRegion::kIntersect_Op, m_clipAntialiasing == AntiAlias ed);
1073 if (ExpensiveCanvasHeuristicParameters::ComplexClipsAreExpensive && !skPath. isRect(0) && canvas()->hasImageBuffer()) { 1028 if (ExpensiveCanvasHeuristicParameters::ComplexClipsAreExpensive && !skPath. isRect(0) && canvas()->hasImageBuffer()) {
1074 canvas()->buffer()->setHasExpensiveOp(); 1029 canvas()->buffer()->setHasExpensiveOp();
1075 } 1030 }
1076 } 1031 }
1077 1032
1078 void CanvasRenderingContext2D::clip(const String& windingRuleString) 1033 void CanvasRenderingContext2D::clip(const String& windingRuleString)
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after
1215 c->drawRect(rect, clearPaint); 1170 c->drawRect(rect, clearPaint);
1216 didDraw(dirtyRect); 1171 didDraw(dirtyRect);
1217 } 1172 }
1218 } 1173 }
1219 1174
1220 if (m_hitRegionManager) { 1175 if (m_hitRegionManager) {
1221 m_hitRegionManager->removeHitRegionsInRect(rect, state().transform()); 1176 m_hitRegionManager->removeHitRegionsInRect(rect, state().transform());
1222 } 1177 }
1223 } 1178 }
1224 1179
1225 void CanvasRenderingContext2D::applyShadow(ShadowMode shadowMode)
1226 {
1227 GraphicsContext* c = drawingContext();
1228 if (!c)
1229 return;
1230
1231 if (state().shouldDrawShadows()) {
1232 c->setShadow(state().shadowOffset(), state().shadowBlur(), state().shado wColor(),
1233 DrawLooperBuilder::ShadowIgnoresTransforms, DrawLooperBuilder::Shado wRespectsAlpha, shadowMode);
1234 } else {
1235 c->clearShadow();
1236 }
1237 }
1238
1239 static inline FloatRect normalizeRect(const FloatRect& rect) 1180 static inline FloatRect normalizeRect(const FloatRect& rect)
1240 { 1181 {
1241 return FloatRect(std::min(rect.x(), rect.maxX()), 1182 return FloatRect(std::min(rect.x(), rect.maxX()),
1242 std::min(rect.y(), rect.maxY()), 1183 std::min(rect.y(), rect.maxY()),
1243 std::max(rect.width(), -rect.width()), 1184 std::max(rect.width(), -rect.width()),
1244 std::max(rect.height(), -rect.height())); 1185 std::max(rect.height(), -rect.height()));
1245 } 1186 }
1246 1187
1247 static inline void clipRectsToImageRect(const FloatRect& imageRect, FloatRect* s rcRect, FloatRect* dstRect) 1188 static inline void clipRectsToImageRect(const FloatRect& imageRect, FloatRect* s rcRect, FloatRect* dstRect)
1248 { 1189 {
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
1294 } 1235 }
1295 1236
1296 void CanvasRenderingContext2D::drawImage(const CanvasImageSourceUnion& imageSour ce, 1237 void CanvasRenderingContext2D::drawImage(const CanvasImageSourceUnion& imageSour ce,
1297 float sx, float sy, float sw, float sh, 1238 float sx, float sy, float sw, float sh,
1298 float dx, float dy, float dw, float dh, ExceptionState& exceptionState) 1239 float dx, float dy, float dw, float dh, ExceptionState& exceptionState)
1299 { 1240 {
1300 CanvasImageSource* imageSourceInternal = toImageSourceInternal(imageSource); 1241 CanvasImageSource* imageSourceInternal = toImageSourceInternal(imageSource);
1301 drawImage(imageSourceInternal, sx, sy, sw, sh, dx, dy, dw, dh, exceptionStat e); 1242 drawImage(imageSourceInternal, sx, sy, sw, sh, dx, dy, dw, dh, exceptionStat e);
1302 } 1243 }
1303 1244
1304 void CanvasRenderingContext2D::drawVideo(CanvasImageSource* imageSource, const F loatRect& srcRect, const FloatRect& dstRect) 1245 bool CanvasRenderingContext2D::shouldDrawImageAntialiased(const FloatRect& destR ect) const
1305 { 1246 {
1306 HTMLVideoElement* video = static_cast<HTMLVideoElement*>(imageSource); 1247 if (!shouldAntialias())
1307 ASSERT(video); 1248 return false;
1308 SkCanvas* c = drawingCanvas(); 1249 SkCanvas* c = drawingCanvas();
1309 if (!c) 1250 ASSERT(c);
1310 return; 1251
1311 c->save(); 1252 const SkMatrix &ctm = c->getTotalMatrix();
1312 c->clipRect(WebCoreFloatRectToSKRect(dstRect)); 1253 // Don't disable anti-aliasing if we're rotated or skewed.
1313 c->translate(dstRect.x(), dstRect.y()); 1254 if (!ctm.rectStaysRect())
1314 c->scale(dstRect.width() / srcRect.width(), dstRect.height() / srcRect.heigh t()); 1255 return true;
1315 c->translate(-srcRect.x(), -srcRect.y()); 1256 // Check if the dimensions of the destination are "small" (less than one
1316 video->paintCurrentFrameInContext(drawingContext(), IntRect(IntPoint(), IntS ize(video->videoWidth(), video->videoHeight()))); 1257 // device pixel). To prevent sudden drop-outs. Since we know that
1317 // In case the paint propagated a queued context loss signal 1258 // kRectStaysRect_Mask is set, the matrix either has scale and no skew or
1318 if (drawingCanvas()) 1259 // vice versa. We can query the kAffine_Mask flag to determine which case
1319 drawingCanvas()->restore(); 1260 // it is.
1261 // FIXME: This queries the CTM while drawing, which is generally
1262 // discouraged. Always drawing with AA can negatively impact performance
1263 // though - that's why it's not always on.
1264 SkScalar widthExpansion, heightExpansion;
1265 if (ctm.getType() & SkMatrix::kAffine_Mask)
1266 widthExpansion = ctm[SkMatrix::kMSkewY], heightExpansion = ctm[SkMatrix: :kMSkewX];
1267 else
1268 widthExpansion = ctm[SkMatrix::kMScaleX], heightExpansion = ctm[SkMatrix ::kMScaleY];
1269 return destRect.width() * fabs(widthExpansion) < 1 || destRect.height() * fa bs(heightExpansion) < 1;
1320 } 1270 }
1321 1271
1322 void CanvasRenderingContext2D::drawImageOnContext(CanvasImageSource* imageSource , Image* image, const FloatRect& srcRect, const FloatRect& dstRect, const SkPain t* paint) 1272 void CanvasRenderingContext2D::drawImageInternal(CanvasImageSource* imageSource, Image* image, const FloatRect& srcRect, const FloatRect& dstRect, const SkPaint * paint)
1323 { 1273 {
1324 SkXfermode::Mode mode; 1274 SkCanvas* c = drawingCanvas();
1325 if (!SkXfermode::AsMode(paint->getXfermode(), &mode)) 1275 ASSERT(c);
1326 mode = SkXfermode::kSrcOver_Mode;
1327 1276
1328 RefPtr<SkImageFilter> imageFilter(paint->getImageFilter()); 1277 int initialSaveCount = c->getSaveCount();
1329 drawingContext()->setDropShadowImageFilter(imageFilter.release()); 1278 SkPaint imagePaint = *paint;
1330 RefPtr<SkDrawLooper> drawLooper(paint->getLooper()); 1279
1331 drawingContext()->setDrawLooper(drawLooper.release()); 1280 if (paint->getImageFilter()) {
1281 SkMatrix ctm = c->getTotalMatrix();
1282 SkMatrix invCtm;
1283 if (!ctm.invert(&invCtm)) {
1284 ASSERT_NOT_REACHED(); // There is an earlier check for invertibility
1285 }
1286 c->save();
1287 c->concat(invCtm);
1288 SkRect bounds = dstRect;
1289 ctm.mapRect(&bounds);
1290 SkRect filteredBounds;
1291 paint->getImageFilter()->computeFastBounds(bounds, &filteredBounds);
1292 SkPaint layerPaint;
1293 layerPaint.setXfermode(paint->getXfermode());
1294 layerPaint.setImageFilter(paint->getImageFilter());
1295 c->saveLayer(&filteredBounds, &layerPaint);
1296 c->concat(ctm);
1297 imagePaint.setXfermodeMode(SkXfermode::kSrcOver_Mode);
1298 imagePaint.setImageFilter(nullptr);
1299 }
1332 1300
1333 if (!imageSource->isVideoElement()) { 1301 if (!imageSource->isVideoElement()) {
1334 drawingContext()->drawImage(image, dstRect, srcRect, mode); 1302 // TODO: Find a way to pass SkCanvas::kBleed_DrawBitmapRectFlag
1303 imagePaint.setAntiAlias(shouldDrawImageAntialiased(dstRect));
1304 image->draw(c, imagePaint, dstRect, srcRect, DoNotRespectImageOrientatio n, Image::DoNotClampImageToSourceRect);
1335 } else { 1305 } else {
1336 SkXfermode::Mode oldMode = drawingContext()->compositeOperation(); 1306 c->save();
1337 drawingContext()->setCompositeOperation(mode); 1307 c->clipRect(WebCoreFloatRectToSKRect(dstRect));
1338 drawVideo(imageSource, srcRect, dstRect); 1308 c->translate(dstRect.x(), dstRect.y());
1339 // Must re-check drawingContext() in case drawVideo propagated a pending context loss signal 1309 c->scale(dstRect.width() / srcRect.width(), dstRect.height() / srcRect.h eight());
1340 if (drawingContext()) 1310 c->translate(-srcRect.x(), -srcRect.y());
1341 drawingContext()->setCompositeOperation(oldMode); 1311 HTMLVideoElement* video = static_cast<HTMLVideoElement*>(imageSource);
1312 video->paintCurrentFrame(c, IntRect(IntPoint(), IntSize(video->videoWidt h(), video->videoHeight())), &imagePaint);
1342 } 1313 }
1314
1315 c->restoreToCount(initialSaveCount);
1343 } 1316 }
1344 1317
1345 void CanvasRenderingContext2D::drawImage(CanvasImageSource* imageSource, 1318 void CanvasRenderingContext2D::drawImage(CanvasImageSource* imageSource,
1346 float sx, float sy, float sw, float sh, 1319 float sx, float sy, float sw, float sh,
1347 float dx, float dy, float dw, float dh, ExceptionState& exceptionState) 1320 float dx, float dy, float dw, float dh, ExceptionState& exceptionState)
1348 { 1321 {
1349 if (!drawingCanvas()) 1322 if (!drawingCanvas())
1350 return; 1323 return;
1351 1324
1352 RefPtr<Image> image; 1325 RefPtr<Image> image;
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
1385 // We make the destination canvas fall out of display list mode by calling 1358 // We make the destination canvas fall out of display list mode by calling
1386 // willAccessPixels. This is to prevent run-away memory consumption caused b y SkSurface 1359 // willAccessPixels. This is to prevent run-away memory consumption caused b y SkSurface
1387 // copyOnWrite when the source canvas is animated and consumed at a rate hig her than the 1360 // copyOnWrite when the source canvas is animated and consumed at a rate hig her than the
1388 // presentation frame rate of the destination canvas. 1361 // presentation frame rate of the destination canvas.
1389 if (imageSource->isCanvasElement()) 1362 if (imageSource->isCanvasElement())
1390 canvas()->buffer()->willAccessPixels(); 1363 canvas()->buffer()->willAccessPixels();
1391 1364
1392 draw( 1365 draw(
1393 [this, &imageSource, &image, &srcRect, dstRect](const SkPaint* paint) // draw lambda 1366 [this, &imageSource, &image, &srcRect, dstRect](const SkPaint* paint) // draw lambda
1394 { 1367 {
1395 if (drawingCanvas()) 1368 drawImageInternal(imageSource, image.get(), srcRect, dstRect, paint) ;
1396 drawImageOnContext(imageSource, image.get(), srcRect, dstRect, p aint);
1397 }, 1369 },
1398 [this, &dstRect](const SkIRect& clipBounds) // overdraw test lambda 1370 [this, &dstRect](const SkIRect& clipBounds) // overdraw test lambda
1399 { 1371 {
1400 return rectContainsTransformedRect(dstRect, clipBounds); 1372 return rectContainsTransformedRect(dstRect, clipBounds);
1401 }, 1373 },
1402 dstRect, 1374 dstRect,
1403 CanvasRenderingContext2DState::FillPaintType, 1375 CanvasRenderingContext2DState::ImagePaintType,
1404 imageSource->isOpaque() ? CanvasRenderingContext2DState::OpaqueImage : C anvasRenderingContext2DState::NonOpaqueImage); 1376 imageSource->isOpaque() ? CanvasRenderingContext2DState::OpaqueImage : C anvasRenderingContext2DState::NonOpaqueImage);
1405 1377
1406 validateStateStack(); 1378 validateStateStack();
1407 1379
1408 bool isExpensive = false; 1380 bool isExpensive = false;
1409 1381
1410 if (ExpensiveCanvasHeuristicParameters::SVGImageSourcesAreExpensive && image && image->isSVGImage()) 1382 if (ExpensiveCanvasHeuristicParameters::SVGImageSourcesAreExpensive && image && image->isSVGImage())
1411 isExpensive = true; 1383 isExpensive = true;
1412 1384
1413 if (imageSource->elementSize().width() * imageSource->elementSize().height() > canvas()->width() * canvas()->height() * ExpensiveCanvasHeuristicParameters:: ExpensiveImageSizeRatio) 1385 if (imageSource->elementSize().width() * imageSource->elementSize().height() > canvas()->width() * canvas()->height() * ExpensiveCanvasHeuristicParameters:: ExpensiveImageSizeRatio)
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after
1539 canvas()->didDraw(SkRect::Make(dirtyRect)); 1511 canvas()->didDraw(SkRect::Make(dirtyRect));
1540 } 1512 }
1541 1513
1542 SkCanvas* CanvasRenderingContext2D::drawingCanvas() const 1514 SkCanvas* CanvasRenderingContext2D::drawingCanvas() const
1543 { 1515 {
1544 if (isContextLost()) 1516 if (isContextLost())
1545 return nullptr; 1517 return nullptr;
1546 return canvas()->drawingCanvas(); 1518 return canvas()->drawingCanvas();
1547 } 1519 }
1548 1520
1549 GraphicsContext* CanvasRenderingContext2D::drawingContext() const
1550 {
1551 if (isContextLost())
1552 return nullptr;
1553 return canvas()->drawingContext();
1554 }
1555
1556 ImageData* CanvasRenderingContext2D::createImageData(ImageData* imageData) const 1521 ImageData* CanvasRenderingContext2D::createImageData(ImageData* imageData) const
1557 { 1522 {
1558 return ImageData::create(imageData->size()); 1523 return ImageData::create(imageData->size());
1559 } 1524 }
1560 1525
1561 ImageData* CanvasRenderingContext2D::createImageData(float sw, float sh, Excepti onState& exceptionState) const 1526 ImageData* CanvasRenderingContext2D::createImageData(float sw, float sh, Excepti onState& exceptionState) const
1562 { 1527 {
1563 if (!sw || !sh) { 1528 if (!sw || !sh) {
1564 exceptionState.throwDOMException(IndexSizeError, String::format("The sou rce %s is 0.", sw ? "height" : "width")); 1529 exceptionState.throwDOMException(IndexSizeError, String::format("The sou rce %s is 0.", sw ? "height" : "width"));
1565 return nullptr; 1530 return nullptr;
(...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after
1723 1688
1724 String fontValue = parsedStyle->getPropertyValue(CSSPropertyFont); 1689 String fontValue = parsedStyle->getPropertyValue(CSSPropertyFont);
1725 1690
1726 // According to http://lists.w3.org/Archives/Public/public-html/2009Jul/0947 .html, 1691 // According to http://lists.w3.org/Archives/Public/public-html/2009Jul/0947 .html,
1727 // the "inherit" and "initial" values must be ignored. 1692 // the "inherit" and "initial" values must be ignored.
1728 if (fontValue == "inherit" || fontValue == "initial") 1693 if (fontValue == "inherit" || fontValue == "initial")
1729 return; 1694 return;
1730 1695
1731 // The parse succeeded. 1696 // The parse succeeded.
1732 String newFontSafeCopy(newFont); // Create a string copy since newFont can b e deleted inside realizeSaves. 1697 String newFontSafeCopy(newFont); // Create a string copy since newFont can b e deleted inside realizeSaves.
1733 realizeSaves(nullptr);
1734 modifiableState().setUnparsedFont(newFontSafeCopy); 1698 modifiableState().setUnparsedFont(newFontSafeCopy);
1735 1699
1736 // Map the <canvas> font into the text style. If the font uses keywords like larger/smaller, these will work 1700 // Map the <canvas> font into the text style. If the font uses keywords like larger/smaller, these will work
1737 // relative to the canvas. 1701 // relative to the canvas.
1738 RefPtr<ComputedStyle> newStyle = ComputedStyle::create(); 1702 RefPtr<ComputedStyle> newStyle = ComputedStyle::create();
1739 canvas()->document().updateLayoutTreeIfNeeded(); 1703 canvas()->document().updateLayoutTreeIfNeeded();
1740 if (const ComputedStyle* computedStyle = canvas()->ensureComputedStyle()) { 1704 if (const ComputedStyle* computedStyle = canvas()->ensureComputedStyle()) {
1741 FontDescription elementFontDescription(computedStyle->fontDescription()) ; 1705 FontDescription elementFontDescription(computedStyle->fontDescription()) ;
1742 // Reset the computed size to avoid inheriting the zoom factor from the <canvas> element. 1706 // Reset the computed size to avoid inheriting the zoom factor from the <canvas> element.
1743 elementFontDescription.setComputedSize(elementFontDescription.specifiedS ize()); 1707 elementFontDescription.setComputedSize(elementFontDescription.specifiedS ize());
(...skipping 22 matching lines...) Expand all
1766 return textAlignName(state().textAlign()); 1730 return textAlignName(state().textAlign());
1767 } 1731 }
1768 1732
1769 void CanvasRenderingContext2D::setTextAlign(const String& s) 1733 void CanvasRenderingContext2D::setTextAlign(const String& s)
1770 { 1734 {
1771 TextAlign align; 1735 TextAlign align;
1772 if (!parseTextAlign(s, align)) 1736 if (!parseTextAlign(s, align))
1773 return; 1737 return;
1774 if (state().textAlign() == align) 1738 if (state().textAlign() == align)
1775 return; 1739 return;
1776 realizeSaves(nullptr);
1777 modifiableState().setTextAlign(align); 1740 modifiableState().setTextAlign(align);
1778 } 1741 }
1779 1742
1780 String CanvasRenderingContext2D::textBaseline() const 1743 String CanvasRenderingContext2D::textBaseline() const
1781 { 1744 {
1782 return textBaselineName(state().textBaseline()); 1745 return textBaselineName(state().textBaseline());
1783 } 1746 }
1784 1747
1785 void CanvasRenderingContext2D::setTextBaseline(const String& s) 1748 void CanvasRenderingContext2D::setTextBaseline(const String& s)
1786 { 1749 {
1787 TextBaseline baseline; 1750 TextBaseline baseline;
1788 if (!parseTextBaseline(s, baseline)) 1751 if (!parseTextBaseline(s, baseline))
1789 return; 1752 return;
1790 if (state().textBaseline() == baseline) 1753 if (state().textBaseline() == baseline)
1791 return; 1754 return;
1792 realizeSaves(nullptr);
1793 modifiableState().setTextBaseline(baseline); 1755 modifiableState().setTextBaseline(baseline);
1794 } 1756 }
1795 1757
1796 static inline TextDirection toTextDirection(CanvasRenderingContext2DState::Direc tion direction, HTMLCanvasElement* canvas, const ComputedStyle** computedStyle = 0) 1758 static inline TextDirection toTextDirection(CanvasRenderingContext2DState::Direc tion direction, HTMLCanvasElement* canvas, const ComputedStyle** computedStyle = 0)
1797 { 1759 {
1798 const ComputedStyle* style = (computedStyle || direction == CanvasRenderingC ontext2DState::DirectionInherit) ? canvas->ensureComputedStyle() : nullptr; 1760 const ComputedStyle* style = (computedStyle || direction == CanvasRenderingC ontext2DState::DirectionInherit) ? canvas->ensureComputedStyle() : nullptr;
1799 if (computedStyle) 1761 if (computedStyle)
1800 *computedStyle = style; 1762 *computedStyle = style;
1801 switch (direction) { 1763 switch (direction) {
1802 case CanvasRenderingContext2DState::DirectionInherit: 1764 case CanvasRenderingContext2DState::DirectionInherit:
(...skipping 22 matching lines...) Expand all
1825 else if (directionString == rtl) 1787 else if (directionString == rtl)
1826 direction = CanvasRenderingContext2DState::DirectionRTL; 1788 direction = CanvasRenderingContext2DState::DirectionRTL;
1827 else if (directionString == ltr) 1789 else if (directionString == ltr)
1828 direction = CanvasRenderingContext2DState::DirectionLTR; 1790 direction = CanvasRenderingContext2DState::DirectionLTR;
1829 else 1791 else
1830 return; 1792 return;
1831 1793
1832 if (state().direction() == direction) 1794 if (state().direction() == direction)
1833 return; 1795 return;
1834 1796
1835 realizeSaves(nullptr);
1836 modifiableState().setDirection(direction); 1797 modifiableState().setDirection(direction);
1837 } 1798 }
1838 1799
1839 void CanvasRenderingContext2D::fillText(const String& text, float x, float y) 1800 void CanvasRenderingContext2D::fillText(const String& text, float x, float y)
1840 { 1801 {
1841 drawTextInternal(text, x, y, CanvasRenderingContext2DState::FillPaintType); 1802 drawTextInternal(text, x, y, CanvasRenderingContext2DState::FillPaintType);
1842 } 1803 }
1843 1804
1844 void CanvasRenderingContext2D::fillText(const String& text, float x, float y, fl oat maxWidth) 1805 void CanvasRenderingContext2D::fillText(const String& text, float x, float y, fl oat maxWidth)
1845 { 1806 {
(...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after
1999 if (state().lineJoin() == MiterJoin) 1960 if (state().lineJoin() == MiterJoin)
2000 delta *= state().miterLimit(); 1961 delta *= state().miterLimit();
2001 else if (state().lineCap() == SquareCap) 1962 else if (state().lineCap() == SquareCap)
2002 delta *= root2; 1963 delta *= root2;
2003 1964
2004 rect.inflate(delta); 1965 rect.inflate(delta);
2005 } 1966 }
2006 1967
2007 const Font& CanvasRenderingContext2D::accessFont() 1968 const Font& CanvasRenderingContext2D::accessFont()
2008 { 1969 {
2009 // This needs style to be up to date, but can't assert so because drawTextIn ternal
2010 // can invalidate style before this is called (e.g. drawingContext invalidat es style).
2011 if (!state().hasRealizedFont()) 1970 if (!state().hasRealizedFont())
2012 setFont(state().unparsedFont()); 1971 setFont(state().unparsedFont());
2013 return state().font(); 1972 return state().font();
2014 } 1973 }
2015 1974
2016 int CanvasRenderingContext2D::getFontBaseline(const FontMetrics& fontMetrics) co nst 1975 int CanvasRenderingContext2D::getFontBaseline(const FontMetrics& fontMetrics) co nst
2017 { 1976 {
2018 switch (state().textBaseline()) { 1977 switch (state().textBaseline()) {
2019 case TopTextBaseline: 1978 case TopTextBaseline:
2020 return fontMetrics.ascent(); 1979 return fontMetrics.ascent();
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
2054 bool CanvasRenderingContext2D::imageSmoothingEnabled() const 2013 bool CanvasRenderingContext2D::imageSmoothingEnabled() const
2055 { 2014 {
2056 return state().imageSmoothingEnabled(); 2015 return state().imageSmoothingEnabled();
2057 } 2016 }
2058 2017
2059 void CanvasRenderingContext2D::setImageSmoothingEnabled(bool enabled) 2018 void CanvasRenderingContext2D::setImageSmoothingEnabled(bool enabled)
2060 { 2019 {
2061 if (enabled == state().imageSmoothingEnabled()) 2020 if (enabled == state().imageSmoothingEnabled())
2062 return; 2021 return;
2063 2022
2064 SkCanvas* c = drawingCanvas();
2065 realizeSaves(c);
2066 modifiableState().setImageSmoothingEnabled(enabled); 2023 modifiableState().setImageSmoothingEnabled(enabled);
2067 if (c)
2068 drawingContext()->setImageInterpolationQuality(enabled ? CanvasDefaultIn terpolationQuality : InterpolationNone);
2069 } 2024 }
2070 2025
2071 void CanvasRenderingContext2D::getContextAttributes(Canvas2DContextAttributes& a ttrs) const 2026 void CanvasRenderingContext2D::getContextAttributes(Canvas2DContextAttributes& a ttrs) const
2072 { 2027 {
2073 attrs.setAlpha(m_hasAlpha); 2028 attrs.setAlpha(m_hasAlpha);
2074 } 2029 }
2075 2030
2076 void CanvasRenderingContext2D::drawFocusIfNeeded(Element* element) 2031 void CanvasRenderingContext2D::drawFocusIfNeeded(Element* element)
2077 { 2032 {
2078 drawFocusIfNeededInternal(m_path, element); 2033 drawFocusIfNeededInternal(m_path, element);
(...skipping 29 matching lines...) Expand all
2108 if (path.isEmpty()) 2063 if (path.isEmpty())
2109 return false; 2064 return false;
2110 if (!element->isDescendantOf(canvas())) 2065 if (!element->isDescendantOf(canvas()))
2111 return false; 2066 return false;
2112 2067
2113 return true; 2068 return true;
2114 } 2069 }
2115 2070
2116 void CanvasRenderingContext2D::drawFocusRing(const Path& path) 2071 void CanvasRenderingContext2D::drawFocusRing(const Path& path)
2117 { 2072 {
2118 GraphicsContext* c = drawingContext(); 2073 if (!drawingCanvas())
2119 if (!c)
2120 return; 2074 return;
2121 2075
2122 // These should match the style defined in html.css. 2076 SkColor color = LayoutTheme::theme().focusRingColor().rgb();
2123 Color focusRingColor = LayoutTheme::theme().focusRingColor();
2124 const int focusRingWidth = 5; 2077 const int focusRingWidth = 5;
2125 const int focusRingOutline = 0; 2078
2079 drawPlatformFocusRing(path.skPath(), drawingCanvas(), color, focusRingWidth) ;
2126 2080
2127 // We need to add focusRingWidth to dirtyRect. 2081 // We need to add focusRingWidth to dirtyRect.
2128 StrokeData strokeData; 2082 StrokeData strokeData;
2129 strokeData.setThickness(focusRingWidth); 2083 strokeData.setThickness(focusRingWidth);
2130 2084
2131 SkIRect dirtyRect; 2085 SkIRect dirtyRect;
2132 if (!computeDirtyRect(path.strokeBoundingRect(strokeData), &dirtyRect)) 2086 if (!computeDirtyRect(path.strokeBoundingRect(strokeData), &dirtyRect))
2133 return; 2087 return;
2134 2088
2135 c->setAlphaAsFloat(1.0);
2136 c->clearShadow();
2137 c->setCompositeOperation(SkXfermode::kSrcOver_Mode);
2138 c->drawFocusRing(path, focusRingWidth, focusRingOutline, focusRingColor);
2139 c->setAlphaAsFloat(state().globalAlpha());
2140 c->setCompositeOperation(state().globalComposite());
2141
2142 validateStateStack();
2143 didDraw(dirtyRect); 2089 didDraw(dirtyRect);
2144 } 2090 }
2145 2091
2146 void CanvasRenderingContext2D::updateFocusRingElementAccessibility(const Path& p ath, Element* element) 2092 void CanvasRenderingContext2D::updateFocusRingElementAccessibility(const Path& p ath, Element* element)
2147 { 2093 {
2148 AXObjectCache* axObjectCache = element->document().existingAXObjectCache(); 2094 AXObjectCache* axObjectCache = element->document().existingAXObjectCache();
2149 LayoutBoxModelObject* lbmo = canvas()->layoutBoxModelObject(); 2095 LayoutBoxModelObject* lbmo = canvas()->layoutBoxModelObject();
2150 LayoutObject* renderer = canvas()->layoutObject(); 2096 LayoutObject* renderer = canvas()->layoutObject();
2151 if (!axObjectCache || !lbmo || !renderer) 2097 if (!axObjectCache || !lbmo || !renderer)
2152 return; 2098 return;
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after
2291 if (imageType == CanvasRenderingContext2DState::NonOpaqueImage) 2237 if (imageType == CanvasRenderingContext2DState::NonOpaqueImage)
2292 return; 2238 return;
2293 if (alpha < 0xFF) 2239 if (alpha < 0xFF)
2294 return; 2240 return;
2295 } 2241 }
2296 2242
2297 canvas()->buffer()->willOverwriteCanvas(); 2243 canvas()->buffer()->willOverwriteCanvas();
2298 } 2244 }
2299 2245
2300 } // namespace blink 2246 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698