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

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: fix for overdraw optimization failures and fix for mac build Created 5 years, 8 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"
70 #include "third_party/skia/include/effects/SkCornerPathEffect.h"
68 #include "wtf/ArrayBufferContents.h" 71 #include "wtf/ArrayBufferContents.h"
69 #include "wtf/CheckedArithmetic.h" 72 #include "wtf/CheckedArithmetic.h"
70 #include "wtf/MathExtras.h" 73 #include "wtf/MathExtras.h"
71 #include "wtf/OwnPtr.h" 74 #include "wtf/OwnPtr.h"
72 #include "wtf/text/StringBuilder.h" 75 #include "wtf/text/StringBuilder.h"
73 76
74 namespace blink { 77 namespace blink {
75 78
76 static const int defaultFontSize = 10; 79 static const int defaultFontSize = 10;
77 static const char defaultFontFamily[] = "sans-serif"; 80 static const char defaultFontFamily[] = "sans-serif";
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
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() - 1) == m_stateStack .size());
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 121 matching lines...) Expand 10 before | Expand all | Expand 10 after
293 WillBeHeapVector<OwnPtrWillBeMember<CanvasRenderingContext2DState>>::iterato r currState; 296 WillBeHeapVector<OwnPtrWillBeMember<CanvasRenderingContext2DState>>::iterato r currState;
294 for (currState = m_stateStack.begin(); currState < m_stateStack.end(); currS tate++) { 297 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 298 // The initial save accounts for the save installed by canvasElementElem ent::m_contextStateSaver
296 c->save(); 299 c->save();
297 c->setMatrix(SkMatrix::I()); 300 c->setMatrix(SkMatrix::I());
298 currState->get()->playbackClips(c); 301 currState->get()->playbackClips(c);
299 c->setMatrix(affineTransformToSkMatrix(currState->get()->transform())); 302 c->setMatrix(affineTransformToSkMatrix(currState->get()->transform()));
300 } 303 }
301 } 304 }
302 305
303 void CanvasRenderingContext2D::realizeSaves(SkCanvas* canvas) 306 void CanvasRenderingContext2D::realizeSaves()
304 { 307 {
305 validateStateStack(); 308 validateStateStack();
306 if (state().hasUnrealizedSaves()) { 309 if (state().hasUnrealizedSaves()) {
307 ASSERT(m_stateStack.size() >= 1); 310 ASSERT(m_stateStack.size() >= 1);
308 // Reduce the current state's unrealized count by one now, 311 // Reduce the current state's unrealized count by one now,
309 // to reflect the fact we are saving one state. 312 // to reflect the fact we are saving one state.
310 m_stateStack.last()->restore(); 313 m_stateStack.last()->restore();
311 m_stateStack.append(adoptPtrWillBeNoop(new CanvasRenderingContext2DState (state(), CanvasRenderingContext2DState::DontCopyClipList))); 314 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. 315 // 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 316 // 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 317 // 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 ). 318 // turn necessary to support correct resizing and unwinding of the stack ).
316 m_stateStack.last()->resetUnrealizedSaveCount(); 319 m_stateStack.last()->resetUnrealizedSaveCount();
317 if (!canvas) 320 SkCanvas* canvas = drawingCanvas();
318 canvas = drawingCanvas();
319 if (canvas) 321 if (canvas)
320 canvas->save(); 322 canvas->save();
321 validateStateStack(); 323 validateStateStack();
322 } 324 }
323 } 325 }
324 326
325 void CanvasRenderingContext2D::save() 327 void CanvasRenderingContext2D::save()
326 { 328 {
327 m_stateStack.last()->save(); 329 m_stateStack.last()->save();
328 } 330 }
329 331
330 void CanvasRenderingContext2D::restore() 332 void CanvasRenderingContext2D::restore()
331 { 333 {
332 validateStateStack(); 334 validateStateStack();
333 if (state().hasUnrealizedSaves()) { 335 if (state().hasUnrealizedSaves()) {
334 // We never realized the save, so just record that it was unnecessary. 336 // We never realized the save, so just record that it was unnecessary.
335 m_stateStack.last()->restore(); 337 m_stateStack.last()->restore();
336 return; 338 return;
337 } 339 }
338 ASSERT(m_stateStack.size() >= 1); 340 ASSERT(m_stateStack.size() >= 1);
339 if (m_stateStack.size() <= 1) 341 if (m_stateStack.size() <= 1)
340 return; 342 return;
341 m_path.transform(state().transform()); 343 m_path.transform(state().transform());
342 m_stateStack.removeLast(); 344 m_stateStack.removeLast();
343 m_path.transform(state().transform().inverse()); 345 m_path.transform(state().transform().inverse());
344 SkCanvas* c = drawingCanvas(); 346 SkCanvas* c = drawingCanvas();
345 if (c) 347 if (c)
346 c->restore(); 348 c->restore();
347 349
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(); 350 validateStateStack();
359 } 351 }
360 352
361 static inline void convertCanvasStyleToUnionType(CanvasStyle* style, StringOrCan vasGradientOrCanvasPattern& returnValue) 353 static inline void convertCanvasStyleToUnionType(CanvasStyle* style, StringOrCan vasGradientOrCanvasPattern& returnValue)
362 { 354 {
363 if (CanvasGradient* gradient = style->canvasGradient()) { 355 if (CanvasGradient* gradient = style->canvasGradient()) {
364 returnValue.setCanvasGradient(gradient); 356 returnValue.setCanvasGradient(gradient);
365 return; 357 return;
366 } 358 }
367 if (CanvasPattern* pattern = style->canvasPattern()) { 359 if (CanvasPattern* pattern = style->canvasPattern()) {
(...skipping 15 matching lines...) Expand all
383 String colorString; 375 String colorString;
384 RefPtrWillBeRawPtr<CanvasStyle> canvasStyle = nullptr; 376 RefPtrWillBeRawPtr<CanvasStyle> canvasStyle = nullptr;
385 if (style.isString()) { 377 if (style.isString()) {
386 colorString = style.getAsString(); 378 colorString = style.getAsString();
387 if (colorString == state().unparsedStrokeColor()) 379 if (colorString == state().unparsedStrokeColor())
388 return; 380 return;
389 RGBA32 parsedColor = 0; 381 RGBA32 parsedColor = 0;
390 if (!parseColorOrCurrentColor(parsedColor, colorString, canvas())) 382 if (!parseColorOrCurrentColor(parsedColor, colorString, canvas()))
391 return; 383 return;
392 if (state().strokeStyle()->isEquivalentRGBA(parsedColor)) { 384 if (state().strokeStyle()->isEquivalentRGBA(parsedColor)) {
393 realizeSaves(nullptr);
394 modifiableState().setUnparsedStrokeColor(colorString); 385 modifiableState().setUnparsedStrokeColor(colorString);
395 return; 386 return;
396 } 387 }
397 canvasStyle = CanvasStyle::createFromRGBA(parsedColor); 388 canvasStyle = CanvasStyle::createFromRGBA(parsedColor);
398 } else if (style.isCanvasGradient()) { 389 } else if (style.isCanvasGradient()) {
399 canvasStyle = CanvasStyle::createFromGradient(style.getAsCanvasGradient( )); 390 canvasStyle = CanvasStyle::createFromGradient(style.getAsCanvasGradient( ));
400 } else if (style.isCanvasPattern()) { 391 } else if (style.isCanvasPattern()) {
401 RefPtrWillBeRawPtr<CanvasPattern> canvasPattern = style.getAsCanvasPatte rn(); 392 RefPtrWillBeRawPtr<CanvasPattern> canvasPattern = style.getAsCanvasPatte rn();
402 393
403 if (canvas()->originClean() && !canvasPattern->originClean()) 394 if (canvas()->originClean() && !canvasPattern->originClean())
404 canvas()->setOriginTainted(); 395 canvas()->setOriginTainted();
405 396
406 canvasStyle = CanvasStyle::createFromPattern(canvasPattern); 397 canvasStyle = CanvasStyle::createFromPattern(canvasPattern);
407 } 398 }
408 399
409 ASSERT(canvasStyle); 400 ASSERT(canvasStyle);
410 401
411 SkCanvas* c = drawingCanvas();
412 realizeSaves(c);
413 modifiableState().setStrokeStyle(canvasStyle.release()); 402 modifiableState().setStrokeStyle(canvasStyle.release());
414 if (!c)
415 return;
416 modifiableState().setUnparsedStrokeColor(colorString); 403 modifiableState().setUnparsedStrokeColor(colorString);
417 } 404 }
418 405
419 void CanvasRenderingContext2D::fillStyle(StringOrCanvasGradientOrCanvasPattern& returnValue) const 406 void CanvasRenderingContext2D::fillStyle(StringOrCanvasGradientOrCanvasPattern& returnValue) const
420 { 407 {
421 convertCanvasStyleToUnionType(state().fillStyle(), returnValue); 408 convertCanvasStyleToUnionType(state().fillStyle(), returnValue);
422 } 409 }
423 410
424 void CanvasRenderingContext2D::setFillStyle(const StringOrCanvasGradientOrCanvas Pattern& style) 411 void CanvasRenderingContext2D::setFillStyle(const StringOrCanvasGradientOrCanvas Pattern& style)
425 { 412 {
426 ASSERT(!style.isNull()); 413 ASSERT(!style.isNull());
427 validateStateStack(); 414 validateStateStack();
428 String colorString; 415 String colorString;
429 RefPtrWillBeRawPtr<CanvasStyle> canvasStyle = nullptr; 416 RefPtrWillBeRawPtr<CanvasStyle> canvasStyle = nullptr;
430 if (style.isString()) { 417 if (style.isString()) {
431 colorString = style.getAsString(); 418 colorString = style.getAsString();
432 if (colorString == state().unparsedFillColor()) 419 if (colorString == state().unparsedFillColor())
433 return; 420 return;
434 RGBA32 parsedColor = 0; 421 RGBA32 parsedColor = 0;
435 if (!parseColorOrCurrentColor(parsedColor, colorString, canvas())) 422 if (!parseColorOrCurrentColor(parsedColor, colorString, canvas()))
436 return; 423 return;
437 if (state().fillStyle()->isEquivalentRGBA(parsedColor)) { 424 if (state().fillStyle()->isEquivalentRGBA(parsedColor)) {
438 realizeSaves(nullptr);
439 modifiableState().setUnparsedFillColor(colorString); 425 modifiableState().setUnparsedFillColor(colorString);
440 return; 426 return;
441 } 427 }
442 canvasStyle = CanvasStyle::createFromRGBA(parsedColor); 428 canvasStyle = CanvasStyle::createFromRGBA(parsedColor);
443 } else if (style.isCanvasGradient()) { 429 } else if (style.isCanvasGradient()) {
444 canvasStyle = CanvasStyle::createFromGradient(style.getAsCanvasGradient( )); 430 canvasStyle = CanvasStyle::createFromGradient(style.getAsCanvasGradient( ));
445 } else if (style.isCanvasPattern()) { 431 } else if (style.isCanvasPattern()) {
446 RefPtrWillBeRawPtr<CanvasPattern> canvasPattern = style.getAsCanvasPatte rn(); 432 RefPtrWillBeRawPtr<CanvasPattern> canvasPattern = style.getAsCanvasPatte rn();
447 433
448 if (canvas()->originClean() && !canvasPattern->originClean()) 434 if (canvas()->originClean() && !canvasPattern->originClean())
449 canvas()->setOriginTainted(); 435 canvas()->setOriginTainted();
450 436
451 canvasStyle = CanvasStyle::createFromPattern(canvasPattern); 437 canvasStyle = CanvasStyle::createFromPattern(canvasPattern);
452 } 438 }
453 439
454 ASSERT(canvasStyle); 440 ASSERT(canvasStyle);
455 SkCanvas* c = drawingCanvas();
456 if (!c)
457 return;
458 realizeSaves(c);
459
460 modifiableState().setFillStyle(canvasStyle.release()); 441 modifiableState().setFillStyle(canvasStyle.release());
461 modifiableState().setUnparsedFillColor(colorString); 442 modifiableState().setUnparsedFillColor(colorString);
462 } 443 }
463 444
464 float CanvasRenderingContext2D::lineWidth() const 445 float CanvasRenderingContext2D::lineWidth() const
465 { 446 {
466 return state().lineWidth(); 447 return state().lineWidth();
467 } 448 }
468 449
469 void CanvasRenderingContext2D::setLineWidth(float width) 450 void CanvasRenderingContext2D::setLineWidth(float width)
470 { 451 {
471 if (!std::isfinite(width) || width <= 0) 452 if (!std::isfinite(width) || width <= 0)
472 return; 453 return;
473 if (state().lineWidth() == width) 454 if (state().lineWidth() == width)
474 return; 455 return;
475 SkCanvas* c = drawingCanvas();
476 realizeSaves(c);
477 modifiableState().setLineWidth(width); 456 modifiableState().setLineWidth(width);
478 if (!c)
479 return;
480 } 457 }
481 458
482 String CanvasRenderingContext2D::lineCap() const 459 String CanvasRenderingContext2D::lineCap() const
483 { 460 {
484 return lineCapName(state().lineCap()); 461 return lineCapName(state().lineCap());
485 } 462 }
486 463
487 void CanvasRenderingContext2D::setLineCap(const String& s) 464 void CanvasRenderingContext2D::setLineCap(const String& s)
488 { 465 {
489 LineCap cap; 466 LineCap cap;
490 if (!parseLineCap(s, cap)) 467 if (!parseLineCap(s, cap))
491 return; 468 return;
492 if (state().lineCap() == cap) 469 if (state().lineCap() == cap)
493 return; 470 return;
494 SkCanvas* c = drawingCanvas();
495 realizeSaves(c);
496 modifiableState().setLineCap(cap); 471 modifiableState().setLineCap(cap);
497 if (!c)
498 return;
499 } 472 }
500 473
501 String CanvasRenderingContext2D::lineJoin() const 474 String CanvasRenderingContext2D::lineJoin() const
502 { 475 {
503 return lineJoinName(state().lineJoin()); 476 return lineJoinName(state().lineJoin());
504 } 477 }
505 478
506 void CanvasRenderingContext2D::setLineJoin(const String& s) 479 void CanvasRenderingContext2D::setLineJoin(const String& s)
507 { 480 {
508 LineJoin join; 481 LineJoin join;
509 if (!parseLineJoin(s, join)) 482 if (!parseLineJoin(s, join))
510 return; 483 return;
511 if (state().lineJoin() == join) 484 if (state().lineJoin() == join)
512 return; 485 return;
513 SkCanvas* c = drawingCanvas();
514 realizeSaves(c);
515 modifiableState().setLineJoin(join); 486 modifiableState().setLineJoin(join);
516 if (!c)
517 return;
518 } 487 }
519 488
520 float CanvasRenderingContext2D::miterLimit() const 489 float CanvasRenderingContext2D::miterLimit() const
521 { 490 {
522 return state().miterLimit(); 491 return state().miterLimit();
523 } 492 }
524 493
525 void CanvasRenderingContext2D::setMiterLimit(float limit) 494 void CanvasRenderingContext2D::setMiterLimit(float limit)
526 { 495 {
527 if (!std::isfinite(limit) || limit <= 0) 496 if (!std::isfinite(limit) || limit <= 0)
528 return; 497 return;
529 if (state().miterLimit() == limit) 498 if (state().miterLimit() == limit)
530 return; 499 return;
531 SkCanvas* c = drawingCanvas();
532 realizeSaves(c);
533 modifiableState().setMiterLimit(limit); 500 modifiableState().setMiterLimit(limit);
534 if (!c)
535 return;
536 } 501 }
537 502
538 float CanvasRenderingContext2D::shadowOffsetX() const 503 float CanvasRenderingContext2D::shadowOffsetX() const
539 { 504 {
540 return state().shadowOffset().width(); 505 return state().shadowOffset().width();
541 } 506 }
542 507
543 void CanvasRenderingContext2D::setShadowOffsetX(float x) 508 void CanvasRenderingContext2D::setShadowOffsetX(float x)
544 { 509 {
545 if (!std::isfinite(x)) 510 if (!std::isfinite(x))
546 return; 511 return;
547 if (state().shadowOffset().width() == x) 512 if (state().shadowOffset().width() == x)
548 return; 513 return;
549 realizeSaves(nullptr);
550 modifiableState().setShadowOffsetX(x); 514 modifiableState().setShadowOffsetX(x);
551 } 515 }
552 516
553 float CanvasRenderingContext2D::shadowOffsetY() const 517 float CanvasRenderingContext2D::shadowOffsetY() const
554 { 518 {
555 return state().shadowOffset().height(); 519 return state().shadowOffset().height();
556 } 520 }
557 521
558 void CanvasRenderingContext2D::setShadowOffsetY(float y) 522 void CanvasRenderingContext2D::setShadowOffsetY(float y)
559 { 523 {
560 if (!std::isfinite(y)) 524 if (!std::isfinite(y))
561 return; 525 return;
562 if (state().shadowOffset().height() == y) 526 if (state().shadowOffset().height() == y)
563 return; 527 return;
564 realizeSaves(nullptr);
565 modifiableState().setShadowOffsetY(y); 528 modifiableState().setShadowOffsetY(y);
566 } 529 }
567 530
568 float CanvasRenderingContext2D::shadowBlur() const 531 float CanvasRenderingContext2D::shadowBlur() const
569 { 532 {
570 return state().shadowBlur(); 533 return state().shadowBlur();
571 } 534 }
572 535
573 void CanvasRenderingContext2D::setShadowBlur(float blur) 536 void CanvasRenderingContext2D::setShadowBlur(float blur)
574 { 537 {
575 if (!std::isfinite(blur) || blur < 0) 538 if (!std::isfinite(blur) || blur < 0)
576 return; 539 return;
577 if (state().shadowBlur() == blur) 540 if (state().shadowBlur() == blur)
578 return; 541 return;
579 realizeSaves(nullptr);
580 modifiableState().setShadowBlur(blur); 542 modifiableState().setShadowBlur(blur);
581 } 543 }
582 544
583 String CanvasRenderingContext2D::shadowColor() const 545 String CanvasRenderingContext2D::shadowColor() const
584 { 546 {
585 return Color(state().shadowColor()).serialized(); 547 return Color(state().shadowColor()).serialized();
586 } 548 }
587 549
588 void CanvasRenderingContext2D::setShadowColor(const String& color) 550 void CanvasRenderingContext2D::setShadowColor(const String& color)
589 { 551 {
590 RGBA32 rgba; 552 RGBA32 rgba;
591 if (!parseColorOrCurrentColor(rgba, color, canvas())) 553 if (!parseColorOrCurrentColor(rgba, color, canvas()))
592 return; 554 return;
593 if (state().shadowColor() == rgba) 555 if (state().shadowColor() == rgba)
594 return; 556 return;
595 realizeSaves(nullptr);
596 modifiableState().setShadowColor(rgba); 557 modifiableState().setShadowColor(rgba);
597 } 558 }
598 559
599 const Vector<float>& CanvasRenderingContext2D::getLineDash() const 560 const Vector<float>& CanvasRenderingContext2D::getLineDash() const
600 { 561 {
601 return state().lineDash(); 562 return state().lineDash();
602 } 563 }
603 564
604 static bool lineDashSequenceIsValid(const Vector<float>& dash) 565 static bool lineDashSequenceIsValid(const Vector<float>& dash)
605 { 566 {
606 for (size_t i = 0; i < dash.size(); i++) { 567 for (size_t i = 0; i < dash.size(); i++) {
607 if (!std::isfinite(dash[i]) || dash[i] < 0) 568 if (!std::isfinite(dash[i]) || dash[i] < 0)
608 return false; 569 return false;
609 } 570 }
610 return true; 571 return true;
611 } 572 }
612 573
613 void CanvasRenderingContext2D::setLineDash(const Vector<float>& dash) 574 void CanvasRenderingContext2D::setLineDash(const Vector<float>& dash)
614 { 575 {
615 if (!lineDashSequenceIsValid(dash)) 576 if (!lineDashSequenceIsValid(dash))
616 return; 577 return;
617
618 realizeSaves(nullptr);
619 modifiableState().setLineDash(dash); 578 modifiableState().setLineDash(dash);
620 } 579 }
621 580
622 float CanvasRenderingContext2D::lineDashOffset() const 581 float CanvasRenderingContext2D::lineDashOffset() const
623 { 582 {
624 return state().lineDashOffset(); 583 return state().lineDashOffset();
625 } 584 }
626 585
627 void CanvasRenderingContext2D::setLineDashOffset(float offset) 586 void CanvasRenderingContext2D::setLineDashOffset(float offset)
628 { 587 {
629 if (!std::isfinite(offset) || state().lineDashOffset() == offset) 588 if (!std::isfinite(offset) || state().lineDashOffset() == offset)
630 return; 589 return;
631
632 realizeSaves(nullptr);
633 modifiableState().setLineDashOffset(offset); 590 modifiableState().setLineDashOffset(offset);
634 } 591 }
635 592
636 float CanvasRenderingContext2D::globalAlpha() const 593 float CanvasRenderingContext2D::globalAlpha() const
637 { 594 {
638 return state().globalAlpha(); 595 return state().globalAlpha();
639 } 596 }
640 597
641 void CanvasRenderingContext2D::setGlobalAlpha(float alpha) 598 void CanvasRenderingContext2D::setGlobalAlpha(float alpha)
642 { 599 {
643 if (!(alpha >= 0 && alpha <= 1)) 600 if (!(alpha >= 0 && alpha <= 1))
644 return; 601 return;
645 if (state().globalAlpha() == alpha) 602 if (state().globalAlpha() == alpha)
646 return; 603 return;
647 SkCanvas* c = drawingCanvas();
648 realizeSaves(c);
649 modifiableState().setGlobalAlpha(alpha); 604 modifiableState().setGlobalAlpha(alpha);
650 if (!c)
651 return;
652 drawingContext()->setAlphaAsFloat(alpha);
653 } 605 }
654 606
655 String CanvasRenderingContext2D::globalCompositeOperation() const 607 String CanvasRenderingContext2D::globalCompositeOperation() const
656 { 608 {
657 return compositeOperatorName(compositeOperatorFromSkia(state().globalComposi te()), blendModeFromSkia(state().globalComposite())); 609 return compositeOperatorName(compositeOperatorFromSkia(state().globalComposi te()), blendModeFromSkia(state().globalComposite()));
658 } 610 }
659 611
660 void CanvasRenderingContext2D::setGlobalCompositeOperation(const String& operati on) 612 void CanvasRenderingContext2D::setGlobalCompositeOperation(const String& operati on)
661 { 613 {
662 CompositeOperator op = CompositeSourceOver; 614 CompositeOperator op = CompositeSourceOver;
663 WebBlendMode blendMode = WebBlendModeNormal; 615 WebBlendMode blendMode = WebBlendModeNormal;
664 // TODO(dshwang): Support nonstandard "darker" until M43. crbug.com/425628 616 // TODO(dshwang): Support nonstandard "darker" until M43. crbug.com/425628
665 String operationName = operation; 617 String operationName = operation;
666 if (operation == "darker") { 618 if (operation == "darker") {
667 operationName = "darken"; 619 operationName = "darken";
668 if (canvas()) 620 if (canvas())
669 UseCounter::countDeprecation(canvas()->document(), UseCounter::Canva sRenderingContext2DCompositeOperationDarker); 621 UseCounter::countDeprecation(canvas()->document(), UseCounter::Canva sRenderingContext2DCompositeOperationDarker);
670 } 622 }
671 if (!parseCompositeAndBlendOperator(operationName, op, blendMode)) 623 if (!parseCompositeAndBlendOperator(operationName, op, blendMode))
672 return; 624 return;
673 SkXfermode::Mode xfermode = WebCoreCompositeToSkiaComposite(op, blendMode); 625 SkXfermode::Mode xfermode = WebCoreCompositeToSkiaComposite(op, blendMode);
674 if (state().globalComposite() == xfermode) 626 if (state().globalComposite() == xfermode)
675 return; 627 return;
676 SkCanvas* c = drawingCanvas();
677 realizeSaves(c);
678 modifiableState().setGlobalComposite(xfermode); 628 modifiableState().setGlobalComposite(xfermode);
679 if (!c)
680 return;
681 drawingContext()->setCompositeOperation(xfermode);
682 } 629 }
683 630
684 PassRefPtrWillBeRawPtr<SVGMatrixTearOff> CanvasRenderingContext2D::currentTransf orm() const 631 PassRefPtrWillBeRawPtr<SVGMatrixTearOff> CanvasRenderingContext2D::currentTransf orm() const
685 { 632 {
686 return SVGMatrixTearOff::create(state().transform()); 633 return SVGMatrixTearOff::create(state().transform());
687 } 634 }
688 635
689 void CanvasRenderingContext2D::setCurrentTransform(PassRefPtrWillBeRawPtr<SVGMat rixTearOff> passMatrixTearOff) 636 void CanvasRenderingContext2D::setCurrentTransform(PassRefPtrWillBeRawPtr<SVGMat rixTearOff> passMatrixTearOff)
690 { 637 {
691 RefPtrWillBeRawPtr<SVGMatrixTearOff> matrixTearOff = passMatrixTearOff; 638 RefPtrWillBeRawPtr<SVGMatrixTearOff> matrixTearOff = passMatrixTearOff;
692 const AffineTransform& transform = matrixTearOff->value(); 639 const AffineTransform& transform = matrixTearOff->value();
693 setTransform(transform.a(), transform.b(), transform.c(), transform.d(), tra nsform.e(), transform.f()); 640 setTransform(transform.a(), transform.b(), transform.c(), transform.d(), tra nsform.e(), transform.f());
694 } 641 }
695 642
696 void CanvasRenderingContext2D::scale(float sx, float sy) 643 void CanvasRenderingContext2D::scale(float sx, float sy)
697 { 644 {
698 SkCanvas* c = drawingCanvas(); 645 SkCanvas* c = drawingCanvas();
699 if (!c) 646 if (!c)
700 return; 647 return;
701 648
702 if (!std::isfinite(sx) || !std::isfinite(sy)) 649 if (!std::isfinite(sx) || !std::isfinite(sy))
703 return; 650 return;
704 651
705 AffineTransform newTransform = state().transform(); 652 AffineTransform newTransform = state().transform();
706 newTransform.scaleNonUniform(sx, sy); 653 newTransform.scaleNonUniform(sx, sy);
707 if (state().transform() == newTransform) 654 if (state().transform() == newTransform)
708 return; 655 return;
709 656
710 realizeSaves(c);
711
712 modifiableState().setTransform(newTransform); 657 modifiableState().setTransform(newTransform);
713 if (!state().isTransformInvertible()) 658 if (!state().isTransformInvertible())
714 return; 659 return;
715 660
716 c->scale(sx, sy); 661 c->scale(sx, sy);
717 m_path.transform(AffineTransform().scaleNonUniform(1.0 / sx, 1.0 / sy)); 662 m_path.transform(AffineTransform().scaleNonUniform(1.0 / sx, 1.0 / sy));
718 } 663 }
719 664
720 void CanvasRenderingContext2D::rotate(float angleInRadians) 665 void CanvasRenderingContext2D::rotate(float angleInRadians)
721 { 666 {
722 SkCanvas* c = drawingCanvas(); 667 SkCanvas* c = drawingCanvas();
723 if (!c) 668 if (!c)
724 return; 669 return;
725 670
726 if (!std::isfinite(angleInRadians)) 671 if (!std::isfinite(angleInRadians))
727 return; 672 return;
728 673
729 AffineTransform newTransform = state().transform(); 674 AffineTransform newTransform = state().transform();
730 newTransform.rotateRadians(angleInRadians); 675 newTransform.rotateRadians(angleInRadians);
731 if (state().transform() == newTransform) 676 if (state().transform() == newTransform)
732 return; 677 return;
733 678
734 realizeSaves(c);
735
736 modifiableState().setTransform(newTransform); 679 modifiableState().setTransform(newTransform);
737 if (!state().isTransformInvertible()) 680 if (!state().isTransformInvertible())
738 return; 681 return;
739 c->rotate(angleInRadians * (180.0f / piFloat)); 682 c->rotate(angleInRadians * (180.0f / piFloat));
740 m_path.transform(AffineTransform().rotateRadians(-angleInRadians)); 683 m_path.transform(AffineTransform().rotateRadians(-angleInRadians));
741 } 684 }
742 685
743 void CanvasRenderingContext2D::translate(float tx, float ty) 686 void CanvasRenderingContext2D::translate(float tx, float ty)
744 { 687 {
745 SkCanvas* c = drawingCanvas(); 688 SkCanvas* c = drawingCanvas();
746 if (!c) 689 if (!c)
747 return; 690 return;
748 if (!state().isTransformInvertible()) 691 if (!state().isTransformInvertible())
749 return; 692 return;
750 693
751 if (!std::isfinite(tx) || !std::isfinite(ty)) 694 if (!std::isfinite(tx) || !std::isfinite(ty))
752 return; 695 return;
753 696
754 AffineTransform newTransform = state().transform(); 697 AffineTransform newTransform = state().transform();
755 newTransform.translate(tx, ty); 698 newTransform.translate(tx, ty);
756 if (state().transform() == newTransform) 699 if (state().transform() == newTransform)
757 return; 700 return;
758 701
759 realizeSaves(c);
760
761 modifiableState().setTransform(newTransform); 702 modifiableState().setTransform(newTransform);
762 if (!state().isTransformInvertible()) 703 if (!state().isTransformInvertible())
763 return; 704 return;
764 c->translate(tx, ty); 705 c->translate(tx, ty);
765 m_path.transform(AffineTransform().translate(-tx, -ty)); 706 m_path.transform(AffineTransform().translate(-tx, -ty));
766 } 707 }
767 708
768 void CanvasRenderingContext2D::transform(float m11, float m12, float m21, float m22, float dx, float dy) 709 void CanvasRenderingContext2D::transform(float m11, float m12, float m21, float m22, float dx, float dy)
769 { 710 {
770 SkCanvas* c = drawingCanvas(); 711 SkCanvas* c = drawingCanvas();
771 if (!c) 712 if (!c)
772 return; 713 return;
773 714
774 if (!std::isfinite(m11) || !std::isfinite(m21) || !std::isfinite(dx) || !std ::isfinite(m12) || !std::isfinite(m22) || !std::isfinite(dy)) 715 if (!std::isfinite(m11) || !std::isfinite(m21) || !std::isfinite(dx) || !std ::isfinite(m12) || !std::isfinite(m22) || !std::isfinite(dy))
775 return; 716 return;
776 717
777 AffineTransform transform(m11, m12, m21, m22, dx, dy); 718 AffineTransform transform(m11, m12, m21, m22, dx, dy);
778 AffineTransform newTransform = state().transform() * transform; 719 AffineTransform newTransform = state().transform() * transform;
779 if (state().transform() == newTransform) 720 if (state().transform() == newTransform)
780 return; 721 return;
781 722
782 realizeSaves(c);
783
784 modifiableState().setTransform(newTransform); 723 modifiableState().setTransform(newTransform);
785 if (!state().isTransformInvertible()) 724 if (!state().isTransformInvertible())
786 return; 725 return;
787 726
788 c->concat(affineTransformToSkMatrix(transform)); 727 c->concat(affineTransformToSkMatrix(transform));
789 m_path.transform(transform.inverse()); 728 m_path.transform(transform.inverse());
790 } 729 }
791 730
792 void CanvasRenderingContext2D::resetTransform() 731 void CanvasRenderingContext2D::resetTransform()
793 { 732 {
794 SkCanvas* c = drawingCanvas(); 733 SkCanvas* c = drawingCanvas();
795 if (!c) 734 if (!c)
796 return; 735 return;
797 736
798 AffineTransform ctm = state().transform(); 737 AffineTransform ctm = state().transform();
799 bool invertibleCTM = state().isTransformInvertible(); 738 bool invertibleCTM = state().isTransformInvertible();
800 // It is possible that CTM is identity while CTM is not invertible. 739 // It is possible that CTM is identity while CTM is not invertible.
801 // When CTM becomes non-invertible, realizeSaves() can make CTM identity. 740 // When CTM becomes non-invertible, realizeSaves() can make CTM identity.
802 if (ctm.isIdentity() && invertibleCTM) 741 if (ctm.isIdentity() && invertibleCTM)
803 return; 742 return;
804 743
805 realizeSaves(c);
806 // resetTransform() resolves the non-invertible CTM state. 744 // resetTransform() resolves the non-invertible CTM state.
807 modifiableState().resetTransform(); 745 modifiableState().resetTransform();
808 c->setMatrix(affineTransformToSkMatrix(canvas()->baseTransform())); 746 c->setMatrix(affineTransformToSkMatrix(canvas()->baseTransform()));
809 747
810 if (invertibleCTM) 748 if (invertibleCTM)
811 m_path.transform(ctm); 749 m_path.transform(ctm);
812 // When else, do nothing because all transform methods didn't update m_path when CTM became non-invertible. 750 // 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. 751 // It means that resetTransform() restores m_path just before CTM became non -invertible.
814 } 752 }
815 753
(...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) 830 bool CanvasRenderingContext2D::draw(const DrawFunc& drawFunc, const ContainsFunc & drawCoversClipBounds, const SkRect& bounds, CanvasRenderingContext2DState::Pai ntType paintType, CanvasRenderingContext2DState::ImageType imageType)
893 { 831 {
894 if (!state().isTransformInvertible()) 832 if (!state().isTransformInvertible())
895 return false; 833 return false;
896 834
897 SkIRect clipBounds; 835 SkIRect clipBounds;
898 if (!drawingCanvas() || !drawingCanvas()->getClipDeviceBounds(&clipBounds)) 836 if (!drawingCanvas() || !drawingCanvas()->getClipDeviceBounds(&clipBounds))
899 return false; 837 return false;
900 838
901 // If gradient size is zero, then paint nothing. 839 // If gradient size is zero, then paint nothing.
902 CanvasGradient* gradient = state().style(paintType)->canvasGradient(); 840 CanvasStyle* style = state().style(paintType);
903 if (gradient && gradient->gradient()->isZeroSize()) 841 if (style) {
904 return false; 842 CanvasGradient* gradient = style->canvasGradient();
843 if (gradient && gradient->gradient()->isZeroSize())
844 return false;
845 }
905 846
906 if (isFullCanvasCompositeMode(state().globalComposite())) { 847 if (isFullCanvasCompositeMode(state().globalComposite())) {
907 fullCanvasCompositedDraw(drawFunc, paintType, imageType); 848 fullCanvasCompositedDraw(drawFunc, paintType, imageType);
908 didDraw(clipBounds); 849 didDraw(clipBounds);
909 } else if (state().globalComposite() == SkXfermode::kSrc_Mode) { 850 } else if (state().globalComposite() == SkXfermode::kSrc_Mode) {
910 clearCanvas(); // takes care of checkOvewrdraw() 851 clearCanvas(); // takes care of checkOvewrdraw()
911 const SkPaint* paint = state().getPaint(paintType, DrawForegroundOnly, i mageType); 852 const SkPaint* paint = state().getPaint(paintType, DrawForegroundOnly, i mageType);
912 drawFunc(paint); 853 drawFunc(paint);
913 didDraw(clipBounds); 854 didDraw(clipBounds);
914 } else { 855 } else {
915 SkIRect dirtyRect; 856 SkIRect dirtyRect;
916 if (computeDirtyRect(bounds, clipBounds, &dirtyRect)) { 857 if (computeDirtyRect(bounds, clipBounds, &dirtyRect)) {
917 const SkPaint* paint = state().getPaint(paintType, DrawShadowAndFore ground, imageType); 858 const SkPaint* paint = state().getPaint(paintType, DrawShadowAndFore ground, imageType);
918 if (paintType == CanvasRenderingContext2DState::FillPaintType && dra wCoversClipBounds(clipBounds)) 859 if (paintType != CanvasRenderingContext2DState::StrokePaintType && d rawCoversClipBounds(clipBounds))
919 checkOverdraw(bounds, paint, imageType, ClipFill); 860 checkOverdraw(bounds, paint, imageType, ClipFill);
920 drawFunc(paint); 861 drawFunc(paint);
921 didDraw(dirtyRect); 862 didDraw(dirtyRect);
922 } 863 }
923 } 864 }
924 return true; 865 return true;
925 } 866 }
926 867
927 static bool isPathExpensive(const Path& path) 868 static bool isPathExpensive(const Path& path)
928 { 869 {
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after
1057 void CanvasRenderingContext2D::clipInternal(const Path& path, const String& wind ingRuleString) 998 void CanvasRenderingContext2D::clipInternal(const Path& path, const String& wind ingRuleString)
1058 { 999 {
1059 SkCanvas* c = drawingCanvas(); 1000 SkCanvas* c = drawingCanvas();
1060 if (!c) { 1001 if (!c) {
1061 return; 1002 return;
1062 } 1003 }
1063 if (!state().isTransformInvertible()) { 1004 if (!state().isTransformInvertible()) {
1064 return; 1005 return;
1065 } 1006 }
1066 1007
1067 realizeSaves(c);
1068
1069 SkPath skPath = path.skPath(); 1008 SkPath skPath = path.skPath();
1070 skPath.setFillType(parseWinding(windingRuleString)); 1009 skPath.setFillType(parseWinding(windingRuleString));
1071 modifiableState().clipPath(skPath, m_clipAntialiasing); 1010 modifiableState().clipPath(skPath, m_clipAntialiasing);
1072 c->clipPath(skPath, SkRegion::kIntersect_Op, m_clipAntialiasing == AntiAlias ed); 1011 c->clipPath(skPath, SkRegion::kIntersect_Op, m_clipAntialiasing == AntiAlias ed);
1073 if (ExpensiveCanvasHeuristicParameters::ComplexClipsAreExpensive && !skPath. isRect(0) && canvas()->hasImageBuffer()) { 1012 if (ExpensiveCanvasHeuristicParameters::ComplexClipsAreExpensive && !skPath. isRect(0) && canvas()->hasImageBuffer()) {
1074 canvas()->buffer()->setHasExpensiveOp(); 1013 canvas()->buffer()->setHasExpensiveOp();
1075 } 1014 }
1076 } 1015 }
1077 1016
1078 void CanvasRenderingContext2D::clip(const String& windingRuleString) 1017 void CanvasRenderingContext2D::clip(const String& windingRuleString)
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after
1215 c->drawRect(rect, clearPaint); 1154 c->drawRect(rect, clearPaint);
1216 didDraw(dirtyRect); 1155 didDraw(dirtyRect);
1217 } 1156 }
1218 } 1157 }
1219 1158
1220 if (m_hitRegionManager) { 1159 if (m_hitRegionManager) {
1221 m_hitRegionManager->removeHitRegionsInRect(rect, state().transform()); 1160 m_hitRegionManager->removeHitRegionsInRect(rect, state().transform());
1222 } 1161 }
1223 } 1162 }
1224 1163
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) 1164 static inline FloatRect normalizeRect(const FloatRect& rect)
1240 { 1165 {
1241 return FloatRect(std::min(rect.x(), rect.maxX()), 1166 return FloatRect(std::min(rect.x(), rect.maxX()),
1242 std::min(rect.y(), rect.maxY()), 1167 std::min(rect.y(), rect.maxY()),
1243 std::max(rect.width(), -rect.width()), 1168 std::max(rect.width(), -rect.width()),
1244 std::max(rect.height(), -rect.height())); 1169 std::max(rect.height(), -rect.height()));
1245 } 1170 }
1246 1171
1247 static inline void clipRectsToImageRect(const FloatRect& imageRect, FloatRect* s rcRect, FloatRect* dstRect) 1172 static inline void clipRectsToImageRect(const FloatRect& imageRect, FloatRect* s rcRect, FloatRect* dstRect)
1248 { 1173 {
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
1294 } 1219 }
1295 1220
1296 void CanvasRenderingContext2D::drawImage(const CanvasImageSourceUnion& imageSour ce, 1221 void CanvasRenderingContext2D::drawImage(const CanvasImageSourceUnion& imageSour ce,
1297 float sx, float sy, float sw, float sh, 1222 float sx, float sy, float sw, float sh,
1298 float dx, float dy, float dw, float dh, ExceptionState& exceptionState) 1223 float dx, float dy, float dw, float dh, ExceptionState& exceptionState)
1299 { 1224 {
1300 CanvasImageSource* imageSourceInternal = toImageSourceInternal(imageSource); 1225 CanvasImageSource* imageSourceInternal = toImageSourceInternal(imageSource);
1301 drawImage(imageSourceInternal, sx, sy, sw, sh, dx, dy, dw, dh, exceptionStat e); 1226 drawImage(imageSourceInternal, sx, sy, sw, sh, dx, dy, dw, dh, exceptionStat e);
1302 } 1227 }
1303 1228
1304 void CanvasRenderingContext2D::drawVideo(CanvasImageSource* imageSource, const F loatRect& srcRect, const FloatRect& dstRect) 1229 void CanvasRenderingContext2D::drawImageInternal(CanvasImageSource* imageSource, Image* image, const FloatRect& srcRect, const FloatRect& dstRect, const SkPaint * paint)
1305 { 1230 {
1306 HTMLVideoElement* video = static_cast<HTMLVideoElement*>(imageSource);
1307 ASSERT(video);
1308 SkCanvas* c = drawingCanvas(); 1231 SkCanvas* c = drawingCanvas();
1309 if (!c) 1232 ASSERT(c);
1310 return;
1311 c->save();
1312 c->clipRect(WebCoreFloatRectToSKRect(dstRect));
1313 c->translate(dstRect.x(), dstRect.y());
1314 c->scale(dstRect.width() / srcRect.width(), dstRect.height() / srcRect.heigh t());
1315 c->translate(-srcRect.x(), -srcRect.y());
1316 video->paintCurrentFrameInContext(drawingContext(), IntRect(IntPoint(), IntS ize(video->videoWidth(), video->videoHeight())));
1317 // In case the paint propagated a queued context loss signal
1318 if (drawingCanvas())
1319 drawingCanvas()->restore();
1320 }
1321 1233
1322 void CanvasRenderingContext2D::drawImageOnContext(CanvasImageSource* imageSource , Image* image, const FloatRect& srcRect, const FloatRect& dstRect, const SkPain t* paint) 1234 int initialSaveCount = c->getSaveCount();
1323 { 1235 SkPaint imagePaint = *paint;
1324 SkXfermode::Mode mode;
1325 if (!SkXfermode::AsMode(paint->getXfermode(), &mode))
1326 mode = SkXfermode::kSrcOver_Mode;
1327 1236
1328 RefPtr<SkImageFilter> imageFilter(paint->getImageFilter()); 1237 if (paint->getImageFilter()) {
1329 drawingContext()->setDropShadowImageFilter(imageFilter.release()); 1238 SkMatrix ctm = c->getTotalMatrix();
1330 RefPtr<SkDrawLooper> drawLooper(paint->getLooper()); 1239 SkMatrix invCtm;
1331 drawingContext()->setDrawLooper(drawLooper.release()); 1240 if (!ctm.invert(&invCtm)) {
1241 ASSERT_NOT_REACHED(); // There is an earlier check for invertibility
1242 }
1243 c->save();
1244 c->concat(invCtm);
1245 SkRect bounds = dstRect;
1246 ctm.mapRect(&bounds);
1247 SkRect filteredBounds;
1248 paint->getImageFilter()->computeFastBounds(bounds, &filteredBounds);
Stephen White 2015/04/17 15:14:56 Nit: I realize this is just moving code from elsew
1249 SkPaint layerPaint;
1250 layerPaint.setXfermode(paint->getXfermode());
1251 layerPaint.setImageFilter(paint->getImageFilter());
1252 c->saveLayer(&filteredBounds, &layerPaint);
Stephen White 2015/04/17 15:14:56 It seems unfortunate to have to call saveLayer() y
1253 c->concat(ctm);
1254 imagePaint.setXfermodeMode(SkXfermode::kSrcOver_Mode);
1255 imagePaint.setImageFilter(nullptr);
1256 }
1332 1257
1333 if (!imageSource->isVideoElement()) { 1258 if (!imageSource->isVideoElement()) {
1334 drawingContext()->drawImage(image, dstRect, srcRect, mode); 1259 // TODO: Find a way to pass SkCanvas::kBleed_DrawBitmapRectFlag
1260 image->draw(c, imagePaint, dstRect, srcRect, DoNotRespectImageOrientatio n);
1335 } else { 1261 } else {
1336 SkXfermode::Mode oldMode = drawingContext()->compositeOperation(); 1262 c->save();
1337 drawingContext()->setCompositeOperation(mode); 1263 c->clipRect(WebCoreFloatRectToSKRect(dstRect));
1338 drawVideo(imageSource, srcRect, dstRect); 1264 c->translate(dstRect.x(), dstRect.y());
1339 // Must re-check drawingContext() in case drawVideo propagated a pending context loss signal 1265 c->scale(dstRect.width() / srcRect.width(), dstRect.height() / srcRect.h eight());
1340 if (drawingContext()) 1266 c->translate(-srcRect.x(), -srcRect.y());
1341 drawingContext()->setCompositeOperation(oldMode); 1267 HTMLVideoElement* video = static_cast<HTMLVideoElement*>(imageSource);
1268 video->paintCurrentFrame(c, IntRect(IntPoint(), IntSize(video->videoWidt h(), video->videoHeight())), &imagePaint);
1342 } 1269 }
1270
1271 c->restoreToCount(initialSaveCount);
1343 } 1272 }
1344 1273
1345 void CanvasRenderingContext2D::drawImage(CanvasImageSource* imageSource, 1274 void CanvasRenderingContext2D::drawImage(CanvasImageSource* imageSource,
1346 float sx, float sy, float sw, float sh, 1275 float sx, float sy, float sw, float sh,
1347 float dx, float dy, float dw, float dh, ExceptionState& exceptionState) 1276 float dx, float dy, float dw, float dh, ExceptionState& exceptionState)
1348 { 1277 {
1349 if (!drawingCanvas()) 1278 if (!drawingCanvas())
1350 return; 1279 return;
1351 1280
1352 RefPtr<Image> image; 1281 RefPtr<Image> image;
(...skipping 29 matching lines...) Expand all
1382 // We make the destination canvas fall out of display list mode by calling 1311 // We make the destination canvas fall out of display list mode by calling
1383 // willAccessPixels. This is to prevent run-away memory consumption caused b y SkSurface 1312 // willAccessPixels. This is to prevent run-away memory consumption caused b y SkSurface
1384 // copyOnWrite when the source canvas is animated and consumed at a rate hig her than the 1313 // copyOnWrite when the source canvas is animated and consumed at a rate hig her than the
1385 // presentation frame rate of the destination canvas. 1314 // presentation frame rate of the destination canvas.
1386 if (imageSource->isCanvasElement()) 1315 if (imageSource->isCanvasElement())
1387 canvas()->buffer()->willAccessPixels(); 1316 canvas()->buffer()->willAccessPixels();
1388 1317
1389 draw( 1318 draw(
1390 [this, &imageSource, &image, &srcRect, dstRect](const SkPaint* paint) // draw lambda 1319 [this, &imageSource, &image, &srcRect, dstRect](const SkPaint* paint) // draw lambda
1391 { 1320 {
1392 if (drawingCanvas()) 1321 drawImageInternal(imageSource, image.get(), srcRect, dstRect, paint) ;
1393 drawImageOnContext(imageSource, image.get(), srcRect, dstRect, p aint);
1394 }, 1322 },
1395 [this, &dstRect](const SkIRect& clipBounds) // overdraw test lambda 1323 [this, &dstRect](const SkIRect& clipBounds) // overdraw test lambda
1396 { 1324 {
1397 return rectContainsTransformedRect(dstRect, clipBounds); 1325 return rectContainsTransformedRect(dstRect, clipBounds);
1398 }, 1326 },
1399 dstRect, 1327 dstRect,
1400 CanvasRenderingContext2DState::FillPaintType, 1328 CanvasRenderingContext2DState::ImagePaintType,
1401 imageSource->isOpaque() ? CanvasRenderingContext2DState::OpaqueImage : C anvasRenderingContext2DState::NonOpaqueImage); 1329 imageSource->isOpaque() ? CanvasRenderingContext2DState::OpaqueImage : C anvasRenderingContext2DState::NonOpaqueImage);
1402 1330
1403 validateStateStack(); 1331 validateStateStack();
1404 1332
1405 if (ExpensiveCanvasHeuristicParameters::SVGImageSourcesAreExpensive && image && image->isSVGImage()) { 1333 if (ExpensiveCanvasHeuristicParameters::SVGImageSourcesAreExpensive && image && image->isSVGImage()) {
1406 ImageBuffer* buffer = canvas()->buffer(); 1334 ImageBuffer* buffer = canvas()->buffer();
1407 if (buffer) 1335 if (buffer)
1408 buffer->setHasExpensiveOp(); 1336 buffer->setHasExpensiveOp();
1409 } 1337 }
1410 1338
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after
1528 canvas()->didDraw(SkRect::Make(dirtyRect)); 1456 canvas()->didDraw(SkRect::Make(dirtyRect));
1529 } 1457 }
1530 1458
1531 SkCanvas* CanvasRenderingContext2D::drawingCanvas() const 1459 SkCanvas* CanvasRenderingContext2D::drawingCanvas() const
1532 { 1460 {
1533 if (isContextLost()) 1461 if (isContextLost())
1534 return nullptr; 1462 return nullptr;
1535 return canvas()->drawingCanvas(); 1463 return canvas()->drawingCanvas();
1536 } 1464 }
1537 1465
1538 GraphicsContext* CanvasRenderingContext2D::drawingContext() const
1539 {
1540 if (isContextLost())
1541 return nullptr;
1542 return canvas()->drawingContext();
1543 }
1544
1545 PassRefPtrWillBeRawPtr<ImageData> CanvasRenderingContext2D::createImageData(Pass RefPtrWillBeRawPtr<ImageData> imageData) const 1466 PassRefPtrWillBeRawPtr<ImageData> CanvasRenderingContext2D::createImageData(Pass RefPtrWillBeRawPtr<ImageData> imageData) const
1546 { 1467 {
1547 return ImageData::create(imageData->size()); 1468 return ImageData::create(imageData->size());
1548 } 1469 }
1549 1470
1550 PassRefPtrWillBeRawPtr<ImageData> CanvasRenderingContext2D::createImageData(floa t sw, float sh, ExceptionState& exceptionState) const 1471 PassRefPtrWillBeRawPtr<ImageData> CanvasRenderingContext2D::createImageData(floa t sw, float sh, ExceptionState& exceptionState) const
1551 { 1472 {
1552 if (!sw || !sh) { 1473 if (!sw || !sh) {
1553 exceptionState.throwDOMException(IndexSizeError, String::format("The sou rce %s is 0.", sw ? "height" : "width")); 1474 exceptionState.throwDOMException(IndexSizeError, String::format("The sou rce %s is 0.", sw ? "height" : "width"));
1554 return nullptr; 1475 return nullptr;
(...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after
1712 1633
1713 String fontValue = parsedStyle->getPropertyValue(CSSPropertyFont); 1634 String fontValue = parsedStyle->getPropertyValue(CSSPropertyFont);
1714 1635
1715 // According to http://lists.w3.org/Archives/Public/public-html/2009Jul/0947 .html, 1636 // According to http://lists.w3.org/Archives/Public/public-html/2009Jul/0947 .html,
1716 // the "inherit" and "initial" values must be ignored. 1637 // the "inherit" and "initial" values must be ignored.
1717 if (fontValue == "inherit" || fontValue == "initial") 1638 if (fontValue == "inherit" || fontValue == "initial")
1718 return; 1639 return;
1719 1640
1720 // The parse succeeded. 1641 // The parse succeeded.
1721 String newFontSafeCopy(newFont); // Create a string copy since newFont can b e deleted inside realizeSaves. 1642 String newFontSafeCopy(newFont); // Create a string copy since newFont can b e deleted inside realizeSaves.
1722 realizeSaves(nullptr);
1723 modifiableState().setUnparsedFont(newFontSafeCopy); 1643 modifiableState().setUnparsedFont(newFontSafeCopy);
1724 1644
1725 // Map the <canvas> font into the text style. If the font uses keywords like larger/smaller, these will work 1645 // Map the <canvas> font into the text style. If the font uses keywords like larger/smaller, these will work
1726 // relative to the canvas. 1646 // relative to the canvas.
1727 RefPtr<ComputedStyle> newStyle = ComputedStyle::create(); 1647 RefPtr<ComputedStyle> newStyle = ComputedStyle::create();
1728 canvas()->document().updateRenderTreeIfNeeded(); 1648 canvas()->document().updateRenderTreeIfNeeded();
1729 if (const ComputedStyle* computedStyle = canvas()->ensureComputedStyle()) { 1649 if (const ComputedStyle* computedStyle = canvas()->ensureComputedStyle()) {
1730 FontDescription elementFontDescription(computedStyle->fontDescription()) ; 1650 FontDescription elementFontDescription(computedStyle->fontDescription()) ;
1731 // Reset the computed size to avoid inheriting the zoom factor from the <canvas> element. 1651 // Reset the computed size to avoid inheriting the zoom factor from the <canvas> element.
1732 elementFontDescription.setComputedSize(elementFontDescription.specifiedS ize()); 1652 elementFontDescription.setComputedSize(elementFontDescription.specifiedS ize());
(...skipping 22 matching lines...) Expand all
1755 return textAlignName(state().textAlign()); 1675 return textAlignName(state().textAlign());
1756 } 1676 }
1757 1677
1758 void CanvasRenderingContext2D::setTextAlign(const String& s) 1678 void CanvasRenderingContext2D::setTextAlign(const String& s)
1759 { 1679 {
1760 TextAlign align; 1680 TextAlign align;
1761 if (!parseTextAlign(s, align)) 1681 if (!parseTextAlign(s, align))
1762 return; 1682 return;
1763 if (state().textAlign() == align) 1683 if (state().textAlign() == align)
1764 return; 1684 return;
1765 realizeSaves(nullptr);
1766 modifiableState().setTextAlign(align); 1685 modifiableState().setTextAlign(align);
1767 } 1686 }
1768 1687
1769 String CanvasRenderingContext2D::textBaseline() const 1688 String CanvasRenderingContext2D::textBaseline() const
1770 { 1689 {
1771 return textBaselineName(state().textBaseline()); 1690 return textBaselineName(state().textBaseline());
1772 } 1691 }
1773 1692
1774 void CanvasRenderingContext2D::setTextBaseline(const String& s) 1693 void CanvasRenderingContext2D::setTextBaseline(const String& s)
1775 { 1694 {
1776 TextBaseline baseline; 1695 TextBaseline baseline;
1777 if (!parseTextBaseline(s, baseline)) 1696 if (!parseTextBaseline(s, baseline))
1778 return; 1697 return;
1779 if (state().textBaseline() == baseline) 1698 if (state().textBaseline() == baseline)
1780 return; 1699 return;
1781 realizeSaves(nullptr);
1782 modifiableState().setTextBaseline(baseline); 1700 modifiableState().setTextBaseline(baseline);
1783 } 1701 }
1784 1702
1785 static inline TextDirection toTextDirection(CanvasRenderingContext2DState::Direc tion direction, HTMLCanvasElement* canvas, const ComputedStyle** computedStyle = 0) 1703 static inline TextDirection toTextDirection(CanvasRenderingContext2DState::Direc tion direction, HTMLCanvasElement* canvas, const ComputedStyle** computedStyle = 0)
1786 { 1704 {
1787 const ComputedStyle* style = (computedStyle || direction == CanvasRenderingC ontext2DState::DirectionInherit) ? canvas->ensureComputedStyle() : nullptr; 1705 const ComputedStyle* style = (computedStyle || direction == CanvasRenderingC ontext2DState::DirectionInherit) ? canvas->ensureComputedStyle() : nullptr;
1788 if (computedStyle) 1706 if (computedStyle)
1789 *computedStyle = style; 1707 *computedStyle = style;
1790 switch (direction) { 1708 switch (direction) {
1791 case CanvasRenderingContext2DState::DirectionInherit: 1709 case CanvasRenderingContext2DState::DirectionInherit:
(...skipping 22 matching lines...) Expand all
1814 else if (directionString == rtl) 1732 else if (directionString == rtl)
1815 direction = CanvasRenderingContext2DState::DirectionRTL; 1733 direction = CanvasRenderingContext2DState::DirectionRTL;
1816 else if (directionString == ltr) 1734 else if (directionString == ltr)
1817 direction = CanvasRenderingContext2DState::DirectionLTR; 1735 direction = CanvasRenderingContext2DState::DirectionLTR;
1818 else 1736 else
1819 return; 1737 return;
1820 1738
1821 if (state().direction() == direction) 1739 if (state().direction() == direction)
1822 return; 1740 return;
1823 1741
1824 realizeSaves(nullptr);
1825 modifiableState().setDirection(direction); 1742 modifiableState().setDirection(direction);
1826 } 1743 }
1827 1744
1828 void CanvasRenderingContext2D::fillText(const String& text, float x, float y) 1745 void CanvasRenderingContext2D::fillText(const String& text, float x, float y)
1829 { 1746 {
1830 drawTextInternal(text, x, y, CanvasRenderingContext2DState::FillPaintType); 1747 drawTextInternal(text, x, y, CanvasRenderingContext2DState::FillPaintType);
1831 } 1748 }
1832 1749
1833 void CanvasRenderingContext2D::fillText(const String& text, float x, float y, fl oat maxWidth) 1750 void CanvasRenderingContext2D::fillText(const String& text, float x, float y, fl oat maxWidth)
1834 { 1751 {
(...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after
1988 if (state().lineJoin() == MiterJoin) 1905 if (state().lineJoin() == MiterJoin)
1989 delta *= state().miterLimit(); 1906 delta *= state().miterLimit();
1990 else if (state().lineCap() == SquareCap) 1907 else if (state().lineCap() == SquareCap)
1991 delta *= root2; 1908 delta *= root2;
1992 1909
1993 rect.inflate(delta); 1910 rect.inflate(delta);
1994 } 1911 }
1995 1912
1996 const Font& CanvasRenderingContext2D::accessFont() 1913 const Font& CanvasRenderingContext2D::accessFont()
1997 { 1914 {
1998 // This needs style to be up to date, but can't assert so because drawTextIn ternal
1999 // can invalidate style before this is called (e.g. drawingContext invalidat es style).
2000 if (!state().hasRealizedFont()) 1915 if (!state().hasRealizedFont())
2001 setFont(state().unparsedFont()); 1916 setFont(state().unparsedFont());
2002 return state().font(); 1917 return state().font();
2003 } 1918 }
2004 1919
2005 int CanvasRenderingContext2D::getFontBaseline(const FontMetrics& fontMetrics) co nst 1920 int CanvasRenderingContext2D::getFontBaseline(const FontMetrics& fontMetrics) co nst
2006 { 1921 {
2007 switch (state().textBaseline()) { 1922 switch (state().textBaseline()) {
2008 case TopTextBaseline: 1923 case TopTextBaseline:
2009 return fontMetrics.ascent(); 1924 return fontMetrics.ascent();
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
2043 bool CanvasRenderingContext2D::imageSmoothingEnabled() const 1958 bool CanvasRenderingContext2D::imageSmoothingEnabled() const
2044 { 1959 {
2045 return state().imageSmoothingEnabled(); 1960 return state().imageSmoothingEnabled();
2046 } 1961 }
2047 1962
2048 void CanvasRenderingContext2D::setImageSmoothingEnabled(bool enabled) 1963 void CanvasRenderingContext2D::setImageSmoothingEnabled(bool enabled)
2049 { 1964 {
2050 if (enabled == state().imageSmoothingEnabled()) 1965 if (enabled == state().imageSmoothingEnabled())
2051 return; 1966 return;
2052 1967
2053 SkCanvas* c = drawingCanvas();
2054 realizeSaves(c);
2055 modifiableState().setImageSmoothingEnabled(enabled); 1968 modifiableState().setImageSmoothingEnabled(enabled);
2056 if (c)
2057 drawingContext()->setImageInterpolationQuality(enabled ? CanvasDefaultIn terpolationQuality : InterpolationNone);
2058 } 1969 }
2059 1970
2060 void CanvasRenderingContext2D::getContextAttributes(Canvas2DContextAttributes& a ttrs) const 1971 void CanvasRenderingContext2D::getContextAttributes(Canvas2DContextAttributes& a ttrs) const
2061 { 1972 {
2062 attrs.setAlpha(m_hasAlpha); 1973 attrs.setAlpha(m_hasAlpha);
2063 } 1974 }
2064 1975
2065 void CanvasRenderingContext2D::drawFocusIfNeeded(Element* element) 1976 void CanvasRenderingContext2D::drawFocusIfNeeded(Element* element)
2066 { 1977 {
2067 drawFocusIfNeededInternal(m_path, element); 1978 drawFocusIfNeededInternal(m_path, element);
(...skipping 29 matching lines...) Expand all
2097 if (path.isEmpty()) 2008 if (path.isEmpty())
2098 return false; 2009 return false;
2099 if (!element->isDescendantOf(canvas())) 2010 if (!element->isDescendantOf(canvas()))
2100 return false; 2011 return false;
2101 2012
2102 return true; 2013 return true;
2103 } 2014 }
2104 2015
2105 void CanvasRenderingContext2D::drawFocusRing(const Path& path) 2016 void CanvasRenderingContext2D::drawFocusRing(const Path& path)
2106 { 2017 {
2107 GraphicsContext* c = drawingContext(); 2018 if (!drawingCanvas())
2108 if (!c)
2109 return; 2019 return;
2110 2020
2111 // These should match the style defined in html.css. 2021 // These should match the style defined in html.css.
2112 Color focusRingColor = LayoutTheme::theme().focusRingColor(); 2022 Color focusRingColor = LayoutTheme::theme().focusRingColor();
2113 const int focusRingWidth = 5; 2023 const int focusRingWidth = 5;
2114 const int focusRingOutline = 0;
2115 2024
2116 // We need to add focusRingWidth to dirtyRect. 2025 // We need to add focusRingWidth to dirtyRect.
2117 StrokeData strokeData; 2026 StrokeData strokeData;
2118 strokeData.setThickness(focusRingWidth); 2027 strokeData.setThickness(focusRingWidth);
2119 2028
2120 SkIRect dirtyRect; 2029 SkIRect dirtyRect;
2121 if (!computeDirtyRect(path.strokeBoundingRect(strokeData), &dirtyRect)) 2030 if (!computeDirtyRect(path.strokeBoundingRect(strokeData), &dirtyRect))
2122 return; 2031 return;
2123 2032
2124 c->setAlphaAsFloat(1.0); 2033 SkPaint paint;
2125 c->clearShadow(); 2034 paint.setAntiAlias(true);
2126 c->setCompositeOperation(SkXfermode::kSrcOver_Mode); 2035 paint.setStyle(SkPaint::kStroke_Style);
2127 c->drawFocusRing(path, focusRingWidth, focusRingOutline, focusRingColor); 2036 paint.setColor(focusRingColor.rgb());
2128 c->setAlphaAsFloat(state().globalAlpha()); 2037 paint.setStrokeWidth(focusRingWidth);
2129 c->setCompositeOperation(state().globalComposite());
2130 2038
2131 validateStateStack(); 2039 #if OS(MACOSX)
Stephen White 2015/04/17 15:14:56 Nit: I wonder if we should keep this stuff in plat
2040 paint.setAlpha(64);
2041 float cornerRadius = (focusRingWidth - 1) * 0.5f;
2042 #else
2043 const float cornerRadius = 1;
2044 #endif
2045
2046 paint.setPathEffect(SkCornerPathEffect::Create(SkFloatToScalar(cornerRadius) ))->unref();
2047
2048 // Outer path
2049 drawingCanvas()->drawPath(path.skPath(), paint);
2050
2051 #if OS(MACOSX)
2052 // Inner path
2053 paint.setAlpha(128);
2054 paint.setStrokeWidth(paint.getStrokeWidth() * 0.5f);
2055 drawingCanvas()->drawPath(path.skPath(), paint);
2056 #endif
2057
2132 didDraw(dirtyRect); 2058 didDraw(dirtyRect);
2133 } 2059 }
2134 2060
2135 void CanvasRenderingContext2D::updateFocusRingElementAccessibility(const Path& p ath, Element* element) 2061 void CanvasRenderingContext2D::updateFocusRingElementAccessibility(const Path& p ath, Element* element)
2136 { 2062 {
2137 AXObjectCache* axObjectCache = element->document().existingAXObjectCache(); 2063 AXObjectCache* axObjectCache = element->document().existingAXObjectCache();
2138 LayoutBoxModelObject* lbmo = canvas()->layoutBoxModelObject(); 2064 LayoutBoxModelObject* lbmo = canvas()->layoutBoxModelObject();
2139 LayoutObject* renderer = canvas()->layoutObject(); 2065 LayoutObject* renderer = canvas()->layoutObject();
2140 if (!axObjectCache || !lbmo || !renderer) 2066 if (!axObjectCache || !lbmo || !renderer)
2141 return; 2067 return;
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after
2280 if (imageType == CanvasRenderingContext2DState::NonOpaqueImage) 2206 if (imageType == CanvasRenderingContext2DState::NonOpaqueImage)
2281 return; 2207 return;
2282 if (alpha < 0xFF) 2208 if (alpha < 0xFF)
2283 return; 2209 return;
2284 } 2210 }
2285 2211
2286 canvas()->buffer()->willOverwriteCanvas(); 2212 canvas()->buffer()->willOverwriteCanvas();
2287 } 2213 }
2288 2214
2289 } // namespace blink 2215 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698