13d60812865bb034851da777a91413ab584929887reed@google.com/* 23d60812865bb034851da777a91413ab584929887reed@google.com * Copyright 2011 Google Inc. 33d60812865bb034851da777a91413ab584929887reed@google.com * 43d60812865bb034851da777a91413ab584929887reed@google.com * Use of this source code is governed by a BSD-style license that can be 53d60812865bb034851da777a91413ab584929887reed@google.com * found in the LICENSE file. 63d60812865bb034851da777a91413ab584929887reed@google.com */ 73d60812865bb034851da777a91413ab584929887reed@google.com 873fe7b07e6391da81dfc48d600d7b3141be1f471Herb Derby#include "SkArenaAlloc.h" 939e085559ddbd088866abdf50a48f7ab5b283830Florin Malita#include "SkBitmap.h" 103d60812865bb034851da777a91413ab584929887reed@google.com#include "SkCanvas.h" 11cdc651d29d88e87ef84d5a586879db2c16ff4579Matt Sarett#include "SkColorSpaceXformer.h" 123d60812865bb034851da777a91413ab584929887reed@google.com#include "SkDrawLooper.h" 139da5a5a198e5dc9148f7f30a6089377590eee55bmsarett#include "SkLightingImageFilter.h" 1479fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org#include "SkTypes.h" 158f6884aab8aecd7657cf3f9cdbc682f0deca29c5tfarina@chromium.org#include "Test.h" 163d60812865bb034851da777a91413ab584929887reed@google.com 173d60812865bb034851da777a91413ab584929887reed@google.com/* 183d60812865bb034851da777a91413ab584929887reed@google.com * Subclass of looper that just draws once, with an offset in X. 193d60812865bb034851da777a91413ab584929887reed@google.com */ 203d60812865bb034851da777a91413ab584929887reed@google.comclass TestLooper : public SkDrawLooper { 213d60812865bb034851da777a91413ab584929887reed@google.compublic: 223d60812865bb034851da777a91413ab584929887reed@google.com 2373fe7b07e6391da81dfc48d600d7b3141be1f471Herb Derby SkDrawLooper::Context* makeContext(SkCanvas*, SkArenaAlloc* alloc) const override { 2473fe7b07e6391da81dfc48d600d7b3141be1f471Herb Derby return alloc->make<TestDrawLooperContext>(); 253d60812865bb034851da777a91413ab584929887reed@google.com } 263d60812865bb034851da777a91413ab584929887reed@google.com 27cdc651d29d88e87ef84d5a586879db2c16ff4579Matt Sarett sk_sp<SkDrawLooper> onMakeColorSpace(SkColorSpaceXformer*) const override { 28cdc651d29d88e87ef84d5a586879db2c16ff4579Matt Sarett return nullptr; 29cdc651d29d88e87ef84d5a586879db2c16ff4579Matt Sarett } 30cdc651d29d88e87ef84d5a586879db2c16ff4579Matt Sarett 310f10f7bf1fb43ca6346dc220a076773b1f19a367commit-bot@chromium.org#ifndef SK_IGNORE_TO_STRING 3236352bf5e38f45a70ee4f4fc132a38048d38206dmtklein void toString(SkString* str) const override { 334991b8f23482afc1494fd17647421ce68de53331robertphillips@google.com str->append("TestLooper:"); 344991b8f23482afc1494fd17647421ce68de53331robertphillips@google.com } 354991b8f23482afc1494fd17647421ce68de53331robertphillips@google.com#endif 364991b8f23482afc1494fd17647421ce68de53331robertphillips@google.com 37fc6c37b981daeece7474ce61070c707c37eefa62Mike Klein SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(TestLooper) 387e44bb191633e225fd0455c267dbf67f9ee8633emtklein 3979fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.orgprivate: 4079fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org class TestDrawLooperContext : public SkDrawLooper::Context { 4179fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org public: 4279fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org TestDrawLooperContext() : fOnce(true) {} 43d3b65972aad96453ff4510caa3e25a2b847c6d1eBrian Salomon ~TestDrawLooperContext() override {} 4479fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org 4536352bf5e38f45a70ee4f4fc132a38048d38206dmtklein bool next(SkCanvas* canvas, SkPaint*) override { 4679fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org if (fOnce) { 4779fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org fOnce = false; 4879fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org canvas->translate(SkIntToScalar(10), 0); 4979fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org return true; 5079fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org } 5179fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org return false; 5279fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org } 53cdc651d29d88e87ef84d5a586879db2c16ff4579Matt Sarett 5479fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org private: 5579fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org bool fOnce; 5679fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org }; 573d60812865bb034851da777a91413ab584929887reed@google.com}; 583d60812865bb034851da777a91413ab584929887reed@google.com 5960c9b58b3214b0154c931656e91e39b230e987d8reedsk_sp<SkFlattenable> TestLooper::CreateProc(SkReadBuffer&) { return sk_make_sp<TestLooper>(); } 607e44bb191633e225fd0455c267dbf67f9ee8633emtklein 613d60812865bb034851da777a91413ab584929887reed@google.comstatic void test_drawBitmap(skiatest::Reporter* reporter) { 623d60812865bb034851da777a91413ab584929887reed@google.com SkBitmap src; 63deee496cd30070e52556dcb538c2e5eb39b66b81mike@reedtribe.org src.allocN32Pixels(10, 10); 643d60812865bb034851da777a91413ab584929887reed@google.com src.eraseColor(SK_ColorWHITE); 653d60812865bb034851da777a91413ab584929887reed@google.com 663d60812865bb034851da777a91413ab584929887reed@google.com SkBitmap dst; 67deee496cd30070e52556dcb538c2e5eb39b66b81mike@reedtribe.org dst.allocN32Pixels(10, 10); 68dbfac8a72393eaf01670aeb3244de0e18d8faf98junov@google.com dst.eraseColor(SK_ColorTRANSPARENT); 693d60812865bb034851da777a91413ab584929887reed@google.com 703d60812865bb034851da777a91413ab584929887reed@google.com SkCanvas canvas(dst); 713d60812865bb034851da777a91413ab584929887reed@google.com SkPaint paint; 723d60812865bb034851da777a91413ab584929887reed@google.com 733d60812865bb034851da777a91413ab584929887reed@google.com // we are initially transparent 743d60812865bb034851da777a91413ab584929887reed@google.com REPORTER_ASSERT(reporter, 0 == *dst.getAddr32(5, 5)); 753d60812865bb034851da777a91413ab584929887reed@google.com 763d60812865bb034851da777a91413ab584929887reed@google.com // we see the bitmap drawn 773d60812865bb034851da777a91413ab584929887reed@google.com canvas.drawBitmap(src, 0, 0, &paint); 783d60812865bb034851da777a91413ab584929887reed@google.com REPORTER_ASSERT(reporter, 0xFFFFFFFF == *dst.getAddr32(5, 5)); 793d60812865bb034851da777a91413ab584929887reed@google.com 803d60812865bb034851da777a91413ab584929887reed@google.com // reverify we are clear again 81dbfac8a72393eaf01670aeb3244de0e18d8faf98junov@google.com dst.eraseColor(SK_ColorTRANSPARENT); 823d60812865bb034851da777a91413ab584929887reed@google.com REPORTER_ASSERT(reporter, 0 == *dst.getAddr32(5, 5)); 833d60812865bb034851da777a91413ab584929887reed@google.com 843d60812865bb034851da777a91413ab584929887reed@google.com // if the bitmap is clipped out, we don't draw it 853d60812865bb034851da777a91413ab584929887reed@google.com canvas.drawBitmap(src, SkIntToScalar(-10), 0, &paint); 863d60812865bb034851da777a91413ab584929887reed@google.com REPORTER_ASSERT(reporter, 0 == *dst.getAddr32(5, 5)); 873d60812865bb034851da777a91413ab584929887reed@google.com 883d60812865bb034851da777a91413ab584929887reed@google.com // now install our looper, which will draw, since it internally translates 893d60812865bb034851da777a91413ab584929887reed@google.com // to the left. The test is to ensure that canvas' quickReject machinary 903d60812865bb034851da777a91413ab584929887reed@google.com // allows us through, even though sans-looper we would look like we should 913d60812865bb034851da777a91413ab584929887reed@google.com // be clipped out. 927b380d0d0e91ae6967c52bfa14853a77b9551de4reed paint.setLooper(sk_make_sp<TestLooper>()); 933d60812865bb034851da777a91413ab584929887reed@google.com canvas.drawBitmap(src, SkIntToScalar(-10), 0, &paint); 943d60812865bb034851da777a91413ab584929887reed@google.com REPORTER_ASSERT(reporter, 0xFFFFFFFF == *dst.getAddr32(5, 5)); 953d60812865bb034851da777a91413ab584929887reed@google.com} 963d60812865bb034851da777a91413ab584929887reed@google.com 979b3aa54bc9605257c701cf465813f5fb1d7ba39ereedstatic void test_layers(skiatest::Reporter* reporter) { 989b3aa54bc9605257c701cf465813f5fb1d7ba39ereed SkCanvas canvas(100, 100); 999b3aa54bc9605257c701cf465813f5fb1d7ba39ereed 1009b3aa54bc9605257c701cf465813f5fb1d7ba39ereed SkRect r = SkRect::MakeWH(10, 10); 1019b3aa54bc9605257c701cf465813f5fb1d7ba39ereed REPORTER_ASSERT(reporter, false == canvas.quickReject(r)); 1029b3aa54bc9605257c701cf465813f5fb1d7ba39ereed 1039b3aa54bc9605257c701cf465813f5fb1d7ba39ereed r.offset(300, 300); 1049b3aa54bc9605257c701cf465813f5fb1d7ba39ereed REPORTER_ASSERT(reporter, true == canvas.quickReject(r)); 1059b3aa54bc9605257c701cf465813f5fb1d7ba39ereed 1069b3aa54bc9605257c701cf465813f5fb1d7ba39ereed // Test that saveLayer updates quickReject 1079b3aa54bc9605257c701cf465813f5fb1d7ba39ereed SkRect bounds = SkRect::MakeLTRB(50, 50, 70, 70); 10896fcdcc219d2a0d3579719b84b28bede76efba64halcanary canvas.saveLayer(&bounds, nullptr); 1099b3aa54bc9605257c701cf465813f5fb1d7ba39ereed REPORTER_ASSERT(reporter, true == canvas.quickReject(SkRect::MakeWH(10, 10))); 1109b3aa54bc9605257c701cf465813f5fb1d7ba39ereed REPORTER_ASSERT(reporter, false == canvas.quickReject(SkRect::MakeWH(60, 60))); 1119b3aa54bc9605257c701cf465813f5fb1d7ba39ereed} 1129b3aa54bc9605257c701cf465813f5fb1d7ba39ereed 113fbfa25802709139c2f14e304319c9541da65ca27msarettstatic void test_quick_reject(skiatest::Reporter* reporter) { 114fbfa25802709139c2f14e304319c9541da65ca27msarett SkCanvas canvas(100, 100); 115fbfa25802709139c2f14e304319c9541da65ca27msarett SkRect r0 = SkRect::MakeLTRB(-50.0f, -50.0f, 50.0f, 50.0f); 116fbfa25802709139c2f14e304319c9541da65ca27msarett SkRect r1 = SkRect::MakeLTRB(-50.0f, 110.0f, 50.0f, 120.0f); 117fbfa25802709139c2f14e304319c9541da65ca27msarett SkRect r2 = SkRect::MakeLTRB(110.0f, -50.0f, 120.0f, 50.0f); 118fbfa25802709139c2f14e304319c9541da65ca27msarett SkRect r3 = SkRect::MakeLTRB(-120.0f, -50.0f, 120.0f, 50.0f); 119fbfa25802709139c2f14e304319c9541da65ca27msarett SkRect r4 = SkRect::MakeLTRB(-50.0f, -120.0f, 50.0f, 120.0f); 120fbfa25802709139c2f14e304319c9541da65ca27msarett SkRect r5 = SkRect::MakeLTRB(-120.0f, -120.0f, 120.0f, 120.0f); 121fbfa25802709139c2f14e304319c9541da65ca27msarett SkRect r6 = SkRect::MakeLTRB(-120.0f, -120.0f, -110.0f, -110.0f); 122fbfa25802709139c2f14e304319c9541da65ca27msarett SkRect r7 = SkRect::MakeLTRB(SK_ScalarNaN, -50.0f, 50.0f, 50.0f); 123fbfa25802709139c2f14e304319c9541da65ca27msarett SkRect r8 = SkRect::MakeLTRB(-50.0f, SK_ScalarNaN, 50.0f, 50.0f); 124fbfa25802709139c2f14e304319c9541da65ca27msarett SkRect r9 = SkRect::MakeLTRB(-50.0f, -50.0f, SK_ScalarNaN, 50.0f); 125fbfa25802709139c2f14e304319c9541da65ca27msarett SkRect r10 = SkRect::MakeLTRB(-50.0f, -50.0f, 50.0f, SK_ScalarNaN); 126fbfa25802709139c2f14e304319c9541da65ca27msarett REPORTER_ASSERT(reporter, false == canvas.quickReject(r0)); 127fbfa25802709139c2f14e304319c9541da65ca27msarett REPORTER_ASSERT(reporter, true == canvas.quickReject(r1)); 128fbfa25802709139c2f14e304319c9541da65ca27msarett REPORTER_ASSERT(reporter, true == canvas.quickReject(r2)); 129fbfa25802709139c2f14e304319c9541da65ca27msarett REPORTER_ASSERT(reporter, false == canvas.quickReject(r3)); 130fbfa25802709139c2f14e304319c9541da65ca27msarett REPORTER_ASSERT(reporter, false == canvas.quickReject(r4)); 131fbfa25802709139c2f14e304319c9541da65ca27msarett REPORTER_ASSERT(reporter, false == canvas.quickReject(r5)); 132fbfa25802709139c2f14e304319c9541da65ca27msarett REPORTER_ASSERT(reporter, true == canvas.quickReject(r6)); 133fbfa25802709139c2f14e304319c9541da65ca27msarett REPORTER_ASSERT(reporter, true == canvas.quickReject(r7)); 134fbfa25802709139c2f14e304319c9541da65ca27msarett REPORTER_ASSERT(reporter, true == canvas.quickReject(r8)); 135fbfa25802709139c2f14e304319c9541da65ca27msarett REPORTER_ASSERT(reporter, true == canvas.quickReject(r9)); 136fbfa25802709139c2f14e304319c9541da65ca27msarett REPORTER_ASSERT(reporter, true == canvas.quickReject(r10)); 137fbfa25802709139c2f14e304319c9541da65ca27msarett 138fbfa25802709139c2f14e304319c9541da65ca27msarett SkMatrix m = SkMatrix::MakeScale(2.0f); 139fbfa25802709139c2f14e304319c9541da65ca27msarett m.setTranslateX(10.0f); 140fbfa25802709139c2f14e304319c9541da65ca27msarett m.setTranslateY(10.0f); 141fbfa25802709139c2f14e304319c9541da65ca27msarett canvas.setMatrix(m); 142fbfa25802709139c2f14e304319c9541da65ca27msarett SkRect r11 = SkRect::MakeLTRB(5.0f, 5.0f, 100.0f, 100.0f); 143fbfa25802709139c2f14e304319c9541da65ca27msarett SkRect r12 = SkRect::MakeLTRB(5.0f, 50.0f, 100.0f, 100.0f); 144fbfa25802709139c2f14e304319c9541da65ca27msarett SkRect r13 = SkRect::MakeLTRB(50.0f, 5.0f, 100.0f, 100.0f); 145fbfa25802709139c2f14e304319c9541da65ca27msarett REPORTER_ASSERT(reporter, false == canvas.quickReject(r11)); 146fbfa25802709139c2f14e304319c9541da65ca27msarett REPORTER_ASSERT(reporter, true == canvas.quickReject(r12)); 147fbfa25802709139c2f14e304319c9541da65ca27msarett REPORTER_ASSERT(reporter, true == canvas.quickReject(r13)); 148fbfa25802709139c2f14e304319c9541da65ca27msarett} 149fbfa25802709139c2f14e304319c9541da65ca27msarett 150e4fafb146e85cdfcf9d5418597b6818aa0754adatfarina@chromium.orgDEF_TEST(QuickReject, reporter) { 1513d60812865bb034851da777a91413ab584929887reed@google.com test_drawBitmap(reporter); 1529b3aa54bc9605257c701cf465813f5fb1d7ba39ereed test_layers(reporter); 153fbfa25802709139c2f14e304319c9541da65ca27msarett test_quick_reject(reporter); 1543d60812865bb034851da777a91413ab584929887reed@google.com} 1559da5a5a198e5dc9148f7f30a6089377590eee55bmsarett 1569da5a5a198e5dc9148f7f30a6089377590eee55bmsarett// Regression test to make sure that we keep fIsScaleTranslate up to date on the canvas. 1579da5a5a198e5dc9148f7f30a6089377590eee55bmsarett// It is possible to set a new matrix on the canvas without calling setMatrix(). This tests 1589da5a5a198e5dc9148f7f30a6089377590eee55bmsarett// that code path. 1599da5a5a198e5dc9148f7f30a6089377590eee55bmsarettDEF_TEST(QuickReject_MatrixState, reporter) { 1609da5a5a198e5dc9148f7f30a6089377590eee55bmsarett SkCanvas canvas(100, 100); 1619da5a5a198e5dc9148f7f30a6089377590eee55bmsarett 1629da5a5a198e5dc9148f7f30a6089377590eee55bmsarett SkMatrix matrix; 1639da5a5a198e5dc9148f7f30a6089377590eee55bmsarett matrix.setRotate(45.0f); 1649da5a5a198e5dc9148f7f30a6089377590eee55bmsarett canvas.setMatrix(matrix); 1659da5a5a198e5dc9148f7f30a6089377590eee55bmsarett 1669da5a5a198e5dc9148f7f30a6089377590eee55bmsarett SkPaint paint; 1679da5a5a198e5dc9148f7f30a6089377590eee55bmsarett sk_sp<SkImageFilter> filter = SkLightingImageFilter::MakeDistantLitDiffuse( 1689da5a5a198e5dc9148f7f30a6089377590eee55bmsarett SkPoint3::Make(1.0f, 1.0f, 1.0f), 0xFF0000FF, 2.0f, 0.5f, nullptr); 1699da5a5a198e5dc9148f7f30a6089377590eee55bmsarett REPORTER_ASSERT(reporter, filter); 1709da5a5a198e5dc9148f7f30a6089377590eee55bmsarett paint.setImageFilter(filter); 1719da5a5a198e5dc9148f7f30a6089377590eee55bmsarett SkCanvas::SaveLayerRec rec; 1729da5a5a198e5dc9148f7f30a6089377590eee55bmsarett rec.fPaint = &paint; 1739da5a5a198e5dc9148f7f30a6089377590eee55bmsarett canvas.saveLayer(rec); 1749da5a5a198e5dc9148f7f30a6089377590eee55bmsarett 1759da5a5a198e5dc9148f7f30a6089377590eee55bmsarett // quickReject() will assert if the matrix is out of sync. 1769da5a5a198e5dc9148f7f30a6089377590eee55bmsarett canvas.quickReject(SkRect::MakeWH(100.0f, 100.0f)); 1779da5a5a198e5dc9148f7f30a6089377590eee55bmsarett} 178