diff options
Diffstat (limited to 'tests')
-rw-r--r-- | tests/Android.mk | 3 | ||||
-rw-r--r-- | tests/BitmapCopyTest.cpp | 2 | ||||
-rw-r--r-- | tests/ClampRangeTest.cpp | 128 | ||||
-rw-r--r-- | tests/ClipStackTest.cpp | 78 | ||||
-rw-r--r-- | tests/ColorFilterTest.cpp | 93 | ||||
-rw-r--r-- | tests/ColorTest.cpp | 32 | ||||
-rw-r--r-- | tests/FlateTest.cpp | 2 | ||||
-rw-r--r-- | tests/PathTest.cpp | 161 | ||||
-rw-r--r-- | tests/UtilsTest.cpp | 2 | ||||
-rw-r--r-- | tests/XfermodeTest.cpp | 25 | ||||
-rw-r--r-- | tests/skia_test.cpp | 2 | ||||
-rw-r--r-- | tests/tests_files.mk | 3 |
12 files changed, 520 insertions, 11 deletions
diff --git a/tests/Android.mk b/tests/Android.mk index a3ea319..09c7739 100644 --- a/tests/Android.mk +++ b/tests/Android.mk @@ -6,9 +6,12 @@ LOCAL_SRC_FILES:= \ BitmapCopyTest.cpp \ BitmapGetColorTest.cpp \ BlitRowTest.cpp \ + ClampRangeTest.cpp \ ClipCubicTest.cpp \ ClipStackTest.cpp \ ClipperTest.cpp \ + ColorFilterTest.cpp \ + ColorTest.cpp \ DequeTest.cpp \ DrawBitmapRectTest.cpp \ FillPathTest.cpp \ diff --git a/tests/BitmapCopyTest.cpp b/tests/BitmapCopyTest.cpp index 1878dfa..6ddb548 100644 --- a/tests/BitmapCopyTest.cpp +++ b/tests/BitmapCopyTest.cpp @@ -553,7 +553,7 @@ static void TestBitmapCopy(skiatest::Reporter* reporter) { REPORTER_ASSERT(reporter, subset.copyPixelsFrom(buf, bufSize, 1) == false); - // Test #6 //////////////////////////////////////////// + // 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. diff --git a/tests/ClampRangeTest.cpp b/tests/ClampRangeTest.cpp new file mode 100644 index 0000000..be9c6ec --- /dev/null +++ b/tests/ClampRangeTest.cpp @@ -0,0 +1,128 @@ +#include "Test.h" +#include "SkClampRange.h" +#include "SkRandom.h" + +static skiatest::Reporter* gReporter; + +static void debug_me() { + if (NULL == gReporter) { + SkDebugf("dsfdssd\n"); + } +} + +#ifdef USE_REPORTER + +#define R_ASSERT(cond) \ + do { if (!(cond)) { \ + debug_me(); \ + REPORTER_ASSERT(gReporter, cond); \ + }} while (0) + +#else +#define R_ASSERT(cond) \ + do { if (!(cond)) { \ + debug_me(); \ + }} while (0) +#endif + +static int classify_value(SkFixed fx, int v0, int v1) { + if (fx <= 0) { + return v0; + } + if (fx >= 0xFFFF) { + return v1; + } + R_ASSERT(false); + return 0; +} + +#define V0 -42 +#define V1 1024 + +static void slow_check(const SkClampRange& range, + SkFixed fx, SkFixed dx, int count) { + SkASSERT(range.fCount0 + range.fCount1 + range.fCount2 == count); + + int i; + if (range.fOverflowed) { + fx = range.fFx1; + for (i = 0; i < range.fCount1; i++) { + R_ASSERT(fx >= 0 && fx <= 0xFFFF); + fx += dx; + } + } else { + for (i = 0; i < range.fCount0; i++) { + int v = classify_value(fx, V0, V1); + R_ASSERT(v == range.fV0); + fx += dx; + } + if (range.fCount1 > 0 && fx != range.fFx1) { + SkDebugf("%x %x\n", fx, range.fFx1); + R_ASSERT(!"bad fFx1"); + return; + } + for (i = 0; i < range.fCount1; i++) { + R_ASSERT(fx >= 0 && fx <= 0xFFFF); + fx += dx; + } + for (i = 0; i < range.fCount2; i++) { + int v = classify_value(fx, V0, V1); + R_ASSERT(v == range.fV1); + fx += dx; + } + } +} + +static void test_range(SkFixed fx, SkFixed dx, int count) { + SkClampRange range; + range.init(fx, dx, count, V0, V1); + slow_check(range, fx, dx, count); +} + +#define ff(x) SkIntToFixed(x) + +void TestClampRange(skiatest::Reporter* reporter); +void TestClampRange(skiatest::Reporter* reporter) { + gReporter = reporter; + + test_range(0, 0, 20); + test_range(0xFFFF, 0, 20); + test_range(-ff(2), 0, 20); + test_range( ff(2), 0, 20); + + test_range(-10, 1, 20); + test_range(10, -1, 20); + test_range(-10, 3, 20); + test_range(10, -3, 20); + + test_range(ff(1), ff(16384), 100); + test_range(ff(-1), ff(-16384), 100); + test_range(ff(1)/2, ff(16384), 100); + test_range(ff(1)/2, ff(-16384), 100); + + SkRandom rand; + + // test non-overflow cases + for (int i = 0; i < 1000000; i++) { + SkFixed fx = rand.nextS() >> 1; + SkFixed sx = rand.nextS() >> 1; + int count = rand.nextU() % 1000 + 1; + SkFixed dx = (sx - fx) / count; + test_range(fx, dx, count); + } + + // test overflow cases + for (int i = 0; i < 100000; i++) { + SkFixed fx = rand.nextS(); + SkFixed dx = rand.nextS(); + int count = rand.nextU() % 1000 + 1; + test_range(fx, dx, count); + } +} + +#ifdef USE_REPORTER + +#include "TestClassDef.h" +DEFINE_TESTCLASS("ClampRange", ClampRangeClass, TestClampRange) + +#endif diff --git a/tests/ClipStackTest.cpp b/tests/ClipStackTest.cpp index e3c95b4..4ef33ff 100644 --- a/tests/ClipStackTest.cpp +++ b/tests/ClipStackTest.cpp @@ -1,5 +1,81 @@ #include "Test.h" #include "SkClipStack.h" +#include "SkPath.h" +#include "SkRect.h" + +static void test_assign_and_comparison(skiatest::Reporter* reporter) { + SkClipStack s; + + // Build up a clip stack with a path, an empty clip, and a rect. + s.save(); + SkPath p; + p.moveTo(5, 6); + p.lineTo(7, 8); + p.lineTo(5, 9); + p.close(); + s.clipDevPath(p); + + s.save(); + SkRect r = SkRect::MakeLTRB(1, 2, 3, 4); + s.clipDevRect(r); + r = SkRect::MakeLTRB(10, 11, 12, 13); + s.clipDevRect(r); + + s.save(); + r = SkRect::MakeLTRB(14, 15, 16, 17); + s.clipDevRect(r, SkRegion::kUnion_Op); + + // Test that assignment works. + SkClipStack copy = s; + REPORTER_ASSERT(reporter, s == copy); + + // Test that different save levels triggers not equal. + s.restore(); + REPORTER_ASSERT(reporter, s != copy); + + // Test that an equal, but not copied version is equal. + s.save(); + r = SkRect::MakeLTRB(14, 15, 16, 17); + s.clipDevRect(r, SkRegion::kUnion_Op); + REPORTER_ASSERT(reporter, s == copy); + + // Test that a different op on one level triggers not equal. + s.restore(); + s.save(); + r = SkRect::MakeLTRB(14, 15, 16, 17); + s.clipDevRect(r); + REPORTER_ASSERT(reporter, s != copy); + + // Test that different state (clip type) triggers not equal. + s.restore(); + s.save(); + SkPath rp; + rp.addRect(r); + s.clipDevPath(rp, SkRegion::kUnion_Op); + REPORTER_ASSERT(reporter, s != copy); + + // Test that different rects triggers not equal. + s.restore(); + s.save(); + r = SkRect::MakeLTRB(24, 25, 26, 27); + s.clipDevRect(r, SkRegion::kUnion_Op); + REPORTER_ASSERT(reporter, s != copy); + + // Sanity check + s.restore(); + copy.restore(); + REPORTER_ASSERT(reporter, s == copy); + s.restore(); + copy.restore(); + REPORTER_ASSERT(reporter, s == copy); + + // Test that different paths triggers not equal. + s.restore(); + s.save(); + p.addRect(r); + s.clipDevPath(p); + REPORTER_ASSERT(reporter, s != copy); +} static void assert_count(skiatest::Reporter* reporter, const SkClipStack& stack, int count) { @@ -43,6 +119,8 @@ static void TestClipStack(skiatest::Reporter* reporter) { stack.reset(); assert_count(reporter, stack, 0); + + test_assign_and_comparison(reporter); } #include "TestClassDef.h" diff --git a/tests/ColorFilterTest.cpp b/tests/ColorFilterTest.cpp new file mode 100644 index 0000000..77575eb --- /dev/null +++ b/tests/ColorFilterTest.cpp @@ -0,0 +1,93 @@ +#include "Test.h" +#include "SkColor.h" +#include "SkColorFilter.h" +#include "SkRandom.h" +#include "SkXfermode.h" + +static SkFlattenable* reincarnate_flattenable(SkFlattenable* obj) { + SkFlattenable::Factory fact = obj->getFactory(); + if (NULL == fact) { + return NULL; + } + + SkFlattenableWriteBuffer wb(1024); + obj->flatten(wb); + + size_t size = wb.size(); + SkAutoSMalloc<1024> storage(size); + // make a copy into storage + wb.flatten(storage.get()); + + SkFlattenableReadBuffer rb(storage.get(), size); + return fact(rb); +} + +template <typename T> T* reincarnate(T* obj) { + return (T*)reincarnate_flattenable(obj); +} + +/////////////////////////////////////////////////////////////////////////////// + +#define ILLEGAL_MODE ((SkXfermode::Mode)-1) + +static void test_asColorMode(skiatest::Reporter* reporter) { + SkRandom rand; + + for (int mode = 0; mode <= SkXfermode::kLastMode; mode++) { + SkColor color = rand.nextU(); + + // ensure we always get a filter, by avoiding the possibility of a + // special case that would return NULL (if color's alpha is 0 or 0xFF) + color = SkColorSetA(color, 0x7F); + + SkColorFilter* cf = SkColorFilter::CreateModeFilter(color, + (SkXfermode::Mode)mode); + + // allow for no filter if we're in Dst mode (its a no op) + if (SkXfermode::kDst_Mode == mode && NULL == cf) { + continue; + } + + SkAutoUnref aur(cf); + REPORTER_ASSERT(reporter, cf); + + SkColor c = ~color; + SkXfermode::Mode m = ILLEGAL_MODE; + + SkColor expectedColor = color; + SkXfermode::Mode expectedMode = (SkXfermode::Mode)mode; + +// SkDebugf("--- mc [%d %x] ", mode, color); + + REPORTER_ASSERT(reporter, cf->asColorMode(&c, &m)); + // handle special-case folding by the factory + if (SkXfermode::kClear_Mode == mode) { + if (c != expectedColor) { + expectedColor = 0; + } + if (m != expectedMode) { + expectedMode = SkXfermode::kSrc_Mode; + } + } + +// SkDebugf("--- got [%d %x] expected [%d %x]\n", m, c, expectedMode, expectedColor); + + REPORTER_ASSERT(reporter, c == expectedColor); + REPORTER_ASSERT(reporter, m == expectedMode); + + { + SkColorFilter* cf2 = reincarnate(cf); + SkAutoUnref aur2(cf2); + REPORTER_ASSERT(reporter, cf2); + + SkColor c2 = ~color; + SkXfermode::Mode m2 = ILLEGAL_MODE; + REPORTER_ASSERT(reporter, cf2->asColorMode(&c2, &m2)); + REPORTER_ASSERT(reporter, c2 == expectedColor); + REPORTER_ASSERT(reporter, m2 == expectedMode); + } + } +} + +#include "TestClassDef.h" +DEFINE_TESTCLASS("ColorFilter", ColorFilterTestClass, test_asColorMode) diff --git a/tests/ColorTest.cpp b/tests/ColorTest.cpp new file mode 100644 index 0000000..ef4b0b6 --- /dev/null +++ b/tests/ColorTest.cpp @@ -0,0 +1,32 @@ +#include "Test.h" +#include "SkColor.h" +#include "SkUnPreMultiply.h" + +static void test_premul(skiatest::Reporter* reporter) { + for (int a = 0; a <= 255; a++) { + for (int x = 0; x <= 255; x++) { + SkColor c0 = SkColorSetARGB(a, x, x, x); + SkPMColor p0 = SkPreMultiplyColor(c0); + + SkColor c1 = SkUnPreMultiply::PMColorToColor(p0); + SkPMColor p1 = SkPreMultiplyColor(c1); + + // we can't promise that c0 == c1, since c0 -> p0 is a many to one + // function, however, we can promise that p0 -> c1 -> p1 : p0 == p1 + REPORTER_ASSERT(reporter, p0 == p1); + + { + int ax = SkMulDiv255Ceiling(x, a); + REPORTER_ASSERT(reporter, ax <= a); + } + } + } +} + + +static void TestColor(skiatest::Reporter* reporter) { + test_premul(reporter); +} + +#include "TestClassDef.h" +DEFINE_TESTCLASS("Color", ColorTestClass, TestColor) diff --git a/tests/FlateTest.cpp b/tests/FlateTest.cpp index f8e0921..fe2bb4a 100644 --- a/tests/FlateTest.cpp +++ b/tests/FlateTest.cpp @@ -90,7 +90,7 @@ static void TestFlate(skiatest::Reporter* reporter, SkMemoryStream* testStream, static void TestFlateCompression(skiatest::Reporter* reporter) { TestFlate(reporter, NULL, 0); -#ifdef SK_ZLIB_INCLUDE +#if defined(SK_ZLIB_INCLUDE) && !defined(SK_DEBUG) REPORTER_ASSERT(reporter, SkFlate::HaveFlate()); SkMemoryStream memStream; diff --git a/tests/PathTest.cpp b/tests/PathTest.cpp index b4b6317..3884308 100644 --- a/tests/PathTest.cpp +++ b/tests/PathTest.cpp @@ -1,7 +1,103 @@ #include "Test.h" #include "SkPath.h" +#include "SkParse.h" #include "SkSize.h" +static void check_convexity(skiatest::Reporter* reporter, const SkPath& path, + SkPath::Convexity expected) { + SkPath::Convexity c = SkPath::ComputeConvexity(path); + REPORTER_ASSERT(reporter, c == expected); +} + +static void test_convexity2(skiatest::Reporter* reporter) { + SkPath pt; + pt.moveTo(0, 0); + pt.close(); +// check_convexity(reporter, pt, SkPath::kConvex_Convexity); + check_convexity(reporter, pt, SkPath::kUnknown_Convexity); + + SkPath line; + line.moveTo(12, 20); + line.lineTo(-12, -20); + line.close(); + // check_convexity(reporter, pt, SkPath::kConvex_Convexity); + check_convexity(reporter, pt, SkPath::kUnknown_Convexity); + + SkPath triLeft; + triLeft.moveTo(0, 0); + triLeft.lineTo(1, 0); + triLeft.lineTo(1, 1); + triLeft.close(); + check_convexity(reporter, triLeft, SkPath::kConvex_Convexity); + + SkPath triRight; + triRight.moveTo(0, 0); + triRight.lineTo(-1, 0); + triRight.lineTo(1, 1); + triRight.close(); + check_convexity(reporter, triRight, SkPath::kConvex_Convexity); + + SkPath square; + square.moveTo(0, 0); + square.lineTo(1, 0); + square.lineTo(1, 1); + square.lineTo(0, 1); + square.close(); + check_convexity(reporter, square, SkPath::kConvex_Convexity); + + SkPath redundantSquare; + redundantSquare.moveTo(0, 0); + redundantSquare.lineTo(0, 0); + redundantSquare.lineTo(0, 0); + redundantSquare.lineTo(1, 0); + redundantSquare.lineTo(1, 0); + redundantSquare.lineTo(1, 0); + redundantSquare.lineTo(1, 1); + redundantSquare.lineTo(1, 1); + redundantSquare.lineTo(1, 1); + redundantSquare.lineTo(0, 1); + redundantSquare.lineTo(0, 1); + redundantSquare.lineTo(0, 1); + redundantSquare.close(); + check_convexity(reporter, redundantSquare, SkPath::kConvex_Convexity); + + SkPath bowTie; + bowTie.moveTo(0, 0); + bowTie.lineTo(0, 0); + bowTie.lineTo(0, 0); + bowTie.lineTo(1, 1); + bowTie.lineTo(1, 1); + bowTie.lineTo(1, 1); + bowTie.lineTo(1, 0); + bowTie.lineTo(1, 0); + bowTie.lineTo(1, 0); + bowTie.lineTo(0, 1); + bowTie.lineTo(0, 1); + bowTie.lineTo(0, 1); + bowTie.close(); + check_convexity(reporter, bowTie, SkPath::kConcave_Convexity); + + SkPath spiral; + spiral.moveTo(0, 0); + spiral.lineTo(1, 0); + spiral.lineTo(1, 1); + spiral.lineTo(0, 1); + spiral.lineTo(0,.5); + spiral.lineTo(.5,.5); + spiral.lineTo(.5,.75); + spiral.close(); + check_convexity(reporter, spiral, SkPath::kConcave_Convexity); + + SkPath dent; + dent.moveTo(0, 0); + dent.lineTo(1, 1); + dent.lineTo(0, 1); + dent.lineTo(-.5,2); + dent.lineTo(-2, 1); + dent.close(); + check_convexity(reporter, dent, SkPath::kConcave_Convexity); +} + static void check_convex_bounds(skiatest::Reporter* reporter, const SkPath& p, const SkRect& bounds) { REPORTER_ASSERT(reporter, p.isConvex()); @@ -17,7 +113,67 @@ static void check_convex_bounds(skiatest::Reporter* reporter, const SkPath& p, REPORTER_ASSERT(reporter, other.getBounds() == bounds); } -static void TestPath(skiatest::Reporter* reporter) { +static void setFromString(SkPath* path, const char str[]) { + bool first = true; + while (str) { + SkScalar x, y; + str = SkParse::FindScalar(str, &x); + if (NULL == str) { + break; + } + str = SkParse::FindScalar(str, &y); + SkASSERT(str); + if (first) { + path->moveTo(x, y); + first = false; + } else { + path->lineTo(x, y); + } + } +} + +static void test_convexity(skiatest::Reporter* reporter) { + static const SkPath::Convexity U = SkPath::kUnknown_Convexity; + static const SkPath::Convexity C = SkPath::kConcave_Convexity; + static const SkPath::Convexity V = SkPath::kConvex_Convexity; + + SkPath path; + + REPORTER_ASSERT(reporter, U == SkPath::ComputeConvexity(path)); + path.addCircle(0, 0, 10); + REPORTER_ASSERT(reporter, V == SkPath::ComputeConvexity(path)); + path.addCircle(0, 0, 10); // 2nd circle + REPORTER_ASSERT(reporter, C == SkPath::ComputeConvexity(path)); + path.reset(); + path.addRect(0, 0, 10, 10, SkPath::kCCW_Direction); + REPORTER_ASSERT(reporter, V == SkPath::ComputeConvexity(path)); + path.reset(); + path.addRect(0, 0, 10, 10, SkPath::kCW_Direction); + REPORTER_ASSERT(reporter, V == SkPath::ComputeConvexity(path)); + + static const struct { + const char* fPathStr; + SkPath::Convexity fExpectedConvexity; + } gRec[] = { + { "0 0", SkPath::kUnknown_Convexity }, + { "0 0 10 10", SkPath::kUnknown_Convexity }, + { "0 0 10 10 20 20 0 0 10 10", SkPath::kConcave_Convexity }, + { "0 0 10 10 10 20", SkPath::kConvex_Convexity }, + { "0 0 10 10 10 0", SkPath::kConvex_Convexity }, + { "0 0 10 10 10 0 0 10", SkPath::kConcave_Convexity }, + { "0 0 10 0 0 10 -10 -10", SkPath::kConcave_Convexity }, + }; + + for (size_t i = 0; i < SK_ARRAY_COUNT(gRec); ++i) { + SkPath path; + setFromString(&path, gRec[i].fPathStr); + SkPath::Convexity c = SkPath::ComputeConvexity(path); + REPORTER_ASSERT(reporter, c == gRec[i].fExpectedConvexity); + } +} + +void TestPath(skiatest::Reporter* reporter); +void TestPath(skiatest::Reporter* reporter) { { SkSize size; size.fWidth = 3.4f; @@ -100,6 +256,9 @@ static void TestPath(skiatest::Reporter* reporter) { REPORTER_ASSERT(reporter, p.isConvex()); p.rewind(); REPORTER_ASSERT(reporter, !p.isConvex()); + + test_convexity(reporter); + test_convexity2(reporter); } #include "TestClassDef.h" diff --git a/tests/UtilsTest.cpp b/tests/UtilsTest.cpp index 2019a77..a051af2 100644 --- a/tests/UtilsTest.cpp +++ b/tests/UtilsTest.cpp @@ -64,7 +64,7 @@ static void test_autounref(skiatest::Reporter* reporter) { REPORTER_ASSERT(reporter, 1 == obj.getRefCnt()); } -/////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// #define kSEARCH_COUNT 91 diff --git a/tests/XfermodeTest.cpp b/tests/XfermodeTest.cpp index 6ab6cd7..b552ce0 100644 --- a/tests/XfermodeTest.cpp +++ b/tests/XfermodeTest.cpp @@ -6,16 +6,27 @@ SkPMColor bogusXfermodeProc(SkPMColor src, SkPMColor dst) { return 42; } +#define ILLEGAL_MODE ((SkXfermode::Mode)-1) + 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); + + SkXfermode::Mode reportedMode = ILLEGAL_MODE; + REPORTER_ASSERT(reporter, reportedMode != mode); + + // test IsMode + REPORTER_ASSERT(reporter, SkXfermode::IsMode(xfer, &reportedMode)); + REPORTER_ASSERT(reporter, reportedMode == mode); + + // repeat that test, but with asMode instead if (xfer) { - REPORTER_ASSERT(reporter, xfer->asMode(&reportedMode)); - REPORTER_ASSERT(reporter, reportedMode == mode); - xfer->unref(); + reportedMode = (SkXfermode::Mode) -1; + REPORTER_ASSERT(reporter, xfer->asMode(&reportedMode)); + REPORTER_ASSERT(reporter, reportedMode == mode); + xfer->unref(); + } else { + REPORTER_ASSERT(reporter, SkXfermode::kSrcOver_Mode == mode); } } @@ -23,6 +34,8 @@ static void test_asMode(skiatest::Reporter* reporter) { SkXfermode::Mode reportedMode = (SkXfermode::Mode) -1; REPORTER_ASSERT(reporter, !bogusXfer->asMode(&reportedMode)); REPORTER_ASSERT(reporter, reportedMode == -1); + REPORTER_ASSERT(reporter, !SkXfermode::IsMode(bogusXfer, &reportedMode)); + REPORTER_ASSERT(reporter, reportedMode == -1); bogusXfer->unref(); } diff --git a/tests/skia_test.cpp b/tests/skia_test.cpp index 25248a3..f931d62 100644 --- a/tests/skia_test.cpp +++ b/tests/skia_test.cpp @@ -123,5 +123,5 @@ int main (int argc, char * const argv[]) { SkDebugf("Finished %d tests, %d failures.\n", count, count - successCount); } - return 0; + return (count == successCount) ? 0 : 1; } diff --git a/tests/tests_files.mk b/tests/tests_files.mk index 9f8d6df..28d5fe7 100644 --- a/tests/tests_files.mk +++ b/tests/tests_files.mk @@ -2,9 +2,12 @@ SOURCE := \ BitmapCopyTest.cpp \ BitmapGetColorTest.cpp \ BlitRowTest.cpp \ + ClampRangeTest.cpp \ ClipCubicTest.cpp \ ClipStackTest.cpp \ ClipperTest.cpp \ + ColorFilterTest.cpp \ + ColorTest.cpp \ DequeTest.cpp \ DrawBitmapRectTest.cpp \ FillPathTest.cpp \ |