| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2003, 2004, 2005, 2006, 2009 Apple Inc. All rights reserved. | 2 * Copyright (C) 2003, 2004, 2005, 2006, 2009 Apple Inc. All rights reserved. |
| 3 * Copyright (C) 2013 Google Inc. All rights reserved. | 3 * Copyright (C) 2013 Google Inc. All rights reserved. |
| 4 * | 4 * |
| 5 * Redistribution and use in source and binary forms, with or without | 5 * Redistribution and use in source and binary forms, with or without |
| 6 * modification, are permitted provided that the following conditions | 6 * modification, are permitted provided that the following conditions |
| 7 * are met: | 7 * are met: |
| 8 * 1. Redistributions of source code must retain the above copyright | 8 * 1. Redistributions of source code must retain the above copyright |
| 9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
| 10 * 2. Redistributions in binary form must reproduce the above copyright | 10 * 2. Redistributions in binary form must reproduce the above copyright |
| (...skipping 23 matching lines...) Expand all Loading... |
| 34 #include "platform/graphics/Gradient.h" | 34 #include "platform/graphics/Gradient.h" |
| 35 #include "platform/graphics/ImageBuffer.h" | 35 #include "platform/graphics/ImageBuffer.h" |
| 36 #include "platform/weborigin/KURL.h" | 36 #include "platform/weborigin/KURL.h" |
| 37 #include "third_party/skia/include/core/SkAnnotation.h" | 37 #include "third_party/skia/include/core/SkAnnotation.h" |
| 38 #include "third_party/skia/include/core/SkColorFilter.h" | 38 #include "third_party/skia/include/core/SkColorFilter.h" |
| 39 #include "third_party/skia/include/core/SkData.h" | 39 #include "third_party/skia/include/core/SkData.h" |
| 40 #include "third_party/skia/include/core/SkPicture.h" | 40 #include "third_party/skia/include/core/SkPicture.h" |
| 41 #include "third_party/skia/include/core/SkPictureRecorder.h" | 41 #include "third_party/skia/include/core/SkPictureRecorder.h" |
| 42 #include "third_party/skia/include/core/SkRRect.h" | 42 #include "third_party/skia/include/core/SkRRect.h" |
| 43 #include "third_party/skia/include/core/SkRefCnt.h" | 43 #include "third_party/skia/include/core/SkRefCnt.h" |
| 44 #include "third_party/skia/include/effects/SkCornerPathEffect.h" | |
| 45 #include "third_party/skia/include/effects/SkDropShadowImageFilter.h" | |
| 46 #include "third_party/skia/include/effects/SkLumaColorFilter.h" | 44 #include "third_party/skia/include/effects/SkLumaColorFilter.h" |
| 47 #include "third_party/skia/include/effects/SkPictureImageFilter.h" | 45 #include "third_party/skia/include/effects/SkPictureImageFilter.h" |
| 48 #include "third_party/skia/include/utils/SkNullCanvas.h" | 46 #include "third_party/skia/include/utils/SkNullCanvas.h" |
| 49 #include "wtf/Assertions.h" | 47 #include "wtf/Assertions.h" |
| 50 #include "wtf/MathExtras.h" | 48 #include "wtf/MathExtras.h" |
| 51 | 49 |
| 52 namespace blink { | 50 namespace blink { |
| 53 | 51 |
| 54 class GraphicsContext::RecordingState { | 52 class GraphicsContext::RecordingState { |
| 55 WTF_MAKE_FAST_ALLOCATED(GraphicsContext::RecordingState); | 53 WTF_MAKE_FAST_ALLOCATED(GraphicsContext::RecordingState); |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 97 , m_paintStateIndex(0) | 95 , m_paintStateIndex(0) |
| 98 #if ENABLE(ASSERT) | 96 #if ENABLE(ASSERT) |
| 99 , m_layerCount(0) | 97 , m_layerCount(0) |
| 100 , m_disableDestructionChecks(false) | 98 , m_disableDestructionChecks(false) |
| 101 , m_inDrawingRecorder(false) | 99 , m_inDrawingRecorder(false) |
| 102 #endif | 100 #endif |
| 103 , m_disabledState(disableContextOrPainting) | 101 , m_disabledState(disableContextOrPainting) |
| 104 , m_deviceScaleFactor(1.0f) | 102 , m_deviceScaleFactor(1.0f) |
| 105 , m_accelerated(false) | 103 , m_accelerated(false) |
| 106 , m_printing(false) | 104 , m_printing(false) |
| 107 , m_antialiasHairlineImages(false) | |
| 108 { | 105 { |
| 109 // FIXME: Do some tests to determine how many states are typically used, and
allocate | 106 // FIXME: Do some tests to determine how many states are typically used, and
allocate |
| 110 // several here. | 107 // several here. |
| 111 m_paintStateStack.append(GraphicsContextState::create()); | 108 m_paintStateStack.append(GraphicsContextState::create()); |
| 112 m_paintState = m_paintStateStack.last().get(); | 109 m_paintState = m_paintStateStack.last().get(); |
| 113 | 110 |
| 114 if (contextDisabled()) { | 111 if (contextDisabled()) { |
| 115 DEFINE_STATIC_LOCAL(RefPtr<SkCanvas>, nullCanvas, (adoptRef(SkCreateNull
Canvas()))); | 112 DEFINE_STATIC_LOCAL(RefPtr<SkCanvas>, nullCanvas, (adoptRef(SkCreateNull
Canvas()))); |
| 116 m_canvas = nullCanvas.get(); | 113 m_canvas = nullCanvas.get(); |
| 117 } | 114 } |
| (...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 272 if (contextDisabled()) | 269 if (contextDisabled()) |
| 273 return; | 270 return; |
| 274 | 271 |
| 275 OwnPtr<DrawLooperBuilder> drawLooperBuilder = DrawLooperBuilder::create(); | 272 OwnPtr<DrawLooperBuilder> drawLooperBuilder = DrawLooperBuilder::create(); |
| 276 if (!color.alpha()) { | 273 if (!color.alpha()) { |
| 277 if (shadowMode == DrawShadowOnly) { | 274 if (shadowMode == DrawShadowOnly) { |
| 278 // shadow only, but there is no shadow: use an empty draw looper to
disable rendering of the source primitive | 275 // shadow only, but there is no shadow: use an empty draw looper to
disable rendering of the source primitive |
| 279 setDrawLooper(drawLooperBuilder.release()); | 276 setDrawLooper(drawLooperBuilder.release()); |
| 280 return; | 277 return; |
| 281 } | 278 } |
| 282 clearShadow(); | 279 clearDrawLooper(); |
| 283 return; | 280 return; |
| 284 } | 281 } |
| 285 | 282 |
| 286 drawLooperBuilder->addShadow(offset, blur, color, shadowTransformMode, shado
wAlphaMode); | 283 drawLooperBuilder->addShadow(offset, blur, color, shadowTransformMode, shado
wAlphaMode); |
| 287 if (shadowMode == DrawShadowAndForeground) { | 284 if (shadowMode == DrawShadowAndForeground) { |
| 288 drawLooperBuilder->addUnmodifiedContent(); | 285 drawLooperBuilder->addUnmodifiedContent(); |
| 289 } | 286 } |
| 290 setDrawLooper(drawLooperBuilder.release()); | 287 setDrawLooper(drawLooperBuilder.release()); |
| 291 | |
| 292 if (shadowTransformMode == DrawLooperBuilder::ShadowIgnoresTransforms | |
| 293 && shadowAlphaMode == DrawLooperBuilder::ShadowRespectsAlpha) { | |
| 294 // This image filter will be used in place of the drawLooper created abo
ve but only for drawing non-opaque bitmaps; | |
| 295 // see preparePaintForDrawRectToRect(). | |
| 296 SkColor skColor = color.rgb(); | |
| 297 // These constants are from RadiusToSigma() from DrawLooperBuilder.cpp. | |
| 298 const SkScalar sigma = 0.288675f * blur + 0.5f; | |
| 299 SkDropShadowImageFilter::ShadowMode dropShadowMode = shadowMode == DrawS
hadowAndForeground ? SkDropShadowImageFilter::kDrawShadowAndForeground_ShadowMod
e : SkDropShadowImageFilter::kDrawShadowOnly_ShadowMode; | |
| 300 RefPtr<SkImageFilter> filter = adoptRef(SkDropShadowImageFilter::Create(
offset.width(), offset.height(), sigma, sigma, skColor, dropShadowMode)); | |
| 301 setDropShadowImageFilter(filter); | |
| 302 } | |
| 303 } | 288 } |
| 304 | 289 |
| 305 void GraphicsContext::setDrawLooper(PassOwnPtr<DrawLooperBuilder> drawLooperBuil
der) | 290 void GraphicsContext::setDrawLooper(PassOwnPtr<DrawLooperBuilder> drawLooperBuil
der) |
| 306 { | 291 { |
| 307 if (contextDisabled()) | 292 if (contextDisabled()) |
| 308 return; | 293 return; |
| 309 | 294 |
| 310 mutableState()->setDrawLooper(drawLooperBuilder->detachDrawLooper()); | 295 mutableState()->setDrawLooper(drawLooperBuilder->detachDrawLooper()); |
| 311 } | 296 } |
| 312 | 297 |
| 313 void GraphicsContext::clearDrawLooper() | 298 void GraphicsContext::clearDrawLooper() |
| 314 { | 299 { |
| 315 if (contextDisabled()) | 300 if (contextDisabled()) |
| 316 return; | 301 return; |
| 317 | 302 |
| 318 mutableState()->clearDrawLooper(); | 303 mutableState()->clearDrawLooper(); |
| 319 } | 304 } |
| 320 | 305 |
| 321 void GraphicsContext::setDropShadowImageFilter(PassRefPtr<SkImageFilter> imageFi
lter) | |
| 322 { | |
| 323 if (contextDisabled()) | |
| 324 return; | |
| 325 | |
| 326 mutableState()->setDropShadowImageFilter(imageFilter); | |
| 327 } | |
| 328 | |
| 329 void GraphicsContext::clearDropShadowImageFilter() | |
| 330 { | |
| 331 if (contextDisabled()) | |
| 332 return; | |
| 333 | |
| 334 mutableState()->clearDropShadowImageFilter(); | |
| 335 } | |
| 336 | |
| 337 SkMatrix GraphicsContext::getTotalMatrix() const | 306 SkMatrix GraphicsContext::getTotalMatrix() const |
| 338 { | 307 { |
| 339 // FIXME: this is a hack to avoid changing all call sites of getTotalMatrix(
) to not use this method. | 308 // FIXME: this is a hack to avoid changing all call sites of getTotalMatrix(
) to not use this method. |
| 340 // The code needs to be cleand up after Slimming Paint is launched. | 309 // The code needs to be cleand up after Slimming Paint is launched. |
| 341 if (RuntimeEnabledFeatures::slimmingPaintEnabled()) | 310 if (RuntimeEnabledFeatures::slimmingPaintEnabled()) |
| 342 return SkMatrix::I(); | 311 return SkMatrix::I(); |
| 343 | 312 |
| 344 if (contextDisabled() || !m_canvas) | 313 if (contextDisabled() || !m_canvas) |
| 345 return SkMatrix::I(); | 314 return SkMatrix::I(); |
| 346 | 315 |
| 347 ASSERT(m_canvas); | 316 ASSERT(m_canvas); |
| 348 | 317 |
| 349 if (!isRecording()) | 318 if (!isRecording()) |
| 350 return m_canvas->getTotalMatrix(); | 319 return m_canvas->getTotalMatrix(); |
| 351 | 320 |
| 352 SkMatrix totalMatrix = m_recordingStateStack.last()->matrix(); | 321 SkMatrix totalMatrix = m_recordingStateStack.last()->matrix(); |
| 353 totalMatrix.preConcat(m_canvas->getTotalMatrix()); | 322 totalMatrix.preConcat(m_canvas->getTotalMatrix()); |
| 354 | 323 |
| 355 return totalMatrix; | 324 return totalMatrix; |
| 356 } | 325 } |
| 357 | 326 |
| 358 void GraphicsContext::setCompositeOperation(SkXfermode::Mode xferMode) | |
| 359 { | |
| 360 if (contextDisabled()) | |
| 361 return; | |
| 362 mutableState()->setCompositeOperation(xferMode); | |
| 363 } | |
| 364 | |
| 365 SkXfermode::Mode GraphicsContext::compositeOperation() const | |
| 366 { | |
| 367 return immutableState()->compositeOperation(); | |
| 368 } | |
| 369 | |
| 370 SkColorFilter* GraphicsContext::colorFilter() const | 327 SkColorFilter* GraphicsContext::colorFilter() const |
| 371 { | 328 { |
| 372 return immutableState()->colorFilter(); | 329 return immutableState()->colorFilter(); |
| 373 } | 330 } |
| 374 | 331 |
| 375 void GraphicsContext::setColorFilter(ColorFilter colorFilter) | 332 void GraphicsContext::setColorFilter(ColorFilter colorFilter) |
| 376 { | 333 { |
| 377 GraphicsContextState* stateToSet = mutableState(); | 334 GraphicsContextState* stateToSet = mutableState(); |
| 378 | 335 |
| 379 // We only support one active color filter at the moment. If (when) this bec
omes a problem, | 336 // We only support one active color filter at the moment. If (when) this bec
omes a problem, |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 413 SkPaint layerPaint; | 370 SkPaint layerPaint; |
| 414 layerPaint.setAlpha(static_cast<unsigned char>(opacity * 255)); | 371 layerPaint.setAlpha(static_cast<unsigned char>(opacity * 255)); |
| 415 layerPaint.setXfermodeMode(xfermode); | 372 layerPaint.setXfermodeMode(xfermode); |
| 416 layerPaint.setColorFilter(WebCoreColorFilterToSkiaColorFilter(colorFilter).g
et()); | 373 layerPaint.setColorFilter(WebCoreColorFilterToSkiaColorFilter(colorFilter).g
et()); |
| 417 layerPaint.setImageFilter(imageFilter); | 374 layerPaint.setImageFilter(imageFilter); |
| 418 | 375 |
| 419 if (bounds) { | 376 if (bounds) { |
| 420 SkRect skBounds = WebCoreFloatRectToSKRect(*bounds); | 377 SkRect skBounds = WebCoreFloatRectToSKRect(*bounds); |
| 421 saveLayer(&skBounds, &layerPaint); | 378 saveLayer(&skBounds, &layerPaint); |
| 422 } else { | 379 } else { |
| 423 saveLayer(0, &layerPaint); | 380 saveLayer(nullptr, &layerPaint); |
| 424 } | 381 } |
| 425 | 382 |
| 426 #if ENABLE(ASSERT) | 383 #if ENABLE(ASSERT) |
| 427 ++m_layerCount; | 384 ++m_layerCount; |
| 428 #endif | 385 #endif |
| 429 } | 386 } |
| 430 | 387 |
| 431 void GraphicsContext::endLayer() | 388 void GraphicsContext::endLayer() |
| 432 { | 389 { |
| 433 if (contextDisabled()) | 390 if (contextDisabled()) |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 525 SkPath path; | 482 SkPath path; |
| 526 setPathFromPoints(&path, numPoints, points); | 483 setPathFromPoints(&path, numPoints, points); |
| 527 | 484 |
| 528 SkPaint paint(immutableState()->fillPaint()); | 485 SkPaint paint(immutableState()->fillPaint()); |
| 529 paint.setAntiAlias(shouldAntialias); | 486 paint.setAntiAlias(shouldAntialias); |
| 530 paint.setColor(color.rgb()); | 487 paint.setColor(color.rgb()); |
| 531 | 488 |
| 532 drawPath(path, paint); | 489 drawPath(path, paint); |
| 533 } | 490 } |
| 534 | 491 |
| 535 float GraphicsContext::prepareFocusRingPaint(SkPaint& paint, const Color& color,
int width) const | |
| 536 { | |
| 537 paint.setAntiAlias(true); | |
| 538 paint.setStyle(SkPaint::kStroke_Style); | |
| 539 paint.setColor(color.rgb()); | |
| 540 paint.setStrokeWidth(focusRingWidth(width)); | |
| 541 | |
| 542 #if OS(MACOSX) | |
| 543 paint.setAlpha(64); | |
| 544 return (width - 1) * 0.5f; | |
| 545 #else | |
| 546 return 1; | |
| 547 #endif | |
| 548 } | |
| 549 | |
| 550 void GraphicsContext::drawFocusRingPath(const SkPath& path, const Color& color,
int width) | 492 void GraphicsContext::drawFocusRingPath(const SkPath& path, const Color& color,
int width) |
| 551 { | 493 { |
| 552 SkPaint paint; | 494 drawPlatformFocusRing(path, m_canvas, color.rgb(), width); |
| 553 float cornerRadius = prepareFocusRingPaint(paint, color, width); | |
| 554 | |
| 555 paint.setPathEffect(SkCornerPathEffect::Create(SkFloatToScalar(cornerRadius)
))->unref(); | |
| 556 | |
| 557 // Outer path | |
| 558 drawPath(path, paint); | |
| 559 | |
| 560 #if OS(MACOSX) | |
| 561 // Inner path | |
| 562 paint.setAlpha(128); | |
| 563 paint.setStrokeWidth(paint.getStrokeWidth() * 0.5f); | |
| 564 drawPath(path, paint); | |
| 565 #endif | |
| 566 } | 495 } |
| 567 | 496 |
| 568 void GraphicsContext::drawFocusRingRect(const SkRect& rect, const Color& color,
int width) | 497 void GraphicsContext::drawFocusRingRect(const SkRect& rect, const Color& color,
int width) |
| 569 { | 498 { |
| 570 SkPaint paint; | 499 drawPlatformFocusRing(rect, m_canvas, color.rgb(), width); |
| 571 float cornerRadius = prepareFocusRingPaint(paint, color, width); | |
| 572 | |
| 573 SkRRect rrect; | |
| 574 rrect.setRectXY(rect, SkFloatToScalar(cornerRadius), SkFloatToScalar(cornerR
adius)); | |
| 575 | |
| 576 // Outer rect | |
| 577 drawRRect(rrect, paint); | |
| 578 | |
| 579 #if OS(MACOSX) | |
| 580 // Inner rect | |
| 581 paint.setAlpha(128); | |
| 582 paint.setStrokeWidth(paint.getStrokeWidth() * 0.5f); | |
| 583 drawRRect(rrect, paint); | |
| 584 #endif | |
| 585 } | 500 } |
| 586 | 501 |
| 587 void GraphicsContext::drawFocusRing(const Path& focusRingPath, int width, int of
fset, const Color& color) | 502 void GraphicsContext::drawFocusRing(const Path& focusRingPath, int width, int of
fset, const Color& color) |
| 588 { | 503 { |
| 589 // FIXME: Implement support for offset. | 504 // FIXME: Implement support for offset. |
| 590 if (contextDisabled()) | 505 if (contextDisabled()) |
| 591 return; | 506 return; |
| 592 | 507 |
| 593 drawFocusRingPath(focusRingPath.skPath(), color, width); | 508 drawFocusRingPath(focusRingPath.skPath(), color, width); |
| 594 } | 509 } |
| (...skipping 284 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 879 int thickness = SkMax32(static_cast<int>(strokeThickness()), 1); | 794 int thickness = SkMax32(static_cast<int>(strokeThickness()), 1); |
| 880 SkRect r; | 795 SkRect r; |
| 881 r.fLeft = WebCoreFloatToSkScalar(pt.x()); | 796 r.fLeft = WebCoreFloatToSkScalar(pt.x()); |
| 882 // Avoid anti-aliasing lines. Currently, these are always horizontal. | 797 // Avoid anti-aliasing lines. Currently, these are always horizontal. |
| 883 // Round to nearest pixel to match text and other content. | 798 // Round to nearest pixel to match text and other content. |
| 884 r.fTop = WebCoreFloatToSkScalar(floorf(pt.y() + 0.5f)); | 799 r.fTop = WebCoreFloatToSkScalar(floorf(pt.y() + 0.5f)); |
| 885 r.fRight = r.fLeft + WebCoreFloatToSkScalar(width); | 800 r.fRight = r.fLeft + WebCoreFloatToSkScalar(width); |
| 886 r.fBottom = r.fTop + SkIntToScalar(thickness); | 801 r.fBottom = r.fTop + SkIntToScalar(thickness); |
| 887 paint = immutableState()->fillPaint(); | 802 paint = immutableState()->fillPaint(); |
| 888 // Text lines are drawn using the stroke color. | 803 // Text lines are drawn using the stroke color. |
| 889 paint.setColor(effectiveStrokeColor()); | 804 paint.setColor(strokeColor().rgb()); |
| 890 drawRect(r, paint); | 805 drawRect(r, paint); |
| 891 return; | 806 return; |
| 892 } | 807 } |
| 893 case DottedStroke: | 808 case DottedStroke: |
| 894 case DashedStroke: { | 809 case DashedStroke: { |
| 895 int y = floorf(pt.y() + std::max<float>(strokeThickness() / 2.0f, 0.5f))
; | 810 int y = floorf(pt.y() + std::max<float>(strokeThickness() / 2.0f, 0.5f))
; |
| 896 drawLine(IntPoint(pt.x(), y), IntPoint(pt.x() + width, y)); | 811 drawLine(IntPoint(pt.x(), y), IntPoint(pt.x() + width, y)); |
| 897 return; | 812 return; |
| 898 } | 813 } |
| 899 } | 814 } |
| (...skipping 13 matching lines...) Expand all Loading... |
| 913 | 828 |
| 914 SkRect skRect = rect; | 829 SkRect skRect = rect; |
| 915 int fillcolorNotTransparent = immutableState()->fillColor().rgb() & 0xFF0000
00; | 830 int fillcolorNotTransparent = immutableState()->fillColor().rgb() & 0xFF0000
00; |
| 916 if (fillcolorNotTransparent) | 831 if (fillcolorNotTransparent) |
| 917 drawRect(skRect, immutableState()->fillPaint()); | 832 drawRect(skRect, immutableState()->fillPaint()); |
| 918 | 833 |
| 919 if (immutableState()->strokeData().style() != NoStroke | 834 if (immutableState()->strokeData().style() != NoStroke |
| 920 && immutableState()->strokeColor().alpha()) { | 835 && immutableState()->strokeColor().alpha()) { |
| 921 // Stroke a width: 1 inset border | 836 // Stroke a width: 1 inset border |
| 922 SkPaint paint(immutableState()->fillPaint()); | 837 SkPaint paint(immutableState()->fillPaint()); |
| 923 paint.setColor(effectiveStrokeColor()); | 838 paint.setColor(strokeColor().rgb()); |
| 924 paint.setStyle(SkPaint::kStroke_Style); | 839 paint.setStyle(SkPaint::kStroke_Style); |
| 925 paint.setStrokeWidth(1); | 840 paint.setStrokeWidth(1); |
| 926 | 841 |
| 927 skRect.inset(0.5f, 0.5f); | 842 skRect.inset(0.5f, 0.5f); |
| 928 drawRect(skRect, paint); | 843 drawRect(skRect, paint); |
| 929 } | 844 } |
| 930 } | 845 } |
| 931 | 846 |
| 932 void GraphicsContext::drawText(const Font& font, const TextRunPaintInfo& runInfo
, const FloatPoint& point, const SkPaint& paint) | 847 void GraphicsContext::drawText(const Font& font, const TextRunPaintInfo& runInfo
, const FloatPoint& point, const SkPaint& paint) |
| 933 { | 848 { |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1004 { | 919 { |
| 1005 if (!image) | 920 if (!image) |
| 1006 return; | 921 return; |
| 1007 drawImage(image, FloatRect(r), FloatRect(FloatPoint(), FloatSize(image->size
())), op, shouldRespectImageOrientation); | 922 drawImage(image, FloatRect(r), FloatRect(FloatPoint(), FloatSize(image->size
())), op, shouldRespectImageOrientation); |
| 1008 } | 923 } |
| 1009 | 924 |
| 1010 void GraphicsContext::drawImage(Image* image, const FloatRect& dest, const Float
Rect& src, SkXfermode::Mode op, RespectImageOrientationEnum shouldRespectImageOr
ientation) | 925 void GraphicsContext::drawImage(Image* image, const FloatRect& dest, const Float
Rect& src, SkXfermode::Mode op, RespectImageOrientationEnum shouldRespectImageOr
ientation) |
| 1011 { | 926 { |
| 1012 if (contextDisabled() || !image) | 927 if (contextDisabled() || !image) |
| 1013 return; | 928 return; |
| 1014 image->draw(this, dest, src, op, shouldRespectImageOrientation); | 929 |
| 930 SkPaint imagePaint = immutableState()->fillPaint(); |
| 931 imagePaint.setXfermodeMode(op); |
| 932 imagePaint.setColor(SK_ColorBLACK); |
| 933 imagePaint.setFilterQuality(computeFilterQuality(image, dest, src)); |
| 934 // Disable anti-aliasing if we're not rotated or skewed. |
| 935 // TODO(junov): crbug.com/492187 This code will disable antialiasing |
| 936 // regardless of whether content is pixel aligned. Is this correct? |
| 937 // For now, just preserving legacy behavior. |
| 938 imagePaint.setAntiAlias(shouldAntialiasImages()); |
| 939 image->draw(m_canvas, imagePaint, dest, src, shouldRespectImageOrientation,
Image::ClampImageToSourceRect); |
| 940 } |
| 941 |
| 942 SkFilterQuality GraphicsContext::computeFilterQuality(Image* image, const FloatR
ect& dest, const FloatRect& src) const |
| 943 { |
| 944 InterpolationQuality resampling; |
| 945 if (printing()) { |
| 946 resampling = InterpolationNone; |
| 947 } else if (image->isLazyDecodedBitmap()) { |
| 948 resampling = InterpolationHigh; |
| 949 } else { |
| 950 // Take into account scale applied to the canvas when computing sampling
mode (e.g. CSS scale or page scale). |
| 951 // FIXME: In slimming paint, we create GCs on the fly when entering a ne
w DisplayItemList |
| 952 // scope, so relying on getTotalMatrix here is not sound. |
| 953 SkRect destRectTarget = dest; |
| 954 SkMatrix totalMatrix = getTotalMatrix(); |
| 955 if (!(totalMatrix.getType() & (SkMatrix::kAffine_Mask | SkMatrix::kPersp
ective_Mask))) |
| 956 totalMatrix.mapRect(&destRectTarget, dest); |
| 957 |
| 958 resampling = computeInterpolationQuality(totalMatrix, |
| 959 SkScalarToFloat(src.width()), SkScalarToFloat(src.height()), |
| 960 SkScalarToFloat(destRectTarget.width()), SkScalarToFloat(destRectTar
get.height()), |
| 961 image->isImmutableBitmap()); |
| 962 } |
| 963 |
| 964 if (resampling == InterpolationNone) { |
| 965 // FIXME: This is to not break tests (it results in the filter bitmap fl
ag |
| 966 // being set to true). We need to decide if we respect InterpolationNone |
| 967 // being returned from computeInterpolationQuality. |
| 968 resampling = InterpolationLow; |
| 969 } |
| 970 return static_cast<SkFilterQuality>(limitInterpolationQuality(this, resampli
ng)); |
| 1015 } | 971 } |
| 1016 | 972 |
| 1017 void GraphicsContext::drawTiledImage(Image* image, const IntRect& destRect, cons
t IntPoint& srcPoint, const IntSize& tileSize, SkXfermode::Mode op, const IntSiz
e& repeatSpacing) | 973 void GraphicsContext::drawTiledImage(Image* image, const IntRect& destRect, cons
t IntPoint& srcPoint, const IntSize& tileSize, SkXfermode::Mode op, const IntSiz
e& repeatSpacing) |
| 1018 { | 974 { |
| 1019 if (contextDisabled() || !image) | 975 if (contextDisabled() || !image) |
| 1020 return; | 976 return; |
| 1021 image->drawTiled(this, destRect, srcPoint, tileSize, op, repeatSpacing); | 977 image->drawTiled(this, destRect, srcPoint, tileSize, op, repeatSpacing); |
| 1022 } | 978 } |
| 1023 | 979 |
| 1024 void GraphicsContext::drawTiledImage(Image* image, const IntRect& dest, const In
tRect& srcRect, | 980 void GraphicsContext::drawTiledImage(Image* image, const IntRect& dest, const In
tRect& srcRect, |
| (...skipping 22 matching lines...) Expand all Loading... |
| 1047 | 1003 |
| 1048 void GraphicsContext::writePixels(const SkImageInfo& info, const void* pixels, s
ize_t rowBytes, int x, int y) | 1004 void GraphicsContext::writePixels(const SkImageInfo& info, const void* pixels, s
ize_t rowBytes, int x, int y) |
| 1049 { | 1005 { |
| 1050 if (contextDisabled()) | 1006 if (contextDisabled()) |
| 1051 return; | 1007 return; |
| 1052 ASSERT(m_canvas); | 1008 ASSERT(m_canvas); |
| 1053 | 1009 |
| 1054 m_canvas->writePixels(info, pixels, rowBytes, x, y); | 1010 m_canvas->writePixels(info, pixels, rowBytes, x, y); |
| 1055 } | 1011 } |
| 1056 | 1012 |
| 1057 void GraphicsContext::drawBitmapRect(const SkBitmap& bitmap, const SkRect* src, | |
| 1058 const SkRect& dst, const SkPaint* paint) | |
| 1059 { | |
| 1060 // Textures are bound to the blink main-thread GrContext, which can not be | |
| 1061 // used on the compositor raster thread. | |
| 1062 // FIXME: Mailbox support would make this possible in the GPU-raster case. | |
| 1063 // If we're printing it is safe to access the texture because we are always | |
| 1064 // on main thread, even if the other conditions are not met. | |
| 1065 ASSERT(!isRecording() || !bitmap.getTexture() || printing()); | |
| 1066 if (contextDisabled()) | |
| 1067 return; | |
| 1068 | |
| 1069 SkCanvas::DrawBitmapRectFlags flags = | |
| 1070 immutableState()->shouldClampToSourceRect() ? SkCanvas::kNone_DrawBitmap
RectFlag : SkCanvas::kBleed_DrawBitmapRectFlag; | |
| 1071 | |
| 1072 ASSERT(m_canvas); | |
| 1073 m_canvas->drawBitmapRectToRect(bitmap, src, dst, paint, flags); | |
| 1074 } | |
| 1075 | |
| 1076 void GraphicsContext::drawOval(const SkRect& oval, const SkPaint& paint) | 1013 void GraphicsContext::drawOval(const SkRect& oval, const SkPaint& paint) |
| 1077 { | 1014 { |
| 1078 if (contextDisabled()) | 1015 if (contextDisabled()) |
| 1079 return; | 1016 return; |
| 1080 ASSERT(m_canvas); | 1017 ASSERT(m_canvas); |
| 1081 | 1018 |
| 1082 m_canvas->drawOval(oval, paint); | 1019 m_canvas->drawOval(oval, paint); |
| 1083 } | 1020 } |
| 1084 | 1021 |
| 1085 void GraphicsContext::drawPath(const SkPath& path, const SkPaint& paint) | 1022 void GraphicsContext::drawPath(const SkPath& path, const SkPaint& paint) |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1132 return; | 1069 return; |
| 1133 | 1070 |
| 1134 drawRect(rect, immutableState()->fillPaint()); | 1071 drawRect(rect, immutableState()->fillPaint()); |
| 1135 } | 1072 } |
| 1136 | 1073 |
| 1137 void GraphicsContext::fillRect(const FloatRect& rect, const Color& color, SkXfer
mode::Mode xferMode) | 1074 void GraphicsContext::fillRect(const FloatRect& rect, const Color& color, SkXfer
mode::Mode xferMode) |
| 1138 { | 1075 { |
| 1139 if (contextDisabled()) | 1076 if (contextDisabled()) |
| 1140 return; | 1077 return; |
| 1141 | 1078 |
| 1142 if (color == fillColor() && xferMode == compositeOperation()) { | |
| 1143 drawRect(rect, immutableState()->fillPaint()); | |
| 1144 return; | |
| 1145 } | |
| 1146 | |
| 1147 SkPaint paint = immutableState()->fillPaint(); | 1079 SkPaint paint = immutableState()->fillPaint(); |
| 1148 paint.setColor(color.rgb()); | 1080 paint.setColor(color.rgb()); |
| 1149 paint.setXfermodeMode(xferMode); | 1081 paint.setXfermodeMode(xferMode); |
| 1150 | 1082 |
| 1151 drawRect(rect, paint); | 1083 drawRect(rect, paint); |
| 1152 } | 1084 } |
| 1153 | 1085 |
| 1154 void GraphicsContext::fillRoundedRect(const FloatRoundedRect& rrect, const Color
& color) | 1086 void GraphicsContext::fillRoundedRect(const FloatRoundedRect& rrect, const Color
& color) |
| 1155 { | 1087 { |
| 1156 if (contextDisabled()) | 1088 if (contextDisabled()) |
| (...skipping 484 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1641 { | 1573 { |
| 1642 static const SkPMColor colors[] = { | 1574 static const SkPMColor colors[] = { |
| 1643 SkPreMultiplyARGB(0x60, 0xFF, 0x00, 0x00), // More transparent red | 1575 SkPreMultiplyARGB(0x60, 0xFF, 0x00, 0x00), // More transparent red |
| 1644 SkPreMultiplyARGB(0x60, 0xC0, 0xC0, 0xC0) // More transparent gray | 1576 SkPreMultiplyARGB(0x60, 0xC0, 0xC0, 0xC0) // More transparent gray |
| 1645 }; | 1577 }; |
| 1646 | 1578 |
| 1647 return colors[index]; | 1579 return colors[index]; |
| 1648 } | 1580 } |
| 1649 #endif | 1581 #endif |
| 1650 | 1582 |
| 1651 int GraphicsContext::preparePaintForDrawRectToRect( | |
| 1652 SkPaint* paint, | |
| 1653 const SkRect& srcRect, | |
| 1654 const SkRect& destRect, | |
| 1655 SkXfermode::Mode compositeOp, | |
| 1656 bool isBitmapWithAlpha, | |
| 1657 bool isLazyDecoded, | |
| 1658 bool isDataComplete) const | |
| 1659 { | |
| 1660 int initialSaveCount = m_canvas->getSaveCount(); | |
| 1661 | |
| 1662 paint->setColorFilter(this->colorFilter()); | |
| 1663 paint->setAlpha(this->getNormalizedAlpha()); | |
| 1664 bool usingImageFilter = false; | |
| 1665 if (dropShadowImageFilter() && isBitmapWithAlpha) { | |
| 1666 SkMatrix ctm = getTotalMatrix(); | |
| 1667 SkMatrix invCtm; | |
| 1668 if (ctm.invert(&invCtm)) { | |
| 1669 usingImageFilter = true; | |
| 1670 // The image filter is meant to ignore tranforms with respect to | |
| 1671 // the shadow parameters. The matrix tweaks below ensures that the i
mage | |
| 1672 // filter is applied in post-transform space. We use concat() instea
d of | |
| 1673 // setMatrix() in case this goes into a recording canvas which may n
eed to | |
| 1674 // respect a parent transform at playback time. | |
| 1675 m_canvas->save(); | |
| 1676 m_canvas->concat(invCtm); | |
| 1677 SkRect bounds = destRect; | |
| 1678 ctm.mapRect(&bounds); | |
| 1679 SkRect filteredBounds; | |
| 1680 dropShadowImageFilter()->computeFastBounds(bounds, &filteredBounds); | |
| 1681 SkPaint layerPaint; | |
| 1682 layerPaint.setXfermodeMode(compositeOp); | |
| 1683 layerPaint.setImageFilter(dropShadowImageFilter()); | |
| 1684 m_canvas->saveLayer(&filteredBounds, &layerPaint); | |
| 1685 m_canvas->concat(ctm); | |
| 1686 } | |
| 1687 } | |
| 1688 | |
| 1689 if (!usingImageFilter) { | |
| 1690 paint->setXfermodeMode(compositeOp); | |
| 1691 paint->setLooper(this->drawLooper()); | |
| 1692 } | |
| 1693 | |
| 1694 paint->setAntiAlias(shouldDrawAntiAliased(this, destRect)); | |
| 1695 | |
| 1696 InterpolationQuality resampling; | |
| 1697 if (this->isAccelerated()) { | |
| 1698 resampling = InterpolationLow; | |
| 1699 } else if (this->printing()) { | |
| 1700 resampling = InterpolationNone; | |
| 1701 } else if (isLazyDecoded) { | |
| 1702 resampling = InterpolationHigh; | |
| 1703 } else { | |
| 1704 // Take into account scale applied to the canvas when computing sampling
mode (e.g. CSS scale or page scale). | |
| 1705 SkRect destRectTarget = destRect; | |
| 1706 SkMatrix totalMatrix = this->getTotalMatrix(); | |
| 1707 if (!(totalMatrix.getType() & (SkMatrix::kAffine_Mask | SkMatrix::kPersp
ective_Mask))) | |
| 1708 totalMatrix.mapRect(&destRectTarget, destRect); | |
| 1709 | |
| 1710 resampling = computeInterpolationQuality(totalMatrix, | |
| 1711 SkScalarToFloat(srcRect.width()), SkScalarToFloat(srcRect.height()), | |
| 1712 SkScalarToFloat(destRectTarget.width()), SkScalarToFloat(destRectTar
get.height()), | |
| 1713 isDataComplete); | |
| 1714 } | |
| 1715 | |
| 1716 if (resampling == InterpolationNone) { | |
| 1717 // FIXME: This is to not break tests (it results in the filter bitmap fl
ag | |
| 1718 // being set to true). We need to decide if we respect InterpolationNone | |
| 1719 // being returned from computeInterpolationQuality. | |
| 1720 resampling = InterpolationLow; | |
| 1721 } | |
| 1722 resampling = limitInterpolationQuality(this, resampling); | |
| 1723 paint->setFilterQuality(static_cast<SkFilterQuality>(resampling)); | |
| 1724 | |
| 1725 return initialSaveCount; | |
| 1726 } | |
| 1727 | |
| 1728 } // namespace blink | 1583 } // namespace blink |
| OLD | NEW |