ClipCubicTest.cpp revision 4b413c8bb123e42ca4b9c7bfa6bc2167283cb84c
1ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com
2ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com/*
3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2011 Google Inc.
4ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com *
5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be
6ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file.
7ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com */
85755a2a9ab531192fd26b523960ae0c551c7b24cturk@google.com#include "Test.h"
95755a2a9ab531192fd26b523960ae0c551c7b24cturk@google.com
105546ef2dd9edad601383b85907f677118f857332reed@google.com#include "SkCanvas.h"
115546ef2dd9edad601383b85907f677118f857332reed@google.com#include "SkPaint.h"
120650c6ca12e026201091f3e9ea9cbf0fed2b6da1reed@android.com#include "SkCubicClipper.h"
135755a2a9ab531192fd26b523960ae0c551c7b24cturk@google.com#include "SkGeometry.h"
145755a2a9ab531192fd26b523960ae0c551c7b24cturk@google.com
155546ef2dd9edad601383b85907f677118f857332reed@google.com// Currently the supersampler blitter uses int16_t for its index into an array
165546ef2dd9edad601383b85907f677118f857332reed@google.com// the width of the clip. Test that we don't crash/assert if we try to draw
175546ef2dd9edad601383b85907f677118f857332reed@google.com// with a device/clip that is larger.
185546ef2dd9edad601383b85907f677118f857332reed@google.comstatic void test_giantClip() {
195546ef2dd9edad601383b85907f677118f857332reed@google.com    SkBitmap bm;
205546ef2dd9edad601383b85907f677118f857332reed@google.com    bm.setConfig(SkBitmap::kARGB_8888_Config, 64919, 1);
215546ef2dd9edad601383b85907f677118f857332reed@google.com    bm.allocPixels();
225546ef2dd9edad601383b85907f677118f857332reed@google.com    SkCanvas canvas(bm);
23dbfac8a72393eaf01670aeb3244de0e18d8faf98junov@google.com    canvas.clear(SK_ColorTRANSPARENT);
24d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
255546ef2dd9edad601383b85907f677118f857332reed@google.com    SkPath path;
265546ef2dd9edad601383b85907f677118f857332reed@google.com    path.moveTo(0, 0); path.lineTo(1, 0); path.lineTo(33, 1);
275546ef2dd9edad601383b85907f677118f857332reed@google.com    SkPaint paint;
285546ef2dd9edad601383b85907f677118f857332reed@google.com    paint.setAntiAlias(true);
295546ef2dd9edad601383b85907f677118f857332reed@google.com    canvas.drawPath(path, paint);
305546ef2dd9edad601383b85907f677118f857332reed@google.com}
315755a2a9ab531192fd26b523960ae0c551c7b24cturk@google.com
325755a2a9ab531192fd26b523960ae0c551c7b24cturk@google.comstatic void PrintCurve(const char *name, const SkPoint crv[4]) {
33fab44db294846ff05d837b9cf0bf97a073891da7bungeman@google.com    SkDebugf("%s: %.10g, %.10g, %.10g, %.10g, %.10g, %.10g, %.10g, %.10g\n",
345755a2a9ab531192fd26b523960ae0c551c7b24cturk@google.com            name,
35d41344553163085bfcfaf7d5882c6028934f8e3breed@android.com            (float)crv[0].fX, (float)crv[0].fY,
36d41344553163085bfcfaf7d5882c6028934f8e3breed@android.com            (float)crv[1].fX, (float)crv[1].fY,
37d41344553163085bfcfaf7d5882c6028934f8e3breed@android.com            (float)crv[2].fX, (float)crv[2].fY,
38d41344553163085bfcfaf7d5882c6028934f8e3breed@android.com            (float)crv[3].fX, (float)crv[3].fY);
397d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com
405755a2a9ab531192fd26b523960ae0c551c7b24cturk@google.com}
415755a2a9ab531192fd26b523960ae0c551c7b24cturk@google.com
425755a2a9ab531192fd26b523960ae0c551c7b24cturk@google.com
437d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.comstatic bool CurvesAreEqual(const SkPoint c0[4],
447d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com                           const SkPoint c1[4],
457d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com                           float tol) {
467d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com    for (int i = 0; i < 4; i++) {
474b413c8bb123e42ca4b9c7bfa6bc2167283cb84ccommit-bot@chromium.org        if (SkScalarAbs(c0[i].fX - c1[i].fX) > tol ||
484b413c8bb123e42ca4b9c7bfa6bc2167283cb84ccommit-bot@chromium.org            SkScalarAbs(c0[i].fY - c1[i].fY) > tol
497d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com        ) {
507d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com            PrintCurve("c0", c0);
517d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com            PrintCurve("c1", c1);
527d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com            return false;
537d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com        }
547d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com    }
557d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com    return true;
565755a2a9ab531192fd26b523960ae0c551c7b24cturk@google.com}
575755a2a9ab531192fd26b523960ae0c551c7b24cturk@google.com
585755a2a9ab531192fd26b523960ae0c551c7b24cturk@google.com
597d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.comstatic SkPoint* SetCurve(float x0, float y0,
607d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com                         float x1, float y1,
617d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com                         float x2, float y2,
627d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com                         float x3, float y3,
637d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com                         SkPoint crv[4]) {
644b413c8bb123e42ca4b9c7bfa6bc2167283cb84ccommit-bot@chromium.org    crv[0].fX = x0;   crv[0].fY = y0;
654b413c8bb123e42ca4b9c7bfa6bc2167283cb84ccommit-bot@chromium.org    crv[1].fX = x1;   crv[1].fY = y1;
664b413c8bb123e42ca4b9c7bfa6bc2167283cb84ccommit-bot@chromium.org    crv[2].fX = x2;   crv[2].fY = y2;
674b413c8bb123e42ca4b9c7bfa6bc2167283cb84ccommit-bot@chromium.org    crv[3].fX = x3;   crv[3].fY = y3;
685755a2a9ab531192fd26b523960ae0c551c7b24cturk@google.com    return crv;
695755a2a9ab531192fd26b523960ae0c551c7b24cturk@google.com}
707d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com
715755a2a9ab531192fd26b523960ae0c551c7b24cturk@google.com
725755a2a9ab531192fd26b523960ae0c551c7b24cturk@google.comstatic void TestCubicClipping(skiatest::Reporter* reporter) {
737d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com    static SkPoint crv[4] = {
74d41344553163085bfcfaf7d5882c6028934f8e3breed@android.com        { SkIntToScalar(0), SkIntToScalar(0)  },
75d41344553163085bfcfaf7d5882c6028934f8e3breed@android.com        { SkIntToScalar(2), SkIntToScalar(3)  },
76d41344553163085bfcfaf7d5882c6028934f8e3breed@android.com        { SkIntToScalar(1), SkIntToScalar(10) },
77d41344553163085bfcfaf7d5882c6028934f8e3breed@android.com        { SkIntToScalar(4), SkIntToScalar(12) }
787d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com    };
797d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com
807d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com    SkCubicClipper clipper;
817d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com    SkPoint clipped[4], shouldbe[4];
827d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com    SkIRect clipRect;
837d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com    bool success;
844b413c8bb123e42ca4b9c7bfa6bc2167283cb84ccommit-bot@chromium.org    const float tol = 1e-4f;
857d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com
867d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com    // Test no clip, with plenty of room.
877d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com    clipRect.set(-2, -2, 6, 14);
887d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com    clipper.setClip(clipRect);
897d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com    success = clipper.clipCubic(crv, clipped);
907d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com    REPORTER_ASSERT(reporter, success == true);
917d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com    REPORTER_ASSERT(reporter, CurvesAreEqual(clipped, SetCurve(
927d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com        0, 0, 2, 3, 1, 10, 4, 12, shouldbe), tol));
937d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com
947d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com    // Test no clip, touching first point.
957d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com    clipRect.set(-2, 0, 6, 14);
967d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com    clipper.setClip(clipRect);
977d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com    success = clipper.clipCubic(crv, clipped);
987d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com    REPORTER_ASSERT(reporter, success == true);
997d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com    REPORTER_ASSERT(reporter, CurvesAreEqual(clipped, SetCurve(
1007d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com        0, 0, 2, 3, 1, 10, 4, 12, shouldbe), tol));
1017d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com
1027d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com    // Test no clip, touching last point.
1037d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com    clipRect.set(-2, -2, 6, 12);
1047d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com    clipper.setClip(clipRect);
1057d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com    success = clipper.clipCubic(crv, clipped);
1067d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com    REPORTER_ASSERT(reporter, success == true);
1077d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com    REPORTER_ASSERT(reporter, CurvesAreEqual(clipped, SetCurve(
1087d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com        0, 0, 2, 3, 1, 10, 4, 12, shouldbe), tol));
1097d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com
1107d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com    // Test all clip.
1117d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com    clipRect.set(-2, 14, 6, 20);
1127d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com    clipper.setClip(clipRect);
1137d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com    success = clipper.clipCubic(crv, clipped);
1147d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com    REPORTER_ASSERT(reporter, success == false);
1157d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com
1167d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com    // Test clip at 1.
1177d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com    clipRect.set(-2, 1, 6, 14);
1187d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com    clipper.setClip(clipRect);
1197d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com    success = clipper.clipCubic(crv, clipped);
1207d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com    REPORTER_ASSERT(reporter, success == true);
1217d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com    REPORTER_ASSERT(reporter, CurvesAreEqual(clipped, SetCurve(
1226853e808a464ca75ff1328338d1eb55ff27c4337robertphillips@google.com        0.5126125216f, 1,
1236853e808a464ca75ff1328338d1eb55ff27c4337robertphillips@google.com        1.841195941f,  4.337081432f,
1246853e808a464ca75ff1328338d1eb55ff27c4337robertphillips@google.com        1.297019958f,  10.19801331f,
1257d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com        4,            12,
1267d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com        shouldbe), tol));
1277d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com
1287d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com    // Test clip at 2.
1297d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com    clipRect.set(-2, 2, 6, 14);
1307d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com    clipper.setClip(clipRect);
1317d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com    success = clipper.clipCubic(crv, clipped);
1327d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com    REPORTER_ASSERT(reporter, success == true);
1337d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com    REPORTER_ASSERT(reporter, CurvesAreEqual(clipped, SetCurve(
1346853e808a464ca75ff1328338d1eb55ff27c4337robertphillips@google.com        00.8412352204f, 2,
1356853e808a464ca75ff1328338d1eb55ff27c4337robertphillips@google.com        1.767683744f,   5.400758266f,
1366853e808a464ca75ff1328338d1eb55ff27c4337robertphillips@google.com        1.55052948f,    10.36701965f,
1377d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com        4,             12,
1387d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com        shouldbe), tol));
1397d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com
1407d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com    // Test clip at 11.
1417d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com    clipRect.set(-2, -2, 6, 11);
1427d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com    clipper.setClip(clipRect);
1437d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com    success = clipper.clipCubic(crv, clipped);
1447d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com    REPORTER_ASSERT(reporter, success == true);
1457d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com    REPORTER_ASSERT(reporter, CurvesAreEqual(clipped, SetCurve(
1467d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com        0,           0,
1476853e808a464ca75ff1328338d1eb55ff27c4337robertphillips@google.com        1.742904663f, 2.614356995f,
1486853e808a464ca75ff1328338d1eb55ff27c4337robertphillips@google.com        1.207521796f, 8.266430855f,
1496853e808a464ca75ff1328338d1eb55ff27c4337robertphillips@google.com        3.026495695f, 11,
1507d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com        shouldbe), tol));
1517d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com
1527d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com    // Test clip at 10.
1537d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com    clipRect.set(-2, -2, 6, 10);
1547d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com    clipper.setClip(clipRect);
1557d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com    success = clipper.clipCubic(crv, clipped);
1567d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com    REPORTER_ASSERT(reporter, success == true);
1577d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com    REPORTER_ASSERT(reporter, CurvesAreEqual(clipped, SetCurve(
1587d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com        0,           0,
1596853e808a464ca75ff1328338d1eb55ff27c4337robertphillips@google.com        1.551193237f, 2.326789856f,
1606853e808a464ca75ff1328338d1eb55ff27c4337robertphillips@google.com        1.297736168f, 7.059780121f,
1616853e808a464ca75ff1328338d1eb55ff27c4337robertphillips@google.com        2.505550385f, 10,
1627d3a58a5e442e0aba239616a4e996e64866ffbd0turk@google.com        shouldbe), tol));
1635546ef2dd9edad601383b85907f677118f857332reed@google.com
1645546ef2dd9edad601383b85907f677118f857332reed@google.com    test_giantClip();
1655755a2a9ab531192fd26b523960ae0c551c7b24cturk@google.com}
1665755a2a9ab531192fd26b523960ae0c551c7b24cturk@google.com
1675755a2a9ab531192fd26b523960ae0c551c7b24cturk@google.com
1685755a2a9ab531192fd26b523960ae0c551c7b24cturk@google.com
1695755a2a9ab531192fd26b523960ae0c551c7b24cturk@google.com
1705755a2a9ab531192fd26b523960ae0c551c7b24cturk@google.com#include "TestClassDef.h"
1715755a2a9ab531192fd26b523960ae0c551c7b24cturk@google.comDEFINE_TESTCLASS("CubicClipper", CubicClippingTestClass, TestCubicClipping)
172