diff options
author | Derek Sollenberger <djsollen@google.com> | 2011-03-14 11:20:24 -0400 |
---|---|---|
committer | Derek Sollenberger <djsollen@google.com> | 2011-03-14 16:33:36 -0400 |
commit | 05b6b4d746867a9fb02e14edfe1bf3685abeb813 (patch) | |
tree | 34b121f598d1693c014df48ee70bffa382b0cc23 /tests | |
parent | 6210a7c68844602ee390bcce61dbb637910a3c6b (diff) | |
download | external_skia-05b6b4d746867a9fb02e14edfe1bf3685abeb813.zip external_skia-05b6b4d746867a9fb02e14edfe1bf3685abeb813.tar.gz external_skia-05b6b4d746867a9fb02e14edfe1bf3685abeb813.tar.bz2 |
Skia Merge (revision 922)
Change-Id: I7ed57d10905d8bad6486a4d7410165eec1cc2b4f
Diffstat (limited to 'tests')
-rw-r--r-- | tests/Android.mk | 44 | ||||
-rw-r--r-- | tests/BitmapCopyTest.cpp | 415 | ||||
-rw-r--r-- | tests/BitmapGetColorTest.cpp | 36 | ||||
-rw-r--r-- | tests/BlitRowTest.cpp | 3 | ||||
-rw-r--r-- | tests/ClipCubicTest.cpp | 18 | ||||
-rw-r--r-- | tests/ClipStackTest.cpp | 49 | ||||
-rw-r--r-- | tests/DequeTest.cpp | 96 | ||||
-rw-r--r-- | tests/FillPathTest.cpp | 60 | ||||
-rw-r--r-- | tests/FlateTest.cpp | 107 | ||||
-rw-r--r-- | tests/InfRectTest.cpp | 44 | ||||
-rw-r--r-- | tests/MathTest.cpp | 47 | ||||
-rw-r--r-- | tests/MatrixTest.cpp | 4 | ||||
-rw-r--r-- | tests/PDFPrimitivesTest.cpp | 210 | ||||
-rw-r--r-- | tests/PaintTest.cpp | 12 | ||||
-rw-r--r-- | tests/PathTest.cpp | 18 | ||||
-rw-r--r-- | tests/RefDictTest.cpp | 66 | ||||
-rw-r--r-- | tests/RegionTest.cpp | 63 | ||||
-rw-r--r-- | tests/StringTest.cpp | 37 | ||||
-rw-r--r-- | tests/TestSize.cpp | 2 | ||||
-rw-r--r-- | tests/UtilsTest.cpp | 66 | ||||
-rw-r--r-- | tests/XfermodeTest.cpp | 30 |
21 files changed, 1386 insertions, 41 deletions
diff --git a/tests/Android.mk b/tests/Android.mk index e1c03ec..a5611ee 100644 --- a/tests/Android.mk +++ b/tests/Android.mk @@ -3,24 +3,40 @@ include $(CLEAR_VARS) LOCAL_SRC_FILES:= \ - BlitRowTest.cpp \ - GeometryTest.cpp \ - MathTest.cpp \ - MatrixTest.cpp \ - PackBitsTest.cpp \ - Sk64Test.cpp \ - StringTest.cpp \ - Test.cpp UtilsTest.cpp \ - PathTest.cpp \ - SrcOverTest.cpp \ - StreamTest.cpp \ - SortTest.cpp \ - PathMeasureTest.cpp + BitmapCopyTest.cpp \ + BitmapGetColorTest.cpp \ + BlitRowTest.cpp \ + ClipCubicTest.cpp \ + ClipStackTest.cpp \ + ClipperTest.cpp \ + DequeTest.cpp \ + FillPathTest.cpp \ + FlateTest.cpp \ + GeometryTest.cpp \ + InfRectTest.cpp \ + MathTest.cpp \ + MatrixTest.cpp \ + PackBitsTest.cpp \ + PaintTest.cpp \ + ParsePathTest.cpp \ + PathMeasureTest.cpp \ + PathTest.cpp \ + RefDictTest.cpp \ + RegionTest.cpp \ + Sk64Test.cpp \ + SortTest.cpp \ + SrcOverTest.cpp \ + StreamTest.cpp \ + StringTest.cpp \ + Test.cpp \ + TestSize.cpp \ + UtilsTest.cpp \ + XfermodeTest.cpp # The name of the file with a main function must # match native test's naming rule: xxx_test.cpp. LOCAL_SRC_FILES += \ - skia_test.cpp + skia_test.cpp LOCAL_MODULE:= skia_test diff --git a/tests/BitmapCopyTest.cpp b/tests/BitmapCopyTest.cpp index be3850e..1878dfa 100644 --- a/tests/BitmapCopyTest.cpp +++ b/tests/BitmapCopyTest.cpp @@ -62,10 +62,14 @@ static void test_isOpaque(skiatest::Reporter* reporter, const SkBitmap& src, } } -static void init_src(const SkBitmap& bitmap) { +static void init_src(const SkBitmap& bitmap, const SkColorTable* ct) { SkAutoLockPixels lock(bitmap); if (bitmap.getPixels()) { - memset(bitmap.getPixels(), 4, bitmap.getSize()); + if (ct) { + sk_bzero(bitmap.getPixels(), bitmap.getSize()); + } else { + bitmap.eraseColor(SK_ColorWHITE); + } } } @@ -81,6 +85,151 @@ struct Pair { const char* fValid; }; +// Utility functions for copyPixelsTo()/copyPixelsFrom() tests. +// getPixel() +// setPixel() +// getSkConfigName() +// struct Coordinates +// reportCopyVerification() +// writeCoordPixels() + +// Utility function to read the value of a given pixel in bm. All +// values converted to uint32_t for simplification of comparisons. +uint32_t getPixel(int x, int y, const SkBitmap& bm) { + uint32_t val = 0; + uint16_t val16; + uint8_t val8, shift; + SkAutoLockPixels lock(bm); + const void* rawAddr = bm.getAddr(x,y); + + switch (bm.getConfig()) { + case SkBitmap::kARGB_8888_Config: + memcpy(&val, rawAddr, sizeof(uint32_t)); + break; + case SkBitmap::kARGB_4444_Config: + case SkBitmap::kRGB_565_Config: + memcpy(&val16, rawAddr, sizeof(uint16_t)); + val = val16; + break; + case SkBitmap::kA8_Config: + case SkBitmap::kIndex8_Config: + memcpy(&val8, rawAddr, sizeof(uint8_t)); + val = val8; + break; + case SkBitmap::kA1_Config: + memcpy(&val8, rawAddr, sizeof(uint8_t)); + shift = x % 8; + val = (val8 >> shift) & 0x1 ; + break; + default: + break; + } + return val; +} + +// Utility function to set value of any pixel in bm. +// bm.getConfig() specifies what format 'val' must be +// converted to, but at present uint32_t can handle all formats. +void setPixel(int x, int y, uint32_t val, SkBitmap& bm) { + uint16_t val16; + uint8_t val8, shift; + SkAutoLockPixels lock(bm); + void* rawAddr = bm.getAddr(x,y); + + switch (bm.getConfig()) { + case SkBitmap::kARGB_8888_Config: + memcpy(rawAddr, &val, sizeof(uint32_t)); + break; + case SkBitmap::kARGB_4444_Config: + case SkBitmap::kRGB_565_Config: + val16 = val & 0xFFFF; + memcpy(rawAddr, &val16, sizeof(uint16_t)); + break; + case SkBitmap::kA8_Config: + case SkBitmap::kIndex8_Config: + val8 = val & 0xFF; + memcpy(rawAddr, &val8, sizeof(uint8_t)); + break; + case SkBitmap::kA1_Config: + shift = x % 8; // We assume we're in the right byte. + memcpy(&val8, rawAddr, sizeof(uint8_t)); + if (val & 0x1) // Turn bit on. + val8 |= (0x1 << shift); + else // Turn bit off. + val8 &= ~(0x1 << shift); + memcpy(rawAddr, &val8, sizeof(uint8_t)); + break; + default: + // Ignore. + break; + } +} + +// Utility to return string containing name of each format, to +// simplify diagnostic output. +const char* getSkConfigName(const SkBitmap& bm) { + switch (bm.getConfig()) { + case SkBitmap::kNo_Config: return "SkBitmap::kNo_Config"; + case SkBitmap::kA1_Config: return "SkBitmap::kA1_Config"; + case SkBitmap::kA8_Config: return "SkBitmap::kA8_Config"; + case SkBitmap::kIndex8_Config: return "SkBitmap::kIndex8_Config"; + case SkBitmap::kRGB_565_Config: return "SkBitmap::kRGB_565_Config"; + case SkBitmap::kARGB_4444_Config: return "SkBitmap::kARGB_4444_Config"; + case SkBitmap::kARGB_8888_Config: return "SkBitmap::kARGB_8888_Config"; + case SkBitmap::kRLE_Index8_Config: + return "SkBitmap::kRLE_Index8_Config,"; + default: return "Unknown SkBitmap configuration."; + } +} + +// Helper struct to contain pixel locations, while avoiding need for STL. +struct Coordinates { + + const int length; + SkIPoint* const data; + + explicit Coordinates(int _length): length(_length) + , data(new SkIPoint[length]) { } + + ~Coordinates(){ + delete [] data; + } + + SkIPoint* operator[](int i) const { + // Use with care, no bounds checking. + return data + i; + } +}; + +// A function to verify that two bitmaps contain the same pixel values +// at all coordinates indicated by coords. Simplifies verification of +// copied bitmaps. +void reportCopyVerification(const SkBitmap& bm1, const SkBitmap& bm2, + Coordinates& coords, + const char* msg, + skiatest::Reporter* reporter){ + bool success = true; + + // Confirm all pixels in the list match. + for (int i = 0; i < coords.length; ++i) + success = success && + (getPixel(coords[i]->fX, coords[i]->fY, bm1) == + getPixel(coords[i]->fX, coords[i]->fY, bm2)); + + if (!success) { + SkString str; + str.printf("%s [config = %s]", + msg, getSkConfigName(bm1)); + reporter->reportFailed(str); + } +} + +// Writes unique pixel values at locations specified by coords. +void writeCoordPixels(SkBitmap& bm, const Coordinates& coords) { + for (int i = 0; i < coords.length; ++i) + setPixel(coords[i]->fX, coords[i]->fY, i, bm); +} + static void TestBitmapCopy(skiatest::Reporter* reporter) { static const Pair gPairs[] = { { SkBitmap::kNo_Config, "00000000" }, @@ -94,6 +243,10 @@ static void TestBitmapCopy(skiatest::Reporter* reporter) { // { SkBitmap::kRLE_Index8_Config, "00101111" } }; + static const bool isExtracted[] = { + false, true + }; + const int W = 20; const int H = 33; @@ -110,7 +263,7 @@ static void TestBitmapCopy(skiatest::Reporter* reporter) { src.allocPixels(ct); SkSafeUnref(ct); - init_src(src); + init_src(src, ct); bool success = src.copyTo(&dst, gPairs[j].fConfig); bool expected = gPairs[i].fValid[j] != '0'; if (success != expected) { @@ -120,7 +273,7 @@ static void TestBitmapCopy(skiatest::Reporter* reporter) { boolStr(success)); reporter->reportFailed(str); } - + bool canSucceed = src.canCopyTo(gPairs[j].fConfig); if (success != canSucceed) { SkString str; @@ -161,7 +314,7 @@ static void TestBitmapCopy(skiatest::Reporter* reporter) { 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 @@ -176,7 +329,257 @@ static void TestBitmapCopy(skiatest::Reporter* reporter) { REPORTER_ASSERT(reporter, dst.width() == 0); REPORTER_ASSERT(reporter, dst.height() == 0); } - } + } // for (size_t j = ... + + // Tests for getSafeSize(), getSafeSize64(), copyPixelsTo(), + // copyPixelsFrom(). + // + for (size_t copyCase = 0; copyCase < SK_ARRAY_COUNT(isExtracted); + ++copyCase) { + // Test copying to/from external buffer. + // Note: the tests below have hard-coded values --- + // Please take care if modifying. + if (gPairs[i].fConfig != SkBitmap::kRLE_Index8_Config) { + + // Tests for getSafeSize64(). + // Test with a very large configuration without pixel buffer + // attached. + SkBitmap tstSafeSize; + tstSafeSize.setConfig(gPairs[i].fConfig, 100000000U, + 100000000U); + Sk64 safeSize = tstSafeSize.getSafeSize64(); + if (safeSize.isNeg()) { + SkString str; + str.printf("getSafeSize64() negative: %s", + getSkConfigName(tstSafeSize)); + reporter->reportFailed(str); + } + bool sizeFail = false; + // Compare against hand-computed values. + switch (gPairs[i].fConfig) { + case SkBitmap::kNo_Config: + break; + + case SkBitmap::kA1_Config: + if (safeSize.fHi != 0x470DE || + safeSize.fLo != 0x4DF82000) + sizeFail = true; + break; + + case SkBitmap::kA8_Config: + case SkBitmap::kIndex8_Config: + if (safeSize.fHi != 0x2386F2 || + safeSize.fLo != 0x6FC10000) + sizeFail = true; + break; + + case SkBitmap::kRGB_565_Config: + case SkBitmap::kARGB_4444_Config: + if (safeSize.fHi != 0x470DE4 || + safeSize.fLo != 0xDF820000) + sizeFail = true; + break; + + case SkBitmap::kARGB_8888_Config: + if (safeSize.fHi != 0x8E1BC9 || + safeSize.fLo != 0xBF040000) + sizeFail = true; + break; + + case SkBitmap::kRLE_Index8_Config: + break; + + default: + break; + } + if (sizeFail) { + SkString str; + str.printf("getSafeSize64() wrong size: %s", + getSkConfigName(tstSafeSize)); + reporter->reportFailed(str); + } + + size_t subW, subH; + // Set sizes to be height = 2 to force the last row of the + // source to be used, thus verifying correct operation if + // the bitmap is an extracted subset. + if (gPairs[i].fConfig == SkBitmap::kA1_Config) { + // If one-bit per pixel, use 9 pixels to force more than + // one byte per row. + subW = 9; + subH = 2; + } else { + // All other configurations are at least one byte per pixel, + // and different configs will test copying different numbers + // of bytes. + subW = subH = 2; + } + + // Create bitmap to act as source for copies and subsets. + SkBitmap src, subset; + SkColorTable* ct = NULL; + if (isExtracted[copyCase]) { // A larger image to extract from. + src.setConfig(gPairs[i].fConfig, 2 * subW + 1, subH); + } else // Tests expect a 2x2 bitmap, so make smaller. + src.setConfig(gPairs[i].fConfig, subW, subH); + if (SkBitmap::kIndex8_Config == src.config() || + SkBitmap::kRLE_Index8_Config == src.config()) { + ct = init_ctable(); + } + + src.allocPixels(ct); + SkSafeUnref(ct); + + // Either copy src or extract into 'subset', which is used + // for subsequent calls to copyPixelsTo/From. + bool srcReady = false; + if (isExtracted[copyCase]) { + // The extractedSubset() test case allows us to test copy- + // ing when src and dst mave possibly different strides. + SkIRect r; + if (gPairs[i].fConfig == SkBitmap::kA1_Config) + // This config seems to need byte-alignment of + // extracted subset bits. + r.set(0, 0, subW, subH); + else + r.set(1, 0, 1 + subW, subH); // 2x2 extracted bitmap + + srcReady = src.extractSubset(&subset, r); + } else { + srcReady = src.copyTo(&subset, src.getConfig()); + } + + // Not all configurations will generate a valid 'subset'. + if (srcReady) { + + // Allocate our target buffer 'buf' for all copies. + // To simplify verifying correctness of copies attach + // buf to a SkBitmap, but copies are done using the + // raw buffer pointer. + const uint32_t bufSize = subH * + SkBitmap::ComputeRowBytes(src.getConfig(), subW) * 2; + uint8_t* buf = new uint8_t[bufSize]; + + SkBitmap bufBm; // Attach buf to this bitmap. + bool successExpected; + + // Set up values for each pixel being copied. + Coordinates coords(subW * subH); + for (size_t x = 0; x < subW; ++x) + for (size_t y = 0; y < subH; ++y) + { + int index = y * subW + x; + SkASSERT(index < coords.length); + coords[index]->fX = x; + coords[index]->fY = y; + } + + writeCoordPixels(subset, coords); + + // Test #1 //////////////////////////////////////////// + + // Before/after comparisons easier if we attach buf + // to an appropriately configured SkBitmap. + memset(buf, 0xFF, bufSize); + // Config with stride greater than src but that fits in buf. + bufBm.setConfig(gPairs[i].fConfig, subW, subH, + SkBitmap::ComputeRowBytes(subset.getConfig(), subW) + * 2); + bufBm.setPixels(buf); + successExpected = false; + // Then attempt to copy with a stride that is too large + // to fit in the buffer. + REPORTER_ASSERT(reporter, + subset.copyPixelsTo(buf, bufSize, bufBm.rowBytes() * 3) + == successExpected); + + if (successExpected) + reportCopyVerification(subset, bufBm, coords, + "copyPixelsTo(buf, bufSize, 1.5*maxRowBytes)", + reporter); + + // Test #2 //////////////////////////////////////////// + // This test should always succeed, but in the case + // of extracted bitmaps only because we handle the + // issue of getSafeSize(). Without getSafeSize() + // buffer overrun/read would occur. + memset(buf, 0xFF, bufSize); + bufBm.setConfig(gPairs[i].fConfig, subW, subH, + subset.rowBytes()); + bufBm.setPixels(buf); + successExpected = subset.getSafeSize() <= bufSize; + REPORTER_ASSERT(reporter, + subset.copyPixelsTo(buf, bufSize) == + successExpected); + if (successExpected) + reportCopyVerification(subset, bufBm, coords, + "copyPixelsTo(buf, bufSize)", reporter); + + // Test #3 //////////////////////////////////////////// + // Copy with different stride between src and dst. + memset(buf, 0xFF, bufSize); + bufBm.setConfig(gPairs[i].fConfig, subW, subH, + subset.rowBytes()+1); + bufBm.setPixels(buf); + successExpected = true; // Should always work. + REPORTER_ASSERT(reporter, + subset.copyPixelsTo(buf, bufSize, + subset.rowBytes()+1) == successExpected); + if (successExpected) + reportCopyVerification(subset, bufBm, coords, + "copyPixelsTo(buf, bufSize, rowBytes+1)", reporter); + + // Test #4 //////////////////////////////////////////// + // Test copy with stride too small. + memset(buf, 0xFF, bufSize); + bufBm.setConfig(gPairs[i].fConfig, subW, subH); + bufBm.setPixels(buf); + successExpected = false; + // Request copy with stride too small. + REPORTER_ASSERT(reporter, + subset.copyPixelsTo(buf, bufSize, bufBm.rowBytes()-1) + == successExpected); + if (successExpected) + reportCopyVerification(subset, bufBm, coords, + "copyPixelsTo(buf, bufSize, rowBytes()-1)", reporter); + + // Test #5 //////////////////////////////////////////// + // Tests the case where the source stride is too small + // for the source configuration. + memset(buf, 0xFF, bufSize); + bufBm.setConfig(gPairs[i].fConfig, subW, subH); + bufBm.setPixels(buf); + writeCoordPixels(bufBm, coords); + REPORTER_ASSERT(reporter, + subset.copyPixelsFrom(buf, bufSize, 1) == false); + + // Test #6 //////////////////////////////////////////// + // Tests basic copy from an external buffer to the bitmap. + // If the bitmap is "extracted", this also tests the case + // where the source stride is different from the dest. + // stride. + // We've made the buffer large enough to always succeed. + bufBm.setConfig(gPairs[i].fConfig, subW, subH); + bufBm.setPixels(buf); + writeCoordPixels(bufBm, coords); + REPORTER_ASSERT(reporter, + subset.copyPixelsFrom(buf, bufSize, bufBm.rowBytes()) == + true); + reportCopyVerification(bufBm, subset, coords, + "copyPixelsFrom(buf, bufSize)", + reporter); + + // Test #7 //////////////////////////////////////////// + // Tests the case where the source buffer is too small + // for the transfer. + REPORTER_ASSERT(reporter, + subset.copyPixelsFrom(buf, 1, subset.rowBytes()) == + false); + + delete [] buf; + } + } + } // for (size_t copyCase ... } } diff --git a/tests/BitmapGetColorTest.cpp b/tests/BitmapGetColorTest.cpp new file mode 100644 index 0000000..81cf412 --- /dev/null +++ b/tests/BitmapGetColorTest.cpp @@ -0,0 +1,36 @@ +#include "Test.h" +#include "SkBitmap.h" + +static void TestGetColor(skiatest::Reporter* reporter) { + static const struct Rec { + SkBitmap::Config fConfig; + SkColor fInColor; + SkColor fOutColor; + } gRec[] = { + // todo: add some tests that involve alpha, so we exercise the + // unpremultiply aspect of getColor() + { SkBitmap::kA8_Config, 0xFF000000, 0xFF000000 }, + { SkBitmap::kA8_Config, 0, 0 }, + { SkBitmap::kARGB_4444_Config, 0xFF224466, 0xFF224466 }, + { SkBitmap::kARGB_4444_Config, 0, 0 }, + { SkBitmap::kRGB_565_Config, 0xFF00FF00, 0xFF00FF00 }, + { SkBitmap::kRGB_565_Config, 0xFFFF00FF, 0xFFFF00FF }, + { SkBitmap::kARGB_8888_Config, 0xFFFFFFFF, 0xFFFFFFFF }, + { SkBitmap::kARGB_8888_Config, 0, 0 }, + { SkBitmap::kARGB_8888_Config, 0xFF224466, 0xFF224466 }, + }; + + for (size_t i = 0; i < SK_ARRAY_COUNT(gRec); i++) { + SkBitmap bm; + uint32_t storage[1]; + bm.setConfig(gRec[i].fConfig, 1, 1); + bm.setPixels(storage); + bm.eraseColor(gRec[i].fInColor); + + SkColor c = bm.getColor(0, 0); + REPORTER_ASSERT(reporter, c == gRec[i].fOutColor); + } +} + +#include "TestClassDef.h" +DEFINE_TESTCLASS("GetColor", TestGetColorClass, TestGetColor) diff --git a/tests/BlitRowTest.cpp b/tests/BlitRowTest.cpp index 91d6b94..d18cb8a 100644 --- a/tests/BlitRowTest.cpp +++ b/tests/BlitRowTest.cpp @@ -207,7 +207,8 @@ static void test_diagonal(skiatest::Reporter* reporter) { SkBitmap srcBM; srcBM.setConfig(SkBitmap::kARGB_8888_Config, W, H); srcBM.allocPixels(); - SkRect srcR = { 0, 0, srcBM.width(), srcBM.height() }; + SkRect srcR = { + 0, 0, SkIntToScalar(srcBM.width()), SkIntToScalar(srcBM.height()) }; // cons up a mesh to draw the bitmap with Mesh mesh(srcBM, &paint); diff --git a/tests/ClipCubicTest.cpp b/tests/ClipCubicTest.cpp index 905b733..e38a22f 100644 --- a/tests/ClipCubicTest.cpp +++ b/tests/ClipCubicTest.cpp @@ -7,10 +7,10 @@ static void PrintCurve(const char *name, const SkPoint crv[4]) { printf("%s: %.10g, %.10g, %.10g, %.10g, %.10g, %.10g, %.10g, %.10g\n", name, - crv[0].fX, crv[0].fY, - crv[1].fX, crv[1].fY, - crv[2].fX, crv[2].fY, - crv[3].fX, crv[3].fY); + (float)crv[0].fX, (float)crv[0].fY, + (float)crv[1].fX, (float)crv[1].fY, + (float)crv[2].fX, (float)crv[2].fY, + (float)crv[3].fX, (float)crv[3].fY); } @@ -46,17 +46,17 @@ static SkPoint* SetCurve(float x0, float y0, static void TestCubicClipping(skiatest::Reporter* reporter) { static SkPoint crv[4] = { - { SkFloatToScalar(0), SkFloatToScalar(0) }, - { SkFloatToScalar(2), SkFloatToScalar(3) }, - { SkFloatToScalar(1), SkFloatToScalar(10) }, - { SkFloatToScalar(4), SkFloatToScalar(12) } + { SkIntToScalar(0), SkIntToScalar(0) }, + { SkIntToScalar(2), SkIntToScalar(3) }, + { SkIntToScalar(1), SkIntToScalar(10) }, + { SkIntToScalar(4), SkIntToScalar(12) } }; SkCubicClipper clipper; SkPoint clipped[4], shouldbe[4]; SkIRect clipRect; bool success; - const float tol = 1e-4; + const float tol = SkFloatToScalar(1e-4); // Test no clip, with plenty of room. clipRect.set(-2, -2, 6, 14); diff --git a/tests/ClipStackTest.cpp b/tests/ClipStackTest.cpp new file mode 100644 index 0000000..e3c95b4 --- /dev/null +++ b/tests/ClipStackTest.cpp @@ -0,0 +1,49 @@ +#include "Test.h" +#include "SkClipStack.h" + +static void assert_count(skiatest::Reporter* reporter, const SkClipStack& stack, + int count) { + REPORTER_ASSERT(reporter, count == stack.getSaveCount()); + + SkClipStack::B2FIter iter(stack); + int counter = 0; + while (iter.next()) { + counter += 1; + } + REPORTER_ASSERT(reporter, count == counter); +} + +static void TestClipStack(skiatest::Reporter* reporter) { + SkClipStack stack; + + assert_count(reporter, stack, 0); + + static const SkIRect gRects[] = { + { 0, 0, 100, 100 }, + { 25, 25, 125, 125 }, + { 0, 0, 1000, 1000 }, + { 0, 0, 75, 75 } + }; + for (size_t i = 0; i < SK_ARRAY_COUNT(gRects); i++) { + stack.clipDevRect(gRects[i]); + } + + // all of the above rects should have been intersected, leaving only 1 rect + SkClipStack::B2FIter iter(stack); + const SkClipStack::B2FIter::Clip* clip = iter.next(); + const SkRect answer = { 25, 25, 75, 75 }; + + REPORTER_ASSERT(reporter, clip); + REPORTER_ASSERT(reporter, clip->fRect); + REPORTER_ASSERT(reporter, !clip->fPath); + REPORTER_ASSERT(reporter, SkRegion::kIntersect_Op == clip->fOp); + REPORTER_ASSERT(reporter, *clip->fRect == answer); + // now check that we only had one in our iterator + REPORTER_ASSERT(reporter, !iter.next()); + + stack.reset(); + assert_count(reporter, stack, 0); +} + +#include "TestClassDef.h" +DEFINE_TESTCLASS("ClipStack", TestClipStackClass, TestClipStack) diff --git a/tests/DequeTest.cpp b/tests/DequeTest.cpp new file mode 100644 index 0000000..e74fd28 --- /dev/null +++ b/tests/DequeTest.cpp @@ -0,0 +1,96 @@ +#include "Test.h" +#include "SkDeque.h" + +static void assert_count(skiatest::Reporter* reporter, const SkDeque& deq, int count) { + if (0 == count) { + REPORTER_ASSERT(reporter, deq.empty()); + REPORTER_ASSERT(reporter, 0 == deq.count()); + REPORTER_ASSERT(reporter, sizeof(int) == deq.elemSize()); + REPORTER_ASSERT(reporter, NULL == deq.front()); + REPORTER_ASSERT(reporter, NULL == deq.back()); + } else { + REPORTER_ASSERT(reporter, !deq.empty()); + REPORTER_ASSERT(reporter, count == deq.count()); + REPORTER_ASSERT(reporter, sizeof(int) == deq.elemSize()); + REPORTER_ASSERT(reporter, NULL != deq.front()); + REPORTER_ASSERT(reporter, NULL != deq.back()); + if (1 == count) { + REPORTER_ASSERT(reporter, deq.back() == deq.front()); + } else { + REPORTER_ASSERT(reporter, deq.back() != deq.front()); + } + } +} + +static void assert_f2biter(skiatest::Reporter* reporter, const SkDeque& deq, + int max, int min) { + SkDeque::F2BIter iter(deq); + void* ptr; + + int value = max; + while ((ptr = iter.next()) != NULL) { + REPORTER_ASSERT(reporter, value == *(int*)ptr); + value -= 1; + } + REPORTER_ASSERT(reporter, value+1 == min); +} + +static void TestDeque(skiatest::Reporter* reporter) { + SkDeque deq(sizeof(int)); + int i; + + // test pushing on the front + + assert_count(reporter, deq, 0); + for (i = 1; i <= 10; i++) { + *(int*)deq.push_front() = i; + } + assert_count(reporter, deq, 10); + assert_f2biter(reporter, deq, 10, 1); + + for (i = 0; i < 5; i++) { + deq.pop_front(); + } + assert_count(reporter, deq, 5); + assert_f2biter(reporter, deq, 5, 1); + + for (i = 0; i < 5; i++) { + deq.pop_front(); + } + assert_count(reporter, deq, 0); + + // now test pushing on the back + + for (i = 10; i >= 1; --i) { + *(int*)deq.push_back() = i; + } + assert_count(reporter, deq, 10); + assert_f2biter(reporter, deq, 10, 1); + + for (i = 0; i < 5; i++) { + deq.pop_back(); + } + assert_count(reporter, deq, 5); + assert_f2biter(reporter, deq, 10, 6); + + for (i = 0; i < 5; i++) { + deq.pop_back(); + } + assert_count(reporter, deq, 0); + + // now tests pushing/poping on both ends + + *(int*)deq.push_front() = 5; + *(int*)deq.push_back() = 4; + *(int*)deq.push_front() = 6; + *(int*)deq.push_back() = 3; + *(int*)deq.push_front() = 7; + *(int*)deq.push_back() = 2; + *(int*)deq.push_front() = 8; + *(int*)deq.push_back() = 1; + assert_count(reporter, deq, 8); + assert_f2biter(reporter, deq, 8, 1); +} + +#include "TestClassDef.h" +DEFINE_TESTCLASS("Deque", TestDequeClass, TestDeque) diff --git a/tests/FillPathTest.cpp b/tests/FillPathTest.cpp new file mode 100644 index 0000000..ffc9f8e --- /dev/null +++ b/tests/FillPathTest.cpp @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2010 The Chromium Authors. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "Test.h" +#include "SkRegion.h" +#include "SkPath.h" +#include "SkScan.h" +#include "SkBlitter.h" + +namespace { + +struct FakeBlitter : public SkBlitter { + FakeBlitter() + : m_blitCount(0) + {} + + virtual void blitH(int x, int y, int width) { + m_blitCount++; + } + + int m_blitCount; +}; + +} + +// http://code.google.com/p/skia/issues/detail?id=87 +// Lines which is not clipped by boundary based clipping, +// but skipped after tessellation, should be cleared by the blitter. +static void TestFillPathInverse(skiatest::Reporter* reporter) { + FakeBlitter blitter; + SkRegion clip; + SkPath path; + int height = 100; + int width = 200; + int expected_lines = 5; + clip.setRect(0, height - expected_lines, width, height); + path.moveTo(0.0, 0.0); + path.quadTo(width/2, height, width, 0.0); + path.close(); + path.setFillType(SkPath::kInverseWinding_FillType); + SkScan::FillPath(path, clip, &blitter); + + REPORTER_ASSERT(reporter, blitter.m_blitCount == expected_lines); +} + +#include "TestClassDef.h" +DEFINE_TESTCLASS("FillPath", FillPathTestClass, TestFillPathInverse) diff --git a/tests/FlateTest.cpp b/tests/FlateTest.cpp new file mode 100644 index 0000000..f8e0921 --- /dev/null +++ b/tests/FlateTest.cpp @@ -0,0 +1,107 @@ +/* + * Copyright (C) 2011 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <stdlib.h> +#include <string.h> + +#include "Test.h" +#include "SkFlate.h" +#include "SkStream.h" + +// A memory stream that reports zero size with the standard call, like +// an unseekable file stream would. +class SkZeroSizeMemStream : public SkMemoryStream { +public: + virtual size_t read(void* buffer, size_t size) { + if (buffer == NULL && size == 0) + return 0; + if (buffer == NULL && size == kGetSizeKey) + size = 0; + return SkMemoryStream::read(buffer, size); + } + + static const size_t kGetSizeKey = 0xDEADBEEF; +}; + +static void TestFlate(skiatest::Reporter* reporter, SkMemoryStream* testStream, + size_t dataSize) { + if (testStream == NULL) + return; + + SkMemoryStream testData(dataSize); + uint8_t* data = (uint8_t*)testData.getMemoryBase(); + srand(0); // Make data deterministic. + for (size_t i = 0; i < dataSize; i++) + data[i] = rand() & 0xFF; + + testStream->setMemory(testData.getMemoryBase(), dataSize, true); + SkDynamicMemoryWStream compressed; + bool status = SkFlate::Deflate(testStream, &compressed); + REPORTER_ASSERT(reporter, status); + + // Check that the input data wasn't changed. + size_t inputSize = testStream->getLength(); + if (inputSize == 0) + inputSize = testStream->read(NULL, SkZeroSizeMemStream::kGetSizeKey); + REPORTER_ASSERT(reporter, testData.getLength() == inputSize); + REPORTER_ASSERT(reporter, memcmp(testData.getMemoryBase(), + testStream->getMemoryBase(), + testData.getLength()) == 0); + + // Assume there are two test sizes, big and small. + if (dataSize < 1024) + REPORTER_ASSERT(reporter, compressed.getOffset() < 1024); + else + REPORTER_ASSERT(reporter, compressed.getOffset() > 1024); + + testStream->setMemory(compressed.getStream(), compressed.getOffset(), true); + SkDynamicMemoryWStream uncompressed; + status = SkFlate::Inflate(testStream, &uncompressed); + REPORTER_ASSERT(reporter, status); + + // Check that the input data wasn't changed. + inputSize = testStream->getLength(); + if (inputSize == 0) + inputSize = testStream->read(NULL, SkZeroSizeMemStream::kGetSizeKey); + REPORTER_ASSERT(reporter, compressed.getOffset() == inputSize); + REPORTER_ASSERT(reporter, memcmp(testStream->getMemoryBase(), + compressed.getStream(), + compressed.getOffset()) == 0); + + // Check that the uncompressed data matches the source data. + REPORTER_ASSERT(reporter, testData.getLength() == uncompressed.getOffset()); + REPORTER_ASSERT(reporter, memcmp(testData.getMemoryBase(), + uncompressed.getStream(), + testData.getLength()) == 0); +} + +static void TestFlateCompression(skiatest::Reporter* reporter) { + TestFlate(reporter, NULL, 0); +#ifdef SK_ZLIB_INCLUDE + REPORTER_ASSERT(reporter, SkFlate::HaveFlate()); + + SkMemoryStream memStream; + TestFlate(reporter, &memStream, 512); + TestFlate(reporter, &memStream, 10240); + + SkZeroSizeMemStream fileStream; + TestFlate(reporter, &fileStream, 512); + TestFlate(reporter, &fileStream, 10240); +#endif +} + +#include "TestClassDef.h" +DEFINE_TESTCLASS("Flate", FlateTestClass, TestFlateCompression) diff --git a/tests/InfRectTest.cpp b/tests/InfRectTest.cpp new file mode 100644 index 0000000..1e15023 --- /dev/null +++ b/tests/InfRectTest.cpp @@ -0,0 +1,44 @@ +#include "Test.h" +#include "SkRect.h" + +#ifdef SK_SCALAR_IS_FLOAT +static float make_zero() { + return sk_float_sin(0); +} +#endif + +static void check_invalid(skiatest::Reporter* reporter, + SkScalar l, SkScalar t, SkScalar r, SkScalar b) { + SkRect rect; + rect.set(l, t, r, b); + REPORTER_ASSERT(reporter, !rect.hasValidCoordinates()); +} + +// Tests that hasValidCoordinates() will reject any rect with +/-inf values +// as one of its coordinates. +static void TestInfRect(skiatest::Reporter* reporter) { +#ifdef SK_SCALAR_IS_FLOAT + float invalid = 1 / make_zero(); // infinity +#else + SkFixed invalid = SK_FixedNaN; +#endif + SkScalar small = SkIntToScalar(10); + SkScalar big = SkIntToScalar(100); + + SkRect rect = SkRect::MakeXYWH(small, small, big, big); + REPORTER_ASSERT(reporter, rect.hasValidCoordinates()); + + check_invalid(reporter, small, small, big, invalid); + check_invalid(reporter, small, small, invalid, big); + check_invalid(reporter, small, invalid, big, big); + check_invalid(reporter, invalid, small, big, big); + check_invalid(reporter, small, small, big, -invalid); + check_invalid(reporter, small, small, -invalid, big); + check_invalid(reporter, small, -invalid, big, big); + check_invalid(reporter, -invalid, small, big, big); +} + +// need tests for SkStrSearch + +#include "TestClassDef.h" +DEFINE_TESTCLASS("InfRect", InfRectTestClass, TestInfRect) diff --git a/tests/MathTest.cpp b/tests/MathTest.cpp index 4bfbd94..493691e 100644 --- a/tests/MathTest.cpp +++ b/tests/MathTest.cpp @@ -146,6 +146,38 @@ static void unittest_fastfloat(skiatest::Reporter* reporter) { } } +#ifdef SK_SCALAR_IS_FLOAT +static float make_zero() { + return sk_float_sin(0); +} +#endif + +static void unittest_isfinite(skiatest::Reporter* reporter) { +#ifdef SK_SCALAR_IS_FLOAT + float nan = ::asin(2); + float inf = 1.0 / make_zero(); + float big = 3.40282e+038; + + REPORTER_ASSERT(reporter, !SkScalarIsNaN(inf)); + REPORTER_ASSERT(reporter, !SkScalarIsNaN(-inf)); + REPORTER_ASSERT(reporter, !SkScalarIsFinite(inf)); + REPORTER_ASSERT(reporter, !SkScalarIsFinite(-inf)); +#else + SkFixed nan = SK_FixedNaN; + SkFixed big = SK_FixedMax; +#endif + + REPORTER_ASSERT(reporter, SkScalarIsNaN(nan)); + REPORTER_ASSERT(reporter, !SkScalarIsNaN(big)); + REPORTER_ASSERT(reporter, !SkScalarIsNaN(-big)); + REPORTER_ASSERT(reporter, !SkScalarIsNaN(0)); + + REPORTER_ASSERT(reporter, !SkScalarIsFinite(nan)); + REPORTER_ASSERT(reporter, SkScalarIsFinite(big)); + REPORTER_ASSERT(reporter, SkScalarIsFinite(-big)); + REPORTER_ASSERT(reporter, SkScalarIsFinite(0)); +} + #endif static void test_muldiv255(skiatest::Reporter* reporter) { @@ -171,6 +203,19 @@ static void test_muldiv255(skiatest::Reporter* reporter) { #endif } +static void test_muldiv255ceiling(skiatest::Reporter* reporter) { + for (int c = 0; c <= 255; c++) { + for (int a = 0; a <= 255; a++) { + int product = (c * a + 255); + int expected_ceiling = (product + (product >> 8)) >> 8; + int webkit_ceiling = (c * a + 254) / 255; + REPORTER_ASSERT(reporter, expected_ceiling == webkit_ceiling); + int skia_ceiling = SkMulDiv255Ceiling(c, a); + REPORTER_ASSERT(reporter, skia_ceiling == webkit_ceiling); + } + } +} + static void test_copysign(skiatest::Reporter* reporter) { static const int32_t gTriples[] = { // x, y, expected result @@ -237,6 +282,7 @@ static void TestMath(skiatest::Reporter* reporter) { #endif test_muldiv255(reporter); + test_muldiv255ceiling(reporter); test_copysign(reporter); { @@ -295,6 +341,7 @@ static void TestMath(skiatest::Reporter* reporter) { #ifdef SK_CAN_USE_FLOAT unittest_fastfloat(reporter); + unittest_isfinite(reporter); #endif #ifdef SkLONGLONG diff --git a/tests/MatrixTest.cpp b/tests/MatrixTest.cpp index 052687d..49a98c2 100644 --- a/tests/MatrixTest.cpp +++ b/tests/MatrixTest.cpp @@ -5,7 +5,7 @@ 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; + const int32_t tolerance = 8; #endif return SkScalarAbs(a - b) <= tolerance; @@ -14,7 +14,7 @@ static bool nearly_equal_scalar(SkScalar a, SkScalar b) { 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]); + printf("not equal %g %g\n", (float)a[i], (float)b[i]); return false; } } diff --git a/tests/PDFPrimitivesTest.cpp b/tests/PDFPrimitivesTest.cpp new file mode 100644 index 0000000..6feab51 --- /dev/null +++ b/tests/PDFPrimitivesTest.cpp @@ -0,0 +1,210 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <string> + +#include "Test.h" +#include "SkPDFCatalog.h" +#include "SkPDFStream.h" +#include "SkPDFTypes.h" +#include "SkScalar.h" +#include "SkStream.h" + +static void CheckObjectOutput(skiatest::Reporter* reporter, SkPDFObject* obj, + const std::string& representation, + bool indirect) { + size_t directSize = obj->getOutputSize(NULL, false); + REPORTER_ASSERT(reporter, directSize == representation.size()); + + SkDynamicMemoryWStream buffer; + obj->emitObject(&buffer, NULL, false); + REPORTER_ASSERT(reporter, directSize == buffer.getOffset()); + REPORTER_ASSERT(reporter, memcmp(buffer.getStream(), representation.c_str(), + directSize) == 0); + + if (indirect) { + // Indirect output. + static char header[] = "1 0 obj\n"; + static size_t headerLen = strlen(header); + static char footer[] = "\nendobj\n"; + static size_t footerLen = strlen(footer); + + SkPDFCatalog catalog; + catalog.addObject(obj, false); + + size_t indirectSize = obj->getOutputSize(&catalog, true); + REPORTER_ASSERT(reporter, + indirectSize == directSize + headerLen + footerLen); + + buffer.reset(); + obj->emitObject(&buffer, &catalog, true); + REPORTER_ASSERT(reporter, indirectSize == buffer.getOffset()); + REPORTER_ASSERT(reporter, memcmp(buffer.getStream(), header, + headerLen) == 0); + REPORTER_ASSERT(reporter, + memcmp(buffer.getStream() + headerLen, + representation.c_str(), directSize) == 0); + REPORTER_ASSERT(reporter, + memcmp(buffer.getStream() + headerLen + directSize, + footer, footerLen) == 0); + } +} + +static void TestCatalog(skiatest::Reporter* reporter) { + SkPDFCatalog catalog; + SkRefPtr<SkPDFInt> int1 = new SkPDFInt(1); + int1->unref(); // SkRefPtr and new both took a reference. + SkRefPtr<SkPDFInt> int2 = new SkPDFInt(2); + int2->unref(); // SkRefPtr and new both took a reference. + SkRefPtr<SkPDFInt> int3 = new SkPDFInt(3); + int3->unref(); // SkRefPtr and new both took a reference. + SkRefPtr<SkPDFInt> int1Again(int1.get()); + + catalog.addObject(int1.get(), false); + catalog.addObject(int2.get(), false); + catalog.addObject(int3.get(), false); + + REPORTER_ASSERT(reporter, catalog.getObjectNumberSize(int1.get()) == 3); + REPORTER_ASSERT(reporter, catalog.getObjectNumberSize(int2.get()) == 3); + REPORTER_ASSERT(reporter, catalog.getObjectNumberSize(int3.get()) == 3); + + SkDynamicMemoryWStream buffer; + catalog.emitObjectNumber(&buffer, int1.get()); + catalog.emitObjectNumber(&buffer, int2.get()); + catalog.emitObjectNumber(&buffer, int3.get()); + catalog.emitObjectNumber(&buffer, int1Again.get()); + char expectedResult[] = "1 02 03 01 0"; + REPORTER_ASSERT(reporter, memcmp(buffer.getStream(), expectedResult, + strlen(expectedResult)) == 0); +} + +static void TestObjectRef(skiatest::Reporter* reporter) { + SkRefPtr<SkPDFInt> int1 = new SkPDFInt(1); + int1->unref(); // SkRefPtr and new both took a reference. + SkRefPtr<SkPDFInt> int2 = new SkPDFInt(2); + int2->unref(); // SkRefPtr and new both took a reference. + SkRefPtr<SkPDFObjRef> int2ref = new SkPDFObjRef(int2.get()); + int2ref->unref(); // SkRefPtr and new both took a reference. + + SkPDFCatalog catalog; + catalog.addObject(int1.get(), false); + catalog.addObject(int2.get(), false); + REPORTER_ASSERT(reporter, catalog.getObjectNumberSize(int1.get()) == 3); + REPORTER_ASSERT(reporter, catalog.getObjectNumberSize(int2.get()) == 3); + + char expectedResult[] = "2 0 R"; + SkDynamicMemoryWStream buffer; + int2ref->emitObject(&buffer, &catalog, false); + REPORTER_ASSERT(reporter, buffer.getOffset() == strlen(expectedResult)); + REPORTER_ASSERT(reporter, memcmp(buffer.getStream(), expectedResult, + buffer.getOffset()) == 0); +} + +static void TestPDFPrimitives(skiatest::Reporter* reporter) { + SkRefPtr<SkPDFInt> int42 = new SkPDFInt(42); + int42->unref(); // SkRefPtr and new both took a reference. + CheckObjectOutput(reporter, int42.get(), "42", true); + + SkRefPtr<SkPDFScalar> realHalf = new SkPDFScalar(SK_ScalarHalf); + realHalf->unref(); // SkRefPtr and new both took a reference. + CheckObjectOutput(reporter, realHalf.get(), "0.5", true); + + SkRefPtr<SkPDFScalar> bigScalar = new SkPDFScalar(110999.75); + bigScalar->unref(); // SkRefPtr and new both took a reference. +#if defined(SK_SCALAR_IS_FIXED) || !defined(SK_ALLOW_LARGE_PDF_SCALARS) + CheckObjectOutput(reporter, bigScalar.get(), "111000", true); +#else + CheckObjectOutput(reporter, bigScalar.get(), "110999.75", true); +#endif + +#if defined(SK_SCALAR_IS_FLOAT) && defined(SK_ALLOW_LARGE_PDF_SCALARS) + SkRefPtr<SkPDFScalar> biggerScalar = new SkPDFScalar(50000000.1); + biggerScalar->unref(); // SkRefPtr and new both took a reference. + CheckObjectOutput(reporter, biggerScalar.get(), "50000000", true); + + SkRefPtr<SkPDFScalar> smallestScalar = new SkPDFScalar(1.0/65536); + smallestScalar->unref(); // SkRefPtr and new both took a reference. + CheckObjectOutput(reporter, smallestScalar.get(), "0.00001526", true); +#endif + + SkRefPtr<SkPDFString> stringSimple = new SkPDFString("test ) string ( foo"); + stringSimple->unref(); // SkRefPtr and new both took a reference. + CheckObjectOutput(reporter, stringSimple.get(), "(test \\) string \\( foo)", + true); + SkRefPtr<SkPDFString> stringComplex = + new SkPDFString("\ttest ) string ( foo"); + stringComplex->unref(); // SkRefPtr and new both took a reference. + CheckObjectOutput(reporter, stringComplex.get(), + "<0974657374202920737472696E67202820666F6F>", true); + + SkRefPtr<SkPDFName> name = new SkPDFName("Test name\twith#tab"); + name->unref(); // SkRefPtr and new both took a reference. + CheckObjectOutput(reporter, name.get(), "/Test#20name#09with#23tab", false); + + SkRefPtr<SkPDFArray> array = new SkPDFArray; + array->unref(); // SkRefPtr and new both took a reference. + CheckObjectOutput(reporter, array.get(), "[]", true); + array->append(int42.get()); + CheckObjectOutput(reporter, array.get(), "[42]", true); + array->append(realHalf.get()); + CheckObjectOutput(reporter, array.get(), "[42 0.5]", true); + SkRefPtr<SkPDFInt> int0 = new SkPDFInt(0); + int0->unref(); // SkRefPtr and new both took a reference. + array->append(int0.get()); + CheckObjectOutput(reporter, array.get(), "[42 0.5 0]", true); + SkRefPtr<SkPDFInt> int1 = new SkPDFInt(1); + int1->unref(); // SkRefPtr and new both took a reference. + array->setAt(0, int1.get()); + CheckObjectOutput(reporter, array.get(), "[1 0.5 0]", true); + + SkRefPtr<SkPDFDict> dict = new SkPDFDict; + dict->unref(); // SkRefPtr and new both took a reference. + CheckObjectOutput(reporter, dict.get(), "<<>>", true); + SkRefPtr<SkPDFName> n1 = new SkPDFName("n1"); + n1->unref(); // SkRefPtr and new both took a reference. + dict->insert(n1.get(), int42.get()); + CheckObjectOutput(reporter, dict.get(), "<</n1 42\n>>", true); + SkRefPtr<SkPDFName> n2 = new SkPDFName("n2"); + n2->unref(); // SkRefPtr and new both took a reference. + SkRefPtr<SkPDFName> n3 = new SkPDFName("n3"); + n3->unref(); // SkRefPtr and new both took a reference. + dict->insert(n2.get(), realHalf.get()); + dict->insert(n3.get(), array.get()); + CheckObjectOutput(reporter, dict.get(), + "<</n1 42\n/n2 0.5\n/n3 [1 0.5 0]\n>>", true); + + char streamBytes[] = "Test\nFoo\tBar"; + SkRefPtr<SkMemoryStream> streamData = new SkMemoryStream( + streamBytes, strlen(streamBytes), true); + streamData->unref(); // SkRefPtr and new both took a reference. + SkRefPtr<SkPDFStream> stream = new SkPDFStream(streamData.get()); + stream->unref(); // SkRefPtr and new both took a reference. + CheckObjectOutput(reporter, stream.get(), + "<</Length 12\n>> stream\nTest\nFoo\tBar\nendstream", + true); + stream->insert(n1.get(), int42.get()); + CheckObjectOutput(reporter, stream.get(), + "<</Length 12\n/n1 42\n>> stream\nTest\nFoo\tBar" + "\nendstream", + true); + + TestCatalog(reporter); + + TestObjectRef(reporter); +} + +#include "TestClassDef.h" +DEFINE_TESTCLASS("PDFPrimitives", PDFPrimitivesTestClass, TestPDFPrimitives) diff --git a/tests/PaintTest.cpp b/tests/PaintTest.cpp index 4e6c8b9..5b19090 100644 --- a/tests/PaintTest.cpp +++ b/tests/PaintTest.cpp @@ -8,10 +8,14 @@ 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); + path.moveTo(SkFloatToFixed(460.2881309415525f), + SkFloatToFixed(303.250847066498)); + path.cubicTo(SkFloatToFixed(463.36378422175284), + SkFloatToFixed(302.1169735073363), + SkFloatToFixed(456.32239330810046), + SkFloatToFixed(304.720354932878), + SkFloatToFixed(453.15255460013304), + SkFloatToFixed(305.788586869862)); SkRect fillR, strokeR; fillR = path.getBounds(); diff --git a/tests/PathTest.cpp b/tests/PathTest.cpp index 9f26d01..b4b6317 100644 --- a/tests/PathTest.cpp +++ b/tests/PathTest.cpp @@ -6,7 +6,7 @@ static void check_convex_bounds(skiatest::Reporter* reporter, const SkPath& p, const SkRect& bounds) { REPORTER_ASSERT(reporter, p.isConvex()); REPORTER_ASSERT(reporter, p.getBounds() == bounds); - + SkPath p2(p); REPORTER_ASSERT(reporter, p2.isConvex()); REPORTER_ASSERT(reporter, p2.getBounds() == bounds); @@ -45,12 +45,12 @@ static void TestPath(skiatest::Reporter* reporter) { p.setIsConvex(false); p.addRoundRect(bounds, SK_Scalar1, SK_Scalar1); check_convex_bounds(reporter, p, bounds); - + p.reset(); p.setIsConvex(false); p.addOval(bounds); check_convex_bounds(reporter, p, bounds); - + p.reset(); p.setIsConvex(false); p.addRect(bounds); @@ -88,6 +88,18 @@ static void TestPath(skiatest::Reporter* reporter) { p.moveTo(SK_Scalar1, 0); p.getLastPt(&pt); REPORTER_ASSERT(reporter, pt.fX == SK_Scalar1); + + // check that reset and rewind clear the convex hint back to false + p.setIsConvex(false); + REPORTER_ASSERT(reporter, !p.isConvex()); + p.setIsConvex(true); + REPORTER_ASSERT(reporter, p.isConvex()); + p.reset(); + REPORTER_ASSERT(reporter, !p.isConvex()); + p.setIsConvex(true); + REPORTER_ASSERT(reporter, p.isConvex()); + p.rewind(); + REPORTER_ASSERT(reporter, !p.isConvex()); } #include "TestClassDef.h" diff --git a/tests/RefDictTest.cpp b/tests/RefDictTest.cpp new file mode 100644 index 0000000..f52541b --- /dev/null +++ b/tests/RefDictTest.cpp @@ -0,0 +1,66 @@ +#include "Test.h" +#include "SkRefDict.h" + +class TestRC : public SkRefCnt { +}; + +static void TestRefDict(skiatest::Reporter* reporter) { + TestRC data0, data1; + SkRefDict dict; + + REPORTER_ASSERT(reporter, NULL == dict.find(NULL)); + REPORTER_ASSERT(reporter, NULL == dict.find("foo")); + REPORTER_ASSERT(reporter, NULL == dict.find("bar")); + + dict.set("foo", &data0); + REPORTER_ASSERT(reporter, &data0 == dict.find("foo")); + REPORTER_ASSERT(reporter, 2 == data0.getRefCnt()); + + dict.set("foo", &data0); + REPORTER_ASSERT(reporter, &data0 == dict.find("foo")); + REPORTER_ASSERT(reporter, 2 == data0.getRefCnt()); + + dict.set("foo", &data1); + REPORTER_ASSERT(reporter, &data1 == dict.find("foo")); + REPORTER_ASSERT(reporter, 1 == data0.getRefCnt()); + REPORTER_ASSERT(reporter, 2 == data1.getRefCnt()); + + dict.set("foo", NULL); + REPORTER_ASSERT(reporter, NULL == dict.find("foo")); + REPORTER_ASSERT(reporter, 1 == data0.getRefCnt()); + REPORTER_ASSERT(reporter, 1 == data1.getRefCnt()); + + dict.set("foo", &data0); + dict.set("bar", &data1); + REPORTER_ASSERT(reporter, &data0 == dict.find("foo")); + REPORTER_ASSERT(reporter, &data1 == dict.find("bar")); + REPORTER_ASSERT(reporter, 2 == data0.getRefCnt()); + REPORTER_ASSERT(reporter, 2 == data1.getRefCnt()); + + dict.set("foo", &data1); + REPORTER_ASSERT(reporter, &data1 == dict.find("foo")); + REPORTER_ASSERT(reporter, &data1 == dict.find("bar")); + REPORTER_ASSERT(reporter, 1 == data0.getRefCnt()); + REPORTER_ASSERT(reporter, 3 == data1.getRefCnt()); + + dict.removeAll(); + REPORTER_ASSERT(reporter, NULL == dict.find("foo")); + REPORTER_ASSERT(reporter, NULL == dict.find("bar")); + REPORTER_ASSERT(reporter, 1 == data0.getRefCnt()); + REPORTER_ASSERT(reporter, 1 == data1.getRefCnt()); + + { + SkRefDict d; + REPORTER_ASSERT(reporter, NULL == d.find("foo")); + REPORTER_ASSERT(reporter, 1 == data0.getRefCnt()); + d.set("foo", &data0); + REPORTER_ASSERT(reporter, &data0 == d.find("foo")); + REPORTER_ASSERT(reporter, 2 == data0.getRefCnt()); + // let d go out of scope still with a ref on data0 + } + // be sure d's destructor lowered data0's owner count back to 1 + REPORTER_ASSERT(reporter, 1 == data0.getRefCnt()); +} + +#include "TestClassDef.h" +DEFINE_TESTCLASS("RefDict", RefDictTestClass, TestRefDict) diff --git a/tests/RegionTest.cpp b/tests/RegionTest.cpp new file mode 100644 index 0000000..ee34d8b --- /dev/null +++ b/tests/RegionTest.cpp @@ -0,0 +1,63 @@ +#include "Test.h" +#include "SkRegion.h" +#include "SkRandom.h" + +static void rand_rect(SkIRect* rect, SkRandom& rand) { + int bits = 6; + int shift = 32 - bits; + rect->set(rand.nextU() >> shift, rand.nextU() >> shift, + rand.nextU() >> shift, rand.nextU() >> shift); + rect->sort(); +} + +static bool test_rects(const SkIRect rect[], int count) { + SkRegion rgn0, rgn1; + + for (int i = 0; i < count; i++) { + rgn0.op(rect[i], SkRegion::kUnion_Op); + } + rgn1.setRects(rect, count); + + if (rgn0 != rgn1) { + SkDebugf("\n"); + for (int i = 0; i < count; i++) { + SkDebugf(" { %d, %d, %d, %d },\n", + rect[i].fLeft, rect[i].fTop, + rect[i].fRight, rect[i].fBottom); + } + SkDebugf("\n"); + return false; + } + return true; +} + +static void TestRegion(skiatest::Reporter* reporter) { + const SkIRect r2[] = { + { 0, 0, 1, 1 }, + { 2, 2, 3, 3 }, + }; + REPORTER_ASSERT(reporter, test_rects(r2, SK_ARRAY_COUNT(r2))); + + const SkIRect rects[] = { + { 0, 0, 1, 2 }, + { 2, 1, 3, 3 }, + { 4, 0, 5, 1 }, + { 6, 0, 7, 4 }, + }; + REPORTER_ASSERT(reporter, test_rects(rects, SK_ARRAY_COUNT(rects))); + + SkRandom rand; + for (int i = 0; i < 1000; i++) { + SkRegion rgn0, rgn1; + + const int N = 8; + SkIRect rect[N]; + for (int j = 0; j < N; j++) { + rand_rect(&rect[j], rand); + } + REPORTER_ASSERT(reporter, test_rects(rect, N)); + } +} + +#include "TestClassDef.h" +DEFINE_TESTCLASS("Region", RegionTestClass, TestRegion) diff --git a/tests/StringTest.cpp b/tests/StringTest.cpp index 344c752..270ccfd 100644 --- a/tests/StringTest.cpp +++ b/tests/StringTest.cpp @@ -48,6 +48,43 @@ static void TestString(skiatest::Reporter* reporter) { a.set("ab"); a.set("abc"); a.set("abcd"); + + a.set(""); + a.appendS64(72036854775808LL, 0); + REPORTER_ASSERT(reporter, a.equals("72036854775808")); + + a.set(""); + a.appendS64(-1844674407370LL, 0); + REPORTER_ASSERT(reporter, a.equals("-1844674407370")); + + a.set(""); + a.appendS64(73709551616LL, 15); + REPORTER_ASSERT(reporter, a.equals("000073709551616")); + + a.set(""); + a.appendS64(-429496729612LL, 15); + REPORTER_ASSERT(reporter, a.equals("-000429496729612")); + + static const struct { + SkScalar fValue; + const char* fString; + } gRec[] = { + { 0, "0" }, + { SK_Scalar1, "1" }, + { -SK_Scalar1, "-1" }, + { SK_Scalar1/2, "0.5" }, +#ifdef SK_SCALAR_IS_FLOAT + { 3.4028234e38f, "3.4028235e+38" }, + { -3.4028234e38f, "-3.4028235e+38" }, +#endif + }; + for (size_t i = 0; i < SK_ARRAY_COUNT(gRec); i++) { + a.reset(); + a.appendScalar(gRec[i].fValue); + REPORTER_ASSERT(reporter, a.size() <= SkStrAppendScalar_MaxSize); +// SkDebugf(" received <%s> expected <%s>\n", a.c_str(), gRec[i].fString); + REPORTER_ASSERT(reporter, a.equals(gRec[i].fString)); + } } #include "TestClassDef.h" diff --git a/tests/TestSize.cpp b/tests/TestSize.cpp index 6551509..9e0aaaa 100644 --- a/tests/TestSize.cpp +++ b/tests/TestSize.cpp @@ -53,7 +53,7 @@ static void TestSize(skiatest::Reporter* reporter) { SkISize ia; ia.set(ix, iy); a.set(x, y); - REPORTER_ASSERT(reporter, a.round() == ia); + REPORTER_ASSERT(reporter, a.toRound() == ia); }; #include "TestClassDef.h" diff --git a/tests/UtilsTest.cpp b/tests/UtilsTest.cpp index 8a8319c..2019a77 100644 --- a/tests/UtilsTest.cpp +++ b/tests/UtilsTest.cpp @@ -1,9 +1,71 @@ #include "Test.h" #include "SkRandom.h" +#include "SkRefCnt.h" #include "SkTSearch.h" #include "SkTSort.h" #include "SkUtils.h" +class RefClass : public SkRefCnt { +public: + RefClass(int n) : fN(n) {} + int get() const { return fN; } + +private: + int fN; +}; + +static void test_refptr(skiatest::Reporter* reporter) { + RefClass* r0 = new RefClass(0); + + SkRefPtr<RefClass> rc0; + REPORTER_ASSERT(reporter, rc0.get() == NULL); + REPORTER_ASSERT(reporter, !rc0); + + SkRefPtr<RefClass> rc1; + REPORTER_ASSERT(reporter, rc0 == rc1); + REPORTER_ASSERT(reporter, rc0.get() != r0); + + rc0 = r0; + REPORTER_ASSERT(reporter, rc0); + REPORTER_ASSERT(reporter, rc0 != rc1); + REPORTER_ASSERT(reporter, rc0.get() == r0); + + rc1 = rc0; + REPORTER_ASSERT(reporter, rc1); + REPORTER_ASSERT(reporter, rc0 == rc1); + REPORTER_ASSERT(reporter, rc0.get() == r0); + + rc0 = NULL; + REPORTER_ASSERT(reporter, rc0.get() == NULL); + REPORTER_ASSERT(reporter, !rc0); + REPORTER_ASSERT(reporter, rc0 != rc1); + + r0->unref(); +} + +static void test_autounref(skiatest::Reporter* reporter) { + RefClass obj(0); + REPORTER_ASSERT(reporter, 1 == obj.getRefCnt()); + + SkAutoTUnref<RefClass> tmp(&obj); + REPORTER_ASSERT(reporter, &obj == tmp.get()); + REPORTER_ASSERT(reporter, 1 == obj.getRefCnt()); + + REPORTER_ASSERT(reporter, &obj == tmp.detach()); + REPORTER_ASSERT(reporter, 1 == obj.getRefCnt()); + REPORTER_ASSERT(reporter, NULL == tmp.detach()); + REPORTER_ASSERT(reporter, NULL == tmp.get()); + + obj.ref(); + REPORTER_ASSERT(reporter, 2 == obj.getRefCnt()); + { + SkAutoTUnref<RefClass> tmp2(&obj); + } + REPORTER_ASSERT(reporter, 1 == obj.getRefCnt()); +} + +/////////////////////////////////////////////////////////////////////////////// + #define kSEARCH_COUNT 91 static void test_search(skiatest::Reporter* reporter) { @@ -103,7 +165,9 @@ static void TestUTF(skiatest::Reporter* reporter) { test_utf16(reporter); test_search(reporter); + test_refptr(reporter); + test_autounref(reporter); } #include "TestClassDef.h" -DEFINE_TESTCLASS("UTF", UtfTestClass, TestUTF) +DEFINE_TESTCLASS("Utils", UtfTestClass, TestUTF) diff --git a/tests/XfermodeTest.cpp b/tests/XfermodeTest.cpp new file mode 100644 index 0000000..6ab6cd7 --- /dev/null +++ b/tests/XfermodeTest.cpp @@ -0,0 +1,30 @@ +#include "Test.h" +#include "SkColor.h" +#include "SkXfermode.h" + +SkPMColor bogusXfermodeProc(SkPMColor src, SkPMColor dst) { + return 42; +} + +static void test_asMode(skiatest::Reporter* reporter) { + for (int mode = 0; mode <= SkXfermode::kLastMode; mode++) { + SkXfermode* xfer = SkXfermode::Create((SkXfermode::Mode) mode); + SkXfermode::Mode reportedMode = (SkXfermode::Mode) -1; + REPORTER_ASSERT(reporter, + xfer != NULL || mode == SkXfermode::kSrcOver_Mode); + if (xfer) { + REPORTER_ASSERT(reporter, xfer->asMode(&reportedMode)); + REPORTER_ASSERT(reporter, reportedMode == mode); + xfer->unref(); + } + } + + SkXfermode* bogusXfer = new SkProcXfermode(bogusXfermodeProc); + SkXfermode::Mode reportedMode = (SkXfermode::Mode) -1; + REPORTER_ASSERT(reporter, !bogusXfer->asMode(&reportedMode)); + REPORTER_ASSERT(reporter, reportedMode == -1); + bogusXfer->unref(); +} + +#include "TestClassDef.h" +DEFINE_TESTCLASS("Xfermode", XfermodeTestClass, test_asMode) |