aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--include/core/SkMath.h9
-rw-r--r--include/core/SkMatrix.h7
-rw-r--r--include/core/SkUserConfig.h2
-rw-r--r--include/core/SkUtils.h7
-rw-r--r--samplecode/SampleTextOnPath.cpp128
-rw-r--r--src/core/SkGraphics.cpp3
-rw-r--r--src/core/SkMath.cpp393
-rw-r--r--src/core/SkMatrix.cpp82
-rw-r--r--src/core/SkUtils.cpp123
-rw-r--r--tests/MathTest.cpp400
-rw-r--r--tests/MatrixTest.cpp119
-rw-r--r--tests/PackBitsTest.cpp144
-rw-r--r--tests/Test.cpp60
-rw-r--r--tests/Test.h98
-rw-r--r--tests/TestXCode/Tests.xcodeproj/project.pbxproj333
-rw-r--r--tests/UtilsTest.cpp130
-rw-r--r--tests/main.cpp67
17 files changed, 1352 insertions, 753 deletions
diff --git a/include/core/SkMath.h b/include/core/SkMath.h
index 5c2b475ef9..683a1ac303 100644
--- a/include/core/SkMath.h
+++ b/include/core/SkMath.h
@@ -217,14 +217,5 @@ static inline unsigned SkMul16ShiftRound(unsigned a, unsigned b, int shift) {
return (prod + (prod >> shift)) >> shift;
}
-///////////////////////////////////////////////////////////////////////////////
-
-#ifdef SK_DEBUG
- class SkMath {
- public:
- static void UnitTest();
- };
-#endif
-
#endif
diff --git a/include/core/SkMatrix.h b/include/core/SkMatrix.h
index 2b25dcada3..aa008cb2d9 100644
--- a/include/core/SkMatrix.h
+++ b/include/core/SkMatrix.h
@@ -403,13 +403,6 @@ public:
void dump() const;
void toDumpString(SkString*) const;
-#ifdef SK_DEBUG
- /** @cond UNIT_TEST */
-
- static void UnitTest();
- /** @endcond */
-#endif
-
private:
enum {
/** Set if the matrix will map a rectangle to another rectangle. This
diff --git a/include/core/SkUserConfig.h b/include/core/SkUserConfig.h
index a3c34a3ba7..498eb8f62b 100644
--- a/include/core/SkUserConfig.h
+++ b/include/core/SkUserConfig.h
@@ -118,7 +118,7 @@
so this flag is optional.
*/
#ifdef SK_DEBUG
-//#define SK_SUPPORT_UNITTEST
+#define SK_SUPPORT_UNITTEST
#endif
#endif
diff --git a/include/core/SkUtils.h b/include/core/SkUtils.h
index f3e33417f1..9f3b1d6f36 100644
--- a/include/core/SkUtils.h
+++ b/include/core/SkUtils.h
@@ -96,13 +96,6 @@ size_t SkUTF16_FromUnichar(SkUnichar uni, uint16_t utf16[] = NULL);
size_t SkUTF16_ToUTF8(const uint16_t utf16[], int numberOf16BitValues,
char utf8[] = NULL);
-class SkUtils {
-public:
-#ifdef SK_DEBUG
- static void UnitTest();
-#endif
-};
-
///////////////////////////////////////////////////////////////////////////////
class SkAutoTrace {
diff --git a/samplecode/SampleTextOnPath.cpp b/samplecode/SampleTextOnPath.cpp
index 97b4e8e340..aec8fd6360 100644
--- a/samplecode/SampleTextOnPath.cpp
+++ b/samplecode/SampleTextOnPath.cpp
@@ -304,137 +304,9 @@ private:
typedef SkView INHERITED;
};
-static const uint16_t gTest0[] = { 0, 0, 1, 1 };
-static const uint16_t gTest1[] = { 1, 2, 3, 4, 5, 6 };
-static const uint16_t gTest2[] = { 0, 0, 0, 1, 2, 3, 3, 3 };
-static const uint16_t gTest3[] = { 0, 0, 0, 0, 0, 0, 1, 2, 3, 3, 3, 0, 0, 1 };
-
-#include "SkRandom.h"
-static SkRandom gRand;
-static void rand_fill(uint16_t buffer[], int count) {
- for (int i = 0; i < count; i++)
- buffer[i] = (uint16_t)gRand.nextU();
-}
-
-static void test_pack16() {
- static const struct {
- const uint16_t* fSrc;
- int fCount;
- } gTests[] = {
- { gTest0, SK_ARRAY_COUNT(gTest0) },
- { gTest1, SK_ARRAY_COUNT(gTest1) },
- { gTest2, SK_ARRAY_COUNT(gTest2) },
- { gTest3, SK_ARRAY_COUNT(gTest3) }
- };
-
- for (size_t i = 0; i < SK_ARRAY_COUNT(gTests); i++) {
- uint8_t dst[100];
- size_t dstSize = SkPackBits::Pack16(gTests[i].fSrc,
- gTests[i].fCount, dst);
- printf("Test[%d] orig size = %d, dst size = %d",
- i, gTests[i].fCount, (int)dstSize);
- uint16_t src[100];
- int srcCount = SkPackBits::Unpack16(dst, dstSize, src);
- printf(", src size = %d", srcCount);
- bool match = gTests[i].fCount == srcCount && memcmp(gTests[i].fSrc, src,
- gTests[i].fCount * sizeof(uint16_t)) == 0;
- printf(", match = %d\n", match);
- }
-
- for (int n = 1000; n; n--) {
- size_t size = 50;
- uint16_t src[100], src2[100];
- uint8_t dst[200];
- rand_fill(src, size);
-
- size_t dstSize = SkPackBits::Pack16(src, size, dst);
- size_t maxSize = SkPackBits::ComputeMaxSize16(size);
- SkASSERT(maxSize >= dstSize);
-
- int srcCount = SkPackBits::Unpack16(dst, dstSize, src2);
- SkASSERT(size == srcCount);
- bool match = memcmp(src, src2, size * sizeof(uint16_t)) == 0;
- SkASSERT(match);
- }
-}
-
-static const uint8_t gTest80[] = { 0, 0, 1, 1 };
-static const uint8_t gTest81[] = { 1, 2, 3, 4, 5, 6 };
-static const uint8_t gTest82[] = { 0, 0, 0, 1, 2, 3, 3, 3 };
-static const uint8_t gTest83[] = { 0, 0, 0, 0, 0, 0, 1, 2, 3, 3, 3, 0, 0, 1 };
-static const uint8_t gTest84[] = { 1, 0, 3, 0, 0, 0, 2, 1, 1, 2 };
-
-static void rand_fill(uint8_t buffer[], int count) {
- for (int i = 0; i < count; i++)
- buffer[i] = (uint8_t)((gRand.nextU() >> 8) & 0x3);
-}
-
-static void test_pack8() {
- static const struct {
- const uint8_t* fSrc;
- int fCount;
- } gTests[] = {
- { gTest80, SK_ARRAY_COUNT(gTest80) },
- { gTest81, SK_ARRAY_COUNT(gTest81) },
- { gTest82, SK_ARRAY_COUNT(gTest82) },
- { gTest83, SK_ARRAY_COUNT(gTest83) },
- { gTest84, SK_ARRAY_COUNT(gTest84) }
- };
-
- for (size_t i = 4; i < SK_ARRAY_COUNT(gTests); i++) {
- uint8_t dst[100];
- size_t maxSize = SkPackBits::ComputeMaxSize8(gTests[i].fCount);
- size_t dstSize = SkPackBits::Pack8(gTests[i].fSrc,
- gTests[i].fCount, dst);
- SkASSERT(dstSize <= maxSize);
- printf("Test[%d] orig size = %d, dst size = %d", i,
- gTests[i].fCount, (int)dstSize);
- uint8_t src[100];
- int srcCount = SkPackBits::Unpack8(dst, dstSize, src);
- printf(", src size = %d", srcCount);
- bool match = gTests[i].fCount == srcCount &&
- memcmp(gTests[i].fSrc, src,
- gTests[i].fCount * sizeof(uint8_t)) == 0;
- printf(", match = %d\n", match);
- }
-
- for (size_t size = 1; size <= 512; size += 1) {
- for (int n = 200; n; n--) {
- uint8_t src[600], src2[600];
- uint8_t dst[600];
- rand_fill(src, size);
-
- size_t dstSize = SkPackBits::Pack8(src, size, dst);
- size_t maxSize = SkPackBits::ComputeMaxSize8(size);
- SkASSERT(maxSize >= dstSize);
-
- int srcCount = SkPackBits::Unpack8(dst, dstSize, src2);
- SkASSERT(size == srcCount);
- bool match = memcmp(src, src2, size * sizeof(uint8_t)) == 0;
- SkASSERT(match);
-
- for (int j = 0; j < 200; j++) {
- size_t skip = gRand.nextU() % size;
- size_t write = gRand.nextU() % size;
- if (skip + write > size) {
- write = size - skip;
- }
- SkPackBits::Unpack8(src, skip, write, dst);
- bool match = memcmp(src, src2 + skip, write) == 0;
- SkASSERT(match);
- }
- }
- }
-}
-
//////////////////////////////////////////////////////////////////////////////
static SkView* MyFactory() {
- static bool gOnce;
- if (!gOnce) {
-// test_pack8();
- gOnce = true;
- }
return new TextOnPathView;
}
diff --git a/src/core/SkGraphics.cpp b/src/core/SkGraphics.cpp
index 7536ca8edc..053d9f0ec6 100644
--- a/src/core/SkGraphics.cpp
+++ b/src/core/SkGraphics.cpp
@@ -345,10 +345,7 @@ void SkGraphics::Init(bool runUnitTests)
void (*fUnitTest)();
} gUnitTests[] = {
unittestline(Sk64),
- unittestline(SkMath),
- unittestline(SkUtils),
unittestline(SkString),
- unittestline(SkMatrix),
unittestline(SkGeometry),
unittestline(SkPath),
unittestline(SkPathMeasure),
diff --git a/src/core/SkMath.cpp b/src/core/SkMath.cpp
index e0babeb5e7..649b51890a 100644
--- a/src/core/SkMath.cpp
+++ b/src/core/SkMath.cpp
@@ -543,396 +543,3 @@ SkFixed SkFixedATan2(SkFixed y, SkFixed x) { return SkCordicATan2(y, x); }
SkFixed SkFixedExp(SkFixed x) { return SkCordicExp(x); }
SkFixed SkFixedLog(SkFixed x) { return SkCordicLog(x); }
-///////////////////////////////////////////////////////////////////////////////
-///////////////////////////////////////////////////////////////////////////////
-
-#ifdef SK_DEBUG
-
-#include "SkRandom.h"
-
-#if defined(SkLONGLONG) && defined(SK_SUPPORT_UNITTEST)
-static int symmetric_fixmul(int a, int b) {
- int sa = SkExtractSign(a);
- int sb = SkExtractSign(b);
-
- a = SkApplySign(a, sa);
- b = SkApplySign(b, sb);
-
-#if 1
- int c = (int)(((SkLONGLONG)a * b) >> 16);
-
- return SkApplySign(c, sa ^ sb);
-#else
- SkLONGLONG ab = (SkLONGLONG)a * b;
- if (sa ^ sb) {
- ab = -ab;
- }
- return ab >> 16;
-#endif
-}
-#endif
-
-#include "SkPoint.h"
-
-#ifdef SK_SUPPORT_UNITTEST
-static void check_length(const SkPoint& p, SkScalar targetLen) {
-#ifdef SK_CAN_USE_FLOAT
- float x = SkScalarToFloat(p.fX);
- float y = SkScalarToFloat(p.fY);
- float len = sk_float_sqrt(x*x + y*y);
-
- len /= SkScalarToFloat(targetLen);
-
- SkASSERT(len > 0.999f && len < 1.001f);
-#endif
-}
-#endif
-
-#if defined(SK_CAN_USE_FLOAT) && defined(SK_SUPPORT_UNITTEST)
-
-static float nextFloat(SkRandom& rand) {
- SkFloatIntUnion data;
- data.fSignBitInt = rand.nextU();
- return data.fFloat;
-}
-
-/* returns true if a == b as resulting from (int)x. Since it is undefined
- what to do if the float exceeds 2^32-1, we check for that explicitly.
-*/
-static bool equal_float_native_skia(float x, uint32_t ni, uint32_t si) {
- if (!(x == x)) { // NAN
- return si == SK_MaxS32 || si == SK_MinS32;
- }
- // for out of range, C is undefined, but skia always should return NaN32
- if (x > SK_MaxS32) {
- return si == SK_MaxS32;
- }
- if (x < -SK_MaxS32) {
- return si == SK_MinS32;
- }
- return si == ni;
-}
-
-static void assert_float_equal(const char op[], float x, uint32_t ni,
- uint32_t si) {
- if (!equal_float_native_skia(x, ni, si)) {
- SkDebugf("-- %s float %g bits %x native %x skia %x\n", op, x, ni, si);
- SkASSERT(!"oops");
- }
-}
-
-static void test_float_cast(float x) {
- int ix = (int)x;
- int iix = SkFloatToIntCast(x);
- assert_float_equal("cast", x, ix, iix);
-}
-
-static void test_float_floor(float x) {
- int ix = (int)floor(x);
- int iix = SkFloatToIntFloor(x);
- assert_float_equal("floor", x, ix, iix);
-}
-
-static void test_float_round(float x) {
- double xx = x + 0.5; // need intermediate double to avoid temp loss
- int ix = (int)floor(xx);
- int iix = SkFloatToIntRound(x);
- assert_float_equal("round", x, ix, iix);
-}
-
-static void test_float_ceil(float x) {
- int ix = (int)ceil(x);
- int iix = SkFloatToIntCeil(x);
- assert_float_equal("ceil", x, ix, iix);
-}
-
-static void test_float_conversions(float x) {
- test_float_cast(x);
- test_float_floor(x);
- test_float_round(x);
- test_float_ceil(x);
-}
-
-static void test_int2float(int ival) {
- float x0 = (float)ival;
- float x1 = SkIntToFloatCast(ival);
- float x2 = SkIntToFloatCast_NoOverflowCheck(ival);
- SkASSERT(x0 == x1);
- SkASSERT(x0 == x2);
-}
-
-static void unittest_fastfloat() {
- SkRandom rand;
- size_t i;
-
- static const float gFloats[] = {
- 0.f, 1.f, 0.5f, 0.499999f, 0.5000001f, 1.f/3,
- 0.000000001f, 1000000000.f, // doesn't overflow
- 0.0000000001f, 10000000000.f // does overflow
- };
- for (i = 0; i < SK_ARRAY_COUNT(gFloats); i++) {
-// SkDebugf("---- test floats %g %d\n", gFloats[i], (int)gFloats[i]);
- test_float_conversions(gFloats[i]);
- test_float_conversions(-gFloats[i]);
- }
-
- for (int outer = 0; outer < 100; outer++) {
- rand.setSeed(outer);
- for (i = 0; i < 100000; i++) {
- float x = nextFloat(rand);
- test_float_conversions(x);
- }
-
- test_int2float(0);
- test_int2float(1);
- test_int2float(-1);
- for (i = 0; i < 100000; i++) {
- // for now only test ints that are 24bits or less, since we don't
- // round (down) large ints the same as IEEE...
- int ival = rand.nextU() & 0xFFFFFF;
- test_int2float(ival);
- test_int2float(-ival);
- }
- }
-}
-
-#endif
-
-#ifdef SK_SUPPORT_UNITTEST
-static void test_muldiv255() {
-#ifdef SK_CAN_USE_FLOAT
- for (int a = 0; a <= 255; a++) {
- for (int b = 0; b <= 255; b++) {
- int ab = a * b;
- float s = ab / 255.0f;
- int round = (int)floorf(s + 0.5f);
- int trunc = (int)floorf(s);
-
- int iround = SkMulDiv255Round(a, b);
- int itrunc = SkMulDiv255Trunc(a, b);
-
- SkASSERT(iround == round);
- SkASSERT(itrunc == trunc);
-
- SkASSERT(itrunc <= iround);
- SkASSERT(iround <= a);
- SkASSERT(iround <= b);
- }
- }
-#endif
-}
-#endif
-
-void SkMath::UnitTest() {
-#ifdef SK_SUPPORT_UNITTEST
- int i;
- int32_t x;
- SkRandom rand;
-
- SkToS8(127); SkToS8(-128); SkToU8(255);
- SkToS16(32767); SkToS16(-32768); SkToU16(65535);
- SkToS32(2*1024*1024); SkToS32(-2*1024*1024); SkToU32(4*1024*1024);
-
- SkCordic_UnitTest();
-
- // these should assert
-#if 0
- SkToS8(128);
- SkToS8(-129);
- SkToU8(256);
- SkToU8(-5);
-
- SkToS16(32768);
- SkToS16(-32769);
- SkToU16(65536);
- SkToU16(-5);
-
- if (sizeof(size_t) > 4) {
- SkToS32(4*1024*1024);
- SkToS32(-4*1024*1024);
- SkToU32(5*1024*1024);
- SkToU32(-5);
- }
-#endif
-
- test_muldiv255();
-
-#ifdef SK_DEBUG
- {
- SkScalar x = SK_ScalarNaN;
- SkASSERT(SkScalarIsNaN(x));
- }
-#endif
-
- for (i = 1; i <= 10; i++) {
- x = SkCubeRootBits(i*i*i, 11);
- SkASSERT(x == i);
- }
-
- x = SkFixedSqrt(SK_Fixed1);
- SkASSERT(x == SK_Fixed1);
- x = SkFixedSqrt(SK_Fixed1/4);
- SkASSERT(x == SK_Fixed1/2);
- x = SkFixedSqrt(SK_Fixed1*4);
- SkASSERT(x == SK_Fixed1*2);
-
- x = SkFractSqrt(SK_Fract1);
- SkASSERT(x == SK_Fract1);
- x = SkFractSqrt(SK_Fract1/4);
- SkASSERT(x == SK_Fract1/2);
- x = SkFractSqrt(SK_Fract1/16);
- SkASSERT(x == SK_Fract1/4);
-
- for (i = 1; i < 100; i++) {
- x = SkFixedSqrt(SK_Fixed1 * i * i);
- SkASSERT(x == SK_Fixed1 * i);
- }
-
- for (i = 0; i < 1000; i++) {
- int value = rand.nextS16();
- int max = rand.nextU16();
-
- int clamp = SkClampMax(value, max);
- int clamp2 = value < 0 ? 0 : (value > max ? max : value);
- SkASSERT(clamp == clamp2);
- }
-
- for (i = 0; i < 100000; i++) {
- SkPoint p;
-
- p.setLength(rand.nextS(), rand.nextS(), SK_Scalar1);
- check_length(p, SK_Scalar1);
- p.setLength(rand.nextS() >> 13, rand.nextS() >> 13, SK_Scalar1);
- check_length(p, SK_Scalar1);
- }
-
- {
- SkFixed result = SkFixedDiv(100, 100);
- SkASSERT(result == SK_Fixed1);
- result = SkFixedDiv(1, SK_Fixed1);
- SkASSERT(result == 1);
- }
-
-#ifdef SK_CAN_USE_FLOAT
- unittest_fastfloat();
-#endif
-
-#ifdef SkLONGLONG
- for (i = 0; i < 100000; i++) {
- SkFixed numer = rand.nextS();
- SkFixed denom = rand.nextS();
- SkFixed result = SkFixedDiv(numer, denom);
- SkLONGLONG check = ((SkLONGLONG)numer << 16) / denom;
-
- (void)SkCLZ(numer);
- (void)SkCLZ(denom);
-
- SkASSERT(result != (SkFixed)SK_NaN32);
- if (check > SK_MaxS32) {
- check = SK_MaxS32;
- } else if (check < -SK_MaxS32) {
- check = SK_MinS32;
- }
- SkASSERT(result == (int32_t)check);
-
- result = SkFractDiv(numer, denom);
- check = ((SkLONGLONG)numer << 30) / denom;
-
- SkASSERT(result != (SkFixed)SK_NaN32);
- if (check > SK_MaxS32) {
- check = SK_MaxS32;
- } else if (check < -SK_MaxS32) {
- check = SK_MinS32;
- }
- SkASSERT(result == (int32_t)check);
-
- // make them <= 2^24, so we don't overflow in fixmul
- numer = numer << 8 >> 8;
- denom = denom << 8 >> 8;
-
- result = SkFixedMul(numer, denom);
- SkFixed r2 = symmetric_fixmul(numer, denom);
-// SkASSERT(result == r2);
-
- result = SkFixedMul(numer, numer);
- r2 = SkFixedSquare(numer);
- SkASSERT(result == r2);
-
-#ifdef SK_CAN_USE_FLOAT
- if (numer >= 0 && denom >= 0) {
- SkFixed mean = SkFixedMean(numer, denom);
- float fm = sk_float_sqrt(sk_float_abs(SkFixedToFloat(numer) * SkFixedToFloat(denom)));
- SkFixed mean2 = SkFloatToFixed(fm);
- int diff = SkAbs32(mean - mean2);
- SkASSERT(diff <= 1);
- }
-
- {
- SkFixed mod = SkFixedMod(numer, denom);
- float n = SkFixedToFloat(numer);
- float d = SkFixedToFloat(denom);
- float m = sk_float_mod(n, d);
-#if 0
- SkDebugf("%g mod %g = %g [%g]\n",
- SkFixedToFloat(numer), SkFixedToFloat(denom),
- SkFixedToFloat(mod), m);
-#endif
- SkASSERT(mod == 0 || (mod < 0) == (m < 0)); // ensure the same sign
- int diff = SkAbs32(mod - SkFloatToFixed(m));
- SkASSERT((diff >> 7) == 0);
- }
-#endif
- }
-#endif
-
-#ifdef SK_CAN_USE_FLOAT
- for (i = 0; i < 100000; i++) {
- SkFract x = rand.nextU() >> 1;
- double xx = (double)x / SK_Fract1;
- SkFract xr = SkFractSqrt(x);
- SkFract check = SkFloatToFract(sqrt(xx));
- SkASSERT(xr == check || xr == check-1 || xr == check+1);
-
- xr = SkFixedSqrt(x);
- xx = (double)x / SK_Fixed1;
- check = SkFloatToFixed(sqrt(xx));
- SkASSERT(xr == check || xr == check-1);
-
- xr = SkSqrt32(x);
- xx = (double)x;
- check = (int32_t)sqrt(xx);
- SkASSERT(xr == check || xr == check-1);
- }
-#endif
-
-#if !defined(SK_SCALAR_IS_FLOAT) && defined(SK_CAN_USE_FLOAT)
- {
- SkFixed s, c;
- s = SkFixedSinCos(0, &c);
- SkASSERT(s == 0);
- SkASSERT(c == SK_Fixed1);
- }
-
- int maxDiff = 0;
- for (i = 0; i < 10000; i++) {
- SkFixed rads = rand.nextS() >> 10;
- double frads = SkFixedToFloat(rads);
-
- SkFixed s, c;
- s = SkScalarSinCos(rads, &c);
-
- double fs = sin(frads);
- double fc = cos(frads);
-
- SkFixed is = SkFloatToFixed(fs);
- SkFixed ic = SkFloatToFixed(fc);
-
- maxDiff = SkMax32(maxDiff, SkAbs32(is - s));
- maxDiff = SkMax32(maxDiff, SkAbs32(ic - c));
- }
- SkDebugf("SinCos: maximum error = %d\n", maxDiff);
-#endif
-#endif
-}
-
-#endif
diff --git a/src/core/SkMatrix.cpp b/src/core/SkMatrix.cpp
index 893aea17d4..ac5ae926e0 100644
--- a/src/core/SkMatrix.cpp
+++ b/src/core/SkMatrix.cpp
@@ -1606,85 +1606,3 @@ void SkMatrix::toDumpString(SkString* str) const {
#endif
}
-///////////////////////////////////////////////////////////////////////////////
-
-#ifdef SK_DEBUG
-
-void SkMatrix::UnitTest() {
-#ifdef SK_SUPPORT_UNITTEST
- SkMatrix mat, inverse, iden1, iden2;
-
- mat.reset();
- mat.setTranslate(SK_Scalar1, SK_Scalar1);
- mat.invert(&inverse);
- inverse.dump();
- iden1.setConcat(mat, inverse);
- iden1.dump();
-
- mat.setScale(SkIntToScalar(2), SkIntToScalar(2));
- mat.invert(&inverse);
- inverse.dump();
- iden1.setConcat(mat, inverse);
- iden1.dump();
-
- mat.setScale(SK_Scalar1/2, SK_Scalar1/2);
- mat.invert(&inverse);
- inverse.dump();
- iden1.setConcat(mat, inverse);
- iden1.dump();
- SkASSERT(iden1.isIdentity());
-
- mat.setScale(SkIntToScalar(3), SkIntToScalar(5), SkIntToScalar(20), 0);
- mat.postRotate(SkIntToScalar(25));
-
- SkASSERT(mat.invert(NULL));
- mat.invert(&inverse);
-
- iden1.setConcat(mat, inverse);
- iden2.setConcat(inverse, mat);
-
- iden1.dump();
-// SkASSERT(iden1.isIdentity());
- iden2.dump();
-// SkASSERT(iden2.isIdentity());
-
- // rectStaysRect test
- {
- static const struct {
- SkScalar m00, m01, m10, m11;
- bool mStaysRect;
- }
- gRectStaysRectSamples[] = {
- { 0, 0, 0, 0, false },
- { 0, 0, 0, SK_Scalar1, false },
- { 0, 0, SK_Scalar1, 0, false },
- { 0, 0, SK_Scalar1, SK_Scalar1, false },
- { 0, SK_Scalar1, 0, 0, false },
- { 0, SK_Scalar1, 0, SK_Scalar1, false },
- { 0, SK_Scalar1, SK_Scalar1, 0, true },
- { 0, SK_Scalar1, SK_Scalar1, SK_Scalar1, false },
- { SK_Scalar1, 0, 0, 0, false },
- { SK_Scalar1, 0, 0, SK_Scalar1, true },
- { SK_Scalar1, 0, SK_Scalar1, 0, false },
- { SK_Scalar1, 0, SK_Scalar1, SK_Scalar1, false },
- { SK_Scalar1, SK_Scalar1, 0, 0, false },
- { SK_Scalar1, SK_Scalar1, 0, SK_Scalar1, false },
- { SK_Scalar1, SK_Scalar1, SK_Scalar1, 0, false },
- { SK_Scalar1, SK_Scalar1, SK_Scalar1, SK_Scalar1, false }
- };
-
- for (size_t i = 0; i < SK_ARRAY_COUNT(gRectStaysRectSamples); i++) {
- SkMatrix m;
-
- m.reset();
- m.set(SkMatrix::kMScaleX, gRectStaysRectSamples[i].m00);
- m.set(SkMatrix::kMSkewX, gRectStaysRectSamples[i].m01);
- m.set(SkMatrix::kMSkewY, gRectStaysRectSamples[i].m10);
- m.set(SkMatrix::kMScaleY, gRectStaysRectSamples[i].m11);
- SkASSERT(m.rectStaysRect() == gRectStaysRectSamples[i].mStaysRect);
- }
- }
-#endif
-}
-
-#endif
diff --git a/src/core/SkUtils.cpp b/src/core/SkUtils.cpp
index a4c6c16cd1..edc5b74954 100644
--- a/src/core/SkUtils.cpp
+++ b/src/core/SkUtils.cpp
@@ -458,126 +458,3 @@ SkAutoMemoryUsageProbe::~SkAutoMemoryUsageProbe()
#endif
}
-////////////////////////////////////////////////////////////////////////////////////
-
-#ifdef SK_DEBUG
-
-#include "SkRandom.h"
-#include "SkTSearch.h"
-#include "SkTSort.h"
-
-#define kSEARCH_COUNT 91
-
-#ifdef SK_SUPPORT_UNITTEST
-static void test_search()
-{
- int i, array[kSEARCH_COUNT];
- SkRandom rand;
-
- for (i = 0; i < kSEARCH_COUNT; i++)
- array[i] = rand.nextS();
-
- SkTHeapSort<int>(array, kSEARCH_COUNT);
- // make sure we got sorted properly
- for (i = 1; i < kSEARCH_COUNT; i++)
- SkASSERT(array[i-1] <= array[i]);
-
- // make sure we can find all of our values
- for (i = 0; i < kSEARCH_COUNT; i++)
- {
- int index = SkTSearch<int>(array, kSEARCH_COUNT, array[i], sizeof(int));
- SkASSERT(index == i);
- }
-
- // make sure that random values are either found, or the correct
- // insertion index is returned
- for (i = 0; i < 10000; i++)
- {
- int value = rand.nextS();
- int index = SkTSearch<int>(array, kSEARCH_COUNT, value, sizeof(int));
-
- if (index >= 0)
- SkASSERT(index < kSEARCH_COUNT && array[index] == value);
- else
- {
- index = ~index;
- SkASSERT(index <= kSEARCH_COUNT);
- if (index < kSEARCH_COUNT)
- {
- SkASSERT(value < array[index]);
- if (index > 0)
- SkASSERT(value > array[index - 1]);
- }
- else // we should append the new value
- {
- SkASSERT(value > array[kSEARCH_COUNT - 1]);
- }
- }
- }
-}
-
-static void test_utf16()
-{
- static const SkUnichar gUni[] = {
- 0x10000, 0x18080, 0x20202, 0xFFFFF, 0x101234
- };
-
- uint16_t buf[2];
-
- for (unsigned i = 0; i < SK_ARRAY_COUNT(gUni); i++)
- {
- size_t count = SkUTF16_FromUnichar(gUni[i], buf);
- SkASSERT(count == 2);
- size_t count2 = SkUTF16_CountUnichars(buf, 2);
- SkASSERT(count2 == 1);
- const uint16_t* ptr = buf;
- SkUnichar c = SkUTF16_NextUnichar(&ptr);
- SkASSERT(c == gUni[i]);
- SkASSERT(ptr - buf == 2);
- }
-}
-
-#endif
-
-void SkUtils::UnitTest()
-{
-#ifdef SK_SUPPORT_UNITTEST
- static const struct {
- const char* fUtf8;
- SkUnichar fUni;
- } gTest[] = {
- { "a", 'a' },
- { "\x7f", 0x7f },
- { "\xC2\x80", 0x80 },
- { "\xC3\x83", (3 << 6) | 3 },
- { "\xDF\xBF", 0x7ff },
- { "\xE0\xA0\x80", 0x800 },
- { "\xE0\xB0\xB8", 0xC38 },
- { "\xE3\x83\x83", (3 << 12) | (3 << 6) | 3 },
- { "\xEF\xBF\xBF", 0xFFFF },
- { "\xF0\x90\x80\x80", 0x10000 },
- { "\xF3\x83\x83\x83", (3 << 18) | (3 << 12) | (3 << 6) | 3 }
- };
-
- for (unsigned i = 0; i < SK_ARRAY_COUNT(gTest); i++)
- {
- const char* p = gTest[i].fUtf8;
- int n = SkUTF8_CountUnichars(p);
- SkUnichar u0 = SkUTF8_ToUnichar(gTest[i].fUtf8);
- SkUnichar u1 = SkUTF8_NextUnichar(&p);
-
- SkASSERT(n == 1);
- SkASSERT(u0 == u1);
- SkASSERT(u0 == gTest[i].fUni);
- SkASSERT(p - gTest[i].fUtf8 == (int)strlen(gTest[i].fUtf8));
- }
-
- test_utf16();
-
- test_search();
-#endif
-}
-
-#endif
-
-
diff --git a/tests/MathTest.cpp b/tests/MathTest.cpp
new file mode 100644
index 0000000000..a759ab19a1
--- /dev/null
+++ b/tests/MathTest.cpp
@@ -0,0 +1,400 @@
+#include "Test.h"
+#include "SkPoint.h"
+#include "SkRandom.h"
+
+#if defined(SkLONGLONG)
+static int symmetric_fixmul(int a, int b) {
+ int sa = SkExtractSign(a);
+ int sb = SkExtractSign(b);
+
+ a = SkApplySign(a, sa);
+ b = SkApplySign(b, sb);
+
+#if 1
+ int c = (int)(((SkLONGLONG)a * b) >> 16);
+
+ return SkApplySign(c, sa ^ sb);
+#else
+ SkLONGLONG ab = (SkLONGLONG)a * b;
+ if (sa ^ sb) {
+ ab = -ab;
+ }
+ return ab >> 16;
+#endif
+}
+#endif
+
+static void check_length(skiatest::Reporter* reporter,
+ const SkPoint& p, SkScalar targetLen) {
+#ifdef SK_CAN_USE_FLOAT
+ float x = SkScalarToFloat(p.fX);
+ float y = SkScalarToFloat(p.fY);
+ float len = sk_float_sqrt(x*x + y*y);
+
+ len /= SkScalarToFloat(targetLen);
+
+ REPORTER_ASSERT(reporter, len > 0.999f && len < 1.001f);
+#endif
+}
+
+#if defined(SK_CAN_USE_FLOAT)
+
+static float nextFloat(SkRandom& rand) {
+ SkFloatIntUnion data;
+ data.fSignBitInt = rand.nextU();
+ return data.fFloat;
+}
+
+/* returns true if a == b as resulting from (int)x. Since it is undefined
+ what to do if the float exceeds 2^32-1, we check for that explicitly.
+ */
+static bool equal_float_native_skia(float x, uint32_t ni, uint32_t si) {
+ if (!(x == x)) { // NAN
+ return si == SK_MaxS32 || si == SK_MinS32;
+ }
+ // for out of range, C is undefined, but skia always should return NaN32
+ if (x > SK_MaxS32) {
+ return si == SK_MaxS32;
+ }
+ if (x < -SK_MaxS32) {
+ return si == SK_MinS32;
+ }
+ return si == ni;
+}
+
+static void assert_float_equal(skiatest::Reporter* reporter, const char op[],
+ float x, uint32_t ni, uint32_t si) {
+ if (!equal_float_native_skia(x, ni, si)) {
+ SkString desc;
+ desc.printf("%s float %g bits %x native %x skia %x\n", op, x, ni, si);
+ reporter->reportFailed(desc);
+ }
+}
+
+static void test_float_cast(skiatest::Reporter* reporter, float x) {
+ int ix = (int)x;
+ int iix = SkFloatToIntCast(x);
+ assert_float_equal(reporter, "cast", x, ix, iix);
+}
+
+static void test_float_floor(skiatest::Reporter* reporter, float x) {
+ int ix = (int)floor(x);
+ int iix = SkFloatToIntFloor(x);
+ assert_float_equal(reporter, "floor", x, ix, iix);
+}
+
+static void test_float_round(skiatest::Reporter* reporter, float x) {
+ double xx = x + 0.5; // need intermediate double to avoid temp loss
+ int ix = (int)floor(xx);
+ int iix = SkFloatToIntRound(x);
+ assert_float_equal(reporter, "round", x, ix, iix);
+}
+
+static void test_float_ceil(skiatest::Reporter* reporter, float x) {
+ int ix = (int)ceil(x);
+ int iix = SkFloatToIntCeil(x);
+ assert_float_equal(reporter, "ceil", x, ix, iix);
+}
+
+static void test_float_conversions(skiatest::Reporter* reporter, float x) {
+ test_float_cast(reporter, x);
+ test_float_floor(reporter, x);
+ test_float_round(reporter, x);
+ test_float_ceil(reporter, x);
+}
+
+static void test_int2float(skiatest::Reporter* reporter, int ival) {
+ float x0 = (float)ival;
+ float x1 = SkIntToFloatCast(ival);
+ float x2 = SkIntToFloatCast_NoOverflowCheck(ival);
+ REPORTER_ASSERT(reporter, x0 == x1);
+ REPORTER_ASSERT(reporter, x0 == x2);
+}
+
+static void unittest_fastfloat(skiatest::Reporter* reporter) {
+ SkRandom rand;
+ size_t i;
+
+ static const float gFloats[] = {
+ 0.f, 1.f, 0.5f, 0.499999f, 0.5000001f, 1.f/3,
+ 0.000000001f, 1000000000.f, // doesn't overflow
+ 0.0000000001f, 10000000000.f // does overflow
+ };
+ for (i = 0; i < SK_ARRAY_COUNT(gFloats); i++) {
+ // SkDebugf("---- test floats %g %d\n", gFloats[i], (int)gFloats[i]);
+ test_float_conversions(reporter, gFloats[i]);
+ test_float_conversions(reporter, -gFloats[i]);
+ }
+
+ for (int outer = 0; outer < 100; outer++) {
+ rand.setSeed(outer);
+ for (i = 0; i < 100000; i++) {
+ float x = nextFloat(rand);
+ test_float_conversions(reporter, x);
+ }
+
+ test_int2float(reporter, 0);
+ test_int2float(reporter, 1);
+ test_int2float(reporter, -1);
+ for (i = 0; i < 100000; i++) {
+ // for now only test ints that are 24bits or less, since we don't
+ // round (down) large ints the same as IEEE...
+ int ival = rand.nextU() & 0xFFFFFF;
+ test_int2float(reporter, ival);
+ test_int2float(reporter, -ival);
+ }
+ }
+}
+
+#endif
+
+static void test_muldiv255(skiatest::Reporter* reporter) {
+#ifdef SK_CAN_USE_FLOAT
+ for (int a = 0; a <= 255; a++) {
+ for (int b = 0; b <= 255; b++) {
+ int ab = a * b;
+ float s = ab / 255.0f;
+ int round = (int)floorf(s + 0.5f);
+ int trunc = (int)floorf(s);
+
+ int iround = SkMulDiv255Round(a, b);
+ int itrunc = SkMulDiv255Trunc(a, b);
+
+ REPORTER_ASSERT(reporter, iround == round);
+ REPORTER_ASSERT(reporter, itrunc == trunc);
+
+ REPORTER_ASSERT(reporter, itrunc <= iround);
+ REPORTER_ASSERT(reporter, iround <= a);
+ REPORTER_ASSERT(reporter, iround <= b);
+ }
+ }
+#endif
+}
+
+static void TestMath(skiatest::Reporter* reporter) {
+ int i;
+ int32_t x;
+ SkRandom rand;
+
+ // these should not assert
+ SkToS8(127); SkToS8(-128); SkToU8(255);
+ SkToS16(32767); SkToS16(-32768); SkToU16(65535);
+ SkToS32(2*1024*1024); SkToS32(-2*1024*1024); SkToU32(4*1024*1024);
+
+ // these should assert
+#if 0
+ SkToS8(128);
+ SkToS8(-129);
+ SkToU8(256);
+ SkToU8(-5);
+
+ SkToS16(32768);
+ SkToS16(-32769);
+ SkToU16(65536);
+ SkToU16(-5);
+
+ if (sizeof(size_t) > 4) {
+ SkToS32(4*1024*1024);
+ SkToS32(-4*1024*1024);
+ SkToU32(5*1024*1024);
+ SkToU32(-5);
+ }
+#endif
+
+ test_muldiv255(reporter);
+
+ {
+ SkScalar x = SK_ScalarNaN;
+ REPORTER_ASSERT(reporter, SkScalarIsNaN(x));
+ }
+
+ for (i = 1; i <= 10; i++) {
+ x = SkCubeRootBits(i*i*i, 11);
+ REPORTER_ASSERT(reporter, x == i);
+ }
+
+ REPORTER_ASSERT(reporter, !"test the reporter");
+
+ x = SkFixedSqrt(SK_Fixed1);
+ REPORTER_ASSERT(reporter, x == SK_Fixed1);
+ x = SkFixedSqrt(SK_Fixed1/4);
+ REPORTER_ASSERT(reporter, x == SK_Fixed1/2);
+ x = SkFixedSqrt(SK_Fixed1*4);
+ REPORTER_ASSERT(reporter, x == SK_Fixed1*2);
+
+ x = SkFractSqrt(SK_Fract1);
+ REPORTER_ASSERT(reporter, x == SK_Fract1);
+ x = SkFractSqrt(SK_Fract1/4);
+ REPORTER_ASSERT(reporter, x == SK_Fract1/2);
+ x = SkFractSqrt(SK_Fract1/16);
+ REPORTER_ASSERT(reporter, x == SK_Fract1/4);
+
+ for (i = 1; i < 100; i++) {
+ x = SkFixedSqrt(SK_Fixed1 * i * i);
+ REPORTER_ASSERT(reporter, x == SK_Fixed1 * i);
+ }
+
+ for (i = 0; i < 1000; i++) {
+ int value = rand.nextS16();
+ int max = rand.nextU16();
+
+ int clamp = SkClampMax(value, max);
+ int clamp2 = value < 0 ? 0 : (value > max ? max : value);
+ REPORTER_ASSERT(reporter, clamp == clamp2);
+ }
+
+ for (i = 0; i < 100000; i++) {
+ SkPoint p;
+
+ p.setLength(rand.nextS(), rand.nextS(), SK_Scalar1);
+ check_length(reporter, p, SK_Scalar1);
+ p.setLength(rand.nextS() >> 13, rand.nextS() >> 13, SK_Scalar1);
+ check_length(reporter, p, SK_Scalar1);
+ }
+
+ {
+ SkFixed result = SkFixedDiv(100, 100);
+ REPORTER_ASSERT(reporter, result == SK_Fixed1);
+ result = SkFixedDiv(1, SK_Fixed1);
+ REPORTER_ASSERT(reporter, result == 1);
+ }
+
+#ifdef SK_CAN_USE_FLOAT
+ unittest_fastfloat(reporter);
+#endif
+
+#ifdef SkLONGLONG
+ for (i = 0; i < 100000; i++) {
+ SkFixed numer = rand.nextS();
+ SkFixed denom = rand.nextS();
+ SkFixed result = SkFixedDiv(numer, denom);
+ SkLONGLONG check = ((SkLONGLONG)numer << 16) / denom;
+
+ (void)SkCLZ(numer);
+ (void)SkCLZ(denom);
+
+ REPORTER_ASSERT(reporter, result != (SkFixed)SK_NaN32);
+ if (check > SK_MaxS32) {
+ check = SK_MaxS32;
+ } else if (check < -SK_MaxS32) {
+ check = SK_MinS32;
+ }
+ REPORTER_ASSERT(reporter, result == (int32_t)check);
+
+ result = SkFractDiv(numer, denom);
+ check = ((SkLONGLONG)numer << 30) / denom;
+
+ REPORTER_ASSERT(reporter, result != (SkFixed)SK_NaN32);
+ if (check > SK_MaxS32) {
+ check = SK_MaxS32;
+ } else if (check < -SK_MaxS32) {
+ check = SK_MinS32;
+ }
+ REPORTER_ASSERT(reporter, result == (int32_t)check);
+
+ // make them <= 2^24, so we don't overflow in fixmul
+ numer = numer << 8 >> 8;
+ denom = denom << 8 >> 8;
+
+ result = SkFixedMul(numer, denom);
+ SkFixed r2 = symmetric_fixmul(numer, denom);
+ // SkASSERT(result == r2);
+
+ result = SkFixedMul(numer, numer);
+ r2 = SkFixedSquare(numer);
+ REPORTER_ASSERT(reporter, result == r2);
+
+#ifdef SK_CAN_USE_FLOAT
+ if (numer >= 0 && denom >= 0) {
+ SkFixed mean = SkFixedMean(numer, denom);
+ float fm = sk_float_sqrt(sk_float_abs(SkFixedToFloat(numer) * SkFixedToFloat(denom)));
+ SkFixed mean2 = SkFloatToFixed(fm);
+ int diff = SkAbs32(mean - mean2);
+ REPORTER_ASSERT(reporter, diff <= 1);
+ }
+
+ {
+ SkFixed mod = SkFixedMod(numer, denom);
+ float n = SkFixedToFloat(numer);
+ float d = SkFixedToFloat(denom);
+ float m = sk_float_mod(n, d);
+ REPORTER_ASSERT(reporter, mod == 0 || (mod < 0) == (m < 0)); // ensure the same sign
+ int diff = SkAbs32(mod - SkFloatToFixed(m));
+ REPORTER_ASSERT(reporter, (diff >> 7) == 0);
+ }
+#endif
+ }
+#endif
+
+#ifdef SK_CAN_USE_FLOAT
+ for (i = 0; i < 100000; i++) {
+ SkFract x = rand.nextU() >> 1;
+ double xx = (double)x / SK_Fract1;
+ SkFract xr = SkFractSqrt(x);
+ SkFract check = SkFloatToFract(sqrt(xx));
+ REPORTER_ASSERT(reporter, xr == check || xr == check-1 || xr == check+1);
+
+ xr = SkFixedSqrt(x);
+ xx = (double)x / SK_Fixed1;
+ check = SkFloatToFixed(sqrt(xx));
+ REPORTER_ASSERT(reporter, xr == check || xr == check-1);
+
+ xr = SkSqrt32(x);
+ xx = (double)x;
+ check = (int32_t)sqrt(xx);
+ REPORTER_ASSERT(reporter, xr == check || xr == check-1);
+ }
+#endif
+
+#if !defined(SK_SCALAR_IS_FLOAT) && defined(SK_CAN_USE_FLOAT)
+ {
+ SkFixed s, c;
+ s = SkFixedSinCos(0, &c);
+ REPORTER_ASSERT(reporter, s == 0);
+ REPORTER_ASSERT(reporter, c == SK_Fixed1);
+ }
+
+ int maxDiff = 0;
+ for (i = 0; i < 10000; i++) {
+ SkFixed rads = rand.nextS() >> 10;
+ double frads = SkFixedToFloat(rads);
+
+ SkFixed s, c;
+ s = SkScalarSinCos(rads, &c);
+
+ double fs = sin(frads);
+ double fc = cos(frads);
+
+ SkFixed is = SkFloatToFixed(fs);
+ SkFixed ic = SkFloatToFixed(fc);
+
+ maxDiff = SkMax32(maxDiff, SkAbs32(is - s));
+ maxDiff = SkMax32(maxDiff, SkAbs32(ic - c));
+ }
+ SkDebugf("SinCos: maximum error = %d\n", maxDiff);
+#endif
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+namespace skiatest {
+
+ class MathTest : public Test {
+ public:
+ static Test* Factory(void*) {
+ return SkNEW(MathTest);
+ }
+
+ protected:
+ virtual void onGetName(SkString* name) {
+ name->set("Math");
+ }
+
+ virtual void onRun(Reporter* reporter) {
+ TestMath(reporter);
+ }
+ };
+
+ static TestRegistry gReg(MathTest::Factory);
+}
+
diff --git a/tests/MatrixTest.cpp b/tests/MatrixTest.cpp
new file mode 100644
index 0000000000..1e4e341f2b
--- /dev/null
+++ b/tests/MatrixTest.cpp
@@ -0,0 +1,119 @@
+#include "Test.h"
+#include "SkMatrix.h"
+
+static bool nearly_equal_scalar(SkScalar a, SkScalar b) {
+#ifdef SK_SCALAR_IS_FLOAT
+ const float tolerance = 0.000005f;
+#else
+ const int32_t tolerance = 3;
+#endif
+
+ return SkScalarAbs(a - b) <= tolerance;
+}
+
+static bool nearly_equal(const SkMatrix& a, const SkMatrix& b) {
+ for (int i = 0; i < 9; i++) {
+ if (!nearly_equal_scalar(a[i], b[i])) {
+ printf("not equal %g %g\n", a[i], b[i]);
+ return false;
+ }
+ }
+ return true;
+}
+
+static bool is_identity(const SkMatrix& m) {
+ SkMatrix identity;
+ identity.reset();
+ return nearly_equal(m, identity);
+}
+
+void TestMatrix(skiatest::Reporter* reporter) {
+ SkMatrix mat, inverse, iden1, iden2;
+
+ mat.reset();
+ mat.setTranslate(SK_Scalar1, SK_Scalar1);
+ mat.invert(&inverse);
+ iden1.setConcat(mat, inverse);
+ REPORTER_ASSERT(reporter, is_identity(iden1));
+
+ mat.setScale(SkIntToScalar(2), SkIntToScalar(2));
+ mat.invert(&inverse);
+ iden1.setConcat(mat, inverse);
+ REPORTER_ASSERT(reporter, is_identity(iden1));
+
+ mat.setScale(SK_Scalar1/2, SK_Scalar1/2);
+ mat.invert(&inverse);
+ iden1.setConcat(mat, inverse);
+ REPORTER_ASSERT(reporter, is_identity(iden1));
+
+ mat.setScale(SkIntToScalar(3), SkIntToScalar(5), SkIntToScalar(20), 0);
+ mat.postRotate(SkIntToScalar(25));
+ REPORTER_ASSERT(reporter, mat.invert(NULL));
+ mat.invert(&inverse);
+ iden1.setConcat(mat, inverse);
+ REPORTER_ASSERT(reporter, is_identity(iden1));
+ iden2.setConcat(inverse, mat);
+ REPORTER_ASSERT(reporter, is_identity(iden2));
+
+ // rectStaysRect test
+ {
+ static const struct {
+ SkScalar m00, m01, m10, m11;
+ bool mStaysRect;
+ }
+ gRectStaysRectSamples[] = {
+ { 0, 0, 0, 0, false },
+ { 0, 0, 0, SK_Scalar1, false },
+ { 0, 0, SK_Scalar1, 0, false },
+ { 0, 0, SK_Scalar1, SK_Scalar1, false },
+ { 0, SK_Scalar1, 0, 0, false },
+ { 0, SK_Scalar1, 0, SK_Scalar1, false },
+ { 0, SK_Scalar1, SK_Scalar1, 0, true },
+ { 0, SK_Scalar1, SK_Scalar1, SK_Scalar1, false },
+ { SK_Scalar1, 0, 0, 0, false },
+ { SK_Scalar1, 0, 0, SK_Scalar1, true },
+ { SK_Scalar1, 0, SK_Scalar1, 0, false },
+ { SK_Scalar1, 0, SK_Scalar1, SK_Scalar1, false },
+ { SK_Scalar1, SK_Scalar1, 0, 0, false },
+ { SK_Scalar1, SK_Scalar1, 0, SK_Scalar1, false },
+ { SK_Scalar1, SK_Scalar1, SK_Scalar1, 0, false },
+ { SK_Scalar1, SK_Scalar1, SK_Scalar1, SK_Scalar1, false }
+ };
+
+ for (size_t i = 0; i < SK_ARRAY_COUNT(gRectStaysRectSamples); i++) {
+ SkMatrix m;
+
+ m.reset();
+ m.set(SkMatrix::kMScaleX, gRectStaysRectSamples[i].m00);
+ m.set(SkMatrix::kMSkewX, gRectStaysRectSamples[i].m01);
+ m.set(SkMatrix::kMSkewY, gRectStaysRectSamples[i].m10);
+ m.set(SkMatrix::kMScaleY, gRectStaysRectSamples[i].m11);
+ REPORTER_ASSERT(reporter,
+ m.rectStaysRect() == gRectStaysRectSamples[i].mStaysRect);
+ }
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+namespace skiatest {
+
+ class MatrixTest : public Test {
+ public:
+ static Test* Factory(void*) {
+ return SkNEW(MatrixTest);
+ }
+
+ protected:
+ virtual void onGetName(SkString* name) {
+ name->set("Matrix");
+ }
+
+ virtual void onRun(Reporter* reporter) {
+ TestMatrix(reporter);
+ }
+ };
+
+ static TestRegistry gReg(MatrixTest::Factory);
+}
+
diff --git a/tests/PackBitsTest.cpp b/tests/PackBitsTest.cpp
new file mode 100644
index 0000000000..6e69f825a4
--- /dev/null
+++ b/tests/PackBitsTest.cpp
@@ -0,0 +1,144 @@
+#include "Test.h"
+#include "SkPackBits.h"
+
+static const uint16_t gTest0[] = { 0, 0, 1, 1 };
+static const uint16_t gTest1[] = { 1, 2, 3, 4, 5, 6 };
+static const uint16_t gTest2[] = { 0, 0, 0, 1, 2, 3, 3, 3 };
+static const uint16_t gTest3[] = { 0, 0, 0, 0, 0, 0, 1, 2, 3, 3, 3, 0, 0, 1 };
+
+#include "SkRandom.h"
+static SkRandom gRand;
+static void rand_fill(uint16_t buffer[], int count) {
+ for (int i = 0; i < count; i++)
+ buffer[i] = (uint16_t)gRand.nextU();
+}
+
+static void test_pack16(skiatest::Reporter* reporter) {
+ static const struct {
+ const uint16_t* fSrc;
+ int fCount;
+ } gTests[] = {
+ { gTest0, SK_ARRAY_COUNT(gTest0) },
+ { gTest1, SK_ARRAY_COUNT(gTest1) },
+ { gTest2, SK_ARRAY_COUNT(gTest2) },
+ { gTest3, SK_ARRAY_COUNT(gTest3) }
+ };
+
+ for (size_t i = 0; i < SK_ARRAY_COUNT(gTests); i++) {
+ uint8_t dst[100];
+ size_t dstSize = SkPackBits::Pack16(gTests[i].fSrc,
+ gTests[i].fCount, dst);
+ uint16_t src[100];
+ int srcCount = SkPackBits::Unpack16(dst, dstSize, src);
+ bool match = gTests[i].fCount == srcCount && memcmp(gTests[i].fSrc, src,
+ gTests[i].fCount * sizeof(uint16_t)) == 0;
+ REPORTER_ASSERT(reporter, match);
+ }
+
+ for (int n = 1000; n; n--) {
+ size_t size = 50;
+ uint16_t src[100], src2[100];
+ uint8_t dst[200];
+ rand_fill(src, size);
+
+ size_t dstSize = SkPackBits::Pack16(src, size, dst);
+ size_t maxSize = SkPackBits::ComputeMaxSize16(size);
+ REPORTER_ASSERT(reporter, maxSize >= dstSize);
+
+ int srcCount = SkPackBits::Unpack16(dst, dstSize, src2);
+ REPORTER_ASSERT(reporter, size == srcCount);
+ bool match = memcmp(src, src2, size * sizeof(uint16_t)) == 0;
+ REPORTER_ASSERT(reporter, match);
+ }
+}
+
+static const uint8_t gTest80[] = { 0, 0, 1, 1 };
+static const uint8_t gTest81[] = { 1, 2, 3, 4, 5, 6 };
+static const uint8_t gTest82[] = { 0, 0, 0, 1, 2, 3, 3, 3 };
+static const uint8_t gTest83[] = { 0, 0, 0, 0, 0, 0, 1, 2, 3, 3, 3, 0, 0, 1 };
+static const uint8_t gTest84[] = { 1, 0, 3, 0, 0, 0, 2, 1, 1, 2 };
+
+static void rand_fill(uint8_t buffer[], int count) {
+ for (int i = 0; i < count; i++)
+ buffer[i] = (uint8_t)((gRand.nextU() >> 8) & 0x3);
+}
+
+static void test_pack8(skiatest::Reporter* reporter) {
+ static const struct {
+ const uint8_t* fSrc;
+ int fCount;
+ } gTests[] = {
+ { gTest80, SK_ARRAY_COUNT(gTest80) },
+ { gTest81, SK_ARRAY_COUNT(gTest81) },
+ { gTest82, SK_ARRAY_COUNT(gTest82) },
+ { gTest83, SK_ARRAY_COUNT(gTest83) },
+ { gTest84, SK_ARRAY_COUNT(gTest84) }
+ };
+
+ for (size_t i = 4; i < SK_ARRAY_COUNT(gTests); i++) {
+ uint8_t dst[100];
+ size_t maxSize = SkPackBits::ComputeMaxSize8(gTests[i].fCount);
+ size_t dstSize = SkPackBits::Pack8(gTests[i].fSrc,
+ gTests[i].fCount, dst);
+ REPORTER_ASSERT(reporter, dstSize <= maxSize);
+ uint8_t src[100];
+ int srcCount = SkPackBits::Unpack8(dst, dstSize, src);
+ bool match = gTests[i].fCount == srcCount &&
+ memcmp(gTests[i].fSrc, src,
+ gTests[i].fCount * sizeof(uint8_t)) == 0;
+ REPORTER_ASSERT(reporter, match);
+ }
+
+ for (size_t size = 1; size <= 512; size += 1) {
+ for (int n = 200; n; n--) {
+ uint8_t src[600], src2[600];
+ uint8_t dst[600];
+ rand_fill(src, size);
+
+ size_t dstSize = SkPackBits::Pack8(src, size, dst);
+ size_t maxSize = SkPackBits::ComputeMaxSize8(size);
+ REPORTER_ASSERT(reporter, maxSize >= dstSize);
+
+ int srcCount = SkPackBits::Unpack8(dst, dstSize, src2);
+ REPORTER_ASSERT(reporter, size == srcCount);
+ bool match = memcmp(src, src2, size * sizeof(uint8_t)) == 0;
+ REPORTER_ASSERT(reporter, match);
+
+ for (int j = 0; j < 200; j++) {
+ size_t skip = gRand.nextU() % size;
+ size_t write = gRand.nextU() % size;
+ if (skip + write > size) {
+ write = size - skip;
+ }
+ SkPackBits::Unpack8(src, skip, write, dst);
+ bool match = memcmp(src, src2 + skip, write) == 0;
+ REPORTER_ASSERT(reporter, match);
+ }
+ }
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+namespace skiatest {
+
+ class PackBitsTest : public Test {
+ public:
+ static Test* Factory(void*) {
+ return SkNEW(PackBitsTest);
+ }
+
+ protected:
+ virtual void onGetName(SkString* name) {
+ name->set("PackBits");
+ }
+
+ virtual void onRun(Reporter* reporter) {
+ test_pack8(reporter);
+ test_pack16(reporter);
+ }
+ };
+
+ static TestRegistry gReg(PackBitsTest::Factory);
+}
+
diff --git a/tests/Test.cpp b/tests/Test.cpp
new file mode 100644
index 0000000000..5b8d439e2f
--- /dev/null
+++ b/tests/Test.cpp
@@ -0,0 +1,60 @@
+#include "Test.h"
+
+using namespace skiatest;
+
+Reporter::Reporter() {
+ this->resetReporting();
+}
+
+void Reporter::resetReporting() {
+ fCurrTest = NULL;
+ fTestCount = 0;
+ bzero(fResultCount, sizeof(fResultCount));
+}
+
+void Reporter::startTest(Test* test) {
+ SkASSERT(NULL == fCurrTest);
+ fCurrTest = test;
+ this->onStart(test);
+ fTestCount += 1;
+}
+
+void Reporter::report(const char desc[], Result result) {
+ if (NULL == desc) {
+ desc = "<no description>";
+ }
+ this->onReport(desc, result);
+ fResultCount[result] += 1;
+}
+
+void Reporter::endTest(Test* test) {
+ SkASSERT(test == fCurrTest);
+ this->onEnd(test);
+ fCurrTest = NULL;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+Test::Test() : fReporter(NULL) {}
+
+Test::~Test() {
+ fReporter->safeUnref();
+}
+
+void Test::setReporter(Reporter* r) {
+ SkRefCnt_SafeAssign(fReporter, r);
+}
+
+const char* Test::getName() {
+ if (fName.size() == 0) {
+ this->onGetName(&fName);
+ }
+ return fName.c_str();
+}
+
+void Test::run() {
+ fReporter->startTest(this);
+ this->onRun(fReporter);
+ fReporter->endTest(this);
+}
+
diff --git a/tests/Test.h b/tests/Test.h
new file mode 100644
index 0000000000..8d2eb87468
--- /dev/null
+++ b/tests/Test.h
@@ -0,0 +1,98 @@
+#ifndef skiatest_Test_DEFINED
+#define skiatest_Test_DEFINED
+
+#include "SkRefCnt.h"
+#include "SkString.h"
+#include "SkTRegistry.h"
+
+namespace skiatest {
+
+ class Test;
+
+ class Reporter : public SkRefCnt {
+ public:
+ Reporter();
+
+ enum Result {
+ kPassed, // must begin with 0
+ kFailed,
+ /////
+ kLastResult = kFailed
+ };
+
+ void resetReporting();
+ int countTests() const { return fTestCount; }
+ int countResults(Result r) {
+ SkASSERT((unsigned)r <= kLastResult);
+ return fResultCount[r];
+ }
+
+ void startTest(Test*);
+ void report(const char testDesc[], Result);
+ void endTest(Test*);
+
+ // helpers for tests
+ void assertTrue(bool cond, const char desc[]) {
+ if (!cond) {
+ this->report(desc, kFailed);
+ }
+ }
+ void assertFalse(bool cond, const char desc[]) {
+ if (cond) {
+ this->report(desc, kFailed);
+ }
+ }
+ void reportFailed(const char desc[]) {
+ this->report(desc, kFailed);
+ }
+ void reportFailed(const SkString& desc) {
+ this->report(desc.c_str(), kFailed);
+ }
+
+ protected:
+ virtual void onStart(Test*) {}
+ virtual void onReport(const char desc[], Result) {}
+ virtual void onEnd(Test*) {}
+
+ private:
+ Test* fCurrTest;
+ int fTestCount;
+ int fResultCount[kLastResult+1];
+
+ typedef SkRefCnt INHERITED;
+ };
+
+ class Test {
+ public:
+ Test();
+ virtual ~Test();
+
+ Reporter* getReporter() const { return fReporter; }
+ void setReporter(Reporter*);
+
+ const char* getName();
+ void run();
+
+ protected:
+ virtual void onGetName(SkString*) = 0;
+ virtual void onRun(Reporter*) = 0;
+
+ private:
+ Reporter* fReporter;
+ SkString fName;
+ };
+
+ typedef SkTRegistry<Test*, void*> TestRegistry;
+}
+
+#define REPORTER_ASSERT(r, cond) \
+ do { \
+ if (!(cond)) { \
+ SkString desc; \
+ desc.printf("%s:%d: %s", __FILE__, __LINE__, #cond); \
+ r->reportFailed(desc); \
+ } \
+ } while(0)
+
+
+#endif
diff --git a/tests/TestXCode/Tests.xcodeproj/project.pbxproj b/tests/TestXCode/Tests.xcodeproj/project.pbxproj
new file mode 100644
index 0000000000..004fb2247e
--- /dev/null
+++ b/tests/TestXCode/Tests.xcodeproj/project.pbxproj
@@ -0,0 +1,333 @@
+// !$*UTF8*$!
+{
+ archiveVersion = 1;
+ classes = {
+ };
+ objectVersion = 44;
+ objects = {
+
+/* Begin PBXBuildFile section */
+ 00857F860F56F8EE0078BE26 /* libcore.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00857F730F56F71B0078BE26 /* libcore.a */; };
+ 00857F920F56F9170078BE26 /* libmaccore.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00857F910F56F9150078BE26 /* libmaccore.a */; };
+ 00857FAA0F56F9620078BE26 /* Test.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 00857FA80F56F9620078BE26 /* Test.cpp */; };
+ 00857FAB0F56F9620078BE26 /* main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 00857FA90F56F9620078BE26 /* main.cpp */; };
+ 00857FB70F56FD340078BE26 /* MathTest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 00857FB60F56FD340078BE26 /* MathTest.cpp */; };
+ 008634DC0F579B7A0044DA64 /* PackBitsTest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 008634DB0F579B7A0044DA64 /* PackBitsTest.cpp */; };
+ 008634F10F579E410044DA64 /* MatrixTest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 008634F00F579E410044DA64 /* MatrixTest.cpp */; };
+ 0086350F0F57A3140044DA64 /* UtilsTest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0086350E0F57A3140044DA64 /* UtilsTest.cpp */; };
+ 8DD76F6A0486A84900D96B5E /* Tests.1 in CopyFiles */ = {isa = PBXBuildFile; fileRef = C6859E8B029090EE04C91782 /* Tests.1 */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXContainerItemProxy section */
+ 00857F720F56F71B0078BE26 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 00857F6B0F56F71B0078BE26 /* core.xcodeproj */;
+ proxyType = 2;
+ remoteGlobalIDString = D2AAC046055464E500DB518D;
+ remoteInfo = core;
+ };
+ 00857F900F56F9150078BE26 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 00857F890F56F9150078BE26 /* maccore.xcodeproj */;
+ proxyType = 2;
+ remoteGlobalIDString = D2AAC046055464E500DB518D;
+ remoteInfo = maccore;
+ };
+ 0086351C0F57A51A0044DA64 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 00857F6B0F56F71B0078BE26 /* core.xcodeproj */;
+ proxyType = 1;
+ remoteGlobalIDString = D2AAC045055464E500DB518D /* core */;
+ remoteInfo = core;
+ };
+ 0086351E0F57A5200044DA64 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 00857F890F56F9150078BE26 /* maccore.xcodeproj */;
+ proxyType = 1;
+ remoteGlobalIDString = D2AAC045055464E500DB518D /* maccore */;
+ remoteInfo = maccore;
+ };
+/* End PBXContainerItemProxy section */
+
+/* Begin PBXCopyFilesBuildPhase section */
+ 8DD76F690486A84900D96B5E /* CopyFiles */ = {
+ isa = PBXCopyFilesBuildPhase;
+ buildActionMask = 8;
+ dstPath = /usr/share/man/man1/;
+ dstSubfolderSpec = 0;
+ files = (
+ 8DD76F6A0486A84900D96B5E /* Tests.1 in CopyFiles */,
+ );
+ runOnlyForDeploymentPostprocessing = 1;
+ };
+/* End PBXCopyFilesBuildPhase section */
+
+/* Begin PBXFileReference section */
+ 00857F630F56F4220078BE26 /* Test.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Test.h; path = ../Test.h; sourceTree = SOURCE_ROOT; };
+ 00857F6B0F56F71B0078BE26 /* core.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = core.xcodeproj; path = ../../xcode/core/core.xcodeproj; sourceTree = SOURCE_ROOT; };
+ 00857F890F56F9150078BE26 /* maccore.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = maccore.xcodeproj; path = ../../xcode/maccore/maccore.xcodeproj; sourceTree = SOURCE_ROOT; };
+ 00857FA80F56F9620078BE26 /* Test.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Test.cpp; path = ../Test.cpp; sourceTree = SOURCE_ROOT; };
+ 00857FA90F56F9620078BE26 /* main.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = main.cpp; path = ../main.cpp; sourceTree = SOURCE_ROOT; };
+ 00857FB60F56FD340078BE26 /* MathTest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = MathTest.cpp; path = ../MathTest.cpp; sourceTree = SOURCE_ROOT; };
+ 008634DB0F579B7A0044DA64 /* PackBitsTest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = PackBitsTest.cpp; path = ../PackBitsTest.cpp; sourceTree = SOURCE_ROOT; };
+ 008634F00F579E410044DA64 /* MatrixTest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = MatrixTest.cpp; path = ../MatrixTest.cpp; sourceTree = SOURCE_ROOT; };
+ 0086350E0F57A3140044DA64 /* UtilsTest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = UtilsTest.cpp; path = ../UtilsTest.cpp; sourceTree = SOURCE_ROOT; };
+ 8DD76F6C0486A84900D96B5E /* Tests */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = Tests; sourceTree = BUILT_PRODUCTS_DIR; };
+ C6859E8B029090EE04C91782 /* Tests.1 */ = {isa = PBXFileReference; lastKnownFileType = text.man; path = Tests.1; sourceTree = "<group>"; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+ 8DD76F660486A84900D96B5E /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 00857F860F56F8EE0078BE26 /* libcore.a in Frameworks */,
+ 00857F920F56F9170078BE26 /* libmaccore.a in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+ 00857F6C0F56F71B0078BE26 /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ 00857F730F56F71B0078BE26 /* libcore.a */,
+ );
+ name = Products;
+ sourceTree = "<group>";
+ };
+ 00857F8A0F56F9150078BE26 /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ 00857F910F56F9150078BE26 /* libmaccore.a */,
+ );
+ name = Products;
+ sourceTree = "<group>";
+ };
+ 08FB7794FE84155DC02AAC07 /* Tests */ = {
+ isa = PBXGroup;
+ children = (
+ 00857F890F56F9150078BE26 /* maccore.xcodeproj */,
+ 00857F6B0F56F71B0078BE26 /* core.xcodeproj */,
+ 08FB7795FE84155DC02AAC07 /* Source */,
+ C6859E8C029090F304C91782 /* Documentation */,
+ 1AB674ADFE9D54B511CA2CBB /* Products */,
+ );
+ name = Tests;
+ sourceTree = "<group>";
+ };
+ 08FB7795FE84155DC02AAC07 /* Source */ = {
+ isa = PBXGroup;
+ children = (
+ 00857FA80F56F9620078BE26 /* Test.cpp */,
+ 00857FA90F56F9620078BE26 /* main.cpp */,
+ 00857F630F56F4220078BE26 /* Test.h */,
+ 00857FB60F56FD340078BE26 /* MathTest.cpp */,
+ 0086350E0F57A3140044DA64 /* UtilsTest.cpp */,
+ 008634F00F579E410044DA64 /* MatrixTest.cpp */,
+ 008634DB0F579B7A0044DA64 /* PackBitsTest.cpp */,
+ );
+ name = Source;
+ sourceTree = "<group>";
+ };
+ 1AB674ADFE9D54B511CA2CBB /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ 8DD76F6C0486A84900D96B5E /* Tests */,
+ );
+ name = Products;
+ sourceTree = "<group>";
+ };
+ C6859E8C029090F304C91782 /* Documentation */ = {
+ isa = PBXGroup;
+ children = (
+ C6859E8B029090EE04C91782 /* Tests.1 */,
+ );
+ name = Documentation;
+ sourceTree = "<group>";
+ };
+/* End PBXGroup section */
+
+/* Begin PBXNativeTarget section */
+ 8DD76F620486A84900D96B5E /* Tests */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 1DEB923108733DC60010E9CD /* Build configuration list for PBXNativeTarget "Tests" */;
+ buildPhases = (
+ 8DD76F640486A84900D96B5E /* Sources */,
+ 8DD76F660486A84900D96B5E /* Frameworks */,
+ 8DD76F690486A84900D96B5E /* CopyFiles */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ 0086351D0F57A51A0044DA64 /* PBXTargetDependency */,
+ 0086351F0F57A5200044DA64 /* PBXTargetDependency */,
+ );
+ name = Tests;
+ productInstallPath = "$(HOME)/bin";
+ productName = Tests;
+ productReference = 8DD76F6C0486A84900D96B5E /* Tests */;
+ productType = "com.apple.product-type.tool";
+ };
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+ 08FB7793FE84155DC02AAC07 /* Project object */ = {
+ isa = PBXProject;
+ buildConfigurationList = 1DEB923508733DC60010E9CD /* Build configuration list for PBXProject "Tests" */;
+ compatibilityVersion = "Xcode 3.0";
+ hasScannedForEncodings = 1;
+ mainGroup = 08FB7794FE84155DC02AAC07 /* Tests */;
+ projectDirPath = "";
+ projectReferences = (
+ {
+ ProductGroup = 00857F6C0F56F71B0078BE26 /* Products */;
+ ProjectRef = 00857F6B0F56F71B0078BE26 /* core.xcodeproj */;
+ },
+ {
+ ProductGroup = 00857F8A0F56F9150078BE26 /* Products */;
+ ProjectRef = 00857F890F56F9150078BE26 /* maccore.xcodeproj */;
+ },
+ );
+ projectRoot = "";
+ targets = (
+ 8DD76F620486A84900D96B5E /* Tests */,
+ );
+ };
+/* End PBXProject section */
+
+/* Begin PBXReferenceProxy section */
+ 00857F730F56F71B0078BE26 /* libcore.a */ = {
+ isa = PBXReferenceProxy;
+ fileType = archive.ar;
+ path = libcore.a;
+ remoteRef = 00857F720F56F71B0078BE26 /* PBXContainerItemProxy */;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+ 00857F910F56F9150078BE26 /* libmaccore.a */ = {
+ isa = PBXReferenceProxy;
+ fileType = archive.ar;
+ path = libmaccore.a;
+ remoteRef = 00857F900F56F9150078BE26 /* PBXContainerItemProxy */;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+/* End PBXReferenceProxy section */
+
+/* Begin PBXSourcesBuildPhase section */
+ 8DD76F640486A84900D96B5E /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 00857FAA0F56F9620078BE26 /* Test.cpp in Sources */,
+ 00857FAB0F56F9620078BE26 /* main.cpp in Sources */,
+ 00857FB70F56FD340078BE26 /* MathTest.cpp in Sources */,
+ 008634DC0F579B7A0044DA64 /* PackBitsTest.cpp in Sources */,
+ 008634F10F579E410044DA64 /* MatrixTest.cpp in Sources */,
+ 0086350F0F57A3140044DA64 /* UtilsTest.cpp in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXSourcesBuildPhase section */
+
+/* Begin PBXTargetDependency section */
+ 0086351D0F57A51A0044DA64 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ name = core;
+ targetProxy = 0086351C0F57A51A0044DA64 /* PBXContainerItemProxy */;
+ };
+ 0086351F0F57A5200044DA64 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ name = maccore;
+ targetProxy = 0086351E0F57A5200044DA64 /* PBXContainerItemProxy */;
+ };
+/* End PBXTargetDependency section */
+
+/* Begin XCBuildConfiguration section */
+ 1DEB923208733DC60010E9CD /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ COPY_PHASE_STRIP = NO;
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_ENABLE_FIX_AND_CONTINUE = YES;
+ GCC_MODEL_TUNING = G5;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "_GLIBCXX_DEBUG=1",
+ "_GLIBCXX_DEBUG_PEDANTIC=1",
+ );
+ INSTALL_PATH = /usr/local/bin;
+ PRODUCT_NAME = Tests;
+ };
+ name = Debug;
+ };
+ 1DEB923308733DC60010E9CD /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+ GCC_MODEL_TUNING = G5;
+ INSTALL_PATH = /usr/local/bin;
+ PRODUCT_NAME = Tests;
+ };
+ name = Release;
+ };
+ 1DEB923608733DC60010E9CD /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ARCHS = "$(NATIVE_ARCH)";
+ GCC_C_LANGUAGE_STANDARD = c99;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ HEADER_SEARCH_PATHS = "../../../**";
+ ONLY_ACTIVE_ARCH = NO;
+ PREBINDING = NO;
+ PRECOMPS_INCLUDE_HEADERS_FROM_BUILT_PRODUCTS_DIR = NO;
+ SDKROOT = "$(DEVELOPER_SDK_DIR)/MacOSX10.4u.sdk";
+ VALID_ARCHS = "i386 x86_64";
+ };
+ name = Debug;
+ };
+ 1DEB923708733DC60010E9CD /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ARCHS = "$(NATIVE_ARCH)";
+ GCC_C_LANGUAGE_STANDARD = c99;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ HEADER_SEARCH_PATHS = "../../../**";
+ ONLY_ACTIVE_ARCH = NO;
+ PREBINDING = NO;
+ PRECOMPS_INCLUDE_HEADERS_FROM_BUILT_PRODUCTS_DIR = NO;
+ SDKROOT = "$(DEVELOPER_SDK_DIR)/MacOSX10.4u.sdk";
+ VALID_ARCHS = "i386 x86_64";
+ };
+ name = Release;
+ };
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+ 1DEB923108733DC60010E9CD /* Build configuration list for PBXNativeTarget "Tests" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 1DEB923208733DC60010E9CD /* Debug */,
+ 1DEB923308733DC60010E9CD /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 1DEB923508733DC60010E9CD /* Build configuration list for PBXProject "Tests" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 1DEB923608733DC60010E9CD /* Debug */,
+ 1DEB923708733DC60010E9CD /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+/* End XCConfigurationList section */
+ };
+ rootObject = 08FB7793FE84155DC02AAC07 /* Project object */;
+}
diff --git a/tests/UtilsTest.cpp b/tests/UtilsTest.cpp
new file mode 100644
index 0000000000..810cb51650
--- /dev/null
+++ b/tests/UtilsTest.cpp
@@ -0,0 +1,130 @@
+#include "Test.h"
+#include "SkRandom.h"
+#include "SkTSearch.h"
+#include "SkTSort.h"
+#include "SkUtils.h"
+
+#define kSEARCH_COUNT 91
+
+static void test_search(skiatest::Reporter* reporter) {
+ int i, array[kSEARCH_COUNT];
+ SkRandom rand;
+
+ for (i = 0; i < kSEARCH_COUNT; i++) {
+ array[i] = rand.nextS();
+ }
+
+ SkTHeapSort<int>(array, kSEARCH_COUNT);
+ // make sure we got sorted properly
+ for (i = 1; i < kSEARCH_COUNT; i++) {
+ REPORTER_ASSERT(reporter, array[i-1] <= array[i]);
+ }
+
+ // make sure we can find all of our values
+ for (i = 0; i < kSEARCH_COUNT; i++) {
+ int index = SkTSearch<int>(array, kSEARCH_COUNT, array[i], sizeof(int));
+ REPORTER_ASSERT(reporter, index == i);
+ }
+
+ // make sure that random values are either found, or the correct
+ // insertion index is returned
+ for (i = 0; i < 10000; i++) {
+ int value = rand.nextS();
+ int index = SkTSearch<int>(array, kSEARCH_COUNT, value, sizeof(int));
+
+ if (index >= 0) {
+ REPORTER_ASSERT(reporter,
+ index < kSEARCH_COUNT && array[index] == value);
+ } else {
+ index = ~index;
+ REPORTER_ASSERT(reporter, index <= kSEARCH_COUNT);
+ if (index < kSEARCH_COUNT) {
+ REPORTER_ASSERT(reporter, value < array[index]);
+ if (index > 0) {
+ REPORTER_ASSERT(reporter, value > array[index - 1]);
+ }
+ } else {
+ // we should append the new value
+ REPORTER_ASSERT(reporter, value > array[kSEARCH_COUNT - 1]);
+ }
+ }
+ }
+}
+
+static void test_utf16(skiatest::Reporter* reporter) {
+ static const SkUnichar gUni[] = {
+ 0x10000, 0x18080, 0x20202, 0xFFFFF, 0x101234
+ };
+
+ uint16_t buf[2];
+
+ for (size_t i = 0; i < SK_ARRAY_COUNT(gUni); i++) {
+ size_t count = SkUTF16_FromUnichar(gUni[i], buf);
+ REPORTER_ASSERT(reporter, count == 2);
+ size_t count2 = SkUTF16_CountUnichars(buf, 2);
+ REPORTER_ASSERT(reporter, count2 == 1);
+ const uint16_t* ptr = buf;
+ SkUnichar c = SkUTF16_NextUnichar(&ptr);
+ REPORTER_ASSERT(reporter, c == gUni[i]);
+ REPORTER_ASSERT(reporter, ptr - buf == 2);
+ }
+}
+
+static void TestUTF(skiatest::Reporter* reporter) {
+ static const struct {
+ const char* fUtf8;
+ SkUnichar fUni;
+ } gTest[] = {
+ { "a", 'a' },
+ { "\x7f", 0x7f },
+ { "\xC2\x80", 0x80 },
+ { "\xC3\x83", (3 << 6) | 3 },
+ { "\xDF\xBF", 0x7ff },
+ { "\xE0\xA0\x80", 0x800 },
+ { "\xE0\xB0\xB8", 0xC38 },
+ { "\xE3\x83\x83", (3 << 12) | (3 << 6) | 3 },
+ { "\xEF\xBF\xBF", 0xFFFF },
+ { "\xF0\x90\x80\x80", 0x10000 },
+ { "\xF3\x83\x83\x83", (3 << 18) | (3 << 12) | (3 << 6) | 3 }
+ };
+
+ for (size_t i = 0; i < SK_ARRAY_COUNT(gTest); i++) {
+ const char* p = gTest[i].fUtf8;
+ int n = SkUTF8_CountUnichars(p);
+ SkUnichar u0 = SkUTF8_ToUnichar(gTest[i].fUtf8);
+ SkUnichar u1 = SkUTF8_NextUnichar(&p);
+
+ REPORTER_ASSERT(reporter, n == 1);
+ REPORTER_ASSERT(reporter, u0 == u1);
+ REPORTER_ASSERT(reporter, u0 == gTest[i].fUni);
+ REPORTER_ASSERT(reporter,
+ p - gTest[i].fUtf8 == (int)strlen(gTest[i].fUtf8));
+ }
+
+ test_utf16(reporter);
+ test_search(reporter);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+namespace skiatest {
+
+ class UtfTest : public Test {
+ public:
+ static Test* Factory(void*) {
+ return SkNEW(UtfTest);
+ }
+
+ protected:
+ virtual void onGetName(SkString* name) {
+ name->set("UTF");
+ }
+
+ virtual void onRun(Reporter* reporter) {
+ TestUTF(reporter);
+ }
+ };
+
+ static TestRegistry gReg(UtfTest::Factory);
+}
+
diff --git a/tests/main.cpp b/tests/main.cpp
new file mode 100644
index 0000000000..0b82af4c0f
--- /dev/null
+++ b/tests/main.cpp
@@ -0,0 +1,67 @@
+#include <iostream>
+
+#include "Test.h"
+
+using namespace skiatest;
+
+class Iter {
+public:
+ Iter(Reporter* r) : fReporter(r) {
+ r->ref();
+ fReg = TestRegistry::Head();
+ }
+
+ ~Iter() {
+ fReporter->unref();
+ }
+
+ Test* next() {
+ if (fReg) {
+ TestRegistry::Factory fact = fReg->factory();
+ fReg = fReg->next();
+ Test* test = fact(NULL);
+ test->setReporter(fReporter);
+ return test;
+ }
+ return NULL;
+ }
+
+private:
+ Reporter* fReporter;
+ const TestRegistry* fReg;
+};
+
+static const char* result2string(Reporter::Result result) {
+ return result == Reporter::kPassed ? "passed" : "FAILED";
+}
+
+class PrintfReporter : public Reporter {
+protected:
+ virtual void onStart(Test* test) {
+ printf("Running %s...\n", test->getName());
+ }
+ virtual void onReport(const char desc[], Reporter::Result result) {
+ printf("\t%s: %s\n", result2string(result), desc);
+ }
+ virtual void onEnd(Test* test) {}
+};
+
+int main (int argc, char * const argv[]) {
+ PrintfReporter reporter;
+ Iter iter(&reporter);
+ Test* test;
+
+ while ((test = iter.next()) != NULL) {
+ test->run();
+ SkDELETE(test);
+ }
+
+ int total = reporter.countTests();
+ int passed = reporter.countResults(Reporter::kPassed);
+ int failed = reporter.countResults(Reporter::kFailed);
+ printf("Tests=%d Passed=%d (%g%%) Failed=%d (%g%%)\n", total,
+ passed, passed * 100.f / total,
+ failed, failed * 100.f / total);
+
+ return 0;
+}