blob: eb1509e79899ecb2cd5a470e30eea20b77b82291 [file] [log] [blame]
caryclark@google.comcd4421d2012-03-01 19:16:31 +00001#include "EdgeWalker_Test.h"
2#include "Intersection_Tests.h"
3#include "SkBitmap.h"
4#include "SkCanvas.h"
5#include "SkPaint.h"
6
7static bool gDrawLastAsciiPaths = true;
8static bool gDrawAllAsciiPaths = false;
9static bool gShowPath = true;
10
11static void showPath(const char* str, const SkPath& path) {
12 if (!gShowPath) {
13 return;
14 }
15 SkDebugf("%s\n", str);
16 SkPath::Iter iter(path, true);
17 uint8_t verb;
18 SkPoint pts[4];
19 while ((verb = iter.next(pts)) != SkPath::kDone_Verb) {
20 switch (verb) {
21 case SkPath::kMove_Verb:
22 SkDebugf("path.moveTo(%g, %g);\n", pts[0].fX, pts[0].fY);
23 continue;
24 case SkPath::kLine_Verb:
25 SkDebugf("path.lineTo(%g, %g);\n", pts[1].fX, pts[1].fY);
26 break;
27 case SkPath::kQuad_Verb:
28 SkDebugf("path.quadTo(%g, %g, %g, %g);\n",
29 pts[1].fX, pts[1].fY, pts[2].fX, pts[2].fY);
30 break;
31 case SkPath::kCubic_Verb:
32 SkDebugf("path.cubicTo(%g, %g, %g, %g);\n",
33 pts[1].fX, pts[1].fY, pts[2].fX, pts[2].fY,
34 pts[3].fX, pts[3].fY);
35 break;
36 case SkPath::kClose_Verb:
37 SkDebugf("path.close();\n");
38 continue;
39 default:
40 SkDEBUGFAIL("bad verb");
41 return;
42 }
43 }
44}
45
46static bool pathsDrawTheSame(const SkPath& one, const SkPath& two) {
47 const SkRect& bounds1 = one.getBounds();
48 const SkRect& bounds2 = two.getBounds();
49 SkRect larger = bounds1;
50 larger.join(bounds2);
51 SkBitmap bits;
52 int bitWidth = SkScalarCeil(larger.width()) + 2;
53 int bitHeight = SkScalarCeil(larger.height()) + 2;
54 bits.setConfig(SkBitmap::kARGB_8888_Config, bitWidth * 2, bitHeight);
55 bits.allocPixels();
56 SkCanvas canvas(bits);
57 canvas.drawColor(SK_ColorWHITE);
58 SkPaint paint;
59 canvas.save();
60 canvas.translate(-bounds1.fLeft + 1, -bounds1.fTop + 1);
61 canvas.drawPath(one, paint);
62 canvas.restore();
63 canvas.save();
64 canvas.translate(-bounds1.fLeft + 1 + bitWidth, -bounds1.fTop + 1);
65 canvas.drawPath(two, paint);
66 canvas.restore();
67 for (int y = 0; y < bitHeight; ++y) {
68 uint32_t* addr1 = bits.getAddr32(0, y);
69 uint32_t* addr2 = bits.getAddr32(bitWidth, y);
70 for (int x = 0; x < bitWidth; ++x) {
71 if (addr1[x] != addr2[x]) {
72 return false;
73 break;
74 }
75 }
76 }
77 return true;
78}
79
80static void drawAsciiPaths(const SkPath& one, const SkPath& two,
81 bool drawPaths) {
82 if (!drawPaths) {
83 return;
84 }
85 if (0) {
86 showPath("one:", one);
87 showPath("two:", two);
88 }
89 const SkRect& bounds1 = one.getBounds();
90 const SkRect& bounds2 = two.getBounds();
91 SkRect larger = bounds1;
92 larger.join(bounds2);
93 SkBitmap bits;
94 int bitWidth = SkScalarCeil(larger.width()) + 2;
95 int bitHeight = SkScalarCeil(larger.height()) + 2;
96 bits.setConfig(SkBitmap::kARGB_8888_Config, bitWidth * 2, bitHeight);
97 bits.allocPixels();
98 SkCanvas canvas(bits);
99 canvas.drawColor(SK_ColorWHITE);
100 SkPaint paint;
101 canvas.save();
102 canvas.translate(-bounds1.fLeft + 1, -bounds1.fTop + 1);
103 canvas.drawPath(one, paint);
104 canvas.restore();
105 canvas.save();
106 canvas.translate(-bounds2.fLeft + 1 + bitWidth, -bounds2.fTop + 1);
107 canvas.drawPath(two, paint);
108 canvas.restore();
109 char out[1024];
110 SkASSERT(bitWidth * 2 + 1 < (int) sizeof(out));
111 for (int y = 0; y < bitHeight; ++y) {
112 uint32_t* addr1 = bits.getAddr32(0, y);
113 int x;
114 char* outPtr = out;
115 for (x = 0; x < bitWidth; ++x) {
116 *outPtr++ = addr1[x] == (uint32_t) -1 ? '_' : 'x';
117 }
118 *outPtr++ = '|';
119 for (x = bitWidth; x < bitWidth * 2; ++x) {
120 *outPtr++ = addr1[x] == (uint32_t) -1 ? '_' : 'x';
121 }
122 *outPtr++ = '\0';
123 SkDebugf("%s\n", out);
124 }
125}
126
127static bool scaledDrawTheSame(const SkPath& one, const SkPath& two,
128 int a, int b, bool drawPaths) {
129 SkMatrix scale;
130 scale.reset();
131 scale.preScale(a * 1.21f, b * 1.11f);
132 SkPath scaledOne, scaledTwo;
133 one.transform(scale, &scaledOne);
134 two.transform(scale, &scaledTwo);
135 if (pathsDrawTheSame(scaledOne, scaledTwo)) {
136 return true;
137 }
138 drawAsciiPaths(scaledOne, scaledTwo, drawPaths);
139 return false;
140}
141
142void comparePaths(const SkPath& one, const SkPath& two) {
143 if (pathsDrawTheSame(one, two)) {
144 return;
145 }
146 drawAsciiPaths(one, two, gDrawAllAsciiPaths);
147 for (int x = 9; x <= 33; ++x) {
148 if (scaledDrawTheSame(one, two, x, x - (x >> 2), gDrawAllAsciiPaths)) {
149 return;
150 }
151 }
152 if (!gDrawAllAsciiPaths) {
153 scaledDrawTheSame(one, two, 9, 7, gDrawLastAsciiPaths);
154 }
155 showPath("original:", one);
156 showPath("simplified:", two);
157 SkASSERT(0);
158}
159
160// doesn't work yet
161void comparePathsTiny(const SkPath& one, const SkPath& two) {
162 const SkRect& bounds1 = one.getBounds();
163 const SkRect& bounds2 = two.getBounds();
164 SkRect larger = bounds1;
165 larger.join(bounds2);
166 SkBitmap bits;
167 int bitWidth = SkScalarCeil(larger.width()) + 2;
168 int bitHeight = SkScalarCeil(larger.height()) + 2;
169 bits.setConfig(SkBitmap::kA1_Config, bitWidth * 2, bitHeight);
170 bits.allocPixels();
171 SkCanvas canvas(bits);
172 canvas.drawColor(SK_ColorWHITE);
173 SkPaint paint;
174 canvas.save();
175 canvas.translate(-bounds1.fLeft + 1, -bounds1.fTop + 1);
176 canvas.drawPath(one, paint);
177 canvas.restore();
178 canvas.save();
179 canvas.translate(-bounds2.fLeft + 1, -bounds2.fTop + 1);
180 canvas.drawPath(two, paint);
181 canvas.restore();
182 for (int y = 0; y < bitHeight; ++y) {
183 uint8_t* addr1 = bits.getAddr1(0, y);
184 uint8_t* addr2 = bits.getAddr1(bitWidth, y);
185 for (int x = 0; x < bits.rowBytes(); ++x) {
186 SkASSERT(addr1[x] == addr2[x]);
187 }
188 }
189}
190