aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Reed <reed@google.com>2010-03-09 10:15:32 -0500
committerMike Reed <reed@google.com>2010-03-09 10:15:32 -0500
commit215473cea1702d8acc0316da3e5a9bf4ce0130ef (patch)
treefd1268ed78c5cd0b723019331bd80cc3380943b5
parent8c8ec35f5e6fd7b2d8c0e7cd5e896e3a4d1ad57b (diff)
downloadskia-215473cea1702d8acc0316da3e5a9bf4ce0130ef.tar.gz
disable neon-opt for 32A->565 + alpha blend since it doesn't correctly treat
src-alpha == 0 as a no-op. update unittests to measure this Change-Id: If4d61ac5f7ff3d7fc27cbc3f242dbdf7ff4e76be http://b/issue?id=2333376
-rw-r--r--Android.mk4
-rw-r--r--src/core/SkBlitRow_D16.cpp23
-rw-r--r--src/opts/SkBlitRow_opts_arm.cpp25
-rw-r--r--tests/Android.mk1
-rw-r--r--tests/BitmapCopyTest.cpp184
-rw-r--r--tests/BlitRowTest.cpp158
-rw-r--r--tests/ClipperTest.cpp89
-rw-r--r--tests/PaintTest.cpp43
-rw-r--r--tests/ParsePathTest.cpp58
-rw-r--r--tests/TestSize.cpp60
-rw-r--r--tests/skia_test.cpp12
11 files changed, 612 insertions, 45 deletions
diff --git a/Android.mk b/Android.mk
index d7b8444658..a418776e18 100644
--- a/Android.mk
+++ b/Android.mk
@@ -280,3 +280,7 @@ include $(BASE_PATH)/bench/Android.mk
# golden-master (fidelity / regression test)
include $(BASE_PATH)/gm/Android.mk
+
+# unit-tests
+include $(BASE_PATH)/tests/Android.mk
+
diff --git a/src/core/SkBlitRow_D16.cpp b/src/core/SkBlitRow_D16.cpp
index 07c42ceb0b..72c9d527dc 100644
--- a/src/core/SkBlitRow_D16.cpp
+++ b/src/core/SkBlitRow_D16.cpp
@@ -63,27 +63,16 @@ static void S32A_D565_Blend(uint16_t* SK_RESTRICT dst,
SkASSERT(255 > alpha);
if (count > 0) {
- int src_scale = SkAlpha255To256(alpha);
do {
SkPMColor sc = *src++;
SkPMColorAssert(sc);
- if (sc)
- {
+ if (sc) {
uint16_t dc = *dst;
- unsigned sa = SkGetPackedA32(sc);
- unsigned dr, dg, db;
-
- if (sa == 255) {
- dr = SkAlphaBlend(SkPacked32ToR16(sc), SkGetPackedR16(dc), src_scale);
- dg = SkAlphaBlend(SkPacked32ToG16(sc), SkGetPackedG16(dc), src_scale);
- db = SkAlphaBlend(SkPacked32ToB16(sc), SkGetPackedB16(dc), src_scale);
- } else {
- unsigned dst_scale = 255 - SkAlphaMul(sa, src_scale);
- dr = (SkPacked32ToR16(sc) * src_scale + SkGetPackedR16(dc) * dst_scale) >> 8;
- dg = (SkPacked32ToG16(sc) * src_scale + SkGetPackedG16(dc) * dst_scale) >> 8;
- db = (SkPacked32ToB16(sc) * src_scale + SkGetPackedB16(dc) * dst_scale) >> 8;
- }
- *dst = SkPackRGB16(dr, dg, db);
+ unsigned dst_scale = 255 - SkMulDiv255Round(SkGetPackedA32(sc), alpha);
+ unsigned dr = SkMulS16(SkPacked32ToR16(sc), alpha) + SkMulS16(SkGetPackedR16(dc), dst_scale);
+ unsigned dg = SkMulS16(SkPacked32ToG16(sc), alpha) + SkMulS16(SkGetPackedG16(dc), dst_scale);
+ unsigned db = SkMulS16(SkPacked32ToB16(sc), alpha) + SkMulS16(SkGetPackedB16(dc), dst_scale);
+ *dst = SkPackRGB16(SkDiv255Round(dr), SkDiv255Round(dg), SkDiv255Round(db));
}
dst += 1;
} while (--count != 0);
diff --git a/src/opts/SkBlitRow_opts_arm.cpp b/src/opts/SkBlitRow_opts_arm.cpp
index 78fc907606..5b6ce7effc 100644
--- a/src/opts/SkBlitRow_opts_arm.cpp
+++ b/src/opts/SkBlitRow_opts_arm.cpp
@@ -281,23 +281,13 @@ static void S32A_D565_Blend_neon(uint16_t* SK_RESTRICT dst,
if (count > 0) {
do {
SkPMColor sc = *src++;
- if (sc)
- {
+ if (sc) {
uint16_t dc = *dst;
- unsigned sa = SkGetPackedA32(sc);
- unsigned dr, dg, db;
-
- if (sa == 255) {
- dr = SkAlphaBlend(SkPacked32ToR16(sc), SkGetPackedR16(dc), alpha);
- dg = SkAlphaBlend(SkPacked32ToG16(sc), SkGetPackedG16(dc), alpha);
- db = SkAlphaBlend(SkPacked32ToB16(sc), SkGetPackedB16(dc), alpha);
- } else {
- unsigned dst_scale = 255 - SkAlphaMul(sa, alpha);
- dr = (SkPacked32ToR16(sc) * alpha + SkGetPackedR16(dc) * dst_scale) >> 8;
- dg = (SkPacked32ToG16(sc) * alpha + SkGetPackedG16(dc) * dst_scale) >> 8;
- db = (SkPacked32ToB16(sc) * alpha + SkGetPackedB16(dc) * dst_scale) >> 8;
- }
- *dst = SkPackRGB16(dr, dg, db);
+ unsigned dst_scale = 255 - SkMulDiv255Round(SkGetPackedA32(sc), alpha);
+ unsigned dr = SkMulS16(SkPacked32ToR16(sc), alpha) + SkMulS16(SkGetPackedR16(dc), dst_scale);
+ unsigned dg = SkMulS16(SkPacked32ToG16(sc), alpha) + SkMulS16(SkGetPackedG16(dc), dst_scale);
+ unsigned db = SkMulS16(SkPacked32ToB16(sc), alpha) + SkMulS16(SkGetPackedB16(dc), dst_scale);
+ *dst = SkPackRGB16(SkDiv255Round(dr), SkDiv255Round(dg), SkDiv255Round(db));
}
dst += 1;
} while (--count != 0);
@@ -988,7 +978,8 @@ static const SkBlitRow::Proc platform_565_procs[] = {
S32_D565_Opaque_PROC,
S32_D565_Blend_PROC,
S32A_D565_Opaque_PROC,
- S32A_D565_Blend_PROC,
+ // fails to treat src==0 as a no-op. see BlitRowTest.cpp
+ NULL, // S32A_D565_Blend_PROC,
// dither
S32_D565_Opaque_Dither_PROC,
diff --git a/tests/Android.mk b/tests/Android.mk
index 9421f8b697..efcceae492 100644
--- a/tests/Android.mk
+++ b/tests/Android.mk
@@ -3,6 +3,7 @@ include $(CLEAR_VARS)
LOCAL_SRC_FILES:= \
+ BlitRowTest.cpp \
GeometryTest.cpp \
MathTest.cpp \
MatrixTest.cpp \
diff --git a/tests/BitmapCopyTest.cpp b/tests/BitmapCopyTest.cpp
new file mode 100644
index 0000000000..be3850e9be
--- /dev/null
+++ b/tests/BitmapCopyTest.cpp
@@ -0,0 +1,184 @@
+#include "Test.h"
+#include "SkBitmap.h"
+#include "SkRect.h"
+
+static const char* boolStr(bool value) {
+ return value ? "true" : "false";
+}
+
+// these are in the same order as the SkBitmap::Config enum
+static const char* gConfigName[] = {
+ "None", "A1", "A8", "Index8", "565", "4444", "8888", "RLE_Index8"
+};
+
+static void report_opaqueness(skiatest::Reporter* reporter, const SkBitmap& src,
+ const SkBitmap& dst) {
+ SkString str;
+ str.printf("src %s opaque:%d, dst %s opaque:%d",
+ gConfigName[src.config()], src.isOpaque(),
+ gConfigName[dst.config()], dst.isOpaque());
+ reporter->reportFailed(str);
+}
+
+static bool canHaveAlpha(SkBitmap::Config config) {
+ return config != SkBitmap::kRGB_565_Config;
+}
+
+// copyTo() should preserve isOpaque when it makes sense
+static void test_isOpaque(skiatest::Reporter* reporter, const SkBitmap& src,
+ SkBitmap::Config dstConfig) {
+ SkBitmap bitmap(src);
+ SkBitmap dst;
+
+ // we need the lock so that we get a valid colorTable (when available)
+ SkAutoLockPixels alp(bitmap);
+ SkColorTable* ctable = bitmap.getColorTable();
+ unsigned ctableFlags = ctable ? ctable->getFlags() : 0;
+
+ if (canHaveAlpha(bitmap.config()) && canHaveAlpha(dstConfig)) {
+ bitmap.setIsOpaque(false);
+ if (ctable) {
+ ctable->setFlags(ctableFlags & ~SkColorTable::kColorsAreOpaque_Flag);
+ }
+ REPORTER_ASSERT(reporter, bitmap.copyTo(&dst, dstConfig));
+ REPORTER_ASSERT(reporter, dst.config() == dstConfig);
+ if (bitmap.isOpaque() != dst.isOpaque()) {
+ report_opaqueness(reporter, bitmap, dst);
+ }
+ }
+
+ bitmap.setIsOpaque(true);
+ if (ctable) {
+ ctable->setFlags(ctableFlags | SkColorTable::kColorsAreOpaque_Flag);
+ }
+ REPORTER_ASSERT(reporter, bitmap.copyTo(&dst, dstConfig));
+ REPORTER_ASSERT(reporter, dst.config() == dstConfig);
+ if (bitmap.isOpaque() != dst.isOpaque()) {
+ report_opaqueness(reporter, bitmap, dst);
+ }
+
+ if (ctable) {
+ ctable->setFlags(ctableFlags);
+ }
+}
+
+static void init_src(const SkBitmap& bitmap) {
+ SkAutoLockPixels lock(bitmap);
+ if (bitmap.getPixels()) {
+ memset(bitmap.getPixels(), 4, bitmap.getSize());
+ }
+}
+
+SkColorTable* init_ctable() {
+ static const SkColor colors[] = {
+ SK_ColorBLACK, SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE, SK_ColorWHITE
+ };
+ return new SkColorTable(colors, SK_ARRAY_COUNT(colors));
+}
+
+struct Pair {
+ SkBitmap::Config fConfig;
+ const char* fValid;
+};
+
+static void TestBitmapCopy(skiatest::Reporter* reporter) {
+ static const Pair gPairs[] = {
+ { SkBitmap::kNo_Config, "00000000" },
+ { SkBitmap::kA1_Config, "01000000" },
+ { SkBitmap::kA8_Config, "00101110" },
+ { SkBitmap::kIndex8_Config, "00111110" },
+ { SkBitmap::kRGB_565_Config, "00101110" },
+ { SkBitmap::kARGB_4444_Config, "00101110" },
+ { SkBitmap::kARGB_8888_Config, "00101110" },
+// TODO: create valid RLE bitmap to test with
+ // { SkBitmap::kRLE_Index8_Config, "00101111" }
+ };
+
+ const int W = 20;
+ const int H = 33;
+
+ for (size_t i = 0; i < SK_ARRAY_COUNT(gPairs); i++) {
+ for (size_t j = 0; j < SK_ARRAY_COUNT(gPairs); j++) {
+ SkBitmap src, dst;
+ SkColorTable* ct = NULL;
+
+ src.setConfig(gPairs[i].fConfig, W, H);
+ if (SkBitmap::kIndex8_Config == src.config() ||
+ SkBitmap::kRLE_Index8_Config == src.config()) {
+ ct = init_ctable();
+ }
+ src.allocPixels(ct);
+ SkSafeUnref(ct);
+
+ init_src(src);
+ bool success = src.copyTo(&dst, gPairs[j].fConfig);
+ bool expected = gPairs[i].fValid[j] != '0';
+ if (success != expected) {
+ SkString str;
+ str.printf("SkBitmap::copyTo from %s to %s. expected %s returned %s",
+ gConfigName[i], gConfigName[j], boolStr(expected),
+ boolStr(success));
+ reporter->reportFailed(str);
+ }
+
+ bool canSucceed = src.canCopyTo(gPairs[j].fConfig);
+ if (success != canSucceed) {
+ SkString str;
+ str.printf("SkBitmap::copyTo from %s to %s. returned %s canCopyTo %s",
+ gConfigName[i], gConfigName[j], boolStr(success),
+ boolStr(canSucceed));
+ reporter->reportFailed(str);
+ }
+
+ if (success) {
+ REPORTER_ASSERT(reporter, src.width() == dst.width());
+ REPORTER_ASSERT(reporter, src.height() == dst.height());
+ REPORTER_ASSERT(reporter, dst.config() == gPairs[j].fConfig);
+ test_isOpaque(reporter, src, dst.config());
+ if (src.config() == dst.config()) {
+ SkAutoLockPixels srcLock(src);
+ SkAutoLockPixels dstLock(dst);
+ REPORTER_ASSERT(reporter, src.readyToDraw());
+ REPORTER_ASSERT(reporter, dst.readyToDraw());
+ const char* srcP = (const char*)src.getAddr(0, 0);
+ const char* dstP = (const char*)dst.getAddr(0, 0);
+ REPORTER_ASSERT(reporter, srcP != dstP);
+ REPORTER_ASSERT(reporter, !memcmp(srcP, dstP,
+ src.getSize()));
+ }
+ // test extractSubset
+ {
+ SkBitmap subset;
+ SkIRect r;
+ r.set(1, 1, 2, 2);
+ if (src.extractSubset(&subset, r)) {
+ REPORTER_ASSERT(reporter, subset.width() == 1);
+ REPORTER_ASSERT(reporter, subset.height() == 1);
+
+ SkBitmap copy;
+ REPORTER_ASSERT(reporter,
+ subset.copyTo(&copy, subset.config()));
+ REPORTER_ASSERT(reporter, copy.width() == 1);
+ REPORTER_ASSERT(reporter, copy.height() == 1);
+ REPORTER_ASSERT(reporter, copy.rowBytes() <= 4);
+
+ SkAutoLockPixels alp0(subset);
+ SkAutoLockPixels alp1(copy);
+ // they should both have, or both not-have, a colortable
+ bool hasCT = subset.getColorTable() != NULL;
+ REPORTER_ASSERT(reporter,
+ (copy.getColorTable() != NULL) == hasCT);
+ }
+ }
+ } else {
+ // dst should be unchanged from its initial state
+ REPORTER_ASSERT(reporter, dst.config() == SkBitmap::kNo_Config);
+ REPORTER_ASSERT(reporter, dst.width() == 0);
+ REPORTER_ASSERT(reporter, dst.height() == 0);
+ }
+ }
+ }
+}
+
+#include "TestClassDef.h"
+DEFINE_TESTCLASS("BitmapCopy", TestBitmapCopyClass, TestBitmapCopy)
diff --git a/tests/BlitRowTest.cpp b/tests/BlitRowTest.cpp
new file mode 100644
index 0000000000..3442b6bbea
--- /dev/null
+++ b/tests/BlitRowTest.cpp
@@ -0,0 +1,158 @@
+#include "Test.h"
+#include "SkBitmap.h"
+#include "SkCanvas.h"
+#include "SkColorPriv.h"
+#include "SkRect.h"
+
+static inline const char* boolStr(bool value) {
+ return value ? "true" : "false";
+}
+
+// these are in the same order as the SkBitmap::Config enum
+static const char* gConfigName[] = {
+ "None", "A1", "A8", "Index8", "565", "4444", "8888", "RLE_Index8"
+};
+
+/** Returns -1 on success, else the x coord of the first bad pixel, return its
+ value in bad
+ */
+typedef int (*Proc)(const void*, int width, uint32_t expected, uint32_t* bad);
+
+static int proc_32(const void* ptr, int w, uint32_t expected, uint32_t* bad) {
+ const SkPMColor* addr = static_cast<const SkPMColor*>(ptr);
+ for (int x = 0; x < w; x++) {
+ if (addr[x] != expected) {
+ *bad = addr[x];
+ return x;
+ }
+ }
+ return -1;
+}
+
+static int proc_16(const void* ptr, int w, uint32_t expected, uint32_t* bad) {
+ const uint16_t* addr = static_cast<const uint16_t*>(ptr);
+ for (int x = 0; x < w; x++) {
+ if (addr[x] != expected) {
+ *bad = addr[x];
+ return x;
+ }
+ }
+ return -1;
+}
+
+static int proc_8(const void* ptr, int w, uint32_t expected, uint32_t* bad) {
+ const SkPMColor* addr = static_cast<const SkPMColor*>(ptr);
+ for (int x = 0; x < w; x++) {
+ if (SkGetPackedA32(addr[x]) != expected) {
+ *bad = SkGetPackedA32(addr[x]);
+ return x;
+ }
+ }
+ return -1;
+}
+
+static int proc_bad(const void* ptr, int, uint32_t, uint32_t* bad) {
+ *bad = 0;
+ return 0;
+}
+
+static Proc find_proc(const SkBitmap& bm, SkPMColor expect32, uint16_t expect16,
+ uint8_t expect8, uint32_t* expect) {
+ switch (bm.config()) {
+ case SkBitmap::kARGB_8888_Config:
+ *expect = expect32;
+ return proc_32;
+ case SkBitmap::kARGB_4444_Config:
+ case SkBitmap::kRGB_565_Config:
+ *expect = expect16;
+ return proc_16;
+ case SkBitmap::kA8_Config:
+ *expect = expect8;
+ return proc_8;
+ default:
+ *expect = 0;
+ return proc_bad;
+ }
+}
+
+static bool check_color(const SkBitmap& bm, SkPMColor expect32,
+ uint16_t expect16, uint8_t expect8,
+ skiatest::Reporter* reporter) {
+ uint32_t expect;
+ Proc proc = find_proc(bm, expect32, expect16, expect8, &expect);
+ for (int y = 0; y < bm.height(); y++) {
+ uint32_t bad;
+ int x = proc(bm.getAddr(0, y), bm.width(), expect, &bad);
+ if (x >= 0) {
+ SkString str;
+ str.printf("BlitRow config=%s [%d %d] expected %x got %x",
+ gConfigName[bm.config()], x, y, expect, bad);
+ reporter->reportFailed(str);
+ return false;
+ }
+ }
+ return true;
+}
+
+static void TestBlitRow(skiatest::Reporter* reporter) {
+ static const int W = 256;
+
+ static const SkBitmap::Config gDstConfig[] = {
+ SkBitmap::kARGB_8888_Config,
+ SkBitmap::kRGB_565_Config,
+// SkBitmap::kARGB_4444_Config,
+// SkBitmap::kA8_Config,
+ };
+
+ static const struct {
+ SkColor fSrc;
+ SkColor fDst;
+ SkPMColor fResult32;
+ uint16_t fResult16;
+ uint8_t fResult8;
+ } gSrcRec[] = {
+ { 0, 0, 0, 0, 0 },
+ { 0, 0xFFFFFFFF, SkPackARGB32(0xFF, 0xFF, 0xFF, 0xFF), 0xFFFF, 0xFF },
+ { 0xFFFFFFFF, 0, SkPackARGB32(0xFF, 0xFF, 0xFF, 0xFF), 0xFFFF, 0xFF },
+ { 0xFFFFFFFF, 0xFFFFFFFF, SkPackARGB32(0xFF, 0xFF, 0xFF, 0xFF), 0xFFFF, 0xFF },
+ };
+
+ SkPaint paint;
+ paint.setDither(true);
+
+ SkBitmap srcBM;
+ srcBM.setConfig(SkBitmap::kARGB_8888_Config, W, 1);
+ srcBM.allocPixels();
+
+ for (size_t i = 0; i < SK_ARRAY_COUNT(gDstConfig); i++) {
+ SkBitmap dstBM;
+ dstBM.setConfig(gDstConfig[i], W, 1);
+ dstBM.allocPixels();
+
+ SkCanvas canvas(dstBM);
+ for (size_t j = 0; j < SK_ARRAY_COUNT(gSrcRec); j++) {
+ srcBM.eraseColor(gSrcRec[j].fSrc);
+ dstBM.eraseColor(gSrcRec[j].fDst);
+
+ for (int k = 0; k < 4; k++) {
+ bool dither = (k & 1) != 0;
+ bool blend = (k & 2) != 0;
+ if (gSrcRec[j].fSrc != 0 && blend) {
+ // can't make a numerical promise about blending anything
+ // but 0
+ // continue;
+ }
+ paint.setDither(dither);
+ paint.setAlpha(blend ? 0x80 : 0xFF);
+ canvas.drawBitmap(srcBM, 0, 0, &paint);
+ if (!check_color(dstBM, gSrcRec[j].fResult32, gSrcRec[j].fResult16,
+ gSrcRec[j].fResult8, reporter)) {
+ SkDebugf("--- src index %d dither %d blend %d\n", j, dither, blend);
+ }
+ }
+ }
+ }
+}
+
+#include "TestClassDef.h"
+DEFINE_TESTCLASS("BlitRow", TestBlitRowClass, TestBlitRow)
diff --git a/tests/ClipperTest.cpp b/tests/ClipperTest.cpp
new file mode 100644
index 0000000000..66301fcfdf
--- /dev/null
+++ b/tests/ClipperTest.cpp
@@ -0,0 +1,89 @@
+#include "Test.h"
+#include "SkPath.h"
+#include "SkLineClipper.h"
+#include "SkEdgeClipper.h"
+
+static void test_intersectline(skiatest::Reporter* reporter) {
+ static const SkScalar L = 0;
+ static const SkScalar T = 0;
+ static const SkScalar R = SkIntToScalar(100);
+ static const SkScalar B = SkIntToScalar(100);
+ static const SkScalar CX = SkScalarHalf(L + R);
+ static const SkScalar CY = SkScalarHalf(T + B);
+ static const SkRect gR = { L, T, R, B };
+
+ size_t i;
+ SkPoint dst[2];
+
+ static const SkPoint gEmpty[] = {
+ // sides
+ { L, CY }, { L - 10, CY },
+ { R, CY }, { R + 10, CY },
+ { CX, T }, { CX, T - 10 },
+ { CX, B }, { CX, B + 10 },
+ // corners
+ { L, T }, { L - 10, T - 10 },
+ { L, B }, { L - 10, B + 10 },
+ { R, T }, { R + 10, T - 10 },
+ { R, B }, { R + 10, B + 10 },
+ };
+ for (i = 0; i < SK_ARRAY_COUNT(gEmpty); i += 2) {
+ bool valid = SkLineClipper::IntersectLine(&gEmpty[i], gR, dst);
+ if (valid) {
+ SkDebugf("----- [%d] %g %g -> %g %g\n", i/2, dst[0].fX, dst[0].fY, dst[1].fX, dst[1].fY);
+ }
+ REPORTER_ASSERT(reporter, !valid);
+ }
+
+ static const SkPoint gFull[] = {
+ // diagonals, chords
+ { L, T }, { R, B },
+ { L, B }, { R, T },
+ { CX, T }, { CX, B },
+ { L, CY }, { R, CY },
+ { CX, T }, { R, CY },
+ { CX, T }, { L, CY },
+ { L, CY }, { CX, B },
+ { R, CY }, { CX, B },
+ // edges
+ { L, T }, { L, B },
+ { R, T }, { R, B },
+ { L, T }, { R, T },
+ { L, B }, { R, B },
+ };
+ for (i = 0; i < SK_ARRAY_COUNT(gFull); i += 2) {
+ bool valid = SkLineClipper::IntersectLine(&gFull[i], gR, dst);
+ if (!valid || memcmp(&gFull[i], dst, sizeof(dst))) {
+ SkDebugf("++++ [%d] %g %g -> %g %g\n", i/2, dst[0].fX, dst[0].fY, dst[1].fX, dst[1].fY);
+ }
+ REPORTER_ASSERT(reporter, valid && !memcmp(&gFull[i], dst, sizeof(dst)));
+ }
+
+ static const SkPoint gPartial[] = {
+ { L - 10, CY }, { CX, CY }, { L, CY }, { CX, CY },
+ { CX, T - 10 }, { CX, CY }, { CX, T }, { CX, CY },
+ { R + 10, CY }, { CX, CY }, { R, CY }, { CX, CY },
+ { CX, B + 10 }, { CX, CY }, { CX, B }, { CX, CY },
+ // extended edges
+ { L, T - 10 }, { L, B + 10 }, { L, T }, { L, B },
+ { R, T - 10 }, { R, B + 10 }, { R, T }, { R, B },
+ { L - 10, T }, { R + 10, T }, { L, T }, { R, T },
+ { L - 10, B }, { R + 10, B }, { L, B }, { R, B },
+ };
+ for (i = 0; i < SK_ARRAY_COUNT(gPartial); i += 4) {
+ bool valid = SkLineClipper::IntersectLine(&gPartial[i], gR, dst);
+ if (!valid || memcmp(&gPartial[i+2], dst, sizeof(dst))) {
+ SkDebugf("++++ [%d] %g %g -> %g %g\n", i/2, dst[0].fX, dst[0].fY, dst[1].fX, dst[1].fY);
+ }
+ REPORTER_ASSERT(reporter, valid &&
+ !memcmp(&gPartial[i+2], dst, sizeof(dst)));
+ }
+
+}
+
+void TestClipper(skiatest::Reporter* reporter) {
+ test_intersectline(reporter);
+}
+
+#include "TestClassDef.h"
+DEFINE_TESTCLASS("Clipper", TestClipperClass, TestClipper)
diff --git a/tests/PaintTest.cpp b/tests/PaintTest.cpp
new file mode 100644
index 0000000000..4e6c8b9d59
--- /dev/null
+++ b/tests/PaintTest.cpp
@@ -0,0 +1,43 @@
+#include "Test.h"
+#include "SkPath.h"
+#include "SkPaint.h"
+
+// found and fixed for webkit: mishandling when we hit recursion limit on
+// mostly degenerate cubic flatness test
+static void regression_cubic(skiatest::Reporter* reporter) {
+ SkPath path, stroke;
+ SkPaint paint;
+
+ path.moveTo(460.2881309415525, 303.250847066498);
+ path.cubicTo(463.36378422175284, 302.1169735073363,
+ 456.32239330810046, 304.720354932878,
+ 453.15255460013304, 305.788586869862);
+
+ SkRect fillR, strokeR;
+ fillR = path.getBounds();
+
+ paint.setStyle(SkPaint::kStroke_Style);
+ paint.setStrokeWidth(SkIntToScalar(2));
+ paint.getFillPath(path, &stroke);
+ strokeR = stroke.getBounds();
+
+ SkRect maxR = fillR;
+ SkScalar miter = SkMaxScalar(SK_Scalar1, paint.getStrokeMiter());
+ SkScalar inset = paint.getStrokeJoin() == SkPaint::kMiter_Join ?
+ SkScalarMul(paint.getStrokeWidth(), miter) :
+ paint.getStrokeWidth();
+ maxR.inset(-inset, -inset);
+
+ // test that our stroke didn't explode
+ REPORTER_ASSERT(reporter, maxR.contains(strokeR));
+}
+
+static void TestPaint(skiatest::Reporter* reporter) {
+ // TODO add general paint tests
+
+ // regression tests
+ regression_cubic(reporter);
+}
+
+#include "TestClassDef.h"
+DEFINE_TESTCLASS("Paint", TestPaintClass, TestPaint)
diff --git a/tests/ParsePathTest.cpp b/tests/ParsePathTest.cpp
new file mode 100644
index 0000000000..917b0cb538
--- /dev/null
+++ b/tests/ParsePathTest.cpp
@@ -0,0 +1,58 @@
+#include "Test.h"
+#include "SkParsePath.h"
+
+static void test_to_from(skiatest::Reporter* reporter, const SkPath& path) {
+ SkString str, str2;
+ SkParsePath::ToSVGString(path, &str);
+
+ SkPath path2;
+ bool success = SkParsePath::FromSVGString(str.c_str(), &path2);
+ REPORTER_ASSERT(reporter, success);
+
+ SkParsePath::ToSVGString(path2, &str2);
+ REPORTER_ASSERT(reporter, str == str2);
+#if 0 // closed paths are not equal, the iter explicitly gives the closing
+ // edge, even if it is not in the path.
+ REPORTER_ASSERT(reporter, path == path2);
+ if (path != path2) {
+ SkDebugf("str1=%s\nstr2=%s\n", str.c_str(), str2.c_str());
+ }
+#endif
+}
+
+static void TestParsePath(skiatest::Reporter* reporter) {
+ static const struct {
+ const char* fStr;
+ SkRect fBounds;
+ } gRec[] = {
+ { "", { 0, 0, 0, 0 } },
+ { "M0,0L10,10", { 0, 0, SkIntToScalar(10), SkIntToScalar(10) } },
+ { "M-5.5,-0.5 Q 0 0 6,6.50",
+ { SkFloatToScalar(-5.5f), SkFloatToScalar(-0.5f),
+ SkFloatToScalar(6), SkFloatToScalar(6.5f) } }
+ };
+
+ for (size_t i = 0; i < SK_ARRAY_COUNT(gRec); i++) {
+ SkPath path;
+ bool success = SkParsePath::FromSVGString(gRec[i].fStr, &path);
+ REPORTER_ASSERT(reporter, success);
+ const SkRect& expectedBounds = gRec[i].fBounds;
+ const SkRect& pathBounds = path.getBounds();
+ REPORTER_ASSERT(reporter, expectedBounds == pathBounds);
+
+ test_to_from(reporter, path);
+ }
+
+ SkRect r;
+ r.set(0, 0, SkFloatToScalar(10), SkFloatToScalar(10.5));
+ SkPath p;
+ p.addRect(r);
+ test_to_from(reporter, p);
+ p.addOval(r);
+ test_to_from(reporter, p);
+ p.addRoundRect(r, SkFloatToScalar(4), SkFloatToScalar(4.5));
+ test_to_from(reporter, p);
+}
+
+#include "TestClassDef.h"
+DEFINE_TESTCLASS("ParsePath", ParsePathClass, TestParsePath)
diff --git a/tests/TestSize.cpp b/tests/TestSize.cpp
new file mode 100644
index 0000000000..6551509e8d
--- /dev/null
+++ b/tests/TestSize.cpp
@@ -0,0 +1,60 @@
+#include "Test.h"
+#include "SkSize.h"
+
+static void TestISize(skiatest::Reporter* reporter) {
+ SkISize a, b;
+
+ a.set(0, 0);
+ REPORTER_ASSERT(reporter, a.isEmpty());
+ a.set(5, -5);
+ REPORTER_ASSERT(reporter, a.isEmpty());
+ a.clampNegToZero();
+ REPORTER_ASSERT(reporter, a.isEmpty());
+ b.set(5, 0);
+ REPORTER_ASSERT(reporter, a == b);
+
+ a.set(3, 5);
+ REPORTER_ASSERT(reporter, !a.isEmpty());
+ b = a;
+ REPORTER_ASSERT(reporter, !b.isEmpty());
+ REPORTER_ASSERT(reporter, a == b);
+ REPORTER_ASSERT(reporter, !(a != b));
+ REPORTER_ASSERT(reporter,
+ a.fWidth == b.fWidth && a.fHeight == b.fHeight);
+}
+
+static void TestSize(skiatest::Reporter* reporter) {
+ TestISize(reporter);
+
+ SkSize a, b;
+ int ix = 5;
+ int iy = 3;
+ SkScalar x = SkIntToScalar(ix);
+ SkScalar y = SkIntToScalar(iy);
+
+ a.set(0, 0);
+ REPORTER_ASSERT(reporter, a.isEmpty());
+ a.set(x, -x);
+ REPORTER_ASSERT(reporter, a.isEmpty());
+ a.clampNegToZero();
+ REPORTER_ASSERT(reporter, a.isEmpty());
+ b.set(x, 0);
+ REPORTER_ASSERT(reporter, a == b);
+
+ a.set(y, x);
+ REPORTER_ASSERT(reporter, !a.isEmpty());
+ b = a;
+ REPORTER_ASSERT(reporter, !b.isEmpty());
+ REPORTER_ASSERT(reporter, a == b);
+ REPORTER_ASSERT(reporter, !(a != b));
+ REPORTER_ASSERT(reporter,
+ a.fWidth == b.fWidth && a.fHeight == b.fHeight);
+
+ SkISize ia;
+ ia.set(ix, iy);
+ a.set(x, y);
+ REPORTER_ASSERT(reporter, a.round() == ia);
+};
+
+#include "TestClassDef.h"
+DEFINE_TESTCLASS("Size", TestSizeClass, TestSize)
diff --git a/tests/skia_test.cpp b/tests/skia_test.cpp
index 91b41edf13..25248a3615 100644
--- a/tests/skia_test.cpp
+++ b/tests/skia_test.cpp
@@ -95,19 +95,9 @@ private:
bool fAndroidMode;
};
-class SkAutoGraphics {
-public:
- SkAutoGraphics() {
- SkGraphics::Init();
- }
- ~SkAutoGraphics() {
- SkGraphics::Term();
- }
-};
-
int main (int argc, char * const argv[]) {
SkAutoGraphics ag;
-
+
bool androidMode = false;
for (int i = 1; i < argc; i++) {
if (!strcmp(argv[i], "-android")) {