11049f1246e7be4ccb68001361efceb8933e6f81ccaryclark/*
21049f1246e7be4ccb68001361efceb8933e6f81ccaryclark * Copyright 2015 Google Inc.
31049f1246e7be4ccb68001361efceb8933e6f81ccaryclark *
41049f1246e7be4ccb68001361efceb8933e6f81ccaryclark * Use of this source code is governed by a BSD-style license that can be
51049f1246e7be4ccb68001361efceb8933e6f81ccaryclark * found in the LICENSE file.
61049f1246e7be4ccb68001361efceb8933e6f81ccaryclark */
71049f1246e7be4ccb68001361efceb8933e6f81ccaryclark#include "PathOpsTestCommon.h"
81049f1246e7be4ccb68001361efceb8933e6f81ccaryclark#include "SkGeometry.h"
91049f1246e7be4ccb68001361efceb8933e6f81ccaryclark#include "SkIntersections.h"
101049f1246e7be4ccb68001361efceb8933e6f81ccaryclark#include "Test.h"
111049f1246e7be4ccb68001361efceb8933e6f81ccaryclark
121049f1246e7be4ccb68001361efceb8933e6f81ccaryclark/*
131049f1246e7be4ccb68001361efceb8933e6f81ccaryclarkmanually compute the intersection of a pair of circles and see if the conic intersection matches
141049f1246e7be4ccb68001361efceb8933e6f81ccaryclark  given two circles
151049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    construct a line connecting their centers
169d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary
171049f1246e7be4ccb68001361efceb8933e6f81ccaryclark */
181049f1246e7be4ccb68001361efceb8933e6f81ccaryclark
19a35ab3e6e024d0b548ded26a2e3b8ecd838ead93caryclarkstatic const ConicPts testSet[] = {
20ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark    {{{{306.588013,-227.983994}, {212.464996,-262.242004}, {95.5512009,58.9763985}}}, 0.707107008f},
21ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark    {{{{377.218994,-141.981003}, {40.578701,-201.339996}, {23.1854992,-102.697998}}}, 0.707107008f},
22ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark
23ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark    {{{{5.1114602088928223, 628.77813720703125},
249d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary        {10.834027290344238, 988.964111328125},
25ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark        {163.40835571289062, 988.964111328125}}}, 0.72944212f},
269d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary    {{{{163.40835571289062, 988.964111328125},
279d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary        {5, 988.964111328125},
28ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark        {5, 614.7423095703125}}}, 0.707106769f},
29ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark
30ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark    {{{{11.17222976684570312, -8.103978157043457031},
31ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark        {22.91432571411132812, -10.37866020202636719},
32ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark        {23.7764129638671875, -7.725424289703369141}}}, 1.00862849f},
33ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark    {{{{-1.545085430145263672, -4.755282402038574219},
34ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark        {22.23132705688476562, -12.48070907592773438},
35ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark        {23.7764129638671875, -7.725427150726318359}}}, 0.707106769f},
36ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark
371049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    {{{{-4,1}, {-4,5}, {0,5}}}, 0.707106769f},
381049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    {{{{-3,4}, {-3,1}, {0,1}}}, 0.707106769f},
391049f1246e7be4ccb68001361efceb8933e6f81ccaryclark
401049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    {{{{0, 0}, {0, 1}, {1, 1}}}, 0.5f},
411049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    {{{{1, 0}, {0, 0}, {0, 1}}}, 0.5f},
42ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark
431049f1246e7be4ccb68001361efceb8933e6f81ccaryclark};
441049f1246e7be4ccb68001361efceb8933e6f81ccaryclark
451049f1246e7be4ccb68001361efceb8933e6f81ccaryclarkconst int testSetCount = (int) SK_ARRAY_COUNT(testSet);
461049f1246e7be4ccb68001361efceb8933e6f81ccaryclark
47ef784fb7f58c9c021172045a8e0b396c81fdc425caryclarkstatic void chopCompare(const SkConic chopped[2], const SkDConic dChopped[2]) {
48ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark    SkASSERT(roughly_equal(chopped[0].fW, dChopped[0].fWeight));
49ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark    SkASSERT(roughly_equal(chopped[1].fW, dChopped[1].fWeight));
50ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark    for (int cIndex = 0; cIndex < 2; ++cIndex) {
51ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark        for (int pIndex = 0; pIndex < 3; ++pIndex) {
52ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark            SkDPoint up;
53ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark            up.set(chopped[cIndex].fPts[pIndex]);
54ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark            SkASSERT(dChopped[cIndex].fPts[pIndex].approximatelyEqual(up));
55ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark        }
56ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark    }
57ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark#if DEBUG_VISUALIZE_CONICS
58ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark    dChopped[0].dump();
59ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark    dChopped[1].dump();
60ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark#endif
61ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark}
62ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark
63ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark#include "SkBitmap.h"
64ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark#include "SkCanvas.h"
65ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark#include "SkImageEncoder.h"
66ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark#include "SkPathOpsRect.h"
67ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark#include "SkPaint.h"
68ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark#include "SkString.h"
69ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark
70ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark#define DEBUG_VISUALIZE_CONICS 0
71ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark
72ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark#if DEBUG_VISUALIZE_CONICS
73ef784fb7f58c9c021172045a8e0b396c81fdc425caryclarkstatic void writePng(const SkConic& c, const SkConic ch[2], const char* name) {
74ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark    const int scale = 10;
75ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark    SkConic conic, chopped[2];
76ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark    for (int index = 0; index < 3; ++index) {
77ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark        conic.fPts[index].fX = c.fPts[index].fX * scale;
78ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark        conic.fPts[index].fY = c.fPts[index].fY * scale;
79ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark        for (int chIndex = 0; chIndex < 2; ++chIndex) {
80ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark            chopped[chIndex].fPts[index].fX = ch[chIndex].fPts[index].fX * scale;
81ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark            chopped[chIndex].fPts[index].fY = ch[chIndex].fPts[index].fY * scale;
82ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark        }
83ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark    }
84ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark    conic.fW = c.fW;
85ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark    chopped[0].fW = ch[0].fW;
86ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark    chopped[1].fW = ch[1].fW;
87ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark    SkBitmap bitmap;
88ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark    SkRect bounds;
89ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark    conic.computeTightBounds(&bounds);
90ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark    bounds.outset(10, 10);
91ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark    bitmap.tryAllocPixels(SkImageInfo::MakeN32Premul(
92ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark          SkScalarRoundToInt(bounds.width()), SkScalarRoundToInt(bounds.height())));
93ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark    SkCanvas canvas(bitmap);
94ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark    SkPaint paint;
95ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark    paint.setAntiAlias(true);
96ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark    paint.setStyle(SkPaint::kStroke_Style);
97ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark    canvas.translate(-bounds.fLeft, -bounds.fTop);
98ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark    canvas.drawColor(SK_ColorWHITE);
99ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark    SkPath path;
100ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark    path.moveTo(conic.fPts[0]);
101ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark    path.conicTo(conic.fPts[1], conic.fPts[2], conic.fW);
102ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark    paint.setARGB(0x80, 0xFF, 0, 0);
103ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark    canvas.drawPath(path, paint);
104ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark    path.reset();
105ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark    path.moveTo(chopped[0].fPts[0]);
106ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark    path.conicTo(chopped[0].fPts[1], chopped[0].fPts[2], chopped[0].fW);
107ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark    path.moveTo(chopped[1].fPts[0]);
108ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark    path.conicTo(chopped[1].fPts[1], chopped[1].fPts[2], chopped[1].fW);
109ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark    paint.setARGB(0x80, 0, 0, 0xFF);
110ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark    canvas.drawPath(path, paint);
111ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark    SkString filename("c:\\Users\\caryclark\\Documents\\");
112ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark    filename.appendf("%s.png", name);
113db6830162eca5b94e61d9825ec93306fc615d204Hal Canary    sk_tool_utils::EncodeImageToFile(filename.c_str(), bitmap,
114db6830162eca5b94e61d9825ec93306fc615d204Hal Canary            SkEncodedImageFormat::kPNG, 100);
115ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark}
116ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark
117ef784fb7f58c9c021172045a8e0b396c81fdc425caryclarkstatic void writeDPng(const SkDConic& dC, const char* name) {
118ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark    const int scale = 5;
1199d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary    SkDConic dConic = {{{ {dC.fPts[0].fX * scale, dC.fPts[0].fY * scale },
1209d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary        {dC.fPts[1].fX * scale, dC.fPts[1].fY * scale },
121ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark        {dC.fPts[2].fX * scale, dC.fPts[2].fY * scale }}}, dC.fWeight };
122ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark    SkBitmap bitmap;
123ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark    SkDRect bounds;
124ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark    bounds.setBounds(dConic);
125ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark    bounds.fLeft -= 10;
126ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark    bounds.fTop -= 10;
127ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark    bounds.fRight += 10;
128ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark    bounds.fBottom += 10;
129ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark    bitmap.tryAllocPixels(SkImageInfo::MakeN32Premul(
130ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark          SkScalarRoundToInt(SkDoubleToScalar(bounds.width())),
131ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark          SkScalarRoundToInt(SkDoubleToScalar(bounds.height()))));
132ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark    SkCanvas canvas(bitmap);
133ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark    SkPaint paint;
134ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark    paint.setAntiAlias(true);
135ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark    paint.setStyle(SkPaint::kStroke_Style);
136ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark    canvas.translate(SkDoubleToScalar(-bounds.fLeft), SkDoubleToScalar(-bounds.fTop));
137ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark    canvas.drawColor(SK_ColorWHITE);
138ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark    SkPath path;
139ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark    path.moveTo(dConic.fPts[0].asSkPoint());
140ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark    path.conicTo(dConic.fPts[1].asSkPoint(), dConic.fPts[2].asSkPoint(), dConic.fWeight);
141ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark    paint.setARGB(0x80, 0xFF, 0, 0);
142ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark    canvas.drawPath(path, paint);
143ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark    path.reset();
144ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark    const int chops = 2;
145ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark    for (int tIndex = 0; tIndex < chops; ++tIndex) {
146ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark        SkDConic chopped = dConic.subDivide(tIndex / (double) chops,
147ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark                (tIndex + 1) / (double) chops);
148ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark        path.moveTo(chopped.fPts[0].asSkPoint());
149ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark        path.conicTo(chopped.fPts[1].asSkPoint(), chopped.fPts[2].asSkPoint(), chopped.fWeight);
150ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark    }
151ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark    paint.setARGB(0x80, 0, 0, 0xFF);
152ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark    canvas.drawPath(path, paint);
153ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark    SkString filename("c:\\Users\\caryclark\\Documents\\");
154ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark    filename.appendf("%s.png", name);
155db6830162eca5b94e61d9825ec93306fc615d204Hal Canary    sk_tool_utils::EncodeImageToFile(filename.c_str(), bitmap,
156db6830162eca5b94e61d9825ec93306fc615d204Hal Canary            SkEncodedImageFormat::kPNG, 100);
157ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark}
158ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark#endif
159ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark
160ef784fb7f58c9c021172045a8e0b396c81fdc425caryclarkstatic void chopBothWays(const SkDConic& dConic, double t, const char* name) {
161ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark    SkConic conic;
162ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark    for (int index = 0; index < 3; ++index) {
163ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark        conic.fPts[index] = dConic.fPts[index].asSkPoint();
164ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark    }
165ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark    conic.fW = dConic.fWeight;
166ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark    SkConic chopped[2];
167ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark    SkDConic dChopped[2];
168414c4295f951d43068666b6294df15b2fd2ba85ccaryclark    if (!conic.chopAt(SkDoubleToScalar(t), chopped)) {
169414c4295f951d43068666b6294df15b2fd2ba85ccaryclark        return;
170414c4295f951d43068666b6294df15b2fd2ba85ccaryclark    }
171ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark    dChopped[0] = dConic.subDivide(0, t);
172ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark    dChopped[1] = dConic.subDivide(t, 1);
173ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark#if DEBUG_VISUALIZE_CONICS
174ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark    dConic.dump();
175ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark#endif
176ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark    chopCompare(chopped, dChopped);
177ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark#if DEBUG_VISUALIZE_CONICS
178ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark    writePng(conic, chopped, name);
179ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark#endif
180ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark}
181ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark
182ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark#if DEBUG_VISUALIZE_CONICS
183ef784fb7f58c9c021172045a8e0b396c81fdc425caryclarkconst SkDConic frame0[] = {
184ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark{{{{306.588013,-227.983994}, {212.464996,-262.242004}, {95.5512009,58.9763985}}}, 0.707107008f},
185ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark{{{{377.218994,-141.981003}, {40.578701,-201.339996}, {23.1854992,-102.697998}}}, 0.707107008f},
186ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark};
187ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark
188ef784fb7f58c9c021172045a8e0b396c81fdc425caryclarkconst SkDConic frame1[] = {
189ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark{{{{377.218994,-141.981003}, {40.578701,-201.339996}, {23.1854992,-102.697998}}}, 0.707107008f},
190ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark{{{{306.58801299999999, -227.983994}, {212.46499600000001, -262.24200400000001}, {95.551200899999998, 58.976398500000002}}}, 0.707107008f},
191ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark{{{{377.21899400000001, -141.98100299999999}, {237.77799285476553, -166.56830755921084}, {134.08399674208422, -155.06258330544892}}}, 0.788580656f},
192ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark{{{{134.08399674208422, -155.06258330544892}, {30.390000629402859, -143.55685905168704}, {23.185499199999999, -102.697998}}}, 0.923879623f},
193ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark};
194ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark
195ef784fb7f58c9c021172045a8e0b396c81fdc425caryclarkconst SkDConic frame2[] = {
196ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark{{{{306.588013,-227.983994}, {212.464996,-262.242004}, {95.5512009,58.9763985}}}, 0.707107008f},
197ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark{{{{377.218994,-141.981003}, {40.578701,-201.339996}, {23.1854992,-102.697998}}}, 0.707107008f},
198ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark{{{{205.78973252799028, -158.12538713371103}, {143.97848953841861, -74.076645245042371}, {95.551200899999998, 58.976398500000002}}}, 0.923879623f},
199ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark{{{{377.21899400000001, -141.98100299999999}, {237.77799285476553, -166.56830755921084}, {134.08399674208422, -155.06258330544892}}}, 0.788580656f},
200ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark};
201ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark
202ef784fb7f58c9c021172045a8e0b396c81fdc425caryclarkconst SkDConic frame3[] = {
203ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark{{{{306.588013,-227.983994}, {212.464996,-262.242004}, {95.5512009,58.9763985}}}, 0.707107008f},
204ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark{{{{377.218994,-141.981003}, {40.578701,-201.339996}, {23.1854992,-102.697998}}}, 0.707107008f},
205ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark{{{{205.78973252799028, -158.12538713371103}, {143.97848953841861, -74.076645245042371}, {95.551200899999998, 58.976398500000002}}}, 0.923879623f},
206ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark{{{{252.08225670812539, -156.90491625851064}, {185.93099479842493, -160.81544543232982}, {134.08399674208422, -155.06258330544892}}}, 0.835816324f},
207ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark};
208ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark
209ef784fb7f58c9c021172045a8e0b396c81fdc425caryclarkconst SkDConic frame4[] = {
210ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark{{{{306.588013,-227.983994}, {212.464996,-262.242004}, {95.5512009,58.9763985}}}, 0.707107008f},
211ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark{{{{377.218994,-141.981003}, {40.578701,-201.339996}, {23.1854992,-102.697998}}}, 0.707107008f},
212ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark{{{{205.78973252799028, -158.12538713371103}, {174.88411103320448, -116.10101618937664}, {145.19509369736275, -56.857102571363754}}}, 0.871667147f},
213ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark{{{{252.08225670812539, -156.90491625851064}, {185.93099479842493, -160.81544543232982}, {134.08399674208422, -155.06258330544892}}}, 0.835816324f},
214ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark};
215ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark
216ef784fb7f58c9c021172045a8e0b396c81fdc425caryclarkconst SkDConic frame5[] = {
217ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark{{{{306.588013,-227.983994}, {212.464996,-262.242004}, {95.5512009,58.9763985}}}, 0.707107008f},
218ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark{{{{377.218994,-141.981003}, {40.578701,-201.339996}, {23.1854992,-102.697998}}}, 0.707107008f},
219ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark{{{{205.78973252799028, -158.12538713371103}, {174.88411103320448, -116.10101618937664}, {145.19509369736275, -56.857102571363754}}}, 0.871667147f},
220ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark{{{{252.08225670812539, -156.90491625851064}, {219.70109133058406, -158.81912754088933}, {190.17095392508796, -158.38373974664466}}}, 0.858306944f},
221ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark};
222ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark
223ef784fb7f58c9c021172045a8e0b396c81fdc425caryclarkconst SkDConic frame6[] = {
224ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark{{{{306.588013,-227.983994}, {212.464996,-262.242004}, {95.5512009,58.9763985}}}, 0.707107008f},
225ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark{{{{377.218994,-141.981003}, {40.578701,-201.339996}, {23.1854992,-102.697998}}}, 0.707107008f},
226ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark{{{{205.78973252799028, -158.12538713371103}, {190.33692178059735, -137.11320166154385}, {174.87004877564593, -111.2132534799228}}}, 0.858117759f},
227ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark{{{{252.08225670812539, -156.90491625851064}, {219.70109133058406, -158.81912754088933}, {190.17095392508796, -158.38373974664466}}}, 0.858306944f},
228ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark};
229ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark
230ef784fb7f58c9c021172045a8e0b396c81fdc425caryclarkconst SkDConic* frames[] = {
2319d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary    frame0, frame1, frame2, frame3, frame4, frame5, frame6
232ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark};
233ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark
234ef784fb7f58c9c021172045a8e0b396c81fdc425caryclarkconst int frameSizes[] = { (int) SK_ARRAY_COUNT(frame0), (int) SK_ARRAY_COUNT(frame1),
235ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark        (int) SK_ARRAY_COUNT(frame2), (int) SK_ARRAY_COUNT(frame3),
236ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark        (int) SK_ARRAY_COUNT(frame4), (int) SK_ARRAY_COUNT(frame5),
237ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark        (int) SK_ARRAY_COUNT(frame6),
238ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark};
239ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark
240ef784fb7f58c9c021172045a8e0b396c81fdc425caryclarkstatic void writeFrames() {
241ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark    const int scale = 5;
242ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark
243ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark    for (int index = 0; index < (int) SK_ARRAY_COUNT(frameSizes); ++index) {
244ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark        SkDRect bounds;
245ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark        bool boundsSet = false;
246ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark        int frameSize = frameSizes[index];
247ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark        for (int fIndex = 0; fIndex < frameSize; ++fIndex) {
248ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark            const SkDConic& dC = frames[index][fIndex];
2499d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary            SkDConic dConic = {{{ {dC.fPts[0].fX * scale, dC.fPts[0].fY * scale },
2509d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary                {dC.fPts[1].fX * scale, dC.fPts[1].fY * scale },
251ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark                {dC.fPts[2].fX * scale, dC.fPts[2].fY * scale }}}, dC.fWeight };
252ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark            SkDRect dBounds;
253ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark            dBounds.setBounds(dConic);
254ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark            if (!boundsSet) {
255ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark                bounds = dBounds;
256ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark                boundsSet = true;
257ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark            } else {
258ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark                bounds.add((SkDPoint&) dBounds.fLeft);
259ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark                bounds.add((SkDPoint&) dBounds.fRight);
260ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark            }
261ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark        }
262ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark        bounds.fLeft -= 10;
263ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark        bounds.fTop -= 10;
264ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark        bounds.fRight += 10;
265ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark        bounds.fBottom += 10;
266ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark        SkBitmap bitmap;
267ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark        bitmap.tryAllocPixels(SkImageInfo::MakeN32Premul(
268ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark              SkScalarRoundToInt(SkDoubleToScalar(bounds.width())),
269ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark              SkScalarRoundToInt(SkDoubleToScalar(bounds.height()))));
270ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark        SkCanvas canvas(bitmap);
271ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark        SkPaint paint;
272ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark        paint.setAntiAlias(true);
273ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark        paint.setStyle(SkPaint::kStroke_Style);
274ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark        canvas.translate(SkDoubleToScalar(-bounds.fLeft), SkDoubleToScalar(-bounds.fTop));
275ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark        canvas.drawColor(SK_ColorWHITE);
276ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark        for (int fIndex = 0; fIndex < frameSize; ++fIndex) {
277ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark            const SkDConic& dC = frames[index][fIndex];
2789d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary            SkDConic dConic = {{{ {dC.fPts[0].fX * scale, dC.fPts[0].fY * scale },
2799d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary                {dC.fPts[1].fX * scale, dC.fPts[1].fY * scale },
280ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark                {dC.fPts[2].fX * scale, dC.fPts[2].fY * scale }}}, dC.fWeight };
281ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark            SkPath path;
282ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark            path.moveTo(dConic.fPts[0].asSkPoint());
283ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark            path.conicTo(dConic.fPts[1].asSkPoint(), dConic.fPts[2].asSkPoint(), dConic.fWeight);
284ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark            if (fIndex < 2) {
285ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark                paint.setARGB(0x80, 0xFF, 0, 0);
286ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark            } else {
287ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark                paint.setARGB(0x80, 0, 0, 0xFF);
288ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark            }
289ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark            canvas.drawPath(path, paint);
290ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark        }
291ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark        SkString filename("c:\\Users\\caryclark\\Documents\\");
292ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark        filename.appendf("f%d.png", index);
293db6830162eca5b94e61d9825ec93306fc615d204Hal Canary        sk_tool_utils::EncodeImageToFile(filename.c_str(), bitmap, SkEncodedImageFormat::kPNG, 100);
294ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark    }
295ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark}
296ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark#endif
297ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark
298a35ab3e6e024d0b548ded26a2e3b8ecd838ead93caryclarkstatic void oneOff(skiatest::Reporter* reporter, const ConicPts& conic1, const ConicPts& conic2,
2991049f1246e7be4ccb68001361efceb8933e6f81ccaryclark        bool coin) {
300ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark#if DEBUG_VISUALIZE_CONICS
301ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark    writeFrames();
302ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark#endif
303a35ab3e6e024d0b548ded26a2e3b8ecd838ead93caryclark    SkDConic c1, c2;
304a35ab3e6e024d0b548ded26a2e3b8ecd838ead93caryclark    c1.debugSet(conic1.fPts.fPts, conic1.fWeight);
305a35ab3e6e024d0b548ded26a2e3b8ecd838ead93caryclark    c2.debugSet(conic2.fPts.fPts, conic2.fWeight);
306ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark    chopBothWays(c1, 0.5, "c1");
307ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark    chopBothWays(c2, 0.5, "c2");
308ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark#if DEBUG_VISUALIZE_CONICS
309ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark    writeDPng(c1, "d1");
310ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark    writeDPng(c2, "d2");
311ef784fb7f58c9c021172045a8e0b396c81fdc425caryclark#endif
3121049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    SkASSERT(ValidConic(c1));
3131049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    SkASSERT(ValidConic(c2));
3141049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    SkIntersections intersections;
3151049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    intersections.intersect(c1, c2);
3161049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    if (coin && intersections.used() != 2) {
3171049f1246e7be4ccb68001361efceb8933e6f81ccaryclark        SkDebugf("");
3181049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    }
3191049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    REPORTER_ASSERT(reporter, !coin || intersections.used() == 2);
3201049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    double tt1, tt2;
3211049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    SkDPoint xy1, xy2;
3221049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    for (int pt3 = 0; pt3 < intersections.used(); ++pt3) {
3231049f1246e7be4ccb68001361efceb8933e6f81ccaryclark        tt1 = intersections[0][pt3];
3241049f1246e7be4ccb68001361efceb8933e6f81ccaryclark        xy1 = c1.ptAtT(tt1);
3251049f1246e7be4ccb68001361efceb8933e6f81ccaryclark        tt2 = intersections[1][pt3];
3261049f1246e7be4ccb68001361efceb8933e6f81ccaryclark        xy2 = c2.ptAtT(tt2);
3271049f1246e7be4ccb68001361efceb8933e6f81ccaryclark        const SkDPoint& iPt = intersections.pt(pt3);
3281049f1246e7be4ccb68001361efceb8933e6f81ccaryclark        REPORTER_ASSERT(reporter, xy1.approximatelyEqual(iPt));
3291049f1246e7be4ccb68001361efceb8933e6f81ccaryclark        REPORTER_ASSERT(reporter, xy2.approximatelyEqual(iPt));
3301049f1246e7be4ccb68001361efceb8933e6f81ccaryclark        REPORTER_ASSERT(reporter, xy1.approximatelyEqual(xy2));
3311049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    }
3321049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    reporter->bumpTestCount();
3331049f1246e7be4ccb68001361efceb8933e6f81ccaryclark}
3341049f1246e7be4ccb68001361efceb8933e6f81ccaryclark
3351049f1246e7be4ccb68001361efceb8933e6f81ccaryclarkstatic void oneOff(skiatest::Reporter* reporter, int outer, int inner) {
336a35ab3e6e024d0b548ded26a2e3b8ecd838ead93caryclark    const ConicPts& c1 = testSet[outer];
337a35ab3e6e024d0b548ded26a2e3b8ecd838ead93caryclark    const ConicPts& c2 = testSet[inner];
3381049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    oneOff(reporter, c1, c2, false);
3391049f1246e7be4ccb68001361efceb8933e6f81ccaryclark}
3401049f1246e7be4ccb68001361efceb8933e6f81ccaryclark
3411049f1246e7be4ccb68001361efceb8933e6f81ccaryclarkstatic void oneOffTests(skiatest::Reporter* reporter) {
3421049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    for (int outer = 0; outer < testSetCount - 1; ++outer) {
3431049f1246e7be4ccb68001361efceb8933e6f81ccaryclark        for (int inner = outer + 1; inner < testSetCount; ++inner) {
3441049f1246e7be4ccb68001361efceb8933e6f81ccaryclark            oneOff(reporter, outer, inner);
3451049f1246e7be4ccb68001361efceb8933e6f81ccaryclark        }
3461049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    }
3471049f1246e7be4ccb68001361efceb8933e6f81ccaryclark}
3481049f1246e7be4ccb68001361efceb8933e6f81ccaryclark
3491049f1246e7be4ccb68001361efceb8933e6f81ccaryclarkDEF_TEST(PathOpsConicIntersectionOneOff, reporter) {
3501049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    oneOff(reporter, 0, 1);
3511049f1246e7be4ccb68001361efceb8933e6f81ccaryclark}
3521049f1246e7be4ccb68001361efceb8933e6f81ccaryclark
3531049f1246e7be4ccb68001361efceb8933e6f81ccaryclarkDEF_TEST(PathOpsConicIntersection, reporter) {
3541049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    oneOffTests(reporter);
3551049f1246e7be4ccb68001361efceb8933e6f81ccaryclark}
356