1ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com/* 2ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2011 Google Inc. 3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * 4ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be 5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file. 6ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com */ 75755a2a9ab531192fd26b523960ae0c551c7b24cturk@google.com 85546ef2dd9edad601383b85907f677118f857332reed@google.com#include "SkCanvas.h" 90650c6ca12e026201091f3e9ea9cbf0fed2b6da1reed@android.com#include "SkCubicClipper.h" 105755a2a9ab531192fd26b523960ae0c551c7b24cturk@google.com#include "SkGeometry.h" 118f6884aab8aecd7657cf3f9cdbc682f0deca29c5tfarina@chromium.org#include "SkPaint.h" 128f6884aab8aecd7657cf3f9cdbc682f0deca29c5tfarina@chromium.org#include "Test.h" 135755a2a9ab531192fd26b523960ae0c551c7b24cturk@google.com 145546ef2dd9edad601383b85907f677118f857332reed@google.com// Currently the supersampler blitter uses int16_t for its index into an array 155546ef2dd9edad601383b85907f677118f857332reed@google.com// the width of the clip. Test that we don't crash/assert if we try to draw 165546ef2dd9edad601383b85907f677118f857332reed@google.com// with a device/clip that is larger. 175546ef2dd9edad601383b85907f677118f857332reed@google.comstatic void test_giantClip() { 185546ef2dd9edad601383b85907f677118f857332reed@google.com SkBitmap bm; 19fa9e5fa42a555712fb7a29d08d2ae2bdef0ed68ecommit-bot@chromium.org bm.allocN32Pixels(64919, 1); 205546ef2dd9edad601383b85907f677118f857332reed@google.com SkCanvas canvas(bm); 21dbfac8a72393eaf01670aeb3244de0e18d8faf98junov@google.com canvas.clear(SK_ColorTRANSPARENT); 22d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com 235546ef2dd9edad601383b85907f677118f857332reed@google.com SkPath path; 245546ef2dd9edad601383b85907f677118f857332reed@google.com path.moveTo(0, 0); path.lineTo(1, 0); path.lineTo(33, 1); 255546ef2dd9edad601383b85907f677118f857332reed@google.com SkPaint paint; 265546ef2dd9edad601383b85907f677118f857332reed@google.com paint.setAntiAlias(true); 275546ef2dd9edad601383b85907f677118f857332reed@google.com canvas.drawPath(path, paint); 285546ef2dd9edad601383b85907f677118f857332reed@google.com} 295755a2a9ab531192fd26b523960ae0c551c7b24cturk@google.com 305755a2a9ab531192fd26b523960ae0c551c7b24cturk@google.comstatic void PrintCurve(const char *name, const SkPoint crv[4]) { 31fab44db294846ff05d837b9cf0bf97a073891da7bungeman@google.com SkDebugf("%s: %.10g, %.10g, %.10g, %.10g, %.10g, %.10g, %.10g, %.10g\n", 325755a2a9ab531192fd26b523960ae0c551c7b24cturk@google.com name, 33d41344553163085bfcfaf7d5882c6028934f8e3breed@android.com (float)crv[0].fX, (float)crv[0].fY, 34d41344553163085bfcfaf7d5882c6028934f8e3breed@android.com (float)crv[1].fX, (float)crv[1].fY, 35d41344553163085bfcfaf7d5882c6028934f8e3breed@android.com (float)crv[2].fX, (float)crv[2].fY, 36d41344553163085bfcfaf7d5882c6028934f8e3breed@android.com (float)crv[3].fX, (float)crv[3].fY); 377d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com 385755a2a9ab531192fd26b523960ae0c551c7b24cturk@google.com} 395755a2a9ab531192fd26b523960ae0c551c7b24cturk@google.com 405755a2a9ab531192fd26b523960ae0c551c7b24cturk@google.com 417d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.comstatic bool CurvesAreEqual(const SkPoint c0[4], 427d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com const SkPoint c1[4], 437d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com float tol) { 447d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com for (int i = 0; i < 4; i++) { 454b413c8bb123e42ca4b9c7bfa6bc2167283cb84ccommit-bot@chromium.org if (SkScalarAbs(c0[i].fX - c1[i].fX) > tol || 464b413c8bb123e42ca4b9c7bfa6bc2167283cb84ccommit-bot@chromium.org SkScalarAbs(c0[i].fY - c1[i].fY) > tol 477d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com ) { 487d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com PrintCurve("c0", c0); 497d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com PrintCurve("c1", c1); 507d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com return false; 517d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com } 527d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com } 537d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com return true; 545755a2a9ab531192fd26b523960ae0c551c7b24cturk@google.com} 555755a2a9ab531192fd26b523960ae0c551c7b24cturk@google.com 565755a2a9ab531192fd26b523960ae0c551c7b24cturk@google.com 577d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.comstatic SkPoint* SetCurve(float x0, float y0, 587d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com float x1, float y1, 597d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com float x2, float y2, 607d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com float x3, float y3, 617d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com SkPoint crv[4]) { 624b413c8bb123e42ca4b9c7bfa6bc2167283cb84ccommit-bot@chromium.org crv[0].fX = x0; crv[0].fY = y0; 634b413c8bb123e42ca4b9c7bfa6bc2167283cb84ccommit-bot@chromium.org crv[1].fX = x1; crv[1].fY = y1; 644b413c8bb123e42ca4b9c7bfa6bc2167283cb84ccommit-bot@chromium.org crv[2].fX = x2; crv[2].fY = y2; 654b413c8bb123e42ca4b9c7bfa6bc2167283cb84ccommit-bot@chromium.org crv[3].fX = x3; crv[3].fY = y3; 665755a2a9ab531192fd26b523960ae0c551c7b24cturk@google.com return crv; 675755a2a9ab531192fd26b523960ae0c551c7b24cturk@google.com} 687d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com 695755a2a9ab531192fd26b523960ae0c551c7b24cturk@google.com 70e4fafb146e85cdfcf9d5418597b6818aa0754adatfarina@chromium.orgDEF_TEST(ClipCubic, reporter) { 717d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com static SkPoint crv[4] = { 72d41344553163085bfcfaf7d5882c6028934f8e3breed@android.com { SkIntToScalar(0), SkIntToScalar(0) }, 73d41344553163085bfcfaf7d5882c6028934f8e3breed@android.com { SkIntToScalar(2), SkIntToScalar(3) }, 74d41344553163085bfcfaf7d5882c6028934f8e3breed@android.com { SkIntToScalar(1), SkIntToScalar(10) }, 75d41344553163085bfcfaf7d5882c6028934f8e3breed@android.com { SkIntToScalar(4), SkIntToScalar(12) } 767d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com }; 777d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com 787d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com SkCubicClipper clipper; 797d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com SkPoint clipped[4], shouldbe[4]; 807d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com SkIRect clipRect; 817d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com bool success; 824b413c8bb123e42ca4b9c7bfa6bc2167283cb84ccommit-bot@chromium.org const float tol = 1e-4f; 837d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com 847d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com // Test no clip, with plenty of room. 857d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com clipRect.set(-2, -2, 6, 14); 867d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com clipper.setClip(clipRect); 877d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com success = clipper.clipCubic(crv, clipped); 887d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com REPORTER_ASSERT(reporter, success == true); 897d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com REPORTER_ASSERT(reporter, CurvesAreEqual(clipped, SetCurve( 907d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com 0, 0, 2, 3, 1, 10, 4, 12, shouldbe), tol)); 917d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com 927d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com // Test no clip, touching first point. 937d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com clipRect.set(-2, 0, 6, 14); 947d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com clipper.setClip(clipRect); 957d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com success = clipper.clipCubic(crv, clipped); 967d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com REPORTER_ASSERT(reporter, success == true); 977d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com REPORTER_ASSERT(reporter, CurvesAreEqual(clipped, SetCurve( 987d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com 0, 0, 2, 3, 1, 10, 4, 12, shouldbe), tol)); 997d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com 1007d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com // Test no clip, touching last point. 1017d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com clipRect.set(-2, -2, 6, 12); 1027d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com clipper.setClip(clipRect); 1037d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com success = clipper.clipCubic(crv, clipped); 1047d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com REPORTER_ASSERT(reporter, success == true); 1057d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com REPORTER_ASSERT(reporter, CurvesAreEqual(clipped, SetCurve( 1067d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com 0, 0, 2, 3, 1, 10, 4, 12, shouldbe), tol)); 1077d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com 1087d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com // Test all clip. 1097d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com clipRect.set(-2, 14, 6, 20); 1107d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com clipper.setClip(clipRect); 1117d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com success = clipper.clipCubic(crv, clipped); 1127d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com REPORTER_ASSERT(reporter, success == false); 1137d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com 1147d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com // Test clip at 1. 1157d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com clipRect.set(-2, 1, 6, 14); 1167d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com clipper.setClip(clipRect); 1177d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com success = clipper.clipCubic(crv, clipped); 1187d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com REPORTER_ASSERT(reporter, success == true); 1197d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com REPORTER_ASSERT(reporter, CurvesAreEqual(clipped, SetCurve( 1206853e808a464ca75ff1328338d1eb55ff27c4337robertphillips@google.com 0.5126125216f, 1, 1216853e808a464ca75ff1328338d1eb55ff27c4337robertphillips@google.com 1.841195941f, 4.337081432f, 1226853e808a464ca75ff1328338d1eb55ff27c4337robertphillips@google.com 1.297019958f, 10.19801331f, 1237d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com 4, 12, 1247d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com shouldbe), tol)); 1257d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com 1267d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com // Test clip at 2. 1277d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com clipRect.set(-2, 2, 6, 14); 1287d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com clipper.setClip(clipRect); 1297d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com success = clipper.clipCubic(crv, clipped); 1307d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com REPORTER_ASSERT(reporter, success == true); 1317d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com REPORTER_ASSERT(reporter, CurvesAreEqual(clipped, SetCurve( 1326853e808a464ca75ff1328338d1eb55ff27c4337robertphillips@google.com 00.8412352204f, 2, 1336853e808a464ca75ff1328338d1eb55ff27c4337robertphillips@google.com 1.767683744f, 5.400758266f, 1346853e808a464ca75ff1328338d1eb55ff27c4337robertphillips@google.com 1.55052948f, 10.36701965f, 1357d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com 4, 12, 1367d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com shouldbe), tol)); 1377d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com 1387d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com // Test clip at 11. 1397d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com clipRect.set(-2, -2, 6, 11); 1407d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com clipper.setClip(clipRect); 1417d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com success = clipper.clipCubic(crv, clipped); 1427d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com REPORTER_ASSERT(reporter, success == true); 1437d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com REPORTER_ASSERT(reporter, CurvesAreEqual(clipped, SetCurve( 1447d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com 0, 0, 1456853e808a464ca75ff1328338d1eb55ff27c4337robertphillips@google.com 1.742904663f, 2.614356995f, 1466853e808a464ca75ff1328338d1eb55ff27c4337robertphillips@google.com 1.207521796f, 8.266430855f, 1476853e808a464ca75ff1328338d1eb55ff27c4337robertphillips@google.com 3.026495695f, 11, 1487d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com shouldbe), tol)); 1497d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com 1507d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com // Test clip at 10. 1517d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com clipRect.set(-2, -2, 6, 10); 1527d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com clipper.setClip(clipRect); 1537d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com success = clipper.clipCubic(crv, clipped); 1547d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com REPORTER_ASSERT(reporter, success == true); 1557d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com REPORTER_ASSERT(reporter, CurvesAreEqual(clipped, SetCurve( 1567d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com 0, 0, 1576853e808a464ca75ff1328338d1eb55ff27c4337robertphillips@google.com 1.551193237f, 2.326789856f, 1586853e808a464ca75ff1328338d1eb55ff27c4337robertphillips@google.com 1.297736168f, 7.059780121f, 1596853e808a464ca75ff1328338d1eb55ff27c4337robertphillips@google.com 2.505550385f, 10, 1607d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com shouldbe), tol)); 1615546ef2dd9edad601383b85907f677118f857332reed@google.com 1625546ef2dd9edad601383b85907f677118f857332reed@google.com test_giantClip(); 1635755a2a9ab531192fd26b523960ae0c551c7b24cturk@google.com} 164